1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 93, 94, 95, 96, 97, 98, 1999, 2000, 01, 02, 2003
3 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* New display code by Gerd Moellmann <gerd@gnu.org>. */
23 /* Xt features made by Fred Pierresteguy. */
27 /* On 4.3 these lose if they come after xterm.h. */
28 /* Putting these at the beginning seems to be standard for other .c files. */
36 #include "blockinput.h"
38 /* Need syssignal.h for various externs and definitions that may be required
39 by some configurations for calls to signal later in this source file. */
40 #include "syssignal.h"
42 /* This may include sys/types.h, and that somehow loses
43 if this is not done before the other system files. */
45 #include <X11/cursorfont.h>
47 /* Load sys/types.h if not already loaded.
48 In some systems loading it twice is suicidal. */
50 #include <sys/types.h>
54 #include <sys/ioctl.h>
55 #endif /* ! defined (BSD_SYSTEM) */
60 #ifndef INCLUDED_FCNTL
67 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
68 /* #include <sys/param.h> */
74 #include "dispextern.h"
76 #include "termhooks.h"
84 #include "intervals.h"
90 #include <X11/Shell.h>
93 #ifdef HAVE_SYS_TIME_H
105 extern int xlwmenu_window_p
P_ ((Widget w
, Window window
));
106 extern void xlwmenu_redisplay
P_ ((Widget
));
109 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
111 extern void free_frame_menubar
P_ ((struct frame
*));
112 extern struct frame
*x_menubar_window_to_frame
P_ ((struct x_display_info
*,
117 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
119 extern void _XEditResCheckMessages ();
120 #endif /* not NO_EDITRES */
122 /* Include toolkit specific headers for the scroll bar widget. */
124 #ifdef USE_TOOLKIT_SCROLL_BARS
125 #if defined USE_MOTIF
126 #include <Xm/Xm.h> /* for LESSTIF_VERSION */
127 #include <Xm/ScrollBar.h>
128 #else /* !USE_MOTIF i.e. use Xaw */
131 #include <X11/Xaw3d/Simple.h>
132 #include <X11/Xaw3d/Scrollbar.h>
133 #define ARROW_SCROLLBAR
134 #define XAW_ARROW_SCROLLBARS
135 #include <X11/Xaw3d/ScrollbarP.h>
136 #else /* !HAVE_XAW3D */
137 #include <X11/Xaw/Simple.h>
138 #include <X11/Xaw/Scrollbar.h>
139 #endif /* !HAVE_XAW3D */
141 #define XtNpickTop "pickTop"
142 #endif /* !XtNpickTop */
143 #endif /* !USE_MOTIF */
144 #endif /* USE_TOOLKIT_SCROLL_BARS */
146 #endif /* USE_X_TOOLKIT */
148 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
149 #define x_any_window_to_frame x_window_to_frame
150 #define x_top_window_to_frame x_window_to_frame
155 #ifndef XtNinitialState
156 #define XtNinitialState "initialState"
160 #define abs(x) ((x) < 0 ? -(x) : (x))
162 /* Default to using XIM if available. */
166 int use_xim
= 0; /* configure --without-xim */
171 /* Non-nil means Emacs uses toolkit scroll bars. */
173 Lisp_Object Vx_toolkit_scroll_bars
;
175 /* Non-zero means that a HELP_EVENT has been generated since Emacs
178 static int any_help_event_p
;
180 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
181 static Lisp_Object last_window
;
183 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
185 int x_use_underline_position_properties
;
187 /* This is a chain of structures for all the X displays currently in
190 struct x_display_info
*x_display_list
;
192 /* This is a list of cons cells, each of the form (NAME
193 . FONT-LIST-CACHE), one for each element of x_display_list and in
194 the same order. NAME is the name of the frame. FONT-LIST-CACHE
195 records previous values returned by x-list-fonts. */
197 Lisp_Object x_display_name_list
;
199 /* Frame being updated by update_frame. This is declared in term.c.
200 This is set by update_begin and looked at by all the XT functions.
201 It is zero while not inside an update. In that case, the XT
202 functions assume that `selected_frame' is the frame to apply to. */
204 extern struct frame
*updating_frame
;
206 /* This is a frame waiting to be auto-raised, within XTread_socket. */
208 struct frame
*pending_autoraise_frame
;
211 /* The application context for Xt use. */
212 XtAppContext Xt_app_con
;
213 static String Xt_default_resources
[] = {0};
214 #endif /* USE_X_TOOLKIT */
216 /* Non-zero means user is interacting with a toolkit scroll bar. */
218 static int toolkit_scroll_bar_interaction
;
222 Formerly, we used PointerMotionHintMask (in standard_event_mask)
223 so that we would have to call XQueryPointer after each MotionNotify
224 event to ask for another such event. However, this made mouse tracking
225 slow, and there was a bug that made it eventually stop.
227 Simply asking for MotionNotify all the time seems to work better.
229 In order to avoid asking for motion events and then throwing most
230 of them away or busy-polling the server for mouse positions, we ask
231 the server for pointer motion hints. This means that we get only
232 one event per group of mouse movements. "Groups" are delimited by
233 other kinds of events (focus changes and button clicks, for
234 example), or by XQueryPointer calls; when one of these happens, we
235 get another MotionNotify event the next time the mouse moves. This
236 is at least as efficient as getting motion events when mouse
237 tracking is on, and I suspect only negligibly worse when tracking
240 /* Where the mouse was last time we reported a mouse event. */
242 static XRectangle last_mouse_glyph
;
243 static Lisp_Object last_mouse_press_frame
;
245 /* The scroll bar in which the last X motion event occurred.
247 If the last X motion event occurred in a scroll bar, we set this so
248 XTmouse_position can know whether to report a scroll bar motion or
251 If the last X motion event didn't occur in a scroll bar, we set
252 this to Qnil, to tell XTmouse_position to return an ordinary motion
255 static Lisp_Object last_mouse_scroll_bar
;
257 /* This is a hack. We would really prefer that XTmouse_position would
258 return the time associated with the position it returns, but there
259 doesn't seem to be any way to wrest the time-stamp from the server
260 along with the position query. So, we just keep track of the time
261 of the last movement we received, and return that in hopes that
262 it's somewhat accurate. */
264 static Time last_mouse_movement_time
;
266 /* Incremented by XTread_socket whenever it really tries to read
270 static int volatile input_signal_count
;
272 static int input_signal_count
;
275 /* Used locally within XTread_socket. */
277 static int x_noop_count
;
279 /* Initial values of argv and argc. */
281 extern char **initial_argv
;
282 extern int initial_argc
;
284 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
286 /* Tells if a window manager is present or not. */
288 extern Lisp_Object Vx_no_window_manager
;
290 extern Lisp_Object Qeql
;
294 /* A mask of extra modifier bits to put into every keyboard char. */
296 extern EMACS_INT extra_keyboard_modifiers
;
298 /* The keysyms to use for the various modifiers. */
300 Lisp_Object Vx_alt_keysym
, Vx_hyper_keysym
, Vx_meta_keysym
, Vx_super_keysym
;
301 Lisp_Object Vx_keysym_table
;
302 static Lisp_Object Qalt
, Qhyper
, Qmeta
, Qsuper
, Qmodifier_value
;
304 static Lisp_Object Qvendor_specific_keysyms
;
305 static Lisp_Object Qlatin_1
;
307 extern XrmDatabase x_load_resources
P_ ((Display
*, char *, char *, char *));
308 extern int x_bitmap_mask
P_ ((FRAME_PTR
, int));
310 static int x_alloc_nearest_color_1
P_ ((Display
*, Colormap
, XColor
*));
311 static void x_set_window_size_1
P_ ((struct frame
*, int, int, int));
312 static const XColor
*x_color_cells
P_ ((Display
*, int *));
313 static void x_update_window_end
P_ ((struct window
*, int, int));
314 void x_delete_display
P_ ((struct x_display_info
*));
315 static unsigned int x_x_to_emacs_modifiers
P_ ((struct x_display_info
*,
317 static int x_io_error_quitter
P_ ((Display
*));
318 int x_catch_errors
P_ ((Display
*));
319 void x_uncatch_errors
P_ ((Display
*, int));
320 void x_lower_frame
P_ ((struct frame
*));
321 void x_scroll_bar_clear
P_ ((struct frame
*));
322 int x_had_errors_p
P_ ((Display
*));
323 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
324 void x_raise_frame
P_ ((struct frame
*));
325 void x_set_window_size
P_ ((struct frame
*, int, int, int));
326 void x_wm_set_window_state
P_ ((struct frame
*, int));
327 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
328 void x_initialize
P_ ((void));
329 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
330 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
331 static void x_update_end
P_ ((struct frame
*));
332 static void XTframe_up_to_date
P_ ((struct frame
*));
333 static void XTset_terminal_modes
P_ ((void));
334 static void XTreset_terminal_modes
P_ ((void));
335 static void x_clear_frame
P_ ((void));
336 static void frame_highlight
P_ ((struct frame
*));
337 static void frame_unhighlight
P_ ((struct frame
*));
338 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
339 static int x_focus_changed
P_ ((int,
341 struct x_display_info
*,
343 struct input_event
*,
345 static int x_detect_focus_change
P_ ((struct x_display_info
*,
347 struct input_event
*,
349 static void XTframe_rehighlight
P_ ((struct frame
*));
350 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
351 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
352 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
353 enum text_cursor_kinds
));
355 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, GC
));
356 static void x_flush
P_ ((struct frame
*f
));
357 static void x_update_begin
P_ ((struct frame
*));
358 static void x_update_window_begin
P_ ((struct window
*));
359 static void x_after_update_window_line
P_ ((struct glyph_row
*));
360 static struct scroll_bar
*x_window_to_scroll_bar
P_ ((Display
*, Window
));
361 static void x_scroll_bar_report_motion
P_ ((struct frame
**, Lisp_Object
*,
362 enum scroll_bar_part
*,
363 Lisp_Object
*, Lisp_Object
*,
365 static void x_check_fullscreen
P_ ((struct frame
*));
366 static void x_check_expected_move
P_ ((struct frame
*));
367 static int handle_one_xevent
P_ ((struct x_display_info
*,
369 struct input_event
**,
374 /* Flush display of frame F, or of all frames if F is null. */
383 Lisp_Object rest
, frame
;
384 FOR_EACH_FRAME (rest
, frame
)
385 x_flush (XFRAME (frame
));
387 else if (FRAME_X_P (f
))
388 XFlush (FRAME_X_DISPLAY (f
));
393 /* Remove calls to XFlush by defining XFlush to an empty replacement.
394 Calls to XFlush should be unnecessary because the X output buffer
395 is flushed automatically as needed by calls to XPending,
396 XNextEvent, or XWindowEvent according to the XFlush man page.
397 XTread_socket calls XPending. Removing XFlush improves
400 #define XFlush(DISPLAY) (void) 0
403 /***********************************************************************
405 ***********************************************************************/
409 /* This is a function useful for recording debugging information about
410 the sequence of occurrences in this file. */
418 struct record event_record
[100];
420 int event_record_index
;
422 record_event (locus
, type
)
426 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
427 event_record_index
= 0;
429 event_record
[event_record_index
].locus
= locus
;
430 event_record
[event_record_index
].type
= type
;
431 event_record_index
++;
438 /* Return the struct x_display_info corresponding to DPY. */
440 struct x_display_info
*
441 x_display_info_for_display (dpy
)
444 struct x_display_info
*dpyinfo
;
446 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
447 if (dpyinfo
->display
== dpy
)
455 /***********************************************************************
456 Starting and ending an update
457 ***********************************************************************/
459 /* Start an update of frame F. This function is installed as a hook
460 for update_begin, i.e. it is called when update_begin is called.
461 This function is called prior to calls to x_update_window_begin for
462 each window being updated. Currently, there is nothing to do here
463 because all interesting stuff is done on a window basis. */
473 /* Start update of window W. Set the global variable updated_window
474 to the window being updated and set output_cursor to the cursor
478 x_update_window_begin (w
)
481 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
482 struct x_display_info
*display_info
= FRAME_X_DISPLAY_INFO (f
);
485 set_output_cursor (&w
->cursor
);
489 if (f
== display_info
->mouse_face_mouse_frame
)
491 /* Don't do highlighting for mouse motion during the update. */
492 display_info
->mouse_face_defer
= 1;
494 /* If F needs to be redrawn, simply forget about any prior mouse
496 if (FRAME_GARBAGED_P (f
))
497 display_info
->mouse_face_window
= Qnil
;
499 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
500 their mouse_face_p flag set, which means that they are always
501 unequal to rows in a desired matrix which never have that
502 flag set. So, rows containing mouse-face glyphs are never
503 scrolled, and we don't have to switch the mouse highlight off
504 here to prevent it from being scrolled. */
506 /* Can we tell that this update does not affect the window
507 where the mouse highlight is? If so, no need to turn off.
508 Likewise, don't do anything if the frame is garbaged;
509 in that case, the frame's current matrix that we would use
510 is all wrong, and we will redisplay that line anyway. */
511 if (!NILP (display_info
->mouse_face_window
)
512 && w
== XWINDOW (display_info
->mouse_face_window
))
516 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
517 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
520 if (i
< w
->desired_matrix
->nrows
)
521 clear_mouse_face (display_info
);
530 /* Draw a vertical window border from (x,y0) to (x,y1) */
533 x_draw_vertical_window_border (w
, x
, y0
, y1
)
537 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
539 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
540 f
->output_data
.x
->normal_gc
, x
, y0
, x
, y1
);
543 /* End update of window W (which is equal to updated_window).
545 Draw vertical borders between horizontally adjacent windows, and
546 display W's cursor if CURSOR_ON_P is non-zero.
548 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
549 glyphs in mouse-face were overwritten. In that case we have to
550 make sure that the mouse-highlight is properly redrawn.
552 W may be a menu bar pseudo-window in case we don't have X toolkit
553 support. Such windows don't have a cursor, so don't display it
557 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
559 int cursor_on_p
, mouse_face_overwritten_p
;
561 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (XFRAME (w
->frame
));
563 if (!w
->pseudo_window_p
)
568 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
570 output_cursor
.x
, output_cursor
.y
);
572 x_draw_vertical_border (w
);
574 draw_window_fringes (w
);
579 /* If a row with mouse-face was overwritten, arrange for
580 XTframe_up_to_date to redisplay the mouse highlight. */
581 if (mouse_face_overwritten_p
)
583 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
584 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
585 dpyinfo
->mouse_face_window
= Qnil
;
588 updated_window
= NULL
;
592 /* End update of frame F. This function is installed as a hook in
599 /* Mouse highlight may be displayed again. */
600 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
604 XFlush (FRAME_X_DISPLAY (f
));
610 /* This function is called from various places in xdisp.c whenever a
611 complete update has been performed. The global variable
612 updated_window is not available here. */
615 XTframe_up_to_date (f
)
620 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
622 if (dpyinfo
->mouse_face_deferred_gc
623 || f
== dpyinfo
->mouse_face_mouse_frame
)
626 if (dpyinfo
->mouse_face_mouse_frame
)
627 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
628 dpyinfo
->mouse_face_mouse_x
,
629 dpyinfo
->mouse_face_mouse_y
);
630 dpyinfo
->mouse_face_deferred_gc
= 0;
637 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
638 arrow bitmaps, or clear the fringes if no bitmaps are required
639 before DESIRED_ROW is made current. The window being updated is
640 found in updated_window. This function It is called from
641 update_window_line only if it is known that there are differences
642 between bitmaps to be drawn between current row and DESIRED_ROW. */
645 x_after_update_window_line (desired_row
)
646 struct glyph_row
*desired_row
;
648 struct window
*w
= updated_window
;
654 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
655 desired_row
->redraw_fringe_bitmaps_p
= 1;
657 /* When a window has disappeared, make sure that no rest of
658 full-width rows stays visible in the internal border. Could
659 check here if updated_window is the leftmost/rightmost window,
660 but I guess it's not worth doing since vertically split windows
661 are almost never used, internal border is rarely set, and the
662 overhead is very small. */
663 if (windows_or_buffers_changed
664 && desired_row
->full_width_p
665 && (f
= XFRAME (w
->frame
),
666 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
668 && (height
= desired_row
->visible_height
,
671 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
673 /* Internal border is drawn below the tool bar. */
674 if (WINDOWP (f
->tool_bar_window
)
675 && w
== XWINDOW (f
->tool_bar_window
))
679 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
680 0, y
, width
, height
, False
);
681 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
682 FRAME_PIXEL_WIDTH (f
) - width
,
683 y
, width
, height
, False
);
689 x_draw_fringe_bitmap (w
, row
, p
)
691 struct glyph_row
*row
;
692 struct draw_fringe_bitmap_params
*p
;
694 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
695 Display
*display
= FRAME_X_DISPLAY (f
);
696 Window window
= FRAME_X_WINDOW (f
);
697 GC gc
= f
->output_data
.x
->normal_gc
;
698 struct face
*face
= p
->face
;
701 /* Must clip because of partially visible lines. */
702 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
705 /* Adjust position of "bottom aligned" bitmap on partially
708 int oldVH
= row
->visible_height
;
709 row
->visible_height
= p
->h
;
710 row
->y
-= rowY
- p
->y
;
711 x_clip_to_row (w
, row
, gc
);
713 row
->visible_height
= oldVH
;
716 x_clip_to_row (w
, row
, gc
);
720 /* In case the same realized face is used for fringes and
721 for something displayed in the text (e.g. face `region' on
722 mono-displays, the fill style may have been changed to
723 FillSolid in x_draw_glyph_string_background. */
725 XSetFillStyle (display
, face
->gc
, FillOpaqueStippled
);
727 XSetForeground (display
, face
->gc
, face
->background
);
729 XFillRectangle (display
, window
, face
->gc
,
730 p
->bx
, p
->by
, p
->nx
, p
->ny
);
733 XSetForeground (display
, face
->gc
, face
->foreground
);
736 if (p
->which
!= NO_FRINGE_BITMAP
)
738 unsigned char *bits
= fringe_bitmaps
[p
->which
].bits
+ p
->dh
;
740 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
742 /* Draw the bitmap. I believe these small pixmaps can be cached
744 pixmap
= XCreatePixmapFromBitmapData (display
, window
, bits
, p
->wd
, p
->h
,
746 face
->background
, depth
);
747 XCopyArea (display
, pixmap
, window
, gc
, 0, 0,
748 p
->wd
, p
->h
, p
->x
, p
->y
);
749 XFreePixmap (display
, pixmap
);
752 XSetClipMask (display
, gc
, None
);
757 /* This is called when starting Emacs and when restarting after
758 suspend. When starting Emacs, no X window is mapped. And nothing
759 must be done to Emacs's own window if it is suspended (though that
763 XTset_terminal_modes ()
767 /* This is called when exiting or suspending Emacs. Exiting will make
768 the X-windows go away, and suspending requires no action. */
771 XTreset_terminal_modes ()
777 /***********************************************************************
779 ***********************************************************************/
781 /* Function prototypes of this page. */
783 static int x_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
786 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
787 is not contained in the font. */
790 x_per_char_metric (font
, char2b
, font_type
)
793 int font_type
; /* unused on X */
795 /* The result metric information. */
796 XCharStruct
*pcm
= NULL
;
798 xassert (font
&& char2b
);
800 if (font
->per_char
!= NULL
)
802 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
804 /* min_char_or_byte2 specifies the linear character index
805 corresponding to the first element of the per_char array,
806 max_char_or_byte2 is the index of the last character. A
807 character with non-zero CHAR2B->byte1 is not in the font.
808 A character with byte2 less than min_char_or_byte2 or
809 greater max_char_or_byte2 is not in the font. */
810 if (char2b
->byte1
== 0
811 && char2b
->byte2
>= font
->min_char_or_byte2
812 && char2b
->byte2
<= font
->max_char_or_byte2
)
813 pcm
= font
->per_char
+ char2b
->byte2
- font
->min_char_or_byte2
;
817 /* If either min_byte1 or max_byte1 are nonzero, both
818 min_char_or_byte2 and max_char_or_byte2 are less than
819 256, and the 2-byte character index values corresponding
820 to the per_char array element N (counting from 0) are:
822 byte1 = N/D + min_byte1
823 byte2 = N\D + min_char_or_byte2
827 D = max_char_or_byte2 - min_char_or_byte2 + 1
829 \ = integer modulus */
830 if (char2b
->byte1
>= font
->min_byte1
831 && char2b
->byte1
<= font
->max_byte1
832 && char2b
->byte2
>= font
->min_char_or_byte2
833 && char2b
->byte2
<= font
->max_char_or_byte2
)
835 pcm
= (font
->per_char
836 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
837 * (char2b
->byte1
- font
->min_byte1
))
838 + (char2b
->byte2
- font
->min_char_or_byte2
));
844 /* If the per_char pointer is null, all glyphs between the first
845 and last character indexes inclusive have the same
846 information, as given by both min_bounds and max_bounds. */
847 if (char2b
->byte2
>= font
->min_char_or_byte2
848 && char2b
->byte2
<= font
->max_char_or_byte2
)
849 pcm
= &font
->max_bounds
;
853 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
858 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
859 the two-byte form of C. Encoding is returned in *CHAR2B. */
862 x_encode_char (c
, char2b
, font_info
, two_byte_p
)
865 struct font_info
*font_info
;
868 int charset
= CHAR_CHARSET (c
);
869 XFontStruct
*font
= font_info
->font
;
871 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
872 This may be either a program in a special encoder language or a
874 if (font_info
->font_encoder
)
876 /* It's a program. */
877 struct ccl_program
*ccl
= font_info
->font_encoder
;
879 if (CHARSET_DIMENSION (charset
) == 1)
881 ccl
->reg
[0] = charset
;
882 ccl
->reg
[1] = char2b
->byte2
;
887 ccl
->reg
[0] = charset
;
888 ccl
->reg
[1] = char2b
->byte1
;
889 ccl
->reg
[2] = char2b
->byte2
;
892 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
894 /* We assume that MSBs are appropriately set/reset by CCL
896 if (font
->max_byte1
== 0) /* 1-byte font */
897 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
899 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
901 else if (font_info
->encoding
[charset
])
903 /* Fixed encoding scheme. See fontset.h for the meaning of the
905 int enc
= font_info
->encoding
[charset
];
907 if ((enc
== 1 || enc
== 2)
908 && CHARSET_DIMENSION (charset
) == 2)
909 char2b
->byte1
|= 0x80;
911 if (enc
== 1 || enc
== 3)
912 char2b
->byte2
|= 0x80;
916 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
918 return FONT_TYPE_UNKNOWN
;
923 /***********************************************************************
925 ***********************************************************************/
929 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
930 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
931 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
933 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
934 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
935 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
936 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
937 static void x_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
938 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
939 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
940 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
941 static int x_alloc_lighter_color
P_ ((struct frame
*, Display
*, Colormap
,
942 unsigned long *, double, int));
943 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
944 double, int, unsigned long));
945 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
946 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
947 static void x_draw_image_relief
P_ ((struct glyph_string
*));
948 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
949 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
950 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
952 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
953 int, int, int, int, XRectangle
*));
954 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
955 int, int, int, XRectangle
*));
958 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
962 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
967 struct glyph_string
*s
;
969 if (s
->font
== FRAME_FONT (s
->f
)
970 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
971 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
973 s
->gc
= s
->f
->output_data
.x
->cursor_gc
;
976 /* Cursor on non-default face: must merge. */
980 xgcv
.background
= s
->f
->output_data
.x
->cursor_pixel
;
981 xgcv
.foreground
= s
->face
->background
;
983 /* If the glyph would be invisible, try a different foreground. */
984 if (xgcv
.foreground
== xgcv
.background
)
985 xgcv
.foreground
= s
->face
->foreground
;
986 if (xgcv
.foreground
== xgcv
.background
)
987 xgcv
.foreground
= s
->f
->output_data
.x
->cursor_foreground_pixel
;
988 if (xgcv
.foreground
== xgcv
.background
)
989 xgcv
.foreground
= s
->face
->foreground
;
991 /* Make sure the cursor is distinct from text in this face. */
992 if (xgcv
.background
== s
->face
->background
993 && xgcv
.foreground
== s
->face
->foreground
)
995 xgcv
.background
= s
->face
->foreground
;
996 xgcv
.foreground
= s
->face
->background
;
999 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1000 xgcv
.font
= s
->font
->fid
;
1001 xgcv
.graphics_exposures
= False
;
1002 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
1004 if (FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1005 XChangeGC (s
->display
, FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1008 FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1009 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1011 s
->gc
= FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1016 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1019 x_set_mouse_face_gc (s
)
1020 struct glyph_string
*s
;
1025 /* What face has to be used last for the mouse face? */
1026 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
1027 face
= FACE_FROM_ID (s
->f
, face_id
);
1029 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
1031 if (s
->first_glyph
->type
== CHAR_GLYPH
)
1032 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
1034 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
1035 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
1036 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1038 /* If font in this face is same as S->font, use it. */
1039 if (s
->font
== s
->face
->font
)
1040 s
->gc
= s
->face
->gc
;
1043 /* Otherwise construct scratch_cursor_gc with values from FACE
1048 xgcv
.background
= s
->face
->background
;
1049 xgcv
.foreground
= s
->face
->foreground
;
1050 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1051 xgcv
.font
= s
->font
->fid
;
1052 xgcv
.graphics_exposures
= False
;
1053 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
1055 if (FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1056 XChangeGC (s
->display
, FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1059 FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1060 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1062 s
->gc
= FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1065 xassert (s
->gc
!= 0);
1069 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1070 Faces to use in the mode line have already been computed when the
1071 matrix was built, so there isn't much to do, here. */
1074 x_set_mode_line_face_gc (s
)
1075 struct glyph_string
*s
;
1077 s
->gc
= s
->face
->gc
;
1081 /* Set S->gc of glyph string S for drawing that glyph string. Set
1082 S->stippled_p to a non-zero value if the face of S has a stipple
1086 x_set_glyph_string_gc (s
)
1087 struct glyph_string
*s
;
1089 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1091 if (s
->hl
== DRAW_NORMAL_TEXT
)
1093 s
->gc
= s
->face
->gc
;
1094 s
->stippled_p
= s
->face
->stipple
!= 0;
1096 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
1098 x_set_mode_line_face_gc (s
);
1099 s
->stippled_p
= s
->face
->stipple
!= 0;
1101 else if (s
->hl
== DRAW_CURSOR
)
1103 x_set_cursor_gc (s
);
1106 else if (s
->hl
== DRAW_MOUSE_FACE
)
1108 x_set_mouse_face_gc (s
);
1109 s
->stippled_p
= s
->face
->stipple
!= 0;
1111 else if (s
->hl
== DRAW_IMAGE_RAISED
1112 || s
->hl
== DRAW_IMAGE_SUNKEN
)
1114 s
->gc
= s
->face
->gc
;
1115 s
->stippled_p
= s
->face
->stipple
!= 0;
1119 s
->gc
= s
->face
->gc
;
1120 s
->stippled_p
= s
->face
->stipple
!= 0;
1123 /* GC must have been set. */
1124 xassert (s
->gc
!= 0);
1128 /* Set clipping for output of glyph string S. S may be part of a mode
1129 line or menu if we don't have X toolkit support. */
1132 x_set_glyph_string_clipping (s
)
1133 struct glyph_string
*s
;
1136 get_glyph_string_clip_rect (s
, &r
);
1137 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, &r
, 1, Unsorted
);
1142 Compute left and right overhang of glyph string S. If S is a glyph
1143 string for a composition, assume overhangs don't exist. */
1146 x_compute_glyph_string_overhangs (s
)
1147 struct glyph_string
*s
;
1150 && s
->first_glyph
->type
== CHAR_GLYPH
)
1153 int direction
, font_ascent
, font_descent
;
1154 XTextExtents16 (s
->font
, s
->char2b
, s
->nchars
, &direction
,
1155 &font_ascent
, &font_descent
, &cs
);
1156 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
1157 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
1162 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1165 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
1166 struct glyph_string
*s
;
1170 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
, &xgcv
);
1171 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
1172 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
1173 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
1177 /* Draw the background of glyph_string S. If S->background_filled_p
1178 is non-zero don't draw it. FORCE_P non-zero means draw the
1179 background even if it wouldn't be drawn normally. This is used
1180 when a string preceding S draws into the background of S, or S
1181 contains the first component of a composition. */
1184 x_draw_glyph_string_background (s
, force_p
)
1185 struct glyph_string
*s
;
1188 /* Nothing to do if background has already been drawn or if it
1189 shouldn't be drawn in the first place. */
1190 if (!s
->background_filled_p
)
1192 int box_line_width
= max (s
->face
->box_line_width
, 0);
1196 /* Fill background with a stipple pattern. */
1197 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
1198 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
1199 s
->y
+ box_line_width
,
1200 s
->background_width
,
1201 s
->height
- 2 * box_line_width
);
1202 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
1203 s
->background_filled_p
= 1;
1205 else if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
1206 || s
->font_not_found_p
1207 || s
->extends_to_end_of_line_p
1210 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
1211 s
->background_width
,
1212 s
->height
- 2 * box_line_width
);
1213 s
->background_filled_p
= 1;
1219 /* Draw the foreground of glyph string S. */
1222 x_draw_glyph_string_foreground (s
)
1223 struct glyph_string
*s
;
1227 /* If first glyph of S has a left box line, start drawing the text
1228 of S to the right of that box line. */
1229 if (s
->face
->box
!= FACE_NO_BOX
1230 && s
->first_glyph
->left_box_line_p
)
1231 x
= s
->x
+ abs (s
->face
->box_line_width
);
1235 /* Draw characters of S as rectangles if S's font could not be
1237 if (s
->font_not_found_p
)
1239 for (i
= 0; i
< s
->nchars
; ++i
)
1241 struct glyph
*g
= s
->first_glyph
+ i
;
1242 XDrawRectangle (s
->display
, s
->window
,
1243 s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
1245 x
+= g
->pixel_width
;
1250 char *char1b
= (char *) s
->char2b
;
1251 int boff
= s
->font_info
->baseline_offset
;
1253 if (s
->font_info
->vertical_centering
)
1254 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
1256 /* If we can use 8-bit functions, condense S->char2b. */
1258 for (i
= 0; i
< s
->nchars
; ++i
)
1259 char1b
[i
] = s
->char2b
[i
].byte2
;
1261 /* Draw text with XDrawString if background has already been
1262 filled. Otherwise, use XDrawImageString. (Note that
1263 XDrawImageString is usually faster than XDrawString.) Always
1264 use XDrawImageString when drawing the cursor so that there is
1265 no chance that characters under a box cursor are invisible. */
1266 if (s
->for_overlaps_p
1267 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
1269 /* Draw characters with 16-bit or 8-bit functions. */
1271 XDrawString16 (s
->display
, s
->window
, s
->gc
, x
,
1272 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
1274 XDrawString (s
->display
, s
->window
, s
->gc
, x
,
1275 s
->ybase
- boff
, char1b
, s
->nchars
);
1280 XDrawImageString16 (s
->display
, s
->window
, s
->gc
, x
,
1281 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
1283 XDrawImageString (s
->display
, s
->window
, s
->gc
, x
,
1284 s
->ybase
- boff
, char1b
, s
->nchars
);
1287 if (s
->face
->overstrike
)
1289 /* For overstriking (to simulate bold-face), draw the
1290 characters again shifted to the right by one pixel. */
1292 XDrawString16 (s
->display
, s
->window
, s
->gc
, x
+ 1,
1293 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
1295 XDrawString (s
->display
, s
->window
, s
->gc
, x
+ 1,
1296 s
->ybase
- boff
, char1b
, s
->nchars
);
1301 /* Draw the foreground of composite glyph string S. */
1304 x_draw_composite_glyph_string_foreground (s
)
1305 struct glyph_string
*s
;
1309 /* If first glyph of S has a left box line, start drawing the text
1310 of S to the right of that box line. */
1311 if (s
->face
->box
!= FACE_NO_BOX
1312 && s
->first_glyph
->left_box_line_p
)
1313 x
= s
->x
+ abs (s
->face
->box_line_width
);
1317 /* S is a glyph string for a composition. S->gidx is the index of
1318 the first character drawn for glyphs of this composition.
1319 S->gidx == 0 means we are drawing the very first character of
1320 this composition. */
1322 /* Draw a rectangle for the composition if the font for the very
1323 first character of the composition could not be loaded. */
1324 if (s
->font_not_found_p
)
1327 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, s
->y
,
1328 s
->width
- 1, s
->height
- 1);
1332 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
1334 XDrawString16 (s
->display
, s
->window
, s
->gc
,
1335 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
1336 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
1338 if (s
->face
->overstrike
)
1339 XDrawString16 (s
->display
, s
->window
, s
->gc
,
1340 x
+ s
->cmp
->offsets
[s
->gidx
* 2] + 1,
1341 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
1348 #ifdef USE_X_TOOLKIT
1350 static struct frame
*x_frame_of_widget
P_ ((Widget
));
1351 static Boolean cvt_string_to_pixel
P_ ((Display
*, XrmValue
*, Cardinal
*,
1352 XrmValue
*, XrmValue
*, XtPointer
*));
1353 static void cvt_pixel_dtor
P_ ((XtAppContext
, XrmValue
*, XtPointer
,
1354 XrmValue
*, Cardinal
*));
1357 /* Return the frame on which widget WIDGET is used.. Abort if frame
1358 cannot be determined. */
1360 static struct frame
*
1361 x_frame_of_widget (widget
)
1364 struct x_display_info
*dpyinfo
;
1368 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
1370 /* Find the top-level shell of the widget. Note that this function
1371 can be called when the widget is not yet realized, so XtWindow
1372 (widget) == 0. That's the reason we can't simply use
1373 x_any_window_to_frame. */
1374 while (!XtIsTopLevelShell (widget
))
1375 widget
= XtParent (widget
);
1377 /* Look for a frame with that top-level widget. Allocate the color
1378 on that frame to get the right gamma correction value. */
1379 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
1380 if (GC_FRAMEP (XCAR (tail
))
1381 && (f
= XFRAME (XCAR (tail
)),
1382 (f
->output_data
.nothing
!= 1
1383 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
1384 && f
->output_data
.x
->widget
== widget
)
1391 /* Allocate the color COLOR->pixel on the screen and display of
1392 widget WIDGET in colormap CMAP. If an exact match cannot be
1393 allocated, try the nearest color available. Value is non-zero
1394 if successful. This is called from lwlib. */
1397 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
1402 struct frame
*f
= x_frame_of_widget (widget
);
1403 return x_alloc_nearest_color (f
, cmap
, color
);
1407 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
1408 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1409 If this produces the same color as PIXEL, try a color where all RGB
1410 values have DELTA added. Return the allocated color in *PIXEL.
1411 DISPLAY is the X display, CMAP is the colormap to operate on.
1412 Value is non-zero if successful. */
1415 x_alloc_lighter_color_for_widget (widget
, display
, cmap
, pixel
, factor
, delta
)
1419 unsigned long *pixel
;
1423 struct frame
*f
= x_frame_of_widget (widget
);
1424 return x_alloc_lighter_color (f
, display
, cmap
, pixel
, factor
, delta
);
1428 /* Structure specifying which arguments should be passed by Xt to
1429 cvt_string_to_pixel. We want the widget's screen and colormap. */
1431 static XtConvertArgRec cvt_string_to_pixel_args
[] =
1433 {XtWidgetBaseOffset
, (XtPointer
) XtOffset (Widget
, core
.screen
),
1435 {XtWidgetBaseOffset
, (XtPointer
) XtOffset (Widget
, core
.colormap
),
1440 /* The address of this variable is returned by
1441 cvt_string_to_pixel. */
1443 static Pixel cvt_string_to_pixel_value
;
1446 /* Convert a color name to a pixel color.
1448 DPY is the display we are working on.
1450 ARGS is an array of *NARGS XrmValue structures holding additional
1451 information about the widget for which the conversion takes place.
1452 The contents of this array are determined by the specification
1453 in cvt_string_to_pixel_args.
1455 FROM is a pointer to an XrmValue which points to the color name to
1456 convert. TO is an XrmValue in which to return the pixel color.
1458 CLOSURE_RET is a pointer to user-data, in which we record if
1459 we allocated the color or not.
1461 Value is True if successful, False otherwise. */
1464 cvt_string_to_pixel (dpy
, args
, nargs
, from
, to
, closure_ret
)
1468 XrmValue
*from
, *to
;
1469 XtPointer
*closure_ret
;
1479 XtAppWarningMsg (XtDisplayToApplicationContext (dpy
),
1480 "wrongParameters", "cvt_string_to_pixel",
1482 "Screen and colormap args required", NULL
, NULL
);
1486 screen
= *(Screen
**) args
[0].addr
;
1487 cmap
= *(Colormap
*) args
[1].addr
;
1488 color_name
= (String
) from
->addr
;
1490 if (strcmp (color_name
, XtDefaultBackground
) == 0)
1492 *closure_ret
= (XtPointer
) False
;
1493 pixel
= WhitePixelOfScreen (screen
);
1495 else if (strcmp (color_name
, XtDefaultForeground
) == 0)
1497 *closure_ret
= (XtPointer
) False
;
1498 pixel
= BlackPixelOfScreen (screen
);
1500 else if (XParseColor (dpy
, cmap
, color_name
, &color
)
1501 && x_alloc_nearest_color_1 (dpy
, cmap
, &color
))
1503 pixel
= color
.pixel
;
1504 *closure_ret
= (XtPointer
) True
;
1509 Cardinal nparams
= 1;
1511 params
[0] = color_name
;
1512 XtAppWarningMsg (XtDisplayToApplicationContext (dpy
),
1513 "badValue", "cvt_string_to_pixel",
1514 "XtToolkitError", "Invalid color `%s'",
1519 if (to
->addr
!= NULL
)
1521 if (to
->size
< sizeof (Pixel
))
1523 to
->size
= sizeof (Pixel
);
1527 *(Pixel
*) to
->addr
= pixel
;
1531 cvt_string_to_pixel_value
= pixel
;
1532 to
->addr
= (XtPointer
) &cvt_string_to_pixel_value
;
1535 to
->size
= sizeof (Pixel
);
1540 /* Free a pixel color which was previously allocated via
1541 cvt_string_to_pixel. This is registered as the destructor
1542 for this type of resource via XtSetTypeConverter.
1544 APP is the application context in which we work.
1546 TO is a pointer to an XrmValue holding the color to free.
1547 CLOSURE is the value we stored in CLOSURE_RET for this color
1548 in cvt_string_to_pixel.
1550 ARGS and NARGS are like for cvt_string_to_pixel. */
1553 cvt_pixel_dtor (app
, to
, closure
, args
, nargs
)
1562 XtAppWarningMsg (app
, "wrongParameters", "cvt_pixel_dtor",
1564 "Screen and colormap arguments required",
1567 else if (closure
!= NULL
)
1569 /* We did allocate the pixel, so free it. */
1570 Screen
*screen
= *(Screen
**) args
[0].addr
;
1571 Colormap cmap
= *(Colormap
*) args
[1].addr
;
1572 x_free_dpy_colors (DisplayOfScreen (screen
), screen
, cmap
,
1573 (Pixel
*) to
->addr
, 1);
1578 #endif /* USE_X_TOOLKIT */
1581 /* Value is an array of XColor structures for the contents of the
1582 color map of display DPY. Set *NCELLS to the size of the array.
1583 Note that this probably shouldn't be called for large color maps,
1584 say a 24-bit TrueColor map. */
1586 static const XColor
*
1587 x_color_cells (dpy
, ncells
)
1591 struct x_display_info
*dpyinfo
= x_display_info_for_display (dpy
);
1593 if (dpyinfo
->color_cells
== NULL
)
1595 Screen
*screen
= dpyinfo
->screen
;
1598 dpyinfo
->ncolor_cells
1599 = XDisplayCells (dpy
, XScreenNumberOfScreen (screen
));
1600 dpyinfo
->color_cells
1601 = (XColor
*) xmalloc (dpyinfo
->ncolor_cells
1602 * sizeof *dpyinfo
->color_cells
);
1604 for (i
= 0; i
< dpyinfo
->ncolor_cells
; ++i
)
1605 dpyinfo
->color_cells
[i
].pixel
= i
;
1607 XQueryColors (dpy
, dpyinfo
->cmap
,
1608 dpyinfo
->color_cells
, dpyinfo
->ncolor_cells
);
1611 *ncells
= dpyinfo
->ncolor_cells
;
1612 return dpyinfo
->color_cells
;
1616 /* On frame F, translate pixel colors to RGB values for the NCOLORS
1617 colors in COLORS. Use cached information, if available. */
1620 x_query_colors (f
, colors
, ncolors
)
1625 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
1627 if (dpyinfo
->color_cells
)
1630 for (i
= 0; i
< ncolors
; ++i
)
1632 unsigned long pixel
= colors
[i
].pixel
;
1633 xassert (pixel
< dpyinfo
->ncolor_cells
);
1634 xassert (dpyinfo
->color_cells
[pixel
].pixel
== pixel
);
1635 colors
[i
] = dpyinfo
->color_cells
[pixel
];
1639 XQueryColors (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), colors
, ncolors
);
1643 /* On frame F, translate pixel color to RGB values for the color in
1644 COLOR. Use cached information, if available. */
1647 x_query_color (f
, color
)
1651 x_query_colors (f
, color
, 1);
1655 /* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP. If an
1656 exact match can't be allocated, try the nearest color available.
1657 Value is non-zero if successful. Set *COLOR to the color
1661 x_alloc_nearest_color_1 (dpy
, cmap
, color
)
1668 rc
= XAllocColor (dpy
, cmap
, color
);
1671 /* If we got to this point, the colormap is full, so we're going
1672 to try to get the next closest color. The algorithm used is
1673 a least-squares matching, which is what X uses for closest
1674 color matching with StaticColor visuals. */
1676 unsigned long nearest_delta
= ~0;
1678 const XColor
*cells
= x_color_cells (dpy
, &ncells
);
1680 for (nearest
= i
= 0; i
< ncells
; ++i
)
1682 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
1683 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
1684 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
1685 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
1687 if (delta
< nearest_delta
)
1690 nearest_delta
= delta
;
1694 color
->red
= cells
[nearest
].red
;
1695 color
->green
= cells
[nearest
].green
;
1696 color
->blue
= cells
[nearest
].blue
;
1697 rc
= XAllocColor (dpy
, cmap
, color
);
1701 /* If allocation succeeded, and the allocated pixel color is not
1702 equal to a cached pixel color recorded earlier, there was a
1703 change in the colormap, so clear the color cache. */
1704 struct x_display_info
*dpyinfo
= x_display_info_for_display (dpy
);
1705 XColor
*cached_color
;
1707 if (dpyinfo
->color_cells
1708 && (cached_color
= &dpyinfo
->color_cells
[color
->pixel
],
1709 (cached_color
->red
!= color
->red
1710 || cached_color
->blue
!= color
->blue
1711 || cached_color
->green
!= color
->green
)))
1713 xfree (dpyinfo
->color_cells
);
1714 dpyinfo
->color_cells
= NULL
;
1715 dpyinfo
->ncolor_cells
= 0;
1719 #ifdef DEBUG_X_COLORS
1721 register_color (color
->pixel
);
1722 #endif /* DEBUG_X_COLORS */
1728 /* Allocate the color COLOR->pixel on frame F, colormap CMAP. If an
1729 exact match can't be allocated, try the nearest color available.
1730 Value is non-zero if successful. Set *COLOR to the color
1734 x_alloc_nearest_color (f
, cmap
, color
)
1739 gamma_correct (f
, color
);
1740 return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f
), cmap
, color
);
1744 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
1745 It's necessary to do this instead of just using PIXEL directly to
1746 get color reference counts right. */
1749 x_copy_color (f
, pixel
)
1751 unsigned long pixel
;
1755 color
.pixel
= pixel
;
1757 x_query_color (f
, &color
);
1758 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
1760 #ifdef DEBUG_X_COLORS
1761 register_color (pixel
);
1767 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
1768 It's necessary to do this instead of just using PIXEL directly to
1769 get color reference counts right. */
1772 x_copy_dpy_color (dpy
, cmap
, pixel
)
1775 unsigned long pixel
;
1779 color
.pixel
= pixel
;
1781 XQueryColor (dpy
, cmap
, &color
);
1782 XAllocColor (dpy
, cmap
, &color
);
1784 #ifdef DEBUG_X_COLORS
1785 register_color (pixel
);
1791 /* Brightness beyond which a color won't have its highlight brightness
1794 Nominally, highlight colors for `3d' faces are calculated by
1795 brightening an object's color by a constant scale factor, but this
1796 doesn't yield good results for dark colors, so for colors who's
1797 brightness is less than this value (on a scale of 0-65535) have an
1798 use an additional additive factor.
1800 The value here is set so that the default menu-bar/mode-line color
1801 (grey75) will not have its highlights changed at all. */
1802 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
1805 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
1806 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1807 If this produces the same color as PIXEL, try a color where all RGB
1808 values have DELTA added. Return the allocated color in *PIXEL.
1809 DISPLAY is the X display, CMAP is the colormap to operate on.
1810 Value is non-zero if successful. */
1813 x_alloc_lighter_color (f
, display
, cmap
, pixel
, factor
, delta
)
1817 unsigned long *pixel
;
1825 /* Get RGB color values. */
1826 color
.pixel
= *pixel
;
1827 x_query_color (f
, &color
);
1829 /* Change RGB values by specified FACTOR. Avoid overflow! */
1830 xassert (factor
>= 0);
1831 new.red
= min (0xffff, factor
* color
.red
);
1832 new.green
= min (0xffff, factor
* color
.green
);
1833 new.blue
= min (0xffff, factor
* color
.blue
);
1835 /* Calculate brightness of COLOR. */
1836 bright
= (2 * color
.red
+ 3 * color
.green
+ color
.blue
) / 6;
1838 /* We only boost colors that are darker than
1839 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
1840 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
1841 /* Make an additive adjustment to NEW, because it's dark enough so
1842 that scaling by FACTOR alone isn't enough. */
1844 /* How far below the limit this color is (0 - 1, 1 being darker). */
1845 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
1846 /* The additive adjustment. */
1847 int min_delta
= delta
* dimness
* factor
/ 2;
1851 new.red
= max (0, new.red
- min_delta
);
1852 new.green
= max (0, new.green
- min_delta
);
1853 new.blue
= max (0, new.blue
- min_delta
);
1857 new.red
= min (0xffff, min_delta
+ new.red
);
1858 new.green
= min (0xffff, min_delta
+ new.green
);
1859 new.blue
= min (0xffff, min_delta
+ new.blue
);
1863 /* Try to allocate the color. */
1864 success_p
= x_alloc_nearest_color (f
, cmap
, &new);
1867 if (new.pixel
== *pixel
)
1869 /* If we end up with the same color as before, try adding
1870 delta to the RGB values. */
1871 x_free_colors (f
, &new.pixel
, 1);
1873 new.red
= min (0xffff, delta
+ color
.red
);
1874 new.green
= min (0xffff, delta
+ color
.green
);
1875 new.blue
= min (0xffff, delta
+ color
.blue
);
1876 success_p
= x_alloc_nearest_color (f
, cmap
, &new);
1887 /* Set up the foreground color for drawing relief lines of glyph
1888 string S. RELIEF is a pointer to a struct relief containing the GC
1889 with which lines will be drawn. Use a color that is FACTOR or
1890 DELTA lighter or darker than the relief's background which is found
1891 in S->f->output_data.x->relief_background. If such a color cannot
1892 be allocated, use DEFAULT_PIXEL, instead. */
1895 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
1897 struct relief
*relief
;
1900 unsigned long default_pixel
;
1903 struct x_output
*di
= f
->output_data
.x
;
1904 unsigned long mask
= GCForeground
| GCLineWidth
| GCGraphicsExposures
;
1905 unsigned long pixel
;
1906 unsigned long background
= di
->relief_background
;
1907 Colormap cmap
= FRAME_X_COLORMAP (f
);
1908 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
1909 Display
*dpy
= FRAME_X_DISPLAY (f
);
1911 xgcv
.graphics_exposures
= False
;
1912 xgcv
.line_width
= 1;
1914 /* Free previously allocated color. The color cell will be reused
1915 when it has been freed as many times as it was allocated, so this
1916 doesn't affect faces using the same colors. */
1918 && relief
->allocated_p
)
1920 x_free_colors (f
, &relief
->pixel
, 1);
1921 relief
->allocated_p
= 0;
1924 /* Allocate new color. */
1925 xgcv
.foreground
= default_pixel
;
1927 if (dpyinfo
->n_planes
!= 1
1928 && x_alloc_lighter_color (f
, dpy
, cmap
, &pixel
, factor
, delta
))
1930 relief
->allocated_p
= 1;
1931 xgcv
.foreground
= relief
->pixel
= pixel
;
1934 if (relief
->gc
== 0)
1936 xgcv
.stipple
= dpyinfo
->gray
;
1938 relief
->gc
= XCreateGC (dpy
, FRAME_X_WINDOW (f
), mask
, &xgcv
);
1941 XChangeGC (dpy
, relief
->gc
, mask
, &xgcv
);
1945 /* Set up colors for the relief lines around glyph string S. */
1948 x_setup_relief_colors (s
)
1949 struct glyph_string
*s
;
1951 struct x_output
*di
= s
->f
->output_data
.x
;
1952 unsigned long color
;
1954 if (s
->face
->use_box_color_for_shadows_p
)
1955 color
= s
->face
->box_color
;
1956 else if (s
->first_glyph
->type
== IMAGE_GLYPH
1958 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
1959 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
1964 /* Get the background color of the face. */
1965 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
1966 color
= xgcv
.background
;
1969 if (di
->white_relief
.gc
== 0
1970 || color
!= di
->relief_background
)
1972 di
->relief_background
= color
;
1973 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
1974 WHITE_PIX_DEFAULT (s
->f
));
1975 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
1976 BLACK_PIX_DEFAULT (s
->f
));
1981 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
1982 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
1983 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
1984 relief. LEFT_P non-zero means draw a relief on the left side of
1985 the rectangle. RIGHT_P non-zero means draw a relief on the right
1986 side of the rectangle. CLIP_RECT is the clipping rectangle to use
1990 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
1991 raised_p
, left_p
, right_p
, clip_rect
)
1993 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
, raised_p
;
1994 XRectangle
*clip_rect
;
1996 Display
*dpy
= FRAME_X_DISPLAY (f
);
1997 Window window
= FRAME_X_WINDOW (f
);
2002 gc
= f
->output_data
.x
->white_relief
.gc
;
2004 gc
= f
->output_data
.x
->black_relief
.gc
;
2005 XSetClipRectangles (dpy
, gc
, 0, 0, clip_rect
, 1, Unsorted
);
2008 for (i
= 0; i
< width
; ++i
)
2009 XDrawLine (dpy
, window
, gc
,
2010 left_x
+ i
* left_p
, top_y
+ i
,
2011 right_x
+ 1 - i
* right_p
, top_y
+ i
);
2015 for (i
= 0; i
< width
; ++i
)
2016 XDrawLine (dpy
, window
, gc
,
2017 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
+ 1);
2019 XSetClipMask (dpy
, gc
, None
);
2021 gc
= f
->output_data
.x
->black_relief
.gc
;
2023 gc
= f
->output_data
.x
->white_relief
.gc
;
2024 XSetClipRectangles (dpy
, gc
, 0, 0, clip_rect
, 1, Unsorted
);
2027 for (i
= 0; i
< width
; ++i
)
2028 XDrawLine (dpy
, window
, gc
,
2029 left_x
+ i
* left_p
, bottom_y
- i
,
2030 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
2034 for (i
= 0; i
< width
; ++i
)
2035 XDrawLine (dpy
, window
, gc
,
2036 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
2038 XSetClipMask (dpy
, gc
, None
);
2042 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2043 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2044 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2045 left side of the rectangle. RIGHT_P non-zero means draw a line
2046 on the right side of the rectangle. CLIP_RECT is the clipping
2047 rectangle to use when drawing. */
2050 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2051 left_p
, right_p
, clip_rect
)
2052 struct glyph_string
*s
;
2053 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
2054 XRectangle
*clip_rect
;
2058 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2059 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
2060 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, clip_rect
, 1, Unsorted
);
2063 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2064 left_x
, top_y
, right_x
- left_x
+ 1, width
);
2068 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2069 left_x
, top_y
, width
, bottom_y
- top_y
+ 1);
2072 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2073 left_x
, bottom_y
- width
+ 1, right_x
- left_x
+ 1, width
);
2077 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2078 right_x
- width
+ 1, top_y
, width
, bottom_y
- top_y
+ 1);
2080 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2081 XSetClipMask (s
->display
, s
->gc
, None
);
2085 /* Draw a box around glyph string S. */
2088 x_draw_glyph_string_box (s
)
2089 struct glyph_string
*s
;
2091 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
2092 int left_p
, right_p
;
2093 struct glyph
*last_glyph
;
2094 XRectangle clip_rect
;
2096 last_x
= window_box_right (s
->w
, s
->area
);
2097 if (s
->row
->full_width_p
2098 && !s
->w
->pseudo_window_p
)
2100 last_x
+= WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s
->w
);
2101 if (s
->area
!= RIGHT_MARGIN_AREA
2102 || WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (s
->w
))
2103 last_x
+= WINDOW_RIGHT_FRINGE_WIDTH (s
->w
);
2106 /* The glyph that may have a right box line. */
2107 last_glyph
= (s
->cmp
|| s
->img
2109 : s
->first_glyph
+ s
->nchars
- 1);
2111 width
= abs (s
->face
->box_line_width
);
2112 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
2114 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2116 : min (last_x
, s
->x
+ s
->background_width
) - 1);
2118 bottom_y
= top_y
+ s
->height
- 1;
2120 left_p
= (s
->first_glyph
->left_box_line_p
2121 || (s
->hl
== DRAW_MOUSE_FACE
2123 || s
->prev
->hl
!= s
->hl
)));
2124 right_p
= (last_glyph
->right_box_line_p
2125 || (s
->hl
== DRAW_MOUSE_FACE
2127 || s
->next
->hl
!= s
->hl
)));
2129 get_glyph_string_clip_rect (s
, &clip_rect
);
2131 if (s
->face
->box
== FACE_SIMPLE_BOX
)
2132 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2133 left_p
, right_p
, &clip_rect
);
2136 x_setup_relief_colors (s
);
2137 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
2138 width
, raised_p
, left_p
, right_p
, &clip_rect
);
2143 /* Draw foreground of image glyph string S. */
2146 x_draw_image_foreground (s
)
2147 struct glyph_string
*s
;
2150 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
);
2152 /* If first glyph of S has a left box line, start drawing it to the
2153 right of that line. */
2154 if (s
->face
->box
!= FACE_NO_BOX
2155 && s
->first_glyph
->left_box_line_p
)
2156 x
= s
->x
+ abs (s
->face
->box_line_width
);
2160 /* If there is a margin around the image, adjust x- and y-position
2162 x
+= s
->img
->hmargin
;
2163 y
+= s
->img
->vmargin
;
2169 /* We can't set both a clip mask and use XSetClipRectangles
2170 because the latter also sets a clip mask. We also can't
2171 trust on the shape extension to be available
2172 (XShapeCombineRegion). So, compute the rectangle to draw
2174 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
2177 XRectangle clip_rect
, image_rect
, r
;
2179 xgcv
.clip_mask
= s
->img
->mask
;
2180 xgcv
.clip_x_origin
= x
;
2181 xgcv
.clip_y_origin
= y
;
2182 xgcv
.function
= GXcopy
;
2183 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
2185 get_glyph_string_clip_rect (s
, &clip_rect
);
2188 image_rect
.width
= s
->img
->width
;
2189 image_rect
.height
= s
->img
->height
;
2190 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
2191 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
2192 r
.x
- x
, r
.y
- y
, r
.width
, r
.height
, r
.x
, r
.y
);
2196 XRectangle clip_rect
, image_rect
, r
;
2198 get_glyph_string_clip_rect (s
, &clip_rect
);
2201 image_rect
.width
= s
->img
->width
;
2202 image_rect
.height
= s
->img
->height
;
2203 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
2204 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
2205 r
.x
- x
, r
.y
- y
, r
.width
, r
.height
, r
.x
, r
.y
);
2207 /* When the image has a mask, we can expect that at
2208 least part of a mouse highlight or a block cursor will
2209 be visible. If the image doesn't have a mask, make
2210 a block cursor visible by drawing a rectangle around
2211 the image. I believe it's looking better if we do
2212 nothing here for mouse-face. */
2213 if (s
->hl
== DRAW_CURSOR
)
2215 int r
= s
->img
->relief
;
2217 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
- r
, y
- r
,
2218 s
->img
->width
+ r
*2 - 1, s
->img
->height
+ r
*2 - 1);
2223 /* Draw a rectangle if image could not be loaded. */
2224 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
2225 s
->img
->width
- 1, s
->img
->height
- 1);
2229 /* Draw a relief around the image glyph string S. */
2232 x_draw_image_relief (s
)
2233 struct glyph_string
*s
;
2235 int x0
, y0
, x1
, y1
, thick
, raised_p
;
2238 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
);
2240 /* If first glyph of S has a left box line, start drawing it to the
2241 right of that line. */
2242 if (s
->face
->box
!= FACE_NO_BOX
2243 && s
->first_glyph
->left_box_line_p
)
2244 x
= s
->x
+ abs (s
->face
->box_line_width
);
2248 /* If there is a margin around the image, adjust x- and y-position
2250 x
+= s
->img
->hmargin
;
2251 y
+= s
->img
->vmargin
;
2253 if (s
->hl
== DRAW_IMAGE_SUNKEN
2254 || s
->hl
== DRAW_IMAGE_RAISED
)
2256 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
2257 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
2261 thick
= abs (s
->img
->relief
);
2262 raised_p
= s
->img
->relief
> 0;
2267 x1
= x
+ s
->img
->width
+ thick
- 1;
2268 y1
= y
+ s
->img
->height
+ thick
- 1;
2270 x_setup_relief_colors (s
);
2271 get_glyph_string_clip_rect (s
, &r
);
2272 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
, 1, 1, &r
);
2276 /* Draw the foreground of image glyph string S to PIXMAP. */
2279 x_draw_image_foreground_1 (s
, pixmap
)
2280 struct glyph_string
*s
;
2284 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
);
2286 /* If first glyph of S has a left box line, start drawing it to the
2287 right of that line. */
2288 if (s
->face
->box
!= FACE_NO_BOX
2289 && s
->first_glyph
->left_box_line_p
)
2290 x
= abs (s
->face
->box_line_width
);
2294 /* If there is a margin around the image, adjust x- and y-position
2296 x
+= s
->img
->hmargin
;
2297 y
+= s
->img
->vmargin
;
2303 /* We can't set both a clip mask and use XSetClipRectangles
2304 because the latter also sets a clip mask. We also can't
2305 trust on the shape extension to be available
2306 (XShapeCombineRegion). So, compute the rectangle to draw
2308 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
2312 xgcv
.clip_mask
= s
->img
->mask
;
2313 xgcv
.clip_x_origin
= x
;
2314 xgcv
.clip_y_origin
= y
;
2315 xgcv
.function
= GXcopy
;
2316 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
2318 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
2319 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
2320 XSetClipMask (s
->display
, s
->gc
, None
);
2324 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
2325 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
2327 /* When the image has a mask, we can expect that at
2328 least part of a mouse highlight or a block cursor will
2329 be visible. If the image doesn't have a mask, make
2330 a block cursor visible by drawing a rectangle around
2331 the image. I believe it's looking better if we do
2332 nothing here for mouse-face. */
2333 if (s
->hl
== DRAW_CURSOR
)
2335 int r
= s
->img
->relief
;
2337 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
- r
, y
- r
,
2338 s
->img
->width
+ r
*2 - 1, s
->img
->height
+ r
*2 - 1);
2343 /* Draw a rectangle if image could not be loaded. */
2344 XDrawRectangle (s
->display
, pixmap
, s
->gc
, x
, y
,
2345 s
->img
->width
- 1, s
->img
->height
- 1);
2349 /* Draw part of the background of glyph string S. X, Y, W, and H
2350 give the rectangle to draw. */
2353 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
2354 struct glyph_string
*s
;
2359 /* Fill background with a stipple pattern. */
2360 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2361 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
2362 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2365 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
2369 /* Draw image glyph string S.
2372 s->x +-------------------------
2375 | +-------------------------
2378 | | +-------------------
2384 x_draw_image_glyph_string (s
)
2385 struct glyph_string
*s
;
2388 int box_line_hwidth
= abs (s
->face
->box_line_width
);
2389 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
2391 Pixmap pixmap
= None
;
2393 height
= s
->height
- 2 * box_line_vwidth
;
2396 /* Fill background with face under the image. Do it only if row is
2397 taller than image or if image has a clip mask to reduce
2399 s
->stippled_p
= s
->face
->stipple
!= 0;
2400 if (height
> s
->img
->height
2404 || s
->img
->pixmap
== 0
2405 || s
->width
!= s
->background_width
)
2407 if (box_line_hwidth
&& s
->first_glyph
->left_box_line_p
)
2408 x
= s
->x
+ box_line_hwidth
;
2412 y
= s
->y
+ box_line_vwidth
;
2416 /* Create a pixmap as large as the glyph string. Fill it
2417 with the background color. Copy the image to it, using
2418 its mask. Copy the temporary pixmap to the display. */
2419 Screen
*screen
= FRAME_X_SCREEN (s
->f
);
2420 int depth
= DefaultDepthOfScreen (screen
);
2422 /* Create a pixmap as large as the glyph string. */
2423 pixmap
= XCreatePixmap (s
->display
, s
->window
,
2424 s
->background_width
,
2427 /* Don't clip in the following because we're working on the
2429 XSetClipMask (s
->display
, s
->gc
, None
);
2431 /* Fill the pixmap with the background color/stipple. */
2434 /* Fill background with a stipple pattern. */
2435 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2436 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2437 0, 0, s
->background_width
, s
->height
);
2438 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2443 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
2445 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
2446 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2447 0, 0, s
->background_width
, s
->height
);
2448 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2452 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
2454 s
->background_filled_p
= 1;
2457 /* Draw the foreground. */
2460 x_draw_image_foreground_1 (s
, pixmap
);
2461 x_set_glyph_string_clipping (s
);
2462 XCopyArea (s
->display
, pixmap
, s
->window
, s
->gc
,
2463 0, 0, s
->background_width
, s
->height
, s
->x
, s
->y
);
2464 XFreePixmap (s
->display
, pixmap
);
2467 x_draw_image_foreground (s
);
2469 /* If we must draw a relief around the image, do it. */
2471 || s
->hl
== DRAW_IMAGE_RAISED
2472 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2473 x_draw_image_relief (s
);
2477 /* Draw stretch glyph string S. */
2480 x_draw_stretch_glyph_string (s
)
2481 struct glyph_string
*s
;
2483 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
2484 s
->stippled_p
= s
->face
->stipple
!= 0;
2486 if (s
->hl
== DRAW_CURSOR
2487 && !x_stretch_cursor_p
)
2489 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
2490 as wide as the stretch glyph. */
2491 int width
= min (FRAME_COLUMN_WIDTH (s
->f
), s
->background_width
);
2494 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
2496 /* Clear rest using the GC of the original non-cursor face. */
2497 if (width
< s
->background_width
)
2499 int x
= s
->x
+ width
, y
= s
->y
;
2500 int w
= s
->background_width
- width
, h
= s
->height
;
2504 if (s
->row
->mouse_face_p
2505 && cursor_in_mouse_face_p (s
->w
))
2507 x_set_mouse_face_gc (s
);
2513 get_glyph_string_clip_rect (s
, &r
);
2514 XSetClipRectangles (s
->display
, gc
, 0, 0, &r
, 1, Unsorted
);
2516 if (s
->face
->stipple
)
2518 /* Fill background with a stipple pattern. */
2519 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
2520 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
2521 XSetFillStyle (s
->display
, gc
, FillSolid
);
2526 XGetGCValues (s
->display
, gc
, GCForeground
| GCBackground
, &xgcv
);
2527 XSetForeground (s
->display
, gc
, xgcv
.background
);
2528 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
2529 XSetForeground (s
->display
, gc
, xgcv
.foreground
);
2533 else if (!s
->background_filled_p
)
2534 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
2537 s
->background_filled_p
= 1;
2541 /* Draw glyph string S. */
2544 x_draw_glyph_string (s
)
2545 struct glyph_string
*s
;
2547 int relief_drawn_p
= 0;
2549 /* If S draws into the background of its successor, draw the
2550 background of the successor first so that S can draw into it.
2551 This makes S->next use XDrawString instead of XDrawImageString. */
2552 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps_p
)
2554 xassert (s
->next
->img
== NULL
);
2555 x_set_glyph_string_gc (s
->next
);
2556 x_set_glyph_string_clipping (s
->next
);
2557 x_draw_glyph_string_background (s
->next
, 1);
2560 /* Set up S->gc, set clipping and draw S. */
2561 x_set_glyph_string_gc (s
);
2563 /* Draw relief (if any) in advance for char/composition so that the
2564 glyph string can be drawn over it. */
2565 if (!s
->for_overlaps_p
2566 && s
->face
->box
!= FACE_NO_BOX
2567 && (s
->first_glyph
->type
== CHAR_GLYPH
2568 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
2571 x_set_glyph_string_clipping (s
);
2572 x_draw_glyph_string_background (s
, 1);
2573 x_draw_glyph_string_box (s
);
2574 x_set_glyph_string_clipping (s
);
2578 x_set_glyph_string_clipping (s
);
2580 switch (s
->first_glyph
->type
)
2583 x_draw_image_glyph_string (s
);
2587 x_draw_stretch_glyph_string (s
);
2591 if (s
->for_overlaps_p
)
2592 s
->background_filled_p
= 1;
2594 x_draw_glyph_string_background (s
, 0);
2595 x_draw_glyph_string_foreground (s
);
2598 case COMPOSITE_GLYPH
:
2599 if (s
->for_overlaps_p
|| s
->gidx
> 0)
2600 s
->background_filled_p
= 1;
2602 x_draw_glyph_string_background (s
, 1);
2603 x_draw_composite_glyph_string_foreground (s
);
2610 if (!s
->for_overlaps_p
)
2612 /* Draw underline. */
2613 if (s
->face
->underline_p
)
2615 unsigned long tem
, h
;
2618 /* Get the underline thickness. Default is 1 pixel. */
2619 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_THICKNESS
, &h
))
2622 /* Get the underline position. This is the recommended
2623 vertical offset in pixels from the baseline to the top of
2624 the underline. This is a signed value according to the
2625 specs, and its default is
2627 ROUND ((maximum descent) / 2), with
2628 ROUND(x) = floor (x + 0.5) */
2630 if (x_use_underline_position_properties
2631 && XGetFontProperty (s
->font
, XA_UNDERLINE_POSITION
, &tem
))
2632 y
= s
->ybase
+ (long) tem
;
2633 else if (s
->face
->font
)
2634 y
= s
->ybase
+ (s
->face
->font
->max_bounds
.descent
+ 1) / 2;
2636 y
= s
->y
+ s
->height
- h
;
2638 if (s
->face
->underline_defaulted_p
)
2639 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2640 s
->x
, y
, s
->width
, h
);
2644 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2645 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
2646 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2647 s
->x
, y
, s
->width
, h
);
2648 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2652 /* Draw overline. */
2653 if (s
->face
->overline_p
)
2655 unsigned long dy
= 0, h
= 1;
2657 if (s
->face
->overline_color_defaulted_p
)
2658 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2663 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2664 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
2665 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2667 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2671 /* Draw strike-through. */
2672 if (s
->face
->strike_through_p
)
2674 unsigned long h
= 1;
2675 unsigned long dy
= (s
->height
- h
) / 2;
2677 if (s
->face
->strike_through_color_defaulted_p
)
2678 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2683 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2684 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
2685 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2687 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2691 /* Draw relief if not yet drawn. */
2692 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
2693 x_draw_glyph_string_box (s
);
2696 /* Reset clipping. */
2697 XSetClipMask (s
->display
, s
->gc
, None
);
2700 /* Shift display to make room for inserted glyphs. */
2703 x_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
2705 int x
, y
, width
, height
, shift_by
;
2707 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
2708 f
->output_data
.x
->normal_gc
,
2709 x
, y
, width
, height
,
2713 /* Delete N glyphs at the nominal cursor position. Not implemented
2724 /* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
2725 If they are <= 0, this is probably an error. */
2728 x_clear_area (dpy
, window
, x
, y
, width
, height
, exposures
)
2735 xassert (width
> 0 && height
> 0);
2736 XClearArea (dpy
, window
, x
, y
, width
, height
, exposures
);
2740 /* Clear entire frame. If updating_frame is non-null, clear that
2741 frame. Otherwise clear the selected frame. */
2751 f
= SELECTED_FRAME ();
2753 /* Clearing the frame will erase any cursor, so mark them all as no
2755 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
2756 output_cursor
.hpos
= output_cursor
.vpos
= 0;
2757 output_cursor
.x
= -1;
2759 /* We don't set the output cursor here because there will always
2760 follow an explicit cursor_to. */
2762 XClearWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
2764 /* We have to clear the scroll bars, too. If we have changed
2765 colors or something like that, then they should be notified. */
2766 x_scroll_bar_clear (f
);
2768 XFlush (FRAME_X_DISPLAY (f
));
2771 xg_frame_cleared (f
);
2779 /* Invert the middle quarter of the frame for .15 sec. */
2781 /* We use the select system call to do the waiting, so we have to make
2782 sure it's available. If it isn't, we just won't do visual bells. */
2784 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
2787 /* Subtract the `struct timeval' values X and Y, storing the result in
2788 *RESULT. Return 1 if the difference is negative, otherwise 0. */
2791 timeval_subtract (result
, x
, y
)
2792 struct timeval
*result
, x
, y
;
2794 /* Perform the carry for the later subtraction by updating y. This
2795 is safer because on some systems the tv_sec member is unsigned. */
2796 if (x
.tv_usec
< y
.tv_usec
)
2798 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
2799 y
.tv_usec
-= 1000000 * nsec
;
2803 if (x
.tv_usec
- y
.tv_usec
> 1000000)
2805 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
2806 y
.tv_usec
+= 1000000 * nsec
;
2810 /* Compute the time remaining to wait. tv_usec is certainly
2812 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
2813 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
2815 /* Return indication of whether the result should be considered
2817 return x
.tv_sec
< y
.tv_sec
;
2829 /* Create a GC that will use the GXxor function to flip foreground
2830 pixels into background pixels. */
2834 values
.function
= GXxor
;
2835 values
.foreground
= (f
->output_data
.x
->foreground_pixel
2836 ^ f
->output_data
.x
->background_pixel
);
2838 gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2839 GCFunction
| GCForeground
, &values
);
2843 /* Get the height not including a menu bar widget. */
2844 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
2845 /* Height of each line to flash. */
2846 int flash_height
= FRAME_LINE_HEIGHT (f
);
2847 /* These will be the left and right margins of the rectangles. */
2848 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
2849 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
2853 /* Don't flash the area between a scroll bar and the frame
2854 edge it is next to. */
2855 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
2857 case vertical_scroll_bar_left
:
2858 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
2861 case vertical_scroll_bar_right
:
2862 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
2869 width
= flash_right
- flash_left
;
2871 /* If window is tall, flash top and bottom line. */
2872 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
2874 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
2876 (FRAME_INTERNAL_BORDER_WIDTH (f
)
2877 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
2878 width
, flash_height
);
2879 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
2881 (height
- flash_height
2882 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
2883 width
, flash_height
);
2886 /* If it is short, flash it all. */
2887 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
2888 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
2889 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
2894 struct timeval wakeup
;
2896 EMACS_GET_TIME (wakeup
);
2898 /* Compute time to wait until, propagating carry from usecs. */
2899 wakeup
.tv_usec
+= 150000;
2900 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
2901 wakeup
.tv_usec
%= 1000000;
2903 /* Keep waiting until past the time wakeup or any input gets
2905 while (! detect_input_pending ())
2907 struct timeval current
;
2908 struct timeval timeout
;
2910 EMACS_GET_TIME (current
);
2912 /* Break if result would be negative. */
2913 if (timeval_subtract (¤t
, wakeup
, current
))
2916 /* How long `select' should wait. */
2918 timeout
.tv_usec
= 10000;
2920 /* Try to wait that long--but we might wake up sooner. */
2921 select (0, NULL
, NULL
, NULL
, &timeout
);
2925 /* If window is tall, flash top and bottom line. */
2926 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
2928 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
2930 (FRAME_INTERNAL_BORDER_WIDTH (f
)
2931 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
2932 width
, flash_height
);
2933 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
2935 (height
- flash_height
2936 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
2937 width
, flash_height
);
2940 /* If it is short, flash it all. */
2941 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
2942 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
2943 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
2945 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
2953 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
2956 /* Make audible bell. */
2961 struct frame
*f
= SELECTED_FRAME ();
2963 if (FRAME_X_DISPLAY (f
))
2965 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
2972 XBell (FRAME_X_DISPLAY (f
), 0);
2973 XFlush (FRAME_X_DISPLAY (f
));
2980 /* Specify how many text lines, from the top of the window,
2981 should be affected by insert-lines and delete-lines operations.
2982 This, and those operations, are used only within an update
2983 that is bounded by calls to x_update_begin and x_update_end. */
2986 XTset_terminal_window (n
)
2989 /* This function intentionally left blank. */
2994 /***********************************************************************
2996 ***********************************************************************/
2998 /* Perform an insert-lines or delete-lines operation, inserting N
2999 lines or deleting -N lines at vertical position VPOS. */
3002 x_ins_del_lines (vpos
, n
)
3009 /* Scroll part of the display as described by RUN. */
3012 x_scroll_run (w
, run
)
3016 struct frame
*f
= XFRAME (w
->frame
);
3017 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
3019 /* Get frame-relative bounding box of the text display area of W,
3020 without mode lines. Include in this box the left and right
3022 window_box (w
, -1, &x
, &y
, &width
, &height
);
3024 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
3025 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
3026 bottom_y
= y
+ height
;
3030 /* Scrolling up. Make sure we don't copy part of the mode
3031 line at the bottom. */
3032 if (from_y
+ run
->height
> bottom_y
)
3033 height
= bottom_y
- from_y
;
3035 height
= run
->height
;
3039 /* Scolling down. Make sure we don't copy over the mode line.
3041 if (to_y
+ run
->height
> bottom_y
)
3042 height
= bottom_y
- to_y
;
3044 height
= run
->height
;
3049 /* Cursor off. Will be switched on again in x_update_window_end. */
3053 XCopyArea (FRAME_X_DISPLAY (f
),
3054 FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
3055 f
->output_data
.x
->normal_gc
,
3065 /***********************************************************************
3067 ***********************************************************************/
3074 /* We used to only do this if Vx_no_window_manager was non-nil, but
3075 the ICCCM (section 4.1.6) says that the window's border pixmap
3076 and border pixel are window attributes which are "private to the
3077 client", so we can always change it to whatever we want. */
3079 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3080 f
->output_data
.x
->border_pixel
);
3082 x_update_cursor (f
, 1);
3086 frame_unhighlight (f
)
3089 /* We used to only do this if Vx_no_window_manager was non-nil, but
3090 the ICCCM (section 4.1.6) says that the window's border pixmap
3091 and border pixel are window attributes which are "private to the
3092 client", so we can always change it to whatever we want. */
3094 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3095 f
->output_data
.x
->border_tile
);
3097 x_update_cursor (f
, 1);
3100 /* The focus has changed. Update the frames as necessary to reflect
3101 the new situation. Note that we can't change the selected frame
3102 here, because the Lisp code we are interrupting might become confused.
3103 Each event gets marked with the frame in which it occurred, so the
3104 Lisp code can tell when the switch took place by examining the events. */
3107 x_new_focus_frame (dpyinfo
, frame
)
3108 struct x_display_info
*dpyinfo
;
3109 struct frame
*frame
;
3111 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
3113 if (frame
!= dpyinfo
->x_focus_frame
)
3115 /* Set this before calling other routines, so that they see
3116 the correct value of x_focus_frame. */
3117 dpyinfo
->x_focus_frame
= frame
;
3119 if (old_focus
&& old_focus
->auto_lower
)
3120 x_lower_frame (old_focus
);
3123 selected_frame
= frame
;
3124 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
3126 Fselect_window (selected_frame
->selected_window
, Qnil
);
3127 choose_minibuf_frame ();
3130 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
3131 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
3133 pending_autoraise_frame
= 0;
3136 x_frame_rehighlight (dpyinfo
);
3139 /* Handle FocusIn and FocusOut state changes for FRAME.
3140 If FRAME has focus and there exists more than one frame, puts
3141 a FOCUS_IN_EVENT into BUFP.
3142 Returns number of events inserted into BUFP. */
3145 x_focus_changed (type
, state
, dpyinfo
, frame
, bufp
, numchars
)
3148 struct x_display_info
*dpyinfo
;
3149 struct frame
*frame
;
3150 struct input_event
*bufp
;
3155 if (type
== FocusIn
)
3157 if (dpyinfo
->x_focus_event_frame
!= frame
)
3159 x_new_focus_frame (dpyinfo
, frame
);
3160 dpyinfo
->x_focus_event_frame
= frame
;
3162 /* Don't stop displaying the initial startup message
3163 for a switch-frame event we don't need. */
3165 && GC_NILP (Vterminal_frame
)
3166 && GC_CONSP (Vframe_list
)
3167 && !GC_NILP (XCDR (Vframe_list
)))
3169 bufp
->kind
= FOCUS_IN_EVENT
;
3170 XSETFRAME (bufp
->frame_or_window
, frame
);
3178 frame
->output_data
.x
->focus_state
|= state
;
3181 if (FRAME_XIC (frame
))
3182 XSetICFocus (FRAME_XIC (frame
));
3185 else if (type
== FocusOut
)
3187 frame
->output_data
.x
->focus_state
&= ~state
;
3189 if (dpyinfo
->x_focus_event_frame
== frame
)
3191 dpyinfo
->x_focus_event_frame
= 0;
3192 x_new_focus_frame (dpyinfo
, 0);
3196 if (FRAME_XIC (frame
))
3197 XUnsetICFocus (FRAME_XIC (frame
));
3204 /* The focus may have changed. Figure out if it is a real focus change,
3205 by checking both FocusIn/Out and Enter/LeaveNotify events.
3207 Returns number of events inserted into BUFP. */
3210 x_detect_focus_change (dpyinfo
, event
, bufp
, numchars
)
3211 struct x_display_info
*dpyinfo
;
3213 struct input_event
*bufp
;
3216 struct frame
*frame
;
3219 frame
= x_any_window_to_frame (dpyinfo
, event
->xany
.window
);
3220 if (! frame
) return nr_events
;
3222 switch (event
->type
)
3227 struct frame
*focus_frame
= dpyinfo
->x_focus_event_frame
;
3229 = focus_frame
? focus_frame
->output_data
.x
->focus_state
: 0;
3231 if (event
->xcrossing
.detail
!= NotifyInferior
3232 && event
->xcrossing
.focus
3233 && ! (focus_state
& FOCUS_EXPLICIT
))
3234 nr_events
= x_focus_changed ((event
->type
== EnterNotify
3235 ? FocusIn
: FocusOut
),
3246 nr_events
= x_focus_changed (event
->type
,
3247 (event
->xfocus
.detail
== NotifyPointer
3248 ? FOCUS_IMPLICIT
: FOCUS_EXPLICIT
),
3260 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3263 x_mouse_leave (dpyinfo
)
3264 struct x_display_info
*dpyinfo
;
3266 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
3269 /* The focus has changed, or we have redirected a frame's focus to
3270 another frame (this happens when a frame uses a surrogate
3271 mini-buffer frame). Shift the highlight as appropriate.
3273 The FRAME argument doesn't necessarily have anything to do with which
3274 frame is being highlighted or un-highlighted; we only use it to find
3275 the appropriate X display info. */
3278 XTframe_rehighlight (frame
)
3279 struct frame
*frame
;
3281 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
3285 x_frame_rehighlight (dpyinfo
)
3286 struct x_display_info
*dpyinfo
;
3288 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
3290 if (dpyinfo
->x_focus_frame
)
3292 dpyinfo
->x_highlight_frame
3293 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
3294 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
3295 : dpyinfo
->x_focus_frame
);
3296 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
3298 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
3299 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
3303 dpyinfo
->x_highlight_frame
= 0;
3305 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
3308 frame_unhighlight (old_highlight
);
3309 if (dpyinfo
->x_highlight_frame
)
3310 frame_highlight (dpyinfo
->x_highlight_frame
);
3316 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3318 /* Initialize mode_switch_bit and modifier_meaning. */
3320 x_find_modifier_meanings (dpyinfo
)
3321 struct x_display_info
*dpyinfo
;
3323 int min_code
, max_code
;
3326 XModifierKeymap
*mods
;
3328 dpyinfo
->meta_mod_mask
= 0;
3329 dpyinfo
->shift_lock_mask
= 0;
3330 dpyinfo
->alt_mod_mask
= 0;
3331 dpyinfo
->super_mod_mask
= 0;
3332 dpyinfo
->hyper_mod_mask
= 0;
3335 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
3337 min_code
= dpyinfo
->display
->min_keycode
;
3338 max_code
= dpyinfo
->display
->max_keycode
;
3341 syms
= XGetKeyboardMapping (dpyinfo
->display
,
3342 min_code
, max_code
- min_code
+ 1,
3344 mods
= XGetModifierMapping (dpyinfo
->display
);
3346 /* Scan the modifier table to see which modifier bits the Meta and
3347 Alt keysyms are on. */
3349 int row
, col
; /* The row and column in the modifier table. */
3351 for (row
= 3; row
< 8; row
++)
3352 for (col
= 0; col
< mods
->max_keypermod
; col
++)
3355 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
3357 /* Zeroes are used for filler. Skip them. */
3361 /* Are any of this keycode's keysyms a meta key? */
3365 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
3367 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
3373 dpyinfo
->meta_mod_mask
|= (1 << row
);
3378 dpyinfo
->alt_mod_mask
|= (1 << row
);
3383 dpyinfo
->hyper_mod_mask
|= (1 << row
);
3388 dpyinfo
->super_mod_mask
|= (1 << row
);
3392 /* Ignore this if it's not on the lock modifier. */
3393 if ((1 << row
) == LockMask
)
3394 dpyinfo
->shift_lock_mask
= LockMask
;
3402 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3403 if (! dpyinfo
->meta_mod_mask
)
3405 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
3406 dpyinfo
->alt_mod_mask
= 0;
3409 /* If some keys are both alt and meta,
3410 make them just meta, not alt. */
3411 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
3413 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
3416 XFree ((char *) syms
);
3417 XFreeModifiermap (mods
);
3420 /* Convert between the modifier bits X uses and the modifier bits
3424 x_x_to_emacs_modifiers (dpyinfo
, state
)
3425 struct x_display_info
*dpyinfo
;
3428 EMACS_UINT mod_meta
= meta_modifier
;
3429 EMACS_UINT mod_alt
= alt_modifier
;
3430 EMACS_UINT mod_hyper
= hyper_modifier
;
3431 EMACS_UINT mod_super
= super_modifier
;
3434 tem
= Fget (Vx_alt_keysym
, Qmodifier_value
);
3435 if (! EQ (tem
, Qnil
)) mod_alt
= XUINT (tem
);
3436 tem
= Fget (Vx_meta_keysym
, Qmodifier_value
);
3437 if (! EQ (tem
, Qnil
)) mod_meta
= XUINT (tem
);
3438 tem
= Fget (Vx_hyper_keysym
, Qmodifier_value
);
3439 if (! EQ (tem
, Qnil
)) mod_hyper
= XUINT (tem
);
3440 tem
= Fget (Vx_super_keysym
, Qmodifier_value
);
3441 if (! EQ (tem
, Qnil
)) mod_super
= XUINT (tem
);
3444 return ( ((state
& (ShiftMask
| dpyinfo
->shift_lock_mask
)) ? shift_modifier
: 0)
3445 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
3446 | ((state
& dpyinfo
->meta_mod_mask
) ? mod_meta
: 0)
3447 | ((state
& dpyinfo
->alt_mod_mask
) ? mod_alt
: 0)
3448 | ((state
& dpyinfo
->super_mod_mask
) ? mod_super
: 0)
3449 | ((state
& dpyinfo
->hyper_mod_mask
) ? mod_hyper
: 0));
3453 x_emacs_to_x_modifiers (dpyinfo
, state
)
3454 struct x_display_info
*dpyinfo
;
3457 EMACS_UINT mod_meta
= meta_modifier
;
3458 EMACS_UINT mod_alt
= alt_modifier
;
3459 EMACS_UINT mod_hyper
= hyper_modifier
;
3460 EMACS_UINT mod_super
= super_modifier
;
3464 tem
= Fget (Vx_alt_keysym
, Qmodifier_value
);
3465 if (! EQ (tem
, Qnil
)) mod_alt
= XUINT (tem
);
3466 tem
= Fget (Vx_meta_keysym
, Qmodifier_value
);
3467 if (! EQ (tem
, Qnil
)) mod_meta
= XUINT (tem
);
3468 tem
= Fget (Vx_hyper_keysym
, Qmodifier_value
);
3469 if (! EQ (tem
, Qnil
)) mod_hyper
= XUINT (tem
);
3470 tem
= Fget (Vx_super_keysym
, Qmodifier_value
);
3471 if (! EQ (tem
, Qnil
)) mod_super
= XUINT (tem
);
3474 return ( ((state
& mod_alt
) ? dpyinfo
->alt_mod_mask
: 0)
3475 | ((state
& mod_super
) ? dpyinfo
->super_mod_mask
: 0)
3476 | ((state
& mod_hyper
) ? dpyinfo
->hyper_mod_mask
: 0)
3477 | ((state
& shift_modifier
) ? ShiftMask
: 0)
3478 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
3479 | ((state
& mod_meta
) ? dpyinfo
->meta_mod_mask
: 0));
3482 /* Convert a keysym to its name. */
3485 x_get_keysym_name (keysym
)
3491 value
= XKeysymToString (keysym
);
3499 /* Mouse clicks and mouse movement. Rah. */
3501 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3503 If the event is a button press, then note that we have grabbed
3507 construct_mouse_click (result
, event
, f
)
3508 struct input_event
*result
;
3509 XButtonEvent
*event
;
3512 /* Make the event type NO_EVENT; we'll change that when we decide
3514 result
->kind
= MOUSE_CLICK_EVENT
;
3515 result
->code
= event
->button
- Button1
;
3516 result
->timestamp
= event
->time
;
3517 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
3519 | (event
->type
== ButtonRelease
3523 XSETINT (result
->x
, event
->x
);
3524 XSETINT (result
->y
, event
->y
);
3525 XSETFRAME (result
->frame_or_window
, f
);
3531 /* Function to report a mouse movement to the mainstream Emacs code.
3532 The input handler calls this.
3534 We have received a mouse movement event, which is given in *event.
3535 If the mouse is over a different glyph than it was last time, tell
3536 the mainstream emacs code by setting mouse_moved. If not, ask for
3537 another motion event, so we can check again the next time it moves. */
3539 static XMotionEvent last_mouse_motion_event
;
3540 static Lisp_Object last_mouse_motion_frame
;
3543 note_mouse_movement (frame
, event
)
3545 XMotionEvent
*event
;
3547 last_mouse_movement_time
= event
->time
;
3548 last_mouse_motion_event
= *event
;
3549 XSETFRAME (last_mouse_motion_frame
, frame
);
3551 if (event
->window
!= FRAME_X_WINDOW (frame
))
3553 frame
->mouse_moved
= 1;
3554 last_mouse_scroll_bar
= Qnil
;
3555 note_mouse_highlight (frame
, -1, -1);
3558 /* Has the mouse moved off the glyph it was on at the last sighting? */
3559 else if (event
->x
< last_mouse_glyph
.x
3560 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
3561 || event
->y
< last_mouse_glyph
.y
3562 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
3564 frame
->mouse_moved
= 1;
3565 last_mouse_scroll_bar
= Qnil
;
3566 note_mouse_highlight (frame
, event
->x
, event
->y
);
3571 /************************************************************************
3573 ************************************************************************/
3576 redo_mouse_highlight ()
3578 if (!NILP (last_mouse_motion_frame
)
3579 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
3580 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
3581 last_mouse_motion_event
.x
,
3582 last_mouse_motion_event
.y
);
3586 static int glyph_rect
P_ ((struct frame
*f
, int, int, XRectangle
*));
3589 /* Try to determine frame pixel position and size of the glyph under
3590 frame pixel coordinates X/Y on frame F . Return the position and
3591 size in *RECT. Value is non-zero if we could compute these
3595 glyph_rect (f
, x
, y
, rect
)
3603 window
= window_from_coordinates (f
, x
, y
, 0, &x
, &y
, 0);
3606 struct window
*w
= XWINDOW (window
);
3607 struct glyph_row
*r
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
3608 struct glyph_row
*end
= r
+ w
->current_matrix
->nrows
- 1;
3610 for (; !found
&& r
< end
&& r
->enabled_p
; ++r
)
3613 struct glyph
*g
= r
->glyphs
[TEXT_AREA
];
3614 struct glyph
*end
= g
+ r
->used
[TEXT_AREA
];
3617 for (gx
= r
->x
; !found
&& g
< end
; gx
+= g
->pixel_width
, ++g
)
3620 rect
->width
= g
->pixel_width
;
3621 rect
->height
= r
->height
;
3622 rect
->x
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
3623 rect
->y
= WINDOW_TO_FRAME_PIXEL_Y (w
, r
->y
);
3633 /* Return the current position of the mouse.
3634 *FP should be a frame which indicates which display to ask about.
3636 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
3637 and *PART to the frame, window, and scroll bar part that the mouse
3638 is over. Set *X and *Y to the portion and whole of the mouse's
3639 position on the scroll bar.
3641 If the mouse movement started elsewhere, set *FP to the frame the
3642 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
3645 Set *TIME to the server time-stamp for the time at which the mouse
3646 was at this position.
3648 Don't store anything if we don't have a valid set of values to report.
3650 This clears the mouse_moved flag, so we can wait for the next mouse
3654 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
3657 Lisp_Object
*bar_window
;
3658 enum scroll_bar_part
*part
;
3660 unsigned long *time
;
3666 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
3667 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
3673 Window dummy_window
;
3676 Lisp_Object frame
, tail
;
3678 /* Clear the mouse-moved flag for every frame on this display. */
3679 FOR_EACH_FRAME (tail
, frame
)
3680 if (FRAME_X_DISPLAY (XFRAME (frame
)) == FRAME_X_DISPLAY (*fp
))
3681 XFRAME (frame
)->mouse_moved
= 0;
3683 last_mouse_scroll_bar
= Qnil
;
3685 /* Figure out which root window we're on. */
3686 XQueryPointer (FRAME_X_DISPLAY (*fp
),
3687 DefaultRootWindow (FRAME_X_DISPLAY (*fp
)),
3689 /* The root window which contains the pointer. */
3692 /* Trash which we can't trust if the pointer is on
3693 a different screen. */
3696 /* The position on that root window. */
3699 /* More trash we can't trust. */
3702 /* Modifier keys and pointer buttons, about which
3704 (unsigned int *) &dummy
);
3706 /* Now we have a position on the root; find the innermost window
3707 containing the pointer. */
3711 int parent_x
= 0, parent_y
= 0;
3716 /* XTranslateCoordinates can get errors if the window
3717 structure is changing at the same time this function
3718 is running. So at least we must not crash from them. */
3720 count
= x_catch_errors (FRAME_X_DISPLAY (*fp
));
3722 if (FRAME_X_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
3723 && FRAME_LIVE_P (last_mouse_frame
))
3725 /* If mouse was grabbed on a frame, give coords for that frame
3726 even if the mouse is now outside it. */
3727 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
3729 /* From-window, to-window. */
3730 root
, FRAME_X_WINDOW (last_mouse_frame
),
3732 /* From-position, to-position. */
3733 root_x
, root_y
, &win_x
, &win_y
,
3737 f1
= last_mouse_frame
;
3743 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
3745 /* From-window, to-window. */
3748 /* From-position, to-position. */
3749 root_x
, root_y
, &win_x
, &win_y
,
3754 if (child
== None
|| child
== win
)
3762 /* Now we know that:
3763 win is the innermost window containing the pointer
3764 (XTC says it has no child containing the pointer),
3765 win_x and win_y are the pointer's position in it
3766 (XTC did this the last time through), and
3767 parent_x and parent_y are the pointer's position in win's parent.
3768 (They are what win_x and win_y were when win was child.
3769 If win is the root window, it has no parent, and
3770 parent_{x,y} are invalid, but that's okay, because we'll
3771 never use them in that case.) */
3773 /* Is win one of our frames? */
3774 f1
= x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp
), win
);
3776 #ifdef USE_X_TOOLKIT
3777 /* If we end up with the menu bar window, say it's not
3780 && f1
->output_data
.x
->menubar_widget
3781 && win
== XtWindow (f1
->output_data
.x
->menubar_widget
))
3783 #endif /* USE_X_TOOLKIT */
3786 if (x_had_errors_p (FRAME_X_DISPLAY (*fp
)))
3789 x_uncatch_errors (FRAME_X_DISPLAY (*fp
), count
);
3791 /* If not, is it one of our scroll bars? */
3794 struct scroll_bar
*bar
;
3796 bar
= x_window_to_scroll_bar (FRAME_X_DISPLAY (*fp
), win
);
3800 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3806 if (f1
== 0 && insist
> 0)
3807 f1
= SELECTED_FRAME ();
3811 /* Ok, we found a frame. Store all the values.
3812 last_mouse_glyph is a rectangle used to reduce the
3813 generation of mouse events. To not miss any motion
3814 events, we must divide the frame into rectangles of the
3815 size of the smallest character that could be displayed
3816 on it, i.e. into the same rectangles that matrices on
3817 the frame are divided into. */
3819 int width
, height
, gx
, gy
;
3822 if (glyph_rect (f1
, win_x
, win_y
, &rect
))
3823 last_mouse_glyph
= rect
;
3826 width
= FRAME_SMALLEST_CHAR_WIDTH (f1
);
3827 height
= FRAME_SMALLEST_FONT_HEIGHT (f1
);
3831 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
3832 round down even for negative values. */
3837 gx
= (gx
+ width
- 1) / width
* width
;
3838 gy
= (gy
+ height
- 1) / height
* height
;
3840 last_mouse_glyph
.width
= width
;
3841 last_mouse_glyph
.height
= height
;
3842 last_mouse_glyph
.x
= gx
;
3843 last_mouse_glyph
.y
= gy
;
3849 XSETINT (*x
, win_x
);
3850 XSETINT (*y
, win_y
);
3851 *time
= last_mouse_movement_time
;
3861 /***********************************************************************
3863 ***********************************************************************/
3865 /* Scroll bar support. */
3867 /* Given an X window ID and a DISPLAY, find the struct scroll_bar which
3869 This can be called in GC, so we have to make sure to strip off mark
3872 static struct scroll_bar
*
3873 x_window_to_scroll_bar (display
, window_id
)
3880 window_id
= (Window
) xg_get_scroll_id_for_window (display
, window_id
);
3881 #endif /* USE_GTK */
3883 for (tail
= Vframe_list
;
3884 XGCTYPE (tail
) == Lisp_Cons
;
3887 Lisp_Object frame
, bar
, condemned
;
3889 frame
= XCAR (tail
);
3890 /* All elements of Vframe_list should be frames. */
3891 if (! GC_FRAMEP (frame
))
3894 /* Scan this frame's scroll bar list for a scroll bar with the
3896 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
3897 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
3898 /* This trick allows us to search both the ordinary and
3899 condemned scroll bar lists with one loop. */
3900 ! GC_NILP (bar
) || (bar
= condemned
,
3903 bar
= XSCROLL_BAR (bar
)->next
)
3904 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
&&
3905 FRAME_X_DISPLAY (XFRAME (frame
)) == display
)
3906 return XSCROLL_BAR (bar
);
3913 #if defined USE_LUCID
3915 /* Return the Lucid menu bar WINDOW is part of. Return null
3916 if WINDOW is not part of a menu bar. */
3919 x_window_to_menu_bar (window
)
3924 for (tail
= Vframe_list
;
3925 XGCTYPE (tail
) == Lisp_Cons
;
3928 Lisp_Object frame
= XCAR (tail
);
3929 Widget menu_bar
= XFRAME (frame
)->output_data
.x
->menubar_widget
;
3931 if (menu_bar
&& xlwmenu_window_p (menu_bar
, window
))
3938 #endif /* USE_LUCID */
3941 /************************************************************************
3943 ************************************************************************/
3945 #ifdef USE_TOOLKIT_SCROLL_BARS
3947 static void x_scroll_bar_to_input_event
P_ ((XEvent
*, struct input_event
*));
3948 static void x_send_scroll_bar_event
P_ ((Lisp_Object
, int, int, int));
3949 static void x_create_toolkit_scroll_bar
P_ ((struct frame
*,
3950 struct scroll_bar
*));
3951 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
3955 /* Lisp window being scrolled. Set when starting to interact with
3956 a toolkit scroll bar, reset to nil when ending the interaction. */
3958 static Lisp_Object window_being_scrolled
;
3960 /* Last scroll bar part sent in xm_scroll_callback. */
3962 static int last_scroll_bar_part
;
3964 /* Whether this is an Xaw with arrow-scrollbars. This should imply
3965 that movements of 1/20 of the screen size are mapped to up/down. */
3968 /* Id of action hook installed for scroll bars. */
3970 static XtActionHookId action_hook_id
;
3972 static Boolean xaw3d_arrow_scroll
;
3974 /* Whether the drag scrolling maintains the mouse at the top of the
3975 thumb. If not, resizing the thumb needs to be done more carefully
3976 to avoid jerkyness. */
3978 static Boolean xaw3d_pick_top
;
3980 extern void set_vertical_scroll_bar
P_ ((struct window
*));
3982 /* Action hook installed via XtAppAddActionHook when toolkit scroll
3983 bars are used.. The hook is responsible for detecting when
3984 the user ends an interaction with the scroll bar, and generates
3985 a `end-scroll' SCROLL_BAR_CLICK_EVENT' event if so. */
3988 xt_action_hook (widget
, client_data
, action_name
, event
, params
,
3991 XtPointer client_data
;
3995 Cardinal
*num_params
;
4001 scroll_bar_p
= XmIsScrollBar (widget
);
4002 end_action
= "Release";
4003 #else /* !USE_MOTIF i.e. use Xaw */
4004 scroll_bar_p
= XtIsSubclass (widget
, scrollbarWidgetClass
);
4005 end_action
= "EndScroll";
4006 #endif /* USE_MOTIF */
4009 && strcmp (action_name
, end_action
) == 0
4010 && WINDOWP (window_being_scrolled
))
4014 x_send_scroll_bar_event (window_being_scrolled
,
4015 scroll_bar_end_scroll
, 0, 0);
4016 w
= XWINDOW (window_being_scrolled
);
4018 if (!NILP (XSCROLL_BAR (w
->vertical_scroll_bar
)->dragging
))
4020 XSCROLL_BAR (w
->vertical_scroll_bar
)->dragging
= Qnil
;
4021 /* The thumb size is incorrect while dragging: fix it. */
4022 set_vertical_scroll_bar (w
);
4024 window_being_scrolled
= Qnil
;
4025 last_scroll_bar_part
= -1;
4027 /* Xt timeouts no longer needed. */
4028 toolkit_scroll_bar_interaction
= 0;
4031 #endif /* not USE_GTK */
4033 /* A vector of windows used for communication between
4034 x_send_scroll_bar_event and x_scroll_bar_to_input_event. */
4036 static struct window
**scroll_bar_windows
;
4037 static int scroll_bar_windows_size
;
4040 /* Send a client message with message type Xatom_Scrollbar for a
4041 scroll action to the frame of WINDOW. PART is a value identifying
4042 the part of the scroll bar that was clicked on. PORTION is the
4043 amount to scroll of a whole of WHOLE. */
4046 x_send_scroll_bar_event (window
, part
, portion
, whole
)
4048 int part
, portion
, whole
;
4051 XClientMessageEvent
*ev
= (XClientMessageEvent
*) &event
;
4052 struct window
*w
= XWINDOW (window
);
4053 struct frame
*f
= XFRAME (w
->frame
);
4058 /* Construct a ClientMessage event to send to the frame. */
4059 ev
->type
= ClientMessage
;
4060 ev
->message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_Scrollbar
;
4061 ev
->display
= FRAME_X_DISPLAY (f
);
4062 ev
->window
= FRAME_X_WINDOW (f
);
4065 /* We can only transfer 32 bits in the XClientMessageEvent, which is
4066 not enough to store a pointer or Lisp_Object on a 64 bit system.
4067 So, store the window in scroll_bar_windows and pass the index
4068 into that array in the event. */
4069 for (i
= 0; i
< scroll_bar_windows_size
; ++i
)
4070 if (scroll_bar_windows
[i
] == NULL
)
4073 if (i
== scroll_bar_windows_size
)
4075 int new_size
= max (10, 2 * scroll_bar_windows_size
);
4076 size_t nbytes
= new_size
* sizeof *scroll_bar_windows
;
4077 size_t old_nbytes
= scroll_bar_windows_size
* sizeof *scroll_bar_windows
;
4079 scroll_bar_windows
= (struct window
**) xrealloc (scroll_bar_windows
,
4081 bzero (&scroll_bar_windows
[i
], nbytes
- old_nbytes
);
4082 scroll_bar_windows_size
= new_size
;
4085 scroll_bar_windows
[i
] = w
;
4086 ev
->data
.l
[0] = (long) i
;
4087 ev
->data
.l
[1] = (long) part
;
4088 ev
->data
.l
[2] = (long) 0;
4089 ev
->data
.l
[3] = (long) portion
;
4090 ev
->data
.l
[4] = (long) whole
;
4092 /* Make Xt timeouts work while the scroll bar is active. */
4093 toolkit_scroll_bar_interaction
= 1;
4095 /* Setting the event mask to zero means that the message will
4096 be sent to the client that created the window, and if that
4097 window no longer exists, no event will be sent. */
4098 XSendEvent (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), False
, 0, &event
);
4103 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
4107 x_scroll_bar_to_input_event (event
, ievent
)
4109 struct input_event
*ievent
;
4111 XClientMessageEvent
*ev
= (XClientMessageEvent
*) event
;
4116 w
= scroll_bar_windows
[ev
->data
.l
[0]];
4117 scroll_bar_windows
[ev
->data
.l
[0]] = NULL
;
4119 XSETWINDOW (window
, w
);
4120 f
= XFRAME (w
->frame
);
4122 ievent
->kind
= SCROLL_BAR_CLICK_EVENT
;
4123 ievent
->frame_or_window
= window
;
4126 ievent
->timestamp
= CurrentTime
;
4128 ievent
->timestamp
= XtLastTimestampProcessed (FRAME_X_DISPLAY (f
));
4130 ievent
->part
= ev
->data
.l
[1];
4131 ievent
->code
= ev
->data
.l
[2];
4132 ievent
->x
= make_number ((int) ev
->data
.l
[3]);
4133 ievent
->y
= make_number ((int) ev
->data
.l
[4]);
4134 ievent
->modifiers
= 0;
4140 /* Minimum and maximum values used for Motif scroll bars. */
4142 #define XM_SB_MAX 10000000
4145 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
4146 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
4147 CALL_DATA is a pointer to a XmScrollBarCallbackStruct. */
4150 xm_scroll_callback (widget
, client_data
, call_data
)
4152 XtPointer client_data
, call_data
;
4154 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
4155 XmScrollBarCallbackStruct
*cs
= (XmScrollBarCallbackStruct
*) call_data
;
4156 int part
= -1, whole
= 0, portion
= 0;
4160 case XmCR_DECREMENT
:
4161 bar
->dragging
= Qnil
;
4162 part
= scroll_bar_up_arrow
;
4165 case XmCR_INCREMENT
:
4166 bar
->dragging
= Qnil
;
4167 part
= scroll_bar_down_arrow
;
4170 case XmCR_PAGE_DECREMENT
:
4171 bar
->dragging
= Qnil
;
4172 part
= scroll_bar_above_handle
;
4175 case XmCR_PAGE_INCREMENT
:
4176 bar
->dragging
= Qnil
;
4177 part
= scroll_bar_below_handle
;
4181 bar
->dragging
= Qnil
;
4182 part
= scroll_bar_to_top
;
4185 case XmCR_TO_BOTTOM
:
4186 bar
->dragging
= Qnil
;
4187 part
= scroll_bar_to_bottom
;
4194 /* Get the slider size. */
4196 XtVaGetValues (widget
, XmNsliderSize
, &slider_size
, NULL
);
4199 whole
= XM_SB_MAX
- slider_size
;
4200 portion
= min (cs
->value
, whole
);
4201 part
= scroll_bar_handle
;
4202 bar
->dragging
= make_number (cs
->value
);
4206 case XmCR_VALUE_CHANGED
:
4212 window_being_scrolled
= bar
->window
;
4213 last_scroll_bar_part
= part
;
4214 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
4219 #else /* !USE_MOTIF, i.e. Xaw or GTK */
4221 /* Scroll bar callback for GTK scroll bars. WIDGET is the scroll
4222 bar widget. DATA is a pointer to the scroll_bar structure. */
4225 xg_scroll_callback (widget
, data
)
4229 struct scroll_bar
*bar
= (struct scroll_bar
*) data
;
4235 int part
= -1, whole
= 0, portion
= 0;
4236 GtkAdjustment
*adj
= GTK_ADJUSTMENT (gtk_range_get_adjustment (widget
));
4238 if (xg_ignore_gtk_scrollbar
) return;
4240 position
= gtk_adjustment_get_value (adj
);
4242 p
= g_object_get_data (G_OBJECT (widget
), XG_LAST_SB_DATA
);
4245 p
= (gdouble
*) xmalloc (sizeof (gdouble
));
4247 g_object_set_data (G_OBJECT (widget
), XG_LAST_SB_DATA
, p
);
4253 diff
= (int) (position
- previous
);
4255 if (diff
== (int) adj
->step_increment
)
4257 part
= scroll_bar_down_arrow
;
4258 bar
->dragging
= Qnil
;
4260 else if (-diff
== (int) adj
->step_increment
)
4262 part
= scroll_bar_up_arrow
;
4263 bar
->dragging
= Qnil
;
4265 else if (diff
== (int) adj
->page_increment
)
4267 part
= scroll_bar_below_handle
;
4268 bar
->dragging
= Qnil
;
4270 else if (-diff
== (int) adj
->page_increment
)
4272 part
= scroll_bar_above_handle
;
4273 bar
->dragging
= Qnil
;
4277 part
= scroll_bar_handle
;
4278 whole
= adj
->upper
- adj
->page_size
;
4279 portion
= min ((int)position
, whole
);
4280 bar
->dragging
= make_number ((int)portion
);
4285 window_being_scrolled
= bar
->window
;
4286 last_scroll_bar_part
= part
;
4287 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
4291 #else /* not USE_GTK */
4293 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
4294 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
4295 scroll bar struct. CALL_DATA is a pointer to a float saying where
4299 xaw_jump_callback (widget
, client_data
, call_data
)
4301 XtPointer client_data
, call_data
;
4303 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
4304 float top
= *(float *) call_data
;
4306 int whole
, portion
, height
;
4309 /* Get the size of the thumb, a value between 0 and 1. */
4311 XtVaGetValues (widget
, XtNshown
, &shown
, XtNheight
, &height
, NULL
);
4315 portion
= shown
< 1 ? top
* whole
: 0;
4317 if (shown
< 1 && (abs (top
+ shown
- 1) < 1.0/height
))
4318 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
4319 the bottom, so we force the scrolling whenever we see that we're
4320 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
4321 we try to ensure that we always stay two pixels away from the
4323 part
= scroll_bar_down_arrow
;
4325 part
= scroll_bar_handle
;
4327 window_being_scrolled
= bar
->window
;
4328 bar
->dragging
= make_number (portion
);
4329 last_scroll_bar_part
= part
;
4330 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
4334 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
4335 i.e. line or page up or down. WIDGET is the Xaw scroll bar
4336 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
4337 the scroll bar. CALL_DATA is an integer specifying the action that
4338 has taken place. Its magnitude is in the range 0..height of the
4339 scroll bar. Negative values mean scroll towards buffer start.
4340 Values < height of scroll bar mean line-wise movement. */
4343 xaw_scroll_callback (widget
, client_data
, call_data
)
4345 XtPointer client_data
, call_data
;
4347 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
4348 /* The position really is stored cast to a pointer. */
4349 int position
= (long) call_data
;
4353 /* Get the height of the scroll bar. */
4355 XtVaGetValues (widget
, XtNheight
, &height
, NULL
);
4358 if (abs (position
) >= height
)
4359 part
= (position
< 0) ? scroll_bar_above_handle
: scroll_bar_below_handle
;
4361 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
4362 it maps line-movement to call_data = max(5, height/20). */
4363 else if (xaw3d_arrow_scroll
&& abs (position
) <= max (5, height
/ 20))
4364 part
= (position
< 0) ? scroll_bar_up_arrow
: scroll_bar_down_arrow
;
4366 part
= scroll_bar_move_ratio
;
4368 window_being_scrolled
= bar
->window
;
4369 bar
->dragging
= Qnil
;
4370 last_scroll_bar_part
= part
;
4371 x_send_scroll_bar_event (bar
->window
, part
, position
, height
);
4374 #endif /* not USE_GTK */
4375 #endif /* not USE_MOTIF */
4377 #define SCROLL_BAR_NAME "verticalScrollBar"
4379 /* Create the widget for scroll bar BAR on frame F. Record the widget
4380 and X window of the scroll bar in BAR. */
4384 x_create_toolkit_scroll_bar (f
, bar
)
4386 struct scroll_bar
*bar
;
4388 char *scroll_bar_name
= SCROLL_BAR_NAME
;
4391 xg_create_scroll_bar (f
, bar
, G_CALLBACK (xg_scroll_callback
),
4396 #else /* not USE_GTK */
4399 x_create_toolkit_scroll_bar (f
, bar
)
4401 struct scroll_bar
*bar
;
4407 char *scroll_bar_name
= SCROLL_BAR_NAME
;
4408 unsigned long pixel
;
4413 /* Set resources. Create the widget. */
4414 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
4415 XtSetArg (av
[ac
], XmNminimum
, 0); ++ac
;
4416 XtSetArg (av
[ac
], XmNmaximum
, XM_SB_MAX
); ++ac
;
4417 XtSetArg (av
[ac
], XmNorientation
, XmVERTICAL
); ++ac
;
4418 XtSetArg (av
[ac
], XmNprocessingDirection
, XmMAX_ON_BOTTOM
), ++ac
;
4419 XtSetArg (av
[ac
], XmNincrement
, 1); ++ac
;
4420 XtSetArg (av
[ac
], XmNpageIncrement
, 1); ++ac
;
4422 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
4425 XtSetArg (av
[ac
], XmNforeground
, pixel
);
4429 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4432 XtSetArg (av
[ac
], XmNbackground
, pixel
);
4436 widget
= XmCreateScrollBar (f
->output_data
.x
->edit_widget
,
4437 scroll_bar_name
, av
, ac
);
4439 /* Add one callback for everything that can happen. */
4440 XtAddCallback (widget
, XmNdecrementCallback
, xm_scroll_callback
,
4442 XtAddCallback (widget
, XmNdragCallback
, xm_scroll_callback
,
4444 XtAddCallback (widget
, XmNincrementCallback
, xm_scroll_callback
,
4446 XtAddCallback (widget
, XmNpageDecrementCallback
, xm_scroll_callback
,
4448 XtAddCallback (widget
, XmNpageIncrementCallback
, xm_scroll_callback
,
4450 XtAddCallback (widget
, XmNtoBottomCallback
, xm_scroll_callback
,
4452 XtAddCallback (widget
, XmNtoTopCallback
, xm_scroll_callback
,
4455 /* Realize the widget. Only after that is the X window created. */
4456 XtRealizeWidget (widget
);
4458 /* Set the cursor to an arrow. I didn't find a resource to do that.
4459 And I'm wondering why it hasn't an arrow cursor by default. */
4460 XDefineCursor (XtDisplay (widget
), XtWindow (widget
),
4461 f
->output_data
.x
->nontext_cursor
);
4463 #else /* !USE_MOTIF i.e. use Xaw */
4465 /* Set resources. Create the widget. The background of the
4466 Xaw3d scroll bar widget is a little bit light for my taste.
4467 We don't alter it here to let users change it according
4468 to their taste with `emacs*verticalScrollBar.background: xxx'. */
4469 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
4470 XtSetArg (av
[ac
], XtNorientation
, XtorientVertical
); ++ac
;
4471 /* For smoother scrolling with Xaw3d -sm */
4472 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
4474 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
4477 XtSetArg (av
[ac
], XtNforeground
, pixel
);
4481 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4484 XtSetArg (av
[ac
], XtNbackground
, pixel
);
4488 /* Top/bottom shadow colors. */
4490 /* Allocate them, if necessary. */
4491 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
== -1)
4493 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4494 if (!x_alloc_lighter_color (f
, FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
4495 &pixel
, 1.2, 0x8000))
4497 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= pixel
;
4499 if (f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
== -1)
4501 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4502 if (!x_alloc_lighter_color (f
, FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
4503 &pixel
, 0.6, 0x4000))
4505 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= pixel
;
4508 /* Tell the toolkit about them. */
4509 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
== -1
4510 || f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
== -1)
4511 /* We tried to allocate a color for the top/bottom shadow, and
4512 failed, so tell Xaw3d to use dithering instead. */
4514 XtSetArg (av
[ac
], XtNbeNiceToColormap
, True
);
4518 /* Tell what colors Xaw3d should use for the top/bottom shadow, to
4519 be more consistent with other emacs 3d colors, and since Xaw3d is
4520 not good at dealing with allocation failure. */
4522 /* This tells Xaw3d to use real colors instead of dithering for
4524 XtSetArg (av
[ac
], XtNbeNiceToColormap
, False
);
4527 /* Specify the colors. */
4528 pixel
= f
->output_data
.x
->scroll_bar_top_shadow_pixel
;
4531 XtSetArg (av
[ac
], "topShadowPixel", pixel
);
4534 pixel
= f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
;
4537 XtSetArg (av
[ac
], "bottomShadowPixel", pixel
);
4542 widget
= XtCreateWidget (scroll_bar_name
, scrollbarWidgetClass
,
4543 f
->output_data
.x
->edit_widget
, av
, ac
);
4547 char *val
= initial
;
4548 XtVaGetValues (widget
, XtNscrollVCursor
, (XtPointer
) &val
,
4549 XtNpickTop
, (XtPointer
) &xaw3d_pick_top
, NULL
);
4551 { /* ARROW_SCROLL */
4552 xaw3d_arrow_scroll
= True
;
4553 /* Isn't that just a personal preference ? -sm */
4554 XtVaSetValues (widget
, XtNcursorName
, "top_left_arrow", NULL
);
4558 /* Define callbacks. */
4559 XtAddCallback (widget
, XtNjumpProc
, xaw_jump_callback
, (XtPointer
) bar
);
4560 XtAddCallback (widget
, XtNscrollProc
, xaw_scroll_callback
,
4563 /* Realize the widget. Only after that is the X window created. */
4564 XtRealizeWidget (widget
);
4566 #endif /* !USE_MOTIF */
4568 /* Install an action hook that lets us detect when the user
4569 finishes interacting with a scroll bar. */
4570 if (action_hook_id
== 0)
4571 action_hook_id
= XtAppAddActionHook (Xt_app_con
, xt_action_hook
, 0);
4573 /* Remember X window and widget in the scroll bar vector. */
4574 SET_SCROLL_BAR_X_WIDGET (bar
, widget
);
4575 xwindow
= XtWindow (widget
);
4576 SET_SCROLL_BAR_X_WINDOW (bar
, xwindow
);
4580 #endif /* not USE_GTK */
4583 /* Set the thumb size and position of scroll bar BAR. We are currently
4584 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4588 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4589 struct scroll_bar
*bar
;
4590 int portion
, position
, whole
;
4592 xg_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
4595 #else /* not USE_GTK */
4597 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4598 struct scroll_bar
*bar
;
4599 int portion
, position
, whole
;
4601 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4602 Widget widget
= SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
);
4609 /* We use an estimate of 30 chars per line rather than the real
4610 `portion' value. This has the disadvantage that the thumb size
4611 is not very representative, but it makes our life a lot easier.
4612 Otherwise, we have to constantly adjust the thumb size, which
4613 we can't always do quickly enough: while dragging, the size of
4614 the thumb might prevent the user from dragging the thumb all the
4615 way to the end. but Motif and some versions of Xaw3d don't allow
4616 updating the thumb size while dragging. Also, even if we can update
4617 its size, the update will often happen too late.
4618 If you don't believe it, check out revision 1.650 of xterm.c to see
4619 what hoops we were going through and the still poor behavior we got. */
4620 portion
= WINDOW_TOTAL_LINES (XWINDOW (bar
->window
)) * 30;
4621 /* When the thumb is at the bottom, position == whole.
4622 So we need to increase `whole' to make space for the thumb. */
4629 top
= (float) position
/ whole
;
4630 shown
= (float) portion
/ whole
;
4633 if (NILP (bar
->dragging
))
4637 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
4638 is the scroll bar's maximum and MIN is the scroll bar's minimum
4640 size
= shown
* XM_SB_MAX
;
4641 size
= min (size
, XM_SB_MAX
);
4642 size
= max (size
, 1);
4644 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
4645 value
= top
* XM_SB_MAX
;
4646 value
= min (value
, XM_SB_MAX
- size
);
4648 XmScrollBarSetValues (widget
, value
, size
, 0, 0, False
);
4650 #else /* !USE_MOTIF i.e. use Xaw */
4656 top
= (float) position
/ whole
;
4657 shown
= (float) portion
/ whole
;
4661 float old_top
, old_shown
;
4663 XtVaGetValues (widget
,
4664 XtNtopOfThumb
, &old_top
,
4665 XtNshown
, &old_shown
,
4669 /* Massage the top+shown values. */
4670 if (NILP (bar
->dragging
) || last_scroll_bar_part
== scroll_bar_down_arrow
)
4671 top
= max (0, min (1, top
));
4674 /* Keep two pixels available for moving the thumb down. */
4675 shown
= max (0, min (1 - top
- (2.0 / height
), shown
));
4677 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
4678 check that your system's configuration file contains a define
4679 for `NARROWPROTO'. See s/freebsd.h for an example. */
4680 if (top
!= old_top
|| shown
!= old_shown
)
4682 if (NILP (bar
->dragging
))
4683 XawScrollbarSetThumb (widget
, top
, shown
);
4687 ScrollbarWidget sb
= (ScrollbarWidget
) widget
;
4688 int scroll_mode
= 0;
4690 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
4691 if (xaw3d_arrow_scroll
)
4693 /* Xaw3d stupidly ignores resize requests while dragging
4694 so we have to make it believe it's not in dragging mode. */
4695 scroll_mode
= sb
->scrollbar
.scroll_mode
;
4696 if (scroll_mode
== 2)
4697 sb
->scrollbar
.scroll_mode
= 0;
4700 /* Try to make the scrolling a tad smoother. */
4701 if (!xaw3d_pick_top
)
4702 shown
= min (shown
, old_shown
);
4704 XawScrollbarSetThumb (widget
, top
, shown
);
4707 if (xaw3d_arrow_scroll
&& scroll_mode
== 2)
4708 sb
->scrollbar
.scroll_mode
= scroll_mode
;
4713 #endif /* !USE_MOTIF */
4717 #endif /* not USE_GTK */
4719 #endif /* USE_TOOLKIT_SCROLL_BARS */
4723 /************************************************************************
4724 Scroll bars, general
4725 ************************************************************************/
4727 /* Create a scroll bar and return the scroll bar vector for it. W is
4728 the Emacs window on which to create the scroll bar. TOP, LEFT,
4729 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4732 static struct scroll_bar
*
4733 x_scroll_bar_create (w
, top
, left
, width
, height
)
4735 int top
, left
, width
, height
;
4737 struct frame
*f
= XFRAME (w
->frame
);
4738 struct scroll_bar
*bar
4739 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4743 #ifdef USE_TOOLKIT_SCROLL_BARS
4744 x_create_toolkit_scroll_bar (f
, bar
);
4745 #else /* not USE_TOOLKIT_SCROLL_BARS */
4747 XSetWindowAttributes a
;
4751 a
.background_pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4752 if (a
.background_pixel
== -1)
4753 a
.background_pixel
= f
->output_data
.x
->background_pixel
;
4755 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
4756 | ButtonMotionMask
| PointerMotionHintMask
4758 a
.cursor
= FRAME_X_DISPLAY_INFO (f
)->vertical_scroll_bar_cursor
;
4760 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
4762 /* Clear the area of W that will serve as a scroll bar. This is
4763 for the case that a window has been split horizontally. In
4764 this case, no clear_frame is generated to reduce flickering. */
4765 if (width
> 0 && height
> 0)
4766 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4768 window_box_height (w
), False
);
4770 window
= XCreateWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4771 /* Position and size of scroll bar. */
4772 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
4774 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4776 /* Border width, depth, class, and visual. */
4783 SET_SCROLL_BAR_X_WINDOW (bar
, window
);
4785 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4787 XSETWINDOW (bar
->window
, w
);
4788 XSETINT (bar
->top
, top
);
4789 XSETINT (bar
->left
, left
);
4790 XSETINT (bar
->width
, width
);
4791 XSETINT (bar
->height
, height
);
4792 XSETINT (bar
->start
, 0);
4793 XSETINT (bar
->end
, 0);
4794 bar
->dragging
= Qnil
;
4796 /* Add bar to its frame's list of scroll bars. */
4797 bar
->next
= FRAME_SCROLL_BARS (f
);
4799 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4800 if (!NILP (bar
->next
))
4801 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4803 /* Map the window/widget. */
4804 #ifdef USE_TOOLKIT_SCROLL_BARS
4807 xg_update_scrollbar_pos (f
,
4808 SCROLL_BAR_X_WINDOW (bar
),
4810 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
4811 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4815 xg_show_scroll_bar (SCROLL_BAR_X_WINDOW (bar
));
4816 #else /* not USE_GTK */
4817 Widget scroll_bar
= SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
);
4818 XtConfigureWidget (scroll_bar
,
4819 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
4821 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4822 max (height
, 1), 0);
4823 XtMapWidget (scroll_bar
);
4824 #endif /* not USE_GTK */
4826 #else /* not USE_TOOLKIT_SCROLL_BARS */
4827 XMapRaised (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
4828 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4835 /* Draw BAR's handle in the proper position.
4837 If the handle is already drawn from START to END, don't bother
4838 redrawing it, unless REBUILD is non-zero; in that case, always
4839 redraw it. (REBUILD is handy for drawing the handle after expose
4842 Normally, we want to constrain the start and end of the handle to
4843 fit inside its rectangle, but if the user is dragging the scroll
4844 bar handle, we want to let them drag it down all the way, so that
4845 the bar's top is as far down as it goes; otherwise, there's no way
4846 to move to the very end of the buffer. */
4848 #ifndef USE_TOOLKIT_SCROLL_BARS
4851 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
4852 struct scroll_bar
*bar
;
4856 int dragging
= ! NILP (bar
->dragging
);
4857 Window w
= SCROLL_BAR_X_WINDOW (bar
);
4858 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4859 GC gc
= f
->output_data
.x
->normal_gc
;
4861 /* If the display is already accurate, do nothing. */
4863 && start
== XINT (bar
->start
)
4864 && end
== XINT (bar
->end
))
4870 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f
, XINT (bar
->width
));
4871 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
4872 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4874 /* Make sure the values are reasonable, and try to preserve
4875 the distance between start and end. */
4877 int length
= end
- start
;
4881 else if (start
> top_range
)
4883 end
= start
+ length
;
4887 else if (end
> top_range
&& ! dragging
)
4891 /* Store the adjusted setting in the scroll bar. */
4892 XSETINT (bar
->start
, start
);
4893 XSETINT (bar
->end
, end
);
4895 /* Clip the end position, just for display. */
4896 if (end
> top_range
)
4899 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
4900 below top positions, to make sure the handle is always at least
4901 that many pixels tall. */
4902 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4904 /* Draw the empty space above the handle. Note that we can't clear
4905 zero-height areas; that means "clear to end of window." */
4907 x_clear_area (FRAME_X_DISPLAY (f
), w
,
4908 /* x, y, width, height, and exposures. */
4909 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
4910 VERTICAL_SCROLL_BAR_TOP_BORDER
,
4911 inside_width
, start
,
4914 /* Change to proper foreground color if one is specified. */
4915 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
4916 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
4917 f
->output_data
.x
->scroll_bar_foreground_pixel
);
4919 /* Draw the handle itself. */
4920 XFillRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
4921 /* x, y, width, height */
4922 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
4923 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
4924 inside_width
, end
- start
);
4926 /* Restore the foreground color of the GC if we changed it above. */
4927 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
4928 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
4929 f
->output_data
.x
->foreground_pixel
);
4931 /* Draw the empty space below the handle. Note that we can't
4932 clear zero-height areas; that means "clear to end of window." */
4933 if (end
< inside_height
)
4934 x_clear_area (FRAME_X_DISPLAY (f
), w
,
4935 /* x, y, width, height, and exposures. */
4936 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
4937 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
4938 inside_width
, inside_height
- end
,
4946 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4948 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4952 x_scroll_bar_remove (bar
)
4953 struct scroll_bar
*bar
;
4955 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4958 #ifdef USE_TOOLKIT_SCROLL_BARS
4960 xg_remove_scroll_bar (f
, SCROLL_BAR_X_WINDOW (bar
));
4961 #else /* not USE_GTK */
4962 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
));
4963 #endif /* not USE_GTK */
4965 XDestroyWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
4968 /* Disassociate this scroll bar from its window. */
4969 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
4975 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4976 that we are displaying PORTION characters out of a total of WHOLE
4977 characters, starting at POSITION. If WINDOW has no scroll bar,
4981 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
4983 int portion
, whole
, position
;
4985 struct frame
*f
= XFRAME (w
->frame
);
4986 struct scroll_bar
*bar
;
4987 int top
, height
, left
, sb_left
, width
, sb_width
;
4988 int window_y
, window_height
;
4990 /* Get window dimensions. */
4991 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
4993 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
4994 height
= window_height
;
4996 /* Compute the left edge of the scroll bar area. */
4997 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
4999 /* Compute the width of the scroll bar which might be less than
5000 the width of the area reserved for the scroll bar. */
5001 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
5002 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
5006 /* Compute the left edge of the scroll bar. */
5007 #ifdef USE_TOOLKIT_SCROLL_BARS
5008 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
5009 sb_left
= left
+ width
- sb_width
- (width
- sb_width
) / 2;
5011 sb_left
= left
+ (width
- sb_width
) / 2;
5013 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
5014 sb_left
= left
+ width
- sb_width
;
5019 /* Does the scroll bar exist yet? */
5020 if (NILP (w
->vertical_scroll_bar
))
5022 if (width
> 0 && height
> 0)
5025 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5026 left
, top
, width
, height
, False
);
5030 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
);
5034 /* It may just need to be moved and resized. */
5035 unsigned int mask
= 0;
5037 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
5041 if (sb_left
!= XINT (bar
->left
))
5043 if (top
!= XINT (bar
->top
))
5045 if (sb_width
!= XINT (bar
->width
))
5047 if (height
!= XINT (bar
->height
))
5050 #ifdef USE_TOOLKIT_SCROLL_BARS
5054 xg_update_scrollbar_pos (f
,
5055 SCROLL_BAR_X_WINDOW (bar
),
5057 sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5058 sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5062 #else /* not USE_GTK */
5064 /* Since toolkit scroll bars are smaller than the space reserved
5065 for them on the frame, we have to clear "under" them. */
5066 if (width
> 0 && height
> 0)
5067 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5068 left
, top
, width
, height
, False
);
5069 /* Move/size the scroll bar widget. */
5071 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
),
5072 sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5074 sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5075 max (height
, 1), 0);
5077 #endif /* not USE_GTK */
5078 #else /* not USE_TOOLKIT_SCROLL_BARS */
5080 /* Clear areas not covered by the scroll bar because of
5081 VERTICAL_SCROLL_BAR_WIDTH_TRIM. */
5082 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM
)
5084 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5085 left
, top
, VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5087 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5088 left
+ width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5089 top
, VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5093 /* Clear areas not covered by the scroll bar because it's not as
5094 wide as the area reserved for it. This makes sure a
5095 previous mode line display is cleared after C-x 2 C-x 1, for
5098 int area_width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
5099 int rest
= area_width
- sb_width
;
5100 if (rest
> 0 && height
> 0)
5102 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
5103 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5104 left
+ area_width
- rest
, top
,
5105 rest
, height
, False
);
5107 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5108 left
, top
, rest
, height
, False
);
5112 /* Move/size the scroll bar window. */
5117 wc
.x
= sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
5119 wc
.width
= sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2;
5121 XConfigureWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
),
5125 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5127 /* Remember new settings. */
5128 XSETINT (bar
->left
, sb_left
);
5129 XSETINT (bar
->top
, top
);
5130 XSETINT (bar
->width
, sb_width
);
5131 XSETINT (bar
->height
, height
);
5136 #ifdef USE_TOOLKIT_SCROLL_BARS
5137 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
5138 #else /* not USE_TOOLKIT_SCROLL_BARS */
5139 /* Set the scroll bar's current state, unless we're currently being
5141 if (NILP (bar
->dragging
))
5143 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
5146 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
5149 int start
= ((double) position
* top_range
) / whole
;
5150 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
5151 x_scroll_bar_set_handle (bar
, start
, end
, 0);
5154 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5156 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
5160 /* The following three hooks are used when we're doing a thorough
5161 redisplay of the frame. We don't explicitly know which scroll bars
5162 are going to be deleted, because keeping track of when windows go
5163 away is a real pain - "Can you say set-window-configuration, boys
5164 and girls?" Instead, we just assert at the beginning of redisplay
5165 that *all* scroll bars are to be removed, and then save a scroll bar
5166 from the fiery pit when we actually redisplay its window. */
5168 /* Arrange for all scroll bars on FRAME to be removed at the next call
5169 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5170 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5173 XTcondemn_scroll_bars (frame
)
5176 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5177 while (! NILP (FRAME_SCROLL_BARS (frame
)))
5180 bar
= FRAME_SCROLL_BARS (frame
);
5181 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
5182 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
5183 XSCROLL_BAR (bar
)->prev
= Qnil
;
5184 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
5185 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
5186 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
5191 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5192 Note that WINDOW isn't necessarily condemned at all. */
5195 XTredeem_scroll_bar (window
)
5196 struct window
*window
;
5198 struct scroll_bar
*bar
;
5201 /* We can't redeem this window's scroll bar if it doesn't have one. */
5202 if (NILP (window
->vertical_scroll_bar
))
5205 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
5207 /* Unlink it from the condemned list. */
5208 f
= XFRAME (WINDOW_FRAME (window
));
5209 if (NILP (bar
->prev
))
5211 /* If the prev pointer is nil, it must be the first in one of
5213 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
5214 /* It's not condemned. Everything's fine. */
5216 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
5217 window
->vertical_scroll_bar
))
5218 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
5220 /* If its prev pointer is nil, it must be at the front of
5221 one or the other! */
5225 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
5227 if (! NILP (bar
->next
))
5228 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
5230 bar
->next
= FRAME_SCROLL_BARS (f
);
5232 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5233 if (! NILP (bar
->next
))
5234 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5237 /* Remove all scroll bars on FRAME that haven't been saved since the
5238 last call to `*condemn_scroll_bars_hook'. */
5241 XTjudge_scroll_bars (f
)
5244 Lisp_Object bar
, next
;
5246 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
5248 /* Clear out the condemned list now so we won't try to process any
5249 more events on the hapless scroll bars. */
5250 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
5252 for (; ! NILP (bar
); bar
= next
)
5254 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
5256 x_scroll_bar_remove (b
);
5259 b
->next
= b
->prev
= Qnil
;
5262 /* Now there should be no references to the condemned scroll bars,
5263 and they should get garbage-collected. */
5267 #ifndef USE_TOOLKIT_SCROLL_BARS
5268 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
5269 is a no-op when using toolkit scroll bars.
5271 This may be called from a signal handler, so we have to ignore GC
5275 x_scroll_bar_expose (bar
, event
)
5276 struct scroll_bar
*bar
;
5279 Window w
= SCROLL_BAR_X_WINDOW (bar
);
5280 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5281 GC gc
= f
->output_data
.x
->normal_gc
;
5282 int width_trim
= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
5286 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
5288 /* Draw a one-pixel border just inside the edges of the scroll bar. */
5289 XDrawRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
5291 /* x, y, width, height */
5293 XINT (bar
->width
) - 1 - width_trim
- width_trim
,
5294 XINT (bar
->height
) - 1);
5299 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5301 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5302 is set to something other than NO_EVENT, it is enqueued.
5304 This may be called from a signal handler, so we have to ignore GC
5309 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
5310 struct scroll_bar
*bar
;
5312 struct input_event
*emacs_event
;
5314 if (! GC_WINDOWP (bar
->window
))
5317 emacs_event
->kind
= SCROLL_BAR_CLICK_EVENT
;
5318 emacs_event
->code
= event
->xbutton
.button
- Button1
;
5319 emacs_event
->modifiers
5320 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
5321 (XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))),
5322 event
->xbutton
.state
)
5323 | (event
->type
== ButtonRelease
5326 emacs_event
->frame_or_window
= bar
->window
;
5327 emacs_event
->arg
= Qnil
;
5328 emacs_event
->timestamp
= event
->xbutton
.time
;
5331 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5333 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
5336 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5337 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
5340 if (y
> top_range
) y
= top_range
;
5342 if (y
< XINT (bar
->start
))
5343 emacs_event
->part
= scroll_bar_above_handle
;
5344 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5345 emacs_event
->part
= scroll_bar_handle
;
5347 emacs_event
->part
= scroll_bar_below_handle
;
5349 /* Just because the user has clicked on the handle doesn't mean
5350 they want to drag it. Lisp code needs to be able to decide
5351 whether or not we're dragging. */
5353 /* If the user has just clicked on the handle, record where they're
5355 if (event
->type
== ButtonPress
5356 && emacs_event
->part
== scroll_bar_handle
)
5357 XSETINT (bar
->dragging
, y
- XINT (bar
->start
));
5360 #ifndef USE_TOOLKIT_SCROLL_BARS
5361 /* If the user has released the handle, set it to its final position. */
5362 if (event
->type
== ButtonRelease
5363 && ! NILP (bar
->dragging
))
5365 int new_start
= y
- XINT (bar
->dragging
);
5366 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5368 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5369 bar
->dragging
= Qnil
;
5373 /* Same deal here as the other #if 0. */
5375 /* Clicks on the handle are always reported as occurring at the top of
5377 if (emacs_event
->part
== scroll_bar_handle
)
5378 emacs_event
->x
= bar
->start
;
5380 XSETINT (emacs_event
->x
, y
);
5382 XSETINT (emacs_event
->x
, y
);
5385 XSETINT (emacs_event
->y
, top_range
);
5389 #ifndef USE_TOOLKIT_SCROLL_BARS
5391 /* Handle some mouse motion while someone is dragging the scroll bar.
5393 This may be called from a signal handler, so we have to ignore GC
5397 x_scroll_bar_note_movement (bar
, event
)
5398 struct scroll_bar
*bar
;
5401 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5403 last_mouse_movement_time
= event
->xmotion
.time
;
5406 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5408 /* If we're dragging the bar, display it. */
5409 if (! GC_NILP (bar
->dragging
))
5411 /* Where should the handle be now? */
5412 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
5414 if (new_start
!= XINT (bar
->start
))
5416 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5418 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5423 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5425 /* Return information to the user about the current position of the mouse
5426 on the scroll bar. */
5429 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5431 Lisp_Object
*bar_window
;
5432 enum scroll_bar_part
*part
;
5434 unsigned long *time
;
5436 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5437 Window w
= SCROLL_BAR_X_WINDOW (bar
);
5438 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5440 Window dummy_window
;
5442 unsigned int dummy_mask
;
5446 /* Get the mouse's position relative to the scroll bar window, and
5448 if (! XQueryPointer (FRAME_X_DISPLAY (f
), w
,
5450 /* Root, child, root x and root y. */
5451 &dummy_window
, &dummy_window
,
5452 &dummy_coord
, &dummy_coord
,
5454 /* Position relative to scroll bar. */
5457 /* Mouse buttons and modifier keys. */
5464 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
5467 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5469 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5471 if (! NILP (bar
->dragging
))
5472 win_y
-= XINT (bar
->dragging
);
5476 if (win_y
> top_range
)
5480 *bar_window
= bar
->window
;
5482 if (! NILP (bar
->dragging
))
5483 *part
= scroll_bar_handle
;
5484 else if (win_y
< XINT (bar
->start
))
5485 *part
= scroll_bar_above_handle
;
5486 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5487 *part
= scroll_bar_handle
;
5489 *part
= scroll_bar_below_handle
;
5491 XSETINT (*x
, win_y
);
5492 XSETINT (*y
, top_range
);
5495 last_mouse_scroll_bar
= Qnil
;
5498 *time
= last_mouse_movement_time
;
5504 /* The screen has been cleared so we may have changed foreground or
5505 background colors, and the scroll bars may need to be redrawn.
5506 Clear out the scroll bars, and ask for expose events, so we can
5510 x_scroll_bar_clear (f
)
5513 #ifndef USE_TOOLKIT_SCROLL_BARS
5516 /* We can have scroll bars even if this is 0,
5517 if we just turned off scroll bar mode.
5518 But in that case we should not clear them. */
5519 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5520 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
5521 bar
= XSCROLL_BAR (bar
)->next
)
5522 XClearArea (FRAME_X_DISPLAY (f
),
5523 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
5525 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5529 /* Define a queue to save up SelectionRequest events for later handling. */
5531 struct selection_event_queue
5534 struct selection_event_queue
*next
;
5537 static struct selection_event_queue
*queue
;
5539 /* Nonzero means queue up certain events--don't process them yet. */
5541 static int x_queue_selection_requests
;
5543 /* Queue up an X event *EVENT, to be processed later. */
5546 x_queue_event (f
, event
)
5550 struct selection_event_queue
*queue_tmp
5551 = (struct selection_event_queue
*) xmalloc (sizeof (struct selection_event_queue
));
5553 if (queue_tmp
!= NULL
)
5555 queue_tmp
->event
= *event
;
5556 queue_tmp
->next
= queue
;
5561 /* Take all the queued events and put them back
5562 so that they get processed afresh. */
5565 x_unqueue_events (display
)
5568 while (queue
!= NULL
)
5570 struct selection_event_queue
*queue_tmp
= queue
;
5571 XPutBackEvent (display
, &queue_tmp
->event
);
5572 queue
= queue_tmp
->next
;
5573 xfree ((char *)queue_tmp
);
5577 /* Start queuing SelectionRequest events. */
5580 x_start_queuing_selection_requests (display
)
5583 x_queue_selection_requests
++;
5586 /* Stop queuing SelectionRequest events. */
5589 x_stop_queuing_selection_requests (display
)
5592 x_queue_selection_requests
--;
5593 x_unqueue_events (display
);
5596 /* The main X event-reading loop - XTread_socket. */
5599 /* Time stamp of enter window event. This is only used by XTread_socket,
5600 but we have to put it out here, since static variables within functions
5601 sometimes don't work. */
5603 static Time enter_timestamp
;
5606 /* This holds the state XLookupString needs to implement dead keys
5607 and other tricks known as "compose processing". _X Window System_
5608 says that a portable program can't use this, but Stephen Gildea assures
5609 me that letting the compiler initialize it to zeros will work okay.
5611 This must be defined outside of XTread_socket, for the same reasons
5612 given for enter_timestamp, above. */
5614 static XComposeStatus compose_status
;
5616 /* Record the last 100 characters stored
5617 to help debug the loss-of-chars-during-GC problem. */
5619 static int temp_index
;
5620 static short temp_buffer
[100];
5622 /* Set this to nonzero to fake an "X I/O error"
5623 on a particular display. */
5625 struct x_display_info
*XTread_socket_fake_io_error
;
5627 /* When we find no input here, we occasionally do a no-op command
5628 to verify that the X server is still running and we can still talk with it.
5629 We try all the open displays, one by one.
5630 This variable is used for cycling thru the displays. */
5632 static struct x_display_info
*next_noop_dpyinfo
;
5634 #define SET_SAVED_MENU_EVENT(size) \
5637 if (f->output_data.x->saved_menu_event == 0) \
5638 f->output_data.x->saved_menu_event \
5639 = (XEvent *) xmalloc (sizeof (XEvent)); \
5640 bcopy (&event, f->output_data.x->saved_menu_event, size); \
5641 if (numchars >= 1) \
5643 bufp->kind = MENU_BAR_ACTIVATE_EVENT; \
5644 XSETFRAME (bufp->frame_or_window, f); \
5653 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
5654 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
5664 /* Filter events for the current X input method.
5665 DPYINFO is the display this event is for.
5666 EVENT is the X event to filter.
5668 Returns non-zero if the event was filtered, caller shall not process
5670 Returns zero if event is wasn't filtered. */
5674 x_filter_event (dpyinfo
, event
)
5675 struct x_display_info
*dpyinfo
;
5678 /* XFilterEvent returns non-zero if the input method has
5679 consumed the event. We pass the frame's X window to
5680 XFilterEvent because that's the one for which the IC
5683 struct frame
*f1
= x_any_window_to_frame (dpyinfo
,
5684 event
->xclient
.window
);
5686 return XFilterEvent (event
, f1
? FRAME_X_WINDOW (f1
) : None
);
5691 static struct input_event
**current_bufp
;
5692 static int *current_numcharsp
;
5693 static int current_count
;
5694 static int current_finish
;
5696 /* This is the filter function invoked by the GTK event loop.
5697 It is invoked before the XEvent is translated to a GdkEvent,
5698 so we have a chanse to act on the event before GTK. */
5699 static GdkFilterReturn
5700 event_handler_gdk (gxev
, ev
, data
)
5705 XEvent
*xev
= (XEvent
*) gxev
;
5707 if (current_numcharsp
)
5709 struct x_display_info
*dpyinfo
;
5711 dpyinfo
= x_display_info_for_display (xev
->xany
.display
);
5714 /* Filter events for the current X input method.
5715 GTK calls XFilterEvent but not for key press and release,
5716 so we do it here. */
5717 if (xev
->type
== KeyPress
|| xev
->type
== KeyRelease
)
5718 if (dpyinfo
&& x_filter_event (dpyinfo
, xev
))
5719 return GDK_FILTER_REMOVE
;
5723 current_finish
= X_EVENT_NORMAL
;
5725 current_count
+= handle_one_xevent (dpyinfo
,
5732 current_finish
= x_dispatch_event (xev
, xev
->xany
.display
);
5734 if (current_finish
== X_EVENT_GOTO_OUT
|| current_finish
== X_EVENT_DROP
)
5735 return GDK_FILTER_REMOVE
;
5737 return GDK_FILTER_CONTINUE
;
5739 #endif /* USE_GTK */
5742 /* Handles the XEvent EVENT on display DPYINFO.
5744 *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
5745 *FINISH is zero if caller should continue reading events.
5746 *FINISH is X_EVENT_DROP if event should not be passed to the toolkit.
5748 Events representing keys are stored in buffer *BUFP_R,
5749 which can hold up to *NUMCHARSP characters.
5750 We return the number of characters stored into the buffer. */
5753 handle_one_xevent (dpyinfo
, eventp
, bufp_r
, numcharsp
, finish
)
5754 struct x_display_info
*dpyinfo
;
5756 /* register */ struct input_event
**bufp_r
;
5757 /* register */ int *numcharsp
;
5763 struct coding_system coding
;
5764 struct input_event
*bufp
= *bufp_r
;
5765 int numchars
= *numcharsp
;
5766 XEvent event
= *eventp
;
5768 *finish
= X_EVENT_NORMAL
;
5774 if (event
.xclient
.message_type
5775 == dpyinfo
->Xatom_wm_protocols
5776 && event
.xclient
.format
== 32)
5778 if (event
.xclient
.data
.l
[0]
5779 == dpyinfo
->Xatom_wm_take_focus
)
5781 /* Use x_any_window_to_frame because this
5782 could be the shell widget window
5783 if the frame has no title bar. */
5784 f
= x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
5786 /* Not quite sure this is needed -pd */
5787 if (f
&& FRAME_XIC (f
))
5788 XSetICFocus (FRAME_XIC (f
));
5790 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
5791 instructs the WM to set the input focus automatically for
5792 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
5793 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
5794 it has set the focus. So, XSetInputFocus below is not
5797 The call to XSetInputFocus below has also caused trouble. In
5798 cases where the XSetInputFocus done by the WM and the one
5799 below are temporally close (on a fast machine), the call
5800 below can generate additional FocusIn events which confuse
5803 /* Since we set WM_TAKE_FOCUS, we must call
5804 XSetInputFocus explicitly. But not if f is null,
5805 since that might be an event for a deleted frame. */
5808 Display
*d
= event
.xclient
.display
;
5809 /* Catch and ignore errors, in case window has been
5810 iconified by a window manager such as GWM. */
5811 int count
= x_catch_errors (d
);
5812 XSetInputFocus (d
, event
.xclient
.window
,
5813 /* The ICCCM says this is
5814 the only valid choice. */
5816 event
.xclient
.data
.l
[1]);
5817 /* This is needed to detect the error
5818 if there is an error. */
5820 x_uncatch_errors (d
, count
);
5822 /* Not certain about handling scroll bars here */
5825 else if (event
.xclient
.data
.l
[0]
5826 == dpyinfo
->Xatom_wm_save_yourself
)
5828 /* Save state modify the WM_COMMAND property to
5829 something which can reinstate us. This notifies
5830 the session manager, who's looking for such a
5831 PropertyNotify. Can restart processing when
5832 a keyboard or mouse event arrives. */
5833 /* If we have a session manager, don't set this.
5834 KDE will then start two Emacsen, one for the
5835 session manager and one for this. */
5838 && ! x_session_have_connection ()
5842 f
= x_top_window_to_frame (dpyinfo
,
5843 event
.xclient
.window
);
5844 /* This is just so we only give real data once
5845 for a single Emacs process. */
5846 if (f
== SELECTED_FRAME ())
5847 XSetCommand (FRAME_X_DISPLAY (f
),
5848 event
.xclient
.window
,
5849 initial_argv
, initial_argc
);
5851 XSetCommand (FRAME_X_DISPLAY (f
),
5852 event
.xclient
.window
,
5856 else if (event
.xclient
.data
.l
[0]
5857 == dpyinfo
->Xatom_wm_delete_window
)
5860 = x_any_window_to_frame (dpyinfo
,
5861 event
.xclient
.window
);
5868 bufp
->kind
= DELETE_WINDOW_EVENT
;
5869 XSETFRAME (bufp
->frame_or_window
, f
);
5877 goto OTHER
; /* May be a dialog that is to be removed */
5880 else if (event
.xclient
.message_type
5881 == dpyinfo
->Xatom_wm_configure_denied
)
5884 else if (event
.xclient
.message_type
5885 == dpyinfo
->Xatom_wm_window_moved
)
5889 = x_window_to_frame (dpyinfo
, event
.xclient
.window
);
5891 new_x
= event
.xclient
.data
.s
[0];
5892 new_y
= event
.xclient
.data
.s
[1];
5896 f
->left_pos
= new_x
;
5901 else if (event
.xclient
.message_type
5902 == dpyinfo
->Xatom_editres
)
5905 = x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
5906 _XEditResCheckMessages (f
->output_data
.x
->widget
, NULL
,
5909 #endif /* HACK_EDITRES */
5910 else if ((event
.xclient
.message_type
5911 == dpyinfo
->Xatom_DONE
)
5912 || (event
.xclient
.message_type
5913 == dpyinfo
->Xatom_PAGE
))
5915 /* Ghostview job completed. Kill it. We could
5916 reply with "Next" if we received "Page", but we
5917 currently never do because we are interested in
5918 images, only, which should have 1 page. */
5919 Pixmap pixmap
= (Pixmap
) event
.xclient
.data
.l
[1];
5921 = x_window_to_frame (dpyinfo
, event
.xclient
.window
);
5922 x_kill_gs_process (pixmap
, f
);
5923 expose_frame (f
, 0, 0, 0, 0);
5925 #ifdef USE_TOOLKIT_SCROLL_BARS
5926 /* Scroll bar callbacks send a ClientMessage from which
5927 we construct an input_event. */
5928 else if (event
.xclient
.message_type
5929 == dpyinfo
->Xatom_Scrollbar
)
5931 x_scroll_bar_to_input_event (&event
, bufp
);
5932 ++bufp
, ++count
, --numchars
;
5935 #endif /* USE_TOOLKIT_SCROLL_BARS */
5941 case SelectionNotify
:
5942 #ifdef USE_X_TOOLKIT
5943 if (! x_window_to_frame (dpyinfo
, event
.xselection
.requestor
))
5945 #endif /* not USE_X_TOOLKIT */
5946 x_handle_selection_notify (&event
.xselection
);
5949 case SelectionClear
: /* Someone has grabbed ownership. */
5950 #ifdef USE_X_TOOLKIT
5951 if (! x_window_to_frame (dpyinfo
, event
.xselectionclear
.window
))
5953 #endif /* USE_X_TOOLKIT */
5955 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
5960 bufp
->kind
= SELECTION_CLEAR_EVENT
;
5961 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
5962 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
5963 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
5964 bufp
->frame_or_window
= Qnil
;
5973 case SelectionRequest
: /* Someone wants our selection. */
5974 #ifdef USE_X_TOOLKIT
5975 if (!x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
))
5977 #endif /* USE_X_TOOLKIT */
5978 if (x_queue_selection_requests
)
5979 x_queue_event (x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
),
5983 XSelectionRequestEvent
*eventp
5984 = (XSelectionRequestEvent
*) &event
;
5989 bufp
->kind
= SELECTION_REQUEST_EVENT
;
5990 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
5991 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
5992 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
5993 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
5994 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
5995 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
5996 bufp
->frame_or_window
= Qnil
;
6005 case PropertyNotify
:
6006 #if 0 /* This is plain wrong. In the case that we are waiting for a
6007 PropertyNotify used as an ACK in incremental selection
6008 transfer, the property will be on the receiver's window. */
6009 #if defined USE_X_TOOLKIT
6010 if (!x_any_window_to_frame (dpyinfo
, event
.xproperty
.window
))
6014 x_handle_property_notify (&event
.xproperty
);
6017 case ReparentNotify
:
6018 f
= x_top_window_to_frame (dpyinfo
, event
.xreparent
.window
);
6022 f
->output_data
.x
->parent_desc
= event
.xreparent
.parent
;
6023 x_real_positions (f
, &x
, &y
);
6027 /* Perhaps reparented due to a WM restart. Reset this. */
6028 FRAME_X_DISPLAY_INFO (f
)->wm_type
= X_WMTYPE_UNKNOWN
;
6034 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
6037 x_check_fullscreen (f
);
6039 if (f
->async_visible
== 0)
6041 f
->async_visible
= 1;
6042 f
->async_iconified
= 0;
6043 f
->output_data
.x
->has_been_visible
= 1;
6044 SET_FRAME_GARBAGED (f
);
6048 event
.xexpose
.x
, event
.xexpose
.y
,
6049 event
.xexpose
.width
, event
.xexpose
.height
);
6053 #ifndef USE_TOOLKIT_SCROLL_BARS
6054 struct scroll_bar
*bar
;
6056 #if defined USE_LUCID
6057 /* Submenus of the Lucid menu bar aren't widgets
6058 themselves, so there's no way to dispatch events
6059 to them. Recognize this case separately. */
6062 = x_window_to_menu_bar (event
.xexpose
.window
);
6064 xlwmenu_redisplay (widget
);
6066 #endif /* USE_LUCID */
6068 #ifdef USE_TOOLKIT_SCROLL_BARS
6069 /* Dispatch event to the widget. */
6071 #else /* not USE_TOOLKIT_SCROLL_BARS */
6072 bar
= x_window_to_scroll_bar (event
.xexpose
.display
,
6073 event
.xexpose
.window
);
6076 x_scroll_bar_expose (bar
, &event
);
6077 #ifdef USE_X_TOOLKIT
6080 #endif /* USE_X_TOOLKIT */
6081 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6085 case GraphicsExpose
: /* This occurs when an XCopyArea's
6086 source area was obscured or not
6088 f
= x_window_to_frame (dpyinfo
, event
.xgraphicsexpose
.drawable
);
6092 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
6093 event
.xgraphicsexpose
.width
,
6094 event
.xgraphicsexpose
.height
);
6096 #ifdef USE_X_TOOLKIT
6099 #endif /* USE_X_TOOLKIT */
6102 case NoExpose
: /* This occurs when an XCopyArea's
6103 source area was completely
6108 /* Redo the mouse-highlight after the tooltip has gone. */
6109 if (event
.xmap
.window
== tip_window
)
6112 redo_mouse_highlight ();
6115 f
= x_top_window_to_frame (dpyinfo
, event
.xunmap
.window
);
6116 if (f
) /* F may no longer exist if
6117 the frame was deleted. */
6119 /* While a frame is unmapped, display generation is
6120 disabled; you don't want to spend time updating a
6121 display that won't ever be seen. */
6122 f
->async_visible
= 0;
6123 /* We can't distinguish, from the event, whether the window
6124 has become iconified or invisible. So assume, if it
6125 was previously visible, than now it is iconified.
6126 But x_make_frame_invisible clears both
6127 the visible flag and the iconified flag;
6128 and that way, we know the window is not iconified now. */
6129 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
6131 f
->async_iconified
= 1;
6133 bufp
->kind
= ICONIFY_EVENT
;
6134 XSETFRAME (bufp
->frame_or_window
, f
);
6144 if (event
.xmap
.window
== tip_window
)
6145 /* The tooltip has been drawn already. Avoid
6146 the SET_FRAME_GARBAGED below. */
6149 /* We use x_top_window_to_frame because map events can
6150 come for sub-windows and they don't mean that the
6151 frame is visible. */
6152 f
= x_top_window_to_frame (dpyinfo
, event
.xmap
.window
);
6155 /* wait_reading_process_input will notice this and update
6156 the frame's display structures.
6157 If we where iconified, we should not set garbaged,
6158 because that stops redrawing on Expose events. This looks
6159 bad if we are called from a recursive event loop
6160 (x_dispatch_event), for example when a dialog is up. */
6161 if (! f
->async_iconified
)
6162 SET_FRAME_GARBAGED (f
);
6164 f
->async_visible
= 1;
6165 f
->async_iconified
= 0;
6166 f
->output_data
.x
->has_been_visible
= 1;
6170 bufp
->kind
= DEICONIFY_EVENT
;
6171 XSETFRAME (bufp
->frame_or_window
, f
);
6177 else if (! NILP (Vframe_list
)
6178 && ! NILP (XCDR (Vframe_list
)))
6179 /* Force a redisplay sooner or later
6180 to update the frame titles
6181 in case this is the second frame. */
6182 record_asynch_buffer_change ();
6188 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6189 /* Dispatch KeyPress events when in menu. */
6190 if (popup_activated ())
6194 f
= x_any_window_to_frame (dpyinfo
, event
.xkey
.window
);
6196 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
6198 dpyinfo
->mouse_face_hidden
= 1;
6199 clear_mouse_face (dpyinfo
);
6202 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
6205 /* Scroll bars consume key events, but we want
6206 the keys to go to the scroll bar's frame. */
6207 Widget widget
= XtWindowToWidget (dpyinfo
->display
,
6209 if (widget
&& XmIsScrollBar (widget
))
6211 widget
= XtParent (widget
);
6212 f
= x_any_window_to_frame (dpyinfo
, XtWindow (widget
));
6215 #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
6219 KeySym keysym
, orig_keysym
;
6220 /* al%imercury@uunet.uu.net says that making this 81
6221 instead of 80 fixed a bug whereby meta chars made
6224 It seems that some version of XmbLookupString has
6225 a bug of not returning XBufferOverflow in
6226 status_return even if the input is too long to
6227 fit in 81 bytes. So, we must prepare sufficient
6228 bytes for copy_buffer. 513 bytes (256 chars for
6229 two-byte character set) seems to be a fairly good
6230 approximation. -- 2000.8.10 handa@etl.go.jp */
6231 unsigned char copy_buffer
[513];
6232 unsigned char *copy_bufptr
= copy_buffer
;
6233 int copy_bufsiz
= sizeof (copy_buffer
);
6235 Lisp_Object coding_system
= Qlatin_1
;
6238 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f
),
6239 extra_keyboard_modifiers
);
6240 modifiers
= event
.xkey
.state
;
6242 /* This will have to go some day... */
6244 /* make_lispy_event turns chars into control chars.
6245 Don't do it here because XLookupString is too eager. */
6246 event
.xkey
.state
&= ~ControlMask
;
6247 event
.xkey
.state
&= ~(dpyinfo
->meta_mod_mask
6248 | dpyinfo
->super_mod_mask
6249 | dpyinfo
->hyper_mod_mask
6250 | dpyinfo
->alt_mod_mask
);
6252 /* In case Meta is ComposeCharacter,
6253 clear its status. According to Markus Ehrnsperger
6254 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
6255 this enables ComposeCharacter to work whether or
6256 not it is combined with Meta. */
6257 if (modifiers
& dpyinfo
->meta_mod_mask
)
6258 bzero (&compose_status
, sizeof (compose_status
));
6263 Status status_return
;
6265 coding_system
= Vlocale_coding_system
;
6266 nbytes
= XmbLookupString (FRAME_XIC (f
),
6267 &event
.xkey
, copy_bufptr
,
6268 copy_bufsiz
, &keysym
,
6270 if (status_return
== XBufferOverflow
)
6272 copy_bufsiz
= nbytes
+ 1;
6273 copy_bufptr
= (char *) alloca (copy_bufsiz
);
6274 nbytes
= XmbLookupString (FRAME_XIC (f
),
6275 &event
.xkey
, copy_bufptr
,
6276 copy_bufsiz
, &keysym
,
6279 /* Xutf8LookupString is a new but already deprecated interface. -stef */
6280 #if 0 && defined X_HAVE_UTF8_STRING
6281 else if (status_return
== XLookupKeySym
)
6282 { /* Try again but with utf-8. */
6283 coding_system
= Qutf_8
;
6284 nbytes
= Xutf8LookupString (FRAME_XIC (f
),
6285 &event
.xkey
, copy_bufptr
,
6286 copy_bufsiz
, &keysym
,
6288 if (status_return
== XBufferOverflow
)
6290 copy_bufsiz
= nbytes
+ 1;
6291 copy_bufptr
= (char *) alloca (copy_bufsiz
);
6292 nbytes
= Xutf8LookupString (FRAME_XIC (f
),
6295 copy_bufsiz
, &keysym
,
6301 if (status_return
== XLookupNone
)
6303 else if (status_return
== XLookupChars
)
6308 else if (status_return
!= XLookupKeySym
6309 && status_return
!= XLookupBoth
)
6313 nbytes
= XLookupString (&event
.xkey
, copy_bufptr
,
6314 copy_bufsiz
, &keysym
,
6317 nbytes
= XLookupString (&event
.xkey
, copy_bufptr
,
6318 copy_bufsiz
, &keysym
,
6322 /* If not using XIM/XIC, and a compose sequence is in progress,
6323 we break here. Otherwise, chars_matched is always 0. */
6324 if (compose_status
.chars_matched
> 0 && nbytes
== 0)
6327 orig_keysym
= keysym
;
6333 /* First deal with keysyms which have defined
6334 translations to characters. */
6335 if (keysym
>= 32 && keysym
< 128)
6336 /* Avoid explicitly decoding each ASCII character. */
6338 bufp
->kind
= ASCII_KEYSTROKE_EVENT
;
6339 bufp
->code
= keysym
;
6340 XSETFRAME (bufp
->frame_or_window
, f
);
6343 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
6345 bufp
->timestamp
= event
.xkey
.time
;
6350 /* Now non-ASCII. */
6351 else if (HASH_TABLE_P (Vx_keysym_table
)
6352 && (NATNUMP (c
= Fgethash (make_number (keysym
),
6356 bufp
->kind
= (SINGLE_BYTE_CHAR_P (XFASTINT (c
))
6357 ? ASCII_KEYSTROKE_EVENT
6358 : MULTIBYTE_CHAR_KEYSTROKE_EVENT
);
6359 bufp
->code
= XFASTINT (c
);
6360 XSETFRAME (bufp
->frame_or_window
, f
);
6363 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
6365 bufp
->timestamp
= event
.xkey
.time
;
6370 /* Random non-modifier sorts of keysyms. */
6371 else if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
6372 || keysym
== XK_Delete
6373 #ifdef XK_ISO_Left_Tab
6374 || (keysym
>= XK_ISO_Left_Tab
6375 && keysym
<= XK_ISO_Enter
)
6377 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
6378 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
6380 /* This recognizes the "extended function
6381 keys". It seems there's no cleaner way.
6382 Test IsModifierKey to avoid handling
6383 mode_switch incorrectly. */
6384 || ((unsigned) (keysym
) >= XK_Select
6385 && (unsigned)(keysym
) < XK_KP_Space
)
6387 #ifdef XK_dead_circumflex
6388 || orig_keysym
== XK_dead_circumflex
6390 #ifdef XK_dead_grave
6391 || orig_keysym
== XK_dead_grave
6393 #ifdef XK_dead_tilde
6394 || orig_keysym
== XK_dead_tilde
6396 #ifdef XK_dead_diaeresis
6397 || orig_keysym
== XK_dead_diaeresis
6399 #ifdef XK_dead_macron
6400 || orig_keysym
== XK_dead_macron
6402 #ifdef XK_dead_degree
6403 || orig_keysym
== XK_dead_degree
6405 #ifdef XK_dead_acute
6406 || orig_keysym
== XK_dead_acute
6408 #ifdef XK_dead_cedilla
6409 || orig_keysym
== XK_dead_cedilla
6411 #ifdef XK_dead_breve
6412 || orig_keysym
== XK_dead_breve
6414 #ifdef XK_dead_ogonek
6415 || orig_keysym
== XK_dead_ogonek
6417 #ifdef XK_dead_caron
6418 || orig_keysym
== XK_dead_caron
6420 #ifdef XK_dead_doubleacute
6421 || orig_keysym
== XK_dead_doubleacute
6423 #ifdef XK_dead_abovedot
6424 || orig_keysym
== XK_dead_abovedot
6426 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
6427 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
6428 /* Any "vendor-specific" key is ok. */
6429 || (orig_keysym
& (1 << 28))
6430 || (keysym
!= NoSymbol
&& nbytes
== 0))
6431 && ! (IsModifierKey (orig_keysym
)
6433 #ifdef XK_Mode_switch
6434 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
6437 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
6439 #endif /* not HAVE_X11R5 */
6440 /* The symbols from XK_ISO_Lock
6441 to XK_ISO_Last_Group_Lock
6442 don't have real modifiers but
6443 should be treated similarly to
6444 Mode_switch by Emacs. */
6445 #if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
6446 || ((unsigned)(orig_keysym
)
6448 && (unsigned)(orig_keysym
)
6449 <= XK_ISO_Last_Group_Lock
)
6453 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
6455 temp_buffer
[temp_index
++] = keysym
;
6456 /* make_lispy_event will convert this to a symbolic
6458 bufp
->kind
= NON_ASCII_KEYSTROKE_EVENT
;
6459 bufp
->code
= keysym
;
6460 XSETFRAME (bufp
->frame_or_window
, f
);
6463 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
6465 bufp
->timestamp
= event
.xkey
.time
;
6470 else if (numchars
> nbytes
)
6471 { /* Raw bytes, not keysym. */
6476 /* The input should be decoded with `coding_system'
6477 which depends on which X*LookupString function
6478 we used just above and the locale. */
6479 setup_coding_system (coding_system
, &coding
);
6480 coding
.src_multibyte
= 0;
6481 coding
.dst_multibyte
= 1;
6482 /* The input is converted to events, thus we can't
6483 handle composition. Anyway, there's no XIM that
6484 gives us composition information. */
6485 coding
.composing
= COMPOSITION_DISABLED
;
6487 for (i
= 0; i
< nbytes
; i
++)
6489 if (temp_index
== (sizeof temp_buffer
6492 temp_buffer
[temp_index
++] = copy_bufptr
[i
];
6496 /* Decode the input data. */
6500 require
= decoding_buffer_size (&coding
, nbytes
);
6501 p
= (unsigned char *) alloca (require
);
6502 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6503 /* We explicitly disable composition
6504 handling because key data should
6505 not contain any composition
6507 coding
.composing
= COMPOSITION_DISABLED
;
6508 decode_coding (&coding
, copy_bufptr
, p
,
6510 nbytes
= coding
.produced
;
6511 nchars
= coding
.produced_char
;
6515 /* Convert the input data to a sequence of
6516 character events. */
6517 for (i
= 0; i
< nbytes
; i
+= len
)
6519 if (nchars
== nbytes
)
6520 c
= copy_bufptr
[i
], len
= 1;
6522 c
= STRING_CHAR_AND_LENGTH (copy_bufptr
+ i
,
6525 bufp
->kind
= (SINGLE_BYTE_CHAR_P (c
)
6526 ? ASCII_KEYSTROKE_EVENT
6527 : MULTIBYTE_CHAR_KEYSTROKE_EVENT
);
6529 XSETFRAME (bufp
->frame_or_window
, f
);
6532 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
6534 bufp
->timestamp
= event
.xkey
.time
;
6541 if (keysym
== NoSymbol
)
6551 /* Don't dispatch this event since XtDispatchEvent calls
6552 XFilterEvent, and two calls in a row may freeze the
6561 /* Don't dispatch this event since XtDispatchEvent calls
6562 XFilterEvent, and two calls in a row may freeze the
6573 n
= x_detect_focus_change (dpyinfo
, &event
, bufp
, numchars
);
6576 bufp
+= n
, count
+= n
, numchars
-= n
;
6579 f
= x_any_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
6582 if (event
.xcrossing
.focus
)
6584 /* Avoid nasty pop/raise loops. */
6585 if (f
&& (!(f
->auto_raise
)
6587 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
6589 x_new_focus_frame (dpyinfo
, f
);
6590 enter_timestamp
= event
.xcrossing
.time
;
6593 else if (f
== dpyinfo
->x_focus_frame
)
6594 x_new_focus_frame (dpyinfo
, 0);
6597 /* EnterNotify counts as mouse movement,
6598 so update things that depend on mouse position. */
6599 if (f
&& !f
->output_data
.x
->hourglass_p
)
6600 note_mouse_movement (f
, &event
.xmotion
);
6608 n
= x_detect_focus_change (dpyinfo
, &event
, bufp
, numchars
);
6611 bufp
+= n
, count
+= n
, numchars
-= n
;
6621 n
= x_detect_focus_change (dpyinfo
, &event
, bufp
, numchars
);
6624 bufp
+= n
, count
+= n
, numchars
-= n
;
6628 f
= x_top_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
6631 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6633 /* If we move outside the frame, then we're
6634 certainly no longer on any text in the frame. */
6635 clear_mouse_face (dpyinfo
);
6636 dpyinfo
->mouse_face_mouse_frame
= 0;
6639 /* Generate a nil HELP_EVENT to cancel a help-echo.
6640 Do it only if there's something to cancel.
6641 Otherwise, the startup message is cleared when
6642 the mouse leaves the frame. */
6643 if (any_help_event_p
)
6648 XSETFRAME (frame
, f
);
6649 help_echo_string
= Qnil
;
6650 n
= gen_help_event (bufp
, numchars
,
6651 Qnil
, frame
, Qnil
, Qnil
, 0);
6652 bufp
+= n
, count
+= n
, numchars
-= n
;
6662 n
= x_detect_focus_change (dpyinfo
, &event
, bufp
, numchars
);
6665 bufp
+= n
, count
+= n
, numchars
-= n
;
6673 previous_help_echo_string
= help_echo_string
;
6674 help_echo_string
= help_echo_object
= help_echo_window
= Qnil
;
6677 if (dpyinfo
->grabbed
&& last_mouse_frame
6678 && FRAME_LIVE_P (last_mouse_frame
))
6679 f
= last_mouse_frame
;
6681 f
= x_window_to_frame (dpyinfo
, event
.xmotion
.window
);
6683 if (dpyinfo
->mouse_face_hidden
)
6685 dpyinfo
->mouse_face_hidden
= 0;
6686 clear_mouse_face (dpyinfo
);
6692 /* Generate SELECT_WINDOW_EVENTs when needed. */
6693 if (mouse_autoselect_window
)
6697 window
= window_from_coordinates (f
,
6698 event
.xmotion
.x
, event
.xmotion
.y
,
6701 /* Window will be selected only when it is not selected now and
6702 last mouse movement event was not in it. Minibuffer window
6703 will be selected iff it is active. */
6704 if (WINDOWP (window
)
6705 && !EQ (window
, last_window
)
6706 && !EQ (window
, selected_window
)
6709 bufp
->kind
= SELECT_WINDOW_EVENT
;
6710 bufp
->frame_or_window
= window
;
6712 ++bufp
, ++count
, --numchars
;
6717 note_mouse_movement (f
, &event
.xmotion
);
6721 #ifndef USE_TOOLKIT_SCROLL_BARS
6722 struct scroll_bar
*bar
6723 = x_window_to_scroll_bar (event
.xmotion
.display
,
6724 event
.xmotion
.window
);
6727 x_scroll_bar_note_movement (bar
, &event
);
6728 #endif /* USE_TOOLKIT_SCROLL_BARS */
6730 /* If we move outside the frame, then we're
6731 certainly no longer on any text in the frame. */
6732 clear_mouse_face (dpyinfo
);
6735 /* If the contents of the global variable help_echo_string
6736 has changed, generate a HELP_EVENT. */
6737 if (!NILP (help_echo_string
)
6738 || !NILP (previous_help_echo_string
))
6744 XSETFRAME (frame
, f
);
6748 any_help_event_p
= 1;
6749 n
= gen_help_event (bufp
, numchars
, help_echo_string
, frame
,
6750 help_echo_window
, help_echo_object
,
6752 bufp
+= n
, count
+= n
, numchars
-= n
;
6758 case ConfigureNotify
:
6759 f
= x_top_window_to_frame (dpyinfo
, event
.xconfigure
.window
);
6762 #ifndef USE_X_TOOLKIT
6764 xg_resize_widgets (f
, event
.xconfigure
.width
,
6765 event
.xconfigure
.height
);
6766 #else /* not USE_GTK */
6767 /* If there is a pending resize for fullscreen, don't
6768 do this one, the right one will come later.
6769 The toolkit version doesn't seem to need this, but we
6770 need to reset it below. */
6772 = ((f
->want_fullscreen
& FULLSCREEN_WAIT
)
6773 && f
->new_text_cols
!= 0);
6774 int rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, event
.xconfigure
.height
);
6775 int columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, event
.xconfigure
.width
);
6780 /* In the toolkit version, change_frame_size
6781 is called by the code that handles resizing
6782 of the EmacsFrame widget. */
6784 /* Even if the number of character rows and columns has
6785 not changed, the font size may have changed, so we need
6786 to check the pixel dimensions as well. */
6787 if (columns
!= FRAME_COLS (f
)
6788 || rows
!= FRAME_LINES (f
)
6789 || event
.xconfigure
.width
!= FRAME_PIXEL_WIDTH (f
)
6790 || event
.xconfigure
.height
!= FRAME_PIXEL_HEIGHT (f
))
6792 change_frame_size (f
, rows
, columns
, 0, 1, 0);
6793 SET_FRAME_GARBAGED (f
);
6794 cancel_mouse_face (f
);
6796 #endif /* not USE_GTK */
6799 FRAME_PIXEL_WIDTH (f
) = event
.xconfigure
.width
;
6800 FRAME_PIXEL_HEIGHT (f
) = event
.xconfigure
.height
;
6803 /* GTK creates windows but doesn't map them.
6804 Only get real positions and check fullscreen when mapped. */
6805 if (FRAME_GTK_OUTER_WIDGET (f
)
6806 && GTK_WIDGET_MAPPED (FRAME_GTK_OUTER_WIDGET (f
)))
6809 /* What we have now is the position of Emacs's own window.
6810 Convert that to the position of the window manager window. */
6811 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
6813 x_check_expected_move (f
);
6814 if (f
->want_fullscreen
& FULLSCREEN_WAIT
)
6815 f
->want_fullscreen
&= ~(FULLSCREEN_WAIT
|FULLSCREEN_BOTH
);
6819 if (FRAME_XIC (f
) && (FRAME_XIC_STYLE (f
) & XIMStatusArea
))
6820 xic_set_statusarea (f
);
6823 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
6825 /* Since the WM decorations come below top_pos now,
6826 we must put them below top_pos in the future. */
6827 f
->win_gravity
= NorthWestGravity
;
6828 x_wm_set_size_hint (f
, (long) 0, 0);
6836 /* If we decide we want to generate an event to be seen
6837 by the rest of Emacs, we put it here. */
6838 struct input_event emacs_event
;
6841 emacs_event
.kind
= NO_EVENT
;
6842 bzero (&compose_status
, sizeof (compose_status
));
6844 if (dpyinfo
->grabbed
6846 && FRAME_LIVE_P (last_mouse_frame
))
6847 f
= last_mouse_frame
;
6849 f
= x_window_to_frame (dpyinfo
, event
.xbutton
.window
);
6853 /* Is this in the tool-bar? */
6854 if (WINDOWP (f
->tool_bar_window
)
6855 && WINDOW_TOTAL_LINES (XWINDOW (f
->tool_bar_window
)))
6858 int x
= event
.xbutton
.x
;
6859 int y
= event
.xbutton
.y
;
6861 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
6862 if (EQ (window
, f
->tool_bar_window
))
6864 if (event
.xbutton
.type
== ButtonPress
)
6865 handle_tool_bar_click (f
, x
, y
, 1, 0);
6867 handle_tool_bar_click (f
, x
, y
, 0,
6868 x_x_to_emacs_modifiers (dpyinfo
,
6869 event
.xbutton
.state
));
6875 if (!dpyinfo
->x_focus_frame
6876 || f
== dpyinfo
->x_focus_frame
)
6878 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6879 if (! popup_activated ())
6881 construct_mouse_click (&emacs_event
, &event
, f
);
6886 struct scroll_bar
*bar
6887 = x_window_to_scroll_bar (event
.xbutton
.display
,
6888 event
.xbutton
.window
);
6890 #ifdef USE_TOOLKIT_SCROLL_BARS
6891 /* Make the "Ctrl-Mouse-2 splits window" work for toolkit
6893 if (bar
&& event
.xbutton
.state
& ControlMask
)
6895 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
6896 *finish
= X_EVENT_DROP
;
6898 #else /* not USE_TOOLKIT_SCROLL_BARS */
6900 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
6901 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6904 if (event
.type
== ButtonPress
)
6906 dpyinfo
->grabbed
|= (1 << event
.xbutton
.button
);
6907 last_mouse_frame
= f
;
6908 /* Ignore any mouse motion that happened
6909 before this event; any subsequent mouse-movement
6910 Emacs events should reflect only motion after
6916 last_tool_bar_item
= -1;
6919 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
6921 if (numchars
>= 1 && emacs_event
.kind
!= NO_EVENT
)
6923 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
6929 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6930 f
= x_menubar_window_to_frame (dpyinfo
, event
.xbutton
.window
);
6931 /* For a down-event in the menu bar,
6932 don't pass it to Xt right now.
6933 Instead, save it away
6934 and we will pass it to Xt from kbd_buffer_get_event.
6935 That way, we can run some Lisp code first. */
6938 ! popup_activated ()
6941 f
&& event
.type
== ButtonPress
6942 /* Verify the event is really within the menu bar
6943 and not just sent to it due to grabbing. */
6944 && event
.xbutton
.x
>= 0
6945 && event
.xbutton
.x
< FRAME_PIXEL_WIDTH (f
)
6946 && event
.xbutton
.y
>= 0
6947 && event
.xbutton
.y
< f
->output_data
.x
->menubar_height
6948 && event
.xbutton
.same_screen
)
6950 SET_SAVED_BUTTON_EVENT
;
6951 XSETFRAME (last_mouse_press_frame
, f
);
6953 *finish
= X_EVENT_DROP
;
6956 else if (event
.type
== ButtonPress
)
6958 last_mouse_press_frame
= Qnil
;
6962 #ifdef USE_MOTIF /* This should do not harm for Lucid,
6963 but I am trying to be cautious. */
6964 else if (event
.type
== ButtonRelease
)
6966 if (!NILP (last_mouse_press_frame
))
6968 f
= XFRAME (last_mouse_press_frame
);
6969 if (f
->output_data
.x
)
6970 SET_SAVED_BUTTON_EVENT
;
6975 #endif /* USE_MOTIF */
6978 #endif /* USE_X_TOOLKIT || USE_GTK */
6982 case CirculateNotify
:
6985 case CirculateRequest
:
6988 case VisibilityNotify
:
6992 /* Someone has changed the keyboard mapping - update the
6994 switch (event
.xmapping
.request
)
6996 case MappingModifier
:
6997 x_find_modifier_meanings (dpyinfo
);
6998 /* This is meant to fall through. */
6999 case MappingKeyboard
:
7000 XRefreshKeyboardMapping (&event
.xmapping
);
7006 #ifdef USE_X_TOOLKIT
7008 if (*finish
!= X_EVENT_DROP
)
7009 XtDispatchEvent (&event
);
7011 #endif /* USE_X_TOOLKIT */
7018 *finish
= X_EVENT_GOTO_OUT
;
7022 *numcharsp
= numchars
;
7029 /* Handles the XEvent EVENT on display DISPLAY.
7030 This is used for event loops outside the normal event handling,
7031 i.e. looping while a popup menu or a dialog is posted.
7033 Returns the value handle_one_xevent sets in the finish argument. */
7035 x_dispatch_event (event
, display
)
7039 struct x_display_info
*dpyinfo
;
7040 struct input_event bufp
[10];
7041 struct input_event
*bufpp
;
7043 int finish
= X_EVENT_NORMAL
;
7045 for (bufpp
= bufp
; bufpp
!= bufp
+ 10; bufpp
++)
7046 EVENT_INIT (*bufpp
);
7049 dpyinfo
= x_display_info_for_display (display
);
7054 events
= handle_one_xevent (dpyinfo
,
7059 for (i
= 0; i
< events
; ++i
)
7060 kbd_buffer_store_event (&bufp
[i
]);
7067 /* Read events coming from the X server.
7068 This routine is called by the SIGIO handler.
7069 We return as soon as there are no more events to be read.
7071 Events representing keys are stored in buffer BUFP,
7072 which can hold up to NUMCHARS characters.
7073 We return the number of characters stored into the buffer,
7074 thus pretending to be `read'.
7076 EXPECTED is nonzero if the caller knows input is available. */
7079 XTread_socket (sd
, bufp
, numchars
, expected
)
7081 /* register */ struct input_event
*bufp
;
7082 /* register */ int numchars
;
7087 int event_found
= 0;
7088 struct x_display_info
*dpyinfo
;
7090 if (interrupt_input_blocked
)
7092 interrupt_input_pending
= 1;
7096 interrupt_input_pending
= 0;
7099 /* So people can tell when we have read the available input. */
7100 input_signal_count
++;
7103 abort (); /* Don't think this happens. */
7107 /* Find the display we are supposed to read input for.
7108 It's the one communicating on descriptor SD. */
7109 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
7111 #if 0 /* This ought to be unnecessary; let's verify it. */
7113 /* If available, Xlib uses FIOSNBIO to make the socket
7114 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
7115 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
7116 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
7117 fcntl (dpyinfo
->connection
, F_SETFL
, 0);
7118 #endif /* ! defined (FIOSNBIO) */
7121 #if 0 /* This code can't be made to work, with multiple displays,
7122 and appears not to be used on any system any more.
7123 Also keyboard.c doesn't turn O_NDELAY on and off
7124 for X connections. */
7127 if (! (fcntl (dpyinfo
->connection
, F_GETFL
, 0) & O_NDELAY
))
7129 extern int read_alarm_should_throw
;
7130 read_alarm_should_throw
= 1;
7131 XPeekEvent (dpyinfo
->display
, &event
);
7132 read_alarm_should_throw
= 0;
7134 #endif /* HAVE_SELECT */
7138 /* For debugging, this gives a way to fake an I/O error. */
7139 if (dpyinfo
== XTread_socket_fake_io_error
)
7141 XTread_socket_fake_io_error
= 0;
7142 x_io_error_quitter (dpyinfo
->display
);
7147 count
+= x_session_check_input (bufp
, &numchars
);
7152 while (XPending (dpyinfo
->display
))
7156 XNextEvent (dpyinfo
->display
, &event
);
7159 /* Filter events for the current X input method. */
7160 if (x_filter_event (dpyinfo
, &event
))
7165 count
+= handle_one_xevent (dpyinfo
,
7171 if (finish
== X_EVENT_GOTO_OUT
)
7174 #endif /* not USE_GTK */
7179 /* For GTK we must use the GTK event loop. But XEvents gets passed
7180 to our filter function above, and then to the big event switch.
7181 We use a bunch of globals to communicate with our filter function,
7182 that is kind of ugly, but it works.
7184 There is no way to do one display at the time, GTK just does events
7185 from all displays. */
7187 while (gtk_events_pending ())
7189 current_count
= count
;
7190 current_numcharsp
= &numchars
;
7191 current_bufp
= &bufp
;
7193 gtk_main_iteration ();
7195 count
= current_count
;
7197 current_numcharsp
= 0;
7199 if (current_finish
== X_EVENT_GOTO_OUT
)
7202 #endif /* USE_GTK */
7206 /* On some systems, an X bug causes Emacs to get no more events
7207 when the window is destroyed. Detect that. (1994.) */
7210 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
7211 One XNOOP in 100 loops will make Emacs terminate.
7212 B. Bretthauer, 1994 */
7214 if (x_noop_count
>= 100)
7218 if (next_noop_dpyinfo
== 0)
7219 next_noop_dpyinfo
= x_display_list
;
7221 XNoOp (next_noop_dpyinfo
->display
);
7223 /* Each time we get here, cycle through the displays now open. */
7224 next_noop_dpyinfo
= next_noop_dpyinfo
->next
;
7228 /* If the focus was just given to an auto-raising frame,
7230 /* ??? This ought to be able to handle more than one such frame. */
7231 if (pending_autoraise_frame
)
7233 x_raise_frame (pending_autoraise_frame
);
7234 pending_autoraise_frame
= 0;
7245 /***********************************************************************
7247 ***********************************************************************/
7249 /* Set clipping for output in glyph row ROW. W is the window in which
7250 we operate. GC is the graphics context to set clipping in.
7252 ROW may be a text row or, e.g., a mode line. Text rows must be
7253 clipped to the interior of the window dedicated to text display,
7254 mode lines must be clipped to the whole window. */
7257 x_clip_to_row (w
, row
, gc
)
7259 struct glyph_row
*row
;
7262 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
7263 XRectangle clip_rect
;
7264 int window_y
, window_width
;
7266 window_box (w
, -1, 0, &window_y
, &window_width
, 0);
7268 clip_rect
.x
= WINDOW_TO_FRAME_PIXEL_X (w
, 0);
7269 clip_rect
.y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
7270 clip_rect
.y
= max (clip_rect
.y
, window_y
);
7271 clip_rect
.width
= window_width
;
7272 clip_rect
.height
= row
->visible_height
;
7274 XSetClipRectangles (FRAME_X_DISPLAY (f
), gc
, 0, 0, &clip_rect
, 1, Unsorted
);
7278 /* Draw a hollow box cursor on window W in glyph row ROW. */
7281 x_draw_hollow_cursor (w
, row
)
7283 struct glyph_row
*row
;
7285 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
7286 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7287 Display
*dpy
= FRAME_X_DISPLAY (f
);
7290 struct glyph
*cursor_glyph
;
7293 /* Get the glyph the cursor is on. If we can't tell because
7294 the current matrix is invalid or such, give up. */
7295 cursor_glyph
= get_phys_cursor_glyph (w
);
7296 if (cursor_glyph
== NULL
)
7299 /* Compute the width of the rectangle to draw. If on a stretch
7300 glyph, and `x-stretch-block-cursor' is nil, don't draw a
7301 rectangle as wide as the glyph, but use a canonical character
7303 wd
= cursor_glyph
->pixel_width
- 1;
7304 if (cursor_glyph
->type
== STRETCH_GLYPH
7305 && !x_stretch_cursor_p
)
7306 wd
= min (FRAME_COLUMN_WIDTH (f
), wd
);
7307 w
->phys_cursor_width
= wd
;
7309 /* Compute frame-relative coordinates from window-relative
7311 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
7312 y
= WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
);
7314 /* Compute the proper height and ascent of the rectangle, based
7315 on the actual glyph. Using the full height of the row looks
7316 bad when there are tall images on that row. */
7317 h
= max (FRAME_LINE_HEIGHT (f
), cursor_glyph
->ascent
+ cursor_glyph
->descent
);
7318 if (h
< row
->height
)
7319 y
+= row
->ascent
/* - w->phys_cursor_ascent */ + cursor_glyph
->descent
- h
;
7322 /* The foreground of cursor_gc is typically the same as the normal
7323 background color, which can cause the cursor box to be invisible. */
7324 xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
7325 if (dpyinfo
->scratch_cursor_gc
)
7326 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
7328 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_X_WINDOW (f
),
7329 GCForeground
, &xgcv
);
7330 gc
= dpyinfo
->scratch_cursor_gc
;
7332 /* Set clipping, draw the rectangle, and reset clipping again. */
7333 x_clip_to_row (w
, row
, gc
);
7334 XDrawRectangle (dpy
, FRAME_X_WINDOW (f
), gc
, x
, y
, wd
, h
);
7335 XSetClipMask (dpy
, gc
, None
);
7339 /* Draw a bar cursor on window W in glyph row ROW.
7341 Implementation note: One would like to draw a bar cursor with an
7342 angle equal to the one given by the font property XA_ITALIC_ANGLE.
7343 Unfortunately, I didn't find a font yet that has this property set.
7347 x_draw_bar_cursor (w
, row
, width
, kind
)
7349 struct glyph_row
*row
;
7351 enum text_cursor_kinds kind
;
7353 struct frame
*f
= XFRAME (w
->frame
);
7354 struct glyph
*cursor_glyph
;
7356 /* If cursor is out of bounds, don't draw garbage. This can happen
7357 in mini-buffer windows when switching between echo area glyphs
7359 cursor_glyph
= get_phys_cursor_glyph (w
);
7360 if (cursor_glyph
== NULL
)
7363 /* If on an image, draw like a normal cursor. That's usually better
7364 visible than drawing a bar, esp. if the image is large so that
7365 the bar might not be in the window. */
7366 if (cursor_glyph
->type
== IMAGE_GLYPH
)
7368 struct glyph_row
*row
;
7369 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
7370 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
7374 Display
*dpy
= FRAME_X_DISPLAY (f
);
7375 Window window
= FRAME_X_WINDOW (f
);
7376 GC gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
7377 unsigned long mask
= GCForeground
| GCBackground
| GCGraphicsExposures
;
7378 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
7381 /* If the glyph's background equals the color we normally draw
7382 the bar cursor in, the bar cursor in its normal color is
7383 invisible. Use the glyph's foreground color instead in this
7384 case, on the assumption that the glyph's colors are chosen so
7385 that the glyph is legible. */
7386 if (face
->background
== f
->output_data
.x
->cursor_pixel
)
7387 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
7389 xgcv
.background
= xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
7390 xgcv
.graphics_exposures
= 0;
7393 XChangeGC (dpy
, gc
, mask
, &xgcv
);
7396 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
7397 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
7401 width
= FRAME_CURSOR_WIDTH (f
);
7402 width
= min (cursor_glyph
->pixel_width
, width
);
7404 w
->phys_cursor_width
= width
;
7405 x_clip_to_row (w
, row
, gc
);
7407 if (kind
== BAR_CURSOR
)
7408 XFillRectangle (dpy
, window
, gc
,
7409 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
7410 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
7411 width
, row
->height
);
7413 XFillRectangle (dpy
, window
, gc
,
7414 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
7415 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
7416 row
->height
- width
),
7417 cursor_glyph
->pixel_width
,
7420 XSetClipMask (dpy
, gc
, None
);
7425 /* RIF: Define cursor CURSOR on frame F. */
7428 x_define_frame_cursor (f
, cursor
)
7432 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), cursor
);
7436 /* RIF: Clear area on frame F. */
7439 x_clear_frame_area (f
, x
, y
, width
, height
)
7441 int x
, y
, width
, height
;
7443 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7444 x
, y
, width
, height
, False
);
7448 /* RIF: Draw cursor on window W. */
7451 x_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
7453 struct glyph_row
*glyph_row
;
7455 int cursor_type
, cursor_width
;
7458 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
7462 w
->phys_cursor_type
= cursor_type
;
7463 w
->phys_cursor_on_p
= 1;
7465 if (glyph_row
->exact_window_width_line_p
7466 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
7468 glyph_row
->cursor_in_fringe_p
= 1;
7469 draw_fringe_bitmap (w
, glyph_row
, 0);
7472 switch (cursor_type
)
7474 case HOLLOW_BOX_CURSOR
:
7475 x_draw_hollow_cursor (w
, glyph_row
);
7478 case FILLED_BOX_CURSOR
:
7479 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
7483 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
7487 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
7491 w
->phys_cursor_width
= 0;
7499 if (w
== XWINDOW (f
->selected_window
))
7500 if (FRAME_XIC (f
) && (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
))
7501 xic_set_preeditarea (w
, x
, y
);
7506 if (updating_frame
!= f
)
7507 XFlush (FRAME_X_DISPLAY (f
));
7514 /* Make the x-window of frame F use the gnu icon bitmap. */
7517 x_bitmap_icon (f
, file
)
7523 if (FRAME_X_WINDOW (f
) == 0)
7526 /* Free up our existing icon bitmap and mask if any. */
7527 if (f
->output_data
.x
->icon_bitmap
> 0)
7528 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
7529 f
->output_data
.x
->icon_bitmap
= 0;
7534 /* Use gtk_window_set_icon_from_file () if available,
7535 It's not restricted to bitmaps */
7536 if (xg_set_icon (f
, file
))
7538 #endif /* USE_GTK */
7539 bitmap_id
= x_create_bitmap_from_file (f
, file
);
7540 x_create_bitmap_mask (f
, bitmap_id
);
7544 /* Create the GNU bitmap and mask if necessary. */
7545 if (FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
7547 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
7548 = x_create_bitmap_from_data (f
, gnu_bits
,
7549 gnu_width
, gnu_height
);
7550 x_create_bitmap_mask (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
7553 /* The first time we create the GNU bitmap and mask,
7554 this increments the ref-count one extra time.
7555 As a result, the GNU bitmap and mask are never freed.
7556 That way, we don't have to worry about allocating it again. */
7557 x_reference_bitmap (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
7559 bitmap_id
= FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
;
7562 x_wm_set_icon_pixmap (f
, bitmap_id
);
7563 f
->output_data
.x
->icon_bitmap
= bitmap_id
;
7569 /* Make the x-window of frame F use a rectangle with text.
7570 Use ICON_NAME as the text. */
7573 x_text_icon (f
, icon_name
)
7577 if (FRAME_X_WINDOW (f
) == 0)
7583 text
.value
= (unsigned char *) icon_name
;
7584 text
.encoding
= XA_STRING
;
7586 text
.nitems
= strlen (icon_name
);
7587 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
), &text
);
7589 #else /* not HAVE_X11R4 */
7590 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
), icon_name
);
7591 #endif /* not HAVE_X11R4 */
7593 if (f
->output_data
.x
->icon_bitmap
> 0)
7594 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
7595 f
->output_data
.x
->icon_bitmap
= 0;
7596 x_wm_set_icon_pixmap (f
, 0);
7601 #define X_ERROR_MESSAGE_SIZE 200
7603 /* If non-nil, this should be a string.
7604 It means catch X errors and store the error message in this string. */
7606 static Lisp_Object x_error_message_string
;
7608 /* An X error handler which stores the error message in
7609 x_error_message_string. This is called from x_error_handler if
7610 x_catch_errors is in effect. */
7613 x_error_catcher (display
, error
)
7617 XGetErrorText (display
, error
->error_code
,
7618 SDATA (x_error_message_string
),
7619 X_ERROR_MESSAGE_SIZE
);
7622 /* Begin trapping X errors for display DPY. Actually we trap X errors
7623 for all displays, but DPY should be the display you are actually
7626 After calling this function, X protocol errors no longer cause
7627 Emacs to exit; instead, they are recorded in the string
7628 stored in x_error_message_string.
7630 Calling x_check_errors signals an Emacs error if an X error has
7631 occurred since the last call to x_catch_errors or x_check_errors.
7633 Calling x_uncatch_errors resumes the normal error handling. */
7635 void x_check_errors ();
7636 static Lisp_Object
x_catch_errors_unwind ();
7639 x_catch_errors (dpy
)
7642 int count
= SPECPDL_INDEX ();
7644 /* Make sure any errors from previous requests have been dealt with. */
7647 record_unwind_protect (x_catch_errors_unwind
,
7648 Fcons (make_save_value (dpy
, 0),
7649 x_error_message_string
));
7651 x_error_message_string
= make_uninit_string (X_ERROR_MESSAGE_SIZE
);
7652 SSET (x_error_message_string
, 0, 0);
7657 /* Unbind the binding that we made to check for X errors. */
7660 x_catch_errors_unwind (old_val
)
7661 Lisp_Object old_val
;
7665 first
= XCAR (old_val
);
7667 XSync (XSAVE_VALUE (first
)->pointer
, False
);
7669 x_error_message_string
= XCDR (old_val
);
7673 /* If any X protocol errors have arrived since the last call to
7674 x_catch_errors or x_check_errors, signal an Emacs error using
7675 sprintf (a buffer, FORMAT, the x error message text) as the text. */
7678 x_check_errors (dpy
, format
)
7682 /* Make sure to catch any errors incurred so far. */
7685 if (SREF (x_error_message_string
, 0))
7686 error (format
, SDATA (x_error_message_string
));
7689 /* Nonzero if we had any X protocol errors
7690 since we did x_catch_errors on DPY. */
7693 x_had_errors_p (dpy
)
7696 /* Make sure to catch any errors incurred so far. */
7699 return SREF (x_error_message_string
, 0) != 0;
7702 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
7705 x_clear_errors (dpy
)
7708 SSET (x_error_message_string
, 0, 0);
7711 /* Stop catching X protocol errors and let them make Emacs die.
7712 DPY should be the display that was passed to x_catch_errors.
7713 COUNT should be the value that was returned by
7714 the corresponding call to x_catch_errors. */
7717 x_uncatch_errors (dpy
, count
)
7721 unbind_to (count
, Qnil
);
7725 static unsigned int x_wire_count
;
7728 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
7733 /* Handle SIGPIPE, which can happen when the connection to a server
7734 simply goes away. SIGPIPE is handled by x_connection_signal.
7735 Don't need to do anything, because the write which caused the
7736 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
7737 which will do the appropriate cleanup for us. */
7740 x_connection_signal (signalnum
) /* If we don't have an argument, */
7741 int signalnum
; /* some compilers complain in signal calls. */
7744 /* USG systems forget handlers when they are used;
7745 must reestablish each time */
7746 signal (signalnum
, x_connection_signal
);
7751 /************************************************************************
7753 ************************************************************************/
7755 /* Error message passed to x_connection_closed. */
7757 static char *error_msg
;
7759 /* Function installed as fatal_error_signal_hook in
7760 x_connection_closed. Print the X error message, and exit normally,
7761 instead of dumping core when XtCloseDisplay fails. */
7764 x_fatal_error_signal ()
7766 fprintf (stderr
, "%s\n", error_msg
);
7770 /* Handle the loss of connection to display DPY. ERROR_MESSAGE is
7771 the text of an error message that lead to the connection loss. */
7774 x_connection_closed (dpy
, error_message
)
7776 char *error_message
;
7778 struct x_display_info
*dpyinfo
= x_display_info_for_display (dpy
);
7779 Lisp_Object frame
, tail
;
7782 error_msg
= (char *) alloca (strlen (error_message
) + 1);
7783 strcpy (error_msg
, error_message
);
7784 handling_signal
= 0;
7786 /* Prevent being called recursively because of an error condition
7787 below. Otherwise, we might end up with printing ``can't find per
7788 display information'' in the recursive call instead of printing
7789 the original message here. */
7790 count
= x_catch_errors (dpy
);
7792 /* We have to close the display to inform Xt that it doesn't
7793 exist anymore. If we don't, Xt will continue to wait for
7794 events from the display. As a consequence, a sequence of
7796 M-x make-frame-on-display RET :1 RET
7797 ...kill the new frame, so that we get an IO error...
7798 M-x make-frame-on-display RET :1 RET
7800 will indefinitely wait in Xt for events for display `:1', opened
7801 in the first class to make-frame-on-display.
7803 Closing the display is reported to lead to a bus error on
7804 OpenWindows in certain situations. I suspect that is a bug
7805 in OpenWindows. I don't know how to cicumvent it here. */
7807 #ifdef USE_X_TOOLKIT
7808 /* If DPYINFO is null, this means we didn't open the display
7809 in the first place, so don't try to close it. */
7812 extern void (*fatal_error_signal_hook
) P_ ((void));
7813 fatal_error_signal_hook
= x_fatal_error_signal
;
7814 XtCloseDisplay (dpy
);
7815 fatal_error_signal_hook
= NULL
;
7821 xg_display_close (dpyinfo
->display
);
7824 /* Indicate that this display is dead. */
7826 dpyinfo
->display
= 0;
7828 /* First delete frames whose mini-buffers are on frames
7829 that are on the dead display. */
7830 FOR_EACH_FRAME (tail
, frame
)
7832 Lisp_Object minibuf_frame
;
7834 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
7835 if (FRAME_X_P (XFRAME (frame
))
7836 && FRAME_X_P (XFRAME (minibuf_frame
))
7837 && ! EQ (frame
, minibuf_frame
)
7838 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame
)) == dpyinfo
)
7839 Fdelete_frame (frame
, Qt
);
7842 /* Now delete all remaining frames on the dead display.
7843 We are now sure none of these is used as the mini-buffer
7844 for another frame that we need to delete. */
7845 FOR_EACH_FRAME (tail
, frame
)
7846 if (FRAME_X_P (XFRAME (frame
))
7847 && FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
7849 /* Set this to t so that Fdelete_frame won't get confused
7850 trying to find a replacement. */
7851 FRAME_KBOARD (XFRAME (frame
))->Vdefault_minibuffer_frame
= Qt
;
7852 Fdelete_frame (frame
, Qt
);
7856 x_delete_display (dpyinfo
);
7858 x_uncatch_errors (dpy
, count
);
7860 if (x_display_list
== 0)
7862 fprintf (stderr
, "%s\n", error_msg
);
7863 shut_down_emacs (0, 0, Qnil
);
7867 /* Ordinary stack unwind doesn't deal with these. */
7869 sigunblock (sigmask (SIGIO
));
7871 sigunblock (sigmask (SIGALRM
));
7872 TOTALLY_UNBLOCK_INPUT
;
7874 clear_waiting_for_input ();
7875 error ("%s", error_msg
);
7879 /* This is the usual handler for X protocol errors.
7880 It kills all frames on the display that we got the error for.
7881 If that was the only one, it prints an error message and kills Emacs. */
7884 x_error_quitter (display
, error
)
7888 char buf
[256], buf1
[356];
7890 /* Note that there is no real way portable across R3/R4 to get the
7891 original error handler. */
7893 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
7894 sprintf (buf1
, "X protocol error: %s on protocol request %d",
7895 buf
, error
->request_code
);
7896 x_connection_closed (display
, buf1
);
7900 /* This is the first-level handler for X protocol errors.
7901 It calls x_error_quitter or x_error_catcher. */
7904 x_error_handler (display
, error
)
7908 if (! NILP (x_error_message_string
))
7909 x_error_catcher (display
, error
);
7911 x_error_quitter (display
, error
);
7915 /* This is the handler for X IO errors, always.
7916 It kills all frames on the display that we lost touch with.
7917 If that was the only one, it prints an error message and kills Emacs. */
7920 x_io_error_quitter (display
)
7925 sprintf (buf
, "Connection lost to X server `%s'", DisplayString (display
));
7926 x_connection_closed (display
, buf
);
7930 /* Changing the font of the frame. */
7932 /* Give frame F the font named FONTNAME as its default font, and
7933 return the full name of that font. FONTNAME may be a wildcard
7934 pattern; in that case, we choose some font that fits the pattern.
7935 The return value shows which font we chose. */
7938 x_new_font (f
, fontname
)
7940 register char *fontname
;
7942 struct font_info
*fontp
7943 = FS_LOAD_FONT (f
, 0, fontname
, -1);
7948 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
7949 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
7950 FRAME_FONTSET (f
) = -1;
7952 FRAME_COLUMN_WIDTH (f
) = FONT_WIDTH (FRAME_FONT (f
));
7953 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
7955 compute_fringe_widths (f
, 1);
7957 /* Compute the scroll bar width in character columns. */
7958 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
7960 int wid
= FRAME_COLUMN_WIDTH (f
);
7961 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
7962 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
7966 int wid
= FRAME_COLUMN_WIDTH (f
);
7967 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
7970 /* Now make the frame display the given font. */
7971 if (FRAME_X_WINDOW (f
) != 0)
7973 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
7974 FRAME_FONT (f
)->fid
);
7975 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
7976 FRAME_FONT (f
)->fid
);
7977 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
7978 FRAME_FONT (f
)->fid
);
7980 /* Don't change the size of a tip frame; there's no point in
7981 doing it because it's done in Fx_show_tip, and it leads to
7982 problems because the tip frame has no widget. */
7983 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
7984 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
7987 return build_string (fontp
->full_name
);
7990 /* Give frame F the fontset named FONTSETNAME as its default font, and
7991 return the full name of that fontset. FONTSETNAME may be a wildcard
7992 pattern; in that case, we choose some fontset that fits the pattern.
7993 The return value shows which fontset we chose. */
7996 x_new_fontset (f
, fontsetname
)
8000 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
8006 if (FRAME_FONTSET (f
) == fontset
)
8007 /* This fontset is already set in frame F. There's nothing more
8009 return fontset_name (fontset
);
8011 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
8013 if (!STRINGP (result
))
8014 /* Can't load ASCII font. */
8017 /* Since x_new_font doesn't update any fontset information, do it now. */
8018 FRAME_FONTSET (f
) = fontset
;
8022 && (FRAME_XIC_STYLE (f
) & (XIMPreeditPosition
| XIMStatusArea
)))
8023 xic_set_xfontset (f
, SDATA (fontset_ascii (fontset
)));
8026 return build_string (fontsetname
);
8030 /***********************************************************************
8032 ***********************************************************************/
8038 /* XIM destroy callback function, which is called whenever the
8039 connection to input method XIM dies. CLIENT_DATA contains a
8040 pointer to the x_display_info structure corresponding to XIM. */
8043 xim_destroy_callback (xim
, client_data
, call_data
)
8045 XPointer client_data
;
8048 struct x_display_info
*dpyinfo
= (struct x_display_info
*) client_data
;
8049 Lisp_Object frame
, tail
;
8053 /* No need to call XDestroyIC.. */
8054 FOR_EACH_FRAME (tail
, frame
)
8056 struct frame
*f
= XFRAME (frame
);
8057 if (FRAME_X_DISPLAY_INFO (f
) == dpyinfo
)
8059 FRAME_XIC (f
) = NULL
;
8060 if (FRAME_XIC_FONTSET (f
))
8062 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
8063 FRAME_XIC_FONTSET (f
) = NULL
;
8068 /* No need to call XCloseIM. */
8069 dpyinfo
->xim
= NULL
;
8070 XFree (dpyinfo
->xim_styles
);
8074 #endif /* HAVE_X11R6 */
8077 /* This isn't prototyped in OSF 5.0 or 5.1a. */
8078 extern char *XSetIMValues
P_ ((XIM
, ...));
8081 /* Open the connection to the XIM server on display DPYINFO.
8082 RESOURCE_NAME is the resource name Emacs uses. */
8085 xim_open_dpy (dpyinfo
, resource_name
)
8086 struct x_display_info
*dpyinfo
;
8087 char *resource_name
;
8094 xim
= XOpenIM (dpyinfo
->display
, dpyinfo
->xrdb
, resource_name
,
8101 XIMCallback destroy
;
8104 /* Get supported styles and XIM values. */
8105 XGetIMValues (xim
, XNQueryInputStyle
, &dpyinfo
->xim_styles
, NULL
);
8108 destroy
.callback
= xim_destroy_callback
;
8109 destroy
.client_data
= (XPointer
)dpyinfo
;
8110 XSetIMValues (xim
, XNDestroyCallback
, &destroy
, NULL
);
8116 #endif /* HAVE_XIM */
8117 dpyinfo
->xim
= NULL
;
8121 #ifdef HAVE_X11R6_XIM
8125 struct x_display_info
*dpyinfo
;
8126 char *resource_name
;
8129 /* XIM instantiate callback function, which is called whenever an XIM
8130 server is available. DISPLAY is the display of the XIM.
8131 CLIENT_DATA contains a pointer to an xim_inst_t structure created
8132 when the callback was registered. */
8135 xim_instantiate_callback (display
, client_data
, call_data
)
8137 XPointer client_data
;
8140 struct xim_inst_t
*xim_inst
= (struct xim_inst_t
*) client_data
;
8141 struct x_display_info
*dpyinfo
= xim_inst
->dpyinfo
;
8143 /* We don't support multiple XIM connections. */
8147 xim_open_dpy (dpyinfo
, xim_inst
->resource_name
);
8149 /* Create XIC for the existing frames on the same display, as long
8150 as they have no XIC. */
8151 if (dpyinfo
->xim
&& dpyinfo
->reference_count
> 0)
8153 Lisp_Object tail
, frame
;
8156 FOR_EACH_FRAME (tail
, frame
)
8158 struct frame
*f
= XFRAME (frame
);
8160 if (FRAME_X_DISPLAY_INFO (f
) == xim_inst
->dpyinfo
)
8161 if (FRAME_XIC (f
) == NULL
)
8163 create_frame_xic (f
);
8164 if (FRAME_XIC_STYLE (f
) & XIMStatusArea
)
8165 xic_set_statusarea (f
);
8166 if (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
)
8168 struct window
*w
= XWINDOW (f
->selected_window
);
8169 xic_set_preeditarea (w
, w
->cursor
.x
, w
->cursor
.y
);
8178 #endif /* HAVE_X11R6_XIM */
8181 /* Open a connection to the XIM server on display DPYINFO.
8182 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
8183 connection only at the first time. On X11R6, open the connection
8184 in the XIM instantiate callback function. */
8187 xim_initialize (dpyinfo
, resource_name
)
8188 struct x_display_info
*dpyinfo
;
8189 char *resource_name
;
8194 #ifdef HAVE_X11R6_XIM
8195 struct xim_inst_t
*xim_inst
;
8198 dpyinfo
->xim
= NULL
;
8199 xim_inst
= (struct xim_inst_t
*) xmalloc (sizeof (struct xim_inst_t
));
8200 xim_inst
->dpyinfo
= dpyinfo
;
8201 len
= strlen (resource_name
);
8202 xim_inst
->resource_name
= (char *) xmalloc (len
+ 1);
8203 bcopy (resource_name
, xim_inst
->resource_name
, len
+ 1);
8204 XRegisterIMInstantiateCallback (dpyinfo
->display
, dpyinfo
->xrdb
,
8205 resource_name
, EMACS_CLASS
,
8206 xim_instantiate_callback
,
8207 /* This is XPointer in XFree86
8208 but (XPointer *) on Tru64, at
8209 least, hence the configure test. */
8210 (XRegisterIMInstantiateCallback_arg6
) xim_inst
);
8211 #else /* not HAVE_X11R6_XIM */
8212 dpyinfo
->xim
= NULL
;
8213 xim_open_dpy (dpyinfo
, resource_name
);
8214 #endif /* not HAVE_X11R6_XIM */
8218 #endif /* HAVE_XIM */
8219 dpyinfo
->xim
= NULL
;
8223 /* Close the connection to the XIM server on display DPYINFO. */
8226 xim_close_dpy (dpyinfo
)
8227 struct x_display_info
*dpyinfo
;
8232 #ifdef HAVE_X11R6_XIM
8233 if (dpyinfo
->display
)
8234 XUnregisterIMInstantiateCallback (dpyinfo
->display
, dpyinfo
->xrdb
,
8236 xim_instantiate_callback
, NULL
);
8237 #endif /* not HAVE_X11R6_XIM */
8238 if (dpyinfo
->display
)
8239 XCloseIM (dpyinfo
->xim
);
8240 dpyinfo
->xim
= NULL
;
8241 XFree (dpyinfo
->xim_styles
);
8243 #endif /* HAVE_XIM */
8246 #endif /* not HAVE_X11R6_XIM */
8250 /* Calculate the absolute position in frame F
8251 from its current recorded position values and gravity. */
8254 x_calc_absolute_position (f
)
8258 int win_x
= 0, win_y
= 0;
8259 int flags
= f
->size_hint_flags
;
8262 /* We have nothing to do if the current position
8263 is already for the top-left corner. */
8264 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
8267 this_window
= FRAME_OUTER_WINDOW (f
);
8269 /* Find the position of the outside upper-left corner of
8270 the inner window, with respect to the outer window.
8271 But do this only if we will need the results. */
8272 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
8277 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
8280 x_clear_errors (FRAME_X_DISPLAY (f
));
8281 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
8283 /* From-window, to-window. */
8285 f
->output_data
.x
->parent_desc
,
8287 /* From-position, to-position. */
8288 0, 0, &win_x
, &win_y
,
8292 if (x_had_errors_p (FRAME_X_DISPLAY (f
)))
8294 Window newroot
, newparent
= 0xdeadbeef;
8295 Window
*newchildren
;
8296 unsigned int nchildren
;
8298 if (! XQueryTree (FRAME_X_DISPLAY (f
), this_window
, &newroot
,
8299 &newparent
, &newchildren
, &nchildren
))
8302 XFree ((char *) newchildren
);
8304 f
->output_data
.x
->parent_desc
= newparent
;
8310 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
8314 /* Treat negative positions as relative to the leftmost bottommost
8315 position that fits on the screen. */
8316 if (flags
& XNegative
)
8317 f
->left_pos
= (FRAME_X_DISPLAY_INFO (f
)->width
8318 - 2 * f
->border_width
- win_x
8319 - FRAME_PIXEL_WIDTH (f
)
8323 int height
= FRAME_PIXEL_HEIGHT (f
);
8325 #if defined USE_X_TOOLKIT && defined USE_MOTIF
8326 /* Something is fishy here. When using Motif, starting Emacs with
8327 `-g -0-0', the frame appears too low by a few pixels.
8329 This seems to be so because initially, while Emacs is starting,
8330 the column widget's height and the frame's pixel height are
8331 different. The column widget's height is the right one. In
8332 later invocations, when Emacs is up, the frame's pixel height
8335 It's not obvious where the initial small difference comes from.
8336 2000-12-01, gerd. */
8338 XtVaGetValues (f
->output_data
.x
->column_widget
, XtNheight
, &height
, NULL
);
8341 if (flags
& YNegative
)
8342 f
->top_pos
= (FRAME_X_DISPLAY_INFO (f
)->height
8343 - 2 * f
->border_width
8349 /* The left_pos and top_pos
8350 are now relative to the top and left screen edges,
8351 so the flags should correspond. */
8352 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
8355 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
8356 to really change the position, and 0 when calling from
8357 x_make_frame_visible (in that case, XOFF and YOFF are the current
8358 position values). It is -1 when calling from x_set_frame_parameters,
8359 which means, do adjust for borders but don't change the gravity. */
8362 x_set_offset (f
, xoff
, yoff
, change_gravity
)
8364 register int xoff
, yoff
;
8367 int modified_top
, modified_left
;
8369 if (change_gravity
> 0)
8373 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
8375 f
->size_hint_flags
|= XNegative
;
8377 f
->size_hint_flags
|= YNegative
;
8378 f
->win_gravity
= NorthWestGravity
;
8380 x_calc_absolute_position (f
);
8383 x_wm_set_size_hint (f
, (long) 0, 0);
8385 modified_left
= f
->left_pos
;
8386 modified_top
= f
->top_pos
;
8388 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
8389 this seems to be unnecessary and incorrect. rms, 4/17/97. */
8390 /* It is a mystery why we need to add the border_width here
8391 when the frame is already visible, but experiment says we do. */
8392 if (change_gravity
!= 0)
8394 modified_left
+= f
->border_width
;
8395 modified_top
+= f
->border_width
;
8399 if (FRAME_X_DISPLAY_INFO (f
)->wm_type
== X_WMTYPE_A
)
8401 /* Some WMs (twm, wmaker at least) has an offset that is smaller
8402 than the WM decorations. So we use the calculated offset instead
8403 of the WM decoration sizes here (x/y_pixels_outer_diff). */
8404 modified_left
+= FRAME_X_OUTPUT (f
)->move_offset_left
;
8405 modified_top
+= FRAME_X_OUTPUT (f
)->move_offset_top
;
8408 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
8409 modified_left
, modified_top
);
8411 if (FRAME_VISIBLE_P (f
)
8412 && FRAME_X_DISPLAY_INFO (f
)->wm_type
== X_WMTYPE_UNKNOWN
)
8414 FRAME_X_OUTPUT (f
)->check_expected_move
= 1;
8415 FRAME_X_OUTPUT (f
)->expected_top
= f
->top_pos
;
8416 FRAME_X_OUTPUT (f
)->expected_left
= f
->left_pos
;
8422 /* Check if we need to resize the frame due to a fullscreen request.
8423 If so needed, resize the frame. */
8425 x_check_fullscreen (f
)
8428 if (f
->want_fullscreen
& FULLSCREEN_BOTH
)
8430 int width
, height
, ign
;
8432 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
8434 x_fullscreen_adjust (f
, &width
, &height
, &ign
, &ign
);
8436 /* We do not need to move the window, it shall be taken care of
8437 when setting WM manager hints.
8438 If the frame is visible already, the position is checked by
8439 x_check_expected_move. */
8440 if (FRAME_COLS (f
) != width
|| FRAME_LINES (f
) != height
)
8442 change_frame_size (f
, height
, width
, 0, 1, 0);
8443 SET_FRAME_GARBAGED (f
);
8444 cancel_mouse_face (f
);
8446 /* Wait for the change of frame size to occur */
8447 f
->want_fullscreen
|= FULLSCREEN_WAIT
;
8452 /* If frame parameters are set after the frame is mapped, we need to move
8454 Some window managers moves the window to the right position, some
8455 moves the outer window manager window to the specified position.
8456 Here we check that we are in the right spot. If not, make a second
8457 move, assuming we are dealing with the second kind of window manager. */
8459 x_check_expected_move (f
)
8462 if (FRAME_X_OUTPUT (f
)->check_expected_move
)
8464 int expect_top
= FRAME_X_OUTPUT (f
)->expected_top
;
8465 int expect_left
= FRAME_X_OUTPUT (f
)->expected_left
;
8467 if (expect_top
!= f
->top_pos
|| expect_left
!= f
->left_pos
)
8469 FRAME_X_DISPLAY_INFO (f
)->wm_type
= X_WMTYPE_A
;
8470 FRAME_X_OUTPUT (f
)->move_offset_left
= expect_left
- f
->left_pos
;
8471 FRAME_X_OUTPUT (f
)->move_offset_top
= expect_top
- f
->top_pos
;
8473 x_set_offset (f
, expect_left
, expect_top
, 1);
8475 else if (FRAME_X_DISPLAY_INFO (f
)->wm_type
== X_WMTYPE_UNKNOWN
)
8476 FRAME_X_DISPLAY_INFO (f
)->wm_type
= X_WMTYPE_B
;
8478 /* Just do this once */
8479 FRAME_X_OUTPUT (f
)->check_expected_move
= 0;
8484 /* Change the size of frame F's X window to COLS/ROWS in the case F
8485 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
8486 top-left-corner window gravity for this size change and subsequent
8487 size changes. Otherwise we leave the window gravity unchanged. */
8490 x_set_window_size_1 (f
, change_gravity
, cols
, rows
)
8495 int pixelwidth
, pixelheight
;
8497 check_frame_size (f
, &rows
, &cols
);
8498 f
->scroll_bar_actual_width
8499 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
8501 : FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0
8502 ? FRAME_CONFIG_SCROLL_BAR_WIDTH (f
)
8503 : (FRAME_CONFIG_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
)));
8505 compute_fringe_widths (f
, 0);
8507 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
8508 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
8510 f
->win_gravity
= NorthWestGravity
;
8511 x_wm_set_size_hint (f
, (long) 0, 0);
8513 XSync (FRAME_X_DISPLAY (f
), False
);
8514 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8515 pixelwidth
, pixelheight
);
8517 /* Now, strictly speaking, we can't be sure that this is accurate,
8518 but the window manager will get around to dealing with the size
8519 change request eventually, and we'll hear how it went when the
8520 ConfigureNotify event gets here.
8522 We could just not bother storing any of this information here,
8523 and let the ConfigureNotify event set everything up, but that
8524 might be kind of confusing to the Lisp code, since size changes
8525 wouldn't be reported in the frame parameters until some random
8526 point in the future when the ConfigureNotify event arrives.
8528 We pass 1 for DELAY since we can't run Lisp code inside of
8530 change_frame_size (f
, rows
, cols
, 0, 1, 0);
8531 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
8532 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
8534 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
8535 receive in the ConfigureNotify event; if we get what we asked
8536 for, then the event won't cause the screen to become garbaged, so
8537 we have to make sure to do it here. */
8538 SET_FRAME_GARBAGED (f
);
8540 XFlush (FRAME_X_DISPLAY (f
));
8544 /* Call this to change the size of frame F's x-window.
8545 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
8546 for this size change and subsequent size changes.
8547 Otherwise we leave the window gravity unchanged. */
8550 x_set_window_size (f
, change_gravity
, cols
, rows
)
8558 if (FRAME_GTK_WIDGET (f
))
8559 xg_frame_set_char_size (f
, cols
, rows
);
8561 x_set_window_size_1 (f
, change_gravity
, cols
, rows
);
8564 if (f
->output_data
.x
->widget
!= NULL
)
8566 /* The x and y position of the widget is clobbered by the
8567 call to XtSetValues within EmacsFrameSetCharSize.
8568 This is a real kludge, but I don't understand Xt so I can't
8569 figure out a correct fix. Can anyone else tell me? -- rms. */
8570 int xpos
= f
->output_data
.x
->widget
->core
.x
;
8571 int ypos
= f
->output_data
.x
->widget
->core
.y
;
8572 EmacsFrameSetCharSize (f
->output_data
.x
->edit_widget
, cols
, rows
);
8573 f
->output_data
.x
->widget
->core
.x
= xpos
;
8574 f
->output_data
.x
->widget
->core
.y
= ypos
;
8577 x_set_window_size_1 (f
, change_gravity
, cols
, rows
);
8579 #else /* not USE_X_TOOLKIT */
8581 x_set_window_size_1 (f
, change_gravity
, cols
, rows
);
8583 #endif /* not USE_X_TOOLKIT */
8585 /* If cursor was outside the new size, mark it as off. */
8586 mark_window_cursors_off (XWINDOW (f
->root_window
));
8588 /* Clear out any recollection of where the mouse highlighting was,
8589 since it might be in a place that's outside the new frame size.
8590 Actually checking whether it is outside is a pain in the neck,
8591 so don't try--just let the highlighting be done afresh with new size. */
8592 cancel_mouse_face (f
);
8597 /* Mouse warping. */
8600 x_set_mouse_position (f
, x
, y
)
8606 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
8607 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
8609 if (pix_x
< 0) pix_x
= 0;
8610 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
8612 if (pix_y
< 0) pix_y
= 0;
8613 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
8617 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
8618 0, 0, 0, 0, pix_x
, pix_y
);
8622 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
8625 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
8631 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
8632 0, 0, 0, 0, pix_x
, pix_y
);
8636 /* focus shifting, raising and lowering. */
8639 x_focus_on_frame (f
)
8642 #if 0 /* This proves to be unpleasant. */
8646 /* I don't think that the ICCCM allows programs to do things like this
8647 without the interaction of the window manager. Whatever you end up
8648 doing with this code, do it to x_unfocus_frame too. */
8649 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8650 RevertToPointerRoot
, CurrentTime
);
8659 /* Look at the remarks in x_focus_on_frame. */
8660 if (FRAME_X_DISPLAY_INFO (f
)->x_focus_frame
== f
)
8661 XSetInputFocus (FRAME_X_DISPLAY (f
), PointerRoot
,
8662 RevertToPointerRoot
, CurrentTime
);
8666 /* Raise frame F. */
8672 if (f
->async_visible
)
8675 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
));
8676 XFlush (FRAME_X_DISPLAY (f
));
8681 /* Lower frame F. */
8687 if (f
->async_visible
)
8690 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
));
8691 XFlush (FRAME_X_DISPLAY (f
));
8697 XTframe_raise_lower (f
, raise_flag
)
8707 /* Change of visibility. */
8709 /* This tries to wait until the frame is really visible.
8710 However, if the window manager asks the user where to position
8711 the frame, this will return before the user finishes doing that.
8712 The frame will not actually be visible at that time,
8713 but it will become visible later when the window manager
8714 finishes with it. */
8717 x_make_frame_visible (f
)
8721 int original_top
, original_left
;
8722 int retry_count
= 2;
8728 type
= x_icon_type (f
);
8730 x_bitmap_icon (f
, type
);
8732 if (! FRAME_VISIBLE_P (f
))
8734 /* We test FRAME_GARBAGED_P here to make sure we don't
8735 call x_set_offset a second time
8736 if we get to x_make_frame_visible a second time
8737 before the window gets really visible. */
8738 if (! FRAME_ICONIFIED_P (f
)
8739 && ! f
->output_data
.x
->asked_for_visible
)
8740 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
8742 f
->output_data
.x
->asked_for_visible
= 1;
8744 if (! EQ (Vx_no_window_manager
, Qt
))
8745 x_wm_set_window_state (f
, NormalState
);
8746 #ifdef USE_X_TOOLKIT
8747 /* This was XtPopup, but that did nothing for an iconified frame. */
8748 XtMapWidget (f
->output_data
.x
->widget
);
8749 #else /* not USE_X_TOOLKIT */
8751 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f
));
8752 gtk_window_deiconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f
)));
8754 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
8755 #endif /* not USE_GTK */
8756 #endif /* not USE_X_TOOLKIT */
8757 #if 0 /* This seems to bring back scroll bars in the wrong places
8758 if the window configuration has changed. They seem
8759 to come back ok without this. */
8760 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
8761 XMapSubwindows (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
8765 XFlush (FRAME_X_DISPLAY (f
));
8767 /* Synchronize to ensure Emacs knows the frame is visible
8768 before we do anything else. We do this loop with input not blocked
8769 so that incoming events are handled. */
8773 /* This must be before UNBLOCK_INPUT
8774 since events that arrive in response to the actions above
8775 will set it when they are handled. */
8776 int previously_visible
= f
->output_data
.x
->has_been_visible
;
8778 original_left
= f
->left_pos
;
8779 original_top
= f
->top_pos
;
8781 /* This must come after we set COUNT. */
8784 /* We unblock here so that arriving X events are processed. */
8786 /* Now move the window back to where it was "supposed to be".
8787 But don't do it if the gravity is negative.
8788 When the gravity is negative, this uses a position
8789 that is 3 pixels too low. Perhaps that's really the border width.
8791 Don't do this if the window has never been visible before,
8792 because the window manager may choose the position
8793 and we don't want to override it. */
8795 if (! FRAME_VISIBLE_P (f
) && ! FRAME_ICONIFIED_P (f
)
8796 && f
->win_gravity
== NorthWestGravity
8797 && previously_visible
)
8801 unsigned int width
, height
, border
, depth
;
8805 /* On some window managers (such as FVWM) moving an existing
8806 window, even to the same place, causes the window manager
8807 to introduce an offset. This can cause the window to move
8808 to an unexpected location. Check the geometry (a little
8809 slow here) and then verify that the window is in the right
8810 place. If the window is not in the right place, move it
8811 there, and take the potential window manager hit. */
8812 XGetGeometry (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
8813 &rootw
, &x
, &y
, &width
, &height
, &border
, &depth
);
8815 if (original_left
!= x
|| original_top
!= y
)
8816 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
8817 original_left
, original_top
);
8822 XSETFRAME (frame
, f
);
8824 /* Wait until the frame is visible. Process X events until a
8825 MapNotify event has been seen, or until we think we won't get a
8826 MapNotify at all.. */
8827 for (count
= input_signal_count
+ 10;
8828 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
8830 /* Force processing of queued events. */
8833 /* Machines that do polling rather than SIGIO have been
8834 observed to go into a busy-wait here. So we'll fake an
8835 alarm signal to let the handler know that there's something
8836 to be read. We used to raise a real alarm, but it seems
8837 that the handler isn't always enabled here. This is
8839 if (input_polling_used ())
8841 /* It could be confusing if a real alarm arrives while
8842 processing the fake one. Turn it off and let the
8843 handler reset it. */
8844 extern void poll_for_input_1
P_ ((void));
8845 int old_poll_suppress_count
= poll_suppress_count
;
8846 poll_suppress_count
= 1;
8847 poll_for_input_1 ();
8848 poll_suppress_count
= old_poll_suppress_count
;
8851 /* See if a MapNotify event has been processed. */
8852 FRAME_SAMPLE_VISIBILITY (f
);
8857 (let ((f (selected-frame)))
8861 the frame is not raised with various window managers on
8862 FreeBSD, GNU/Linux and Solaris. It turns out that, for some
8863 unknown reason, the call to XtMapWidget is completely ignored.
8864 Mapping the widget a second time works. */
8866 if (!FRAME_VISIBLE_P (f
) && --retry_count
> 0)
8871 /* Change from mapped state to withdrawn state. */
8873 /* Make the frame visible (mapped and not iconified). */
8876 x_make_frame_invisible (f
)
8881 /* Use the frame's outermost window, not the one we normally draw on. */
8882 window
= FRAME_OUTER_WINDOW (f
);
8884 /* Don't keep the highlight on an invisible frame. */
8885 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
8886 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
8888 #if 0/* This might add unreliability; I don't trust it -- rms. */
8889 if (! f
->async_visible
&& ! f
->async_iconified
)
8895 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
8896 that the current position of the window is user-specified, rather than
8897 program-specified, so that when the window is mapped again, it will be
8898 placed at the same location, without forcing the user to position it
8899 by hand again (they have already done that once for this window.) */
8900 x_wm_set_size_hint (f
, (long) 0, 1);
8903 if (FRAME_GTK_OUTER_WIDGET (f
))
8904 gtk_widget_hide (FRAME_GTK_OUTER_WIDGET (f
));
8910 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
8911 DefaultScreen (FRAME_X_DISPLAY (f
))))
8913 UNBLOCK_INPUT_RESIGNAL
;
8914 error ("Can't notify window manager of window withdrawal");
8916 #else /* ! defined (HAVE_X11R4) */
8918 /* Tell the window manager what we're going to do. */
8919 if (! EQ (Vx_no_window_manager
, Qt
))
8923 unmap
.xunmap
.type
= UnmapNotify
;
8924 unmap
.xunmap
.window
= window
;
8925 unmap
.xunmap
.event
= DefaultRootWindow (FRAME_X_DISPLAY (f
));
8926 unmap
.xunmap
.from_configure
= False
;
8927 if (! XSendEvent (FRAME_X_DISPLAY (f
),
8928 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
8930 SubstructureRedirectMaskSubstructureNotifyMask
,
8933 UNBLOCK_INPUT_RESIGNAL
;
8934 error ("Can't notify window manager of withdrawal");
8938 /* Unmap the window ourselves. Cheeky! */
8939 XUnmapWindow (FRAME_X_DISPLAY (f
), window
);
8940 #endif /* ! defined (HAVE_X11R4) */
8943 /* We can't distinguish this from iconification
8944 just by the event that we get from the server.
8945 So we can't win using the usual strategy of letting
8946 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
8947 and synchronize with the server to make sure we agree. */
8949 FRAME_ICONIFIED_P (f
) = 0;
8950 f
->async_visible
= 0;
8951 f
->async_iconified
= 0;
8958 /* Change window state from mapped to iconified. */
8967 /* Don't keep the highlight on an invisible frame. */
8968 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
8969 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
8971 if (f
->async_iconified
)
8976 FRAME_SAMPLE_VISIBILITY (f
);
8978 type
= x_icon_type (f
);
8980 x_bitmap_icon (f
, type
);
8983 if (FRAME_GTK_OUTER_WIDGET (f
))
8985 if (! FRAME_VISIBLE_P (f
))
8986 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f
));
8988 gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f
)));
8991 f
->async_iconified
= 1;
8992 f
->async_visible
= 0;
8998 #ifdef USE_X_TOOLKIT
9000 if (! FRAME_VISIBLE_P (f
))
9002 if (! EQ (Vx_no_window_manager
, Qt
))
9003 x_wm_set_window_state (f
, IconicState
);
9004 /* This was XtPopup, but that did nothing for an iconified frame. */
9005 XtMapWidget (f
->output_data
.x
->widget
);
9006 /* The server won't give us any event to indicate
9007 that an invisible frame was changed to an icon,
9008 so we have to record it here. */
9011 f
->async_iconified
= 1;
9012 f
->async_visible
= 0;
9017 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
9018 XtWindow (f
->output_data
.x
->widget
),
9019 DefaultScreen (FRAME_X_DISPLAY (f
)));
9023 error ("Can't notify window manager of iconification");
9025 f
->async_iconified
= 1;
9026 f
->async_visible
= 0;
9030 XFlush (FRAME_X_DISPLAY (f
));
9032 #else /* not USE_X_TOOLKIT */
9034 /* Make sure the X server knows where the window should be positioned,
9035 in case the user deiconifies with the window manager. */
9036 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
9037 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
9039 /* Since we don't know which revision of X we're running, we'll use both
9040 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
9042 /* X11R4: send a ClientMessage to the window manager using the
9043 WM_CHANGE_STATE type. */
9047 message
.xclient
.window
= FRAME_X_WINDOW (f
);
9048 message
.xclient
.type
= ClientMessage
;
9049 message
.xclient
.message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
9050 message
.xclient
.format
= 32;
9051 message
.xclient
.data
.l
[0] = IconicState
;
9053 if (! XSendEvent (FRAME_X_DISPLAY (f
),
9054 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
9056 SubstructureRedirectMask
| SubstructureNotifyMask
,
9059 UNBLOCK_INPUT_RESIGNAL
;
9060 error ("Can't notify window manager of iconification");
9064 /* X11R3: set the initial_state field of the window manager hints to
9066 x_wm_set_window_state (f
, IconicState
);
9068 if (!FRAME_VISIBLE_P (f
))
9070 /* If the frame was withdrawn, before, we must map it. */
9071 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
9074 f
->async_iconified
= 1;
9075 f
->async_visible
= 0;
9077 XFlush (FRAME_X_DISPLAY (f
));
9079 #endif /* not USE_X_TOOLKIT */
9083 /* Free X resources of frame F. */
9086 x_free_frame_resources (f
)
9089 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9091 struct scroll_bar
*b
;
9095 /* If a display connection is dead, don't try sending more
9096 commands to the X server. */
9097 if (dpyinfo
->display
)
9099 if (f
->output_data
.x
->icon_desc
)
9100 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->icon_desc
);
9102 #ifdef USE_X_TOOLKIT
9103 /* Explicitly destroy the scroll bars of the frame. Without
9104 this, we get "BadDrawable" errors from the toolkit later on,
9105 presumably from expose events generated for the disappearing
9106 toolkit scroll bars. */
9107 for (bar
= FRAME_SCROLL_BARS (f
); !NILP (bar
); bar
= b
->next
)
9109 b
= XSCROLL_BAR (bar
);
9110 x_scroll_bar_remove (b
);
9119 #ifdef USE_X_TOOLKIT
9120 if (f
->output_data
.x
->widget
)
9122 XtDestroyWidget (f
->output_data
.x
->widget
);
9123 f
->output_data
.x
->widget
= NULL
;
9125 /* Tooltips don't have widgets, only a simple X window, even if
9126 we are using a toolkit. */
9127 else if (FRAME_X_WINDOW (f
))
9128 XDestroyWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
9130 free_frame_menubar (f
);
9131 #else /* !USE_X_TOOLKIT */
9134 /* In the GTK version, tooltips are normal X
9135 frames. We must check and free both types. */
9136 if (FRAME_GTK_OUTER_WIDGET (f
))
9138 gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f
));
9139 FRAME_X_WINDOW (f
) = 0; /* Set to avoid XDestroyWindow below */
9140 FRAME_GTK_OUTER_WIDGET (f
) = 0;
9142 #endif /* USE_GTK */
9144 if (FRAME_X_WINDOW (f
))
9145 XDestroyWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
9146 #endif /* !USE_X_TOOLKIT */
9148 unload_color (f
, f
->output_data
.x
->foreground_pixel
);
9149 unload_color (f
, f
->output_data
.x
->background_pixel
);
9150 unload_color (f
, f
->output_data
.x
->cursor_pixel
);
9151 unload_color (f
, f
->output_data
.x
->cursor_foreground_pixel
);
9152 unload_color (f
, f
->output_data
.x
->border_pixel
);
9153 unload_color (f
, f
->output_data
.x
->mouse_pixel
);
9155 if (f
->output_data
.x
->scroll_bar_background_pixel
!= -1)
9156 unload_color (f
, f
->output_data
.x
->scroll_bar_background_pixel
);
9157 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
9158 unload_color (f
, f
->output_data
.x
->scroll_bar_foreground_pixel
);
9159 #ifdef USE_TOOLKIT_SCROLL_BARS
9160 /* Scrollbar shadow colors. */
9161 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
!= -1)
9162 unload_color (f
, f
->output_data
.x
->scroll_bar_top_shadow_pixel
);
9163 if (f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
!= -1)
9164 unload_color (f
, f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
);
9165 #endif /* USE_TOOLKIT_SCROLL_BARS */
9166 if (f
->output_data
.x
->white_relief
.allocated_p
)
9167 unload_color (f
, f
->output_data
.x
->white_relief
.pixel
);
9168 if (f
->output_data
.x
->black_relief
.allocated_p
)
9169 unload_color (f
, f
->output_data
.x
->black_relief
.pixel
);
9171 if (FRAME_FACE_CACHE (f
))
9172 free_frame_faces (f
);
9175 XFlush (FRAME_X_DISPLAY (f
));
9178 if (f
->output_data
.x
->saved_menu_event
)
9179 xfree (f
->output_data
.x
->saved_menu_event
);
9181 xfree (f
->output_data
.x
);
9182 f
->output_data
.x
= NULL
;
9184 if (f
== dpyinfo
->x_focus_frame
)
9185 dpyinfo
->x_focus_frame
= 0;
9186 if (f
== dpyinfo
->x_focus_event_frame
)
9187 dpyinfo
->x_focus_event_frame
= 0;
9188 if (f
== dpyinfo
->x_highlight_frame
)
9189 dpyinfo
->x_highlight_frame
= 0;
9191 if (f
== dpyinfo
->mouse_face_mouse_frame
)
9193 dpyinfo
->mouse_face_beg_row
9194 = dpyinfo
->mouse_face_beg_col
= -1;
9195 dpyinfo
->mouse_face_end_row
9196 = dpyinfo
->mouse_face_end_col
= -1;
9197 dpyinfo
->mouse_face_window
= Qnil
;
9198 dpyinfo
->mouse_face_deferred_gc
= 0;
9199 dpyinfo
->mouse_face_mouse_frame
= 0;
9206 /* Destroy the X window of frame F. */
9209 x_destroy_window (f
)
9212 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9214 /* If a display connection is dead, don't try sending more
9215 commands to the X server. */
9216 if (dpyinfo
->display
!= 0)
9217 x_free_frame_resources (f
);
9219 dpyinfo
->reference_count
--;
9223 /* Setting window manager hints. */
9225 /* Set the normal size hints for the window manager, for frame F.
9226 FLAGS is the flags word to use--or 0 meaning preserve the flags
9227 that the window now has.
9228 If USER_POSITION is nonzero, we set the USPosition
9229 flag (this is useful when FLAGS is 0).
9230 The GTK version is in gtkutils.c */
9234 x_wm_set_size_hint (f
, flags
, user_position
)
9239 XSizeHints size_hints
;
9241 #ifdef USE_X_TOOLKIT
9244 Dimension widget_width
, widget_height
;
9247 Window window
= FRAME_OUTER_WINDOW (f
);
9249 /* Setting PMaxSize caused various problems. */
9250 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
9252 size_hints
.x
= f
->left_pos
;
9253 size_hints
.y
= f
->top_pos
;
9255 #ifdef USE_X_TOOLKIT
9256 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
9257 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
9258 XtGetValues (f
->output_data
.x
->widget
, al
, ac
);
9259 size_hints
.height
= widget_height
;
9260 size_hints
.width
= widget_width
;
9261 #else /* not USE_X_TOOLKIT */
9262 size_hints
.height
= FRAME_PIXEL_HEIGHT (f
);
9263 size_hints
.width
= FRAME_PIXEL_WIDTH (f
);
9264 #endif /* not USE_X_TOOLKIT */
9266 size_hints
.width_inc
= FRAME_COLUMN_WIDTH (f
);
9267 size_hints
.height_inc
= FRAME_LINE_HEIGHT (f
);
9268 size_hints
.max_width
9269 = FRAME_X_DISPLAY_INFO (f
)->width
- FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
9270 size_hints
.max_height
9271 = FRAME_X_DISPLAY_INFO (f
)->height
- FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
9273 /* Calculate the base and minimum sizes.
9275 (When we use the X toolkit, we don't do it here.
9276 Instead we copy the values that the widgets are using, below.) */
9277 #ifndef USE_X_TOOLKIT
9279 int base_width
, base_height
;
9280 int min_rows
= 0, min_cols
= 0;
9282 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
9283 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
9285 check_frame_size (f
, &min_rows
, &min_cols
);
9287 /* The window manager uses the base width hints to calculate the
9288 current number of rows and columns in the frame while
9289 resizing; min_width and min_height aren't useful for this
9290 purpose, since they might not give the dimensions for a
9291 zero-row, zero-column frame.
9293 We use the base_width and base_height members if we have
9294 them; otherwise, we set the min_width and min_height members
9295 to the size for a zero x zero frame. */
9298 size_hints
.flags
|= PBaseSize
;
9299 size_hints
.base_width
= base_width
;
9300 size_hints
.base_height
= base_height
;
9301 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
9302 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
9304 size_hints
.min_width
= base_width
;
9305 size_hints
.min_height
= base_height
;
9309 /* If we don't need the old flags, we don't need the old hint at all. */
9312 size_hints
.flags
|= flags
;
9315 #endif /* not USE_X_TOOLKIT */
9318 XSizeHints hints
; /* Sometimes I hate X Windows... */
9319 long supplied_return
;
9323 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
9326 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
9329 #ifdef USE_X_TOOLKIT
9330 size_hints
.base_height
= hints
.base_height
;
9331 size_hints
.base_width
= hints
.base_width
;
9332 size_hints
.min_height
= hints
.min_height
;
9333 size_hints
.min_width
= hints
.min_width
;
9337 size_hints
.flags
|= flags
;
9342 if (hints
.flags
& PSize
)
9343 size_hints
.flags
|= PSize
;
9344 if (hints
.flags
& PPosition
)
9345 size_hints
.flags
|= PPosition
;
9346 if (hints
.flags
& USPosition
)
9347 size_hints
.flags
|= USPosition
;
9348 if (hints
.flags
& USSize
)
9349 size_hints
.flags
|= USSize
;
9353 #ifndef USE_X_TOOLKIT
9358 size_hints
.win_gravity
= f
->win_gravity
;
9359 size_hints
.flags
|= PWinGravity
;
9363 size_hints
.flags
&= ~ PPosition
;
9364 size_hints
.flags
|= USPosition
;
9366 #endif /* PWinGravity */
9369 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
9371 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
9374 #endif /* not USE_GTK */
9376 /* Used for IconicState or NormalState */
9379 x_wm_set_window_state (f
, state
)
9383 #ifdef USE_X_TOOLKIT
9386 XtSetArg (al
[0], XtNinitialState
, state
);
9387 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
9388 #else /* not USE_X_TOOLKIT */
9389 Window window
= FRAME_X_WINDOW (f
);
9391 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
9392 f
->output_data
.x
->wm_hints
.initial_state
= state
;
9394 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
9395 #endif /* not USE_X_TOOLKIT */
9399 x_wm_set_icon_pixmap (f
, pixmap_id
)
9403 Pixmap icon_pixmap
, icon_mask
;
9405 #ifndef USE_X_TOOLKIT
9406 Window window
= FRAME_OUTER_WINDOW (f
);
9411 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
9412 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
9413 icon_mask
= x_bitmap_mask (f
, pixmap_id
);
9414 f
->output_data
.x
->wm_hints
.icon_mask
= icon_mask
;
9418 /* It seems there is no way to turn off use of an icon pixmap.
9419 The following line does it, only if no icon has yet been created,
9420 for some window managers. But with mwm it crashes.
9421 Some people say it should clear the IconPixmapHint bit in this case,
9422 but that doesn't work, and the X consortium said it isn't the
9423 right thing at all. Since there is no way to win,
9424 best to explicitly give up. */
9426 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
9427 f
->output_data
.x
->wm_hints
.icon_mask
= None
;
9433 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
9437 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
9438 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
9439 XtSetArg (al
[0], XtNiconMask
, icon_mask
);
9440 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
9443 #else /* not USE_X_TOOLKIT */
9445 f
->output_data
.x
->wm_hints
.flags
|= (IconPixmapHint
| IconMaskHint
);
9446 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
9448 #endif /* not USE_X_TOOLKIT */
9452 x_wm_set_icon_position (f
, icon_x
, icon_y
)
9456 Window window
= FRAME_OUTER_WINDOW (f
);
9458 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
9459 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
9460 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
9462 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
9466 /***********************************************************************
9468 ***********************************************************************/
9470 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
9473 x_get_font_info (f
, font_idx
)
9477 return (FRAME_X_FONT_TABLE (f
) + font_idx
);
9481 /* Return a list of names of available fonts matching PATTERN on frame F.
9483 If SIZE is > 0, it is the size (maximum bounds width) of fonts
9486 SIZE < 0 means include scalable fonts.
9488 Frame F null means we have not yet created any frame on X, and
9489 consult the first display in x_display_list. MAXNAMES sets a limit
9490 on how many fonts to match. */
9493 x_list_fonts (f
, pattern
, size
, maxnames
)
9495 Lisp_Object pattern
;
9499 Lisp_Object list
= Qnil
, patterns
, newlist
= Qnil
, key
= Qnil
;
9500 Lisp_Object tem
, second_best
;
9501 struct x_display_info
*dpyinfo
9502 = f
? FRAME_X_DISPLAY_INFO (f
) : x_display_list
;
9503 Display
*dpy
= dpyinfo
->display
;
9504 int try_XLoadQueryFont
= 0;
9506 int allow_auto_scaled_font
= 0;
9510 allow_auto_scaled_font
= 1;
9514 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
9515 if (NILP (patterns
))
9516 patterns
= Fcons (pattern
, Qnil
);
9518 if (maxnames
== 1 && !size
)
9519 /* We can return any single font matching PATTERN. */
9520 try_XLoadQueryFont
= 1;
9522 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
9525 char **names
= NULL
;
9527 pattern
= XCAR (patterns
);
9528 /* See if we cached the result for this particular query.
9529 The cache is an alist of the form:
9530 ((((PATTERN . MAXNAMES) . SCALABLE) (FONTNAME . WIDTH) ...) ...) */
9531 tem
= XCDR (dpyinfo
->name_list_element
);
9532 key
= Fcons (Fcons (pattern
, make_number (maxnames
)),
9533 allow_auto_scaled_font
? Qt
: Qnil
);
9534 list
= Fassoc (key
, tem
);
9537 list
= Fcdr_safe (list
);
9538 /* We have a cashed list. Don't have to get the list again. */
9542 /* At first, put PATTERN in the cache. */
9545 count
= x_catch_errors (dpy
);
9547 if (try_XLoadQueryFont
)
9550 unsigned long value
;
9552 font
= XLoadQueryFont (dpy
, SDATA (pattern
));
9553 if (x_had_errors_p (dpy
))
9555 /* This error is perhaps due to insufficient memory on X
9556 server. Let's just ignore it. */
9558 x_clear_errors (dpy
);
9562 && XGetFontProperty (font
, XA_FONT
, &value
))
9564 char *name
= (char *) XGetAtomName (dpy
, (Atom
) value
);
9565 int len
= strlen (name
);
9568 /* If DXPC (a Differential X Protocol Compressor)
9569 Ver.3.7 is running, XGetAtomName will return null
9570 string. We must avoid such a name. */
9572 try_XLoadQueryFont
= 0;
9576 names
= (char **) alloca (sizeof (char *));
9577 /* Some systems only allow alloca assigned to a
9579 tmp
= (char *) alloca (len
+ 1); names
[0] = tmp
;
9580 bcopy (name
, names
[0], len
+ 1);
9585 try_XLoadQueryFont
= 0;
9588 XFreeFont (dpy
, font
);
9591 if (!try_XLoadQueryFont
)
9593 /* We try at least 10 fonts because XListFonts will return
9594 auto-scaled fonts at the head. */
9601 names
= XListFonts (dpy
, SDATA (pattern
), limit
, &num_fonts
);
9602 if (num_fonts
== limit
)
9605 XFreeFontNames (names
);
9614 names
= XListFonts (dpy
, SDATA (pattern
), max (maxnames
, 10),
9617 if (x_had_errors_p (dpy
))
9619 /* This error is perhaps due to insufficient memory on X
9620 server. Let's just ignore it. */
9622 x_clear_errors (dpy
);
9626 x_uncatch_errors (dpy
, count
);
9633 /* Make a list of all the fonts we got back.
9634 Store that in the font cache for the display. */
9635 for (i
= 0; i
< num_fonts
; i
++)
9639 int average_width
= -1, resx
= 0, dashes
= 0;
9641 /* Count the number of dashes in NAMES[I]. If there are
9642 14 dashes, the field value following 9th dash
9643 (RESOLUTION_X) is nonzero, and the field value
9644 following 12th dash (AVERAGE_WIDTH) is 0, this is a
9645 auto-scaled font which is usually too ugly to be used
9646 for editing. Let's ignore it. */
9651 if (dashes
== 7) /* PIXEL_SIZE field */
9653 else if (dashes
== 9)
9655 else if (dashes
== 12) /* AVERAGE_WIDTH field */
9656 average_width
= atoi (p
);
9659 if (allow_auto_scaled_font
9660 || dashes
< 14 || average_width
!= 0 || resx
== 0)
9662 tem
= build_string (names
[i
]);
9663 if (NILP (Fassoc (tem
, list
)))
9665 if (STRINGP (Vx_pixel_size_width_font_regexp
)
9666 && ((fast_c_string_match_ignore_case
9667 (Vx_pixel_size_width_font_regexp
, names
[i
]))
9669 /* We can set the value of PIXEL_SIZE to the
9670 width of this font. */
9671 list
= Fcons (Fcons (tem
, make_number (width
)), list
);
9673 /* For the moment, width is not known. */
9674 list
= Fcons (Fcons (tem
, Qnil
), list
);
9679 if (!try_XLoadQueryFont
)
9682 XFreeFontNames (names
);
9687 /* Now store the result in the cache. */
9688 XSETCDR (dpyinfo
->name_list_element
,
9689 Fcons (Fcons (key
, list
), XCDR (dpyinfo
->name_list_element
)));
9692 if (NILP (list
)) continue; /* Try the remaining alternatives. */
9694 newlist
= second_best
= Qnil
;
9695 /* Make a list of the fonts that have the right width. */
9696 for (; CONSP (list
); list
= XCDR (list
))
9702 if (!CONSP (tem
) || NILP (XCAR (tem
)))
9706 newlist
= Fcons (XCAR (tem
), newlist
);
9710 if (!INTEGERP (XCDR (tem
)))
9712 /* Since we have not yet known the size of this font, we
9713 must try slow function call XLoadQueryFont. */
9714 XFontStruct
*thisinfo
;
9717 count
= x_catch_errors (dpy
);
9718 thisinfo
= XLoadQueryFont (dpy
,
9719 SDATA (XCAR (tem
)));
9720 if (x_had_errors_p (dpy
))
9722 /* This error is perhaps due to insufficient memory on X
9723 server. Let's just ignore it. */
9725 x_clear_errors (dpy
);
9727 x_uncatch_errors (dpy
, count
);
9733 (thisinfo
->min_bounds
.width
== 0
9735 : make_number (thisinfo
->max_bounds
.width
)));
9737 XFreeFont (dpy
, thisinfo
);
9741 /* For unknown reason, the previous call of XListFont had
9742 returned a font which can't be opened. Record the size
9743 as 0 not to try to open it again. */
9744 XSETCDR (tem
, make_number (0));
9747 found_size
= XINT (XCDR (tem
));
9748 if (found_size
== size
)
9749 newlist
= Fcons (XCAR (tem
), newlist
);
9750 else if (found_size
> 0)
9752 if (NILP (second_best
))
9754 else if (found_size
< size
)
9756 if (XINT (XCDR (second_best
)) > size
9757 || XINT (XCDR (second_best
)) < found_size
)
9762 if (XINT (XCDR (second_best
)) > size
9763 && XINT (XCDR (second_best
)) > found_size
)
9768 if (!NILP (newlist
))
9770 else if (!NILP (second_best
))
9772 newlist
= Fcons (XCAR (second_best
), Qnil
);
9783 /* Check that FONT is valid on frame F. It is if it can be found in F's
9787 x_check_font (f
, font
)
9792 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9794 xassert (font
!= NULL
);
9796 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9797 if (dpyinfo
->font_table
[i
].name
9798 && font
== dpyinfo
->font_table
[i
].font
)
9801 xassert (i
< dpyinfo
->n_fonts
);
9804 #endif /* GLYPH_DEBUG != 0 */
9806 /* Set *W to the minimum width, *H to the minimum font height of FONT.
9807 Note: There are (broken) X fonts out there with invalid XFontStruct
9808 min_bounds contents. For example, handa@etl.go.jp reports that
9809 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
9810 have font->min_bounds.width == 0. */
9813 x_font_min_bounds (font
, w
, h
)
9817 *h
= FONT_HEIGHT (font
);
9818 *w
= font
->min_bounds
.width
;
9820 /* Try to handle the case where FONT->min_bounds has invalid
9821 contents. Since the only font known to have invalid min_bounds
9822 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
9824 *w
= font
->max_bounds
.width
;
9828 /* Compute the smallest character width and smallest font height over
9829 all fonts available on frame F. Set the members smallest_char_width
9830 and smallest_font_height in F's x_display_info structure to
9831 the values computed. Value is non-zero if smallest_font_height or
9832 smallest_char_width become smaller than they were before. */
9835 x_compute_min_glyph_bounds (f
)
9839 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9841 int old_width
= dpyinfo
->smallest_char_width
;
9842 int old_height
= dpyinfo
->smallest_font_height
;
9844 dpyinfo
->smallest_font_height
= 100000;
9845 dpyinfo
->smallest_char_width
= 100000;
9847 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
9848 if (dpyinfo
->font_table
[i
].name
)
9850 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
9853 font
= (XFontStruct
*) fontp
->font
;
9854 xassert (font
!= (XFontStruct
*) ~0);
9855 x_font_min_bounds (font
, &w
, &h
);
9857 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
9858 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
9861 xassert (dpyinfo
->smallest_char_width
> 0
9862 && dpyinfo
->smallest_font_height
> 0);
9864 return (dpyinfo
->n_fonts
== 1
9865 || dpyinfo
->smallest_char_width
< old_width
9866 || dpyinfo
->smallest_font_height
< old_height
);
9870 /* Load font named FONTNAME of the size SIZE for frame F, and return a
9871 pointer to the structure font_info while allocating it dynamically.
9872 If SIZE is 0, load any size of font.
9873 If loading is failed, return NULL. */
9876 x_load_font (f
, fontname
, size
)
9878 register char *fontname
;
9881 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9882 Lisp_Object font_names
;
9885 /* Get a list of all the fonts that match this name. Once we
9886 have a list of matching fonts, we compare them against the fonts
9887 we already have by comparing names. */
9888 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
9890 if (!NILP (font_names
))
9895 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9896 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
9897 if (dpyinfo
->font_table
[i
].name
9898 && (!strcmp (dpyinfo
->font_table
[i
].name
,
9899 SDATA (XCAR (tail
)))
9900 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
9901 SDATA (XCAR (tail
)))))
9902 return (dpyinfo
->font_table
+ i
);
9905 /* Load the font and add it to the table. */
9909 struct font_info
*fontp
;
9910 unsigned long value
;
9913 /* If we have found fonts by x_list_font, load one of them. If
9914 not, we still try to load a font by the name given as FONTNAME
9915 because XListFonts (called in x_list_font) of some X server has
9916 a bug of not finding a font even if the font surely exists and
9917 is loadable by XLoadQueryFont. */
9918 if (size
> 0 && !NILP (font_names
))
9919 fontname
= (char *) SDATA (XCAR (font_names
));
9922 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
9923 font
= (XFontStruct
*) XLoadQueryFont (FRAME_X_DISPLAY (f
), fontname
);
9924 if (x_had_errors_p (FRAME_X_DISPLAY (f
)))
9926 /* This error is perhaps due to insufficient memory on X
9927 server. Let's just ignore it. */
9929 x_clear_errors (FRAME_X_DISPLAY (f
));
9931 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
9936 /* Find a free slot in the font table. */
9937 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
9938 if (dpyinfo
->font_table
[i
].name
== NULL
)
9941 /* If no free slot found, maybe enlarge the font table. */
9942 if (i
== dpyinfo
->n_fonts
9943 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
9946 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
9947 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
9949 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
9952 fontp
= dpyinfo
->font_table
+ i
;
9953 if (i
== dpyinfo
->n_fonts
)
9956 /* Now fill in the slots of *FONTP. */
9958 bzero (fontp
, sizeof (*fontp
));
9960 fontp
->font_idx
= i
;
9961 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
9962 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
9964 /* Try to get the full name of FONT. Put it in FULL_NAME. */
9966 if (XGetFontProperty (font
, XA_FONT
, &value
))
9968 char *name
= (char *) XGetAtomName (FRAME_X_DISPLAY (f
), (Atom
) value
);
9972 /* Count the number of dashes in the "full name".
9973 If it is too few, this isn't really the font's full name,
9975 In X11R4, the fonts did not come with their canonical names
9986 full_name
= (char *) xmalloc (p
- name
+ 1);
9987 bcopy (name
, full_name
, p
- name
+ 1);
9994 fontp
->full_name
= full_name
;
9996 fontp
->full_name
= fontp
->name
;
9998 fontp
->size
= font
->max_bounds
.width
;
9999 fontp
->height
= FONT_HEIGHT (font
);
10001 if (NILP (font_names
))
10003 /* We come here because of a bug of XListFonts mentioned at
10004 the head of this block. Let's store this information in
10005 the cache for x_list_fonts. */
10006 Lisp_Object lispy_name
= build_string (fontname
);
10007 Lisp_Object lispy_full_name
= build_string (fontp
->full_name
);
10008 Lisp_Object key
= Fcons (Fcons (lispy_name
, make_number (256)),
10011 XSETCDR (dpyinfo
->name_list_element
,
10013 Fcons (Fcons (lispy_full_name
,
10014 make_number (fontp
->size
)),
10016 XCDR (dpyinfo
->name_list_element
)));
10019 key
= Fcons (Fcons (lispy_full_name
, make_number (256)),
10021 XSETCDR (dpyinfo
->name_list_element
,
10023 Fcons (Fcons (lispy_full_name
,
10024 make_number (fontp
->size
)),
10026 XCDR (dpyinfo
->name_list_element
)));
10030 /* The slot `encoding' specifies how to map a character
10031 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
10032 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
10033 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
10034 2:0xA020..0xFF7F). For the moment, we don't know which charset
10035 uses this font. So, we set information in fontp->encoding[1]
10036 which is never used by any charset. If mapping can't be
10037 decided, set FONT_ENCODING_NOT_DECIDED. */
10039 = (font
->max_byte1
== 0
10041 ? (font
->min_char_or_byte2
< 0x80
10042 ? (font
->max_char_or_byte2
< 0x80
10043 ? 0 /* 0x20..0x7F */
10044 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
10045 : 1) /* 0xA0..0xFF */
10047 : (font
->min_byte1
< 0x80
10048 ? (font
->max_byte1
< 0x80
10049 ? (font
->min_char_or_byte2
< 0x80
10050 ? (font
->max_char_or_byte2
< 0x80
10051 ? 0 /* 0x2020..0x7F7F */
10052 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
10053 : 3) /* 0x20A0..0x7FFF */
10054 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
10055 : (font
->min_char_or_byte2
< 0x80
10056 ? (font
->max_char_or_byte2
< 0x80
10057 ? 2 /* 0xA020..0xFF7F */
10058 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
10059 : 1))); /* 0xA0A0..0xFFFF */
10061 fontp
->baseline_offset
10062 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
10063 ? (long) value
: 0);
10064 fontp
->relative_compose
10065 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
10066 ? (long) value
: 0);
10067 fontp
->default_ascent
10068 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
10069 ? (long) value
: 0);
10071 /* Set global flag fonts_changed_p to non-zero if the font loaded
10072 has a character with a smaller width than any other character
10073 before, or if the font loaded has a smaller height than any
10074 other font loaded before. If this happens, it will make a
10075 glyph matrix reallocation necessary. */
10076 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
10083 /* Return a pointer to struct font_info of a font named FONTNAME for
10084 frame F. If no such font is loaded, return NULL. */
10087 x_query_font (f
, fontname
)
10089 register char *fontname
;
10091 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
10094 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
10095 if (dpyinfo
->font_table
[i
].name
10096 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
10097 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
10098 return (dpyinfo
->font_table
+ i
);
10103 /* Find a CCL program for a font specified by FONTP, and set the member
10104 `encoder' of the structure. */
10107 x_find_ccl_program (fontp
)
10108 struct font_info
*fontp
;
10110 Lisp_Object list
, elt
;
10113 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
10117 && STRINGP (XCAR (elt
))
10118 && ((fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
10120 || (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->full_name
)
10127 struct ccl_program
*ccl
10128 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
10130 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
10133 fontp
->font_encoder
= ccl
;
10139 /***********************************************************************
10141 ***********************************************************************/
10143 #ifdef USE_X_TOOLKIT
10144 static XrmOptionDescRec emacs_options
[] = {
10145 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
10146 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
10148 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
10149 XrmoptionSepArg
, NULL
},
10150 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
10152 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
10153 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
10154 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
10155 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
10156 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
10157 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
10158 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
10160 #endif /* USE_X_TOOLKIT */
10162 static int x_initialized
;
10164 #ifdef MULTI_KBOARD
10165 /* Test whether two display-name strings agree up to the dot that separates
10166 the screen number from the server number. */
10168 same_x_server (name1
, name2
)
10169 const char *name1
, *name2
;
10171 int seen_colon
= 0;
10172 const unsigned char *system_name
= SDATA (Vsystem_name
);
10173 int system_name_length
= strlen (system_name
);
10174 int length_until_period
= 0;
10176 while (system_name
[length_until_period
] != 0
10177 && system_name
[length_until_period
] != '.')
10178 length_until_period
++;
10180 /* Treat `unix' like an empty host name. */
10181 if (! strncmp (name1
, "unix:", 5))
10183 if (! strncmp (name2
, "unix:", 5))
10185 /* Treat this host's name like an empty host name. */
10186 if (! strncmp (name1
, system_name
, system_name_length
)
10187 && name1
[system_name_length
] == ':')
10188 name1
+= system_name_length
;
10189 if (! strncmp (name2
, system_name
, system_name_length
)
10190 && name2
[system_name_length
] == ':')
10191 name2
+= system_name_length
;
10192 /* Treat this host's domainless name like an empty host name. */
10193 if (! strncmp (name1
, system_name
, length_until_period
)
10194 && name1
[length_until_period
] == ':')
10195 name1
+= length_until_period
;
10196 if (! strncmp (name2
, system_name
, length_until_period
)
10197 && name2
[length_until_period
] == ':')
10198 name2
+= length_until_period
;
10200 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
10204 if (seen_colon
&& *name1
== '.')
10208 && (*name1
== '.' || *name1
== '\0')
10209 && (*name2
== '.' || *name2
== '\0'));
10213 /* Count number of set bits in mask and number of bits to shift to
10214 get to the first bit. With MASK 0x7e0, *BITS is set to 6, and *OFFSET
10217 get_bits_and_offset (mask
, bits
, offset
)
10218 unsigned long mask
;
10225 while (!(mask
& 1))
10241 struct x_display_info
*
10242 x_term_init (display_name
, xrm_option
, resource_name
)
10243 Lisp_Object display_name
;
10245 char *resource_name
;
10249 struct x_display_info
*dpyinfo
;
10254 if (!x_initialized
)
10262 #define NUM_ARGV 10
10264 char *argv
[NUM_ARGV
];
10265 char **argv2
= argv
;
10268 if (x_initialized
++ > 1)
10270 /* Opening another display. If xg_display_open returns less
10271 than zero, we are probably on GTK 2.0, which can only handle
10272 one display. GTK 2.2 or later can handle more than one. */
10273 if (xg_display_open (SDATA (display_name
), &dpy
) < 0)
10274 error ("Sorry, this version of GTK can only handle one display");
10278 for (argc
= 0; argc
< NUM_ARGV
; ++argc
)
10282 argv
[argc
++] = initial_argv
[0];
10284 if (! NILP (display_name
))
10286 argv
[argc
++] = "--display";
10287 argv
[argc
++] = SDATA (display_name
);
10290 argv
[argc
++] = "--name";
10291 argv
[argc
++] = resource_name
;
10294 XSetLocaleModifiers ("");
10297 gtk_init (&argc
, &argv2
);
10299 /* gtk_init does set_locale. We must fix locale after calling it. */
10303 dpy
= GDK_DISPLAY ();
10305 /* NULL window -> events for all windows go to our function */
10306 gdk_window_add_filter (NULL
, event_handler_gdk
, NULL
);
10308 /* Load our own gtkrc if it exists. */
10310 struct gcpro gcpro1
, gcpro2
;
10311 char *file
= "~/.emacs.d/gtkrc";
10312 Lisp_Object s
, abs_file
;
10314 GCPRO2 (s
, abs_file
);
10315 s
= make_string (file
, strlen (file
));
10316 abs_file
= Fexpand_file_name (s
, Qnil
);
10318 if (! NILP (abs_file
) && !NILP (Ffile_readable_p (abs_file
)))
10319 gtk_rc_parse (SDATA (abs_file
));
10324 XSetErrorHandler (x_error_handler
);
10325 XSetIOErrorHandler (x_io_error_quitter
);
10328 #else /* not USE_GTK */
10329 #ifdef USE_X_TOOLKIT
10330 /* weiner@footloose.sps.mot.com reports that this causes
10332 X protocol error: BadAtom (invalid Atom parameter)
10333 on protocol request 18skiloaf.
10334 So let's not use it until R6. */
10335 #ifdef HAVE_X11XTR6
10336 XtSetLanguageProc (NULL
, NULL
, NULL
);
10347 argv
[argc
++] = "-xrm";
10348 argv
[argc
++] = xrm_option
;
10350 turn_on_atimers (0);
10351 dpy
= XtOpenDisplay (Xt_app_con
, SDATA (display_name
),
10352 resource_name
, EMACS_CLASS
,
10353 emacs_options
, XtNumber (emacs_options
),
10355 turn_on_atimers (1);
10357 #ifdef HAVE_X11XTR6
10358 /* I think this is to compensate for XtSetLanguageProc. */
10363 #else /* not USE_X_TOOLKIT */
10365 XSetLocaleModifiers ("");
10367 dpy
= XOpenDisplay (SDATA (display_name
));
10368 #endif /* not USE_X_TOOLKIT */
10369 #endif /* not USE_GTK*/
10371 /* Detect failure. */
10378 /* We have definitely succeeded. Record the new connection. */
10380 dpyinfo
= (struct x_display_info
*) xmalloc (sizeof (struct x_display_info
));
10381 bzero (dpyinfo
, sizeof *dpyinfo
);
10383 #ifdef MULTI_KBOARD
10385 struct x_display_info
*share
;
10388 for (share
= x_display_list
, tail
= x_display_name_list
; share
;
10389 share
= share
->next
, tail
= XCDR (tail
))
10390 if (same_x_server (SDATA (XCAR (XCAR (tail
))),
10391 SDATA (display_name
)))
10394 dpyinfo
->kboard
= share
->kboard
;
10397 dpyinfo
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
10398 init_kboard (dpyinfo
->kboard
);
10399 if (!EQ (XSYMBOL (Qvendor_specific_keysyms
)->function
, Qunbound
))
10401 char *vendor
= ServerVendor (dpy
);
10403 dpyinfo
->kboard
->Vsystem_key_alist
10404 = call1 (Qvendor_specific_keysyms
,
10405 build_string (vendor
? vendor
: ""));
10409 dpyinfo
->kboard
->next_kboard
= all_kboards
;
10410 all_kboards
= dpyinfo
->kboard
;
10411 /* Don't let the initial kboard remain current longer than necessary.
10412 That would cause problems if a file loaded on startup tries to
10413 prompt in the mini-buffer. */
10414 if (current_kboard
== initial_kboard
)
10415 current_kboard
= dpyinfo
->kboard
;
10417 dpyinfo
->kboard
->reference_count
++;
10421 /* Put this display on the chain. */
10422 dpyinfo
->next
= x_display_list
;
10423 x_display_list
= dpyinfo
;
10425 /* Put it on x_display_name_list as well, to keep them parallel. */
10426 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
10427 x_display_name_list
);
10428 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
10430 dpyinfo
->display
= dpy
;
10433 XSetAfterFunction (x_current_display
, x_trace_wire
);
10437 = (char *) xmalloc (SBYTES (Vinvocation_name
)
10438 + SBYTES (Vsystem_name
)
10440 sprintf (dpyinfo
->x_id_name
, "%s@%s",
10441 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
10443 /* Figure out which modifier bits mean what. */
10444 x_find_modifier_meanings (dpyinfo
);
10446 /* Get the scroll bar cursor. */
10448 /* We must create a GTK cursor, it is required for GTK widgets. */
10449 dpyinfo
->xg_cursor
= xg_create_default_cursor (dpyinfo
->display
);
10450 #endif /* USE_GTK */
10452 dpyinfo
->vertical_scroll_bar_cursor
10453 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
10455 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
10456 resource_name
, EMACS_CLASS
);
10457 #ifdef HAVE_XRMSETDATABASE
10458 XrmSetDatabase (dpyinfo
->display
, xrdb
);
10460 dpyinfo
->display
->db
= xrdb
;
10462 /* Put the rdb where we can find it in a way that works on
10464 dpyinfo
->xrdb
= xrdb
;
10466 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
10467 DefaultScreen (dpyinfo
->display
));
10468 select_visual (dpyinfo
);
10469 dpyinfo
->cmap
= DefaultColormapOfScreen (dpyinfo
->screen
);
10470 dpyinfo
->height
= HeightOfScreen (dpyinfo
->screen
);
10471 dpyinfo
->width
= WidthOfScreen (dpyinfo
->screen
);
10472 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
10473 dpyinfo
->client_leader_window
= 0;
10474 dpyinfo
->grabbed
= 0;
10475 dpyinfo
->reference_count
= 0;
10476 dpyinfo
->icon_bitmap_id
= -1;
10477 dpyinfo
->font_table
= NULL
;
10478 dpyinfo
->n_fonts
= 0;
10479 dpyinfo
->font_table_size
= 0;
10480 dpyinfo
->bitmaps
= 0;
10481 dpyinfo
->bitmaps_size
= 0;
10482 dpyinfo
->bitmaps_last
= 0;
10483 dpyinfo
->scratch_cursor_gc
= 0;
10484 dpyinfo
->mouse_face_mouse_frame
= 0;
10485 dpyinfo
->mouse_face_deferred_gc
= 0;
10486 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
10487 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
10488 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
10489 dpyinfo
->mouse_face_window
= Qnil
;
10490 dpyinfo
->mouse_face_overlay
= Qnil
;
10491 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
10492 dpyinfo
->mouse_face_defer
= 0;
10493 dpyinfo
->mouse_face_hidden
= 0;
10494 dpyinfo
->x_focus_frame
= 0;
10495 dpyinfo
->x_focus_event_frame
= 0;
10496 dpyinfo
->x_highlight_frame
= 0;
10497 dpyinfo
->image_cache
= make_image_cache ();
10498 dpyinfo
->wm_type
= X_WMTYPE_UNKNOWN
;
10500 /* See if we can construct pixel values from RGB values. */
10501 dpyinfo
->red_bits
= dpyinfo
->blue_bits
= dpyinfo
->green_bits
= 0;
10502 dpyinfo
->red_offset
= dpyinfo
->blue_offset
= dpyinfo
->green_offset
= 0;
10504 if (dpyinfo
->visual
->class == TrueColor
)
10506 get_bits_and_offset (dpyinfo
->visual
->red_mask
,
10507 &dpyinfo
->red_bits
, &dpyinfo
->red_offset
);
10508 get_bits_and_offset (dpyinfo
->visual
->blue_mask
,
10509 &dpyinfo
->blue_bits
, &dpyinfo
->blue_offset
);
10510 get_bits_and_offset (dpyinfo
->visual
->green_mask
,
10511 &dpyinfo
->green_bits
, &dpyinfo
->green_offset
);
10514 /* See if a private colormap is requested. */
10515 if (dpyinfo
->visual
== DefaultVisualOfScreen (dpyinfo
->screen
))
10517 if (dpyinfo
->visual
->class == PseudoColor
)
10520 value
= display_x_get_resource (dpyinfo
,
10521 build_string ("privateColormap"),
10522 build_string ("PrivateColormap"),
10524 if (STRINGP (value
)
10525 && (!strcmp (SDATA (value
), "true")
10526 || !strcmp (SDATA (value
), "on")))
10527 dpyinfo
->cmap
= XCopyColormapAndFree (dpyinfo
->display
, dpyinfo
->cmap
);
10531 dpyinfo
->cmap
= XCreateColormap (dpyinfo
->display
, dpyinfo
->root_window
,
10532 dpyinfo
->visual
, AllocNone
);
10535 int screen_number
= XScreenNumberOfScreen (dpyinfo
->screen
);
10536 double pixels
= DisplayHeight (dpyinfo
->display
, screen_number
);
10537 double mm
= DisplayHeightMM (dpyinfo
->display
, screen_number
);
10538 dpyinfo
->resy
= pixels
* 25.4 / mm
;
10539 pixels
= DisplayWidth (dpyinfo
->display
, screen_number
);
10540 mm
= DisplayWidthMM (dpyinfo
->display
, screen_number
);
10541 dpyinfo
->resx
= pixels
* 25.4 / mm
;
10544 dpyinfo
->Xatom_wm_protocols
10545 = XInternAtom (dpyinfo
->display
, "WM_PROTOCOLS", False
);
10546 dpyinfo
->Xatom_wm_take_focus
10547 = XInternAtom (dpyinfo
->display
, "WM_TAKE_FOCUS", False
);
10548 dpyinfo
->Xatom_wm_save_yourself
10549 = XInternAtom (dpyinfo
->display
, "WM_SAVE_YOURSELF", False
);
10550 dpyinfo
->Xatom_wm_delete_window
10551 = XInternAtom (dpyinfo
->display
, "WM_DELETE_WINDOW", False
);
10552 dpyinfo
->Xatom_wm_change_state
10553 = XInternAtom (dpyinfo
->display
, "WM_CHANGE_STATE", False
);
10554 dpyinfo
->Xatom_wm_configure_denied
10555 = XInternAtom (dpyinfo
->display
, "WM_CONFIGURE_DENIED", False
);
10556 dpyinfo
->Xatom_wm_window_moved
10557 = XInternAtom (dpyinfo
->display
, "WM_MOVED", False
);
10558 dpyinfo
->Xatom_wm_client_leader
10559 = XInternAtom (dpyinfo
->display
, "WM_CLIENT_LEADER", False
);
10560 dpyinfo
->Xatom_editres
10561 = XInternAtom (dpyinfo
->display
, "Editres", False
);
10562 dpyinfo
->Xatom_CLIPBOARD
10563 = XInternAtom (dpyinfo
->display
, "CLIPBOARD", False
);
10564 dpyinfo
->Xatom_TIMESTAMP
10565 = XInternAtom (dpyinfo
->display
, "TIMESTAMP", False
);
10566 dpyinfo
->Xatom_TEXT
10567 = XInternAtom (dpyinfo
->display
, "TEXT", False
);
10568 dpyinfo
->Xatom_COMPOUND_TEXT
10569 = XInternAtom (dpyinfo
->display
, "COMPOUND_TEXT", False
);
10570 dpyinfo
->Xatom_UTF8_STRING
10571 = XInternAtom (dpyinfo
->display
, "UTF8_STRING", False
);
10572 dpyinfo
->Xatom_DELETE
10573 = XInternAtom (dpyinfo
->display
, "DELETE", False
);
10574 dpyinfo
->Xatom_MULTIPLE
10575 = XInternAtom (dpyinfo
->display
, "MULTIPLE", False
);
10576 dpyinfo
->Xatom_INCR
10577 = XInternAtom (dpyinfo
->display
, "INCR", False
);
10578 dpyinfo
->Xatom_EMACS_TMP
10579 = XInternAtom (dpyinfo
->display
, "_EMACS_TMP_", False
);
10580 dpyinfo
->Xatom_TARGETS
10581 = XInternAtom (dpyinfo
->display
, "TARGETS", False
);
10582 dpyinfo
->Xatom_NULL
10583 = XInternAtom (dpyinfo
->display
, "NULL", False
);
10584 dpyinfo
->Xatom_ATOM_PAIR
10585 = XInternAtom (dpyinfo
->display
, "ATOM_PAIR", False
);
10586 /* For properties of font. */
10587 dpyinfo
->Xatom_PIXEL_SIZE
10588 = XInternAtom (dpyinfo
->display
, "PIXEL_SIZE", False
);
10589 dpyinfo
->Xatom_MULE_BASELINE_OFFSET
10590 = XInternAtom (dpyinfo
->display
, "_MULE_BASELINE_OFFSET", False
);
10591 dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
10592 = XInternAtom (dpyinfo
->display
, "_MULE_RELATIVE_COMPOSE", False
);
10593 dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
10594 = XInternAtom (dpyinfo
->display
, "_MULE_DEFAULT_ASCENT", False
);
10596 /* Ghostscript support. */
10597 dpyinfo
->Xatom_PAGE
= XInternAtom (dpyinfo
->display
, "PAGE", False
);
10598 dpyinfo
->Xatom_DONE
= XInternAtom (dpyinfo
->display
, "DONE", False
);
10600 dpyinfo
->Xatom_Scrollbar
= XInternAtom (dpyinfo
->display
, "SCROLLBAR",
10603 dpyinfo
->cut_buffers_initialized
= 0;
10605 connection
= ConnectionNumber (dpyinfo
->display
);
10606 dpyinfo
->connection
= connection
;
10611 null_bits
[0] = 0x00;
10613 dpyinfo
->null_pixel
10614 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
10615 null_bits
, 1, 1, (long) 0, (long) 0,
10620 extern int gray_bitmap_width
, gray_bitmap_height
;
10621 extern char *gray_bitmap_bits
;
10623 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
10625 gray_bitmap_width
, gray_bitmap_height
,
10626 (unsigned long) 1, (unsigned long) 0, 1);
10630 xim_initialize (dpyinfo
, resource_name
);
10633 #ifdef subprocesses
10634 /* This is only needed for distinguishing keyboard and process input. */
10635 if (connection
!= 0)
10636 add_keyboard_wait_descriptor (connection
);
10639 #ifndef F_SETOWN_BUG
10641 #ifdef F_SETOWN_SOCK_NEG
10642 /* stdin is a socket here */
10643 fcntl (connection
, F_SETOWN
, -getpid ());
10644 #else /* ! defined (F_SETOWN_SOCK_NEG) */
10645 fcntl (connection
, F_SETOWN
, getpid ());
10646 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
10647 #endif /* ! defined (F_SETOWN) */
10648 #endif /* F_SETOWN_BUG */
10651 if (interrupt_input
)
10652 init_sigio (connection
);
10653 #endif /* ! defined (SIGIO) */
10656 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
10657 /* Make sure that we have a valid font for dialog boxes
10658 so that Xt does not crash. */
10660 Display
*dpy
= dpyinfo
->display
;
10661 XrmValue d
, fr
, to
;
10665 d
.addr
= (XPointer
)&dpy
;
10666 d
.size
= sizeof (Display
*);
10667 fr
.addr
= XtDefaultFont
;
10668 fr
.size
= sizeof (XtDefaultFont
);
10669 to
.size
= sizeof (Font
*);
10670 to
.addr
= (XPointer
)&font
;
10671 count
= x_catch_errors (dpy
);
10672 if (!XtCallConverter (dpy
, XtCvtStringToFont
, &d
, 1, &fr
, &to
, NULL
))
10674 if (x_had_errors_p (dpy
) || !XQueryFont (dpy
, font
))
10675 XrmPutLineResource (&xrdb
, "Emacs.dialog.*.font: 9x15");
10676 x_uncatch_errors (dpy
, count
);
10681 /* See if we should run in synchronous mode. This is useful
10682 for debugging X code. */
10685 value
= display_x_get_resource (dpyinfo
,
10686 build_string ("synchronous"),
10687 build_string ("Synchronous"),
10689 if (STRINGP (value
)
10690 && (!strcmp (SDATA (value
), "true")
10691 || !strcmp (SDATA (value
), "on")))
10692 XSynchronize (dpyinfo
->display
, True
);
10697 value
= display_x_get_resource (dpyinfo
,
10698 build_string ("useXIM"),
10699 build_string ("UseXIM"),
10702 if (STRINGP (value
)
10703 && (!strcmp (XSTRING (value
)->data
, "false")
10704 || !strcmp (XSTRING (value
)->data
, "off")))
10707 if (STRINGP (value
)
10708 && (!strcmp (XSTRING (value
)->data
, "true")
10709 || !strcmp (XSTRING (value
)->data
, "on")))
10715 /* Only do this for the first display. */
10716 if (x_initialized
== 1)
10717 x_session_initialize (dpyinfo
);
10725 /* Get rid of display DPYINFO, assuming all frames are already gone,
10726 and without sending any more commands to the X server. */
10729 x_delete_display (dpyinfo
)
10730 struct x_display_info
*dpyinfo
;
10734 delete_keyboard_wait_descriptor (dpyinfo
->connection
);
10736 /* Discard this display from x_display_name_list and x_display_list.
10737 We can't use Fdelq because that can quit. */
10738 if (! NILP (x_display_name_list
)
10739 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
10740 x_display_name_list
= XCDR (x_display_name_list
);
10745 tail
= x_display_name_list
;
10746 while (CONSP (tail
) && CONSP (XCDR (tail
)))
10748 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
10750 XSETCDR (tail
, XCDR (XCDR (tail
)));
10753 tail
= XCDR (tail
);
10757 if (next_noop_dpyinfo
== dpyinfo
)
10758 next_noop_dpyinfo
= dpyinfo
->next
;
10760 if (x_display_list
== dpyinfo
)
10761 x_display_list
= dpyinfo
->next
;
10764 struct x_display_info
*tail
;
10766 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
10767 if (tail
->next
== dpyinfo
)
10768 tail
->next
= tail
->next
->next
;
10771 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
10772 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
10773 XrmDestroyDatabase (dpyinfo
->xrdb
);
10776 #ifdef MULTI_KBOARD
10777 if (--dpyinfo
->kboard
->reference_count
== 0)
10778 delete_kboard (dpyinfo
->kboard
);
10782 xim_close_dpy (dpyinfo
);
10785 /* Free the font names in the font table. */
10786 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
10787 if (dpyinfo
->font_table
[i
].name
)
10789 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
10790 xfree (dpyinfo
->font_table
[i
].full_name
);
10791 xfree (dpyinfo
->font_table
[i
].name
);
10794 if (dpyinfo
->font_table
->font_encoder
)
10795 xfree (dpyinfo
->font_table
->font_encoder
);
10797 xfree (dpyinfo
->font_table
);
10798 xfree (dpyinfo
->x_id_name
);
10799 xfree (dpyinfo
->color_cells
);
10803 #ifdef USE_X_TOOLKIT
10805 /* Atimer callback function for TIMER. Called every 0.1s to process
10806 Xt timeouts, if needed. We must avoid calling XtAppPending as
10807 much as possible because that function does an implicit XFlush
10808 that slows us down. */
10811 x_process_timeouts (timer
)
10812 struct atimer
*timer
;
10814 if (toolkit_scroll_bar_interaction
|| popup_activated ())
10817 while (XtAppPending (Xt_app_con
) & XtIMTimer
)
10818 XtAppProcessEvent (Xt_app_con
, XtIMTimer
);
10823 #endif /* USE_X_TOOLKIT */
10826 /* Set up use of X before we make the first connection. */
10828 extern frame_parm_handler x_frame_parm_handlers
[];
10830 static struct redisplay_interface x_redisplay_interface
=
10832 x_frame_parm_handlers
,
10836 x_clear_end_of_line
,
10838 x_after_update_window_line
,
10839 x_update_window_begin
,
10840 x_update_window_end
,
10846 0, /* flush_display_optional */
10848 x_clear_window_mouse_face
,
10849 x_get_glyph_overhangs
,
10850 x_fix_overlapping_area
,
10851 x_draw_fringe_bitmap
,
10854 x_compute_glyph_string_overhangs
,
10855 x_draw_glyph_string
,
10856 x_define_frame_cursor
,
10857 x_clear_frame_area
,
10858 x_draw_window_cursor
,
10859 x_draw_vertical_window_border
,
10860 x_shift_glyphs_for_insert
10866 rif
= &x_redisplay_interface
;
10868 clear_frame_hook
= x_clear_frame
;
10869 ins_del_lines_hook
= x_ins_del_lines
;
10870 delete_glyphs_hook
= x_delete_glyphs
;
10871 ring_bell_hook
= XTring_bell
;
10872 reset_terminal_modes_hook
= XTreset_terminal_modes
;
10873 set_terminal_modes_hook
= XTset_terminal_modes
;
10874 update_begin_hook
= x_update_begin
;
10875 update_end_hook
= x_update_end
;
10876 set_terminal_window_hook
= XTset_terminal_window
;
10877 read_socket_hook
= XTread_socket
;
10878 frame_up_to_date_hook
= XTframe_up_to_date
;
10879 mouse_position_hook
= XTmouse_position
;
10880 frame_rehighlight_hook
= XTframe_rehighlight
;
10881 frame_raise_lower_hook
= XTframe_raise_lower
;
10882 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
10883 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
10884 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
10885 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
10887 scroll_region_ok
= 1; /* we'll scroll partial frames */
10888 char_ins_del_ok
= 1;
10889 line_ins_del_ok
= 1; /* we'll just blt 'em */
10890 fast_clear_end_of_line
= 1; /* X does this well */
10891 memory_below_frame
= 0; /* we don't remember what scrolls
10896 last_tool_bar_item
= -1;
10897 any_help_event_p
= 0;
10899 /* Try to use interrupt input; if we can't, then start polling. */
10900 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
10902 #ifdef USE_X_TOOLKIT
10903 XtToolkitInitialize ();
10905 Xt_app_con
= XtCreateApplicationContext ();
10907 /* Register a converter from strings to pixels, which uses
10908 Emacs' color allocation infrastructure. */
10909 XtAppSetTypeConverter (Xt_app_con
,
10910 XtRString
, XtRPixel
, cvt_string_to_pixel
,
10911 cvt_string_to_pixel_args
,
10912 XtNumber (cvt_string_to_pixel_args
),
10913 XtCacheByDisplay
, cvt_pixel_dtor
);
10915 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
10917 /* Install an asynchronous timer that processes Xt timeout events
10918 every 0.1s. This is necessary because some widget sets use
10919 timeouts internally, for example the LessTif menu bar, or the
10920 Xaw3d scroll bar. When Xt timouts aren't processed, these
10921 widgets don't behave normally. */
10923 EMACS_TIME interval
;
10924 EMACS_SET_SECS_USECS (interval
, 0, 100000);
10925 start_atimer (ATIMER_CONTINUOUS
, interval
, x_process_timeouts
, 0);
10929 #ifdef USE_TOOLKIT_SCROLL_BARS
10931 xaw3d_arrow_scroll
= False
;
10932 xaw3d_pick_top
= True
;
10936 /* Note that there is no real way portable across R3/R4 to get the
10937 original error handler. */
10938 XSetErrorHandler (x_error_handler
);
10939 XSetIOErrorHandler (x_io_error_quitter
);
10941 /* Disable Window Change signals; they are handled by X events. */
10943 signal (SIGWINCH
, SIG_DFL
);
10944 #endif /* SIGWINCH */
10946 signal (SIGPIPE
, x_connection_signal
);
10953 staticpro (&x_error_message_string
);
10954 x_error_message_string
= Qnil
;
10956 staticpro (&x_display_name_list
);
10957 x_display_name_list
= Qnil
;
10959 staticpro (&last_mouse_scroll_bar
);
10960 last_mouse_scroll_bar
= Qnil
;
10962 staticpro (&Qvendor_specific_keysyms
);
10963 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
10965 staticpro (&Qutf_8
);
10966 Qutf_8
= intern ("utf-8");
10967 staticpro (&Qlatin_1
);
10968 Qlatin_1
= intern ("latin-1");
10970 staticpro (&last_mouse_press_frame
);
10971 last_mouse_press_frame
= Qnil
;
10973 DEFVAR_BOOL ("x-use-underline-position-properties",
10974 &x_use_underline_position_properties
,
10975 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
10976 nil means ignore them. If you encounter fonts with bogus
10977 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
10978 to 4.1, set this to nil. */);
10979 x_use_underline_position_properties
= 1;
10981 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
10982 doc
: /* What X toolkit scroll bars Emacs uses.
10983 A value of nil means Emacs doesn't use X toolkit scroll bars.
10984 Otherwise, value is a symbol describing the X toolkit. */);
10985 #ifdef USE_TOOLKIT_SCROLL_BARS
10987 Vx_toolkit_scroll_bars
= intern ("motif");
10988 #elif defined HAVE_XAW3D
10989 Vx_toolkit_scroll_bars
= intern ("xaw3d");
10991 Vx_toolkit_scroll_bars
= intern ("gtk");
10993 Vx_toolkit_scroll_bars
= intern ("xaw");
10996 Vx_toolkit_scroll_bars
= Qnil
;
10999 staticpro (&last_mouse_motion_frame
);
11000 last_mouse_motion_frame
= Qnil
;
11002 Qmodifier_value
= intern ("modifier-value");
11003 Qalt
= intern ("alt");
11004 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
11005 Qhyper
= intern ("hyper");
11006 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
11007 Qmeta
= intern ("meta");
11008 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
11009 Qsuper
= intern ("super");
11010 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
11012 DEFVAR_LISP ("x-alt-keysym", &Vx_alt_keysym
,
11013 doc
: /* Which keys Emacs uses for the alt modifier.
11014 This should be one of the symbols `alt', `hyper', `meta', `super'.
11015 For example, `alt' means use the Alt_L and Alt_R keysyms. The default
11016 is nil, which is the same as `alt'. */);
11017 Vx_alt_keysym
= Qnil
;
11019 DEFVAR_LISP ("x-hyper-keysym", &Vx_hyper_keysym
,
11020 doc
: /* Which keys Emacs uses for the hyper modifier.
11021 This should be one of the symbols `alt', `hyper', `meta', `super'.
11022 For example, `hyper' means use the Hyper_L and Hyper_R keysyms. The
11023 default is nil, which is the same as `hyper'. */);
11024 Vx_hyper_keysym
= Qnil
;
11026 DEFVAR_LISP ("x-meta-keysym", &Vx_meta_keysym
,
11027 doc
: /* Which keys Emacs uses for the meta modifier.
11028 This should be one of the symbols `alt', `hyper', `meta', `super'.
11029 For example, `meta' means use the Meta_L and Meta_R keysyms. The
11030 default is nil, which is the same as `meta'. */);
11031 Vx_meta_keysym
= Qnil
;
11033 DEFVAR_LISP ("x-super-keysym", &Vx_super_keysym
,
11034 doc
: /* Which keys Emacs uses for the super modifier.
11035 This should be one of the symbols `alt', `hyper', `meta', `super'.
11036 For example, `super' means use the Super_L and Super_R keysyms. The
11037 default is nil, which is the same as `super'. */);
11038 Vx_super_keysym
= Qnil
;
11040 DEFVAR_LISP ("x-keysym-table", &Vx_keysym_table
,
11041 doc
: /* Hash table of character codes indexed by X keysym codes. */);
11042 Vx_keysym_table
= make_hash_table (Qeql
, make_number (900),
11043 make_float (DEFAULT_REHASH_SIZE
),
11044 make_float (DEFAULT_REHASH_THRESHOLD
),
11048 #endif /* HAVE_X_WINDOWS */
11050 /* arch-tag: 6d4e4cb7-abc1-4302-9585-d84dcfb09d0f
11051 (do not change this comment) */