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. */
42 #include "syssignal.h"
47 #include "blockinput.h"
49 /* This may include sys/types.h, and that somehow loses
50 if this is not done before the other system files. */
52 #include <X11/cursorfont.h>
55 /* Load sys/types.h if not already loaded.
56 In some systems loading it twice is suicidal. */
58 #include <sys/types.h>
63 #include <sys/ioctl.h>
65 #else /* ! defined (BSD) */
69 #endif /* ! defined (BSD) */
79 #include <sys/param.h>
81 #include "dispextern.h"
82 #include "termhooks.h"
96 extern XtAppContext Xt_app_con
;
97 extern Widget Xt_app_shell
;
98 #endif /* USE_X_TOOLKIT */
101 #define XMapWindow XMapRaised /* Raise them when mapping. */
102 #else /* ! defined (HAVE_X11) */
103 #include <X/Xkeyboard.h>
104 /*#include <X/Xproto.h> */
105 #endif /* ! defined (HAVE_X11) */
108 /* We could get this from param.h, but better not to depend on finding that.
109 And better not to risk that it might define other symbols used in this
112 #define MAXDESC FD_SETSIZE
116 #define SELECT_TYPE fd_set
117 #else /* no FD_SET */
119 #define SELECT_TYPE int
121 /* Define the macros to access a single-int bitmap of descriptors. */
122 #define FD_SET(n, p) (*(p) |= (1 << (n)))
123 #define FD_CLR(n, p) (*(p) &= ~(1 << (n)))
124 #define FD_ISSET(n, p) (*(p) & (1 << (n)))
125 #define FD_ZERO(p) (*(p) = 0)
126 #endif /* no FD_SET */
128 /* For sending Meta-characters. Do we need this? */
131 #define min(a,b) ((a)<(b) ? (a) : (b))
132 #define max(a,b) ((a)>(b) ? (a) : (b))
134 /* Nonzero means we must reprint all windows
135 because 1) we received an ExposeWindow event
136 or 2) we received too many ExposeRegion events to record.
138 This is never needed under X11. */
139 static int expose_all_windows
;
141 /* Nonzero means we must reprint all icon windows. */
143 static int expose_all_icons
;
146 /* ExposeRegion events, when received, are copied into this queue
147 for later processing. */
149 static struct event_queue x_expose_queue
;
151 /* ButtonPress and ButtonReleased events, when received,
152 are copied into this queue for later processing. */
154 struct event_queue x_mouse_queue
;
155 #endif /* HAVE_X11 */
157 #if defined (SIGIO) && defined (FIONREAD)
158 int BLOCK_INPUT_mask
;
159 #endif /* ! defined (SIGIO) && defined (FIONREAD) */
161 /* The id of a bitmap used for icon windows.
162 One such map is shared by all Emacs icon windows.
163 This is zero if we have not yet had a need to create the bitmap. */
165 static Bitmap icon_bitmap
;
167 /* Font used for text icons. */
169 static FONT_TYPE
*icon_font_info
;
171 /* Stuff for dealing with the main icon title. */
173 extern Lisp_Object Vcommand_line_args
;
174 char *hostname
, *x_id_name
;
176 /* This is the X connection that we are using. */
178 Display
*x_current_display
;
180 /* The cursor to use for vertical scroll bars on x_current_display. */
181 static Cursor x_vertical_scroll_bar_cursor
;
183 /* Frame being updated by update_frame. This is declared in term.c.
184 This is set by update_begin and looked at by all the
185 XT functions. It is zero while not inside an update.
186 In that case, the XT functions assume that `selected_frame'
187 is the frame to apply to. */
188 extern struct frame
*updating_frame
;
190 /* The frame (if any) which has the X window that has keyboard focus.
191 Zero if none. This is examined by Ffocus_frame in frame.c. Note
192 that a mere EnterNotify event can set this; if you need to know the
193 last frame specified in a FocusIn or FocusOut event, use
194 x_focus_event_frame. */
195 struct frame
*x_focus_frame
;
197 /* The last frame mentioned in a FocusIn or FocusOut event. This is
198 separate from x_focus_frame, because whether or not LeaveNotify
199 events cause us to lose focus depends on whether or not we have
200 received a FocusIn event for it. */
201 struct frame
*x_focus_event_frame
;
203 /* The frame which currently has the visual highlight, and should get
204 keyboard input (other sorts of input have the frame encoded in the
205 event). It points to the X focus frame's selected window's
206 frame. It differs from x_focus_frame when we're using a global
208 static struct frame
*x_highlight_frame
;
210 /* From .Xdefaults, the value of "emacs.WarpMouse". If non-zero,
211 mouse is moved to inside of frame when frame is de-iconified. */
213 static int warp_mouse_on_deiconify
;
215 /* During an update, maximum vpos for ins/del line operations to affect. */
217 static int flexlines
;
219 /* During an update, nonzero if chars output now should be highlighted. */
221 static int highlight
;
223 /* Nominal cursor position -- where to draw output.
224 During an update, these are different from the cursor-box position. */
231 In order to avoid asking for motion events and then throwing most
232 of them away or busy-polling the server for mouse positions, we ask
233 the server for pointer motion hints. This means that we get only
234 one event per group of mouse movements. "Groups" are delimited by
235 other kinds of events (focus changes and button clicks, for
236 example), or by XQueryPointer calls; when one of these happens, we
237 get another MotionNotify event the next time the mouse moves. This
238 is at least as efficient as getting motion events when mouse
239 tracking is on, and I suspect only negligibly worse when tracking
242 The silly O'Reilly & Associates Nutshell guides barely document
243 pointer motion hints at all (I think you have to infer how they
244 work from an example), and the description of XQueryPointer doesn't
245 mention that calling it causes you to get another motion hint from
246 the server, which is very important. */
248 /* Where the mouse was last time we reported a mouse event. */
249 static FRAME_PTR last_mouse_frame
;
250 static XRectangle last_mouse_glyph
;
252 /* The scroll bar in which the last X motion event occurred.
254 If the last X motion event occurred in a scroll bar, we set this
255 so XTmouse_position can know whether to report a scroll bar motion or
258 If the last X motion event didn't occur in a scroll bar, we set this
259 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
260 static Lisp_Object last_mouse_scroll_bar
;
262 /* Record which buttons are currently pressed. */
263 unsigned int x_mouse_grabbed
;
265 /* This is a hack. We would really prefer that XTmouse_position would
266 return the time associated with the position it returns, but there
267 doesn't seem to be any way to wrest the timestamp from the server
268 along with the position query. So, we just keep track of the time
269 of the last movement we received, and return that in hopes that
270 it's somewhat accurate. */
271 static Time last_mouse_movement_time
;
274 /* `t' if a mouse button is depressed. */
276 extern Lisp_Object Vmouse_depressed
;
278 /* Tells if a window manager is present or not. */
280 extern Lisp_Object Vx_no_window_manager
;
282 /* Timestamp that we requested selection data was made. */
283 extern Time requestor_time
;
285 /* ID of the window requesting selection data. */
286 extern Window requestor_window
;
288 /* Nonzero enables some debugging for the X interface code. */
291 #else /* ! defined (HAVE_X11) */
293 /* Bit patterns for the mouse cursor. */
295 short MouseCursor
[] = {
296 0x0000, 0x0008, 0x0018, 0x0038,
297 0x0078, 0x00f8, 0x01f8, 0x03f8,
298 0x07f8, 0x00f8, 0x00d8, 0x0188,
299 0x0180, 0x0300, 0x0300, 0x0000};
301 short MouseMask
[] = {
302 0x000c, 0x001c, 0x003c, 0x007c,
303 0x00fc, 0x01fc, 0x03fc, 0x07fc,
304 0x0ffc, 0x0ffc, 0x01fc, 0x03dc,
305 0x03cc, 0x0780, 0x0780, 0x0300};
307 static short grey_bits
[] = {
308 0x0005, 0x000a, 0x0005, 0x000a};
310 static Pixmap GreyPixmap
= 0;
311 #endif /* ! defined (HAVE_X11) */
313 /* From time to time we get info on an Emacs window, here. */
315 static WINDOWINFO_TYPE windowinfo
;
319 /* A mask of extra modifier bits to put into every keyboard char. */
320 extern int extra_keyboard_modifiers
;
322 extern Display
*XOpenDisplay ();
323 extern Window
XCreateWindow ();
325 extern Cursor
XCreateCursor ();
326 extern FONT_TYPE
*XOpenFont ();
328 static void flashback ();
329 static void redraw_previous_char ();
330 static unsigned int x_x_to_emacs_modifiers ();
333 static void dumpqueue ();
334 #endif /* HAVE_X11 */
337 static int XTcursor_to ();
338 static int XTclear_end_of_line ();
341 /* Starting and ending updates.
343 These hooks are called by update_frame at the beginning and end
344 of a frame update. We record in `updating_frame' the identity
345 of the frame being updated, so that the XT... functions do not
346 need to take a frame as argument. Most of the XT... functions
347 should never be called except during an update, the only exceptions
348 being XTcursor_to, XTwrite_glyphs and XTreassert_line_highlight. */
350 extern int mouse_track_top
, mouse_track_left
, mouse_track_width
;
361 flexlines
= f
->height
;
367 #endif /* HAVE_X11 */
372 static void x_do_pending_expose ();
384 x_do_pending_expose ();
385 #endif /* HAVE_X11 */
387 x_display_cursor (f
, 1);
393 /* External interface to control of standout mode.
394 Call this when about to modify line at position VPOS
395 and not change whether it is highlighted. */
397 XTreassert_line_highlight (new, vpos
)
403 /* Call this when about to modify line at position VPOS
404 and change whether it is highlighted. */
407 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
408 int new_highlight
, vpos
, first_unused_hpos
;
410 highlight
= new_highlight
;
411 XTcursor_to (vpos
, 0);
412 XTclear_end_of_line (updating_frame
->width
);
415 /* This is used when starting Emacs and when restarting after suspend.
416 When starting Emacs, no X window is mapped. And nothing must be done
417 to Emacs's own window if it is suspended (though that rarely happens). */
420 XTset_terminal_modes ()
424 /* This is called when exiting or suspending Emacs.
425 Exiting will make the X-windows go away, and suspending
426 requires no action. */
429 XTreset_terminal_modes ()
431 /* XTclear_frame (); */
434 /* Set the nominal cursor position of the frame.
435 This is where display update commands will take effect.
436 This does not affect the place where the cursor-box is displayed. */
439 XTcursor_to (row
, col
)
440 register int row
, col
;
448 if (updating_frame
== 0)
451 x_display_cursor (selected_frame
, 1);
457 /* Display a sequence of N glyphs found at GP.
458 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
459 HL is 1 if this text is highlighted, 2 if the cursor is on it.
461 FONT is the default font to use (for glyphs whose font-code is 0).
463 Since the display generation code is responsible for calling
464 compute_char_face and compute_glyph_face on everything it puts in
465 the display structure, we can assume that the face code on each
466 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
467 to which we can actually apply intern_face.
468 Call this function with input blocked. */
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.
756 Call this function with input blocked. */
759 redraw_previous_char (f
, x
, y
)
763 /* Erase the character before the new ones, in case
764 what was here before overlaps it.
765 Reoutput that character, and the previous character
766 (in case the previous character overlaps it). */
772 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
773 CHAR_TO_PIXEL_COL (f
, x
- 1),
774 CHAR_TO_PIXEL_ROW (f
, y
),
775 FONT_WIDTH (f
->display
.x
->font
),
776 FONT_HEIGHT (f
->display
.x
->font
), False
);
778 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, start_x
),
779 CHAR_TO_PIXEL_ROW (f
, y
),
780 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][start_x
],
781 x
- start_x
, highlight
);
789 struct frame
*f
= updating_frame
;
794 f
->phys_cursor_x
= -1; /* Cursor not visible. */
795 curs_x
= 0; /* Nominal cursor position is top left. */
800 XClear (FRAME_X_WINDOW (f
));
802 /* We have to clear the scroll bars, too. If we have changed
803 colors or something like that, then they should be notified. */
804 x_scroll_bar_clear (f
);
808 #endif /* HAVE_X11 */
814 /* Invert the middle quarter of the frame for .15 sec. */
816 /* We use the select system call to do the waiting, so we have to make sure
817 it's available. If it isn't, we just won't do visual bells. */
818 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
820 /* Subtract the `struct timeval' values X and Y,
821 storing the result in RESULT.
822 Return 1 if the difference is negative, otherwise 0. */
825 timeval_subtract (result
, x
, y
)
826 struct timeval
*result
, x
, y
;
828 /* Perform the carry for the later subtraction by updating y.
829 This is safer because on some systems
830 the tv_sec member is unsigned. */
831 if (x
.tv_usec
< y
.tv_usec
)
833 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
834 y
.tv_usec
-= 1000000 * nsec
;
837 if (x
.tv_usec
- y
.tv_usec
> 1000000)
839 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
840 y
.tv_usec
+= 1000000 * nsec
;
844 /* Compute the time remaining to wait. tv_usec is certainly positive. */
845 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
846 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
848 /* Return indication of whether the result should be considered negative. */
849 return x
.tv_sec
< y
.tv_sec
;
860 /* Create a GC that will use the GXxor function to flip foreground pixels
861 into background pixels. */
865 values
.function
= GXxor
;
866 values
.foreground
= (f
->display
.x
->foreground_pixel
867 ^ f
->display
.x
->background_pixel
);
869 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
870 GCFunction
| GCForeground
, &values
);
874 int width
= PIXEL_WIDTH (f
);
875 int height
= PIXEL_HEIGHT (f
);
877 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
878 width
/4, height
/4, width
/2, height
/2);
879 XFlush (x_current_display
);
882 struct timeval wakeup
, now
;
884 EMACS_GET_TIME (wakeup
);
886 /* Compute time to wait until, propagating carry from usecs. */
887 wakeup
.tv_usec
+= 150000;
888 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
889 wakeup
.tv_usec
%= 1000000;
891 /* Keep waiting until past the time wakeup. */
894 struct timeval timeout
;
896 EMACS_GET_TIME (timeout
);
898 /* In effect, timeout = wakeup - timeout.
899 Break if result would be negative. */
900 if (timeval_subtract (&timeout
, wakeup
, timeout
))
903 /* Try to wait that long--but we might wake up sooner. */
904 select (0, 0, 0, 0, &timeout
);
908 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
), gc
,
909 width
/4, height
/4, width
/2, height
/2);
910 XFreeGC (x_current_display
, gc
);
911 XFlush (x_current_display
);
921 /* Make audible bell. */
924 #define XRINGBELL XBell (x_current_display, 0)
925 #else /* ! defined (HAVE_X11) */
926 #define XRINGBELL XFeep (0);
927 #endif /* ! defined (HAVE_X11) */
931 if (x_current_display
== 0)
934 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
936 XTflash (selected_frame
);
947 /* Insert and delete character.
948 These are not supposed to be used because we are supposed to turn
949 off the feature of using them. */
952 XTinsert_glyphs (start
, len
)
953 register char *start
;
966 /* Specify how many text lines, from the top of the window,
967 should be affected by insert-lines and delete-lines operations.
968 This, and those operations, are used only within an update
969 that is bounded by calls to XTupdate_begin and XTupdate_end. */
972 XTset_terminal_window (n
)
975 if (updating_frame
== 0)
978 if ((n
<= 0) || (n
> updating_frame
->height
))
979 flexlines
= updating_frame
->height
;
984 /* Perform an insert-lines operation.
985 Insert N lines at a vertical position curs_y. */
991 register int topregion
, bottomregion
;
992 register int length
, newtop
, mask
;
993 register struct frame
*f
= updating_frame
;
994 int intborder
= f
->display
.x
->internal_border_width
;
996 if (curs_y
>= flexlines
)
1000 bottomregion
= flexlines
- (n
+ 1);
1001 newtop
= topregion
+ n
;
1002 length
= (bottomregion
- topregion
) + 1;
1006 #endif /* HAVE_X11 */
1008 if ((length
> 0) && (newtop
<= flexlines
))
1011 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
1012 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
1013 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
1014 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1015 length
* FONT_HEIGHT (f
->display
.x
->font
), intborder
,
1016 CHAR_TO_PIXEL_ROW (f
, newtop
));
1017 #else /* ! defined (HAVE_X11) */
1018 XMoveArea (FRAME_X_WINDOW (f
),
1019 intborder
, CHAR_TO_PIXEL_ROW (f
, topregion
),
1020 intborder
, CHAR_TO_PIXEL_ROW (f
, newtop
),
1021 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1022 length
* FONT_HEIGHT (f
->display
.x
->font
));
1023 /* Now we must process any ExposeRegion events that occur
1024 if the area being copied from is obscured.
1025 We can't let it wait because further i/d operations
1026 may want to copy this area to another area. */
1028 #endif /* ! defined (HAVE_X11) */
1031 newtop
= min (newtop
, (flexlines
- 1));
1032 length
= newtop
- topregion
;
1036 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
1037 CHAR_TO_PIXEL_ROW (f
, topregion
),
1038 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1039 n
* FONT_HEIGHT (f
->display
.x
->font
), False
);
1040 #else /* ! defined (HAVE_X11) */
1041 XPixSet (FRAME_X_WINDOW (f
),
1043 CHAR_TO_PIXEL_ROW (f
, topregion
),
1044 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1045 n
* FONT_HEIGHT (f
->display
.x
->font
),
1046 f
->display
.x
->background_pixel
);
1047 #endif /* ! defined (HAVE_X11) */
1051 /* Perform a delete-lines operation, deleting N lines
1052 at a vertical position curs_y. */
1059 register struct frame
*f
= updating_frame
;
1060 int intborder
= f
->display
.x
->internal_border_width
;
1062 if (curs_y
>= flexlines
)
1067 #endif /* HAVE_X11 */
1069 if ((curs_y
+ n
) >= flexlines
)
1071 if (flexlines
>= (curs_y
+ 1))
1074 XClearArea (x_current_display
, FRAME_X_WINDOW (f
), intborder
,
1075 CHAR_TO_PIXEL_ROW (f
, curs_y
),
1076 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1077 (flexlines
- curs_y
) * FONT_HEIGHT (f
->display
.x
->font
), False
);
1078 #else /* ! defined (HAVE_X11) */
1079 XPixSet (FRAME_X_WINDOW (f
),
1080 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
1081 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1082 (flexlines
- curs_y
) * FONT_HEIGHT (f
->display
.x
->font
),
1083 f
->display
.x
->background_pixel
);
1084 #endif /* ! defined (HAVE_X11) */
1090 XCopyArea (x_current_display
, FRAME_X_WINDOW (f
),
1091 FRAME_X_WINDOW (f
), f
->display
.x
->normal_gc
,
1093 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
1094 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1095 (flexlines
- (curs_y
+ n
)) * FONT_HEIGHT (f
->display
.x
->font
),
1096 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
));
1097 XClearArea (x_current_display
, FRAME_X_WINDOW (f
),
1099 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
1100 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1101 n
* FONT_HEIGHT (f
->display
.x
->font
), False
);
1102 #else /* ! defined (HAVE_X11) */
1103 XMoveArea (FRAME_X_WINDOW (f
),
1105 CHAR_TO_PIXEL_ROW (f
, curs_y
+ n
),
1106 intborder
, CHAR_TO_PIXEL_ROW (f
, curs_y
),
1107 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1108 (flexlines
- (curs_y
+ n
)) * FONT_HEIGHT (f
->display
.x
->font
));
1109 /* Now we must process any ExposeRegion events that occur
1110 if the area being copied from is obscured.
1111 We can't let it wait because further i/d operations
1112 may want to copy this area to another area. */
1114 XPixSet (FRAME_X_WINDOW (f
), intborder
,
1115 CHAR_TO_PIXEL_ROW (f
, flexlines
- n
),
1116 f
->width
* FONT_WIDTH (f
->display
.x
->font
),
1117 n
* FONT_HEIGHT (f
->display
.x
->font
), f
->display
.x
->background_pixel
);
1118 #endif /* ! defined (HAVE_X11) */
1122 /* Perform an insert-lines or delete-lines operation,
1123 inserting N lines or deleting -N lines at vertical position VPOS. */
1125 XTins_del_lines (vpos
, n
)
1128 if (updating_frame
== 0)
1131 /* Hide the cursor. */
1132 x_display_cursor (updating_frame
, 0);
1134 XTcursor_to (vpos
, 0);
1145 /* Support routines for exposure events. */
1146 static void clear_cursor ();
1148 /* Output into a rectangle of an X-window (for frame F)
1149 the characters in f->phys_lines that overlap that rectangle.
1150 TOP and LEFT are the position of the upper left corner of the rectangle.
1151 ROWS and COLS are the size of the rectangle.
1152 Call this function with input blocked. */
1155 dumprectangle (f
, left
, top
, cols
, rows
)
1157 register int left
, top
, cols
, rows
;
1159 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1160 int cursor_cleared
= 0;
1164 if (FRAME_GARBAGED_P (f
))
1167 /* Express rectangle as four edges, instead of position-and-size. */
1168 bottom
= top
+ rows
;
1169 right
= left
+ cols
;
1171 #ifndef HAVE_X11 /* Window manger does this for X11. */
1173 int intborder
= f
->display
.x
->internal_border_width
;
1175 /* If the rectangle includes any of the internal border area,
1176 redisplay the border emphasis. */
1177 if (top
< intborder
|| left
< intborder
1178 || bottom
> intborder
+ f
->height
* FONT_HEIGHT (f
->display
.x
->font
)
1179 || right
> intborder
+ f
->width
* FONT_WIDTH (f
->display
.x
->font
))
1182 #endif /* HAVE_X11 Window manger does this for X11. */
1184 /* Convert rectangle edges in pixels to edges in chars.
1185 Round down for left and top, up for right and bottom. */
1186 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1187 left
= PIXEL_TO_CHAR_COL (f
, left
);
1188 bottom
+= (FONT_HEIGHT (f
->display
.x
->font
) - 1);
1189 right
+= (FONT_WIDTH (f
->display
.x
->font
) - 1);
1190 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1191 right
= PIXEL_TO_CHAR_COL (f
, right
);
1193 /* Clip the rectangle to what can be visible. */
1198 if (right
> f
->width
)
1200 if (bottom
> f
->height
)
1203 /* Get size in chars of the rectangle. */
1204 cols
= right
- left
;
1205 rows
= bottom
- top
;
1207 /* If rectangle has zero area, return. */
1208 if (rows
<= 0) return;
1209 if (cols
<= 0) return;
1211 /* Turn off the cursor if it is in the rectangle.
1212 We will turn it back on afterward. */
1213 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1214 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1220 /* Display the text in the rectangle, one text line at a time. */
1222 for (y
= top
; y
< bottom
; y
++)
1224 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1226 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1230 CHAR_TO_PIXEL_COL (f
, left
),
1231 CHAR_TO_PIXEL_ROW (f
, y
),
1232 line
, min (cols
, active_frame
->used
[y
] - left
),
1233 active_frame
->highlight
[y
]);
1236 /* Turn the cursor on if we turned it off. */
1239 x_display_cursor (f
, 1);
1243 /* Process all queued ExposeRegion events. */
1249 XExposeRegionEvent r
;
1251 while (dequeue_event (&r
, &x_expose_queue
))
1253 struct frame
*f
= x_window_to_frame (r
.window
);
1254 if (f
->display
.x
->icon_desc
== r
.window
)
1257 dumprectangle (f
, r
.x
, r
.y
, r
.width
, r
.height
);
1261 #endif /* HAVE_X11 */
1263 /* Process all expose events that are pending, for X10.
1264 Redraws the cursor if necessary on any frame that
1265 is not in the process of being updated with update_frame. */
1269 x_do_pending_expose ()
1273 Lisp_Object tail
, frame
;
1275 if (expose_all_windows
)
1277 expose_all_windows
= 0;
1278 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
1280 register int temp_width
, temp_height
;
1283 frame
= XCONS (tail
)->car
;
1284 if (XGCTYPE (frame
) != Lisp_Frame
)
1287 if (! FRAME_X_P (f
))
1289 if (!f
->async_visible
)
1291 if (!f
->display
.x
->needs_exposure
)
1294 intborder
= f
->display
.x
->internal_border_width
;
1297 XGetWindowInfo (FRAME_X_WINDOW (f
), &windowinfo
);
1298 temp_width
= ((windowinfo
.width
- 2 * intborder
1299 - f
->display
.x
->v_scroll_bar_width
)
1300 / FONT_WIDTH (f
->display
.x
->font
));
1301 temp_height
= ((windowinfo
.height
- 2 * intborder
1302 - f
->display
.x
->h_scroll_bar_height
)
1303 / FONT_HEIGHT (f
->display
.x
->font
));
1304 if (temp_width
!= f
->width
|| temp_height
!= f
->height
)
1306 change_frame_size (f
, max (1, temp_height
),
1307 max (1, temp_width
), 0, 1);
1308 x_resize_scroll_bars (f
);
1310 f
->display
.x
->left_pos
= windowinfo
.x
;
1311 f
->display
.x
->top_pos
= windowinfo
.y
;
1312 dumprectangle (f
, 0, 0, PIXEL_WIDTH (f
), PIXEL_HEIGHT (f
));
1316 f
->display
.x
->needs_exposure
= 0;
1317 if (updating_frame
!= f
)
1318 x_display_cursor (f
, 1);
1323 /* Handle any individual-rectangle expose events queued
1324 for various windows. */
1327 #else /* ! defined (HAVE_X11) */
1329 #endif /* ! defined (HAVE_X11) */
1335 frame_highlight (frame
)
1336 struct frame
*frame
;
1338 /* We used to only do this if Vx_no_window_manager was non-nil, but
1339 the ICCCM (section 4.1.6) says that the window's border pixmap
1340 and border pixel are window attributes which are "private to the
1341 client", so we can always change it to whatever we want. */
1343 XSetWindowBorder (x_current_display
, FRAME_X_WINDOW (frame
),
1344 frame
->display
.x
->border_pixel
);
1346 x_display_cursor (frame
, 1);
1350 frame_unhighlight (frame
)
1351 struct frame
*frame
;
1353 /* We used to only do this if Vx_no_window_manager was non-nil, but
1354 the ICCCM (section 4.1.6) says that the window's border pixmap
1355 and border pixel are window attributes which are "private to the
1356 client", so we can always change it to whatever we want. */
1358 XSetWindowBorderPixmap (x_current_display
, FRAME_X_WINDOW (frame
),
1359 frame
->display
.x
->border_tile
);
1361 x_display_cursor (frame
, 1);
1363 #else /* ! defined (HAVE_X11) */
1364 /* Dump the border-emphasis of frame F.
1365 If F is selected, this is a lining of the same color as the border,
1366 just within the border, occupying a portion of the internal border.
1367 If F is not selected, it is background in the same place.
1368 If ALWAYS is 0, don't bother explicitly drawing if it's background.
1370 ALWAYS = 1 is used when a frame becomes selected or deselected.
1371 In that case, we also turn the cursor off and on again
1372 so it will appear in the proper shape (solid if selected; else hollow.) */
1375 dumpborder (f
, always
)
1379 int thickness
= f
->display
.x
->internal_border_width
/ 2;
1380 int width
= PIXEL_WIDTH (f
);
1381 int height
= PIXEL_HEIGHT (f
);
1384 if (f
!= selected_frame
)
1389 pixel
= f
->display
.x
->background_pixel
;
1393 pixel
= f
->display
.x
->border_pixel
;
1396 XPixSet (FRAME_X_WINDOW (f
), 0, 0, width
, thickness
, pixel
);
1397 XPixSet (FRAME_X_WINDOW (f
), 0, 0, thickness
, height
, pixel
);
1398 XPixSet (FRAME_X_WINDOW (f
), 0, height
- thickness
, width
,
1400 XPixSet (FRAME_X_WINDOW (f
), width
- thickness
, 0, thickness
,
1404 x_display_cursor (f
, 1);
1406 #endif /* ! defined (HAVE_X11) */
1408 static void XTframe_rehighlight ();
1410 /* The focus has changed. Update the frames as necessary to reflect
1411 the new situation. Note that we can't change the selected frame
1412 here, because the lisp code we are interrupting might become confused.
1413 Each event gets marked with the frame in which it occurred, so the
1414 lisp code can tell when the switch took place by examining the events. */
1417 x_new_focus_frame (frame
)
1418 struct frame
*frame
;
1420 struct frame
*old_focus
= x_focus_frame
;
1421 int events_enqueued
= 0;
1423 if (frame
!= x_focus_frame
)
1425 /* Set this before calling other routines, so that they see
1426 the correct value of x_focus_frame. */
1427 x_focus_frame
= frame
;
1429 if (old_focus
&& old_focus
->auto_lower
)
1430 x_lower_frame (old_focus
);
1433 selected_frame
= frame
;
1434 XSET (XWINDOW (selected_frame
->selected_window
)->frame
,
1435 Lisp_Frame
, selected_frame
);
1436 Fselect_window (selected_frame
->selected_window
);
1437 choose_minibuf_frame ();
1440 if (x_focus_frame
&& x_focus_frame
->auto_raise
)
1441 x_raise_frame (x_focus_frame
);
1444 XTframe_rehighlight ();
1448 /* The focus has changed, or we have redirected a frame's focus to
1449 another frame (this happens when a frame uses a surrogate
1450 minibuffer frame). Shift the highlight as appropriate. */
1452 XTframe_rehighlight ()
1454 struct frame
*old_highlight
= x_highlight_frame
;
1459 ((XGCTYPE (FRAME_FOCUS_FRAME (x_focus_frame
)) == Lisp_Frame
)
1460 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame
))
1462 if (! FRAME_LIVE_P (x_highlight_frame
))
1464 FRAME_FOCUS_FRAME (x_focus_frame
) = Qnil
;
1465 x_highlight_frame
= x_focus_frame
;
1469 x_highlight_frame
= 0;
1471 if (x_highlight_frame
!= old_highlight
)
1474 frame_unhighlight (old_highlight
);
1475 if (x_highlight_frame
)
1476 frame_highlight (x_highlight_frame
);
1480 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
1482 /* Which modifier keys are on which modifier bits?
1484 With each keystroke, X returns eight bits indicating which modifier
1485 keys were held down when the key was pressed. The interpretation
1486 of the top five modifier bits depends on what keys are attached
1487 to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
1490 x_meta_mod_mask is a mask containing the bits used for the meta key.
1491 It may have more than one bit set, if more than one modifier bit
1492 has meta keys on it. Basically, if EVENT is a KeyPress event,
1493 the meta key is pressed if (EVENT.state & x_meta_mod_mask) != 0.
1495 x_shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
1496 lock modifier bit, or zero otherwise. Non-alphabetic keys should
1497 only be affected by the lock modifier bit if XK_Shift_Lock is in
1498 use; XK_Caps_Lock should only affect alphabetic keys. With this
1499 arrangement, the lock modifier should shift the character if
1500 (EVENT.state & x_shift_lock_mask) != 0. */
1501 static int x_meta_mod_mask
, x_shift_lock_mask
;
1503 /* These are like x_meta_mod_mask, but for different modifiers. */
1504 static int x_alt_mod_mask
, x_super_mod_mask
, x_hyper_mod_mask
;
1506 /* Initialize mode_switch_bit and modifier_meaning. */
1508 x_find_modifier_meanings ()
1510 int min_code
, max_code
;
1513 XModifierKeymap
*mods
;
1515 x_meta_mod_mask
= 0;
1516 x_shift_lock_mask
= 0;
1518 x_super_mod_mask
= 0;
1519 x_hyper_mod_mask
= 0;
1522 XDisplayKeycodes (x_current_display
, &min_code
, &max_code
);
1524 min_code
= x_current_display
->min_keycode
;
1525 max_code
= x_current_display
->max_keycode
;
1528 syms
= XGetKeyboardMapping (x_current_display
,
1529 min_code
, max_code
- min_code
+ 1,
1531 mods
= XGetModifierMapping (x_current_display
);
1533 /* Scan the modifier table to see which modifier bits the Meta and
1534 Alt keysyms are on. */
1536 int row
, col
; /* The row and column in the modifier table. */
1538 for (row
= 3; row
< 8; row
++)
1539 for (col
= 0; col
< mods
->max_keypermod
; col
++)
1542 mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
1544 /* Are any of this keycode's keysyms a meta key? */
1548 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
1550 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
1556 x_meta_mod_mask
|= (1 << row
);
1561 x_alt_mod_mask
|= (1 << row
);
1566 x_hyper_mod_mask
|= (1 << row
);
1571 x_super_mod_mask
|= (1 << row
);
1575 /* Ignore this if it's not on the lock modifier. */
1576 if ((1 << row
) == LockMask
)
1577 x_shift_lock_mask
= LockMask
;
1585 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1586 if (! x_meta_mod_mask
)
1588 x_meta_mod_mask
= x_alt_mod_mask
;
1592 /* If some keys are both alt and meta,
1593 make them just meta, not alt. */
1594 if (x_alt_mod_mask
& x_meta_mod_mask
)
1596 x_alt_mod_mask
&= ~x_meta_mod_mask
;
1599 XFree ((char *) syms
);
1600 XFreeModifiermap (mods
);
1603 /* Prepare a menu-event in *RESULT for placement in the input queue. */
1606 construct_menu_click (result
, event
, f
)
1607 struct input_event
*result
;
1608 XButtonEvent
*event
;
1611 /* Make the event type no_event; we'll change that when we decide
1613 result
->kind
= mouse_click
;
1614 XSET (result
->code
, Lisp_Int
, event
->button
- Button1
);
1615 result
->timestamp
= event
->time
;
1616 result
->modifiers
= (x_x_to_emacs_modifiers (event
->state
)
1617 | (event
->type
== ButtonRelease
1622 XFASTINT (result
->x
) = event
->x
;
1623 XFASTINT (result
->y
) = -1; /* special meaning for menubar */
1624 XSET (result
->frame_or_window
, Lisp_Frame
, f
);
1628 /* Convert between the modifier bits X uses and the modifier bits
1631 x_x_to_emacs_modifiers (state
)
1634 return ( ((state
& (ShiftMask
| x_shift_lock_mask
)) ? shift_modifier
: 0)
1635 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
1636 | ((state
& x_meta_mod_mask
) ? meta_modifier
: 0)
1637 | ((state
& x_alt_mod_mask
) ? alt_modifier
: 0)
1638 | ((state
& x_super_mod_mask
) ? super_modifier
: 0)
1639 | ((state
& x_hyper_mod_mask
) ? hyper_modifier
: 0));
1643 x_emacs_to_x_modifiers (state
)
1646 return ( ((state
& alt_modifier
) ? x_alt_mod_mask
: 0)
1647 | ((state
& super_modifier
) ? x_super_mod_mask
: 0)
1648 | ((state
& hyper_modifier
) ? x_hyper_mod_mask
: 0)
1649 | ((state
& shift_modifier
) ? ShiftMask
: 0)
1650 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
1651 | ((state
& meta_modifier
) ? x_meta_mod_mask
: 0));
1654 /* Return true iff KEYSYM is a vendor-specific keysym that we should
1655 return as a function key. If you add a keysym to this, you should
1656 make sure that the tables make_lispy_event uses contain a suitable
1659 x_is_vendor_fkey (sym
)
1664 || (sym
== DXK_Remove
)
1670 /* Mouse clicks and mouse movement. Rah. */
1673 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1674 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1675 that the glyph at X, Y occupies, if BOUNDS != 0.
1676 If NOCLIP is nonzero, do not force the value into range. */
1679 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1681 register int pix_x
, pix_y
;
1682 register int *x
, *y
;
1686 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1687 even for negative values. */
1689 pix_x
-= FONT_WIDTH ((f
)->display
.x
->font
) - 1;
1691 pix_y
-= FONT_HEIGHT ((f
)->display
.x
->font
) - 1;
1693 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1694 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1698 bounds
->width
= FONT_WIDTH (f
->display
.x
->font
);
1699 bounds
->height
= FONT_HEIGHT (f
->display
.x
->font
);
1700 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1701 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1708 else if (pix_x
> f
->width
)
1713 else if (pix_y
> f
->height
)
1721 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1723 If the event is a button press, then note that we have grabbed
1727 construct_mouse_click (result
, event
, f
)
1728 struct input_event
*result
;
1729 XButtonEvent
*event
;
1732 /* Make the event type no_event; we'll change that when we decide
1734 result
->kind
= mouse_click
;
1735 result
->code
= event
->button
- Button1
;
1736 result
->timestamp
= event
->time
;
1737 result
->modifiers
= (x_x_to_emacs_modifiers (event
->state
)
1738 | (event
->type
== ButtonRelease
1742 /* Notice if the mouse is still grabbed. */
1743 if (event
->type
== ButtonPress
)
1745 if (! x_mouse_grabbed
)
1746 Vmouse_depressed
= Qt
;
1747 x_mouse_grabbed
|= (1 << event
->button
);
1748 last_mouse_frame
= f
;
1750 else if (event
->type
== ButtonRelease
)
1752 x_mouse_grabbed
&= ~(1 << event
->button
);
1753 if (!x_mouse_grabbed
)
1754 Vmouse_depressed
= Qnil
;
1760 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
, 0);
1761 XFASTINT (result
->x
) = column
;
1762 XFASTINT (result
->y
) = row
;
1763 XSET (result
->frame_or_window
, Lisp_Frame
, f
);
1767 /* Function to report a mouse movement to the mainstream Emacs code.
1768 The input handler calls this.
1770 We have received a mouse movement event, which is given in *event.
1771 If the mouse is over a different glyph than it was last time, tell
1772 the mainstream emacs code by setting mouse_moved. If not, ask for
1773 another motion event, so we can check again the next time it moves. */
1775 note_mouse_movement (frame
, event
)
1777 XMotionEvent
*event
;
1780 last_mouse_movement_time
= event
->time
;
1782 /* Has the mouse moved off the glyph it was on at the last sighting? */
1783 if (event
->x
< last_mouse_glyph
.x
1784 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
1785 || event
->y
< last_mouse_glyph
.y
1786 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
1789 last_mouse_scroll_bar
= Qnil
;
1793 /* It's on the same glyph. Call XQueryPointer so we'll get an
1794 event the next time the mouse moves and we can see if it's
1795 *still* on the same glyph. */
1798 XQueryPointer (event
->display
, event
->window
,
1799 (Window
*) &dummy
, (Window
*) &dummy
,
1800 &dummy
, &dummy
, &dummy
, &dummy
,
1801 (unsigned int *) &dummy
);
1805 static struct scroll_bar
*x_window_to_scroll_bar ();
1806 static void x_scroll_bar_report_motion ();
1808 /* Return the current position of the mouse.
1810 If the mouse movement started in a scroll bar, set *f, *bar_window,
1811 and *part to the frame, window, and scroll bar part that the mouse
1812 is over. Set *x and *y to the portion and whole of the mouse's
1813 position on the scroll bar.
1815 If the mouse movement started elsewhere, set *f to the frame the
1816 mouse is on, *bar_window to nil, and *x and *y to the character cell
1819 Set *time to the server timestamp for the time at which the mouse
1820 was at this position.
1822 Don't store anything if we don't have a valid set of values to report.
1824 This clears the mouse_moved flag, so we can wait for the next mouse
1825 movement. This also calls XQueryPointer, which will cause the
1826 server to give us another MotionNotify when the mouse moves
1830 XTmouse_position (f
, bar_window
, part
, x
, y
, time
)
1832 Lisp_Object
*bar_window
;
1833 enum scroll_bar_part
*part
;
1835 unsigned long *time
;
1841 if (! NILP (last_mouse_scroll_bar
))
1842 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
);
1848 Window dummy_window
;
1852 last_mouse_scroll_bar
= Qnil
;
1854 /* Figure out which root window we're on. */
1855 XQueryPointer (x_current_display
,
1856 DefaultRootWindow (x_current_display
),
1858 /* The root window which contains the pointer. */
1861 /* Trash which we can't trust if the pointer is on
1862 a different screen. */
1865 /* The position on that root window. */
1868 /* More trash we can't trust. */
1871 /* Modifier keys and pointer buttons, about which
1873 (unsigned int *) &dummy
);
1875 /* Now we have a position on the root; find the innermost window
1876 containing the pointer. */
1880 int parent_x
, parent_y
;
1884 if (x_mouse_grabbed
)
1886 /* If mouse was grabbed on a frame, give coords for that frame
1887 even if the mouse is now outside it. */
1888 XTranslateCoordinates (x_current_display
,
1890 /* From-window, to-window. */
1891 root
, FRAME_X_WINDOW (last_mouse_frame
),
1893 /* From-position, to-position. */
1894 root_x
, root_y
, &win_x
, &win_y
,
1898 f1
= last_mouse_frame
;
1904 XTranslateCoordinates (x_current_display
,
1906 /* From-window, to-window. */
1909 /* From-position, to-position. */
1910 root_x
, root_y
, &win_x
, &win_y
,
1923 /* Now we know that:
1924 win is the innermost window containing the pointer
1925 (XTC says it has no child containing the pointer),
1926 win_x and win_y are the pointer's position in it
1927 (XTC did this the last time through), and
1928 parent_x and parent_y are the pointer's position in win's parent.
1929 (They are what win_x and win_y were when win was child.
1930 If win is the root window, it has no parent, and
1931 parent_{x,y} are invalid, but that's okay, because we'll
1932 never use them in that case.) */
1934 /* Is win one of our frames? */
1935 f1
= x_window_to_frame (win
);
1938 /* If not, is it one of our scroll bars? */
1941 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
1945 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1953 /* Ok, we found a frame. Convert from pixels to characters
1954 and store all the values. */
1956 pixel_to_glyph_coords (f1
, win_x
, win_y
, &win_x
, &win_y
,
1957 &last_mouse_glyph
, x_mouse_grabbed
);
1962 XSET (*x
, Lisp_Int
, win_x
);
1963 XSET (*y
, Lisp_Int
, win_y
);
1964 *time
= last_mouse_movement_time
;
1972 #else /* ! defined (HAVE_X11) */
1973 #define XEvent XKeyPressedEvent
1974 #endif /* ! defined (HAVE_X11) */
1976 /* Scroll bar support. */
1978 /* Given an X window ID, find the struct scroll_bar which manages it.
1979 This can be called in GC, so we have to make sure to strip off mark
1981 static struct scroll_bar
*
1982 x_window_to_scroll_bar (window_id
)
1985 Lisp_Object tail
, frame
;
1987 for (tail
= Vframe_list
;
1988 XGCTYPE (tail
) == Lisp_Cons
;
1989 tail
= XCONS (tail
)->cdr
)
1991 Lisp_Object frame
= XCONS (tail
)->car
;
1992 Lisp_Object bar
, condemned
;
1994 /* All elements of Vframe_list should be frames. */
1995 if (XGCTYPE (frame
) != Lisp_Frame
)
1998 /* Scan this frame's scroll bar list for a scroll bar with the
2000 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
2001 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
2002 /* This trick allows us to search both the ordinary and
2003 condemned scroll bar lists with one loop. */
2004 ! GC_NILP (bar
) || (bar
= condemned
,
2007 bar
= XSCROLL_BAR (bar
)->next
)
2008 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
2009 return XSCROLL_BAR (bar
);
2015 /* Open a new X window to serve as a scroll bar, and return the
2016 scroll bar vector for it. */
2017 static struct scroll_bar
*
2018 x_scroll_bar_create (window
, top
, left
, width
, height
)
2019 struct window
*window
;
2020 int top
, left
, width
, height
;
2022 FRAME_PTR frame
= XFRAME (WINDOW_FRAME (window
));
2023 struct scroll_bar
*bar
=
2024 XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2029 XSetWindowAttributes a
;
2031 a
.background_pixel
= frame
->display
.x
->background_pixel
;
2032 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
2033 | ButtonMotionMask
| PointerMotionHintMask
2035 a
.cursor
= x_vertical_scroll_bar_cursor
;
2037 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
2042 XtSetArg (al
[ac
], XtNx
, left
); ac
++;
2043 XtSetArg (al
[ac
], XtNy
, top
); ac
++;
2044 XtSetArg (al
[ac
], XtNwidth
, width
); ac
++;
2045 XtSetArg (al
[ac
], XtNheight
, height
); ac
++;
2046 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
2047 sb_widget
= XtCreateManagedWidget ("box",
2049 frame
->display
.x
->edit_widget
, al
, ac
);
2050 SET_SCROLL_BAR_X_WINDOW
2051 (bar
, sb_widget
->core
.window
);
2053 SET_SCROLL_BAR_X_WINDOW
2055 XCreateWindow (x_current_display
, FRAME_X_WINDOW (frame
),
2057 /* Position and size of scroll bar. */
2058 left
, top
, width
, height
,
2060 /* Border width, depth, class, and visual. */
2061 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
2067 XSET (bar
->window
, Lisp_Window
, window
);
2068 XSET (bar
->top
, Lisp_Int
, top
);
2069 XSET (bar
->left
, Lisp_Int
, left
);
2070 XSET (bar
->width
, Lisp_Int
, width
);
2071 XSET (bar
->height
, Lisp_Int
, height
);
2072 XSET (bar
->start
, Lisp_Int
, 0);
2073 XSET (bar
->end
, Lisp_Int
, 0);
2074 bar
->dragging
= Qnil
;
2076 /* Add bar to its frame's list of scroll bars. */
2077 bar
->next
= FRAME_SCROLL_BARS (frame
);
2079 XSET (FRAME_SCROLL_BARS (frame
), Lisp_Vector
, bar
);
2080 if (! NILP (bar
->next
))
2081 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
2083 XMapWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
2090 /* Draw BAR's handle in the proper position.
2091 If the handle is already drawn from START to END, don't bother
2092 redrawing it, unless REBUILD is non-zero; in that case, always
2093 redraw it. (REBUILD is handy for drawing the handle after expose
2096 Normally, we want to constrain the start and end of the handle to
2097 fit inside its rectangle, but if the user is dragging the scroll bar
2098 handle, we want to let them drag it down all the way, so that the
2099 bar's top is as far down as it goes; otherwise, there's no way to
2100 move to the very end of the buffer. */
2102 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
2103 struct scroll_bar
*bar
;
2107 int dragging
= ! NILP (bar
->dragging
);
2108 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2109 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
2111 /* If the display is already accurate, do nothing. */
2113 && start
== XINT (bar
->start
)
2114 && end
== XINT (bar
->end
))
2120 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar
->width
));
2121 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2122 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2124 /* Make sure the values are reasonable, and try to preserve
2125 the distance between start and end. */
2127 int length
= end
- start
;
2131 else if (start
> top_range
)
2133 end
= start
+ length
;
2137 else if (end
> top_range
&& ! dragging
)
2141 /* Store the adjusted setting in the scroll bar. */
2142 XSET (bar
->start
, Lisp_Int
, start
);
2143 XSET (bar
->end
, Lisp_Int
, end
);
2145 /* Clip the end position, just for display. */
2146 if (end
> top_range
)
2149 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
2150 below top positions, to make sure the handle is always at least
2151 that many pixels tall. */
2152 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2154 /* Draw the empty space above the handle. Note that we can't clear
2155 zero-height areas; that means "clear to end of window." */
2157 XClearArea (x_current_display
, w
,
2159 /* x, y, width, height, and exposures. */
2160 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2161 VERTICAL_SCROLL_BAR_TOP_BORDER
,
2162 inside_width
, start
,
2165 /* Draw the handle itself. */
2166 XFillRectangle (x_current_display
, w
, gc
,
2168 /* x, y, width, height */
2169 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2170 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
2171 inside_width
, end
- start
);
2174 /* Draw the empty space below the handle. Note that we can't
2175 clear zero-height areas; that means "clear to end of window." */
2176 if (end
< inside_height
)
2177 XClearArea (x_current_display
, w
,
2179 /* x, y, width, height, and exposures. */
2180 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
2181 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
2182 inside_width
, inside_height
- end
,
2190 /* Move a scroll bar around on the screen, to accommodate changing
2191 window configurations. */
2193 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2194 struct scroll_bar
*bar
;
2195 int top
, left
, width
, height
;
2201 unsigned int mask
= 0;
2208 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
2209 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
2210 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
2211 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
2214 XConfigureWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
),
2218 XSET (bar
->left
, Lisp_Int
, left
);
2219 XSET (bar
->top
, Lisp_Int
, top
);
2220 XSET (bar
->width
, Lisp_Int
, width
);
2221 XSET (bar
->height
, Lisp_Int
, height
);
2226 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2229 x_scroll_bar_remove (bar
)
2230 struct scroll_bar
*bar
;
2232 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2236 /* Destroy the window. */
2237 XDestroyWindow (x_current_display
, SCROLL_BAR_X_WINDOW (bar
));
2239 /* Disassociate this scroll bar from its window. */
2240 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2245 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2246 that we are displaying PORTION characters out of a total of WHOLE
2247 characters, starting at POSITION. If WINDOW has no scroll bar,
2250 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
2251 struct window
*window
;
2252 int portion
, whole
, position
;
2254 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2255 int top
= XINT (window
->top
);
2256 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2257 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2259 /* Where should this scroll bar be, pixelwise? */
2260 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2261 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2262 int pixel_width
= VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
);
2263 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2265 struct scroll_bar
*bar
;
2267 /* Does the scroll bar exist yet? */
2268 if (NILP (window
->vertical_scroll_bar
))
2269 bar
= x_scroll_bar_create (window
,
2270 pixel_top
, pixel_left
,
2271 pixel_width
, pixel_height
);
2274 /* It may just need to be moved and resized. */
2275 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2276 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2279 /* Set the scroll bar's current state, unless we're currently being
2281 if (NILP (bar
->dragging
))
2284 VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2287 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2290 int start
= ((double) position
* top_range
) / whole
;
2291 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
2293 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2297 XSET (window
->vertical_scroll_bar
, Lisp_Vector
, bar
);
2301 /* The following three hooks are used when we're doing a thorough
2302 redisplay of the frame. We don't explicitly know which scroll bars
2303 are going to be deleted, because keeping track of when windows go
2304 away is a real pain - "Can you say set-window-configuration, boys
2305 and girls?" Instead, we just assert at the beginning of redisplay
2306 that *all* scroll bars are to be removed, and then save a scroll bar
2307 from the fiery pit when we actually redisplay its window. */
2309 /* Arrange for all scroll bars on FRAME to be removed at the next call
2310 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2311 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2313 XTcondemn_scroll_bars (frame
)
2316 /* The condemned list should be empty at this point; if it's not,
2317 then the rest of Emacs isn't using the condemn/redeem/judge
2318 protocol correctly. */
2319 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2322 /* Move them all to the "condemned" list. */
2323 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2324 FRAME_SCROLL_BARS (frame
) = Qnil
;
2327 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2328 Note that WINDOW isn't necessarily condemned at all. */
2330 XTredeem_scroll_bar (window
)
2331 struct window
*window
;
2333 struct scroll_bar
*bar
;
2335 /* We can't redeem this window's scroll bar if it doesn't have one. */
2336 if (NILP (window
->vertical_scroll_bar
))
2339 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2341 /* Unlink it from the condemned list. */
2343 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2345 if (NILP (bar
->prev
))
2347 /* If the prev pointer is nil, it must be the first in one of
2349 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2350 /* It's not condemned. Everything's fine. */
2352 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2353 window
->vertical_scroll_bar
))
2354 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2356 /* If its prev pointer is nil, it must be at the front of
2357 one or the other! */
2361 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2363 if (! NILP (bar
->next
))
2364 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2366 bar
->next
= FRAME_SCROLL_BARS (f
);
2368 XSET (FRAME_SCROLL_BARS (f
), Lisp_Vector
, bar
);
2369 if (! NILP (bar
->next
))
2370 XSET (XSCROLL_BAR (bar
->next
)->prev
, Lisp_Vector
, bar
);
2374 /* Remove all scroll bars on FRAME that haven't been saved since the
2375 last call to `*condemn_scroll_bars_hook'. */
2377 XTjudge_scroll_bars (f
)
2380 Lisp_Object bar
, next
;
2382 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2384 /* Clear out the condemned list now so we won't try to process any
2385 more events on the hapless scroll bars. */
2386 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2388 for (; ! NILP (bar
); bar
= next
)
2390 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2392 x_scroll_bar_remove (b
);
2395 b
->next
= b
->prev
= Qnil
;
2398 /* Now there should be no references to the condemned scroll bars,
2399 and they should get garbage-collected. */
2403 /* Handle an Expose or GraphicsExpose event on a scroll bar.
2405 This may be called from a signal handler, so we have to ignore GC
2408 x_scroll_bar_expose (bar
, event
)
2409 struct scroll_bar
*bar
;
2412 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2413 GC gc
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))->display
.x
->normal_gc
;
2417 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
2419 /* Draw a one-pixel border just inside the edges of the scroll bar. */
2420 XDrawRectangle (x_current_display
, w
, gc
,
2422 /* x, y, width, height */
2423 0, 0, XINT (bar
->width
) - 1, XINT (bar
->height
) - 1);
2425 /* Draw another line to make the extra-thick border on the right. */
2426 XFillRectangle (x_current_display
, w
, gc
,
2428 /* x, y, width, height */
2429 XINT (bar
->width
) - 2, 1, 1, XINT (bar
->height
) - 2);
2434 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2435 is set to something other than no_event, it is enqueued.
2437 This may be called from a signal handler, so we have to ignore GC
2440 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
2441 struct scroll_bar
*bar
;
2443 struct input_event
*emacs_event
;
2445 if (XGCTYPE (bar
->window
) != Lisp_Window
)
2448 emacs_event
->kind
= scroll_bar_click
;
2449 emacs_event
->code
= event
->xbutton
.button
- Button1
;
2450 emacs_event
->modifiers
=
2451 (x_x_to_emacs_modifiers (event
->xbutton
.state
)
2452 | (event
->type
== ButtonRelease
2455 emacs_event
->frame_or_window
= bar
->window
;
2456 emacs_event
->timestamp
= event
->xbutton
.time
;
2458 int internal_height
=
2459 VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2461 VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2462 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
2465 if (y
> top_range
) y
= top_range
;
2467 if (y
< XINT (bar
->start
))
2468 emacs_event
->part
= scroll_bar_above_handle
;
2469 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2470 emacs_event
->part
= scroll_bar_handle
;
2472 emacs_event
->part
= scroll_bar_below_handle
;
2474 /* Just because the user has clicked on the handle doesn't mean
2475 they want to drag it. Lisp code needs to be able to decide
2476 whether or not we're dragging. */
2478 /* If the user has just clicked on the handle, record where they're
2480 if (event
->type
== ButtonPress
2481 && emacs_event
->part
== scroll_bar_handle
)
2482 XSET (bar
->dragging
, Lisp_Int
, y
- XINT (bar
->start
));
2485 /* If the user has released the handle, set it to its final position. */
2486 if (event
->type
== ButtonRelease
2487 && ! NILP (bar
->dragging
))
2489 int new_start
= y
- XINT (bar
->dragging
);
2490 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2492 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2493 bar
->dragging
= Qnil
;
2496 /* Same deal here as the other #if 0. */
2498 /* Clicks on the handle are always reported as occurring at the top of
2500 if (emacs_event
->part
== scroll_bar_handle
)
2501 emacs_event
->x
= bar
->start
;
2503 XSET (emacs_event
->x
, Lisp_Int
, y
);
2505 XSET (emacs_event
->x
, Lisp_Int
, y
);
2508 XSET (emacs_event
->y
, Lisp_Int
, top_range
);
2512 /* Handle some mouse motion while someone is dragging the scroll bar.
2514 This may be called from a signal handler, so we have to ignore GC
2517 x_scroll_bar_note_movement (bar
, event
)
2518 struct scroll_bar
*bar
;
2521 last_mouse_movement_time
= event
->xmotion
.time
;
2524 XSET (last_mouse_scroll_bar
, Lisp_Vector
, bar
);
2526 /* If we're dragging the bar, display it. */
2527 if (! GC_NILP (bar
->dragging
))
2529 /* Where should the handle be now? */
2530 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
2532 if (new_start
!= XINT (bar
->start
))
2534 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2536 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2540 /* Call XQueryPointer so we'll get an event the next time the mouse
2541 moves and we can see *still* on the same position. */
2545 XQueryPointer (event
->xmotion
.display
, event
->xmotion
.window
,
2546 (Window
*) &dummy
, (Window
*) &dummy
,
2547 &dummy
, &dummy
, &dummy
, &dummy
,
2548 (unsigned int *) &dummy
);
2552 /* Return information to the user about the current position of the mouse
2553 on the scroll bar. */
2555 x_scroll_bar_report_motion (f
, bar_window
, part
, x
, y
, time
)
2557 Lisp_Object
*bar_window
;
2558 enum scroll_bar_part
*part
;
2560 unsigned long *time
;
2562 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
2564 Window dummy_window
;
2566 unsigned int dummy_mask
;
2570 /* Get the mouse's position relative to the scroll bar window, and
2572 if (! XQueryPointer (x_current_display
,
2573 SCROLL_BAR_X_WINDOW (bar
),
2575 /* Root, child, root x and root y. */
2576 &dummy_window
, &dummy_window
,
2577 &dummy_coord
, &dummy_coord
,
2579 /* Position relative to scroll bar. */
2582 /* Mouse buttons and modifier keys. */
2588 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2590 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2592 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
2594 if (! NILP (bar
->dragging
))
2595 win_y
-= XINT (bar
->dragging
);
2599 if (win_y
> top_range
)
2602 *f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2603 *bar_window
= bar
->window
;
2605 if (! NILP (bar
->dragging
))
2606 *part
= scroll_bar_handle
;
2607 else if (win_y
< XINT (bar
->start
))
2608 *part
= scroll_bar_above_handle
;
2609 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2610 *part
= scroll_bar_handle
;
2612 *part
= scroll_bar_below_handle
;
2614 XSET (*x
, Lisp_Int
, win_y
);
2615 XSET (*y
, Lisp_Int
, top_range
);
2618 last_mouse_scroll_bar
= Qnil
;
2621 *time
= last_mouse_movement_time
;
2627 /* The screen has been cleared so we may have changed foreground or
2628 background colors, and the scroll bars may need to be redrawn.
2629 Clear out the scroll bars, and ask for expose events, so we can
2632 x_scroll_bar_clear (f
)
2637 for (bar
= FRAME_SCROLL_BARS (f
);
2638 XTYPE (bar
) == Lisp_Vector
;
2639 bar
= XSCROLL_BAR (bar
)->next
)
2640 XClearArea (x_current_display
, SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
2644 /* This processes Expose events from the menubar specific X event
2645 loop in menubar.c. This allows to redisplay the frame if necessary
2646 when handling menubar or popup items. */
2649 process_expose_from_menu (event
)
2656 f
= x_window_to_frame (event
.xexpose
.window
);
2659 if (f
->async_visible
== 0)
2661 f
->async_visible
= 1;
2662 f
->async_iconified
= 0;
2663 SET_FRAME_GARBAGED (f
);
2667 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
2668 event
.xexpose
.x
, event
.xexpose
.y
,
2669 event
.xexpose
.width
, event
.xexpose
.height
);
2674 struct scroll_bar
*bar
2675 = x_window_to_scroll_bar (event
.xexpose
.window
);
2678 x_scroll_bar_expose (bar
, &event
);
2685 /* The main X event-reading loop - XTread_socket. */
2687 /* Timestamp of enter window event. This is only used by XTread_socket,
2688 but we have to put it out here, since static variables within functions
2689 sometimes don't work. */
2690 static Time enter_timestamp
;
2692 /* This holds the state XLookupString needs to implement dead keys
2693 and other tricks known as "compose processing". _X Window System_
2694 says that a portable program can't use this, but Stephen Gildea assures
2695 me that letting the compiler initialize it to zeros will work okay.
2697 This must be defined outside of XTread_socket, for the same reasons
2698 given for enter_timestamp, above. */
2699 static XComposeStatus compose_status
;
2701 /* Communication with window managers. */
2702 Atom Xatom_wm_protocols
;
2704 /* Kinds of protocol things we may receive. */
2705 Atom Xatom_wm_take_focus
;
2706 Atom Xatom_wm_save_yourself
;
2707 Atom Xatom_wm_delete_window
;
2709 /* Other WM communication */
2710 Atom Xatom_wm_configure_denied
; /* When our config request is denied */
2711 Atom Xatom_wm_window_moved
; /* When the WM moves us. */
2713 /* Window manager communication. */
2714 Atom Xatom_wm_change_state
;
2716 /* Record the last 100 characters stored
2717 to help debug the loss-of-chars-during-GC problem. */
2719 short temp_buffer
[100];
2721 /* Read events coming from the X server.
2722 This routine is called by the SIGIO handler.
2723 We return as soon as there are no more events to be read.
2725 Events representing keys are stored in buffer BUFP,
2726 which can hold up to NUMCHARS characters.
2727 We return the number of characters stored into the buffer,
2728 thus pretending to be `read'.
2730 WAITP is nonzero if we should block until input arrives.
2731 EXPECTED is nonzero if the caller knows input is available. */
2734 XTread_socket (sd
, bufp
, numchars
, waitp
, expected
)
2736 register struct input_event
*bufp
;
2737 register int numchars
;
2744 int items_pending
; /* How many items are in the X queue. */
2747 int event_found
= 0;
2751 if (interrupt_input_blocked
)
2753 interrupt_input_pending
= 1;
2757 interrupt_input_pending
= 0;
2761 abort (); /* Don't think this happens. */
2764 /* If available, Xlib uses FIOSNBIO to make the socket
2765 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
2766 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
2767 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
2768 fcntl (fileno (stdin
), F_SETFL
, 0);
2769 #endif /* ! defined (FIOSNBIO) */
2773 if (! (fcntl (fileno (stdin
), F_GETFL
, 0) & O_NDELAY
))
2775 extern int read_alarm_should_throw
;
2776 read_alarm_should_throw
= 1;
2777 XPeekEvent (XDISPLAY
&event
);
2778 read_alarm_should_throw
= 0;
2780 #endif /* HAVE_SELECT */
2783 while (XStuffPending () != 0)
2785 XNextEvent (XDISPLAY
&event
);
2793 if (event
.xclient
.message_type
== Xatom_wm_protocols
2794 && event
.xclient
.format
== 32)
2796 if (event
.xclient
.data
.l
[0] == Xatom_wm_take_focus
)
2798 #ifdef USE_X_TOOLKIT
2799 /* f = x_any_window_to_frame (event.xclient.window); */
2800 f
= x_window_to_frame (event
.xclient
.window
);
2802 f
= x_window_to_frame (event
.xclient
.window
);
2805 x_focus_on_frame (f
);
2806 /* Not certain about handling scroll bars here */
2808 else if (event
.xclient
.data
.l
[0] == Xatom_wm_save_yourself
)
2810 /* Save state modify the WM_COMMAND property to
2811 something which can reinstate us. This notifies
2812 the session manager, who's looking for such a
2813 PropertyNotify. Can restart processing when
2814 a keyboard or mouse event arrives. */
2819 else if (event
.xclient
.data
.l
[0] == Xatom_wm_delete_window
)
2821 struct frame
*f
= x_window_to_frame (event
.xclient
.window
);
2828 bufp
->kind
= delete_window_event
;
2829 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
2837 else if (event
.xclient
.message_type
== Xatom_wm_configure_denied
)
2840 else if (event
.xclient
.message_type
== Xatom_wm_window_moved
)
2843 struct frame
*f
= x_window_to_frame (event
.xclient
.window
);
2845 new_x
= event
.xclient
.data
.s
[0];
2846 new_y
= event
.xclient
.data
.s
[1];
2850 f
->display
.x
->left_pos
= new_x
;
2851 f
->display
.x
->top_pos
= new_y
;
2857 #ifdef NEW_SELECTIONS
2858 case SelectionNotify
:
2859 #ifdef USE_X_TOOLKIT
2860 if (x_window_to_frame (event
.xselection
.requestor
))
2861 x_handle_selection_notify (&event
);
2864 #else /* not USE_X_TOOLKIT */
2865 x_handle_selection_notify (&event
);
2866 #endif /* not USE_X_TOOLKIT */
2868 #endif /* NEW_SELECTIONS */
2870 case SelectionClear
: /* Someone has grabbed ownership. */
2871 #ifdef NEW_SELECTIONS
2873 #ifdef USE_X_TOOLKIT
2874 if (x_window_to_frame (event
.xselectionclear
.window
))
2876 #endif /* USE_X_TOOLKIT */
2877 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
2882 bufp
->kind
= selection_clear_event
;
2883 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
2884 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
2885 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
2890 #ifdef USE_X_TOOLKIT
2894 #endif /* USE_X_TOOLKIT */
2896 #else /* not NEW_SELECTIONS */
2897 x_disown_selection (event
.xselectionclear
.window
,
2898 event
.xselectionclear
.selection
,
2899 event
.xselectionclear
.time
);
2900 #endif /* not NEW_SELECTIONS */
2903 case SelectionRequest
: /* Someone wants our selection. */
2904 #ifdef NEW_SELECTIONS
2906 #ifdef USE_X_TOOLKIT
2907 if (x_window_to_frame (event
.xselectionrequest
.owner
))
2909 #endif /* USE_X_TOOLKIT */
2910 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
2915 bufp
->kind
= selection_request_event
;
2916 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
2917 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
2918 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
2919 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
2920 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
2921 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
2926 #ifdef USE_X_TOOLKIT
2930 #endif /* USE_X_TOOLKIT */
2932 #else /* not NEW_SELECTIONS */
2933 x_answer_selection_request (event
);
2934 #endif /* not NEW_SELECTIONS */
2937 case PropertyNotify
:
2938 #ifdef NEW_SELECTIONS
2939 #ifdef USE_X_TOOLKIT
2940 if (x_any_window_to_frame (event
.xproperty
.window
))
2941 x_handle_property_notify (&event
);
2944 #else /* not USE_X_TOOLKIT */
2945 x_handle_property_notify (&event
);
2946 #endif /* not USE_X_TOOLKIT */
2947 #else /* not NEW_SELECTIONS */
2948 /* If we're being told about a root window property, then it's
2949 a cut buffer change. */
2950 if (event
.xproperty
.window
== ROOT_WINDOW
)
2951 x_invalidate_cut_buffer_cache (&event
.xproperty
);
2953 /* Otherwise, we're probably handling an incremental
2954 selection transmission. */
2957 /* If we were to do this synchronously, there'd be no worry
2958 about re-selecting. */
2959 x_send_incremental (event
);
2961 #endif /* not NEW_SELECTIONS */
2964 case ReparentNotify
:
2965 f
= x_window_to_frame (event
.xreparent
.window
);
2967 f
->display
.x
->parent_desc
= event
.xreparent
.parent
;
2971 f
= x_window_to_frame (event
.xexpose
.window
);
2974 if (f
->async_visible
== 0)
2976 f
->async_visible
= 1;
2977 f
->async_iconified
= 0;
2978 SET_FRAME_GARBAGED (f
);
2982 dumprectangle (x_window_to_frame (event
.xexpose
.window
),
2983 event
.xexpose
.x
, event
.xexpose
.y
,
2984 event
.xexpose
.width
, event
.xexpose
.height
);
2989 struct scroll_bar
*bar
2990 = x_window_to_scroll_bar (event
.xexpose
.window
);
2993 x_scroll_bar_expose (bar
, &event
);
2994 #ifdef USE_X_TOOLKIT
2997 #endif /* USE_X_TOOLKIT */
3001 case GraphicsExpose
: /* This occurs when an XCopyArea's
3002 source area was obscured or not
3004 f
= x_window_to_frame (event
.xgraphicsexpose
.drawable
);
3008 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
3009 event
.xgraphicsexpose
.width
,
3010 event
.xgraphicsexpose
.height
);
3012 #ifdef USE_X_TOOLKIT
3015 #endif /* USE_X_TOOLKIT */
3018 case NoExpose
: /* This occurs when an XCopyArea's
3019 source area was completely
3022 #else /* ! defined (HAVE_X11) */
3024 if (event
.subwindow
!= 0)
3025 break; /* duplicate event */
3026 f
= x_window_to_frame (event
.window
);
3027 if (event
.window
== f
->display
.x
->icon_desc
)
3030 f
->async_iconified
= 1;
3032 if (event
.window
== FRAME_X_WINDOW (f
))
3034 /* Say must check all windows' needs_exposure flags. */
3035 expose_all_windows
= 1;
3036 f
->display
.x
->needs_exposure
= 1;
3037 f
->async_visible
= 1;
3042 if (event
.subwindow
!= 0)
3043 break; /* duplicate event */
3044 f
= x_window_to_frame (event
.window
);
3045 if (event
.window
== f
->display
.x
->icon_desc
)
3050 /* If window already needs full redraw, ignore this rectangle. */
3051 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
3053 /* Put the event on the queue of rectangles to redraw. */
3054 if (enqueue_event (&event
, &x_expose_queue
))
3055 /* If it is full, we can't record the rectangle,
3056 so redraw this entire window. */
3058 /* Say must check all windows' needs_exposure flags. */
3059 expose_all_windows
= 1;
3060 f
->display
.x
->needs_exposure
= 1;
3065 /* This should happen only when we are expecting it,
3066 in x_read_exposes. */
3068 #endif /* ! defined (HAVE_X11) */
3072 f
= x_window_to_frame (event
.xunmap
.window
);
3073 if (f
) /* F may no longer exist if
3074 the frame was deleted. */
3076 /* While a frame is unmapped, display generation is
3077 disabled; you don't want to spend time updating a
3078 display that won't ever be seen. */
3079 f
->async_visible
= 0;
3080 /* The window manager never makes a window invisible
3081 ("withdrawn"); all it does is switch between visible
3082 and iconified. Frames get into the invisible state
3083 only through x_make_frame_invisible. */
3084 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
3085 f
->async_iconified
= 1;
3087 #ifdef USE_X_TOOLKIT
3089 #endif /* USE_X_TOOLKIT */
3093 #ifdef USE_X_TOOLKIT
3094 f
= x_any_window_to_frame (event
.xmap
.window
);
3095 #else /* not USE_X_TOOLKIT */
3096 f
= x_window_to_frame (event
.xmap
.window
);
3097 #endif /* not USE_X_TOOLKIT */
3100 f
->async_visible
= 1;
3101 f
->async_iconified
= 0;
3103 /* wait_reading_process_input will notice this and update
3104 the frame's display structures. */
3105 SET_FRAME_GARBAGED (f
);
3107 #ifdef USE_X_TOOLKIT
3109 #endif /* USE_X_TOOLKIT */
3112 /* Turn off processing if we become fully obscured. */
3113 case VisibilityNotify
:
3116 #else /* ! defined (HAVE_X11) */
3118 f
= x_window_to_frame (event
.window
);
3119 if (event
.window
== f
->display
.x
->icon_desc
)
3120 f
->async_iconified
= 0;
3121 if (event
.window
== FRAME_X_WINDOW (f
))
3122 f
->async_visible
= 0;
3124 #endif /* ! defined (HAVE_X11) */
3128 f
= x_window_to_frame (event
.xkey
.window
);
3132 KeySym keysym
, orig_keysym
;
3133 /* al%imercury@uunet.uu.net says that making this 81 instead of
3134 80 fixed a bug whereby meta chars made his Emacs hang. */
3135 unsigned char copy_buffer
[81];
3139 |= x_emacs_to_x_modifiers (extra_keyboard_modifiers
);
3140 modifiers
= event
.xkey
.state
;
3142 /* This will have to go some day... */
3144 /* make_lispy_event turns chars into control chars.
3145 Don't do it here because XLookupString is too eager. */
3146 event
.xkey
.state
&= ~ControlMask
;
3148 XLookupString (&event
.xkey
, copy_buffer
, 80, &keysym
,
3151 /* Strip off the vendor-specific keysym bit, and take a shot
3152 at recognizing the codes. HP servers have extra keysyms
3153 that fit into the MiscFunctionKey category. */
3154 orig_keysym
= keysym
;
3159 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
3160 || keysym
== XK_Delete
3161 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
3162 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
3164 /* This recognizes the "extended function keys".
3165 It seems there's no cleaner way.
3166 Test IsModifierKey to avoid handling mode_switch
3168 || ((unsigned) (keysym
) >= XK_Select
3169 && (unsigned)(keysym
) < XK_KP_Space
)
3171 #ifdef XK_dead_circumflex
3172 || orig_keysym
== XK_dead_circumflex
3174 #ifdef XK_dead_grave
3175 || orig_keysym
== XK_dead_grave
3177 #ifdef XK_dead_tilde
3178 || orig_keysym
== XK_dead_tilde
3180 #ifdef XK_dead_diaeresis
3181 || orig_keysym
== XK_dead_diaeresis
3183 #ifdef XK_dead_macron
3184 || orig_keysym
== XK_dead_macron
3186 #ifdef XK_dead_degree
3187 || orig_keysym
== XK_dead_degree
3189 #ifdef XK_dead_acute
3190 || orig_keysym
== XK_dead_acute
3192 #ifdef XK_dead_cedilla
3193 || orig_keysym
== XK_dead_cedilla
3195 #ifdef XK_dead_breve
3196 || orig_keysym
== XK_dead_breve
3198 #ifdef XK_dead_ogonek
3199 || orig_keysym
== XK_dead_ogonek
3201 #ifdef XK_dead_caron
3202 || orig_keysym
== XK_dead_caron
3204 #ifdef XK_dead_doubleacute
3205 || orig_keysym
== XK_dead_doubleacute
3207 #ifdef XK_dead_abovedot
3208 || orig_keysym
== XK_dead_abovedot
3210 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
3211 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
3212 || x_is_vendor_fkey (orig_keysym
))
3213 && ! (IsModifierKey (orig_keysym
)
3215 #ifdef XK_Mode_switch
3216 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
3219 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
3221 #endif /* not HAVE_X11R5 */
3224 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3226 temp_buffer
[temp_index
++] = keysym
;
3227 bufp
->kind
= non_ascii_keystroke
;
3228 bufp
->code
= keysym
;
3229 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3230 bufp
->modifiers
= x_x_to_emacs_modifiers (modifiers
);
3231 bufp
->timestamp
= event
.xkey
.time
;
3236 else if (numchars
> nbytes
)
3240 for (i
= 0; i
< nbytes
; i
++)
3242 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3244 temp_buffer
[temp_index
++] = copy_buffer
[i
];
3245 bufp
->kind
= ascii_keystroke
;
3246 bufp
->code
= copy_buffer
[i
];
3247 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3248 bufp
->modifiers
= x_x_to_emacs_modifiers (modifiers
);
3249 bufp
->timestamp
= event
.xkey
.time
;
3263 #else /* ! defined (HAVE_X11) */
3266 register char *where_mapping
;
3268 f
= x_window_to_frame (event
.window
);
3269 /* Ignore keys typed on icon windows. */
3270 if (f
!= 0 && event
.window
== f
->display
.x
->icon_desc
)
3272 where_mapping
= XLookupMapping (&event
, &nbytes
);
3273 /* Nasty fix for arrow keys */
3274 if (!nbytes
&& IsCursorKey (event
.detail
& 0xff))
3276 switch (event
.detail
& 0xff)
3278 case KC_CURSOR_LEFT
:
3279 where_mapping
= "\002";
3281 case KC_CURSOR_RIGHT
:
3282 where_mapping
= "\006";
3285 where_mapping
= "\020";
3287 case KC_CURSOR_DOWN
:
3288 where_mapping
= "\016";
3293 if (numchars
- nbytes
> 0)
3297 for (i
= 0; i
< nbytes
; i
++)
3299 bufp
->kind
= ascii_keystroke
;
3300 bufp
->code
= where_mapping
[i
];
3301 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3302 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3310 #endif /* ! defined (HAVE_X11) */
3314 /* Here's a possible interpretation of the whole
3315 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3316 FocusIn event, you have to get a FocusOut event before you
3317 relinquish the focus. If you haven't received a FocusIn event,
3318 then a mere LeaveNotify is enough to free you. */
3321 f
= x_window_to_frame (event
.xcrossing
.window
);
3323 if (event
.xcrossing
.focus
) /* Entered Window */
3325 /* Avoid nasty pop/raise loops. */
3326 if (f
&& (!(f
->auto_raise
)
3328 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
3330 x_new_focus_frame (f
);
3331 enter_timestamp
= event
.xcrossing
.time
;
3334 else if (f
== x_focus_frame
)
3335 x_new_focus_frame (0);
3336 #ifdef USE_X_TOOLKIT
3338 #endif /* USE_X_TOOLKIT */
3342 f
= x_window_to_frame (event
.xfocus
.window
);
3343 if (event
.xfocus
.detail
!= NotifyPointer
)
3344 x_focus_event_frame
= f
;
3346 x_new_focus_frame (f
);
3347 #ifdef USE_X_TOOLKIT
3349 #endif /* USE_X_TOOLKIT */
3354 f
= x_window_to_frame (event
.xcrossing
.window
);
3356 if (event
.xcrossing
.focus
)
3358 if (! x_focus_event_frame
)
3359 x_new_focus_frame (0);
3361 x_new_focus_frame (f
);
3365 if (f
== x_focus_event_frame
)
3366 x_focus_event_frame
= 0;
3367 if (f
== x_focus_frame
)
3368 x_new_focus_frame (0);
3370 #ifdef USE_X_TOOLKIT
3372 #endif /* USE_X_TOOLKIT */
3376 f
= x_window_to_frame (event
.xfocus
.window
);
3377 if (event
.xfocus
.detail
!= NotifyPointer
3378 && f
== x_focus_event_frame
)
3379 x_focus_event_frame
= 0;
3380 if (f
&& f
== x_focus_frame
)
3381 x_new_focus_frame (0);
3382 #ifdef USE_X_TOOLKIT
3384 #endif /* USE_X_TOOLKIT */
3387 #else /* ! defined (HAVE_X11) */
3390 if ((event
.detail
& 0xFF) == 1)
3391 break; /* Coming from our own subwindow */
3392 if (event
.subwindow
!= 0)
3393 break; /* Entering our own subwindow. */
3396 f
= x_window_to_frame (event
.window
);
3399 x_new_focus_frame (f
);
3404 if ((event
.detail
& 0xFF) == 1)
3405 break; /* Entering our own subwindow */
3406 if (event
.subwindow
!= 0)
3407 break; /* Leaving our own subwindow. */
3410 if (x_focus_frame
== 0
3411 && x_input_frame
!= 0
3412 && x_input_frame
== x_window_to_frame (event
.window
)
3413 && event
.window
== FRAME_X_WINDOW (x_input_frame
))
3418 frame_unhighlight (f
);
3421 #endif /* ! defined (HAVE_X11) */
3426 if (x_mouse_grabbed
)
3427 f
= last_mouse_frame
;
3429 f
= x_window_to_frame (event
.xmotion
.window
);
3431 note_mouse_movement (f
, &event
.xmotion
);
3434 struct scroll_bar
*bar
3435 = x_window_to_scroll_bar (event
.xmotion
.window
);
3438 x_scroll_bar_note_movement (bar
, &event
);
3441 #ifdef USE_X_TOOLKIT
3443 #endif /* USE_X_TOOLKIT */
3446 case ConfigureNotify
:
3447 #ifdef USE_X_TOOLKIT
3448 /* process done in widget.c */
3450 #else /* not USE_X_TOOLKIT */
3451 f
= x_window_to_frame (event
.xconfigure
.window
);
3454 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
3455 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
3457 /* Even if the number of character rows and columns has
3458 not changed, the font size may have changed, so we need
3459 to check the pixel dimensions as well. */
3460 if (columns
!= f
->width
3461 || rows
!= f
->height
3462 || event
.xconfigure
.width
!= f
->display
.x
->pixel_width
3463 || event
.xconfigure
.height
!= f
->display
.x
->pixel_height
)
3465 change_frame_size (f
, rows
, columns
, 0, 1);
3466 SET_FRAME_GARBAGED (f
);
3469 if (! event
.xconfigure
.send_event
)
3474 /* Find the position of the outside upper-left corner of
3475 the window, in the root coordinate system. Don't
3476 refer to the parent window here; we may be processing
3477 this event after the window manager has changed our
3478 parent, but before we have reached the ReparentNotify. */
3479 XTranslateCoordinates (x_current_display
,
3481 /* From-window, to-window. */
3482 f
->display
.x
->window_desc
,
3485 /* From-position, to-position. */
3486 -event
.xconfigure
.border_width
,
3487 -event
.xconfigure
.border_width
,
3492 event
.xconfigure
.x
= win_x
;
3493 event
.xconfigure
.y
= win_y
;
3496 f
->display
.x
->pixel_width
= event
.xconfigure
.width
;
3497 f
->display
.x
->pixel_height
= event
.xconfigure
.height
;
3498 f
->display
.x
->left_pos
= event
.xconfigure
.x
;
3499 f
->display
.x
->top_pos
= event
.xconfigure
.y
;
3501 #endif /* not USE_X_TOOLKIT */
3507 /* If we decide we want to generate an event to be seen
3508 by the rest of Emacs, we put it here. */
3509 struct input_event emacs_event
;
3510 emacs_event
.kind
= no_event
;
3512 f
= x_window_to_frame (event
.xbutton
.window
);
3515 if (!x_focus_frame
|| (f
== x_focus_frame
))
3516 construct_mouse_click (&emacs_event
, &event
, f
);
3520 struct scroll_bar
*bar
=
3521 x_window_to_scroll_bar (event
.xbutton
.window
);
3524 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
3525 #ifdef USE_X_TOOLKIT
3528 f
= x_any_window_to_frame (event
.xbutton
.window
);
3529 if (f
&& event
.type
== ButtonPress
)
3530 construct_menu_click (&emacs_event
,
3533 #endif /* USE_X_TOOLKIT */
3536 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
3538 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
3544 #ifdef USE_X_TOOLKIT
3546 #endif /* USE_X_TOOLKIT */
3550 #else /* ! defined (HAVE_X11) */
3552 case ButtonReleased
:
3553 f
= x_window_to_frame (event
.window
);
3556 if (event
.window
== f
->display
.x
->icon_desc
)
3558 x_make_frame_visible (f
);
3560 if (warp_mouse_on_deiconify
)
3561 XWarpMouse (FRAME_X_WINDOW (f
), 10, 10);
3564 if (event
.window
== FRAME_X_WINDOW (f
))
3570 enqueue_event (&event
, &x_mouse_queue
);
3573 bufp
->kind
= ascii_keystroke
;
3574 bufp
->code
= 'X' & 037; /* C-x */
3575 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3576 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3579 bufp
->kind
= ascii_keystroke
;
3580 bufp
->code
= 0; /* C-@ */
3581 XSET (bufp
->frame_or_window
, Lisp_Frame
, f
);
3582 XSET (bufp
->time
, Lisp_Int
, event
.xkey
.time
);
3589 #endif /* ! defined (HAVE_X11) */
3593 case CirculateNotify
:
3595 case CirculateRequest
:
3598 #endif /* ! defined (HAVE_X11) */
3601 /* Someone has changed the keyboard mapping - update the
3603 switch (event
.xmapping
.request
)
3605 case MappingModifier
:
3606 x_find_modifier_meanings ();
3607 /* This is meant to fall through. */
3608 case MappingKeyboard
:
3609 XRefreshKeyboardMapping (&event
.xmapping
);
3611 #ifdef USE_X_TOOLKIT
3613 #endif /* USE_X_TOOLKIT */
3617 #ifdef USE_X_TOOLKIT
3620 XtDispatchEvent (&event
);
3622 #endif /* USE_X_TOOLKIT */
3629 /* On some systems, an X bug causes Emacs to get no more events
3630 when the window is destroyed. Detect that. */
3631 XNoOp (x_current_display
);
3632 #endif /* X_IO_BUG */
3635 if (expected
&& ! event_found
)
3637 /* AOJ 880406: if select returns true but XPending doesn't, it means that
3638 there is an EOF condition; in other words, that X has died.
3639 Act as if there had been a hangup. */
3640 int fd
= ConnectionNumber (x_current_display
);
3641 SELECT_TYPE mask
, junk1
, junk2
;
3646 EMACS_SET_SECS_USECS (timeout
, 0, 0);
3649 if (0 != select (fd
+ 1, &mask
, &junk1
, &junk2
, &timeout
)
3650 && !XStuffPending ())
3651 kill (getpid (), SIGHUP
);
3653 #endif /* HAVE_SELECT */
3656 if (updating_frame
== 0)
3657 x_do_pending_expose ();
3665 /* Read and process only Expose events
3666 until we get an ExposeCopy event; then return.
3667 This is used in insert/delete line.
3668 We assume input is already blocked. */
3674 XKeyPressedEvent event
;
3678 /* while there are more events*/
3679 XMaskEvent (ExposeWindow
| ExposeRegion
| ExposeCopy
, &event
);
3683 if (event
.subwindow
!= 0)
3684 break; /* duplicate event */
3685 f
= x_window_to_frame (event
.window
);
3686 if (event
.window
== f
->display
.x
->icon_desc
)
3691 if (event
.window
== FRAME_X_WINDOW (f
))
3693 expose_all_windows
= 1;
3694 f
->display
.x
->needs_exposure
= 1;
3700 if (event
.subwindow
!= 0)
3701 break; /* duplicate event */
3702 f
= x_window_to_frame (event
.window
);
3703 if (event
.window
== f
->display
.x
->icon_desc
)
3708 /* If window already needs full redraw, ignore this rectangle. */
3709 if (expose_all_windows
&& f
->display
.x
->needs_exposure
)
3711 /* Put the event on the queue of rectangles to redraw. */
3712 if (enqueue_event (&event
, &x_expose_queue
))
3713 /* If it is full, we can't record the rectangle,
3714 so redraw this entire window. */
3716 /* Say must check all windows' needs_exposure flags. */
3717 expose_all_windows
= 1;
3718 f
->display
.x
->needs_exposure
= 1;
3727 #endif /* HAVE_X11 */
3730 /* Drawing the cursor. */
3733 /* Draw a hollow box cursor. Don't change the inside of the box. */
3739 int left
= CHAR_TO_PIXEL_COL (f
, f
->cursor_x
);
3740 int top
= CHAR_TO_PIXEL_ROW (f
, f
->cursor_y
);
3741 int width
= FONT_WIDTH (f
->display
.x
->font
);
3742 int height
= FONT_HEIGHT (f
->display
.x
->font
);
3745 XDrawRectangle (x_current_display
, FRAME_X_WINDOW (f
),
3746 f
->display
.x
->cursor_gc
,
3747 left
, top
, width
- 1, height
- 1);
3748 #else /* ! defined (HAVE_X11) */
3749 XPixSet (FRAME_X_WINDOW (f
),
3750 left
, top
, width
, 1,
3751 f
->display
.x
->cursor_pixel
);
3753 XPixSet (FRAME_X_WINDOW (f
),
3754 left
, top
, 1, height
,
3755 f
->display
.x
->cursor_pixel
);
3757 XPixSet (FRAME_X_WINDOW (f
),
3758 left
+width
-1, top
, 1, height
,
3759 f
->display
.x
->cursor_pixel
);
3761 XPixSet (FRAME_X_WINDOW (f
),
3762 left
, top
+height
-1, width
, 1,
3763 f
->display
.x
->cursor_pixel
);
3764 #endif /* ! defined (HAVE_X11) */
3767 /* Clear the cursor of frame F to background color,
3768 and mark the cursor as not shown.
3769 This is used when the text where the cursor is
3770 is about to be rewritten. */
3778 if (! FRAME_VISIBLE_P (f
)
3779 || f
->phys_cursor_x
< 0)
3783 x_display_cursor (f
, 0);
3784 #else /* ! defined (HAVE_X11) */
3785 XPixSet (FRAME_X_WINDOW (f
),
3786 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
3787 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
3788 FONT_WIDTH (f
->display
.x
->font
), FONT_HEIGHT (f
->display
.x
->font
),
3789 f
->display
.x
->background_pixel
);
3790 #endif /* ! defined (HAVE_X11) */
3791 f
->phys_cursor_x
= -1;
3794 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
3795 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
3799 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
3806 CHAR_TO_PIXEL_COL (f
, column
),
3807 CHAR_TO_PIXEL_ROW (f
, row
),
3808 &glyph
, 1, highlight
);
3812 x_display_bar_cursor (f
, on
)
3816 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3818 /* This is pointless on invisible frames, and dangerous on garbaged
3819 frames; in the latter case, the frame may be in the midst of
3820 changing its size, and curs_x and curs_y may be off the frame. */
3821 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
3824 if (! on
&& f
->phys_cursor_x
< 0)
3827 /* If we're not updating, then we want to use the current frame's
3828 cursor position, not our local idea of where the cursor ought to be. */
3829 if (f
!= updating_frame
)
3831 curs_x
= FRAME_CURSOR_X (f
);
3832 curs_y
= FRAME_CURSOR_Y (f
);
3835 /* If there is anything wrong with the current cursor state, remove it. */
3836 if (f
->phys_cursor_x
>= 0
3838 || f
->phys_cursor_x
!= curs_x
3839 || f
->phys_cursor_y
!= curs_y
3840 || f
->display
.x
->current_cursor
!= bar_cursor
))
3842 /* Erase the cursor by redrawing the character underneath it. */
3843 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3844 f
->phys_cursor_glyph
,
3845 current_glyphs
->highlight
[f
->phys_cursor_y
]);
3846 f
->phys_cursor_x
= -1;
3849 /* If we now need a cursor in the new place or in the new form, do it so. */
3851 && (f
->phys_cursor_x
< 0
3852 || (f
->display
.x
->current_cursor
!= bar_cursor
)))
3854 f
->phys_cursor_glyph
3855 = ((current_glyphs
->enable
[curs_y
]
3856 && curs_x
< current_glyphs
->used
[curs_y
])
3857 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
3859 XFillRectangle (x_current_display
, FRAME_X_WINDOW (f
),
3860 f
->display
.x
->cursor_gc
,
3861 CHAR_TO_PIXEL_COL (f
, curs_x
),
3862 CHAR_TO_PIXEL_ROW (f
, curs_y
),
3863 1, FONT_HEIGHT (f
->display
.x
->font
));
3865 f
->phys_cursor_x
= curs_x
;
3866 f
->phys_cursor_y
= curs_y
;
3868 f
->display
.x
->current_cursor
= bar_cursor
;
3871 if (updating_frame
!= f
)
3876 /* Turn the displayed cursor of frame F on or off according to ON.
3877 If ON is nonzero, where to put the cursor is specified
3878 by F->cursor_x and F->cursor_y. */
3881 x_display_box_cursor (f
, on
)
3885 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3887 /* This is pointless on invisible frames, and dangerous on garbaged
3888 frames; in the latter case, the frame may be in the midst of
3889 changing its size, and curs_x and curs_y may be off the frame. */
3890 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
3893 /* If cursor is off and we want it off, return quickly. */
3894 if (!on
&& f
->phys_cursor_x
< 0)
3897 /* If we're not updating, then we want to use the current frame's
3898 cursor position, not our local idea of where the cursor ought to be. */
3899 if (f
!= updating_frame
)
3901 curs_x
= FRAME_CURSOR_X (f
);
3902 curs_y
= FRAME_CURSOR_Y (f
);
3905 /* If cursor is currently being shown and we don't want it to be
3906 or it is in the wrong place,
3907 or we want a hollow box and it's not so, (pout!)
3909 if (f
->phys_cursor_x
>= 0
3911 || f
->phys_cursor_x
!= curs_x
3912 || f
->phys_cursor_y
!= curs_y
3913 || (f
->display
.x
->current_cursor
!= hollow_box_cursor
3914 && (f
!= x_highlight_frame
))))
3916 /* Erase the cursor by redrawing the character underneath it. */
3917 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3918 f
->phys_cursor_glyph
,
3919 current_glyphs
->highlight
[f
->phys_cursor_y
]);
3920 f
->phys_cursor_x
= -1;
3923 /* If we want to show a cursor,
3924 or we want a box cursor and it's not so,
3925 write it in the right place. */
3927 && (f
->phys_cursor_x
< 0
3928 || (f
->display
.x
->current_cursor
!= filled_box_cursor
3929 && f
== x_highlight_frame
)))
3931 f
->phys_cursor_glyph
3932 = ((current_glyphs
->enable
[curs_y
]
3933 && curs_x
< current_glyphs
->used
[curs_y
])
3934 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
3936 if (f
!= x_highlight_frame
)
3939 f
->display
.x
->current_cursor
= hollow_box_cursor
;
3943 x_draw_single_glyph (f
, curs_y
, curs_x
,
3944 f
->phys_cursor_glyph
, 2);
3945 f
->display
.x
->current_cursor
= filled_box_cursor
;
3948 f
->phys_cursor_x
= curs_x
;
3949 f
->phys_cursor_y
= curs_y
;
3952 if (updating_frame
!= f
)
3956 x_display_cursor (f
, on
)
3962 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
3963 x_display_box_cursor (f
, on
);
3964 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
3965 x_display_bar_cursor (f
, on
);
3967 /* Those are the only two we have implemented! */
3975 /* Refresh bitmap kitchen sink icon for frame F
3976 when we get an expose event for it. */
3982 /* Normally, the window manager handles this function. */
3983 #else /* ! defined (HAVE_X11) */
3986 if (f
->display
.x
->icon_bitmap_flag
)
3987 XBitmapBitsPut (f
->display
.x
->icon_desc
, 0, 0, sink_width
, sink_height
,
3988 sink_bits
, BlackPixel
, WHITE_PIX_DEFAULT
,
3989 icon_bitmap
, GXcopy
, AllPlanes
);
3992 extern struct frame
*selected_frame
;
3993 struct Lisp_String
*str
;
3994 unsigned char *string
;
3997 = XSTRING (XBUFFER (XWINDOW (f
->selected_window
)->buffer
)->name
)->data
;
3999 if (f
->display
.x
->icon_label
!= string
)
4001 f
->display
.x
->icon_label
= string
;
4002 XChangeWindow (f
->display
.x
->icon_desc
,
4003 XQueryWidth (string
, icon_font_info
->id
) + 10,
4004 icon_font_info
->height
+ 10);
4007 XText (f
->display
.x
->icon_desc
, 5, 5, string
,
4008 str
->size
, icon_font_info
->id
,
4009 BLACK_PIX_DEFAULT
, WHITE_PIX_DEFAULT
);
4012 #endif /* ! defined (HAVE_X11) */
4015 /* Make the x-window of frame F use the gnu icon bitmap. */
4024 if (FRAME_X_WINDOW (f
) == 0)
4030 XCreateBitmapFromData (x_current_display
, FRAME_X_WINDOW (f
),
4031 gnu_bits
, gnu_width
, gnu_height
);
4032 x_wm_set_icon_pixmap (f
, icon_bitmap
);
4033 f
->display
.x
->icon_bitmap_flag
= 1;
4034 #else /* ! defined (HAVE_X11) */
4035 if (f
->display
.x
->icon_desc
)
4037 XClearIconWindow (FRAME_X_WINDOW (f
));
4038 XDestroyWindow (f
->display
.x
->icon_desc
);
4041 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
4042 0, 0, sink_width
, sink_height
,
4043 2, WhitePixmap
, (Pixmap
) NULL
);
4045 if (icon_window
== 0)
4048 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
4049 XSelectInput (icon_window
, ExposeWindow
| UnmapWindow
);
4051 f
->display
.x
->icon_desc
= icon_window
;
4052 f
->display
.x
->icon_bitmap_flag
= 1;
4054 if (icon_bitmap
== 0)
4056 = XStoreBitmap (sink_mask_width
, sink_mask_height
, sink_mask_bits
);
4057 #endif /* ! defined (HAVE_X11) */
4063 /* Make the x-window of frame F use a rectangle with text. */
4066 x_text_icon (f
, icon_name
)
4074 char *X_DefaultValue
;
4078 #define WhitePixel 1
4079 #endif /* WhitePixel */
4082 #define BlackPixel 0
4083 #endif /* BlackPixel */
4084 #endif /* HAVE_X11 */
4086 if (FRAME_X_WINDOW (f
) == 0)
4091 f
->display
.x
->icon_label
= icon_name
;
4093 if (! f
->display
.x
->icon_label
)
4094 f
->display
.x
->icon_label
= " *emacs* ";
4097 XSetIconName (x_current_display
, FRAME_X_WINDOW (f
),
4098 (char *) f
->display
.x
->icon_label
);
4101 f
->display
.x
->icon_bitmap_flag
= 0;
4102 x_wm_set_icon_pixmap (f
, 0);
4103 #else /* ! defined (HAVE_X11) */
4104 if (icon_font_info
== 0)
4106 = XGetFont (XGetDefault (XDISPLAY
4107 (char *) XSTRING (Vinvocation_name
)->data
,
4110 if (f
->display
.x
->icon_desc
)
4112 XClearIconWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4113 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
4117 f
->display
.x
->icon_label
= (unsigned char *) icon_name
;
4119 if (! f
->display
.x
->icon_label
)
4120 f
->display
.x
->icon_label
= XSTRING (f
->name
)->data
;
4122 width
= XStringWidth (f
->display
.x
->icon_label
, icon_font_info
, 0, 0);
4123 icon_window
= XCreateWindow (f
->display
.x
->parent_desc
,
4124 f
->display
.x
->left_pos
,
4125 f
->display
.x
->top_pos
,
4126 width
+ 10, icon_font_info
->height
+ 10,
4127 2, BlackPixmap
, WhitePixmap
);
4129 if (icon_window
== 0)
4132 XSetIconWindow (FRAME_X_WINDOW (f
), icon_window
);
4133 XSelectInput (icon_window
, ExposeWindow
| ExposeRegion
| UnmapWindow
| ButtonPressed
);
4135 f
->display
.x
->icon_desc
= icon_window
;
4136 f
->display
.x
->icon_bitmap_flag
= 0;
4137 f
->display
.x
->icon_label
= 0;
4138 #endif /* ! defined (HAVE_X11) */
4143 /* Handling X errors. */
4145 /* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
4146 X server's connection, or an error reported via the X protocol. */
4149 x_connection_closed ()
4154 shut_down_emacs (0, 1, Qnil
);
4159 /* An X error handler which prints an error message and then kills
4160 Emacs. This is what's normally installed as Xlib's handler for
4163 x_error_quitter (display
, error
)
4169 /* Note that there is no real way portable across R3/R4 to get the
4170 original error handler. */
4172 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
4173 fprintf (stderr
, "X protocol error: %s on protocol request %d\n",
4174 buf
, error
->request_code
);
4177 /* While we're testing Emacs 19, we'll just dump core whenever we
4178 get an X error, so we can figure out why it happened. */
4182 x_connection_closed ();
4185 /* A handler for X IO errors which prints an error message and then
4186 kills Emacs. This is what is always installed as Xlib's handler
4189 x_io_error_quitter (display
)
4192 fprintf (stderr
, "Connection to X server %s lost.\n",
4193 XDisplayName (DisplayString (display
)));
4196 /* While we're testing Emacs 19, we'll just dump core whenever we
4197 get an X error, so we can figure out why it happened. */
4201 x_connection_closed ();
4204 /* A buffer for storing X error messages. */
4205 static char *x_caught_error_message
;
4206 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
4208 /* An X error handler which stores the error message in
4209 x_caught_error_message. This is what's installed when
4210 x_catch_errors is in effect. */
4212 x_error_catcher (display
, error
)
4216 XGetErrorText (display
, error
->error_code
,
4217 x_caught_error_message
, X_CAUGHT_ERROR_MESSAGE_SIZE
);
4221 /* Begin trapping X errors.
4223 After calling this function, X protocol errors no longer cause
4224 Emacs to exit; instead, they are recorded in x_cfc_error_message.
4226 Calling x_check_errors signals an Emacs error if an X error has
4227 occurred since the last call to x_catch_errors or x_check_errors.
4229 Calling x_uncatch_errors resumes the normal error handling. */
4231 void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
4236 /* Make sure any errors from previous requests have been dealt with. */
4237 XSync (x_current_display
, False
);
4239 /* Set up the error buffer. */
4240 x_caught_error_message
4241 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE
);
4242 x_caught_error_message
[0] = '\0';
4244 /* Install our little error handler. */
4245 XHandleError (x_error_catcher
);
4248 /* If any X protocol errors have arrived since the last call to
4249 x_catch_errors or x_check_errors, signal an Emacs error using
4250 sprintf (a buffer, FORMAT, the x error message text) as the text. */
4252 x_check_errors (format
)
4255 /* Make sure to catch any errors incurred so far. */
4256 XSync (x_current_display
, False
);
4258 if (x_caught_error_message
[0])
4260 char buf
[X_CAUGHT_ERROR_MESSAGE_SIZE
+ 56];
4262 sprintf (buf
, format
, x_caught_error_message
);
4263 x_uncatch_errors ();
4271 xfree (x_caught_error_message
);
4272 x_caught_error_message
= 0;
4273 XHandleError (x_error_quitter
);
4277 static unsigned int x_wire_count
;
4280 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
4285 /* Changing the font of the frame. */
4287 /* Set the font of the x-window specified by frame F
4288 to the font named NEWNAME. This is safe to use
4289 even before F has an actual x-window. */
4299 /* A table of all the fonts we have already loaded. */
4300 static struct font_info
*x_font_table
;
4302 /* The current capacity of x_font_table. */
4303 static int x_font_table_size
;
4305 /* The number of fonts actually stored in x_font_table.
4306 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
4307 0 <= n_fonts <= x_font_table_size. */
4311 x_new_font (f
, fontname
)
4313 register char *fontname
;
4316 int n_matching_fonts
;
4317 XFontStruct
*font_info
;
4320 /* Get a list of all the fonts that match this name. Once we
4321 have a list of matching fonts, we compare them against the fonts
4322 we already have by comparing font ids. */
4323 font_names
= (char **) XListFonts (x_current_display
, fontname
,
4324 1024, &n_matching_fonts
);
4325 /* Apparently it doesn't set n_matching_fonts to zero when it can't
4326 find any matches; font_names == 0 is the only clue. */
4328 n_matching_fonts
= 0;
4330 /* Don't just give up if n_matching_fonts is 0.
4331 Apparently there's a bug on Suns: XListFontsWithInfo can
4332 fail to find a font, but XLoadQueryFont may still find it. */
4334 /* See if we've already loaded a matching font. */
4335 already_loaded
= -1;
4336 if (n_matching_fonts
!= 0)
4340 for (i
= 0; i
< n_fonts
; i
++)
4341 for (j
= 0; j
< n_matching_fonts
; j
++)
4342 if (!strcmp (x_font_table
[i
].name
, font_names
[j
]))
4345 fontname
= font_names
[j
];
4351 /* If we have, just return it from the table. */
4352 if (already_loaded
>= 0)
4353 f
->display
.x
->font
= x_font_table
[already_loaded
].font
;
4355 /* Otherwise, load the font and add it to the table. */
4361 /* Try to find a character-cell font in the list. */
4363 /* A laudable goal, but this isn't how to do it. */
4364 for (i
= 0; i
< n_matching_fonts
; i
++)
4365 if (! font_info
[i
].per_char
)
4371 /* See comment above. */
4372 if (n_matching_fonts
!= 0)
4373 fontname
= font_names
[i
];
4375 font
= (XFontStruct
*) XLoadQueryFont (x_current_display
, fontname
);
4378 /* Free the information from XListFonts. */
4379 if (n_matching_fonts
)
4380 XFreeFontNames (font_names
);
4384 /* Do we need to create the table? */
4385 if (x_font_table_size
== 0)
4387 x_font_table_size
= 16;
4389 = (struct font_info
*) xmalloc (x_font_table_size
4390 * sizeof (x_font_table
[0]));
4392 /* Do we need to grow the table? */
4393 else if (n_fonts
>= x_font_table_size
)
4395 x_font_table_size
*= 2;
4397 = (struct font_info
*) xrealloc (x_font_table
,
4399 * sizeof (x_font_table
[0])));
4402 x_font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
4403 bcopy (fontname
, x_font_table
[n_fonts
].name
, strlen (fontname
) + 1);
4404 f
->display
.x
->font
= x_font_table
[n_fonts
++].font
= font
;
4407 /* Now make the frame display the given font. */
4408 if (FRAME_X_WINDOW (f
) != 0)
4410 XSetFont (x_current_display
, f
->display
.x
->normal_gc
,
4411 f
->display
.x
->font
->fid
);
4412 XSetFont (x_current_display
, f
->display
.x
->reverse_gc
,
4413 f
->display
.x
->font
->fid
);
4414 XSetFont (x_current_display
, f
->display
.x
->cursor_gc
,
4415 f
->display
.x
->font
->fid
);
4417 x_set_window_size (f
, 0, f
->width
, f
->height
);
4421 Lisp_Object lispy_name
= build_string (fontname
);
4424 /* Free the information from XListFonts. The data
4425 we actually retain comes from XLoadQueryFont. */
4426 XFreeFontNames (font_names
);
4431 #else /* ! defined (HAVE_X11) */
4432 x_new_font (f
, newname
)
4434 register char *newname
;
4439 temp
= XGetFont (newname
);
4440 if (temp
== (FONT_TYPE
*) 0)
4443 if (f
->display
.x
->font
)
4444 XLoseFont (f
->display
.x
->font
);
4446 f
->display
.x
->font
= temp
;
4448 if (FRAME_X_WINDOW (f
) != 0)
4449 x_set_window_size (f
, 0, f
->width
, f
->height
);
4453 #endif /* ! defined (HAVE_X11) */
4455 x_calc_absolute_position (f
)
4460 int win_x
= 0, win_y
= 0;
4462 /* Find the position of the outside upper-left corner of
4463 the inner window, with respect to the outer window. */
4464 if (f
->display
.x
->parent_desc
!= ROOT_WINDOW
)
4467 XTranslateCoordinates (x_current_display
,
4469 /* From-window, to-window. */
4470 f
->display
.x
->window_desc
,
4471 f
->display
.x
->parent_desc
,
4473 /* From-position, to-position. */
4474 0, 0, &win_x
, &win_y
,
4481 /* Treat negative positions as relative to the leftmost bottommost
4482 position that fits on the screen. */
4483 if (f
->display
.x
->left_pos
< 0)
4484 f
->display
.x
->left_pos
= (x_screen_width
4485 - 2 * f
->display
.x
->border_width
- win_x
4487 + f
->display
.x
->left_pos
);
4489 if (f
->display
.x
->top_pos
< 0)
4490 f
->display
.x
->top_pos
= (x_screen_height
4491 - 2 * f
->display
.x
->border_width
- win_y
4493 + f
->display
.x
->top_pos
);
4495 #else /* ! defined (HAVE_X11) */
4496 WINDOWINFO_TYPE parentinfo
;
4498 XGetWindowInfo (FRAME_X_WINDOW (f
), &parentinfo
);
4500 if (f
->display
.x
->left_pos
< 0)
4501 f
->display
.x
->left_pos
= parentinfo
.width
+ (f
->display
.x
->left_pos
+ 1)
4502 - PIXEL_WIDTH (f
) - 2 * f
->display
.x
->internal_border_width
;
4504 if (f
->display
.x
->top_pos
< 0)
4505 f
->display
.x
->top_pos
= parentinfo
.height
+ (f
->display
.x
->top_pos
+ 1)
4506 - PIXEL_HEIGHT (f
) - 2 * f
->display
.x
->internal_border_width
;
4507 #endif /* ! defined (HAVE_X11) */
4510 x_set_offset (f
, xoff
, yoff
)
4512 register int xoff
, yoff
;
4514 f
->display
.x
->top_pos
= yoff
;
4515 f
->display
.x
->left_pos
= xoff
;
4516 x_calc_absolute_position (f
);
4519 #ifdef USE_X_TOOLKIT
4520 XMoveWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
),
4521 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
4522 #else /* not USE_X_TOOLKIT */
4523 XMoveWindow (XDISPLAY
FRAME_X_WINDOW (f
),
4524 f
->display
.x
->left_pos
, f
->display
.x
->top_pos
);
4525 #endif /* not USE_X_TOOLKIT */
4527 x_wm_set_size_hint (f
, 0, 1, xoff
, yoff
);
4528 #endif /* ! defined (HAVE_X11) */
4532 /* Call this to change the size of frame F's x-window.
4533 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
4534 for this size change and subsequent size changes.
4535 Otherwise we leave the window gravity unchanged. */
4537 x_set_window_size (f
, change_gravity
, cols
, rows
)
4542 int pixelwidth
, pixelheight
;
4545 #ifdef USE_X_TOOLKIT
4547 EmacsFrameSetCharSize (f
->display
.x
->edit_widget
, cols
, rows
);
4550 #else /* not USE_X_TOOLKIT */
4554 check_frame_size (f
, &rows
, &cols
);
4555 f
->display
.x
->vertical_scroll_bar_extra
4556 = (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
4557 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f
)
4559 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
4560 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
4563 x_wm_set_size_hint (f
, 0, change_gravity
, 0, 0);
4564 #endif /* ! defined (HAVE_X11) */
4565 XChangeWindowSize (FRAME_X_WINDOW (f
), pixelwidth
, pixelheight
);
4567 /* Now, strictly speaking, we can't be sure that this is accurate,
4568 but the window manager will get around to dealing with the size
4569 change request eventually, and we'll hear how it went when the
4570 ConfigureNotify event gets here.
4572 We could just not bother storing any of this information here,
4573 and let the ConfigureNotify event set everything up, but that
4574 might be kind of confusing to the lisp code, since size changes
4575 wouldn't be reported in the frame parameters until some random
4576 point in the future when the ConfigureNotify event arrives. */
4577 change_frame_size (f
, rows
, cols
, 0, 0);
4578 PIXEL_WIDTH (f
) = pixelwidth
;
4579 PIXEL_HEIGHT (f
) = pixelheight
;
4581 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4582 receive in the ConfigureNotify event; if we get what we asked
4583 for, then the event won't cause the screen to become garbaged, so
4584 we have to make sure to do it here. */
4585 SET_FRAME_GARBAGED (f
);
4589 #endif /* not USE_X_TOOLKIT */
4593 x_set_resize_hint (f
)
4596 XSetResizeHint (FRAME_X_WINDOW (f
),
4597 2 * f
->display
.x
->internal_border_width
,
4598 2 * f
->display
.x
->internal_border_width
,
4599 FONT_WIDTH (f
->display
.x
->font
),
4600 FONT_HEIGHT (f
->display
.x
->font
));
4602 #endif /* HAVE_X11 */
4604 /* Mouse warping, focus shifting, raising and lowering. */
4606 x_set_mouse_position (f
, x
, y
)
4612 #if 0 /* Let the user ask for this if he wants it. */
4616 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->display
.x
->font
) / 2;
4617 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + FONT_HEIGHT (f
->display
.x
->font
) / 2;
4619 if (pix_x
< 0) pix_x
= 0;
4620 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
4622 if (pix_y
< 0) pix_y
= 0;
4623 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
4627 XWarpMousePointer (FRAME_X_WINDOW (f
), pix_x
, pix_y
);
4632 x_focus_on_frame (f
)
4635 #if 0 /* This proves to be unpleasant. */
4639 /* I don't think that the ICCCM allows programs to do things like this
4640 without the interaction of the window manager. Whatever you end up
4641 doing with this code, do it to x_unfocus_frame too. */
4642 XSetInputFocus (x_current_display
, FRAME_X_WINDOW (f
),
4643 RevertToPointerRoot
, CurrentTime
);
4651 /* Look at the remarks in x_focus_on_frame. */
4652 if (x_focus_frame
== f
)
4653 XSetInputFocus (x_current_display
, PointerRoot
,
4654 RevertToPointerRoot
, CurrentTime
);
4658 #endif /* ! defined (HAVE_X11) */
4660 /* Raise frame F. */
4665 if (f
->async_visible
)
4668 #ifdef USE_X_TOOLKIT
4669 XRaiseWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
));
4670 #else /* not USE_X_TOOLKIT */
4671 XRaiseWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4672 #endif /* not USE_X_TOOLKIT */
4678 /* Lower frame F. */
4683 if (f
->async_visible
)
4686 #ifdef USE_X_TOOLKIT
4687 XLowerWindow (XDISPLAY
XtWindow (f
->display
.x
->widget
));
4688 #else /* not USE_X_TOOLKIT */
4689 XLowerWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4690 #endif /* not USE_X_TOOLKIT */
4697 XTframe_raise_lower (f
, raise
)
4708 /* Change from withdrawn state to mapped state. */
4710 x_make_frame_visible (f
)
4717 if (! FRAME_VISIBLE_P (f
))
4720 if (! EQ (Vx_no_window_manager
, Qt
))
4721 x_wm_set_window_state (f
, NormalState
);
4722 #ifdef USE_X_TOOLKIT
4723 XtPopup (f
->display
.x
->widget
, XtGrabNone
);
4724 #else /* not USE_X_TOOLKIT */
4725 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4726 #endif /* not USE_X_TOOLKIT */
4727 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
4728 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
4729 #else /* ! defined (HAVE_X11) */
4730 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4731 if (f
->display
.x
->icon_desc
!= 0)
4732 XUnmapWindow (f
->display
.x
->icon_desc
);
4734 /* Handled by the MapNotify event for X11 */
4735 f
->async_visible
= 1;
4736 f
->async_iconified
= 0;
4738 /* NOTE: this may cause problems for the first frame. */
4740 #endif /* ! defined (HAVE_X11) */
4748 /* Change from mapped state to withdrawn state. */
4750 x_make_frame_invisible (f
)
4755 /* Don't keep the highlight on an invisible frame. */
4756 if (x_highlight_frame
== f
)
4757 x_highlight_frame
= 0;
4759 if (! f
->async_visible
&& ! f
->async_iconified
)
4766 #ifdef USE_X_TOOLKIT
4767 if (! XWithdrawWindow (x_current_display
, XtWindow (f
->display
.x
->widget
),
4768 DefaultScreen (x_current_display
)))
4769 #else /* not USE_X_TOOLKIT */
4770 if (! XWithdrawWindow (x_current_display
, FRAME_X_WINDOW (f
),
4771 DefaultScreen (x_current_display
)))
4772 #endif /* not USE_X_TOOLKIT */
4774 UNBLOCK_INPUT_RESIGNAL
;
4775 error ("can't notify window manager of window withdrawal");
4778 #else /* ! defined (HAVE_X11R4) */
4781 /* Tell the window manager what we're going to do. */
4782 if (! EQ (Vx_no_window_manager
, Qt
))
4786 unmap
.xunmap
.type
= UnmapNotify
;
4787 #ifdef USE_X_TOOLKIT
4788 unmap
.xunmap
.window
= XtWindow (f
->display
.x
->widget
);
4789 #else /* not USE_X_TOOLKIT */
4790 unmap
.xunmap
.window
= FRAME_X_WINDOW (f
);
4791 #endif /* not USE_X_TOOLKIT */
4792 unmap
.xunmap
.event
= DefaultRootWindow (x_current_display
);
4793 unmap
.xunmap
.from_configure
= False
;
4794 if (! XSendEvent (x_current_display
,
4795 DefaultRootWindow (x_current_display
),
4797 SubstructureRedirectMask
|SubstructureNotifyMask
,
4800 UNBLOCK_INPUT_RESIGNAL
;
4801 error ("can't notify window manager of withdrawal");
4805 /* Unmap the window ourselves. Cheeky! */
4806 #ifdef USE_X_TOOLKIT
4807 XUnmapWindow (x_current_display
, XtWindow (f
->display
.x
->widget
));
4808 #else /* not USE_X_TOOLKIT */
4809 XUnmapWindow (x_current_display
, FRAME_X_WINDOW (f
));
4810 #endif /* not USE_X_TOOLKIT */
4811 #else /* ! defined (HAVE_X11) */
4813 XUnmapWindow (FRAME_X_WINDOW (f
));
4814 f
->async_visible
= 0; /* Handled by the UnMap event for X11 */
4815 if (f
->display
.x
->icon_desc
!= 0)
4816 XUnmapWindow (f
->display
.x
->icon_desc
);
4818 #endif /* ! defined (HAVE_X11) */
4819 #endif /* ! defined (HAVE_X11R4) */
4825 /* Change window state from mapped to iconified. */
4833 /* Don't keep the highlight on an invisible frame. */
4834 if (x_highlight_frame
== f
)
4835 x_highlight_frame
= 0;
4837 if (f
->async_iconified
)
4840 #ifdef USE_X_TOOLKIT
4842 result
= XIconifyWindow (x_current_display
,
4843 XtWindow (f
->display
.x
->widget
),
4844 DefaultScreen (x_current_display
));
4848 error ("Can't notify window manager of iconification.");
4850 f
->async_iconified
= 1;
4855 #else /* not USE_X_TOOLKIT */
4860 /* Since we don't know which revision of X we're running, we'll use both
4861 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
4863 /* X11R4: send a ClientMessage to the window manager using the
4864 WM_CHANGE_STATE type. */
4868 message
.xclient
.window
= FRAME_X_WINDOW (f
);
4869 message
.xclient
.type
= ClientMessage
;
4870 message
.xclient
.message_type
= Xatom_wm_change_state
;
4871 message
.xclient
.format
= 32;
4872 message
.xclient
.data
.l
[0] = IconicState
;
4874 if (! XSendEvent (x_current_display
,
4875 DefaultRootWindow (x_current_display
),
4877 SubstructureRedirectMask
| SubstructureNotifyMask
,
4880 UNBLOCK_INPUT_RESIGNAL
;
4881 error ("Can't notify window manager of iconification.");
4885 /* X11R3: set the initial_state field of the window manager hints to
4887 x_wm_set_window_state (f
, IconicState
);
4889 if (!FRAME_VISIBLE_P (f
))
4891 /* If the frame was withdrawn, before, we must map it. */
4892 XMapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4893 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
4894 XMapSubwindows (x_current_display
, FRAME_X_WINDOW (f
));
4897 f
->async_iconified
= 1;
4898 #else /* ! defined (HAVE_X11) */
4899 XUnmapWindow (XDISPLAY
FRAME_X_WINDOW (f
));
4901 f
->async_visible
= 0; /* Handled in the UnMap event for X11. */
4902 if (f
->display
.x
->icon_desc
!= 0)
4904 XMapWindow (XDISPLAY f
->display
.x
->icon_desc
);
4907 #endif /* ! defined (HAVE_X11) */
4911 #endif /* not USE_X_TOOLKIT */
4914 /* Destroy the X window of frame F. */
4916 x_destroy_window (f
)
4921 if (f
->display
.x
->icon_desc
!= 0)
4922 XDestroyWindow (XDISPLAY f
->display
.x
->icon_desc
);
4923 XDestroyWindow (XDISPLAY f
->display
.x
->window_desc
);
4924 #ifdef USE_X_TOOLKIT
4925 XtDestroyWidget (f
->display
.x
->widget
);
4926 #endif /* USE_X_TOOLKIT */
4928 free_frame_faces (f
);
4931 xfree (f
->display
.x
);
4933 if (f
== x_focus_frame
)
4935 if (f
== x_highlight_frame
)
4936 x_highlight_frame
= 0;
4941 /* Manage event queues for X10. */
4945 /* Manage event queues.
4947 This code is only used by the X10 support.
4949 We cannot leave events in the X queue and get them when we are ready
4950 because X does not provide a subroutine to get only a certain kind
4951 of event but not block if there are no queued events of that kind.
4953 Therefore, we must examine events as they come in and copy events
4954 of certain kinds into our private queues.
4956 All ExposeRegion events are put in x_expose_queue.
4957 All ButtonPress and ButtonRelease events are put in x_mouse_queue. */
4960 /* Write the event *P_XREP into the event queue *QUEUE.
4961 If the queue is full, do nothing, but return nonzero. */
4964 enqueue_event (p_xrep
, queue
)
4965 register XEvent
*p_xrep
;
4966 register struct event_queue
*queue
;
4968 int newindex
= queue
->windex
+ 1;
4969 if (newindex
== EVENT_BUFFER_SIZE
)
4971 if (newindex
== queue
->rindex
)
4973 queue
->xrep
[queue
->windex
] = *p_xrep
;
4974 queue
->windex
= newindex
;
4978 /* Fetch the next event from queue *QUEUE and store it in *P_XREP.
4979 If *QUEUE is empty, do nothing and return 0. */
4982 dequeue_event (p_xrep
, queue
)
4983 register XEvent
*p_xrep
;
4984 register struct event_queue
*queue
;
4986 if (queue
->windex
== queue
->rindex
)
4988 *p_xrep
= queue
->xrep
[queue
->rindex
++];
4989 if (queue
->rindex
== EVENT_BUFFER_SIZE
)
4994 /* Return the number of events buffered in *QUEUE. */
4997 queue_event_count (queue
)
4998 register struct event_queue
*queue
;
5000 int tem
= queue
->windex
- queue
->rindex
;
5003 return EVENT_BUFFER_SIZE
+ tem
;
5006 /* Return nonzero if mouse input is pending. */
5009 mouse_event_pending_p ()
5011 return queue_event_count (&x_mouse_queue
);
5013 #endif /* HAVE_X11 */
5015 /* Setting window manager hints. */
5019 /* Record the gravity used previously, in case CHANGE_GRAVITY is 0. */
5020 static int previous_gravity
;
5022 /* SPEC_X and SPEC_Y are the specified positions.
5023 We look only at their sign, to decide the gravity.
5024 If CHANGE_GRAVITY is 0, we ignore SPEC_X and SPEC_Y
5025 and leave the gravity unchanged. */
5027 x_wm_set_size_hint (f
, prompting
, change_gravity
, spec_x
, spec_y
)
5033 XSizeHints size_hints
;
5035 #ifdef USE_X_TOOLKIT
5036 Window window
= XtWindow (f
->display
.x
->widget
);
5037 #else /* not USE_X_TOOLKIT */
5038 Window window
= FRAME_X_WINDOW (f
);
5039 #endif /* not USE_X_TOOLKIT */
5041 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
5043 flexlines
= f
->height
;
5045 size_hints
.x
= f
->display
.x
->left_pos
;
5046 size_hints
.y
= f
->display
.x
->top_pos
;
5047 size_hints
.height
= PIXEL_HEIGHT (f
);
5048 size_hints
.width
= PIXEL_WIDTH (f
);
5049 size_hints
.width_inc
= FONT_WIDTH (f
->display
.x
->font
);
5050 size_hints
.height_inc
= FONT_HEIGHT (f
->display
.x
->font
);
5052 size_hints
.max_width
= x_screen_width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
5053 size_hints
.max_height
= x_screen_height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
5056 int base_width
, base_height
;
5058 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
5059 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
5062 int min_rows
= 0, min_cols
= 0;
5063 check_frame_size (f
, &min_rows
, &min_cols
);
5065 /* The window manager uses the base width hints to calculate the
5066 current number of rows and columns in the frame while
5067 resizing; min_width and min_height aren't useful for this
5068 purpose, since they might not give the dimensions for a
5069 zero-row, zero-column frame.
5071 We use the base_width and base_height members if we have
5072 them; otherwise, we set the min_width and min_height members
5073 to the size for a zero x zero frame. */
5076 size_hints
.flags
|= PBaseSize
;
5077 size_hints
.base_width
= base_width
;
5078 size_hints
.base_height
= base_height
;
5079 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
5080 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
5082 size_hints
.min_width
= base_width
;
5083 size_hints
.min_height
= base_height
;
5090 size_hints
.flags
|= prompting
;
5093 XSizeHints hints
; /* Sometimes I hate X Windows... */
5095 if (XGetNormalHints (x_current_display
, window
, &hints
) == 0)
5097 if (hints
.flags
& PSize
)
5098 size_hints
.flags
|= PSize
;
5099 if (hints
.flags
& PPosition
)
5100 size_hints
.flags
|= PPosition
;
5101 if (hints
.flags
& USPosition
)
5102 size_hints
.flags
|= USPosition
;
5103 if (hints
.flags
& USSize
)
5104 size_hints
.flags
|= USSize
;
5106 #if defined (PWinGravity)
5109 switch (((spec_x
< 0) << 1) + (spec_y
< 0))
5112 size_hints
.win_gravity
= NorthWestGravity
;
5115 size_hints
.win_gravity
= NorthEastGravity
;
5118 size_hints
.win_gravity
= SouthWestGravity
;
5121 size_hints
.win_gravity
= SouthEastGravity
;
5124 previous_gravity
= size_hints
.win_gravity
;
5127 size_hints
.win_gravity
= previous_gravity
;
5129 size_hints
.flags
|= PWinGravity
;
5130 #endif /* PWinGravity */
5133 XSetWMNormalHints (x_current_display
, window
, &size_hints
);
5135 XSetNormalHints (x_current_display
, window
, &size_hints
);
5139 /* Used for IconicState or NormalState */
5140 x_wm_set_window_state (f
, state
)
5144 #ifdef USE_X_TOOLKIT
5145 Window window
= XtWindow (f
->display
.x
->widget
);
5146 #else /* not USE_X_TOOLKIT */
5147 Window window
= FRAME_X_WINDOW (f
);
5148 #endif /* not USE_X_TOOLKIT */
5150 f
->display
.x
->wm_hints
.flags
|= StateHint
;
5151 f
->display
.x
->wm_hints
.initial_state
= state
;
5153 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
5156 x_wm_set_icon_pixmap (f
, icon_pixmap
)
5160 Window window
= FRAME_X_WINDOW (f
);
5164 f
->display
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
5165 f
->display
.x
->wm_hints
.flags
|= IconPixmapHint
;
5168 f
->display
.x
->wm_hints
.flags
&= ~IconPixmapHint
;
5170 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
5173 x_wm_set_icon_position (f
, icon_x
, icon_y
)
5177 Window window
= FRAME_X_WINDOW (f
);
5179 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
5180 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
5181 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
5183 XSetWMHints (x_current_display
, window
, &f
->display
.x
->wm_hints
);
5187 /* Initialization. */
5189 #ifdef USE_X_TOOLKIT
5190 static XrmOptionDescRec emacs_options
[] = {
5191 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
5192 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
5194 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
5195 XrmoptionSepArg
, NULL
},
5196 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
5198 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5199 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5200 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
5201 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5202 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
5203 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
5204 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
5206 #endif /* USE_X_TOOLKIT */
5209 x_term_init (display_name
)
5216 #ifndef F_SETOWN_BUG
5218 extern int old_fcntl_owner
;
5219 #endif /* ! defined (F_SETOWN) */
5220 #endif /* F_SETOWN_BUG */
5222 x_focus_frame
= x_highlight_frame
= 0;
5224 #ifdef USE_X_TOOLKIT
5225 argv
= (char **) XtMalloc (3 * sizeof (char *));
5227 argv
[1] = "-display";
5228 argv
[2] = display_name
;
5230 Xt_app_shell
= XtAppInitialize (&Xt_app_con
, "Emacs",
5231 emacs_options
, XtNumber (emacs_options
),
5235 x_current_display
= XtDisplay (Xt_app_shell
);
5237 #else /* not USE_X_TOOLKIT */
5238 x_current_display
= XOpenDisplay (display_name
);
5239 #endif /* not USE_X_TOOLKIT */
5240 if (x_current_display
== 0)
5241 fatal ("X server %s not responding.\n\
5242 Check the DISPLAY environment variable or use \"-d\"\n",
5248 XSetAfterFunction (x_current_display
, x_trace_wire
);
5250 hostname
= get_system_name ();
5251 x_id_name
= (char *) xmalloc (XSTRING (Vinvocation_name
)->size
5254 sprintf (x_id_name
, "%s@%s", XSTRING (Vinvocation_name
)->data
, hostname
);
5257 /* Figure out which modifier bits mean what. */
5258 x_find_modifier_meanings ();
5260 /* Get the scroll bar cursor. */
5261 x_vertical_scroll_bar_cursor
5262 = XCreateFontCursor (x_current_display
, XC_sb_v_double_arrow
);
5265 /* Watch for PropertyNotify events on the root window; we use them
5266 to figure out when to invalidate our cache of the cut buffers. */
5267 x_watch_cut_buffer_cache ();
5270 if (ConnectionNumber (x_current_display
) != 0)
5271 change_keyboard_wait_descriptor (ConnectionNumber (x_current_display
));
5272 change_input_fd (ConnectionNumber (x_current_display
));
5274 #endif /* ! defined (HAVE_X11) */
5276 #ifndef F_SETOWN_BUG
5278 old_fcntl_owner
= fcntl (ConnectionNumber (x_current_display
), F_GETOWN
, 0);
5279 #ifdef F_SETOWN_SOCK_NEG
5280 /* stdin is a socket here */
5281 fcntl (ConnectionNumber (x_current_display
), F_SETOWN
, -getpid ());
5282 #else /* ! defined (F_SETOWN_SOCK_NEG) */
5283 fcntl (ConnectionNumber (x_current_display
), F_SETOWN
, getpid ());
5284 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
5285 #endif /* ! defined (F_SETOWN) */
5286 #endif /* F_SETOWN_BUG */
5290 #endif /* ! defined (SIGIO) */
5292 expose_all_windows
= 0;
5294 clear_frame_hook
= XTclear_frame
;
5295 clear_end_of_line_hook
= XTclear_end_of_line
;
5296 ins_del_lines_hook
= XTins_del_lines
;
5297 change_line_highlight_hook
= XTchange_line_highlight
;
5298 insert_glyphs_hook
= XTinsert_glyphs
;
5299 write_glyphs_hook
= XTwrite_glyphs
;
5300 delete_glyphs_hook
= XTdelete_glyphs
;
5301 ring_bell_hook
= XTring_bell
;
5302 reset_terminal_modes_hook
= XTreset_terminal_modes
;
5303 set_terminal_modes_hook
= XTset_terminal_modes
;
5304 update_begin_hook
= XTupdate_begin
;
5305 update_end_hook
= XTupdate_end
;
5306 set_terminal_window_hook
= XTset_terminal_window
;
5307 read_socket_hook
= XTread_socket
;
5308 cursor_to_hook
= XTcursor_to
;
5309 reassert_line_highlight_hook
= XTreassert_line_highlight
;
5310 mouse_position_hook
= XTmouse_position
;
5311 frame_rehighlight_hook
= XTframe_rehighlight
;
5312 frame_raise_lower_hook
= XTframe_raise_lower
;
5313 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
5314 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
5315 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
5316 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
5318 scroll_region_ok
= 1; /* we'll scroll partial frames */
5319 char_ins_del_ok
= 0; /* just as fast to write the line */
5320 line_ins_del_ok
= 1; /* we'll just blt 'em */
5321 fast_clear_end_of_line
= 1; /* X does this well */
5322 memory_below_frame
= 0; /* we don't remember what scrolls
5326 /* Try to use interrupt input; if we can't, then start polling. */
5327 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
5329 /* Note that there is no real way portable across R3/R4 to get the
5330 original error handler. */
5331 XHandleError (x_error_quitter
);
5332 XHandleIOError (x_io_error_quitter
);
5334 /* Disable Window Change signals; they are handled by X events. */
5336 signal (SIGWINCH
, SIG_DFL
);
5337 #endif /* ! defined (SIGWINCH) */
5339 signal (SIGPIPE
, x_connection_closed
);
5345 staticpro (&last_mouse_scroll_bar
);
5346 last_mouse_scroll_bar
= Qnil
;
5348 #endif /* ! defined (HAVE_X11) */
5349 #endif /* ! defined (HAVE_X_WINDOWS) */