1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1993 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. */
22 Kludge: dup2 is used to put the X-connection socket into desc # 0
23 so that wait_reading_process_input will wait for it in place of
24 actual terminal input.
28 /* Xt features made by Fred Pierresteguy. */
30 #define NEW_SELECTIONS
32 /* On 4.3 these lose if they come after xterm.h. */
33 /* On HP-UX 8.0 signal.h loses if it comes after config.h. */
34 /* Putting these at the beginning seems to be standard for other .c files. */
40 /* Need syssignal.h for various externs and definitions that may be required
41 * by some configurations for calls to signal() later in this source file.
43 #include "syssignal.h"
48 #include "blockinput.h"
50 /* This may include sys/types.h, and that somehow loses
51 if this is not done before the other system files. */
53 #include <X11/cursorfont.h>
56 /* Load sys/types.h if not already loaded.
57 In some systems loading it twice is suicidal. */
59 #include <sys/types.h>
64 #include <sys/ioctl.h>
66 #else /* ! defined (BSD) */
70 #endif /* ! defined (BSD) */
80 #include <sys/param.h>
82 #include "dispextern.h"
83 #include "termhooks.h"
97 extern XtAppContext Xt_app_con
;
98 extern Widget Xt_app_shell
;
99 #endif /* USE_X_TOOLKIT */
102 #define XMapWindow XMapRaised /* Raise them when mapping. */
103 #else /* ! defined (HAVE_X11) */
104 #include <X/Xkeyboard.h>
105 /*#include <X/Xproto.h> */
106 #endif /* ! defined (HAVE_X11) */
109 /* We could get this from param.h, but better not to depend on finding that.
110 And better not to risk that it might define other symbols used in this
113 #define MAXDESC FD_SETSIZE
117 #define SELECT_TYPE fd_set
118 #else /* no FD_SET */
120 #define SELECT_TYPE int
122 /* Define the macros to access a single-int bitmap of descriptors. */
123 #define FD_SET(n, p) (*(p) |= (1 << (n)))
124 #define FD_CLR(n, p) (*(p) &= ~(1 << (n)))
125 #define FD_ISSET(n, p) (*(p) & (1 << (n)))
126 #define FD_ZERO(p) (*(p) = 0)
127 #endif /* no FD_SET */
129 /* For sending Meta-characters. Do we need this? */
132 #define min(a,b) ((a)<(b) ? (a) : (b))
133 #define max(a,b) ((a)>(b) ? (a) : (b))
135 /* Nonzero means we must reprint all windows
136 because 1) we received an ExposeWindow event
137 or 2) we received too many ExposeRegion events to record.
139 This is never needed under X11. */
140 static int expose_all_windows
;
142 /* Nonzero means we must reprint all icon windows. */
144 static int expose_all_icons
;
147 /* ExposeRegion events, when received, are copied into this queue
148 for later processing. */
150 static struct event_queue x_expose_queue
;
152 /* ButtonPress and ButtonReleased events, when received,
153 are copied into this queue for later processing. */
155 struct event_queue x_mouse_queue
;
156 #endif /* HAVE_X11 */
158 #if defined (SIGIO) && defined (FIONREAD)
159 int BLOCK_INPUT_mask
;
160 #endif /* ! defined (SIGIO) && defined (FIONREAD) */
162 /* The id of a bitmap used for icon windows.
163 One such map is shared by all Emacs icon windows.
164 This is zero if we have not yet had a need to create the bitmap. */
166 static Bitmap icon_bitmap
;
168 /* Font used for text icons. */
170 static FONT_TYPE
*icon_font_info
;
172 /* Stuff for dealing with the main icon title. */
174 extern Lisp_Object Vcommand_line_args
;
175 char *hostname
, *x_id_name
;
177 /* This is the X connection that we are using. */
179 Display
*x_current_display
;
181 /* The cursor to use for vertical scroll bars on x_current_display. */
182 static Cursor x_vertical_scroll_bar_cursor
;
184 /* Frame being updated by update_frame. This is declared in term.c.
185 This is set by update_begin and looked at by all the
186 XT functions. It is zero while not inside an update.
187 In that case, the XT functions assume that `selected_frame'
188 is the frame to apply to. */
189 extern struct frame
*updating_frame
;
191 /* The frame (if any) which has the X window that has keyboard focus.
192 Zero if none. This is examined by Ffocus_frame in frame.c. Note
193 that a mere EnterNotify event can set this; if you need to know the
194 last frame specified in a FocusIn or FocusOut event, use
195 x_focus_event_frame. */
196 struct frame
*x_focus_frame
;
198 /* The last frame mentioned in a FocusIn or FocusOut event. This is
199 separate from x_focus_frame, because whether or not LeaveNotify
200 events cause us to lose focus depends on whether or not we have
201 received a FocusIn event for it. */
202 struct frame
*x_focus_event_frame
;
204 /* The frame which currently has the visual highlight, and should get
205 keyboard input (other sorts of input have the frame encoded in the
206 event). It points to the X focus frame's selected window's
207 frame. It differs from x_focus_frame when we're using a global
209 static struct frame
*x_highlight_frame
;
211 /* From .Xdefaults, the value of "emacs.WarpMouse". If non-zero,
212 mouse is moved to inside of frame when frame is de-iconified. */
214 static int warp_mouse_on_deiconify
;
216 /* During an update, maximum vpos for ins/del line operations to affect. */
218 static int flexlines
;
220 /* During an update, nonzero if chars output now should be highlighted. */
222 static int highlight
;
224 /* Nominal cursor position -- where to draw output.
225 During an update, these are different from the cursor-box position. */
232 In order to avoid asking for motion events and then throwing most
233 of them away or busy-polling the server for mouse positions, we ask
234 the server for pointer motion hints. This means that we get only
235 one event per group of mouse movements. "Groups" are delimited by
236 other kinds of events (focus changes and button clicks, for
237 example), or by XQueryPointer calls; when one of these happens, we
238 get another MotionNotify event the next time the mouse moves. This
239 is at least as efficient as getting motion events when mouse
240 tracking is on, and I suspect only negligibly worse when tracking
243 The silly O'Reilly & Associates Nutshell guides barely document
244 pointer motion hints at all (I think you have to infer how they
245 work from an example), and the description of XQueryPointer doesn't
246 mention that calling it causes you to get another motion hint from
247 the server, which is very important. */
249 /* Where the mouse was last time we reported a mouse event. */
250 static FRAME_PTR last_mouse_frame
;
251 static XRectangle last_mouse_glyph
;
253 /* The scroll bar in which the last X motion event occurred.
255 If the last X motion event occurred in a scroll bar, we set this
256 so XTmouse_position can know whether to report a scroll bar motion or
259 If the last X motion event didn't occur in a scroll bar, we set this
260 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
261 static Lisp_Object last_mouse_scroll_bar
;
263 /* Record which buttons are currently pressed. */
264 unsigned int x_mouse_grabbed
;
266 /* This is a hack. We would really prefer that XTmouse_position would
267 return the time associated with the position it returns, but there
268 doesn't seem to be any way to wrest the timestamp from the server
269 along with the position query. So, we just keep track of the time
270 of the last movement we received, and return that in hopes that
271 it's somewhat accurate. */
272 static Time last_mouse_movement_time
;
275 /* `t' if a mouse button is depressed. */
277 extern Lisp_Object Vmouse_depressed
;
279 /* Tells if a window manager is present or not. */
281 extern Lisp_Object Vx_no_window_manager
;
283 /* Timestamp that we requested selection data was made. */
284 extern Time requestor_time
;
286 /* ID of the window requesting selection data. */
287 extern Window requestor_window
;
289 /* Nonzero enables some debugging for the X interface code. */
292 #else /* ! defined (HAVE_X11) */
294 /* Bit patterns for the mouse cursor. */
296 short MouseCursor
[] = {
297 0x0000, 0x0008, 0x0018, 0x0038,
298 0x0078, 0x00f8, 0x01f8, 0x03f8,
299 0x07f8, 0x00f8, 0x00d8, 0x0188,
300 0x0180, 0x0300, 0x0300, 0x0000};
302 short MouseMask
[] = {
303 0x000c, 0x001c, 0x003c, 0x007c,
304 0x00fc, 0x01fc, 0x03fc, 0x07fc,
305 0x0ffc, 0x0ffc, 0x01fc, 0x03dc,
306 0x03cc, 0x0780, 0x0780, 0x0300};
308 static short grey_bits
[] = {
309 0x0005, 0x000a, 0x0005, 0x000a};
311 static Pixmap GreyPixmap
= 0;
312 #endif /* ! defined (HAVE_X11) */
314 /* From time to time we get info on an Emacs window, here. */
316 static WINDOWINFO_TYPE windowinfo
;
320 /* A mask of extra modifier bits to put into every keyboard char. */
321 extern int extra_keyboard_modifiers
;
323 extern Display
*XOpenDisplay ();
324 extern Window
XCreateWindow ();
326 extern Cursor
XCreateCursor ();
327 extern FONT_TYPE
*XOpenFont ();
329 static void flashback ();
330 static void redraw_previous_char ();
331 static unsigned int x_x_to_emacs_modifiers ();
334 static void dumpqueue ();
335 #endif /* HAVE_X11 */
338 static int XTcursor_to ();
339 static int XTclear_end_of_line ();
342 /* Starting and ending updates.
344 These hooks are called by update_frame at the beginning and end
345 of a frame update. We record in `updating_frame' the identity
346 of the frame being updated, so that the XT... functions do not
347 need to take a frame as argument. Most of the XT... functions
348 should never be called except during an update, the only exceptions
349 being XTcursor_to, XTwrite_glyphs and XTreassert_line_highlight. */
351 extern int mouse_track_top
, mouse_track_left
, mouse_track_width
;
362 flexlines
= f
->height
;
368 #endif /* HAVE_X11 */
373 static void x_do_pending_expose ();
385 x_do_pending_expose ();
386 #endif /* HAVE_X11 */
388 x_display_cursor (f
, 1);
394 /* External interface to control of standout mode.
395 Call this when about to modify line at position VPOS
396 and not change whether it is highlighted. */
398 XTreassert_line_highlight (new, vpos
)
404 /* Call this when about to modify line at position VPOS
405 and change whether it is highlighted. */
408 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
409 int new_highlight
, vpos
, first_unused_hpos
;
411 highlight
= new_highlight
;
412 XTcursor_to (vpos
, 0);
413 XTclear_end_of_line (updating_frame
->width
);
416 /* This is used when starting Emacs and when restarting after suspend.
417 When starting Emacs, no X window is mapped. And nothing must be done
418 to Emacs's own window if it is suspended (though that rarely happens). */
421 XTset_terminal_modes ()
425 /* This is called when exiting or suspending Emacs.
426 Exiting will make the X-windows go away, and suspending
427 requires no action. */
430 XTreset_terminal_modes ()
432 /* XTclear_frame (); */
435 /* Set the nominal cursor position of the frame.
436 This is where display update commands will take effect.
437 This does not affect the place where the cursor-box is displayed. */
440 XTcursor_to (row
, col
)
441 register int row
, col
;
449 if (updating_frame
== 0)
452 x_display_cursor (selected_frame
, 1);
458 /* Display a sequence of N glyphs found at GP.
459 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
460 HL is 1 if this text is highlighted, 2 if the cursor is on it.
462 FONT is the default font to use (for glyphs whose font-code is 0).
464 Since the display generation code is responsible for calling
465 compute_char_face and compute_glyph_face on everything it puts in
466 the display structure, we can assume that the face code on each
467 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
468 to which we can actually apply intern_face. */
471 /* This is the multi-face code. */
474 dumpglyphs (f
, left
, top
, gp
, n
, hl
)
477 register GLYPH
*gp
; /* Points to first GLYPH. */
478 register int n
; /* Number of glyphs to display. */
481 /* Holds characters to be displayed. */
482 char *buf
= (char *) alloca (f
->width
* sizeof (*buf
));
483 register char *cp
; /* Steps through buf[]. */
484 register int tlen
= GLYPH_TABLE_LENGTH
;
485 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
486 Window window
= FRAME_X_WINDOW (f
);
490 /* Get the face-code of the next GLYPH. */
494 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
497 /* Find the run of consecutive glyphs with the same face-code.
498 Extract their character codes into BUF. */
503 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
504 if (GLYPH_FACE (g
) != cf
)
507 *cp
++ = GLYPH_CHAR (g
);
512 /* LEN gets the length of the run. */
515 /* Now output this run of chars, with the font and pixel values
516 determined by the face code CF. */
518 struct face
*face
= FRAME_DEFAULT_FACE (f
);
519 FONT_TYPE
*font
= FACE_FONT (face
);
520 GC gc
= FACE_GC (face
);
522 int gc_temporary
= 0;
524 /* First look at the face of the text itself. */
527 /* It's possible for the display table to specify
528 a face code that is out of range. Use 0 in that case. */
529 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
530 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
534 face
= FRAME_MODE_LINE_FACE (f
);
536 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
537 font
= FACE_FONT (face
);
542 /* Then comes the distinction between modeline and normal text. */
547 face
= FRAME_MODE_LINE_FACE (f
);
548 font
= FACE_FONT (face
);
553 #define FACE_DEFAULT (~0)
555 /* Now override that if the cursor's on this character. */
560 || (int) face
->font
== FACE_DEFAULT
)
562 gc
= f
->display
.x
->cursor_gc
;
564 /* Cursor on non-default face: must merge. */
570 xgcv
.background
= f
->display
.x
->cursor_pixel
;
571 xgcv
.foreground
= f
->display
.x
->cursor_foreground_pixel
;
572 xgcv
.font
= face
->font
->fid
;
573 xgcv
.graphics_exposures
= 0;
574 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
575 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
578 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
579 XSetStipple (x_current_display
, gc
, face
->stipple
);
585 if ((int) font
== FACE_DEFAULT
)
586 font
= f
->display
.x
->font
;
588 XDrawImageString (x_current_display
, window
, gc
,
589 left
, top
+ FONT_BASE (font
), buf
, len
);
592 XFreeGC (x_current_display
, gc
);
594 /* We should probably check for XA_UNDERLINE_POSITION and
595 XA_UNDERLINE_THICKNESS properties on the font, but let's
596 just get the thing working, and come back to that. */
598 int underline_position
= 1;
600 if (font
->descent
<= underline_position
)
601 underline_position
= font
->descent
- 1;
604 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
608 + underline_position
),
609 len
* FONT_WIDTH (font
), 1);
612 left
+= len
* FONT_WIDTH (font
);
619 /* This is the old single-face code. */
622 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
625 register GLYPH
*gp
; /* Points to first GLYPH. */
626 register int n
; /* Number of glyphs to display. */
631 Window window
= FRAME_X_WINDOW (f
);
632 GC drawing_gc
= (hl
== 2 ? f
->display
.x
->cursor_gc
633 : (hl
? f
->display
.x
->reverse_gc
634 : f
->display
.x
->normal_gc
));
636 if (sizeof (GLYPH
) == sizeof (XChar2b
))
637 XDrawImageString16 (x_current_display
, window
, drawing_gc
,
638 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
639 else if (sizeof (GLYPH
) == sizeof (unsigned char))
640 XDrawImageString (x_current_display
, window
, drawing_gc
,
641 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
643 /* What size of glyph ARE you using? And does X have a function to
649 /* Output some text at the nominal frame cursor position.
650 Advance the cursor over the text.
651 Output LEN glyphs at START.
653 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
654 controls the pixel values used for foreground and background. */
657 XTwrite_glyphs (start
, len
)
658 register GLYPH
*start
;
661 register int temp_length
;
671 /* If not within an update,
672 output at the frame's visible cursor. */
673 curs_x
= f
->cursor_x
;
674 curs_y
= f
->cursor_y
;
678 CHAR_TO_PIXEL_COL (f
, curs_x
),
679 CHAR_TO_PIXEL_ROW (f
, curs_y
),
680 start
, len
, highlight
);
682 /* If we drew on top of the cursor, note that it is turned off. */
683 if (curs_y
== f
->phys_cursor_y
684 && curs_x
<= f
->phys_cursor_x
685 && curs_x
+ len
> f
->phys_cursor_x
)
686 f
->phys_cursor_x
= -1;
688 if (updating_frame
== 0)
691 x_display_cursor (f
, 1);
700 /* Clear to the end of the line.
701 Erase the current text line from the nominal cursor position (inclusive)
702 to column FIRST_UNUSED (exclusive). The idea is that everything
703 from FIRST_UNUSED onward is already erased. */
706 XTclear_end_of_line (first_unused
)
707 register int first_unused
;
709 struct frame
*f
= updating_frame
;
715 if (curs_y
< 0 || curs_y
>= f
->height
)
717 if (first_unused
<= 0)
720 if (first_unused
>= f
->width
)
721 first_unused
= f
->width
;
725 /* Notice if the cursor will be cleared by this operation. */
726 if (curs_y
== f
->phys_cursor_y
727 && curs_x
<= f
->phys_cursor_x
728 && f
->phys_cursor_x
< first_unused
)
729 f
->phys_cursor_x
= -1;
732 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
733 CHAR_TO_PIXEL_COL (f
, curs_x
),
734 CHAR_TO_PIXEL_ROW (f
, curs_y
),
735 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
736 FONT_HEIGHT (f
->display
.x
->font
), False
);
738 redraw_previous_char (f
, curs_x
, curs_y
);
740 #else /* ! defined (HAVE_X11) */
741 XPixSet (FRAME_X_WINDOW (f
),
742 CHAR_TO_PIXEL_COL (f
, curs_x
),
743 CHAR_TO_PIXEL_ROW (f
, curs_y
),
744 FONT_WIDTH (f
->display
.x
->font
) * (first_unused
- curs_x
),
745 FONT_HEIGHT (f
->display
.x
->font
),
746 f
->display
.x
->background_pixel
);
747 #endif /* ! defined (HAVE_X11) */
752 /* Erase the character (if any) at the position just before X, Y in frame F,
753 then redraw it and the character before it.
754 This is necessary when we erase starting at X,
755 in case the character after X overlaps into the one before X. */
758 redraw_previous_char (f
, x
, y
)
762 /* Erase the character before the new ones, in case
763 what was here before overlaps it.
764 Reoutput that character, and the previous character
765 (in case the previous character overlaps it). */
771 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
772 CHAR_TO_PIXEL_COL (f
, x
- 1),
773 CHAR_TO_PIXEL_ROW (f
, y
),
774 FONT_WIDTH (f
->display
.x
->font
),
775 FONT_HEIGHT (f
->display
.x
->font
), False
);
777 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, start_x
),
778 CHAR_TO_PIXEL_ROW (f
, y
),
779 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][start_x
],
780 x
- start_x
, highlight
);
788 struct frame
*f
= updating_frame
;
793 f
->phys_cursor_x
= -1; /* Cursor not visible. */
794 curs_x
= 0; /* Nominal cursor position is top left. */
799 XClear (FRAME_X_WINDOW (f
));
801 /* We have to clear the scroll bars, too. If we have changed
802 colors or something like that, then they should be notified. */
803 x_scroll_bar_clear (f
);
807 #endif /* HAVE_X11 */
813 /* Invert the middle quarter of the frame for .15 sec. */
815 /* We use the select system call to do the waiting, so we have to make sure
816 it's available. If it isn't, we just won't do visual bells. */
817 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
819 /* Subtract the `struct timeval' values X and Y,
820 storing the result in RESULT.
821 Return 1 if the difference is negative, otherwise 0. */
824 timeval_subtract (result
, x
, y
)
825 struct timeval
*result
, x
, y
;
827 /* Perform the carry for the later subtraction by updating y.
828 This is safer because on some systems
829 the tv_sec member is unsigned. */
830 if (x
.tv_usec
< y
.tv_usec
)
832 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
833 y
.tv_usec
-= 1000000 * nsec
;
836 if (x
.tv_usec
- y
.tv_usec
> 1000000)
838 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
839 y
.tv_usec
+= 1000000 * nsec
;
843 /* Compute the time remaining to wait. tv_usec is certainly positive. */
844 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
845 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
847 /* Return indication of whether the result should be considered negative. */
848 return x
.tv_sec
< y
.tv_sec
;
859 /* Create a GC that will use the GXxor function to flip foreground pixels
860 into background pixels. */
864 values
.function
= GXxor
;
865 values
.foreground
= (f
->display
.x
->foreground_pixel
866 ^ f
->display
.x
->background_pixel
);
868 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
869 GCFunction
| GCForeground
, &values
);
873 int width
= PIXEL_WIDTH (f
);
874 int height
= PIXEL_HEIGHT (f
);
876 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
877 width
/4, height
/4, width
/2, height
/2);
878 XFlush (x_current_display
);
881 struct timeval wakeup
, now
;
883 EMACS_GET_TIME (wakeup
);
885 /* Compute time to wait until, propagating carry from usecs. */
886 wakeup
.tv_usec
+= 150000;
887 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
888 wakeup
.tv_usec
%= 1000000;
890 /* Keep waiting until past the time wakeup. */
893 struct timeval timeout
;
895 EMACS_GET_TIME (timeout
);
897 /* In effect, timeout = wakeup - timeout.
898 Break if result would be negative. */
899 if (timeval_subtract (&timeout
, wakeup
, timeout
))
902 /* Try to wait that long--but we might wake up sooner. */
903 select (0, 0, 0, 0, &timeout
);
907 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
908 width
/4, height
/4, width
/2, height
/2);
909 XFreeGC (x_current_display
, gc
);
910 XFlush (x_current_display
);
920 /* Make audible bell. */
923 #define XRINGBELL XBell(x_current_display, 0)
924 #else /* ! defined (HAVE_X11) */
925 #define XRINGBELL XFeep(0);
926 #endif /* ! defined (HAVE_X11) */
930 if (x_current_display
== 0)
933 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
935 XTflash (selected_frame
);
946 /* Insert and delete character.
947 These are not supposed to be used because we are supposed to turn
948 off the feature of using them. */
951 XTinsert_glyphs (start
, len
)
952 register char *start
;
965 /* Specify how many text lines, from the top of the window,
966 should be affected by insert-lines and delete-lines operations.
967 This, and those operations, are used only within an update
968 that is bounded by calls to XTupdate_begin and XTupdate_end. */
971 XTset_terminal_window (n
)
974 if (updating_frame
== 0)
977 if ((n
<= 0) || (n
> updating_frame
->height
))
978 flexlines
= updating_frame
->height
;
983 /* Perform an insert-lines operation.
984 Insert N lines at a vertical position curs_y. */
990 register int topregion
, bottomregion
;
991 register int length
, newtop
, mask
;
992 register struct frame
*f
= updating_frame
;
993 int intborder
= f
->display
.x
->internal_border_width
;
995 if (curs_y
>= flexlines
)
999 bottomregion
= flexlines
- (n
+ 1);
1000 newtop
= topregion
+ n
;
1001 length
= (bottomregion
- topregion
) + 1;
1005 #endif /* HAVE_X11 */
1007 if ((length
> 0) && (newtop
<= flexlines
))
1010 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
1011 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
1012 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
1013 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1014 length
* FONT_HEIGHT (f
->display
.x
->font
), intborder
,
1015 CHAR_TO_PIXEL_ROW (f
, newtop
));
1016 #else /* ! defined (HAVE_X11) */
1017 XMoveArea (FRAME_X_WINDOW (f
),
1018 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
1019 intborder
, CHAR_TO_PIXEL_ROW (f
, newtop
),
1020 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1021 length
* FONT_HEIGHT (f
->display
.x
->font
));
1022 /* Now we must process any ExposeRegion events that occur
1023 if the area being copied from is obscured.
1024 We can't let it wait because further i/d operations
1025 may want to copy this area to another area. */
1027 #endif /* ! defined (HAVE_X11) */
1030 newtop
= min (newtop
, (flexlines
- 1));
1031 length
= newtop
- topregion
;
1035 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
1036 CHAR_TO_PIXEL_ROW (f
, topregion
),
1037 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1038 n
* FONT_HEIGHT (f
->display
.x
->font
), False
);
1039 #else /* ! defined (HAVE_X11) */
1040 XPixSet (FRAME_X_WINDOW (f
),
1042 CHAR_TO_PIXEL_ROW (f
, topregion
),
1043 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1044 n
* FONT_HEIGHT (f
->display
.x
->font
),
1045 f
->display
.x
->background_pixel
);
1046 #endif /* ! defined (HAVE_X11) */
1050 /* Perform a delete-lines operation, deleting N lines
1051 at a vertical position curs_y. */
1058 register struct frame
*f
= updating_frame
;
1059 int intborder
= f
->display
.x
->internal_border_width
;
1061 if (curs_y
>= flexlines
)
1066 #endif /* HAVE_X11 */
1068 if ((curs_y
+ n
) >= flexlines
)
1070 if (flexlines
>= (curs_y
+ 1))
1073 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
1074 CHAR_TO_PIXEL_ROW (f
, curs_y
),
1075 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1076 (flexlines
- curs_y
) * FONT_HEIGHT (f
->display
.x
->font
), False
);
1077 #else /* ! defined (HAVE_X11) */
1078 XPixSet (FRAME_X_WINDOW (f
),
1079 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
1080 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1081 (flexlines
- curs_y
) * FONT_HEIGHT (f
->display
.x
->font
),
1082 f
->display
.x
->background_pixel
);
1083 #endif /* ! defined (HAVE_X11) */
1089 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
1090 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
1092 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
1093 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1094 (flexlines
- (curs_y
+ n
)) * FONT_HEIGHT (f
->display
.x
->font
),
1095 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
));
1096 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
1098 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
1099 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1100 n
* FONT_HEIGHT (f
->display
.x
->font
), False
);
1101 #else /* ! defined (HAVE_X11) */
1102 XMoveArea (FRAME_X_WINDOW (f
),
1104 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
1105 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
1106 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1107 (flexlines
- (curs_y
+ n
)) * FONT_HEIGHT (f
->display
.x
->font
));
1108 /* Now we must process any ExposeRegion events that occur
1109 if the area being copied from is obscured.
1110 We can't let it wait because further i/d operations
1111 may want to copy this area to another area. */
1113 XPixSet (FRAME_X_WINDOW (f
), intborder
,
1114 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
1115 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1116 n
* FONT_HEIGHT (f
->display
.x
->font
), f
->display
.x
->background_pixel
);
1117 #endif /* ! defined (HAVE_X11) */
1121 /* Perform an insert-lines or delete-lines operation,
1122 inserting N lines or deleting -N lines at vertical position VPOS. */
1124 XTins_del_lines (vpos
, n
)
1127 if (updating_frame
== 0)
1130 /* Hide the cursor. */
1131 x_display_cursor (updating_frame
, 0);
1133 XTcursor_to (vpos
, 0);
1144 /* Support routines for exposure events. */
1145 static void clear_cursor ();
1147 /* Output into a rectangle of an X-window (for frame F)
1148 the characters in f->phys_lines that overlap that rectangle.
1149 TOP and LEFT are the position of the upper left corner of the rectangle.
1150 ROWS and COLS are the size of the rectangle. */
1153 dumprectangle (f
, left
, top
, cols
, rows
)
1155 register int left
, top
, cols
, rows
;
1157 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1158 int cursor_cleared
= 0;
1162 if (FRAME_GARBAGED_P (f
))
1165 /* Express rectangle as four edges, instead of position-and-size. */
1166 bottom
= top
+ rows
;
1167 right
= left
+ cols
;
1169 #ifndef HAVE_X11 /* Window manger does this for X11. */
1171 int intborder
= f
->display
.x
->internal_border_width
;
1173 /* If the rectangle includes any of the internal border area,
1174 redisplay the border emphasis. */
1175 if (top
< intborder
|| left
< intborder
1176 || bottom
> intborder
+ f
->height
* FONT_HEIGHT (f
->display
.x
->font
)
1177 || right
> intborder
+ f
->width
* FONT_WIDTH (f
->display
.x
->font
))
1180 #endif /* HAVE_X11 Window manger does this for X11. */
1182 /* Convert rectangle edges in pixels to edges in chars.
1183 Round down for left and top, up for right and bottom. */
1184 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1185 left
= PIXEL_TO_CHAR_COL (f
, left
);
1186 bottom
+= (FONT_HEIGHT (f
->display
.x
->font
) - 1);
1187 right
+= (FONT_WIDTH (f
->display
.x
->font
) - 1);
1188 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1189 right
= PIXEL_TO_CHAR_COL (f
, right
);
1191 /* Clip the rectangle to what can be visible. */
1196 if (right
> f
->width
)
1198 if (bottom
> f
->height
)
1201 /* Get size in chars of the rectangle. */
1202 cols
= right
- left
;
1203 rows
= bottom
- top
;
1205 /* If rectangle has zero area, return. */
1206 if (rows
<= 0) return;
1207 if (cols
<= 0) return;
1209 /* Turn off the cursor if it is in the rectangle.
1210 We will turn it back on afterward. */
1211 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1212 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1218 /* Display the text in the rectangle, one text line at a time. */
1220 for (y
= top
; y
< bottom
; y
++)
1222 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1224 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1228 CHAR_TO_PIXEL_COL (f
, left
),
1229 CHAR_TO_PIXEL_ROW (f
, y
),
1230 line
, min (cols
, active_frame
->used
[y
] - left
),
1231 active_frame
->highlight
[y
]);
1234 /* Turn the cursor on if we turned it off. */
1237 x_display_cursor (f
, 1);
1241 /* Process all queued ExposeRegion events. */
1247 XExposeRegionEvent r
;
1249 while (dequeue_event (&r
, &x_expose_queue
))
1251 struct frame
*f
= x_window_to_frame (r
.window
);
1252 if (f
->display
.x
->icon_desc
== r
.window
)
1255 dumprectangle (f
, r
.x
, r
.y
, r
.width
, r
.height
);
1259 #endif /* HAVE_X11 */
1261 /* Process all expose events that are pending, for X10.
1262 Redraws the cursor if necessary on any frame that
1263 is not in the process of being updated with update_frame. */
1267 x_do_pending_expose ()
1271 Lisp_Object tail
, frame
;
1273 if (expose_all_windows
)
1275 expose_all_windows
= 0;
1276 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
1278 register int temp_width
, temp_height
;
1281 frame
= XCONS (tail
)->car
;
1282 if (XGCTYPE (frame
) != Lisp_Frame
)
1285 if (! FRAME_X_P (f
))
1287 if (!f
->async_visible
)
1289 if (!f
->display
.x
->needs_exposure
)
1292 intborder
= f
->display
.x
->internal_border_width
;
1295 XGetWindowInfo (FRAME_X_WINDOW (f
), &windowinfo
);
1296 temp_width
= ((windowinfo
.width
- 2 * intborder
1297 - f
->display
.x
->v_scroll_bar_width
)
1298 / FONT_WIDTH (f
->display
.x
->font
));
1299 temp_height
= ((windowinfo
.height
- 2 * intborder
1300 - f
->display
.x
->h_scroll_bar_height
)
1301 / FONT_HEIGHT (f
->display
.x
->font
));
1302 if (temp_width
!= f
->width
|| temp_height
!= f
->height
)
1304 change_frame_size (f
, max (1, temp_height
),
1305 max (1, temp_width
), 0, 1);
1306 x_resize_scroll_bars (f
);
1308 f
->display
.x
->left_pos
= windowinfo
.x
;
1309 f
->display
.x
->top_pos
= windowinfo
.y
;
1310 dumprectangle (f
, 0, 0, PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
));
1314 f
->display
.x
->needs_exposure
= 0;
1315 if (updating_frame
!= f
)
1316 x_display_cursor (f
, 1);
1321 /* Handle any individual-rectangle expose events queued
1322 for various windows. */
1325 #else /* ! defined (HAVE_X11) */
1327 #endif /* ! defined (HAVE_X11) */
1333 frame_highlight (frame
)
1334 struct frame
*frame
;
1336 /* We used to only do this if Vx_no_window_manager was non-nil, but
1337 the ICCCM (section 4.1.6) says that the window's border pixmap
1338 and border pixel are window attributes which are "private to the
1339 client", so we can always change it to whatever we want. */
1341 XSetWindowBorder (x_current_display
, FRAME_X_WINDOW (frame
),
1342 frame
->display
.x
->border_pixel
);
1344 x_display_cursor (frame
, 1);
1348 frame_unhighlight (frame
)
1349 struct frame
*frame
;
1351 /* We used to only do this if Vx_no_window_manager was non-nil, but
1352 the ICCCM (section 4.1.6) says that the window's border pixmap
1353 and border pixel are window attributes which are "private to the
1354 client", so we can always change it to whatever we want. */
1356 XSetWindowBorderPixmap (x_current_display
, FRAME_X_WINDOW (frame
),
1357 frame
->display
.x
->border_tile
);
1359 x_display_cursor (frame
, 1);
1361 #else /* ! defined (HAVE_X11) */
1362 /* Dump the border-emphasis of frame F.
1363 If F is selected, this is a lining of the same color as the border,
1364 just within the border, occupying a portion of the internal border.
1365 If F is not selected, it is background in the same place.
1366 If ALWAYS is 0, don't bother explicitly drawing if it's background.
1368 ALWAYS = 1 is used when a frame becomes selected or deselected.
1369 In that case, we also turn the cursor off and on again
1370 so it will appear in the proper shape (solid if selected; else hollow.) */
1373 dumpborder (f
, always
)
1377 int thickness
= f
->display
.x
->internal_border_width
/ 2;
1378 int width
= PIXEL_WIDTH (f
);
1379 int height
= PIXEL_HEIGHT (f
);
1382 if (f
!= selected_frame
)
1387 pixel
= f
->display
.x
->background_pixel
;
1391 pixel
= f
->display
.x
->border_pixel
;
1394 XPixSet (FRAME_X_WINDOW (f
), 0, 0, width
, thickness
, pixel
);
1395 XPixSet (FRAME_X_WINDOW (f
), 0, 0, thickness
, height
, pixel
);
1396 XPixSet (FRAME_X_WINDOW (f
), 0, height
- thickness
, width
,
1398 XPixSet (FRAME_X_WINDOW (f
), width
- thickness
, 0, thickness
,
1402 x_display_cursor (f
, 1);
1404 #endif /* ! defined (HAVE_X11) */
1406 static void XTframe_rehighlight ();
1408 /* The focus has changed. Update the frames as necessary to reflect
1409 the new situation. Note that we can't change the selected frame
1410 here, because the lisp code we are interrupting might become confused.
1411 Each event gets marked with the frame in which it occurred, so the
1412 lisp code can tell when the switch took place by examining the events. */
1415 x_new_focus_frame (frame
)
1416 struct frame
*frame
;
1418 struct frame
*old_focus
= x_focus_frame
;
1419 int events_enqueued
= 0;
1421 if (frame
!= x_focus_frame
)
1423 /* Set this before calling other routines, so that they see
1424 the correct value of x_focus_frame. */
1425 x_focus_frame
= frame
;
1427 if (old_focus
&& old_focus
->auto_lower
)
1428 x_lower_frame (old_focus
);
1431 selected_frame
= frame
;
1432 XSET (XWINDOW (selected_frame
->selected_window
)->frame
,
1433 Lisp_Frame
, selected_frame
);
1434 Fselect_window (selected_frame
->selected_window
);
1435 choose_minibuf_frame ();
1438 if (x_focus_frame
&& x_focus_frame
->auto_raise
)
1439 x_raise_frame (x_focus_frame
);
1442 XTframe_rehighlight ();
1446 /* The focus has changed, or we have redirected a frame's focus to
1447 another frame (this happens when a frame uses a surrogate
1448 minibuffer frame). Shift the highlight as appropriate. */
1450 XTframe_rehighlight ()
1452 struct frame
*old_highlight
= x_highlight_frame
;
1457 ((XGCTYPE (FRAME_FOCUS_FRAME (x_focus_frame
)) == Lisp_Frame
)
1458 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame
))
1460 if (! FRAME_LIVE_P (x_highlight_frame
))
1462 FRAME_FOCUS_FRAME (x_focus_frame
) = Qnil
;
1463 x_highlight_frame
= x_focus_frame
;
1467 x_highlight_frame
= 0;
1469 if (x_highlight_frame
!= old_highlight
)
1472 frame_unhighlight (old_highlight
);
1473 if (x_highlight_frame
)
1474 frame_highlight (x_highlight_frame
);
1478 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
1480 /* Which modifier keys are on which modifier bits?
1482 With each keystroke, X returns eight bits indicating which modifier
1483 keys were held down when the key was pressed. The interpretation
1484 of the top five modifier bits depends on what keys are attached
1485 to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
1488 x_meta_mod_mask is a mask containing the bits used for the meta key.
1489 It may have more than one bit set, if more than one modifier bit
1490 has meta keys on it. Basically, if EVENT is a KeyPress event,
1491 the meta key is pressed if (EVENT.state & x_meta_mod_mask) != 0.
1493 x_shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
1494 lock modifier bit, or zero otherwise. Non-alphabetic keys should
1495 only be affected by the lock modifier bit if XK_Shift_Lock is in
1496 use; XK_Caps_Lock should only affect alphabetic keys. With this
1497 arrangement, the lock modifier should shift the character if
1498 (EVENT.state & x_shift_lock_mask) != 0. */
1499 static int x_meta_mod_mask
, x_shift_lock_mask
;
1501 /* These are like x_meta_mod_mask, but for different modifiers. */
1502 static int x_alt_mod_mask
, x_super_mod_mask
, x_hyper_mod_mask
;
1504 /* Initialize mode_switch_bit and modifier_meaning. */
1506 x_find_modifier_meanings ()
1508 int min_code
, max_code
;
1511 XModifierKeymap
*mods
;
1513 x_meta_mod_mask
= 0;
1514 x_shift_lock_mask
= 0;
1516 x_super_mod_mask
= 0;
1517 x_hyper_mod_mask
= 0;
1520 XDisplayKeycodes (x_current_display
, &min_code
, &max_code
);
1522 min_code
= x_current_display
->min_keycode
;
1523 max_code
= x_current_display
->max_keycode
;
1526 syms
= XGetKeyboardMapping (x_current_display
,
1527 min_code
, max_code
- min_code
+ 1,
1529 mods
= XGetModifierMapping (x_current_display
);
1531 /* Scan the modifier table to see which modifier bits the Meta and
1532 Alt keysyms are on. */
1534 int row
, col
; /* The row and column in the modifier table. */
1536 for (row
= 3; row
< 8; row
++)
1537 for (col
= 0; col
< mods
->max_keypermod
; col
++)
1540 mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
1542 /* Are any of this keycode's keysyms a meta key? */
1546 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
1548 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
1554 x_meta_mod_mask
|= (1 << row
);
1559 x_alt_mod_mask
|= (1 << row
);
1564 x_hyper_mod_mask
|= (1 << row
);
1569 x_super_mod_mask
|= (1 << row
);
1573 /* Ignore this if it's not on the lock modifier. */
1574 if ((1 << row
) == LockMask
)
1575 x_shift_lock_mask
= LockMask
;
1583 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1584 if (! x_meta_mod_mask
)
1586 x_meta_mod_mask
= x_alt_mod_mask
;
1590 /* If some keys are both alt and meta,
1591 make them just meta, not alt. */
1592 if (x_alt_mod_mask
& x_meta_mod_mask
)
1594 x_alt_mod_mask
&= ~x_meta_mod_mask
;
1597 XFree ((char *) syms
);
1598 XFreeModifiermap (mods
);
1601 /* Prepare a menu-event in *RESULT for placement in the input queue. */
1604 construct_menu_click (result
, event
, f
)
1605 struct input_event
*result
;
1606 XButtonEvent
*event
;
1609 /* Make the event type no_event; we'll change that when we decide
1611 result
->kind
= mouse_click
;
1612 XSET (result
->code
, Lisp_Int
, event
->button
- Button1
);
1613 result
->timestamp
= event
->time
;
1614 result
->modifiers
= (x_x_to_emacs_modifiers (event
->state
)
1615 | (event
->type
== ButtonRelease
1620 XFASTINT (result
->x
) = event
->x
;
1621 XFASTINT (result
->y
) = -1; /* special meaning for menubar */
1622 XSET (result
->frame_or_window
, Lisp_Frame
, f
);
1626 /* Convert between the modifier bits X uses and the modifier bits
1629 x_x_to_emacs_modifiers (state
)
1632 return ( ((state
& (ShiftMask
| x_shift_lock_mask
)) ? shift_modifier
: 0)
1633 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
1634 | ((state
& x_meta_mod_mask
) ? meta_modifier
: 0)
1635 | ((state
& x_alt_mod_mask
) ? alt_modifier
: 0)
1636 | ((state
& x_super_mod_mask
) ? super_modifier
: 0)
1637 | ((state
& x_hyper_mod_mask
) ? hyper_modifier
: 0));
1641 x_emacs_to_x_modifiers (state
)
1644 return ( ((state
& alt_modifier
) ? x_alt_mod_mask
: 0)
1645 | ((state
& super_modifier
) ? x_super_mod_mask
: 0)
1646 | ((state
& hyper_modifier
) ? x_hyper_mod_mask
: 0)
1647 | ((state
& shift_modifier
) ? ShiftMask
: 0)
1648 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
1649 | ((state
& meta_modifier
) ? x_meta_mod_mask
: 0));
1652 /* Return true iff KEYSYM is a vendor-specific keysym that we should
1653 return as a function key. If you add a keysym to this, you should
1654 make sure that the tables make_lispy_event uses contain a suitable
1657 x_is_vendor_fkey (sym
)
1662 || (sym
== DXK_Remove
)
1668 /* Mouse clicks and mouse movement. Rah. */
1671 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1672 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1673 that the glyph at X, Y occupies, if BOUNDS != 0.
1674 If NOCLIP is nonzero, do not force the value into range. */
1677 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1679 register int pix_x
, pix_y
;
1680 register int *x
, *y
;
1684 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1685 even for negative values. */
1687 pix_x
-= FONT_WIDTH ((f
)->display
.x
->font
) - 1;
1689 pix_y
-= FONT_HEIGHT ((f
)->display
.x
->font
) - 1;
1691 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1692 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1696 bounds
->width
= FONT_WIDTH (f
->display
.x
->font
);
1697 bounds
->height
= FONT_HEIGHT (f
->display
.x
->font
);
1698 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1699 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1706 else if (pix_x
> f
->width
)
1711 else if (pix_y
> f
->height
)
1719 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1721 If the event is a button press, then note that we have grabbed
1725 construct_mouse_click (result
, event
, f
)
1726 struct input_event
*result
;
1727 XButtonEvent
*event
;
1730 /* Make the event type no_event; we'll change that when we decide
1732 result
->kind
= mouse_click
;
1733 result
->code
= event
->button
- Button1
;
1734 result
->timestamp
= event
->time
;
1735 result
->modifiers
= (x_x_to_emacs_modifiers (event
->state
)
1736 | (event
->type
== ButtonRelease
1740 /* Notice if the mouse is still grabbed. */
1741 if (event
->type
== ButtonPress
)
1743 if (! x_mouse_grabbed
)
1744 Vmouse_depressed
= Qt
;
1745 x_mouse_grabbed
|= (1 << event
->button
);
1746 last_mouse_frame
= f
;
1748 else if (event
->type
== ButtonRelease
)
1750 x_mouse_grabbed
&= ~(1 << event
->button
);
1751 if (!x_mouse_grabbed
)
1752 Vmouse_depressed
= Qnil
;
1758 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
, 0);
1759 XFASTINT (result
->x
) = column
;
1760 XFASTINT (result
->y
) = row
;
1761 XSET (result
->frame_or_window
, Lisp_Frame
, f
);
1765 /* Function to report a mouse movement to the mainstream Emacs code.
1766 The input handler calls this.
1768 We have received a mouse movement event, which is given in *event.
1769 If the mouse is over a different glyph than it was last time, tell
1770 the mainstream emacs code by setting mouse_moved. If not, ask for
1771 another motion event, so we can check again the next time it moves. */
1773 note_mouse_movement (frame
, event
)
1775 XMotionEvent
*event
;
1778 last_mouse_movement_time
= event
->time
;
1780 /* Has the mouse moved off the glyph it was on at the last sighting? */
1781 if (event
->x
< last_mouse_glyph
.x
1782 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
1783 || event
->y
< last_mouse_glyph
.y
1784 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
1787 last_mouse_scroll_bar
= Qnil
;
1791 /* It's on the same glyph. Call XQueryPointer so we'll get an
1792 event the next time the mouse moves and we can see if it's
1793 *still* on the same glyph. */
1796 XQueryPointer (event
->display
, event
->window
,
1797 (Window
*) &dummy
, (Window
*) &dummy
,
1798 &dummy
, &dummy
, &dummy
, &dummy
,
1799 (unsigned int *) &dummy
);
1803 static struct scroll_bar
*x_window_to_scroll_bar ();
1804 static void x_scroll_bar_report_motion ();
1806 /* Return the current position of the mouse.
1808 If the mouse movement started in a scroll bar, set *f, *bar_window,
1809 and *part to the frame, window, and scroll bar part that the mouse
1810 is over. Set *x and *y to the portion and whole of the mouse's
1811 position on the scroll bar.
1813 If the mouse movement started elsewhere, set *f to the frame the
1814 mouse is on, *bar_window to nil, and *x and *y to the character cell
1817 Set *time to the server timestamp for the time at which the mouse
1818 was at this position.
1820 Don't store anything if we don't have a valid set of values to report.
1822 This clears the mouse_moved flag, so we can wait for the next mouse
1823 movement. This also calls XQueryPointer, which will cause the
1824 server to give us another MotionNotify when the mouse moves
1828 XTmouse_position (f
, bar_window
, part
, x
, y
, time
)
1830 Lisp_Object
*bar_window
;
1831 enum scroll_bar_part
*part
;
1833 unsigned long *time
;
1839 if (! NILP (last_mouse_scroll_bar
))
1840 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
);
1846 Window dummy_window
;
1850 last_mouse_scroll_bar
= Qnil
;
1852 /* Figure out which root window we're on. */
1853 XQueryPointer (x_current_display
,
1854 DefaultRootWindow (x_current_display
),
1856 /* The root window which contains the pointer. */
1859 /* Trash which we can't trust if the pointer is on
1860 a different screen. */
1863 /* The position on that root window. */
1866 /* More trash we can't trust. */
1869 /* Modifier keys and pointer buttons, about which
1871 (unsigned int *) &dummy
);
1873 /* Now we have a position on the root; find the innermost window
1874 containing the pointer. */
1878 int parent_x
, parent_y
;
1882 if (x_mouse_grabbed
)
1884 /* If mouse was grabbed on a frame, give coords for that frame
1885 even if the mouse is now outside it. */
1886 XTranslateCoordinates (x_current_display
,
1888 /* From-window, to-window. */
1889 root
, FRAME_X_WINDOW (last_mouse_frame
),
1891 /* From-position, to-position. */
1892 root_x
, root_y
, &win_x
, &win_y
,
1896 f1
= last_mouse_frame
;
1902 XTranslateCoordinates (x_current_display
,
1904 /* From-window, to-window. */
1907 /* From-position, to-position. */
1908 root_x
, root_y
, &win_x
, &win_y
,
1921 /* Now we know that:
1922 win is the innermost window containing the pointer
1923 (XTC says it has no child containing the pointer),
1924 win_x and win_y are the pointer's position in it
1925 (XTC did this the last time through), and
1926 parent_x and parent_y are the pointer's position in win's parent.
1927 (They are what win_x and win_y were when win was child.
1928 If win is the root window, it has no parent, and
1929 parent_{x,y} are invalid, but that's okay, because we'll
1930 never use them in that case.) */
1932 /* Is win one of our frames? */
1933 f1
= x_window_to_frame (win
);
1936 /* If not, is it one of our scroll bars? */
1939 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
1943 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1951 /* Ok, we found a frame. Convert from pixels to characters
1952 and store all the values. */
1954 pixel_to_glyph_coords (f1
, win_x
, win_y
, &win_x
, &win_y
,
1955 &last_mouse_glyph
, x_mouse_grabbed
);
1960 XSET (*x
, Lisp_Int
, win_x
);
1961 XSET (*y
, Lisp_Int
, win_y
);
1962 *time
= last_mouse_movement_time
;
1970 #else /* ! defined (HAVE_X11) */
1971 #define XEvent XKeyPressedEvent
1972 #endif /* ! defined (HAVE_X11) */
1974 /* Scroll bar support. */
1976 /* Given an X window ID, find the struct scroll_bar which manages it.
1977 This can be called in GC, so we have to make sure to strip off mark
1979 static struct scroll_bar
*
1980 x_window_to_scroll_bar (window_id
)
1983 Lisp_Object tail
, frame
;
1985 for (tail
= Vframe_list
;
1986 XGCTYPE (tail
) == Lisp_Cons
;
1987 tail
= XCONS (tail
)->cdr
)
1989 Lisp_Object frame
= XCONS (tail
)->car
;
1990 Lisp_Object bar
, condemned
;
1992 /* All elements of Vframe_list should be frames. */
1993 if (XGCTYPE (frame
) != Lisp_Frame
)
1996 /* Scan this frame's scroll bar list for a scroll bar with the
1998 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
1999 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
2000 /* This trick allows us to search both the ordinary and
2001 condemned scroll bar lists with one loop. */
2002 ! GC_NILP (bar
) || (bar
= condemned
,
2005 bar
= XSCROLL_BAR(bar
)->next
)
2006 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
2007 return XSCROLL_BAR (bar
);
2013 /* Open a new X window to serve as a scroll bar, and return the
2014 scroll bar vector for it. */
2015 static struct scroll_bar
*
2016 x_scroll_bar_create (window
, top
, left
, width
, height
)
2017 struct window
*window
;
2018 int top
, left
, width
, height
;
2020 FRAME_PTR frame
= XFRAME (WINDOW_FRAME (window
));
2021 struct scroll_bar
*bar
=
2022 XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2027 XSetWindowAttributes a
;
2029 a
.background_pixel
= frame
->display
.x
->background_pixel
;
2030 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
2031 | ButtonMotionMask
| PointerMotionHintMask
2033 a
.cursor
= x_vertical_scroll_bar_cursor
;
2035 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
2040 XtSetArg (al
[ac
], XtNx
, left
); ac
++;
2041 XtSetArg (al
[ac
], XtNy
, top
); ac
++;
2042 XtSetArg (al
[ac
], XtNwidth
, width
); ac
++;
2043 XtSetArg (al
[ac
], XtNheight
, height
); ac
++;
2044 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
2045 sb_widget
= XtCreateManagedWidget ("box",
2047 frame
->display
.x
->edit_widget
, al
, ac
);
2048 SET_SCROLL_BAR_X_WINDOW
2049 (bar
, sb_widget
->core
.window
);
2051 SET_SCROLL_BAR_X_WINDOW
2053 XCreateWindow (x_current_display
, FRAME_X_WINDOW (frame
),
2055 /* Position and size of scroll bar. */
2056 left
, top
, width
, height
,
2058 /* Border width, depth, class, and visual. */
2059 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
2065 XSET (bar
->window
, Lisp_Window
, window
);
2066 XSET (bar
->top
, Lisp_Int
, top
);
2067 XSET (bar
->left
, Lisp_Int
, left
);
2068 XSET (bar
->width
, Lisp_Int
, width
);
2069 XSET (bar
->height
, Lisp_Int
, height
);
2070 XSET (bar
->start
, Lisp_Int
, 0);
2071 XSET (bar
->end
, Lisp_Int
, 0);
2072 bar
->dragging
= Qnil
;
2074 /* Add bar to its frame's list of scroll bars. */
2075 bar
->next
= FRAME_SCROLL_BARS (frame
);
2077 XSET (FRAME_SCROLL_BARS (frame
), Lisp_Vector
, bar
);
2078 if (! NILP (bar
->next
))
2079 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
2081 XMapWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
2088 /* Draw BAR's handle in the proper position.
2089 If the handle is already drawn from START to END, don't bother
2090 redrawing it, unless REBUILD is non-zero; in that case, always
2091 redraw it. (REBUILD is handy for drawing the handle after expose
2094 Normally, we want to constrain the start and end of the handle to
2095 fit inside its rectangle, but if the user is dragging the scroll bar
2096 handle, we want to let them drag it down all the way, so that the
2097 bar's top is as far down as it goes; otherwise, there's no way to
2098 move to the very end of the buffer. */
2100 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
2101 struct scroll_bar
*bar
;
2105 int dragging
= ! NILP (bar
->dragging
);
2106 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2107 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
2109 /* If the display is already accurate, do nothing. */
2111 && start
== XINT (bar
->start
)
2112 && end
== XINT (bar
->end
))
2118 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar
->width
));
2119 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2120 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2122 /* Make sure the values are reasonable, and try to preserve
2123 the distance between start and end. */
2125 int length
= end
- start
;
2129 else if (start
> top_range
)
2131 end
= start
+ length
;
2135 else if (end
> top_range
&& ! dragging
)
2139 /* Store the adjusted setting in the scroll bar. */
2140 XSET (bar
->start
, Lisp_Int
, start
);
2141 XSET (bar
->end
, Lisp_Int
, end
);
2143 /* Clip the end position, just for display. */
2144 if (end
> top_range
)
2147 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
2148 below top positions, to make sure the handle is always at least
2149 that many pixels tall. */
2150 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2152 /* Draw the empty space above the handle. Note that we can't clear
2153 zero-height areas; that means "clear to end of window." */
2155 XClearArea (x_current_display
, w
,
2157 /* x, y, width, height, and exposures. */
2158 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2159 VERTICAL_SCROLL_BAR_TOP_BORDER
,
2160 inside_width
, start
,
2163 /* Draw the handle itself. */
2164 XFillRectangle (x_current_display
, w
, gc
,
2166 /* x, y, width, height */
2167 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2168 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
2169 inside_width
, end
- start
);
2172 /* Draw the empty space below the handle. Note that we can't
2173 clear zero-height areas; that means "clear to end of window." */
2174 if (end
< inside_height
)
2175 XClearArea (x_current_display
, w
,
2177 /* x, y, width, height, and exposures. */
2178 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2179 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
2180 inside_width
, inside_height
- end
,
2188 /* Move a scroll bar around on the screen, to accommodate changing
2189 window configurations. */
2191 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2192 struct scroll_bar
*bar
;
2193 int top
, left
, width
, height
;
2199 unsigned int mask
= 0;
2206 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
2207 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
2208 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
2209 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
2212 XConfigureWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
),
2216 XSET (bar
->left
, Lisp_Int
, left
);
2217 XSET (bar
->top
, Lisp_Int
, top
);
2218 XSET (bar
->width
, Lisp_Int
, width
);
2219 XSET (bar
->height
, Lisp_Int
, height
);
2224 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2227 x_scroll_bar_remove (bar
)
2228 struct scroll_bar
*bar
;
2230 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2234 /* Destroy the window. */
2235 XDestroyWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
2237 /* Disassociate this scroll bar from its window. */
2238 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2243 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2244 that we are displaying PORTION characters out of a total of WHOLE
2245 characters, starting at POSITION. If WINDOW has no scroll bar,
2248 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
2249 struct window
*window
;
2250 int portion
, whole
, position
;
2252 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2253 int top
= XINT (window
->top
);
2254 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2255 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2257 /* Where should this scroll bar be, pixelwise? */
2258 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2259 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2260 int pixel_width
= VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
);
2261 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2263 struct scroll_bar
*bar
;
2265 /* Does the scroll bar exist yet? */
2266 if (NILP (window
->vertical_scroll_bar
))
2267 bar
= x_scroll_bar_create (window
,
2268 pixel_top
, pixel_left
,
2269 pixel_width
, pixel_height
);
2272 /* It may just need to be moved and resized. */
2273 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2274 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2277 /* Set the scroll bar's current state, unless we're currently being
2279 if (NILP (bar
->dragging
))
2282 VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2285 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2288 int start
= ((double) position
* top_range
) / whole
;
2289 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
2291 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2295 XSET (window
->vertical_scroll_bar
, Lisp_Vector
, bar
);
2299 /* The following three hooks are used when we're doing a thorough
2300 redisplay of the frame. We don't explicitly know which scroll bars
2301 are going to be deleted, because keeping track of when windows go
2302 away is a real pain - "Can you say set-window-configuration, boys
2303 and girls?" Instead, we just assert at the beginning of redisplay
2304 that *all* scroll bars are to be removed, and then save a scroll bar
2305 from the fiery pit when we actually redisplay its window. */
2307 /* Arrange for all scroll bars on FRAME to be removed at the next call
2308 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2309 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2311 XTcondemn_scroll_bars (frame
)
2314 /* The condemned list should be empty at this point; if it's not,
2315 then the rest of Emacs isn't using the condemn/redeem/judge
2316 protocol correctly. */
2317 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2320 /* Move them all to the "condemned" list. */
2321 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2322 FRAME_SCROLL_BARS (frame
) = Qnil
;
2325 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2326 Note that WINDOW isn't necessarily condemned at all. */
2328 XTredeem_scroll_bar (window
)
2329 struct window
*window
;
2331 struct scroll_bar
*bar
;
2333 /* We can't redeem this window's scroll bar if it doesn't have one. */
2334 if (NILP (window
->vertical_scroll_bar
))
2337 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2339 /* Unlink it from the condemned list. */
2341 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2343 if (NILP (bar
->prev
))
2345 /* If the prev pointer is nil, it must be the first in one of
2347 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2348 /* It's not condemned. Everything's fine. */
2350 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2351 window
->vertical_scroll_bar
))
2352 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2354 /* If its prev pointer is nil, it must be at the front of
2355 one or the other! */
2359 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2361 if (! NILP (bar
->next
))
2362 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2364 bar
->next
= FRAME_SCROLL_BARS (f
);
2366 XSET (FRAME_SCROLL_BARS (f
), Lisp_Vector
, bar
);
2367 if (! NILP (bar
->next
))
2368 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
2372 /* Remove all scroll bars on FRAME that haven't been saved since the
2373 last call to `*condemn_scroll_bars_hook'. */
2375 XTjudge_scroll_bars (f
)
2378 Lisp_Object bar
, next
;
2380 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2382 /* Clear out the condemned list now so we won't try to process any
2383 more events on the hapless scroll bars. */
2384 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2386 for (; ! NILP (bar
); bar
= next
)
2388 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2390 x_scroll_bar_remove (b
);
2393 b
->next
= b
->prev
= Qnil
;
2396 /* Now there should be no references to the condemned scroll bars,
2397 and they should get garbage-collected. */
2401 /* Handle an Expose or GraphicsExpose event on a scroll bar.
2403 This may be called from a signal handler, so we have to ignore GC
2406 x_scroll_bar_expose (bar
, event
)
2407 struct scroll_bar
*bar
;
2410 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2411 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
2415 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
2417 /* Draw a one-pixel border just inside the edges of the scroll bar. */
2418 XDrawRectangle (x_current_display
, w
, gc
,
2420 /* x, y, width, height */
2421 0, 0, XINT (bar
->width
) - 1, XINT (bar
->height
) - 1);
2423 /* Draw another line to make the extra-thick border on the right. */
2424 XFillRectangle (x_current_display
, w
, gc
,
2426 /* x, y, width, height */
2427 XINT (bar
->width
) - 2, 1, 1, XINT (bar
->height
) - 2);
2432 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2433 is set to something other than no_event, it is enqueued.
2435 This may be called from a signal handler, so we have to ignore GC
2438 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
2439 struct scroll_bar
*bar
;
2441 struct input_event
*emacs_event
;
2443 if (XGCTYPE (bar
->window
) != Lisp_Window
)
2446 emacs_event
->kind
= scroll_bar_click
;
2447 emacs_event
->code
= event
->xbutton
.button
- Button1
;
2448 emacs_event
->modifiers
=
2449 (x_x_to_emacs_modifiers (event
->xbutton
.state
)
2450 | (event
->type
== ButtonRelease
2453 emacs_event
->frame_or_window
= bar
->window
;
2454 emacs_event
->timestamp
= event
->xbutton
.time
;
2456 int internal_height
=
2457 VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2459 VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2460 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
2463 if (y
> top_range
) y
= top_range
;
2465 if (y
< XINT (bar
->start
))
2466 emacs_event
->part
= scroll_bar_above_handle
;
2467 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2468 emacs_event
->part
= scroll_bar_handle
;
2470 emacs_event
->part
= scroll_bar_below_handle
;
2472 /* Just because the user has clicked on the handle doesn't mean
2473 they want to drag it. Lisp code needs to be able to decide
2474 whether or not we're dragging. */
2476 /* If the user has just clicked on the handle, record where they're
2478 if (event
->type
== ButtonPress
2479 && emacs_event
->part
== scroll_bar_handle
)
2480 XSET (bar
->dragging
, Lisp_Int
, y
- XINT (bar
->start
));
2483 /* If the user has released the handle, set it to its final position. */
2484 if (event
->type
== ButtonRelease
2485 && ! NILP (bar
->dragging
))
2487 int new_start
= y
- XINT (bar
->dragging
);
2488 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2490 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2491 bar
->dragging
= Qnil
;
2494 /* Same deal here as the other #if 0. */
2496 /* Clicks on the handle are always reported as occurring at the top of
2498 if (emacs_event
->part
== scroll_bar_handle
)
2499 emacs_event
->x
= bar
->start
;
2501 XSET (emacs_event
->x
, Lisp_Int
, y
);
2503 XSET (emacs_event
->x
, Lisp_Int
, y
);
2506 XSET (emacs_event
->y
, Lisp_Int
, top_range
);
2510 /* Handle some mouse motion while someone is dragging the scroll bar.
2512 This may be called from a signal handler, so we have to ignore GC
2515 x_scroll_bar_note_movement (bar
, event
)
2516 struct scroll_bar
*bar
;
2519 last_mouse_movement_time
= event
->xmotion
.time
;
2522 XSET (last_mouse_scroll_bar
, Lisp_Vector
, bar
);
2524 /* If we're dragging the bar, display it. */
2525 if (! GC_NILP (bar
->dragging
))
2527 /* Where should the handle be now? */
2528 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
2530 if (new_start
!= XINT (bar
->start
))
2532 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2534 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2538 /* Call XQueryPointer so we'll get an event the next time the mouse
2539 moves and we can see *still* on the same position. */
2543 XQueryPointer (event
->xmotion
.display
, event
->xmotion
.window
,
2544 (Window
*) &dummy
, (Window
*) &dummy
,
2545 &dummy
, &dummy
, &dummy
, &dummy
,
2546 (unsigned int *) &dummy
);
2550 /* Return information to the user about the current position of the mouse
2551 on the scroll bar. */
2553 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
)
2555 Lisp_Object
*bar_window
;
2556 enum scroll_bar_part
*part
;
2558 unsigned long *time
;
2560 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
2562 Window dummy_window
;
2564 unsigned int dummy_mask
;
2568 /* Get the mouse's position relative to the scroll bar window, and
2570 if (! XQueryPointer (x_current_display
,
2571 SCROLL_BAR_X_WINDOW (bar
),
2573 /* Root, child, root x and root y. */
2574 &dummy_window
, &dummy_window
,
2575 &dummy_coord
, &dummy_coord
,
2577 /* Position relative to scroll bar. */
2580 /* Mouse buttons and modifier keys. */
2586 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2588 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2590 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
2592 if (! NILP (bar
->dragging
))
2593 win_y
-= XINT (bar
->dragging
);
2597 if (win_y
> top_range
)
2600 *f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2601 *bar_window
= bar
->window
;
2603 if (! NILP (bar
->dragging
))
2604 *part
= scroll_bar_handle
;
2605 else if (win_y
< XINT (bar
->start
))
2606 *part
= scroll_bar_above_handle
;
2607 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2608 *part
= scroll_bar_handle
;
2610 *part
= scroll_bar_below_handle
;
2612 XSET (*x
, Lisp_Int
, win_y
);
2613 XSET (*y
, Lisp_Int
, top_range
);
2616 last_mouse_scroll_bar
= Qnil
;
2619 *time
= last_mouse_movement_time
;
2625 /* The screen has been cleared so we may have changed foreground or
2626 background colors, and the scroll bars may need to be redrawn.
2627 Clear out the scroll bars, and ask for expose events, so we can
2630 x_scroll_bar_clear (f
)
2635 for (bar
= FRAME_SCROLL_BARS (f
);
2636 XTYPE (bar
) == Lisp_Vector
;
2637 bar
= XSCROLL_BAR (bar
)->next
)
2638 XClearArea (x_current_display
, SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
2642 /* This processes Expose events from the menubar specific X event
2643 loop in menubar.c. This allows to redisplay the frame if necessary
2644 when handling menubar or popup items. */
2647 process_expose_from_menu (event
)
2652 f
= x_window_to_frame (event
.xexpose
.window
);
2655 if (f
->async_visible
== 0)
2657 f
->async_visible
= 1;
2658 f
->async_iconified
= 0;
2659 SET_FRAME_GARBAGED (f
);
2663 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
2664 event
.xexpose
.x
, event
.xexpose
.y
,
2665 event
.xexpose
.width
, event
.xexpose
.height
);
2670 struct scroll_bar
*bar
2671 = x_window_to_scroll_bar (event
.xexpose
.window
);
2674 x_scroll_bar_expose (bar
, &event
);
2679 /* The main X event-reading loop - XTread_socket. */
2681 /* Timestamp of enter window event. This is only used by XTread_socket,
2682 but we have to put it out here, since static variables within functions
2683 sometimes don't work. */
2684 static Time enter_timestamp
;
2686 /* This holds the state XLookupString needs to implement dead keys
2687 and other tricks known as "compose processing". _X Window System_
2688 says that a portable program can't use this, but Stephen Gildea assures
2689 me that letting the compiler initialize it to zeros will work okay.
2691 This must be defined outside of XTread_socket, for the same reasons
2692 given for enter_timestamp, above. */
2693 static XComposeStatus compose_status
;
2695 /* Communication with window managers. */
2696 Atom Xatom_wm_protocols
;
2698 /* Kinds of protocol things we may receive. */
2699 Atom Xatom_wm_take_focus
;
2700 Atom Xatom_wm_save_yourself
;
2701 Atom Xatom_wm_delete_window
;
2703 /* Other WM communication */
2704 Atom Xatom_wm_configure_denied
; /* When our config request is denied */
2705 Atom Xatom_wm_window_moved
; /* When the WM moves us. */
2707 /* Window manager communication. */
2708 Atom Xatom_wm_change_state
;
2710 /* Record the last 100 characters stored
2711 to help debug the loss-of-chars-during-GC problem. */
2713 short temp_buffer
[100];
2715 /* Read events coming from the X server.
2716 This routine is called by the SIGIO handler.
2717 We return as soon as there are no more events to be read.
2719 Events representing keys are stored in buffer BUFP,
2720 which can hold up to NUMCHARS characters.
2721 We return the number of characters stored into the buffer,
2722 thus pretending to be `read'.
2724 WAITP is nonzero if we should block until input arrives.
2725 EXPECTED is nonzero if the caller knows input is available. */
2728 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
2730 register struct input_event
*bufp
;
2731 register int numchars
;
2738 int items_pending
; /* How many items are in the X queue. */
2741 int event_found
= 0;
2745 if (interrupt_input_blocked
)
2747 interrupt_input_pending
= 1;
2751 interrupt_input_pending
= 0;
2755 abort (); /* Don't think this happens. */
2758 /* If available, Xlib uses FIOSNBIO to make the socket
2759 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
2760 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
2761 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
2762 fcntl (fileno (stdin
), F_SETFL
, 0);
2763 #endif /* ! defined (FIOSNBIO) */
2767 if (! (fcntl (fileno (stdin
), F_GETFL
, 0) & O_NDELAY
))
2769 extern int read_alarm_should_throw
;
2770 read_alarm_should_throw
= 1;
2771 XPeekEvent (XDISPLAY
&event
);
2772 read_alarm_should_throw
= 0;
2774 #endif /* HAVE_SELECT */
2777 while (XStuffPending () != 0)
2779 XNextEvent (XDISPLAY
&event
);
2787 if (event
.xclient
.message_type
== Xatom_wm_protocols
2788 && event
.xclient
.format
== 32)
2790 if (event
.xclient
.data
.l
[0] == Xatom_wm_take_focus
)
2792 #ifdef USE_X_TOOLKIT
2793 /* f = x_any_window_to_frame (event.xclient.window); */
2794 f
= x_window_to_frame (event
.xclient
.window
);
2796 f
= x_window_to_frame (event
.xclient
.window
);
2799 x_focus_on_frame (f
);
2800 /* Not certain about handling scroll bars here */
2802 else if (event
.xclient
.data
.l
[0] == Xatom_wm_save_yourself
)
2804 /* Save state modify the WM_COMMAND property to
2805 something which can reinstate us. This notifies
2806 the session manager, who's looking for such a
2807 PropertyNotify. Can restart processing when
2808 a keyboard or mouse event arrives. */
2813 else if (event
.xclient
.data
.l
[0] == Xatom_wm_delete_window
)
2815 struct frame
*f
= x_window_to_frame (event
.xclient
.window
);
2822 bufp
->kind
= delete_window_event
;
2823 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2831 else if (event
.xclient
.message_type
== Xatom_wm_configure_denied
)
2834 else if (event
.xclient
.message_type
== Xatom_wm_window_moved
)
2837 struct frame
*f
= x_window_to_frame (event
.xclient
.window
);
2839 new_x
= event
.xclient
.data
.s
[0];
2840 new_y
= event
.xclient
.data
.s
[1];
2844 f
->display
.x
->left_pos
= new_x
;
2845 f
->display
.x
->top_pos
= new_y
;
2851 #ifdef NEW_SELECTIONS
2852 case SelectionNotify
:
2853 #ifdef USE_X_TOOLKIT
2854 if (x_window_to_frame (event
.xselection
.requestor
))
2855 x_handle_selection_notify (&event
);
2858 #else /* not USE_X_TOOLKIT */
2859 x_handle_selection_notify (&event
);
2860 #endif /* not USE_X_TOOLKIT */
2862 #endif /* NEW_SELECTIONS */
2864 case SelectionClear
: /* Someone has grabbed ownership. */
2865 #ifdef NEW_SELECTIONS
2867 #ifdef USE_X_TOOLKIT
2868 if (x_window_to_frame (event
.xselectionclear
.window
))
2870 #endif /* USE_X_TOOLKIT */
2871 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
2876 bufp
->kind
= selection_clear_event
;
2877 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
2878 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
2879 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
2884 #ifdef USE_X_TOOLKIT
2888 #endif /* USE_X_TOOLKIT */
2890 #else /* not NEW_SELECTIONS */
2891 x_disown_selection (event
.xselectionclear
.window
,
2892 event
.xselectionclear
.selection
,
2893 event
.xselectionclear
.time
);
2894 #endif /* not NEW_SELECTIONS */
2897 case SelectionRequest
: /* Someone wants our selection. */
2898 #ifdef NEW_SELECTIONS
2900 #ifdef USE_X_TOOLKIT
2901 if (x_window_to_frame (event
.xselectionrequest
.owner
))
2903 #endif /* USE_X_TOOLKIT */
2904 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
2909 bufp
->kind
= selection_request_event
;
2910 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
2911 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
2912 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
2913 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
2914 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
2915 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
2920 #ifdef USE_X_TOOLKIT
2924 #endif /* USE_X_TOOLKIT */
2926 #else /* not NEW_SELECTIONS */
2927 x_answer_selection_request (event
);
2928 #endif /* not NEW_SELECTIONS */
2931 case PropertyNotify
:
2932 #ifdef NEW_SELECTIONS
2933 #ifdef USE_X_TOOLKIT
2934 if (x_any_window_to_frame (event
.xproperty
.window
))
2935 x_handle_property_notify (&event
);
2938 #else /* not USE_X_TOOLKIT */
2939 x_handle_property_notify (&event
);
2940 #endif /* not USE_X_TOOLKIT */
2941 #else /* not NEW_SELECTIONS */
2942 /* If we're being told about a root window property, then it's
2943 a cut buffer change. */
2944 if (event
.xproperty
.window
== ROOT_WINDOW
)
2945 x_invalidate_cut_buffer_cache (&event
.xproperty
);
2947 /* Otherwise, we're probably handling an incremental
2948 selection transmission. */
2951 /* If we were to do this synchronously, there'd be no worry
2952 about re-selecting. */
2953 x_send_incremental (event
);
2955 #endif /* not NEW_SELECTIONS */
2958 case ReparentNotify
:
2959 f
= x_window_to_frame (event
.xreparent
.window
);
2961 f
->display
.x
->parent_desc
= event
.xreparent
.parent
;
2965 f
= x_window_to_frame (event
.xexpose
.window
);
2968 if (f
->async_visible
== 0)
2970 f
->async_visible
= 1;
2971 f
->async_iconified
= 0;
2972 SET_FRAME_GARBAGED (f
);
2976 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
2977 event
.xexpose
.x
, event
.xexpose
.y
,
2978 event
.xexpose
.width
, event
.xexpose
.height
);
2983 struct scroll_bar
*bar
2984 = x_window_to_scroll_bar (event
.xexpose
.window
);
2987 x_scroll_bar_expose (bar
, &event
);
2988 #ifdef USE_X_TOOLKIT
2991 #endif /* USE_X_TOOLKIT */
2995 case GraphicsExpose
: /* This occurs when an XCopyArea's
2996 source area was obscured or not
2998 f
= x_window_to_frame (event
.xgraphicsexpose
.drawable
);
3002 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
3003 event
.xgraphicsexpose
.width
,
3004 event
.xgraphicsexpose
.height
);
3006 #ifdef USE_X_TOOLKIT
3009 #endif /* USE_X_TOOLKIT */
3012 case NoExpose
: /* This occurs when an XCopyArea's
3013 source area was completely
3016 #else /* ! defined (HAVE_X11) */
3018 if (event
.subwindow
!= 0)
3019 break; /* duplicate event */
3020 f
= x_window_to_frame (event
.window
);
3021 if (event
.window
== f
->display
.x
->icon_desc
)
3024 f
->async_iconified
= 1;
3026 if (event
.window
== FRAME_X_WINDOW (f
))
3028 /* Say must check all windows' needs_exposure flags. */
3029 expose_all_windows
= 1;
3030 f
->display
.x
->needs_exposure
= 1;
3031 f
->async_visible
= 1;
3036 if (event
.subwindow
!= 0)
3037 break; /* duplicate event */
3038 f
= x_window_to_frame (event
.window
);
3039 if (event
.window
== f
->display
.x
->icon_desc
)
3044 /* If window already needs full redraw, ignore this rectangle. */
3045 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
3047 /* Put the event on the queue of rectangles to redraw. */
3048 if (enqueue_event (&event
, &x_expose_queue
))
3049 /* If it is full, we can't record the rectangle,
3050 so redraw this entire window. */
3052 /* Say must check all windows' needs_exposure flags. */
3053 expose_all_windows
= 1;
3054 f
->display
.x
->needs_exposure
= 1;
3059 /* This should happen only when we are expecting it,
3060 in x_read_exposes. */
3062 #endif /* ! defined (HAVE_X11) */
3066 f
= x_window_to_frame (event
.xunmap
.window
);
3067 if (f
) /* F may no longer exist if
3068 the frame was deleted. */
3070 /* While a frame is unmapped, display generation is
3071 disabled; you don't want to spend time updating a
3072 display that won't ever be seen. */
3073 f
->async_visible
= 0;
3074 /* The window manager never makes a window invisible
3075 ("withdrawn"); all it does is switch between visible
3076 and iconified. Frames get into the invisible state
3077 only through x_make_frame_invisible. */
3078 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
3079 f
->async_iconified
= 1;
3081 #ifdef USE_X_TOOLKIT
3083 #endif /* USE_X_TOOLKIT */
3087 #ifdef USE_X_TOOLKIT
3088 f
= x_any_window_to_frame (event
.xmap
.window
);
3089 #else /* not USE_X_TOOLKIT */
3090 f
= x_window_to_frame (event
.xmap
.window
);
3091 #endif /* not USE_X_TOOLKIT */
3094 f
->async_visible
= 1;
3095 f
->async_iconified
= 0;
3097 /* wait_reading_process_input will notice this and update
3098 the frame's display structures. */
3099 SET_FRAME_GARBAGED (f
);
3101 #ifdef USE_X_TOOLKIT
3103 #endif /* USE_X_TOOLKIT */
3106 /* Turn off processing if we become fully obscured. */
3107 case VisibilityNotify
:
3110 #else /* ! defined (HAVE_X11) */
3112 f
= x_window_to_frame (event
.window
);
3113 if (event
.window
== f
->display
.x
->icon_desc
)
3114 f
->async_iconified
= 0;
3115 if (event
.window
== FRAME_X_WINDOW (f
))
3116 f
->async_visible
= 0;
3118 #endif /* ! defined (HAVE_X11) */
3122 f
= x_window_to_frame (event
.xkey
.window
);
3126 KeySym keysym
, orig_keysym
;
3127 /* al%imercury@uunet.uu.net says that making this 81 instead of
3128 80 fixed a bug whereby meta chars made his Emacs hang. */
3129 unsigned char copy_buffer
[81];
3133 |= x_emacs_to_x_modifiers (extra_keyboard_modifiers
);
3134 modifiers
= event
.xkey
.state
;
3136 /* This will have to go some day... */
3138 /* make_lispy_event turns chars into control chars.
3139 Don't do it here because XLookupString is too eager. */
3140 event
.xkey
.state
&= ~ControlMask
;
3142 XLookupString (&event
.xkey
, copy_buffer
, 80, &keysym
,
3145 /* Strip off the vendor-specific keysym bit, and take a shot
3146 at recognizing the codes. HP servers have extra keysyms
3147 that fit into the MiscFunctionKey category. */
3148 orig_keysym
= keysym
;
3153 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
3154 || keysym
== XK_Delete
3155 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
3156 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
3158 /* This recognizes the "extended function keys".
3159 It seems there's no cleaner way.
3160 Test IsModifierKey to avoid handling mode_switch
3162 || ((unsigned) (keysym
) >= XK_Select
3163 && (unsigned)(keysym
) < XK_KP_Space
)
3165 #ifdef XK_dead_circumflex
3166 || orig_keysym
== XK_dead_circumflex
3168 #ifdef XK_dead_grave
3169 || orig_keysym
== XK_dead_grave
3171 #ifdef XK_dead_tilde
3172 || orig_keysym
== XK_dead_tilde
3174 #ifdef XK_dead_diaeresis
3175 || orig_keysym
== XK_dead_diaeresis
3177 #ifdef XK_dead_macron
3178 || orig_keysym
== XK_dead_macron
3180 #ifdef XK_dead_degree
3181 || orig_keysym
== XK_dead_degree
3183 #ifdef XK_dead_acute
3184 || orig_keysym
== XK_dead_acute
3186 #ifdef XK_dead_cedilla
3187 || orig_keysym
== XK_dead_cedilla
3189 #ifdef XK_dead_breve
3190 || orig_keysym
== XK_dead_breve
3192 #ifdef XK_dead_ogonek
3193 || orig_keysym
== XK_dead_ogonek
3195 #ifdef XK_dead_caron
3196 || orig_keysym
== XK_dead_caron
3198 #ifdef XK_dead_doubleacute
3199 || orig_keysym
== XK_dead_doubleacute
3201 #ifdef XK_dead_abovedot
3202 || orig_keysym
== XK_dead_abovedot
3204 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
3205 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
3206 || x_is_vendor_fkey (orig_keysym
))
3207 && ! (IsModifierKey (orig_keysym
)
3209 #ifdef XK_Mode_switch
3210 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
3213 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
3215 #endif /* not HAVE_X11R5 */
3218 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3220 temp_buffer
[temp_index
++] = keysym
;
3221 bufp
->kind
= non_ascii_keystroke
;
3222 bufp
->code
= keysym
;
3223 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3224 bufp
->modifiers
= x_x_to_emacs_modifiers (modifiers
);
3225 bufp
->timestamp
= event
.xkey
.time
;
3230 else if (numchars
> nbytes
)
3234 for (i
= 0; i
< nbytes
; i
++)
3236 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3238 temp_buffer
[temp_index
++] = copy_buffer
[i
];
3239 bufp
->kind
= ascii_keystroke
;
3240 bufp
->code
= copy_buffer
[i
];
3241 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3242 bufp
->modifiers
= x_x_to_emacs_modifiers (modifiers
);
3243 bufp
->timestamp
= event
.xkey
.time
;
3257 #else /* ! defined (HAVE_X11) */
3260 register char *where_mapping
;
3262 f
= x_window_to_frame (event
.window
);
3263 /* Ignore keys typed on icon windows. */
3264 if (f
!= 0 && event
.window
== f
->display
.x
->icon_desc
)
3266 where_mapping
= XLookupMapping (&event
, &nbytes
);
3267 /* Nasty fix for arrow keys */
3268 if (!nbytes
&& IsCursorKey (event
.detail
& 0xff))
3270 switch (event
.detail
& 0xff)
3272 case KC_CURSOR_LEFT
:
3273 where_mapping
= "\002";
3275 case KC_CURSOR_RIGHT
:
3276 where_mapping
= "\006";
3279 where_mapping
= "\020";
3281 case KC_CURSOR_DOWN
:
3282 where_mapping
= "\016";
3287 if (numchars
- nbytes
> 0)
3291 for (i
= 0; i
< nbytes
; i
++)
3293 bufp
->kind
= ascii_keystroke
;
3294 bufp
->code
= where_mapping
[i
];
3295 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3296 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3304 #endif /* ! defined (HAVE_X11) */
3308 /* Here's a possible interpretation of the whole
3309 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3310 FocusIn event, you have to get a FocusOut event before you
3311 relinquish the focus. If you haven't received a FocusIn event,
3312 then a mere LeaveNotify is enough to free you. */
3315 f
= x_window_to_frame (event
.xcrossing
.window
);
3317 if (event
.xcrossing
.focus
) /* Entered Window */
3319 /* Avoid nasty pop/raise loops. */
3320 if (f
&& (!(f
->auto_raise
)
3322 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
3324 x_new_focus_frame (f
);
3325 enter_timestamp
= event
.xcrossing
.time
;
3328 else if (f
== x_focus_frame
)
3329 x_new_focus_frame (0);
3330 #ifdef USE_X_TOOLKIT
3332 #endif /* USE_X_TOOLKIT */
3336 f
= x_window_to_frame (event
.xfocus
.window
);
3337 if (event
.xfocus
.detail
!= NotifyPointer
)
3338 x_focus_event_frame
= f
;
3340 x_new_focus_frame (f
);
3341 #ifdef USE_X_TOOLKIT
3343 #endif /* USE_X_TOOLKIT */
3348 f
= x_window_to_frame (event
.xcrossing
.window
);
3350 if (event
.xcrossing
.focus
)
3352 if (! x_focus_event_frame
)
3353 x_new_focus_frame (0);
3355 x_new_focus_frame (f
);
3359 if (f
== x_focus_event_frame
)
3360 x_focus_event_frame
= 0;
3361 if (f
== x_focus_frame
)
3362 x_new_focus_frame (0);
3364 #ifdef USE_X_TOOLKIT
3366 #endif /* USE_X_TOOLKIT */
3370 f
= x_window_to_frame (event
.xfocus
.window
);
3371 if (event
.xfocus
.detail
!= NotifyPointer
3372 && f
== x_focus_event_frame
)
3373 x_focus_event_frame
= 0;
3374 if (f
&& f
== x_focus_frame
)
3375 x_new_focus_frame (0);
3376 #ifdef USE_X_TOOLKIT
3378 #endif /* USE_X_TOOLKIT */
3381 #else /* ! defined (HAVE_X11) */
3384 if ((event
.detail
& 0xFF) == 1)
3385 break; /* Coming from our own subwindow */
3386 if (event
.subwindow
!= 0)
3387 break; /* Entering our own subwindow. */
3390 f
= x_window_to_frame (event
.window
);
3393 x_new_focus_frame (f
);
3398 if ((event
.detail
& 0xFF) == 1)
3399 break; /* Entering our own subwindow */
3400 if (event
.subwindow
!= 0)
3401 break; /* Leaving our own subwindow. */
3404 if (x_focus_frame
== 0
3405 && x_input_frame
!= 0
3406 && x_input_frame
== x_window_to_frame (event
.window
)
3407 && event
.window
== FRAME_X_WINDOW (x_input_frame
))
3412 frame_unhighlight (f
);
3415 #endif /* ! defined (HAVE_X11) */
3420 if (x_mouse_grabbed
)
3421 f
= last_mouse_frame
;
3423 f
= x_window_to_frame (event
.xmotion
.window
);
3425 note_mouse_movement (f
, &event
.xmotion
);
3428 struct scroll_bar
*bar
3429 = x_window_to_scroll_bar (event
.xmotion
.window
);
3432 x_scroll_bar_note_movement (bar
, &event
);
3435 #ifdef USE_X_TOOLKIT
3437 #endif /* USE_X_TOOLKIT */
3440 case ConfigureNotify
:
3441 #ifdef USE_X_TOOLKIT
3442 /* process done in widget.c */
3444 #else /* not USE_X_TOOLKIT */
3445 f
= x_window_to_frame (event
.xconfigure
.window
);
3448 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
3449 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
3451 /* Even if the number of character rows and columns has
3452 not changed, the font size may have changed, so we need
3453 to check the pixel dimensions as well. */
3454 if (columns
!= f
->width
3455 || rows
!= f
->height
3456 || event
.xconfigure
.width
!= f
->display
.x
->pixel_width
3457 || event
.xconfigure
.height
!= f
->display
.x
->pixel_height
)
3459 change_frame_size (f
, rows
, columns
, 0, 1);
3460 SET_FRAME_GARBAGED (f
);
3463 if (! event
.xconfigure
.send_event
)
3468 /* Find the position of the outside upper-left corner of
3469 the window, in the root coordinate system. Don't
3470 refer to the parent window here; we may be processing
3471 this event after the window manager has changed our
3472 parent, but before we have reached the ReparentNotify. */
3473 XTranslateCoordinates (x_current_display
,
3475 /* From-window, to-window. */
3476 f
->display
.x
->window_desc
,
3479 /* From-position, to-position. */
3480 -event
.xconfigure
.border_width
,
3481 -event
.xconfigure
.border_width
,
3486 event
.xconfigure
.x
= win_x
;
3487 event
.xconfigure
.y
= win_y
;
3490 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
3491 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
3492 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
3493 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
3495 #endif /* not USE_X_TOOLKIT */
3501 /* If we decide we want to generate an event to be seen
3502 by the rest of Emacs, we put it here. */
3503 struct input_event emacs_event
;
3504 emacs_event
.kind
= no_event
;
3506 f
= x_window_to_frame (event
.xbutton
.window
);
3509 if (!x_focus_frame
|| (f
== x_focus_frame
))
3510 construct_mouse_click (&emacs_event
, &event
, f
);
3514 struct scroll_bar
*bar
=
3515 x_window_to_scroll_bar (event
.xbutton
.window
);
3518 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
3519 #ifdef USE_X_TOOLKIT
3522 f
= x_any_window_to_frame (event
.xbutton
.window
);
3523 if (f
&& event
.type
== ButtonPress
)
3524 construct_menu_click (&emacs_event
,
3527 #endif /* USE_X_TOOLKIT */
3530 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
3532 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
3538 #ifdef USE_X_TOOLKIT
3540 #endif /* USE_X_TOOLKIT */
3544 #else /* ! defined (HAVE_X11) */
3546 case ButtonReleased
:
3547 f
= x_window_to_frame (event
.window
);
3550 if (event
.window
== f
->display
.x
->icon_desc
)
3552 x_make_frame_visible (f
);
3554 if (warp_mouse_on_deiconify
)
3555 XWarpMouse (FRAME_X_WINDOW (f
), 10, 10);
3558 if (event
.window
== FRAME_X_WINDOW (f
))
3564 enqueue_event (&event
, &x_mouse_queue
);
3567 bufp
->kind
= ascii_keystroke
;
3568 bufp
->code
= 'X' & 037; /* C-x */
3569 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3570 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3573 bufp
->kind
= ascii_keystroke
;
3574 bufp
->code
= 0; /* C-@ */
3575 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3576 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3583 #endif /* ! defined (HAVE_X11) */
3587 case CirculateNotify
:
3589 case CirculateRequest
:
3592 #endif /* ! defined (HAVE_X11) */
3595 /* Someone has changed the keyboard mapping - update the
3597 switch (event
.xmapping
.request
)
3599 case MappingModifier
:
3600 x_find_modifier_meanings ();
3601 /* This is meant to fall through. */
3602 case MappingKeyboard
:
3603 XRefreshKeyboardMapping (&event
.xmapping
);
3605 #ifdef USE_X_TOOLKIT
3607 #endif /* USE_X_TOOLKIT */
3611 #ifdef USE_X_TOOLKIT
3614 XtDispatchEvent (&event
);
3616 #endif /* USE_X_TOOLKIT */
3623 /* On some systems, an X bug causes Emacs to get no more events
3624 when the window is destroyed. Detect that. */
3625 XNoOp (x_current_display
);
3626 #endif /* X_IO_BUG */
3629 if (expected
&& ! event_found
)
3631 /* AOJ 880406: if select returns true but XPending doesn't, it means that
3632 there is an EOF condition; in other words, that X has died.
3633 Act as if there had been a hangup. */
3634 int fd
= ConnectionNumber (x_current_display
);
3635 SELECT_TYPE mask
, junk1
, junk2
;
3640 EMACS_SET_SECS_USECS (timeout
, 0, 0);
3643 if (0 != select (fd
+ 1, &mask
, &junk1
, &junk2
, &timeout
)
3644 && !XStuffPending ())
3645 kill (getpid (), SIGHUP
);
3647 #endif /* HAVE_SELECT */
3650 if (updating_frame
== 0)
3651 x_do_pending_expose ();
3659 /* Read and process only Expose events
3660 until we get an ExposeCopy event; then return.
3661 This is used in insert/delete line.
3662 We assume input is already blocked. */
3668 XKeyPressedEvent event
;
3672 /* while there are more events*/
3673 XMaskEvent (ExposeWindow
| ExposeRegion
| ExposeCopy
, &event
);
3677 if (event
.subwindow
!= 0)
3678 break; /* duplicate event */
3679 f
= x_window_to_frame (event
.window
);
3680 if (event
.window
== f
->display
.x
->icon_desc
)
3685 if (event
.window
== FRAME_X_WINDOW (f
))
3687 expose_all_windows
= 1;
3688 f
->display
.x
->needs_exposure
= 1;
3694 if (event
.subwindow
!= 0)
3695 break; /* duplicate event */
3696 f
= x_window_to_frame (event
.window
);
3697 if (event
.window
== f
->display
.x
->icon_desc
)
3702 /* If window already needs full redraw, ignore this rectangle. */
3703 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
3705 /* Put the event on the queue of rectangles to redraw. */
3706 if (enqueue_event (&event
, &x_expose_queue
))
3707 /* If it is full, we can't record the rectangle,
3708 so redraw this entire window. */
3710 /* Say must check all windows' needs_exposure flags. */
3711 expose_all_windows
= 1;
3712 f
->display
.x
->needs_exposure
= 1;
3721 #endif /* HAVE_X11 */
3724 /* Drawing the cursor. */
3727 /* Draw a hollow box cursor. Don't change the inside of the box. */
3733 int left
= CHAR_TO_PIXEL_COL (f
, f
->cursor_x
);
3734 int top
= CHAR_TO_PIXEL_ROW (f
, f
->cursor_y
);
3735 int width
= FONT_WIDTH (f
->display
.x
->font
);
3736 int height
= FONT_HEIGHT (f
->display
.x
->font
);
3739 XDrawRectangle (x_current_display
, FRAME_X_WINDOW (f
),
3740 f
->display
.x
->cursor_gc
,
3741 left
, top
, width
- 1, height
- 1);
3742 #else /* ! defined (HAVE_X11) */
3743 XPixSet (FRAME_X_WINDOW (f
),
3744 left
, top
, width
, 1,
3745 f
->display
.x
->cursor_pixel
);
3747 XPixSet (FRAME_X_WINDOW (f
),
3748 left
, top
, 1, height
,
3749 f
->display
.x
->cursor_pixel
);
3751 XPixSet (FRAME_X_WINDOW (f
),
3752 left
+width
-1, top
, 1, height
,
3753 f
->display
.x
->cursor_pixel
);
3755 XPixSet (FRAME_X_WINDOW (f
),
3756 left
, top
+height
-1, width
, 1,
3757 f
->display
.x
->cursor_pixel
);
3758 #endif /* ! defined (HAVE_X11) */
3761 /* Clear the cursor of frame F to background color,
3762 and mark the cursor as not shown.
3763 This is used when the text where the cursor is
3764 is about to be rewritten. */
3772 if (! FRAME_VISIBLE_P (f
)
3773 || f
->phys_cursor_x
< 0)
3777 x_display_cursor (f
, 0);
3778 #else /* ! defined (HAVE_X11) */
3779 XPixSet (FRAME_X_WINDOW (f
),
3780 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
3781 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
3782 FONT_WIDTH (f
->display
.x
->font
), FONT_HEIGHT (f
->display
.x
->font
),
3783 f
->display
.x
->background_pixel
);
3784 #endif /* ! defined (HAVE_X11) */
3785 f
->phys_cursor_x
= -1;
3788 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
3789 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
3793 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
3800 CHAR_TO_PIXEL_COL (f
, column
),
3801 CHAR_TO_PIXEL_ROW (f
, row
),
3802 &glyph
, 1, highlight
);
3806 x_display_bar_cursor (f
, on
)
3810 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3812 /* This is pointless on invisible frames, and dangerous on garbaged
3813 frames; in the latter case, the frame may be in the midst of
3814 changing its size, and curs_x and curs_y may be off the frame. */
3815 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
3818 if (! on
&& f
->phys_cursor_x
< 0)
3821 /* If we're not updating, then we want to use the current frame's
3822 cursor position, not our local idea of where the cursor ought to be. */
3823 if (f
!= updating_frame
)
3825 curs_x
= FRAME_CURSOR_X (f
);
3826 curs_y
= FRAME_CURSOR_Y (f
);
3829 /* If there is anything wrong with the current cursor state, remove it. */
3830 if (f
->phys_cursor_x
>= 0
3832 || f
->phys_cursor_x
!= curs_x
3833 || f
->phys_cursor_y
!= curs_y
3834 || f
->display
.x
->current_cursor
!= bar_cursor
))
3836 /* Erase the cursor by redrawing the character underneath it. */
3837 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3838 f
->phys_cursor_glyph
,
3839 current_glyphs
->highlight
[f
->phys_cursor_y
]);
3840 f
->phys_cursor_x
= -1;
3843 /* If we now need a cursor in the new place or in the new form, do it so. */
3845 && (f
->phys_cursor_x
< 0
3846 || (f
->display
.x
->current_cursor
!= bar_cursor
)))
3848 f
->phys_cursor_glyph
3849 = ((current_glyphs
->enable
[curs_y
]
3850 && curs_x
< current_glyphs
->used
[curs_y
])
3851 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
3853 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
3854 f
->display
.x
->cursor_gc
,
3855 CHAR_TO_PIXEL_COL (f
, curs_x
),
3856 CHAR_TO_PIXEL_ROW (f
, curs_y
),
3857 1, FONT_HEIGHT (f
->display
.x
->font
));
3859 f
->phys_cursor_x
= curs_x
;
3860 f
->phys_cursor_y
= curs_y
;
3862 f
->display
.x
->current_cursor
= bar_cursor
;
3865 if (updating_frame
!= f
)
3870 /* Turn the displayed cursor of frame F on or off according to ON.
3871 If ON is nonzero, where to put the cursor is specified
3872 by F->cursor_x and F->cursor_y. */
3875 x_display_box_cursor (f
, on
)
3879 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3881 /* This is pointless on invisible frames, and dangerous on garbaged
3882 frames; in the latter case, the frame may be in the midst of
3883 changing its size, and curs_x and curs_y may be off the frame. */
3884 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
3887 /* If cursor is off and we want it off, return quickly. */
3888 if (!on
&& f
->phys_cursor_x
< 0)
3891 /* If we're not updating, then we want to use the current frame's
3892 cursor position, not our local idea of where the cursor ought to be. */
3893 if (f
!= updating_frame
)
3895 curs_x
= FRAME_CURSOR_X (f
);
3896 curs_y
= FRAME_CURSOR_Y (f
);
3899 /* If cursor is currently being shown and we don't want it to be
3900 or it is in the wrong place,
3901 or we want a hollow box and it's not so, (pout!)
3903 if (f
->phys_cursor_x
>= 0
3905 || f
->phys_cursor_x
!= curs_x
3906 || f
->phys_cursor_y
!= curs_y
3907 || (f
->display
.x
->current_cursor
!= hollow_box_cursor
3908 && (f
!= x_highlight_frame
))))
3910 /* Erase the cursor by redrawing the character underneath it. */
3911 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3912 f
->phys_cursor_glyph
,
3913 current_glyphs
->highlight
[f
->phys_cursor_y
]);
3914 f
->phys_cursor_x
= -1;
3917 /* If we want to show a cursor,
3918 or we want a box cursor and it's not so,
3919 write it in the right place. */
3921 && (f
->phys_cursor_x
< 0
3922 || (f
->display
.x
->current_cursor
!= filled_box_cursor
3923 && f
== x_highlight_frame
)))
3925 f
->phys_cursor_glyph
3926 = ((current_glyphs
->enable
[curs_y
]
3927 && curs_x
< current_glyphs
->used
[curs_y
])
3928 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
3930 if (f
!= x_highlight_frame
)
3933 f
->display
.x
->current_cursor
= hollow_box_cursor
;
3937 x_draw_single_glyph (f
, curs_y
, curs_x
,
3938 f
->phys_cursor_glyph
, 2);
3939 f
->display
.x
->current_cursor
= filled_box_cursor
;
3942 f
->phys_cursor_x
= curs_x
;
3943 f
->phys_cursor_y
= curs_y
;
3946 if (updating_frame
!= f
)
3950 x_display_cursor (f
, on
)
3954 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
3955 x_display_box_cursor (f
, on
);
3956 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
3957 x_display_bar_cursor (f
, on
);
3959 /* Those are the only two we have implemented! */
3965 /* Refresh bitmap kitchen sink icon for frame F
3966 when we get an expose event for it. */
3972 /* Normally, the window manager handles this function. */
3973 #else /* ! defined (HAVE_X11) */
3976 if (f
->display
.x
->icon_bitmap_flag
)
3977 XBitmapBitsPut (f
->display
.x
->icon_desc
, 0, 0, sink_width
, sink_height
,
3978 sink_bits
, BlackPixel
, WHITE_PIX_DEFAULT
,
3979 icon_bitmap
, GXcopy
, AllPlanes
);
3982 extern struct frame
*selected_frame
;
3983 struct Lisp_String
*str
;
3984 unsigned char *string
;
3987 = XSTRING (XBUFFER (XWINDOW (f
->selected_window
)->buffer
)->name
)->data
;
3989 if (f
->display
.x
->icon_label
!= string
)
3991 f
->display
.x
->icon_label
= string
;
3992 XChangeWindow (f
->display
.x
->icon_desc
,
3993 XQueryWidth (string
, icon_font_info
->id
) + 10,
3994 icon_font_info
->height
+ 10);
3997 XText (f
->display
.x
->icon_desc
, 5, 5, string
,
3998 str
->size
, icon_font_info
->id
,
3999 BLACK_PIX_DEFAULT
, WHITE_PIX_DEFAULT
);
4002 #endif /* ! defined (HAVE_X11) */
4005 /* Make the x-window of frame F use the gnu icon bitmap. */
4014 if (FRAME_X_WINDOW (f
) == 0)
4020 XCreateBitmapFromData (x_current_display
, FRAME_X_WINDOW (f
),
4021 gnu_bits
, gnu_width
, gnu_height
);
4022 x_wm_set_icon_pixmap (f
, icon_bitmap
);
4023 f
->display
.x
->icon_bitmap_flag
= 1;
4024 #else /* ! defined (HAVE_X11) */
4025 if (f
->display
.x
->icon_desc
)
4027 XClearIconWindow (FRAME_X_WINDOW (f
));
4028 XDestroyWindow (f
->display
.x
->icon_desc
);
4031 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
4032 0, 0, sink_width
, sink_height
,
4033 2, WhitePixmap
, (Pixmap
) NULL
);
4035 if (icon_window
== 0)
4038 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
4039 XSelectInput (icon_window
, ExposeWindow
| UnmapWindow
);
4041 f
->display
.x
->icon_desc
= icon_window
;
4042 f
->display
.x
->icon_bitmap_flag
= 1;
4044 if (icon_bitmap
== 0)
4046 = XStoreBitmap (sink_mask_width
, sink_mask_height
, sink_mask_bits
);
4047 #endif /* ! defined (HAVE_X11) */
4053 /* Make the x-window of frame F use a rectangle with text. */
4056 x_text_icon (f
, icon_name
)
4064 char *X_DefaultValue
;
4068 #define WhitePixel 1
4069 #endif /* WhitePixel */
4072 #define BlackPixel 0
4073 #endif /* BlackPixel */
4074 #endif /* HAVE_X11 */
4076 if (FRAME_X_WINDOW (f
) == 0)
4081 f
->display
.x
->icon_label
= icon_name
;
4083 if (! f
->display
.x
->icon_label
)
4084 f
->display
.x
->icon_label
= " *emacs* ";
4087 XSetIconName (x_current_display
, FRAME_X_WINDOW (f
),
4088 (char *) f
->display
.x
->icon_label
);
4091 f
->display
.x
->icon_bitmap_flag
= 0;
4092 x_wm_set_icon_pixmap (f
, 0);
4093 #else /* ! defined (HAVE_X11) */
4094 if (icon_font_info
== 0)
4096 = XGetFont (XGetDefault (XDISPLAY
4097 (char *) XSTRING (Vinvocation_name
)->data
,
4100 if (f
->display
.x
->icon_desc
)
4102 XClearIconWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4103 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
4107 f
->display
.x
->icon_label
= (unsigned char *) icon_name
;
4109 if (! f
->display
.x
->icon_label
)
4110 f
->display
.x
->icon_label
= XSTRING (f
->name
)->data
;
4112 width
= XStringWidth (f
->display
.x
->icon_label
, icon_font_info
, 0, 0);
4113 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
4114 f
->display
.x
->left_pos
,
4115 f
->display
.x
->top_pos
,
4116 width
+ 10, icon_font_info
->height
+ 10,
4117 2, BlackPixmap
, WhitePixmap
);
4119 if (icon_window
== 0)
4122 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
4123 XSelectInput (icon_window
, ExposeWindow
| ExposeRegion
| UnmapWindow
| ButtonPressed
);
4125 f
->display
.x
->icon_desc
= icon_window
;
4126 f
->display
.x
->icon_bitmap_flag
= 0;
4127 f
->display
.x
->icon_label
= 0;
4128 #endif /* ! defined (HAVE_X11) */
4133 /* Handling X errors. */
4135 /* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
4136 X server's connection, or an error reported via the X protocol. */
4139 x_connection_closed ()
4144 shut_down_emacs (0, 1, Qnil
);
4149 /* An X error handler which prints an error message and then kills
4150 Emacs. This is what's normally installed as Xlib's handler for
4153 x_error_quitter (display
, error
)
4159 /* Note that there is no real way portable across R3/R4 to get the
4160 original error handler. */
4162 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
4163 fprintf (stderr
, "X protocol error: %s on protocol request %d\n",
4164 buf
, error
->request_code
);
4167 /* While we're testing Emacs 19, we'll just dump core whenever we
4168 get an X error, so we can figure out why it happened. */
4172 x_connection_closed ();
4175 /* A handler for X IO errors which prints an error message and then
4176 kills Emacs. This is what is always installed as Xlib's handler
4179 x_io_error_quitter (display
)
4182 fprintf (stderr
, "Connection to X server %s lost.\n",
4183 XDisplayName (DisplayString (display
)));
4186 /* While we're testing Emacs 19, we'll just dump core whenever we
4187 get an X error, so we can figure out why it happened. */
4191 x_connection_closed ();
4194 /* A buffer for storing X error messages. */
4195 static char *x_caught_error_message
;
4196 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
4198 /* An X error handler which stores the error message in
4199 x_caught_error_message. This is what's installed when
4200 x_catch_errors is in effect. */
4202 x_error_catcher (display
, error
)
4206 XGetErrorText (display
, error
->error_code
,
4207 x_caught_error_message
, X_CAUGHT_ERROR_MESSAGE_SIZE
);
4211 /* Begin trapping X errors.
4213 After calling this function, X protocol errors no longer cause
4214 Emacs to exit; instead, they are recorded in x_cfc_error_message.
4216 Calling x_check_errors signals an Emacs error if an X error has
4217 occurred since the last call to x_catch_errors or x_check_errors.
4219 Calling x_uncatch_errors resumes the normal error handling. */
4221 void x_catch_errors(), x_check_errors (), x_uncatch_errors ();
4226 /* Make sure any errors from previous requests have been dealt with. */
4227 XSync (x_current_display
, False
);
4229 /* Set up the error buffer. */
4230 x_caught_error_message
4231 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE
);
4232 x_caught_error_message
[0] = '\0';
4234 /* Install our little error handler. */
4235 XHandleError (x_error_catcher
);
4238 /* If any X protocol errors have arrived since the last call to
4239 x_catch_errors or x_check_errors, signal an Emacs error using
4240 sprintf (a buffer, FORMAT, the x error message text) as the text. */
4242 x_check_errors (format
)
4245 /* Make sure to catch any errors incurred so far. */
4246 XSync (x_current_display
, False
);
4248 if (x_caught_error_message
[0])
4250 char buf
[X_CAUGHT_ERROR_MESSAGE_SIZE
+ 56];
4252 sprintf (buf
, format
, x_caught_error_message
);
4253 x_uncatch_errors ();
4261 xfree (x_caught_error_message
);
4262 x_caught_error_message
= 0;
4263 XHandleError (x_error_quitter
);
4267 static unsigned int x_wire_count
;
4270 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
4275 /* Changing the font of the frame. */
4277 /* Set the font of the x-window specified by frame F
4278 to the font named NEWNAME. This is safe to use
4279 even before F has an actual x-window. */
4289 /* A table of all the fonts we have already loaded. */
4290 static struct font_info
*x_font_table
;
4292 /* The current capacity of x_font_table. */
4293 static int x_font_table_size
;
4295 /* The number of fonts actually stored in x_font_table.
4296 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
4297 0 <= n_fonts <= x_font_table_size. */
4301 x_new_font (f
, fontname
)
4303 register char *fontname
;
4306 int n_matching_fonts
;
4307 XFontStruct
*font_info
;
4310 /* Get a list of all the fonts that match this name. Once we
4311 have a list of matching fonts, we compare them against the fonts
4312 we already have by comparing font ids. */
4313 font_names
= (char **) XListFonts (x_current_display
, fontname
,
4314 1024, &n_matching_fonts
);
4315 /* Apparently it doesn't set n_matching_fonts to zero when it can't
4316 find any matches; font_names == 0 is the only clue. */
4318 n_matching_fonts
= 0;
4320 /* Don't just give up if n_matching_fonts is 0.
4321 Apparently there's a bug on Suns: XListFontsWithInfo can
4322 fail to find a font, but XLoadQueryFont may still find it. */
4324 /* See if we've already loaded a matching font. */
4325 already_loaded
= -1;
4326 if (n_matching_fonts
!= 0)
4330 for (i
= 0; i
< n_fonts
; i
++)
4331 for (j
= 0; j
< n_matching_fonts
; j
++)
4332 if (!strcmp (x_font_table
[i
].name
, font_names
[j
]))
4335 fontname
= font_names
[j
];
4341 /* If we have, just return it from the table. */
4342 if (already_loaded
>= 0)
4343 f
->display
.x
->font
= x_font_table
[already_loaded
].font
;
4345 /* Otherwise, load the font and add it to the table. */
4351 /* Try to find a character-cell font in the list. */
4353 /* A laudable goal, but this isn't how to do it. */
4354 for (i
= 0; i
< n_matching_fonts
; i
++)
4355 if (! font_info
[i
].per_char
)
4361 /* See comment above. */
4362 if (n_matching_fonts
!= 0)
4363 fontname
= font_names
[i
];
4365 font
= (XFontStruct
*) XLoadQueryFont (x_current_display
, fontname
);
4368 /* Free the information from XListFonts. */
4369 if (n_matching_fonts
)
4370 XFreeFontNames (font_names
);
4374 /* Do we need to create the table? */
4375 if (x_font_table_size
== 0)
4377 x_font_table_size
= 16;
4379 = (struct font_info
*) xmalloc (x_font_table_size
4380 * sizeof (x_font_table
[0]));
4382 /* Do we need to grow the table? */
4383 else if (n_fonts
>= x_font_table_size
)
4385 x_font_table_size
*= 2;
4387 = (struct font_info
*) xrealloc (x_font_table
,
4389 * sizeof (x_font_table
[0])));
4392 x_font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
4393 bcopy (fontname
, x_font_table
[n_fonts
].name
, strlen (fontname
) + 1);
4394 f
->display
.x
->font
= x_font_table
[n_fonts
++].font
= font
;
4397 /* Now make the frame display the given font. */
4398 if (FRAME_X_WINDOW (f
) != 0)
4400 XSetFont (x_current_display
, f
->display
.x
->normal_gc
,
4401 f
->display
.x
->font
->fid
);
4402 XSetFont (x_current_display
, f
->display
.x
->reverse_gc
,
4403 f
->display
.x
->font
->fid
);
4404 XSetFont (x_current_display
, f
->display
.x
->cursor_gc
,
4405 f
->display
.x
->font
->fid
);
4407 x_set_window_size (f
, f
->width
, f
->height
);
4411 Lisp_Object lispy_name
= build_string (fontname
);
4414 /* Free the information from XListFonts. The data
4415 we actually retain comes from XLoadQueryFont. */
4416 XFreeFontNames (font_names
);
4421 #else /* ! defined (HAVE_X11) */
4422 x_new_font (f
, newname
)
4424 register char *newname
;
4429 temp
= XGetFont (newname
);
4430 if (temp
== (FONT_TYPE
*) 0)
4433 if (f
->display
.x
->font
)
4434 XLoseFont (f
->display
.x
->font
);
4436 f
->display
.x
->font
= temp
;
4438 if (FRAME_X_WINDOW (f
) != 0)
4439 x_set_window_size (f
, f
->width
, f
->height
);
4443 #endif /* ! defined (HAVE_X11) */
4445 x_calc_absolute_position (f
)
4450 int win_x
= 0, win_y
= 0;
4452 /* Find the position of the outside upper-left corner of
4453 the inner window, with respect to the outer window. */
4454 if (f
->display
.x
->parent_desc
!= ROOT_WINDOW
)
4457 XTranslateCoordinates (x_current_display
,
4459 /* From-window, to-window. */
4460 f
->display
.x
->window_desc
,
4461 f
->display
.x
->parent_desc
,
4463 /* From-position, to-position. */
4464 0, 0, &win_x
, &win_y
,
4471 /* Treat negative positions as relative to the leftmost bottommost
4472 position that fits on the screen. */
4473 if (f
->display
.x
->left_pos
< 0)
4474 f
->display
.x
->left_pos
= (x_screen_width
4475 - 2 * f
->display
.x
->border_width
- win_x
4477 + f
->display
.x
->left_pos
);
4479 if (f
->display
.x
->top_pos
< 0)
4480 f
->display
.x
->top_pos
= (x_screen_height
4481 - 2 * f
->display
.x
->border_width
- win_y
4483 + f
->display
.x
->top_pos
);
4485 #else /* ! defined (HAVE_X11) */
4486 WINDOWINFO_TYPE parentinfo
;
4488 XGetWindowInfo (FRAME_X_WINDOW (f
), &parentinfo
);
4490 if (f
->display
.x
->left_pos
< 0)
4491 f
->display
.x
->left_pos
= parentinfo
.width
+ (f
->display
.x
->left_pos
+ 1)
4492 - PIXEL_WIDTH (f
) - 2 * f
->display
.x
->internal_border_width
;
4494 if (f
->display
.x
->top_pos
< 0)
4495 f
->display
.x
->top_pos
= parentinfo
.height
+ (f
->display
.x
->top_pos
+ 1)
4496 - PIXEL_HEIGHT (f
) - 2 * f
->display
.x
->internal_border_width
;
4497 #endif /* ! defined (HAVE_X11) */
4500 x_set_offset (f
, xoff
, yoff
)
4502 register int xoff
, yoff
;
4504 f
->display
.x
->top_pos
= yoff
;
4505 f
->display
.x
->left_pos
= xoff
;
4506 x_calc_absolute_position (f
);
4509 #ifdef USE_X_TOOLKIT
4510 XMoveWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
),
4511 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
4512 #else /* not USE_X_TOOLKIT */
4513 XMoveWindow (XDISPLAY
FRAME_X_WINDOW (f
),
4514 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
4515 #endif /* not USE_X_TOOLKIT */
4517 x_wm_set_size_hint (f
, 0, xoff
, yoff
);
4518 #endif /* ! defined (HAVE_X11) */
4522 /* Call this to change the size of frame F's x-window. */
4524 x_set_window_size (f
, cols
, rows
)
4528 int pixelwidth
, pixelheight
;
4531 #ifdef USE_X_TOOLKIT
4533 EmacsFrameSetCharSize (f
->display
.x
->edit_widget
, cols
, rows
);
4536 #else /* not USE_X_TOOLKIT */
4540 check_frame_size (f
, &rows
, &cols
);
4541 f
->display
.x
->vertical_scroll_bar_extra
4542 = (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
4543 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
)
4545 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
4546 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
4549 x_wm_set_size_hint (f
, 0, 0, 0);
4550 #endif /* ! defined (HAVE_X11) */
4551 XChangeWindowSize (FRAME_X_WINDOW (f
), pixelwidth
, pixelheight
);
4553 /* Now, strictly speaking, we can't be sure that this is accurate,
4554 but the window manager will get around to dealing with the size
4555 change request eventually, and we'll hear how it went when the
4556 ConfigureNotify event gets here.
4558 We could just not bother storing any of this information here,
4559 and let the ConfigureNotify event set everything up, but that
4560 might be kind of confusing to the lisp code, since size changes
4561 wouldn't be reported in the frame parameters until some random
4562 point in the future when the ConfigureNotify event arrives. */
4563 change_frame_size (f
, rows
, cols
, 0, 0);
4564 PIXEL_WIDTH (f
) = pixelwidth
;
4565 PIXEL_HEIGHT (f
) = pixelheight
;
4567 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4568 receive in the ConfigureNotify event; if we get what we asked
4569 for, then the event won't cause the screen to become garbaged, so
4570 we have to make sure to do it here. */
4571 SET_FRAME_GARBAGED (f
);
4575 #endif /* not USE_X_TOOLKIT */
4579 x_set_resize_hint (f
)
4582 XSetResizeHint (FRAME_X_WINDOW (f
),
4583 2 * f
->display
.x
->internal_border_width
,
4584 2 * f
->display
.x
->internal_border_width
,
4585 FONT_WIDTH (f
->display
.x
->font
),
4586 FONT_HEIGHT (f
->display
.x
->font
));
4588 #endif /* HAVE_X11 */
4590 /* Mouse warping, focus shifting, raising and lowering. */
4592 x_set_mouse_position (f
, x
, y
)
4598 #if 0 /* Let the user ask for this if he wants it. */
4602 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->display
.x
->font
) / 2;
4603 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + FONT_HEIGHT (f
->display
.x
->font
) / 2;
4605 if (pix_x
< 0) pix_x
= 0;
4606 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
4608 if (pix_y
< 0) pix_y
= 0;
4609 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
4613 XWarpMousePointer (FRAME_X_WINDOW (f
), pix_x
, pix_y
);
4618 x_focus_on_frame (f
)
4621 #if 0 /* This proves to be unpleasant. */
4625 /* I don't think that the ICCCM allows programs to do things like this
4626 without the interaction of the window manager. Whatever you end up
4627 doing with this code, do it to x_unfocus_frame too. */
4628 XSetInputFocus (x_current_display
, FRAME_X_WINDOW (f
),
4629 RevertToPointerRoot
, CurrentTime
);
4637 /* Look at the remarks in x_focus_on_frame. */
4638 if (x_focus_frame
== f
)
4639 XSetInputFocus (x_current_display
, PointerRoot
,
4640 RevertToPointerRoot
, CurrentTime
);
4644 #endif /* ! defined (HAVE_X11) */
4646 /* Raise frame F. */
4651 if (f
->async_visible
)
4654 #ifdef USE_X_TOOLKIT
4655 XRaiseWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
));
4656 #else /* not USE_X_TOOLKIT */
4657 XRaiseWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4658 #endif /* not USE_X_TOOLKIT */
4664 /* Lower frame F. */
4669 if (f
->async_visible
)
4672 #ifdef USE_X_TOOLKIT
4673 XLowerWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
));
4674 #else /* not USE_X_TOOLKIT */
4675 XLowerWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4676 #endif /* not USE_X_TOOLKIT */
4683 XTframe_raise_lower (f
, raise
)
4694 /* Change from withdrawn state to mapped state. */
4696 x_make_frame_visible (f
)
4703 if (! FRAME_VISIBLE_P (f
))
4706 if (! EQ (Vx_no_window_manager
, Qt
))
4707 x_wm_set_window_state (f
, NormalState
);
4708 #ifdef USE_X_TOOLKIT
4709 XtPopup (f
->display
.x
->widget
, XtGrabNone
);
4710 #else /* not USE_X_TOOLKIT */
4711 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4712 #endif /* not USE_X_TOOLKIT */
4713 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
4714 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
4715 #else /* ! defined (HAVE_X11) */
4716 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4717 if (f
->display
.x
->icon_desc
!= 0)
4718 XUnmapWindow (f
->display
.x
->icon_desc
);
4720 /* Handled by the MapNotify event for X11 */
4721 f
->async_visible
= 1;
4722 f
->async_iconified
= 0;
4724 /* NOTE: this may cause problems for the first frame. */
4726 #endif /* ! defined (HAVE_X11) */
4734 /* Change from mapped state to withdrawn state. */
4736 x_make_frame_invisible (f
)
4741 /* Don't keep the highlight on an invisible frame. */
4742 if (x_highlight_frame
== f
)
4743 x_highlight_frame
= 0;
4745 if (! f
->async_visible
&& ! f
->async_iconified
)
4752 if (! XWithdrawWindow (x_current_display
, FRAME_X_WINDOW (f
),
4753 DefaultScreen (x_current_display
)))
4755 UNBLOCK_INPUT_RESIGNAL
;
4756 error ("can't notify window manager of window withdrawal");
4759 #else /* ! defined (HAVE_X11R4) */
4762 /* Tell the window manager what we're going to do. */
4763 if (! EQ (Vx_no_window_manager
, Qt
))
4767 unmap
.xunmap
.type
= UnmapNotify
;
4768 unmap
.xunmap
.window
= FRAME_X_WINDOW (f
);
4769 unmap
.xunmap
.event
= DefaultRootWindow (x_current_display
);
4770 unmap
.xunmap
.from_configure
= False
;
4771 if (! XSendEvent (x_current_display
,
4772 DefaultRootWindow (x_current_display
),
4774 SubstructureRedirectMask
|SubstructureNotifyMask
,
4777 UNBLOCK_INPUT_RESIGNAL
;
4778 error ("can't notify window manager of withdrawal");
4782 /* Unmap the window ourselves. Cheeky! */
4783 XUnmapWindow (x_current_display
, FRAME_X_WINDOW (f
));
4785 #else /* ! defined (HAVE_X11) */
4787 XUnmapWindow (FRAME_X_WINDOW (f
));
4788 f
->async_visible
= 0; /* Handled by the UnMap event for X11 */
4789 if (f
->display
.x
->icon_desc
!= 0)
4790 XUnmapWindow (f
->display
.x
->icon_desc
);
4792 #endif /* ! defined (HAVE_X11) */
4793 #endif /* ! defined (HAVE_X11R4) */
4799 /* Change window state from mapped to iconified. */
4807 /* Don't keep the highlight on an invisible frame. */
4808 if (x_highlight_frame
== f
)
4809 x_highlight_frame
= 0;
4811 if (f
->async_iconified
)
4814 #ifdef USE_X_TOOLKIT
4816 result
= XIconifyWindow (x_current_display
,
4817 XtWindow(f
->display
.x
->widget
),
4818 DefaultScreen (x_current_display
));
4822 error ("Can't notify window manager of iconification.");
4824 f
->async_iconified
= 1;
4829 #else /* not USE_X_TOOLKIT */
4834 /* Since we don't know which revision of X we're running, we'll use both
4835 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
4837 /* X11R4: send a ClientMessage to the window manager using the
4838 WM_CHANGE_STATE type. */
4842 message
.xclient
.window
= FRAME_X_WINDOW (f
);
4843 message
.xclient
.type
= ClientMessage
;
4844 message
.xclient
.message_type
= Xatom_wm_change_state
;
4845 message
.xclient
.format
= 32;
4846 message
.xclient
.data
.l
[0] = IconicState
;
4848 if (! XSendEvent (x_current_display
,
4849 DefaultRootWindow (x_current_display
),
4851 SubstructureRedirectMask
| SubstructureNotifyMask
,
4854 UNBLOCK_INPUT_RESIGNAL
;
4855 error ("Can't notify window manager of iconification.");
4859 /* X11R3: set the initial_state field of the window manager hints to
4861 x_wm_set_window_state (f
, IconicState
);
4863 if (!FRAME_VISIBLE_P (f
))
4865 /* If the frame was withdrawn, before, we must map it. */
4866 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4867 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
4868 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
4871 f
->async_iconified
= 1;
4872 #else /* ! defined (HAVE_X11) */
4873 XUnmapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4875 f
->async_visible
= 0; /* Handled in the UnMap event for X11. */
4876 if (f
->display
.x
->icon_desc
!= 0)
4878 XMapWindow (XDISPLAY f
->display
.x
->icon_desc
);
4881 #endif /* ! defined (HAVE_X11) */
4885 #endif /* not USE_X_TOOLKIT */
4888 /* Destroy the X window of frame F. */
4890 x_destroy_window (f
)
4895 if (f
->display
.x
->icon_desc
!= 0)
4896 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
4897 XDestroyWindow (XDISPLAY f
->display
.x
->window_desc
);
4898 #ifdef USE_X_TOOLKIT
4899 XtDestroyWidget (f
->display
.x
->widget
);
4900 #endif /* USE_X_TOOLKIT */
4902 free_frame_faces (f
);
4905 xfree (f
->display
.x
);
4907 if (f
== x_focus_frame
)
4909 if (f
== x_highlight_frame
)
4910 x_highlight_frame
= 0;
4915 /* Manage event queues for X10. */
4919 /* Manage event queues.
4921 This code is only used by the X10 support.
4923 We cannot leave events in the X queue and get them when we are ready
4924 because X does not provide a subroutine to get only a certain kind
4925 of event but not block if there are no queued events of that kind.
4927 Therefore, we must examine events as they come in and copy events
4928 of certain kinds into our private queues.
4930 All ExposeRegion events are put in x_expose_queue.
4931 All ButtonPress and ButtonRelease events are put in x_mouse_queue. */
4934 /* Write the event *P_XREP into the event queue *QUEUE.
4935 If the queue is full, do nothing, but return nonzero. */
4938 enqueue_event (p_xrep
, queue
)
4939 register XEvent
*p_xrep
;
4940 register struct event_queue
*queue
;
4942 int newindex
= queue
->windex
+ 1;
4943 if (newindex
== EVENT_BUFFER_SIZE
)
4945 if (newindex
== queue
->rindex
)
4947 queue
->xrep
[queue
->windex
] = *p_xrep
;
4948 queue
->windex
= newindex
;
4952 /* Fetch the next event from queue *QUEUE and store it in *P_XREP.
4953 If *QUEUE is empty, do nothing and return 0. */
4956 dequeue_event (p_xrep
, queue
)
4957 register XEvent
*p_xrep
;
4958 register struct event_queue
*queue
;
4960 if (queue
->windex
== queue
->rindex
)
4962 *p_xrep
= queue
->xrep
[queue
->rindex
++];
4963 if (queue
->rindex
== EVENT_BUFFER_SIZE
)
4968 /* Return the number of events buffered in *QUEUE. */
4971 queue_event_count (queue
)
4972 register struct event_queue
*queue
;
4974 int tem
= queue
->windex
- queue
->rindex
;
4977 return EVENT_BUFFER_SIZE
+ tem
;
4980 /* Return nonzero if mouse input is pending. */
4983 mouse_event_pending_p ()
4985 return queue_event_count (&x_mouse_queue
);
4987 #endif /* HAVE_X11 */
4989 /* Setting window manager hints. */
4993 /* SPEC_X and SPEC_Y are the specified positions.
4994 We look only at their sign, to decide the gravity. */
4996 x_wm_set_size_hint (f
, prompting
, spec_x
, spec_y
)
5001 XSizeHints size_hints
;
5003 #ifdef USE_X_TOOLKIT
5004 Window window
= XtWindow(f
->display
.x
->widget
);
5005 #else /* not USE_X_TOOLKIT */
5006 Window window
= FRAME_X_WINDOW (f
);
5007 #endif /* not USE_X_TOOLKIT */
5009 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
5011 flexlines
= f
->height
;
5013 size_hints
.x
= f
->display
.x
->left_pos
;
5014 size_hints
.y
= f
->display
.x
->top_pos
;
5015 size_hints
.height
= PIXEL_HEIGHT (f
);
5016 size_hints
.width
= PIXEL_WIDTH (f
);
5017 size_hints
.width_inc
= FONT_WIDTH (f
->display
.x
->font
);
5018 size_hints
.height_inc
= FONT_HEIGHT (f
->display
.x
->font
);
5020 size_hints
.max_width
= x_screen_width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
5021 size_hints
.max_height
= x_screen_height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
5024 int base_width
, base_height
;
5026 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
5027 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
5030 int min_rows
= 0, min_cols
= 0;
5031 check_frame_size (f
, &min_rows
, &min_cols
);
5033 /* The window manager uses the base width hints to calculate the
5034 current number of rows and columns in the frame while
5035 resizing; min_width and min_height aren't useful for this
5036 purpose, since they might not give the dimensions for a
5037 zero-row, zero-column frame.
5039 We use the base_width and base_height members if we have
5040 them; otherwise, we set the min_width and min_height members
5041 to the size for a zero x zero frame. */
5044 size_hints
.flags
|= PBaseSize
;
5045 size_hints
.base_width
= base_width
;
5046 size_hints
.base_height
= base_height
;
5047 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
5048 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
5050 size_hints
.min_width
= base_width
;
5051 size_hints
.min_height
= base_height
;
5058 size_hints
.flags
|= prompting
;
5061 XSizeHints hints
; /* Sometimes I hate X Windows... */
5063 if (XGetNormalHints (x_current_display
, window
, &hints
) == 0)
5065 if (hints
.flags
& PSize
)
5066 size_hints
.flags
|= PSize
;
5067 if (hints
.flags
& PPosition
)
5068 size_hints
.flags
|= PPosition
;
5069 if (hints
.flags
& USPosition
)
5070 size_hints
.flags
|= USPosition
;
5071 if (hints
.flags
& USSize
)
5072 size_hints
.flags
|= USSize
;
5074 #if defined (PWinGravity)
5075 switch (((spec_x
< 0) << 1) + (spec_y
< 0))
5078 size_hints
.win_gravity
= NorthWestGravity
;
5081 size_hints
.win_gravity
= NorthEastGravity
;
5084 size_hints
.win_gravity
= SouthWestGravity
;
5087 size_hints
.win_gravity
= SouthEastGravity
;
5090 size_hints
.flags
|= PWinGravity
;
5091 #endif /* PWinGravity */
5094 XSetWMNormalHints (x_current_display
, window
, &size_hints
);
5096 XSetNormalHints (x_current_display
, window
, &size_hints
);
5100 /* Used for IconicState or NormalState */
5101 x_wm_set_window_state (f
, state
)
5105 #ifdef USE_X_TOOLKIT
5106 Window window
= XtWindow(f
->display
.x
->widget
);
5107 #else /* not USE_X_TOOLKIT */
5108 Window window
= FRAME_X_WINDOW (f
);
5109 #endif /* not USE_X_TOOLKIT */
5111 f
->display
.x
->wm_hints
.flags
|= StateHint
;
5112 f
->display
.x
->wm_hints
.initial_state
= state
;
5114 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
5117 x_wm_set_icon_pixmap (f
, icon_pixmap
)
5121 Window window
= FRAME_X_WINDOW (f
);
5125 f
->display
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
5126 f
->display
.x
->wm_hints
.flags
|= IconPixmapHint
;
5129 f
->display
.x
->wm_hints
.flags
&= ~IconPixmapHint
;
5131 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
5134 x_wm_set_icon_position (f
, icon_x
, icon_y
)
5138 Window window
= FRAME_X_WINDOW (f
);
5140 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
5141 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
5142 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
5144 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
5148 /* Initialization. */
5150 #ifdef USE_X_TOOLKIT
5151 static XrmOptionDescRec emacs_options
[] = {
5152 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
5153 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
5155 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
5156 XrmoptionSepArg
, NULL
},
5157 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
5159 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5160 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5161 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5162 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5163 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5164 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
5165 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
5167 #endif /* USE_X_TOOLKIT */
5170 x_term_init (display_name
)
5177 #ifndef F_SETOWN_BUG
5179 extern int old_fcntl_owner
;
5180 #endif /* ! defined (F_SETOWN) */
5181 #endif /* F_SETOWN_BUG */
5183 x_focus_frame
= x_highlight_frame
= 0;
5185 #ifdef USE_X_TOOLKIT
5186 argv
= (char **) XtMalloc (3 * sizeof (char *));
5188 argv
[1] = "-display";
5189 argv
[2] = display_name
;
5191 Xt_app_shell
= XtAppInitialize (&Xt_app_con
, "Emacs",
5192 emacs_options
, XtNumber(emacs_options
),
5196 x_current_display
= XtDisplay (Xt_app_shell
);
5198 #else /* not USE_X_TOOLKIT */
5199 x_current_display
= XOpenDisplay (display_name
);
5200 #endif /* not USE_X_TOOLKIT */
5201 if (x_current_display
== 0)
5202 fatal ("X server %s not responding.\n\
5203 Check the DISPLAY environment variable or use \"-d\"\n",
5209 XSetAfterFunction (x_current_display
, x_trace_wire
);
5211 hostname
= get_system_name ();
5212 x_id_name
= (char *) xmalloc (XSTRING (Vinvocation_name
)->size
5215 sprintf (x_id_name
, "%s@%s", XSTRING (Vinvocation_name
)->data
, hostname
);
5218 /* Figure out which modifier bits mean what. */
5219 x_find_modifier_meanings ();
5221 /* Get the scroll bar cursor. */
5222 x_vertical_scroll_bar_cursor
5223 = XCreateFontCursor (x_current_display
, XC_sb_v_double_arrow
);
5226 /* Watch for PropertyNotify events on the root window; we use them
5227 to figure out when to invalidate our cache of the cut buffers. */
5228 x_watch_cut_buffer_cache ();
5231 if (ConnectionNumber (x_current_display
) != 0)
5232 change_keyboard_wait_descriptor (ConnectionNumber (x_current_display
));
5233 change_input_fd (ConnectionNumber (x_current_display
));
5235 #endif /* ! defined (HAVE_X11) */
5237 #ifndef F_SETOWN_BUG
5239 old_fcntl_owner
= fcntl (ConnectionNumber (x_current_display
), F_GETOWN
, 0);
5240 #ifdef F_SETOWN_SOCK_NEG
5241 /* stdin is a socket here */
5242 fcntl (ConnectionNumber (x_current_display
), F_SETOWN
, -getpid ());
5243 #else /* ! defined (F_SETOWN_SOCK_NEG) */
5244 fcntl (ConnectionNumber (x_current_display
), F_SETOWN
, getpid ());
5245 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
5246 #endif /* ! defined (F_SETOWN) */
5247 #endif /* F_SETOWN_BUG */
5251 #endif /* ! defined (SIGIO) */
5253 expose_all_windows
= 0;
5255 clear_frame_hook
= XTclear_frame
;
5256 clear_end_of_line_hook
= XTclear_end_of_line
;
5257 ins_del_lines_hook
= XTins_del_lines
;
5258 change_line_highlight_hook
= XTchange_line_highlight
;
5259 insert_glyphs_hook
= XTinsert_glyphs
;
5260 write_glyphs_hook
= XTwrite_glyphs
;
5261 delete_glyphs_hook
= XTdelete_glyphs
;
5262 ring_bell_hook
= XTring_bell
;
5263 reset_terminal_modes_hook
= XTreset_terminal_modes
;
5264 set_terminal_modes_hook
= XTset_terminal_modes
;
5265 update_begin_hook
= XTupdate_begin
;
5266 update_end_hook
= XTupdate_end
;
5267 set_terminal_window_hook
= XTset_terminal_window
;
5268 read_socket_hook
= XTread_socket
;
5269 cursor_to_hook
= XTcursor_to
;
5270 reassert_line_highlight_hook
= XTreassert_line_highlight
;
5271 mouse_position_hook
= XTmouse_position
;
5272 frame_rehighlight_hook
= XTframe_rehighlight
;
5273 frame_raise_lower_hook
= XTframe_raise_lower
;
5274 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
5275 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
5276 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
5277 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
5279 scroll_region_ok
= 1; /* we'll scroll partial frames */
5280 char_ins_del_ok
= 0; /* just as fast to write the line */
5281 line_ins_del_ok
= 1; /* we'll just blt 'em */
5282 fast_clear_end_of_line
= 1; /* X does this well */
5283 memory_below_frame
= 0; /* we don't remember what scrolls
5287 /* Try to use interrupt input; if we can't, then start polling. */
5288 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
5290 /* Note that there is no real way portable across R3/R4 to get the
5291 original error handler. */
5292 XHandleError (x_error_quitter
);
5293 XHandleIOError (x_io_error_quitter
);
5295 /* Disable Window Change signals; they are handled by X events. */
5297 signal (SIGWINCH
, SIG_DFL
);
5298 #endif /* ! defined (SIGWINCH) */
5300 signal (SIGPIPE
, x_connection_closed
);
5306 staticpro (&last_mouse_scroll_bar
);
5307 last_mouse_scroll_bar
= Qnil
;
5309 #endif /* ! defined (HAVE_X11) */
5310 #endif /* ! defined (HAVE_X_WINDOWS) */