1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1993, 1994 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20 /* Xt features made by Fred Pierresteguy. */
22 /* On 4.3 these lose if they come after xterm.h. */
23 /* On HP-UX 8.0 signal.h loses if it comes after config.h. */
24 /* Putting these at the beginning seems to be standard for other .c files. */
31 /* Need syssignal.h for various externs and definitions that may be required
32 by some configurations for calls to signal later in this source file. */
33 #include "syssignal.h"
38 #include "blockinput.h"
40 /* This may include sys/types.h, and that somehow loses
41 if this is not done before the other system files. */
43 #include <X11/cursorfont.h>
46 /* Load sys/types.h if not already loaded.
47 In some systems loading it twice is suicidal. */
49 #include <sys/types.h>
54 #include <sys/ioctl.h>
55 #endif /* ! defined (BSD) */
60 #ifndef INCLUDED_FCNTL
67 #include <sys/param.h>
69 #include "dispextern.h"
70 #include "termhooks.h"
83 #include "intervals.h"
86 extern XtAppContext Xt_app_con
;
87 extern Widget Xt_app_shell
;
88 extern void free_frame_menubar ();
89 extern void _XEditResCheckMessages ();
90 #endif /* USE_X_TOOLKIT */
93 #define x_any_window_to_frame x_window_to_frame
94 #define x_top_window_to_frame x_window_to_frame
98 #ifndef XtNinitialState
99 #define XtNinitialState "initialState"
103 #define XMapWindow XMapRaised /* Raise them when mapping. */
106 /* We could get this from param.h, but better not to depend on finding that.
107 And better not to risk that it might define other symbols used in this
110 #define MAXDESC FD_SETSIZE
114 #define SELECT_TYPE fd_set
115 #else /* no FD_SET */
117 #define SELECT_TYPE int
119 /* Define the macros to access a single-int bitmap of descriptors. */
120 #define FD_SET(n, p) (*(p) |= (1 << (n)))
121 #define FD_CLR(n, p) (*(p) &= ~(1 << (n)))
122 #define FD_ISSET(n, p) (*(p) & (1 << (n)))
123 #define FD_ZERO(p) (*(p) = 0)
124 #endif /* no FD_SET */
126 /* For sending Meta-characters. Do we need this? */
129 #define min(a,b) ((a)<(b) ? (a) : (b))
130 #define max(a,b) ((a)>(b) ? (a) : (b))
132 /* Nonzero means we must reprint all windows
133 because 1) we received an ExposeWindow event
134 or 2) we received too many ExposeRegion events to record.
136 This is never needed under X11. */
137 static int expose_all_windows
;
139 /* Nonzero means we must reprint all icon windows. */
141 static int expose_all_icons
;
143 #if defined (SIGIO) && defined (FIONREAD)
144 int BLOCK_INPUT_mask
;
145 #endif /* ! defined (SIGIO) && defined (FIONREAD) */
147 /* The id of a bitmap used for icon windows.
148 One such map is shared by all Emacs icon windows.
149 This is zero if we have not yet had a need to create the bitmap. */
151 static Bitmap icon_bitmap
;
153 /* Font used for text icons. */
155 static FONT_TYPE
*icon_font_info
;
157 /* Stuff for dealing with the main icon title. */
159 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
162 /* Initial values of argv and argc. */
163 extern char **initial_argv
;
164 extern int initial_argc
;
166 /* This is the X connection that we are using. */
168 Display
*x_current_display
;
170 /* The cursor to use for vertical scroll bars on x_current_display. */
171 static Cursor x_vertical_scroll_bar_cursor
;
173 /* Frame being updated by update_frame. This is declared in term.c.
174 This is set by update_begin and looked at by all the
175 XT functions. It is zero while not inside an update.
176 In that case, the XT functions assume that `selected_frame'
177 is the frame to apply to. */
178 extern struct frame
*updating_frame
;
180 /* The frame (if any) which has the X window that has keyboard focus.
181 Zero if none. This is examined by Ffocus_frame in frame.c. Note
182 that a mere EnterNotify event can set this; if you need to know the
183 last frame specified in a FocusIn or FocusOut event, use
184 x_focus_event_frame. */
185 struct frame
*x_focus_frame
;
187 /* This is a frame waiting to be autoraised, within XTread_socket. */
188 struct frame
*pending_autoraise_frame
;
190 /* The last frame mentioned in a FocusIn or FocusOut event. This is
191 separate from x_focus_frame, because whether or not LeaveNotify
192 events cause us to lose focus depends on whether or not we have
193 received a FocusIn event for it. */
194 struct frame
*x_focus_event_frame
;
196 /* The frame which currently has the visual highlight, and should get
197 keyboard input (other sorts of input have the frame encoded in the
198 event). It points to the X focus frame's selected window's
199 frame. It differs from x_focus_frame when we're using a global
201 static struct frame
*x_highlight_frame
;
203 /* From .Xdefaults, the value of "emacs.WarpMouse". If non-zero,
204 mouse is moved to inside of frame when frame is de-iconified. */
206 static int warp_mouse_on_deiconify
;
208 /* During an update, maximum vpos for ins/del line operations to affect. */
210 static int flexlines
;
212 /* During an update, nonzero if chars output now should be highlighted. */
214 static int highlight
;
216 /* Nominal cursor position -- where to draw output.
217 During an update, these are different from the cursor-box position. */
222 /* Reusable Graphics Context for drawing a cursor in a non-default face. */
223 static GC scratch_cursor_gc
;
227 In order to avoid asking for motion events and then throwing most
228 of them away or busy-polling the server for mouse positions, we ask
229 the server for pointer motion hints. This means that we get only
230 one event per group of mouse movements. "Groups" are delimited by
231 other kinds of events (focus changes and button clicks, for
232 example), or by XQueryPointer calls; when one of these happens, we
233 get another MotionNotify event the next time the mouse moves. This
234 is at least as efficient as getting motion events when mouse
235 tracking is on, and I suspect only negligibly worse when tracking
238 The silly O'Reilly & Associates Nutshell guides barely document
239 pointer motion hints at all (I think you have to infer how they
240 work from an example), and the description of XQueryPointer doesn't
241 mention that calling it causes you to get another motion hint from
242 the server, which is very important. */
244 /* Where the mouse was last time we reported a mouse event. */
245 static FRAME_PTR last_mouse_frame
;
246 static XRectangle last_mouse_glyph
;
248 /* The scroll bar in which the last X motion event occurred.
250 If the last X motion event occurred in a scroll bar, we set this
251 so XTmouse_position can know whether to report a scroll bar motion or
254 If the last X motion event didn't occur in a scroll bar, we set this
255 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
256 static Lisp_Object last_mouse_scroll_bar
;
258 /* Record which buttons are currently pressed. */
259 unsigned int x_mouse_grabbed
;
261 /* This is a hack. We would really prefer that XTmouse_position would
262 return the time associated with the position it returns, but there
263 doesn't seem to be any way to wrest the timestamp from the server
264 along with the position query. So, we just keep track of the time
265 of the last movement we received, and return that in hopes that
266 it's somewhat accurate. */
267 static Time last_mouse_movement_time
;
269 /* These variables describe the range of text currently shown
270 in its mouse-face, together with the window they apply to.
271 As long as the mouse stays within this range, we need not
272 redraw anything on its account. */
273 static int mouse_face_beg_row
, mouse_face_beg_col
;
274 static int mouse_face_end_row
, mouse_face_end_col
;
275 static int mouse_face_past_end
;
276 static Lisp_Object mouse_face_window
;
277 static int mouse_face_face_id
;
279 /* 1 if a mouse motion event came and we didn't handle it right away because
280 gc was in progress. */
281 static int mouse_face_deferred_gc
;
283 /* FRAME and X, Y position of mouse when last checked for
284 highlighting. X and Y can be negative or out of range for the frame. */
285 static FRAME_PTR mouse_face_mouse_frame
;
286 static int mouse_face_mouse_x
, mouse_face_mouse_y
;
288 /* Nonzero means defer mouse-motion highlighting. */
289 static int mouse_face_defer
;
291 /* `t' if a mouse button is depressed. */
293 extern Lisp_Object Vmouse_depressed
;
295 /* Tells if a window manager is present or not. */
297 extern Lisp_Object Vx_no_window_manager
;
299 /* Timestamp that we requested selection data was made. */
300 extern Time requestor_time
;
302 /* ID of the window requesting selection data. */
303 extern Window requestor_window
;
305 /* Nonzero enables some debugging for the X interface code. */
308 extern Lisp_Object Qface
, Qmouse_face
;
310 static int x_noop_count
;
313 /* From time to time we get info on an Emacs window, here. */
315 static WINDOWINFO_TYPE windowinfo
;
319 /* A mask of extra modifier bits to put into every keyboard char. */
320 extern int extra_keyboard_modifiers
;
322 extern Display
*XOpenDisplay ();
323 extern Window
XCreateWindow ();
325 extern Cursor
XCreateCursor ();
326 extern FONT_TYPE
*XOpenFont ();
328 static void flashback ();
329 static void redraw_previous_char ();
330 static void redraw_following_char ();
331 static unsigned int x_x_to_emacs_modifiers ();
333 static int fast_find_position ();
334 static void note_mouse_highlight ();
335 static void clear_mouse_face ();
336 static void show_mouse_face ();
339 static int XTcursor_to ();
340 static int XTclear_end_of_line ();
343 /* Starting and ending updates.
345 These hooks are called by update_frame at the beginning and end
346 of a frame update. We record in `updating_frame' the identity
347 of the frame being updated, so that the XT... functions do not
348 need to take a frame as argument. Most of the XT... functions
349 should never be called except during an update, the only exceptions
350 being XTcursor_to, XTwrite_glyphs and XTreassert_line_highlight. */
352 extern int mouse_track_top
, mouse_track_left
, mouse_track_width
;
363 flexlines
= f
->height
;
368 if (f
== mouse_face_mouse_frame
)
370 /* Don't do highlighting for mouse motion during the update. */
371 mouse_face_defer
= 1;
372 if (!NILP (mouse_face_window
))
374 int firstline
, lastline
, i
;
375 struct window
*w
= XWINDOW (mouse_face_window
);
377 /* Find the first, and the last+1, lines affected by redisplay. */
378 for (firstline
= 0; firstline
< f
->height
; firstline
++)
379 if (FRAME_DESIRED_GLYPHS (f
)->enable
[firstline
])
382 lastline
= f
->height
;
383 for (i
= f
->height
- 1; i
>= 0; i
--)
385 if (FRAME_DESIRED_GLYPHS (f
)->enable
[i
])
391 /* Can we tell that this update does not affect the window
392 where the mouse highlight is? If so, no need to turn off. */
393 if (! (firstline
> (XFASTINT (w
->top
) + window_internal_height (w
))
394 || lastline
< XFASTINT (w
->top
)))
395 /* Otherwise turn off the mouse highlight now. */
411 x_display_cursor (f
, 1);
413 if (f
== mouse_face_mouse_frame
)
414 mouse_face_defer
= 0;
416 /* This fails in the case of having updated only the echo area
417 if we have switched buffers. In that case, FRAME_CURRENT_GLYPHS
418 has no relation to the current contents, and its charstarts
419 have no relation to the contents of the window-buffer.
420 I don't know a clean way to check
421 for that case. window_end_valid isn't set up yet. */
422 if (f
== mouse_face_mouse_frame
)
423 note_mouse_highlight (f
, mouse_face_mouse_x
, mouse_face_mouse_y
);
430 /* This is called after a redisplay on frame F. */
433 XTframe_up_to_date (f
)
436 if (mouse_face_deferred_gc
|| f
== mouse_face_mouse_frame
)
438 note_mouse_highlight (mouse_face_mouse_frame
,
439 mouse_face_mouse_x
, mouse_face_mouse_y
);
440 mouse_face_deferred_gc
= 0;
444 /* External interface to control of standout mode.
445 Call this when about to modify line at position VPOS
446 and not change whether it is highlighted. */
448 XTreassert_line_highlight (new, vpos
)
454 /* Call this when about to modify line at position VPOS
455 and change whether it is highlighted. */
458 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
459 int new_highlight
, vpos
, first_unused_hpos
;
461 highlight
= new_highlight
;
462 XTcursor_to (vpos
, 0);
463 XTclear_end_of_line (updating_frame
->width
);
466 /* This is used when starting Emacs and when restarting after suspend.
467 When starting Emacs, no X window is mapped. And nothing must be done
468 to Emacs's own window if it is suspended (though that rarely happens). */
471 XTset_terminal_modes ()
475 /* This is called when exiting or suspending Emacs.
476 Exiting will make the X-windows go away, and suspending
477 requires no action. */
480 XTreset_terminal_modes ()
482 /* XTclear_frame (); */
485 /* Set the nominal cursor position of the frame.
486 This is where display update commands will take effect.
487 This does not affect the place where the cursor-box is displayed. */
490 XTcursor_to (row
, col
)
491 register int row
, col
;
499 if (updating_frame
== 0)
502 x_display_cursor (selected_frame
, 1);
508 /* Display a sequence of N glyphs found at GP.
509 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
510 HL is 1 if this text is highlighted, 2 if the cursor is on it,
511 3 if should appear in its mouse-face.
512 JUST_FOREGROUND if 1 means draw only the foreground;
513 don't alter the background.
515 FONT is the default font to use (for glyphs whose font-code is 0).
517 Since the display generation code is responsible for calling
518 compute_char_face and compute_glyph_face on everything it puts in
519 the display structure, we can assume that the face code on each
520 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
521 to which we can actually apply intern_face.
522 Call this function with input blocked. */
525 /* This is the multi-face code. */
528 dumpglyphs (f
, left
, top
, gp
, n
, hl
, just_foreground
)
531 register GLYPH
*gp
; /* Points to first GLYPH. */
532 register int n
; /* Number of glyphs to display. */
536 /* Holds characters to be displayed. */
537 char *buf
= (char *) alloca (f
->width
* sizeof (*buf
));
538 register char *cp
; /* Steps through buf[]. */
539 register int tlen
= GLYPH_TABLE_LENGTH
;
540 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
541 Window window
= FRAME_X_WINDOW (f
);
542 int orig_left
= left
;
546 /* Get the face-code of the next GLYPH. */
550 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
551 cf
= FAST_GLYPH_FACE (g
);
553 /* Find the run of consecutive glyphs with the same face-code.
554 Extract their character codes into BUF. */
559 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
560 if (FAST_GLYPH_FACE (g
) != cf
)
563 *cp
++ = FAST_GLYPH_CHAR (g
);
568 /* LEN gets the length of the run. */
571 /* Now output this run of chars, with the font and pixel values
572 determined by the face code CF. */
574 struct face
*face
= FRAME_DEFAULT_FACE (f
);
575 FONT_TYPE
*font
= FACE_FONT (face
);
576 GC gc
= FACE_GC (face
);
578 /* HL = 3 means use a mouse face previously chosen. */
580 cf
= mouse_face_face_id
;
582 /* First look at the face of the text itself. */
585 /* It's possible for the display table to specify
586 a face code that is out of range. Use 0 in that case. */
587 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
588 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
592 face
= FRAME_MODE_LINE_FACE (f
);
594 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
595 font
= FACE_FONT (face
);
599 /* Then comes the distinction between modeline and normal text. */
604 face
= FRAME_MODE_LINE_FACE (f
);
605 font
= FACE_FONT (face
);
609 #define FACE_DEFAULT (~0)
611 /* Now override that if the cursor's on this character. */
615 || (int) face
->font
== FACE_DEFAULT
616 || face
->font
== f
->display
.x
->font
)
617 && face
->background
== f
->display
.x
->background_pixel
618 && face
->foreground
== f
->display
.x
->foreground_pixel
)
620 gc
= f
->display
.x
->cursor_gc
;
622 /* Cursor on non-default face: must merge. */
628 xgcv
.background
= f
->display
.x
->cursor_pixel
;
629 xgcv
.foreground
= face
->background
;
630 /* If the glyph would be invisible,
631 try a different foreground. */
632 if (xgcv
.foreground
== xgcv
.background
)
633 xgcv
.foreground
= face
->foreground
;
634 if (xgcv
.foreground
== xgcv
.background
)
635 xgcv
.foreground
= f
->display
.x
->cursor_foreground_pixel
;
636 if (xgcv
.foreground
== xgcv
.background
)
637 xgcv
.foreground
= face
->foreground
;
638 /* Make sure the cursor is distinct from text in this face. */
639 if (xgcv
.background
== face
->background
640 && xgcv
.foreground
== face
->foreground
)
642 xgcv
.background
= face
->foreground
;
643 xgcv
.foreground
= face
->background
;
645 xgcv
.font
= face
->font
->fid
;
646 xgcv
.graphics_exposures
= 0;
647 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
648 if (scratch_cursor_gc
)
649 XChangeGC (x_current_display
, scratch_cursor_gc
, mask
, &xgcv
);
652 XCreateGC (x_current_display
, window
, mask
, &xgcv
);
653 gc
= scratch_cursor_gc
;
655 /* If this code is restored, it must also reset to the default stipple
657 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
658 XSetStipple (x_current_display
, gc
, face
->stipple
);
663 if ((int) font
== FACE_DEFAULT
)
664 font
= f
->display
.x
->font
;
667 XDrawString (x_current_display
, window
, gc
,
668 left
, top
+ FONT_BASE (font
), buf
, len
);
671 XDrawImageString (x_current_display
, window
, gc
,
672 left
, top
+ FONT_BASE (font
), buf
, len
);
673 /* Clear the rest of the line's height. */
674 if (f
->display
.x
->line_height
!= FONT_HEIGHT (font
))
675 XClearArea (x_current_display
, window
, left
,
676 top
+ FONT_HEIGHT (font
),
677 FONT_WIDTH (font
) * len
,
678 /* This is how many pixels of height
680 f
->display
.x
->line_height
- FONT_HEIGHT (font
),
684 #if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
685 which often is not up to date yet. */
686 if (!just_foreground
)
688 if (left
== orig_left
)
689 redraw_previous_char (f
, PIXEL_TO_CHAR_COL (f
, left
),
690 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
692 redraw_following_char (f
, PIXEL_TO_CHAR_COL (f
, left
+ len
* FONT_WIDTH (font
)),
693 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
697 /* We should probably check for XA_UNDERLINE_POSITION and
698 XA_UNDERLINE_THICKNESS properties on the font, but let's
699 just get the thing working, and come back to that. */
701 int underline_position
= 1;
703 if (font
->descent
<= underline_position
)
704 underline_position
= font
->descent
- 1;
707 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
711 + underline_position
),
712 len
* FONT_WIDTH (font
), 1);
715 left
+= len
* FONT_WIDTH (font
);
722 /* This is the old single-face code. */
725 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
728 register GLYPH
*gp
; /* Points to first GLYPH. */
729 register int n
; /* Number of glyphs to display. */
734 Window window
= FRAME_X_WINDOW (f
);
735 GC drawing_gc
= (hl
== 2 ? f
->display
.x
->cursor_gc
736 : (hl
? f
->display
.x
->reverse_gc
737 : f
->display
.x
->normal_gc
));
739 if (sizeof (GLYPH
) == sizeof (XChar2b
))
740 XDrawImageString16 (x_current_display
, window
, drawing_gc
,
741 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
742 else if (sizeof (GLYPH
) == sizeof (unsigned char))
743 XDrawImageString (x_current_display
, window
, drawing_gc
,
744 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
746 /* What size of glyph ARE you using? And does X have a function to
752 /* Output some text at the nominal frame cursor position.
753 Advance the cursor over the text.
754 Output LEN glyphs at START.
756 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
757 controls the pixel values used for foreground and background. */
760 XTwrite_glyphs (start
, len
)
761 register GLYPH
*start
;
764 register int temp_length
;
774 /* If not within an update,
775 output at the frame's visible cursor. */
776 curs_x
= f
->cursor_x
;
777 curs_y
= f
->cursor_y
;
781 CHAR_TO_PIXEL_COL (f
, curs_x
),
782 CHAR_TO_PIXEL_ROW (f
, curs_y
),
783 start
, len
, highlight
, 0);
785 /* If we drew on top of the cursor, note that it is turned off. */
786 if (curs_y
== f
->phys_cursor_y
787 && curs_x
<= f
->phys_cursor_x
788 && curs_x
+ len
> f
->phys_cursor_x
)
789 f
->phys_cursor_x
= -1;
791 if (updating_frame
== 0)
794 x_display_cursor (f
, 1);
803 /* Clear to the end of the line.
804 Erase the current text line from the nominal cursor position (inclusive)
805 to column FIRST_UNUSED (exclusive). The idea is that everything
806 from FIRST_UNUSED onward is already erased. */
809 XTclear_end_of_line (first_unused
)
810 register int first_unused
;
812 struct frame
*f
= updating_frame
;
818 if (curs_y
< 0 || curs_y
>= f
->height
)
820 if (first_unused
<= 0)
823 if (first_unused
>= f
->width
)
824 first_unused
= f
->width
;
828 /* Notice if the cursor will be cleared by this operation. */
829 if (curs_y
== f
->phys_cursor_y
830 && curs_x
<= f
->phys_cursor_x
831 && f
->phys_cursor_x
< first_unused
)
832 f
->phys_cursor_x
= -1;
834 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
835 CHAR_TO_PIXEL_COL (f
, curs_x
),
836 CHAR_TO_PIXEL_ROW (f
, curs_y
),
837 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
838 f
->display
.x
->line_height
, False
);
840 redraw_previous_char (f
, curs_x
, curs_y
, highlight
);
850 struct frame
*f
= updating_frame
;
855 f
->phys_cursor_x
= -1; /* Cursor not visible. */
856 curs_x
= 0; /* Nominal cursor position is top left. */
861 XClear (FRAME_X_WINDOW (f
));
863 /* We have to clear the scroll bars, too. If we have changed
864 colors or something like that, then they should be notified. */
865 x_scroll_bar_clear (f
);
872 /* This currently does not work because FRAME_CURRENT_GLYPHS doesn't
873 always contain the right glyphs to use.
875 It also needs to be changed to look at the details of the font and
876 see whether there is really overlap, and do nothing when there is
877 not. This can use font_char_overlap_left and font_char_overlap_right,
878 but just how to use them is not clear. */
880 /* Erase the character (if any) at the position just before X, Y in frame F,
881 then redraw it and the character before it.
882 This is necessary when we erase starting at X,
883 in case the character after X overlaps into the one before X.
884 Call this function with input blocked. */
887 redraw_previous_char (f
, x
, y
, highlight_flag
)
892 /* Erase the character before the new ones, in case
893 what was here before overlaps it.
894 Reoutput that character, and the previous character
895 (in case the previous character overlaps it). */
901 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
902 CHAR_TO_PIXEL_COL (f
, x
- 1),
903 CHAR_TO_PIXEL_ROW (f
, y
),
904 FONT_WIDTH (f
->display
.x
->font
),
905 f
->display
.x
->line_height
, False
);
907 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, start_x
),
908 CHAR_TO_PIXEL_ROW (f
, y
),
909 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][start_x
],
910 x
- start_x
, highlight_flag
, 1);
914 /* Erase the character (if any) at the position X, Y in frame F,
915 then redraw it and the character after it.
916 This is necessary when we erase endng at X,
917 in case the character after X overlaps into the one before X.
918 Call this function with input blocked. */
921 redraw_following_char (f
, x
, y
, highlight_flag
)
926 int limit
= FRAME_CURRENT_GLYPHS (f
)->used
[y
];
927 /* Erase the character after the new ones, in case
928 what was here before overlaps it.
929 Reoutput that character, and the following character
930 (in case the following character overlaps it). */
932 && FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
] != SPACEGLYPH
)
937 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
938 CHAR_TO_PIXEL_COL (f
, x
),
939 CHAR_TO_PIXEL_ROW (f
, y
),
940 FONT_WIDTH (f
->display
.x
->font
),
941 f
->display
.x
->line_height
, False
);
943 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, x
),
944 CHAR_TO_PIXEL_ROW (f
, y
),
945 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
],
946 end_x
- x
, highlight_flag
, 1);
951 #if 0 /* Not in use yet */
953 /* Return 1 if character C in font F extends past its left edge. */
956 font_char_overlap_left (font
, c
)
962 /* Find the bounding-box info for C. */
963 if (font
->per_char
== 0)
964 s
= &font
->max_bounds
;
967 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
970 /* Decode char into row number (byte 1) and code within row (byte 2). */
973 if (!(within
>= font
->min_char_or_byte2
974 && within
<= font
->max_char_or_byte2
975 && row
>= font
->min_byte1
976 && row
<= font
->max_byte1
))
978 /* If char is out of range, try the font's default char instead. */
979 c
= font
->default_char
;
980 row
= c
>> (INTBITS
- 8);
983 if (!(within
>= font
->min_char_or_byte2
984 && within
<= font
->max_char_or_byte2
985 && row
>= font
->min_byte1
986 && row
<= font
->max_byte1
))
987 /* Still out of range means this char does not overlap. */
990 /* We found the info for this char. */
991 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
995 return (s
&& s
->lbearing
< 0);
998 /* Return 1 if character C in font F extends past its right edge. */
1001 font_char_overlap_right (font
, c
)
1007 /* Find the bounding-box info for C. */
1008 if (font
->per_char
== 0)
1009 s
= &font
->max_bounds
;
1012 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
1015 /* Decode char into row number (byte 1) and code within row (byte 2). */
1018 if (!(within
>= font
->min_char_or_byte2
1019 && within
<= font
->max_char_or_byte2
1020 && row
>= font
->min_byte1
1021 && row
<= font
->max_byte1
))
1023 /* If char is out of range, try the font's default char instead. */
1024 c
= font
->default_char
;
1025 row
= c
>> (INTBITS
- 8);
1028 if (!(within
>= font
->min_char_or_byte2
1029 && within
<= font
->max_char_or_byte2
1030 && row
>= font
->min_byte1
1031 && row
<= font
->max_byte1
))
1032 /* Still out of range means this char does not overlap. */
1035 /* We found the info for this char. */
1036 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1040 return (s
&& s
->rbearing
>= s
->width
);
1044 /* Invert the middle quarter of the frame for .15 sec. */
1046 /* We use the select system call to do the waiting, so we have to make sure
1047 it's available. If it isn't, we just won't do visual bells. */
1048 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1050 /* Subtract the `struct timeval' values X and Y,
1051 storing the result in RESULT.
1052 Return 1 if the difference is negative, otherwise 0. */
1055 timeval_subtract (result
, x
, y
)
1056 struct timeval
*result
, x
, y
;
1058 /* Perform the carry for the later subtraction by updating y.
1059 This is safer because on some systems
1060 the tv_sec member is unsigned. */
1061 if (x
.tv_usec
< y
.tv_usec
)
1063 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
1064 y
.tv_usec
-= 1000000 * nsec
;
1067 if (x
.tv_usec
- y
.tv_usec
> 1000000)
1069 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
1070 y
.tv_usec
+= 1000000 * nsec
;
1074 /* Compute the time remaining to wait. tv_usec is certainly positive. */
1075 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
1076 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
1078 /* Return indication of whether the result should be considered negative. */
1079 return x
.tv_sec
< y
.tv_sec
;
1090 /* Create a GC that will use the GXxor function to flip foreground pixels
1091 into background pixels. */
1095 values
.function
= GXxor
;
1096 values
.foreground
= (f
->display
.x
->foreground_pixel
1097 ^ f
->display
.x
->background_pixel
);
1099 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
1100 GCFunction
| GCForeground
, &values
);
1104 int width
= PIXEL_WIDTH (f
);
1105 int height
= PIXEL_HEIGHT (f
);
1107 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
1108 width
/4, height
/4, width
/2, height
/2);
1109 XFlush (x_current_display
);
1112 struct timeval wakeup
, now
;
1114 EMACS_GET_TIME (wakeup
);
1116 /* Compute time to wait until, propagating carry from usecs. */
1117 wakeup
.tv_usec
+= 150000;
1118 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
1119 wakeup
.tv_usec
%= 1000000;
1121 /* Keep waiting until past the time wakeup. */
1124 struct timeval timeout
;
1126 EMACS_GET_TIME (timeout
);
1128 /* In effect, timeout = wakeup - timeout.
1129 Break if result would be negative. */
1130 if (timeval_subtract (&timeout
, wakeup
, timeout
))
1133 /* Try to wait that long--but we might wake up sooner. */
1134 select (0, 0, 0, 0, &timeout
);
1138 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
1139 width
/4, height
/4, width
/2, height
/2);
1140 XFreeGC (x_current_display
, gc
);
1141 XFlush (x_current_display
);
1151 /* Make audible bell. */
1153 #define XRINGBELL XBell (x_current_display, 0)
1157 if (x_current_display
== 0)
1160 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1162 XTflash (selected_frame
);
1173 /* Insert and delete character.
1174 These are not supposed to be used because we are supposed to turn
1175 off the feature of using them. */
1178 XTinsert_glyphs (start
, len
)
1179 register char *start
;
1192 /* Specify how many text lines, from the top of the window,
1193 should be affected by insert-lines and delete-lines operations.
1194 This, and those operations, are used only within an update
1195 that is bounded by calls to XTupdate_begin and XTupdate_end. */
1198 XTset_terminal_window (n
)
1201 if (updating_frame
== 0)
1204 if ((n
<= 0) || (n
> updating_frame
->height
))
1205 flexlines
= updating_frame
->height
;
1210 /* Perform an insert-lines operation.
1211 Insert N lines at a vertical position curs_y. */
1217 register int topregion
, bottomregion
;
1218 register int length
, newtop
, mask
;
1219 register struct frame
*f
= updating_frame
;
1220 int intborder
= f
->display
.x
->internal_border_width
;
1222 if (curs_y
>= flexlines
)
1226 bottomregion
= flexlines
- (n
+ 1);
1227 newtop
= topregion
+ n
;
1228 length
= (bottomregion
- topregion
) + 1;
1230 if ((length
> 0) && (newtop
<= flexlines
))
1231 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
1232 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
1233 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
1234 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1235 length
* f
->display
.x
->line_height
, intborder
,
1236 CHAR_TO_PIXEL_ROW (f
, newtop
));
1238 newtop
= min (newtop
, (flexlines
- 1));
1239 length
= newtop
- topregion
;
1241 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
1242 CHAR_TO_PIXEL_ROW (f
, topregion
),
1243 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1244 n
* f
->display
.x
->line_height
, False
);
1247 /* Perform a delete-lines operation, deleting N lines
1248 at a vertical position curs_y. */
1255 register struct frame
*f
= updating_frame
;
1256 int intborder
= f
->display
.x
->internal_border_width
;
1258 if (curs_y
>= flexlines
)
1261 if ((curs_y
+ n
) >= flexlines
)
1263 if (flexlines
>= (curs_y
+ 1))
1264 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
1265 CHAR_TO_PIXEL_ROW (f
, curs_y
),
1266 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1267 (flexlines
- curs_y
) * f
->display
.x
->line_height
, False
);
1271 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
1272 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
1274 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
1275 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1276 (flexlines
- (curs_y
+ n
)) * f
->display
.x
->line_height
,
1277 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
));
1278 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
1280 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
1281 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1282 n
* f
->display
.x
->line_height
, False
);
1286 /* Perform an insert-lines or delete-lines operation,
1287 inserting N lines or deleting -N lines at vertical position VPOS. */
1289 XTins_del_lines (vpos
, n
)
1292 if (updating_frame
== 0)
1295 /* Hide the cursor. */
1296 x_display_cursor (updating_frame
, 0);
1298 XTcursor_to (vpos
, 0);
1309 /* Support routines for exposure events. */
1310 static void clear_cursor ();
1312 /* Output into a rectangle of an X-window (for frame F)
1313 the characters in f->phys_lines that overlap that rectangle.
1314 TOP and LEFT are the position of the upper left corner of the rectangle.
1315 ROWS and COLS are the size of the rectangle.
1316 Call this function with input blocked. */
1319 dumprectangle (f
, left
, top
, cols
, rows
)
1321 register int left
, top
, cols
, rows
;
1323 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1324 int cursor_cleared
= 0;
1328 if (FRAME_GARBAGED_P (f
))
1331 /* Express rectangle as four edges, instead of position-and-size. */
1332 bottom
= top
+ rows
;
1333 right
= left
+ cols
;
1335 /* Convert rectangle edges in pixels to edges in chars.
1336 Round down for left and top, up for right and bottom. */
1337 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1338 left
= PIXEL_TO_CHAR_COL (f
, left
);
1339 bottom
+= (f
->display
.x
->line_height
- 1);
1340 right
+= (FONT_WIDTH (f
->display
.x
->font
) - 1);
1341 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1342 right
= PIXEL_TO_CHAR_COL (f
, right
);
1344 /* Clip the rectangle to what can be visible. */
1349 if (right
> f
->width
)
1351 if (bottom
> f
->height
)
1354 /* Get size in chars of the rectangle. */
1355 cols
= right
- left
;
1356 rows
= bottom
- top
;
1358 /* If rectangle has zero area, return. */
1359 if (rows
<= 0) return;
1360 if (cols
<= 0) return;
1362 /* Turn off the cursor if it is in the rectangle.
1363 We will turn it back on afterward. */
1364 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1365 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1371 /* Display the text in the rectangle, one text line at a time. */
1373 for (y
= top
; y
< bottom
; y
++)
1375 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1377 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1381 CHAR_TO_PIXEL_COL (f
, left
),
1382 CHAR_TO_PIXEL_ROW (f
, y
),
1383 line
, min (cols
, active_frame
->used
[y
] - left
),
1384 active_frame
->highlight
[y
], 0);
1387 /* Turn the cursor on if we turned it off. */
1390 x_display_cursor (f
, 1);
1394 frame_highlight (frame
)
1395 struct frame
*frame
;
1397 /* We used to only do this if Vx_no_window_manager was non-nil, but
1398 the ICCCM (section 4.1.6) says that the window's border pixmap
1399 and border pixel are window attributes which are "private to the
1400 client", so we can always change it to whatever we want. */
1402 XSetWindowBorder (x_current_display
, FRAME_X_WINDOW (frame
),
1403 frame
->display
.x
->border_pixel
);
1405 x_display_cursor (frame
, 1);
1409 frame_unhighlight (frame
)
1410 struct frame
*frame
;
1412 /* We used to only do this if Vx_no_window_manager was non-nil, but
1413 the ICCCM (section 4.1.6) says that the window's border pixmap
1414 and border pixel are window attributes which are "private to the
1415 client", so we can always change it to whatever we want. */
1417 XSetWindowBorderPixmap (x_current_display
, FRAME_X_WINDOW (frame
),
1418 frame
->display
.x
->border_tile
);
1420 x_display_cursor (frame
, 1);
1423 static void XTframe_rehighlight ();
1425 /* The focus has changed. Update the frames as necessary to reflect
1426 the new situation. Note that we can't change the selected frame
1427 here, because the lisp code we are interrupting might become confused.
1428 Each event gets marked with the frame in which it occurred, so the
1429 lisp code can tell when the switch took place by examining the events. */
1432 x_new_focus_frame (frame
)
1433 struct frame
*frame
;
1435 struct frame
*old_focus
= x_focus_frame
;
1436 int events_enqueued
= 0;
1438 if (frame
!= x_focus_frame
)
1440 /* Set this before calling other routines, so that they see
1441 the correct value of x_focus_frame. */
1442 x_focus_frame
= frame
;
1444 if (old_focus
&& old_focus
->auto_lower
)
1445 x_lower_frame (old_focus
);
1448 selected_frame
= frame
;
1449 XSET (XWINDOW (selected_frame
->selected_window
)->frame
,
1450 Lisp_Frame
, selected_frame
);
1451 Fselect_window (selected_frame
->selected_window
);
1452 choose_minibuf_frame ();
1455 if (x_focus_frame
&& x_focus_frame
->auto_raise
)
1456 pending_autoraise_frame
= x_focus_frame
;
1458 pending_autoraise_frame
= 0;
1461 XTframe_rehighlight ();
1465 /* The focus has changed, or we have redirected a frame's focus to
1466 another frame (this happens when a frame uses a surrogate
1467 minibuffer frame). Shift the highlight as appropriate. */
1469 XTframe_rehighlight ()
1471 struct frame
*old_highlight
= x_highlight_frame
;
1476 ((XGCTYPE (FRAME_FOCUS_FRAME (x_focus_frame
)) == Lisp_Frame
)
1477 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame
))
1479 if (! FRAME_LIVE_P (x_highlight_frame
))
1481 FRAME_FOCUS_FRAME (x_focus_frame
) = Qnil
;
1482 x_highlight_frame
= x_focus_frame
;
1486 x_highlight_frame
= 0;
1488 if (x_highlight_frame
!= old_highlight
)
1491 frame_unhighlight (old_highlight
);
1492 if (x_highlight_frame
)
1493 frame_highlight (x_highlight_frame
);
1497 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
1499 /* Which modifier keys are on which modifier bits?
1501 With each keystroke, X returns eight bits indicating which modifier
1502 keys were held down when the key was pressed. The interpretation
1503 of the top five modifier bits depends on what keys are attached
1504 to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
1507 x_meta_mod_mask is a mask containing the bits used for the meta key.
1508 It may have more than one bit set, if more than one modifier bit
1509 has meta keys on it. Basically, if EVENT is a KeyPress event,
1510 the meta key is pressed if (EVENT.state & x_meta_mod_mask) != 0.
1512 x_shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
1513 lock modifier bit, or zero otherwise. Non-alphabetic keys should
1514 only be affected by the lock modifier bit if XK_Shift_Lock is in
1515 use; XK_Caps_Lock should only affect alphabetic keys. With this
1516 arrangement, the lock modifier should shift the character if
1517 (EVENT.state & x_shift_lock_mask) != 0. */
1518 static int x_meta_mod_mask
, x_shift_lock_mask
;
1520 /* These are like x_meta_mod_mask, but for different modifiers. */
1521 static int x_alt_mod_mask
, x_super_mod_mask
, x_hyper_mod_mask
;
1523 /* Initialize mode_switch_bit and modifier_meaning. */
1525 x_find_modifier_meanings ()
1527 int min_code
, max_code
;
1530 XModifierKeymap
*mods
;
1532 x_meta_mod_mask
= 0;
1533 x_shift_lock_mask
= 0;
1535 x_super_mod_mask
= 0;
1536 x_hyper_mod_mask
= 0;
1539 XDisplayKeycodes (x_current_display
, &min_code
, &max_code
);
1541 min_code
= x_current_display
->min_keycode
;
1542 max_code
= x_current_display
->max_keycode
;
1545 syms
= XGetKeyboardMapping (x_current_display
,
1546 min_code
, max_code
- min_code
+ 1,
1548 mods
= XGetModifierMapping (x_current_display
);
1550 /* Scan the modifier table to see which modifier bits the Meta and
1551 Alt keysyms are on. */
1553 int row
, col
; /* The row and column in the modifier table. */
1555 for (row
= 3; row
< 8; row
++)
1556 for (col
= 0; col
< mods
->max_keypermod
; col
++)
1559 mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
1561 /* Zeroes are used for filler. Skip them. */
1565 /* Are any of this keycode's keysyms a meta key? */
1569 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
1571 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
1577 x_meta_mod_mask
|= (1 << row
);
1582 x_alt_mod_mask
|= (1 << row
);
1587 x_hyper_mod_mask
|= (1 << row
);
1592 x_super_mod_mask
|= (1 << row
);
1596 /* Ignore this if it's not on the lock modifier. */
1597 if ((1 << row
) == LockMask
)
1598 x_shift_lock_mask
= LockMask
;
1606 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1607 if (! x_meta_mod_mask
)
1609 x_meta_mod_mask
= x_alt_mod_mask
;
1613 /* If some keys are both alt and meta,
1614 make them just meta, not alt. */
1615 if (x_alt_mod_mask
& x_meta_mod_mask
)
1617 x_alt_mod_mask
&= ~x_meta_mod_mask
;
1620 XFree ((char *) syms
);
1621 XFreeModifiermap (mods
);
1624 /* Convert between the modifier bits X uses and the modifier bits
1627 x_x_to_emacs_modifiers (state
)
1630 return ( ((state
& (ShiftMask
| x_shift_lock_mask
)) ? shift_modifier
: 0)
1631 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
1632 | ((state
& x_meta_mod_mask
) ? meta_modifier
: 0)
1633 | ((state
& x_alt_mod_mask
) ? alt_modifier
: 0)
1634 | ((state
& x_super_mod_mask
) ? super_modifier
: 0)
1635 | ((state
& x_hyper_mod_mask
) ? hyper_modifier
: 0));
1639 x_emacs_to_x_modifiers (state
)
1642 return ( ((state
& alt_modifier
) ? x_alt_mod_mask
: 0)
1643 | ((state
& super_modifier
) ? x_super_mod_mask
: 0)
1644 | ((state
& hyper_modifier
) ? x_hyper_mod_mask
: 0)
1645 | ((state
& shift_modifier
) ? ShiftMask
: 0)
1646 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
1647 | ((state
& meta_modifier
) ? x_meta_mod_mask
: 0));
1650 /* Mouse clicks and mouse movement. Rah. */
1652 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1653 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1654 that the glyph at X, Y occupies, if BOUNDS != 0.
1655 If NOCLIP is nonzero, do not force the value into range. */
1658 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1660 register int pix_x
, pix_y
;
1661 register int *x
, *y
;
1665 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1666 even for negative values. */
1668 pix_x
-= FONT_WIDTH ((f
)->display
.x
->font
) - 1;
1670 pix_y
-= (f
)->display
.x
->line_height
- 1;
1672 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1673 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1677 bounds
->width
= FONT_WIDTH (f
->display
.x
->font
);
1678 bounds
->height
= f
->display
.x
->line_height
;
1679 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1680 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1687 else if (pix_x
> f
->width
)
1692 else if (pix_y
> f
->height
)
1701 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1704 register int *pix_x
, *pix_y
;
1706 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
1707 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
1710 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1712 If the event is a button press, then note that we have grabbed
1716 construct_mouse_click (result
, event
, f
)
1717 struct input_event
*result
;
1718 XButtonEvent
*event
;
1721 /* Make the event type no_event; we'll change that when we decide
1723 result
->kind
= mouse_click
;
1724 result
->code
= event
->button
- Button1
;
1725 result
->timestamp
= event
->time
;
1726 result
->modifiers
= (x_x_to_emacs_modifiers (event
->state
)
1727 | (event
->type
== ButtonRelease
1735 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
, 0);
1736 XFASTINT (result
->x
) = column
;
1737 XFASTINT (result
->y
) = row
;
1739 XSET (result
->x
, Lisp_Int
, event
->x
);
1740 XSET (result
->y
, Lisp_Int
, event
->y
);
1741 XSET (result
->frame_or_window
, Lisp_Frame
, f
);
1745 /* Prepare a menu-event in *RESULT for placement in the input queue. */
1748 construct_menu_click (result
, event
, f
)
1749 struct input_event
*result
;
1750 XButtonEvent
*event
;
1753 /* Make the event type no_event; we'll change that when we decide
1755 result
->kind
= mouse_click
;
1756 XSET (result
->code
, Lisp_Int
, event
->button
- Button1
);
1757 result
->timestamp
= event
->time
;
1758 result
->modifiers
= (x_x_to_emacs_modifiers (event
->state
)
1759 | (event
->type
== ButtonRelease
1763 XSET (result
->x
, Lisp_Int
, event
->x
);
1764 XSET (result
->y
, Lisp_Int
, -1);
1765 XSET (result
->frame_or_window
, Lisp_Frame
, f
);
1768 /* Function to report a mouse movement to the mainstream Emacs code.
1769 The input handler calls this.
1771 We have received a mouse movement event, which is given in *event.
1772 If the mouse is over a different glyph than it was last time, tell
1773 the mainstream emacs code by setting mouse_moved. If not, ask for
1774 another motion event, so we can check again the next time it moves. */
1777 note_mouse_movement (frame
, event
)
1779 XMotionEvent
*event
;
1782 last_mouse_movement_time
= event
->time
;
1784 if (event
->window
!= FRAME_X_WINDOW (frame
))
1787 last_mouse_scroll_bar
= Qnil
;
1789 note_mouse_highlight (frame
, -1, -1);
1791 /* Ask for another mouse motion event. */
1794 Window dummy_window
;
1796 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
1797 &dummy_window
, &dummy_window
,
1798 &dummy
, &dummy
, &dummy
, &dummy
,
1799 (unsigned int *) &dummy
);
1803 /* Has the mouse moved off the glyph it was on at the last sighting? */
1804 else if (event
->x
< last_mouse_glyph
.x
1805 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
1806 || event
->y
< last_mouse_glyph
.y
1807 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
1810 last_mouse_scroll_bar
= Qnil
;
1812 note_mouse_highlight (frame
, event
->x
, event
->y
);
1814 /* Ask for another mouse motion event. */
1817 Window dummy_window
;
1819 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
1820 &dummy_window
, &dummy_window
,
1821 &dummy
, &dummy
, &dummy
, &dummy
,
1822 (unsigned int *) &dummy
);
1827 /* It's on the same glyph. Call XQueryPointer so we'll get an
1828 event the next time the mouse moves and we can see if it's
1829 *still* on the same glyph. */
1831 Window dummy_window
;
1833 XQueryPointer (event
->display
, FRAME_X_WINDOW (frame
),
1834 &dummy_window
, &dummy_window
,
1835 &dummy
, &dummy
, &dummy
, &dummy
,
1836 (unsigned int *) &dummy
);
1840 /* This is used for debugging, to turn off note_mouse_highlight. */
1841 static int disable_mouse_highlight
;
1843 /* Take proper action when the mouse has moved to position X, Y on frame F
1844 as regards highlighting characters that have mouse-face properties.
1845 Also dehighlighting chars where the mouse was before.
1846 X and Y can be negative or out of range. */
1849 note_mouse_highlight (f
, x
, y
)
1852 int row
, column
, portion
;
1853 XRectangle new_glyph
;
1857 if (disable_mouse_highlight
)
1860 mouse_face_mouse_x
= x
;
1861 mouse_face_mouse_y
= y
;
1862 mouse_face_mouse_frame
= f
;
1864 if (mouse_face_defer
)
1869 mouse_face_deferred_gc
= 1;
1873 /* Find out which glyph the mouse is on. */
1874 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
1875 &new_glyph
, x_mouse_grabbed
);
1877 /* Which window is that in? */
1878 window
= window_from_coordinates (f
, column
, row
, &portion
);
1879 w
= XWINDOW (window
);
1881 /* If we were displaying active text in another window, clear that. */
1882 if (! EQ (window
, mouse_face_window
))
1883 clear_mouse_face ();
1885 /* Are we in a window whose display is up to date?
1886 And verify the buffer's text has not changed. */
1887 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
1888 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
1889 && EQ (w
->window_end_valid
, w
->buffer
)
1890 && w
->last_modified
== BUF_MODIFF (XBUFFER (w
->buffer
)))
1892 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
1895 /* Find which buffer position the mouse corresponds to. */
1896 for (i
= column
; i
>= 0; i
--)
1900 /* Is it outside the displayed active region (if any)? */
1902 clear_mouse_face ();
1903 else if (! (EQ (window
, mouse_face_window
)
1904 && row
>= mouse_face_beg_row
1905 && row
<= mouse_face_end_row
1906 && (row
> mouse_face_beg_row
|| column
>= mouse_face_beg_col
)
1907 && (row
< mouse_face_end_row
|| column
< mouse_face_end_col
1908 || mouse_face_past_end
)))
1910 Lisp_Object mouse_face
, overlay
, position
;
1911 Lisp_Object
*overlay_vec
;
1912 int len
, noverlays
, ignor1
;
1913 struct buffer
*obuf
;
1916 /* If we get an out-of-range value, return now; avoid an error. */
1917 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
1920 /* Make the window's buffer temporarily current for
1921 overlays_at and compute_char_face. */
1922 obuf
= current_buffer
;
1923 current_buffer
= XBUFFER (w
->buffer
);
1929 /* Yes. Clear the display of the old active region, if any. */
1930 clear_mouse_face ();
1932 /* Is this char mouse-active? */
1933 XSET (position
, Lisp_Int
, pos
);
1936 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
1938 /* Put all the overlays we want in a vector in overlay_vec.
1939 Store the length in len. */
1940 noverlays
= overlays_at (XINT (pos
), 1, &overlay_vec
, &len
,
1942 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
1944 /* Find the highest priority overlay that has a mouse-face prop. */
1946 for (i
= 0; i
< noverlays
; i
++)
1948 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
1949 if (!NILP (mouse_face
))
1951 overlay
= overlay_vec
[i
];
1956 /* If no overlay applies, get a text property. */
1958 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
1960 /* Handle the overlay case. */
1961 if (! NILP (overlay
))
1963 /* Find the range of text around this char that
1964 should be active. */
1965 Lisp_Object before
, after
;
1968 before
= Foverlay_start (overlay
);
1969 after
= Foverlay_end (overlay
);
1970 /* Record this as the current active region. */
1971 fast_find_position (window
, before
, &mouse_face_beg_col
,
1972 &mouse_face_beg_row
);
1974 = !fast_find_position (window
, after
, &mouse_face_end_col
,
1975 &mouse_face_end_row
);
1976 mouse_face_window
= window
;
1977 mouse_face_face_id
= compute_char_face (f
, w
, pos
, 0, 0,
1978 &ignore
, pos
+ 1, 1);
1980 /* Display it as active. */
1981 show_mouse_face (1);
1983 /* Handle the text property case. */
1984 else if (! NILP (mouse_face
))
1986 /* Find the range of text around this char that
1987 should be active. */
1988 Lisp_Object before
, after
, beginning
, end
;
1991 beginning
= Fmarker_position (w
->start
);
1992 XSET (end
, Lisp_Int
,
1993 (BUF_Z (XBUFFER (w
->buffer
))
1994 - XFASTINT (w
->window_end_pos
)));
1996 = Fprevious_single_property_change (make_number (pos
+ 1),
1998 w
->buffer
, beginning
);
2000 = Fnext_single_property_change (position
, Qmouse_face
,
2002 /* Record this as the current active region. */
2003 fast_find_position (window
, before
, &mouse_face_beg_col
,
2004 &mouse_face_beg_row
);
2006 = !fast_find_position (window
, after
, &mouse_face_end_col
,
2007 &mouse_face_end_row
);
2008 mouse_face_window
= window
;
2010 = compute_char_face (f
, w
, pos
, 0, 0,
2011 &ignore
, pos
+ 1, 1);
2013 /* Display it as active. */
2014 show_mouse_face (1);
2018 current_buffer
= obuf
;
2023 /* Find the row and column of position POS in window WINDOW.
2024 Store them in *COLUMNP and *ROWP.
2025 This assumes display in WINDOW is up to date.
2026 If POS is above start of WINDOW, return coords
2027 of start of first screen line.
2028 If POS is after end of WINDOW, return coords of end of last screen line.
2030 Value is 1 if POS is in range, 0 if it was off screen. */
2033 fast_find_position (window
, pos
, columnp
, rowp
)
2036 int *columnp
, *rowp
;
2038 struct window
*w
= XWINDOW (window
);
2039 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2044 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
2045 int width
= window_internal_width (w
);
2049 /* Find the right row. */
2054 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
2055 if (linestart
> pos
)
2061 /* Find the right column with in it. */
2062 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
2064 for (i
= 0; i
< width
; i
++)
2066 if (charstarts
[left
+ i
] == pos
)
2069 *columnp
= i
+ left
;
2072 else if (charstarts
[left
+ i
] > pos
)
2074 else if (charstarts
[left
+ i
] > 0)
2083 /* Display the active region described by mouse_face_*
2084 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2087 show_mouse_face (hl
)
2090 struct window
*w
= XWINDOW (mouse_face_window
);
2091 int width
= window_internal_width (w
);
2092 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2095 int old_curs_x
= curs_x
;
2096 int old_curs_y
= curs_y
;
2098 /* Set these variables temporarily
2099 so that if we have to turn the cursor off and on again
2100 we will put it back at the same place. */
2101 curs_x
= f
->phys_cursor_x
;
2102 curs_y
= f
->phys_cursor_y
;
2104 for (i
= mouse_face_beg_row
; i
<= mouse_face_end_row
; i
++)
2106 int column
= (i
== mouse_face_beg_row
? mouse_face_beg_col
: w
->left
);
2107 int endcolumn
= (i
== mouse_face_end_row
? mouse_face_end_col
: w
->left
+ width
);
2108 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
]);
2110 /* If the cursor's in the text we are about to rewrite,
2111 turn the cursor off. */
2113 && curs_x
>= mouse_face_beg_col
- 1 && curs_x
<= mouse_face_end_col
)
2115 x_display_cursor (f
, 0);
2120 CHAR_TO_PIXEL_COL (f
, column
),
2121 CHAR_TO_PIXEL_ROW (f
, i
),
2122 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
2124 /* Highlight with mouse face if hl > 0. */
2128 /* If we turned the cursor off, turn it back on. */
2130 x_display_cursor (f
, 1);
2132 curs_x
= old_curs_x
;
2133 curs_y
= old_curs_y
;
2135 /* Change the mouse cursor according to the value of HL. */
2137 XDefineCursor (XDISPLAY
FRAME_X_WINDOW (f
), f
->display
.x
->cross_cursor
);
2139 XDefineCursor (XDISPLAY
FRAME_X_WINDOW (f
), f
->display
.x
->text_cursor
);
2142 /* Clear out the mouse-highlighted active region.
2143 Redraw it unhighlighted first. */
2148 if (! NILP (mouse_face_window
))
2149 show_mouse_face (0);
2151 mouse_face_beg_row
= mouse_face_beg_col
= -1;
2152 mouse_face_end_row
= mouse_face_end_col
= -1;
2153 mouse_face_window
= Qnil
;
2156 static struct scroll_bar
*x_window_to_scroll_bar ();
2157 static void x_scroll_bar_report_motion ();
2159 /* Return the current position of the mouse.
2161 If the mouse movement started in a scroll bar, set *f, *bar_window,
2162 and *part to the frame, window, and scroll bar part that the mouse
2163 is over. Set *x and *y to the portion and whole of the mouse's
2164 position on the scroll bar.
2166 If the mouse movement started elsewhere, set *f to the frame the
2167 mouse is on, *bar_window to nil, and *x and *y to the character cell
2170 Set *time to the server timestamp for the time at which the mouse
2171 was at this position.
2173 Don't store anything if we don't have a valid set of values to report.
2175 This clears the mouse_moved flag, so we can wait for the next mouse
2176 movement. This also calls XQueryPointer, which will cause the
2177 server to give us another MotionNotify when the mouse moves
2181 XTmouse_position (f
, bar_window
, part
, x
, y
, time
)
2183 Lisp_Object
*bar_window
;
2184 enum scroll_bar_part
*part
;
2186 unsigned long *time
;
2192 if (! NILP (last_mouse_scroll_bar
))
2193 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
);
2199 Window dummy_window
;
2203 last_mouse_scroll_bar
= Qnil
;
2205 /* Figure out which root window we're on. */
2206 XQueryPointer (x_current_display
,
2207 DefaultRootWindow (x_current_display
),
2209 /* The root window which contains the pointer. */
2212 /* Trash which we can't trust if the pointer is on
2213 a different screen. */
2216 /* The position on that root window. */
2219 /* More trash we can't trust. */
2222 /* Modifier keys and pointer buttons, about which
2224 (unsigned int *) &dummy
);
2226 /* Now we have a position on the root; find the innermost window
2227 containing the pointer. */
2231 int parent_x
, parent_y
;
2235 if (x_mouse_grabbed
&& last_mouse_frame
2236 && FRAME_LIVE_P (last_mouse_frame
))
2238 /* If mouse was grabbed on a frame, give coords for that frame
2239 even if the mouse is now outside it. */
2240 XTranslateCoordinates (x_current_display
,
2242 /* From-window, to-window. */
2243 root
, FRAME_X_WINDOW (last_mouse_frame
),
2245 /* From-position, to-position. */
2246 root_x
, root_y
, &win_x
, &win_y
,
2250 f1
= last_mouse_frame
;
2256 XTranslateCoordinates (x_current_display
,
2258 /* From-window, to-window. */
2261 /* From-position, to-position. */
2262 root_x
, root_y
, &win_x
, &win_y
,
2275 /* Now we know that:
2276 win is the innermost window containing the pointer
2277 (XTC says it has no child containing the pointer),
2278 win_x and win_y are the pointer's position in it
2279 (XTC did this the last time through), and
2280 parent_x and parent_y are the pointer's position in win's parent.
2281 (They are what win_x and win_y were when win was child.
2282 If win is the root window, it has no parent, and
2283 parent_{x,y} are invalid, but that's okay, because we'll
2284 never use them in that case.) */
2286 /* Is win one of our frames? */
2287 f1
= x_any_window_to_frame (win
);
2290 /* If not, is it one of our scroll bars? */
2293 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
2297 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2305 int ignore1
, ignore2
;
2307 /* Ok, we found a frame. Store all the values. */
2309 pixel_to_glyph_coords (f1
, win_x
, win_y
, &ignore1
, &ignore2
,
2310 &last_mouse_glyph
, x_mouse_grabbed
);
2315 XSET (*x
, Lisp_Int
, win_x
);
2316 XSET (*y
, Lisp_Int
, win_y
);
2317 *time
= last_mouse_movement_time
;
2325 /* Scroll bar support. */
2327 /* Given an X window ID, find the struct scroll_bar which manages it.
2328 This can be called in GC, so we have to make sure to strip off mark
2330 static struct scroll_bar
*
2331 x_window_to_scroll_bar (window_id
)
2334 Lisp_Object tail
, frame
;
2336 for (tail
= Vframe_list
;
2337 XGCTYPE (tail
) == Lisp_Cons
;
2338 tail
= XCONS (tail
)->cdr
)
2340 Lisp_Object frame
, bar
, condemned
;
2342 frame
= XCONS (tail
)->car
;
2343 /* All elements of Vframe_list should be frames. */
2344 if (XGCTYPE (frame
) != Lisp_Frame
)
2347 /* Scan this frame's scroll bar list for a scroll bar with the
2349 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
2350 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
2351 /* This trick allows us to search both the ordinary and
2352 condemned scroll bar lists with one loop. */
2353 ! GC_NILP (bar
) || (bar
= condemned
,
2356 bar
= XSCROLL_BAR (bar
)->next
)
2357 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
2358 return XSCROLL_BAR (bar
);
2364 /* Open a new X window to serve as a scroll bar, and return the
2365 scroll bar vector for it. */
2366 static struct scroll_bar
*
2367 x_scroll_bar_create (window
, top
, left
, width
, height
)
2368 struct window
*window
;
2369 int top
, left
, width
, height
;
2371 FRAME_PTR frame
= XFRAME (WINDOW_FRAME (window
));
2372 struct scroll_bar
*bar
=
2373 XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2378 XSetWindowAttributes a
;
2380 a
.background_pixel
= frame
->display
.x
->background_pixel
;
2381 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
2382 | ButtonMotionMask
| PointerMotionHintMask
2384 a
.cursor
= x_vertical_scroll_bar_cursor
;
2386 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
2391 XtSetArg (al
[ac
], XtNx
, left
); ac
++;
2392 XtSetArg (al
[ac
], XtNy
, top
); ac
++;
2393 XtSetArg (al
[ac
], XtNwidth
, width
); ac
++;
2394 XtSetArg (al
[ac
], XtNheight
, height
); ac
++;
2395 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
2396 sb_widget
= XtCreateManagedWidget ("box",
2398 frame
->display
.x
->edit_widget
, al
, ac
);
2399 SET_SCROLL_BAR_X_WINDOW
2400 (bar
, sb_widget
->core
.window
);
2402 SET_SCROLL_BAR_X_WINDOW
2404 XCreateWindow (x_current_display
, FRAME_X_WINDOW (frame
),
2406 /* Position and size of scroll bar. */
2407 left
, top
, width
, height
,
2409 /* Border width, depth, class, and visual. */
2410 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
2416 XSET (bar
->window
, Lisp_Window
, window
);
2417 XSET (bar
->top
, Lisp_Int
, top
);
2418 XSET (bar
->left
, Lisp_Int
, left
);
2419 XSET (bar
->width
, Lisp_Int
, width
);
2420 XSET (bar
->height
, Lisp_Int
, height
);
2421 XSET (bar
->start
, Lisp_Int
, 0);
2422 XSET (bar
->end
, Lisp_Int
, 0);
2423 bar
->dragging
= Qnil
;
2425 /* Add bar to its frame's list of scroll bars. */
2426 bar
->next
= FRAME_SCROLL_BARS (frame
);
2428 XSET (FRAME_SCROLL_BARS (frame
), Lisp_Vector
, bar
);
2429 if (! NILP (bar
->next
))
2430 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
2432 XMapWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
2439 /* Draw BAR's handle in the proper position.
2440 If the handle is already drawn from START to END, don't bother
2441 redrawing it, unless REBUILD is non-zero; in that case, always
2442 redraw it. (REBUILD is handy for drawing the handle after expose
2445 Normally, we want to constrain the start and end of the handle to
2446 fit inside its rectangle, but if the user is dragging the scroll bar
2447 handle, we want to let them drag it down all the way, so that the
2448 bar's top is as far down as it goes; otherwise, there's no way to
2449 move to the very end of the buffer. */
2451 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
2452 struct scroll_bar
*bar
;
2456 int dragging
= ! NILP (bar
->dragging
);
2457 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2458 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
2460 /* If the display is already accurate, do nothing. */
2462 && start
== XINT (bar
->start
)
2463 && end
== XINT (bar
->end
))
2469 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar
->width
));
2470 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2471 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2473 /* Make sure the values are reasonable, and try to preserve
2474 the distance between start and end. */
2476 int length
= end
- start
;
2480 else if (start
> top_range
)
2482 end
= start
+ length
;
2486 else if (end
> top_range
&& ! dragging
)
2490 /* Store the adjusted setting in the scroll bar. */
2491 XSET (bar
->start
, Lisp_Int
, start
);
2492 XSET (bar
->end
, Lisp_Int
, end
);
2494 /* Clip the end position, just for display. */
2495 if (end
> top_range
)
2498 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
2499 below top positions, to make sure the handle is always at least
2500 that many pixels tall. */
2501 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2503 /* Draw the empty space above the handle. Note that we can't clear
2504 zero-height areas; that means "clear to end of window." */
2506 XClearArea (x_current_display
, w
,
2508 /* x, y, width, height, and exposures. */
2509 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2510 VERTICAL_SCROLL_BAR_TOP_BORDER
,
2511 inside_width
, start
,
2514 /* Draw the handle itself. */
2515 XFillRectangle (x_current_display
, w
, gc
,
2517 /* x, y, width, height */
2518 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2519 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
2520 inside_width
, end
- start
);
2523 /* Draw the empty space below the handle. Note that we can't
2524 clear zero-height areas; that means "clear to end of window." */
2525 if (end
< inside_height
)
2526 XClearArea (x_current_display
, w
,
2528 /* x, y, width, height, and exposures. */
2529 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2530 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
2531 inside_width
, inside_height
- end
,
2539 /* Move a scroll bar around on the screen, to accommodate changing
2540 window configurations. */
2542 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2543 struct scroll_bar
*bar
;
2544 int top
, left
, width
, height
;
2550 unsigned int mask
= 0;
2557 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
2558 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
2559 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
2560 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
2563 XConfigureWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
),
2567 XSET (bar
->left
, Lisp_Int
, left
);
2568 XSET (bar
->top
, Lisp_Int
, top
);
2569 XSET (bar
->width
, Lisp_Int
, width
);
2570 XSET (bar
->height
, Lisp_Int
, height
);
2575 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2578 x_scroll_bar_remove (bar
)
2579 struct scroll_bar
*bar
;
2581 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2585 /* Destroy the window. */
2586 XDestroyWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
2588 /* Disassociate this scroll bar from its window. */
2589 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2594 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2595 that we are displaying PORTION characters out of a total of WHOLE
2596 characters, starting at POSITION. If WINDOW has no scroll bar,
2599 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
2600 struct window
*window
;
2601 int portion
, whole
, position
;
2603 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2604 int top
= XINT (window
->top
);
2605 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2606 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2608 /* Where should this scroll bar be, pixelwise? */
2609 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2610 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2612 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
2613 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
2614 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->display
.x
->font
)));
2615 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2617 struct scroll_bar
*bar
;
2619 /* Does the scroll bar exist yet? */
2620 if (NILP (window
->vertical_scroll_bar
))
2621 bar
= x_scroll_bar_create (window
,
2622 pixel_top
, pixel_left
,
2623 pixel_width
, pixel_height
);
2626 /* It may just need to be moved and resized. */
2627 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2628 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2631 /* Set the scroll bar's current state, unless we're currently being
2633 if (NILP (bar
->dragging
))
2636 VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2639 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2642 int start
= ((double) position
* top_range
) / whole
;
2643 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
2645 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2649 XSET (window
->vertical_scroll_bar
, Lisp_Vector
, bar
);
2653 /* The following three hooks are used when we're doing a thorough
2654 redisplay of the frame. We don't explicitly know which scroll bars
2655 are going to be deleted, because keeping track of when windows go
2656 away is a real pain - "Can you say set-window-configuration, boys
2657 and girls?" Instead, we just assert at the beginning of redisplay
2658 that *all* scroll bars are to be removed, and then save a scroll bar
2659 from the fiery pit when we actually redisplay its window. */
2661 /* Arrange for all scroll bars on FRAME to be removed at the next call
2662 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2663 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2665 XTcondemn_scroll_bars (frame
)
2668 /* The condemned list should be empty at this point; if it's not,
2669 then the rest of Emacs isn't using the condemn/redeem/judge
2670 protocol correctly. */
2671 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2674 /* Move them all to the "condemned" list. */
2675 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2676 FRAME_SCROLL_BARS (frame
) = Qnil
;
2679 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2680 Note that WINDOW isn't necessarily condemned at all. */
2682 XTredeem_scroll_bar (window
)
2683 struct window
*window
;
2685 struct scroll_bar
*bar
;
2687 /* We can't redeem this window's scroll bar if it doesn't have one. */
2688 if (NILP (window
->vertical_scroll_bar
))
2691 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2693 /* Unlink it from the condemned list. */
2695 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2697 if (NILP (bar
->prev
))
2699 /* If the prev pointer is nil, it must be the first in one of
2701 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2702 /* It's not condemned. Everything's fine. */
2704 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2705 window
->vertical_scroll_bar
))
2706 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2708 /* If its prev pointer is nil, it must be at the front of
2709 one or the other! */
2713 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2715 if (! NILP (bar
->next
))
2716 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2718 bar
->next
= FRAME_SCROLL_BARS (f
);
2720 XSET (FRAME_SCROLL_BARS (f
), Lisp_Vector
, bar
);
2721 if (! NILP (bar
->next
))
2722 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
2726 /* Remove all scroll bars on FRAME that haven't been saved since the
2727 last call to `*condemn_scroll_bars_hook'. */
2729 XTjudge_scroll_bars (f
)
2732 Lisp_Object bar
, next
;
2734 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2736 /* Clear out the condemned list now so we won't try to process any
2737 more events on the hapless scroll bars. */
2738 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2740 for (; ! NILP (bar
); bar
= next
)
2742 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2744 x_scroll_bar_remove (b
);
2747 b
->next
= b
->prev
= Qnil
;
2750 /* Now there should be no references to the condemned scroll bars,
2751 and they should get garbage-collected. */
2755 /* Handle an Expose or GraphicsExpose event on a scroll bar.
2757 This may be called from a signal handler, so we have to ignore GC
2760 x_scroll_bar_expose (bar
, event
)
2761 struct scroll_bar
*bar
;
2764 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2765 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
2769 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
2771 /* Draw a one-pixel border just inside the edges of the scroll bar. */
2772 XDrawRectangle (x_current_display
, w
, gc
,
2774 /* x, y, width, height */
2775 0, 0, XINT (bar
->width
) - 1, XINT (bar
->height
) - 1);
2780 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2781 is set to something other than no_event, it is enqueued.
2783 This may be called from a signal handler, so we have to ignore GC
2786 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
2787 struct scroll_bar
*bar
;
2789 struct input_event
*emacs_event
;
2791 if (XGCTYPE (bar
->window
) != Lisp_Window
)
2794 emacs_event
->kind
= scroll_bar_click
;
2795 emacs_event
->code
= event
->xbutton
.button
- Button1
;
2796 emacs_event
->modifiers
=
2797 (x_x_to_emacs_modifiers (event
->xbutton
.state
)
2798 | (event
->type
== ButtonRelease
2801 emacs_event
->frame_or_window
= bar
->window
;
2802 emacs_event
->timestamp
= event
->xbutton
.time
;
2804 int internal_height
=
2805 VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2807 VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2808 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
2811 if (y
> top_range
) y
= top_range
;
2813 if (y
< XINT (bar
->start
))
2814 emacs_event
->part
= scroll_bar_above_handle
;
2815 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2816 emacs_event
->part
= scroll_bar_handle
;
2818 emacs_event
->part
= scroll_bar_below_handle
;
2820 /* Just because the user has clicked on the handle doesn't mean
2821 they want to drag it. Lisp code needs to be able to decide
2822 whether or not we're dragging. */
2824 /* If the user has just clicked on the handle, record where they're
2826 if (event
->type
== ButtonPress
2827 && emacs_event
->part
== scroll_bar_handle
)
2828 XSET (bar
->dragging
, Lisp_Int
, y
- XINT (bar
->start
));
2831 /* If the user has released the handle, set it to its final position. */
2832 if (event
->type
== ButtonRelease
2833 && ! NILP (bar
->dragging
))
2835 int new_start
= y
- XINT (bar
->dragging
);
2836 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2838 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2839 bar
->dragging
= Qnil
;
2842 /* Same deal here as the other #if 0. */
2844 /* Clicks on the handle are always reported as occurring at the top of
2846 if (emacs_event
->part
== scroll_bar_handle
)
2847 emacs_event
->x
= bar
->start
;
2849 XSET (emacs_event
->x
, Lisp_Int
, y
);
2851 XSET (emacs_event
->x
, Lisp_Int
, y
);
2854 XSET (emacs_event
->y
, Lisp_Int
, top_range
);
2858 /* Handle some mouse motion while someone is dragging the scroll bar.
2860 This may be called from a signal handler, so we have to ignore GC
2863 x_scroll_bar_note_movement (bar
, event
)
2864 struct scroll_bar
*bar
;
2867 last_mouse_movement_time
= event
->xmotion
.time
;
2870 XSET (last_mouse_scroll_bar
, Lisp_Vector
, bar
);
2872 /* If we're dragging the bar, display it. */
2873 if (! GC_NILP (bar
->dragging
))
2875 /* Where should the handle be now? */
2876 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
2878 if (new_start
!= XINT (bar
->start
))
2880 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2882 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2886 /* Call XQueryPointer so we'll get an event the next time the mouse
2887 moves and we can see *still* on the same position. */
2890 Window dummy_window
;
2892 XQueryPointer (event
->xmotion
.display
, event
->xmotion
.window
,
2893 &dummy_window
, &dummy_window
,
2894 &dummy
, &dummy
, &dummy
, &dummy
,
2895 (unsigned int *) &dummy
);
2899 /* Return information to the user about the current position of the mouse
2900 on the scroll bar. */
2902 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
)
2904 Lisp_Object
*bar_window
;
2905 enum scroll_bar_part
*part
;
2907 unsigned long *time
;
2909 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
2911 Window dummy_window
;
2913 unsigned int dummy_mask
;
2917 /* Get the mouse's position relative to the scroll bar window, and
2919 if (! XQueryPointer (x_current_display
,
2920 SCROLL_BAR_X_WINDOW (bar
),
2922 /* Root, child, root x and root y. */
2923 &dummy_window
, &dummy_window
,
2924 &dummy_coord
, &dummy_coord
,
2926 /* Position relative to scroll bar. */
2929 /* Mouse buttons and modifier keys. */
2935 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2937 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2939 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
2941 if (! NILP (bar
->dragging
))
2942 win_y
-= XINT (bar
->dragging
);
2946 if (win_y
> top_range
)
2949 *f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2950 *bar_window
= bar
->window
;
2952 if (! NILP (bar
->dragging
))
2953 *part
= scroll_bar_handle
;
2954 else if (win_y
< XINT (bar
->start
))
2955 *part
= scroll_bar_above_handle
;
2956 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2957 *part
= scroll_bar_handle
;
2959 *part
= scroll_bar_below_handle
;
2961 XSET (*x
, Lisp_Int
, win_y
);
2962 XSET (*y
, Lisp_Int
, top_range
);
2965 last_mouse_scroll_bar
= Qnil
;
2968 *time
= last_mouse_movement_time
;
2974 /* The screen has been cleared so we may have changed foreground or
2975 background colors, and the scroll bars may need to be redrawn.
2976 Clear out the scroll bars, and ask for expose events, so we can
2979 x_scroll_bar_clear (f
)
2984 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
2985 bar
= XSCROLL_BAR (bar
)->next
)
2986 XClearArea (x_current_display
, SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
2990 /* This processes Expose events from the menubar specific X event
2991 loop in menubar.c. This allows to redisplay the frame if necessary
2992 when handling menubar or popup items. */
2995 process_expose_from_menu (event
)
3002 f
= x_window_to_frame (event
.xexpose
.window
);
3005 if (f
->async_visible
== 0)
3007 f
->async_visible
= 1;
3008 f
->async_iconified
= 0;
3009 SET_FRAME_GARBAGED (f
);
3013 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
3014 event
.xexpose
.x
, event
.xexpose
.y
,
3015 event
.xexpose
.width
, event
.xexpose
.height
);
3020 struct scroll_bar
*bar
3021 = x_window_to_scroll_bar (event
.xexpose
.window
);
3024 x_scroll_bar_expose (bar
, &event
);
3030 /* Define a queue to save up SelectionRequest events for later handling. */
3032 struct selection_event_queue
3035 struct selection_event_queue
*next
;
3038 static struct selection_event_queue
*queue
;
3040 /* Nonzero means queue up certain events--don't process them yet. */
3041 static int x_queue_selection_requests
;
3043 /* Queue up an X event *EVENT, to be processed later. */
3046 x_queue_event (event
)
3049 struct selection_event_queue
*queue_tmp
3050 = (struct selection_event_queue
*) malloc (sizeof (struct selection_event_queue
));
3052 if (queue_tmp
!= NULL
)
3054 queue_tmp
->event
= *event
;
3055 queue_tmp
->next
= queue
;
3060 /* Take all the queued events and put them back
3061 so that they get processed afresh. */
3066 while (queue
!= NULL
)
3068 struct selection_event_queue
*queue_tmp
= queue
;
3069 XPutBackEvent (XDISPLAY
&queue_tmp
->event
);
3070 queue
= queue_tmp
->next
;
3071 free ((char *)queue_tmp
);
3075 /* Start queuing SelectionRequest events. */
3078 x_start_queuing_selection_requests ()
3080 x_queue_selection_requests
++;
3083 /* Stop queuing SelectionRequest events. */
3086 x_stop_queuing_selection_requests ()
3088 x_queue_selection_requests
--;
3089 x_unqueue_events ();
3092 /* The main X event-reading loop - XTread_socket. */
3094 /* Timestamp of enter window event. This is only used by XTread_socket,
3095 but we have to put it out here, since static variables within functions
3096 sometimes don't work. */
3097 static Time enter_timestamp
;
3099 /* This holds the state XLookupString needs to implement dead keys
3100 and other tricks known as "compose processing". _X Window System_
3101 says that a portable program can't use this, but Stephen Gildea assures
3102 me that letting the compiler initialize it to zeros will work okay.
3104 This must be defined outside of XTread_socket, for the same reasons
3105 given for enter_timestamp, above. */
3106 static XComposeStatus compose_status
;
3108 /* Communication with window managers. */
3109 Atom Xatom_wm_protocols
;
3111 /* Kinds of protocol things we may receive. */
3112 Atom Xatom_wm_take_focus
;
3113 Atom Xatom_wm_save_yourself
;
3114 Atom Xatom_wm_delete_window
;
3116 /* Other WM communication */
3117 Atom Xatom_wm_configure_denied
; /* When our config request is denied */
3118 Atom Xatom_wm_window_moved
; /* When the WM moves us. */
3120 /* Window manager communication. */
3121 Atom Xatom_wm_change_state
;
3123 /* EditRes protocol */
3124 Atom Xatom_editres_name
;
3126 /* Record the last 100 characters stored
3127 to help debug the loss-of-chars-during-GC problem. */
3129 short temp_buffer
[100];
3131 /* Read events coming from the X server.
3132 This routine is called by the SIGIO handler.
3133 We return as soon as there are no more events to be read.
3135 Events representing keys are stored in buffer BUFP,
3136 which can hold up to NUMCHARS characters.
3137 We return the number of characters stored into the buffer,
3138 thus pretending to be `read'.
3140 WAITP is nonzero if we should block until input arrives.
3141 EXPECTED is nonzero if the caller knows input is available. */
3144 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
3146 register struct input_event
*bufp
;
3147 register int numchars
;
3154 int items_pending
; /* How many items are in the X queue. */
3157 int event_found
= 0;
3161 if (interrupt_input_blocked
)
3163 interrupt_input_pending
= 1;
3167 interrupt_input_pending
= 0;
3171 abort (); /* Don't think this happens. */
3174 /* If available, Xlib uses FIOSNBIO to make the socket
3175 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
3176 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
3177 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
3178 fcntl (fileno (stdin
), F_SETFL
, 0);
3179 #endif /* ! defined (FIOSNBIO) */
3183 if (! (fcntl (fileno (stdin
), F_GETFL
, 0) & O_NDELAY
))
3185 extern int read_alarm_should_throw
;
3186 read_alarm_should_throw
= 1;
3187 XPeekEvent (XDISPLAY
&event
);
3188 read_alarm_should_throw
= 0;
3190 #endif /* HAVE_SELECT */
3193 while (XStuffPending () != 0)
3195 XNextEvent (XDISPLAY
&event
);
3202 if (event
.xclient
.message_type
== Xatom_wm_protocols
3203 && event
.xclient
.format
== 32)
3205 if (event
.xclient
.data
.l
[0] == Xatom_wm_take_focus
)
3207 f
= x_window_to_frame (event
.xclient
.window
);
3208 /* Since we set WM_TAKE_FOCUS, we must call
3209 XSetInputFocus explicitly. But not if f is null,
3210 since that might be an event for a deleted frame. */
3212 XSetInputFocus (event
.xclient
.display
,
3213 event
.xclient
.window
,
3214 RevertToPointerRoot
,
3215 event
.xclient
.data
.l
[1]);
3216 /* Not certain about handling scroll bars here */
3218 else if (event
.xclient
.data
.l
[0] == Xatom_wm_save_yourself
)
3220 /* Save state modify the WM_COMMAND property to
3221 something which can reinstate us. This notifies
3222 the session manager, who's looking for such a
3223 PropertyNotify. Can restart processing when
3224 a keyboard or mouse event arrives. */
3227 /* This is just so we only give real data once
3228 for a single Emacs process. */
3229 if (x_top_window_to_frame (event
.xclient
.window
)
3231 XSetCommand (x_current_display
,
3232 event
.xclient
.window
,
3233 initial_argv
, initial_argc
);
3235 XSetCommand (x_current_display
,
3236 event
.xclient
.window
,
3240 else if (event
.xclient
.data
.l
[0] == Xatom_wm_delete_window
)
3242 struct frame
*f
= x_any_window_to_frame (event
.xclient
.window
);
3249 bufp
->kind
= delete_window_event
;
3250 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3258 else if (event
.xclient
.message_type
== Xatom_wm_configure_denied
)
3261 else if (event
.xclient
.message_type
== Xatom_wm_window_moved
)
3264 struct frame
*f
= x_window_to_frame (event
.xclient
.window
);
3266 new_x
= event
.xclient
.data
.s
[0];
3267 new_y
= event
.xclient
.data
.s
[1];
3271 f
->display
.x
->left_pos
= new_x
;
3272 f
->display
.x
->top_pos
= new_y
;
3275 #if defined (USE_X_TOOLKIT) && defined (HAVE_X11R5)
3276 else if (event
.xclient
.message_type
== Xatom_editres_name
)
3278 struct frame
*f
= x_any_window_to_frame (event
.xclient
.window
);
3279 _XEditResCheckMessages (f
->display
.x
->widget
, NULL
, &event
, NULL
);
3281 #endif /* USE_X_TOOLKIT and HAVE_X11R5 */
3285 case SelectionNotify
:
3286 #ifdef USE_X_TOOLKIT
3287 if (! x_window_to_frame (event
.xselection
.requestor
))
3289 #endif /* not USE_X_TOOLKIT */
3290 x_handle_selection_notify (&event
);
3293 case SelectionClear
: /* Someone has grabbed ownership. */
3294 #ifdef USE_X_TOOLKIT
3295 if (! x_window_to_frame (event
.xselectionclear
.window
))
3297 #endif /* USE_X_TOOLKIT */
3299 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
3304 bufp
->kind
= selection_clear_event
;
3305 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3306 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3307 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3315 case SelectionRequest
: /* Someone wants our selection. */
3316 #ifdef USE_X_TOOLKIT
3317 if (!x_window_to_frame (event
.xselectionrequest
.owner
))
3319 #endif /* USE_X_TOOLKIT */
3320 if (x_queue_selection_requests
)
3321 x_queue_event (&event
);
3324 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
3329 bufp
->kind
= selection_request_event
;
3330 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3331 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
3332 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3333 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
3334 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
3335 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3343 case PropertyNotify
:
3344 #ifdef USE_X_TOOLKIT
3345 if (!x_any_window_to_frame (event
.xproperty
.window
))
3347 #endif /* not USE_X_TOOLKIT */
3348 x_handle_property_notify (&event
);
3351 case ReparentNotify
:
3352 f
= x_top_window_to_frame (event
.xreparent
.window
);
3356 f
->display
.x
->parent_desc
= event
.xreparent
.parent
;
3357 x_real_positions (f
, &x
, &y
);
3358 f
->display
.x
->left_pos
= x
;
3359 f
->display
.x
->top_pos
= y
;
3364 f
= x_window_to_frame (event
.xexpose
.window
);
3367 if (f
->async_visible
== 0)
3369 f
->async_visible
= 1;
3370 f
->async_iconified
= 0;
3371 SET_FRAME_GARBAGED (f
);
3374 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
3375 event
.xexpose
.x
, event
.xexpose
.y
,
3376 event
.xexpose
.width
, event
.xexpose
.height
);
3380 struct scroll_bar
*bar
3381 = x_window_to_scroll_bar (event
.xexpose
.window
);
3384 x_scroll_bar_expose (bar
, &event
);
3385 #ifdef USE_X_TOOLKIT
3388 #endif /* USE_X_TOOLKIT */
3392 case GraphicsExpose
: /* This occurs when an XCopyArea's
3393 source area was obscured or not
3395 f
= x_window_to_frame (event
.xgraphicsexpose
.drawable
);
3399 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
3400 event
.xgraphicsexpose
.width
,
3401 event
.xgraphicsexpose
.height
);
3403 #ifdef USE_X_TOOLKIT
3406 #endif /* USE_X_TOOLKIT */
3409 case NoExpose
: /* This occurs when an XCopyArea's
3410 source area was completely
3415 f
= x_any_window_to_frame (event
.xunmap
.window
);
3416 if (f
) /* F may no longer exist if
3417 the frame was deleted. */
3419 /* While a frame is unmapped, display generation is
3420 disabled; you don't want to spend time updating a
3421 display that won't ever be seen. */
3422 f
->async_visible
= 0;
3423 /* We can't distinguish, from the event, whether the window
3424 has become iconified or invisible. So assume, if it
3425 was previously visible, than now it is iconified.
3426 We depend on x_make_frame_invisible to mark it iconified. */
3427 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
3428 f
->async_iconified
= 1;
3430 #ifdef USE_X_TOOLKIT
3432 #endif /* USE_X_TOOLKIT */
3436 /* We use x_top_window_to_frame because map events can come
3437 for subwindows and they don't mean that the frame is visible. */
3438 f
= x_top_window_to_frame (event
.xmap
.window
);
3441 f
->async_visible
= 1;
3442 f
->async_iconified
= 0;
3444 /* wait_reading_process_input will notice this and update
3445 the frame's display structures. */
3446 SET_FRAME_GARBAGED (f
);
3448 #ifdef USE_X_TOOLKIT
3450 #endif /* USE_X_TOOLKIT */
3453 /* Turn off processing if we become fully obscured. */
3454 case VisibilityNotify
:
3458 f
= x_any_window_to_frame (event
.xkey
.window
);
3462 KeySym keysym
, orig_keysym
;
3463 /* al%imercury@uunet.uu.net says that making this 81 instead of
3464 80 fixed a bug whereby meta chars made his Emacs hang. */
3465 unsigned char copy_buffer
[81];
3469 |= x_emacs_to_x_modifiers (extra_keyboard_modifiers
);
3470 modifiers
= event
.xkey
.state
;
3472 /* This will have to go some day... */
3474 /* make_lispy_event turns chars into control chars.
3475 Don't do it here because XLookupString is too eager. */
3476 event
.xkey
.state
&= ~ControlMask
;
3478 XLookupString (&event
.xkey
, copy_buffer
, 80, &keysym
,
3481 orig_keysym
= keysym
;
3485 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
3486 || keysym
== XK_Delete
3487 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
3488 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
3490 /* This recognizes the "extended function keys".
3491 It seems there's no cleaner way.
3492 Test IsModifierKey to avoid handling mode_switch
3494 || ((unsigned) (keysym
) >= XK_Select
3495 && (unsigned)(keysym
) < XK_KP_Space
)
3497 #ifdef XK_dead_circumflex
3498 || orig_keysym
== XK_dead_circumflex
3500 #ifdef XK_dead_grave
3501 || orig_keysym
== XK_dead_grave
3503 #ifdef XK_dead_tilde
3504 || orig_keysym
== XK_dead_tilde
3506 #ifdef XK_dead_diaeresis
3507 || orig_keysym
== XK_dead_diaeresis
3509 #ifdef XK_dead_macron
3510 || orig_keysym
== XK_dead_macron
3512 #ifdef XK_dead_degree
3513 || orig_keysym
== XK_dead_degree
3515 #ifdef XK_dead_acute
3516 || orig_keysym
== XK_dead_acute
3518 #ifdef XK_dead_cedilla
3519 || orig_keysym
== XK_dead_cedilla
3521 #ifdef XK_dead_breve
3522 || orig_keysym
== XK_dead_breve
3524 #ifdef XK_dead_ogonek
3525 || orig_keysym
== XK_dead_ogonek
3527 #ifdef XK_dead_caron
3528 || orig_keysym
== XK_dead_caron
3530 #ifdef XK_dead_doubleacute
3531 || orig_keysym
== XK_dead_doubleacute
3533 #ifdef XK_dead_abovedot
3534 || orig_keysym
== XK_dead_abovedot
3536 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
3537 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
3538 /* Any "vendor-specific" key is ok. */
3539 || (orig_keysym
& (1 << 28)))
3540 && ! (IsModifierKey (orig_keysym
)
3542 #ifdef XK_Mode_switch
3543 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
3546 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
3548 #endif /* not HAVE_X11R5 */
3551 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3553 temp_buffer
[temp_index
++] = keysym
;
3554 bufp
->kind
= non_ascii_keystroke
;
3555 bufp
->code
= keysym
;
3556 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3557 bufp
->modifiers
= x_x_to_emacs_modifiers (modifiers
);
3558 bufp
->timestamp
= event
.xkey
.time
;
3563 else if (numchars
> nbytes
)
3567 for (i
= 0; i
< nbytes
; i
++)
3569 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3571 temp_buffer
[temp_index
++] = copy_buffer
[i
];
3572 bufp
->kind
= ascii_keystroke
;
3573 bufp
->code
= copy_buffer
[i
];
3574 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3575 bufp
->modifiers
= x_x_to_emacs_modifiers (modifiers
);
3576 bufp
->timestamp
= event
.xkey
.time
;
3591 /* Here's a possible interpretation of the whole
3592 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3593 FocusIn event, you have to get a FocusOut event before you
3594 relinquish the focus. If you haven't received a FocusIn event,
3595 then a mere LeaveNotify is enough to free you. */
3598 f
= x_any_window_to_frame (event
.xcrossing
.window
);
3600 if (event
.xcrossing
.focus
) /* Entered Window */
3602 /* Avoid nasty pop/raise loops. */
3603 if (f
&& (!(f
->auto_raise
)
3605 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
3607 x_new_focus_frame (f
);
3608 enter_timestamp
= event
.xcrossing
.time
;
3611 else if (f
== x_focus_frame
)
3612 x_new_focus_frame (0);
3613 /* EnterNotify counts as mouse movement,
3614 so update things that depend on mouse position. */
3616 note_mouse_movement (f
, &event
.xmotion
);
3617 #ifdef USE_X_TOOLKIT
3619 #endif /* USE_X_TOOLKIT */
3623 f
= x_any_window_to_frame (event
.xfocus
.window
);
3624 if (event
.xfocus
.detail
!= NotifyPointer
)
3625 x_focus_event_frame
= f
;
3627 x_new_focus_frame (f
);
3628 #ifdef USE_X_TOOLKIT
3630 #endif /* USE_X_TOOLKIT */
3635 f
= x_top_window_to_frame (event
.xcrossing
.window
);
3638 if (f
== mouse_face_mouse_frame
)
3639 /* If we move outside the frame,
3640 then we're certainly no longer on any text in the frame. */
3641 clear_mouse_face ();
3643 if (event
.xcrossing
.focus
)
3645 if (! x_focus_event_frame
)
3646 x_new_focus_frame (0);
3648 x_new_focus_frame (f
);
3652 if (f
== x_focus_event_frame
)
3653 x_focus_event_frame
= 0;
3654 if (f
== x_focus_frame
)
3655 x_new_focus_frame (0);
3658 #ifdef USE_X_TOOLKIT
3660 #endif /* USE_X_TOOLKIT */
3664 f
= x_any_window_to_frame (event
.xfocus
.window
);
3665 if (event
.xfocus
.detail
!= NotifyPointer
3666 && f
== x_focus_event_frame
)
3667 x_focus_event_frame
= 0;
3668 if (f
&& f
== x_focus_frame
)
3669 x_new_focus_frame (0);
3670 #ifdef USE_X_TOOLKIT
3672 #endif /* USE_X_TOOLKIT */
3677 if (x_mouse_grabbed
&& last_mouse_frame
3678 && FRAME_LIVE_P (last_mouse_frame
))
3679 f
= last_mouse_frame
;
3681 f
= x_window_to_frame (event
.xmotion
.window
);
3683 note_mouse_movement (f
, &event
.xmotion
);
3686 struct scroll_bar
*bar
3687 = x_window_to_scroll_bar (event
.xmotion
.window
);
3690 x_scroll_bar_note_movement (bar
, &event
);
3692 /* If we move outside the frame,
3693 then we're certainly no longer on any text in the frame. */
3694 clear_mouse_face ();
3697 #if 0 /* This should be unnecessary, since the toolkit has no use
3698 for motion events that happen outside of the menu event loop,
3699 and it seems to cause the bug that mouse events stop coming
3701 #ifdef USE_X_TOOLKIT
3703 #endif /* USE_X_TOOLKIT */
3707 case ConfigureNotify
:
3708 f
= x_any_window_to_frame (event
.xconfigure
.window
);
3709 #ifdef USE_X_TOOLKIT
3712 && ! event
.xconfigure
.send_event
3714 && (event
.xconfigure
.window
== XtWindow (f
->display
.x
->widget
)))
3719 /* Find the position of the outside upper-left corner of
3720 the window, in the root coordinate system. Don't
3721 refer to the parent window here; we may be processing
3722 this event after the window manager has changed our
3723 parent, but before we have reached the ReparentNotify. */
3724 XTranslateCoordinates (x_current_display
,
3726 /* From-window, to-window. */
3727 XtWindow (f
->display
.x
->widget
),
3730 /* From-position, to-position. */
3731 -event
.xconfigure
.border_width
,
3732 -event
.xconfigure
.border_width
,
3737 event
.xconfigure
.x
= win_x
;
3738 event
.xconfigure
.y
= win_y
;
3740 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
3741 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
3742 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
3743 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
3745 /* What we have now is the position of Emacs's own window.
3746 Convert that to the position of the window manager window. */
3749 x_real_positions (f
, &x
, &y
);
3750 f
->display
.x
->left_pos
= x
;
3751 f
->display
.x
->top_pos
= y
;
3755 #else /* not USE_X_TOOLKIT */
3758 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
3759 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
3761 /* Even if the number of character rows and columns has
3762 not changed, the font size may have changed, so we need
3763 to check the pixel dimensions as well. */
3764 if (columns
!= f
->width
3765 || rows
!= f
->height
3766 || event
.xconfigure
.width
!= f
->display
.x
->pixel_width
3767 || event
.xconfigure
.height
!= f
->display
.x
->pixel_height
)
3769 change_frame_size (f
, rows
, columns
, 0, 1);
3770 SET_FRAME_GARBAGED (f
);
3773 if (! event
.xconfigure
.send_event
)
3778 /* Find the position of the outside upper-left corner of
3779 the window, in the root coordinate system. Don't
3780 refer to the parent window here; we may be processing
3781 this event after the window manager has changed our
3782 parent, but before we have reached the ReparentNotify. */
3783 XTranslateCoordinates (x_current_display
,
3785 /* From-window, to-window. */
3786 f
->display
.x
->window_desc
,
3789 /* From-position, to-position. */
3790 -event
.xconfigure
.border_width
,
3791 -event
.xconfigure
.border_width
,
3796 event
.xconfigure
.x
= win_x
;
3797 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
;
3812 if (y
!= event
.xconfigure
.y
)
3814 /* Since the WM decorations come below top_pos now,
3815 we must put them below top_pos in the future. */
3816 f
->display
.x
->win_gravity
= NorthWestGravity
;
3817 x_wm_set_size_hint (f
, 0, 0);
3821 #endif /* not USE_X_TOOLKIT */
3827 /* If we decide we want to generate an event to be seen
3828 by the rest of Emacs, we put it here. */
3829 struct input_event emacs_event
;
3830 emacs_event
.kind
= no_event
;
3832 bzero (&compose_status
, sizeof (compose_status
));
3834 f
= x_window_to_frame (event
.xbutton
.window
);
3837 if (!x_focus_frame
|| (f
== x_focus_frame
))
3838 construct_mouse_click (&emacs_event
, &event
, f
);
3842 struct scroll_bar
*bar
3843 = x_window_to_scroll_bar (event
.xbutton
.window
);
3846 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
3847 #ifdef USE_X_TOOLKIT
3850 f
= x_any_window_to_frame (event
.xbutton
.window
);
3851 if (f
&& event
.type
== ButtonPress
)
3852 construct_menu_click (&emacs_event
,
3855 #endif /* USE_X_TOOLKIT */
3858 if (event
.type
== ButtonPress
)
3860 x_mouse_grabbed
|= (1 << event
.xbutton
.button
);
3861 Vmouse_depressed
= Qt
;
3862 last_mouse_frame
= f
;
3866 x_mouse_grabbed
&= ~(1 << event
.xbutton
.button
);
3867 if (!x_mouse_grabbed
)
3868 Vmouse_depressed
= Qnil
;
3871 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
3873 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
3879 #ifdef USE_X_TOOLKIT
3881 #endif /* USE_X_TOOLKIT */
3885 case CirculateNotify
:
3887 case CirculateRequest
:
3891 /* Someone has changed the keyboard mapping - update the
3893 switch (event
.xmapping
.request
)
3895 case MappingModifier
:
3896 x_find_modifier_meanings ();
3897 /* This is meant to fall through. */
3898 case MappingKeyboard
:
3899 XRefreshKeyboardMapping (&event
.xmapping
);
3901 #ifdef USE_X_TOOLKIT
3903 #endif /* USE_X_TOOLKIT */
3907 #ifdef USE_X_TOOLKIT
3910 XtDispatchEvent (&event
);
3912 #endif /* USE_X_TOOLKIT */
3917 /* On some systems, an X bug causes Emacs to get no more events
3918 when the window is destroyed. Detect that. (1994.) */
3921 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
3922 One XNOOP in 100 loops will make Emacs terminate.
3923 B. Bretthauer, 1994 */
3925 if (x_noop_count
>= 100)
3928 XNoOp (x_current_display
);
3932 #if 0 /* This fails for serial-line connections to the X server,
3933 because the characters arrive one by one, and a partial
3934 command makes select return but gives nothing to read.
3935 We'll have to hope that the bug that this tried to fix
3936 in 1988 has been fixed in Xlib or the X server. */
3938 if (expected
&& ! event_found
)
3940 /* AOJ 880406: if select returns true but XPending doesn't, it means that
3941 there is an EOF condition; in other words, that X has died.
3942 Act as if there had been a hangup. */
3943 int fd
= ConnectionNumber (x_current_display
);
3944 SELECT_TYPE mask
, junk1
, junk2
;
3949 EMACS_SET_SECS_USECS (timeout
, 0, 0);
3952 if (0 != select (fd
+ 1, &mask
, &junk1
, &junk2
, &timeout
)
3953 && !XStuffPending ())
3954 kill (getpid (), SIGHUP
);
3956 #endif /* HAVE_SELECT */
3959 /* If the focus was just given to an autoraising frame,
3961 if (pending_autoraise_frame
)
3963 x_raise_frame (pending_autoraise_frame
);
3964 pending_autoraise_frame
= 0;
3971 /* Drawing the cursor. */
3974 /* Draw a hollow box cursor. Don't change the inside of the box. */
3980 int left
= CHAR_TO_PIXEL_COL (f
, curs_x
);
3981 int top
= CHAR_TO_PIXEL_ROW (f
, curs_y
);
3982 int width
= FONT_WIDTH (f
->display
.x
->font
);
3983 int height
= f
->display
.x
->line_height
;
3985 XDrawRectangle (x_current_display
, FRAME_X_WINDOW (f
),
3986 f
->display
.x
->cursor_gc
,
3987 left
, top
, width
- 1, height
- 1);
3990 /* Clear the cursor of frame F to background color,
3991 and mark the cursor as not shown.
3992 This is used when the text where the cursor is
3993 is about to be rewritten. */
4001 if (! FRAME_VISIBLE_P (f
)
4002 || f
->phys_cursor_x
< 0)
4005 x_display_cursor (f
, 0);
4006 f
->phys_cursor_x
= -1;
4009 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
4010 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4014 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
4021 CHAR_TO_PIXEL_COL (f
, column
),
4022 CHAR_TO_PIXEL_ROW (f
, row
),
4023 &glyph
, 1, highlight
, 0);
4027 x_display_bar_cursor (f
, on
)
4031 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4033 /* This is pointless on invisible frames, and dangerous on garbaged
4034 frames; in the latter case, the frame may be in the midst of
4035 changing its size, and curs_x and curs_y may be off the frame. */
4036 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4039 if (! on
&& f
->phys_cursor_x
< 0)
4042 /* If we're not updating, then we want to use the current frame's
4043 cursor position, not our local idea of where the cursor ought to be. */
4044 if (f
!= updating_frame
)
4046 curs_x
= FRAME_CURSOR_X (f
);
4047 curs_y
= FRAME_CURSOR_Y (f
);
4050 /* If there is anything wrong with the current cursor state, remove it. */
4051 if (f
->phys_cursor_x
>= 0
4053 || f
->phys_cursor_x
!= curs_x
4054 || f
->phys_cursor_y
!= curs_y
4055 || f
->display
.x
->current_cursor
!= bar_cursor
))
4057 /* Erase the cursor by redrawing the character underneath it. */
4058 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4059 f
->phys_cursor_glyph
,
4060 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4061 f
->phys_cursor_x
= -1;
4064 /* If we now need a cursor in the new place or in the new form, do it so. */
4066 && (f
->phys_cursor_x
< 0
4067 || (f
->display
.x
->current_cursor
!= bar_cursor
)))
4069 f
->phys_cursor_glyph
4070 = ((current_glyphs
->enable
[curs_y
]
4071 && curs_x
< current_glyphs
->used
[curs_y
])
4072 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4074 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
4075 f
->display
.x
->cursor_gc
,
4076 CHAR_TO_PIXEL_COL (f
, curs_x
),
4077 CHAR_TO_PIXEL_ROW (f
, curs_y
),
4078 1, f
->display
.x
->line_height
);
4080 f
->phys_cursor_x
= curs_x
;
4081 f
->phys_cursor_y
= curs_y
;
4083 f
->display
.x
->current_cursor
= bar_cursor
;
4086 if (updating_frame
!= f
)
4091 /* Turn the displayed cursor of frame F on or off according to ON.
4092 If ON is nonzero, where to put the cursor is specified
4093 by F->cursor_x and F->cursor_y. */
4096 x_display_box_cursor (f
, on
)
4100 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4102 /* This is pointless on invisible frames, and dangerous on garbaged
4103 frames; in the latter case, the frame may be in the midst of
4104 changing its size, and curs_x and curs_y may be off the frame. */
4105 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4108 /* If cursor is off and we want it off, return quickly. */
4109 if (!on
&& f
->phys_cursor_x
< 0)
4112 /* If we're not updating, then we want to use the current frame's
4113 cursor position, not our local idea of where the cursor ought to be. */
4114 if (f
!= updating_frame
)
4116 curs_x
= FRAME_CURSOR_X (f
);
4117 curs_y
= FRAME_CURSOR_Y (f
);
4120 /* If cursor is currently being shown and we don't want it to be
4121 or it is in the wrong place,
4122 or we want a hollow box and it's not so, (pout!)
4124 if (f
->phys_cursor_x
>= 0
4126 || f
->phys_cursor_x
!= curs_x
4127 || f
->phys_cursor_y
!= curs_y
4128 || (f
->display
.x
->current_cursor
!= hollow_box_cursor
4129 && (f
!= x_highlight_frame
))))
4131 int mouse_face_here
= 0;
4133 /* If the cursor is in the mouse face area, redisplay that when
4134 we clear the cursor. */
4135 if (f
== mouse_face_mouse_frame
4137 (f
->phys_cursor_y
> mouse_face_beg_row
4138 || (f
->phys_cursor_y
== mouse_face_beg_row
4139 && f
->phys_cursor_x
>= mouse_face_beg_col
))
4141 (f
->phys_cursor_y
< mouse_face_end_row
4142 || (f
->phys_cursor_y
== mouse_face_end_row
4143 && f
->phys_cursor_x
< mouse_face_end_col
)))
4144 mouse_face_here
= 1;
4146 /* If the font is not as tall as a whole line,
4147 we must explicitly clear the line's whole height. */
4148 if (FONT_HEIGHT (f
->display
.x
->font
) != f
->display
.x
->line_height
)
4149 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
4150 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4151 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4152 FONT_WIDTH (f
->display
.x
->font
),
4153 f
->display
.x
->line_height
, False
);
4154 /* Erase the cursor by redrawing the character underneath it. */
4155 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4156 f
->phys_cursor_glyph
,
4159 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
4160 f
->phys_cursor_x
= -1;
4163 /* If we want to show a cursor,
4164 or we want a box cursor and it's not so,
4165 write it in the right place. */
4167 && (f
->phys_cursor_x
< 0
4168 || (f
->display
.x
->current_cursor
!= filled_box_cursor
4169 && f
== x_highlight_frame
)))
4171 f
->phys_cursor_glyph
4172 = ((current_glyphs
->enable
[curs_y
]
4173 && curs_x
< current_glyphs
->used
[curs_y
])
4174 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4176 if (f
!= x_highlight_frame
)
4179 f
->display
.x
->current_cursor
= hollow_box_cursor
;
4183 x_draw_single_glyph (f
, curs_y
, curs_x
,
4184 f
->phys_cursor_glyph
, 2);
4185 f
->display
.x
->current_cursor
= filled_box_cursor
;
4188 f
->phys_cursor_x
= curs_x
;
4189 f
->phys_cursor_y
= curs_y
;
4192 if (updating_frame
!= f
)
4196 x_display_cursor (f
, on
)
4202 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4203 x_display_box_cursor (f
, on
);
4204 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4205 x_display_bar_cursor (f
, on
);
4207 /* Those are the only two we have implemented! */
4215 /* Refresh bitmap kitchen sink icon for frame F
4216 when we get an expose event for it. */
4221 /* Normally, the window manager handles this function. */
4224 /* Make the x-window of frame F use the gnu icon bitmap. */
4233 if (FRAME_X_WINDOW (f
) == 0)
4238 XCreateBitmapFromData (x_current_display
, FRAME_X_WINDOW (f
),
4239 gnu_bits
, gnu_width
, gnu_height
);
4240 x_wm_set_icon_pixmap (f
, icon_bitmap
);
4241 f
->display
.x
->icon_bitmap_flag
= 1;
4247 /* Make the x-window of frame F use a rectangle with text. */
4250 x_text_icon (f
, icon_name
)
4254 if (FRAME_X_WINDOW (f
) == 0)
4258 f
->display
.x
->icon_label
= icon_name
;
4260 if (! f
->display
.x
->icon_label
)
4261 f
->display
.x
->icon_label
= " *emacs* ";
4264 XSetIconName (x_current_display
, FRAME_X_WINDOW (f
),
4265 (char *) f
->display
.x
->icon_label
);
4268 f
->display
.x
->icon_bitmap_flag
= 0;
4269 x_wm_set_icon_pixmap (f
, 0);
4274 /* Handling X errors. */
4276 /* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
4277 X server's connection, or an error reported via the X protocol. */
4280 x_connection_closed ()
4285 shut_down_emacs (0, 1, Qnil
);
4290 /* An X error handler which prints an error message and then kills
4291 Emacs. This is what's normally installed as Xlib's handler for
4294 x_error_quitter (display
, error
)
4300 /* Note that there is no real way portable across R3/R4 to get the
4301 original error handler. */
4303 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
4304 fprintf (stderr
, "X protocol error: %s on protocol request %d\n",
4305 buf
, error
->request_code
);
4308 /* While we're testing Emacs 19, we'll just dump core whenever we
4309 get an X error, so we can figure out why it happened. */
4313 x_connection_closed ();
4316 /* A handler for X IO errors which prints an error message and then
4317 kills Emacs. This is what is always installed as Xlib's handler
4320 x_io_error_quitter (display
)
4323 fprintf (stderr
, "Connection to X server %s lost.\n",
4324 XDisplayName (DisplayString (display
)));
4327 /* While we're testing Emacs 19, we'll just dump core whenever we
4328 get an X error, so we can figure out why it happened. */
4332 x_connection_closed ();
4335 /* A buffer for storing X error messages. */
4336 static char *x_caught_error_message
;
4337 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
4339 /* An X error handler which stores the error message in
4340 x_caught_error_message. This is what's installed when
4341 x_catch_errors is in effect. */
4343 x_error_catcher (display
, error
)
4347 XGetErrorText (display
, error
->error_code
,
4348 x_caught_error_message
, X_CAUGHT_ERROR_MESSAGE_SIZE
);
4352 /* Begin trapping X errors.
4354 After calling this function, X protocol errors no longer cause
4355 Emacs to exit; instead, they are recorded in x_cfc_error_message.
4357 Calling x_check_errors signals an Emacs error if an X error has
4358 occurred since the last call to x_catch_errors or x_check_errors.
4360 Calling x_uncatch_errors resumes the normal error handling. */
4362 void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
4367 /* Make sure any errors from previous requests have been dealt with. */
4368 XSync (x_current_display
, False
);
4370 /* Set up the error buffer. */
4371 x_caught_error_message
4372 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE
);
4373 x_caught_error_message
[0] = '\0';
4375 /* Install our little error handler. */
4376 XHandleError (x_error_catcher
);
4379 /* If any X protocol errors have arrived since the last call to
4380 x_catch_errors or x_check_errors, signal an Emacs error using
4381 sprintf (a buffer, FORMAT, the x error message text) as the text. */
4384 x_check_errors (format
)
4387 /* Make sure to catch any errors incurred so far. */
4388 XSync (x_current_display
, False
);
4390 if (x_caught_error_message
[0])
4392 char buf
[X_CAUGHT_ERROR_MESSAGE_SIZE
+ 56];
4394 sprintf (buf
, format
, x_caught_error_message
);
4395 x_uncatch_errors ();
4400 /* Nonzero if we had any X protocol errors since we did x_catch_errors. */
4405 /* Make sure to catch any errors incurred so far. */
4406 XSync (x_current_display
, False
);
4408 return x_caught_error_message
[0] != 0;
4411 /* Stop catching X protocol errors and let them make Emacs die. */
4416 xfree (x_caught_error_message
);
4417 x_caught_error_message
= 0;
4418 XHandleError (x_error_quitter
);
4422 static unsigned int x_wire_count
;
4425 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
4430 /* Changing the font of the frame. */
4432 /* Set the font of the x-window specified by frame F
4433 to the font named NEWNAME. This is safe to use
4434 even before F has an actual x-window. */
4443 /* A table of all the fonts we have already loaded. */
4444 static struct font_info
*x_font_table
;
4446 /* The current capacity of x_font_table. */
4447 static int x_font_table_size
;
4449 /* The number of fonts actually stored in x_font_table.
4450 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
4451 0 <= n_fonts <= x_font_table_size. */
4454 /* Give frame F the font named FONTNAME as its default font, and
4455 return the full name of that font. FONTNAME may be a wildcard
4456 pattern; in that case, we choose some font that fits the pattern.
4457 The return value shows which font we chose. */
4460 x_new_font (f
, fontname
)
4462 register char *fontname
;
4465 int n_matching_fonts
;
4466 XFontStruct
*font_info
;
4469 /* Get a list of all the fonts that match this name. Once we
4470 have a list of matching fonts, we compare them against the fonts
4471 we already have by comparing font ids. */
4472 font_names
= (char **) XListFonts (x_current_display
, fontname
,
4473 1024, &n_matching_fonts
);
4474 /* Apparently it doesn't set n_matching_fonts to zero when it can't
4475 find any matches; font_names == 0 is the only clue. */
4477 n_matching_fonts
= 0;
4479 /* Don't just give up if n_matching_fonts is 0.
4480 Apparently there's a bug on Suns: XListFontsWithInfo can
4481 fail to find a font, but XLoadQueryFont may still find it. */
4483 /* See if we've already loaded a matching font. */
4484 already_loaded
= -1;
4485 if (n_matching_fonts
!= 0)
4489 for (i
= 0; i
< n_fonts
; i
++)
4490 for (j
= 0; j
< n_matching_fonts
; j
++)
4491 if (!strcmp (x_font_table
[i
].name
, font_names
[j
])
4492 || !strcmp (x_font_table
[i
].full_name
, font_names
[j
]))
4495 fontname
= x_font_table
[i
].full_name
;
4501 /* If we have, just return it from the table. */
4502 if (already_loaded
>= 0)
4503 f
->display
.x
->font
= x_font_table
[already_loaded
].font
;
4504 /* Otherwise, load the font and add it to the table. */
4511 /* Try to find a character-cell font in the list. */
4513 /* A laudable goal, but this isn't how to do it. */
4514 for (i
= 0; i
< n_matching_fonts
; i
++)
4515 if (! font_info
[i
].per_char
)
4521 /* See comment above. */
4522 if (n_matching_fonts
!= 0)
4523 fontname
= font_names
[i
];
4525 font
= (XFontStruct
*) XLoadQueryFont (x_current_display
, fontname
);
4528 /* Free the information from XListFonts. */
4529 if (n_matching_fonts
)
4530 XFreeFontNames (font_names
);
4534 /* Do we need to create the table? */
4535 if (x_font_table_size
== 0)
4537 x_font_table_size
= 16;
4539 = (struct font_info
*) xmalloc (x_font_table_size
4540 * sizeof (x_font_table
[0]));
4542 /* Do we need to grow the table? */
4543 else if (n_fonts
>= x_font_table_size
)
4545 x_font_table_size
*= 2;
4547 = (struct font_info
*) xrealloc (x_font_table
,
4549 * sizeof (x_font_table
[0])));
4552 /* Try to get the full name of FONT. Put it in full_name. */
4554 for (i
= 0; i
< font
->n_properties
; i
++)
4557 = XGetAtomName (x_current_display
, font
->properties
[i
].name
);
4558 if (!strcmp (atom
, "FONT"))
4560 char *name
= XGetAtomName (x_current_display
,
4561 (Atom
) (font
->properties
[i
].card32
));
4565 /* Count the number of dashes in the "full name".
4566 If it is too few, this isn't really the font's full name,
4568 In X11R4, the fonts did not come with their canonical names
4584 x_font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
4585 bcopy (fontname
, x_font_table
[n_fonts
].name
, strlen (fontname
) + 1);
4587 x_font_table
[n_fonts
].full_name
= full_name
;
4589 x_font_table
[n_fonts
].full_name
= x_font_table
[n_fonts
].name
;
4590 f
->display
.x
->font
= x_font_table
[n_fonts
++].font
= font
;
4593 fontname
= full_name
;
4596 /* Compute the scroll bar width in character columns. */
4597 if (f
->scroll_bar_pixel_width
> 0)
4599 int wid
= FONT_WIDTH (f
->display
.x
->font
);
4600 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
4603 f
->scroll_bar_cols
= 2;
4605 /* Now make the frame display the given font. */
4606 if (FRAME_X_WINDOW (f
) != 0)
4608 XSetFont (x_current_display
, f
->display
.x
->normal_gc
,
4609 f
->display
.x
->font
->fid
);
4610 XSetFont (x_current_display
, f
->display
.x
->reverse_gc
,
4611 f
->display
.x
->font
->fid
);
4612 XSetFont (x_current_display
, f
->display
.x
->cursor_gc
,
4613 f
->display
.x
->font
->fid
);
4615 frame_update_line_height (f
);
4616 x_set_window_size (f
, 0, f
->width
, f
->height
);
4619 /* If we are setting a new frame's font for the first time,
4620 there are no faces yet, so this font's height is the line height. */
4621 f
->display
.x
->line_height
= FONT_HEIGHT (f
->display
.x
->font
);
4624 Lisp_Object lispy_name
;
4626 lispy_name
= build_string (fontname
);
4628 /* Free the information from XListFonts. The data
4629 we actually retain comes from XLoadQueryFont. */
4630 XFreeFontNames (font_names
);
4636 x_calc_absolute_position (f
)
4640 int win_x
= 0, win_y
= 0;
4641 int flags
= f
->display
.x
->size_hint_flags
;
4643 /* Find the position of the outside upper-left corner of
4644 the inner window, with respect to the outer window. */
4645 if (f
->display
.x
->parent_desc
!= ROOT_WINDOW
)
4648 XTranslateCoordinates (x_current_display
,
4650 /* From-window, to-window. */
4651 f
->display
.x
->window_desc
,
4652 f
->display
.x
->parent_desc
,
4654 /* From-position, to-position. */
4655 0, 0, &win_x
, &win_y
,
4662 /* Treat negative positions as relative to the leftmost bottommost
4663 position that fits on the screen. */
4664 if (flags
& XNegative
)
4665 f
->display
.x
->left_pos
= (x_screen_width
4666 - 2 * f
->display
.x
->border_width
- win_x
4668 + f
->display
.x
->left_pos
);
4670 if (flags
& YNegative
)
4671 f
->display
.x
->top_pos
= (x_screen_height
4672 - 2 * f
->display
.x
->border_width
- win_y
4674 + f
->display
.x
->top_pos
);
4675 /* The left_pos and top_pos
4676 are now relative to the top and left screen edges,
4677 so the flags should correspond. */
4678 f
->display
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
4681 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
4682 to really change the position, and 0 when calling from
4683 x_make_frame_visible (in that case, XOFF and YOFF are the current
4684 position values). */
4686 x_set_offset (f
, xoff
, yoff
, change_gravity
)
4688 register int xoff
, yoff
;
4693 f
->display
.x
->top_pos
= yoff
;
4694 f
->display
.x
->left_pos
= xoff
;
4695 f
->display
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
4697 f
->display
.x
->size_hint_flags
|= XNegative
;
4699 f
->display
.x
->size_hint_flags
|= YNegative
;
4700 f
->display
.x
->win_gravity
= NorthWestGravity
;
4702 x_calc_absolute_position (f
);
4705 x_wm_set_size_hint (f
, 0, 0);
4707 #ifdef USE_X_TOOLKIT
4708 XMoveWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
),
4709 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
4710 #else /* not USE_X_TOOLKIT */
4711 XMoveWindow (XDISPLAY
FRAME_X_WINDOW (f
),
4712 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
4713 #endif /* not USE_X_TOOLKIT */
4717 /* Call this to change the size of frame F's x-window.
4718 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
4719 for this size change and subsequent size changes.
4720 Otherwise we leave the window gravity unchanged. */
4722 x_set_window_size (f
, change_gravity
, cols
, rows
)
4727 int pixelwidth
, pixelheight
;
4730 #ifdef USE_X_TOOLKIT
4733 /* The x and y position of the widget is clobbered by the
4734 call to XtSetValues within EmacsFrameSetCharSize.
4735 This is a real kludge, but I don't understand Xt so I can't
4736 figure out a correct fix. Can anyone else tell me? -- rms. */
4737 int xpos
= f
->display
.x
->widget
->core
.x
;
4738 int ypos
= f
->display
.x
->widget
->core
.y
;
4739 EmacsFrameSetCharSize (f
->display
.x
->edit_widget
, cols
, rows
);
4740 f
->display
.x
->widget
->core
.x
= xpos
;
4741 f
->display
.x
->widget
->core
.y
= ypos
;
4745 #else /* not USE_X_TOOLKIT */
4749 check_frame_size (f
, &rows
, &cols
);
4750 f
->display
.x
->vertical_scroll_bar_extra
4751 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
4753 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
4754 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
4755 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->display
.x
->font
)));
4756 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
4757 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
4759 f
->display
.x
->win_gravity
= NorthWestGravity
;
4760 x_wm_set_size_hint (f
, 0, 0);
4762 XSync (x_current_display
, False
);
4763 XChangeWindowSize (FRAME_X_WINDOW (f
), pixelwidth
, pixelheight
);
4765 /* Now, strictly speaking, we can't be sure that this is accurate,
4766 but the window manager will get around to dealing with the size
4767 change request eventually, and we'll hear how it went when the
4768 ConfigureNotify event gets here.
4770 We could just not bother storing any of this information here,
4771 and let the ConfigureNotify event set everything up, but that
4772 might be kind of confusing to the lisp code, since size changes
4773 wouldn't be reported in the frame parameters until some random
4774 point in the future when the ConfigureNotify event arrives. */
4775 change_frame_size (f
, rows
, cols
, 0, 0);
4776 PIXEL_WIDTH (f
) = pixelwidth
;
4777 PIXEL_HEIGHT (f
) = pixelheight
;
4779 /* If cursor was outside the new size, mark it as off. */
4780 if (f
->phys_cursor_y
>= rows
4781 || f
->phys_cursor_x
>= cols
)
4783 f
->phys_cursor_x
= -1;
4784 f
->phys_cursor_y
= -1;
4787 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4788 receive in the ConfigureNotify event; if we get what we asked
4789 for, then the event won't cause the screen to become garbaged, so
4790 we have to make sure to do it here. */
4791 SET_FRAME_GARBAGED (f
);
4795 #endif /* not USE_X_TOOLKIT */
4798 /* Mouse warping, focus shifting, raising and lowering. */
4801 x_set_mouse_position (f
, x
, y
)
4807 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->display
.x
->font
) / 2;
4808 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->display
.x
->line_height
/ 2;
4810 if (pix_x
< 0) pix_x
= 0;
4811 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
4813 if (pix_y
< 0) pix_y
= 0;
4814 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
4818 XWarpMousePointer (FRAME_X_WINDOW (f
), pix_x
, pix_y
);
4822 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
4825 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
4831 XWarpMousePointer (FRAME_X_WINDOW (f
), pix_x
, pix_y
);
4835 x_focus_on_frame (f
)
4838 #if 0 /* This proves to be unpleasant. */
4842 /* I don't think that the ICCCM allows programs to do things like this
4843 without the interaction of the window manager. Whatever you end up
4844 doing with this code, do it to x_unfocus_frame too. */
4845 XSetInputFocus (x_current_display
, FRAME_X_WINDOW (f
),
4846 RevertToPointerRoot
, CurrentTime
);
4854 /* Look at the remarks in x_focus_on_frame. */
4855 if (x_focus_frame
== f
)
4856 XSetInputFocus (x_current_display
, PointerRoot
,
4857 RevertToPointerRoot
, CurrentTime
);
4861 /* Raise frame F. */
4866 if (f
->async_visible
)
4869 #ifdef USE_X_TOOLKIT
4870 XRaiseWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
));
4871 #else /* not USE_X_TOOLKIT */
4872 XRaiseWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4873 #endif /* not USE_X_TOOLKIT */
4879 /* Lower frame F. */
4884 if (f
->async_visible
)
4887 #ifdef USE_X_TOOLKIT
4888 XLowerWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
));
4889 #else /* not USE_X_TOOLKIT */
4890 XLowerWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4891 #endif /* not USE_X_TOOLKIT */
4898 XTframe_raise_lower (f
, raise
)
4909 /* Change from withdrawn state to mapped state,
4912 x_make_frame_visible (f
)
4919 if (! FRAME_VISIBLE_P (f
))
4921 #ifndef USE_X_TOOLKIT
4922 if (! FRAME_ICONIFIED_P (f
))
4923 x_set_offset (f
, f
->display
.x
->left_pos
, f
->display
.x
->top_pos
, 0);
4926 if (! EQ (Vx_no_window_manager
, Qt
))
4927 x_wm_set_window_state (f
, NormalState
);
4928 #ifdef USE_X_TOOLKIT
4929 /* This was XtPopup, but that did nothing for an iconified frame. */
4930 XtMapWidget (f
->display
.x
->widget
);
4931 #else /* not USE_X_TOOLKIT */
4932 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4933 #endif /* not USE_X_TOOLKIT */
4934 #if 0 /* This seems to bring back scroll bars in the wrong places
4935 if the window configuration has changed. They seem
4936 to come back ok without this. */
4937 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
4938 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
4946 /* Synchronize to ensure Emacs knows the frame is visible
4947 before we do anything else. We do this loop with input not blocked
4948 so that incoming events are handled. */
4951 XSET (frame
, Lisp_Frame
, f
);
4952 while (! f
->async_visible
)
4955 /* Machines that do polling rather than SIGIO have been observed
4956 to go into a busy-wait here. So we'll fake an alarm signal
4957 to let the handler know that there's something to be read.
4958 We used to raise a real alarm, but it seems that the handler
4959 isn't always enabled here. This is probably a bug. */
4960 if (input_polling_used ())
4962 /* It could be confusing if a real alarm arrives while processing
4963 the fake one. Turn it off and let the handler reset it. */
4965 input_poll_signal ();
4968 FRAME_SAMPLE_VISIBILITY (f
);
4972 /* Change from mapped state to withdrawn state. */
4974 x_make_frame_invisible (f
)
4980 #ifdef USE_X_TOOLKIT
4981 /* Use the frame's outermost window, not the one we normally draw on. */
4982 window
= XtWindow (f
->display
.x
->widget
);
4983 #else /* not USE_X_TOOLKIT */
4984 window
= FRAME_X_WINDOW (f
);
4985 #endif /* not USE_X_TOOLKIT */
4987 /* Don't keep the highlight on an invisible frame. */
4988 if (x_highlight_frame
== f
)
4989 x_highlight_frame
= 0;
4991 #if 0/* This might add unreliability; I don't trust it -- rms. */
4992 if (! f
->async_visible
&& ! f
->async_iconified
)
4998 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
4999 that the current position of the window is user-specified, rather than
5000 program-specified, so that when the window is mapped again, it will be
5001 placed at the same location, without forcing the user to position it
5002 by hand again (they have already done that once for this window.) */
5003 x_wm_set_size_hint (f
, 0, 1);
5007 if (! XWithdrawWindow (x_current_display
, window
,
5008 DefaultScreen (x_current_display
)))
5010 UNBLOCK_INPUT_RESIGNAL
;
5011 error ("Can't notify window manager of window withdrawal");
5013 #else /* ! defined (HAVE_X11R4) */
5015 /* Tell the window manager what we're going to do. */
5016 if (! EQ (Vx_no_window_manager
, Qt
))
5020 unmap
.xunmap
.type
= UnmapNotify
;
5021 unmap
.xunmap
.window
= window
;
5022 unmap
.xunmap
.event
= DefaultRootWindow (x_current_display
);
5023 unmap
.xunmap
.from_configure
= False
;
5024 if (! XSendEvent (x_current_display
,
5025 DefaultRootWindow (x_current_display
),
5027 SubstructureRedirectMask
|SubstructureNotifyMask
,
5030 UNBLOCK_INPUT_RESIGNAL
;
5031 error ("Can't notify window manager of withdrawal");
5035 /* Unmap the window ourselves. Cheeky! */
5036 XUnmapWindow (x_current_display
, window
);
5037 #endif /* ! defined (HAVE_X11R4) */
5039 /* We can't distinguish this from iconification
5040 just by the event that we get from the server.
5041 So we can't win using the usual strategy of letting
5042 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5043 and synchronize with the server to make sure we agree. */
5045 FRAME_ICONIFIED_P (f
) = 0;
5046 f
->async_visible
= 0;
5047 f
->async_iconified
= 0;
5054 /* Change window state from mapped to iconified. */
5062 /* Don't keep the highlight on an invisible frame. */
5063 if (x_highlight_frame
== f
)
5064 x_highlight_frame
= 0;
5066 if (f
->async_iconified
)
5069 #ifdef USE_X_TOOLKIT
5072 if (! FRAME_VISIBLE_P (f
))
5074 if (! EQ (Vx_no_window_manager
, Qt
))
5075 x_wm_set_window_state (f
, IconicState
);
5076 /* This was XtPopup, but that did nothing for an iconified frame. */
5077 XtMapWidget (f
->display
.x
->widget
);
5082 result
= XIconifyWindow (x_current_display
,
5083 XtWindow (f
->display
.x
->widget
),
5084 DefaultScreen (x_current_display
));
5088 error ("Can't notify window manager of iconification");
5090 f
->async_iconified
= 1;
5095 #else /* not USE_X_TOOLKIT */
5099 /* Make sure the X server knows where the window should be positioned,
5100 in case the user deiconifies with the window manager. */
5101 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
5102 x_set_offset (f
, f
->display
.x
->left_pos
, f
->display
.x
->top_pos
, 0);
5104 /* Since we don't know which revision of X we're running, we'll use both
5105 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
5107 /* X11R4: send a ClientMessage to the window manager using the
5108 WM_CHANGE_STATE type. */
5112 message
.xclient
.window
= FRAME_X_WINDOW (f
);
5113 message
.xclient
.type
= ClientMessage
;
5114 message
.xclient
.message_type
= Xatom_wm_change_state
;
5115 message
.xclient
.format
= 32;
5116 message
.xclient
.data
.l
[0] = IconicState
;
5118 if (! XSendEvent (x_current_display
,
5119 DefaultRootWindow (x_current_display
),
5121 SubstructureRedirectMask
| SubstructureNotifyMask
,
5124 UNBLOCK_INPUT_RESIGNAL
;
5125 error ("Can't notify window manager of iconification");
5129 /* X11R3: set the initial_state field of the window manager hints to
5131 x_wm_set_window_state (f
, IconicState
);
5133 if (!FRAME_VISIBLE_P (f
))
5135 /* If the frame was withdrawn, before, we must map it. */
5136 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
5137 #if 0 /* We don't have subwindows in the icon. */
5138 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5139 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
5143 f
->async_iconified
= 1;
5147 #endif /* not USE_X_TOOLKIT */
5150 /* Destroy the X window of frame F. */
5152 x_destroy_window (f
)
5157 if (f
->display
.x
->icon_desc
!= 0)
5158 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
5159 XDestroyWindow (XDISPLAY f
->display
.x
->window_desc
);
5160 #ifdef USE_X_TOOLKIT
5161 XtDestroyWidget (f
->display
.x
->widget
);
5162 free_frame_menubar (f
);
5163 #endif /* USE_X_TOOLKIT */
5165 free_frame_faces (f
);
5168 FRAME_X_SCREEN (f
)->reference_count
--;
5170 if (FRAME_X_SCREEN (f
)->reference_count
== 0)
5171 free (FRAME_X_SCREEN (f
));
5174 xfree (f
->display
.x
);
5176 if (f
== x_focus_frame
)
5178 if (f
== x_highlight_frame
)
5179 x_highlight_frame
= 0;
5181 if (f
== mouse_face_mouse_frame
)
5183 mouse_face_beg_row
= mouse_face_beg_col
= -1;
5184 mouse_face_end_row
= mouse_face_end_col
= -1;
5185 mouse_face_window
= Qnil
;
5191 /* Setting window manager hints. */
5193 /* Set the normal size hints for the window manager, for frame F.
5194 FLAGS is the flags word to use--or 0 meaning preserve the flags
5195 that the window now has.
5196 If USER_POSITION is nonzero, we set the USPosition
5197 flag (this is useful when FLAGS is 0). */
5199 x_wm_set_size_hint (f
, flags
, user_position
)
5204 XSizeHints size_hints
;
5206 #ifdef USE_X_TOOLKIT
5209 Dimension widget_width
, widget_height
;
5210 Window window
= XtWindow (f
->display
.x
->widget
);
5211 #else /* not USE_X_TOOLKIT */
5212 Window window
= FRAME_X_WINDOW (f
);
5213 #endif /* not USE_X_TOOLKIT */
5215 /* Setting PMaxSize caused various problems. */
5216 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
5218 flexlines
= f
->height
;
5220 size_hints
.x
= f
->display
.x
->left_pos
;
5221 size_hints
.y
= f
->display
.x
->top_pos
;
5223 #ifdef USE_X_TOOLKIT
5224 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
5225 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
5226 XtGetValues (f
->display
.x
->column_widget
, al
, ac
);
5227 size_hints
.height
= widget_height
;
5228 size_hints
.width
= widget_width
;
5229 #else /* not USE_X_TOOLKIT */
5230 size_hints
.height
= PIXEL_HEIGHT (f
);
5231 size_hints
.width
= PIXEL_WIDTH (f
);
5232 #endif /* not USE_X_TOOLKIT */
5234 size_hints
.width_inc
= FONT_WIDTH (f
->display
.x
->font
);
5235 size_hints
.height_inc
= f
->display
.x
->line_height
;
5236 size_hints
.max_width
= x_screen_width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
5237 size_hints
.max_height
= x_screen_height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
5240 int base_width
, base_height
;
5241 int min_rows
= 0, min_cols
= 0;
5243 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
5244 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
5246 check_frame_size (f
, &min_rows
, &min_cols
);
5248 /* The window manager uses the base width hints to calculate the
5249 current number of rows and columns in the frame while
5250 resizing; min_width and min_height aren't useful for this
5251 purpose, since they might not give the dimensions for a
5252 zero-row, zero-column frame.
5254 We use the base_width and base_height members if we have
5255 them; otherwise, we set the min_width and min_height members
5256 to the size for a zero x zero frame. */
5259 size_hints
.flags
|= PBaseSize
;
5260 size_hints
.base_width
= base_width
;
5261 size_hints
.base_height
= base_height
;
5262 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
5263 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
5265 size_hints
.min_width
= base_width
;
5266 size_hints
.min_height
= base_height
;
5271 size_hints
.flags
|= flags
;
5274 XSizeHints hints
; /* Sometimes I hate X Windows... */
5275 long supplied_return
;
5279 value
= XGetWMNormalHints (x_current_display
, window
, &hints
,
5282 value
= XGetNormalHints (x_current_display
, window
, &hints
);
5287 if (hints
.flags
& PSize
)
5288 size_hints
.flags
|= PSize
;
5289 if (hints
.flags
& PPosition
)
5290 size_hints
.flags
|= PPosition
;
5291 if (hints
.flags
& USPosition
)
5292 size_hints
.flags
|= USPosition
;
5293 if (hints
.flags
& USSize
)
5294 size_hints
.flags
|= USSize
;
5298 size_hints
.win_gravity
= f
->display
.x
->win_gravity
;
5299 size_hints
.flags
|= PWinGravity
;
5303 size_hints
.flags
&= ~ PPosition
;
5304 size_hints
.flags
|= USPosition
;
5306 #endif /* PWinGravity */
5309 XSetWMNormalHints (x_current_display
, window
, &size_hints
);
5311 XSetNormalHints (x_current_display
, window
, &size_hints
);
5315 /* Used for IconicState or NormalState */
5316 x_wm_set_window_state (f
, state
)
5320 #ifdef USE_X_TOOLKIT
5323 XtSetArg (al
[0], XtNinitialState
, state
);
5324 XtSetValues (f
->display
.x
->widget
, al
, 1);
5325 #else /* not USE_X_TOOLKIT */
5326 Window window
= FRAME_X_WINDOW (f
);
5328 f
->display
.x
->wm_hints
.flags
|= StateHint
;
5329 f
->display
.x
->wm_hints
.initial_state
= state
;
5331 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
5332 #endif /* not USE_X_TOOLKIT */
5335 x_wm_set_icon_pixmap (f
, icon_pixmap
)
5339 #ifdef USE_X_TOOLKIT
5340 Window window
= XtWindow (f
->display
.x
->widget
);
5342 Window window
= FRAME_X_WINDOW (f
);
5347 f
->display
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
5348 f
->display
.x
->wm_hints
.flags
|= IconPixmapHint
;
5351 f
->display
.x
->wm_hints
.flags
&= ~IconPixmapHint
;
5353 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
5356 x_wm_set_icon_position (f
, icon_x
, icon_y
)
5360 #ifdef USE_X_TOOLKIT
5361 Window window
= XtWindow (f
->display
.x
->widget
);
5363 Window window
= FRAME_X_WINDOW (f
);
5366 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
5367 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
5368 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
5370 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
5374 /* Initialization. */
5376 #ifdef USE_X_TOOLKIT
5377 static XrmOptionDescRec emacs_options
[] = {
5378 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
5379 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
5381 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
5382 XrmoptionSepArg
, NULL
},
5383 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
5385 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5386 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5387 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5388 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5389 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5390 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
5391 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
5393 #endif /* USE_X_TOOLKIT */
5396 x_term_init (display_name
, xrm_option
, resource_name
)
5399 char *resource_name
;
5405 #ifndef F_SETOWN_BUG
5407 extern int old_fcntl_owner
;
5408 #endif /* ! defined (F_SETOWN) */
5409 #endif /* F_SETOWN_BUG */
5413 x_focus_frame
= x_highlight_frame
= 0;
5415 #ifdef USE_X_TOOLKIT
5416 argv
= (char **) XtMalloc (7 * sizeof (char *));
5418 argv
[1] = "-display";
5419 argv
[2] = display_name
;
5421 /* Usually `emacs', but not always. */
5422 argv
[4] = resource_name
;
5426 argv
[argc
++] = "-xrm";
5427 argv
[argc
++] = xrm_option
;
5429 Xt_app_shell
= XtAppInitialize (&Xt_app_con
, "Emacs",
5430 emacs_options
, XtNumber (emacs_options
),
5433 XtFree ((char *)argv
);
5434 x_current_display
= XtDisplay (Xt_app_shell
);
5436 #else /* not USE_X_TOOLKIT */
5437 x_current_display
= XOpenDisplay (display_name
);
5438 #endif /* not USE_X_TOOLKIT */
5439 if (x_current_display
== 0)
5440 fatal ("X server %s not responding.\n\
5441 Check the DISPLAY environment variable or use \"-d\"\n",
5446 XSetAfterFunction (x_current_display
, x_trace_wire
);
5448 x_id_name
= (char *) xmalloc (XSTRING (Vinvocation_name
)->size
5449 + XSTRING (Vsystem_name
)->size
5451 sprintf (x_id_name
, "%s@%s",
5452 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
5455 /* Figure out which modifier bits mean what. */
5456 x_find_modifier_meanings ();
5458 /* Get the scroll bar cursor. */
5459 x_vertical_scroll_bar_cursor
5460 = XCreateFontCursor (x_current_display
, XC_sb_v_double_arrow
);
5463 /* Watch for PropertyNotify events on the root window; we use them
5464 to figure out when to invalidate our cache of the cut buffers. */
5465 x_watch_cut_buffer_cache ();
5468 if (ConnectionNumber (x_current_display
) != 0)
5469 change_keyboard_wait_descriptor (ConnectionNumber (x_current_display
));
5470 change_input_fd (ConnectionNumber (x_current_display
));
5472 #ifndef F_SETOWN_BUG
5474 old_fcntl_owner
= fcntl (ConnectionNumber (x_current_display
), F_GETOWN
, 0);
5475 #ifdef F_SETOWN_SOCK_NEG
5476 /* stdin is a socket here */
5477 fcntl (ConnectionNumber (x_current_display
), F_SETOWN
, -getpid ());
5478 #else /* ! defined (F_SETOWN_SOCK_NEG) */
5479 fcntl (ConnectionNumber (x_current_display
), F_SETOWN
, getpid ());
5480 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
5481 #endif /* ! defined (F_SETOWN) */
5482 #endif /* F_SETOWN_BUG */
5486 #endif /* ! defined (SIGIO) */
5488 expose_all_windows
= 0;
5490 clear_frame_hook
= XTclear_frame
;
5491 clear_end_of_line_hook
= XTclear_end_of_line
;
5492 ins_del_lines_hook
= XTins_del_lines
;
5493 change_line_highlight_hook
= XTchange_line_highlight
;
5494 insert_glyphs_hook
= XTinsert_glyphs
;
5495 write_glyphs_hook
= XTwrite_glyphs
;
5496 delete_glyphs_hook
= XTdelete_glyphs
;
5497 ring_bell_hook
= XTring_bell
;
5498 reset_terminal_modes_hook
= XTreset_terminal_modes
;
5499 set_terminal_modes_hook
= XTset_terminal_modes
;
5500 update_begin_hook
= XTupdate_begin
;
5501 update_end_hook
= XTupdate_end
;
5502 set_terminal_window_hook
= XTset_terminal_window
;
5503 read_socket_hook
= XTread_socket
;
5504 frame_up_to_date_hook
= XTframe_up_to_date
;
5505 cursor_to_hook
= XTcursor_to
;
5506 reassert_line_highlight_hook
= XTreassert_line_highlight
;
5507 mouse_position_hook
= XTmouse_position
;
5508 frame_rehighlight_hook
= XTframe_rehighlight
;
5509 frame_raise_lower_hook
= XTframe_raise_lower
;
5510 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
5511 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
5512 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
5513 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
5515 scroll_region_ok
= 1; /* we'll scroll partial frames */
5516 char_ins_del_ok
= 0; /* just as fast to write the line */
5517 line_ins_del_ok
= 1; /* we'll just blt 'em */
5518 fast_clear_end_of_line
= 1; /* X does this well */
5519 memory_below_frame
= 0; /* we don't remember what scrolls
5523 /* Try to use interrupt input; if we can't, then start polling. */
5524 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
5526 /* Note that there is no real way portable across R3/R4 to get the
5527 original error handler. */
5528 XHandleError (x_error_quitter
);
5529 XHandleIOError (x_io_error_quitter
);
5531 /* Disable Window Change signals; they are handled by X events. */
5533 signal (SIGWINCH
, SIG_DFL
);
5534 #endif /* ! defined (SIGWINCH) */
5536 signal (SIGPIPE
, x_connection_closed
);
5542 staticpro (&last_mouse_scroll_bar
);
5543 last_mouse_scroll_bar
= Qnil
;
5544 staticpro (&mouse_face_window
);
5545 mouse_face_window
= Qnil
;
5547 #endif /* ! defined (HAVE_X_WINDOWS) */