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) */
59 #ifndef INCLUDED_FCNTL
66 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
67 /* #include <sys/param.h> */
73 #include "dispextern.h"
75 #include "termhooks.h"
83 #include "intervals.h"
89 #include <X11/Shell.h>
92 #ifdef HAVE_SYS_TIME_H
104 extern int xlwmenu_window_p
P_ ((Widget w
, Window window
));
105 extern void xlwmenu_redisplay
P_ ((Widget
));
108 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
110 extern void free_frame_menubar
P_ ((struct frame
*));
111 extern struct frame
*x_menubar_window_to_frame
P_ ((struct x_display_info
*,
116 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
118 extern void _XEditResCheckMessages ();
119 #endif /* not NO_EDITRES */
121 /* Include toolkit specific headers for the scroll bar widget. */
123 #ifdef USE_TOOLKIT_SCROLL_BARS
124 #if defined USE_MOTIF
125 #include <Xm/Xm.h> /* for LESSTIF_VERSION */
126 #include <Xm/ScrollBar.h>
127 #else /* !USE_MOTIF i.e. use Xaw */
130 #include <X11/Xaw3d/Simple.h>
131 #include <X11/Xaw3d/Scrollbar.h>
132 #define ARROW_SCROLLBAR
133 #define XAW_ARROW_SCROLLBARS
134 #include <X11/Xaw3d/ScrollbarP.h>
135 #else /* !HAVE_XAW3D */
136 #include <X11/Xaw/Simple.h>
137 #include <X11/Xaw/Scrollbar.h>
138 #endif /* !HAVE_XAW3D */
140 #define XtNpickTop "pickTop"
141 #endif /* !XtNpickTop */
142 #endif /* !USE_MOTIF */
143 #endif /* USE_TOOLKIT_SCROLL_BARS */
145 #endif /* USE_X_TOOLKIT */
147 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
148 #define x_any_window_to_frame x_window_to_frame
149 #define x_top_window_to_frame x_window_to_frame
154 #ifndef XtNinitialState
155 #define XtNinitialState "initialState"
159 #define abs(x) ((x) < 0 ? -(x) : (x))
161 /* Default to using XIM if available. */
165 int use_xim
= 0; /* configure --without-xim */
170 /* Non-nil means Emacs uses toolkit scroll bars. */
172 Lisp_Object Vx_toolkit_scroll_bars
;
174 /* Non-zero means that a HELP_EVENT has been generated since Emacs
177 static int any_help_event_p
;
179 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
180 static Lisp_Object last_window
;
182 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
184 int x_use_underline_position_properties
;
186 /* This is a chain of structures for all the X displays currently in
189 struct x_display_info
*x_display_list
;
191 /* This is a list of cons cells, each of the form (NAME
192 . FONT-LIST-CACHE), one for each element of x_display_list and in
193 the same order. NAME is the name of the frame. FONT-LIST-CACHE
194 records previous values returned by x-list-fonts. */
196 Lisp_Object x_display_name_list
;
198 /* Frame being updated by update_frame. This is declared in term.c.
199 This is set by update_begin and looked at by all the XT functions.
200 It is zero while not inside an update. In that case, the XT
201 functions assume that `selected_frame' is the frame to apply to. */
203 extern struct frame
*updating_frame
;
205 /* This is a frame waiting to be auto-raised, within XTread_socket. */
207 struct frame
*pending_autoraise_frame
;
210 /* The application context for Xt use. */
211 XtAppContext Xt_app_con
;
212 static String Xt_default_resources
[] = {0};
213 #endif /* USE_X_TOOLKIT */
215 /* Non-zero means user is interacting with a toolkit scroll bar. */
217 static int toolkit_scroll_bar_interaction
;
219 /* Non-zero means to not move point as a result of clicking on a
220 frame to focus it (when focus-follows-mouse is nil). */
222 int x_mouse_click_focus_ignore_position
;
224 /* Non-zero timeout value means ignore next mouse click if it arrives
225 before that timeout elapses (i.e. as part of the same sequence of
226 events resulting from clicking on a frame to select it). */
228 static unsigned long ignore_next_mouse_click_timeout
;
232 Formerly, we used PointerMotionHintMask (in standard_event_mask)
233 so that we would have to call XQueryPointer after each MotionNotify
234 event to ask for another such event. However, this made mouse tracking
235 slow, and there was a bug that made it eventually stop.
237 Simply asking for MotionNotify all the time seems to work better.
239 In order to avoid asking for motion events and then throwing most
240 of them away or busy-polling the server for mouse positions, we ask
241 the server for pointer motion hints. This means that we get only
242 one event per group of mouse movements. "Groups" are delimited by
243 other kinds of events (focus changes and button clicks, for
244 example), or by XQueryPointer calls; when one of these happens, we
245 get another MotionNotify event the next time the mouse moves. This
246 is at least as efficient as getting motion events when mouse
247 tracking is on, and I suspect only negligibly worse when tracking
250 /* Where the mouse was last time we reported a mouse event. */
252 static XRectangle last_mouse_glyph
;
253 static Lisp_Object last_mouse_press_frame
;
255 /* The scroll bar in which the last X motion event occurred.
257 If the last X motion event occurred in a scroll bar, we set this so
258 XTmouse_position can know whether to report a scroll bar motion or
261 If the last X motion event didn't occur in a scroll bar, we set
262 this to Qnil, to tell XTmouse_position to return an ordinary motion
265 static Lisp_Object last_mouse_scroll_bar
;
267 /* This is a hack. We would really prefer that XTmouse_position would
268 return the time associated with the position it returns, but there
269 doesn't seem to be any way to wrest the time-stamp from the server
270 along with the position query. So, we just keep track of the time
271 of the last movement we received, and return that in hopes that
272 it's somewhat accurate. */
274 static Time last_mouse_movement_time
;
276 /* Incremented by XTread_socket whenever it really tries to read
280 static int volatile input_signal_count
;
282 static int input_signal_count
;
285 /* Used locally within XTread_socket. */
287 static int x_noop_count
;
289 /* Initial values of argv and argc. */
291 extern char **initial_argv
;
292 extern int initial_argc
;
294 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
296 /* Tells if a window manager is present or not. */
298 extern Lisp_Object Vx_no_window_manager
;
300 extern Lisp_Object Qeql
;
304 /* A mask of extra modifier bits to put into every keyboard char. */
306 extern EMACS_INT extra_keyboard_modifiers
;
308 /* The keysyms to use for the various modifiers. */
310 Lisp_Object Vx_alt_keysym
, Vx_hyper_keysym
, Vx_meta_keysym
, Vx_super_keysym
;
311 Lisp_Object Vx_keysym_table
;
312 static Lisp_Object Qalt
, Qhyper
, Qmeta
, Qsuper
, Qmodifier_value
;
314 static Lisp_Object Qvendor_specific_keysyms
;
315 static Lisp_Object Qlatin_1
;
317 extern XrmDatabase x_load_resources
P_ ((Display
*, char *, char *, char *));
318 extern int x_bitmap_mask
P_ ((FRAME_PTR
, int));
320 static int x_alloc_nearest_color_1
P_ ((Display
*, Colormap
, XColor
*));
321 static void x_set_window_size_1
P_ ((struct frame
*, int, int, int));
322 static const XColor
*x_color_cells
P_ ((Display
*, int *));
323 static void x_update_window_end
P_ ((struct window
*, int, int));
324 void x_delete_display
P_ ((struct x_display_info
*));
325 static unsigned int x_x_to_emacs_modifiers
P_ ((struct x_display_info
*,
327 static int x_io_error_quitter
P_ ((Display
*));
328 int x_catch_errors
P_ ((Display
*));
329 void x_uncatch_errors
P_ ((Display
*, int));
330 void x_lower_frame
P_ ((struct frame
*));
331 void x_scroll_bar_clear
P_ ((struct frame
*));
332 int x_had_errors_p
P_ ((Display
*));
333 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
334 void x_raise_frame
P_ ((struct frame
*));
335 void x_set_window_size
P_ ((struct frame
*, int, int, int));
336 void x_wm_set_window_state
P_ ((struct frame
*, int));
337 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
338 struct display
*x_create_frame_display
P_ ((struct x_display_info
*));
339 void x_delete_frame_display
P_ ((struct display
*));
340 void x_initialize
P_ ((void));
341 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
342 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
343 static void x_update_end
P_ ((struct frame
*));
344 static void XTframe_up_to_date
P_ ((struct frame
*));
345 static void XTset_terminal_modes
P_ ((struct display
*));
346 static void XTreset_terminal_modes
P_ ((struct display
*));
347 static void x_clear_frame
P_ ((void));
348 static void frame_highlight
P_ ((struct frame
*));
349 static void frame_unhighlight
P_ ((struct frame
*));
350 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
351 static void x_focus_changed
P_ ((int, int, struct x_display_info
*,
352 struct frame
*, struct input_event
*));
353 static void x_detect_focus_change
P_ ((struct x_display_info
*,
354 XEvent
*, struct input_event
*));
355 static void XTframe_rehighlight
P_ ((struct frame
*));
356 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
357 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
358 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
359 enum text_cursor_kinds
));
361 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, GC
));
362 static void x_flush
P_ ((struct frame
*f
));
363 static void x_update_begin
P_ ((struct frame
*));
364 static void x_update_window_begin
P_ ((struct window
*));
365 static void x_after_update_window_line
P_ ((struct glyph_row
*));
366 static struct scroll_bar
*x_window_to_scroll_bar
P_ ((Display
*, Window
));
367 static void x_scroll_bar_report_motion
P_ ((struct frame
**, Lisp_Object
*,
368 enum scroll_bar_part
*,
369 Lisp_Object
*, Lisp_Object
*,
371 static void x_check_fullscreen
P_ ((struct frame
*));
372 static void x_check_expected_move
P_ ((struct frame
*));
373 static int handle_one_xevent
P_ ((struct x_display_info
*, XEvent
*,
374 int *, struct input_event
*));
377 /* Flush display of frame F, or of all frames if F is null. */
386 Lisp_Object rest
, frame
;
387 FOR_EACH_FRAME (rest
, frame
)
388 if (FRAME_X_P (XFRAME (frame
)))
389 x_flush (XFRAME (frame
));
391 else if (FRAME_X_P (f
))
392 XFlush (FRAME_X_DISPLAY (f
));
397 /* Remove calls to XFlush by defining XFlush to an empty replacement.
398 Calls to XFlush should be unnecessary because the X output buffer
399 is flushed automatically as needed by calls to XPending,
400 XNextEvent, or XWindowEvent according to the XFlush man page.
401 XTread_socket calls XPending. Removing XFlush improves
404 #define XFlush(DISPLAY) (void) 0
407 /***********************************************************************
409 ***********************************************************************/
413 /* This is a function useful for recording debugging information about
414 the sequence of occurrences in this file. */
422 struct record event_record
[100];
424 int event_record_index
;
426 record_event (locus
, type
)
430 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
431 event_record_index
= 0;
433 event_record
[event_record_index
].locus
= locus
;
434 event_record
[event_record_index
].type
= type
;
435 event_record_index
++;
442 /* Return the struct x_display_info corresponding to DPY. */
444 struct x_display_info
*
445 x_display_info_for_display (dpy
)
448 struct x_display_info
*dpyinfo
;
450 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
451 if (dpyinfo
->display
== dpy
)
459 /***********************************************************************
460 Starting and ending an update
461 ***********************************************************************/
463 /* Start an update of frame F. This function is installed as a hook
464 for update_begin, i.e. it is called when update_begin is called.
465 This function is called prior to calls to x_update_window_begin for
466 each window being updated. Currently, there is nothing to do here
467 because all interesting stuff is done on a window basis. */
476 /* Start update of window W. Set the global variable updated_window
477 to the window being updated and set output_cursor to the cursor
481 x_update_window_begin (w
)
484 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
485 struct x_display_info
*display_info
= FRAME_X_DISPLAY_INFO (f
);
488 set_output_cursor (&w
->cursor
);
492 if (f
== display_info
->mouse_face_mouse_frame
)
494 /* Don't do highlighting for mouse motion during the update. */
495 display_info
->mouse_face_defer
= 1;
497 /* If F needs to be redrawn, simply forget about any prior mouse
499 if (FRAME_GARBAGED_P (f
))
500 display_info
->mouse_face_window
= Qnil
;
502 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
503 their mouse_face_p flag set, which means that they are always
504 unequal to rows in a desired matrix which never have that
505 flag set. So, rows containing mouse-face glyphs are never
506 scrolled, and we don't have to switch the mouse highlight off
507 here to prevent it from being scrolled. */
509 /* Can we tell that this update does not affect the window
510 where the mouse highlight is? If so, no need to turn off.
511 Likewise, don't do anything if the frame is garbaged;
512 in that case, the frame's current matrix that we would use
513 is all wrong, and we will redisplay that line anyway. */
514 if (!NILP (display_info
->mouse_face_window
)
515 && w
== XWINDOW (display_info
->mouse_face_window
))
519 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
520 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
523 if (i
< w
->desired_matrix
->nrows
)
524 clear_mouse_face (display_info
);
533 /* Draw a vertical window border from (x,y0) to (x,y1) */
536 x_draw_vertical_window_border (w
, x
, y0
, y1
)
540 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
542 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
543 f
->output_data
.x
->normal_gc
, x
, y0
, x
, y1
);
546 /* End update of window W (which is equal to updated_window).
548 Draw vertical borders between horizontally adjacent windows, and
549 display W's cursor if CURSOR_ON_P is non-zero.
551 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
552 glyphs in mouse-face were overwritten. In that case we have to
553 make sure that the mouse-highlight is properly redrawn.
555 W may be a menu bar pseudo-window in case we don't have X toolkit
556 support. Such windows don't have a cursor, so don't display it
560 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
562 int cursor_on_p
, mouse_face_overwritten_p
;
564 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (XFRAME (w
->frame
));
566 if (!w
->pseudo_window_p
)
571 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
573 output_cursor
.x
, output_cursor
.y
);
575 x_draw_vertical_border (w
);
577 draw_window_fringes (w
);
582 /* If a row with mouse-face was overwritten, arrange for
583 XTframe_up_to_date to redisplay the mouse highlight. */
584 if (mouse_face_overwritten_p
)
586 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
587 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
588 dpyinfo
->mouse_face_window
= Qnil
;
591 updated_window
= NULL
;
595 /* End update of frame F. This function is installed as a hook in
602 /* Mouse highlight may be displayed again. */
603 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
607 XFlush (FRAME_X_DISPLAY (f
));
613 /* This function is called from various places in xdisp.c whenever a
614 complete update has been performed. The global variable
615 updated_window is not available here. */
618 XTframe_up_to_date (f
)
623 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
625 if (dpyinfo
->mouse_face_deferred_gc
626 || f
== dpyinfo
->mouse_face_mouse_frame
)
629 if (dpyinfo
->mouse_face_mouse_frame
)
630 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
631 dpyinfo
->mouse_face_mouse_x
,
632 dpyinfo
->mouse_face_mouse_y
);
633 dpyinfo
->mouse_face_deferred_gc
= 0;
640 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
641 arrow bitmaps, or clear the fringes if no bitmaps are required
642 before DESIRED_ROW is made current. The window being updated is
643 found in updated_window. This function It is called from
644 update_window_line only if it is known that there are differences
645 between bitmaps to be drawn between current row and DESIRED_ROW. */
648 x_after_update_window_line (desired_row
)
649 struct glyph_row
*desired_row
;
651 struct window
*w
= updated_window
;
657 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
658 desired_row
->redraw_fringe_bitmaps_p
= 1;
660 /* When a window has disappeared, make sure that no rest of
661 full-width rows stays visible in the internal border. Could
662 check here if updated_window is the leftmost/rightmost window,
663 but I guess it's not worth doing since vertically split windows
664 are almost never used, internal border is rarely set, and the
665 overhead is very small. */
666 if (windows_or_buffers_changed
667 && desired_row
->full_width_p
668 && (f
= XFRAME (w
->frame
),
669 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
671 && (height
= desired_row
->visible_height
,
674 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
676 /* Internal border is drawn below the tool bar. */
677 if (WINDOWP (f
->tool_bar_window
)
678 && w
== XWINDOW (f
->tool_bar_window
))
682 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
683 0, y
, width
, height
, False
);
684 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
685 FRAME_PIXEL_WIDTH (f
) - width
,
686 y
, width
, height
, False
);
692 x_draw_fringe_bitmap (w
, row
, p
)
694 struct glyph_row
*row
;
695 struct draw_fringe_bitmap_params
*p
;
697 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
698 Display
*display
= FRAME_X_DISPLAY (f
);
699 Window window
= FRAME_X_WINDOW (f
);
700 GC gc
= f
->output_data
.x
->normal_gc
;
701 struct face
*face
= p
->face
;
704 /* Must clip because of partially visible lines. */
705 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
708 /* Adjust position of "bottom aligned" bitmap on partially
711 int oldVH
= row
->visible_height
;
712 row
->visible_height
= p
->h
;
713 row
->y
-= rowY
- p
->y
;
714 x_clip_to_row (w
, row
, gc
);
716 row
->visible_height
= oldVH
;
719 x_clip_to_row (w
, row
, gc
);
721 if (p
->bx
>= 0 && !p
->overlay_p
)
723 /* In case the same realized face is used for fringes and
724 for something displayed in the text (e.g. face `region' on
725 mono-displays, the fill style may have been changed to
726 FillSolid in x_draw_glyph_string_background. */
728 XSetFillStyle (display
, face
->gc
, FillOpaqueStippled
);
730 XSetForeground (display
, face
->gc
, face
->background
);
732 XFillRectangle (display
, window
, face
->gc
,
733 p
->bx
, p
->by
, p
->nx
, p
->ny
);
736 XSetForeground (display
, face
->gc
, face
->foreground
);
742 Pixmap pixmap
, clipmask
= (Pixmap
) 0;
743 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
747 bits
= (unsigned char *)(p
->bits
+ p
->dh
);
749 bits
= (unsigned char *)p
->bits
+ p
->dh
;
751 /* Draw the bitmap. I believe these small pixmaps can be cached
753 pixmap
= XCreatePixmapFromBitmapData (display
, window
, bits
, p
->wd
, p
->h
,
755 ? (p
->overlay_p
? face
->background
756 : f
->output_data
.x
->cursor_pixel
)
758 face
->background
, depth
);
762 clipmask
= XCreatePixmapFromBitmapData (display
,
763 FRAME_X_DISPLAY_INFO (f
)->root_window
,
766 gcv
.clip_mask
= clipmask
;
767 gcv
.clip_x_origin
= p
->x
;
768 gcv
.clip_y_origin
= p
->y
;
769 XChangeGC (display
, gc
, GCClipMask
| GCClipXOrigin
| GCClipYOrigin
, &gcv
);
772 XCopyArea (display
, pixmap
, window
, gc
, 0, 0,
773 p
->wd
, p
->h
, p
->x
, p
->y
);
774 XFreePixmap (display
, pixmap
);
778 gcv
.clip_mask
= (Pixmap
) 0;
779 XChangeGC (display
, gc
, GCClipMask
, &gcv
);
780 XFreePixmap (display
, clipmask
);
784 XSetClipMask (display
, gc
, None
);
789 /* This is called when starting Emacs and when restarting after
790 suspend. When starting Emacs, no X window is mapped. And nothing
791 must be done to Emacs's own window if it is suspended (though that
795 XTset_terminal_modes (struct display
*display
)
799 /* This is called when exiting or suspending Emacs. Exiting will make
800 the X-windows go away, and suspending requires no action. */
803 XTreset_terminal_modes (struct display
*display
)
809 /***********************************************************************
811 ***********************************************************************/
813 /* Function prototypes of this page. */
815 static int x_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
818 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
819 is not contained in the font. */
822 x_per_char_metric (font
, char2b
, font_type
)
825 int font_type
; /* unused on X */
827 /* The result metric information. */
828 XCharStruct
*pcm
= NULL
;
830 xassert (font
&& char2b
);
832 if (font
->per_char
!= NULL
)
834 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
836 /* min_char_or_byte2 specifies the linear character index
837 corresponding to the first element of the per_char array,
838 max_char_or_byte2 is the index of the last character. A
839 character with non-zero CHAR2B->byte1 is not in the font.
840 A character with byte2 less than min_char_or_byte2 or
841 greater max_char_or_byte2 is not in the font. */
842 if (char2b
->byte1
== 0
843 && char2b
->byte2
>= font
->min_char_or_byte2
844 && char2b
->byte2
<= font
->max_char_or_byte2
)
845 pcm
= font
->per_char
+ char2b
->byte2
- font
->min_char_or_byte2
;
849 /* If either min_byte1 or max_byte1 are nonzero, both
850 min_char_or_byte2 and max_char_or_byte2 are less than
851 256, and the 2-byte character index values corresponding
852 to the per_char array element N (counting from 0) are:
854 byte1 = N/D + min_byte1
855 byte2 = N\D + min_char_or_byte2
859 D = max_char_or_byte2 - min_char_or_byte2 + 1
861 \ = integer modulus */
862 if (char2b
->byte1
>= font
->min_byte1
863 && char2b
->byte1
<= font
->max_byte1
864 && char2b
->byte2
>= font
->min_char_or_byte2
865 && char2b
->byte2
<= font
->max_char_or_byte2
)
867 pcm
= (font
->per_char
868 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
869 * (char2b
->byte1
- font
->min_byte1
))
870 + (char2b
->byte2
- font
->min_char_or_byte2
));
876 /* If the per_char pointer is null, all glyphs between the first
877 and last character indexes inclusive have the same
878 information, as given by both min_bounds and max_bounds. */
879 if (char2b
->byte2
>= font
->min_char_or_byte2
880 && char2b
->byte2
<= font
->max_char_or_byte2
)
881 pcm
= &font
->max_bounds
;
885 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
890 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
891 the two-byte form of C. Encoding is returned in *CHAR2B. */
894 x_encode_char (c
, char2b
, font_info
, two_byte_p
)
897 struct font_info
*font_info
;
900 int charset
= CHAR_CHARSET (c
);
901 XFontStruct
*font
= font_info
->font
;
903 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
904 This may be either a program in a special encoder language or a
906 if (font_info
->font_encoder
)
908 /* It's a program. */
909 struct ccl_program
*ccl
= font_info
->font_encoder
;
911 if (CHARSET_DIMENSION (charset
) == 1)
913 ccl
->reg
[0] = charset
;
914 ccl
->reg
[1] = char2b
->byte2
;
919 ccl
->reg
[0] = charset
;
920 ccl
->reg
[1] = char2b
->byte1
;
921 ccl
->reg
[2] = char2b
->byte2
;
924 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
926 /* We assume that MSBs are appropriately set/reset by CCL
928 if (font
->max_byte1
== 0) /* 1-byte font */
929 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
931 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
933 else if (font_info
->encoding
[charset
])
935 /* Fixed encoding scheme. See fontset.h for the meaning of the
937 int enc
= font_info
->encoding
[charset
];
939 if ((enc
== 1 || enc
== 2)
940 && CHARSET_DIMENSION (charset
) == 2)
941 char2b
->byte1
|= 0x80;
943 if (enc
== 1 || enc
== 3)
944 char2b
->byte2
|= 0x80;
948 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
950 return FONT_TYPE_UNKNOWN
;
955 /***********************************************************************
957 ***********************************************************************/
961 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
962 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
963 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
965 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
966 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
967 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
968 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
969 static void x_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
970 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
971 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
972 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
973 static int x_alloc_lighter_color
P_ ((struct frame
*, Display
*, Colormap
,
974 unsigned long *, double, int));
975 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
976 double, int, unsigned long));
977 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
978 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
979 static void x_draw_image_relief
P_ ((struct glyph_string
*));
980 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
981 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
982 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
984 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
985 int, int, int, int, XRectangle
*));
986 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
987 int, int, int, XRectangle
*));
990 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
994 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
999 struct glyph_string
*s
;
1001 if (s
->font
== FRAME_FONT (s
->f
)
1002 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
1003 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
1005 s
->gc
= s
->f
->output_data
.x
->cursor_gc
;
1008 /* Cursor on non-default face: must merge. */
1012 xgcv
.background
= s
->f
->output_data
.x
->cursor_pixel
;
1013 xgcv
.foreground
= s
->face
->background
;
1015 /* If the glyph would be invisible, try a different foreground. */
1016 if (xgcv
.foreground
== xgcv
.background
)
1017 xgcv
.foreground
= s
->face
->foreground
;
1018 if (xgcv
.foreground
== xgcv
.background
)
1019 xgcv
.foreground
= s
->f
->output_data
.x
->cursor_foreground_pixel
;
1020 if (xgcv
.foreground
== xgcv
.background
)
1021 xgcv
.foreground
= s
->face
->foreground
;
1023 /* Make sure the cursor is distinct from text in this face. */
1024 if (xgcv
.background
== s
->face
->background
1025 && xgcv
.foreground
== s
->face
->foreground
)
1027 xgcv
.background
= s
->face
->foreground
;
1028 xgcv
.foreground
= s
->face
->background
;
1031 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1032 xgcv
.font
= s
->font
->fid
;
1033 xgcv
.graphics_exposures
= False
;
1034 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
1036 if (FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1037 XChangeGC (s
->display
, FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1040 FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1041 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1043 s
->gc
= FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1048 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1051 x_set_mouse_face_gc (s
)
1052 struct glyph_string
*s
;
1057 /* What face has to be used last for the mouse face? */
1058 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
1059 face
= FACE_FROM_ID (s
->f
, face_id
);
1061 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
1063 if (s
->first_glyph
->type
== CHAR_GLYPH
)
1064 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
1066 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
1067 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
1068 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1070 /* If font in this face is same as S->font, use it. */
1071 if (s
->font
== s
->face
->font
)
1072 s
->gc
= s
->face
->gc
;
1075 /* Otherwise construct scratch_cursor_gc with values from FACE
1080 xgcv
.background
= s
->face
->background
;
1081 xgcv
.foreground
= s
->face
->foreground
;
1082 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1083 xgcv
.font
= s
->font
->fid
;
1084 xgcv
.graphics_exposures
= False
;
1085 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
1087 if (FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1088 XChangeGC (s
->display
, FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1091 FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1092 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1094 s
->gc
= FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1097 xassert (s
->gc
!= 0);
1101 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1102 Faces to use in the mode line have already been computed when the
1103 matrix was built, so there isn't much to do, here. */
1106 x_set_mode_line_face_gc (s
)
1107 struct glyph_string
*s
;
1109 s
->gc
= s
->face
->gc
;
1113 /* Set S->gc of glyph string S for drawing that glyph string. Set
1114 S->stippled_p to a non-zero value if the face of S has a stipple
1118 x_set_glyph_string_gc (s
)
1119 struct glyph_string
*s
;
1121 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1123 if (s
->hl
== DRAW_NORMAL_TEXT
)
1125 s
->gc
= s
->face
->gc
;
1126 s
->stippled_p
= s
->face
->stipple
!= 0;
1128 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
1130 x_set_mode_line_face_gc (s
);
1131 s
->stippled_p
= s
->face
->stipple
!= 0;
1133 else if (s
->hl
== DRAW_CURSOR
)
1135 x_set_cursor_gc (s
);
1138 else if (s
->hl
== DRAW_MOUSE_FACE
)
1140 x_set_mouse_face_gc (s
);
1141 s
->stippled_p
= s
->face
->stipple
!= 0;
1143 else if (s
->hl
== DRAW_IMAGE_RAISED
1144 || s
->hl
== DRAW_IMAGE_SUNKEN
)
1146 s
->gc
= s
->face
->gc
;
1147 s
->stippled_p
= s
->face
->stipple
!= 0;
1151 s
->gc
= s
->face
->gc
;
1152 s
->stippled_p
= s
->face
->stipple
!= 0;
1155 /* GC must have been set. */
1156 xassert (s
->gc
!= 0);
1160 /* Set clipping for output of glyph string S. S may be part of a mode
1161 line or menu if we don't have X toolkit support. */
1164 x_set_glyph_string_clipping (s
)
1165 struct glyph_string
*s
;
1168 get_glyph_string_clip_rect (s
, &r
);
1169 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, &r
, 1, Unsorted
);
1174 Compute left and right overhang of glyph string S. If S is a glyph
1175 string for a composition, assume overhangs don't exist. */
1178 x_compute_glyph_string_overhangs (s
)
1179 struct glyph_string
*s
;
1182 && s
->first_glyph
->type
== CHAR_GLYPH
)
1185 int direction
, font_ascent
, font_descent
;
1186 XTextExtents16 (s
->font
, s
->char2b
, s
->nchars
, &direction
,
1187 &font_ascent
, &font_descent
, &cs
);
1188 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
1189 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
1194 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1197 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
1198 struct glyph_string
*s
;
1202 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
, &xgcv
);
1203 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
1204 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
1205 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
1209 /* Draw the background of glyph_string S. If S->background_filled_p
1210 is non-zero don't draw it. FORCE_P non-zero means draw the
1211 background even if it wouldn't be drawn normally. This is used
1212 when a string preceding S draws into the background of S, or S
1213 contains the first component of a composition. */
1216 x_draw_glyph_string_background (s
, force_p
)
1217 struct glyph_string
*s
;
1220 /* Nothing to do if background has already been drawn or if it
1221 shouldn't be drawn in the first place. */
1222 if (!s
->background_filled_p
)
1224 int box_line_width
= max (s
->face
->box_line_width
, 0);
1228 /* Fill background with a stipple pattern. */
1229 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
1230 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
1231 s
->y
+ box_line_width
,
1232 s
->background_width
,
1233 s
->height
- 2 * box_line_width
);
1234 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
1235 s
->background_filled_p
= 1;
1237 else if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
1238 || s
->font_not_found_p
1239 || s
->extends_to_end_of_line_p
1242 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
1243 s
->background_width
,
1244 s
->height
- 2 * box_line_width
);
1245 s
->background_filled_p
= 1;
1251 /* Draw the foreground of glyph string S. */
1254 x_draw_glyph_string_foreground (s
)
1255 struct glyph_string
*s
;
1259 /* If first glyph of S has a left box line, start drawing the text
1260 of S to the right of that box line. */
1261 if (s
->face
->box
!= FACE_NO_BOX
1262 && s
->first_glyph
->left_box_line_p
)
1263 x
= s
->x
+ abs (s
->face
->box_line_width
);
1267 /* Draw characters of S as rectangles if S's font could not be
1269 if (s
->font_not_found_p
)
1271 for (i
= 0; i
< s
->nchars
; ++i
)
1273 struct glyph
*g
= s
->first_glyph
+ i
;
1274 XDrawRectangle (s
->display
, s
->window
,
1275 s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
1277 x
+= g
->pixel_width
;
1282 char *char1b
= (char *) s
->char2b
;
1283 int boff
= s
->font_info
->baseline_offset
;
1285 if (s
->font_info
->vertical_centering
)
1286 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
1288 /* If we can use 8-bit functions, condense S->char2b. */
1290 for (i
= 0; i
< s
->nchars
; ++i
)
1291 char1b
[i
] = s
->char2b
[i
].byte2
;
1293 /* Draw text with XDrawString if background has already been
1294 filled. Otherwise, use XDrawImageString. (Note that
1295 XDrawImageString is usually faster than XDrawString.) Always
1296 use XDrawImageString when drawing the cursor so that there is
1297 no chance that characters under a box cursor are invisible. */
1298 if (s
->for_overlaps_p
1299 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
1301 /* Draw characters with 16-bit or 8-bit functions. */
1303 XDrawString16 (s
->display
, s
->window
, s
->gc
, x
,
1304 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
1306 XDrawString (s
->display
, s
->window
, s
->gc
, x
,
1307 s
->ybase
- boff
, char1b
, s
->nchars
);
1312 XDrawImageString16 (s
->display
, s
->window
, s
->gc
, x
,
1313 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
1315 XDrawImageString (s
->display
, s
->window
, s
->gc
, x
,
1316 s
->ybase
- boff
, char1b
, s
->nchars
);
1319 if (s
->face
->overstrike
)
1321 /* For overstriking (to simulate bold-face), draw the
1322 characters again shifted to the right by one pixel. */
1324 XDrawString16 (s
->display
, s
->window
, s
->gc
, x
+ 1,
1325 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
1327 XDrawString (s
->display
, s
->window
, s
->gc
, x
+ 1,
1328 s
->ybase
- boff
, char1b
, s
->nchars
);
1333 /* Draw the foreground of composite glyph string S. */
1336 x_draw_composite_glyph_string_foreground (s
)
1337 struct glyph_string
*s
;
1341 /* If first glyph of S has a left box line, start drawing the text
1342 of S to the right of that box line. */
1343 if (s
->face
->box
!= FACE_NO_BOX
1344 && s
->first_glyph
->left_box_line_p
)
1345 x
= s
->x
+ abs (s
->face
->box_line_width
);
1349 /* S is a glyph string for a composition. S->gidx is the index of
1350 the first character drawn for glyphs of this composition.
1351 S->gidx == 0 means we are drawing the very first character of
1352 this composition. */
1354 /* Draw a rectangle for the composition if the font for the very
1355 first character of the composition could not be loaded. */
1356 if (s
->font_not_found_p
)
1359 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, s
->y
,
1360 s
->width
- 1, s
->height
- 1);
1364 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
1366 XDrawString16 (s
->display
, s
->window
, s
->gc
,
1367 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
1368 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
1370 if (s
->face
->overstrike
)
1371 XDrawString16 (s
->display
, s
->window
, s
->gc
,
1372 x
+ s
->cmp
->offsets
[s
->gidx
* 2] + 1,
1373 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
1380 #ifdef USE_X_TOOLKIT
1382 static struct frame
*x_frame_of_widget
P_ ((Widget
));
1383 static Boolean cvt_string_to_pixel
P_ ((Display
*, XrmValue
*, Cardinal
*,
1384 XrmValue
*, XrmValue
*, XtPointer
*));
1385 static void cvt_pixel_dtor
P_ ((XtAppContext
, XrmValue
*, XtPointer
,
1386 XrmValue
*, Cardinal
*));
1389 /* Return the frame on which widget WIDGET is used.. Abort if frame
1390 cannot be determined. */
1392 static struct frame
*
1393 x_frame_of_widget (widget
)
1396 struct x_display_info
*dpyinfo
;
1400 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
1402 /* Find the top-level shell of the widget. Note that this function
1403 can be called when the widget is not yet realized, so XtWindow
1404 (widget) == 0. That's the reason we can't simply use
1405 x_any_window_to_frame. */
1406 while (!XtIsTopLevelShell (widget
))
1407 widget
= XtParent (widget
);
1409 /* Look for a frame with that top-level widget. Allocate the color
1410 on that frame to get the right gamma correction value. */
1411 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
1412 if (GC_FRAMEP (XCAR (tail
))
1413 && (f
= XFRAME (XCAR (tail
)),
1415 && f
->output_data
.nothing
!= 1
1416 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
1417 && f
->output_data
.x
->widget
== widget
)
1424 /* Allocate the color COLOR->pixel on the screen and display of
1425 widget WIDGET in colormap CMAP. If an exact match cannot be
1426 allocated, try the nearest color available. Value is non-zero
1427 if successful. This is called from lwlib. */
1430 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
1435 struct frame
*f
= x_frame_of_widget (widget
);
1436 return x_alloc_nearest_color (f
, cmap
, color
);
1440 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
1441 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1442 If this produces the same color as PIXEL, try a color where all RGB
1443 values have DELTA added. Return the allocated color in *PIXEL.
1444 DISPLAY is the X display, CMAP is the colormap to operate on.
1445 Value is non-zero if successful. */
1448 x_alloc_lighter_color_for_widget (widget
, display
, cmap
, pixel
, factor
, delta
)
1452 unsigned long *pixel
;
1456 struct frame
*f
= x_frame_of_widget (widget
);
1457 return x_alloc_lighter_color (f
, display
, cmap
, pixel
, factor
, delta
);
1461 /* Structure specifying which arguments should be passed by Xt to
1462 cvt_string_to_pixel. We want the widget's screen and colormap. */
1464 static XtConvertArgRec cvt_string_to_pixel_args
[] =
1466 {XtWidgetBaseOffset
, (XtPointer
) XtOffset (Widget
, core
.screen
),
1468 {XtWidgetBaseOffset
, (XtPointer
) XtOffset (Widget
, core
.colormap
),
1473 /* The address of this variable is returned by
1474 cvt_string_to_pixel. */
1476 static Pixel cvt_string_to_pixel_value
;
1479 /* Convert a color name to a pixel color.
1481 DPY is the display we are working on.
1483 ARGS is an array of *NARGS XrmValue structures holding additional
1484 information about the widget for which the conversion takes place.
1485 The contents of this array are determined by the specification
1486 in cvt_string_to_pixel_args.
1488 FROM is a pointer to an XrmValue which points to the color name to
1489 convert. TO is an XrmValue in which to return the pixel color.
1491 CLOSURE_RET is a pointer to user-data, in which we record if
1492 we allocated the color or not.
1494 Value is True if successful, False otherwise. */
1497 cvt_string_to_pixel (dpy
, args
, nargs
, from
, to
, closure_ret
)
1501 XrmValue
*from
, *to
;
1502 XtPointer
*closure_ret
;
1512 XtAppWarningMsg (XtDisplayToApplicationContext (dpy
),
1513 "wrongParameters", "cvt_string_to_pixel",
1515 "Screen and colormap args required", NULL
, NULL
);
1519 screen
= *(Screen
**) args
[0].addr
;
1520 cmap
= *(Colormap
*) args
[1].addr
;
1521 color_name
= (String
) from
->addr
;
1523 if (strcmp (color_name
, XtDefaultBackground
) == 0)
1525 *closure_ret
= (XtPointer
) False
;
1526 pixel
= WhitePixelOfScreen (screen
);
1528 else if (strcmp (color_name
, XtDefaultForeground
) == 0)
1530 *closure_ret
= (XtPointer
) False
;
1531 pixel
= BlackPixelOfScreen (screen
);
1533 else if (XParseColor (dpy
, cmap
, color_name
, &color
)
1534 && x_alloc_nearest_color_1 (dpy
, cmap
, &color
))
1536 pixel
= color
.pixel
;
1537 *closure_ret
= (XtPointer
) True
;
1542 Cardinal nparams
= 1;
1544 params
[0] = color_name
;
1545 XtAppWarningMsg (XtDisplayToApplicationContext (dpy
),
1546 "badValue", "cvt_string_to_pixel",
1547 "XtToolkitError", "Invalid color `%s'",
1552 if (to
->addr
!= NULL
)
1554 if (to
->size
< sizeof (Pixel
))
1556 to
->size
= sizeof (Pixel
);
1560 *(Pixel
*) to
->addr
= pixel
;
1564 cvt_string_to_pixel_value
= pixel
;
1565 to
->addr
= (XtPointer
) &cvt_string_to_pixel_value
;
1568 to
->size
= sizeof (Pixel
);
1573 /* Free a pixel color which was previously allocated via
1574 cvt_string_to_pixel. This is registered as the destructor
1575 for this type of resource via XtSetTypeConverter.
1577 APP is the application context in which we work.
1579 TO is a pointer to an XrmValue holding the color to free.
1580 CLOSURE is the value we stored in CLOSURE_RET for this color
1581 in cvt_string_to_pixel.
1583 ARGS and NARGS are like for cvt_string_to_pixel. */
1586 cvt_pixel_dtor (app
, to
, closure
, args
, nargs
)
1595 XtAppWarningMsg (app
, "wrongParameters", "cvt_pixel_dtor",
1597 "Screen and colormap arguments required",
1600 else if (closure
!= NULL
)
1602 /* We did allocate the pixel, so free it. */
1603 Screen
*screen
= *(Screen
**) args
[0].addr
;
1604 Colormap cmap
= *(Colormap
*) args
[1].addr
;
1605 x_free_dpy_colors (DisplayOfScreen (screen
), screen
, cmap
,
1606 (Pixel
*) to
->addr
, 1);
1611 #endif /* USE_X_TOOLKIT */
1614 /* Value is an array of XColor structures for the contents of the
1615 color map of display DPY. Set *NCELLS to the size of the array.
1616 Note that this probably shouldn't be called for large color maps,
1617 say a 24-bit TrueColor map. */
1619 static const XColor
*
1620 x_color_cells (dpy
, ncells
)
1624 struct x_display_info
*dpyinfo
= x_display_info_for_display (dpy
);
1626 if (dpyinfo
->color_cells
== NULL
)
1628 Screen
*screen
= dpyinfo
->screen
;
1631 dpyinfo
->ncolor_cells
1632 = XDisplayCells (dpy
, XScreenNumberOfScreen (screen
));
1633 dpyinfo
->color_cells
1634 = (XColor
*) xmalloc (dpyinfo
->ncolor_cells
1635 * sizeof *dpyinfo
->color_cells
);
1637 for (i
= 0; i
< dpyinfo
->ncolor_cells
; ++i
)
1638 dpyinfo
->color_cells
[i
].pixel
= i
;
1640 XQueryColors (dpy
, dpyinfo
->cmap
,
1641 dpyinfo
->color_cells
, dpyinfo
->ncolor_cells
);
1644 *ncells
= dpyinfo
->ncolor_cells
;
1645 return dpyinfo
->color_cells
;
1649 /* On frame F, translate pixel colors to RGB values for the NCOLORS
1650 colors in COLORS. Use cached information, if available. */
1653 x_query_colors (f
, colors
, ncolors
)
1658 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
1660 if (dpyinfo
->color_cells
)
1663 for (i
= 0; i
< ncolors
; ++i
)
1665 unsigned long pixel
= colors
[i
].pixel
;
1666 xassert (pixel
< dpyinfo
->ncolor_cells
);
1667 xassert (dpyinfo
->color_cells
[pixel
].pixel
== pixel
);
1668 colors
[i
] = dpyinfo
->color_cells
[pixel
];
1672 XQueryColors (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), colors
, ncolors
);
1676 /* On frame F, translate pixel color to RGB values for the color in
1677 COLOR. Use cached information, if available. */
1680 x_query_color (f
, color
)
1684 x_query_colors (f
, color
, 1);
1688 /* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP. If an
1689 exact match can't be allocated, try the nearest color available.
1690 Value is non-zero if successful. Set *COLOR to the color
1694 x_alloc_nearest_color_1 (dpy
, cmap
, color
)
1701 rc
= XAllocColor (dpy
, cmap
, color
);
1704 /* If we got to this point, the colormap is full, so we're going
1705 to try to get the next closest color. The algorithm used is
1706 a least-squares matching, which is what X uses for closest
1707 color matching with StaticColor visuals. */
1709 unsigned long nearest_delta
= ~0;
1711 const XColor
*cells
= x_color_cells (dpy
, &ncells
);
1713 for (nearest
= i
= 0; i
< ncells
; ++i
)
1715 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
1716 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
1717 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
1718 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
1720 if (delta
< nearest_delta
)
1723 nearest_delta
= delta
;
1727 color
->red
= cells
[nearest
].red
;
1728 color
->green
= cells
[nearest
].green
;
1729 color
->blue
= cells
[nearest
].blue
;
1730 rc
= XAllocColor (dpy
, cmap
, color
);
1734 /* If allocation succeeded, and the allocated pixel color is not
1735 equal to a cached pixel color recorded earlier, there was a
1736 change in the colormap, so clear the color cache. */
1737 struct x_display_info
*dpyinfo
= x_display_info_for_display (dpy
);
1738 XColor
*cached_color
;
1740 if (dpyinfo
->color_cells
1741 && (cached_color
= &dpyinfo
->color_cells
[color
->pixel
],
1742 (cached_color
->red
!= color
->red
1743 || cached_color
->blue
!= color
->blue
1744 || cached_color
->green
!= color
->green
)))
1746 xfree (dpyinfo
->color_cells
);
1747 dpyinfo
->color_cells
= NULL
;
1748 dpyinfo
->ncolor_cells
= 0;
1752 #ifdef DEBUG_X_COLORS
1754 register_color (color
->pixel
);
1755 #endif /* DEBUG_X_COLORS */
1761 /* Allocate the color COLOR->pixel on frame F, colormap CMAP. If an
1762 exact match can't be allocated, try the nearest color available.
1763 Value is non-zero if successful. Set *COLOR to the color
1767 x_alloc_nearest_color (f
, cmap
, color
)
1772 gamma_correct (f
, color
);
1773 return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f
), cmap
, color
);
1777 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
1778 It's necessary to do this instead of just using PIXEL directly to
1779 get color reference counts right. */
1782 x_copy_color (f
, pixel
)
1784 unsigned long pixel
;
1788 color
.pixel
= pixel
;
1790 x_query_color (f
, &color
);
1791 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
1793 #ifdef DEBUG_X_COLORS
1794 register_color (pixel
);
1800 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
1801 It's necessary to do this instead of just using PIXEL directly to
1802 get color reference counts right. */
1805 x_copy_dpy_color (dpy
, cmap
, pixel
)
1808 unsigned long pixel
;
1812 color
.pixel
= pixel
;
1814 XQueryColor (dpy
, cmap
, &color
);
1815 XAllocColor (dpy
, cmap
, &color
);
1817 #ifdef DEBUG_X_COLORS
1818 register_color (pixel
);
1824 /* Brightness beyond which a color won't have its highlight brightness
1827 Nominally, highlight colors for `3d' faces are calculated by
1828 brightening an object's color by a constant scale factor, but this
1829 doesn't yield good results for dark colors, so for colors who's
1830 brightness is less than this value (on a scale of 0-65535) have an
1831 use an additional additive factor.
1833 The value here is set so that the default menu-bar/mode-line color
1834 (grey75) will not have its highlights changed at all. */
1835 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
1838 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
1839 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1840 If this produces the same color as PIXEL, try a color where all RGB
1841 values have DELTA added. Return the allocated color in *PIXEL.
1842 DISPLAY is the X display, CMAP is the colormap to operate on.
1843 Value is non-zero if successful. */
1846 x_alloc_lighter_color (f
, display
, cmap
, pixel
, factor
, delta
)
1850 unsigned long *pixel
;
1858 /* Get RGB color values. */
1859 color
.pixel
= *pixel
;
1860 x_query_color (f
, &color
);
1862 /* Change RGB values by specified FACTOR. Avoid overflow! */
1863 xassert (factor
>= 0);
1864 new.red
= min (0xffff, factor
* color
.red
);
1865 new.green
= min (0xffff, factor
* color
.green
);
1866 new.blue
= min (0xffff, factor
* color
.blue
);
1868 /* Calculate brightness of COLOR. */
1869 bright
= (2 * color
.red
+ 3 * color
.green
+ color
.blue
) / 6;
1871 /* We only boost colors that are darker than
1872 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
1873 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
1874 /* Make an additive adjustment to NEW, because it's dark enough so
1875 that scaling by FACTOR alone isn't enough. */
1877 /* How far below the limit this color is (0 - 1, 1 being darker). */
1878 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
1879 /* The additive adjustment. */
1880 int min_delta
= delta
* dimness
* factor
/ 2;
1884 new.red
= max (0, new.red
- min_delta
);
1885 new.green
= max (0, new.green
- min_delta
);
1886 new.blue
= max (0, new.blue
- min_delta
);
1890 new.red
= min (0xffff, min_delta
+ new.red
);
1891 new.green
= min (0xffff, min_delta
+ new.green
);
1892 new.blue
= min (0xffff, min_delta
+ new.blue
);
1896 /* Try to allocate the color. */
1897 success_p
= x_alloc_nearest_color (f
, cmap
, &new);
1900 if (new.pixel
== *pixel
)
1902 /* If we end up with the same color as before, try adding
1903 delta to the RGB values. */
1904 x_free_colors (f
, &new.pixel
, 1);
1906 new.red
= min (0xffff, delta
+ color
.red
);
1907 new.green
= min (0xffff, delta
+ color
.green
);
1908 new.blue
= min (0xffff, delta
+ color
.blue
);
1909 success_p
= x_alloc_nearest_color (f
, cmap
, &new);
1920 /* Set up the foreground color for drawing relief lines of glyph
1921 string S. RELIEF is a pointer to a struct relief containing the GC
1922 with which lines will be drawn. Use a color that is FACTOR or
1923 DELTA lighter or darker than the relief's background which is found
1924 in S->f->output_data.x->relief_background. If such a color cannot
1925 be allocated, use DEFAULT_PIXEL, instead. */
1928 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
1930 struct relief
*relief
;
1933 unsigned long default_pixel
;
1936 struct x_output
*di
= f
->output_data
.x
;
1937 unsigned long mask
= GCForeground
| GCLineWidth
| GCGraphicsExposures
;
1938 unsigned long pixel
;
1939 unsigned long background
= di
->relief_background
;
1940 Colormap cmap
= FRAME_X_COLORMAP (f
);
1941 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
1942 Display
*dpy
= FRAME_X_DISPLAY (f
);
1944 xgcv
.graphics_exposures
= False
;
1945 xgcv
.line_width
= 1;
1947 /* Free previously allocated color. The color cell will be reused
1948 when it has been freed as many times as it was allocated, so this
1949 doesn't affect faces using the same colors. */
1951 && relief
->allocated_p
)
1953 x_free_colors (f
, &relief
->pixel
, 1);
1954 relief
->allocated_p
= 0;
1957 /* Allocate new color. */
1958 xgcv
.foreground
= default_pixel
;
1960 if (dpyinfo
->n_planes
!= 1
1961 && x_alloc_lighter_color (f
, dpy
, cmap
, &pixel
, factor
, delta
))
1963 relief
->allocated_p
= 1;
1964 xgcv
.foreground
= relief
->pixel
= pixel
;
1967 if (relief
->gc
== 0)
1969 xgcv
.stipple
= dpyinfo
->gray
;
1971 relief
->gc
= XCreateGC (dpy
, FRAME_X_WINDOW (f
), mask
, &xgcv
);
1974 XChangeGC (dpy
, relief
->gc
, mask
, &xgcv
);
1978 /* Set up colors for the relief lines around glyph string S. */
1981 x_setup_relief_colors (s
)
1982 struct glyph_string
*s
;
1984 struct x_output
*di
= s
->f
->output_data
.x
;
1985 unsigned long color
;
1987 if (s
->face
->use_box_color_for_shadows_p
)
1988 color
= s
->face
->box_color
;
1989 else if (s
->first_glyph
->type
== IMAGE_GLYPH
1991 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
1992 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
1997 /* Get the background color of the face. */
1998 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
1999 color
= xgcv
.background
;
2002 if (di
->white_relief
.gc
== 0
2003 || color
!= di
->relief_background
)
2005 di
->relief_background
= color
;
2006 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
2007 WHITE_PIX_DEFAULT (s
->f
));
2008 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
2009 BLACK_PIX_DEFAULT (s
->f
));
2014 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2015 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2016 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2017 relief. LEFT_P non-zero means draw a relief on the left side of
2018 the rectangle. RIGHT_P non-zero means draw a relief on the right
2019 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2023 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
2024 raised_p
, left_p
, right_p
, clip_rect
)
2026 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
, raised_p
;
2027 XRectangle
*clip_rect
;
2029 Display
*dpy
= FRAME_X_DISPLAY (f
);
2030 Window window
= FRAME_X_WINDOW (f
);
2035 gc
= f
->output_data
.x
->white_relief
.gc
;
2037 gc
= f
->output_data
.x
->black_relief
.gc
;
2038 XSetClipRectangles (dpy
, gc
, 0, 0, clip_rect
, 1, Unsorted
);
2041 for (i
= 0; i
< width
; ++i
)
2042 XDrawLine (dpy
, window
, gc
,
2043 left_x
+ i
* left_p
, top_y
+ i
,
2044 right_x
+ 1 - i
* right_p
, top_y
+ i
);
2048 for (i
= 0; i
< width
; ++i
)
2049 XDrawLine (dpy
, window
, gc
,
2050 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
+ 1);
2052 XSetClipMask (dpy
, gc
, None
);
2054 gc
= f
->output_data
.x
->black_relief
.gc
;
2056 gc
= f
->output_data
.x
->white_relief
.gc
;
2057 XSetClipRectangles (dpy
, gc
, 0, 0, clip_rect
, 1, Unsorted
);
2060 for (i
= 0; i
< width
; ++i
)
2061 XDrawLine (dpy
, window
, gc
,
2062 left_x
+ i
* left_p
, bottom_y
- i
,
2063 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
2067 for (i
= 0; i
< width
; ++i
)
2068 XDrawLine (dpy
, window
, gc
,
2069 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
2071 XSetClipMask (dpy
, gc
, None
);
2075 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2076 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2077 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2078 left side of the rectangle. RIGHT_P non-zero means draw a line
2079 on the right side of the rectangle. CLIP_RECT is the clipping
2080 rectangle to use when drawing. */
2083 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2084 left_p
, right_p
, clip_rect
)
2085 struct glyph_string
*s
;
2086 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
2087 XRectangle
*clip_rect
;
2091 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2092 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
2093 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, clip_rect
, 1, Unsorted
);
2096 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2097 left_x
, top_y
, right_x
- left_x
+ 1, width
);
2101 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2102 left_x
, top_y
, width
, bottom_y
- top_y
+ 1);
2105 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2106 left_x
, bottom_y
- width
+ 1, right_x
- left_x
+ 1, width
);
2110 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2111 right_x
- width
+ 1, top_y
, width
, bottom_y
- top_y
+ 1);
2113 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2114 XSetClipMask (s
->display
, s
->gc
, None
);
2118 /* Draw a box around glyph string S. */
2121 x_draw_glyph_string_box (s
)
2122 struct glyph_string
*s
;
2124 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
2125 int left_p
, right_p
;
2126 struct glyph
*last_glyph
;
2127 XRectangle clip_rect
;
2129 last_x
= window_box_right (s
->w
, s
->area
);
2130 if (s
->row
->full_width_p
2131 && !s
->w
->pseudo_window_p
)
2133 last_x
+= WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s
->w
);
2134 if (s
->area
!= RIGHT_MARGIN_AREA
2135 || WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (s
->w
))
2136 last_x
+= WINDOW_RIGHT_FRINGE_WIDTH (s
->w
);
2139 /* The glyph that may have a right box line. */
2140 last_glyph
= (s
->cmp
|| s
->img
2142 : s
->first_glyph
+ s
->nchars
- 1);
2144 width
= abs (s
->face
->box_line_width
);
2145 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
2147 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2149 : min (last_x
, s
->x
+ s
->background_width
) - 1);
2151 bottom_y
= top_y
+ s
->height
- 1;
2153 left_p
= (s
->first_glyph
->left_box_line_p
2154 || (s
->hl
== DRAW_MOUSE_FACE
2156 || s
->prev
->hl
!= s
->hl
)));
2157 right_p
= (last_glyph
->right_box_line_p
2158 || (s
->hl
== DRAW_MOUSE_FACE
2160 || s
->next
->hl
!= s
->hl
)));
2162 get_glyph_string_clip_rect (s
, &clip_rect
);
2164 if (s
->face
->box
== FACE_SIMPLE_BOX
)
2165 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2166 left_p
, right_p
, &clip_rect
);
2169 x_setup_relief_colors (s
);
2170 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
2171 width
, raised_p
, left_p
, right_p
, &clip_rect
);
2176 /* Draw foreground of image glyph string S. */
2179 x_draw_image_foreground (s
)
2180 struct glyph_string
*s
;
2183 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
);
2185 /* If first glyph of S has a left box line, start drawing it to the
2186 right of that line. */
2187 if (s
->face
->box
!= FACE_NO_BOX
2188 && s
->first_glyph
->left_box_line_p
)
2189 x
= s
->x
+ abs (s
->face
->box_line_width
);
2193 /* If there is a margin around the image, adjust x- and y-position
2195 x
+= s
->img
->hmargin
;
2196 y
+= s
->img
->vmargin
;
2202 /* We can't set both a clip mask and use XSetClipRectangles
2203 because the latter also sets a clip mask. We also can't
2204 trust on the shape extension to be available
2205 (XShapeCombineRegion). So, compute the rectangle to draw
2207 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
2210 XRectangle clip_rect
, image_rect
, r
;
2212 xgcv
.clip_mask
= s
->img
->mask
;
2213 xgcv
.clip_x_origin
= x
;
2214 xgcv
.clip_y_origin
= y
;
2215 xgcv
.function
= GXcopy
;
2216 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
2218 get_glyph_string_clip_rect (s
, &clip_rect
);
2221 image_rect
.width
= s
->img
->width
;
2222 image_rect
.height
= s
->img
->height
;
2223 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
2224 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
2225 r
.x
- x
, r
.y
- y
, r
.width
, r
.height
, r
.x
, r
.y
);
2229 XRectangle clip_rect
, image_rect
, r
;
2231 get_glyph_string_clip_rect (s
, &clip_rect
);
2234 image_rect
.width
= s
->img
->width
;
2235 image_rect
.height
= s
->img
->height
;
2236 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
2237 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
2238 r
.x
- x
, r
.y
- y
, r
.width
, r
.height
, r
.x
, r
.y
);
2240 /* When the image has a mask, we can expect that at
2241 least part of a mouse highlight or a block cursor will
2242 be visible. If the image doesn't have a mask, make
2243 a block cursor visible by drawing a rectangle around
2244 the image. I believe it's looking better if we do
2245 nothing here for mouse-face. */
2246 if (s
->hl
== DRAW_CURSOR
)
2248 int r
= s
->img
->relief
;
2250 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
- r
, y
- r
,
2251 s
->img
->width
+ r
*2 - 1, s
->img
->height
+ r
*2 - 1);
2256 /* Draw a rectangle if image could not be loaded. */
2257 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
2258 s
->img
->width
- 1, s
->img
->height
- 1);
2262 /* Draw a relief around the image glyph string S. */
2265 x_draw_image_relief (s
)
2266 struct glyph_string
*s
;
2268 int x0
, y0
, x1
, y1
, thick
, raised_p
;
2271 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
);
2273 /* If first glyph of S has a left box line, start drawing it to the
2274 right of that line. */
2275 if (s
->face
->box
!= FACE_NO_BOX
2276 && s
->first_glyph
->left_box_line_p
)
2277 x
= s
->x
+ abs (s
->face
->box_line_width
);
2281 /* If there is a margin around the image, adjust x- and y-position
2283 x
+= s
->img
->hmargin
;
2284 y
+= s
->img
->vmargin
;
2286 if (s
->hl
== DRAW_IMAGE_SUNKEN
2287 || s
->hl
== DRAW_IMAGE_RAISED
)
2289 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
2290 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
2294 thick
= abs (s
->img
->relief
);
2295 raised_p
= s
->img
->relief
> 0;
2300 x1
= x
+ s
->img
->width
+ thick
- 1;
2301 y1
= y
+ s
->img
->height
+ thick
- 1;
2303 x_setup_relief_colors (s
);
2304 get_glyph_string_clip_rect (s
, &r
);
2305 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
, 1, 1, &r
);
2309 /* Draw the foreground of image glyph string S to PIXMAP. */
2312 x_draw_image_foreground_1 (s
, pixmap
)
2313 struct glyph_string
*s
;
2317 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
);
2319 /* If first glyph of S has a left box line, start drawing it to the
2320 right of that line. */
2321 if (s
->face
->box
!= FACE_NO_BOX
2322 && s
->first_glyph
->left_box_line_p
)
2323 x
= abs (s
->face
->box_line_width
);
2327 /* If there is a margin around the image, adjust x- and y-position
2329 x
+= s
->img
->hmargin
;
2330 y
+= s
->img
->vmargin
;
2336 /* We can't set both a clip mask and use XSetClipRectangles
2337 because the latter also sets a clip mask. We also can't
2338 trust on the shape extension to be available
2339 (XShapeCombineRegion). So, compute the rectangle to draw
2341 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
2345 xgcv
.clip_mask
= s
->img
->mask
;
2346 xgcv
.clip_x_origin
= x
;
2347 xgcv
.clip_y_origin
= y
;
2348 xgcv
.function
= GXcopy
;
2349 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
2351 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
2352 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
2353 XSetClipMask (s
->display
, s
->gc
, None
);
2357 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
2358 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
2360 /* When the image has a mask, we can expect that at
2361 least part of a mouse highlight or a block cursor will
2362 be visible. If the image doesn't have a mask, make
2363 a block cursor visible by drawing a rectangle around
2364 the image. I believe it's looking better if we do
2365 nothing here for mouse-face. */
2366 if (s
->hl
== DRAW_CURSOR
)
2368 int r
= s
->img
->relief
;
2370 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
- r
, y
- r
,
2371 s
->img
->width
+ r
*2 - 1, s
->img
->height
+ r
*2 - 1);
2376 /* Draw a rectangle if image could not be loaded. */
2377 XDrawRectangle (s
->display
, pixmap
, s
->gc
, x
, y
,
2378 s
->img
->width
- 1, s
->img
->height
- 1);
2382 /* Draw part of the background of glyph string S. X, Y, W, and H
2383 give the rectangle to draw. */
2386 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
2387 struct glyph_string
*s
;
2392 /* Fill background with a stipple pattern. */
2393 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2394 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
2395 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2398 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
2402 /* Draw image glyph string S.
2405 s->x +-------------------------
2408 | +-------------------------
2411 | | +-------------------
2417 x_draw_image_glyph_string (s
)
2418 struct glyph_string
*s
;
2421 int box_line_hwidth
= abs (s
->face
->box_line_width
);
2422 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
2424 Pixmap pixmap
= None
;
2426 height
= s
->height
- 2 * box_line_vwidth
;
2429 /* Fill background with face under the image. Do it only if row is
2430 taller than image or if image has a clip mask to reduce
2432 s
->stippled_p
= s
->face
->stipple
!= 0;
2433 if (height
> s
->img
->height
2437 || s
->img
->pixmap
== 0
2438 || s
->width
!= s
->background_width
)
2440 if (box_line_hwidth
&& s
->first_glyph
->left_box_line_p
)
2441 x
= s
->x
+ box_line_hwidth
;
2445 y
= s
->y
+ box_line_vwidth
;
2449 /* Create a pixmap as large as the glyph string. Fill it
2450 with the background color. Copy the image to it, using
2451 its mask. Copy the temporary pixmap to the display. */
2452 Screen
*screen
= FRAME_X_SCREEN (s
->f
);
2453 int depth
= DefaultDepthOfScreen (screen
);
2455 /* Create a pixmap as large as the glyph string. */
2456 pixmap
= XCreatePixmap (s
->display
, s
->window
,
2457 s
->background_width
,
2460 /* Don't clip in the following because we're working on the
2462 XSetClipMask (s
->display
, s
->gc
, None
);
2464 /* Fill the pixmap with the background color/stipple. */
2467 /* Fill background with a stipple pattern. */
2468 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2469 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2470 0, 0, s
->background_width
, s
->height
);
2471 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2476 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
2478 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
2479 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2480 0, 0, s
->background_width
, s
->height
);
2481 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2485 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
2487 s
->background_filled_p
= 1;
2490 /* Draw the foreground. */
2493 x_draw_image_foreground_1 (s
, pixmap
);
2494 x_set_glyph_string_clipping (s
);
2495 XCopyArea (s
->display
, pixmap
, s
->window
, s
->gc
,
2496 0, 0, s
->background_width
, s
->height
, s
->x
, s
->y
);
2497 XFreePixmap (s
->display
, pixmap
);
2500 x_draw_image_foreground (s
);
2502 /* If we must draw a relief around the image, do it. */
2504 || s
->hl
== DRAW_IMAGE_RAISED
2505 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2506 x_draw_image_relief (s
);
2510 /* Draw stretch glyph string S. */
2513 x_draw_stretch_glyph_string (s
)
2514 struct glyph_string
*s
;
2516 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
2517 s
->stippled_p
= s
->face
->stipple
!= 0;
2519 if (s
->hl
== DRAW_CURSOR
2520 && !x_stretch_cursor_p
)
2522 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
2523 as wide as the stretch glyph. */
2524 int width
= min (FRAME_COLUMN_WIDTH (s
->f
), s
->background_width
);
2527 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
2529 /* Clear rest using the GC of the original non-cursor face. */
2530 if (width
< s
->background_width
)
2532 int x
= s
->x
+ width
, y
= s
->y
;
2533 int w
= s
->background_width
- width
, h
= s
->height
;
2537 if (s
->row
->mouse_face_p
2538 && cursor_in_mouse_face_p (s
->w
))
2540 x_set_mouse_face_gc (s
);
2546 get_glyph_string_clip_rect (s
, &r
);
2547 XSetClipRectangles (s
->display
, gc
, 0, 0, &r
, 1, Unsorted
);
2549 if (s
->face
->stipple
)
2551 /* Fill background with a stipple pattern. */
2552 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
2553 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
2554 XSetFillStyle (s
->display
, gc
, FillSolid
);
2559 XGetGCValues (s
->display
, gc
, GCForeground
| GCBackground
, &xgcv
);
2560 XSetForeground (s
->display
, gc
, xgcv
.background
);
2561 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
2562 XSetForeground (s
->display
, gc
, xgcv
.foreground
);
2566 else if (!s
->background_filled_p
)
2567 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
2570 s
->background_filled_p
= 1;
2574 /* Draw glyph string S. */
2577 x_draw_glyph_string (s
)
2578 struct glyph_string
*s
;
2580 int relief_drawn_p
= 0;
2582 /* If S draws into the background of its successor, draw the
2583 background of the successor first so that S can draw into it.
2584 This makes S->next use XDrawString instead of XDrawImageString. */
2585 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps_p
)
2587 xassert (s
->next
->img
== NULL
);
2588 x_set_glyph_string_gc (s
->next
);
2589 x_set_glyph_string_clipping (s
->next
);
2590 x_draw_glyph_string_background (s
->next
, 1);
2593 /* Set up S->gc, set clipping and draw S. */
2594 x_set_glyph_string_gc (s
);
2596 /* Draw relief (if any) in advance for char/composition so that the
2597 glyph string can be drawn over it. */
2598 if (!s
->for_overlaps_p
2599 && s
->face
->box
!= FACE_NO_BOX
2600 && (s
->first_glyph
->type
== CHAR_GLYPH
2601 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
2604 x_set_glyph_string_clipping (s
);
2605 x_draw_glyph_string_background (s
, 1);
2606 x_draw_glyph_string_box (s
);
2607 x_set_glyph_string_clipping (s
);
2611 x_set_glyph_string_clipping (s
);
2613 switch (s
->first_glyph
->type
)
2616 x_draw_image_glyph_string (s
);
2620 x_draw_stretch_glyph_string (s
);
2624 if (s
->for_overlaps_p
)
2625 s
->background_filled_p
= 1;
2627 x_draw_glyph_string_background (s
, 0);
2628 x_draw_glyph_string_foreground (s
);
2631 case COMPOSITE_GLYPH
:
2632 if (s
->for_overlaps_p
|| s
->gidx
> 0)
2633 s
->background_filled_p
= 1;
2635 x_draw_glyph_string_background (s
, 1);
2636 x_draw_composite_glyph_string_foreground (s
);
2643 if (!s
->for_overlaps_p
)
2645 /* Draw underline. */
2646 if (s
->face
->underline_p
)
2648 unsigned long tem
, h
;
2651 /* Get the underline thickness. Default is 1 pixel. */
2652 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_THICKNESS
, &h
))
2655 /* Get the underline position. This is the recommended
2656 vertical offset in pixels from the baseline to the top of
2657 the underline. This is a signed value according to the
2658 specs, and its default is
2660 ROUND ((maximum descent) / 2), with
2661 ROUND(x) = floor (x + 0.5) */
2663 if (x_use_underline_position_properties
2664 && XGetFontProperty (s
->font
, XA_UNDERLINE_POSITION
, &tem
))
2665 y
= s
->ybase
+ (long) tem
;
2666 else if (s
->face
->font
)
2667 y
= s
->ybase
+ (s
->face
->font
->max_bounds
.descent
+ 1) / 2;
2669 y
= s
->y
+ s
->height
- h
;
2671 if (s
->face
->underline_defaulted_p
)
2672 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2673 s
->x
, y
, s
->width
, h
);
2677 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2678 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
2679 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2680 s
->x
, y
, s
->width
, h
);
2681 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2685 /* Draw overline. */
2686 if (s
->face
->overline_p
)
2688 unsigned long dy
= 0, h
= 1;
2690 if (s
->face
->overline_color_defaulted_p
)
2691 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2696 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2697 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
2698 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2700 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2704 /* Draw strike-through. */
2705 if (s
->face
->strike_through_p
)
2707 unsigned long h
= 1;
2708 unsigned long dy
= (s
->height
- h
) / 2;
2710 if (s
->face
->strike_through_color_defaulted_p
)
2711 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2716 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2717 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
2718 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2720 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2724 /* Draw relief if not yet drawn. */
2725 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
2726 x_draw_glyph_string_box (s
);
2729 /* Reset clipping. */
2730 XSetClipMask (s
->display
, s
->gc
, None
);
2733 /* Shift display to make room for inserted glyphs. */
2736 x_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
2738 int x
, y
, width
, height
, shift_by
;
2740 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
2741 f
->output_data
.x
->normal_gc
,
2742 x
, y
, width
, height
,
2746 /* Delete N glyphs at the nominal cursor position. Not implemented
2757 /* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
2758 If they are <= 0, this is probably an error. */
2761 x_clear_area (dpy
, window
, x
, y
, width
, height
, exposures
)
2768 xassert (width
> 0 && height
> 0);
2769 XClearArea (dpy
, window
, x
, y
, width
, height
, exposures
);
2773 /* Clear entire frame. If updating_frame is non-null, clear that
2774 frame. Otherwise clear the selected frame. */
2784 f
= SELECTED_FRAME ();
2786 /* Clearing the frame will erase any cursor, so mark them all as no
2788 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
2789 output_cursor
.hpos
= output_cursor
.vpos
= 0;
2790 output_cursor
.x
= -1;
2792 /* We don't set the output cursor here because there will always
2793 follow an explicit cursor_to. */
2795 XClearWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
2797 /* We have to clear the scroll bars, too. If we have changed
2798 colors or something like that, then they should be notified. */
2799 x_scroll_bar_clear (f
);
2801 XFlush (FRAME_X_DISPLAY (f
));
2804 xg_frame_cleared (f
);
2812 /* Invert the middle quarter of the frame for .15 sec. */
2814 /* We use the select system call to do the waiting, so we have to make
2815 sure it's available. If it isn't, we just won't do visual bells. */
2817 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
2820 /* Subtract the `struct timeval' values X and Y, storing the result in
2821 *RESULT. Return 1 if the difference is negative, otherwise 0. */
2824 timeval_subtract (result
, x
, y
)
2825 struct timeval
*result
, x
, y
;
2827 /* Perform the carry for the later subtraction by updating y. This
2828 is safer because on some systems the tv_sec member is unsigned. */
2829 if (x
.tv_usec
< y
.tv_usec
)
2831 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
2832 y
.tv_usec
-= 1000000 * nsec
;
2836 if (x
.tv_usec
- y
.tv_usec
> 1000000)
2838 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
2839 y
.tv_usec
+= 1000000 * nsec
;
2843 /* Compute the time remaining to wait. tv_usec is certainly
2845 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
2846 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
2848 /* Return indication of whether the result should be considered
2850 return x
.tv_sec
< y
.tv_sec
;
2862 /* Create a GC that will use the GXxor function to flip foreground
2863 pixels into background pixels. */
2867 values
.function
= GXxor
;
2868 values
.foreground
= (f
->output_data
.x
->foreground_pixel
2869 ^ f
->output_data
.x
->background_pixel
);
2871 gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2872 GCFunction
| GCForeground
, &values
);
2876 /* Get the height not including a menu bar widget. */
2877 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
2878 /* Height of each line to flash. */
2879 int flash_height
= FRAME_LINE_HEIGHT (f
);
2880 /* These will be the left and right margins of the rectangles. */
2881 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
2882 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
2886 /* Don't flash the area between a scroll bar and the frame
2887 edge it is next to. */
2888 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
2890 case vertical_scroll_bar_left
:
2891 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
2894 case vertical_scroll_bar_right
:
2895 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
2902 width
= flash_right
- flash_left
;
2904 /* If window is tall, flash top and bottom line. */
2905 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
2907 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
2909 (FRAME_INTERNAL_BORDER_WIDTH (f
)
2910 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
2911 width
, flash_height
);
2912 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
2914 (height
- flash_height
2915 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
2916 width
, flash_height
);
2919 /* If it is short, flash it all. */
2920 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
2921 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
2922 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
2927 struct timeval wakeup
;
2929 EMACS_GET_TIME (wakeup
);
2931 /* Compute time to wait until, propagating carry from usecs. */
2932 wakeup
.tv_usec
+= 150000;
2933 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
2934 wakeup
.tv_usec
%= 1000000;
2936 /* Keep waiting until past the time wakeup or any input gets
2938 while (! detect_input_pending ())
2940 struct timeval current
;
2941 struct timeval timeout
;
2943 EMACS_GET_TIME (current
);
2945 /* Break if result would be negative. */
2946 if (timeval_subtract (¤t
, wakeup
, current
))
2949 /* How long `select' should wait. */
2951 timeout
.tv_usec
= 10000;
2953 /* Try to wait that long--but we might wake up sooner. */
2954 select (0, NULL
, NULL
, NULL
, &timeout
);
2958 /* If window is tall, flash top and bottom line. */
2959 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
2961 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
2963 (FRAME_INTERNAL_BORDER_WIDTH (f
)
2964 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
2965 width
, flash_height
);
2966 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
2968 (height
- flash_height
2969 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
2970 width
, flash_height
);
2973 /* If it is short, flash it all. */
2974 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
2975 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
2976 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
2978 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
2986 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
2989 /* Make audible bell. */
2994 struct frame
*f
= SELECTED_FRAME ();
2996 if (FRAME_X_DISPLAY (f
))
2998 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3005 XBell (FRAME_X_DISPLAY (f
), 0);
3006 XFlush (FRAME_X_DISPLAY (f
));
3013 /* Specify how many text lines, from the top of the window,
3014 should be affected by insert-lines and delete-lines operations.
3015 This, and those operations, are used only within an update
3016 that is bounded by calls to x_update_begin and x_update_end. */
3019 XTset_terminal_window (n
)
3022 /* This function intentionally left blank. */
3027 /***********************************************************************
3029 ***********************************************************************/
3031 /* Perform an insert-lines or delete-lines operation, inserting N
3032 lines or deleting -N lines at vertical position VPOS. */
3035 x_ins_del_lines (vpos
, n
)
3042 /* Scroll part of the display as described by RUN. */
3045 x_scroll_run (w
, run
)
3049 struct frame
*f
= XFRAME (w
->frame
);
3050 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
3052 /* Get frame-relative bounding box of the text display area of W,
3053 without mode lines. Include in this box the left and right
3055 window_box (w
, -1, &x
, &y
, &width
, &height
);
3057 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
3058 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
3059 bottom_y
= y
+ height
;
3063 /* Scrolling up. Make sure we don't copy part of the mode
3064 line at the bottom. */
3065 if (from_y
+ run
->height
> bottom_y
)
3066 height
= bottom_y
- from_y
;
3068 height
= run
->height
;
3072 /* Scolling down. Make sure we don't copy over the mode line.
3074 if (to_y
+ run
->height
> bottom_y
)
3075 height
= bottom_y
- to_y
;
3077 height
= run
->height
;
3082 /* Cursor off. Will be switched on again in x_update_window_end. */
3086 XCopyArea (FRAME_X_DISPLAY (f
),
3087 FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
3088 f
->output_data
.x
->normal_gc
,
3098 /***********************************************************************
3100 ***********************************************************************/
3107 /* We used to only do this if Vx_no_window_manager was non-nil, but
3108 the ICCCM (section 4.1.6) says that the window's border pixmap
3109 and border pixel are window attributes which are "private to the
3110 client", so we can always change it to whatever we want. */
3112 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3113 f
->output_data
.x
->border_pixel
);
3115 x_update_cursor (f
, 1);
3119 frame_unhighlight (f
)
3122 /* We used to only do this if Vx_no_window_manager was non-nil, but
3123 the ICCCM (section 4.1.6) says that the window's border pixmap
3124 and border pixel are window attributes which are "private to the
3125 client", so we can always change it to whatever we want. */
3127 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3128 f
->output_data
.x
->border_tile
);
3130 x_update_cursor (f
, 1);
3133 /* The focus has changed. Update the frames as necessary to reflect
3134 the new situation. Note that we can't change the selected frame
3135 here, because the Lisp code we are interrupting might become confused.
3136 Each event gets marked with the frame in which it occurred, so the
3137 Lisp code can tell when the switch took place by examining the events. */
3140 x_new_focus_frame (dpyinfo
, frame
)
3141 struct x_display_info
*dpyinfo
;
3142 struct frame
*frame
;
3144 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
3146 if (frame
!= dpyinfo
->x_focus_frame
)
3148 /* Set this before calling other routines, so that they see
3149 the correct value of x_focus_frame. */
3150 dpyinfo
->x_focus_frame
= frame
;
3152 if (old_focus
&& old_focus
->auto_lower
)
3153 x_lower_frame (old_focus
);
3156 selected_frame
= frame
;
3157 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
3159 Fselect_window (selected_frame
->selected_window
, Qnil
);
3160 choose_minibuf_frame ();
3163 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
3164 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
3166 pending_autoraise_frame
= 0;
3169 x_frame_rehighlight (dpyinfo
);
3172 /* Handle FocusIn and FocusOut state changes for FRAME.
3173 If FRAME has focus and there exists more than one frame, puts
3174 a FOCUS_IN_EVENT into *BUFP. */
3177 x_focus_changed (type
, state
, dpyinfo
, frame
, bufp
)
3180 struct x_display_info
*dpyinfo
;
3181 struct frame
*frame
;
3182 struct input_event
*bufp
;
3184 if (type
== FocusIn
)
3186 if (dpyinfo
->x_focus_event_frame
!= frame
)
3188 x_new_focus_frame (dpyinfo
, frame
);
3189 dpyinfo
->x_focus_event_frame
= frame
;
3191 /* Don't stop displaying the initial startup message
3192 for a switch-frame event we don't need. */
3193 if (GC_NILP (Vterminal_frame
)
3194 && GC_CONSP (Vframe_list
)
3195 && !GC_NILP (XCDR (Vframe_list
)))
3197 bufp
->kind
= FOCUS_IN_EVENT
;
3198 XSETFRAME (bufp
->frame_or_window
, frame
);
3202 frame
->output_data
.x
->focus_state
|= state
;
3205 if (FRAME_XIC (frame
))
3206 XSetICFocus (FRAME_XIC (frame
));
3209 else if (type
== FocusOut
)
3211 frame
->output_data
.x
->focus_state
&= ~state
;
3213 if (dpyinfo
->x_focus_event_frame
== frame
)
3215 dpyinfo
->x_focus_event_frame
= 0;
3216 x_new_focus_frame (dpyinfo
, 0);
3220 if (FRAME_XIC (frame
))
3221 XUnsetICFocus (FRAME_XIC (frame
));
3226 /* The focus may have changed. Figure out if it is a real focus change,
3227 by checking both FocusIn/Out and Enter/LeaveNotify events.
3229 Returns FOCUS_IN_EVENT event in *BUFP. */
3232 x_detect_focus_change (dpyinfo
, event
, bufp
)
3233 struct x_display_info
*dpyinfo
;
3235 struct input_event
*bufp
;
3237 struct frame
*frame
;
3239 frame
= x_any_window_to_frame (dpyinfo
, event
->xany
.window
);
3243 switch (event
->type
)
3248 struct frame
*focus_frame
= dpyinfo
->x_focus_event_frame
;
3250 = focus_frame
? focus_frame
->output_data
.x
->focus_state
: 0;
3252 if (event
->xcrossing
.detail
!= NotifyInferior
3253 && event
->xcrossing
.focus
3254 && ! (focus_state
& FOCUS_EXPLICIT
))
3255 x_focus_changed ((event
->type
== EnterNotify
? FocusIn
: FocusOut
),
3257 dpyinfo
, frame
, bufp
);
3263 x_focus_changed (event
->type
,
3264 (event
->xfocus
.detail
== NotifyPointer
?
3265 FOCUS_IMPLICIT
: FOCUS_EXPLICIT
),
3266 dpyinfo
, frame
, bufp
);
3272 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3275 x_mouse_leave (dpyinfo
)
3276 struct x_display_info
*dpyinfo
;
3278 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
3281 /* The focus has changed, or we have redirected a frame's focus to
3282 another frame (this happens when a frame uses a surrogate
3283 mini-buffer frame). Shift the highlight as appropriate.
3285 The FRAME argument doesn't necessarily have anything to do with which
3286 frame is being highlighted or un-highlighted; we only use it to find
3287 the appropriate X display info. */
3290 XTframe_rehighlight (frame
)
3291 struct frame
*frame
;
3293 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
3297 x_frame_rehighlight (dpyinfo
)
3298 struct x_display_info
*dpyinfo
;
3300 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
3302 if (dpyinfo
->x_focus_frame
)
3304 dpyinfo
->x_highlight_frame
3305 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
3306 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
3307 : dpyinfo
->x_focus_frame
);
3308 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
3310 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
3311 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
3315 dpyinfo
->x_highlight_frame
= 0;
3317 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
3320 frame_unhighlight (old_highlight
);
3321 if (dpyinfo
->x_highlight_frame
)
3322 frame_highlight (dpyinfo
->x_highlight_frame
);
3328 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3330 /* Initialize mode_switch_bit and modifier_meaning. */
3332 x_find_modifier_meanings (dpyinfo
)
3333 struct x_display_info
*dpyinfo
;
3335 int min_code
, max_code
;
3338 XModifierKeymap
*mods
;
3340 dpyinfo
->meta_mod_mask
= 0;
3341 dpyinfo
->shift_lock_mask
= 0;
3342 dpyinfo
->alt_mod_mask
= 0;
3343 dpyinfo
->super_mod_mask
= 0;
3344 dpyinfo
->hyper_mod_mask
= 0;
3347 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
3349 min_code
= dpyinfo
->display
->min_keycode
;
3350 max_code
= dpyinfo
->display
->max_keycode
;
3353 syms
= XGetKeyboardMapping (dpyinfo
->display
,
3354 min_code
, max_code
- min_code
+ 1,
3356 mods
= XGetModifierMapping (dpyinfo
->display
);
3358 /* Scan the modifier table to see which modifier bits the Meta and
3359 Alt keysyms are on. */
3361 int row
, col
; /* The row and column in the modifier table. */
3363 for (row
= 3; row
< 8; row
++)
3364 for (col
= 0; col
< mods
->max_keypermod
; col
++)
3367 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
3369 /* Zeroes are used for filler. Skip them. */
3373 /* Are any of this keycode's keysyms a meta key? */
3377 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
3379 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
3385 dpyinfo
->meta_mod_mask
|= (1 << row
);
3390 dpyinfo
->alt_mod_mask
|= (1 << row
);
3395 dpyinfo
->hyper_mod_mask
|= (1 << row
);
3400 dpyinfo
->super_mod_mask
|= (1 << row
);
3404 /* Ignore this if it's not on the lock modifier. */
3405 if ((1 << row
) == LockMask
)
3406 dpyinfo
->shift_lock_mask
= LockMask
;
3414 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3415 if (! dpyinfo
->meta_mod_mask
)
3417 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
3418 dpyinfo
->alt_mod_mask
= 0;
3421 /* If some keys are both alt and meta,
3422 make them just meta, not alt. */
3423 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
3425 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
3428 XFree ((char *) syms
);
3429 XFreeModifiermap (mods
);
3432 /* Convert between the modifier bits X uses and the modifier bits
3436 x_x_to_emacs_modifiers (dpyinfo
, state
)
3437 struct x_display_info
*dpyinfo
;
3440 EMACS_UINT mod_meta
= meta_modifier
;
3441 EMACS_UINT mod_alt
= alt_modifier
;
3442 EMACS_UINT mod_hyper
= hyper_modifier
;
3443 EMACS_UINT mod_super
= super_modifier
;
3446 tem
= Fget (Vx_alt_keysym
, Qmodifier_value
);
3447 if (! EQ (tem
, Qnil
)) mod_alt
= XUINT (tem
);
3448 tem
= Fget (Vx_meta_keysym
, Qmodifier_value
);
3449 if (! EQ (tem
, Qnil
)) mod_meta
= XUINT (tem
);
3450 tem
= Fget (Vx_hyper_keysym
, Qmodifier_value
);
3451 if (! EQ (tem
, Qnil
)) mod_hyper
= XUINT (tem
);
3452 tem
= Fget (Vx_super_keysym
, Qmodifier_value
);
3453 if (! EQ (tem
, Qnil
)) mod_super
= XUINT (tem
);
3456 return ( ((state
& (ShiftMask
| dpyinfo
->shift_lock_mask
)) ? shift_modifier
: 0)
3457 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
3458 | ((state
& dpyinfo
->meta_mod_mask
) ? mod_meta
: 0)
3459 | ((state
& dpyinfo
->alt_mod_mask
) ? mod_alt
: 0)
3460 | ((state
& dpyinfo
->super_mod_mask
) ? mod_super
: 0)
3461 | ((state
& dpyinfo
->hyper_mod_mask
) ? mod_hyper
: 0));
3465 x_emacs_to_x_modifiers (dpyinfo
, state
)
3466 struct x_display_info
*dpyinfo
;
3469 EMACS_UINT mod_meta
= meta_modifier
;
3470 EMACS_UINT mod_alt
= alt_modifier
;
3471 EMACS_UINT mod_hyper
= hyper_modifier
;
3472 EMACS_UINT mod_super
= super_modifier
;
3476 tem
= Fget (Vx_alt_keysym
, Qmodifier_value
);
3477 if (! EQ (tem
, Qnil
)) mod_alt
= XUINT (tem
);
3478 tem
= Fget (Vx_meta_keysym
, Qmodifier_value
);
3479 if (! EQ (tem
, Qnil
)) mod_meta
= XUINT (tem
);
3480 tem
= Fget (Vx_hyper_keysym
, Qmodifier_value
);
3481 if (! EQ (tem
, Qnil
)) mod_hyper
= XUINT (tem
);
3482 tem
= Fget (Vx_super_keysym
, Qmodifier_value
);
3483 if (! EQ (tem
, Qnil
)) mod_super
= XUINT (tem
);
3486 return ( ((state
& mod_alt
) ? dpyinfo
->alt_mod_mask
: 0)
3487 | ((state
& mod_super
) ? dpyinfo
->super_mod_mask
: 0)
3488 | ((state
& mod_hyper
) ? dpyinfo
->hyper_mod_mask
: 0)
3489 | ((state
& shift_modifier
) ? ShiftMask
: 0)
3490 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
3491 | ((state
& mod_meta
) ? dpyinfo
->meta_mod_mask
: 0));
3494 /* Convert a keysym to its name. */
3497 x_get_keysym_name (keysym
)
3503 value
= XKeysymToString (keysym
);
3511 /* Mouse clicks and mouse movement. Rah. */
3513 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3515 If the event is a button press, then note that we have grabbed
3519 construct_mouse_click (result
, event
, f
)
3520 struct input_event
*result
;
3521 XButtonEvent
*event
;
3524 /* Make the event type NO_EVENT; we'll change that when we decide
3526 result
->kind
= MOUSE_CLICK_EVENT
;
3527 result
->code
= event
->button
- Button1
;
3528 result
->timestamp
= event
->time
;
3529 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
3531 | (event
->type
== ButtonRelease
3535 XSETINT (result
->x
, event
->x
);
3536 XSETINT (result
->y
, event
->y
);
3537 XSETFRAME (result
->frame_or_window
, f
);
3543 /* Function to report a mouse movement to the mainstream Emacs code.
3544 The input handler calls this.
3546 We have received a mouse movement event, which is given in *event.
3547 If the mouse is over a different glyph than it was last time, tell
3548 the mainstream emacs code by setting mouse_moved. If not, ask for
3549 another motion event, so we can check again the next time it moves. */
3551 static XMotionEvent last_mouse_motion_event
;
3552 static Lisp_Object last_mouse_motion_frame
;
3555 note_mouse_movement (frame
, event
)
3557 XMotionEvent
*event
;
3559 last_mouse_movement_time
= event
->time
;
3560 last_mouse_motion_event
= *event
;
3561 XSETFRAME (last_mouse_motion_frame
, frame
);
3563 if (event
->window
!= FRAME_X_WINDOW (frame
))
3565 frame
->mouse_moved
= 1;
3566 last_mouse_scroll_bar
= Qnil
;
3567 note_mouse_highlight (frame
, -1, -1);
3570 /* Has the mouse moved off the glyph it was on at the last sighting? */
3571 else if (event
->x
< last_mouse_glyph
.x
3572 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
3573 || event
->y
< last_mouse_glyph
.y
3574 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
3576 frame
->mouse_moved
= 1;
3577 last_mouse_scroll_bar
= Qnil
;
3578 note_mouse_highlight (frame
, event
->x
, event
->y
);
3583 /************************************************************************
3585 ************************************************************************/
3588 redo_mouse_highlight ()
3590 if (!NILP (last_mouse_motion_frame
)
3591 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
3592 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
3593 last_mouse_motion_event
.x
,
3594 last_mouse_motion_event
.y
);
3598 static int glyph_rect
P_ ((struct frame
*f
, int, int, XRectangle
*));
3601 /* Try to determine frame pixel position and size of the glyph under
3602 frame pixel coordinates X/Y on frame F . Return the position and
3603 size in *RECT. Value is non-zero if we could compute these
3607 glyph_rect (f
, x
, y
, rect
)
3614 struct glyph_row
*r
, *end_row
;
3616 window
= window_from_coordinates (f
, x
, y
, 0, &x
, &y
, 0);
3620 w
= XWINDOW (window
);
3621 r
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
3622 end_row
= r
+ w
->current_matrix
->nrows
- 1;
3624 for (; r
< end_row
&& r
->enabled_p
; ++r
)
3628 struct glyph
*g
= r
->glyphs
[TEXT_AREA
];
3629 struct glyph
*end
= g
+ r
->used
[TEXT_AREA
];
3631 while (g
< end
&& gx
< x
)
3632 gx
+= g
->pixel_width
, ++g
;
3635 rect
->width
= g
->pixel_width
;
3636 rect
->height
= r
->height
;
3637 rect
->x
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
3638 rect
->y
= WINDOW_TO_FRAME_PIXEL_Y (w
, r
->y
);
3649 /* Return the current position of the mouse.
3650 *FP should be a frame which indicates which display to ask about.
3652 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
3653 and *PART to the frame, window, and scroll bar part that the mouse
3654 is over. Set *X and *Y to the portion and whole of the mouse's
3655 position on the scroll bar.
3657 If the mouse movement started elsewhere, set *FP to the frame the
3658 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
3661 Set *TIME to the server time-stamp for the time at which the mouse
3662 was at this position.
3664 Don't store anything if we don't have a valid set of values to report.
3666 This clears the mouse_moved flag, so we can wait for the next mouse
3670 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
3673 Lisp_Object
*bar_window
;
3674 enum scroll_bar_part
*part
;
3676 unsigned long *time
;
3682 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
3683 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
3689 Window dummy_window
;
3692 Lisp_Object frame
, tail
;
3694 /* Clear the mouse-moved flag for every frame on this display. */
3695 FOR_EACH_FRAME (tail
, frame
)
3696 if (FRAME_X_P (XFRAME (frame
))
3697 && FRAME_X_DISPLAY (XFRAME (frame
)) == FRAME_X_DISPLAY (*fp
))
3698 XFRAME (frame
)->mouse_moved
= 0;
3700 last_mouse_scroll_bar
= Qnil
;
3702 /* Figure out which root window we're on. */
3703 XQueryPointer (FRAME_X_DISPLAY (*fp
),
3704 DefaultRootWindow (FRAME_X_DISPLAY (*fp
)),
3706 /* The root window which contains the pointer. */
3709 /* Trash which we can't trust if the pointer is on
3710 a different screen. */
3713 /* The position on that root window. */
3716 /* More trash we can't trust. */
3719 /* Modifier keys and pointer buttons, about which
3721 (unsigned int *) &dummy
);
3723 /* Now we have a position on the root; find the innermost window
3724 containing the pointer. */
3728 int parent_x
= 0, parent_y
= 0;
3733 /* XTranslateCoordinates can get errors if the window
3734 structure is changing at the same time this function
3735 is running. So at least we must not crash from them. */
3737 count
= x_catch_errors (FRAME_X_DISPLAY (*fp
));
3739 if (FRAME_X_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
3740 && FRAME_LIVE_P (last_mouse_frame
))
3742 /* If mouse was grabbed on a frame, give coords for that frame
3743 even if the mouse is now outside it. */
3744 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
3746 /* From-window, to-window. */
3747 root
, FRAME_X_WINDOW (last_mouse_frame
),
3749 /* From-position, to-position. */
3750 root_x
, root_y
, &win_x
, &win_y
,
3754 f1
= last_mouse_frame
;
3760 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
3762 /* From-window, to-window. */
3765 /* From-position, to-position. */
3766 root_x
, root_y
, &win_x
, &win_y
,
3771 if (child
== None
|| child
== win
)
3779 /* Now we know that:
3780 win is the innermost window containing the pointer
3781 (XTC says it has no child containing the pointer),
3782 win_x and win_y are the pointer's position in it
3783 (XTC did this the last time through), and
3784 parent_x and parent_y are the pointer's position in win's parent.
3785 (They are what win_x and win_y were when win was child.
3786 If win is the root window, it has no parent, and
3787 parent_{x,y} are invalid, but that's okay, because we'll
3788 never use them in that case.) */
3790 /* Is win one of our frames? */
3791 f1
= x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp
), win
);
3793 #ifdef USE_X_TOOLKIT
3794 /* If we end up with the menu bar window, say it's not
3797 && f1
->output_data
.x
->menubar_widget
3798 && win
== XtWindow (f1
->output_data
.x
->menubar_widget
))
3800 #endif /* USE_X_TOOLKIT */
3803 if (x_had_errors_p (FRAME_X_DISPLAY (*fp
)))
3806 x_uncatch_errors (FRAME_X_DISPLAY (*fp
), count
);
3808 /* If not, is it one of our scroll bars? */
3811 struct scroll_bar
*bar
;
3813 bar
= x_window_to_scroll_bar (FRAME_X_DISPLAY (*fp
), win
);
3817 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3823 if (f1
== 0 && insist
> 0)
3824 f1
= SELECTED_FRAME ();
3828 /* Ok, we found a frame. Store all the values.
3829 last_mouse_glyph is a rectangle used to reduce the
3830 generation of mouse events. To not miss any motion
3831 events, we must divide the frame into rectangles of the
3832 size of the smallest character that could be displayed
3833 on it, i.e. into the same rectangles that matrices on
3834 the frame are divided into. */
3836 int width
, height
, gx
, gy
;
3839 if (glyph_rect (f1
, win_x
, win_y
, &rect
))
3840 last_mouse_glyph
= rect
;
3843 width
= FRAME_SMALLEST_CHAR_WIDTH (f1
);
3844 height
= FRAME_SMALLEST_FONT_HEIGHT (f1
);
3848 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
3849 round down even for negative values. */
3854 gx
= (gx
+ width
- 1) / width
* width
;
3855 gy
= (gy
+ height
- 1) / height
* height
;
3857 last_mouse_glyph
.width
= width
;
3858 last_mouse_glyph
.height
= height
;
3859 last_mouse_glyph
.x
= gx
;
3860 last_mouse_glyph
.y
= gy
;
3866 XSETINT (*x
, win_x
);
3867 XSETINT (*y
, win_y
);
3868 *time
= last_mouse_movement_time
;
3878 /***********************************************************************
3880 ***********************************************************************/
3882 /* Scroll bar support. */
3884 /* Given an X window ID and a DISPLAY, find the struct scroll_bar which
3886 This can be called in GC, so we have to make sure to strip off mark
3889 static struct scroll_bar
*
3890 x_window_to_scroll_bar (display
, window_id
)
3897 window_id
= (Window
) xg_get_scroll_id_for_window (display
, window_id
);
3898 #endif /* USE_GTK */
3900 for (tail
= Vframe_list
;
3901 XGCTYPE (tail
) == Lisp_Cons
;
3904 Lisp_Object frame
, bar
, condemned
;
3906 frame
= XCAR (tail
);
3907 /* All elements of Vframe_list should be frames. */
3908 if (! GC_FRAMEP (frame
))
3911 if (! FRAME_X_P (XFRAME (frame
)))
3914 /* Scan this frame's scroll bar list for a scroll bar with the
3916 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
3917 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
3918 /* This trick allows us to search both the ordinary and
3919 condemned scroll bar lists with one loop. */
3920 ! GC_NILP (bar
) || (bar
= condemned
,
3923 bar
= XSCROLL_BAR (bar
)->next
)
3924 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
&&
3925 FRAME_X_DISPLAY (XFRAME (frame
)) == display
)
3926 return XSCROLL_BAR (bar
);
3933 #if defined USE_LUCID
3935 /* Return the Lucid menu bar WINDOW is part of. Return null
3936 if WINDOW is not part of a menu bar. */
3939 x_window_to_menu_bar (window
)
3944 for (tail
= Vframe_list
;
3945 XGCTYPE (tail
) == Lisp_Cons
;
3948 if (FRAME_X_P (XFRAME (XCAR (tail
))))
3950 Lisp_Object frame
= XCAR (tail
);
3951 Widget menu_bar
= XFRAME (frame
)->output_data
.x
->menubar_widget
;
3953 if (menu_bar
&& xlwmenu_window_p (menu_bar
, window
))
3961 #endif /* USE_LUCID */
3964 /************************************************************************
3966 ************************************************************************/
3968 #ifdef USE_TOOLKIT_SCROLL_BARS
3970 static void x_scroll_bar_to_input_event
P_ ((XEvent
*, struct input_event
*));
3971 static void x_send_scroll_bar_event
P_ ((Lisp_Object
, int, int, int));
3972 static void x_create_toolkit_scroll_bar
P_ ((struct frame
*,
3973 struct scroll_bar
*));
3974 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
3978 /* Lisp window being scrolled. Set when starting to interact with
3979 a toolkit scroll bar, reset to nil when ending the interaction. */
3981 static Lisp_Object window_being_scrolled
;
3983 /* Last scroll bar part sent in xm_scroll_callback. */
3985 static int last_scroll_bar_part
;
3987 /* Whether this is an Xaw with arrow-scrollbars. This should imply
3988 that movements of 1/20 of the screen size are mapped to up/down. */
3991 /* Id of action hook installed for scroll bars. */
3993 static XtActionHookId action_hook_id
;
3995 static Boolean xaw3d_arrow_scroll
;
3997 /* Whether the drag scrolling maintains the mouse at the top of the
3998 thumb. If not, resizing the thumb needs to be done more carefully
3999 to avoid jerkyness. */
4001 static Boolean xaw3d_pick_top
;
4003 extern void set_vertical_scroll_bar
P_ ((struct window
*));
4005 /* Action hook installed via XtAppAddActionHook when toolkit scroll
4006 bars are used.. The hook is responsible for detecting when
4007 the user ends an interaction with the scroll bar, and generates
4008 a `end-scroll' SCROLL_BAR_CLICK_EVENT' event if so. */
4011 xt_action_hook (widget
, client_data
, action_name
, event
, params
,
4014 XtPointer client_data
;
4018 Cardinal
*num_params
;
4024 scroll_bar_p
= XmIsScrollBar (widget
);
4025 end_action
= "Release";
4026 #else /* !USE_MOTIF i.e. use Xaw */
4027 scroll_bar_p
= XtIsSubclass (widget
, scrollbarWidgetClass
);
4028 end_action
= "EndScroll";
4029 #endif /* USE_MOTIF */
4032 && strcmp (action_name
, end_action
) == 0
4033 && WINDOWP (window_being_scrolled
))
4037 x_send_scroll_bar_event (window_being_scrolled
,
4038 scroll_bar_end_scroll
, 0, 0);
4039 w
= XWINDOW (window_being_scrolled
);
4041 if (!NILP (XSCROLL_BAR (w
->vertical_scroll_bar
)->dragging
))
4043 XSCROLL_BAR (w
->vertical_scroll_bar
)->dragging
= Qnil
;
4044 /* The thumb size is incorrect while dragging: fix it. */
4045 set_vertical_scroll_bar (w
);
4047 window_being_scrolled
= Qnil
;
4048 last_scroll_bar_part
= -1;
4050 /* Xt timeouts no longer needed. */
4051 toolkit_scroll_bar_interaction
= 0;
4054 #endif /* not USE_GTK */
4056 /* A vector of windows used for communication between
4057 x_send_scroll_bar_event and x_scroll_bar_to_input_event. */
4059 static struct window
**scroll_bar_windows
;
4060 static int scroll_bar_windows_size
;
4063 /* Send a client message with message type Xatom_Scrollbar for a
4064 scroll action to the frame of WINDOW. PART is a value identifying
4065 the part of the scroll bar that was clicked on. PORTION is the
4066 amount to scroll of a whole of WHOLE. */
4069 x_send_scroll_bar_event (window
, part
, portion
, whole
)
4071 int part
, portion
, whole
;
4074 XClientMessageEvent
*ev
= (XClientMessageEvent
*) &event
;
4075 struct window
*w
= XWINDOW (window
);
4076 struct frame
*f
= XFRAME (w
->frame
);
4081 /* Construct a ClientMessage event to send to the frame. */
4082 ev
->type
= ClientMessage
;
4083 ev
->message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_Scrollbar
;
4084 ev
->display
= FRAME_X_DISPLAY (f
);
4085 ev
->window
= FRAME_X_WINDOW (f
);
4088 /* We can only transfer 32 bits in the XClientMessageEvent, which is
4089 not enough to store a pointer or Lisp_Object on a 64 bit system.
4090 So, store the window in scroll_bar_windows and pass the index
4091 into that array in the event. */
4092 for (i
= 0; i
< scroll_bar_windows_size
; ++i
)
4093 if (scroll_bar_windows
[i
] == NULL
)
4096 if (i
== scroll_bar_windows_size
)
4098 int new_size
= max (10, 2 * scroll_bar_windows_size
);
4099 size_t nbytes
= new_size
* sizeof *scroll_bar_windows
;
4100 size_t old_nbytes
= scroll_bar_windows_size
* sizeof *scroll_bar_windows
;
4102 scroll_bar_windows
= (struct window
**) xrealloc (scroll_bar_windows
,
4104 bzero (&scroll_bar_windows
[i
], nbytes
- old_nbytes
);
4105 scroll_bar_windows_size
= new_size
;
4108 scroll_bar_windows
[i
] = w
;
4109 ev
->data
.l
[0] = (long) i
;
4110 ev
->data
.l
[1] = (long) part
;
4111 ev
->data
.l
[2] = (long) 0;
4112 ev
->data
.l
[3] = (long) portion
;
4113 ev
->data
.l
[4] = (long) whole
;
4115 /* Make Xt timeouts work while the scroll bar is active. */
4116 toolkit_scroll_bar_interaction
= 1;
4118 /* Setting the event mask to zero means that the message will
4119 be sent to the client that created the window, and if that
4120 window no longer exists, no event will be sent. */
4121 XSendEvent (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), False
, 0, &event
);
4126 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
4130 x_scroll_bar_to_input_event (event
, ievent
)
4132 struct input_event
*ievent
;
4134 XClientMessageEvent
*ev
= (XClientMessageEvent
*) event
;
4139 w
= scroll_bar_windows
[ev
->data
.l
[0]];
4140 scroll_bar_windows
[ev
->data
.l
[0]] = NULL
;
4142 XSETWINDOW (window
, w
);
4143 f
= XFRAME (w
->frame
);
4145 ievent
->kind
= SCROLL_BAR_CLICK_EVENT
;
4146 ievent
->frame_or_window
= window
;
4149 ievent
->timestamp
= CurrentTime
;
4151 ievent
->timestamp
= XtLastTimestampProcessed (FRAME_X_DISPLAY (f
));
4153 ievent
->part
= ev
->data
.l
[1];
4154 ievent
->code
= ev
->data
.l
[2];
4155 ievent
->x
= make_number ((int) ev
->data
.l
[3]);
4156 ievent
->y
= make_number ((int) ev
->data
.l
[4]);
4157 ievent
->modifiers
= 0;
4163 /* Minimum and maximum values used for Motif scroll bars. */
4165 #define XM_SB_MAX 10000000
4168 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
4169 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
4170 CALL_DATA is a pointer to a XmScrollBarCallbackStruct. */
4173 xm_scroll_callback (widget
, client_data
, call_data
)
4175 XtPointer client_data
, call_data
;
4177 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
4178 XmScrollBarCallbackStruct
*cs
= (XmScrollBarCallbackStruct
*) call_data
;
4179 int part
= -1, whole
= 0, portion
= 0;
4183 case XmCR_DECREMENT
:
4184 bar
->dragging
= Qnil
;
4185 part
= scroll_bar_up_arrow
;
4188 case XmCR_INCREMENT
:
4189 bar
->dragging
= Qnil
;
4190 part
= scroll_bar_down_arrow
;
4193 case XmCR_PAGE_DECREMENT
:
4194 bar
->dragging
= Qnil
;
4195 part
= scroll_bar_above_handle
;
4198 case XmCR_PAGE_INCREMENT
:
4199 bar
->dragging
= Qnil
;
4200 part
= scroll_bar_below_handle
;
4204 bar
->dragging
= Qnil
;
4205 part
= scroll_bar_to_top
;
4208 case XmCR_TO_BOTTOM
:
4209 bar
->dragging
= Qnil
;
4210 part
= scroll_bar_to_bottom
;
4217 /* Get the slider size. */
4219 XtVaGetValues (widget
, XmNsliderSize
, &slider_size
, NULL
);
4222 whole
= XM_SB_MAX
- slider_size
;
4223 portion
= min (cs
->value
, whole
);
4224 part
= scroll_bar_handle
;
4225 bar
->dragging
= make_number (cs
->value
);
4229 case XmCR_VALUE_CHANGED
:
4235 window_being_scrolled
= bar
->window
;
4236 last_scroll_bar_part
= part
;
4237 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
4242 #else /* !USE_MOTIF, i.e. Xaw or GTK */
4244 /* Scroll bar callback for GTK scroll bars. WIDGET is the scroll
4245 bar widget. DATA is a pointer to the scroll_bar structure. */
4248 xg_scroll_callback (widget
, data
)
4252 struct scroll_bar
*bar
= (struct scroll_bar
*) data
;
4258 int part
= -1, whole
= 0, portion
= 0;
4259 GtkAdjustment
*adj
= GTK_ADJUSTMENT (gtk_range_get_adjustment (widget
));
4261 if (xg_ignore_gtk_scrollbar
) return;
4263 position
= gtk_adjustment_get_value (adj
);
4265 p
= g_object_get_data (G_OBJECT (widget
), XG_LAST_SB_DATA
);
4268 p
= (gdouble
*) xmalloc (sizeof (gdouble
));
4270 g_object_set_data (G_OBJECT (widget
), XG_LAST_SB_DATA
, p
);
4276 diff
= (int) (position
- previous
);
4278 if (diff
== (int) adj
->step_increment
)
4280 part
= scroll_bar_down_arrow
;
4281 bar
->dragging
= Qnil
;
4283 else if (-diff
== (int) adj
->step_increment
)
4285 part
= scroll_bar_up_arrow
;
4286 bar
->dragging
= Qnil
;
4288 else if (diff
== (int) adj
->page_increment
)
4290 part
= scroll_bar_below_handle
;
4291 bar
->dragging
= Qnil
;
4293 else if (-diff
== (int) adj
->page_increment
)
4295 part
= scroll_bar_above_handle
;
4296 bar
->dragging
= Qnil
;
4300 part
= scroll_bar_handle
;
4301 whole
= adj
->upper
- adj
->page_size
;
4302 portion
= min ((int)position
, whole
);
4303 bar
->dragging
= make_number ((int)portion
);
4308 window_being_scrolled
= bar
->window
;
4309 last_scroll_bar_part
= part
;
4310 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
4314 #else /* not USE_GTK */
4316 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
4317 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
4318 scroll bar struct. CALL_DATA is a pointer to a float saying where
4322 xaw_jump_callback (widget
, client_data
, call_data
)
4324 XtPointer client_data
, call_data
;
4326 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
4327 float top
= *(float *) call_data
;
4329 int whole
, portion
, height
;
4332 /* Get the size of the thumb, a value between 0 and 1. */
4334 XtVaGetValues (widget
, XtNshown
, &shown
, XtNheight
, &height
, NULL
);
4338 portion
= shown
< 1 ? top
* whole
: 0;
4340 if (shown
< 1 && (abs (top
+ shown
- 1) < 1.0/height
))
4341 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
4342 the bottom, so we force the scrolling whenever we see that we're
4343 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
4344 we try to ensure that we always stay two pixels away from the
4346 part
= scroll_bar_down_arrow
;
4348 part
= scroll_bar_handle
;
4350 window_being_scrolled
= bar
->window
;
4351 bar
->dragging
= make_number (portion
);
4352 last_scroll_bar_part
= part
;
4353 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
4357 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
4358 i.e. line or page up or down. WIDGET is the Xaw scroll bar
4359 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
4360 the scroll bar. CALL_DATA is an integer specifying the action that
4361 has taken place. Its magnitude is in the range 0..height of the
4362 scroll bar. Negative values mean scroll towards buffer start.
4363 Values < height of scroll bar mean line-wise movement. */
4366 xaw_scroll_callback (widget
, client_data
, call_data
)
4368 XtPointer client_data
, call_data
;
4370 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
4371 /* The position really is stored cast to a pointer. */
4372 int position
= (long) call_data
;
4376 /* Get the height of the scroll bar. */
4378 XtVaGetValues (widget
, XtNheight
, &height
, NULL
);
4381 if (abs (position
) >= height
)
4382 part
= (position
< 0) ? scroll_bar_above_handle
: scroll_bar_below_handle
;
4384 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
4385 it maps line-movement to call_data = max(5, height/20). */
4386 else if (xaw3d_arrow_scroll
&& abs (position
) <= max (5, height
/ 20))
4387 part
= (position
< 0) ? scroll_bar_up_arrow
: scroll_bar_down_arrow
;
4389 part
= scroll_bar_move_ratio
;
4391 window_being_scrolled
= bar
->window
;
4392 bar
->dragging
= Qnil
;
4393 last_scroll_bar_part
= part
;
4394 x_send_scroll_bar_event (bar
->window
, part
, position
, height
);
4397 #endif /* not USE_GTK */
4398 #endif /* not USE_MOTIF */
4400 #define SCROLL_BAR_NAME "verticalScrollBar"
4402 /* Create the widget for scroll bar BAR on frame F. Record the widget
4403 and X window of the scroll bar in BAR. */
4407 x_create_toolkit_scroll_bar (f
, bar
)
4409 struct scroll_bar
*bar
;
4411 char *scroll_bar_name
= SCROLL_BAR_NAME
;
4414 xg_create_scroll_bar (f
, bar
, G_CALLBACK (xg_scroll_callback
),
4419 #else /* not USE_GTK */
4422 x_create_toolkit_scroll_bar (f
, bar
)
4424 struct scroll_bar
*bar
;
4430 char *scroll_bar_name
= SCROLL_BAR_NAME
;
4431 unsigned long pixel
;
4436 /* Set resources. Create the widget. */
4437 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
4438 XtSetArg (av
[ac
], XmNminimum
, 0); ++ac
;
4439 XtSetArg (av
[ac
], XmNmaximum
, XM_SB_MAX
); ++ac
;
4440 XtSetArg (av
[ac
], XmNorientation
, XmVERTICAL
); ++ac
;
4441 XtSetArg (av
[ac
], XmNprocessingDirection
, XmMAX_ON_BOTTOM
), ++ac
;
4442 XtSetArg (av
[ac
], XmNincrement
, 1); ++ac
;
4443 XtSetArg (av
[ac
], XmNpageIncrement
, 1); ++ac
;
4445 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
4448 XtSetArg (av
[ac
], XmNforeground
, pixel
);
4452 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4455 XtSetArg (av
[ac
], XmNbackground
, pixel
);
4459 widget
= XmCreateScrollBar (f
->output_data
.x
->edit_widget
,
4460 scroll_bar_name
, av
, ac
);
4462 /* Add one callback for everything that can happen. */
4463 XtAddCallback (widget
, XmNdecrementCallback
, xm_scroll_callback
,
4465 XtAddCallback (widget
, XmNdragCallback
, xm_scroll_callback
,
4467 XtAddCallback (widget
, XmNincrementCallback
, xm_scroll_callback
,
4469 XtAddCallback (widget
, XmNpageDecrementCallback
, xm_scroll_callback
,
4471 XtAddCallback (widget
, XmNpageIncrementCallback
, xm_scroll_callback
,
4473 XtAddCallback (widget
, XmNtoBottomCallback
, xm_scroll_callback
,
4475 XtAddCallback (widget
, XmNtoTopCallback
, xm_scroll_callback
,
4478 /* Realize the widget. Only after that is the X window created. */
4479 XtRealizeWidget (widget
);
4481 /* Set the cursor to an arrow. I didn't find a resource to do that.
4482 And I'm wondering why it hasn't an arrow cursor by default. */
4483 XDefineCursor (XtDisplay (widget
), XtWindow (widget
),
4484 f
->output_data
.x
->nontext_cursor
);
4486 #else /* !USE_MOTIF i.e. use Xaw */
4488 /* Set resources. Create the widget. The background of the
4489 Xaw3d scroll bar widget is a little bit light for my taste.
4490 We don't alter it here to let users change it according
4491 to their taste with `emacs*verticalScrollBar.background: xxx'. */
4492 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
4493 XtSetArg (av
[ac
], XtNorientation
, XtorientVertical
); ++ac
;
4494 /* For smoother scrolling with Xaw3d -sm */
4495 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
4497 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
4500 XtSetArg (av
[ac
], XtNforeground
, pixel
);
4504 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4507 XtSetArg (av
[ac
], XtNbackground
, pixel
);
4511 /* Top/bottom shadow colors. */
4513 /* Allocate them, if necessary. */
4514 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
== -1)
4516 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4517 if (!x_alloc_lighter_color (f
, FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
4518 &pixel
, 1.2, 0x8000))
4520 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= pixel
;
4522 if (f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
== -1)
4524 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4525 if (!x_alloc_lighter_color (f
, FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
4526 &pixel
, 0.6, 0x4000))
4528 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= pixel
;
4531 /* Tell the toolkit about them. */
4532 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
== -1
4533 || f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
== -1)
4534 /* We tried to allocate a color for the top/bottom shadow, and
4535 failed, so tell Xaw3d to use dithering instead. */
4537 XtSetArg (av
[ac
], XtNbeNiceToColormap
, True
);
4541 /* Tell what colors Xaw3d should use for the top/bottom shadow, to
4542 be more consistent with other emacs 3d colors, and since Xaw3d is
4543 not good at dealing with allocation failure. */
4545 /* This tells Xaw3d to use real colors instead of dithering for
4547 XtSetArg (av
[ac
], XtNbeNiceToColormap
, False
);
4550 /* Specify the colors. */
4551 pixel
= f
->output_data
.x
->scroll_bar_top_shadow_pixel
;
4554 XtSetArg (av
[ac
], "topShadowPixel", pixel
);
4557 pixel
= f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
;
4560 XtSetArg (av
[ac
], "bottomShadowPixel", pixel
);
4565 widget
= XtCreateWidget (scroll_bar_name
, scrollbarWidgetClass
,
4566 f
->output_data
.x
->edit_widget
, av
, ac
);
4570 char *val
= initial
;
4571 XtVaGetValues (widget
, XtNscrollVCursor
, (XtPointer
) &val
,
4572 XtNpickTop
, (XtPointer
) &xaw3d_pick_top
, NULL
);
4574 { /* ARROW_SCROLL */
4575 xaw3d_arrow_scroll
= True
;
4576 /* Isn't that just a personal preference ? -sm */
4577 XtVaSetValues (widget
, XtNcursorName
, "top_left_arrow", NULL
);
4581 /* Define callbacks. */
4582 XtAddCallback (widget
, XtNjumpProc
, xaw_jump_callback
, (XtPointer
) bar
);
4583 XtAddCallback (widget
, XtNscrollProc
, xaw_scroll_callback
,
4586 /* Realize the widget. Only after that is the X window created. */
4587 XtRealizeWidget (widget
);
4589 #endif /* !USE_MOTIF */
4591 /* Install an action hook that lets us detect when the user
4592 finishes interacting with a scroll bar. */
4593 if (action_hook_id
== 0)
4594 action_hook_id
= XtAppAddActionHook (Xt_app_con
, xt_action_hook
, 0);
4596 /* Remember X window and widget in the scroll bar vector. */
4597 SET_SCROLL_BAR_X_WIDGET (bar
, widget
);
4598 xwindow
= XtWindow (widget
);
4599 SET_SCROLL_BAR_X_WINDOW (bar
, xwindow
);
4603 #endif /* not USE_GTK */
4606 /* Set the thumb size and position of scroll bar BAR. We are currently
4607 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4611 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4612 struct scroll_bar
*bar
;
4613 int portion
, position
, whole
;
4615 xg_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
4618 #else /* not USE_GTK */
4620 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4621 struct scroll_bar
*bar
;
4622 int portion
, position
, whole
;
4624 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4625 Widget widget
= SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
);
4632 /* We use an estimate of 30 chars per line rather than the real
4633 `portion' value. This has the disadvantage that the thumb size
4634 is not very representative, but it makes our life a lot easier.
4635 Otherwise, we have to constantly adjust the thumb size, which
4636 we can't always do quickly enough: while dragging, the size of
4637 the thumb might prevent the user from dragging the thumb all the
4638 way to the end. but Motif and some versions of Xaw3d don't allow
4639 updating the thumb size while dragging. Also, even if we can update
4640 its size, the update will often happen too late.
4641 If you don't believe it, check out revision 1.650 of xterm.c to see
4642 what hoops we were going through and the still poor behavior we got. */
4643 portion
= WINDOW_TOTAL_LINES (XWINDOW (bar
->window
)) * 30;
4644 /* When the thumb is at the bottom, position == whole.
4645 So we need to increase `whole' to make space for the thumb. */
4652 top
= (float) position
/ whole
;
4653 shown
= (float) portion
/ whole
;
4656 if (NILP (bar
->dragging
))
4660 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
4661 is the scroll bar's maximum and MIN is the scroll bar's minimum
4663 size
= shown
* XM_SB_MAX
;
4664 size
= min (size
, XM_SB_MAX
);
4665 size
= max (size
, 1);
4667 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
4668 value
= top
* XM_SB_MAX
;
4669 value
= min (value
, XM_SB_MAX
- size
);
4671 XmScrollBarSetValues (widget
, value
, size
, 0, 0, False
);
4673 #else /* !USE_MOTIF i.e. use Xaw */
4679 top
= (float) position
/ whole
;
4680 shown
= (float) portion
/ whole
;
4684 float old_top
, old_shown
;
4686 XtVaGetValues (widget
,
4687 XtNtopOfThumb
, &old_top
,
4688 XtNshown
, &old_shown
,
4692 /* Massage the top+shown values. */
4693 if (NILP (bar
->dragging
) || last_scroll_bar_part
== scroll_bar_down_arrow
)
4694 top
= max (0, min (1, top
));
4697 /* Keep two pixels available for moving the thumb down. */
4698 shown
= max (0, min (1 - top
- (2.0 / height
), shown
));
4700 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
4701 check that your system's configuration file contains a define
4702 for `NARROWPROTO'. See s/freebsd.h for an example. */
4703 if (top
!= old_top
|| shown
!= old_shown
)
4705 if (NILP (bar
->dragging
))
4706 XawScrollbarSetThumb (widget
, top
, shown
);
4710 ScrollbarWidget sb
= (ScrollbarWidget
) widget
;
4711 int scroll_mode
= 0;
4713 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
4714 if (xaw3d_arrow_scroll
)
4716 /* Xaw3d stupidly ignores resize requests while dragging
4717 so we have to make it believe it's not in dragging mode. */
4718 scroll_mode
= sb
->scrollbar
.scroll_mode
;
4719 if (scroll_mode
== 2)
4720 sb
->scrollbar
.scroll_mode
= 0;
4723 /* Try to make the scrolling a tad smoother. */
4724 if (!xaw3d_pick_top
)
4725 shown
= min (shown
, old_shown
);
4727 XawScrollbarSetThumb (widget
, top
, shown
);
4730 if (xaw3d_arrow_scroll
&& scroll_mode
== 2)
4731 sb
->scrollbar
.scroll_mode
= scroll_mode
;
4736 #endif /* !USE_MOTIF */
4740 #endif /* not USE_GTK */
4742 #endif /* USE_TOOLKIT_SCROLL_BARS */
4746 /************************************************************************
4747 Scroll bars, general
4748 ************************************************************************/
4750 /* Create a scroll bar and return the scroll bar vector for it. W is
4751 the Emacs window on which to create the scroll bar. TOP, LEFT,
4752 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4755 static struct scroll_bar
*
4756 x_scroll_bar_create (w
, top
, left
, width
, height
)
4758 int top
, left
, width
, height
;
4760 struct frame
*f
= XFRAME (w
->frame
);
4761 struct scroll_bar
*bar
4762 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4766 #ifdef USE_TOOLKIT_SCROLL_BARS
4767 x_create_toolkit_scroll_bar (f
, bar
);
4768 #else /* not USE_TOOLKIT_SCROLL_BARS */
4770 XSetWindowAttributes a
;
4774 a
.background_pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4775 if (a
.background_pixel
== -1)
4776 a
.background_pixel
= f
->output_data
.x
->background_pixel
;
4778 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
4779 | ButtonMotionMask
| PointerMotionHintMask
4781 a
.cursor
= FRAME_X_DISPLAY_INFO (f
)->vertical_scroll_bar_cursor
;
4783 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
4785 /* Clear the area of W that will serve as a scroll bar. This is
4786 for the case that a window has been split horizontally. In
4787 this case, no clear_frame is generated to reduce flickering. */
4788 if (width
> 0 && height
> 0)
4789 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4791 window_box_height (w
), False
);
4793 window
= XCreateWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4794 /* Position and size of scroll bar. */
4795 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
4797 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4799 /* Border width, depth, class, and visual. */
4806 SET_SCROLL_BAR_X_WINDOW (bar
, window
);
4808 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4810 XSETWINDOW (bar
->window
, w
);
4811 XSETINT (bar
->top
, top
);
4812 XSETINT (bar
->left
, left
);
4813 XSETINT (bar
->width
, width
);
4814 XSETINT (bar
->height
, height
);
4815 XSETINT (bar
->start
, 0);
4816 XSETINT (bar
->end
, 0);
4817 bar
->dragging
= Qnil
;
4819 /* Add bar to its frame's list of scroll bars. */
4820 bar
->next
= FRAME_SCROLL_BARS (f
);
4822 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4823 if (!NILP (bar
->next
))
4824 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4826 /* Map the window/widget. */
4827 #ifdef USE_TOOLKIT_SCROLL_BARS
4830 xg_update_scrollbar_pos (f
,
4831 SCROLL_BAR_X_WINDOW (bar
),
4833 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
4834 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4838 xg_show_scroll_bar (SCROLL_BAR_X_WINDOW (bar
));
4839 #else /* not USE_GTK */
4840 Widget scroll_bar
= SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
);
4841 XtConfigureWidget (scroll_bar
,
4842 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
4844 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4845 max (height
, 1), 0);
4846 XtMapWidget (scroll_bar
);
4847 #endif /* not USE_GTK */
4849 #else /* not USE_TOOLKIT_SCROLL_BARS */
4850 XMapRaised (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
4851 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4858 /* Draw BAR's handle in the proper position.
4860 If the handle is already drawn from START to END, don't bother
4861 redrawing it, unless REBUILD is non-zero; in that case, always
4862 redraw it. (REBUILD is handy for drawing the handle after expose
4865 Normally, we want to constrain the start and end of the handle to
4866 fit inside its rectangle, but if the user is dragging the scroll
4867 bar handle, we want to let them drag it down all the way, so that
4868 the bar's top is as far down as it goes; otherwise, there's no way
4869 to move to the very end of the buffer. */
4871 #ifndef USE_TOOLKIT_SCROLL_BARS
4874 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
4875 struct scroll_bar
*bar
;
4879 int dragging
= ! NILP (bar
->dragging
);
4880 Window w
= SCROLL_BAR_X_WINDOW (bar
);
4881 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4882 GC gc
= f
->output_data
.x
->normal_gc
;
4884 /* If the display is already accurate, do nothing. */
4886 && start
== XINT (bar
->start
)
4887 && end
== XINT (bar
->end
))
4893 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f
, XINT (bar
->width
));
4894 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
4895 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4897 /* Make sure the values are reasonable, and try to preserve
4898 the distance between start and end. */
4900 int length
= end
- start
;
4904 else if (start
> top_range
)
4906 end
= start
+ length
;
4910 else if (end
> top_range
&& ! dragging
)
4914 /* Store the adjusted setting in the scroll bar. */
4915 XSETINT (bar
->start
, start
);
4916 XSETINT (bar
->end
, end
);
4918 /* Clip the end position, just for display. */
4919 if (end
> top_range
)
4922 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
4923 below top positions, to make sure the handle is always at least
4924 that many pixels tall. */
4925 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4927 /* Draw the empty space above the handle. Note that we can't clear
4928 zero-height areas; that means "clear to end of window." */
4930 x_clear_area (FRAME_X_DISPLAY (f
), w
,
4931 /* x, y, width, height, and exposures. */
4932 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
4933 VERTICAL_SCROLL_BAR_TOP_BORDER
,
4934 inside_width
, start
,
4937 /* Change to proper foreground color if one is specified. */
4938 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
4939 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
4940 f
->output_data
.x
->scroll_bar_foreground_pixel
);
4942 /* Draw the handle itself. */
4943 XFillRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
4944 /* x, y, width, height */
4945 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
4946 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
4947 inside_width
, end
- start
);
4949 /* Restore the foreground color of the GC if we changed it above. */
4950 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
4951 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
4952 f
->output_data
.x
->foreground_pixel
);
4954 /* Draw the empty space below the handle. Note that we can't
4955 clear zero-height areas; that means "clear to end of window." */
4956 if (end
< inside_height
)
4957 x_clear_area (FRAME_X_DISPLAY (f
), w
,
4958 /* x, y, width, height, and exposures. */
4959 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
4960 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
4961 inside_width
, inside_height
- end
,
4969 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4971 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4975 x_scroll_bar_remove (bar
)
4976 struct scroll_bar
*bar
;
4978 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4981 #ifdef USE_TOOLKIT_SCROLL_BARS
4983 xg_remove_scroll_bar (f
, SCROLL_BAR_X_WINDOW (bar
));
4984 #else /* not USE_GTK */
4985 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
));
4986 #endif /* not USE_GTK */
4988 XDestroyWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
4991 /* Disassociate this scroll bar from its window. */
4992 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
4998 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4999 that we are displaying PORTION characters out of a total of WHOLE
5000 characters, starting at POSITION. If WINDOW has no scroll bar,
5004 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
5006 int portion
, whole
, position
;
5008 struct frame
*f
= XFRAME (w
->frame
);
5009 struct scroll_bar
*bar
;
5010 int top
, height
, left
, sb_left
, width
, sb_width
;
5011 int window_y
, window_height
;
5013 /* Get window dimensions. */
5014 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
5016 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
5017 height
= window_height
;
5019 /* Compute the left edge of the scroll bar area. */
5020 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
5022 /* Compute the width of the scroll bar which might be less than
5023 the width of the area reserved for the scroll bar. */
5024 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
5025 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
5029 /* Compute the left edge of the scroll bar. */
5030 #ifdef USE_TOOLKIT_SCROLL_BARS
5031 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
5032 sb_left
= left
+ width
- sb_width
- (width
- sb_width
) / 2;
5034 sb_left
= left
+ (width
- sb_width
) / 2;
5036 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
5037 sb_left
= left
+ width
- sb_width
;
5042 /* Does the scroll bar exist yet? */
5043 if (NILP (w
->vertical_scroll_bar
))
5045 if (width
> 0 && height
> 0)
5048 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5049 left
, top
, width
, height
, False
);
5053 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
);
5057 /* It may just need to be moved and resized. */
5058 unsigned int mask
= 0;
5060 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
5064 if (sb_left
!= XINT (bar
->left
))
5066 if (top
!= XINT (bar
->top
))
5068 if (sb_width
!= XINT (bar
->width
))
5070 if (height
!= XINT (bar
->height
))
5073 #ifdef USE_TOOLKIT_SCROLL_BARS
5077 xg_update_scrollbar_pos (f
,
5078 SCROLL_BAR_X_WINDOW (bar
),
5080 sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5081 sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5085 #else /* not USE_GTK */
5087 /* Since toolkit scroll bars are smaller than the space reserved
5088 for them on the frame, we have to clear "under" them. */
5089 if (width
> 0 && height
> 0)
5090 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5091 left
, top
, width
, height
, False
);
5092 /* Move/size the scroll bar widget. */
5094 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
),
5095 sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5097 sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5098 max (height
, 1), 0);
5100 #endif /* not USE_GTK */
5101 #else /* not USE_TOOLKIT_SCROLL_BARS */
5103 /* Clear areas not covered by the scroll bar because of
5104 VERTICAL_SCROLL_BAR_WIDTH_TRIM. */
5105 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM
)
5107 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5108 left
, top
, VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5110 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5111 left
+ width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5112 top
, VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5116 /* Clear areas not covered by the scroll bar because it's not as
5117 wide as the area reserved for it. This makes sure a
5118 previous mode line display is cleared after C-x 2 C-x 1, for
5121 int area_width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
5122 int rest
= area_width
- sb_width
;
5123 if (rest
> 0 && height
> 0)
5125 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
5126 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5127 left
+ area_width
- rest
, top
,
5128 rest
, height
, False
);
5130 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5131 left
, top
, rest
, height
, False
);
5135 /* Move/size the scroll bar window. */
5140 wc
.x
= sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
5142 wc
.width
= sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2;
5144 XConfigureWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
),
5148 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5150 /* Remember new settings. */
5151 XSETINT (bar
->left
, sb_left
);
5152 XSETINT (bar
->top
, top
);
5153 XSETINT (bar
->width
, sb_width
);
5154 XSETINT (bar
->height
, height
);
5159 #ifdef USE_TOOLKIT_SCROLL_BARS
5160 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
5161 #else /* not USE_TOOLKIT_SCROLL_BARS */
5162 /* Set the scroll bar's current state, unless we're currently being
5164 if (NILP (bar
->dragging
))
5166 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
5169 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
5172 int start
= ((double) position
* top_range
) / whole
;
5173 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
5174 x_scroll_bar_set_handle (bar
, start
, end
, 0);
5177 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5179 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
5183 /* The following three hooks are used when we're doing a thorough
5184 redisplay of the frame. We don't explicitly know which scroll bars
5185 are going to be deleted, because keeping track of when windows go
5186 away is a real pain - "Can you say set-window-configuration, boys
5187 and girls?" Instead, we just assert at the beginning of redisplay
5188 that *all* scroll bars are to be removed, and then save a scroll bar
5189 from the fiery pit when we actually redisplay its window. */
5191 /* Arrange for all scroll bars on FRAME to be removed at the next call
5192 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5193 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5196 XTcondemn_scroll_bars (frame
)
5199 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5200 while (! NILP (FRAME_SCROLL_BARS (frame
)))
5203 bar
= FRAME_SCROLL_BARS (frame
);
5204 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
5205 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
5206 XSCROLL_BAR (bar
)->prev
= Qnil
;
5207 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
5208 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
5209 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
5214 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5215 Note that WINDOW isn't necessarily condemned at all. */
5218 XTredeem_scroll_bar (window
)
5219 struct window
*window
;
5221 struct scroll_bar
*bar
;
5224 /* We can't redeem this window's scroll bar if it doesn't have one. */
5225 if (NILP (window
->vertical_scroll_bar
))
5228 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
5230 /* Unlink it from the condemned list. */
5231 f
= XFRAME (WINDOW_FRAME (window
));
5232 if (NILP (bar
->prev
))
5234 /* If the prev pointer is nil, it must be the first in one of
5236 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
5237 /* It's not condemned. Everything's fine. */
5239 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
5240 window
->vertical_scroll_bar
))
5241 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
5243 /* If its prev pointer is nil, it must be at the front of
5244 one or the other! */
5248 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
5250 if (! NILP (bar
->next
))
5251 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
5253 bar
->next
= FRAME_SCROLL_BARS (f
);
5255 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5256 if (! NILP (bar
->next
))
5257 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5260 /* Remove all scroll bars on FRAME that haven't been saved since the
5261 last call to `*condemn_scroll_bars_hook'. */
5264 XTjudge_scroll_bars (f
)
5267 Lisp_Object bar
, next
;
5269 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
5271 /* Clear out the condemned list now so we won't try to process any
5272 more events on the hapless scroll bars. */
5273 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
5275 for (; ! NILP (bar
); bar
= next
)
5277 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
5279 x_scroll_bar_remove (b
);
5282 b
->next
= b
->prev
= Qnil
;
5285 /* Now there should be no references to the condemned scroll bars,
5286 and they should get garbage-collected. */
5290 #ifndef USE_TOOLKIT_SCROLL_BARS
5291 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
5292 is a no-op when using toolkit scroll bars.
5294 This may be called from a signal handler, so we have to ignore GC
5298 x_scroll_bar_expose (bar
, event
)
5299 struct scroll_bar
*bar
;
5302 Window w
= SCROLL_BAR_X_WINDOW (bar
);
5303 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5304 GC gc
= f
->output_data
.x
->normal_gc
;
5305 int width_trim
= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
5309 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
5311 /* Draw a one-pixel border just inside the edges of the scroll bar. */
5312 XDrawRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
5314 /* x, y, width, height */
5316 XINT (bar
->width
) - 1 - width_trim
- width_trim
,
5317 XINT (bar
->height
) - 1);
5322 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5324 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5325 is set to something other than NO_EVENT, it is enqueued.
5327 This may be called from a signal handler, so we have to ignore GC
5332 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
5333 struct scroll_bar
*bar
;
5335 struct input_event
*emacs_event
;
5337 if (! GC_WINDOWP (bar
->window
))
5340 emacs_event
->kind
= SCROLL_BAR_CLICK_EVENT
;
5341 emacs_event
->code
= event
->xbutton
.button
- Button1
;
5342 emacs_event
->modifiers
5343 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
5344 (XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))),
5345 event
->xbutton
.state
)
5346 | (event
->type
== ButtonRelease
5349 emacs_event
->frame_or_window
= bar
->window
;
5350 emacs_event
->arg
= Qnil
;
5351 emacs_event
->timestamp
= event
->xbutton
.time
;
5354 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5356 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
5359 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5360 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
5363 if (y
> top_range
) y
= top_range
;
5365 if (y
< XINT (bar
->start
))
5366 emacs_event
->part
= scroll_bar_above_handle
;
5367 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5368 emacs_event
->part
= scroll_bar_handle
;
5370 emacs_event
->part
= scroll_bar_below_handle
;
5372 /* Just because the user has clicked on the handle doesn't mean
5373 they want to drag it. Lisp code needs to be able to decide
5374 whether or not we're dragging. */
5376 /* If the user has just clicked on the handle, record where they're
5378 if (event
->type
== ButtonPress
5379 && emacs_event
->part
== scroll_bar_handle
)
5380 XSETINT (bar
->dragging
, y
- XINT (bar
->start
));
5383 #ifndef USE_TOOLKIT_SCROLL_BARS
5384 /* If the user has released the handle, set it to its final position. */
5385 if (event
->type
== ButtonRelease
5386 && ! NILP (bar
->dragging
))
5388 int new_start
= y
- XINT (bar
->dragging
);
5389 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5391 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5392 bar
->dragging
= Qnil
;
5396 /* Same deal here as the other #if 0. */
5398 /* Clicks on the handle are always reported as occurring at the top of
5400 if (emacs_event
->part
== scroll_bar_handle
)
5401 emacs_event
->x
= bar
->start
;
5403 XSETINT (emacs_event
->x
, y
);
5405 XSETINT (emacs_event
->x
, y
);
5408 XSETINT (emacs_event
->y
, top_range
);
5412 #ifndef USE_TOOLKIT_SCROLL_BARS
5414 /* Handle some mouse motion while someone is dragging the scroll bar.
5416 This may be called from a signal handler, so we have to ignore GC
5420 x_scroll_bar_note_movement (bar
, event
)
5421 struct scroll_bar
*bar
;
5424 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5426 last_mouse_movement_time
= event
->xmotion
.time
;
5429 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5431 /* If we're dragging the bar, display it. */
5432 if (! GC_NILP (bar
->dragging
))
5434 /* Where should the handle be now? */
5435 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
5437 if (new_start
!= XINT (bar
->start
))
5439 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5441 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5446 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5448 /* Return information to the user about the current position of the mouse
5449 on the scroll bar. */
5452 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5454 Lisp_Object
*bar_window
;
5455 enum scroll_bar_part
*part
;
5457 unsigned long *time
;
5459 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5460 Window w
= SCROLL_BAR_X_WINDOW (bar
);
5461 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5463 Window dummy_window
;
5465 unsigned int dummy_mask
;
5469 /* Get the mouse's position relative to the scroll bar window, and
5471 if (! XQueryPointer (FRAME_X_DISPLAY (f
), w
,
5473 /* Root, child, root x and root y. */
5474 &dummy_window
, &dummy_window
,
5475 &dummy_coord
, &dummy_coord
,
5477 /* Position relative to scroll bar. */
5480 /* Mouse buttons and modifier keys. */
5487 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
5490 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5492 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5494 if (! NILP (bar
->dragging
))
5495 win_y
-= XINT (bar
->dragging
);
5499 if (win_y
> top_range
)
5503 *bar_window
= bar
->window
;
5505 if (! NILP (bar
->dragging
))
5506 *part
= scroll_bar_handle
;
5507 else if (win_y
< XINT (bar
->start
))
5508 *part
= scroll_bar_above_handle
;
5509 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5510 *part
= scroll_bar_handle
;
5512 *part
= scroll_bar_below_handle
;
5514 XSETINT (*x
, win_y
);
5515 XSETINT (*y
, top_range
);
5518 last_mouse_scroll_bar
= Qnil
;
5521 *time
= last_mouse_movement_time
;
5527 /* The screen has been cleared so we may have changed foreground or
5528 background colors, and the scroll bars may need to be redrawn.
5529 Clear out the scroll bars, and ask for expose events, so we can
5533 x_scroll_bar_clear (f
)
5536 #ifndef USE_TOOLKIT_SCROLL_BARS
5539 /* We can have scroll bars even if this is 0,
5540 if we just turned off scroll bar mode.
5541 But in that case we should not clear them. */
5542 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5543 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
5544 bar
= XSCROLL_BAR (bar
)->next
)
5545 XClearArea (FRAME_X_DISPLAY (f
),
5546 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
5548 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5552 /* Define a queue to save up SelectionRequest events for later handling. */
5554 struct selection_event_queue
5557 struct selection_event_queue
*next
;
5560 static struct selection_event_queue
*queue
;
5562 /* Nonzero means queue up certain events--don't process them yet. */
5564 static int x_queue_selection_requests
;
5566 /* Queue up an X event *EVENT, to be processed later. */
5569 x_queue_event (f
, event
)
5573 struct selection_event_queue
*queue_tmp
5574 = (struct selection_event_queue
*) xmalloc (sizeof (struct selection_event_queue
));
5576 if (queue_tmp
!= NULL
)
5578 queue_tmp
->event
= *event
;
5579 queue_tmp
->next
= queue
;
5584 /* Take all the queued events and put them back
5585 so that they get processed afresh. */
5588 x_unqueue_events (display
)
5591 while (queue
!= NULL
)
5593 struct selection_event_queue
*queue_tmp
= queue
;
5594 XPutBackEvent (display
, &queue_tmp
->event
);
5595 queue
= queue_tmp
->next
;
5596 xfree ((char *)queue_tmp
);
5600 /* Start queuing SelectionRequest events. */
5603 x_start_queuing_selection_requests (display
)
5606 x_queue_selection_requests
++;
5609 /* Stop queuing SelectionRequest events. */
5612 x_stop_queuing_selection_requests (display
)
5615 x_queue_selection_requests
--;
5616 x_unqueue_events (display
);
5619 /* The main X event-reading loop - XTread_socket. */
5622 /* Time stamp of enter window event. This is only used by XTread_socket,
5623 but we have to put it out here, since static variables within functions
5624 sometimes don't work. */
5626 static Time enter_timestamp
;
5629 /* This holds the state XLookupString needs to implement dead keys
5630 and other tricks known as "compose processing". _X Window System_
5631 says that a portable program can't use this, but Stephen Gildea assures
5632 me that letting the compiler initialize it to zeros will work okay.
5634 This must be defined outside of XTread_socket, for the same reasons
5635 given for enter_timestamp, above. */
5637 static XComposeStatus compose_status
;
5639 /* Record the last 100 characters stored
5640 to help debug the loss-of-chars-during-GC problem. */
5642 static int temp_index
;
5643 static short temp_buffer
[100];
5645 #define STORE_KEYSYM_FOR_DEBUG(keysym) \
5646 if (temp_index == sizeof temp_buffer / sizeof (short)) \
5648 temp_buffer[temp_index++] = (keysym)
5650 /* Set this to nonzero to fake an "X I/O error"
5651 on a particular display. */
5653 struct x_display_info
*XTread_socket_fake_io_error
;
5655 /* When we find no input here, we occasionally do a no-op command
5656 to verify that the X server is still running and we can still talk with it.
5657 We try all the open displays, one by one.
5658 This variable is used for cycling thru the displays. */
5660 static struct x_display_info
*next_noop_dpyinfo
;
5662 #define SET_SAVED_MENU_EVENT(size) \
5665 if (f->output_data.x->saved_menu_event == 0) \
5666 f->output_data.x->saved_menu_event \
5667 = (XEvent *) xmalloc (sizeof (XEvent)); \
5668 bcopy (&event, f->output_data.x->saved_menu_event, size); \
5669 inev.kind = MENU_BAR_ACTIVATE_EVENT; \
5670 XSETFRAME (inev.frame_or_window, f); \
5674 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
5675 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
5685 /* Filter events for the current X input method.
5686 DPYINFO is the display this event is for.
5687 EVENT is the X event to filter.
5689 Returns non-zero if the event was filtered, caller shall not process
5691 Returns zero if event is wasn't filtered. */
5695 x_filter_event (dpyinfo
, event
)
5696 struct x_display_info
*dpyinfo
;
5699 /* XFilterEvent returns non-zero if the input method has
5700 consumed the event. We pass the frame's X window to
5701 XFilterEvent because that's the one for which the IC
5704 struct frame
*f1
= x_any_window_to_frame (dpyinfo
,
5705 event
->xclient
.window
);
5707 return XFilterEvent (event
, f1
? FRAME_X_WINDOW (f1
) : None
);
5712 static int current_count
;
5713 static int current_finish
;
5714 static struct input_event
*current_hold_quit
;
5716 /* This is the filter function invoked by the GTK event loop.
5717 It is invoked before the XEvent is translated to a GdkEvent,
5718 so we have a chance to act on the event before GTK. */
5719 static GdkFilterReturn
5720 event_handler_gdk (gxev
, ev
, data
)
5725 XEvent
*xev
= (XEvent
*) gxev
;
5727 if (current_count
>= 0)
5729 struct x_display_info
*dpyinfo
;
5731 dpyinfo
= x_display_info_for_display (xev
->xany
.display
);
5734 /* Filter events for the current X input method.
5735 GTK calls XFilterEvent but not for key press and release,
5736 so we do it here. */
5737 if (xev
->type
== KeyPress
|| xev
->type
== KeyRelease
)
5738 if (dpyinfo
&& x_filter_event (dpyinfo
, xev
))
5739 return GDK_FILTER_REMOVE
;
5743 current_finish
= X_EVENT_NORMAL
;
5747 handle_one_xevent (dpyinfo
, xev
, ¤t_finish
,
5752 current_finish
= x_dispatch_event (xev
, xev
->xany
.display
);
5754 if (current_finish
== X_EVENT_GOTO_OUT
|| current_finish
== X_EVENT_DROP
)
5755 return GDK_FILTER_REMOVE
;
5757 return GDK_FILTER_CONTINUE
;
5759 #endif /* USE_GTK */
5762 /* Handles the XEvent EVENT on display DPYINFO.
5764 *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
5765 *FINISH is zero if caller should continue reading events.
5766 *FINISH is X_EVENT_DROP if event should not be passed to the toolkit.
5768 We return the number of characters stored into the buffer. */
5771 handle_one_xevent (dpyinfo
, eventp
, finish
, hold_quit
)
5772 struct x_display_info
*dpyinfo
;
5775 struct input_event
*hold_quit
;
5777 struct input_event inev
;
5782 struct coding_system coding
;
5783 XEvent event
= *eventp
;
5785 *finish
= X_EVENT_NORMAL
;
5788 inev
.kind
= NO_EVENT
;
5795 if (event
.xclient
.message_type
5796 == dpyinfo
->Xatom_wm_protocols
5797 && event
.xclient
.format
== 32)
5799 if (event
.xclient
.data
.l
[0]
5800 == dpyinfo
->Xatom_wm_take_focus
)
5802 /* Use x_any_window_to_frame because this
5803 could be the shell widget window
5804 if the frame has no title bar. */
5805 f
= x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
5807 /* Not quite sure this is needed -pd */
5808 if (f
&& FRAME_XIC (f
))
5809 XSetICFocus (FRAME_XIC (f
));
5811 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
5812 instructs the WM to set the input focus automatically for
5813 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
5814 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
5815 it has set the focus. So, XSetInputFocus below is not
5818 The call to XSetInputFocus below has also caused trouble. In
5819 cases where the XSetInputFocus done by the WM and the one
5820 below are temporally close (on a fast machine), the call
5821 below can generate additional FocusIn events which confuse
5824 /* Since we set WM_TAKE_FOCUS, we must call
5825 XSetInputFocus explicitly. But not if f is null,
5826 since that might be an event for a deleted frame. */
5829 Display
*d
= event
.xclient
.display
;
5830 /* Catch and ignore errors, in case window has been
5831 iconified by a window manager such as GWM. */
5832 int count
= x_catch_errors (d
);
5833 XSetInputFocus (d
, event
.xclient
.window
,
5834 /* The ICCCM says this is
5835 the only valid choice. */
5837 event
.xclient
.data
.l
[1]);
5838 /* This is needed to detect the error
5839 if there is an error. */
5841 x_uncatch_errors (d
, count
);
5843 /* Not certain about handling scroll bars here */
5848 if (event
.xclient
.data
.l
[0]
5849 == dpyinfo
->Xatom_wm_save_yourself
)
5851 /* Save state modify the WM_COMMAND property to
5852 something which can reinstate us. This notifies
5853 the session manager, who's looking for such a
5854 PropertyNotify. Can restart processing when
5855 a keyboard or mouse event arrives. */
5856 /* If we have a session manager, don't set this.
5857 KDE will then start two Emacsen, one for the
5858 session manager and one for this. */
5860 if (! x_session_have_connection ())
5863 f
= x_top_window_to_frame (dpyinfo
,
5864 event
.xclient
.window
);
5865 /* This is just so we only give real data once
5866 for a single Emacs process. */
5867 if (f
== SELECTED_FRAME ())
5868 XSetCommand (FRAME_X_DISPLAY (f
),
5869 event
.xclient
.window
,
5870 initial_argv
, initial_argc
);
5872 XSetCommand (FRAME_X_DISPLAY (f
),
5873 event
.xclient
.window
,
5879 if (event
.xclient
.data
.l
[0]
5880 == dpyinfo
->Xatom_wm_delete_window
)
5882 f
= x_any_window_to_frame (dpyinfo
,
5883 event
.xclient
.window
);
5885 goto OTHER
; /* May be a dialog that is to be removed */
5887 inev
.kind
= DELETE_WINDOW_EVENT
;
5888 XSETFRAME (inev
.frame_or_window
, f
);
5895 if (event
.xclient
.message_type
5896 == dpyinfo
->Xatom_wm_configure_denied
)
5901 if (event
.xclient
.message_type
5902 == dpyinfo
->Xatom_wm_window_moved
)
5905 f
= x_window_to_frame (dpyinfo
, event
.xclient
.window
);
5907 new_x
= event
.xclient
.data
.s
[0];
5908 new_y
= event
.xclient
.data
.s
[1];
5912 f
->left_pos
= new_x
;
5919 if (event
.xclient
.message_type
5920 == dpyinfo
->Xatom_editres
)
5922 f
= x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
5923 _XEditResCheckMessages (f
->output_data
.x
->widget
, NULL
,
5927 #endif /* HACK_EDITRES */
5929 if ((event
.xclient
.message_type
5930 == dpyinfo
->Xatom_DONE
)
5931 || (event
.xclient
.message_type
5932 == dpyinfo
->Xatom_PAGE
))
5934 /* Ghostview job completed. Kill it. We could
5935 reply with "Next" if we received "Page", but we
5936 currently never do because we are interested in
5937 images, only, which should have 1 page. */
5938 Pixmap pixmap
= (Pixmap
) event
.xclient
.data
.l
[1];
5939 f
= x_window_to_frame (dpyinfo
, event
.xclient
.window
);
5940 x_kill_gs_process (pixmap
, f
);
5941 expose_frame (f
, 0, 0, 0, 0);
5945 #ifdef USE_TOOLKIT_SCROLL_BARS
5946 /* Scroll bar callbacks send a ClientMessage from which
5947 we construct an input_event. */
5948 if (event
.xclient
.message_type
5949 == dpyinfo
->Xatom_Scrollbar
)
5951 x_scroll_bar_to_input_event (&event
, &inev
);
5952 *finish
= X_EVENT_GOTO_OUT
;
5955 #endif /* USE_TOOLKIT_SCROLL_BARS */
5957 f
= x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
5962 if (x_handle_dnd_message (f
, &event
.xclient
, dpyinfo
, &inev
))
5963 *finish
= X_EVENT_DROP
;
5967 case SelectionNotify
:
5968 #ifdef USE_X_TOOLKIT
5969 if (! x_window_to_frame (dpyinfo
, event
.xselection
.requestor
))
5971 #endif /* not USE_X_TOOLKIT */
5972 x_handle_selection_notify (&event
.xselection
);
5975 case SelectionClear
: /* Someone has grabbed ownership. */
5976 #ifdef USE_X_TOOLKIT
5977 if (! x_window_to_frame (dpyinfo
, event
.xselectionclear
.window
))
5979 #endif /* USE_X_TOOLKIT */
5981 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
5983 inev
.kind
= SELECTION_CLEAR_EVENT
;
5984 SELECTION_EVENT_DISPLAY (&inev
) = eventp
->display
;
5985 SELECTION_EVENT_SELECTION (&inev
) = eventp
->selection
;
5986 SELECTION_EVENT_TIME (&inev
) = eventp
->time
;
5987 inev
.frame_or_window
= Qnil
;
5991 case SelectionRequest
: /* Someone wants our selection. */
5992 #ifdef USE_X_TOOLKIT
5993 if (!x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
))
5995 #endif /* USE_X_TOOLKIT */
5996 if (x_queue_selection_requests
)
5997 x_queue_event (x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
),
6001 XSelectionRequestEvent
*eventp
6002 = (XSelectionRequestEvent
*) &event
;
6004 inev
.kind
= SELECTION_REQUEST_EVENT
;
6005 SELECTION_EVENT_DISPLAY (&inev
) = eventp
->display
;
6006 SELECTION_EVENT_REQUESTOR (&inev
) = eventp
->requestor
;
6007 SELECTION_EVENT_SELECTION (&inev
) = eventp
->selection
;
6008 SELECTION_EVENT_TARGET (&inev
) = eventp
->target
;
6009 SELECTION_EVENT_PROPERTY (&inev
) = eventp
->property
;
6010 SELECTION_EVENT_TIME (&inev
) = eventp
->time
;
6011 inev
.frame_or_window
= Qnil
;
6015 case PropertyNotify
:
6016 #if 0 /* This is plain wrong. In the case that we are waiting for a
6017 PropertyNotify used as an ACK in incremental selection
6018 transfer, the property will be on the receiver's window. */
6019 #if defined USE_X_TOOLKIT
6020 if (!x_any_window_to_frame (dpyinfo
, event
.xproperty
.window
))
6024 x_handle_property_notify (&event
.xproperty
);
6027 case ReparentNotify
:
6028 f
= x_top_window_to_frame (dpyinfo
, event
.xreparent
.window
);
6032 f
->output_data
.x
->parent_desc
= event
.xreparent
.parent
;
6033 x_real_positions (f
, &x
, &y
);
6037 /* Perhaps reparented due to a WM restart. Reset this. */
6038 FRAME_X_DISPLAY_INFO (f
)->wm_type
= X_WMTYPE_UNKNOWN
;
6043 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
6046 x_check_fullscreen (f
);
6048 if (f
->async_visible
== 0)
6050 f
->async_visible
= 1;
6051 f
->async_iconified
= 0;
6052 f
->output_data
.x
->has_been_visible
= 1;
6053 SET_FRAME_GARBAGED (f
);
6057 event
.xexpose
.x
, event
.xexpose
.y
,
6058 event
.xexpose
.width
, event
.xexpose
.height
);
6062 #ifndef USE_TOOLKIT_SCROLL_BARS
6063 struct scroll_bar
*bar
;
6065 #if defined USE_LUCID
6066 /* Submenus of the Lucid menu bar aren't widgets
6067 themselves, so there's no way to dispatch events
6068 to them. Recognize this case separately. */
6071 = x_window_to_menu_bar (event
.xexpose
.window
);
6073 xlwmenu_redisplay (widget
);
6075 #endif /* USE_LUCID */
6077 #ifdef USE_TOOLKIT_SCROLL_BARS
6078 /* Dispatch event to the widget. */
6080 #else /* not USE_TOOLKIT_SCROLL_BARS */
6081 bar
= x_window_to_scroll_bar (event
.xexpose
.display
,
6082 event
.xexpose
.window
);
6085 x_scroll_bar_expose (bar
, &event
);
6086 #ifdef USE_X_TOOLKIT
6089 #endif /* USE_X_TOOLKIT */
6090 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6094 case GraphicsExpose
: /* This occurs when an XCopyArea's
6095 source area was obscured or not
6097 f
= x_window_to_frame (dpyinfo
, event
.xgraphicsexpose
.drawable
);
6101 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
6102 event
.xgraphicsexpose
.width
,
6103 event
.xgraphicsexpose
.height
);
6105 #ifdef USE_X_TOOLKIT
6108 #endif /* USE_X_TOOLKIT */
6111 case NoExpose
: /* This occurs when an XCopyArea's
6112 source area was completely
6117 /* Redo the mouse-highlight after the tooltip has gone. */
6118 if (event
.xmap
.window
== tip_window
)
6121 redo_mouse_highlight ();
6124 f
= x_top_window_to_frame (dpyinfo
, event
.xunmap
.window
);
6125 if (f
) /* F may no longer exist if
6126 the frame was deleted. */
6128 /* While a frame is unmapped, display generation is
6129 disabled; you don't want to spend time updating a
6130 display that won't ever be seen. */
6131 f
->async_visible
= 0;
6132 /* We can't distinguish, from the event, whether the window
6133 has become iconified or invisible. So assume, if it
6134 was previously visible, than now it is iconified.
6135 But x_make_frame_invisible clears both
6136 the visible flag and the iconified flag;
6137 and that way, we know the window is not iconified now. */
6138 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
6140 f
->async_iconified
= 1;
6142 inev
.kind
= ICONIFY_EVENT
;
6143 XSETFRAME (inev
.frame_or_window
, f
);
6149 if (event
.xmap
.window
== tip_window
)
6150 /* The tooltip has been drawn already. Avoid
6151 the SET_FRAME_GARBAGED below. */
6154 /* We use x_top_window_to_frame because map events can
6155 come for sub-windows and they don't mean that the
6156 frame is visible. */
6157 f
= x_top_window_to_frame (dpyinfo
, event
.xmap
.window
);
6160 /* wait_reading_process_input will notice this and update
6161 the frame's display structures.
6162 If we where iconified, we should not set garbaged,
6163 because that stops redrawing on Expose events. This looks
6164 bad if we are called from a recursive event loop
6165 (x_dispatch_event), for example when a dialog is up. */
6166 if (! f
->async_iconified
)
6167 SET_FRAME_GARBAGED (f
);
6169 f
->async_visible
= 1;
6170 f
->async_iconified
= 0;
6171 f
->output_data
.x
->has_been_visible
= 1;
6175 inev
.kind
= DEICONIFY_EVENT
;
6176 XSETFRAME (inev
.frame_or_window
, f
);
6178 else if (! NILP (Vframe_list
)
6179 && ! NILP (XCDR (Vframe_list
)))
6180 /* Force a redisplay sooner or later
6181 to update the frame titles
6182 in case this is the second frame. */
6183 record_asynch_buffer_change ();
6189 ignore_next_mouse_click_timeout
= 0;
6191 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6192 /* Dispatch KeyPress events when in menu. */
6193 if (popup_activated ())
6197 f
= x_any_window_to_frame (dpyinfo
, event
.xkey
.window
);
6199 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
6201 dpyinfo
->mouse_face_hidden
= 1;
6202 clear_mouse_face (dpyinfo
);
6205 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
6208 /* Scroll bars consume key events, but we want
6209 the keys to go to the scroll bar's frame. */
6210 Widget widget
= XtWindowToWidget (dpyinfo
->display
,
6212 if (widget
&& XmIsScrollBar (widget
))
6214 widget
= XtParent (widget
);
6215 f
= x_any_window_to_frame (dpyinfo
, XtWindow (widget
));
6218 #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
6222 KeySym keysym
, orig_keysym
;
6223 /* al%imercury@uunet.uu.net says that making this 81
6224 instead of 80 fixed a bug whereby meta chars made
6227 It seems that some version of XmbLookupString has
6228 a bug of not returning XBufferOverflow in
6229 status_return even if the input is too long to
6230 fit in 81 bytes. So, we must prepare sufficient
6231 bytes for copy_buffer. 513 bytes (256 chars for
6232 two-byte character set) seems to be a fairly good
6233 approximation. -- 2000.8.10 handa@etl.go.jp */
6234 unsigned char copy_buffer
[513];
6235 unsigned char *copy_bufptr
= copy_buffer
;
6236 int copy_bufsiz
= sizeof (copy_buffer
);
6238 Lisp_Object coding_system
= Qlatin_1
;
6242 /* Don't pass keys to GTK. A Tab will shift focus to the
6243 tool bar in GTK 2.4. Keys will still go to menus and
6244 dialogs because in that case popup_activated is TRUE
6246 *finish
= X_EVENT_DROP
;
6250 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f
),
6251 extra_keyboard_modifiers
);
6252 modifiers
= event
.xkey
.state
;
6254 /* This will have to go some day... */
6256 /* make_lispy_event turns chars into control chars.
6257 Don't do it here because XLookupString is too eager. */
6258 event
.xkey
.state
&= ~ControlMask
;
6259 event
.xkey
.state
&= ~(dpyinfo
->meta_mod_mask
6260 | dpyinfo
->super_mod_mask
6261 | dpyinfo
->hyper_mod_mask
6262 | dpyinfo
->alt_mod_mask
);
6264 /* In case Meta is ComposeCharacter,
6265 clear its status. According to Markus Ehrnsperger
6266 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
6267 this enables ComposeCharacter to work whether or
6268 not it is combined with Meta. */
6269 if (modifiers
& dpyinfo
->meta_mod_mask
)
6270 bzero (&compose_status
, sizeof (compose_status
));
6275 Status status_return
;
6277 coding_system
= Vlocale_coding_system
;
6278 nbytes
= XmbLookupString (FRAME_XIC (f
),
6279 &event
.xkey
, copy_bufptr
,
6280 copy_bufsiz
, &keysym
,
6282 if (status_return
== XBufferOverflow
)
6284 copy_bufsiz
= nbytes
+ 1;
6285 copy_bufptr
= (char *) alloca (copy_bufsiz
);
6286 nbytes
= XmbLookupString (FRAME_XIC (f
),
6287 &event
.xkey
, copy_bufptr
,
6288 copy_bufsiz
, &keysym
,
6291 /* Xutf8LookupString is a new but already deprecated interface. -stef */
6292 #if 0 && defined X_HAVE_UTF8_STRING
6293 else if (status_return
== XLookupKeySym
)
6294 { /* Try again but with utf-8. */
6295 coding_system
= Qutf_8
;
6296 nbytes
= Xutf8LookupString (FRAME_XIC (f
),
6297 &event
.xkey
, copy_bufptr
,
6298 copy_bufsiz
, &keysym
,
6300 if (status_return
== XBufferOverflow
)
6302 copy_bufsiz
= nbytes
+ 1;
6303 copy_bufptr
= (char *) alloca (copy_bufsiz
);
6304 nbytes
= Xutf8LookupString (FRAME_XIC (f
),
6307 copy_bufsiz
, &keysym
,
6313 if (status_return
== XLookupNone
)
6315 else if (status_return
== XLookupChars
)
6320 else if (status_return
!= XLookupKeySym
6321 && status_return
!= XLookupBoth
)
6325 nbytes
= XLookupString (&event
.xkey
, copy_bufptr
,
6326 copy_bufsiz
, &keysym
,
6329 nbytes
= XLookupString (&event
.xkey
, copy_bufptr
,
6330 copy_bufsiz
, &keysym
,
6334 /* If not using XIM/XIC, and a compose sequence is in progress,
6335 we break here. Otherwise, chars_matched is always 0. */
6336 if (compose_status
.chars_matched
> 0 && nbytes
== 0)
6339 orig_keysym
= keysym
;
6341 /* Common for all keysym input events. */
6342 XSETFRAME (inev
.frame_or_window
, f
);
6344 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
), modifiers
);
6345 inev
.timestamp
= event
.xkey
.time
;
6347 /* First deal with keysyms which have defined
6348 translations to characters. */
6349 if (keysym
>= 32 && keysym
< 128)
6350 /* Avoid explicitly decoding each ASCII character. */
6352 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
6357 /* Now non-ASCII. */
6358 if (HASH_TABLE_P (Vx_keysym_table
)
6359 && (NATNUMP (c
= Fgethash (make_number (keysym
),
6363 inev
.kind
= (SINGLE_BYTE_CHAR_P (XFASTINT (c
))
6364 ? ASCII_KEYSTROKE_EVENT
6365 : MULTIBYTE_CHAR_KEYSTROKE_EVENT
);
6366 inev
.code
= XFASTINT (c
);
6370 /* Random non-modifier sorts of keysyms. */
6371 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 STORE_KEYSYM_FOR_DEBUG (keysym
);
6454 /* make_lispy_event will convert this to a symbolic
6456 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
6461 { /* Raw bytes, not keysym. */
6466 /* The input should be decoded with `coding_system'
6467 which depends on which X*LookupString function
6468 we used just above and the locale. */
6469 setup_coding_system (coding_system
, &coding
);
6470 coding
.src_multibyte
= 0;
6471 coding
.dst_multibyte
= 1;
6472 /* The input is converted to events, thus we can't
6473 handle composition. Anyway, there's no XIM that
6474 gives us composition information. */
6475 coding
.composing
= COMPOSITION_DISABLED
;
6477 for (i
= 0; i
< nbytes
; i
++)
6479 STORE_KEYSYM_FOR_DEBUG (copy_bufptr
[i
]);
6483 /* Decode the input data. */
6487 require
= decoding_buffer_size (&coding
, nbytes
);
6488 p
= (unsigned char *) alloca (require
);
6489 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6490 /* We explicitly disable composition handling because
6491 key data should not contain any composition sequence. */
6492 coding
.composing
= COMPOSITION_DISABLED
;
6493 decode_coding (&coding
, copy_bufptr
, p
, nbytes
, require
);
6494 nbytes
= coding
.produced
;
6495 nchars
= coding
.produced_char
;
6499 /* Convert the input data to a sequence of
6500 character events. */
6501 for (i
= 0; i
< nbytes
; i
+= len
)
6503 if (nchars
== nbytes
)
6504 c
= copy_bufptr
[i
], len
= 1;
6506 c
= STRING_CHAR_AND_LENGTH (copy_bufptr
+ i
,
6508 inev
.kind
= (SINGLE_BYTE_CHAR_P (c
)
6509 ? ASCII_KEYSTROKE_EVENT
6510 : MULTIBYTE_CHAR_KEYSTROKE_EVENT
);
6512 kbd_buffer_store_event_hold (&inev
, hold_quit
);
6515 /* Previous code updated count by nchars rather than nbytes,
6516 but that seems bogus to me. ++kfs */
6519 inev
.kind
= NO_EVENT
; /* Already stored above. */
6521 if (keysym
== NoSymbol
)
6527 /* Don't dispatch this event since XtDispatchEvent calls
6528 XFilterEvent, and two calls in a row may freeze the
6537 /* Don't dispatch this event since XtDispatchEvent calls
6538 XFilterEvent, and two calls in a row may freeze the
6546 x_detect_focus_change (dpyinfo
, &event
, &inev
);
6548 f
= x_any_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
6550 if (f
&& x_mouse_click_focus_ignore_position
)
6551 ignore_next_mouse_click_timeout
= event
.xmotion
.time
+ 200;
6554 if (event
.xcrossing
.focus
)
6556 /* Avoid nasty pop/raise loops. */
6557 if (f
&& (!(f
->auto_raise
)
6559 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
6561 x_new_focus_frame (dpyinfo
, f
);
6562 enter_timestamp
= event
.xcrossing
.time
;
6565 else if (f
== dpyinfo
->x_focus_frame
)
6566 x_new_focus_frame (dpyinfo
, 0);
6569 /* EnterNotify counts as mouse movement,
6570 so update things that depend on mouse position. */
6571 if (f
&& !f
->output_data
.x
->hourglass_p
)
6572 note_mouse_movement (f
, &event
.xmotion
);
6576 x_detect_focus_change (dpyinfo
, &event
, &inev
);
6580 x_detect_focus_change (dpyinfo
, &event
, &inev
);
6582 f
= x_top_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
6585 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6587 /* If we move outside the frame, then we're
6588 certainly no longer on any text in the frame. */
6589 clear_mouse_face (dpyinfo
);
6590 dpyinfo
->mouse_face_mouse_frame
= 0;
6593 /* Generate a nil HELP_EVENT to cancel a help-echo.
6594 Do it only if there's something to cancel.
6595 Otherwise, the startup message is cleared when
6596 the mouse leaves the frame. */
6597 if (any_help_event_p
)
6603 x_detect_focus_change (dpyinfo
, &event
, &inev
);
6608 previous_help_echo_string
= help_echo_string
;
6609 help_echo_string
= help_echo_object
= help_echo_window
= Qnil
;
6612 if (dpyinfo
->grabbed
&& last_mouse_frame
6613 && FRAME_LIVE_P (last_mouse_frame
))
6614 f
= last_mouse_frame
;
6616 f
= x_window_to_frame (dpyinfo
, event
.xmotion
.window
);
6618 if (dpyinfo
->mouse_face_hidden
)
6620 dpyinfo
->mouse_face_hidden
= 0;
6621 clear_mouse_face (dpyinfo
);
6627 /* Generate SELECT_WINDOW_EVENTs when needed. */
6628 if (mouse_autoselect_window
)
6632 window
= window_from_coordinates (f
,
6633 event
.xmotion
.x
, event
.xmotion
.y
,
6636 /* Window will be selected only when it is not selected now and
6637 last mouse movement event was not in it. Minibuffer window
6638 will be selected iff it is active. */
6639 if (WINDOWP (window
)
6640 && !EQ (window
, last_window
)
6641 && !EQ (window
, selected_window
))
6643 inev
.kind
= SELECT_WINDOW_EVENT
;
6644 inev
.frame_or_window
= window
;
6649 note_mouse_movement (f
, &event
.xmotion
);
6653 #ifndef USE_TOOLKIT_SCROLL_BARS
6654 struct scroll_bar
*bar
6655 = x_window_to_scroll_bar (event
.xmotion
.display
,
6656 event
.xmotion
.window
);
6659 x_scroll_bar_note_movement (bar
, &event
);
6660 #endif /* USE_TOOLKIT_SCROLL_BARS */
6662 /* If we move outside the frame, then we're
6663 certainly no longer on any text in the frame. */
6664 clear_mouse_face (dpyinfo
);
6667 /* If the contents of the global variable help_echo_string
6668 has changed, generate a HELP_EVENT. */
6669 if (!NILP (help_echo_string
)
6670 || !NILP (previous_help_echo_string
))
6675 case ConfigureNotify
:
6676 f
= x_top_window_to_frame (dpyinfo
, event
.xconfigure
.window
);
6679 #ifndef USE_X_TOOLKIT
6681 xg_resize_widgets (f
, event
.xconfigure
.width
,
6682 event
.xconfigure
.height
);
6683 #else /* not USE_GTK */
6684 /* If there is a pending resize for fullscreen, don't
6685 do this one, the right one will come later.
6686 The toolkit version doesn't seem to need this, but we
6687 need to reset it below. */
6689 = ((f
->want_fullscreen
& FULLSCREEN_WAIT
)
6690 && f
->new_text_cols
!= 0);
6691 int rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, event
.xconfigure
.height
);
6692 int columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, event
.xconfigure
.width
);
6697 /* In the toolkit version, change_frame_size
6698 is called by the code that handles resizing
6699 of the EmacsFrame widget. */
6701 /* Even if the number of character rows and columns has
6702 not changed, the font size may have changed, so we need
6703 to check the pixel dimensions as well. */
6704 if (columns
!= FRAME_COLS (f
)
6705 || rows
!= FRAME_LINES (f
)
6706 || event
.xconfigure
.width
!= FRAME_PIXEL_WIDTH (f
)
6707 || event
.xconfigure
.height
!= FRAME_PIXEL_HEIGHT (f
))
6709 change_frame_size (f
, rows
, columns
, 0, 1, 0);
6710 SET_FRAME_GARBAGED (f
);
6711 cancel_mouse_face (f
);
6713 #endif /* not USE_GTK */
6716 FRAME_PIXEL_WIDTH (f
) = event
.xconfigure
.width
;
6717 FRAME_PIXEL_HEIGHT (f
) = event
.xconfigure
.height
;
6720 /* GTK creates windows but doesn't map them.
6721 Only get real positions and check fullscreen when mapped. */
6722 if (FRAME_GTK_OUTER_WIDGET (f
)
6723 && GTK_WIDGET_MAPPED (FRAME_GTK_OUTER_WIDGET (f
)))
6726 /* What we have now is the position of Emacs's own window.
6727 Convert that to the position of the window manager window. */
6728 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
6730 x_check_expected_move (f
);
6731 if (f
->want_fullscreen
& FULLSCREEN_WAIT
)
6732 f
->want_fullscreen
&= ~(FULLSCREEN_WAIT
|FULLSCREEN_BOTH
);
6736 if (FRAME_XIC (f
) && (FRAME_XIC_STYLE (f
) & XIMStatusArea
))
6737 xic_set_statusarea (f
);
6740 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
6742 /* Since the WM decorations come below top_pos now,
6743 we must put them below top_pos in the future. */
6744 f
->win_gravity
= NorthWestGravity
;
6745 x_wm_set_size_hint (f
, (long) 0, 0);
6753 /* If we decide we want to generate an event to be seen
6754 by the rest of Emacs, we put it here. */
6757 bzero (&compose_status
, sizeof (compose_status
));
6759 if (dpyinfo
->grabbed
6761 && FRAME_LIVE_P (last_mouse_frame
))
6762 f
= last_mouse_frame
;
6764 f
= x_window_to_frame (dpyinfo
, event
.xbutton
.window
);
6768 /* Is this in the tool-bar? */
6769 if (WINDOWP (f
->tool_bar_window
)
6770 && WINDOW_TOTAL_LINES (XWINDOW (f
->tool_bar_window
)))
6773 int x
= event
.xbutton
.x
;
6774 int y
= event
.xbutton
.y
;
6776 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
6777 if (EQ (window
, f
->tool_bar_window
))
6779 if (event
.xbutton
.type
== ButtonPress
)
6780 handle_tool_bar_click (f
, x
, y
, 1, 0);
6782 handle_tool_bar_click (f
, x
, y
, 0,
6783 x_x_to_emacs_modifiers (dpyinfo
,
6784 event
.xbutton
.state
));
6790 if (!dpyinfo
->x_focus_frame
6791 || f
== dpyinfo
->x_focus_frame
)
6793 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6794 if (! popup_activated ())
6797 if (ignore_next_mouse_click_timeout
)
6799 if (event
.type
== ButtonPress
6800 && (int)(event
.xbutton
.time
- ignore_next_mouse_click_timeout
) > 0)
6802 ignore_next_mouse_click_timeout
= 0;
6803 construct_mouse_click (&inev
, &event
, f
);
6805 if (event
.type
== ButtonRelease
)
6806 ignore_next_mouse_click_timeout
= 0;
6809 construct_mouse_click (&inev
, &event
, f
);
6815 struct scroll_bar
*bar
6816 = x_window_to_scroll_bar (event
.xbutton
.display
,
6817 event
.xbutton
.window
);
6819 #ifdef USE_TOOLKIT_SCROLL_BARS
6820 /* Make the "Ctrl-Mouse-2 splits window" work for toolkit
6822 if (bar
&& event
.xbutton
.state
& ControlMask
)
6824 x_scroll_bar_handle_click (bar
, &event
, &inev
);
6825 *finish
= X_EVENT_DROP
;
6827 #else /* not USE_TOOLKIT_SCROLL_BARS */
6829 x_scroll_bar_handle_click (bar
, &event
, &inev
);
6830 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6833 if (event
.type
== ButtonPress
)
6835 dpyinfo
->grabbed
|= (1 << event
.xbutton
.button
);
6836 last_mouse_frame
= f
;
6837 /* Ignore any mouse motion that happened
6838 before this event; any subsequent mouse-movement
6839 Emacs events should reflect only motion after
6845 last_tool_bar_item
= -1;
6848 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
6850 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6851 f
= x_menubar_window_to_frame (dpyinfo
, event
.xbutton
.window
);
6852 /* For a down-event in the menu bar,
6853 don't pass it to Xt right now.
6854 Instead, save it away
6855 and we will pass it to Xt from kbd_buffer_get_event.
6856 That way, we can run some Lisp code first. */
6859 ! popup_activated ()
6862 f
&& event
.type
== ButtonPress
6863 /* Verify the event is really within the menu bar
6864 and not just sent to it due to grabbing. */
6865 && event
.xbutton
.x
>= 0
6866 && event
.xbutton
.x
< FRAME_PIXEL_WIDTH (f
)
6867 && event
.xbutton
.y
>= 0
6868 && event
.xbutton
.y
< f
->output_data
.x
->menubar_height
6869 && event
.xbutton
.same_screen
)
6871 SET_SAVED_BUTTON_EVENT
;
6872 XSETFRAME (last_mouse_press_frame
, f
);
6874 *finish
= X_EVENT_DROP
;
6877 else if (event
.type
== ButtonPress
)
6879 last_mouse_press_frame
= Qnil
;
6883 #ifdef USE_MOTIF /* This should do not harm for Lucid,
6884 but I am trying to be cautious. */
6885 else if (event
.type
== ButtonRelease
)
6887 if (!NILP (last_mouse_press_frame
))
6889 f
= XFRAME (last_mouse_press_frame
);
6890 if (f
->output_data
.x
)
6891 SET_SAVED_BUTTON_EVENT
;
6896 #endif /* USE_MOTIF */
6899 #endif /* USE_X_TOOLKIT || USE_GTK */
6903 case CirculateNotify
:
6906 case CirculateRequest
:
6909 case VisibilityNotify
:
6913 /* Someone has changed the keyboard mapping - update the
6915 switch (event
.xmapping
.request
)
6917 case MappingModifier
:
6918 x_find_modifier_meanings (dpyinfo
);
6919 /* This is meant to fall through. */
6920 case MappingKeyboard
:
6921 XRefreshKeyboardMapping (&event
.xmapping
);
6927 #ifdef USE_X_TOOLKIT
6929 if (*finish
!= X_EVENT_DROP
)
6930 XtDispatchEvent (&event
);
6932 #endif /* USE_X_TOOLKIT */
6937 if (inev
.kind
!= NO_EVENT
)
6939 kbd_buffer_store_event_hold (&inev
, hold_quit
);
6944 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
6949 XSETFRAME (frame
, f
);
6955 any_help_event_p
= 1;
6956 gen_help_event (help_echo_string
, frame
, help_echo_window
,
6957 help_echo_object
, help_echo_pos
);
6961 help_echo_string
= Qnil
;
6962 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
6972 /* Handles the XEvent EVENT on display DISPLAY.
6973 This is used for event loops outside the normal event handling,
6974 i.e. looping while a popup menu or a dialog is posted.
6976 Returns the value handle_one_xevent sets in the finish argument. */
6978 x_dispatch_event (event
, display
)
6982 struct x_display_info
*dpyinfo
;
6983 int finish
= X_EVENT_NORMAL
;
6985 dpyinfo
= x_display_info_for_display (display
);
6988 handle_one_xevent (dpyinfo
, event
, &finish
, 0);
6994 /* Read events coming from the X server.
6995 This routine is called by the SIGIO handler.
6996 We return as soon as there are no more events to be read.
6998 We return the number of characters stored into the buffer,
6999 thus pretending to be `read'.
7001 EXPECTED is nonzero if the caller knows input is available. */
7004 XTread_socket (display
, expected
, hold_quit
)
7005 struct display
*display
;
7007 struct input_event
*hold_quit
;
7011 int event_found
= 0;
7012 struct x_display_info
*dpyinfo
;
7014 if (interrupt_input_blocked
)
7016 interrupt_input_pending
= 1;
7020 interrupt_input_pending
= 0;
7023 /* So people can tell when we have read the available input. */
7024 input_signal_count
++;
7028 /* Find the display we are supposed to read input for.
7029 It's the one communicating on descriptor SD. */
7030 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
7032 #if 0 /* This ought to be unnecessary; let's verify it. */
7034 /* If available, Xlib uses FIOSNBIO to make the socket
7035 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
7036 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
7037 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
7038 fcntl (dpyinfo
->connection
, F_SETFL
, 0);
7039 #endif /* ! defined (FIOSNBIO) */
7042 #if 0 /* This code can't be made to work, with multiple displays,
7043 and appears not to be used on any system any more.
7044 Also keyboard.c doesn't turn O_NDELAY on and off
7045 for X connections. */
7048 if (! (fcntl (dpyinfo
->connection
, F_GETFL
, 0) & O_NDELAY
))
7050 extern int read_alarm_should_throw
;
7051 read_alarm_should_throw
= 1;
7052 XPeekEvent (dpyinfo
->display
, &event
);
7053 read_alarm_should_throw
= 0;
7055 #endif /* HAVE_SELECT */
7059 /* For debugging, this gives a way to fake an I/O error. */
7060 if (dpyinfo
== XTread_socket_fake_io_error
)
7062 XTread_socket_fake_io_error
= 0;
7063 x_io_error_quitter (dpyinfo
->display
);
7068 struct input_event inev
;
7070 /* We don't need to EVENT_INIT (inev) here, as
7071 x_session_check_input copies an entire input_event. */
7072 if (x_session_check_input (&inev
))
7074 kbd_buffer_store_event_hold (&inev
, hold_quit
);
7082 while (XPending (dpyinfo
->display
))
7086 XNextEvent (dpyinfo
->display
, &event
);
7089 /* Filter events for the current X input method. */
7090 if (x_filter_event (dpyinfo
, &event
))
7095 count
+= handle_one_xevent (dpyinfo
, &event
, &finish
, hold_quit
);
7097 if (finish
== X_EVENT_GOTO_OUT
)
7100 #endif /* not USE_GTK */
7105 /* For GTK we must use the GTK event loop. But XEvents gets passed
7106 to our filter function above, and then to the big event switch.
7107 We use a bunch of globals to communicate with our filter function,
7108 that is kind of ugly, but it works.
7110 There is no way to do one display at the time, GTK just does events
7111 from all displays. */
7113 while (gtk_events_pending ())
7115 current_count
= count
;
7116 current_hold_quit
= hold_quit
;
7118 gtk_main_iteration ();
7120 count
= current_count
;
7122 current_hold_quit
= 0;
7124 if (current_finish
== X_EVENT_GOTO_OUT
)
7127 #endif /* USE_GTK */
7131 /* On some systems, an X bug causes Emacs to get no more events
7132 when the window is destroyed. Detect that. (1994.) */
7135 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
7136 One XNOOP in 100 loops will make Emacs terminate.
7137 B. Bretthauer, 1994 */
7139 if (x_noop_count
>= 100)
7143 if (next_noop_dpyinfo
== 0)
7144 next_noop_dpyinfo
= x_display_list
;
7146 XNoOp (next_noop_dpyinfo
->display
);
7148 /* Each time we get here, cycle through the displays now open. */
7149 next_noop_dpyinfo
= next_noop_dpyinfo
->next
;
7153 /* If the focus was just given to an auto-raising frame,
7155 /* ??? This ought to be able to handle more than one such frame. */
7156 if (pending_autoraise_frame
)
7158 x_raise_frame (pending_autoraise_frame
);
7159 pending_autoraise_frame
= 0;
7171 /***********************************************************************
7173 ***********************************************************************/
7175 /* Set clipping for output in glyph row ROW. W is the window in which
7176 we operate. GC is the graphics context to set clipping in.
7178 ROW may be a text row or, e.g., a mode line. Text rows must be
7179 clipped to the interior of the window dedicated to text display,
7180 mode lines must be clipped to the whole window. */
7183 x_clip_to_row (w
, row
, gc
)
7185 struct glyph_row
*row
;
7188 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
7189 XRectangle clip_rect
;
7190 int window_y
, window_width
;
7192 window_box (w
, -1, 0, &window_y
, &window_width
, 0);
7194 clip_rect
.x
= WINDOW_TO_FRAME_PIXEL_X (w
, 0);
7195 clip_rect
.y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
7196 clip_rect
.y
= max (clip_rect
.y
, window_y
);
7197 clip_rect
.width
= window_width
;
7198 clip_rect
.height
= row
->visible_height
;
7200 XSetClipRectangles (FRAME_X_DISPLAY (f
), gc
, 0, 0, &clip_rect
, 1, Unsorted
);
7204 /* Draw a hollow box cursor on window W in glyph row ROW. */
7207 x_draw_hollow_cursor (w
, row
)
7209 struct glyph_row
*row
;
7211 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
7212 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7213 Display
*dpy
= FRAME_X_DISPLAY (f
);
7216 struct glyph
*cursor_glyph
;
7219 /* Get the glyph the cursor is on. If we can't tell because
7220 the current matrix is invalid or such, give up. */
7221 cursor_glyph
= get_phys_cursor_glyph (w
);
7222 if (cursor_glyph
== NULL
)
7225 /* Compute the width of the rectangle to draw. If on a stretch
7226 glyph, and `x-stretch-block-cursor' is nil, don't draw a
7227 rectangle as wide as the glyph, but use a canonical character
7229 wd
= cursor_glyph
->pixel_width
- 1;
7230 if (cursor_glyph
->type
== STRETCH_GLYPH
7231 && !x_stretch_cursor_p
)
7232 wd
= min (FRAME_COLUMN_WIDTH (f
), wd
);
7233 w
->phys_cursor_width
= wd
;
7235 /* Compute frame-relative coordinates from window-relative
7237 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
7238 y
= WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
);
7240 /* Compute the proper height and ascent of the rectangle, based
7241 on the actual glyph. Using the full height of the row looks
7242 bad when there are tall images on that row. */
7243 h
= max (FRAME_LINE_HEIGHT (f
), cursor_glyph
->ascent
+ cursor_glyph
->descent
);
7244 if (h
< row
->height
)
7245 y
+= row
->ascent
/* - w->phys_cursor_ascent */ + cursor_glyph
->descent
- h
;
7248 /* The foreground of cursor_gc is typically the same as the normal
7249 background color, which can cause the cursor box to be invisible. */
7250 xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
7251 if (dpyinfo
->scratch_cursor_gc
)
7252 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
7254 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_X_WINDOW (f
),
7255 GCForeground
, &xgcv
);
7256 gc
= dpyinfo
->scratch_cursor_gc
;
7258 /* Set clipping, draw the rectangle, and reset clipping again. */
7259 x_clip_to_row (w
, row
, gc
);
7260 XDrawRectangle (dpy
, FRAME_X_WINDOW (f
), gc
, x
, y
, wd
, h
);
7261 XSetClipMask (dpy
, gc
, None
);
7265 /* Draw a bar cursor on window W in glyph row ROW.
7267 Implementation note: One would like to draw a bar cursor with an
7268 angle equal to the one given by the font property XA_ITALIC_ANGLE.
7269 Unfortunately, I didn't find a font yet that has this property set.
7273 x_draw_bar_cursor (w
, row
, width
, kind
)
7275 struct glyph_row
*row
;
7277 enum text_cursor_kinds kind
;
7279 struct frame
*f
= XFRAME (w
->frame
);
7280 struct glyph
*cursor_glyph
;
7282 /* If cursor is out of bounds, don't draw garbage. This can happen
7283 in mini-buffer windows when switching between echo area glyphs
7285 cursor_glyph
= get_phys_cursor_glyph (w
);
7286 if (cursor_glyph
== NULL
)
7289 /* If on an image, draw like a normal cursor. That's usually better
7290 visible than drawing a bar, esp. if the image is large so that
7291 the bar might not be in the window. */
7292 if (cursor_glyph
->type
== IMAGE_GLYPH
)
7294 struct glyph_row
*row
;
7295 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
7296 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
7300 Display
*dpy
= FRAME_X_DISPLAY (f
);
7301 Window window
= FRAME_X_WINDOW (f
);
7302 GC gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
7303 unsigned long mask
= GCForeground
| GCBackground
| GCGraphicsExposures
;
7304 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
7307 /* If the glyph's background equals the color we normally draw
7308 the bar cursor in, the bar cursor in its normal color is
7309 invisible. Use the glyph's foreground color instead in this
7310 case, on the assumption that the glyph's colors are chosen so
7311 that the glyph is legible. */
7312 if (face
->background
== f
->output_data
.x
->cursor_pixel
)
7313 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
7315 xgcv
.background
= xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
7316 xgcv
.graphics_exposures
= 0;
7319 XChangeGC (dpy
, gc
, mask
, &xgcv
);
7322 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
7323 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
7327 width
= FRAME_CURSOR_WIDTH (f
);
7328 width
= min (cursor_glyph
->pixel_width
, width
);
7330 w
->phys_cursor_width
= width
;
7331 x_clip_to_row (w
, row
, gc
);
7333 if (kind
== BAR_CURSOR
)
7334 XFillRectangle (dpy
, window
, gc
,
7335 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
7336 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
7337 width
, row
->height
);
7339 XFillRectangle (dpy
, window
, gc
,
7340 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
7341 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
7342 row
->height
- width
),
7343 cursor_glyph
->pixel_width
,
7346 XSetClipMask (dpy
, gc
, None
);
7351 /* RIF: Define cursor CURSOR on frame F. */
7354 x_define_frame_cursor (f
, cursor
)
7358 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), cursor
);
7362 /* RIF: Clear area on frame F. */
7365 x_clear_frame_area (f
, x
, y
, width
, height
)
7367 int x
, y
, width
, height
;
7369 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7370 x
, y
, width
, height
, False
);
7374 /* RIF: Draw cursor on window W. */
7377 x_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
7379 struct glyph_row
*glyph_row
;
7381 int cursor_type
, cursor_width
;
7384 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
7388 w
->phys_cursor_type
= cursor_type
;
7389 w
->phys_cursor_on_p
= 1;
7391 if (glyph_row
->exact_window_width_line_p
7392 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
7394 glyph_row
->cursor_in_fringe_p
= 1;
7395 draw_fringe_bitmap (w
, glyph_row
, 0);
7398 switch (cursor_type
)
7400 case HOLLOW_BOX_CURSOR
:
7401 x_draw_hollow_cursor (w
, glyph_row
);
7404 case FILLED_BOX_CURSOR
:
7405 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
7409 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
7413 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
7417 w
->phys_cursor_width
= 0;
7425 if (w
== XWINDOW (f
->selected_window
))
7426 if (FRAME_XIC (f
) && (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
))
7427 xic_set_preeditarea (w
, x
, y
);
7432 if (updating_frame
!= f
)
7433 XFlush (FRAME_X_DISPLAY (f
));
7440 /* Make the x-window of frame F use the gnu icon bitmap. */
7443 x_bitmap_icon (f
, file
)
7449 if (FRAME_X_WINDOW (f
) == 0)
7452 /* Free up our existing icon bitmap and mask if any. */
7453 if (f
->output_data
.x
->icon_bitmap
> 0)
7454 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
7455 f
->output_data
.x
->icon_bitmap
= 0;
7460 /* Use gtk_window_set_icon_from_file () if available,
7461 It's not restricted to bitmaps */
7462 if (xg_set_icon (f
, file
))
7464 #endif /* USE_GTK */
7465 bitmap_id
= x_create_bitmap_from_file (f
, file
);
7466 x_create_bitmap_mask (f
, bitmap_id
);
7470 /* Create the GNU bitmap and mask if necessary. */
7471 if (FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
7473 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
7474 = x_create_bitmap_from_data (f
, gnu_bits
,
7475 gnu_width
, gnu_height
);
7476 x_create_bitmap_mask (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
7479 /* The first time we create the GNU bitmap and mask,
7480 this increments the ref-count one extra time.
7481 As a result, the GNU bitmap and mask are never freed.
7482 That way, we don't have to worry about allocating it again. */
7483 x_reference_bitmap (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
7485 bitmap_id
= FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
;
7488 x_wm_set_icon_pixmap (f
, bitmap_id
);
7489 f
->output_data
.x
->icon_bitmap
= bitmap_id
;
7495 /* Make the x-window of frame F use a rectangle with text.
7496 Use ICON_NAME as the text. */
7499 x_text_icon (f
, icon_name
)
7503 if (FRAME_X_WINDOW (f
) == 0)
7509 text
.value
= (unsigned char *) icon_name
;
7510 text
.encoding
= XA_STRING
;
7512 text
.nitems
= strlen (icon_name
);
7513 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
), &text
);
7515 #else /* not HAVE_X11R4 */
7516 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
), icon_name
);
7517 #endif /* not HAVE_X11R4 */
7519 if (f
->output_data
.x
->icon_bitmap
> 0)
7520 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
7521 f
->output_data
.x
->icon_bitmap
= 0;
7522 x_wm_set_icon_pixmap (f
, 0);
7527 #define X_ERROR_MESSAGE_SIZE 200
7529 /* If non-nil, this should be a string.
7530 It means catch X errors and store the error message in this string. */
7532 static Lisp_Object x_error_message_string
;
7534 /* An X error handler which stores the error message in
7535 x_error_message_string. This is called from x_error_handler if
7536 x_catch_errors is in effect. */
7539 x_error_catcher (display
, error
)
7543 XGetErrorText (display
, error
->error_code
,
7544 SDATA (x_error_message_string
),
7545 X_ERROR_MESSAGE_SIZE
);
7548 /* Begin trapping X errors for display DPY. Actually we trap X errors
7549 for all displays, but DPY should be the display you are actually
7552 After calling this function, X protocol errors no longer cause
7553 Emacs to exit; instead, they are recorded in the string
7554 stored in x_error_message_string.
7556 Calling x_check_errors signals an Emacs error if an X error has
7557 occurred since the last call to x_catch_errors or x_check_errors.
7559 Calling x_uncatch_errors resumes the normal error handling. */
7561 void x_check_errors ();
7562 static Lisp_Object
x_catch_errors_unwind ();
7565 x_catch_errors (dpy
)
7568 int count
= SPECPDL_INDEX ();
7570 /* Make sure any errors from previous requests have been dealt with. */
7573 record_unwind_protect (x_catch_errors_unwind
,
7574 Fcons (make_save_value (dpy
, 0),
7575 x_error_message_string
));
7577 x_error_message_string
= make_uninit_string (X_ERROR_MESSAGE_SIZE
);
7578 SSET (x_error_message_string
, 0, 0);
7583 /* Unbind the binding that we made to check for X errors. */
7586 x_catch_errors_unwind (old_val
)
7587 Lisp_Object old_val
;
7591 first
= XCAR (old_val
);
7593 #if 0 /* XXX This has dumped core on me several times when my X
7594 server crashed. If this call is important, maybe we should
7595 check that the display is still alive. -- lorentey */
7596 XSync (XSAVE_VALUE (first
)->pointer
, False
);
7599 x_error_message_string
= XCDR (old_val
);
7603 /* If any X protocol errors have arrived since the last call to
7604 x_catch_errors or x_check_errors, signal an Emacs error using
7605 sprintf (a buffer, FORMAT, the x error message text) as the text. */
7608 x_check_errors (dpy
, format
)
7612 /* Make sure to catch any errors incurred so far. */
7615 if (SREF (x_error_message_string
, 0))
7616 error (format
, SDATA (x_error_message_string
));
7619 /* Nonzero if we had any X protocol errors
7620 since we did x_catch_errors on DPY. */
7623 x_had_errors_p (dpy
)
7626 /* Make sure to catch any errors incurred so far. */
7629 return SREF (x_error_message_string
, 0) != 0;
7632 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
7635 x_clear_errors (dpy
)
7638 SSET (x_error_message_string
, 0, 0);
7641 /* Stop catching X protocol errors and let them make Emacs die.
7642 DPY should be the display that was passed to x_catch_errors.
7643 COUNT should be the value that was returned by
7644 the corresponding call to x_catch_errors. */
7647 x_uncatch_errors (dpy
, count
)
7651 unbind_to (count
, Qnil
);
7655 static unsigned int x_wire_count
;
7658 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
7663 /* Handle SIGPIPE, which can happen when the connection to a server
7664 simply goes away. SIGPIPE is handled by x_connection_signal.
7665 Don't need to do anything, because the write which caused the
7666 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
7667 which will do the appropriate cleanup for us. */
7670 x_connection_signal (signalnum
) /* If we don't have an argument, */
7671 int signalnum
; /* some compilers complain in signal calls. */
7674 /* USG systems forget handlers when they are used;
7675 must reestablish each time */
7676 signal (signalnum
, x_connection_signal
);
7681 /************************************************************************
7683 ************************************************************************/
7685 /* Error message passed to x_connection_closed. */
7687 static char *error_msg
;
7689 /* Function installed as fatal_error_signal_hook in
7690 x_connection_closed. Print the X error message, and exit normally,
7691 instead of dumping core when XtCloseDisplay fails. */
7694 x_fatal_error_signal ()
7696 fprintf (stderr
, "%s\n", error_msg
);
7700 /* Handle the loss of connection to display DPY. ERROR_MESSAGE is
7701 the text of an error message that lead to the connection loss. */
7704 x_connection_closed (dpy
, error_message
)
7706 char *error_message
;
7708 struct x_display_info
*dpyinfo
= x_display_info_for_display (dpy
);
7709 Lisp_Object frame
, tail
;
7712 error_msg
= (char *) alloca (strlen (error_message
) + 1);
7713 strcpy (error_msg
, error_message
);
7714 handling_signal
= 0;
7716 /* Prevent being called recursively because of an error condition
7717 below. Otherwise, we might end up with printing ``can't find per
7718 display information'' in the recursive call instead of printing
7719 the original message here. */
7720 count
= x_catch_errors (dpy
);
7722 /* We have to close the display to inform Xt that it doesn't
7723 exist anymore. If we don't, Xt will continue to wait for
7724 events from the display. As a consequence, a sequence of
7726 M-x make-frame-on-display RET :1 RET
7727 ...kill the new frame, so that we get an IO error...
7728 M-x make-frame-on-display RET :1 RET
7730 will indefinitely wait in Xt for events for display `:1', opened
7731 in the first class to make-frame-on-display.
7733 Closing the display is reported to lead to a bus error on
7734 OpenWindows in certain situations. I suspect that is a bug
7735 in OpenWindows. I don't know how to cicumvent it here. */
7737 #ifdef USE_X_TOOLKIT
7738 /* If DPYINFO is null, this means we didn't open the display
7739 in the first place, so don't try to close it. */
7742 extern void (*fatal_error_signal_hook
) P_ ((void));
7743 fatal_error_signal_hook
= x_fatal_error_signal
;
7744 XtCloseDisplay (dpy
);
7745 fatal_error_signal_hook
= NULL
;
7751 xg_display_close (dpyinfo
->display
);
7754 /* Indicate that this display is dead. */
7756 dpyinfo
->display
= 0;
7758 /* First delete frames whose mini-buffers are on frames
7759 that are on the dead display. */
7760 FOR_EACH_FRAME (tail
, frame
)
7762 Lisp_Object minibuf_frame
;
7764 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
7765 if (FRAME_X_P (XFRAME (frame
))
7766 && FRAME_X_P (XFRAME (minibuf_frame
))
7767 && ! EQ (frame
, minibuf_frame
)
7768 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame
)) == dpyinfo
)
7769 Fdelete_frame (frame
, Qt
);
7772 /* Now delete all remaining frames on the dead display.
7773 We are now sure none of these is used as the mini-buffer
7774 for another frame that we need to delete. */
7775 FOR_EACH_FRAME (tail
, frame
)
7776 if (FRAME_X_P (XFRAME (frame
))
7777 && FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
7779 /* Set this to t so that Fdelete_frame won't get confused
7780 trying to find a replacement. */
7781 FRAME_KBOARD (XFRAME (frame
))->Vdefault_minibuffer_frame
= Qt
;
7782 Fdelete_frame (frame
, Qt
);
7786 x_delete_display (dpyinfo
);
7788 x_uncatch_errors (dpy
, count
);
7790 if (display_list
== 0)
7792 fprintf (stderr
, "%s\n", error_msg
);
7793 shut_down_emacs (0, 0, Qnil
);
7797 /* Ordinary stack unwind doesn't deal with these. */
7799 sigunblock (sigmask (SIGIO
));
7801 sigunblock (sigmask (SIGALRM
));
7802 TOTALLY_UNBLOCK_INPUT
;
7804 clear_waiting_for_input ();
7805 error ("%s", error_msg
);
7809 /* This is the usual handler for X protocol errors.
7810 It kills all frames on the display that we got the error for.
7811 If that was the only one, it prints an error message and kills Emacs. */
7814 x_error_quitter (display
, error
)
7818 char buf
[256], buf1
[356];
7820 /* Note that there is no real way portable across R3/R4 to get the
7821 original error handler. */
7823 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
7824 sprintf (buf1
, "X protocol error: %s on protocol request %d",
7825 buf
, error
->request_code
);
7826 x_connection_closed (display
, buf1
);
7830 /* This is the first-level handler for X protocol errors.
7831 It calls x_error_quitter or x_error_catcher. */
7834 x_error_handler (display
, error
)
7838 if (! NILP (x_error_message_string
))
7839 x_error_catcher (display
, error
);
7841 x_error_quitter (display
, error
);
7845 /* This is the handler for X IO errors, always.
7846 It kills all frames on the display that we lost touch with.
7847 If that was the only one, it prints an error message and kills Emacs. */
7850 x_io_error_quitter (display
)
7855 sprintf (buf
, "Connection lost to X server `%s'", DisplayString (display
));
7856 x_connection_closed (display
, buf
);
7860 /* Changing the font of the frame. */
7862 /* Give frame F the font named FONTNAME as its default font, and
7863 return the full name of that font. FONTNAME may be a wildcard
7864 pattern; in that case, we choose some font that fits the pattern.
7865 The return value shows which font we chose. */
7868 x_new_font (f
, fontname
)
7870 register char *fontname
;
7872 struct font_info
*fontp
7873 = FS_LOAD_FONT (f
, 0, fontname
, -1);
7878 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
7879 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
7880 FRAME_FONTSET (f
) = -1;
7882 FRAME_COLUMN_WIDTH (f
) = FONT_WIDTH (FRAME_FONT (f
));
7883 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
7885 compute_fringe_widths (f
, 1);
7887 /* Compute the scroll bar width in character columns. */
7888 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
7890 int wid
= FRAME_COLUMN_WIDTH (f
);
7891 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
7892 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
7896 int wid
= FRAME_COLUMN_WIDTH (f
);
7897 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
7900 /* Now make the frame display the given font. */
7901 if (FRAME_X_WINDOW (f
) != 0)
7903 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
7904 FRAME_FONT (f
)->fid
);
7905 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
7906 FRAME_FONT (f
)->fid
);
7907 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
7908 FRAME_FONT (f
)->fid
);
7910 /* Don't change the size of a tip frame; there's no point in
7911 doing it because it's done in Fx_show_tip, and it leads to
7912 problems because the tip frame has no widget. */
7913 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
7914 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
7917 return build_string (fontp
->full_name
);
7920 /* Give frame F the fontset named FONTSETNAME as its default font, and
7921 return the full name of that fontset. FONTSETNAME may be a wildcard
7922 pattern; in that case, we choose some fontset that fits the pattern.
7923 The return value shows which fontset we chose. */
7926 x_new_fontset (f
, fontsetname
)
7930 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
7936 if (FRAME_FONTSET (f
) == fontset
)
7937 /* This fontset is already set in frame F. There's nothing more
7939 return fontset_name (fontset
);
7941 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
7943 if (!STRINGP (result
))
7944 /* Can't load ASCII font. */
7947 /* Since x_new_font doesn't update any fontset information, do it now. */
7948 FRAME_FONTSET (f
) = fontset
;
7952 && (FRAME_XIC_STYLE (f
) & (XIMPreeditPosition
| XIMStatusArea
)))
7953 xic_set_xfontset (f
, SDATA (fontset_ascii (fontset
)));
7956 return build_string (fontsetname
);
7960 /***********************************************************************
7962 ***********************************************************************/
7968 /* XIM destroy callback function, which is called whenever the
7969 connection to input method XIM dies. CLIENT_DATA contains a
7970 pointer to the x_display_info structure corresponding to XIM. */
7973 xim_destroy_callback (xim
, client_data
, call_data
)
7975 XPointer client_data
;
7978 struct x_display_info
*dpyinfo
= (struct x_display_info
*) client_data
;
7979 Lisp_Object frame
, tail
;
7983 /* No need to call XDestroyIC.. */
7984 FOR_EACH_FRAME (tail
, frame
)
7986 struct frame
*f
= XFRAME (frame
);
7987 if (FRAME_X_P (f
) && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
)
7989 FRAME_XIC (f
) = NULL
;
7990 if (FRAME_XIC_FONTSET (f
))
7992 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
7993 FRAME_XIC_FONTSET (f
) = NULL
;
7998 /* No need to call XCloseIM. */
7999 dpyinfo
->xim
= NULL
;
8000 XFree (dpyinfo
->xim_styles
);
8004 #endif /* HAVE_X11R6 */
8007 /* This isn't prototyped in OSF 5.0 or 5.1a. */
8008 extern char *XSetIMValues
P_ ((XIM
, ...));
8011 /* Open the connection to the XIM server on display DPYINFO.
8012 RESOURCE_NAME is the resource name Emacs uses. */
8015 xim_open_dpy (dpyinfo
, resource_name
)
8016 struct x_display_info
*dpyinfo
;
8017 char *resource_name
;
8024 xim
= XOpenIM (dpyinfo
->display
, dpyinfo
->xrdb
, resource_name
,
8031 XIMCallback destroy
;
8034 /* Get supported styles and XIM values. */
8035 XGetIMValues (xim
, XNQueryInputStyle
, &dpyinfo
->xim_styles
, NULL
);
8038 destroy
.callback
= xim_destroy_callback
;
8039 destroy
.client_data
= (XPointer
)dpyinfo
;
8040 XSetIMValues (xim
, XNDestroyCallback
, &destroy
, NULL
);
8046 #endif /* HAVE_XIM */
8047 dpyinfo
->xim
= NULL
;
8051 #ifdef HAVE_X11R6_XIM
8055 struct x_display_info
*dpyinfo
;
8056 char *resource_name
;
8059 /* XIM instantiate callback function, which is called whenever an XIM
8060 server is available. DISPLAY is the display of the XIM.
8061 CLIENT_DATA contains a pointer to an xim_inst_t structure created
8062 when the callback was registered. */
8065 xim_instantiate_callback (display
, client_data
, call_data
)
8067 XPointer client_data
;
8070 struct xim_inst_t
*xim_inst
= (struct xim_inst_t
*) client_data
;
8071 struct x_display_info
*dpyinfo
= xim_inst
->dpyinfo
;
8073 /* We don't support multiple XIM connections. */
8077 xim_open_dpy (dpyinfo
, xim_inst
->resource_name
);
8079 /* Create XIC for the existing frames on the same display, as long
8080 as they have no XIC. */
8081 if (dpyinfo
->xim
&& dpyinfo
->reference_count
> 0)
8083 Lisp_Object tail
, frame
;
8086 FOR_EACH_FRAME (tail
, frame
)
8088 struct frame
*f
= XFRAME (frame
);
8091 && FRAME_X_DISPLAY_INFO (f
) == xim_inst
->dpyinfo
)
8092 if (FRAME_XIC (f
) == NULL
)
8094 create_frame_xic (f
);
8095 if (FRAME_XIC_STYLE (f
) & XIMStatusArea
)
8096 xic_set_statusarea (f
);
8097 if (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
)
8099 struct window
*w
= XWINDOW (f
->selected_window
);
8100 xic_set_preeditarea (w
, w
->cursor
.x
, w
->cursor
.y
);
8109 #endif /* HAVE_X11R6_XIM */
8112 /* Open a connection to the XIM server on display DPYINFO.
8113 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
8114 connection only at the first time. On X11R6, open the connection
8115 in the XIM instantiate callback function. */
8118 xim_initialize (dpyinfo
, resource_name
)
8119 struct x_display_info
*dpyinfo
;
8120 char *resource_name
;
8125 #ifdef HAVE_X11R6_XIM
8126 struct xim_inst_t
*xim_inst
;
8129 dpyinfo
->xim
= NULL
;
8130 xim_inst
= (struct xim_inst_t
*) xmalloc (sizeof (struct xim_inst_t
));
8131 xim_inst
->dpyinfo
= dpyinfo
;
8132 len
= strlen (resource_name
);
8133 xim_inst
->resource_name
= (char *) xmalloc (len
+ 1);
8134 bcopy (resource_name
, xim_inst
->resource_name
, len
+ 1);
8135 XRegisterIMInstantiateCallback (dpyinfo
->display
, dpyinfo
->xrdb
,
8136 resource_name
, EMACS_CLASS
,
8137 xim_instantiate_callback
,
8138 /* This is XPointer in XFree86
8139 but (XPointer *) on Tru64, at
8140 least, hence the configure test. */
8141 (XRegisterIMInstantiateCallback_arg6
) xim_inst
);
8142 #else /* not HAVE_X11R6_XIM */
8143 dpyinfo
->xim
= NULL
;
8144 xim_open_dpy (dpyinfo
, resource_name
);
8145 #endif /* not HAVE_X11R6_XIM */
8149 #endif /* HAVE_XIM */
8150 dpyinfo
->xim
= NULL
;
8154 /* Close the connection to the XIM server on display DPYINFO. */
8157 xim_close_dpy (dpyinfo
)
8158 struct x_display_info
*dpyinfo
;
8163 #ifdef HAVE_X11R6_XIM
8164 if (dpyinfo
->display
)
8165 XUnregisterIMInstantiateCallback (dpyinfo
->display
, dpyinfo
->xrdb
,
8167 xim_instantiate_callback
, NULL
);
8168 #endif /* not HAVE_X11R6_XIM */
8169 if (dpyinfo
->display
)
8170 XCloseIM (dpyinfo
->xim
);
8171 dpyinfo
->xim
= NULL
;
8172 XFree (dpyinfo
->xim_styles
);
8174 #endif /* HAVE_XIM */
8177 #endif /* not HAVE_X11R6_XIM */
8181 /* Calculate the absolute position in frame F
8182 from its current recorded position values and gravity. */
8185 x_calc_absolute_position (f
)
8188 int win_x
= 0, win_y
= 0;
8189 int flags
= f
->size_hint_flags
;
8191 /* We have nothing to do if the current position
8192 is already for the top-left corner. */
8193 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
8196 /* Find the offsets of the outside upper-left corner of
8197 the inner window, with respect to the outer window.
8198 But do this only if we will need the results. */
8199 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
8200 /* This is to get *_pixels_outer_diff. */
8201 x_real_positions (f
, &win_x
, &win_y
);
8203 /* Treat negative positions as relative to the leftmost bottommost
8204 position that fits on the screen. */
8205 if (flags
& XNegative
)
8206 f
->left_pos
= (FRAME_X_DISPLAY_INFO (f
)->width
8207 - 2 * FRAME_X_OUTPUT (f
)->x_pixels_outer_diff
8208 - FRAME_PIXEL_WIDTH (f
)
8212 int height
= FRAME_PIXEL_HEIGHT (f
);
8214 #if defined USE_X_TOOLKIT && defined USE_MOTIF
8215 /* Something is fishy here. When using Motif, starting Emacs with
8216 `-g -0-0', the frame appears too low by a few pixels.
8218 This seems to be so because initially, while Emacs is starting,
8219 the column widget's height and the frame's pixel height are
8220 different. The column widget's height is the right one. In
8221 later invocations, when Emacs is up, the frame's pixel height
8224 It's not obvious where the initial small difference comes from.
8225 2000-12-01, gerd. */
8227 XtVaGetValues (f
->output_data
.x
->column_widget
, XtNheight
, &height
, NULL
);
8230 if (flags
& YNegative
)
8231 f
->top_pos
= (FRAME_X_DISPLAY_INFO (f
)->height
8232 - FRAME_X_OUTPUT (f
)->y_pixels_outer_diff
8234 /* Assume the window manager decorations are the same size on
8235 three sides, i.e. left, right and bottom. This is to
8236 compensate for the bottom part. */
8237 - FRAME_X_OUTPUT (f
)->x_pixels_outer_diff
8242 /* The left_pos and top_pos
8243 are now relative to the top and left screen edges,
8244 so the flags should correspond. */
8245 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
8248 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
8249 to really change the position, and 0 when calling from
8250 x_make_frame_visible (in that case, XOFF and YOFF are the current
8251 position values). It is -1 when calling from x_set_frame_parameters,
8252 which means, do adjust for borders but don't change the gravity. */
8255 x_set_offset (f
, xoff
, yoff
, change_gravity
)
8257 register int xoff
, yoff
;
8260 int modified_top
, modified_left
;
8262 if (change_gravity
> 0)
8266 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
8268 f
->size_hint_flags
|= XNegative
;
8270 f
->size_hint_flags
|= YNegative
;
8271 f
->win_gravity
= NorthWestGravity
;
8273 x_calc_absolute_position (f
);
8276 x_wm_set_size_hint (f
, (long) 0, 0);
8278 modified_left
= f
->left_pos
;
8279 modified_top
= f
->top_pos
;
8281 if (FRAME_X_DISPLAY_INFO (f
)->wm_type
== X_WMTYPE_A
)
8283 /* Some WMs (twm, wmaker at least) has an offset that is smaller
8284 than the WM decorations. So we use the calculated offset instead
8285 of the WM decoration sizes here (x/y_pixels_outer_diff). */
8286 modified_left
+= FRAME_X_OUTPUT (f
)->move_offset_left
;
8287 modified_top
+= FRAME_X_OUTPUT (f
)->move_offset_top
;
8290 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
8291 modified_left
, modified_top
);
8293 if (FRAME_VISIBLE_P (f
)
8294 && FRAME_X_DISPLAY_INFO (f
)->wm_type
== X_WMTYPE_UNKNOWN
)
8296 FRAME_X_OUTPUT (f
)->check_expected_move
= 1;
8297 FRAME_X_OUTPUT (f
)->expected_top
= f
->top_pos
;
8298 FRAME_X_OUTPUT (f
)->expected_left
= f
->left_pos
;
8304 /* Check if we need to resize the frame due to a fullscreen request.
8305 If so needed, resize the frame. */
8307 x_check_fullscreen (f
)
8310 if (f
->want_fullscreen
& FULLSCREEN_BOTH
)
8312 int width
, height
, ign
;
8314 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
8316 x_fullscreen_adjust (f
, &width
, &height
, &ign
, &ign
);
8318 /* We do not need to move the window, it shall be taken care of
8319 when setting WM manager hints.
8320 If the frame is visible already, the position is checked by
8321 x_check_expected_move. */
8322 if (FRAME_COLS (f
) != width
|| FRAME_LINES (f
) != height
)
8324 change_frame_size (f
, height
, width
, 0, 1, 0);
8325 SET_FRAME_GARBAGED (f
);
8326 cancel_mouse_face (f
);
8328 /* Wait for the change of frame size to occur */
8329 f
->want_fullscreen
|= FULLSCREEN_WAIT
;
8334 /* If frame parameters are set after the frame is mapped, we need to move
8336 Some window managers moves the window to the right position, some
8337 moves the outer window manager window to the specified position.
8338 Here we check that we are in the right spot. If not, make a second
8339 move, assuming we are dealing with the second kind of window manager. */
8341 x_check_expected_move (f
)
8344 if (FRAME_X_OUTPUT (f
)->check_expected_move
)
8346 int expect_top
= FRAME_X_OUTPUT (f
)->expected_top
;
8347 int expect_left
= FRAME_X_OUTPUT (f
)->expected_left
;
8349 if (expect_top
!= f
->top_pos
|| expect_left
!= f
->left_pos
)
8351 FRAME_X_DISPLAY_INFO (f
)->wm_type
= X_WMTYPE_A
;
8352 FRAME_X_OUTPUT (f
)->move_offset_left
= expect_left
- f
->left_pos
;
8353 FRAME_X_OUTPUT (f
)->move_offset_top
= expect_top
- f
->top_pos
;
8355 x_set_offset (f
, expect_left
, expect_top
, 1);
8357 else if (FRAME_X_DISPLAY_INFO (f
)->wm_type
== X_WMTYPE_UNKNOWN
)
8358 FRAME_X_DISPLAY_INFO (f
)->wm_type
= X_WMTYPE_B
;
8360 /* Just do this once */
8361 FRAME_X_OUTPUT (f
)->check_expected_move
= 0;
8366 /* Change the size of frame F's X window to COLS/ROWS in the case F
8367 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
8368 top-left-corner window gravity for this size change and subsequent
8369 size changes. Otherwise we leave the window gravity unchanged. */
8372 x_set_window_size_1 (f
, change_gravity
, cols
, rows
)
8377 int pixelwidth
, pixelheight
;
8379 check_frame_size (f
, &rows
, &cols
);
8380 f
->scroll_bar_actual_width
8381 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
8383 : FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0
8384 ? FRAME_CONFIG_SCROLL_BAR_WIDTH (f
)
8385 : (FRAME_CONFIG_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
)));
8387 compute_fringe_widths (f
, 0);
8389 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
8390 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
8392 f
->win_gravity
= NorthWestGravity
;
8393 x_wm_set_size_hint (f
, (long) 0, 0);
8395 XSync (FRAME_X_DISPLAY (f
), False
);
8396 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8397 pixelwidth
, pixelheight
);
8399 /* Now, strictly speaking, we can't be sure that this is accurate,
8400 but the window manager will get around to dealing with the size
8401 change request eventually, and we'll hear how it went when the
8402 ConfigureNotify event gets here.
8404 We could just not bother storing any of this information here,
8405 and let the ConfigureNotify event set everything up, but that
8406 might be kind of confusing to the Lisp code, since size changes
8407 wouldn't be reported in the frame parameters until some random
8408 point in the future when the ConfigureNotify event arrives.
8410 We pass 1 for DELAY since we can't run Lisp code inside of
8412 change_frame_size (f
, rows
, cols
, 0, 1, 0);
8413 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
8414 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
8416 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
8417 receive in the ConfigureNotify event; if we get what we asked
8418 for, then the event won't cause the screen to become garbaged, so
8419 we have to make sure to do it here. */
8420 SET_FRAME_GARBAGED (f
);
8422 XFlush (FRAME_X_DISPLAY (f
));
8426 /* Call this to change the size of frame F's x-window.
8427 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
8428 for this size change and subsequent size changes.
8429 Otherwise we leave the window gravity unchanged. */
8432 x_set_window_size (f
, change_gravity
, cols
, rows
)
8440 if (FRAME_GTK_WIDGET (f
))
8441 xg_frame_set_char_size (f
, cols
, rows
);
8443 x_set_window_size_1 (f
, change_gravity
, cols
, rows
);
8446 if (f
->output_data
.x
->widget
!= NULL
)
8448 /* The x and y position of the widget is clobbered by the
8449 call to XtSetValues within EmacsFrameSetCharSize.
8450 This is a real kludge, but I don't understand Xt so I can't
8451 figure out a correct fix. Can anyone else tell me? -- rms. */
8452 int xpos
= f
->output_data
.x
->widget
->core
.x
;
8453 int ypos
= f
->output_data
.x
->widget
->core
.y
;
8454 EmacsFrameSetCharSize (f
->output_data
.x
->edit_widget
, cols
, rows
);
8455 f
->output_data
.x
->widget
->core
.x
= xpos
;
8456 f
->output_data
.x
->widget
->core
.y
= ypos
;
8459 x_set_window_size_1 (f
, change_gravity
, cols
, rows
);
8461 #else /* not USE_X_TOOLKIT */
8463 x_set_window_size_1 (f
, change_gravity
, cols
, rows
);
8465 #endif /* not USE_X_TOOLKIT */
8467 /* If cursor was outside the new size, mark it as off. */
8468 mark_window_cursors_off (XWINDOW (f
->root_window
));
8470 /* Clear out any recollection of where the mouse highlighting was,
8471 since it might be in a place that's outside the new frame size.
8472 Actually checking whether it is outside is a pain in the neck,
8473 so don't try--just let the highlighting be done afresh with new size. */
8474 cancel_mouse_face (f
);
8479 /* Mouse warping. */
8482 x_set_mouse_position (f
, x
, y
)
8488 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
8489 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
8491 if (pix_x
< 0) pix_x
= 0;
8492 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
8494 if (pix_y
< 0) pix_y
= 0;
8495 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
8499 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
8500 0, 0, 0, 0, pix_x
, pix_y
);
8504 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
8507 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
8513 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
8514 0, 0, 0, 0, pix_x
, pix_y
);
8518 /* focus shifting, raising and lowering. */
8521 x_focus_on_frame (f
)
8524 #if 0 /* This proves to be unpleasant. */
8528 /* I don't think that the ICCCM allows programs to do things like this
8529 without the interaction of the window manager. Whatever you end up
8530 doing with this code, do it to x_unfocus_frame too. */
8531 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8532 RevertToPointerRoot
, CurrentTime
);
8541 /* Look at the remarks in x_focus_on_frame. */
8542 if (FRAME_X_DISPLAY_INFO (f
)->x_focus_frame
== f
)
8543 XSetInputFocus (FRAME_X_DISPLAY (f
), PointerRoot
,
8544 RevertToPointerRoot
, CurrentTime
);
8548 /* Raise frame F. */
8554 if (f
->async_visible
)
8557 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
));
8558 XFlush (FRAME_X_DISPLAY (f
));
8563 /* Lower frame F. */
8569 if (f
->async_visible
)
8572 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
));
8573 XFlush (FRAME_X_DISPLAY (f
));
8579 XTframe_raise_lower (f
, raise_flag
)
8589 /* Change of visibility. */
8591 /* This tries to wait until the frame is really visible.
8592 However, if the window manager asks the user where to position
8593 the frame, this will return before the user finishes doing that.
8594 The frame will not actually be visible at that time,
8595 but it will become visible later when the window manager
8596 finishes with it. */
8599 x_make_frame_visible (f
)
8603 int original_top
, original_left
;
8604 int retry_count
= 2;
8610 type
= x_icon_type (f
);
8612 x_bitmap_icon (f
, type
);
8614 if (! FRAME_VISIBLE_P (f
))
8616 /* We test FRAME_GARBAGED_P here to make sure we don't
8617 call x_set_offset a second time
8618 if we get to x_make_frame_visible a second time
8619 before the window gets really visible. */
8620 if (! FRAME_ICONIFIED_P (f
)
8621 && ! f
->output_data
.x
->asked_for_visible
)
8622 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
8624 f
->output_data
.x
->asked_for_visible
= 1;
8626 if (! EQ (Vx_no_window_manager
, Qt
))
8627 x_wm_set_window_state (f
, NormalState
);
8628 #ifdef USE_X_TOOLKIT
8629 /* This was XtPopup, but that did nothing for an iconified frame. */
8630 XtMapWidget (f
->output_data
.x
->widget
);
8631 #else /* not USE_X_TOOLKIT */
8633 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f
));
8634 gtk_window_deiconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f
)));
8636 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
8637 #endif /* not USE_GTK */
8638 #endif /* not USE_X_TOOLKIT */
8639 #if 0 /* This seems to bring back scroll bars in the wrong places
8640 if the window configuration has changed. They seem
8641 to come back ok without this. */
8642 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
8643 XMapSubwindows (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
8647 XFlush (FRAME_X_DISPLAY (f
));
8649 /* Synchronize to ensure Emacs knows the frame is visible
8650 before we do anything else. We do this loop with input not blocked
8651 so that incoming events are handled. */
8655 /* This must be before UNBLOCK_INPUT
8656 since events that arrive in response to the actions above
8657 will set it when they are handled. */
8658 int previously_visible
= f
->output_data
.x
->has_been_visible
;
8660 original_left
= f
->left_pos
;
8661 original_top
= f
->top_pos
;
8663 /* This must come after we set COUNT. */
8666 /* We unblock here so that arriving X events are processed. */
8668 /* Now move the window back to where it was "supposed to be".
8669 But don't do it if the gravity is negative.
8670 When the gravity is negative, this uses a position
8671 that is 3 pixels too low. Perhaps that's really the border width.
8673 Don't do this if the window has never been visible before,
8674 because the window manager may choose the position
8675 and we don't want to override it. */
8677 if (! FRAME_VISIBLE_P (f
) && ! FRAME_ICONIFIED_P (f
)
8678 && f
->win_gravity
== NorthWestGravity
8679 && previously_visible
)
8683 unsigned int width
, height
, border
, depth
;
8687 /* On some window managers (such as FVWM) moving an existing
8688 window, even to the same place, causes the window manager
8689 to introduce an offset. This can cause the window to move
8690 to an unexpected location. Check the geometry (a little
8691 slow here) and then verify that the window is in the right
8692 place. If the window is not in the right place, move it
8693 there, and take the potential window manager hit. */
8694 XGetGeometry (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
8695 &rootw
, &x
, &y
, &width
, &height
, &border
, &depth
);
8697 if (original_left
!= x
|| original_top
!= y
)
8698 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
8699 original_left
, original_top
);
8704 XSETFRAME (frame
, f
);
8706 /* Wait until the frame is visible. Process X events until a
8707 MapNotify event has been seen, or until we think we won't get a
8708 MapNotify at all.. */
8709 for (count
= input_signal_count
+ 10;
8710 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
8712 /* Force processing of queued events. */
8715 /* Machines that do polling rather than SIGIO have been
8716 observed to go into a busy-wait here. So we'll fake an
8717 alarm signal to let the handler know that there's something
8718 to be read. We used to raise a real alarm, but it seems
8719 that the handler isn't always enabled here. This is
8721 if (input_polling_used ())
8723 /* It could be confusing if a real alarm arrives while
8724 processing the fake one. Turn it off and let the
8725 handler reset it. */
8726 extern void poll_for_input_1
P_ ((void));
8727 int old_poll_suppress_count
= poll_suppress_count
;
8728 poll_suppress_count
= 1;
8729 poll_for_input_1 ();
8730 poll_suppress_count
= old_poll_suppress_count
;
8733 /* See if a MapNotify event has been processed. */
8734 FRAME_SAMPLE_VISIBILITY (f
);
8739 (let ((f (selected-frame)))
8743 the frame is not raised with various window managers on
8744 FreeBSD, GNU/Linux and Solaris. It turns out that, for some
8745 unknown reason, the call to XtMapWidget is completely ignored.
8746 Mapping the widget a second time works. */
8748 if (!FRAME_VISIBLE_P (f
) && --retry_count
> 0)
8753 /* Change from mapped state to withdrawn state. */
8755 /* Make the frame visible (mapped and not iconified). */
8758 x_make_frame_invisible (f
)
8763 /* Use the frame's outermost window, not the one we normally draw on. */
8764 window
= FRAME_OUTER_WINDOW (f
);
8766 /* Don't keep the highlight on an invisible frame. */
8767 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
8768 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
8770 #if 0/* This might add unreliability; I don't trust it -- rms. */
8771 if (! f
->async_visible
&& ! f
->async_iconified
)
8777 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
8778 that the current position of the window is user-specified, rather than
8779 program-specified, so that when the window is mapped again, it will be
8780 placed at the same location, without forcing the user to position it
8781 by hand again (they have already done that once for this window.) */
8782 x_wm_set_size_hint (f
, (long) 0, 1);
8785 if (FRAME_GTK_OUTER_WIDGET (f
))
8786 gtk_widget_hide (FRAME_GTK_OUTER_WIDGET (f
));
8792 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
8793 DefaultScreen (FRAME_X_DISPLAY (f
))))
8795 UNBLOCK_INPUT_RESIGNAL
;
8796 error ("Can't notify window manager of window withdrawal");
8798 #else /* ! defined (HAVE_X11R4) */
8800 /* Tell the window manager what we're going to do. */
8801 if (! EQ (Vx_no_window_manager
, Qt
))
8805 unmap
.xunmap
.type
= UnmapNotify
;
8806 unmap
.xunmap
.window
= window
;
8807 unmap
.xunmap
.event
= DefaultRootWindow (FRAME_X_DISPLAY (f
));
8808 unmap
.xunmap
.from_configure
= False
;
8809 if (! XSendEvent (FRAME_X_DISPLAY (f
),
8810 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
8812 SubstructureRedirectMaskSubstructureNotifyMask
,
8815 UNBLOCK_INPUT_RESIGNAL
;
8816 error ("Can't notify window manager of withdrawal");
8820 /* Unmap the window ourselves. Cheeky! */
8821 XUnmapWindow (FRAME_X_DISPLAY (f
), window
);
8822 #endif /* ! defined (HAVE_X11R4) */
8825 /* We can't distinguish this from iconification
8826 just by the event that we get from the server.
8827 So we can't win using the usual strategy of letting
8828 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
8829 and synchronize with the server to make sure we agree. */
8831 FRAME_ICONIFIED_P (f
) = 0;
8832 f
->async_visible
= 0;
8833 f
->async_iconified
= 0;
8840 /* Change window state from mapped to iconified. */
8849 /* Don't keep the highlight on an invisible frame. */
8850 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
8851 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
8853 if (f
->async_iconified
)
8858 FRAME_SAMPLE_VISIBILITY (f
);
8860 type
= x_icon_type (f
);
8862 x_bitmap_icon (f
, type
);
8865 if (FRAME_GTK_OUTER_WIDGET (f
))
8867 if (! FRAME_VISIBLE_P (f
))
8868 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f
));
8870 gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f
)));
8873 f
->async_iconified
= 1;
8874 f
->async_visible
= 0;
8880 #ifdef USE_X_TOOLKIT
8882 if (! FRAME_VISIBLE_P (f
))
8884 if (! EQ (Vx_no_window_manager
, Qt
))
8885 x_wm_set_window_state (f
, IconicState
);
8886 /* This was XtPopup, but that did nothing for an iconified frame. */
8887 XtMapWidget (f
->output_data
.x
->widget
);
8888 /* The server won't give us any event to indicate
8889 that an invisible frame was changed to an icon,
8890 so we have to record it here. */
8893 f
->async_iconified
= 1;
8894 f
->async_visible
= 0;
8899 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
8900 XtWindow (f
->output_data
.x
->widget
),
8901 DefaultScreen (FRAME_X_DISPLAY (f
)));
8905 error ("Can't notify window manager of iconification");
8907 f
->async_iconified
= 1;
8908 f
->async_visible
= 0;
8912 XFlush (FRAME_X_DISPLAY (f
));
8914 #else /* not USE_X_TOOLKIT */
8916 /* Make sure the X server knows where the window should be positioned,
8917 in case the user deiconifies with the window manager. */
8918 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
8919 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
8921 /* Since we don't know which revision of X we're running, we'll use both
8922 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
8924 /* X11R4: send a ClientMessage to the window manager using the
8925 WM_CHANGE_STATE type. */
8929 message
.xclient
.window
= FRAME_X_WINDOW (f
);
8930 message
.xclient
.type
= ClientMessage
;
8931 message
.xclient
.message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
8932 message
.xclient
.format
= 32;
8933 message
.xclient
.data
.l
[0] = IconicState
;
8935 if (! XSendEvent (FRAME_X_DISPLAY (f
),
8936 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
8938 SubstructureRedirectMask
| SubstructureNotifyMask
,
8941 UNBLOCK_INPUT_RESIGNAL
;
8942 error ("Can't notify window manager of iconification");
8946 /* X11R3: set the initial_state field of the window manager hints to
8948 x_wm_set_window_state (f
, IconicState
);
8950 if (!FRAME_VISIBLE_P (f
))
8952 /* If the frame was withdrawn, before, we must map it. */
8953 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
8956 f
->async_iconified
= 1;
8957 f
->async_visible
= 0;
8959 XFlush (FRAME_X_DISPLAY (f
));
8961 #endif /* not USE_X_TOOLKIT */
8965 /* Free X resources of frame F. */
8968 x_free_frame_resources (f
)
8971 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
8973 struct scroll_bar
*b
;
8977 /* If a display connection is dead, don't try sending more
8978 commands to the X server. */
8979 if (dpyinfo
->display
)
8981 if (f
->output_data
.x
->icon_desc
)
8982 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->icon_desc
);
8984 #ifdef USE_X_TOOLKIT
8985 /* Explicitly destroy the scroll bars of the frame. Without
8986 this, we get "BadDrawable" errors from the toolkit later on,
8987 presumably from expose events generated for the disappearing
8988 toolkit scroll bars. */
8989 for (bar
= FRAME_SCROLL_BARS (f
); !NILP (bar
); bar
= b
->next
)
8991 b
= XSCROLL_BAR (bar
);
8992 x_scroll_bar_remove (b
);
9001 #ifdef USE_X_TOOLKIT
9002 if (f
->output_data
.x
->widget
)
9004 XtDestroyWidget (f
->output_data
.x
->widget
);
9005 f
->output_data
.x
->widget
= NULL
;
9007 /* Tooltips don't have widgets, only a simple X window, even if
9008 we are using a toolkit. */
9009 else if (FRAME_X_WINDOW (f
))
9010 XDestroyWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
9012 free_frame_menubar (f
);
9013 #else /* !USE_X_TOOLKIT */
9016 /* In the GTK version, tooltips are normal X
9017 frames. We must check and free both types. */
9018 if (FRAME_GTK_OUTER_WIDGET (f
))
9020 gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f
));
9021 FRAME_X_WINDOW (f
) = 0; /* Set to avoid XDestroyWindow below */
9022 FRAME_GTK_OUTER_WIDGET (f
) = 0;
9024 #endif /* USE_GTK */
9026 if (FRAME_X_WINDOW (f
))
9027 XDestroyWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
9028 #endif /* !USE_X_TOOLKIT */
9030 unload_color (f
, f
->output_data
.x
->foreground_pixel
);
9031 unload_color (f
, f
->output_data
.x
->background_pixel
);
9032 unload_color (f
, f
->output_data
.x
->cursor_pixel
);
9033 unload_color (f
, f
->output_data
.x
->cursor_foreground_pixel
);
9034 unload_color (f
, f
->output_data
.x
->border_pixel
);
9035 unload_color (f
, f
->output_data
.x
->mouse_pixel
);
9037 if (f
->output_data
.x
->scroll_bar_background_pixel
!= -1)
9038 unload_color (f
, f
->output_data
.x
->scroll_bar_background_pixel
);
9039 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
9040 unload_color (f
, f
->output_data
.x
->scroll_bar_foreground_pixel
);
9041 #ifdef USE_TOOLKIT_SCROLL_BARS
9042 /* Scrollbar shadow colors. */
9043 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
!= -1)
9044 unload_color (f
, f
->output_data
.x
->scroll_bar_top_shadow_pixel
);
9045 if (f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
!= -1)
9046 unload_color (f
, f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
);
9047 #endif /* USE_TOOLKIT_SCROLL_BARS */
9048 if (f
->output_data
.x
->white_relief
.allocated_p
)
9049 unload_color (f
, f
->output_data
.x
->white_relief
.pixel
);
9050 if (f
->output_data
.x
->black_relief
.allocated_p
)
9051 unload_color (f
, f
->output_data
.x
->black_relief
.pixel
);
9053 if (FRAME_FACE_CACHE (f
))
9054 free_frame_faces (f
);
9057 XFlush (FRAME_X_DISPLAY (f
));
9060 if (f
->output_data
.x
->saved_menu_event
)
9061 xfree (f
->output_data
.x
->saved_menu_event
);
9063 xfree (f
->output_data
.x
);
9064 f
->output_data
.x
= NULL
;
9066 if (f
== dpyinfo
->x_focus_frame
)
9067 dpyinfo
->x_focus_frame
= 0;
9068 if (f
== dpyinfo
->x_focus_event_frame
)
9069 dpyinfo
->x_focus_event_frame
= 0;
9070 if (f
== dpyinfo
->x_highlight_frame
)
9071 dpyinfo
->x_highlight_frame
= 0;
9073 if (f
== dpyinfo
->mouse_face_mouse_frame
)
9075 dpyinfo
->mouse_face_beg_row
9076 = dpyinfo
->mouse_face_beg_col
= -1;
9077 dpyinfo
->mouse_face_end_row
9078 = dpyinfo
->mouse_face_end_col
= -1;
9079 dpyinfo
->mouse_face_window
= Qnil
;
9080 dpyinfo
->mouse_face_deferred_gc
= 0;
9081 dpyinfo
->mouse_face_mouse_frame
= 0;
9088 /* Destroy the X window of frame F. */
9091 x_destroy_window (f
)
9094 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9096 /* If a display connection is dead, don't try sending more
9097 commands to the X server. */
9098 if (dpyinfo
->display
!= 0)
9099 x_free_frame_resources (f
);
9101 dpyinfo
->reference_count
--;
9105 /* Setting window manager hints. */
9107 /* Set the normal size hints for the window manager, for frame F.
9108 FLAGS is the flags word to use--or 0 meaning preserve the flags
9109 that the window now has.
9110 If USER_POSITION is nonzero, we set the USPosition
9111 flag (this is useful when FLAGS is 0).
9112 The GTK version is in gtkutils.c */
9116 x_wm_set_size_hint (f
, flags
, user_position
)
9121 XSizeHints size_hints
;
9123 #ifdef USE_X_TOOLKIT
9126 Dimension widget_width
, widget_height
;
9129 Window window
= FRAME_OUTER_WINDOW (f
);
9131 /* Setting PMaxSize caused various problems. */
9132 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
9134 size_hints
.x
= f
->left_pos
;
9135 size_hints
.y
= f
->top_pos
;
9137 #ifdef USE_X_TOOLKIT
9138 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
9139 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
9140 XtGetValues (f
->output_data
.x
->widget
, al
, ac
);
9141 size_hints
.height
= widget_height
;
9142 size_hints
.width
= widget_width
;
9143 #else /* not USE_X_TOOLKIT */
9144 size_hints
.height
= FRAME_PIXEL_HEIGHT (f
);
9145 size_hints
.width
= FRAME_PIXEL_WIDTH (f
);
9146 #endif /* not USE_X_TOOLKIT */
9148 size_hints
.width_inc
= FRAME_COLUMN_WIDTH (f
);
9149 size_hints
.height_inc
= FRAME_LINE_HEIGHT (f
);
9150 size_hints
.max_width
9151 = FRAME_X_DISPLAY_INFO (f
)->width
- FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
9152 size_hints
.max_height
9153 = FRAME_X_DISPLAY_INFO (f
)->height
- FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
9155 /* Calculate the base and minimum sizes.
9157 (When we use the X toolkit, we don't do it here.
9158 Instead we copy the values that the widgets are using, below.) */
9159 #ifndef USE_X_TOOLKIT
9161 int base_width
, base_height
;
9162 int min_rows
= 0, min_cols
= 0;
9164 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
9165 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
9167 check_frame_size (f
, &min_rows
, &min_cols
);
9169 /* The window manager uses the base width hints to calculate the
9170 current number of rows and columns in the frame while
9171 resizing; min_width and min_height aren't useful for this
9172 purpose, since they might not give the dimensions for a
9173 zero-row, zero-column frame.
9175 We use the base_width and base_height members if we have
9176 them; otherwise, we set the min_width and min_height members
9177 to the size for a zero x zero frame. */
9180 size_hints
.flags
|= PBaseSize
;
9181 size_hints
.base_width
= base_width
;
9182 size_hints
.base_height
= base_height
;
9183 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
9184 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
9186 size_hints
.min_width
= base_width
;
9187 size_hints
.min_height
= base_height
;
9191 /* If we don't need the old flags, we don't need the old hint at all. */
9194 size_hints
.flags
|= flags
;
9197 #endif /* not USE_X_TOOLKIT */
9200 XSizeHints hints
; /* Sometimes I hate X Windows... */
9201 long supplied_return
;
9205 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
9208 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
9211 #ifdef USE_X_TOOLKIT
9212 size_hints
.base_height
= hints
.base_height
;
9213 size_hints
.base_width
= hints
.base_width
;
9214 size_hints
.min_height
= hints
.min_height
;
9215 size_hints
.min_width
= hints
.min_width
;
9219 size_hints
.flags
|= flags
;
9224 if (hints
.flags
& PSize
)
9225 size_hints
.flags
|= PSize
;
9226 if (hints
.flags
& PPosition
)
9227 size_hints
.flags
|= PPosition
;
9228 if (hints
.flags
& USPosition
)
9229 size_hints
.flags
|= USPosition
;
9230 if (hints
.flags
& USSize
)
9231 size_hints
.flags
|= USSize
;
9235 #ifndef USE_X_TOOLKIT
9240 size_hints
.win_gravity
= f
->win_gravity
;
9241 size_hints
.flags
|= PWinGravity
;
9245 size_hints
.flags
&= ~ PPosition
;
9246 size_hints
.flags
|= USPosition
;
9248 #endif /* PWinGravity */
9251 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
9253 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
9256 #endif /* not USE_GTK */
9258 /* Used for IconicState or NormalState */
9261 x_wm_set_window_state (f
, state
)
9265 #ifdef USE_X_TOOLKIT
9268 XtSetArg (al
[0], XtNinitialState
, state
);
9269 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
9270 #else /* not USE_X_TOOLKIT */
9271 Window window
= FRAME_X_WINDOW (f
);
9273 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
9274 f
->output_data
.x
->wm_hints
.initial_state
= state
;
9276 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
9277 #endif /* not USE_X_TOOLKIT */
9281 x_wm_set_icon_pixmap (f
, pixmap_id
)
9285 Pixmap icon_pixmap
, icon_mask
;
9287 #ifndef USE_X_TOOLKIT
9288 Window window
= FRAME_OUTER_WINDOW (f
);
9293 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
9294 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
9295 icon_mask
= x_bitmap_mask (f
, pixmap_id
);
9296 f
->output_data
.x
->wm_hints
.icon_mask
= icon_mask
;
9300 /* It seems there is no way to turn off use of an icon pixmap.
9301 The following line does it, only if no icon has yet been created,
9302 for some window managers. But with mwm it crashes.
9303 Some people say it should clear the IconPixmapHint bit in this case,
9304 but that doesn't work, and the X consortium said it isn't the
9305 right thing at all. Since there is no way to win,
9306 best to explicitly give up. */
9308 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
9309 f
->output_data
.x
->wm_hints
.icon_mask
= None
;
9315 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
9319 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
9320 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
9321 XtSetArg (al
[0], XtNiconMask
, icon_mask
);
9322 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
9325 #else /* not USE_X_TOOLKIT */
9327 f
->output_data
.x
->wm_hints
.flags
|= (IconPixmapHint
| IconMaskHint
);
9328 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
9330 #endif /* not USE_X_TOOLKIT */
9334 x_wm_set_icon_position (f
, icon_x
, icon_y
)
9338 Window window
= FRAME_OUTER_WINDOW (f
);
9340 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
9341 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
9342 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
9344 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
9348 /***********************************************************************
9350 ***********************************************************************/
9352 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
9355 x_get_font_info (f
, font_idx
)
9359 return (FRAME_X_FONT_TABLE (f
) + font_idx
);
9363 /* Return a list of names of available fonts matching PATTERN on frame F.
9365 If SIZE is > 0, it is the size (maximum bounds width) of fonts
9368 SIZE < 0 means include scalable fonts.
9370 Frame F null means we have not yet created any frame on X, and
9371 consult the first display in x_display_list. MAXNAMES sets a limit
9372 on how many fonts to match. */
9375 x_list_fonts (f
, pattern
, size
, maxnames
)
9377 Lisp_Object pattern
;
9381 Lisp_Object list
= Qnil
, patterns
, newlist
= Qnil
, key
= Qnil
;
9382 Lisp_Object tem
, second_best
;
9383 struct x_display_info
*dpyinfo
9384 = f
? FRAME_X_DISPLAY_INFO (f
) : x_display_list
;
9385 Display
*dpy
= dpyinfo
->display
;
9386 int try_XLoadQueryFont
= 0;
9388 int allow_auto_scaled_font
= 0;
9392 allow_auto_scaled_font
= 1;
9396 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
9397 if (NILP (patterns
))
9398 patterns
= Fcons (pattern
, Qnil
);
9400 if (maxnames
== 1 && !size
)
9401 /* We can return any single font matching PATTERN. */
9402 try_XLoadQueryFont
= 1;
9404 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
9407 char **names
= NULL
;
9409 pattern
= XCAR (patterns
);
9410 /* See if we cached the result for this particular query.
9411 The cache is an alist of the form:
9412 ((((PATTERN . MAXNAMES) . SCALABLE) (FONTNAME . WIDTH) ...) ...) */
9413 tem
= XCDR (dpyinfo
->name_list_element
);
9414 key
= Fcons (Fcons (pattern
, make_number (maxnames
)),
9415 allow_auto_scaled_font
? Qt
: Qnil
);
9416 list
= Fassoc (key
, tem
);
9419 list
= Fcdr_safe (list
);
9420 /* We have a cashed list. Don't have to get the list again. */
9424 /* At first, put PATTERN in the cache. */
9427 count
= x_catch_errors (dpy
);
9429 if (try_XLoadQueryFont
)
9432 unsigned long value
;
9434 font
= XLoadQueryFont (dpy
, SDATA (pattern
));
9435 if (x_had_errors_p (dpy
))
9437 /* This error is perhaps due to insufficient memory on X
9438 server. Let's just ignore it. */
9440 x_clear_errors (dpy
);
9444 && XGetFontProperty (font
, XA_FONT
, &value
))
9446 char *name
= (char *) XGetAtomName (dpy
, (Atom
) value
);
9447 int len
= strlen (name
);
9450 /* If DXPC (a Differential X Protocol Compressor)
9451 Ver.3.7 is running, XGetAtomName will return null
9452 string. We must avoid such a name. */
9454 try_XLoadQueryFont
= 0;
9458 names
= (char **) alloca (sizeof (char *));
9459 /* Some systems only allow alloca assigned to a
9461 tmp
= (char *) alloca (len
+ 1); names
[0] = tmp
;
9462 bcopy (name
, names
[0], len
+ 1);
9467 try_XLoadQueryFont
= 0;
9470 XFreeFont (dpy
, font
);
9473 if (!try_XLoadQueryFont
)
9475 /* We try at least 10 fonts because XListFonts will return
9476 auto-scaled fonts at the head. */
9483 names
= XListFonts (dpy
, SDATA (pattern
), limit
, &num_fonts
);
9484 if (num_fonts
== limit
)
9487 XFreeFontNames (names
);
9496 names
= XListFonts (dpy
, SDATA (pattern
), max (maxnames
, 10),
9499 if (x_had_errors_p (dpy
))
9501 /* This error is perhaps due to insufficient memory on X
9502 server. Let's just ignore it. */
9504 x_clear_errors (dpy
);
9508 x_uncatch_errors (dpy
, count
);
9515 /* Make a list of all the fonts we got back.
9516 Store that in the font cache for the display. */
9517 for (i
= 0; i
< num_fonts
; i
++)
9521 int average_width
= -1, resx
= 0, dashes
= 0;
9523 /* Count the number of dashes in NAMES[I]. If there are
9524 14 dashes, the field value following 9th dash
9525 (RESOLUTION_X) is nonzero, and the field value
9526 following 12th dash (AVERAGE_WIDTH) is 0, this is a
9527 auto-scaled font which is usually too ugly to be used
9528 for editing. Let's ignore it. */
9533 if (dashes
== 7) /* PIXEL_SIZE field */
9535 else if (dashes
== 9)
9537 else if (dashes
== 12) /* AVERAGE_WIDTH field */
9538 average_width
= atoi (p
);
9541 if (allow_auto_scaled_font
9542 || dashes
< 14 || average_width
!= 0 || resx
== 0)
9544 tem
= build_string (names
[i
]);
9545 if (NILP (Fassoc (tem
, list
)))
9547 if (STRINGP (Vx_pixel_size_width_font_regexp
)
9548 && ((fast_c_string_match_ignore_case
9549 (Vx_pixel_size_width_font_regexp
, names
[i
]))
9551 /* We can set the value of PIXEL_SIZE to the
9552 width of this font. */
9553 list
= Fcons (Fcons (tem
, make_number (width
)), list
);
9555 /* For the moment, width is not known. */
9556 list
= Fcons (Fcons (tem
, Qnil
), list
);
9561 if (!try_XLoadQueryFont
)
9564 XFreeFontNames (names
);
9569 /* Now store the result in the cache. */
9570 XSETCDR (dpyinfo
->name_list_element
,
9571 Fcons (Fcons (key
, list
), XCDR (dpyinfo
->name_list_element
)));
9574 if (NILP (list
)) continue; /* Try the remaining alternatives. */
9576 newlist
= second_best
= Qnil
;
9577 /* Make a list of the fonts that have the right width. */
9578 for (; CONSP (list
); list
= XCDR (list
))
9584 if (!CONSP (tem
) || NILP (XCAR (tem
)))
9588 newlist
= Fcons (XCAR (tem
), newlist
);
9592 if (!INTEGERP (XCDR (tem
)))
9594 /* Since we have not yet known the size of this font, we
9595 must try slow function call XLoadQueryFont. */
9596 XFontStruct
*thisinfo
;
9599 count
= x_catch_errors (dpy
);
9600 thisinfo
= XLoadQueryFont (dpy
,
9601 SDATA (XCAR (tem
)));
9602 if (x_had_errors_p (dpy
))
9604 /* This error is perhaps due to insufficient memory on X
9605 server. Let's just ignore it. */
9607 x_clear_errors (dpy
);
9609 x_uncatch_errors (dpy
, count
);
9615 (thisinfo
->min_bounds
.width
== 0
9617 : make_number (thisinfo
->max_bounds
.width
)));
9619 XFreeFont (dpy
, thisinfo
);
9623 /* For unknown reason, the previous call of XListFont had
9624 returned a font which can't be opened. Record the size
9625 as 0 not to try to open it again. */
9626 XSETCDR (tem
, make_number (0));
9629 found_size
= XINT (XCDR (tem
));
9630 if (found_size
== size
)
9631 newlist
= Fcons (XCAR (tem
), newlist
);
9632 else if (found_size
> 0)
9634 if (NILP (second_best
))
9636 else if (found_size
< size
)
9638 if (XINT (XCDR (second_best
)) > size
9639 || XINT (XCDR (second_best
)) < found_size
)
9644 if (XINT (XCDR (second_best
)) > size
9645 && XINT (XCDR (second_best
)) > found_size
)
9650 if (!NILP (newlist
))
9652 else if (!NILP (second_best
))
9654 newlist
= Fcons (XCAR (second_best
), Qnil
);
9665 /* Check that FONT is valid on frame F. It is if it can be found in F's
9669 x_check_font (f
, font
)
9674 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9676 xassert (font
!= NULL
);
9678 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9679 if (dpyinfo
->font_table
[i
].name
9680 && font
== dpyinfo
->font_table
[i
].font
)
9683 xassert (i
< dpyinfo
->n_fonts
);
9686 #endif /* GLYPH_DEBUG != 0 */
9688 /* Set *W to the minimum width, *H to the minimum font height of FONT.
9689 Note: There are (broken) X fonts out there with invalid XFontStruct
9690 min_bounds contents. For example, handa@etl.go.jp reports that
9691 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
9692 have font->min_bounds.width == 0. */
9695 x_font_min_bounds (font
, w
, h
)
9699 *h
= FONT_HEIGHT (font
);
9700 *w
= font
->min_bounds
.width
;
9702 /* Try to handle the case where FONT->min_bounds has invalid
9703 contents. Since the only font known to have invalid min_bounds
9704 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
9706 *w
= font
->max_bounds
.width
;
9710 /* Compute the smallest character width and smallest font height over
9711 all fonts available on frame F. Set the members smallest_char_width
9712 and smallest_font_height in F's x_display_info structure to
9713 the values computed. Value is non-zero if smallest_font_height or
9714 smallest_char_width become smaller than they were before. */
9717 x_compute_min_glyph_bounds (f
)
9721 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9723 int old_width
= dpyinfo
->smallest_char_width
;
9724 int old_height
= dpyinfo
->smallest_font_height
;
9726 dpyinfo
->smallest_font_height
= 100000;
9727 dpyinfo
->smallest_char_width
= 100000;
9729 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
9730 if (dpyinfo
->font_table
[i
].name
)
9732 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
9735 font
= (XFontStruct
*) fontp
->font
;
9736 xassert (font
!= (XFontStruct
*) ~0);
9737 x_font_min_bounds (font
, &w
, &h
);
9739 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
9740 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
9743 xassert (dpyinfo
->smallest_char_width
> 0
9744 && dpyinfo
->smallest_font_height
> 0);
9746 return (dpyinfo
->n_fonts
== 1
9747 || dpyinfo
->smallest_char_width
< old_width
9748 || dpyinfo
->smallest_font_height
< old_height
);
9752 /* Load font named FONTNAME of the size SIZE for frame F, and return a
9753 pointer to the structure font_info while allocating it dynamically.
9754 If SIZE is 0, load any size of font.
9755 If loading is failed, return NULL. */
9758 x_load_font (f
, fontname
, size
)
9760 register char *fontname
;
9763 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9764 Lisp_Object font_names
;
9767 /* Get a list of all the fonts that match this name. Once we
9768 have a list of matching fonts, we compare them against the fonts
9769 we already have by comparing names. */
9770 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
9772 if (!NILP (font_names
))
9777 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9778 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
9779 if (dpyinfo
->font_table
[i
].name
9780 && (!strcmp (dpyinfo
->font_table
[i
].name
,
9781 SDATA (XCAR (tail
)))
9782 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
9783 SDATA (XCAR (tail
)))))
9784 return (dpyinfo
->font_table
+ i
);
9787 /* Load the font and add it to the table. */
9791 struct font_info
*fontp
;
9792 unsigned long value
;
9795 /* If we have found fonts by x_list_font, load one of them. If
9796 not, we still try to load a font by the name given as FONTNAME
9797 because XListFonts (called in x_list_font) of some X server has
9798 a bug of not finding a font even if the font surely exists and
9799 is loadable by XLoadQueryFont. */
9800 if (size
> 0 && !NILP (font_names
))
9801 fontname
= (char *) SDATA (XCAR (font_names
));
9804 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
9805 font
= (XFontStruct
*) XLoadQueryFont (FRAME_X_DISPLAY (f
), fontname
);
9806 if (x_had_errors_p (FRAME_X_DISPLAY (f
)))
9808 /* This error is perhaps due to insufficient memory on X
9809 server. Let's just ignore it. */
9811 x_clear_errors (FRAME_X_DISPLAY (f
));
9813 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
9818 /* Find a free slot in the font table. */
9819 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
9820 if (dpyinfo
->font_table
[i
].name
== NULL
)
9823 /* If no free slot found, maybe enlarge the font table. */
9824 if (i
== dpyinfo
->n_fonts
9825 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
9828 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
9829 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
9831 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
9834 fontp
= dpyinfo
->font_table
+ i
;
9835 if (i
== dpyinfo
->n_fonts
)
9838 /* Now fill in the slots of *FONTP. */
9840 bzero (fontp
, sizeof (*fontp
));
9842 fontp
->font_idx
= i
;
9843 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
9844 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
9846 /* Try to get the full name of FONT. Put it in FULL_NAME. */
9848 if (XGetFontProperty (font
, XA_FONT
, &value
))
9850 char *name
= (char *) XGetAtomName (FRAME_X_DISPLAY (f
), (Atom
) value
);
9854 /* Count the number of dashes in the "full name".
9855 If it is too few, this isn't really the font's full name,
9857 In X11R4, the fonts did not come with their canonical names
9868 full_name
= (char *) xmalloc (p
- name
+ 1);
9869 bcopy (name
, full_name
, p
- name
+ 1);
9876 fontp
->full_name
= full_name
;
9878 fontp
->full_name
= fontp
->name
;
9880 fontp
->size
= font
->max_bounds
.width
;
9881 fontp
->height
= FONT_HEIGHT (font
);
9883 if (NILP (font_names
))
9885 /* We come here because of a bug of XListFonts mentioned at
9886 the head of this block. Let's store this information in
9887 the cache for x_list_fonts. */
9888 Lisp_Object lispy_name
= build_string (fontname
);
9889 Lisp_Object lispy_full_name
= build_string (fontp
->full_name
);
9890 Lisp_Object key
= Fcons (Fcons (lispy_name
, make_number (256)),
9893 XSETCDR (dpyinfo
->name_list_element
,
9895 Fcons (Fcons (lispy_full_name
,
9896 make_number (fontp
->size
)),
9898 XCDR (dpyinfo
->name_list_element
)));
9901 key
= Fcons (Fcons (lispy_full_name
, make_number (256)),
9903 XSETCDR (dpyinfo
->name_list_element
,
9905 Fcons (Fcons (lispy_full_name
,
9906 make_number (fontp
->size
)),
9908 XCDR (dpyinfo
->name_list_element
)));
9912 /* The slot `encoding' specifies how to map a character
9913 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
9914 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
9915 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
9916 2:0xA020..0xFF7F). For the moment, we don't know which charset
9917 uses this font. So, we set information in fontp->encoding[1]
9918 which is never used by any charset. If mapping can't be
9919 decided, set FONT_ENCODING_NOT_DECIDED. */
9921 = (font
->max_byte1
== 0
9923 ? (font
->min_char_or_byte2
< 0x80
9924 ? (font
->max_char_or_byte2
< 0x80
9925 ? 0 /* 0x20..0x7F */
9926 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
9927 : 1) /* 0xA0..0xFF */
9929 : (font
->min_byte1
< 0x80
9930 ? (font
->max_byte1
< 0x80
9931 ? (font
->min_char_or_byte2
< 0x80
9932 ? (font
->max_char_or_byte2
< 0x80
9933 ? 0 /* 0x2020..0x7F7F */
9934 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
9935 : 3) /* 0x20A0..0x7FFF */
9936 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
9937 : (font
->min_char_or_byte2
< 0x80
9938 ? (font
->max_char_or_byte2
< 0x80
9939 ? 2 /* 0xA020..0xFF7F */
9940 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
9941 : 1))); /* 0xA0A0..0xFFFF */
9943 fontp
->baseline_offset
9944 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
9945 ? (long) value
: 0);
9946 fontp
->relative_compose
9947 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
9948 ? (long) value
: 0);
9949 fontp
->default_ascent
9950 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
9951 ? (long) value
: 0);
9953 /* Set global flag fonts_changed_p to non-zero if the font loaded
9954 has a character with a smaller width than any other character
9955 before, or if the font loaded has a smaller height than any
9956 other font loaded before. If this happens, it will make a
9957 glyph matrix reallocation necessary. */
9958 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
9965 /* Return a pointer to struct font_info of a font named FONTNAME for
9966 frame F. If no such font is loaded, return NULL. */
9969 x_query_font (f
, fontname
)
9971 register char *fontname
;
9973 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9976 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9977 if (dpyinfo
->font_table
[i
].name
9978 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
9979 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
9980 return (dpyinfo
->font_table
+ i
);
9985 /* Find a CCL program for a font specified by FONTP, and set the member
9986 `encoder' of the structure. */
9989 x_find_ccl_program (fontp
)
9990 struct font_info
*fontp
;
9992 Lisp_Object list
, elt
;
9995 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
9999 && STRINGP (XCAR (elt
))
10000 && ((fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
10002 || (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->full_name
)
10009 struct ccl_program
*ccl
10010 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
10012 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
10015 fontp
->font_encoder
= ccl
;
10021 /***********************************************************************
10023 ***********************************************************************/
10025 #ifdef USE_X_TOOLKIT
10026 static XrmOptionDescRec emacs_options
[] = {
10027 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
10028 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
10030 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
10031 XrmoptionSepArg
, NULL
},
10032 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
10034 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
10035 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
10036 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
10037 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
10038 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
10039 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
10040 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
10042 #endif /* USE_X_TOOLKIT */
10044 static int x_initialized
;
10046 #ifdef MULTI_KBOARD
10047 /* Test whether two display-name strings agree up to the dot that separates
10048 the screen number from the server number. */
10050 same_x_server (name1
, name2
)
10051 const char *name1
, *name2
;
10053 int seen_colon
= 0;
10054 const unsigned char *system_name
= SDATA (Vsystem_name
);
10055 int system_name_length
= strlen (system_name
);
10056 int length_until_period
= 0;
10058 while (system_name
[length_until_period
] != 0
10059 && system_name
[length_until_period
] != '.')
10060 length_until_period
++;
10062 /* Treat `unix' like an empty host name. */
10063 if (! strncmp (name1
, "unix:", 5))
10065 if (! strncmp (name2
, "unix:", 5))
10067 /* Treat this host's name like an empty host name. */
10068 if (! strncmp (name1
, system_name
, system_name_length
)
10069 && name1
[system_name_length
] == ':')
10070 name1
+= system_name_length
;
10071 if (! strncmp (name2
, system_name
, system_name_length
)
10072 && name2
[system_name_length
] == ':')
10073 name2
+= system_name_length
;
10074 /* Treat this host's domainless name like an empty host name. */
10075 if (! strncmp (name1
, system_name
, length_until_period
)
10076 && name1
[length_until_period
] == ':')
10077 name1
+= length_until_period
;
10078 if (! strncmp (name2
, system_name
, length_until_period
)
10079 && name2
[length_until_period
] == ':')
10080 name2
+= length_until_period
;
10082 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
10086 if (seen_colon
&& *name1
== '.')
10090 && (*name1
== '.' || *name1
== '\0')
10091 && (*name2
== '.' || *name2
== '\0'));
10095 /* Count number of set bits in mask and number of bits to shift to
10096 get to the first bit. With MASK 0x7e0, *BITS is set to 6, and *OFFSET
10099 get_bits_and_offset (mask
, bits
, offset
)
10100 unsigned long mask
;
10107 while (!(mask
& 1))
10123 struct x_display_info
*
10124 x_term_init (display_name
, xrm_option
, resource_name
)
10125 Lisp_Object display_name
;
10127 char *resource_name
;
10131 struct display
*display
;
10132 struct x_display_info
*dpyinfo
;
10137 if (!x_initialized
)
10145 #define NUM_ARGV 10
10147 char *argv
[NUM_ARGV
];
10148 char **argv2
= argv
;
10151 if (x_initialized
++ > 1)
10153 /* Opening another display. If xg_display_open returns less
10154 than zero, we are probably on GTK 2.0, which can only handle
10155 one display. GTK 2.2 or later can handle more than one. */
10156 if (xg_display_open (SDATA (display_name
), &dpy
) < 0)
10157 error ("Sorry, this version of GTK can only handle one display");
10161 for (argc
= 0; argc
< NUM_ARGV
; ++argc
)
10165 argv
[argc
++] = initial_argv
[0];
10167 if (! NILP (display_name
))
10169 argv
[argc
++] = "--display";
10170 argv
[argc
++] = SDATA (display_name
);
10173 argv
[argc
++] = "--name";
10174 argv
[argc
++] = resource_name
;
10177 XSetLocaleModifiers ("");
10180 gtk_init (&argc
, &argv2
);
10182 /* gtk_init does set_locale. We must fix locale after calling it. */
10186 dpy
= GDK_DISPLAY ();
10188 /* NULL window -> events for all windows go to our function */
10189 gdk_window_add_filter (NULL
, event_handler_gdk
, NULL
);
10191 /* Load our own gtkrc if it exists. */
10193 struct gcpro gcpro1
, gcpro2
;
10194 char *file
= "~/.emacs.d/gtkrc";
10195 Lisp_Object s
, abs_file
;
10197 GCPRO2 (s
, abs_file
);
10198 s
= make_string (file
, strlen (file
));
10199 abs_file
= Fexpand_file_name (s
, Qnil
);
10201 if (! NILP (abs_file
) && !NILP (Ffile_readable_p (abs_file
)))
10202 gtk_rc_parse (SDATA (abs_file
));
10207 XSetErrorHandler (x_error_handler
);
10208 XSetIOErrorHandler (x_io_error_quitter
);
10211 #else /* not USE_GTK */
10212 #ifdef USE_X_TOOLKIT
10213 /* weiner@footloose.sps.mot.com reports that this causes
10215 X protocol error: BadAtom (invalid Atom parameter)
10216 on protocol request 18skiloaf.
10217 So let's not use it until R6. */
10218 #ifdef HAVE_X11XTR6
10219 XtSetLanguageProc (NULL
, NULL
, NULL
);
10230 argv
[argc
++] = "-xrm";
10231 argv
[argc
++] = xrm_option
;
10233 turn_on_atimers (0);
10234 dpy
= XtOpenDisplay (Xt_app_con
, SDATA (display_name
),
10235 resource_name
, EMACS_CLASS
,
10236 emacs_options
, XtNumber (emacs_options
),
10238 turn_on_atimers (1);
10240 #ifdef HAVE_X11XTR6
10241 /* I think this is to compensate for XtSetLanguageProc. */
10246 #else /* not USE_X_TOOLKIT */
10248 XSetLocaleModifiers ("");
10250 dpy
= XOpenDisplay (SDATA (display_name
));
10251 #endif /* not USE_X_TOOLKIT */
10252 #endif /* not USE_GTK*/
10254 /* Detect failure. */
10261 /* We have definitely succeeded. Record the new connection. */
10263 dpyinfo
= (struct x_display_info
*) xmalloc (sizeof (struct x_display_info
));
10264 bzero (dpyinfo
, sizeof *dpyinfo
);
10266 display
= x_create_frame_display (dpyinfo
);
10268 #ifdef MULTI_KBOARD
10270 struct x_display_info
*share
;
10273 for (share
= x_display_list
, tail
= x_display_name_list
; share
;
10274 share
= share
->next
, tail
= XCDR (tail
))
10275 if (same_x_server (SDATA (XCAR (XCAR (tail
))),
10276 SDATA (display_name
)))
10279 dpyinfo
->kboard
= share
->kboard
;
10282 dpyinfo
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
10283 init_kboard (dpyinfo
->kboard
);
10284 if (!EQ (XSYMBOL (Qvendor_specific_keysyms
)->function
, Qunbound
))
10286 char *vendor
= ServerVendor (dpy
);
10288 dpyinfo
->kboard
->Vsystem_key_alist
10289 = call1 (Qvendor_specific_keysyms
,
10290 build_string (vendor
? vendor
: ""));
10294 dpyinfo
->kboard
->next_kboard
= all_kboards
;
10295 all_kboards
= dpyinfo
->kboard
;
10296 /* Don't let the initial kboard remain current longer than necessary.
10297 That would cause problems if a file loaded on startup tries to
10298 prompt in the mini-buffer. */
10299 if (current_kboard
== initial_kboard
)
10300 current_kboard
= dpyinfo
->kboard
;
10302 dpyinfo
->kboard
->reference_count
++;
10306 /* Put this display on the chain. */
10307 dpyinfo
->next
= x_display_list
;
10308 x_display_list
= dpyinfo
;
10310 /* Put it on x_display_name_list as well, to keep them parallel. */
10311 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
10312 x_display_name_list
);
10313 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
10315 dpyinfo
->display
= dpy
;
10318 XSetAfterFunction (x_current_display
, x_trace_wire
);
10322 = (char *) xmalloc (SBYTES (Vinvocation_name
)
10323 + SBYTES (Vsystem_name
)
10325 sprintf (dpyinfo
->x_id_name
, "%s@%s",
10326 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
10328 /* Figure out which modifier bits mean what. */
10329 x_find_modifier_meanings (dpyinfo
);
10331 /* Get the scroll bar cursor. */
10333 /* We must create a GTK cursor, it is required for GTK widgets. */
10334 dpyinfo
->xg_cursor
= xg_create_default_cursor (dpyinfo
->display
);
10335 #endif /* USE_GTK */
10337 dpyinfo
->vertical_scroll_bar_cursor
10338 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
10340 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
10341 resource_name
, EMACS_CLASS
);
10342 #ifdef HAVE_XRMSETDATABASE
10343 XrmSetDatabase (dpyinfo
->display
, xrdb
);
10345 dpyinfo
->display
->db
= xrdb
;
10347 /* Put the rdb where we can find it in a way that works on
10349 dpyinfo
->xrdb
= xrdb
;
10351 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
10352 DefaultScreen (dpyinfo
->display
));
10353 select_visual (dpyinfo
);
10354 dpyinfo
->cmap
= DefaultColormapOfScreen (dpyinfo
->screen
);
10355 dpyinfo
->height
= HeightOfScreen (dpyinfo
->screen
);
10356 dpyinfo
->width
= WidthOfScreen (dpyinfo
->screen
);
10357 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
10358 dpyinfo
->client_leader_window
= 0;
10359 dpyinfo
->grabbed
= 0;
10360 dpyinfo
->reference_count
= 0;
10361 dpyinfo
->icon_bitmap_id
= -1;
10362 dpyinfo
->font_table
= NULL
;
10363 dpyinfo
->n_fonts
= 0;
10364 dpyinfo
->font_table_size
= 0;
10365 dpyinfo
->bitmaps
= 0;
10366 dpyinfo
->bitmaps_size
= 0;
10367 dpyinfo
->bitmaps_last
= 0;
10368 dpyinfo
->scratch_cursor_gc
= 0;
10369 dpyinfo
->mouse_face_mouse_frame
= 0;
10370 dpyinfo
->mouse_face_deferred_gc
= 0;
10371 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
10372 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
10373 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
10374 dpyinfo
->mouse_face_window
= Qnil
;
10375 dpyinfo
->mouse_face_overlay
= Qnil
;
10376 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
10377 dpyinfo
->mouse_face_defer
= 0;
10378 dpyinfo
->mouse_face_hidden
= 0;
10379 dpyinfo
->x_focus_frame
= 0;
10380 dpyinfo
->x_focus_event_frame
= 0;
10381 dpyinfo
->x_highlight_frame
= 0;
10382 dpyinfo
->image_cache
= make_image_cache ();
10383 dpyinfo
->wm_type
= X_WMTYPE_UNKNOWN
;
10385 /* See if we can construct pixel values from RGB values. */
10386 dpyinfo
->red_bits
= dpyinfo
->blue_bits
= dpyinfo
->green_bits
= 0;
10387 dpyinfo
->red_offset
= dpyinfo
->blue_offset
= dpyinfo
->green_offset
= 0;
10389 if (dpyinfo
->visual
->class == TrueColor
)
10391 get_bits_and_offset (dpyinfo
->visual
->red_mask
,
10392 &dpyinfo
->red_bits
, &dpyinfo
->red_offset
);
10393 get_bits_and_offset (dpyinfo
->visual
->blue_mask
,
10394 &dpyinfo
->blue_bits
, &dpyinfo
->blue_offset
);
10395 get_bits_and_offset (dpyinfo
->visual
->green_mask
,
10396 &dpyinfo
->green_bits
, &dpyinfo
->green_offset
);
10399 /* See if a private colormap is requested. */
10400 if (dpyinfo
->visual
== DefaultVisualOfScreen (dpyinfo
->screen
))
10402 if (dpyinfo
->visual
->class == PseudoColor
)
10405 value
= display_x_get_resource (dpyinfo
,
10406 build_string ("privateColormap"),
10407 build_string ("PrivateColormap"),
10409 if (STRINGP (value
)
10410 && (!strcmp (SDATA (value
), "true")
10411 || !strcmp (SDATA (value
), "on")))
10412 dpyinfo
->cmap
= XCopyColormapAndFree (dpyinfo
->display
, dpyinfo
->cmap
);
10416 dpyinfo
->cmap
= XCreateColormap (dpyinfo
->display
, dpyinfo
->root_window
,
10417 dpyinfo
->visual
, AllocNone
);
10420 int screen_number
= XScreenNumberOfScreen (dpyinfo
->screen
);
10421 double pixels
= DisplayHeight (dpyinfo
->display
, screen_number
);
10422 double mm
= DisplayHeightMM (dpyinfo
->display
, screen_number
);
10423 dpyinfo
->resy
= pixels
* 25.4 / mm
;
10424 pixels
= DisplayWidth (dpyinfo
->display
, screen_number
);
10425 mm
= DisplayWidthMM (dpyinfo
->display
, screen_number
);
10426 dpyinfo
->resx
= pixels
* 25.4 / mm
;
10429 dpyinfo
->Xatom_wm_protocols
10430 = XInternAtom (dpyinfo
->display
, "WM_PROTOCOLS", False
);
10431 dpyinfo
->Xatom_wm_take_focus
10432 = XInternAtom (dpyinfo
->display
, "WM_TAKE_FOCUS", False
);
10433 dpyinfo
->Xatom_wm_save_yourself
10434 = XInternAtom (dpyinfo
->display
, "WM_SAVE_YOURSELF", False
);
10435 dpyinfo
->Xatom_wm_delete_window
10436 = XInternAtom (dpyinfo
->display
, "WM_DELETE_WINDOW", False
);
10437 dpyinfo
->Xatom_wm_change_state
10438 = XInternAtom (dpyinfo
->display
, "WM_CHANGE_STATE", False
);
10439 dpyinfo
->Xatom_wm_configure_denied
10440 = XInternAtom (dpyinfo
->display
, "WM_CONFIGURE_DENIED", False
);
10441 dpyinfo
->Xatom_wm_window_moved
10442 = XInternAtom (dpyinfo
->display
, "WM_MOVED", False
);
10443 dpyinfo
->Xatom_wm_client_leader
10444 = XInternAtom (dpyinfo
->display
, "WM_CLIENT_LEADER", False
);
10445 dpyinfo
->Xatom_editres
10446 = XInternAtom (dpyinfo
->display
, "Editres", False
);
10447 dpyinfo
->Xatom_CLIPBOARD
10448 = XInternAtom (dpyinfo
->display
, "CLIPBOARD", False
);
10449 dpyinfo
->Xatom_TIMESTAMP
10450 = XInternAtom (dpyinfo
->display
, "TIMESTAMP", False
);
10451 dpyinfo
->Xatom_TEXT
10452 = XInternAtom (dpyinfo
->display
, "TEXT", False
);
10453 dpyinfo
->Xatom_COMPOUND_TEXT
10454 = XInternAtom (dpyinfo
->display
, "COMPOUND_TEXT", False
);
10455 dpyinfo
->Xatom_UTF8_STRING
10456 = XInternAtom (dpyinfo
->display
, "UTF8_STRING", False
);
10457 dpyinfo
->Xatom_DELETE
10458 = XInternAtom (dpyinfo
->display
, "DELETE", False
);
10459 dpyinfo
->Xatom_MULTIPLE
10460 = XInternAtom (dpyinfo
->display
, "MULTIPLE", False
);
10461 dpyinfo
->Xatom_INCR
10462 = XInternAtom (dpyinfo
->display
, "INCR", False
);
10463 dpyinfo
->Xatom_EMACS_TMP
10464 = XInternAtom (dpyinfo
->display
, "_EMACS_TMP_", False
);
10465 dpyinfo
->Xatom_TARGETS
10466 = XInternAtom (dpyinfo
->display
, "TARGETS", False
);
10467 dpyinfo
->Xatom_NULL
10468 = XInternAtom (dpyinfo
->display
, "NULL", False
);
10469 dpyinfo
->Xatom_ATOM_PAIR
10470 = XInternAtom (dpyinfo
->display
, "ATOM_PAIR", False
);
10471 /* For properties of font. */
10472 dpyinfo
->Xatom_PIXEL_SIZE
10473 = XInternAtom (dpyinfo
->display
, "PIXEL_SIZE", False
);
10474 dpyinfo
->Xatom_MULE_BASELINE_OFFSET
10475 = XInternAtom (dpyinfo
->display
, "_MULE_BASELINE_OFFSET", False
);
10476 dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
10477 = XInternAtom (dpyinfo
->display
, "_MULE_RELATIVE_COMPOSE", False
);
10478 dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
10479 = XInternAtom (dpyinfo
->display
, "_MULE_DEFAULT_ASCENT", False
);
10481 /* Ghostscript support. */
10482 dpyinfo
->Xatom_PAGE
= XInternAtom (dpyinfo
->display
, "PAGE", False
);
10483 dpyinfo
->Xatom_DONE
= XInternAtom (dpyinfo
->display
, "DONE", False
);
10485 dpyinfo
->Xatom_Scrollbar
= XInternAtom (dpyinfo
->display
, "SCROLLBAR",
10488 dpyinfo
->cut_buffers_initialized
= 0;
10490 connection
= ConnectionNumber (dpyinfo
->display
);
10491 dpyinfo
->connection
= connection
;
10496 null_bits
[0] = 0x00;
10498 dpyinfo
->null_pixel
10499 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
10500 null_bits
, 1, 1, (long) 0, (long) 0,
10505 extern int gray_bitmap_width
, gray_bitmap_height
;
10506 extern char *gray_bitmap_bits
;
10508 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
10510 gray_bitmap_width
, gray_bitmap_height
,
10511 (unsigned long) 1, (unsigned long) 0, 1);
10515 xim_initialize (dpyinfo
, resource_name
);
10518 #ifdef subprocesses
10519 /* This is only needed for distinguishing keyboard and process input. */
10520 if (connection
!= 0)
10521 add_keyboard_wait_descriptor (connection
);
10524 #ifndef F_SETOWN_BUG
10526 #ifdef F_SETOWN_SOCK_NEG
10527 /* stdin is a socket here */
10528 fcntl (connection
, F_SETOWN
, -getpid ());
10529 #else /* ! defined (F_SETOWN_SOCK_NEG) */
10530 fcntl (connection
, F_SETOWN
, getpid ());
10531 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
10532 #endif /* ! defined (F_SETOWN) */
10533 #endif /* F_SETOWN_BUG */
10536 if (interrupt_input
)
10537 init_sigio (connection
);
10538 #endif /* ! defined (SIGIO) */
10541 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
10542 /* Make sure that we have a valid font for dialog boxes
10543 so that Xt does not crash. */
10545 Display
*dpy
= dpyinfo
->display
;
10546 XrmValue d
, fr
, to
;
10550 d
.addr
= (XPointer
)&dpy
;
10551 d
.size
= sizeof (Display
*);
10552 fr
.addr
= XtDefaultFont
;
10553 fr
.size
= sizeof (XtDefaultFont
);
10554 to
.size
= sizeof (Font
*);
10555 to
.addr
= (XPointer
)&font
;
10556 count
= x_catch_errors (dpy
);
10557 if (!XtCallConverter (dpy
, XtCvtStringToFont
, &d
, 1, &fr
, &to
, NULL
))
10559 if (x_had_errors_p (dpy
) || !XQueryFont (dpy
, font
))
10560 XrmPutLineResource (&xrdb
, "Emacs.dialog.*.font: 9x15");
10561 x_uncatch_errors (dpy
, count
);
10566 /* See if we should run in synchronous mode. This is useful
10567 for debugging X code. */
10570 value
= display_x_get_resource (dpyinfo
,
10571 build_string ("synchronous"),
10572 build_string ("Synchronous"),
10574 if (STRINGP (value
)
10575 && (!strcmp (SDATA (value
), "true")
10576 || !strcmp (SDATA (value
), "on")))
10577 XSynchronize (dpyinfo
->display
, True
);
10582 value
= display_x_get_resource (dpyinfo
,
10583 build_string ("useXIM"),
10584 build_string ("UseXIM"),
10587 if (STRINGP (value
)
10588 && (!strcmp (XSTRING (value
)->data
, "false")
10589 || !strcmp (XSTRING (value
)->data
, "off")))
10592 if (STRINGP (value
)
10593 && (!strcmp (XSTRING (value
)->data
, "true")
10594 || !strcmp (XSTRING (value
)->data
, "on")))
10600 /* Only do this for the first display. */
10601 if (x_initialized
== 1)
10602 x_session_initialize (dpyinfo
);
10610 /* Get rid of display DPYINFO, assuming all frames are already gone,
10611 and without sending any more commands to the X server. */
10614 x_delete_display (dpyinfo
)
10615 struct x_display_info
*dpyinfo
;
10620 /* Delete the generic struct display for this X display. */
10622 for (d
= display_list
; d
; d
= d
->next_display
)
10623 if (d
->type
== output_x_window
&& d
->display_info
.x
== dpyinfo
)
10625 delete_display (d
);
10630 delete_keyboard_wait_descriptor (dpyinfo
->connection
);
10632 /* Discard this display from x_display_name_list and x_display_list.
10633 We can't use Fdelq because that can quit. */
10634 if (! NILP (x_display_name_list
)
10635 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
10636 x_display_name_list
= XCDR (x_display_name_list
);
10641 tail
= x_display_name_list
;
10642 while (CONSP (tail
) && CONSP (XCDR (tail
)))
10644 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
10646 XSETCDR (tail
, XCDR (XCDR (tail
)));
10649 tail
= XCDR (tail
);
10653 if (next_noop_dpyinfo
== dpyinfo
)
10654 next_noop_dpyinfo
= dpyinfo
->next
;
10656 if (x_display_list
== dpyinfo
)
10657 x_display_list
= dpyinfo
->next
;
10660 struct x_display_info
*tail
;
10662 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
10663 if (tail
->next
== dpyinfo
)
10664 tail
->next
= tail
->next
->next
;
10667 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
10668 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
10669 XrmDestroyDatabase (dpyinfo
->xrdb
);
10672 #ifdef MULTI_KBOARD
10673 if (--dpyinfo
->kboard
->reference_count
== 0)
10674 delete_kboard (dpyinfo
->kboard
);
10678 xim_close_dpy (dpyinfo
);
10681 /* Free the font names in the font table. */
10682 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
10683 if (dpyinfo
->font_table
[i
].name
)
10685 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
10686 xfree (dpyinfo
->font_table
[i
].full_name
);
10687 xfree (dpyinfo
->font_table
[i
].name
);
10690 if (dpyinfo
->font_table
->font_encoder
)
10691 xfree (dpyinfo
->font_table
->font_encoder
);
10693 xfree (dpyinfo
->font_table
);
10694 xfree (dpyinfo
->x_id_name
);
10695 xfree (dpyinfo
->color_cells
);
10699 #ifdef USE_X_TOOLKIT
10701 /* Atimer callback function for TIMER. Called every 0.1s to process
10702 Xt timeouts, if needed. We must avoid calling XtAppPending as
10703 much as possible because that function does an implicit XFlush
10704 that slows us down. */
10707 x_process_timeouts (timer
)
10708 struct atimer
*timer
;
10710 if (toolkit_scroll_bar_interaction
|| popup_activated ())
10713 while (XtAppPending (Xt_app_con
) & XtIMTimer
)
10714 XtAppProcessEvent (Xt_app_con
, XtIMTimer
);
10719 #endif /* USE_X_TOOLKIT */
10722 /* Set up use of X before we make the first connection. */
10724 extern frame_parm_handler x_frame_parm_handlers
[];
10726 static struct redisplay_interface x_redisplay_interface
=
10728 x_frame_parm_handlers
,
10732 x_clear_end_of_line
,
10734 x_after_update_window_line
,
10735 x_update_window_begin
,
10736 x_update_window_end
,
10742 0, /* flush_display_optional */
10744 x_clear_window_mouse_face
,
10745 x_get_glyph_overhangs
,
10746 x_fix_overlapping_area
,
10747 x_draw_fringe_bitmap
,
10748 0, /* define_fringe_bitmap */
10749 0, /* destroy_fringe_bitmap */
10752 x_compute_glyph_string_overhangs
,
10753 x_draw_glyph_string
,
10754 x_define_frame_cursor
,
10755 x_clear_frame_area
,
10756 x_draw_window_cursor
,
10757 x_draw_vertical_window_border
,
10758 x_shift_glyphs_for_insert
10762 /* This function is called when the last frame on a display is deleted. */
10764 x_delete_frame_display (struct display
*display
)
10766 /* We don't do anything, the connection to the X server must remain
10772 x_create_frame_display (struct x_display_info
*dpyinfo
)
10774 struct display
*display
;
10776 display
= create_display ();
10778 display
->type
= output_x_window
;
10779 display
->display_info
.x
= dpyinfo
;
10780 dpyinfo
->frame_display
= display
;
10782 display
->clear_frame_hook
= x_clear_frame
;
10783 display
->ins_del_lines_hook
= x_ins_del_lines
;
10784 display
->delete_glyphs_hook
= x_delete_glyphs
;
10785 display
->ring_bell_hook
= XTring_bell
;
10786 display
->reset_terminal_modes_hook
= XTreset_terminal_modes
;
10787 display
->set_terminal_modes_hook
= XTset_terminal_modes
;
10788 display
->update_begin_hook
= x_update_begin
;
10789 display
->update_end_hook
= x_update_end
;
10790 display
->set_terminal_window_hook
= XTset_terminal_window
;
10791 display
->read_socket_hook
= XTread_socket
;
10792 display
->frame_up_to_date_hook
= XTframe_up_to_date
;
10793 display
->mouse_position_hook
= XTmouse_position
;
10794 display
->frame_rehighlight_hook
= XTframe_rehighlight
;
10795 display
->frame_raise_lower_hook
= XTframe_raise_lower
;
10796 display
->set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
10797 display
->condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
10798 display
->redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
10799 display
->judge_scroll_bars_hook
= XTjudge_scroll_bars
;
10801 display
->delete_frame_hook
= x_destroy_window
;
10802 display
->delete_display_hook
= x_delete_frame_display
;
10804 display
->rif
= &x_redisplay_interface
;
10805 display
->scroll_region_ok
= 1; /* We'll scroll partial frames. */
10806 display
->char_ins_del_ok
= 1;
10807 display
->line_ins_del_ok
= 1; /* We'll just blt 'em. */
10808 display
->fast_clear_end_of_line
= 1; /* X does this well. */
10809 display
->memory_below_frame
= 0; /* We don't remember what scrolls
10821 last_tool_bar_item
= -1;
10822 any_help_event_p
= 0;
10823 ignore_next_mouse_click_timeout
= 0;
10826 current_count
= -1;
10829 /* Try to use interrupt input; if we can't, then start polling. */
10830 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
10832 #ifdef USE_X_TOOLKIT
10833 XtToolkitInitialize ();
10835 Xt_app_con
= XtCreateApplicationContext ();
10837 /* Register a converter from strings to pixels, which uses
10838 Emacs' color allocation infrastructure. */
10839 XtAppSetTypeConverter (Xt_app_con
,
10840 XtRString
, XtRPixel
, cvt_string_to_pixel
,
10841 cvt_string_to_pixel_args
,
10842 XtNumber (cvt_string_to_pixel_args
),
10843 XtCacheByDisplay
, cvt_pixel_dtor
);
10845 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
10847 /* Install an asynchronous timer that processes Xt timeout events
10848 every 0.1s. This is necessary because some widget sets use
10849 timeouts internally, for example the LessTif menu bar, or the
10850 Xaw3d scroll bar. When Xt timouts aren't processed, these
10851 widgets don't behave normally. */
10853 EMACS_TIME interval
;
10854 EMACS_SET_SECS_USECS (interval
, 0, 100000);
10855 start_atimer (ATIMER_CONTINUOUS
, interval
, x_process_timeouts
, 0);
10859 #ifdef USE_TOOLKIT_SCROLL_BARS
10861 xaw3d_arrow_scroll
= False
;
10862 xaw3d_pick_top
= True
;
10866 /* Note that there is no real way portable across R3/R4 to get the
10867 original error handler. */
10868 XSetErrorHandler (x_error_handler
);
10869 XSetIOErrorHandler (x_io_error_quitter
);
10871 /* Disable Window Change signals; they are handled by X events. */
10873 signal (SIGWINCH
, SIG_DFL
);
10874 #endif /* SIGWINCH */
10876 signal (SIGPIPE
, x_connection_signal
);
10883 staticpro (&x_error_message_string
);
10884 x_error_message_string
= Qnil
;
10886 staticpro (&x_display_name_list
);
10887 x_display_name_list
= Qnil
;
10889 staticpro (&last_mouse_scroll_bar
);
10890 last_mouse_scroll_bar
= Qnil
;
10892 staticpro (&Qvendor_specific_keysyms
);
10893 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
10895 staticpro (&Qutf_8
);
10896 Qutf_8
= intern ("utf-8");
10897 staticpro (&Qlatin_1
);
10898 Qlatin_1
= intern ("latin-1");
10900 staticpro (&last_mouse_press_frame
);
10901 last_mouse_press_frame
= Qnil
;
10903 DEFVAR_BOOL ("x-use-underline-position-properties",
10904 &x_use_underline_position_properties
,
10905 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
10906 nil means ignore them. If you encounter fonts with bogus
10907 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
10908 to 4.1, set this to nil. */);
10909 x_use_underline_position_properties
= 1;
10911 DEFVAR_BOOL ("x-mouse-click-focus-ignore-position",
10912 &x_mouse_click_focus_ignore_position
,
10913 doc
: /* Non-nil means that a mouse click to focus a frame does not move point.
10914 This variable is only used when the window manager requires that you
10915 click on a frame to select it (give it focus). In that case, a value
10916 of nil, means that the selected window and cursor position changes to
10917 reflect the mouse click position, while a non-nil value means that the
10918 selected window or cursor position is preserved. */);
10919 x_mouse_click_focus_ignore_position
= 0;
10921 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
10922 doc
: /* What X toolkit scroll bars Emacs uses.
10923 A value of nil means Emacs doesn't use X toolkit scroll bars.
10924 Otherwise, value is a symbol describing the X toolkit. */);
10925 #ifdef USE_TOOLKIT_SCROLL_BARS
10927 Vx_toolkit_scroll_bars
= intern ("motif");
10928 #elif defined HAVE_XAW3D
10929 Vx_toolkit_scroll_bars
= intern ("xaw3d");
10931 Vx_toolkit_scroll_bars
= intern ("gtk");
10933 Vx_toolkit_scroll_bars
= intern ("xaw");
10936 Vx_toolkit_scroll_bars
= Qnil
;
10939 staticpro (&last_mouse_motion_frame
);
10940 last_mouse_motion_frame
= Qnil
;
10942 Qmodifier_value
= intern ("modifier-value");
10943 Qalt
= intern ("alt");
10944 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
10945 Qhyper
= intern ("hyper");
10946 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
10947 Qmeta
= intern ("meta");
10948 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
10949 Qsuper
= intern ("super");
10950 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
10952 DEFVAR_LISP ("x-alt-keysym", &Vx_alt_keysym
,
10953 doc
: /* Which keys Emacs uses for the alt modifier.
10954 This should be one of the symbols `alt', `hyper', `meta', `super'.
10955 For example, `alt' means use the Alt_L and Alt_R keysyms. The default
10956 is nil, which is the same as `alt'. */);
10957 Vx_alt_keysym
= Qnil
;
10959 DEFVAR_LISP ("x-hyper-keysym", &Vx_hyper_keysym
,
10960 doc
: /* Which keys Emacs uses for the hyper modifier.
10961 This should be one of the symbols `alt', `hyper', `meta', `super'.
10962 For example, `hyper' means use the Hyper_L and Hyper_R keysyms. The
10963 default is nil, which is the same as `hyper'. */);
10964 Vx_hyper_keysym
= Qnil
;
10966 DEFVAR_LISP ("x-meta-keysym", &Vx_meta_keysym
,
10967 doc
: /* Which keys Emacs uses for the meta modifier.
10968 This should be one of the symbols `alt', `hyper', `meta', `super'.
10969 For example, `meta' means use the Meta_L and Meta_R keysyms. The
10970 default is nil, which is the same as `meta'. */);
10971 Vx_meta_keysym
= Qnil
;
10973 DEFVAR_LISP ("x-super-keysym", &Vx_super_keysym
,
10974 doc
: /* Which keys Emacs uses for the super modifier.
10975 This should be one of the symbols `alt', `hyper', `meta', `super'.
10976 For example, `super' means use the Super_L and Super_R keysyms. The
10977 default is nil, which is the same as `super'. */);
10978 Vx_super_keysym
= Qnil
;
10980 DEFVAR_LISP ("x-keysym-table", &Vx_keysym_table
,
10981 doc
: /* Hash table of character codes indexed by X keysym codes. */);
10982 Vx_keysym_table
= make_hash_table (Qeql
, make_number (900),
10983 make_float (DEFAULT_REHASH_SIZE
),
10984 make_float (DEFAULT_REHASH_THRESHOLD
),
10988 #endif /* HAVE_X_WINDOWS */
10990 /* arch-tag: 6d4e4cb7-abc1-4302-9585-d84dcfb09d0f
10991 (do not change this comment) */