1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
3 2002, 2003, 2004, 2005 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_ ((struct frame
*));
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
*, int, 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 if (draw_window_fringes (w
, 1))
576 x_draw_vertical_border (w
);
581 /* If a row with mouse-face was overwritten, arrange for
582 XTframe_up_to_date to redisplay the mouse highlight. */
583 if (mouse_face_overwritten_p
)
585 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
586 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
587 dpyinfo
->mouse_face_window
= Qnil
;
590 updated_window
= NULL
;
594 /* End update of frame F. This function is installed as a hook in
601 /* Mouse highlight may be displayed again. */
602 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
606 XFlush (FRAME_X_DISPLAY (f
));
612 /* This function is called from various places in xdisp.c whenever a
613 complete update has been performed. The global variable
614 updated_window is not available here. */
617 XTframe_up_to_date (f
)
622 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
624 if (dpyinfo
->mouse_face_deferred_gc
625 || f
== dpyinfo
->mouse_face_mouse_frame
)
628 if (dpyinfo
->mouse_face_mouse_frame
)
629 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
630 dpyinfo
->mouse_face_mouse_x
,
631 dpyinfo
->mouse_face_mouse_y
);
632 dpyinfo
->mouse_face_deferred_gc
= 0;
639 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
640 arrow bitmaps, or clear the fringes if no bitmaps are required
641 before DESIRED_ROW is made current. The window being updated is
642 found in updated_window. This function It is called from
643 update_window_line only if it is known that there are differences
644 between bitmaps to be drawn between current row and DESIRED_ROW. */
647 x_after_update_window_line (desired_row
)
648 struct glyph_row
*desired_row
;
650 struct window
*w
= updated_window
;
656 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
657 desired_row
->redraw_fringe_bitmaps_p
= 1;
659 /* When a window has disappeared, make sure that no rest of
660 full-width rows stays visible in the internal border. Could
661 check here if updated_window is the leftmost/rightmost window,
662 but I guess it's not worth doing since vertically split windows
663 are almost never used, internal border is rarely set, and the
664 overhead is very small. */
665 if (windows_or_buffers_changed
666 && desired_row
->full_width_p
667 && (f
= XFRAME (w
->frame
),
668 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
670 && (height
= desired_row
->visible_height
,
673 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
675 /* Internal border is drawn below the tool bar. */
676 if (WINDOWP (f
->tool_bar_window
)
677 && w
== XWINDOW (f
->tool_bar_window
))
681 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
682 0, y
, width
, height
, False
);
683 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
684 FRAME_PIXEL_WIDTH (f
) - width
,
685 y
, width
, height
, False
);
691 x_draw_fringe_bitmap (w
, row
, p
)
693 struct glyph_row
*row
;
694 struct draw_fringe_bitmap_params
*p
;
696 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
697 Display
*display
= FRAME_X_DISPLAY (f
);
698 Window window
= FRAME_X_WINDOW (f
);
699 GC gc
= f
->output_data
.x
->normal_gc
;
700 struct face
*face
= p
->face
;
703 /* Must clip because of partially visible lines. */
704 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
707 /* Adjust position of "bottom aligned" bitmap on partially
710 int oldVH
= row
->visible_height
;
711 row
->visible_height
= p
->h
;
712 row
->y
-= rowY
- p
->y
;
713 x_clip_to_row (w
, row
, -1, gc
);
715 row
->visible_height
= oldVH
;
718 x_clip_to_row (w
, row
, -1, gc
);
720 if (p
->bx
>= 0 && !p
->overlay_p
)
722 /* In case the same realized face is used for fringes and
723 for something displayed in the text (e.g. face `region' on
724 mono-displays, the fill style may have been changed to
725 FillSolid in x_draw_glyph_string_background. */
727 XSetFillStyle (display
, face
->gc
, FillOpaqueStippled
);
729 XSetForeground (display
, face
->gc
, face
->background
);
731 XFillRectangle (display
, window
, face
->gc
,
732 p
->bx
, p
->by
, p
->nx
, p
->ny
);
735 XSetForeground (display
, face
->gc
, face
->foreground
);
741 Pixmap pixmap
, clipmask
= (Pixmap
) 0;
742 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
746 bits
= (unsigned char *)(p
->bits
+ p
->dh
);
748 bits
= (unsigned char *)p
->bits
+ p
->dh
;
750 /* Draw the bitmap. I believe these small pixmaps can be cached
752 pixmap
= XCreatePixmapFromBitmapData (display
, window
, bits
, p
->wd
, p
->h
,
754 ? (p
->overlay_p
? face
->background
755 : f
->output_data
.x
->cursor_pixel
)
757 face
->background
, depth
);
761 clipmask
= XCreatePixmapFromBitmapData (display
,
762 FRAME_X_DISPLAY_INFO (f
)->root_window
,
765 gcv
.clip_mask
= clipmask
;
766 gcv
.clip_x_origin
= p
->x
;
767 gcv
.clip_y_origin
= p
->y
;
768 XChangeGC (display
, gc
, GCClipMask
| GCClipXOrigin
| GCClipYOrigin
, &gcv
);
771 XCopyArea (display
, pixmap
, window
, gc
, 0, 0,
772 p
->wd
, p
->h
, p
->x
, p
->y
);
773 XFreePixmap (display
, pixmap
);
777 gcv
.clip_mask
= (Pixmap
) 0;
778 XChangeGC (display
, gc
, GCClipMask
, &gcv
);
779 XFreePixmap (display
, clipmask
);
783 XSetClipMask (display
, gc
, None
);
788 /* This is called when starting Emacs and when restarting after
789 suspend. When starting Emacs, no X window is mapped. And nothing
790 must be done to Emacs's own window if it is suspended (though that
794 XTset_terminal_modes (struct display
*display
)
798 /* This is called when exiting or suspending Emacs. Exiting will make
799 the X-windows go away, and suspending requires no action. */
802 XTreset_terminal_modes (struct display
*display
)
808 /***********************************************************************
810 ***********************************************************************/
812 /* Function prototypes of this page. */
814 static int x_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
817 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
818 is not contained in the font. */
821 x_per_char_metric (font
, char2b
, font_type
)
824 int font_type
; /* unused on X */
826 /* The result metric information. */
827 XCharStruct
*pcm
= NULL
;
829 xassert (font
&& char2b
);
831 if (font
->per_char
!= NULL
)
833 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
835 /* min_char_or_byte2 specifies the linear character index
836 corresponding to the first element of the per_char array,
837 max_char_or_byte2 is the index of the last character. A
838 character with non-zero CHAR2B->byte1 is not in the font.
839 A character with byte2 less than min_char_or_byte2 or
840 greater max_char_or_byte2 is not in the font. */
841 if (char2b
->byte1
== 0
842 && char2b
->byte2
>= font
->min_char_or_byte2
843 && char2b
->byte2
<= font
->max_char_or_byte2
)
844 pcm
= font
->per_char
+ char2b
->byte2
- font
->min_char_or_byte2
;
848 /* If either min_byte1 or max_byte1 are nonzero, both
849 min_char_or_byte2 and max_char_or_byte2 are less than
850 256, and the 2-byte character index values corresponding
851 to the per_char array element N (counting from 0) are:
853 byte1 = N/D + min_byte1
854 byte2 = N\D + min_char_or_byte2
858 D = max_char_or_byte2 - min_char_or_byte2 + 1
860 \ = integer modulus */
861 if (char2b
->byte1
>= font
->min_byte1
862 && char2b
->byte1
<= font
->max_byte1
863 && char2b
->byte2
>= font
->min_char_or_byte2
864 && char2b
->byte2
<= font
->max_char_or_byte2
)
866 pcm
= (font
->per_char
867 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
868 * (char2b
->byte1
- font
->min_byte1
))
869 + (char2b
->byte2
- font
->min_char_or_byte2
));
875 /* If the per_char pointer is null, all glyphs between the first
876 and last character indexes inclusive have the same
877 information, as given by both min_bounds and max_bounds. */
878 if (char2b
->byte2
>= font
->min_char_or_byte2
879 && char2b
->byte2
<= font
->max_char_or_byte2
)
880 pcm
= &font
->max_bounds
;
884 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
889 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
890 the two-byte form of C. Encoding is returned in *CHAR2B. */
893 x_encode_char (c
, char2b
, font_info
, two_byte_p
)
896 struct font_info
*font_info
;
899 int charset
= CHAR_CHARSET (c
);
900 XFontStruct
*font
= font_info
->font
;
902 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
903 This may be either a program in a special encoder language or a
905 if (font_info
->font_encoder
)
907 /* It's a program. */
908 struct ccl_program
*ccl
= font_info
->font_encoder
;
910 if (CHARSET_DIMENSION (charset
) == 1)
912 ccl
->reg
[0] = charset
;
913 ccl
->reg
[1] = char2b
->byte2
;
918 ccl
->reg
[0] = charset
;
919 ccl
->reg
[1] = char2b
->byte1
;
920 ccl
->reg
[2] = char2b
->byte2
;
923 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
925 /* We assume that MSBs are appropriately set/reset by CCL
927 if (font
->max_byte1
== 0) /* 1-byte font */
928 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
930 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
932 else if (font_info
->encoding
[charset
])
934 /* Fixed encoding scheme. See fontset.h for the meaning of the
936 int enc
= font_info
->encoding
[charset
];
938 if ((enc
== 1 || enc
== 2)
939 && CHARSET_DIMENSION (charset
) == 2)
940 char2b
->byte1
|= 0x80;
942 if (enc
== 1 || enc
== 3)
943 char2b
->byte2
|= 0x80;
947 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
949 return FONT_TYPE_UNKNOWN
;
954 /***********************************************************************
956 ***********************************************************************/
960 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
961 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
962 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
964 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
965 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
966 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
967 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
968 static void x_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
969 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
970 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
971 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
972 static int x_alloc_lighter_color
P_ ((struct frame
*, Display
*, Colormap
,
973 unsigned long *, double, int));
974 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
975 double, int, unsigned long));
976 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
977 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
978 static void x_draw_image_relief
P_ ((struct glyph_string
*));
979 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
980 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
981 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
983 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
984 int, int, int, int, int, int,
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
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
2026 int left_x
, top_y
, right_x
, bottom_y
, width
;
2027 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
2028 XRectangle
*clip_rect
;
2030 Display
*dpy
= FRAME_X_DISPLAY (f
);
2031 Window window
= FRAME_X_WINDOW (f
);
2036 gc
= f
->output_data
.x
->white_relief
.gc
;
2038 gc
= f
->output_data
.x
->black_relief
.gc
;
2039 XSetClipRectangles (dpy
, gc
, 0, 0, clip_rect
, 1, Unsorted
);
2043 for (i
= 0; i
< width
; ++i
)
2044 XDrawLine (dpy
, window
, gc
,
2045 left_x
+ i
* left_p
, top_y
+ i
,
2046 right_x
+ 1 - i
* right_p
, top_y
+ i
);
2050 for (i
= 0; i
< width
; ++i
)
2051 XDrawLine (dpy
, window
, gc
,
2052 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
+ 1);
2054 XSetClipMask (dpy
, gc
, None
);
2056 gc
= f
->output_data
.x
->black_relief
.gc
;
2058 gc
= f
->output_data
.x
->white_relief
.gc
;
2059 XSetClipRectangles (dpy
, gc
, 0, 0, clip_rect
, 1, Unsorted
);
2063 for (i
= 0; i
< width
; ++i
)
2064 XDrawLine (dpy
, window
, gc
,
2065 left_x
+ i
* left_p
, bottom_y
- i
,
2066 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
2070 for (i
= 0; i
< width
; ++i
)
2071 XDrawLine (dpy
, window
, gc
,
2072 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
2074 XSetClipMask (dpy
, gc
, None
);
2078 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2079 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2080 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2081 left side of the rectangle. RIGHT_P non-zero means draw a line
2082 on the right side of the rectangle. CLIP_RECT is the clipping
2083 rectangle to use when drawing. */
2086 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2087 left_p
, right_p
, clip_rect
)
2088 struct glyph_string
*s
;
2089 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
2090 XRectangle
*clip_rect
;
2094 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2095 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
2096 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, clip_rect
, 1, Unsorted
);
2099 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2100 left_x
, top_y
, right_x
- left_x
+ 1, width
);
2104 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2105 left_x
, top_y
, width
, bottom_y
- top_y
+ 1);
2108 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2109 left_x
, bottom_y
- width
+ 1, right_x
- left_x
+ 1, width
);
2113 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2114 right_x
- width
+ 1, top_y
, width
, bottom_y
- top_y
+ 1);
2116 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2117 XSetClipMask (s
->display
, s
->gc
, None
);
2121 /* Draw a box around glyph string S. */
2124 x_draw_glyph_string_box (s
)
2125 struct glyph_string
*s
;
2127 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
2128 int left_p
, right_p
;
2129 struct glyph
*last_glyph
;
2130 XRectangle clip_rect
;
2132 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
2133 ? WINDOW_RIGHT_EDGE_X (s
->w
)
2134 : window_box_right (s
->w
, s
->area
));
2136 /* The glyph that may have a right box line. */
2137 last_glyph
= (s
->cmp
|| s
->img
2139 : s
->first_glyph
+ s
->nchars
- 1);
2141 width
= abs (s
->face
->box_line_width
);
2142 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
2144 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2146 : min (last_x
, s
->x
+ s
->background_width
) - 1);
2148 bottom_y
= top_y
+ s
->height
- 1;
2150 left_p
= (s
->first_glyph
->left_box_line_p
2151 || (s
->hl
== DRAW_MOUSE_FACE
2153 || s
->prev
->hl
!= s
->hl
)));
2154 right_p
= (last_glyph
->right_box_line_p
2155 || (s
->hl
== DRAW_MOUSE_FACE
2157 || s
->next
->hl
!= s
->hl
)));
2159 get_glyph_string_clip_rect (s
, &clip_rect
);
2161 if (s
->face
->box
== FACE_SIMPLE_BOX
)
2162 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2163 left_p
, right_p
, &clip_rect
);
2166 x_setup_relief_colors (s
);
2167 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
2168 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
2173 /* Draw foreground of image glyph string S. */
2176 x_draw_image_foreground (s
)
2177 struct glyph_string
*s
;
2180 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2182 /* If first glyph of S has a left box line, start drawing it to the
2183 right of that line. */
2184 if (s
->face
->box
!= FACE_NO_BOX
2185 && s
->first_glyph
->left_box_line_p
2187 x
+= abs (s
->face
->box_line_width
);
2189 /* If there is a margin around the image, adjust x- and y-position
2191 if (s
->slice
.x
== 0)
2192 x
+= s
->img
->hmargin
;
2193 if (s
->slice
.y
== 0)
2194 y
+= s
->img
->vmargin
;
2200 /* We can't set both a clip mask and use XSetClipRectangles
2201 because the latter also sets a clip mask. We also can't
2202 trust on the shape extension to be available
2203 (XShapeCombineRegion). So, compute the rectangle to draw
2205 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
2208 XRectangle clip_rect
, image_rect
, r
;
2210 xgcv
.clip_mask
= s
->img
->mask
;
2211 xgcv
.clip_x_origin
= x
;
2212 xgcv
.clip_y_origin
= y
;
2213 xgcv
.function
= GXcopy
;
2214 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
2216 get_glyph_string_clip_rect (s
, &clip_rect
);
2219 image_rect
.width
= s
->slice
.width
;
2220 image_rect
.height
= s
->slice
.height
;
2221 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
2222 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
2223 s
->slice
.x
+ r
.x
- x
, s
->slice
.y
+ r
.y
- y
,
2224 r
.width
, r
.height
, r
.x
, r
.y
);
2228 XRectangle clip_rect
, image_rect
, r
;
2230 get_glyph_string_clip_rect (s
, &clip_rect
);
2233 image_rect
.width
= s
->slice
.width
;
2234 image_rect
.height
= s
->slice
.height
;
2235 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
2236 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
2237 s
->slice
.x
+ r
.x
- x
, s
->slice
.y
+ r
.y
- y
,
2238 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
,
2252 s
->slice
.width
+ r
*2 - 1,
2253 s
->slice
.height
+ r
*2 - 1);
2258 /* Draw a rectangle if image could not be loaded. */
2259 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
2260 s
->slice
.width
- 1, s
->slice
.height
- 1);
2264 /* Draw a relief around the image glyph string S. */
2267 x_draw_image_relief (s
)
2268 struct glyph_string
*s
;
2270 int x0
, y0
, x1
, y1
, thick
, raised_p
;
2273 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2275 /* If first glyph of S has a left box line, start drawing it to the
2276 right of that line. */
2277 if (s
->face
->box
!= FACE_NO_BOX
2278 && s
->first_glyph
->left_box_line_p
2280 x
+= abs (s
->face
->box_line_width
);
2282 /* If there is a margin around the image, adjust x- and y-position
2284 if (s
->slice
.x
== 0)
2285 x
+= s
->img
->hmargin
;
2286 if (s
->slice
.y
== 0)
2287 y
+= s
->img
->vmargin
;
2289 if (s
->hl
== DRAW_IMAGE_SUNKEN
2290 || s
->hl
== DRAW_IMAGE_RAISED
)
2292 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
2293 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
2297 thick
= abs (s
->img
->relief
);
2298 raised_p
= s
->img
->relief
> 0;
2303 x1
= x
+ s
->slice
.width
+ thick
- 1;
2304 y1
= y
+ s
->slice
.height
+ thick
- 1;
2306 x_setup_relief_colors (s
);
2307 get_glyph_string_clip_rect (s
, &r
);
2308 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
2310 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
2312 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
2317 /* Draw the foreground of image glyph string S to PIXMAP. */
2320 x_draw_image_foreground_1 (s
, pixmap
)
2321 struct glyph_string
*s
;
2325 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2327 /* If first glyph of S has a left box line, start drawing it to the
2328 right of that line. */
2329 if (s
->face
->box
!= FACE_NO_BOX
2330 && s
->first_glyph
->left_box_line_p
2332 x
+= abs (s
->face
->box_line_width
);
2334 /* If there is a margin around the image, adjust x- and y-position
2336 if (s
->slice
.x
== 0)
2337 x
+= s
->img
->hmargin
;
2338 if (s
->slice
.y
== 0)
2339 y
+= s
->img
->vmargin
;
2345 /* We can't set both a clip mask and use XSetClipRectangles
2346 because the latter also sets a clip mask. We also can't
2347 trust on the shape extension to be available
2348 (XShapeCombineRegion). So, compute the rectangle to draw
2350 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
2354 xgcv
.clip_mask
= s
->img
->mask
;
2355 xgcv
.clip_x_origin
= x
- s
->slice
.x
;
2356 xgcv
.clip_y_origin
= y
- s
->slice
.y
;
2357 xgcv
.function
= GXcopy
;
2358 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
2360 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
2361 s
->slice
.x
, s
->slice
.y
,
2362 s
->slice
.width
, s
->slice
.height
, x
, y
);
2363 XSetClipMask (s
->display
, s
->gc
, None
);
2367 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
2368 s
->slice
.x
, s
->slice
.y
,
2369 s
->slice
.width
, s
->slice
.height
, x
, y
);
2371 /* When the image has a mask, we can expect that at
2372 least part of a mouse highlight or a block cursor will
2373 be visible. If the image doesn't have a mask, make
2374 a block cursor visible by drawing a rectangle around
2375 the image. I believe it's looking better if we do
2376 nothing here for mouse-face. */
2377 if (s
->hl
== DRAW_CURSOR
)
2379 int r
= s
->img
->relief
;
2381 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
- r
, y
- r
,
2382 s
->slice
.width
+ r
*2 - 1,
2383 s
->slice
.height
+ r
*2 - 1);
2388 /* Draw a rectangle if image could not be loaded. */
2389 XDrawRectangle (s
->display
, pixmap
, s
->gc
, x
, y
,
2390 s
->slice
.width
- 1, s
->slice
.height
- 1);
2394 /* Draw part of the background of glyph string S. X, Y, W, and H
2395 give the rectangle to draw. */
2398 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
2399 struct glyph_string
*s
;
2404 /* Fill background with a stipple pattern. */
2405 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2406 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
2407 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2410 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
2414 /* Draw image glyph string S.
2417 s->x +-------------------------
2420 | +-------------------------
2423 | | +-------------------
2429 x_draw_image_glyph_string (s
)
2430 struct glyph_string
*s
;
2432 int box_line_hwidth
= abs (s
->face
->box_line_width
);
2433 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
2435 Pixmap pixmap
= None
;
2438 if (s
->slice
.y
== 0)
2439 height
-= box_line_vwidth
;
2440 if (s
->slice
.y
+ s
->slice
.height
>= s
->img
->height
)
2441 height
-= box_line_vwidth
;
2443 /* Fill background with face under the image. Do it only if row is
2444 taller than image or if image has a clip mask to reduce
2446 s
->stippled_p
= s
->face
->stipple
!= 0;
2447 if (height
> s
->slice
.height
2451 || s
->img
->pixmap
== 0
2452 || s
->width
!= s
->background_width
)
2456 /* Create a pixmap as large as the glyph string. Fill it
2457 with the background color. Copy the image to it, using
2458 its mask. Copy the temporary pixmap to the display. */
2459 Screen
*screen
= FRAME_X_SCREEN (s
->f
);
2460 int depth
= DefaultDepthOfScreen (screen
);
2462 /* Create a pixmap as large as the glyph string. */
2463 pixmap
= XCreatePixmap (s
->display
, s
->window
,
2464 s
->background_width
,
2467 /* Don't clip in the following because we're working on the
2469 XSetClipMask (s
->display
, s
->gc
, None
);
2471 /* Fill the pixmap with the background color/stipple. */
2474 /* Fill background with a stipple pattern. */
2475 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2476 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2477 0, 0, s
->background_width
, s
->height
);
2478 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2483 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
2485 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
2486 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2487 0, 0, s
->background_width
, s
->height
);
2488 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2496 if (s
->first_glyph
->left_box_line_p
2498 x
+= box_line_hwidth
;
2500 if (s
->slice
.y
== 0)
2501 y
+= box_line_vwidth
;
2503 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
2506 s
->background_filled_p
= 1;
2509 /* Draw the foreground. */
2512 x_draw_image_foreground_1 (s
, pixmap
);
2513 x_set_glyph_string_clipping (s
);
2514 XCopyArea (s
->display
, pixmap
, s
->window
, s
->gc
,
2515 0, 0, s
->background_width
, s
->height
, s
->x
, s
->y
);
2516 XFreePixmap (s
->display
, pixmap
);
2519 x_draw_image_foreground (s
);
2521 /* If we must draw a relief around the image, do it. */
2523 || s
->hl
== DRAW_IMAGE_RAISED
2524 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2525 x_draw_image_relief (s
);
2529 /* Draw stretch glyph string S. */
2532 x_draw_stretch_glyph_string (s
)
2533 struct glyph_string
*s
;
2535 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
2536 s
->stippled_p
= s
->face
->stipple
!= 0;
2538 if (s
->hl
== DRAW_CURSOR
2539 && !x_stretch_cursor_p
)
2541 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
2542 as wide as the stretch glyph. */
2543 int width
= min (FRAME_COLUMN_WIDTH (s
->f
), s
->background_width
);
2546 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
2548 /* Clear rest using the GC of the original non-cursor face. */
2549 if (width
< s
->background_width
)
2551 int x
= s
->x
+ width
, y
= s
->y
;
2552 int w
= s
->background_width
- width
, h
= s
->height
;
2556 if (s
->row
->mouse_face_p
2557 && cursor_in_mouse_face_p (s
->w
))
2559 x_set_mouse_face_gc (s
);
2565 get_glyph_string_clip_rect (s
, &r
);
2566 XSetClipRectangles (s
->display
, gc
, 0, 0, &r
, 1, Unsorted
);
2568 if (s
->face
->stipple
)
2570 /* Fill background with a stipple pattern. */
2571 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
2572 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
2573 XSetFillStyle (s
->display
, gc
, FillSolid
);
2578 XGetGCValues (s
->display
, gc
, GCForeground
| GCBackground
, &xgcv
);
2579 XSetForeground (s
->display
, gc
, xgcv
.background
);
2580 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
2581 XSetForeground (s
->display
, gc
, xgcv
.foreground
);
2585 else if (!s
->background_filled_p
)
2586 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
2589 s
->background_filled_p
= 1;
2593 /* Draw glyph string S. */
2596 x_draw_glyph_string (s
)
2597 struct glyph_string
*s
;
2599 int relief_drawn_p
= 0;
2601 /* If S draws into the background of its successor, draw the
2602 background of the successor first so that S can draw into it.
2603 This makes S->next use XDrawString instead of XDrawImageString. */
2604 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps_p
)
2606 xassert (s
->next
->img
== NULL
);
2607 x_set_glyph_string_gc (s
->next
);
2608 x_set_glyph_string_clipping (s
->next
);
2609 x_draw_glyph_string_background (s
->next
, 1);
2612 /* Set up S->gc, set clipping and draw S. */
2613 x_set_glyph_string_gc (s
);
2615 /* Draw relief (if any) in advance for char/composition so that the
2616 glyph string can be drawn over it. */
2617 if (!s
->for_overlaps_p
2618 && s
->face
->box
!= FACE_NO_BOX
2619 && (s
->first_glyph
->type
== CHAR_GLYPH
2620 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
2623 x_set_glyph_string_clipping (s
);
2624 x_draw_glyph_string_background (s
, 1);
2625 x_draw_glyph_string_box (s
);
2626 x_set_glyph_string_clipping (s
);
2630 x_set_glyph_string_clipping (s
);
2632 switch (s
->first_glyph
->type
)
2635 x_draw_image_glyph_string (s
);
2639 x_draw_stretch_glyph_string (s
);
2643 if (s
->for_overlaps_p
)
2644 s
->background_filled_p
= 1;
2646 x_draw_glyph_string_background (s
, 0);
2647 x_draw_glyph_string_foreground (s
);
2650 case COMPOSITE_GLYPH
:
2651 if (s
->for_overlaps_p
|| s
->gidx
> 0)
2652 s
->background_filled_p
= 1;
2654 x_draw_glyph_string_background (s
, 1);
2655 x_draw_composite_glyph_string_foreground (s
);
2662 if (!s
->for_overlaps_p
)
2664 /* Draw underline. */
2665 if (s
->face
->underline_p
)
2667 unsigned long tem
, h
;
2670 /* Get the underline thickness. Default is 1 pixel. */
2671 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_THICKNESS
, &h
))
2674 /* Get the underline position. This is the recommended
2675 vertical offset in pixels from the baseline to the top of
2676 the underline. This is a signed value according to the
2677 specs, and its default is
2679 ROUND ((maximum descent) / 2), with
2680 ROUND(x) = floor (x + 0.5) */
2682 if (x_use_underline_position_properties
2683 && XGetFontProperty (s
->font
, XA_UNDERLINE_POSITION
, &tem
))
2684 y
= s
->ybase
+ (long) tem
;
2685 else if (s
->face
->font
)
2686 y
= s
->ybase
+ (s
->face
->font
->max_bounds
.descent
+ 1) / 2;
2688 y
= s
->y
+ s
->height
- h
;
2690 if (s
->face
->underline_defaulted_p
)
2691 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2692 s
->x
, y
, s
->width
, h
);
2696 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2697 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
2698 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2699 s
->x
, y
, s
->width
, h
);
2700 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2704 /* Draw overline. */
2705 if (s
->face
->overline_p
)
2707 unsigned long dy
= 0, h
= 1;
2709 if (s
->face
->overline_color_defaulted_p
)
2710 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2715 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2716 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
2717 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2719 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2723 /* Draw strike-through. */
2724 if (s
->face
->strike_through_p
)
2726 unsigned long h
= 1;
2727 unsigned long dy
= (s
->height
- h
) / 2;
2729 if (s
->face
->strike_through_color_defaulted_p
)
2730 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2735 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2736 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
2737 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2739 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2743 /* Draw relief if not yet drawn. */
2744 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
2745 x_draw_glyph_string_box (s
);
2748 /* Reset clipping. */
2749 XSetClipMask (s
->display
, s
->gc
, None
);
2752 /* Shift display to make room for inserted glyphs. */
2755 x_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
2757 int x
, y
, width
, height
, shift_by
;
2759 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
2760 f
->output_data
.x
->normal_gc
,
2761 x
, y
, width
, height
,
2765 /* Delete N glyphs at the nominal cursor position. Not implemented
2769 x_delete_glyphs (f
, n
)
2777 /* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
2778 If they are <= 0, this is probably an error. */
2781 x_clear_area (dpy
, window
, x
, y
, width
, height
, exposures
)
2788 xassert (width
> 0 && height
> 0);
2789 XClearArea (dpy
, window
, x
, y
, width
, height
, exposures
);
2793 /* Clear an entire frame. */
2796 x_clear_frame (struct frame
*f
)
2798 /* Clearing the frame will erase any cursor, so mark them all as no
2800 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
2801 output_cursor
.hpos
= output_cursor
.vpos
= 0;
2802 output_cursor
.x
= -1;
2804 /* We don't set the output cursor here because there will always
2805 follow an explicit cursor_to. */
2807 XClearWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
2809 /* We have to clear the scroll bars, too. If we have changed
2810 colors or something like that, then they should be notified. */
2811 x_scroll_bar_clear (f
);
2813 XFlush (FRAME_X_DISPLAY (f
));
2820 /* Invert the middle quarter of the frame for .15 sec. */
2822 /* We use the select system call to do the waiting, so we have to make
2823 sure it's available. If it isn't, we just won't do visual bells. */
2825 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
2828 /* Subtract the `struct timeval' values X and Y, storing the result in
2829 *RESULT. Return 1 if the difference is negative, otherwise 0. */
2832 timeval_subtract (result
, x
, y
)
2833 struct timeval
*result
, x
, y
;
2835 /* Perform the carry for the later subtraction by updating y. This
2836 is safer because on some systems the tv_sec member is unsigned. */
2837 if (x
.tv_usec
< y
.tv_usec
)
2839 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
2840 y
.tv_usec
-= 1000000 * nsec
;
2844 if (x
.tv_usec
- y
.tv_usec
> 1000000)
2846 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
2847 y
.tv_usec
+= 1000000 * nsec
;
2851 /* Compute the time remaining to wait. tv_usec is certainly
2853 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
2854 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
2856 /* Return indication of whether the result should be considered
2858 return x
.tv_sec
< y
.tv_sec
;
2870 /* Create a GC that will use the GXxor function to flip foreground
2871 pixels into background pixels. */
2875 values
.function
= GXxor
;
2876 values
.foreground
= (f
->output_data
.x
->foreground_pixel
2877 ^ f
->output_data
.x
->background_pixel
);
2879 gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2880 GCFunction
| GCForeground
, &values
);
2884 /* Get the height not including a menu bar widget. */
2885 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
2886 /* Height of each line to flash. */
2887 int flash_height
= FRAME_LINE_HEIGHT (f
);
2888 /* These will be the left and right margins of the rectangles. */
2889 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
2890 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
2894 /* Don't flash the area between a scroll bar and the frame
2895 edge it is next to. */
2896 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
2898 case vertical_scroll_bar_left
:
2899 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
2902 case vertical_scroll_bar_right
:
2903 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
2910 width
= flash_right
- flash_left
;
2912 /* If window is tall, flash top and bottom line. */
2913 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
2915 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
2917 (FRAME_INTERNAL_BORDER_WIDTH (f
)
2918 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
2919 width
, flash_height
);
2920 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
2922 (height
- flash_height
2923 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
2924 width
, flash_height
);
2927 /* If it is short, flash it all. */
2928 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
2929 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
2930 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
2935 struct timeval wakeup
;
2937 EMACS_GET_TIME (wakeup
);
2939 /* Compute time to wait until, propagating carry from usecs. */
2940 wakeup
.tv_usec
+= 150000;
2941 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
2942 wakeup
.tv_usec
%= 1000000;
2944 /* Keep waiting until past the time wakeup or any input gets
2946 while (! detect_input_pending ())
2948 struct timeval current
;
2949 struct timeval timeout
;
2951 EMACS_GET_TIME (current
);
2953 /* Break if result would be negative. */
2954 if (timeval_subtract (¤t
, wakeup
, current
))
2957 /* How long `select' should wait. */
2959 timeout
.tv_usec
= 10000;
2961 /* Try to wait that long--but we might wake up sooner. */
2962 select (0, NULL
, NULL
, NULL
, &timeout
);
2966 /* If window is tall, flash top and bottom line. */
2967 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
2969 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
2971 (FRAME_INTERNAL_BORDER_WIDTH (f
)
2972 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
2973 width
, flash_height
);
2974 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
2976 (height
- flash_height
2977 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
2978 width
, flash_height
);
2981 /* If it is short, flash it all. */
2982 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
2983 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
2984 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
2986 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
2994 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
2997 /* Make audible bell. */
3002 struct frame
*f
= SELECTED_FRAME ();
3004 if (FRAME_X_DISPLAY (f
))
3006 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3013 XBell (FRAME_X_DISPLAY (f
), 0);
3014 XFlush (FRAME_X_DISPLAY (f
));
3021 /* Specify how many text lines, from the top of the window,
3022 should be affected by insert-lines and delete-lines operations.
3023 This, and those operations, are used only within an update
3024 that is bounded by calls to x_update_begin and x_update_end. */
3027 XTset_terminal_window (n
)
3030 /* This function intentionally left blank. */
3035 /***********************************************************************
3037 ***********************************************************************/
3039 /* Perform an insert-lines or delete-lines operation, inserting N
3040 lines or deleting -N lines at vertical position VPOS. */
3043 x_ins_del_lines (f
, vpos
, n
)
3051 /* Scroll part of the display as described by RUN. */
3054 x_scroll_run (w
, run
)
3058 struct frame
*f
= XFRAME (w
->frame
);
3059 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
3061 /* Get frame-relative bounding box of the text display area of W,
3062 without mode lines. Include in this box the left and right
3064 window_box (w
, -1, &x
, &y
, &width
, &height
);
3066 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
3067 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
3068 bottom_y
= y
+ height
;
3072 /* Scrolling up. Make sure we don't copy part of the mode
3073 line at the bottom. */
3074 if (from_y
+ run
->height
> bottom_y
)
3075 height
= bottom_y
- from_y
;
3077 height
= run
->height
;
3081 /* Scolling down. Make sure we don't copy over the mode line.
3083 if (to_y
+ run
->height
> bottom_y
)
3084 height
= bottom_y
- to_y
;
3086 height
= run
->height
;
3091 /* Cursor off. Will be switched on again in x_update_window_end. */
3095 XCopyArea (FRAME_X_DISPLAY (f
),
3096 FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
3097 f
->output_data
.x
->normal_gc
,
3107 /***********************************************************************
3109 ***********************************************************************/
3116 /* We used to only do this if Vx_no_window_manager was non-nil, but
3117 the ICCCM (section 4.1.6) says that the window's border pixmap
3118 and border pixel are window attributes which are "private to the
3119 client", so we can always change it to whatever we want. */
3121 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3122 f
->output_data
.x
->border_pixel
);
3124 x_update_cursor (f
, 1);
3128 frame_unhighlight (f
)
3131 /* We used to only do this if Vx_no_window_manager was non-nil, but
3132 the ICCCM (section 4.1.6) says that the window's border pixmap
3133 and border pixel are window attributes which are "private to the
3134 client", so we can always change it to whatever we want. */
3136 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3137 f
->output_data
.x
->border_tile
);
3139 x_update_cursor (f
, 1);
3142 /* The focus has changed. Update the frames as necessary to reflect
3143 the new situation. Note that we can't change the selected frame
3144 here, because the Lisp code we are interrupting might become confused.
3145 Each event gets marked with the frame in which it occurred, so the
3146 Lisp code can tell when the switch took place by examining the events. */
3149 x_new_focus_frame (dpyinfo
, frame
)
3150 struct x_display_info
*dpyinfo
;
3151 struct frame
*frame
;
3153 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
3155 if (frame
!= dpyinfo
->x_focus_frame
)
3157 /* Set this before calling other routines, so that they see
3158 the correct value of x_focus_frame. */
3159 dpyinfo
->x_focus_frame
= frame
;
3161 if (old_focus
&& old_focus
->auto_lower
)
3162 x_lower_frame (old_focus
);
3165 selected_frame
= frame
;
3166 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
3168 Fselect_window (selected_frame
->selected_window
, Qnil
);
3169 choose_minibuf_frame ();
3172 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
3173 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
3175 pending_autoraise_frame
= 0;
3178 x_frame_rehighlight (dpyinfo
);
3181 /* Handle FocusIn and FocusOut state changes for FRAME.
3182 If FRAME has focus and there exists more than one frame, puts
3183 a FOCUS_IN_EVENT into *BUFP. */
3186 x_focus_changed (type
, state
, dpyinfo
, frame
, bufp
)
3189 struct x_display_info
*dpyinfo
;
3190 struct frame
*frame
;
3191 struct input_event
*bufp
;
3193 if (type
== FocusIn
)
3195 if (dpyinfo
->x_focus_event_frame
!= frame
)
3197 x_new_focus_frame (dpyinfo
, frame
);
3198 dpyinfo
->x_focus_event_frame
= frame
;
3200 /* Don't stop displaying the initial startup message
3201 for a switch-frame event we don't need. */
3202 if (GC_NILP (Vterminal_frame
)
3203 && GC_CONSP (Vframe_list
)
3204 && !GC_NILP (XCDR (Vframe_list
)))
3206 bufp
->kind
= FOCUS_IN_EVENT
;
3207 XSETFRAME (bufp
->frame_or_window
, frame
);
3211 frame
->output_data
.x
->focus_state
|= state
;
3214 if (FRAME_XIC (frame
))
3215 XSetICFocus (FRAME_XIC (frame
));
3218 else if (type
== FocusOut
)
3220 frame
->output_data
.x
->focus_state
&= ~state
;
3222 if (dpyinfo
->x_focus_event_frame
== frame
)
3224 dpyinfo
->x_focus_event_frame
= 0;
3225 x_new_focus_frame (dpyinfo
, 0);
3229 if (FRAME_XIC (frame
))
3230 XUnsetICFocus (FRAME_XIC (frame
));
3235 /* The focus may have changed. Figure out if it is a real focus change,
3236 by checking both FocusIn/Out and Enter/LeaveNotify events.
3238 Returns FOCUS_IN_EVENT event in *BUFP. */
3241 x_detect_focus_change (dpyinfo
, event
, bufp
)
3242 struct x_display_info
*dpyinfo
;
3244 struct input_event
*bufp
;
3246 struct frame
*frame
;
3248 frame
= x_any_window_to_frame (dpyinfo
, event
->xany
.window
);
3252 switch (event
->type
)
3257 struct frame
*focus_frame
= dpyinfo
->x_focus_event_frame
;
3259 = focus_frame
? focus_frame
->output_data
.x
->focus_state
: 0;
3261 if (event
->xcrossing
.detail
!= NotifyInferior
3262 && event
->xcrossing
.focus
3263 && ! (focus_state
& FOCUS_EXPLICIT
))
3264 x_focus_changed ((event
->type
== EnterNotify
? FocusIn
: FocusOut
),
3266 dpyinfo
, frame
, bufp
);
3272 x_focus_changed (event
->type
,
3273 (event
->xfocus
.detail
== NotifyPointer
?
3274 FOCUS_IMPLICIT
: FOCUS_EXPLICIT
),
3275 dpyinfo
, frame
, bufp
);
3281 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3284 x_mouse_leave (dpyinfo
)
3285 struct x_display_info
*dpyinfo
;
3287 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
3290 /* The focus has changed, or we have redirected a frame's focus to
3291 another frame (this happens when a frame uses a surrogate
3292 mini-buffer frame). Shift the highlight as appropriate.
3294 The FRAME argument doesn't necessarily have anything to do with which
3295 frame is being highlighted or un-highlighted; we only use it to find
3296 the appropriate X display info. */
3299 XTframe_rehighlight (frame
)
3300 struct frame
*frame
;
3302 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
3306 x_frame_rehighlight (dpyinfo
)
3307 struct x_display_info
*dpyinfo
;
3309 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
3311 if (dpyinfo
->x_focus_frame
)
3313 dpyinfo
->x_highlight_frame
3314 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
3315 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
3316 : dpyinfo
->x_focus_frame
);
3317 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
3319 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
3320 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
3324 dpyinfo
->x_highlight_frame
= 0;
3326 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
3329 frame_unhighlight (old_highlight
);
3330 if (dpyinfo
->x_highlight_frame
)
3331 frame_highlight (dpyinfo
->x_highlight_frame
);
3337 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3339 /* Initialize mode_switch_bit and modifier_meaning. */
3341 x_find_modifier_meanings (dpyinfo
)
3342 struct x_display_info
*dpyinfo
;
3344 int min_code
, max_code
;
3347 XModifierKeymap
*mods
;
3349 dpyinfo
->meta_mod_mask
= 0;
3350 dpyinfo
->shift_lock_mask
= 0;
3351 dpyinfo
->alt_mod_mask
= 0;
3352 dpyinfo
->super_mod_mask
= 0;
3353 dpyinfo
->hyper_mod_mask
= 0;
3356 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
3358 min_code
= dpyinfo
->display
->min_keycode
;
3359 max_code
= dpyinfo
->display
->max_keycode
;
3362 syms
= XGetKeyboardMapping (dpyinfo
->display
,
3363 min_code
, max_code
- min_code
+ 1,
3365 mods
= XGetModifierMapping (dpyinfo
->display
);
3367 /* Scan the modifier table to see which modifier bits the Meta and
3368 Alt keysyms are on. */
3370 int row
, col
; /* The row and column in the modifier table. */
3371 int found_alt_or_meta
;
3373 for (row
= 3; row
< 8; row
++)
3375 found_alt_or_meta
= 0;
3376 for (col
= 0; col
< mods
->max_keypermod
; col
++)
3378 KeyCode code
= mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
3380 /* Zeroes are used for filler. Skip them. */
3384 /* Are any of this keycode's keysyms a meta key? */
3388 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
3390 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
3396 found_alt_or_meta
= 1;
3397 dpyinfo
->meta_mod_mask
|= (1 << row
);
3402 found_alt_or_meta
= 1;
3403 dpyinfo
->alt_mod_mask
|= (1 << row
);
3408 if (!found_alt_or_meta
)
3409 dpyinfo
->hyper_mod_mask
|= (1 << row
);
3410 code_col
= syms_per_code
;
3411 col
= mods
->max_keypermod
;
3416 if (!found_alt_or_meta
)
3417 dpyinfo
->super_mod_mask
|= (1 << row
);
3418 code_col
= syms_per_code
;
3419 col
= mods
->max_keypermod
;
3423 /* Ignore this if it's not on the lock modifier. */
3424 if (!found_alt_or_meta
&& ((1 << row
) == LockMask
))
3425 dpyinfo
->shift_lock_mask
= LockMask
;
3426 code_col
= syms_per_code
;
3427 col
= mods
->max_keypermod
;
3436 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3437 if (! dpyinfo
->meta_mod_mask
)
3439 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
3440 dpyinfo
->alt_mod_mask
= 0;
3443 /* If some keys are both alt and meta,
3444 make them just meta, not alt. */
3445 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
3447 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
3450 XFree ((char *) syms
);
3451 XFreeModifiermap (mods
);
3454 /* Convert between the modifier bits X uses and the modifier bits
3458 x_x_to_emacs_modifiers (dpyinfo
, state
)
3459 struct x_display_info
*dpyinfo
;
3462 EMACS_UINT mod_meta
= meta_modifier
;
3463 EMACS_UINT mod_alt
= alt_modifier
;
3464 EMACS_UINT mod_hyper
= hyper_modifier
;
3465 EMACS_UINT mod_super
= super_modifier
;
3468 tem
= Fget (Vx_alt_keysym
, Qmodifier_value
);
3469 if (! EQ (tem
, Qnil
)) mod_alt
= XUINT (tem
);
3470 tem
= Fget (Vx_meta_keysym
, Qmodifier_value
);
3471 if (! EQ (tem
, Qnil
)) mod_meta
= XUINT (tem
);
3472 tem
= Fget (Vx_hyper_keysym
, Qmodifier_value
);
3473 if (! EQ (tem
, Qnil
)) mod_hyper
= XUINT (tem
);
3474 tem
= Fget (Vx_super_keysym
, Qmodifier_value
);
3475 if (! EQ (tem
, Qnil
)) mod_super
= XUINT (tem
);
3478 return ( ((state
& (ShiftMask
| dpyinfo
->shift_lock_mask
)) ? shift_modifier
: 0)
3479 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
3480 | ((state
& dpyinfo
->meta_mod_mask
) ? mod_meta
: 0)
3481 | ((state
& dpyinfo
->alt_mod_mask
) ? mod_alt
: 0)
3482 | ((state
& dpyinfo
->super_mod_mask
) ? mod_super
: 0)
3483 | ((state
& dpyinfo
->hyper_mod_mask
) ? mod_hyper
: 0));
3487 x_emacs_to_x_modifiers (dpyinfo
, state
)
3488 struct x_display_info
*dpyinfo
;
3491 EMACS_UINT mod_meta
= meta_modifier
;
3492 EMACS_UINT mod_alt
= alt_modifier
;
3493 EMACS_UINT mod_hyper
= hyper_modifier
;
3494 EMACS_UINT mod_super
= super_modifier
;
3498 tem
= Fget (Vx_alt_keysym
, Qmodifier_value
);
3499 if (! EQ (tem
, Qnil
)) mod_alt
= XUINT (tem
);
3500 tem
= Fget (Vx_meta_keysym
, Qmodifier_value
);
3501 if (! EQ (tem
, Qnil
)) mod_meta
= XUINT (tem
);
3502 tem
= Fget (Vx_hyper_keysym
, Qmodifier_value
);
3503 if (! EQ (tem
, Qnil
)) mod_hyper
= XUINT (tem
);
3504 tem
= Fget (Vx_super_keysym
, Qmodifier_value
);
3505 if (! EQ (tem
, Qnil
)) mod_super
= XUINT (tem
);
3508 return ( ((state
& mod_alt
) ? dpyinfo
->alt_mod_mask
: 0)
3509 | ((state
& mod_super
) ? dpyinfo
->super_mod_mask
: 0)
3510 | ((state
& mod_hyper
) ? dpyinfo
->hyper_mod_mask
: 0)
3511 | ((state
& shift_modifier
) ? ShiftMask
: 0)
3512 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
3513 | ((state
& mod_meta
) ? dpyinfo
->meta_mod_mask
: 0));
3516 /* Convert a keysym to its name. */
3519 x_get_keysym_name (keysym
)
3525 value
= XKeysymToString (keysym
);
3533 /* Mouse clicks and mouse movement. Rah. */
3535 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3537 If the event is a button press, then note that we have grabbed
3541 construct_mouse_click (result
, event
, f
)
3542 struct input_event
*result
;
3543 XButtonEvent
*event
;
3546 /* Make the event type NO_EVENT; we'll change that when we decide
3548 result
->kind
= MOUSE_CLICK_EVENT
;
3549 result
->code
= event
->button
- Button1
;
3550 result
->timestamp
= event
->time
;
3551 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
3553 | (event
->type
== ButtonRelease
3557 XSETINT (result
->x
, event
->x
);
3558 XSETINT (result
->y
, event
->y
);
3559 XSETFRAME (result
->frame_or_window
, f
);
3565 /* Function to report a mouse movement to the mainstream Emacs code.
3566 The input handler calls this.
3568 We have received a mouse movement event, which is given in *event.
3569 If the mouse is over a different glyph than it was last time, tell
3570 the mainstream emacs code by setting mouse_moved. If not, ask for
3571 another motion event, so we can check again the next time it moves. */
3573 static XMotionEvent last_mouse_motion_event
;
3574 static Lisp_Object last_mouse_motion_frame
;
3577 note_mouse_movement (frame
, event
)
3579 XMotionEvent
*event
;
3581 last_mouse_movement_time
= event
->time
;
3582 last_mouse_motion_event
= *event
;
3583 XSETFRAME (last_mouse_motion_frame
, frame
);
3585 if (event
->window
!= FRAME_X_WINDOW (frame
))
3587 frame
->mouse_moved
= 1;
3588 last_mouse_scroll_bar
= Qnil
;
3589 note_mouse_highlight (frame
, -1, -1);
3592 /* Has the mouse moved off the glyph it was on at the last sighting? */
3593 else if (event
->x
< last_mouse_glyph
.x
3594 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
3595 || event
->y
< last_mouse_glyph
.y
3596 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
3598 frame
->mouse_moved
= 1;
3599 last_mouse_scroll_bar
= Qnil
;
3600 note_mouse_highlight (frame
, event
->x
, event
->y
);
3605 /************************************************************************
3607 ************************************************************************/
3610 redo_mouse_highlight ()
3612 if (!NILP (last_mouse_motion_frame
)
3613 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
3614 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
3615 last_mouse_motion_event
.x
,
3616 last_mouse_motion_event
.y
);
3620 static int glyph_rect
P_ ((struct frame
*f
, int, int, XRectangle
*));
3623 /* Try to determine frame pixel position and size of the glyph under
3624 frame pixel coordinates X/Y on frame F . Return the position and
3625 size in *RECT. Value is non-zero if we could compute these
3629 glyph_rect (f
, x
, y
, rect
)
3636 struct glyph_row
*r
, *end_row
;
3638 window
= window_from_coordinates (f
, x
, y
, 0, &x
, &y
, 0);
3642 w
= XWINDOW (window
);
3643 r
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
3644 end_row
= r
+ w
->current_matrix
->nrows
- 1;
3646 for (; r
< end_row
&& r
->enabled_p
; ++r
)
3650 struct glyph
*g
= r
->glyphs
[TEXT_AREA
];
3651 struct glyph
*end
= g
+ r
->used
[TEXT_AREA
];
3653 while (g
< end
&& gx
< x
)
3654 gx
+= g
->pixel_width
, ++g
;
3657 rect
->width
= g
->pixel_width
;
3658 rect
->height
= r
->height
;
3659 rect
->x
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
3660 rect
->y
= WINDOW_TO_FRAME_PIXEL_Y (w
, r
->y
);
3671 /* Return the current position of the mouse.
3672 *FP should be a frame which indicates which display to ask about.
3674 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
3675 and *PART to the frame, window, and scroll bar part that the mouse
3676 is over. Set *X and *Y to the portion and whole of the mouse's
3677 position on the scroll bar.
3679 If the mouse movement started elsewhere, set *FP to the frame the
3680 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
3683 Set *TIME to the server time-stamp for the time at which the mouse
3684 was at this position.
3686 Don't store anything if we don't have a valid set of values to report.
3688 This clears the mouse_moved flag, so we can wait for the next mouse
3692 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
3695 Lisp_Object
*bar_window
;
3696 enum scroll_bar_part
*part
;
3698 unsigned long *time
;
3704 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
3705 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
3711 Window dummy_window
;
3714 Lisp_Object frame
, tail
;
3716 /* Clear the mouse-moved flag for every frame on this display. */
3717 FOR_EACH_FRAME (tail
, frame
)
3718 if (FRAME_X_P (XFRAME (frame
))
3719 && FRAME_X_DISPLAY (XFRAME (frame
)) == FRAME_X_DISPLAY (*fp
))
3720 XFRAME (frame
)->mouse_moved
= 0;
3722 last_mouse_scroll_bar
= Qnil
;
3724 /* Figure out which root window we're on. */
3725 XQueryPointer (FRAME_X_DISPLAY (*fp
),
3726 DefaultRootWindow (FRAME_X_DISPLAY (*fp
)),
3728 /* The root window which contains the pointer. */
3731 /* Trash which we can't trust if the pointer is on
3732 a different screen. */
3735 /* The position on that root window. */
3738 /* More trash we can't trust. */
3741 /* Modifier keys and pointer buttons, about which
3743 (unsigned int *) &dummy
);
3745 /* Now we have a position on the root; find the innermost window
3746 containing the pointer. */
3750 int parent_x
= 0, parent_y
= 0;
3755 /* XTranslateCoordinates can get errors if the window
3756 structure is changing at the same time this function
3757 is running. So at least we must not crash from them. */
3759 count
= x_catch_errors (FRAME_X_DISPLAY (*fp
));
3761 if (FRAME_X_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
3762 && FRAME_LIVE_P (last_mouse_frame
))
3764 /* If mouse was grabbed on a frame, give coords for that frame
3765 even if the mouse is now outside it. */
3766 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
3768 /* From-window, to-window. */
3769 root
, FRAME_X_WINDOW (last_mouse_frame
),
3771 /* From-position, to-position. */
3772 root_x
, root_y
, &win_x
, &win_y
,
3776 f1
= last_mouse_frame
;
3782 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
3784 /* From-window, to-window. */
3787 /* From-position, to-position. */
3788 root_x
, root_y
, &win_x
, &win_y
,
3793 if (child
== None
|| child
== win
)
3801 /* Now we know that:
3802 win is the innermost window containing the pointer
3803 (XTC says it has no child containing the pointer),
3804 win_x and win_y are the pointer's position in it
3805 (XTC did this the last time through), and
3806 parent_x and parent_y are the pointer's position in win's parent.
3807 (They are what win_x and win_y were when win was child.
3808 If win is the root window, it has no parent, and
3809 parent_{x,y} are invalid, but that's okay, because we'll
3810 never use them in that case.) */
3812 /* Is win one of our frames? */
3813 f1
= x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp
), win
);
3815 #ifdef USE_X_TOOLKIT
3816 /* If we end up with the menu bar window, say it's not
3819 && f1
->output_data
.x
->menubar_widget
3820 && win
== XtWindow (f1
->output_data
.x
->menubar_widget
))
3822 #endif /* USE_X_TOOLKIT */
3825 if (x_had_errors_p (FRAME_X_DISPLAY (*fp
)))
3828 x_uncatch_errors (FRAME_X_DISPLAY (*fp
), count
);
3830 /* If not, is it one of our scroll bars? */
3833 struct scroll_bar
*bar
;
3835 bar
= x_window_to_scroll_bar (FRAME_X_DISPLAY (*fp
), win
);
3839 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3845 if (f1
== 0 && insist
> 0)
3846 f1
= SELECTED_FRAME ();
3850 /* Ok, we found a frame. Store all the values.
3851 last_mouse_glyph is a rectangle used to reduce the
3852 generation of mouse events. To not miss any motion
3853 events, we must divide the frame into rectangles of the
3854 size of the smallest character that could be displayed
3855 on it, i.e. into the same rectangles that matrices on
3856 the frame are divided into. */
3858 int width
, height
, gx
, gy
;
3861 if (glyph_rect (f1
, win_x
, win_y
, &rect
))
3862 last_mouse_glyph
= rect
;
3865 width
= FRAME_SMALLEST_CHAR_WIDTH (f1
);
3866 height
= FRAME_SMALLEST_FONT_HEIGHT (f1
);
3870 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
3871 round down even for negative values. */
3876 gx
= (gx
+ width
- 1) / width
* width
;
3877 gy
= (gy
+ height
- 1) / height
* height
;
3879 last_mouse_glyph
.width
= width
;
3880 last_mouse_glyph
.height
= height
;
3881 last_mouse_glyph
.x
= gx
;
3882 last_mouse_glyph
.y
= gy
;
3888 XSETINT (*x
, win_x
);
3889 XSETINT (*y
, win_y
);
3890 *time
= last_mouse_movement_time
;
3900 /***********************************************************************
3902 ***********************************************************************/
3904 /* Scroll bar support. */
3906 /* Given an X window ID and a DISPLAY, find the struct scroll_bar which
3908 This can be called in GC, so we have to make sure to strip off mark
3911 static struct scroll_bar
*
3912 x_window_to_scroll_bar (display
, window_id
)
3918 #if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
3919 window_id
= (Window
) xg_get_scroll_id_for_window (display
, window_id
);
3920 #endif /* USE_GTK && USE_TOOLKIT_SCROLL_BARS */
3922 for (tail
= Vframe_list
;
3923 XGCTYPE (tail
) == Lisp_Cons
;
3926 Lisp_Object frame
, bar
, condemned
;
3928 frame
= XCAR (tail
);
3929 /* All elements of Vframe_list should be frames. */
3930 if (! GC_FRAMEP (frame
))
3933 if (! FRAME_X_P (XFRAME (frame
)))
3936 /* Scan this frame's scroll bar list for a scroll bar with the
3938 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
3939 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
3940 /* This trick allows us to search both the ordinary and
3941 condemned scroll bar lists with one loop. */
3942 ! GC_NILP (bar
) || (bar
= condemned
,
3945 bar
= XSCROLL_BAR (bar
)->next
)
3946 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
&&
3947 FRAME_X_DISPLAY (XFRAME (frame
)) == display
)
3948 return XSCROLL_BAR (bar
);
3955 #if defined USE_LUCID
3957 /* Return the Lucid menu bar WINDOW is part of. Return null
3958 if WINDOW is not part of a menu bar. */
3961 x_window_to_menu_bar (window
)
3966 for (tail
= Vframe_list
;
3967 XGCTYPE (tail
) == Lisp_Cons
;
3970 if (FRAME_X_P (XFRAME (XCAR (tail
))))
3972 Lisp_Object frame
= XCAR (tail
);
3973 Widget menu_bar
= XFRAME (frame
)->output_data
.x
->menubar_widget
;
3975 if (menu_bar
&& xlwmenu_window_p (menu_bar
, window
))
3983 #endif /* USE_LUCID */
3986 /************************************************************************
3988 ************************************************************************/
3990 #ifdef USE_TOOLKIT_SCROLL_BARS
3992 static void x_scroll_bar_to_input_event
P_ ((XEvent
*, struct input_event
*));
3993 static void x_send_scroll_bar_event
P_ ((Lisp_Object
, int, int, int));
3994 static void x_create_toolkit_scroll_bar
P_ ((struct frame
*,
3995 struct scroll_bar
*));
3996 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4000 /* Lisp window being scrolled. Set when starting to interact with
4001 a toolkit scroll bar, reset to nil when ending the interaction. */
4003 static Lisp_Object window_being_scrolled
;
4005 /* Last scroll bar part sent in xm_scroll_callback. */
4007 static int last_scroll_bar_part
;
4009 /* Whether this is an Xaw with arrow-scrollbars. This should imply
4010 that movements of 1/20 of the screen size are mapped to up/down. */
4013 /* Id of action hook installed for scroll bars. */
4015 static XtActionHookId action_hook_id
;
4017 static Boolean xaw3d_arrow_scroll
;
4019 /* Whether the drag scrolling maintains the mouse at the top of the
4020 thumb. If not, resizing the thumb needs to be done more carefully
4021 to avoid jerkyness. */
4023 static Boolean xaw3d_pick_top
;
4025 extern void set_vertical_scroll_bar
P_ ((struct window
*));
4027 /* Action hook installed via XtAppAddActionHook when toolkit scroll
4028 bars are used.. The hook is responsible for detecting when
4029 the user ends an interaction with the scroll bar, and generates
4030 a `end-scroll' SCROLL_BAR_CLICK_EVENT' event if so. */
4033 xt_action_hook (widget
, client_data
, action_name
, event
, params
,
4036 XtPointer client_data
;
4040 Cardinal
*num_params
;
4046 scroll_bar_p
= XmIsScrollBar (widget
);
4047 end_action
= "Release";
4048 #else /* !USE_MOTIF i.e. use Xaw */
4049 scroll_bar_p
= XtIsSubclass (widget
, scrollbarWidgetClass
);
4050 end_action
= "EndScroll";
4051 #endif /* USE_MOTIF */
4054 && strcmp (action_name
, end_action
) == 0
4055 && WINDOWP (window_being_scrolled
))
4059 x_send_scroll_bar_event (window_being_scrolled
,
4060 scroll_bar_end_scroll
, 0, 0);
4061 w
= XWINDOW (window_being_scrolled
);
4063 if (!NILP (XSCROLL_BAR (w
->vertical_scroll_bar
)->dragging
))
4065 XSCROLL_BAR (w
->vertical_scroll_bar
)->dragging
= Qnil
;
4066 /* The thumb size is incorrect while dragging: fix it. */
4067 set_vertical_scroll_bar (w
);
4069 window_being_scrolled
= Qnil
;
4070 last_scroll_bar_part
= -1;
4072 /* Xt timeouts no longer needed. */
4073 toolkit_scroll_bar_interaction
= 0;
4076 #endif /* not USE_GTK */
4078 /* A vector of windows used for communication between
4079 x_send_scroll_bar_event and x_scroll_bar_to_input_event. */
4081 static struct window
**scroll_bar_windows
;
4082 static int scroll_bar_windows_size
;
4085 /* Send a client message with message type Xatom_Scrollbar for a
4086 scroll action to the frame of WINDOW. PART is a value identifying
4087 the part of the scroll bar that was clicked on. PORTION is the
4088 amount to scroll of a whole of WHOLE. */
4091 x_send_scroll_bar_event (window
, part
, portion
, whole
)
4093 int part
, portion
, whole
;
4096 XClientMessageEvent
*ev
= (XClientMessageEvent
*) &event
;
4097 struct window
*w
= XWINDOW (window
);
4098 struct frame
*f
= XFRAME (w
->frame
);
4103 /* Construct a ClientMessage event to send to the frame. */
4104 ev
->type
= ClientMessage
;
4105 ev
->message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_Scrollbar
;
4106 ev
->display
= FRAME_X_DISPLAY (f
);
4107 ev
->window
= FRAME_X_WINDOW (f
);
4110 /* We can only transfer 32 bits in the XClientMessageEvent, which is
4111 not enough to store a pointer or Lisp_Object on a 64 bit system.
4112 So, store the window in scroll_bar_windows and pass the index
4113 into that array in the event. */
4114 for (i
= 0; i
< scroll_bar_windows_size
; ++i
)
4115 if (scroll_bar_windows
[i
] == NULL
)
4118 if (i
== scroll_bar_windows_size
)
4120 int new_size
= max (10, 2 * scroll_bar_windows_size
);
4121 size_t nbytes
= new_size
* sizeof *scroll_bar_windows
;
4122 size_t old_nbytes
= scroll_bar_windows_size
* sizeof *scroll_bar_windows
;
4124 scroll_bar_windows
= (struct window
**) xrealloc (scroll_bar_windows
,
4126 bzero (&scroll_bar_windows
[i
], nbytes
- old_nbytes
);
4127 scroll_bar_windows_size
= new_size
;
4130 scroll_bar_windows
[i
] = w
;
4131 ev
->data
.l
[0] = (long) i
;
4132 ev
->data
.l
[1] = (long) part
;
4133 ev
->data
.l
[2] = (long) 0;
4134 ev
->data
.l
[3] = (long) portion
;
4135 ev
->data
.l
[4] = (long) whole
;
4137 /* Make Xt timeouts work while the scroll bar is active. */
4138 toolkit_scroll_bar_interaction
= 1;
4140 /* Setting the event mask to zero means that the message will
4141 be sent to the client that created the window, and if that
4142 window no longer exists, no event will be sent. */
4143 XSendEvent (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), False
, 0, &event
);
4148 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
4152 x_scroll_bar_to_input_event (event
, ievent
)
4154 struct input_event
*ievent
;
4156 XClientMessageEvent
*ev
= (XClientMessageEvent
*) event
;
4161 w
= scroll_bar_windows
[ev
->data
.l
[0]];
4162 scroll_bar_windows
[ev
->data
.l
[0]] = NULL
;
4164 XSETWINDOW (window
, w
);
4165 f
= XFRAME (w
->frame
);
4167 ievent
->kind
= SCROLL_BAR_CLICK_EVENT
;
4168 ievent
->frame_or_window
= window
;
4171 ievent
->timestamp
= CurrentTime
;
4173 ievent
->timestamp
= XtLastTimestampProcessed (FRAME_X_DISPLAY (f
));
4175 ievent
->part
= ev
->data
.l
[1];
4176 ievent
->code
= ev
->data
.l
[2];
4177 ievent
->x
= make_number ((int) ev
->data
.l
[3]);
4178 ievent
->y
= make_number ((int) ev
->data
.l
[4]);
4179 ievent
->modifiers
= 0;
4185 /* Minimum and maximum values used for Motif scroll bars. */
4187 #define XM_SB_MAX 10000000
4190 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
4191 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
4192 CALL_DATA is a pointer to a XmScrollBarCallbackStruct. */
4195 xm_scroll_callback (widget
, client_data
, call_data
)
4197 XtPointer client_data
, call_data
;
4199 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
4200 XmScrollBarCallbackStruct
*cs
= (XmScrollBarCallbackStruct
*) call_data
;
4201 int part
= -1, whole
= 0, portion
= 0;
4205 case XmCR_DECREMENT
:
4206 bar
->dragging
= Qnil
;
4207 part
= scroll_bar_up_arrow
;
4210 case XmCR_INCREMENT
:
4211 bar
->dragging
= Qnil
;
4212 part
= scroll_bar_down_arrow
;
4215 case XmCR_PAGE_DECREMENT
:
4216 bar
->dragging
= Qnil
;
4217 part
= scroll_bar_above_handle
;
4220 case XmCR_PAGE_INCREMENT
:
4221 bar
->dragging
= Qnil
;
4222 part
= scroll_bar_below_handle
;
4226 bar
->dragging
= Qnil
;
4227 part
= scroll_bar_to_top
;
4230 case XmCR_TO_BOTTOM
:
4231 bar
->dragging
= Qnil
;
4232 part
= scroll_bar_to_bottom
;
4239 /* Get the slider size. */
4241 XtVaGetValues (widget
, XmNsliderSize
, &slider_size
, NULL
);
4244 whole
= XM_SB_MAX
- slider_size
;
4245 portion
= min (cs
->value
, whole
);
4246 part
= scroll_bar_handle
;
4247 bar
->dragging
= make_number (cs
->value
);
4251 case XmCR_VALUE_CHANGED
:
4257 window_being_scrolled
= bar
->window
;
4258 last_scroll_bar_part
= part
;
4259 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
4264 #else /* !USE_MOTIF, i.e. Xaw or GTK */
4266 /* Scroll bar callback for GTK scroll bars. WIDGET is the scroll
4267 bar widget. DATA is a pointer to the scroll_bar structure. */
4270 xg_scroll_callback (widget
, data
)
4274 struct scroll_bar
*bar
= (struct scroll_bar
*) data
;
4280 int part
= -1, whole
= 0, portion
= 0;
4281 GtkAdjustment
*adj
= GTK_ADJUSTMENT (gtk_range_get_adjustment (widget
));
4283 position
= gtk_adjustment_get_value (adj
);
4285 p
= g_object_get_data (G_OBJECT (widget
), XG_LAST_SB_DATA
);
4288 p
= (gdouble
*) xmalloc (sizeof (gdouble
));
4290 g_object_set_data (G_OBJECT (widget
), XG_LAST_SB_DATA
, p
);
4296 if (xg_ignore_gtk_scrollbar
) return;
4298 diff
= (int) (position
- previous
);
4300 if (diff
== (int) adj
->step_increment
)
4302 part
= scroll_bar_down_arrow
;
4303 bar
->dragging
= Qnil
;
4305 else if (-diff
== (int) adj
->step_increment
)
4307 part
= scroll_bar_up_arrow
;
4308 bar
->dragging
= Qnil
;
4310 else if (diff
== (int) adj
->page_increment
)
4312 part
= scroll_bar_below_handle
;
4313 bar
->dragging
= Qnil
;
4315 else if (-diff
== (int) adj
->page_increment
)
4317 part
= scroll_bar_above_handle
;
4318 bar
->dragging
= Qnil
;
4322 part
= scroll_bar_handle
;
4323 whole
= adj
->upper
- adj
->page_size
;
4324 portion
= min ((int)position
, whole
);
4325 bar
->dragging
= make_number ((int)portion
);
4330 window_being_scrolled
= bar
->window
;
4331 last_scroll_bar_part
= part
;
4332 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
4336 #else /* not USE_GTK */
4338 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
4339 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
4340 scroll bar struct. CALL_DATA is a pointer to a float saying where
4344 xaw_jump_callback (widget
, client_data
, call_data
)
4346 XtPointer client_data
, call_data
;
4348 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
4349 float top
= *(float *) call_data
;
4351 int whole
, portion
, height
;
4354 /* Get the size of the thumb, a value between 0 and 1. */
4356 XtVaGetValues (widget
, XtNshown
, &shown
, XtNheight
, &height
, NULL
);
4360 portion
= shown
< 1 ? top
* whole
: 0;
4362 if (shown
< 1 && (abs (top
+ shown
- 1) < 1.0/height
))
4363 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
4364 the bottom, so we force the scrolling whenever we see that we're
4365 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
4366 we try to ensure that we always stay two pixels away from the
4368 part
= scroll_bar_down_arrow
;
4370 part
= scroll_bar_handle
;
4372 window_being_scrolled
= bar
->window
;
4373 bar
->dragging
= make_number (portion
);
4374 last_scroll_bar_part
= part
;
4375 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
4379 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
4380 i.e. line or page up or down. WIDGET is the Xaw scroll bar
4381 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
4382 the scroll bar. CALL_DATA is an integer specifying the action that
4383 has taken place. Its magnitude is in the range 0..height of the
4384 scroll bar. Negative values mean scroll towards buffer start.
4385 Values < height of scroll bar mean line-wise movement. */
4388 xaw_scroll_callback (widget
, client_data
, call_data
)
4390 XtPointer client_data
, call_data
;
4392 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
4393 /* The position really is stored cast to a pointer. */
4394 int position
= (long) call_data
;
4398 /* Get the height of the scroll bar. */
4400 XtVaGetValues (widget
, XtNheight
, &height
, NULL
);
4403 if (abs (position
) >= height
)
4404 part
= (position
< 0) ? scroll_bar_above_handle
: scroll_bar_below_handle
;
4406 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
4407 it maps line-movement to call_data = max(5, height/20). */
4408 else if (xaw3d_arrow_scroll
&& abs (position
) <= max (5, height
/ 20))
4409 part
= (position
< 0) ? scroll_bar_up_arrow
: scroll_bar_down_arrow
;
4411 part
= scroll_bar_move_ratio
;
4413 window_being_scrolled
= bar
->window
;
4414 bar
->dragging
= Qnil
;
4415 last_scroll_bar_part
= part
;
4416 x_send_scroll_bar_event (bar
->window
, part
, position
, height
);
4419 #endif /* not USE_GTK */
4420 #endif /* not USE_MOTIF */
4422 #define SCROLL_BAR_NAME "verticalScrollBar"
4424 /* Create the widget for scroll bar BAR on frame F. Record the widget
4425 and X window of the scroll bar in BAR. */
4429 x_create_toolkit_scroll_bar (f
, bar
)
4431 struct scroll_bar
*bar
;
4433 char *scroll_bar_name
= SCROLL_BAR_NAME
;
4436 xg_create_scroll_bar (f
, bar
, G_CALLBACK (xg_scroll_callback
),
4441 #else /* not USE_GTK */
4444 x_create_toolkit_scroll_bar (f
, bar
)
4446 struct scroll_bar
*bar
;
4452 char *scroll_bar_name
= SCROLL_BAR_NAME
;
4453 unsigned long pixel
;
4458 /* Set resources. Create the widget. */
4459 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
4460 XtSetArg (av
[ac
], XmNminimum
, 0); ++ac
;
4461 XtSetArg (av
[ac
], XmNmaximum
, XM_SB_MAX
); ++ac
;
4462 XtSetArg (av
[ac
], XmNorientation
, XmVERTICAL
); ++ac
;
4463 XtSetArg (av
[ac
], XmNprocessingDirection
, XmMAX_ON_BOTTOM
), ++ac
;
4464 XtSetArg (av
[ac
], XmNincrement
, 1); ++ac
;
4465 XtSetArg (av
[ac
], XmNpageIncrement
, 1); ++ac
;
4467 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
4470 XtSetArg (av
[ac
], XmNforeground
, pixel
);
4474 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4477 XtSetArg (av
[ac
], XmNbackground
, pixel
);
4481 widget
= XmCreateScrollBar (f
->output_data
.x
->edit_widget
,
4482 scroll_bar_name
, av
, ac
);
4484 /* Add one callback for everything that can happen. */
4485 XtAddCallback (widget
, XmNdecrementCallback
, xm_scroll_callback
,
4487 XtAddCallback (widget
, XmNdragCallback
, xm_scroll_callback
,
4489 XtAddCallback (widget
, XmNincrementCallback
, xm_scroll_callback
,
4491 XtAddCallback (widget
, XmNpageDecrementCallback
, xm_scroll_callback
,
4493 XtAddCallback (widget
, XmNpageIncrementCallback
, xm_scroll_callback
,
4495 XtAddCallback (widget
, XmNtoBottomCallback
, xm_scroll_callback
,
4497 XtAddCallback (widget
, XmNtoTopCallback
, xm_scroll_callback
,
4500 /* Realize the widget. Only after that is the X window created. */
4501 XtRealizeWidget (widget
);
4503 /* Set the cursor to an arrow. I didn't find a resource to do that.
4504 And I'm wondering why it hasn't an arrow cursor by default. */
4505 XDefineCursor (XtDisplay (widget
), XtWindow (widget
),
4506 f
->output_data
.x
->nontext_cursor
);
4508 #else /* !USE_MOTIF i.e. use Xaw */
4510 /* Set resources. Create the widget. The background of the
4511 Xaw3d scroll bar widget is a little bit light for my taste.
4512 We don't alter it here to let users change it according
4513 to their taste with `emacs*verticalScrollBar.background: xxx'. */
4514 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
4515 XtSetArg (av
[ac
], XtNorientation
, XtorientVertical
); ++ac
;
4516 /* For smoother scrolling with Xaw3d -sm */
4517 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
4519 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
4522 XtSetArg (av
[ac
], XtNforeground
, pixel
);
4526 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4529 XtSetArg (av
[ac
], XtNbackground
, pixel
);
4533 /* Top/bottom shadow colors. */
4535 /* Allocate them, if necessary. */
4536 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
== -1)
4538 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4539 if (!x_alloc_lighter_color (f
, FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
4540 &pixel
, 1.2, 0x8000))
4542 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= pixel
;
4544 if (f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
== -1)
4546 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4547 if (!x_alloc_lighter_color (f
, FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
4548 &pixel
, 0.6, 0x4000))
4550 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= pixel
;
4553 /* Tell the toolkit about them. */
4554 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
== -1
4555 || f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
== -1)
4556 /* We tried to allocate a color for the top/bottom shadow, and
4557 failed, so tell Xaw3d to use dithering instead. */
4559 XtSetArg (av
[ac
], XtNbeNiceToColormap
, True
);
4563 /* Tell what colors Xaw3d should use for the top/bottom shadow, to
4564 be more consistent with other emacs 3d colors, and since Xaw3d is
4565 not good at dealing with allocation failure. */
4567 /* This tells Xaw3d to use real colors instead of dithering for
4569 XtSetArg (av
[ac
], XtNbeNiceToColormap
, False
);
4572 /* Specify the colors. */
4573 pixel
= f
->output_data
.x
->scroll_bar_top_shadow_pixel
;
4576 XtSetArg (av
[ac
], "topShadowPixel", pixel
);
4579 pixel
= f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
;
4582 XtSetArg (av
[ac
], "bottomShadowPixel", pixel
);
4587 widget
= XtCreateWidget (scroll_bar_name
, scrollbarWidgetClass
,
4588 f
->output_data
.x
->edit_widget
, av
, ac
);
4592 char *val
= initial
;
4593 XtVaGetValues (widget
, XtNscrollVCursor
, (XtPointer
) &val
,
4594 XtNpickTop
, (XtPointer
) &xaw3d_pick_top
, NULL
);
4596 { /* ARROW_SCROLL */
4597 xaw3d_arrow_scroll
= True
;
4598 /* Isn't that just a personal preference ? -sm */
4599 XtVaSetValues (widget
, XtNcursorName
, "top_left_arrow", NULL
);
4603 /* Define callbacks. */
4604 XtAddCallback (widget
, XtNjumpProc
, xaw_jump_callback
, (XtPointer
) bar
);
4605 XtAddCallback (widget
, XtNscrollProc
, xaw_scroll_callback
,
4608 /* Realize the widget. Only after that is the X window created. */
4609 XtRealizeWidget (widget
);
4611 #endif /* !USE_MOTIF */
4613 /* Install an action hook that lets us detect when the user
4614 finishes interacting with a scroll bar. */
4615 if (action_hook_id
== 0)
4616 action_hook_id
= XtAppAddActionHook (Xt_app_con
, xt_action_hook
, 0);
4618 /* Remember X window and widget in the scroll bar vector. */
4619 SET_SCROLL_BAR_X_WIDGET (bar
, widget
);
4620 xwindow
= XtWindow (widget
);
4621 SET_SCROLL_BAR_X_WINDOW (bar
, xwindow
);
4625 #endif /* not USE_GTK */
4628 /* Set the thumb size and position of scroll bar BAR. We are currently
4629 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4633 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4634 struct scroll_bar
*bar
;
4635 int portion
, position
, whole
;
4637 xg_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
4640 #else /* not USE_GTK */
4642 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4643 struct scroll_bar
*bar
;
4644 int portion
, position
, whole
;
4646 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4647 Widget widget
= SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
);
4654 /* We use an estimate of 30 chars per line rather than the real
4655 `portion' value. This has the disadvantage that the thumb size
4656 is not very representative, but it makes our life a lot easier.
4657 Otherwise, we have to constantly adjust the thumb size, which
4658 we can't always do quickly enough: while dragging, the size of
4659 the thumb might prevent the user from dragging the thumb all the
4660 way to the end. but Motif and some versions of Xaw3d don't allow
4661 updating the thumb size while dragging. Also, even if we can update
4662 its size, the update will often happen too late.
4663 If you don't believe it, check out revision 1.650 of xterm.c to see
4664 what hoops we were going through and the still poor behavior we got. */
4665 portion
= WINDOW_TOTAL_LINES (XWINDOW (bar
->window
)) * 30;
4666 /* When the thumb is at the bottom, position == whole.
4667 So we need to increase `whole' to make space for the thumb. */
4674 top
= (float) position
/ whole
;
4675 shown
= (float) portion
/ whole
;
4678 if (NILP (bar
->dragging
))
4682 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
4683 is the scroll bar's maximum and MIN is the scroll bar's minimum
4685 size
= shown
* XM_SB_MAX
;
4686 size
= min (size
, XM_SB_MAX
);
4687 size
= max (size
, 1);
4689 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
4690 value
= top
* XM_SB_MAX
;
4691 value
= min (value
, XM_SB_MAX
- size
);
4693 XmScrollBarSetValues (widget
, value
, size
, 0, 0, False
);
4695 #else /* !USE_MOTIF i.e. use Xaw */
4701 top
= (float) position
/ whole
;
4702 shown
= (float) portion
/ whole
;
4706 float old_top
, old_shown
;
4708 XtVaGetValues (widget
,
4709 XtNtopOfThumb
, &old_top
,
4710 XtNshown
, &old_shown
,
4714 /* Massage the top+shown values. */
4715 if (NILP (bar
->dragging
) || last_scroll_bar_part
== scroll_bar_down_arrow
)
4716 top
= max (0, min (1, top
));
4719 /* Keep two pixels available for moving the thumb down. */
4720 shown
= max (0, min (1 - top
- (2.0 / height
), shown
));
4722 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
4723 check that your system's configuration file contains a define
4724 for `NARROWPROTO'. See s/freebsd.h for an example. */
4725 if (top
!= old_top
|| shown
!= old_shown
)
4727 if (NILP (bar
->dragging
))
4728 XawScrollbarSetThumb (widget
, top
, shown
);
4732 ScrollbarWidget sb
= (ScrollbarWidget
) widget
;
4733 int scroll_mode
= 0;
4735 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
4736 if (xaw3d_arrow_scroll
)
4738 /* Xaw3d stupidly ignores resize requests while dragging
4739 so we have to make it believe it's not in dragging mode. */
4740 scroll_mode
= sb
->scrollbar
.scroll_mode
;
4741 if (scroll_mode
== 2)
4742 sb
->scrollbar
.scroll_mode
= 0;
4745 /* Try to make the scrolling a tad smoother. */
4746 if (!xaw3d_pick_top
)
4747 shown
= min (shown
, old_shown
);
4749 XawScrollbarSetThumb (widget
, top
, shown
);
4752 if (xaw3d_arrow_scroll
&& scroll_mode
== 2)
4753 sb
->scrollbar
.scroll_mode
= scroll_mode
;
4758 #endif /* !USE_MOTIF */
4762 #endif /* not USE_GTK */
4764 #endif /* USE_TOOLKIT_SCROLL_BARS */
4768 /************************************************************************
4769 Scroll bars, general
4770 ************************************************************************/
4772 /* Create a scroll bar and return the scroll bar vector for it. W is
4773 the Emacs window on which to create the scroll bar. TOP, LEFT,
4774 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4777 static struct scroll_bar
*
4778 x_scroll_bar_create (w
, top
, left
, width
, height
)
4780 int top
, left
, width
, height
;
4782 struct frame
*f
= XFRAME (w
->frame
);
4783 struct scroll_bar
*bar
4784 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4788 #ifdef USE_TOOLKIT_SCROLL_BARS
4789 x_create_toolkit_scroll_bar (f
, bar
);
4790 #else /* not USE_TOOLKIT_SCROLL_BARS */
4792 XSetWindowAttributes a
;
4796 a
.background_pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4797 if (a
.background_pixel
== -1)
4798 a
.background_pixel
= f
->output_data
.x
->background_pixel
;
4800 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
4801 | ButtonMotionMask
| PointerMotionHintMask
4803 a
.cursor
= FRAME_X_DISPLAY_INFO (f
)->vertical_scroll_bar_cursor
;
4805 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
4807 /* Clear the area of W that will serve as a scroll bar. This is
4808 for the case that a window has been split horizontally. In
4809 this case, no clear_frame is generated to reduce flickering. */
4810 if (width
> 0 && height
> 0)
4811 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4813 window_box_height (w
), False
);
4815 window
= XCreateWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4816 /* Position and size of scroll bar. */
4817 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
4819 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4821 /* Border width, depth, class, and visual. */
4828 SET_SCROLL_BAR_X_WINDOW (bar
, window
);
4830 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4832 XSETWINDOW (bar
->window
, w
);
4833 XSETINT (bar
->top
, top
);
4834 XSETINT (bar
->left
, left
);
4835 XSETINT (bar
->width
, width
);
4836 XSETINT (bar
->height
, height
);
4837 XSETINT (bar
->start
, 0);
4838 XSETINT (bar
->end
, 0);
4839 bar
->dragging
= Qnil
;
4841 /* Add bar to its frame's list of scroll bars. */
4842 bar
->next
= FRAME_SCROLL_BARS (f
);
4844 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4845 if (!NILP (bar
->next
))
4846 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4848 /* Map the window/widget. */
4849 #ifdef USE_TOOLKIT_SCROLL_BARS
4852 xg_update_scrollbar_pos (f
,
4853 SCROLL_BAR_X_WINDOW (bar
),
4855 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
4856 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4858 xg_show_scroll_bar (SCROLL_BAR_X_WINDOW (bar
));
4859 #else /* not USE_GTK */
4860 Widget scroll_bar
= SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
);
4861 XtConfigureWidget (scroll_bar
,
4862 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
4864 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4865 max (height
, 1), 0);
4866 XtMapWidget (scroll_bar
);
4867 #endif /* not USE_GTK */
4869 #else /* not USE_TOOLKIT_SCROLL_BARS */
4870 XMapRaised (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
4871 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4878 /* Draw BAR's handle in the proper position.
4880 If the handle is already drawn from START to END, don't bother
4881 redrawing it, unless REBUILD is non-zero; in that case, always
4882 redraw it. (REBUILD is handy for drawing the handle after expose
4885 Normally, we want to constrain the start and end of the handle to
4886 fit inside its rectangle, but if the user is dragging the scroll
4887 bar handle, we want to let them drag it down all the way, so that
4888 the bar's top is as far down as it goes; otherwise, there's no way
4889 to move to the very end of the buffer. */
4891 #ifndef USE_TOOLKIT_SCROLL_BARS
4894 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
4895 struct scroll_bar
*bar
;
4899 int dragging
= ! NILP (bar
->dragging
);
4900 Window w
= SCROLL_BAR_X_WINDOW (bar
);
4901 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4902 GC gc
= f
->output_data
.x
->normal_gc
;
4904 /* If the display is already accurate, do nothing. */
4906 && start
== XINT (bar
->start
)
4907 && end
== XINT (bar
->end
))
4913 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f
, XINT (bar
->width
));
4914 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
4915 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4917 /* Make sure the values are reasonable, and try to preserve
4918 the distance between start and end. */
4920 int length
= end
- start
;
4924 else if (start
> top_range
)
4926 end
= start
+ length
;
4930 else if (end
> top_range
&& ! dragging
)
4934 /* Store the adjusted setting in the scroll bar. */
4935 XSETINT (bar
->start
, start
);
4936 XSETINT (bar
->end
, end
);
4938 /* Clip the end position, just for display. */
4939 if (end
> top_range
)
4942 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
4943 below top positions, to make sure the handle is always at least
4944 that many pixels tall. */
4945 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4947 /* Draw the empty space above the handle. Note that we can't clear
4948 zero-height areas; that means "clear to end of window." */
4950 x_clear_area (FRAME_X_DISPLAY (f
), w
,
4951 /* x, y, width, height, and exposures. */
4952 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
4953 VERTICAL_SCROLL_BAR_TOP_BORDER
,
4954 inside_width
, start
,
4957 /* Change to proper foreground color if one is specified. */
4958 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
4959 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
4960 f
->output_data
.x
->scroll_bar_foreground_pixel
);
4962 /* Draw the handle itself. */
4963 XFillRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
4964 /* x, y, width, height */
4965 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
4966 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
4967 inside_width
, end
- start
);
4969 /* Restore the foreground color of the GC if we changed it above. */
4970 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
4971 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
4972 f
->output_data
.x
->foreground_pixel
);
4974 /* Draw the empty space below the handle. Note that we can't
4975 clear zero-height areas; that means "clear to end of window." */
4976 if (end
< inside_height
)
4977 x_clear_area (FRAME_X_DISPLAY (f
), w
,
4978 /* x, y, width, height, and exposures. */
4979 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
4980 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
4981 inside_width
, inside_height
- end
,
4989 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4991 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4995 x_scroll_bar_remove (bar
)
4996 struct scroll_bar
*bar
;
4998 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5001 #ifdef USE_TOOLKIT_SCROLL_BARS
5003 xg_remove_scroll_bar (f
, SCROLL_BAR_X_WINDOW (bar
));
5004 #else /* not USE_GTK */
5005 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
));
5006 #endif /* not USE_GTK */
5008 XDestroyWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
5011 /* Disassociate this scroll bar from its window. */
5012 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
5018 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5019 that we are displaying PORTION characters out of a total of WHOLE
5020 characters, starting at POSITION. If WINDOW has no scroll bar,
5024 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
5026 int portion
, whole
, position
;
5028 struct frame
*f
= XFRAME (w
->frame
);
5029 struct scroll_bar
*bar
;
5030 int top
, height
, left
, sb_left
, width
, sb_width
;
5031 int window_y
, window_height
;
5033 /* Get window dimensions. */
5034 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
5036 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
5037 height
= window_height
;
5039 /* Compute the left edge of the scroll bar area. */
5040 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
5042 /* Compute the width of the scroll bar which might be less than
5043 the width of the area reserved for the scroll bar. */
5044 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
5045 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
5049 /* Compute the left edge of the scroll bar. */
5050 #ifdef USE_TOOLKIT_SCROLL_BARS
5051 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
5053 (WINDOW_RIGHTMOST_P (w
)
5054 ? width
- sb_width
- (width
- sb_width
) / 2
5058 (WINDOW_LEFTMOST_P (w
)
5059 ? (width
- sb_width
) / 2
5060 : width
- sb_width
));
5062 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
5063 sb_left
= left
+ width
- sb_width
;
5068 /* Does the scroll bar exist yet? */
5069 if (NILP (w
->vertical_scroll_bar
))
5071 if (width
> 0 && height
> 0)
5074 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5075 left
, top
, width
, height
, False
);
5079 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
);
5083 /* It may just need to be moved and resized. */
5084 unsigned int mask
= 0;
5086 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
5090 if (sb_left
!= XINT (bar
->left
))
5092 if (top
!= XINT (bar
->top
))
5094 if (sb_width
!= XINT (bar
->width
))
5096 if (height
!= XINT (bar
->height
))
5099 #ifdef USE_TOOLKIT_SCROLL_BARS
5101 /* Move/size the scroll bar widget. */
5104 /* Since toolkit scroll bars are smaller than the space reserved
5105 for them on the frame, we have to clear "under" them. */
5106 if (width
> 0 && height
> 0)
5107 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5108 left
, top
, width
, height
, False
);
5110 xg_update_scrollbar_pos (f
,
5111 SCROLL_BAR_X_WINDOW (bar
),
5113 sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5114 sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
*2,
5116 #else /* not USE_GTK */
5117 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
),
5118 sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5120 sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5121 max (height
, 1), 0);
5122 #endif /* not USE_GTK */
5124 #else /* not USE_TOOLKIT_SCROLL_BARS */
5126 /* Clear areas not covered by the scroll bar because of
5127 VERTICAL_SCROLL_BAR_WIDTH_TRIM. */
5128 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM
)
5130 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5131 left
, top
, VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5133 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5134 left
+ width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5135 top
, VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5139 /* Clear areas not covered by the scroll bar because it's not as
5140 wide as the area reserved for it. This makes sure a
5141 previous mode line display is cleared after C-x 2 C-x 1, for
5144 int area_width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
5145 int rest
= area_width
- sb_width
;
5146 if (rest
> 0 && height
> 0)
5148 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
5149 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5150 left
+ area_width
- rest
, top
,
5151 rest
, height
, False
);
5153 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5154 left
, top
, rest
, height
, False
);
5158 /* Move/size the scroll bar window. */
5163 wc
.x
= sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
5165 wc
.width
= sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2;
5167 XConfigureWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
),
5171 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5173 /* Remember new settings. */
5174 XSETINT (bar
->left
, sb_left
);
5175 XSETINT (bar
->top
, top
);
5176 XSETINT (bar
->width
, sb_width
);
5177 XSETINT (bar
->height
, height
);
5182 #ifdef USE_TOOLKIT_SCROLL_BARS
5183 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
5184 #else /* not USE_TOOLKIT_SCROLL_BARS */
5185 /* Set the scroll bar's current state, unless we're currently being
5187 if (NILP (bar
->dragging
))
5189 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
5192 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
5195 int start
= ((double) position
* top_range
) / whole
;
5196 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
5197 x_scroll_bar_set_handle (bar
, start
, end
, 0);
5200 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5202 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
5206 /* The following three hooks are used when we're doing a thorough
5207 redisplay of the frame. We don't explicitly know which scroll bars
5208 are going to be deleted, because keeping track of when windows go
5209 away is a real pain - "Can you say set-window-configuration, boys
5210 and girls?" Instead, we just assert at the beginning of redisplay
5211 that *all* scroll bars are to be removed, and then save a scroll bar
5212 from the fiery pit when we actually redisplay its window. */
5214 /* Arrange for all scroll bars on FRAME to be removed at the next call
5215 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5216 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5219 XTcondemn_scroll_bars (frame
)
5222 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5223 while (! NILP (FRAME_SCROLL_BARS (frame
)))
5226 bar
= FRAME_SCROLL_BARS (frame
);
5227 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
5228 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
5229 XSCROLL_BAR (bar
)->prev
= Qnil
;
5230 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
5231 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
5232 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
5237 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5238 Note that WINDOW isn't necessarily condemned at all. */
5241 XTredeem_scroll_bar (window
)
5242 struct window
*window
;
5244 struct scroll_bar
*bar
;
5247 /* We can't redeem this window's scroll bar if it doesn't have one. */
5248 if (NILP (window
->vertical_scroll_bar
))
5251 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
5253 /* Unlink it from the condemned list. */
5254 f
= XFRAME (WINDOW_FRAME (window
));
5255 if (NILP (bar
->prev
))
5257 /* If the prev pointer is nil, it must be the first in one of
5259 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
5260 /* It's not condemned. Everything's fine. */
5262 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
5263 window
->vertical_scroll_bar
))
5264 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
5266 /* If its prev pointer is nil, it must be at the front of
5267 one or the other! */
5271 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
5273 if (! NILP (bar
->next
))
5274 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
5276 bar
->next
= FRAME_SCROLL_BARS (f
);
5278 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5279 if (! NILP (bar
->next
))
5280 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5283 /* Remove all scroll bars on FRAME that haven't been saved since the
5284 last call to `*condemn_scroll_bars_hook'. */
5287 XTjudge_scroll_bars (f
)
5290 Lisp_Object bar
, next
;
5292 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
5294 /* Clear out the condemned list now so we won't try to process any
5295 more events on the hapless scroll bars. */
5296 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
5298 for (; ! NILP (bar
); bar
= next
)
5300 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
5302 x_scroll_bar_remove (b
);
5305 b
->next
= b
->prev
= Qnil
;
5308 /* Now there should be no references to the condemned scroll bars,
5309 and they should get garbage-collected. */
5313 #ifndef USE_TOOLKIT_SCROLL_BARS
5314 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
5315 is a no-op when using toolkit scroll bars.
5317 This may be called from a signal handler, so we have to ignore GC
5321 x_scroll_bar_expose (bar
, event
)
5322 struct scroll_bar
*bar
;
5325 Window w
= SCROLL_BAR_X_WINDOW (bar
);
5326 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5327 GC gc
= f
->output_data
.x
->normal_gc
;
5328 int width_trim
= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
5332 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
5334 /* Draw a one-pixel border just inside the edges of the scroll bar. */
5335 XDrawRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
5337 /* x, y, width, height */
5339 XINT (bar
->width
) - 1 - width_trim
- width_trim
,
5340 XINT (bar
->height
) - 1);
5345 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5347 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5348 is set to something other than NO_EVENT, it is enqueued.
5350 This may be called from a signal handler, so we have to ignore GC
5355 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
5356 struct scroll_bar
*bar
;
5358 struct input_event
*emacs_event
;
5360 if (! GC_WINDOWP (bar
->window
))
5363 emacs_event
->kind
= SCROLL_BAR_CLICK_EVENT
;
5364 emacs_event
->code
= event
->xbutton
.button
- Button1
;
5365 emacs_event
->modifiers
5366 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
5367 (XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))),
5368 event
->xbutton
.state
)
5369 | (event
->type
== ButtonRelease
5372 emacs_event
->frame_or_window
= bar
->window
;
5373 emacs_event
->arg
= Qnil
;
5374 emacs_event
->timestamp
= event
->xbutton
.time
;
5377 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5379 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
5382 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5383 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
5386 if (y
> top_range
) y
= top_range
;
5388 if (y
< XINT (bar
->start
))
5389 emacs_event
->part
= scroll_bar_above_handle
;
5390 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5391 emacs_event
->part
= scroll_bar_handle
;
5393 emacs_event
->part
= scroll_bar_below_handle
;
5395 /* Just because the user has clicked on the handle doesn't mean
5396 they want to drag it. Lisp code needs to be able to decide
5397 whether or not we're dragging. */
5399 /* If the user has just clicked on the handle, record where they're
5401 if (event
->type
== ButtonPress
5402 && emacs_event
->part
== scroll_bar_handle
)
5403 XSETINT (bar
->dragging
, y
- XINT (bar
->start
));
5406 #ifndef USE_TOOLKIT_SCROLL_BARS
5407 /* If the user has released the handle, set it to its final position. */
5408 if (event
->type
== ButtonRelease
5409 && ! NILP (bar
->dragging
))
5411 int new_start
= y
- XINT (bar
->dragging
);
5412 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5414 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5415 bar
->dragging
= Qnil
;
5419 /* Same deal here as the other #if 0. */
5421 /* Clicks on the handle are always reported as occurring at the top of
5423 if (emacs_event
->part
== scroll_bar_handle
)
5424 emacs_event
->x
= bar
->start
;
5426 XSETINT (emacs_event
->x
, y
);
5428 XSETINT (emacs_event
->x
, y
);
5431 XSETINT (emacs_event
->y
, top_range
);
5435 #ifndef USE_TOOLKIT_SCROLL_BARS
5437 /* Handle some mouse motion while someone is dragging the scroll bar.
5439 This may be called from a signal handler, so we have to ignore GC
5443 x_scroll_bar_note_movement (bar
, event
)
5444 struct scroll_bar
*bar
;
5447 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5449 last_mouse_movement_time
= event
->xmotion
.time
;
5452 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5454 /* If we're dragging the bar, display it. */
5455 if (! GC_NILP (bar
->dragging
))
5457 /* Where should the handle be now? */
5458 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
5460 if (new_start
!= XINT (bar
->start
))
5462 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5464 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5469 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5471 /* Return information to the user about the current position of the mouse
5472 on the scroll bar. */
5475 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5477 Lisp_Object
*bar_window
;
5478 enum scroll_bar_part
*part
;
5480 unsigned long *time
;
5482 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5483 Window w
= SCROLL_BAR_X_WINDOW (bar
);
5484 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5486 Window dummy_window
;
5488 unsigned int dummy_mask
;
5492 /* Get the mouse's position relative to the scroll bar window, and
5494 if (! XQueryPointer (FRAME_X_DISPLAY (f
), w
,
5496 /* Root, child, root x and root y. */
5497 &dummy_window
, &dummy_window
,
5498 &dummy_coord
, &dummy_coord
,
5500 /* Position relative to scroll bar. */
5503 /* Mouse buttons and modifier keys. */
5510 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
5513 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5515 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5517 if (! NILP (bar
->dragging
))
5518 win_y
-= XINT (bar
->dragging
);
5522 if (win_y
> top_range
)
5526 *bar_window
= bar
->window
;
5528 if (! NILP (bar
->dragging
))
5529 *part
= scroll_bar_handle
;
5530 else if (win_y
< XINT (bar
->start
))
5531 *part
= scroll_bar_above_handle
;
5532 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5533 *part
= scroll_bar_handle
;
5535 *part
= scroll_bar_below_handle
;
5537 XSETINT (*x
, win_y
);
5538 XSETINT (*y
, top_range
);
5541 last_mouse_scroll_bar
= Qnil
;
5544 *time
= last_mouse_movement_time
;
5550 /* The screen has been cleared so we may have changed foreground or
5551 background colors, and the scroll bars may need to be redrawn.
5552 Clear out the scroll bars, and ask for expose events, so we can
5556 x_scroll_bar_clear (f
)
5559 #ifndef USE_TOOLKIT_SCROLL_BARS
5562 /* We can have scroll bars even if this is 0,
5563 if we just turned off scroll bar mode.
5564 But in that case we should not clear them. */
5565 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5566 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
5567 bar
= XSCROLL_BAR (bar
)->next
)
5568 XClearArea (FRAME_X_DISPLAY (f
),
5569 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
5571 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5575 /* The main X event-reading loop - XTread_socket. */
5578 /* Time stamp of enter window event. This is only used by XTread_socket,
5579 but we have to put it out here, since static variables within functions
5580 sometimes don't work. */
5582 static Time enter_timestamp
;
5585 /* This holds the state XLookupString needs to implement dead keys
5586 and other tricks known as "compose processing". _X Window System_
5587 says that a portable program can't use this, but Stephen Gildea assures
5588 me that letting the compiler initialize it to zeros will work okay.
5590 This must be defined outside of XTread_socket, for the same reasons
5591 given for enter_timestamp, above. */
5593 static XComposeStatus compose_status
;
5595 /* Record the last 100 characters stored
5596 to help debug the loss-of-chars-during-GC problem. */
5598 static int temp_index
;
5599 static short temp_buffer
[100];
5601 #define STORE_KEYSYM_FOR_DEBUG(keysym) \
5602 if (temp_index == sizeof temp_buffer / sizeof (short)) \
5604 temp_buffer[temp_index++] = (keysym)
5606 /* Set this to nonzero to fake an "X I/O error"
5607 on a particular display. */
5609 struct x_display_info
*XTread_socket_fake_io_error
;
5611 /* When we find no input here, we occasionally do a no-op command
5612 to verify that the X server is still running and we can still talk with it.
5613 We try all the open displays, one by one.
5614 This variable is used for cycling thru the displays. */
5616 static struct x_display_info
*next_noop_dpyinfo
;
5618 #define SET_SAVED_MENU_EVENT(size) \
5621 if (f->output_data.x->saved_menu_event == 0) \
5622 f->output_data.x->saved_menu_event \
5623 = (XEvent *) xmalloc (sizeof (XEvent)); \
5624 bcopy (&event, f->output_data.x->saved_menu_event, size); \
5625 inev.kind = MENU_BAR_ACTIVATE_EVENT; \
5626 XSETFRAME (inev.frame_or_window, f); \
5630 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
5631 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
5641 /* Filter events for the current X input method.
5642 DPYINFO is the display this event is for.
5643 EVENT is the X event to filter.
5645 Returns non-zero if the event was filtered, caller shall not process
5647 Returns zero if event is wasn't filtered. */
5651 x_filter_event (dpyinfo
, event
)
5652 struct x_display_info
*dpyinfo
;
5655 /* XFilterEvent returns non-zero if the input method has
5656 consumed the event. We pass the frame's X window to
5657 XFilterEvent because that's the one for which the IC
5660 struct frame
*f1
= x_any_window_to_frame (dpyinfo
,
5661 event
->xclient
.window
);
5663 return XFilterEvent (event
, f1
? FRAME_X_WINDOW (f1
) : None
);
5668 static int current_count
;
5669 static int current_finish
;
5670 static struct input_event
*current_hold_quit
;
5672 /* This is the filter function invoked by the GTK event loop.
5673 It is invoked before the XEvent is translated to a GdkEvent,
5674 so we have a chance to act on the event before GTK. */
5675 static GdkFilterReturn
5676 event_handler_gdk (gxev
, ev
, data
)
5681 XEvent
*xev
= (XEvent
*) gxev
;
5683 if (current_count
>= 0)
5685 struct x_display_info
*dpyinfo
;
5687 dpyinfo
= x_display_info_for_display (xev
->xany
.display
);
5690 /* Filter events for the current X input method.
5691 GTK calls XFilterEvent but not for key press and release,
5692 so we do it here. */
5693 if (xev
->type
== KeyPress
|| xev
->type
== KeyRelease
)
5694 if (dpyinfo
&& x_filter_event (dpyinfo
, xev
))
5695 return GDK_FILTER_REMOVE
;
5699 current_finish
= X_EVENT_NORMAL
;
5703 handle_one_xevent (dpyinfo
, xev
, ¤t_finish
,
5708 current_finish
= x_dispatch_event (xev
, xev
->xany
.display
);
5710 if (current_finish
== X_EVENT_GOTO_OUT
|| current_finish
== X_EVENT_DROP
)
5711 return GDK_FILTER_REMOVE
;
5713 return GDK_FILTER_CONTINUE
;
5715 #endif /* USE_GTK */
5718 /* Handles the XEvent EVENT on display DPYINFO.
5720 *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
5721 *FINISH is zero if caller should continue reading events.
5722 *FINISH is X_EVENT_DROP if event should not be passed to the toolkit.
5724 We return the number of characters stored into the buffer. */
5727 handle_one_xevent (dpyinfo
, eventp
, finish
, hold_quit
)
5728 struct x_display_info
*dpyinfo
;
5731 struct input_event
*hold_quit
;
5733 struct input_event inev
;
5738 struct coding_system coding
;
5739 XEvent event
= *eventp
;
5741 *finish
= X_EVENT_NORMAL
;
5744 inev
.kind
= NO_EVENT
;
5751 if (event
.xclient
.message_type
5752 == dpyinfo
->Xatom_wm_protocols
5753 && event
.xclient
.format
== 32)
5755 if (event
.xclient
.data
.l
[0]
5756 == dpyinfo
->Xatom_wm_take_focus
)
5758 /* Use x_any_window_to_frame because this
5759 could be the shell widget window
5760 if the frame has no title bar. */
5761 f
= x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
5763 /* Not quite sure this is needed -pd */
5764 if (f
&& FRAME_XIC (f
))
5765 XSetICFocus (FRAME_XIC (f
));
5767 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
5768 instructs the WM to set the input focus automatically for
5769 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
5770 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
5771 it has set the focus. So, XSetInputFocus below is not
5774 The call to XSetInputFocus below has also caused trouble. In
5775 cases where the XSetInputFocus done by the WM and the one
5776 below are temporally close (on a fast machine), the call
5777 below can generate additional FocusIn events which confuse
5780 /* Since we set WM_TAKE_FOCUS, we must call
5781 XSetInputFocus explicitly. But not if f is null,
5782 since that might be an event for a deleted frame. */
5785 Display
*d
= event
.xclient
.display
;
5786 /* Catch and ignore errors, in case window has been
5787 iconified by a window manager such as GWM. */
5788 int count
= x_catch_errors (d
);
5789 XSetInputFocus (d
, event
.xclient
.window
,
5790 /* The ICCCM says this is
5791 the only valid choice. */
5793 event
.xclient
.data
.l
[1]);
5794 /* This is needed to detect the error
5795 if there is an error. */
5797 x_uncatch_errors (d
, count
);
5799 /* Not certain about handling scroll bars here */
5804 if (event
.xclient
.data
.l
[0]
5805 == dpyinfo
->Xatom_wm_save_yourself
)
5807 /* Save state modify the WM_COMMAND property to
5808 something which can reinstate us. This notifies
5809 the session manager, who's looking for such a
5810 PropertyNotify. Can restart processing when
5811 a keyboard or mouse event arrives. */
5812 /* If we have a session manager, don't set this.
5813 KDE will then start two Emacsen, one for the
5814 session manager and one for this. */
5816 if (! x_session_have_connection ())
5819 f
= x_top_window_to_frame (dpyinfo
,
5820 event
.xclient
.window
);
5821 /* This is just so we only give real data once
5822 for a single Emacs process. */
5823 if (f
== SELECTED_FRAME ())
5824 XSetCommand (FRAME_X_DISPLAY (f
),
5825 event
.xclient
.window
,
5826 initial_argv
, initial_argc
);
5828 XSetCommand (FRAME_X_DISPLAY (f
),
5829 event
.xclient
.window
,
5835 if (event
.xclient
.data
.l
[0]
5836 == dpyinfo
->Xatom_wm_delete_window
)
5838 f
= x_any_window_to_frame (dpyinfo
,
5839 event
.xclient
.window
);
5841 goto OTHER
; /* May be a dialog that is to be removed */
5843 inev
.kind
= DELETE_WINDOW_EVENT
;
5844 XSETFRAME (inev
.frame_or_window
, f
);
5851 if (event
.xclient
.message_type
5852 == dpyinfo
->Xatom_wm_configure_denied
)
5857 if (event
.xclient
.message_type
5858 == dpyinfo
->Xatom_wm_window_moved
)
5861 f
= x_window_to_frame (dpyinfo
, event
.xclient
.window
);
5863 new_x
= event
.xclient
.data
.s
[0];
5864 new_y
= event
.xclient
.data
.s
[1];
5868 f
->left_pos
= new_x
;
5875 if (event
.xclient
.message_type
5876 == dpyinfo
->Xatom_editres
)
5878 f
= x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
5879 _XEditResCheckMessages (f
->output_data
.x
->widget
, NULL
,
5883 #endif /* HACK_EDITRES */
5885 if ((event
.xclient
.message_type
5886 == dpyinfo
->Xatom_DONE
)
5887 || (event
.xclient
.message_type
5888 == dpyinfo
->Xatom_PAGE
))
5890 /* Ghostview job completed. Kill it. We could
5891 reply with "Next" if we received "Page", but we
5892 currently never do because we are interested in
5893 images, only, which should have 1 page. */
5894 Pixmap pixmap
= (Pixmap
) event
.xclient
.data
.l
[1];
5895 f
= x_window_to_frame (dpyinfo
, event
.xclient
.window
);
5896 x_kill_gs_process (pixmap
, f
);
5897 expose_frame (f
, 0, 0, 0, 0);
5901 #ifdef USE_TOOLKIT_SCROLL_BARS
5902 /* Scroll bar callbacks send a ClientMessage from which
5903 we construct an input_event. */
5904 if (event
.xclient
.message_type
5905 == dpyinfo
->Xatom_Scrollbar
)
5907 x_scroll_bar_to_input_event (&event
, &inev
);
5908 *finish
= X_EVENT_GOTO_OUT
;
5911 #endif /* USE_TOOLKIT_SCROLL_BARS */
5913 f
= x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
5918 if (x_handle_dnd_message (f
, &event
.xclient
, dpyinfo
, &inev
))
5919 *finish
= X_EVENT_DROP
;
5923 case SelectionNotify
:
5924 #ifdef USE_X_TOOLKIT
5925 if (! x_window_to_frame (dpyinfo
, event
.xselection
.requestor
))
5927 #endif /* not USE_X_TOOLKIT */
5928 x_handle_selection_notify (&event
.xselection
);
5931 case SelectionClear
: /* Someone has grabbed ownership. */
5932 #ifdef USE_X_TOOLKIT
5933 if (! x_window_to_frame (dpyinfo
, event
.xselectionclear
.window
))
5935 #endif /* USE_X_TOOLKIT */
5937 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
5939 inev
.kind
= SELECTION_CLEAR_EVENT
;
5940 SELECTION_EVENT_DISPLAY (&inev
) = eventp
->display
;
5941 SELECTION_EVENT_SELECTION (&inev
) = eventp
->selection
;
5942 SELECTION_EVENT_TIME (&inev
) = eventp
->time
;
5943 inev
.frame_or_window
= Qnil
;
5947 case SelectionRequest
: /* Someone wants our selection. */
5948 #ifdef USE_X_TOOLKIT
5949 if (!x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
))
5951 #endif /* USE_X_TOOLKIT */
5953 XSelectionRequestEvent
*eventp
5954 = (XSelectionRequestEvent
*) &event
;
5956 inev
.kind
= SELECTION_REQUEST_EVENT
;
5957 SELECTION_EVENT_DISPLAY (&inev
) = eventp
->display
;
5958 SELECTION_EVENT_REQUESTOR (&inev
) = eventp
->requestor
;
5959 SELECTION_EVENT_SELECTION (&inev
) = eventp
->selection
;
5960 SELECTION_EVENT_TARGET (&inev
) = eventp
->target
;
5961 SELECTION_EVENT_PROPERTY (&inev
) = eventp
->property
;
5962 SELECTION_EVENT_TIME (&inev
) = eventp
->time
;
5963 inev
.frame_or_window
= Qnil
;
5967 case PropertyNotify
:
5968 #if 0 /* This is plain wrong. In the case that we are waiting for a
5969 PropertyNotify used as an ACK in incremental selection
5970 transfer, the property will be on the receiver's window. */
5971 #if defined USE_X_TOOLKIT
5972 if (!x_any_window_to_frame (dpyinfo
, event
.xproperty
.window
))
5976 x_handle_property_notify (&event
.xproperty
);
5979 case ReparentNotify
:
5980 f
= x_top_window_to_frame (dpyinfo
, event
.xreparent
.window
);
5984 f
->output_data
.x
->parent_desc
= event
.xreparent
.parent
;
5985 x_real_positions (f
, &x
, &y
);
5989 /* Perhaps reparented due to a WM restart. Reset this. */
5990 FRAME_X_DISPLAY_INFO (f
)->wm_type
= X_WMTYPE_UNKNOWN
;
5995 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
5998 x_check_fullscreen (f
);
6001 /* This seems to be needed for GTK 2.6. */
6002 x_clear_area (event
.xexpose
.display
,
6003 event
.xexpose
.window
,
6004 event
.xexpose
.x
, event
.xexpose
.y
,
6005 event
.xexpose
.width
, event
.xexpose
.height
,
6008 if (f
->async_visible
== 0)
6010 f
->async_visible
= 1;
6011 f
->async_iconified
= 0;
6012 f
->output_data
.x
->has_been_visible
= 1;
6013 SET_FRAME_GARBAGED (f
);
6017 event
.xexpose
.x
, event
.xexpose
.y
,
6018 event
.xexpose
.width
, event
.xexpose
.height
);
6022 #ifndef USE_TOOLKIT_SCROLL_BARS
6023 struct scroll_bar
*bar
;
6025 #if defined USE_LUCID
6026 /* Submenus of the Lucid menu bar aren't widgets
6027 themselves, so there's no way to dispatch events
6028 to them. Recognize this case separately. */
6031 = x_window_to_menu_bar (event
.xexpose
.window
);
6033 xlwmenu_redisplay (widget
);
6035 #endif /* USE_LUCID */
6037 #ifdef USE_TOOLKIT_SCROLL_BARS
6038 /* Dispatch event to the widget. */
6040 #else /* not USE_TOOLKIT_SCROLL_BARS */
6041 bar
= x_window_to_scroll_bar (event
.xexpose
.display
,
6042 event
.xexpose
.window
);
6045 x_scroll_bar_expose (bar
, &event
);
6046 #ifdef USE_X_TOOLKIT
6049 #endif /* USE_X_TOOLKIT */
6050 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6054 case GraphicsExpose
: /* This occurs when an XCopyArea's
6055 source area was obscured or not
6057 f
= x_window_to_frame (dpyinfo
, event
.xgraphicsexpose
.drawable
);
6061 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
6062 event
.xgraphicsexpose
.width
,
6063 event
.xgraphicsexpose
.height
);
6065 #ifdef USE_X_TOOLKIT
6068 #endif /* USE_X_TOOLKIT */
6071 case NoExpose
: /* This occurs when an XCopyArea's
6072 source area was completely
6077 /* Redo the mouse-highlight after the tooltip has gone. */
6078 if (event
.xmap
.window
== tip_window
)
6081 redo_mouse_highlight ();
6084 f
= x_top_window_to_frame (dpyinfo
, event
.xunmap
.window
);
6085 if (f
) /* F may no longer exist if
6086 the frame was deleted. */
6088 /* While a frame is unmapped, display generation is
6089 disabled; you don't want to spend time updating a
6090 display that won't ever be seen. */
6091 f
->async_visible
= 0;
6092 /* We can't distinguish, from the event, whether the window
6093 has become iconified or invisible. So assume, if it
6094 was previously visible, than now it is iconified.
6095 But x_make_frame_invisible clears both
6096 the visible flag and the iconified flag;
6097 and that way, we know the window is not iconified now. */
6098 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
6100 f
->async_iconified
= 1;
6102 inev
.kind
= ICONIFY_EVENT
;
6103 XSETFRAME (inev
.frame_or_window
, f
);
6109 if (event
.xmap
.window
== tip_window
)
6110 /* The tooltip has been drawn already. Avoid
6111 the SET_FRAME_GARBAGED below. */
6114 /* We use x_top_window_to_frame because map events can
6115 come for sub-windows and they don't mean that the
6116 frame is visible. */
6117 f
= x_top_window_to_frame (dpyinfo
, event
.xmap
.window
);
6120 /* wait_reading_process_output will notice this and update
6121 the frame's display structures.
6122 If we where iconified, we should not set garbaged,
6123 because that stops redrawing on Expose events. This looks
6124 bad if we are called from a recursive event loop
6125 (x_dispatch_event), for example when a dialog is up. */
6126 if (! f
->async_iconified
)
6127 SET_FRAME_GARBAGED (f
);
6129 f
->async_visible
= 1;
6130 f
->async_iconified
= 0;
6131 f
->output_data
.x
->has_been_visible
= 1;
6135 inev
.kind
= DEICONIFY_EVENT
;
6136 XSETFRAME (inev
.frame_or_window
, f
);
6138 else if (! NILP (Vframe_list
)
6139 && ! NILP (XCDR (Vframe_list
)))
6140 /* Force a redisplay sooner or later
6141 to update the frame titles
6142 in case this is the second frame. */
6143 record_asynch_buffer_change ();
6149 ignore_next_mouse_click_timeout
= 0;
6151 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6152 /* Dispatch KeyPress events when in menu. */
6153 if (popup_activated ())
6157 f
= x_any_window_to_frame (dpyinfo
, event
.xkey
.window
);
6159 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
6161 clear_mouse_face (dpyinfo
);
6162 dpyinfo
->mouse_face_hidden
= 1;
6165 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
6168 /* Scroll bars consume key events, but we want
6169 the keys to go to the scroll bar's frame. */
6170 Widget widget
= XtWindowToWidget (dpyinfo
->display
,
6172 if (widget
&& XmIsScrollBar (widget
))
6174 widget
= XtParent (widget
);
6175 f
= x_any_window_to_frame (dpyinfo
, XtWindow (widget
));
6178 #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
6182 KeySym keysym
, orig_keysym
;
6183 /* al%imercury@uunet.uu.net says that making this 81
6184 instead of 80 fixed a bug whereby meta chars made
6187 It seems that some version of XmbLookupString has
6188 a bug of not returning XBufferOverflow in
6189 status_return even if the input is too long to
6190 fit in 81 bytes. So, we must prepare sufficient
6191 bytes for copy_buffer. 513 bytes (256 chars for
6192 two-byte character set) seems to be a fairly good
6193 approximation. -- 2000.8.10 handa@etl.go.jp */
6194 unsigned char copy_buffer
[513];
6195 unsigned char *copy_bufptr
= copy_buffer
;
6196 int copy_bufsiz
= sizeof (copy_buffer
);
6198 Lisp_Object coding_system
= Qlatin_1
;
6202 /* Don't pass keys to GTK. A Tab will shift focus to the
6203 tool bar in GTK 2.4. Keys will still go to menus and
6204 dialogs because in that case popup_activated is TRUE
6206 *finish
= X_EVENT_DROP
;
6210 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f
),
6211 extra_keyboard_modifiers
);
6212 modifiers
= event
.xkey
.state
;
6214 /* This will have to go some day... */
6216 /* make_lispy_event turns chars into control chars.
6217 Don't do it here because XLookupString is too eager. */
6218 event
.xkey
.state
&= ~ControlMask
;
6219 event
.xkey
.state
&= ~(dpyinfo
->meta_mod_mask
6220 | dpyinfo
->super_mod_mask
6221 | dpyinfo
->hyper_mod_mask
6222 | dpyinfo
->alt_mod_mask
);
6224 /* In case Meta is ComposeCharacter,
6225 clear its status. According to Markus Ehrnsperger
6226 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
6227 this enables ComposeCharacter to work whether or
6228 not it is combined with Meta. */
6229 if (modifiers
& dpyinfo
->meta_mod_mask
)
6230 bzero (&compose_status
, sizeof (compose_status
));
6235 Status status_return
;
6237 coding_system
= Vlocale_coding_system
;
6238 nbytes
= XmbLookupString (FRAME_XIC (f
),
6239 &event
.xkey
, copy_bufptr
,
6240 copy_bufsiz
, &keysym
,
6242 if (status_return
== XBufferOverflow
)
6244 copy_bufsiz
= nbytes
+ 1;
6245 copy_bufptr
= (char *) alloca (copy_bufsiz
);
6246 nbytes
= XmbLookupString (FRAME_XIC (f
),
6247 &event
.xkey
, copy_bufptr
,
6248 copy_bufsiz
, &keysym
,
6251 /* Xutf8LookupString is a new but already deprecated interface. -stef */
6252 #if 0 && defined X_HAVE_UTF8_STRING
6253 else if (status_return
== XLookupKeySym
)
6254 { /* Try again but with utf-8. */
6255 coding_system
= Qutf_8
;
6256 nbytes
= Xutf8LookupString (FRAME_XIC (f
),
6257 &event
.xkey
, copy_bufptr
,
6258 copy_bufsiz
, &keysym
,
6260 if (status_return
== XBufferOverflow
)
6262 copy_bufsiz
= nbytes
+ 1;
6263 copy_bufptr
= (char *) alloca (copy_bufsiz
);
6264 nbytes
= Xutf8LookupString (FRAME_XIC (f
),
6267 copy_bufsiz
, &keysym
,
6273 if (status_return
== XLookupNone
)
6275 else if (status_return
== XLookupChars
)
6280 else if (status_return
!= XLookupKeySym
6281 && status_return
!= XLookupBoth
)
6285 nbytes
= XLookupString (&event
.xkey
, copy_bufptr
,
6286 copy_bufsiz
, &keysym
,
6289 nbytes
= XLookupString (&event
.xkey
, copy_bufptr
,
6290 copy_bufsiz
, &keysym
,
6294 /* If not using XIM/XIC, and a compose sequence is in progress,
6295 we break here. Otherwise, chars_matched is always 0. */
6296 if (compose_status
.chars_matched
> 0 && nbytes
== 0)
6299 orig_keysym
= keysym
;
6301 /* Common for all keysym input events. */
6302 XSETFRAME (inev
.frame_or_window
, f
);
6304 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
), modifiers
);
6305 inev
.timestamp
= event
.xkey
.time
;
6307 /* First deal with keysyms which have defined
6308 translations to characters. */
6309 if (keysym
>= 32 && keysym
< 128)
6310 /* Avoid explicitly decoding each ASCII character. */
6312 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
6317 /* Now non-ASCII. */
6318 if (HASH_TABLE_P (Vx_keysym_table
)
6319 && (NATNUMP (c
= Fgethash (make_number (keysym
),
6323 inev
.kind
= (SINGLE_BYTE_CHAR_P (XFASTINT (c
))
6324 ? ASCII_KEYSTROKE_EVENT
6325 : MULTIBYTE_CHAR_KEYSTROKE_EVENT
);
6326 inev
.code
= XFASTINT (c
);
6330 /* Random non-modifier sorts of keysyms. */
6331 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
6332 || keysym
== XK_Delete
6333 #ifdef XK_ISO_Left_Tab
6334 || (keysym
>= XK_ISO_Left_Tab
6335 && keysym
<= XK_ISO_Enter
)
6337 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
6338 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
6340 /* This recognizes the "extended function
6341 keys". It seems there's no cleaner way.
6342 Test IsModifierKey to avoid handling
6343 mode_switch incorrectly. */
6344 || ((unsigned) (keysym
) >= XK_Select
6345 && (unsigned)(keysym
) < XK_KP_Space
)
6347 #ifdef XK_dead_circumflex
6348 || orig_keysym
== XK_dead_circumflex
6350 #ifdef XK_dead_grave
6351 || orig_keysym
== XK_dead_grave
6353 #ifdef XK_dead_tilde
6354 || orig_keysym
== XK_dead_tilde
6356 #ifdef XK_dead_diaeresis
6357 || orig_keysym
== XK_dead_diaeresis
6359 #ifdef XK_dead_macron
6360 || orig_keysym
== XK_dead_macron
6362 #ifdef XK_dead_degree
6363 || orig_keysym
== XK_dead_degree
6365 #ifdef XK_dead_acute
6366 || orig_keysym
== XK_dead_acute
6368 #ifdef XK_dead_cedilla
6369 || orig_keysym
== XK_dead_cedilla
6371 #ifdef XK_dead_breve
6372 || orig_keysym
== XK_dead_breve
6374 #ifdef XK_dead_ogonek
6375 || orig_keysym
== XK_dead_ogonek
6377 #ifdef XK_dead_caron
6378 || orig_keysym
== XK_dead_caron
6380 #ifdef XK_dead_doubleacute
6381 || orig_keysym
== XK_dead_doubleacute
6383 #ifdef XK_dead_abovedot
6384 || orig_keysym
== XK_dead_abovedot
6386 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
6387 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
6388 /* Any "vendor-specific" key is ok. */
6389 || (orig_keysym
& (1 << 28))
6390 || (keysym
!= NoSymbol
&& nbytes
== 0))
6391 && ! (IsModifierKey (orig_keysym
)
6393 #ifdef XK_Mode_switch
6394 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
6397 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
6399 #endif /* not HAVE_X11R5 */
6400 /* The symbols from XK_ISO_Lock
6401 to XK_ISO_Last_Group_Lock
6402 don't have real modifiers but
6403 should be treated similarly to
6404 Mode_switch by Emacs. */
6405 #if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
6406 || ((unsigned)(orig_keysym
)
6408 && (unsigned)(orig_keysym
)
6409 <= XK_ISO_Last_Group_Lock
)
6413 STORE_KEYSYM_FOR_DEBUG (keysym
);
6414 /* make_lispy_event will convert this to a symbolic
6416 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
6421 { /* Raw bytes, not keysym. */
6426 /* The input should be decoded with `coding_system'
6427 which depends on which X*LookupString function
6428 we used just above and the locale. */
6429 setup_coding_system (coding_system
, &coding
);
6430 coding
.src_multibyte
= 0;
6431 coding
.dst_multibyte
= 1;
6432 /* The input is converted to events, thus we can't
6433 handle composition. Anyway, there's no XIM that
6434 gives us composition information. */
6435 coding
.composing
= COMPOSITION_DISABLED
;
6437 for (i
= 0; i
< nbytes
; i
++)
6439 STORE_KEYSYM_FOR_DEBUG (copy_bufptr
[i
]);
6443 /* Decode the input data. */
6447 require
= decoding_buffer_size (&coding
, nbytes
);
6448 p
= (unsigned char *) alloca (require
);
6449 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6450 /* We explicitly disable composition handling because
6451 key data should not contain any composition sequence. */
6452 coding
.composing
= COMPOSITION_DISABLED
;
6453 decode_coding (&coding
, copy_bufptr
, p
, nbytes
, require
);
6454 nbytes
= coding
.produced
;
6455 nchars
= coding
.produced_char
;
6459 /* Convert the input data to a sequence of
6460 character events. */
6461 for (i
= 0; i
< nbytes
; i
+= len
)
6463 if (nchars
== nbytes
)
6464 c
= copy_bufptr
[i
], len
= 1;
6466 c
= STRING_CHAR_AND_LENGTH (copy_bufptr
+ i
,
6468 inev
.kind
= (SINGLE_BYTE_CHAR_P (c
)
6469 ? ASCII_KEYSTROKE_EVENT
6470 : MULTIBYTE_CHAR_KEYSTROKE_EVENT
);
6472 kbd_buffer_store_event_hold (&inev
, hold_quit
);
6475 /* Previous code updated count by nchars rather than nbytes,
6476 but that seems bogus to me. ++kfs */
6479 inev
.kind
= NO_EVENT
; /* Already stored above. */
6481 if (keysym
== NoSymbol
)
6487 /* Don't dispatch this event since XtDispatchEvent calls
6488 XFilterEvent, and two calls in a row may freeze the
6497 /* Don't dispatch this event since XtDispatchEvent calls
6498 XFilterEvent, and two calls in a row may freeze the
6506 x_detect_focus_change (dpyinfo
, &event
, &inev
);
6508 f
= x_any_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
6510 if (f
&& x_mouse_click_focus_ignore_position
)
6511 ignore_next_mouse_click_timeout
= event
.xmotion
.time
+ 200;
6514 if (event
.xcrossing
.focus
)
6516 /* Avoid nasty pop/raise loops. */
6517 if (f
&& (!(f
->auto_raise
)
6519 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
6521 x_new_focus_frame (dpyinfo
, f
);
6522 enter_timestamp
= event
.xcrossing
.time
;
6525 else if (f
== dpyinfo
->x_focus_frame
)
6526 x_new_focus_frame (dpyinfo
, 0);
6529 /* EnterNotify counts as mouse movement,
6530 so update things that depend on mouse position. */
6531 if (f
&& !f
->output_data
.x
->hourglass_p
)
6532 note_mouse_movement (f
, &event
.xmotion
);
6536 x_detect_focus_change (dpyinfo
, &event
, &inev
);
6540 x_detect_focus_change (dpyinfo
, &event
, &inev
);
6542 f
= x_top_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
6545 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6547 /* If we move outside the frame, then we're
6548 certainly no longer on any text in the frame. */
6549 clear_mouse_face (dpyinfo
);
6550 dpyinfo
->mouse_face_mouse_frame
= 0;
6553 /* Generate a nil HELP_EVENT to cancel a help-echo.
6554 Do it only if there's something to cancel.
6555 Otherwise, the startup message is cleared when
6556 the mouse leaves the frame. */
6557 if (any_help_event_p
)
6563 x_detect_focus_change (dpyinfo
, &event
, &inev
);
6568 previous_help_echo_string
= help_echo_string
;
6569 help_echo_string
= help_echo_object
= help_echo_window
= Qnil
;
6572 if (dpyinfo
->grabbed
&& last_mouse_frame
6573 && FRAME_LIVE_P (last_mouse_frame
))
6574 f
= last_mouse_frame
;
6576 f
= x_window_to_frame (dpyinfo
, event
.xmotion
.window
);
6578 if (dpyinfo
->mouse_face_hidden
)
6580 dpyinfo
->mouse_face_hidden
= 0;
6581 clear_mouse_face (dpyinfo
);
6587 /* Generate SELECT_WINDOW_EVENTs when needed. */
6588 if (mouse_autoselect_window
)
6592 window
= window_from_coordinates (f
,
6593 event
.xmotion
.x
, event
.xmotion
.y
,
6596 /* Window will be selected only when it is not selected now and
6597 last mouse movement event was not in it. Minibuffer window
6598 will be selected iff it is active. */
6599 if (WINDOWP (window
)
6600 && !EQ (window
, last_window
)
6601 && !EQ (window
, selected_window
))
6603 inev
.kind
= SELECT_WINDOW_EVENT
;
6604 inev
.frame_or_window
= window
;
6609 note_mouse_movement (f
, &event
.xmotion
);
6613 #ifndef USE_TOOLKIT_SCROLL_BARS
6614 struct scroll_bar
*bar
6615 = x_window_to_scroll_bar (event
.xmotion
.display
,
6616 event
.xmotion
.window
);
6619 x_scroll_bar_note_movement (bar
, &event
);
6620 #endif /* USE_TOOLKIT_SCROLL_BARS */
6622 /* If we move outside the frame, then we're
6623 certainly no longer on any text in the frame. */
6624 clear_mouse_face (dpyinfo
);
6627 /* If the contents of the global variable help_echo_string
6628 has changed, generate a HELP_EVENT. */
6629 if (!NILP (help_echo_string
)
6630 || !NILP (previous_help_echo_string
))
6635 case ConfigureNotify
:
6636 f
= x_top_window_to_frame (dpyinfo
, event
.xconfigure
.window
);
6639 #ifndef USE_X_TOOLKIT
6641 xg_resize_widgets (f
, event
.xconfigure
.width
,
6642 event
.xconfigure
.height
);
6643 #else /* not USE_GTK */
6644 /* If there is a pending resize for fullscreen, don't
6645 do this one, the right one will come later.
6646 The toolkit version doesn't seem to need this, but we
6647 need to reset it below. */
6649 = ((f
->want_fullscreen
& FULLSCREEN_WAIT
)
6650 && f
->new_text_cols
!= 0);
6651 int rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, event
.xconfigure
.height
);
6652 int columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, event
.xconfigure
.width
);
6657 /* In the toolkit version, change_frame_size
6658 is called by the code that handles resizing
6659 of the EmacsFrame widget. */
6661 /* Even if the number of character rows and columns has
6662 not changed, the font size may have changed, so we need
6663 to check the pixel dimensions as well. */
6664 if (columns
!= FRAME_COLS (f
)
6665 || rows
!= FRAME_LINES (f
)
6666 || event
.xconfigure
.width
!= FRAME_PIXEL_WIDTH (f
)
6667 || event
.xconfigure
.height
!= FRAME_PIXEL_HEIGHT (f
))
6669 change_frame_size (f
, rows
, columns
, 0, 1, 0);
6670 SET_FRAME_GARBAGED (f
);
6671 cancel_mouse_face (f
);
6673 #endif /* not USE_GTK */
6676 FRAME_PIXEL_WIDTH (f
) = event
.xconfigure
.width
;
6677 FRAME_PIXEL_HEIGHT (f
) = event
.xconfigure
.height
;
6680 /* GTK creates windows but doesn't map them.
6681 Only get real positions and check fullscreen when mapped. */
6682 if (FRAME_GTK_OUTER_WIDGET (f
)
6683 && GTK_WIDGET_MAPPED (FRAME_GTK_OUTER_WIDGET (f
)))
6686 /* What we have now is the position of Emacs's own window.
6687 Convert that to the position of the window manager window. */
6688 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
6690 x_check_expected_move (f
);
6691 if (f
->want_fullscreen
& FULLSCREEN_WAIT
)
6692 f
->want_fullscreen
&= ~(FULLSCREEN_WAIT
|FULLSCREEN_BOTH
);
6696 if (FRAME_XIC (f
) && (FRAME_XIC_STYLE (f
) & XIMStatusArea
))
6697 xic_set_statusarea (f
);
6700 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
6702 /* Since the WM decorations come below top_pos now,
6703 we must put them below top_pos in the future. */
6704 f
->win_gravity
= NorthWestGravity
;
6705 x_wm_set_size_hint (f
, (long) 0, 0);
6713 /* If we decide we want to generate an event to be seen
6714 by the rest of Emacs, we put it here. */
6717 bzero (&compose_status
, sizeof (compose_status
));
6719 if (dpyinfo
->grabbed
6721 && FRAME_LIVE_P (last_mouse_frame
))
6722 f
= last_mouse_frame
;
6724 f
= x_window_to_frame (dpyinfo
, event
.xbutton
.window
);
6728 /* Is this in the tool-bar? */
6729 if (WINDOWP (f
->tool_bar_window
)
6730 && WINDOW_TOTAL_LINES (XWINDOW (f
->tool_bar_window
)))
6733 int x
= event
.xbutton
.x
;
6734 int y
= event
.xbutton
.y
;
6736 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
6737 if (EQ (window
, f
->tool_bar_window
))
6739 if (event
.xbutton
.type
== ButtonPress
)
6740 handle_tool_bar_click (f
, x
, y
, 1, 0);
6742 handle_tool_bar_click (f
, x
, y
, 0,
6743 x_x_to_emacs_modifiers (dpyinfo
,
6744 event
.xbutton
.state
));
6750 if (!dpyinfo
->x_focus_frame
6751 || f
== dpyinfo
->x_focus_frame
)
6753 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6754 if (! popup_activated ())
6757 if (ignore_next_mouse_click_timeout
)
6759 if (event
.type
== ButtonPress
6760 && (int)(event
.xbutton
.time
- ignore_next_mouse_click_timeout
) > 0)
6762 ignore_next_mouse_click_timeout
= 0;
6763 construct_mouse_click (&inev
, &event
, f
);
6765 if (event
.type
== ButtonRelease
)
6766 ignore_next_mouse_click_timeout
= 0;
6769 construct_mouse_click (&inev
, &event
, f
);
6775 struct scroll_bar
*bar
6776 = x_window_to_scroll_bar (event
.xbutton
.display
,
6777 event
.xbutton
.window
);
6779 #ifdef USE_TOOLKIT_SCROLL_BARS
6780 /* Make the "Ctrl-Mouse-2 splits window" work for toolkit
6782 if (bar
&& event
.xbutton
.state
& ControlMask
)
6784 x_scroll_bar_handle_click (bar
, &event
, &inev
);
6785 *finish
= X_EVENT_DROP
;
6787 #else /* not USE_TOOLKIT_SCROLL_BARS */
6789 x_scroll_bar_handle_click (bar
, &event
, &inev
);
6790 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6793 if (event
.type
== ButtonPress
)
6795 dpyinfo
->grabbed
|= (1 << event
.xbutton
.button
);
6796 last_mouse_frame
= f
;
6797 /* Ignore any mouse motion that happened
6798 before this event; any subsequent mouse-movement
6799 Emacs events should reflect only motion after
6805 last_tool_bar_item
= -1;
6808 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
6810 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6811 f
= x_menubar_window_to_frame (dpyinfo
, event
.xbutton
.window
);
6812 /* For a down-event in the menu bar,
6813 don't pass it to Xt right now.
6814 Instead, save it away
6815 and we will pass it to Xt from kbd_buffer_get_event.
6816 That way, we can run some Lisp code first. */
6819 ! popup_activated ()
6822 f
&& event
.type
== ButtonPress
6823 /* Verify the event is really within the menu bar
6824 and not just sent to it due to grabbing. */
6825 && event
.xbutton
.x
>= 0
6826 && event
.xbutton
.x
< FRAME_PIXEL_WIDTH (f
)
6827 && event
.xbutton
.y
>= 0
6828 && event
.xbutton
.y
< f
->output_data
.x
->menubar_height
6829 && event
.xbutton
.same_screen
)
6831 SET_SAVED_BUTTON_EVENT
;
6832 XSETFRAME (last_mouse_press_frame
, f
);
6834 *finish
= X_EVENT_DROP
;
6837 else if (event
.type
== ButtonPress
)
6839 last_mouse_press_frame
= Qnil
;
6843 #ifdef USE_MOTIF /* This should do not harm for Lucid,
6844 but I am trying to be cautious. */
6845 else if (event
.type
== ButtonRelease
)
6847 if (!NILP (last_mouse_press_frame
))
6849 f
= XFRAME (last_mouse_press_frame
);
6850 if (f
->output_data
.x
)
6851 SET_SAVED_BUTTON_EVENT
;
6856 #endif /* USE_MOTIF */
6859 #endif /* USE_X_TOOLKIT || USE_GTK */
6863 case CirculateNotify
:
6866 case CirculateRequest
:
6869 case VisibilityNotify
:
6873 /* Someone has changed the keyboard mapping - update the
6875 switch (event
.xmapping
.request
)
6877 case MappingModifier
:
6878 x_find_modifier_meanings (dpyinfo
);
6879 /* This is meant to fall through. */
6880 case MappingKeyboard
:
6881 XRefreshKeyboardMapping (&event
.xmapping
);
6887 #ifdef USE_X_TOOLKIT
6889 if (*finish
!= X_EVENT_DROP
)
6890 XtDispatchEvent (&event
);
6892 #endif /* USE_X_TOOLKIT */
6897 if (inev
.kind
!= NO_EVENT
)
6899 kbd_buffer_store_event_hold (&inev
, hold_quit
);
6904 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
6909 XSETFRAME (frame
, f
);
6915 any_help_event_p
= 1;
6916 gen_help_event (help_echo_string
, frame
, help_echo_window
,
6917 help_echo_object
, help_echo_pos
);
6921 help_echo_string
= Qnil
;
6922 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
6932 /* Handles the XEvent EVENT on display DISPLAY.
6933 This is used for event loops outside the normal event handling,
6934 i.e. looping while a popup menu or a dialog is posted.
6936 Returns the value handle_one_xevent sets in the finish argument. */
6938 x_dispatch_event (event
, display
)
6942 struct x_display_info
*dpyinfo
;
6943 int finish
= X_EVENT_NORMAL
;
6945 dpyinfo
= x_display_info_for_display (display
);
6948 handle_one_xevent (dpyinfo
, event
, &finish
, 0);
6954 /* Read events coming from the X server.
6955 This routine is called by the SIGIO handler.
6956 We return as soon as there are no more events to be read.
6958 We return the number of characters stored into the buffer,
6959 thus pretending to be `read'.
6961 EXPECTED is nonzero if the caller knows input is available. */
6964 XTread_socket (display
, expected
, hold_quit
)
6965 struct display
*display
;
6967 struct input_event
*hold_quit
;
6971 int event_found
= 0;
6972 struct x_display_info
*dpyinfo
;
6974 if (interrupt_input_blocked
)
6976 interrupt_input_pending
= 1;
6980 interrupt_input_pending
= 0;
6983 /* So people can tell when we have read the available input. */
6984 input_signal_count
++;
6988 /* Find the display we are supposed to read input for.
6989 It's the one communicating on descriptor SD. */
6990 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
6992 #if 0 /* This ought to be unnecessary; let's verify it. */
6994 /* If available, Xlib uses FIOSNBIO to make the socket
6995 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
6996 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
6997 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
6998 fcntl (dpyinfo
->connection
, F_SETFL
, 0);
6999 #endif /* ! defined (FIOSNBIO) */
7002 #if 0 /* This code can't be made to work, with multiple displays,
7003 and appears not to be used on any system any more.
7004 Also keyboard.c doesn't turn O_NDELAY on and off
7005 for X connections. */
7008 if (! (fcntl (dpyinfo
->connection
, F_GETFL
, 0) & O_NDELAY
))
7010 extern int read_alarm_should_throw
;
7011 read_alarm_should_throw
= 1;
7012 XPeekEvent (dpyinfo
->display
, &event
);
7013 read_alarm_should_throw
= 0;
7015 #endif /* HAVE_SELECT */
7019 /* For debugging, this gives a way to fake an I/O error. */
7020 if (dpyinfo
== XTread_socket_fake_io_error
)
7022 XTread_socket_fake_io_error
= 0;
7023 x_io_error_quitter (dpyinfo
->display
);
7028 struct input_event inev
;
7030 /* We don't need to EVENT_INIT (inev) here, as
7031 x_session_check_input copies an entire input_event. */
7032 if (x_session_check_input (&inev
))
7034 kbd_buffer_store_event_hold (&inev
, hold_quit
);
7042 while (XPending (dpyinfo
->display
))
7046 XNextEvent (dpyinfo
->display
, &event
);
7049 /* Filter events for the current X input method. */
7050 if (x_filter_event (dpyinfo
, &event
))
7055 count
+= handle_one_xevent (dpyinfo
, &event
, &finish
, hold_quit
);
7057 if (finish
== X_EVENT_GOTO_OUT
)
7060 #endif /* not USE_GTK */
7065 /* For GTK we must use the GTK event loop. But XEvents gets passed
7066 to our filter function above, and then to the big event switch.
7067 We use a bunch of globals to communicate with our filter function,
7068 that is kind of ugly, but it works.
7070 There is no way to do one display at the time, GTK just does events
7071 from all displays. */
7073 while (gtk_events_pending ())
7075 current_count
= count
;
7076 current_hold_quit
= hold_quit
;
7078 gtk_main_iteration ();
7080 count
= current_count
;
7082 current_hold_quit
= 0;
7084 if (current_finish
== X_EVENT_GOTO_OUT
)
7087 #endif /* USE_GTK */
7091 /* On some systems, an X bug causes Emacs to get no more events
7092 when the window is destroyed. Detect that. (1994.) */
7095 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
7096 One XNOOP in 100 loops will make Emacs terminate.
7097 B. Bretthauer, 1994 */
7099 if (x_noop_count
>= 100)
7103 if (next_noop_dpyinfo
== 0)
7104 next_noop_dpyinfo
= x_display_list
;
7106 XNoOp (next_noop_dpyinfo
->display
);
7108 /* Each time we get here, cycle through the displays now open. */
7109 next_noop_dpyinfo
= next_noop_dpyinfo
->next
;
7113 /* If the focus was just given to an auto-raising frame,
7115 /* ??? This ought to be able to handle more than one such frame. */
7116 if (pending_autoraise_frame
)
7118 x_raise_frame (pending_autoraise_frame
);
7119 pending_autoraise_frame
= 0;
7131 /***********************************************************************
7133 ***********************************************************************/
7135 /* Set clipping for output in glyph row ROW. W is the window in which
7136 we operate. GC is the graphics context to set clipping in.
7138 ROW may be a text row or, e.g., a mode line. Text rows must be
7139 clipped to the interior of the window dedicated to text display,
7140 mode lines must be clipped to the whole window. */
7143 x_clip_to_row (w
, row
, area
, gc
)
7145 struct glyph_row
*row
;
7149 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
7150 XRectangle clip_rect
;
7151 int window_x
, window_y
, window_width
;
7153 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
7155 clip_rect
.x
= window_x
;
7156 clip_rect
.y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, row
->y
));
7157 clip_rect
.y
= max (clip_rect
.y
, window_y
);
7158 clip_rect
.width
= window_width
;
7159 clip_rect
.height
= row
->visible_height
;
7161 XSetClipRectangles (FRAME_X_DISPLAY (f
), gc
, 0, 0, &clip_rect
, 1, Unsorted
);
7165 /* Draw a hollow box cursor on window W in glyph row ROW. */
7168 x_draw_hollow_cursor (w
, row
)
7170 struct glyph_row
*row
;
7172 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
7173 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7174 Display
*dpy
= FRAME_X_DISPLAY (f
);
7177 struct glyph
*cursor_glyph
;
7180 /* Get the glyph the cursor is on. If we can't tell because
7181 the current matrix is invalid or such, give up. */
7182 cursor_glyph
= get_phys_cursor_glyph (w
);
7183 if (cursor_glyph
== NULL
)
7186 /* Compute frame-relative coordinates for phys cursor. */
7187 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
7188 y
= get_phys_cursor_geometry (w
, row
, cursor_glyph
, &h
);
7189 wd
= w
->phys_cursor_width
;
7191 /* The foreground of cursor_gc is typically the same as the normal
7192 background color, which can cause the cursor box to be invisible. */
7193 xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
7194 if (dpyinfo
->scratch_cursor_gc
)
7195 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
7197 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_X_WINDOW (f
),
7198 GCForeground
, &xgcv
);
7199 gc
= dpyinfo
->scratch_cursor_gc
;
7201 /* Set clipping, draw the rectangle, and reset clipping again. */
7202 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
7203 XDrawRectangle (dpy
, FRAME_X_WINDOW (f
), gc
, x
, y
, wd
, h
);
7204 XSetClipMask (dpy
, gc
, None
);
7208 /* Draw a bar cursor on window W in glyph row ROW.
7210 Implementation note: One would like to draw a bar cursor with an
7211 angle equal to the one given by the font property XA_ITALIC_ANGLE.
7212 Unfortunately, I didn't find a font yet that has this property set.
7216 x_draw_bar_cursor (w
, row
, width
, kind
)
7218 struct glyph_row
*row
;
7220 enum text_cursor_kinds kind
;
7222 struct frame
*f
= XFRAME (w
->frame
);
7223 struct glyph
*cursor_glyph
;
7225 /* If cursor is out of bounds, don't draw garbage. This can happen
7226 in mini-buffer windows when switching between echo area glyphs
7228 cursor_glyph
= get_phys_cursor_glyph (w
);
7229 if (cursor_glyph
== NULL
)
7232 /* If on an image, draw like a normal cursor. That's usually better
7233 visible than drawing a bar, esp. if the image is large so that
7234 the bar might not be in the window. */
7235 if (cursor_glyph
->type
== IMAGE_GLYPH
)
7237 struct glyph_row
*row
;
7238 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
7239 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
7243 Display
*dpy
= FRAME_X_DISPLAY (f
);
7244 Window window
= FRAME_X_WINDOW (f
);
7245 GC gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
7246 unsigned long mask
= GCForeground
| GCBackground
| GCGraphicsExposures
;
7247 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
7250 /* If the glyph's background equals the color we normally draw
7251 the bar cursor in, the bar cursor in its normal color is
7252 invisible. Use the glyph's foreground color instead in this
7253 case, on the assumption that the glyph's colors are chosen so
7254 that the glyph is legible. */
7255 if (face
->background
== f
->output_data
.x
->cursor_pixel
)
7256 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
7258 xgcv
.background
= xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
7259 xgcv
.graphics_exposures
= 0;
7262 XChangeGC (dpy
, gc
, mask
, &xgcv
);
7265 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
7266 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
7270 width
= FRAME_CURSOR_WIDTH (f
);
7271 width
= min (cursor_glyph
->pixel_width
, width
);
7273 w
->phys_cursor_width
= width
;
7274 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
7276 if (kind
== BAR_CURSOR
)
7277 XFillRectangle (dpy
, window
, gc
,
7278 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
7279 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
7280 width
, row
->height
);
7282 XFillRectangle (dpy
, window
, gc
,
7283 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
7284 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
7285 row
->height
- width
),
7286 cursor_glyph
->pixel_width
,
7289 XSetClipMask (dpy
, gc
, None
);
7294 /* RIF: Define cursor CURSOR on frame F. */
7297 x_define_frame_cursor (f
, cursor
)
7301 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), cursor
);
7305 /* RIF: Clear area on frame F. */
7308 x_clear_frame_area (f
, x
, y
, width
, height
)
7310 int x
, y
, width
, height
;
7312 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7313 x
, y
, width
, height
, False
);
7317 /* RIF: Draw cursor on window W. */
7320 x_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
7322 struct glyph_row
*glyph_row
;
7324 int cursor_type
, cursor_width
;
7327 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
7331 w
->phys_cursor_type
= cursor_type
;
7332 w
->phys_cursor_on_p
= 1;
7334 if (glyph_row
->exact_window_width_line_p
7335 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
7337 glyph_row
->cursor_in_fringe_p
= 1;
7338 draw_fringe_bitmap (w
, glyph_row
, 0);
7341 switch (cursor_type
)
7343 case HOLLOW_BOX_CURSOR
:
7344 x_draw_hollow_cursor (w
, glyph_row
);
7347 case FILLED_BOX_CURSOR
:
7348 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
7352 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
7356 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
7360 w
->phys_cursor_width
= 0;
7368 if (w
== XWINDOW (f
->selected_window
))
7369 if (FRAME_XIC (f
) && (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
))
7370 xic_set_preeditarea (w
, x
, y
);
7375 XFlush (FRAME_X_DISPLAY (f
));
7382 /* Make the x-window of frame F use the gnu icon bitmap. */
7385 x_bitmap_icon (f
, file
)
7391 if (FRAME_X_WINDOW (f
) == 0)
7394 /* Free up our existing icon bitmap and mask if any. */
7395 if (f
->output_data
.x
->icon_bitmap
> 0)
7396 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
7397 f
->output_data
.x
->icon_bitmap
= 0;
7402 /* Use gtk_window_set_icon_from_file () if available,
7403 It's not restricted to bitmaps */
7404 if (xg_set_icon (f
, file
))
7406 #endif /* USE_GTK */
7407 bitmap_id
= x_create_bitmap_from_file (f
, file
);
7408 x_create_bitmap_mask (f
, bitmap_id
);
7412 /* Create the GNU bitmap and mask if necessary. */
7413 if (FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
7415 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
7416 = x_create_bitmap_from_data (f
, gnu_bits
,
7417 gnu_width
, gnu_height
);
7418 x_create_bitmap_mask (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
7421 /* The first time we create the GNU bitmap and mask,
7422 this increments the ref-count one extra time.
7423 As a result, the GNU bitmap and mask are never freed.
7424 That way, we don't have to worry about allocating it again. */
7425 x_reference_bitmap (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
7427 bitmap_id
= FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
;
7430 x_wm_set_icon_pixmap (f
, bitmap_id
);
7431 f
->output_data
.x
->icon_bitmap
= bitmap_id
;
7437 /* Make the x-window of frame F use a rectangle with text.
7438 Use ICON_NAME as the text. */
7441 x_text_icon (f
, icon_name
)
7445 if (FRAME_X_WINDOW (f
) == 0)
7451 text
.value
= (unsigned char *) icon_name
;
7452 text
.encoding
= XA_STRING
;
7454 text
.nitems
= strlen (icon_name
);
7455 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
), &text
);
7457 #else /* not HAVE_X11R4 */
7458 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
), icon_name
);
7459 #endif /* not HAVE_X11R4 */
7461 if (f
->output_data
.x
->icon_bitmap
> 0)
7462 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
7463 f
->output_data
.x
->icon_bitmap
= 0;
7464 x_wm_set_icon_pixmap (f
, 0);
7469 #define X_ERROR_MESSAGE_SIZE 200
7471 /* If non-nil, this should be a string.
7472 It means catch X errors and store the error message in this string. */
7474 static Lisp_Object x_error_message_string
;
7476 /* An X error handler which stores the error message in
7477 x_error_message_string. This is called from x_error_handler if
7478 x_catch_errors is in effect. */
7481 x_error_catcher (display
, error
)
7485 XGetErrorText (display
, error
->error_code
,
7486 SDATA (x_error_message_string
),
7487 X_ERROR_MESSAGE_SIZE
);
7490 /* Begin trapping X errors for display DPY. Actually we trap X errors
7491 for all displays, but DPY should be the display you are actually
7494 After calling this function, X protocol errors no longer cause
7495 Emacs to exit; instead, they are recorded in the string
7496 stored in x_error_message_string.
7498 Calling x_check_errors signals an Emacs error if an X error has
7499 occurred since the last call to x_catch_errors or x_check_errors.
7501 Calling x_uncatch_errors resumes the normal error handling. */
7503 void x_check_errors ();
7504 static Lisp_Object
x_catch_errors_unwind ();
7507 x_catch_errors (dpy
)
7510 int count
= SPECPDL_INDEX ();
7512 /* Make sure any errors from previous requests have been dealt with. */
7515 record_unwind_protect (x_catch_errors_unwind
,
7516 Fcons (make_save_value (dpy
, 0),
7517 x_error_message_string
));
7519 x_error_message_string
= make_uninit_string (X_ERROR_MESSAGE_SIZE
);
7520 SSET (x_error_message_string
, 0, 0);
7525 /* Unbind the binding that we made to check for X errors. */
7528 x_catch_errors_unwind (old_val
)
7529 Lisp_Object old_val
;
7531 Lisp_Object first
= XCAR (old_val
);
7532 Display
*dpy
= XSAVE_VALUE (first
)->pointer
;
7534 /* The display may have been closed before this function is called.
7535 Check if it is still open before calling XSync. */
7536 if (x_display_info_for_display (dpy
) != 0)
7543 x_error_message_string
= XCDR (old_val
);
7547 /* If any X protocol errors have arrived since the last call to
7548 x_catch_errors or x_check_errors, signal an Emacs error using
7549 sprintf (a buffer, FORMAT, the x error message text) as the text. */
7552 x_check_errors (dpy
, format
)
7556 /* Make sure to catch any errors incurred so far. */
7559 if (SREF (x_error_message_string
, 0))
7560 error (format
, SDATA (x_error_message_string
));
7563 /* Nonzero if we had any X protocol errors
7564 since we did x_catch_errors on DPY. */
7567 x_had_errors_p (dpy
)
7570 /* Make sure to catch any errors incurred so far. */
7573 return SREF (x_error_message_string
, 0) != 0;
7576 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
7579 x_clear_errors (dpy
)
7582 SSET (x_error_message_string
, 0, 0);
7585 /* Stop catching X protocol errors and let them make Emacs die.
7586 DPY should be the display that was passed to x_catch_errors.
7587 COUNT should be the value that was returned by
7588 the corresponding call to x_catch_errors. */
7591 x_uncatch_errors (dpy
, count
)
7595 unbind_to (count
, Qnil
);
7599 static unsigned int x_wire_count
;
7602 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
7607 /* Handle SIGPIPE, which can happen when the connection to a server
7608 simply goes away. SIGPIPE is handled by x_connection_signal.
7609 Don't need to do anything, because the write which caused the
7610 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
7611 which will do the appropriate cleanup for us. */
7614 x_connection_signal (signalnum
) /* If we don't have an argument, */
7615 int signalnum
; /* some compilers complain in signal calls. */
7618 /* USG systems forget handlers when they are used;
7619 must reestablish each time */
7620 signal (signalnum
, x_connection_signal
);
7625 /************************************************************************
7627 ************************************************************************/
7629 /* Error message passed to x_connection_closed. */
7631 static char *error_msg
;
7633 /* Function installed as fatal_error_signal_hook in
7634 x_connection_closed. Print the X error message, and exit normally,
7635 instead of dumping core when XtCloseDisplay fails. */
7638 x_fatal_error_signal ()
7640 fprintf (stderr
, "%s\n", error_msg
);
7644 /* Handle the loss of connection to display DPY. ERROR_MESSAGE is
7645 the text of an error message that lead to the connection loss. */
7648 x_connection_closed (dpy
, error_message
)
7650 char *error_message
;
7652 struct x_display_info
*dpyinfo
= x_display_info_for_display (dpy
);
7653 Lisp_Object frame
, tail
;
7655 int index
= SPECPDL_INDEX ();
7657 error_msg
= (char *) alloca (strlen (error_message
) + 1);
7658 strcpy (error_msg
, error_message
);
7659 handling_signal
= 0;
7661 /* Prevent being called recursively because of an error condition
7662 below. Otherwise, we might end up with printing ``can't find per
7663 display information'' in the recursive call instead of printing
7664 the original message here. */
7665 count
= x_catch_errors (dpy
);
7667 /* We have to close the display to inform Xt that it doesn't
7668 exist anymore. If we don't, Xt will continue to wait for
7669 events from the display. As a consequence, a sequence of
7671 M-x make-frame-on-display RET :1 RET
7672 ...kill the new frame, so that we get an IO error...
7673 M-x make-frame-on-display RET :1 RET
7675 will indefinitely wait in Xt for events for display `:1', opened
7676 in the first class to make-frame-on-display.
7678 Closing the display is reported to lead to a bus error on
7679 OpenWindows in certain situations. I suspect that is a bug
7680 in OpenWindows. I don't know how to cicumvent it here. */
7682 #ifdef USE_X_TOOLKIT
7683 /* If DPYINFO is null, this means we didn't open the display
7684 in the first place, so don't try to close it. */
7687 extern void (*fatal_error_signal_hook
) P_ ((void));
7688 fatal_error_signal_hook
= x_fatal_error_signal
;
7689 XtCloseDisplay (dpy
);
7690 fatal_error_signal_hook
= NULL
;
7696 xg_display_close (dpyinfo
->display
);
7699 /* Indicate that this display is dead. */
7701 dpyinfo
->display
= 0;
7703 /* Inhibit redisplay while frames are being deleted. */
7704 specbind (Qinhibit_redisplay
, Qt
);
7706 /* First delete frames whose mini-buffers are on frames
7707 that are on the dead display. */
7708 FOR_EACH_FRAME (tail
, frame
)
7710 Lisp_Object minibuf_frame
;
7712 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
7713 if (FRAME_X_P (XFRAME (frame
))
7714 && FRAME_X_P (XFRAME (minibuf_frame
))
7715 && ! EQ (frame
, minibuf_frame
)
7716 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame
)) == dpyinfo
)
7717 Fdelete_frame (frame
, Qt
);
7720 /* Now delete all remaining frames on the dead display.
7721 We are now sure none of these is used as the mini-buffer
7722 for another frame that we need to delete. */
7723 FOR_EACH_FRAME (tail
, frame
)
7724 if (FRAME_X_P (XFRAME (frame
))
7725 && FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
7727 /* Set this to t so that Fdelete_frame won't get confused
7728 trying to find a replacement. */
7729 FRAME_KBOARD (XFRAME (frame
))->Vdefault_minibuffer_frame
= Qt
;
7730 Fdelete_frame (frame
, Qt
);
7734 x_delete_display (dpyinfo
);
7736 x_uncatch_errors (dpy
, count
);
7738 if (display_list
== 0)
7740 fprintf (stderr
, "%s\n", error_msg
);
7741 shut_down_emacs (0, 0, Qnil
);
7745 /* Ordinary stack unwind doesn't deal with these. */
7747 sigunblock (sigmask (SIGIO
));
7749 sigunblock (sigmask (SIGALRM
));
7750 TOTALLY_UNBLOCK_INPUT
;
7752 unbind_to (index
, Qnil
);
7753 clear_waiting_for_input ();
7754 error ("%s", error_msg
);
7757 /* We specifically use it before defining it, so that gcc doesn't inline it,
7758 otherwise gdb doesn't know how to properly put a breakpoint on it. */
7759 static void x_error_quitter (Display
*display
, XErrorEvent
*error
);
7761 /* This is the first-level handler for X protocol errors.
7762 It calls x_error_quitter or x_error_catcher. */
7765 x_error_handler (display
, error
)
7769 if (! NILP (x_error_message_string
))
7770 x_error_catcher (display
, error
);
7772 x_error_quitter (display
, error
);
7776 /* This is the usual handler for X protocol errors.
7777 It kills all frames on the display that we got the error for.
7778 If that was the only one, it prints an error message and kills Emacs. */
7780 /* .gdbinit puts a breakpoint here, so make sure it is not inlined. */
7782 #if __GNUC__ >= 3 /* On GCC 3.0 we might get a warning. */
7783 #define NO_INLINE __attribute__((noinline))
7788 /* On older GCC versions, just putting x_error_quitter
7789 after x_error_handler prevents inlining into the former. */
7791 static void NO_INLINE
7792 x_error_quitter (display
, error
)
7796 char buf
[256], buf1
[356];
7798 /* Note that there is no real way portable across R3/R4 to get the
7799 original error handler. */
7801 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
7802 sprintf (buf1
, "X protocol error: %s on protocol request %d",
7803 buf
, error
->request_code
);
7804 x_connection_closed (display
, buf1
);
7808 /* This is the handler for X IO errors, always.
7809 It kills all frames on the display that we lost touch with.
7810 If that was the only one, it prints an error message and kills Emacs. */
7813 x_io_error_quitter (display
)
7818 sprintf (buf
, "Connection lost to X server `%s'", DisplayString (display
));
7819 x_connection_closed (display
, buf
);
7823 /* Changing the font of the frame. */
7825 /* Give frame F the font named FONTNAME as its default font, and
7826 return the full name of that font. FONTNAME may be a wildcard
7827 pattern; in that case, we choose some font that fits the pattern.
7828 The return value shows which font we chose. */
7831 x_new_font (f
, fontname
)
7833 register char *fontname
;
7835 struct font_info
*fontp
7836 = FS_LOAD_FONT (f
, 0, fontname
, -1);
7841 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
7842 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
7843 FRAME_FONTSET (f
) = -1;
7845 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
7846 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
7847 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
7849 compute_fringe_widths (f
, 1);
7851 /* Compute the scroll bar width in character columns. */
7852 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
7854 int wid
= FRAME_COLUMN_WIDTH (f
);
7855 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
7856 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
7860 int wid
= FRAME_COLUMN_WIDTH (f
);
7861 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
7864 /* Now make the frame display the given font. */
7865 if (FRAME_X_WINDOW (f
) != 0)
7867 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
7868 FRAME_FONT (f
)->fid
);
7869 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
7870 FRAME_FONT (f
)->fid
);
7871 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
7872 FRAME_FONT (f
)->fid
);
7874 /* Don't change the size of a tip frame; there's no point in
7875 doing it because it's done in Fx_show_tip, and it leads to
7876 problems because the tip frame has no widget. */
7877 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
7878 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
7881 return build_string (fontp
->full_name
);
7884 /* Give frame F the fontset named FONTSETNAME as its default font, and
7885 return the full name of that fontset. FONTSETNAME may be a wildcard
7886 pattern; in that case, we choose some fontset that fits the pattern.
7887 The return value shows which fontset we chose. */
7890 x_new_fontset (f
, fontsetname
)
7894 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
7900 if (FRAME_FONTSET (f
) == fontset
)
7901 /* This fontset is already set in frame F. There's nothing more
7903 return fontset_name (fontset
);
7905 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
7907 if (!STRINGP (result
))
7908 /* Can't load ASCII font. */
7911 /* Since x_new_font doesn't update any fontset information, do it now. */
7912 FRAME_FONTSET (f
) = fontset
;
7916 && (FRAME_XIC_STYLE (f
) & (XIMPreeditPosition
| XIMStatusArea
)))
7917 xic_set_xfontset (f
, SDATA (fontset_ascii (fontset
)));
7920 return build_string (fontsetname
);
7924 /***********************************************************************
7926 ***********************************************************************/
7932 /* XIM destroy callback function, which is called whenever the
7933 connection to input method XIM dies. CLIENT_DATA contains a
7934 pointer to the x_display_info structure corresponding to XIM. */
7937 xim_destroy_callback (xim
, client_data
, call_data
)
7939 XPointer client_data
;
7942 struct x_display_info
*dpyinfo
= (struct x_display_info
*) client_data
;
7943 Lisp_Object frame
, tail
;
7947 /* No need to call XDestroyIC.. */
7948 FOR_EACH_FRAME (tail
, frame
)
7950 struct frame
*f
= XFRAME (frame
);
7951 if (FRAME_X_P (f
) && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
)
7953 FRAME_XIC (f
) = NULL
;
7954 xic_free_xfontset (f
);
7958 /* No need to call XCloseIM. */
7959 dpyinfo
->xim
= NULL
;
7960 XFree (dpyinfo
->xim_styles
);
7964 #endif /* HAVE_X11R6 */
7967 /* This isn't prototyped in OSF 5.0 or 5.1a. */
7968 extern char *XSetIMValues
P_ ((XIM
, ...));
7971 /* Open the connection to the XIM server on display DPYINFO.
7972 RESOURCE_NAME is the resource name Emacs uses. */
7975 xim_open_dpy (dpyinfo
, resource_name
)
7976 struct x_display_info
*dpyinfo
;
7977 char *resource_name
;
7984 xim
= XOpenIM (dpyinfo
->display
, dpyinfo
->xrdb
, resource_name
,
7991 XIMCallback destroy
;
7994 /* Get supported styles and XIM values. */
7995 XGetIMValues (xim
, XNQueryInputStyle
, &dpyinfo
->xim_styles
, NULL
);
7998 destroy
.callback
= xim_destroy_callback
;
7999 destroy
.client_data
= (XPointer
)dpyinfo
;
8000 XSetIMValues (xim
, XNDestroyCallback
, &destroy
, NULL
);
8006 #endif /* HAVE_XIM */
8007 dpyinfo
->xim
= NULL
;
8011 #ifdef HAVE_X11R6_XIM
8015 struct x_display_info
*dpyinfo
;
8016 char *resource_name
;
8019 /* XIM instantiate callback function, which is called whenever an XIM
8020 server is available. DISPLAY is the display of the XIM.
8021 CLIENT_DATA contains a pointer to an xim_inst_t structure created
8022 when the callback was registered. */
8025 xim_instantiate_callback (display
, client_data
, call_data
)
8027 XPointer client_data
;
8030 struct xim_inst_t
*xim_inst
= (struct xim_inst_t
*) client_data
;
8031 struct x_display_info
*dpyinfo
= xim_inst
->dpyinfo
;
8033 /* We don't support multiple XIM connections. */
8037 xim_open_dpy (dpyinfo
, xim_inst
->resource_name
);
8039 /* Create XIC for the existing frames on the same display, as long
8040 as they have no XIC. */
8041 if (dpyinfo
->xim
&& dpyinfo
->reference_count
> 0)
8043 Lisp_Object tail
, frame
;
8046 FOR_EACH_FRAME (tail
, frame
)
8048 struct frame
*f
= XFRAME (frame
);
8051 && FRAME_X_DISPLAY_INFO (f
) == xim_inst
->dpyinfo
)
8052 if (FRAME_XIC (f
) == NULL
)
8054 create_frame_xic (f
);
8055 if (FRAME_XIC_STYLE (f
) & XIMStatusArea
)
8056 xic_set_statusarea (f
);
8057 if (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
)
8059 struct window
*w
= XWINDOW (f
->selected_window
);
8060 xic_set_preeditarea (w
, w
->cursor
.x
, w
->cursor
.y
);
8069 #endif /* HAVE_X11R6_XIM */
8072 /* Open a connection to the XIM server on display DPYINFO.
8073 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
8074 connection only at the first time. On X11R6, open the connection
8075 in the XIM instantiate callback function. */
8078 xim_initialize (dpyinfo
, resource_name
)
8079 struct x_display_info
*dpyinfo
;
8080 char *resource_name
;
8085 #ifdef HAVE_X11R6_XIM
8086 struct xim_inst_t
*xim_inst
;
8089 dpyinfo
->xim
= NULL
;
8090 xim_inst
= (struct xim_inst_t
*) xmalloc (sizeof (struct xim_inst_t
));
8091 xim_inst
->dpyinfo
= dpyinfo
;
8092 len
= strlen (resource_name
);
8093 xim_inst
->resource_name
= (char *) xmalloc (len
+ 1);
8094 bcopy (resource_name
, xim_inst
->resource_name
, len
+ 1);
8095 XRegisterIMInstantiateCallback (dpyinfo
->display
, dpyinfo
->xrdb
,
8096 resource_name
, EMACS_CLASS
,
8097 xim_instantiate_callback
,
8098 /* This is XPointer in XFree86
8099 but (XPointer *) on Tru64, at
8100 least, hence the configure test. */
8101 (XRegisterIMInstantiateCallback_arg6
) xim_inst
);
8102 #else /* not HAVE_X11R6_XIM */
8103 dpyinfo
->xim
= NULL
;
8104 xim_open_dpy (dpyinfo
, resource_name
);
8105 #endif /* not HAVE_X11R6_XIM */
8109 #endif /* HAVE_XIM */
8110 dpyinfo
->xim
= NULL
;
8114 /* Close the connection to the XIM server on display DPYINFO. */
8117 xim_close_dpy (dpyinfo
)
8118 struct x_display_info
*dpyinfo
;
8123 #ifdef HAVE_X11R6_XIM
8124 if (dpyinfo
->display
)
8125 XUnregisterIMInstantiateCallback (dpyinfo
->display
, dpyinfo
->xrdb
,
8127 xim_instantiate_callback
, NULL
);
8128 #endif /* not HAVE_X11R6_XIM */
8129 if (dpyinfo
->display
)
8130 XCloseIM (dpyinfo
->xim
);
8131 dpyinfo
->xim
= NULL
;
8132 XFree (dpyinfo
->xim_styles
);
8134 #endif /* HAVE_XIM */
8137 #endif /* not HAVE_X11R6_XIM */
8141 /* Calculate the absolute position in frame F
8142 from its current recorded position values and gravity. */
8145 x_calc_absolute_position (f
)
8148 int win_x
= 0, win_y
= 0;
8149 int flags
= f
->size_hint_flags
;
8151 /* We have nothing to do if the current position
8152 is already for the top-left corner. */
8153 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
8156 /* Treat negative positions as relative to the leftmost bottommost
8157 position that fits on the screen. */
8158 if (flags
& XNegative
)
8159 f
->left_pos
= (FRAME_X_DISPLAY_INFO (f
)->width
8160 - FRAME_PIXEL_WIDTH (f
) + f
->left_pos
);
8163 int height
= FRAME_PIXEL_HEIGHT (f
);
8165 #if defined USE_X_TOOLKIT && defined USE_MOTIF
8166 /* Something is fishy here. When using Motif, starting Emacs with
8167 `-g -0-0', the frame appears too low by a few pixels.
8169 This seems to be so because initially, while Emacs is starting,
8170 the column widget's height and the frame's pixel height are
8171 different. The column widget's height is the right one. In
8172 later invocations, when Emacs is up, the frame's pixel height
8175 It's not obvious where the initial small difference comes from.
8176 2000-12-01, gerd. */
8178 XtVaGetValues (f
->output_data
.x
->column_widget
, XtNheight
, &height
, NULL
);
8181 if (flags
& YNegative
)
8182 f
->top_pos
= (FRAME_X_DISPLAY_INFO (f
)->height
- height
+ f
->top_pos
);
8185 /* The left_pos and top_pos
8186 are now relative to the top and left screen edges,
8187 so the flags should correspond. */
8188 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
8191 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
8192 to really change the position, and 0 when calling from
8193 x_make_frame_visible (in that case, XOFF and YOFF are the current
8194 position values). It is -1 when calling from x_set_frame_parameters,
8195 which means, do adjust for borders but don't change the gravity. */
8198 x_set_offset (f
, xoff
, yoff
, change_gravity
)
8200 register int xoff
, yoff
;
8203 int modified_top
, modified_left
;
8205 if (change_gravity
> 0)
8209 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
8211 f
->size_hint_flags
|= XNegative
;
8213 f
->size_hint_flags
|= YNegative
;
8214 f
->win_gravity
= NorthWestGravity
;
8216 x_calc_absolute_position (f
);
8219 x_wm_set_size_hint (f
, (long) 0, 0);
8221 modified_left
= f
->left_pos
;
8222 modified_top
= f
->top_pos
;
8224 if (FRAME_X_DISPLAY_INFO (f
)->wm_type
== X_WMTYPE_A
)
8226 /* Some WMs (twm, wmaker at least) has an offset that is smaller
8227 than the WM decorations. So we use the calculated offset instead
8228 of the WM decoration sizes here (x/y_pixels_outer_diff). */
8229 modified_left
+= FRAME_X_OUTPUT (f
)->move_offset_left
;
8230 modified_top
+= FRAME_X_OUTPUT (f
)->move_offset_top
;
8233 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
8234 modified_left
, modified_top
);
8236 if (FRAME_VISIBLE_P (f
)
8237 && FRAME_X_DISPLAY_INFO (f
)->wm_type
== X_WMTYPE_UNKNOWN
)
8239 FRAME_X_OUTPUT (f
)->check_expected_move
= 1;
8240 FRAME_X_OUTPUT (f
)->expected_top
= f
->top_pos
;
8241 FRAME_X_OUTPUT (f
)->expected_left
= f
->left_pos
;
8247 /* Check if we need to resize the frame due to a fullscreen request.
8248 If so needed, resize the frame. */
8250 x_check_fullscreen (f
)
8253 if (f
->want_fullscreen
& FULLSCREEN_BOTH
)
8255 int width
, height
, ign
;
8257 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
8259 x_fullscreen_adjust (f
, &width
, &height
, &ign
, &ign
);
8261 /* We do not need to move the window, it shall be taken care of
8262 when setting WM manager hints.
8263 If the frame is visible already, the position is checked by
8264 x_check_expected_move. */
8265 if (FRAME_COLS (f
) != width
|| FRAME_LINES (f
) != height
)
8267 change_frame_size (f
, height
, width
, 0, 1, 0);
8268 SET_FRAME_GARBAGED (f
);
8269 cancel_mouse_face (f
);
8271 /* Wait for the change of frame size to occur */
8272 f
->want_fullscreen
|= FULLSCREEN_WAIT
;
8277 /* If frame parameters are set after the frame is mapped, we need to move
8279 Some window managers moves the window to the right position, some
8280 moves the outer window manager window to the specified position.
8281 Here we check that we are in the right spot. If not, make a second
8282 move, assuming we are dealing with the second kind of window manager. */
8284 x_check_expected_move (f
)
8287 if (FRAME_X_OUTPUT (f
)->check_expected_move
)
8289 int expect_top
= FRAME_X_OUTPUT (f
)->expected_top
;
8290 int expect_left
= FRAME_X_OUTPUT (f
)->expected_left
;
8292 if (expect_top
!= f
->top_pos
|| expect_left
!= f
->left_pos
)
8294 FRAME_X_DISPLAY_INFO (f
)->wm_type
= X_WMTYPE_A
;
8295 FRAME_X_OUTPUT (f
)->move_offset_left
= expect_left
- f
->left_pos
;
8296 FRAME_X_OUTPUT (f
)->move_offset_top
= expect_top
- f
->top_pos
;
8298 f
->left_pos
= expect_left
;
8299 f
->top_pos
= expect_top
;
8300 x_set_offset (f
, expect_left
, expect_top
, 0);
8302 else if (FRAME_X_DISPLAY_INFO (f
)->wm_type
== X_WMTYPE_UNKNOWN
)
8303 FRAME_X_DISPLAY_INFO (f
)->wm_type
= X_WMTYPE_B
;
8305 /* Just do this once */
8306 FRAME_X_OUTPUT (f
)->check_expected_move
= 0;
8311 /* Change the size of frame F's X window to COLS/ROWS in the case F
8312 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
8313 top-left-corner window gravity for this size change and subsequent
8314 size changes. Otherwise we leave the window gravity unchanged. */
8317 x_set_window_size_1 (f
, change_gravity
, cols
, rows
)
8322 int pixelwidth
, pixelheight
;
8324 check_frame_size (f
, &rows
, &cols
);
8325 f
->scroll_bar_actual_width
8326 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
8328 : FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0
8329 ? FRAME_CONFIG_SCROLL_BAR_WIDTH (f
)
8330 : (FRAME_CONFIG_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
)));
8332 compute_fringe_widths (f
, 0);
8334 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
8335 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
8337 f
->win_gravity
= NorthWestGravity
;
8338 x_wm_set_size_hint (f
, (long) 0, 0);
8340 XSync (FRAME_X_DISPLAY (f
), False
);
8341 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8342 pixelwidth
, pixelheight
);
8344 /* Now, strictly speaking, we can't be sure that this is accurate,
8345 but the window manager will get around to dealing with the size
8346 change request eventually, and we'll hear how it went when the
8347 ConfigureNotify event gets here.
8349 We could just not bother storing any of this information here,
8350 and let the ConfigureNotify event set everything up, but that
8351 might be kind of confusing to the Lisp code, since size changes
8352 wouldn't be reported in the frame parameters until some random
8353 point in the future when the ConfigureNotify event arrives.
8355 We pass 1 for DELAY since we can't run Lisp code inside of
8357 change_frame_size (f
, rows
, cols
, 0, 1, 0);
8358 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
8359 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
8361 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
8362 receive in the ConfigureNotify event; if we get what we asked
8363 for, then the event won't cause the screen to become garbaged, so
8364 we have to make sure to do it here. */
8365 SET_FRAME_GARBAGED (f
);
8367 XFlush (FRAME_X_DISPLAY (f
));
8371 /* Call this to change the size of frame F's x-window.
8372 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
8373 for this size change and subsequent size changes.
8374 Otherwise we leave the window gravity unchanged. */
8377 x_set_window_size (f
, change_gravity
, cols
, rows
)
8385 if (FRAME_GTK_WIDGET (f
))
8386 xg_frame_set_char_size (f
, cols
, rows
);
8388 x_set_window_size_1 (f
, change_gravity
, cols
, rows
);
8391 if (f
->output_data
.x
->widget
!= NULL
)
8393 /* The x and y position of the widget is clobbered by the
8394 call to XtSetValues within EmacsFrameSetCharSize.
8395 This is a real kludge, but I don't understand Xt so I can't
8396 figure out a correct fix. Can anyone else tell me? -- rms. */
8397 int xpos
= f
->output_data
.x
->widget
->core
.x
;
8398 int ypos
= f
->output_data
.x
->widget
->core
.y
;
8399 EmacsFrameSetCharSize (f
->output_data
.x
->edit_widget
, cols
, rows
);
8400 f
->output_data
.x
->widget
->core
.x
= xpos
;
8401 f
->output_data
.x
->widget
->core
.y
= ypos
;
8404 x_set_window_size_1 (f
, change_gravity
, cols
, rows
);
8406 #else /* not USE_X_TOOLKIT */
8408 x_set_window_size_1 (f
, change_gravity
, cols
, rows
);
8410 #endif /* not USE_X_TOOLKIT */
8412 /* If cursor was outside the new size, mark it as off. */
8413 mark_window_cursors_off (XWINDOW (f
->root_window
));
8415 /* Clear out any recollection of where the mouse highlighting was,
8416 since it might be in a place that's outside the new frame size.
8417 Actually checking whether it is outside is a pain in the neck,
8418 so don't try--just let the highlighting be done afresh with new size. */
8419 cancel_mouse_face (f
);
8424 /* Mouse warping. */
8427 x_set_mouse_position (f
, x
, y
)
8433 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
8434 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
8436 if (pix_x
< 0) pix_x
= 0;
8437 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
8439 if (pix_y
< 0) pix_y
= 0;
8440 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
8444 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
8445 0, 0, 0, 0, pix_x
, pix_y
);
8449 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
8452 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
8458 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
8459 0, 0, 0, 0, pix_x
, pix_y
);
8463 /* focus shifting, raising and lowering. */
8466 x_focus_on_frame (f
)
8469 #if 0 /* This proves to be unpleasant. */
8473 /* I don't think that the ICCCM allows programs to do things like this
8474 without the interaction of the window manager. Whatever you end up
8475 doing with this code, do it to x_unfocus_frame too. */
8476 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8477 RevertToPointerRoot
, CurrentTime
);
8486 /* Look at the remarks in x_focus_on_frame. */
8487 if (FRAME_X_DISPLAY_INFO (f
)->x_focus_frame
== f
)
8488 XSetInputFocus (FRAME_X_DISPLAY (f
), PointerRoot
,
8489 RevertToPointerRoot
, CurrentTime
);
8493 /* Raise frame F. */
8499 if (f
->async_visible
)
8502 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
));
8503 XFlush (FRAME_X_DISPLAY (f
));
8508 /* Lower frame F. */
8514 if (f
->async_visible
)
8517 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
));
8518 XFlush (FRAME_X_DISPLAY (f
));
8524 XTframe_raise_lower (f
, raise_flag
)
8534 /* Change of visibility. */
8536 /* This tries to wait until the frame is really visible.
8537 However, if the window manager asks the user where to position
8538 the frame, this will return before the user finishes doing that.
8539 The frame will not actually be visible at that time,
8540 but it will become visible later when the window manager
8541 finishes with it. */
8544 x_make_frame_visible (f
)
8548 int original_top
, original_left
;
8549 int retry_count
= 2;
8555 type
= x_icon_type (f
);
8557 x_bitmap_icon (f
, type
);
8559 if (! FRAME_VISIBLE_P (f
))
8561 /* We test FRAME_GARBAGED_P here to make sure we don't
8562 call x_set_offset a second time
8563 if we get to x_make_frame_visible a second time
8564 before the window gets really visible. */
8565 if (! FRAME_ICONIFIED_P (f
)
8566 && ! f
->output_data
.x
->asked_for_visible
)
8567 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
8569 f
->output_data
.x
->asked_for_visible
= 1;
8571 if (! EQ (Vx_no_window_manager
, Qt
))
8572 x_wm_set_window_state (f
, NormalState
);
8573 #ifdef USE_X_TOOLKIT
8574 /* This was XtPopup, but that did nothing for an iconified frame. */
8575 XtMapWidget (f
->output_data
.x
->widget
);
8576 #else /* not USE_X_TOOLKIT */
8578 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f
));
8579 gtk_window_deiconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f
)));
8581 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
8582 #endif /* not USE_GTK */
8583 #endif /* not USE_X_TOOLKIT */
8584 #if 0 /* This seems to bring back scroll bars in the wrong places
8585 if the window configuration has changed. They seem
8586 to come back ok without this. */
8587 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
8588 XMapSubwindows (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
8592 XFlush (FRAME_X_DISPLAY (f
));
8594 /* Synchronize to ensure Emacs knows the frame is visible
8595 before we do anything else. We do this loop with input not blocked
8596 so that incoming events are handled. */
8600 /* This must be before UNBLOCK_INPUT
8601 since events that arrive in response to the actions above
8602 will set it when they are handled. */
8603 int previously_visible
= f
->output_data
.x
->has_been_visible
;
8605 original_left
= f
->left_pos
;
8606 original_top
= f
->top_pos
;
8608 /* This must come after we set COUNT. */
8611 /* We unblock here so that arriving X events are processed. */
8613 /* Now move the window back to where it was "supposed to be".
8614 But don't do it if the gravity is negative.
8615 When the gravity is negative, this uses a position
8616 that is 3 pixels too low. Perhaps that's really the border width.
8618 Don't do this if the window has never been visible before,
8619 because the window manager may choose the position
8620 and we don't want to override it. */
8622 if (! FRAME_VISIBLE_P (f
) && ! FRAME_ICONIFIED_P (f
)
8623 && f
->win_gravity
== NorthWestGravity
8624 && previously_visible
)
8628 unsigned int width
, height
, border
, depth
;
8632 /* On some window managers (such as FVWM) moving an existing
8633 window, even to the same place, causes the window manager
8634 to introduce an offset. This can cause the window to move
8635 to an unexpected location. Check the geometry (a little
8636 slow here) and then verify that the window is in the right
8637 place. If the window is not in the right place, move it
8638 there, and take the potential window manager hit. */
8639 XGetGeometry (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
8640 &rootw
, &x
, &y
, &width
, &height
, &border
, &depth
);
8642 if (original_left
!= x
|| original_top
!= y
)
8643 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
8644 original_left
, original_top
);
8649 XSETFRAME (frame
, f
);
8651 /* Wait until the frame is visible. Process X events until a
8652 MapNotify event has been seen, or until we think we won't get a
8653 MapNotify at all.. */
8654 for (count
= input_signal_count
+ 10;
8655 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
8657 /* Force processing of queued events. */
8660 /* Machines that do polling rather than SIGIO have been
8661 observed to go into a busy-wait here. So we'll fake an
8662 alarm signal to let the handler know that there's something
8663 to be read. We used to raise a real alarm, but it seems
8664 that the handler isn't always enabled here. This is
8666 if (input_polling_used ())
8668 /* It could be confusing if a real alarm arrives while
8669 processing the fake one. Turn it off and let the
8670 handler reset it. */
8671 extern void poll_for_input_1
P_ ((void));
8672 int old_poll_suppress_count
= poll_suppress_count
;
8673 poll_suppress_count
= 1;
8674 poll_for_input_1 ();
8675 poll_suppress_count
= old_poll_suppress_count
;
8678 /* See if a MapNotify event has been processed. */
8679 FRAME_SAMPLE_VISIBILITY (f
);
8684 (let ((f (selected-frame)))
8688 the frame is not raised with various window managers on
8689 FreeBSD, GNU/Linux and Solaris. It turns out that, for some
8690 unknown reason, the call to XtMapWidget is completely ignored.
8691 Mapping the widget a second time works. */
8693 if (!FRAME_VISIBLE_P (f
) && --retry_count
> 0)
8698 /* Change from mapped state to withdrawn state. */
8700 /* Make the frame visible (mapped and not iconified). */
8703 x_make_frame_invisible (f
)
8708 /* Use the frame's outermost window, not the one we normally draw on. */
8709 window
= FRAME_OUTER_WINDOW (f
);
8711 /* Don't keep the highlight on an invisible frame. */
8712 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
8713 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
8715 #if 0/* This might add unreliability; I don't trust it -- rms. */
8716 if (! f
->async_visible
&& ! f
->async_iconified
)
8722 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
8723 that the current position of the window is user-specified, rather than
8724 program-specified, so that when the window is mapped again, it will be
8725 placed at the same location, without forcing the user to position it
8726 by hand again (they have already done that once for this window.) */
8727 x_wm_set_size_hint (f
, (long) 0, 1);
8730 if (FRAME_GTK_OUTER_WIDGET (f
))
8731 gtk_widget_hide (FRAME_GTK_OUTER_WIDGET (f
));
8737 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
8738 DefaultScreen (FRAME_X_DISPLAY (f
))))
8740 UNBLOCK_INPUT_RESIGNAL
;
8741 error ("Can't notify window manager of window withdrawal");
8743 #else /* ! defined (HAVE_X11R4) */
8745 /* Tell the window manager what we're going to do. */
8746 if (! EQ (Vx_no_window_manager
, Qt
))
8750 unmap
.xunmap
.type
= UnmapNotify
;
8751 unmap
.xunmap
.window
= window
;
8752 unmap
.xunmap
.event
= DefaultRootWindow (FRAME_X_DISPLAY (f
));
8753 unmap
.xunmap
.from_configure
= False
;
8754 if (! XSendEvent (FRAME_X_DISPLAY (f
),
8755 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
8757 SubstructureRedirectMaskSubstructureNotifyMask
,
8760 UNBLOCK_INPUT_RESIGNAL
;
8761 error ("Can't notify window manager of withdrawal");
8765 /* Unmap the window ourselves. Cheeky! */
8766 XUnmapWindow (FRAME_X_DISPLAY (f
), window
);
8767 #endif /* ! defined (HAVE_X11R4) */
8770 /* We can't distinguish this from iconification
8771 just by the event that we get from the server.
8772 So we can't win using the usual strategy of letting
8773 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
8774 and synchronize with the server to make sure we agree. */
8776 FRAME_ICONIFIED_P (f
) = 0;
8777 f
->async_visible
= 0;
8778 f
->async_iconified
= 0;
8785 /* Change window state from mapped to iconified. */
8794 /* Don't keep the highlight on an invisible frame. */
8795 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
8796 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
8798 if (f
->async_iconified
)
8803 FRAME_SAMPLE_VISIBILITY (f
);
8805 type
= x_icon_type (f
);
8807 x_bitmap_icon (f
, type
);
8810 if (FRAME_GTK_OUTER_WIDGET (f
))
8812 if (! FRAME_VISIBLE_P (f
))
8813 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f
));
8815 gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f
)));
8818 f
->async_iconified
= 1;
8819 f
->async_visible
= 0;
8825 #ifdef USE_X_TOOLKIT
8827 if (! FRAME_VISIBLE_P (f
))
8829 if (! EQ (Vx_no_window_manager
, Qt
))
8830 x_wm_set_window_state (f
, IconicState
);
8831 /* This was XtPopup, but that did nothing for an iconified frame. */
8832 XtMapWidget (f
->output_data
.x
->widget
);
8833 /* The server won't give us any event to indicate
8834 that an invisible frame was changed to an icon,
8835 so we have to record it here. */
8838 f
->async_iconified
= 1;
8839 f
->async_visible
= 0;
8844 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
8845 XtWindow (f
->output_data
.x
->widget
),
8846 DefaultScreen (FRAME_X_DISPLAY (f
)));
8850 error ("Can't notify window manager of iconification");
8852 f
->async_iconified
= 1;
8853 f
->async_visible
= 0;
8857 XFlush (FRAME_X_DISPLAY (f
));
8859 #else /* not USE_X_TOOLKIT */
8861 /* Make sure the X server knows where the window should be positioned,
8862 in case the user deiconifies with the window manager. */
8863 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
8864 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
8866 /* Since we don't know which revision of X we're running, we'll use both
8867 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
8869 /* X11R4: send a ClientMessage to the window manager using the
8870 WM_CHANGE_STATE type. */
8874 message
.xclient
.window
= FRAME_X_WINDOW (f
);
8875 message
.xclient
.type
= ClientMessage
;
8876 message
.xclient
.message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
8877 message
.xclient
.format
= 32;
8878 message
.xclient
.data
.l
[0] = IconicState
;
8880 if (! XSendEvent (FRAME_X_DISPLAY (f
),
8881 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
8883 SubstructureRedirectMask
| SubstructureNotifyMask
,
8886 UNBLOCK_INPUT_RESIGNAL
;
8887 error ("Can't notify window manager of iconification");
8891 /* X11R3: set the initial_state field of the window manager hints to
8893 x_wm_set_window_state (f
, IconicState
);
8895 if (!FRAME_VISIBLE_P (f
))
8897 /* If the frame was withdrawn, before, we must map it. */
8898 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
8901 f
->async_iconified
= 1;
8902 f
->async_visible
= 0;
8904 XFlush (FRAME_X_DISPLAY (f
));
8906 #endif /* not USE_X_TOOLKIT */
8910 /* Free X resources of frame F. */
8913 x_free_frame_resources (f
)
8916 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
8918 struct scroll_bar
*b
;
8922 /* If a display connection is dead, don't try sending more
8923 commands to the X server. */
8924 if (dpyinfo
->display
)
8926 if (f
->output_data
.x
->icon_desc
)
8927 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->icon_desc
);
8929 #ifdef USE_X_TOOLKIT
8930 /* Explicitly destroy the scroll bars of the frame. Without
8931 this, we get "BadDrawable" errors from the toolkit later on,
8932 presumably from expose events generated for the disappearing
8933 toolkit scroll bars. */
8934 for (bar
= FRAME_SCROLL_BARS (f
); !NILP (bar
); bar
= b
->next
)
8936 b
= XSCROLL_BAR (bar
);
8937 x_scroll_bar_remove (b
);
8946 #ifdef USE_X_TOOLKIT
8947 if (f
->output_data
.x
->widget
)
8949 XtDestroyWidget (f
->output_data
.x
->widget
);
8950 f
->output_data
.x
->widget
= NULL
;
8952 /* Tooltips don't have widgets, only a simple X window, even if
8953 we are using a toolkit. */
8954 else if (FRAME_X_WINDOW (f
))
8955 XDestroyWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
8957 free_frame_menubar (f
);
8958 #else /* !USE_X_TOOLKIT */
8961 /* In the GTK version, tooltips are normal X
8962 frames. We must check and free both types. */
8963 if (FRAME_GTK_OUTER_WIDGET (f
))
8965 gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f
));
8966 FRAME_X_WINDOW (f
) = 0; /* Set to avoid XDestroyWindow below */
8967 FRAME_GTK_OUTER_WIDGET (f
) = 0;
8969 #endif /* USE_GTK */
8971 if (FRAME_X_WINDOW (f
))
8972 XDestroyWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
8973 #endif /* !USE_X_TOOLKIT */
8975 unload_color (f
, f
->output_data
.x
->foreground_pixel
);
8976 unload_color (f
, f
->output_data
.x
->background_pixel
);
8977 unload_color (f
, f
->output_data
.x
->cursor_pixel
);
8978 unload_color (f
, f
->output_data
.x
->cursor_foreground_pixel
);
8979 unload_color (f
, f
->output_data
.x
->border_pixel
);
8980 unload_color (f
, f
->output_data
.x
->mouse_pixel
);
8982 if (f
->output_data
.x
->scroll_bar_background_pixel
!= -1)
8983 unload_color (f
, f
->output_data
.x
->scroll_bar_background_pixel
);
8984 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
8985 unload_color (f
, f
->output_data
.x
->scroll_bar_foreground_pixel
);
8986 #ifdef USE_TOOLKIT_SCROLL_BARS
8987 /* Scrollbar shadow colors. */
8988 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
!= -1)
8989 unload_color (f
, f
->output_data
.x
->scroll_bar_top_shadow_pixel
);
8990 if (f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
!= -1)
8991 unload_color (f
, f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
);
8992 #endif /* USE_TOOLKIT_SCROLL_BARS */
8993 if (f
->output_data
.x
->white_relief
.allocated_p
)
8994 unload_color (f
, f
->output_data
.x
->white_relief
.pixel
);
8995 if (f
->output_data
.x
->black_relief
.allocated_p
)
8996 unload_color (f
, f
->output_data
.x
->black_relief
.pixel
);
8998 if (FRAME_FACE_CACHE (f
))
8999 free_frame_faces (f
);
9002 XFlush (FRAME_X_DISPLAY (f
));
9005 if (f
->output_data
.x
->saved_menu_event
)
9006 xfree (f
->output_data
.x
->saved_menu_event
);
9008 xfree (f
->output_data
.x
);
9009 f
->output_data
.x
= NULL
;
9011 if (f
== dpyinfo
->x_focus_frame
)
9012 dpyinfo
->x_focus_frame
= 0;
9013 if (f
== dpyinfo
->x_focus_event_frame
)
9014 dpyinfo
->x_focus_event_frame
= 0;
9015 if (f
== dpyinfo
->x_highlight_frame
)
9016 dpyinfo
->x_highlight_frame
= 0;
9018 if (f
== dpyinfo
->mouse_face_mouse_frame
)
9020 dpyinfo
->mouse_face_beg_row
9021 = dpyinfo
->mouse_face_beg_col
= -1;
9022 dpyinfo
->mouse_face_end_row
9023 = dpyinfo
->mouse_face_end_col
= -1;
9024 dpyinfo
->mouse_face_window
= Qnil
;
9025 dpyinfo
->mouse_face_deferred_gc
= 0;
9026 dpyinfo
->mouse_face_mouse_frame
= 0;
9033 /* Destroy the X window of frame F. */
9036 x_destroy_window (f
)
9039 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9041 /* If a display connection is dead, don't try sending more
9042 commands to the X server. */
9043 if (dpyinfo
->display
!= 0)
9044 x_free_frame_resources (f
);
9046 dpyinfo
->reference_count
--;
9050 /* Setting window manager hints. */
9052 /* Set the normal size hints for the window manager, for frame F.
9053 FLAGS is the flags word to use--or 0 meaning preserve the flags
9054 that the window now has.
9055 If USER_POSITION is nonzero, we set the USPosition
9056 flag (this is useful when FLAGS is 0).
9057 The GTK version is in gtkutils.c */
9061 x_wm_set_size_hint (f
, flags
, user_position
)
9066 XSizeHints size_hints
;
9068 #ifdef USE_X_TOOLKIT
9071 Dimension widget_width
, widget_height
;
9074 Window window
= FRAME_OUTER_WINDOW (f
);
9076 /* Setting PMaxSize caused various problems. */
9077 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
9079 size_hints
.x
= f
->left_pos
;
9080 size_hints
.y
= f
->top_pos
;
9082 #ifdef USE_X_TOOLKIT
9083 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
9084 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
9085 XtGetValues (f
->output_data
.x
->widget
, al
, ac
);
9086 size_hints
.height
= widget_height
;
9087 size_hints
.width
= widget_width
;
9088 #else /* not USE_X_TOOLKIT */
9089 size_hints
.height
= FRAME_PIXEL_HEIGHT (f
);
9090 size_hints
.width
= FRAME_PIXEL_WIDTH (f
);
9091 #endif /* not USE_X_TOOLKIT */
9093 size_hints
.width_inc
= FRAME_COLUMN_WIDTH (f
);
9094 size_hints
.height_inc
= FRAME_LINE_HEIGHT (f
);
9095 size_hints
.max_width
9096 = FRAME_X_DISPLAY_INFO (f
)->width
- FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
9097 size_hints
.max_height
9098 = FRAME_X_DISPLAY_INFO (f
)->height
- FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
9100 /* Calculate the base and minimum sizes.
9102 (When we use the X toolkit, we don't do it here.
9103 Instead we copy the values that the widgets are using, below.) */
9104 #ifndef USE_X_TOOLKIT
9106 int base_width
, base_height
;
9107 int min_rows
= 0, min_cols
= 0;
9109 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
9110 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
9112 check_frame_size (f
, &min_rows
, &min_cols
);
9114 /* The window manager uses the base width hints to calculate the
9115 current number of rows and columns in the frame while
9116 resizing; min_width and min_height aren't useful for this
9117 purpose, since they might not give the dimensions for a
9118 zero-row, zero-column frame.
9120 We use the base_width and base_height members if we have
9121 them; otherwise, we set the min_width and min_height members
9122 to the size for a zero x zero frame. */
9125 size_hints
.flags
|= PBaseSize
;
9126 size_hints
.base_width
= base_width
;
9127 size_hints
.base_height
= base_height
;
9128 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
9129 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
9131 size_hints
.min_width
= base_width
;
9132 size_hints
.min_height
= base_height
;
9136 /* If we don't need the old flags, we don't need the old hint at all. */
9139 size_hints
.flags
|= flags
;
9142 #endif /* not USE_X_TOOLKIT */
9145 XSizeHints hints
; /* Sometimes I hate X Windows... */
9146 long supplied_return
;
9150 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
9153 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
9156 #ifdef USE_X_TOOLKIT
9157 size_hints
.base_height
= hints
.base_height
;
9158 size_hints
.base_width
= hints
.base_width
;
9159 size_hints
.min_height
= hints
.min_height
;
9160 size_hints
.min_width
= hints
.min_width
;
9164 size_hints
.flags
|= flags
;
9169 if (hints
.flags
& PSize
)
9170 size_hints
.flags
|= PSize
;
9171 if (hints
.flags
& PPosition
)
9172 size_hints
.flags
|= PPosition
;
9173 if (hints
.flags
& USPosition
)
9174 size_hints
.flags
|= USPosition
;
9175 if (hints
.flags
& USSize
)
9176 size_hints
.flags
|= USSize
;
9180 #ifndef USE_X_TOOLKIT
9185 size_hints
.win_gravity
= f
->win_gravity
;
9186 size_hints
.flags
|= PWinGravity
;
9190 size_hints
.flags
&= ~ PPosition
;
9191 size_hints
.flags
|= USPosition
;
9193 #endif /* PWinGravity */
9196 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
9198 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
9201 #endif /* not USE_GTK */
9203 /* Used for IconicState or NormalState */
9206 x_wm_set_window_state (f
, state
)
9210 #ifdef USE_X_TOOLKIT
9213 XtSetArg (al
[0], XtNinitialState
, state
);
9214 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
9215 #else /* not USE_X_TOOLKIT */
9216 Window window
= FRAME_X_WINDOW (f
);
9218 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
9219 f
->output_data
.x
->wm_hints
.initial_state
= state
;
9221 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
9222 #endif /* not USE_X_TOOLKIT */
9226 x_wm_set_icon_pixmap (f
, pixmap_id
)
9230 Pixmap icon_pixmap
, icon_mask
;
9232 #ifndef USE_X_TOOLKIT
9233 Window window
= FRAME_OUTER_WINDOW (f
);
9238 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
9239 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
9240 icon_mask
= x_bitmap_mask (f
, pixmap_id
);
9241 f
->output_data
.x
->wm_hints
.icon_mask
= icon_mask
;
9245 /* It seems there is no way to turn off use of an icon pixmap.
9246 The following line does it, only if no icon has yet been created,
9247 for some window managers. But with mwm it crashes.
9248 Some people say it should clear the IconPixmapHint bit in this case,
9249 but that doesn't work, and the X consortium said it isn't the
9250 right thing at all. Since there is no way to win,
9251 best to explicitly give up. */
9253 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
9254 f
->output_data
.x
->wm_hints
.icon_mask
= None
;
9260 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
9264 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
9265 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
9266 XtSetArg (al
[0], XtNiconMask
, icon_mask
);
9267 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
9270 #else /* not USE_X_TOOLKIT */
9272 f
->output_data
.x
->wm_hints
.flags
|= (IconPixmapHint
| IconMaskHint
);
9273 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
9275 #endif /* not USE_X_TOOLKIT */
9279 x_wm_set_icon_position (f
, icon_x
, icon_y
)
9283 Window window
= FRAME_OUTER_WINDOW (f
);
9285 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
9286 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
9287 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
9289 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
9293 /***********************************************************************
9295 ***********************************************************************/
9297 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
9300 x_get_font_info (f
, font_idx
)
9304 return (FRAME_X_FONT_TABLE (f
) + font_idx
);
9308 /* Return a list of names of available fonts matching PATTERN on frame F.
9310 If SIZE is > 0, it is the size (maximum bounds width) of fonts
9313 SIZE < 0 means include scalable fonts.
9315 Frame F null means we have not yet created any frame on X, and
9316 consult the first display in x_display_list. MAXNAMES sets a limit
9317 on how many fonts to match. */
9320 x_list_fonts (f
, pattern
, size
, maxnames
)
9322 Lisp_Object pattern
;
9326 Lisp_Object list
= Qnil
, patterns
, newlist
= Qnil
, key
= Qnil
;
9327 Lisp_Object tem
, second_best
;
9328 struct x_display_info
*dpyinfo
9329 = f
? FRAME_X_DISPLAY_INFO (f
) : x_display_list
;
9330 Display
*dpy
= dpyinfo
->display
;
9331 int try_XLoadQueryFont
= 0;
9333 int allow_auto_scaled_font
= 0;
9337 allow_auto_scaled_font
= 1;
9341 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
9342 if (NILP (patterns
))
9343 patterns
= Fcons (pattern
, Qnil
);
9345 if (maxnames
== 1 && !size
)
9346 /* We can return any single font matching PATTERN. */
9347 try_XLoadQueryFont
= 1;
9349 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
9352 char **names
= NULL
;
9354 pattern
= XCAR (patterns
);
9355 /* See if we cached the result for this particular query.
9356 The cache is an alist of the form:
9357 ((((PATTERN . MAXNAMES) . SCALABLE) (FONTNAME . WIDTH) ...) ...) */
9358 tem
= XCDR (dpyinfo
->name_list_element
);
9359 key
= Fcons (Fcons (pattern
, make_number (maxnames
)),
9360 allow_auto_scaled_font
? Qt
: Qnil
);
9361 list
= Fassoc (key
, tem
);
9364 list
= Fcdr_safe (list
);
9365 /* We have a cashed list. Don't have to get the list again. */
9369 /* At first, put PATTERN in the cache. */
9372 count
= x_catch_errors (dpy
);
9374 if (try_XLoadQueryFont
)
9377 unsigned long value
;
9379 font
= XLoadQueryFont (dpy
, SDATA (pattern
));
9380 if (x_had_errors_p (dpy
))
9382 /* This error is perhaps due to insufficient memory on X
9383 server. Let's just ignore it. */
9385 x_clear_errors (dpy
);
9389 && XGetFontProperty (font
, XA_FONT
, &value
))
9391 char *name
= (char *) XGetAtomName (dpy
, (Atom
) value
);
9392 int len
= strlen (name
);
9395 /* If DXPC (a Differential X Protocol Compressor)
9396 Ver.3.7 is running, XGetAtomName will return null
9397 string. We must avoid such a name. */
9399 try_XLoadQueryFont
= 0;
9403 names
= (char **) alloca (sizeof (char *));
9404 /* Some systems only allow alloca assigned to a
9406 tmp
= (char *) alloca (len
+ 1); names
[0] = tmp
;
9407 bcopy (name
, names
[0], len
+ 1);
9412 try_XLoadQueryFont
= 0;
9415 XFreeFont (dpy
, font
);
9418 if (!try_XLoadQueryFont
)
9420 /* We try at least 10 fonts because XListFonts will return
9421 auto-scaled fonts at the head. */
9428 names
= XListFonts (dpy
, SDATA (pattern
), limit
, &num_fonts
);
9429 if (num_fonts
== limit
)
9432 XFreeFontNames (names
);
9441 names
= XListFonts (dpy
, SDATA (pattern
), max (maxnames
, 10),
9444 if (x_had_errors_p (dpy
))
9446 /* This error is perhaps due to insufficient memory on X
9447 server. Let's just ignore it. */
9449 x_clear_errors (dpy
);
9453 x_uncatch_errors (dpy
, count
);
9460 /* Make a list of all the fonts we got back.
9461 Store that in the font cache for the display. */
9462 for (i
= 0; i
< num_fonts
; i
++)
9466 int average_width
= -1, resx
= 0, dashes
= 0;
9468 /* Count the number of dashes in NAMES[I]. If there are
9469 14 dashes, the field value following 9th dash
9470 (RESOLUTION_X) is nonzero, and the field value
9471 following 12th dash (AVERAGE_WIDTH) is 0, this is a
9472 auto-scaled font which is usually too ugly to be used
9473 for editing. Let's ignore it. */
9478 if (dashes
== 7) /* PIXEL_SIZE field */
9480 else if (dashes
== 9)
9482 else if (dashes
== 12) /* AVERAGE_WIDTH field */
9483 average_width
= atoi (p
);
9486 if (allow_auto_scaled_font
9487 || dashes
< 14 || average_width
!= 0 || resx
== 0)
9489 tem
= build_string (names
[i
]);
9490 if (NILP (Fassoc (tem
, list
)))
9492 if (STRINGP (Vx_pixel_size_width_font_regexp
)
9493 && ((fast_c_string_match_ignore_case
9494 (Vx_pixel_size_width_font_regexp
, names
[i
]))
9496 /* We can set the value of PIXEL_SIZE to the
9497 width of this font. */
9498 list
= Fcons (Fcons (tem
, make_number (width
)), list
);
9500 /* For the moment, width is not known. */
9501 list
= Fcons (Fcons (tem
, Qnil
), list
);
9506 if (!try_XLoadQueryFont
)
9509 XFreeFontNames (names
);
9514 /* Now store the result in the cache. */
9515 XSETCDR (dpyinfo
->name_list_element
,
9516 Fcons (Fcons (key
, list
), XCDR (dpyinfo
->name_list_element
)));
9519 if (NILP (list
)) continue; /* Try the remaining alternatives. */
9521 newlist
= second_best
= Qnil
;
9522 /* Make a list of the fonts that have the right width. */
9523 for (; CONSP (list
); list
= XCDR (list
))
9529 if (!CONSP (tem
) || NILP (XCAR (tem
)))
9533 newlist
= Fcons (XCAR (tem
), newlist
);
9537 if (!INTEGERP (XCDR (tem
)))
9539 /* Since we have not yet known the size of this font, we
9540 must try slow function call XLoadQueryFont. */
9541 XFontStruct
*thisinfo
;
9544 count
= x_catch_errors (dpy
);
9545 thisinfo
= XLoadQueryFont (dpy
,
9546 SDATA (XCAR (tem
)));
9547 if (x_had_errors_p (dpy
))
9549 /* This error is perhaps due to insufficient memory on X
9550 server. Let's just ignore it. */
9552 x_clear_errors (dpy
);
9554 x_uncatch_errors (dpy
, count
);
9560 (thisinfo
->min_bounds
.width
== 0
9562 : make_number (thisinfo
->max_bounds
.width
)));
9564 XFreeFont (dpy
, thisinfo
);
9568 /* For unknown reason, the previous call of XListFont had
9569 returned a font which can't be opened. Record the size
9570 as 0 not to try to open it again. */
9571 XSETCDR (tem
, make_number (0));
9574 found_size
= XINT (XCDR (tem
));
9575 if (found_size
== size
)
9576 newlist
= Fcons (XCAR (tem
), newlist
);
9577 else if (found_size
> 0)
9579 if (NILP (second_best
))
9581 else if (found_size
< size
)
9583 if (XINT (XCDR (second_best
)) > size
9584 || XINT (XCDR (second_best
)) < found_size
)
9589 if (XINT (XCDR (second_best
)) > size
9590 && XINT (XCDR (second_best
)) > found_size
)
9595 if (!NILP (newlist
))
9597 else if (!NILP (second_best
))
9599 newlist
= Fcons (XCAR (second_best
), Qnil
);
9610 /* Check that FONT is valid on frame F. It is if it can be found in F's
9614 x_check_font (f
, font
)
9619 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9621 xassert (font
!= NULL
);
9623 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9624 if (dpyinfo
->font_table
[i
].name
9625 && font
== dpyinfo
->font_table
[i
].font
)
9628 xassert (i
< dpyinfo
->n_fonts
);
9631 #endif /* GLYPH_DEBUG != 0 */
9633 /* Set *W to the minimum width, *H to the minimum font height of FONT.
9634 Note: There are (broken) X fonts out there with invalid XFontStruct
9635 min_bounds contents. For example, handa@etl.go.jp reports that
9636 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
9637 have font->min_bounds.width == 0. */
9640 x_font_min_bounds (font
, w
, h
)
9644 *h
= FONT_HEIGHT (font
);
9645 *w
= font
->min_bounds
.width
;
9647 /* Try to handle the case where FONT->min_bounds has invalid
9648 contents. Since the only font known to have invalid min_bounds
9649 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
9651 *w
= font
->max_bounds
.width
;
9655 /* Compute the smallest character width and smallest font height over
9656 all fonts available on frame F. Set the members smallest_char_width
9657 and smallest_font_height in F's x_display_info structure to
9658 the values computed. Value is non-zero if smallest_font_height or
9659 smallest_char_width become smaller than they were before. */
9662 x_compute_min_glyph_bounds (f
)
9666 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9668 int old_width
= dpyinfo
->smallest_char_width
;
9669 int old_height
= dpyinfo
->smallest_font_height
;
9671 dpyinfo
->smallest_font_height
= 100000;
9672 dpyinfo
->smallest_char_width
= 100000;
9674 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
9675 if (dpyinfo
->font_table
[i
].name
)
9677 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
9680 font
= (XFontStruct
*) fontp
->font
;
9681 xassert (font
!= (XFontStruct
*) ~0);
9682 x_font_min_bounds (font
, &w
, &h
);
9684 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
9685 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
9688 xassert (dpyinfo
->smallest_char_width
> 0
9689 && dpyinfo
->smallest_font_height
> 0);
9691 return (dpyinfo
->n_fonts
== 1
9692 || dpyinfo
->smallest_char_width
< old_width
9693 || dpyinfo
->smallest_font_height
< old_height
);
9697 /* Load font named FONTNAME of the size SIZE for frame F, and return a
9698 pointer to the structure font_info while allocating it dynamically.
9699 If SIZE is 0, load any size of font.
9700 If loading is failed, return NULL. */
9703 x_load_font (f
, fontname
, size
)
9705 register char *fontname
;
9708 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9709 Lisp_Object font_names
;
9712 /* Get a list of all the fonts that match this name. Once we
9713 have a list of matching fonts, we compare them against the fonts
9714 we already have by comparing names. */
9715 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
9717 if (!NILP (font_names
))
9722 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9723 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
9724 if (dpyinfo
->font_table
[i
].name
9725 && (!strcmp (dpyinfo
->font_table
[i
].name
,
9726 SDATA (XCAR (tail
)))
9727 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
9728 SDATA (XCAR (tail
)))))
9729 return (dpyinfo
->font_table
+ i
);
9732 /* Load the font and add it to the table. */
9736 struct font_info
*fontp
;
9737 unsigned long value
;
9740 /* If we have found fonts by x_list_font, load one of them. If
9741 not, we still try to load a font by the name given as FONTNAME
9742 because XListFonts (called in x_list_font) of some X server has
9743 a bug of not finding a font even if the font surely exists and
9744 is loadable by XLoadQueryFont. */
9745 if (size
> 0 && !NILP (font_names
))
9746 fontname
= (char *) SDATA (XCAR (font_names
));
9749 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
9750 font
= (XFontStruct
*) XLoadQueryFont (FRAME_X_DISPLAY (f
), fontname
);
9751 if (x_had_errors_p (FRAME_X_DISPLAY (f
)))
9753 /* This error is perhaps due to insufficient memory on X
9754 server. Let's just ignore it. */
9756 x_clear_errors (FRAME_X_DISPLAY (f
));
9758 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
9763 /* Find a free slot in the font table. */
9764 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
9765 if (dpyinfo
->font_table
[i
].name
== NULL
)
9768 /* If no free slot found, maybe enlarge the font table. */
9769 if (i
== dpyinfo
->n_fonts
9770 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
9773 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
9774 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
9776 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
9779 fontp
= dpyinfo
->font_table
+ i
;
9780 if (i
== dpyinfo
->n_fonts
)
9783 /* Now fill in the slots of *FONTP. */
9785 bzero (fontp
, sizeof (*fontp
));
9787 fontp
->font_idx
= i
;
9788 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
9789 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
9791 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
9793 /* Fixed width font. */
9794 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
9801 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
9802 pcm
= x_per_char_metric (font
, &char2b
, 0);
9804 fontp
->space_width
= pcm
->width
;
9806 fontp
->space_width
= FONT_WIDTH (font
);
9808 fontp
->average_width
9809 = (XGetFontProperty (font
, dpyinfo
->Xatom_AVERAGE_WIDTH
, &value
)
9810 ? (long) value
/ 10 : 0);
9811 if (fontp
->average_width
< 0)
9812 fontp
->average_width
= - fontp
->average_width
;
9813 if (fontp
->average_width
== 0)
9817 int width
= pcm
->width
;
9818 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
9819 if ((pcm
= x_per_char_metric (font
, &char2b
, 0)) != NULL
)
9820 width
+= pcm
->width
;
9821 fontp
->average_width
= width
/ 95;
9824 fontp
->average_width
= FONT_WIDTH (font
);
9828 /* Try to get the full name of FONT. Put it in FULL_NAME. */
9830 if (XGetFontProperty (font
, XA_FONT
, &value
))
9832 char *name
= (char *) XGetAtomName (FRAME_X_DISPLAY (f
), (Atom
) value
);
9836 /* Count the number of dashes in the "full name".
9837 If it is too few, this isn't really the font's full name,
9839 In X11R4, the fonts did not come with their canonical names
9850 full_name
= (char *) xmalloc (p
- name
+ 1);
9851 bcopy (name
, full_name
, p
- name
+ 1);
9858 fontp
->full_name
= full_name
;
9860 fontp
->full_name
= fontp
->name
;
9862 fontp
->size
= font
->max_bounds
.width
;
9863 fontp
->height
= FONT_HEIGHT (font
);
9865 if (NILP (font_names
))
9867 /* We come here because of a bug of XListFonts mentioned at
9868 the head of this block. Let's store this information in
9869 the cache for x_list_fonts. */
9870 Lisp_Object lispy_name
= build_string (fontname
);
9871 Lisp_Object lispy_full_name
= build_string (fontp
->full_name
);
9872 Lisp_Object key
= Fcons (Fcons (lispy_name
, make_number (256)),
9875 XSETCDR (dpyinfo
->name_list_element
,
9877 Fcons (Fcons (lispy_full_name
,
9878 make_number (fontp
->size
)),
9880 XCDR (dpyinfo
->name_list_element
)));
9883 key
= Fcons (Fcons (lispy_full_name
, make_number (256)),
9885 XSETCDR (dpyinfo
->name_list_element
,
9887 Fcons (Fcons (lispy_full_name
,
9888 make_number (fontp
->size
)),
9890 XCDR (dpyinfo
->name_list_element
)));
9894 /* The slot `encoding' specifies how to map a character
9895 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
9896 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
9897 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
9898 2:0xA020..0xFF7F). For the moment, we don't know which charset
9899 uses this font. So, we set information in fontp->encoding[1]
9900 which is never used by any charset. If mapping can't be
9901 decided, set FONT_ENCODING_NOT_DECIDED. */
9903 = (font
->max_byte1
== 0
9905 ? (font
->min_char_or_byte2
< 0x80
9906 ? (font
->max_char_or_byte2
< 0x80
9907 ? 0 /* 0x20..0x7F */
9908 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
9909 : 1) /* 0xA0..0xFF */
9911 : (font
->min_byte1
< 0x80
9912 ? (font
->max_byte1
< 0x80
9913 ? (font
->min_char_or_byte2
< 0x80
9914 ? (font
->max_char_or_byte2
< 0x80
9915 ? 0 /* 0x2020..0x7F7F */
9916 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
9917 : 3) /* 0x20A0..0x7FFF */
9918 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
9919 : (font
->min_char_or_byte2
< 0x80
9920 ? (font
->max_char_or_byte2
< 0x80
9921 ? 2 /* 0xA020..0xFF7F */
9922 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
9923 : 1))); /* 0xA0A0..0xFFFF */
9925 fontp
->baseline_offset
9926 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
9927 ? (long) value
: 0);
9928 fontp
->relative_compose
9929 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
9930 ? (long) value
: 0);
9931 fontp
->default_ascent
9932 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
9933 ? (long) value
: 0);
9935 /* Set global flag fonts_changed_p to non-zero if the font loaded
9936 has a character with a smaller width than any other character
9937 before, or if the font loaded has a smaller height than any
9938 other font loaded before. If this happens, it will make a
9939 glyph matrix reallocation necessary. */
9940 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
9947 /* Return a pointer to struct font_info of a font named FONTNAME for
9948 frame F. If no such font is loaded, return NULL. */
9951 x_query_font (f
, fontname
)
9953 register char *fontname
;
9955 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9958 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9959 if (dpyinfo
->font_table
[i
].name
9960 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
9961 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
9962 return (dpyinfo
->font_table
+ i
);
9967 /* Find a CCL program for a font specified by FONTP, and set the member
9968 `encoder' of the structure. */
9971 x_find_ccl_program (fontp
)
9972 struct font_info
*fontp
;
9974 Lisp_Object list
, elt
;
9977 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
9981 && STRINGP (XCAR (elt
))
9982 && ((fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
9984 || (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->full_name
)
9991 struct ccl_program
*ccl
9992 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
9994 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
9997 fontp
->font_encoder
= ccl
;
10003 /***********************************************************************
10005 ***********************************************************************/
10007 #ifdef USE_X_TOOLKIT
10008 static XrmOptionDescRec emacs_options
[] = {
10009 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
10010 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
10012 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
10013 XrmoptionSepArg
, NULL
},
10014 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
10016 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
10017 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
10018 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
10019 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
10020 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
10021 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
10022 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
10024 #endif /* USE_X_TOOLKIT */
10026 static int x_initialized
;
10028 #ifdef MULTI_KBOARD
10029 /* Test whether two display-name strings agree up to the dot that separates
10030 the screen number from the server number. */
10032 same_x_server (name1
, name2
)
10033 const char *name1
, *name2
;
10035 int seen_colon
= 0;
10036 const unsigned char *system_name
= SDATA (Vsystem_name
);
10037 int system_name_length
= strlen (system_name
);
10038 int length_until_period
= 0;
10040 while (system_name
[length_until_period
] != 0
10041 && system_name
[length_until_period
] != '.')
10042 length_until_period
++;
10044 /* Treat `unix' like an empty host name. */
10045 if (! strncmp (name1
, "unix:", 5))
10047 if (! strncmp (name2
, "unix:", 5))
10049 /* Treat this host's name like an empty host name. */
10050 if (! strncmp (name1
, system_name
, system_name_length
)
10051 && name1
[system_name_length
] == ':')
10052 name1
+= system_name_length
;
10053 if (! strncmp (name2
, system_name
, system_name_length
)
10054 && name2
[system_name_length
] == ':')
10055 name2
+= system_name_length
;
10056 /* Treat this host's domainless name like an empty host name. */
10057 if (! strncmp (name1
, system_name
, length_until_period
)
10058 && name1
[length_until_period
] == ':')
10059 name1
+= length_until_period
;
10060 if (! strncmp (name2
, system_name
, length_until_period
)
10061 && name2
[length_until_period
] == ':')
10062 name2
+= length_until_period
;
10064 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
10068 if (seen_colon
&& *name1
== '.')
10072 && (*name1
== '.' || *name1
== '\0')
10073 && (*name2
== '.' || *name2
== '\0'));
10077 /* Count number of set bits in mask and number of bits to shift to
10078 get to the first bit. With MASK 0x7e0, *BITS is set to 6, and *OFFSET
10081 get_bits_and_offset (mask
, bits
, offset
)
10082 unsigned long mask
;
10089 while (!(mask
& 1))
10105 struct x_display_info
*
10106 x_term_init (display_name
, xrm_option
, resource_name
)
10107 Lisp_Object display_name
;
10109 char *resource_name
;
10113 struct display
*display
;
10114 struct x_display_info
*dpyinfo
;
10119 if (!x_initialized
)
10127 #define NUM_ARGV 10
10129 char *argv
[NUM_ARGV
];
10130 char **argv2
= argv
;
10133 if (x_initialized
++ > 1)
10135 /* Opening another display. If xg_display_open returns less
10136 than zero, we are probably on GTK 2.0, which can only handle
10137 one display. GTK 2.2 or later can handle more than one. */
10138 if (xg_display_open (SDATA (display_name
), &dpy
) < 0)
10139 error ("Sorry, this version of GTK can only handle one display");
10143 for (argc
= 0; argc
< NUM_ARGV
; ++argc
)
10147 argv
[argc
++] = initial_argv
[0];
10149 if (! NILP (display_name
))
10151 argv
[argc
++] = "--display";
10152 argv
[argc
++] = SDATA (display_name
);
10155 argv
[argc
++] = "--name";
10156 argv
[argc
++] = resource_name
;
10159 XSetLocaleModifiers ("");
10162 gtk_init (&argc
, &argv2
);
10164 /* gtk_init does set_locale. We must fix locale after calling it. */
10168 dpy
= GDK_DISPLAY ();
10170 /* NULL window -> events for all windows go to our function */
10171 gdk_window_add_filter (NULL
, event_handler_gdk
, NULL
);
10173 /* Load our own gtkrc if it exists. */
10175 struct gcpro gcpro1
, gcpro2
;
10176 char *file
= "~/.emacs.d/gtkrc";
10177 Lisp_Object s
, abs_file
;
10179 GCPRO2 (s
, abs_file
);
10180 s
= make_string (file
, strlen (file
));
10181 abs_file
= Fexpand_file_name (s
, Qnil
);
10183 if (! NILP (abs_file
) && !NILP (Ffile_readable_p (abs_file
)))
10184 gtk_rc_parse (SDATA (abs_file
));
10189 XSetErrorHandler (x_error_handler
);
10190 XSetIOErrorHandler (x_io_error_quitter
);
10193 #else /* not USE_GTK */
10194 #ifdef USE_X_TOOLKIT
10195 /* weiner@footloose.sps.mot.com reports that this causes
10197 X protocol error: BadAtom (invalid Atom parameter)
10198 on protocol request 18skiloaf.
10199 So let's not use it until R6. */
10200 #ifdef HAVE_X11XTR6
10201 XtSetLanguageProc (NULL
, NULL
, NULL
);
10212 argv
[argc
++] = "-xrm";
10213 argv
[argc
++] = xrm_option
;
10215 turn_on_atimers (0);
10216 dpy
= XtOpenDisplay (Xt_app_con
, SDATA (display_name
),
10217 resource_name
, EMACS_CLASS
,
10218 emacs_options
, XtNumber (emacs_options
),
10220 turn_on_atimers (1);
10222 #ifdef HAVE_X11XTR6
10223 /* I think this is to compensate for XtSetLanguageProc. */
10228 #else /* not USE_X_TOOLKIT */
10230 XSetLocaleModifiers ("");
10232 dpy
= XOpenDisplay (SDATA (display_name
));
10233 #endif /* not USE_X_TOOLKIT */
10234 #endif /* not USE_GTK*/
10236 /* Detect failure. */
10243 /* We have definitely succeeded. Record the new connection. */
10245 dpyinfo
= (struct x_display_info
*) xmalloc (sizeof (struct x_display_info
));
10246 bzero (dpyinfo
, sizeof *dpyinfo
);
10248 display
= x_create_frame_display (dpyinfo
);
10250 #ifdef MULTI_KBOARD
10252 struct x_display_info
*share
;
10255 for (share
= x_display_list
, tail
= x_display_name_list
; share
;
10256 share
= share
->next
, tail
= XCDR (tail
))
10257 if (same_x_server (SDATA (XCAR (XCAR (tail
))),
10258 SDATA (display_name
)))
10261 dpyinfo
->kboard
= share
->kboard
;
10264 dpyinfo
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
10265 init_kboard (dpyinfo
->kboard
);
10266 if (!EQ (XSYMBOL (Qvendor_specific_keysyms
)->function
, Qunbound
))
10268 char *vendor
= ServerVendor (dpy
);
10270 dpyinfo
->kboard
->Vsystem_key_alist
10271 = call1 (Qvendor_specific_keysyms
,
10272 build_string (vendor
? vendor
: ""));
10276 dpyinfo
->kboard
->next_kboard
= all_kboards
;
10277 all_kboards
= dpyinfo
->kboard
;
10278 /* Don't let the initial kboard remain current longer than necessary.
10279 That would cause problems if a file loaded on startup tries to
10280 prompt in the mini-buffer. */
10281 if (current_kboard
== initial_kboard
)
10282 current_kboard
= dpyinfo
->kboard
;
10284 dpyinfo
->kboard
->reference_count
++;
10288 /* Put this display on the chain. */
10289 dpyinfo
->next
= x_display_list
;
10290 x_display_list
= dpyinfo
;
10292 /* Put it on x_display_name_list as well, to keep them parallel. */
10293 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
10294 x_display_name_list
);
10295 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
10297 dpyinfo
->display
= dpy
;
10299 /* Set the name of the display. */
10300 display
->name
= (char *) xmalloc (SBYTES (display_name
) + 1);
10301 strncpy (display
->name
, SDATA (display_name
), SBYTES (display_name
));
10302 display
->name
[SBYTES (display_name
)] = 0;
10305 XSetAfterFunction (x_current_display
, x_trace_wire
);
10309 = (char *) xmalloc (SBYTES (Vinvocation_name
)
10310 + SBYTES (Vsystem_name
)
10312 sprintf (dpyinfo
->x_id_name
, "%s@%s",
10313 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
10315 /* Figure out which modifier bits mean what. */
10316 x_find_modifier_meanings (dpyinfo
);
10318 /* Get the scroll bar cursor. */
10320 /* We must create a GTK cursor, it is required for GTK widgets. */
10321 dpyinfo
->xg_cursor
= xg_create_default_cursor (dpyinfo
->display
);
10322 #endif /* USE_GTK */
10324 dpyinfo
->vertical_scroll_bar_cursor
10325 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
10327 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
10328 resource_name
, EMACS_CLASS
);
10329 #ifdef HAVE_XRMSETDATABASE
10330 XrmSetDatabase (dpyinfo
->display
, xrdb
);
10332 dpyinfo
->display
->db
= xrdb
;
10334 /* Put the rdb where we can find it in a way that works on
10336 dpyinfo
->xrdb
= xrdb
;
10338 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
10339 DefaultScreen (dpyinfo
->display
));
10340 select_visual (dpyinfo
);
10341 dpyinfo
->cmap
= DefaultColormapOfScreen (dpyinfo
->screen
);
10342 dpyinfo
->height
= HeightOfScreen (dpyinfo
->screen
);
10343 dpyinfo
->width
= WidthOfScreen (dpyinfo
->screen
);
10344 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
10345 dpyinfo
->client_leader_window
= 0;
10346 dpyinfo
->grabbed
= 0;
10347 dpyinfo
->reference_count
= 0;
10348 dpyinfo
->icon_bitmap_id
= -1;
10349 dpyinfo
->font_table
= NULL
;
10350 dpyinfo
->n_fonts
= 0;
10351 dpyinfo
->font_table_size
= 0;
10352 dpyinfo
->bitmaps
= 0;
10353 dpyinfo
->bitmaps_size
= 0;
10354 dpyinfo
->bitmaps_last
= 0;
10355 dpyinfo
->scratch_cursor_gc
= 0;
10356 dpyinfo
->mouse_face_mouse_frame
= 0;
10357 dpyinfo
->mouse_face_deferred_gc
= 0;
10358 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
10359 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
10360 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
10361 dpyinfo
->mouse_face_window
= Qnil
;
10362 dpyinfo
->mouse_face_overlay
= Qnil
;
10363 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
10364 dpyinfo
->mouse_face_defer
= 0;
10365 dpyinfo
->mouse_face_hidden
= 0;
10366 dpyinfo
->x_focus_frame
= 0;
10367 dpyinfo
->x_focus_event_frame
= 0;
10368 dpyinfo
->x_highlight_frame
= 0;
10369 dpyinfo
->image_cache
= make_image_cache ();
10370 dpyinfo
->wm_type
= X_WMTYPE_UNKNOWN
;
10372 /* See if we can construct pixel values from RGB values. */
10373 dpyinfo
->red_bits
= dpyinfo
->blue_bits
= dpyinfo
->green_bits
= 0;
10374 dpyinfo
->red_offset
= dpyinfo
->blue_offset
= dpyinfo
->green_offset
= 0;
10376 if (dpyinfo
->visual
->class == TrueColor
)
10378 get_bits_and_offset (dpyinfo
->visual
->red_mask
,
10379 &dpyinfo
->red_bits
, &dpyinfo
->red_offset
);
10380 get_bits_and_offset (dpyinfo
->visual
->blue_mask
,
10381 &dpyinfo
->blue_bits
, &dpyinfo
->blue_offset
);
10382 get_bits_and_offset (dpyinfo
->visual
->green_mask
,
10383 &dpyinfo
->green_bits
, &dpyinfo
->green_offset
);
10386 /* See if a private colormap is requested. */
10387 if (dpyinfo
->visual
== DefaultVisualOfScreen (dpyinfo
->screen
))
10389 if (dpyinfo
->visual
->class == PseudoColor
)
10392 value
= display_x_get_resource (dpyinfo
,
10393 build_string ("privateColormap"),
10394 build_string ("PrivateColormap"),
10396 if (STRINGP (value
)
10397 && (!strcmp (SDATA (value
), "true")
10398 || !strcmp (SDATA (value
), "on")))
10399 dpyinfo
->cmap
= XCopyColormapAndFree (dpyinfo
->display
, dpyinfo
->cmap
);
10403 dpyinfo
->cmap
= XCreateColormap (dpyinfo
->display
, dpyinfo
->root_window
,
10404 dpyinfo
->visual
, AllocNone
);
10407 int screen_number
= XScreenNumberOfScreen (dpyinfo
->screen
);
10408 double pixels
= DisplayHeight (dpyinfo
->display
, screen_number
);
10409 double mm
= DisplayHeightMM (dpyinfo
->display
, screen_number
);
10410 /* Mac OS X 10.3's Xserver sometimes reports 0.0mm. */
10411 dpyinfo
->resy
= (mm
< 1) ? 100 : pixels
* 25.4 / mm
;
10412 pixels
= DisplayWidth (dpyinfo
->display
, screen_number
);
10413 /* Mac OS X 10.3's Xserver sometimes reports 0.0mm. */
10414 mm
= DisplayWidthMM (dpyinfo
->display
, screen_number
);
10415 dpyinfo
->resx
= (mm
< 1) ? 100 : pixels
* 25.4 / mm
;
10418 dpyinfo
->Xatom_wm_protocols
10419 = XInternAtom (dpyinfo
->display
, "WM_PROTOCOLS", False
);
10420 dpyinfo
->Xatom_wm_take_focus
10421 = XInternAtom (dpyinfo
->display
, "WM_TAKE_FOCUS", False
);
10422 dpyinfo
->Xatom_wm_save_yourself
10423 = XInternAtom (dpyinfo
->display
, "WM_SAVE_YOURSELF", False
);
10424 dpyinfo
->Xatom_wm_delete_window
10425 = XInternAtom (dpyinfo
->display
, "WM_DELETE_WINDOW", False
);
10426 dpyinfo
->Xatom_wm_change_state
10427 = XInternAtom (dpyinfo
->display
, "WM_CHANGE_STATE", False
);
10428 dpyinfo
->Xatom_wm_configure_denied
10429 = XInternAtom (dpyinfo
->display
, "WM_CONFIGURE_DENIED", False
);
10430 dpyinfo
->Xatom_wm_window_moved
10431 = XInternAtom (dpyinfo
->display
, "WM_MOVED", False
);
10432 dpyinfo
->Xatom_wm_client_leader
10433 = XInternAtom (dpyinfo
->display
, "WM_CLIENT_LEADER", False
);
10434 dpyinfo
->Xatom_editres
10435 = XInternAtom (dpyinfo
->display
, "Editres", False
);
10436 dpyinfo
->Xatom_CLIPBOARD
10437 = XInternAtom (dpyinfo
->display
, "CLIPBOARD", False
);
10438 dpyinfo
->Xatom_TIMESTAMP
10439 = XInternAtom (dpyinfo
->display
, "TIMESTAMP", False
);
10440 dpyinfo
->Xatom_TEXT
10441 = XInternAtom (dpyinfo
->display
, "TEXT", False
);
10442 dpyinfo
->Xatom_COMPOUND_TEXT
10443 = XInternAtom (dpyinfo
->display
, "COMPOUND_TEXT", False
);
10444 dpyinfo
->Xatom_UTF8_STRING
10445 = XInternAtom (dpyinfo
->display
, "UTF8_STRING", False
);
10446 dpyinfo
->Xatom_DELETE
10447 = XInternAtom (dpyinfo
->display
, "DELETE", False
);
10448 dpyinfo
->Xatom_MULTIPLE
10449 = XInternAtom (dpyinfo
->display
, "MULTIPLE", False
);
10450 dpyinfo
->Xatom_INCR
10451 = XInternAtom (dpyinfo
->display
, "INCR", False
);
10452 dpyinfo
->Xatom_EMACS_TMP
10453 = XInternAtom (dpyinfo
->display
, "_EMACS_TMP_", False
);
10454 dpyinfo
->Xatom_TARGETS
10455 = XInternAtom (dpyinfo
->display
, "TARGETS", False
);
10456 dpyinfo
->Xatom_NULL
10457 = XInternAtom (dpyinfo
->display
, "NULL", False
);
10458 dpyinfo
->Xatom_ATOM_PAIR
10459 = XInternAtom (dpyinfo
->display
, "ATOM_PAIR", False
);
10460 /* For properties of font. */
10461 dpyinfo
->Xatom_PIXEL_SIZE
10462 = XInternAtom (dpyinfo
->display
, "PIXEL_SIZE", False
);
10463 dpyinfo
->Xatom_AVERAGE_WIDTH
10464 = XInternAtom (dpyinfo
->display
, "AVERAGE_WIDTH", False
);
10465 dpyinfo
->Xatom_MULE_BASELINE_OFFSET
10466 = XInternAtom (dpyinfo
->display
, "_MULE_BASELINE_OFFSET", False
);
10467 dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
10468 = XInternAtom (dpyinfo
->display
, "_MULE_RELATIVE_COMPOSE", False
);
10469 dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
10470 = XInternAtom (dpyinfo
->display
, "_MULE_DEFAULT_ASCENT", False
);
10472 /* Ghostscript support. */
10473 dpyinfo
->Xatom_PAGE
= XInternAtom (dpyinfo
->display
, "PAGE", False
);
10474 dpyinfo
->Xatom_DONE
= XInternAtom (dpyinfo
->display
, "DONE", False
);
10476 dpyinfo
->Xatom_Scrollbar
= XInternAtom (dpyinfo
->display
, "SCROLLBAR",
10479 dpyinfo
->cut_buffers_initialized
= 0;
10481 connection
= ConnectionNumber (dpyinfo
->display
);
10482 dpyinfo
->connection
= connection
;
10487 null_bits
[0] = 0x00;
10489 dpyinfo
->null_pixel
10490 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
10491 null_bits
, 1, 1, (long) 0, (long) 0,
10496 extern int gray_bitmap_width
, gray_bitmap_height
;
10497 extern char *gray_bitmap_bits
;
10499 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
10501 gray_bitmap_width
, gray_bitmap_height
,
10502 (unsigned long) 1, (unsigned long) 0, 1);
10506 xim_initialize (dpyinfo
, resource_name
);
10509 #ifdef subprocesses
10510 /* This is only needed for distinguishing keyboard and process input. */
10511 if (connection
!= 0)
10512 add_keyboard_wait_descriptor (connection
);
10515 #ifndef F_SETOWN_BUG
10517 #ifdef F_SETOWN_SOCK_NEG
10518 /* stdin is a socket here */
10519 fcntl (connection
, F_SETOWN
, -getpid ());
10520 #else /* ! defined (F_SETOWN_SOCK_NEG) */
10521 fcntl (connection
, F_SETOWN
, getpid ());
10522 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
10523 #endif /* ! defined (F_SETOWN) */
10524 #endif /* F_SETOWN_BUG */
10527 if (interrupt_input
)
10528 init_sigio (connection
);
10529 #endif /* ! defined (SIGIO) */
10532 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
10533 /* Make sure that we have a valid font for dialog boxes
10534 so that Xt does not crash. */
10536 Display
*dpy
= dpyinfo
->display
;
10537 XrmValue d
, fr
, to
;
10541 d
.addr
= (XPointer
)&dpy
;
10542 d
.size
= sizeof (Display
*);
10543 fr
.addr
= XtDefaultFont
;
10544 fr
.size
= sizeof (XtDefaultFont
);
10545 to
.size
= sizeof (Font
*);
10546 to
.addr
= (XPointer
)&font
;
10547 count
= x_catch_errors (dpy
);
10548 if (!XtCallConverter (dpy
, XtCvtStringToFont
, &d
, 1, &fr
, &to
, NULL
))
10550 if (x_had_errors_p (dpy
) || !XQueryFont (dpy
, font
))
10551 XrmPutLineResource (&xrdb
, "Emacs.dialog.*.font: 9x15");
10552 x_uncatch_errors (dpy
, count
);
10557 /* See if we should run in synchronous mode. This is useful
10558 for debugging X code. */
10561 value
= display_x_get_resource (dpyinfo
,
10562 build_string ("synchronous"),
10563 build_string ("Synchronous"),
10565 if (STRINGP (value
)
10566 && (!strcmp (SDATA (value
), "true")
10567 || !strcmp (SDATA (value
), "on")))
10568 XSynchronize (dpyinfo
->display
, True
);
10573 value
= display_x_get_resource (dpyinfo
,
10574 build_string ("useXIM"),
10575 build_string ("UseXIM"),
10578 if (STRINGP (value
)
10579 && (!strcmp (XSTRING (value
)->data
, "false")
10580 || !strcmp (XSTRING (value
)->data
, "off")))
10583 if (STRINGP (value
)
10584 && (!strcmp (XSTRING (value
)->data
, "true")
10585 || !strcmp (XSTRING (value
)->data
, "on")))
10591 /* Only do this for the first display. */
10592 if (x_initialized
== 1)
10593 x_session_initialize (dpyinfo
);
10601 /* Get rid of display DPYINFO, assuming all frames are already gone,
10602 and without sending any more commands to the X server. */
10605 x_delete_display (dpyinfo
)
10606 struct x_display_info
*dpyinfo
;
10611 /* Delete the generic struct display for this X display. */
10613 for (d
= display_list
; d
; d
= d
->next_display
)
10614 if (d
->type
== output_x_window
&& d
->display_info
.x
== dpyinfo
)
10616 delete_display (d
);
10621 delete_keyboard_wait_descriptor (dpyinfo
->connection
);
10623 /* Discard this display from x_display_name_list and x_display_list.
10624 We can't use Fdelq because that can quit. */
10625 if (! NILP (x_display_name_list
)
10626 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
10627 x_display_name_list
= XCDR (x_display_name_list
);
10632 tail
= x_display_name_list
;
10633 while (CONSP (tail
) && CONSP (XCDR (tail
)))
10635 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
10637 XSETCDR (tail
, XCDR (XCDR (tail
)));
10640 tail
= XCDR (tail
);
10644 if (next_noop_dpyinfo
== dpyinfo
)
10645 next_noop_dpyinfo
= dpyinfo
->next
;
10647 if (x_display_list
== dpyinfo
)
10648 x_display_list
= dpyinfo
->next
;
10651 struct x_display_info
*tail
;
10653 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
10654 if (tail
->next
== dpyinfo
)
10655 tail
->next
= tail
->next
->next
;
10658 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
10659 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
10660 XrmDestroyDatabase (dpyinfo
->xrdb
);
10663 #ifdef MULTI_KBOARD
10664 if (--dpyinfo
->kboard
->reference_count
== 0)
10665 delete_kboard (dpyinfo
->kboard
);
10669 xim_close_dpy (dpyinfo
);
10672 /* Free the font names in the font table. */
10673 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
10674 if (dpyinfo
->font_table
[i
].name
)
10676 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
10677 xfree (dpyinfo
->font_table
[i
].full_name
);
10678 xfree (dpyinfo
->font_table
[i
].name
);
10681 if (dpyinfo
->font_table
&& dpyinfo
->font_table
->font_encoder
)
10682 xfree (dpyinfo
->font_table
->font_encoder
);
10684 if (dpyinfo
->font_table
)
10685 xfree (dpyinfo
->font_table
);
10686 xfree (dpyinfo
->x_id_name
);
10687 xfree (dpyinfo
->color_cells
);
10691 #ifdef USE_X_TOOLKIT
10693 /* Atimer callback function for TIMER. Called every 0.1s to process
10694 Xt timeouts, if needed. We must avoid calling XtAppPending as
10695 much as possible because that function does an implicit XFlush
10696 that slows us down. */
10699 x_process_timeouts (timer
)
10700 struct atimer
*timer
;
10702 if (toolkit_scroll_bar_interaction
|| popup_activated ())
10705 while (XtAppPending (Xt_app_con
) & XtIMTimer
)
10706 XtAppProcessEvent (Xt_app_con
, XtIMTimer
);
10711 #endif /* USE_X_TOOLKIT */
10714 /* Set up use of X before we make the first connection. */
10716 extern frame_parm_handler x_frame_parm_handlers
[];
10718 static struct redisplay_interface x_redisplay_interface
=
10720 x_frame_parm_handlers
,
10724 x_clear_end_of_line
,
10726 x_after_update_window_line
,
10727 x_update_window_begin
,
10728 x_update_window_end
,
10734 0, /* flush_display_optional */
10736 x_clear_window_mouse_face
,
10737 x_get_glyph_overhangs
,
10738 x_fix_overlapping_area
,
10739 x_draw_fringe_bitmap
,
10740 0, /* define_fringe_bitmap */
10741 0, /* destroy_fringe_bitmap */
10744 x_compute_glyph_string_overhangs
,
10745 x_draw_glyph_string
,
10746 x_define_frame_cursor
,
10747 x_clear_frame_area
,
10748 x_draw_window_cursor
,
10749 x_draw_vertical_window_border
,
10750 x_shift_glyphs_for_insert
10754 /* This function is called when the last frame on a display is deleted. */
10756 x_delete_frame_display (struct display
*display
)
10758 /* We don't do anything, the connection to the X server must remain
10764 x_create_frame_display (struct x_display_info
*dpyinfo
)
10766 struct display
*display
;
10768 display
= create_display ();
10770 display
->type
= output_x_window
;
10771 display
->display_info
.x
= dpyinfo
;
10772 dpyinfo
->frame_display
= display
;
10774 display
->clear_frame_hook
= x_clear_frame
;
10775 display
->ins_del_lines_hook
= x_ins_del_lines
;
10776 display
->delete_glyphs_hook
= x_delete_glyphs
;
10777 display
->ring_bell_hook
= XTring_bell
;
10778 display
->reset_terminal_modes_hook
= XTreset_terminal_modes
;
10779 display
->set_terminal_modes_hook
= XTset_terminal_modes
;
10780 display
->update_begin_hook
= x_update_begin
;
10781 display
->update_end_hook
= x_update_end
;
10782 display
->set_terminal_window_hook
= XTset_terminal_window
;
10783 display
->read_socket_hook
= XTread_socket
;
10784 display
->frame_up_to_date_hook
= XTframe_up_to_date
;
10785 display
->mouse_position_hook
= XTmouse_position
;
10786 display
->frame_rehighlight_hook
= XTframe_rehighlight
;
10787 display
->frame_raise_lower_hook
= XTframe_raise_lower
;
10788 display
->set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
10789 display
->condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
10790 display
->redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
10791 display
->judge_scroll_bars_hook
= XTjudge_scroll_bars
;
10793 display
->delete_frame_hook
= x_destroy_window
;
10794 display
->delete_display_hook
= x_delete_frame_display
;
10796 display
->rif
= &x_redisplay_interface
;
10797 display
->scroll_region_ok
= 1; /* We'll scroll partial frames. */
10798 display
->char_ins_del_ok
= 1;
10799 display
->line_ins_del_ok
= 1; /* We'll just blt 'em. */
10800 display
->fast_clear_end_of_line
= 1; /* X does this well. */
10801 display
->memory_below_frame
= 0; /* We don't remember what scrolls
10813 last_tool_bar_item
= -1;
10814 any_help_event_p
= 0;
10815 ignore_next_mouse_click_timeout
= 0;
10818 current_count
= -1;
10821 /* Try to use interrupt input; if we can't, then start polling. */
10822 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
10824 #ifdef USE_X_TOOLKIT
10825 XtToolkitInitialize ();
10827 Xt_app_con
= XtCreateApplicationContext ();
10829 /* Register a converter from strings to pixels, which uses
10830 Emacs' color allocation infrastructure. */
10831 XtAppSetTypeConverter (Xt_app_con
,
10832 XtRString
, XtRPixel
, cvt_string_to_pixel
,
10833 cvt_string_to_pixel_args
,
10834 XtNumber (cvt_string_to_pixel_args
),
10835 XtCacheByDisplay
, cvt_pixel_dtor
);
10837 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
10839 /* Install an asynchronous timer that processes Xt timeout events
10840 every 0.1s. This is necessary because some widget sets use
10841 timeouts internally, for example the LessTif menu bar, or the
10842 Xaw3d scroll bar. When Xt timouts aren't processed, these
10843 widgets don't behave normally. */
10845 EMACS_TIME interval
;
10846 EMACS_SET_SECS_USECS (interval
, 0, 100000);
10847 start_atimer (ATIMER_CONTINUOUS
, interval
, x_process_timeouts
, 0);
10851 #ifdef USE_TOOLKIT_SCROLL_BARS
10853 xaw3d_arrow_scroll
= False
;
10854 xaw3d_pick_top
= True
;
10858 /* Note that there is no real way portable across R3/R4 to get the
10859 original error handler. */
10860 XSetErrorHandler (x_error_handler
);
10861 XSetIOErrorHandler (x_io_error_quitter
);
10863 /* Disable Window Change signals; they are handled by X events. */
10864 #if 0 /* Don't. We may want to open tty frames later. */
10866 signal (SIGWINCH
, SIG_DFL
);
10867 #endif /* SIGWINCH */
10870 signal (SIGPIPE
, x_connection_signal
);
10877 staticpro (&x_error_message_string
);
10878 x_error_message_string
= Qnil
;
10880 staticpro (&x_display_name_list
);
10881 x_display_name_list
= Qnil
;
10883 staticpro (&last_mouse_scroll_bar
);
10884 last_mouse_scroll_bar
= Qnil
;
10886 staticpro (&Qvendor_specific_keysyms
);
10887 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
10889 staticpro (&Qutf_8
);
10890 Qutf_8
= intern ("utf-8");
10891 staticpro (&Qlatin_1
);
10892 Qlatin_1
= intern ("latin-1");
10894 staticpro (&last_mouse_press_frame
);
10895 last_mouse_press_frame
= Qnil
;
10897 DEFVAR_BOOL ("x-use-underline-position-properties",
10898 &x_use_underline_position_properties
,
10899 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
10900 nil means ignore them. If you encounter fonts with bogus
10901 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
10902 to 4.1, set this to nil. */);
10903 x_use_underline_position_properties
= 1;
10905 DEFVAR_BOOL ("x-mouse-click-focus-ignore-position",
10906 &x_mouse_click_focus_ignore_position
,
10907 doc
: /* Non-nil means that a mouse click to focus a frame does not move point.
10908 This variable is only used when the window manager requires that you
10909 click on a frame to select it (give it focus). In that case, a value
10910 of nil, means that the selected window and cursor position changes to
10911 reflect the mouse click position, while a non-nil value means that the
10912 selected window or cursor position is preserved. */);
10913 x_mouse_click_focus_ignore_position
= 0;
10915 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
10916 doc
: /* What X toolkit scroll bars Emacs uses.
10917 A value of nil means Emacs doesn't use X toolkit scroll bars.
10918 Otherwise, value is a symbol describing the X toolkit. */);
10919 #ifdef USE_TOOLKIT_SCROLL_BARS
10921 Vx_toolkit_scroll_bars
= intern ("motif");
10922 #elif defined HAVE_XAW3D
10923 Vx_toolkit_scroll_bars
= intern ("xaw3d");
10925 Vx_toolkit_scroll_bars
= intern ("gtk");
10927 Vx_toolkit_scroll_bars
= intern ("xaw");
10930 Vx_toolkit_scroll_bars
= Qnil
;
10933 staticpro (&last_mouse_motion_frame
);
10934 last_mouse_motion_frame
= Qnil
;
10936 Qmodifier_value
= intern ("modifier-value");
10937 Qalt
= intern ("alt");
10938 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
10939 Qhyper
= intern ("hyper");
10940 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
10941 Qmeta
= intern ("meta");
10942 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
10943 Qsuper
= intern ("super");
10944 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
10946 DEFVAR_LISP ("x-alt-keysym", &Vx_alt_keysym
,
10947 doc
: /* Which keys Emacs uses for the alt modifier.
10948 This should be one of the symbols `alt', `hyper', `meta', `super'.
10949 For example, `alt' means use the Alt_L and Alt_R keysyms. The default
10950 is nil, which is the same as `alt'. */);
10951 Vx_alt_keysym
= Qnil
;
10953 DEFVAR_LISP ("x-hyper-keysym", &Vx_hyper_keysym
,
10954 doc
: /* Which keys Emacs uses for the hyper modifier.
10955 This should be one of the symbols `alt', `hyper', `meta', `super'.
10956 For example, `hyper' means use the Hyper_L and Hyper_R keysyms. The
10957 default is nil, which is the same as `hyper'. */);
10958 Vx_hyper_keysym
= Qnil
;
10960 DEFVAR_LISP ("x-meta-keysym", &Vx_meta_keysym
,
10961 doc
: /* Which keys Emacs uses for the meta modifier.
10962 This should be one of the symbols `alt', `hyper', `meta', `super'.
10963 For example, `meta' means use the Meta_L and Meta_R keysyms. The
10964 default is nil, which is the same as `meta'. */);
10965 Vx_meta_keysym
= Qnil
;
10967 DEFVAR_LISP ("x-super-keysym", &Vx_super_keysym
,
10968 doc
: /* Which keys Emacs uses for the super modifier.
10969 This should be one of the symbols `alt', `hyper', `meta', `super'.
10970 For example, `super' means use the Super_L and Super_R keysyms. The
10971 default is nil, which is the same as `super'. */);
10972 Vx_super_keysym
= Qnil
;
10974 DEFVAR_LISP ("x-keysym-table", &Vx_keysym_table
,
10975 doc
: /* Hash table of character codes indexed by X keysym codes. */);
10976 Vx_keysym_table
= make_hash_table (Qeql
, make_number (900),
10977 make_float (DEFAULT_REHASH_SIZE
),
10978 make_float (DEFAULT_REHASH_THRESHOLD
),
10982 #endif /* HAVE_X_WINDOWS */
10984 /* arch-tag: 6d4e4cb7-abc1-4302-9585-d84dcfb09d0f
10985 (do not change this comment) */