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, 2006, 2007 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., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* New display code by Gerd Moellmann <gerd@gnu.org>. */
23 /* Xt features made by Fred Pierresteguy. */
27 /* On 4.3 these lose if they come after xterm.h. */
28 /* Putting these at the beginning seems to be standard for other .c files. */
36 #include "blockinput.h"
38 /* Need syssignal.h for various externs and definitions that may be required
39 by some configurations for calls to signal later in this source file. */
40 #include "syssignal.h"
42 /* This may include sys/types.h, and that somehow loses
43 if this is not done before the other system files. */
45 #include <X11/cursorfont.h>
47 /* Load sys/types.h if not already loaded.
48 In some systems loading it twice is suicidal. */
50 #include <sys/types.h>
54 #include <sys/ioctl.h>
55 #endif /* ! defined (BSD_SYSTEM) */
60 #ifndef INCLUDED_FCNTL
67 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
68 /* #include <sys/param.h> */
71 #include "character.h"
75 #include "dispextern.h"
77 #include "termhooks.h"
85 #include "intervals.h"
91 #include <X11/Shell.h>
94 #ifdef HAVE_SYS_TIME_H
105 #ifdef USE_FONT_BACKEND
107 #endif /* USE_FONT_BACKEND */
110 extern int xlwmenu_window_p
P_ ((Widget w
, Window window
));
111 extern void xlwmenu_redisplay
P_ ((Widget
));
114 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
116 extern void free_frame_menubar
P_ ((struct frame
*));
117 extern struct frame
*x_menubar_window_to_frame
P_ ((struct x_display_info
*,
122 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
124 extern void _XEditResCheckMessages ();
125 #endif /* not NO_EDITRES */
127 /* Include toolkit specific headers for the scroll bar widget. */
129 #ifdef USE_TOOLKIT_SCROLL_BARS
130 #if defined USE_MOTIF
131 #include <Xm/Xm.h> /* for LESSTIF_VERSION */
132 #include <Xm/ScrollBar.h>
133 #else /* !USE_MOTIF i.e. use Xaw */
136 #include <X11/Xaw3d/Simple.h>
137 #include <X11/Xaw3d/Scrollbar.h>
138 #include <X11/Xaw3d/ThreeD.h>
139 #else /* !HAVE_XAW3D */
140 #include <X11/Xaw/Simple.h>
141 #include <X11/Xaw/Scrollbar.h>
142 #endif /* !HAVE_XAW3D */
144 #define XtNpickTop "pickTop"
145 #endif /* !XtNpickTop */
146 #endif /* !USE_MOTIF */
147 #endif /* USE_TOOLKIT_SCROLL_BARS */
149 #endif /* USE_X_TOOLKIT */
151 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
152 #define x_any_window_to_frame x_window_to_frame
153 #define x_top_window_to_frame x_window_to_frame
158 #ifndef XtNinitialState
159 #define XtNinitialState "initialState"
163 #define abs(x) ((x) < 0 ? -(x) : (x))
165 /* Default to using XIM if available. */
169 int use_xim
= 0; /* configure --without-xim */
174 /* Non-nil means Emacs uses toolkit scroll bars. */
176 Lisp_Object Vx_toolkit_scroll_bars
;
178 /* Non-zero means that a HELP_EVENT has been generated since Emacs
181 static int any_help_event_p
;
183 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
184 static Lisp_Object last_window
;
186 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
188 int x_use_underline_position_properties
;
190 /* Non-zero means to draw the underline at the same place as the descent line. */
192 int x_underline_at_descent_line
;
194 /* This is a chain of structures for all the X displays currently in
197 struct x_display_info
*x_display_list
;
199 /* This is a list of cons cells, each of the form (NAME
200 . FONT-LIST-CACHE), one for each element of x_display_list and in
201 the same order. NAME is the name of the frame. FONT-LIST-CACHE
202 records previous values returned by x-list-fonts. */
204 Lisp_Object x_display_name_list
;
206 /* Frame being updated by update_frame. This is declared in term.c.
207 This is set by update_begin and looked at by all the XT functions.
208 It is zero while not inside an update. In that case, the XT
209 functions assume that `selected_frame' is the frame to apply to. */
211 extern struct frame
*updating_frame
;
213 /* This is a frame waiting to be auto-raised, within XTread_socket. */
215 struct frame
*pending_autoraise_frame
;
218 /* The application context for Xt use. */
219 XtAppContext Xt_app_con
;
220 static String Xt_default_resources
[] = {0};
221 #endif /* USE_X_TOOLKIT */
223 /* Non-zero means user is interacting with a toolkit scroll bar. */
225 static int toolkit_scroll_bar_interaction
;
227 /* Non-zero means to not move point as a result of clicking on a
228 frame to focus it (when focus-follows-mouse is nil). */
230 int x_mouse_click_focus_ignore_position
;
232 /* Non-zero timeout value means ignore next mouse click if it arrives
233 before that timeout elapses (i.e. as part of the same sequence of
234 events resulting from clicking on a frame to select it). */
236 static unsigned long ignore_next_mouse_click_timeout
;
240 Formerly, we used PointerMotionHintMask (in standard_event_mask)
241 so that we would have to call XQueryPointer after each MotionNotify
242 event to ask for another such event. However, this made mouse tracking
243 slow, and there was a bug that made it eventually stop.
245 Simply asking for MotionNotify all the time seems to work better.
247 In order to avoid asking for motion events and then throwing most
248 of them away or busy-polling the server for mouse positions, we ask
249 the server for pointer motion hints. This means that we get only
250 one event per group of mouse movements. "Groups" are delimited by
251 other kinds of events (focus changes and button clicks, for
252 example), or by XQueryPointer calls; when one of these happens, we
253 get another MotionNotify event the next time the mouse moves. This
254 is at least as efficient as getting motion events when mouse
255 tracking is on, and I suspect only negligibly worse when tracking
258 /* Where the mouse was last time we reported a mouse event. */
260 static XRectangle last_mouse_glyph
;
261 static FRAME_PTR last_mouse_glyph_frame
;
262 static Lisp_Object last_mouse_press_frame
;
264 /* The scroll bar in which the last X motion event occurred.
266 If the last X motion event occurred in a scroll bar, we set this so
267 XTmouse_position can know whether to report a scroll bar motion or
270 If the last X motion event didn't occur in a scroll bar, we set
271 this to Qnil, to tell XTmouse_position to return an ordinary motion
274 static Lisp_Object last_mouse_scroll_bar
;
276 /* This is a hack. We would really prefer that XTmouse_position would
277 return the time associated with the position it returns, but there
278 doesn't seem to be any way to wrest the time-stamp from the server
279 along with the position query. So, we just keep track of the time
280 of the last movement we received, and return that in hopes that
281 it's somewhat accurate. */
283 static Time last_mouse_movement_time
;
285 /* Time for last user interaction as returned in X events. */
287 static Time last_user_time
;
289 /* Incremented by XTread_socket whenever it really tries to read
293 static int volatile input_signal_count
;
295 static int input_signal_count
;
298 /* Used locally within XTread_socket. */
300 static int x_noop_count
;
302 /* Initial values of argv and argc. */
304 extern char **initial_argv
;
305 extern int initial_argc
;
307 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
309 /* Tells if a window manager is present or not. */
311 extern Lisp_Object Vx_no_window_manager
;
313 extern Lisp_Object Qeql
;
317 /* A mask of extra modifier bits to put into every keyboard char. */
319 extern EMACS_INT extra_keyboard_modifiers
;
321 /* The keysyms to use for the various modifiers. */
323 Lisp_Object Vx_alt_keysym
, Vx_hyper_keysym
, Vx_meta_keysym
, Vx_super_keysym
;
324 Lisp_Object Vx_keysym_table
;
325 static Lisp_Object Qalt
, Qhyper
, Qmeta
, Qsuper
, Qmodifier_value
;
327 static Lisp_Object Qvendor_specific_keysyms
;
328 static Lisp_Object Qlatin_1
;
330 extern XrmDatabase x_load_resources
P_ ((Display
*, char *, char *, char *));
331 extern int x_bitmap_mask
P_ ((FRAME_PTR
, int));
333 static int x_alloc_nearest_color_1
P_ ((Display
*, Colormap
, XColor
*));
334 static void x_set_window_size_1
P_ ((struct frame
*, int, int, int));
335 static const XColor
*x_color_cells
P_ ((Display
*, int *));
336 static void x_update_window_end
P_ ((struct window
*, int, int));
338 static int x_io_error_quitter
P_ ((Display
*));
339 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
340 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
341 static void x_update_end
P_ ((struct frame
*));
342 static void XTframe_up_to_date
P_ ((struct frame
*));
343 static void XTset_terminal_modes
P_ ((void));
344 static void XTreset_terminal_modes
P_ ((void));
345 static void x_clear_frame
P_ ((void));
346 static void frame_highlight
P_ ((struct frame
*));
347 static void frame_unhighlight
P_ ((struct frame
*));
348 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
349 static void x_focus_changed
P_ ((int, int, struct x_display_info
*,
350 struct frame
*, struct input_event
*));
351 static void x_detect_focus_change
P_ ((struct x_display_info
*,
352 XEvent
*, struct input_event
*));
353 static void XTframe_rehighlight
P_ ((struct frame
*));
354 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
355 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
356 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
357 enum text_cursor_kinds
));
359 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, int, GC
));
360 static void x_flush
P_ ((struct frame
*f
));
361 static void x_update_begin
P_ ((struct frame
*));
362 static void x_update_window_begin
P_ ((struct window
*));
363 static void x_after_update_window_line
P_ ((struct glyph_row
*));
364 static struct scroll_bar
*x_window_to_scroll_bar
P_ ((Display
*, Window
));
365 static void x_scroll_bar_report_motion
P_ ((struct frame
**, Lisp_Object
*,
366 enum scroll_bar_part
*,
367 Lisp_Object
*, Lisp_Object
*,
369 static void x_check_fullscreen
P_ ((struct frame
*));
370 static void x_check_expected_move
P_ ((struct frame
*, int, int));
371 static void x_sync_with_move
P_ ((struct frame
*, int, int, int));
372 static int handle_one_xevent
P_ ((struct x_display_info
*, XEvent
*,
373 int *, struct input_event
*));
374 static SIGTYPE x_connection_closed
P_ ((Display
*, char *)) NO_RETURN
;
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 x_flush (XFRAME (frame
));
390 else if (FRAME_X_P (f
))
391 XFlush (FRAME_X_DISPLAY (f
));
396 /* Remove calls to XFlush by defining XFlush to an empty replacement.
397 Calls to XFlush should be unnecessary because the X output buffer
398 is flushed automatically as needed by calls to XPending,
399 XNextEvent, or XWindowEvent according to the XFlush man page.
400 XTread_socket calls XPending. Removing XFlush improves
403 #define XFlush(DISPLAY) (void) 0
406 /***********************************************************************
408 ***********************************************************************/
412 /* This is a function useful for recording debugging information about
413 the sequence of occurrences in this file. */
421 struct record event_record
[100];
423 int event_record_index
;
425 record_event (locus
, type
)
429 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
430 event_record_index
= 0;
432 event_record
[event_record_index
].locus
= locus
;
433 event_record
[event_record_index
].type
= type
;
434 event_record_index
++;
441 /* Return the struct x_display_info corresponding to DPY. */
443 struct x_display_info
*
444 x_display_info_for_display (dpy
)
447 struct x_display_info
*dpyinfo
;
449 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
450 if (dpyinfo
->display
== dpy
)
458 /***********************************************************************
459 Starting and ending an update
460 ***********************************************************************/
462 /* Start an update of frame F. This function is installed as a hook
463 for update_begin, i.e. it is called when update_begin is called.
464 This function is called prior to calls to x_update_window_begin for
465 each window being updated. Currently, there is nothing to do here
466 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
));
543 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
545 XSetForeground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
548 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
549 f
->output_data
.x
->normal_gc
, x
, y0
, x
, y1
);
552 /* End update of window W (which is equal to updated_window).
554 Draw vertical borders between horizontally adjacent windows, and
555 display W's cursor if CURSOR_ON_P is non-zero.
557 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
558 glyphs in mouse-face were overwritten. In that case we have to
559 make sure that the mouse-highlight is properly redrawn.
561 W may be a menu bar pseudo-window in case we don't have X toolkit
562 support. Such windows don't have a cursor, so don't display it
566 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
568 int cursor_on_p
, mouse_face_overwritten_p
;
570 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (XFRAME (w
->frame
));
572 if (!w
->pseudo_window_p
)
577 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
579 output_cursor
.x
, output_cursor
.y
);
581 if (draw_window_fringes (w
, 1))
582 x_draw_vertical_border (w
);
587 /* If a row with mouse-face was overwritten, arrange for
588 XTframe_up_to_date to redisplay the mouse highlight. */
589 if (mouse_face_overwritten_p
)
591 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
592 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
593 dpyinfo
->mouse_face_window
= Qnil
;
596 updated_window
= NULL
;
600 /* End update of frame F. This function is installed as a hook in
607 /* Mouse highlight may be displayed again. */
608 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
612 XFlush (FRAME_X_DISPLAY (f
));
618 /* This function is called from various places in xdisp.c whenever a
619 complete update has been performed. The global variable
620 updated_window is not available here. */
623 XTframe_up_to_date (f
)
628 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
630 if (dpyinfo
->mouse_face_deferred_gc
631 || f
== dpyinfo
->mouse_face_mouse_frame
)
634 if (dpyinfo
->mouse_face_mouse_frame
)
635 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
636 dpyinfo
->mouse_face_mouse_x
,
637 dpyinfo
->mouse_face_mouse_y
);
638 dpyinfo
->mouse_face_deferred_gc
= 0;
645 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
646 arrow bitmaps, or clear the fringes if no bitmaps are required
647 before DESIRED_ROW is made current. The window being updated is
648 found in updated_window. This function It is called from
649 update_window_line only if it is known that there are differences
650 between bitmaps to be drawn between current row and DESIRED_ROW. */
653 x_after_update_window_line (desired_row
)
654 struct glyph_row
*desired_row
;
656 struct window
*w
= updated_window
;
662 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
663 desired_row
->redraw_fringe_bitmaps_p
= 1;
665 /* When a window has disappeared, make sure that no rest of
666 full-width rows stays visible in the internal border. Could
667 check here if updated_window is the leftmost/rightmost window,
668 but I guess it's not worth doing since vertically split windows
669 are almost never used, internal border is rarely set, and the
670 overhead is very small. */
671 if (windows_or_buffers_changed
672 && desired_row
->full_width_p
673 && (f
= XFRAME (w
->frame
),
674 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
676 && (height
= desired_row
->visible_height
,
679 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
681 /* Internal border is drawn below the tool bar. */
682 if (WINDOWP (f
->tool_bar_window
)
683 && w
== XWINDOW (f
->tool_bar_window
))
687 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
688 0, y
, width
, height
, False
);
689 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
690 FRAME_PIXEL_WIDTH (f
) - width
,
691 y
, width
, height
, False
);
697 x_draw_fringe_bitmap (w
, row
, p
)
699 struct glyph_row
*row
;
700 struct draw_fringe_bitmap_params
*p
;
702 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
703 Display
*display
= FRAME_X_DISPLAY (f
);
704 Window window
= FRAME_X_WINDOW (f
);
705 GC gc
= f
->output_data
.x
->normal_gc
;
706 struct face
*face
= p
->face
;
709 /* Must clip because of partially visible lines. */
710 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
713 /* Adjust position of "bottom aligned" bitmap on partially
716 int oldVH
= row
->visible_height
;
717 row
->visible_height
= p
->h
;
718 row
->y
-= rowY
- p
->y
;
719 x_clip_to_row (w
, row
, -1, gc
);
721 row
->visible_height
= oldVH
;
724 x_clip_to_row (w
, row
, -1, gc
);
726 if (p
->bx
>= 0 && !p
->overlay_p
)
728 /* In case the same realized face is used for fringes and
729 for something displayed in the text (e.g. face `region' on
730 mono-displays, the fill style may have been changed to
731 FillSolid in x_draw_glyph_string_background. */
733 XSetFillStyle (display
, face
->gc
, FillOpaqueStippled
);
735 XSetForeground (display
, face
->gc
, face
->background
);
737 XFillRectangle (display
, window
, face
->gc
,
738 p
->bx
, p
->by
, p
->nx
, p
->ny
);
741 XSetForeground (display
, face
->gc
, face
->foreground
);
747 Pixmap pixmap
, clipmask
= (Pixmap
) 0;
748 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
752 bits
= (unsigned char *)(p
->bits
+ p
->dh
);
754 bits
= (unsigned char *)p
->bits
+ p
->dh
;
756 /* Draw the bitmap. I believe these small pixmaps can be cached
758 pixmap
= XCreatePixmapFromBitmapData (display
, window
, bits
, p
->wd
, p
->h
,
760 ? (p
->overlay_p
? face
->background
761 : f
->output_data
.x
->cursor_pixel
)
763 face
->background
, depth
);
767 clipmask
= XCreatePixmapFromBitmapData (display
,
768 FRAME_X_DISPLAY_INFO (f
)->root_window
,
771 gcv
.clip_mask
= clipmask
;
772 gcv
.clip_x_origin
= p
->x
;
773 gcv
.clip_y_origin
= p
->y
;
774 XChangeGC (display
, gc
, GCClipMask
| GCClipXOrigin
| GCClipYOrigin
, &gcv
);
777 XCopyArea (display
, pixmap
, window
, gc
, 0, 0,
778 p
->wd
, p
->h
, p
->x
, p
->y
);
779 XFreePixmap (display
, pixmap
);
783 gcv
.clip_mask
= (Pixmap
) 0;
784 XChangeGC (display
, gc
, GCClipMask
, &gcv
);
785 XFreePixmap (display
, clipmask
);
789 XSetClipMask (display
, gc
, None
);
794 /* This is called when starting Emacs and when restarting after
795 suspend. When starting Emacs, no X window is mapped. And nothing
796 must be done to Emacs's own window if it is suspended (though that
800 XTset_terminal_modes ()
804 /* This is called when exiting or suspending Emacs. Exiting will make
805 the X-windows go away, and suspending requires no action. */
808 XTreset_terminal_modes ()
814 /***********************************************************************
816 ***********************************************************************/
818 /* Function prototypes of this page. */
820 static int x_encode_char
P_ ((int, XChar2b
*, struct font_info
*,
821 struct charset
*, int *));
824 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
825 is not contained in the font. */
828 x_per_char_metric (font
, char2b
, font_type
)
831 int font_type
; /* unused on X */
833 /* The result metric information. */
834 XCharStruct
*pcm
= NULL
;
836 xassert (font
&& char2b
);
838 if (font
->per_char
!= NULL
)
840 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
842 /* min_char_or_byte2 specifies the linear character index
843 corresponding to the first element of the per_char array,
844 max_char_or_byte2 is the index of the last character. A
845 character with non-zero CHAR2B->byte1 is not in the font.
846 A character with byte2 less than min_char_or_byte2 or
847 greater max_char_or_byte2 is not in the font. */
848 if (char2b
->byte1
== 0
849 && char2b
->byte2
>= font
->min_char_or_byte2
850 && char2b
->byte2
<= font
->max_char_or_byte2
)
851 pcm
= font
->per_char
+ char2b
->byte2
- font
->min_char_or_byte2
;
855 /* If either min_byte1 or max_byte1 are nonzero, both
856 min_char_or_byte2 and max_char_or_byte2 are less than
857 256, and the 2-byte character index values corresponding
858 to the per_char array element N (counting from 0) are:
860 byte1 = N/D + min_byte1
861 byte2 = N\D + min_char_or_byte2
865 D = max_char_or_byte2 - min_char_or_byte2 + 1
867 \ = integer modulus */
868 if (char2b
->byte1
>= font
->min_byte1
869 && char2b
->byte1
<= font
->max_byte1
870 && char2b
->byte2
>= font
->min_char_or_byte2
871 && char2b
->byte2
<= font
->max_char_or_byte2
)
873 pcm
= (font
->per_char
874 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
875 * (char2b
->byte1
- font
->min_byte1
))
876 + (char2b
->byte2
- font
->min_char_or_byte2
));
882 /* If the per_char pointer is null, all glyphs between the first
883 and last character indexes inclusive have the same
884 information, as given by both min_bounds and max_bounds. */
885 if (char2b
->byte2
>= font
->min_char_or_byte2
886 && char2b
->byte2
<= font
->max_char_or_byte2
)
887 pcm
= &font
->max_bounds
;
891 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
896 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
897 the two-byte form of C. Encoding is returned in *CHAR2B. */
900 x_encode_char (c
, char2b
, font_info
, charset
, two_byte_p
)
903 struct font_info
*font_info
;
904 struct charset
*charset
;
907 XFontStruct
*font
= font_info
->font
;
909 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
910 This may be either a program in a special encoder language or a
912 if (font_info
->font_encoder
)
914 /* It's a program. */
915 struct ccl_program
*ccl
= font_info
->font_encoder
;
917 check_ccl_update (ccl
);
918 if (CHARSET_DIMENSION (charset
) == 1)
920 ccl
->reg
[0] = CHARSET_ID (charset
);
921 ccl
->reg
[1] = char2b
->byte2
;
926 ccl
->reg
[0] = CHARSET_ID (charset
);
927 ccl
->reg
[1] = char2b
->byte1
;
928 ccl
->reg
[2] = char2b
->byte2
;
931 ccl_driver (ccl
, NULL
, NULL
, 0, 0, Qnil
);
933 /* We assume that MSBs are appropriately set/reset by CCL
935 if (font
->max_byte1
== 0) /* 1-byte font */
936 STORE_XCHAR2B (char2b
, 0, ccl
->reg
[1]);
938 STORE_XCHAR2B (char2b
, ccl
->reg
[1], ccl
->reg
[2]);
940 else if (font_info
->encoding_type
)
942 /* Fixed encoding scheme. See fontset.h for the meaning of the
944 unsigned char enc
= font_info
->encoding_type
;
946 if ((enc
== 1 || enc
== 2)
947 && CHARSET_DIMENSION (charset
) == 2)
948 char2b
->byte1
|= 0x80;
950 if (enc
== 1 || enc
== 3)
951 char2b
->byte2
|= 0x80;
955 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
957 return FONT_TYPE_UNKNOWN
;
962 /***********************************************************************
964 ***********************************************************************/
968 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
969 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
970 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
972 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
973 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
974 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
975 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
976 static void x_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
977 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
978 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
979 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
980 static int x_alloc_lighter_color
P_ ((struct frame
*, Display
*, Colormap
,
981 unsigned long *, double, int));
982 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
983 double, int, unsigned long));
984 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
985 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
986 static void x_draw_image_relief
P_ ((struct glyph_string
*));
987 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
988 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
989 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
991 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
992 int, int, int, int, int, int,
994 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
995 int, int, int, XRectangle
*));
998 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
1002 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1007 struct glyph_string
*s
;
1009 if (s
->font
== FRAME_FONT (s
->f
)
1010 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
1011 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
1013 s
->gc
= s
->f
->output_data
.x
->cursor_gc
;
1016 /* Cursor on non-default face: must merge. */
1020 xgcv
.background
= s
->f
->output_data
.x
->cursor_pixel
;
1021 xgcv
.foreground
= s
->face
->background
;
1023 /* If the glyph would be invisible, try a different foreground. */
1024 if (xgcv
.foreground
== xgcv
.background
)
1025 xgcv
.foreground
= s
->face
->foreground
;
1026 if (xgcv
.foreground
== xgcv
.background
)
1027 xgcv
.foreground
= s
->f
->output_data
.x
->cursor_foreground_pixel
;
1028 if (xgcv
.foreground
== xgcv
.background
)
1029 xgcv
.foreground
= s
->face
->foreground
;
1031 /* Make sure the cursor is distinct from text in this face. */
1032 if (xgcv
.background
== s
->face
->background
1033 && xgcv
.foreground
== s
->face
->foreground
)
1035 xgcv
.background
= s
->face
->foreground
;
1036 xgcv
.foreground
= s
->face
->background
;
1039 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1040 xgcv
.font
= s
->font
->fid
;
1041 xgcv
.graphics_exposures
= False
;
1042 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
1044 if (FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1045 XChangeGC (s
->display
, FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1048 FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1049 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1051 s
->gc
= FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1056 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1059 x_set_mouse_face_gc (s
)
1060 struct glyph_string
*s
;
1065 /* What face has to be used last for the mouse face? */
1066 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
1067 face
= FACE_FROM_ID (s
->f
, face_id
);
1069 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
1071 if (s
->first_glyph
->type
== CHAR_GLYPH
)
1072 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
, -1, Qnil
);
1074 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0, -1, Qnil
);
1075 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
1076 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1078 /* If font in this face is same as S->font, use it. */
1079 if (s
->font
== s
->face
->font
)
1080 s
->gc
= s
->face
->gc
;
1081 #ifdef USE_FONT_BACKEND
1082 else if (enable_font_backend
)
1083 /* No need of setting a font for s->gc. */
1084 s
->gc
= s
->face
->gc
;
1085 #endif /* USE_FONT_BACKEND */
1088 /* Otherwise construct scratch_cursor_gc with values from FACE
1093 xgcv
.background
= s
->face
->background
;
1094 xgcv
.foreground
= s
->face
->foreground
;
1095 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1096 xgcv
.font
= s
->font
->fid
;
1097 xgcv
.graphics_exposures
= False
;
1098 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
1100 if (FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1101 XChangeGC (s
->display
, FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1104 FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1105 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1107 s
->gc
= FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1110 xassert (s
->gc
!= 0);
1114 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1115 Faces to use in the mode line have already been computed when the
1116 matrix was built, so there isn't much to do, here. */
1119 x_set_mode_line_face_gc (s
)
1120 struct glyph_string
*s
;
1122 s
->gc
= s
->face
->gc
;
1126 /* Set S->gc of glyph string S for drawing that glyph string. Set
1127 S->stippled_p to a non-zero value if the face of S has a stipple
1131 x_set_glyph_string_gc (s
)
1132 struct glyph_string
*s
;
1134 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1136 if (s
->hl
== DRAW_NORMAL_TEXT
)
1138 s
->gc
= s
->face
->gc
;
1139 s
->stippled_p
= s
->face
->stipple
!= 0;
1141 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
1143 x_set_mode_line_face_gc (s
);
1144 s
->stippled_p
= s
->face
->stipple
!= 0;
1146 else if (s
->hl
== DRAW_CURSOR
)
1148 x_set_cursor_gc (s
);
1151 else if (s
->hl
== DRAW_MOUSE_FACE
)
1153 x_set_mouse_face_gc (s
);
1154 s
->stippled_p
= s
->face
->stipple
!= 0;
1156 else if (s
->hl
== DRAW_IMAGE_RAISED
1157 || s
->hl
== DRAW_IMAGE_SUNKEN
)
1159 s
->gc
= s
->face
->gc
;
1160 s
->stippled_p
= s
->face
->stipple
!= 0;
1164 s
->gc
= s
->face
->gc
;
1165 s
->stippled_p
= s
->face
->stipple
!= 0;
1168 /* GC must have been set. */
1169 xassert (s
->gc
!= 0);
1173 /* Set clipping for output of glyph string S. S may be part of a mode
1174 line or menu if we don't have X toolkit support. */
1177 x_set_glyph_string_clipping (s
)
1178 struct glyph_string
*s
;
1181 get_glyph_string_clip_rect (s
, &r
);
1182 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, &r
, 1, Unsorted
);
1183 #ifdef USE_FONT_BACKEND
1184 s
->clip_x
= r
.x
, s
->clip_y
= r
.y
;
1185 s
->clip_width
= r
.width
, s
->clip_height
= r
.height
;
1186 #endif /* USE_FONT_BACKEND */
1190 /* Set SRC's clipping for output of glyph string DST. This is called
1191 when we are drawing DST's left_overhang or right_overhang only in
1195 x_set_glyph_string_clipping_exactly (src
, dst
)
1196 struct glyph_string
*src
, *dst
;
1200 #ifdef USE_FONT_BACKEND
1201 if (enable_font_backend
)
1203 r
.x
= dst
->clip_x
= src
->x
;
1204 r
.width
= dst
->clip_width
= src
->width
;
1205 r
.y
= dst
->clip_y
= src
->y
;
1206 r
.height
= dst
->clip_height
= src
->height
;
1210 #endif /* USE_FONT_BACKEND */
1211 struct glyph_string
*clip_head
= src
->clip_head
;
1212 struct glyph_string
*clip_tail
= src
->clip_tail
;
1214 /* This foces clipping just this glyph string. */
1215 src
->clip_head
= src
->clip_tail
= src
;
1216 get_glyph_string_clip_rect (src
, &r
);
1217 src
->clip_head
= clip_head
, src
->clip_tail
= clip_tail
;
1218 #ifdef USE_FONT_BACKEND
1220 #endif /* USE_FONT_BACKEND */
1221 XSetClipRectangles (dst
->display
, dst
->gc
, 0, 0, &r
, 1, Unsorted
);
1226 Compute left and right overhang of glyph string S. */
1229 x_compute_glyph_string_overhangs (s
)
1230 struct glyph_string
*s
;
1233 && s
->first_glyph
->type
== CHAR_GLYPH
)
1236 int direction
, font_ascent
, font_descent
;
1238 #ifdef USE_FONT_BACKEND
1239 if (enable_font_backend
)
1241 unsigned *code
= alloca (sizeof (unsigned) * s
->nchars
);
1242 struct font
*font
= (struct font
*) s
->font_info
;
1243 struct font_metrics metrics
;
1246 for (i
= 0; i
< s
->nchars
; i
++)
1247 code
[i
] = (s
->char2b
[i
].byte1
<< 8) | s
->char2b
[i
].byte2
;
1248 font
->driver
->text_extents (font
, code
, s
->nchars
, &metrics
);
1249 cs
.rbearing
= metrics
.rbearing
;
1250 cs
.lbearing
= metrics
.lbearing
;
1251 cs
.width
= metrics
.width
;
1254 #endif /* USE_FONT_BACKEND */
1255 XTextExtents16 (s
->font
, s
->char2b
, s
->nchars
, &direction
,
1256 &font_ascent
, &font_descent
, &cs
);
1257 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
1258 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
1262 s
->right_overhang
= s
->cmp
->rbearing
- s
->cmp
->pixel_width
;
1263 s
->left_overhang
= - s
->cmp
->lbearing
;
1268 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1271 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
1272 struct glyph_string
*s
;
1276 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
, &xgcv
);
1277 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
1278 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
1279 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
1283 /* Draw the background of glyph_string S. If S->background_filled_p
1284 is non-zero don't draw it. FORCE_P non-zero means draw the
1285 background even if it wouldn't be drawn normally. This is used
1286 when a string preceding S draws into the background of S, or S
1287 contains the first component of a composition. */
1290 x_draw_glyph_string_background (s
, force_p
)
1291 struct glyph_string
*s
;
1294 /* Nothing to do if background has already been drawn or if it
1295 shouldn't be drawn in the first place. */
1296 if (!s
->background_filled_p
)
1298 int box_line_width
= max (s
->face
->box_line_width
, 0);
1302 /* Fill background with a stipple pattern. */
1303 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
1304 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
1305 s
->y
+ box_line_width
,
1306 s
->background_width
,
1307 s
->height
- 2 * box_line_width
);
1308 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
1309 s
->background_filled_p
= 1;
1311 else if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
1312 || s
->font_not_found_p
1313 || s
->extends_to_end_of_line_p
1316 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
1317 s
->background_width
,
1318 s
->height
- 2 * box_line_width
);
1319 s
->background_filled_p
= 1;
1325 /* Draw the foreground of glyph string S. */
1328 x_draw_glyph_string_foreground (s
)
1329 struct glyph_string
*s
;
1333 /* If first glyph of S has a left box line, start drawing the text
1334 of S to the right of that box line. */
1335 if (s
->face
->box
!= FACE_NO_BOX
1336 && s
->first_glyph
->left_box_line_p
)
1337 x
= s
->x
+ abs (s
->face
->box_line_width
);
1341 /* Draw characters of S as rectangles if S's font could not be
1343 if (s
->font_not_found_p
)
1345 for (i
= 0; i
< s
->nchars
; ++i
)
1347 struct glyph
*g
= s
->first_glyph
+ i
;
1348 XDrawRectangle (s
->display
, s
->window
,
1349 s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
1351 x
+= g
->pixel_width
;
1354 #ifdef USE_FONT_BACKEND
1355 else if (enable_font_backend
)
1357 unsigned *code
= alloca (sizeof (unsigned) * s
->nchars
);
1358 int boff
= s
->font_info
->baseline_offset
;
1359 struct font
*font
= (struct font
*) s
->font_info
;
1362 for (i
= 0; i
< s
->nchars
; i
++)
1363 code
[i
] = (s
->char2b
[i
].byte1
<< 8) | s
->char2b
[i
].byte2
;
1365 if (s
->font_info
->vertical_centering
)
1366 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
1368 y
= s
->ybase
- boff
;
1370 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
1371 font
->driver
->draw (s
, 0, s
->nchars
, x
, y
, 0);
1373 font
->driver
->draw (s
, 0, s
->nchars
, x
, y
, 1);
1374 if (s
->face
->overstrike
)
1375 font
->driver
->draw (s
, 0, s
->nchars
, x
+ 1, y
, 0);
1377 #endif /* USE_FONT_BACKEND */
1380 char *char1b
= (char *) s
->char2b
;
1381 int boff
= s
->font_info
->baseline_offset
;
1383 if (s
->font_info
->vertical_centering
)
1384 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
1386 /* If we can use 8-bit functions, condense S->char2b. */
1388 for (i
= 0; i
< s
->nchars
; ++i
)
1389 char1b
[i
] = s
->char2b
[i
].byte2
;
1391 /* Draw text with XDrawString if background has already been
1392 filled. Otherwise, use XDrawImageString. (Note that
1393 XDrawImageString is usually faster than XDrawString.) Always
1394 use XDrawImageString when drawing the cursor so that there is
1395 no chance that characters under a box cursor are invisible. */
1397 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
1399 /* Draw characters with 16-bit or 8-bit functions. */
1401 XDrawString16 (s
->display
, s
->window
, s
->gc
, x
,
1402 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
1404 XDrawString (s
->display
, s
->window
, s
->gc
, x
,
1405 s
->ybase
- boff
, char1b
, s
->nchars
);
1410 XDrawImageString16 (s
->display
, s
->window
, s
->gc
, x
,
1411 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
1413 XDrawImageString (s
->display
, s
->window
, s
->gc
, x
,
1414 s
->ybase
- boff
, char1b
, s
->nchars
);
1417 if (s
->face
->overstrike
)
1419 /* For overstriking (to simulate bold-face), draw the
1420 characters again shifted to the right by one pixel. */
1422 XDrawString16 (s
->display
, s
->window
, s
->gc
, x
+ 1,
1423 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
1425 XDrawString (s
->display
, s
->window
, s
->gc
, x
+ 1,
1426 s
->ybase
- boff
, char1b
, s
->nchars
);
1431 /* Draw the foreground of composite glyph string S. */
1434 x_draw_composite_glyph_string_foreground (s
)
1435 struct glyph_string
*s
;
1439 /* If first glyph of S has a left box line, start drawing the text
1440 of S to the right of that box line. */
1441 if (s
->face
&& s
->face
->box
!= FACE_NO_BOX
1442 && s
->first_glyph
->left_box_line_p
)
1443 x
= s
->x
+ abs (s
->face
->box_line_width
);
1447 /* S is a glyph string for a composition. S->gidx is the index of
1448 the first character drawn for glyphs of this composition.
1449 S->gidx == 0 means we are drawing the very first character of
1450 this composition. */
1452 /* Draw a rectangle for the composition if the font for the very
1453 first character of the composition could not be loaded. */
1454 if (s
->font_not_found_p
)
1457 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, s
->y
,
1458 s
->width
- 1, s
->height
- 1);
1460 #ifdef USE_FONT_BACKEND
1461 else if (enable_font_backend
)
1463 struct font
*font
= (struct font
*) s
->font_info
;
1467 if (s
->cmp
->method
== COMPOSITION_WITH_GLYPH_STRING
)
1469 Lisp_Object gstring
= AREF (XHASH_TABLE (composition_hash_table
)
1471 s
->cmp
->hash_index
* 2);
1474 for (i
= from
= 0; i
< s
->nchars
; i
++)
1476 Lisp_Object g
= LGSTRING_GLYPH (gstring
, i
);
1477 Lisp_Object adjustment
= LGLYPH_ADJUSTMENT (g
);
1478 int xoff
, yoff
, wadjust
;
1480 if (! VECTORP (adjustment
))
1482 width
+= XINT (LGLYPH_WIDTH (g
));
1487 font
->driver
->draw (s
, from
, i
, x
, y
, 0);
1490 xoff
= XINT (AREF (adjustment
, 0));
1491 yoff
= XINT (AREF (adjustment
, 1));
1492 wadjust
= XINT (AREF (adjustment
, 2));
1494 font
->driver
->draw (s
, i
, i
+ 1, x
+ xoff
, y
+ yoff
, 0);
1495 x
+= XINT (LGLYPH_WIDTH (g
)) + wadjust
;
1500 font
->driver
->draw (s
, from
, i
, x
, y
, 0);
1504 for (i
= 0, j
= s
->gidx
; i
< s
->nchars
; i
++, j
++)
1505 if (COMPOSITION_GLYPH (s
->cmp
, j
) != '\t')
1507 int xx
= x
+ s
->cmp
->offsets
[j
* 2];
1508 int yy
= y
- s
->cmp
->offsets
[j
* 2 + 1];
1510 font
->driver
->draw (s
, j
, j
+ 1, xx
, yy
, 0);
1511 if (s
->face
->overstrike
)
1512 font
->driver
->draw (s
, j
, j
+ 1, xx
+ 1, yy
, 0);
1516 #endif /* USE_FONT_BACKEND */
1519 for (i
= 0, j
= s
->gidx
; i
< s
->nchars
; i
++, j
++)
1522 XDrawString16 (s
->display
, s
->window
, s
->gc
,
1523 x
+ s
->cmp
->offsets
[j
* 2],
1524 s
->ybase
- s
->cmp
->offsets
[j
* 2 + 1],
1526 if (s
->face
->overstrike
)
1527 XDrawString16 (s
->display
, s
->window
, s
->gc
,
1528 x
+ s
->cmp
->offsets
[j
* 2] + 1,
1529 s
->ybase
- s
->cmp
->offsets
[j
* 2 + 1],
1536 #ifdef USE_X_TOOLKIT
1538 static struct frame
*x_frame_of_widget
P_ ((Widget
));
1539 static Boolean cvt_string_to_pixel
P_ ((Display
*, XrmValue
*, Cardinal
*,
1540 XrmValue
*, XrmValue
*, XtPointer
*));
1541 static void cvt_pixel_dtor
P_ ((XtAppContext
, XrmValue
*, XtPointer
,
1542 XrmValue
*, Cardinal
*));
1545 /* Return the frame on which widget WIDGET is used.. Abort if frame
1546 cannot be determined. */
1548 static struct frame
*
1549 x_frame_of_widget (widget
)
1552 struct x_display_info
*dpyinfo
;
1556 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
1558 /* Find the top-level shell of the widget. Note that this function
1559 can be called when the widget is not yet realized, so XtWindow
1560 (widget) == 0. That's the reason we can't simply use
1561 x_any_window_to_frame. */
1562 while (!XtIsTopLevelShell (widget
))
1563 widget
= XtParent (widget
);
1565 /* Look for a frame with that top-level widget. Allocate the color
1566 on that frame to get the right gamma correction value. */
1567 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
1568 if (GC_FRAMEP (XCAR (tail
))
1569 && (f
= XFRAME (XCAR (tail
)),
1570 (f
->output_data
.nothing
!= 1
1571 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
1572 && f
->output_data
.x
->widget
== widget
)
1579 /* Allocate the color COLOR->pixel on the screen and display of
1580 widget WIDGET in colormap CMAP. If an exact match cannot be
1581 allocated, try the nearest color available. Value is non-zero
1582 if successful. This is called from lwlib. */
1585 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
1590 struct frame
*f
= x_frame_of_widget (widget
);
1591 return x_alloc_nearest_color (f
, cmap
, color
);
1595 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
1596 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1597 If this produces the same color as PIXEL, try a color where all RGB
1598 values have DELTA added. Return the allocated color in *PIXEL.
1599 DISPLAY is the X display, CMAP is the colormap to operate on.
1600 Value is non-zero if successful. */
1603 x_alloc_lighter_color_for_widget (widget
, display
, cmap
, pixel
, factor
, delta
)
1607 unsigned long *pixel
;
1611 struct frame
*f
= x_frame_of_widget (widget
);
1612 return x_alloc_lighter_color (f
, display
, cmap
, pixel
, factor
, delta
);
1616 /* Structure specifying which arguments should be passed by Xt to
1617 cvt_string_to_pixel. We want the widget's screen and colormap. */
1619 static XtConvertArgRec cvt_string_to_pixel_args
[] =
1621 {XtWidgetBaseOffset
, (XtPointer
) XtOffset (Widget
, core
.screen
),
1623 {XtWidgetBaseOffset
, (XtPointer
) XtOffset (Widget
, core
.colormap
),
1628 /* The address of this variable is returned by
1629 cvt_string_to_pixel. */
1631 static Pixel cvt_string_to_pixel_value
;
1634 /* Convert a color name to a pixel color.
1636 DPY is the display we are working on.
1638 ARGS is an array of *NARGS XrmValue structures holding additional
1639 information about the widget for which the conversion takes place.
1640 The contents of this array are determined by the specification
1641 in cvt_string_to_pixel_args.
1643 FROM is a pointer to an XrmValue which points to the color name to
1644 convert. TO is an XrmValue in which to return the pixel color.
1646 CLOSURE_RET is a pointer to user-data, in which we record if
1647 we allocated the color or not.
1649 Value is True if successful, False otherwise. */
1652 cvt_string_to_pixel (dpy
, args
, nargs
, from
, to
, closure_ret
)
1656 XrmValue
*from
, *to
;
1657 XtPointer
*closure_ret
;
1667 XtAppWarningMsg (XtDisplayToApplicationContext (dpy
),
1668 "wrongParameters", "cvt_string_to_pixel",
1670 "Screen and colormap args required", NULL
, NULL
);
1674 screen
= *(Screen
**) args
[0].addr
;
1675 cmap
= *(Colormap
*) args
[1].addr
;
1676 color_name
= (String
) from
->addr
;
1678 if (strcmp (color_name
, XtDefaultBackground
) == 0)
1680 *closure_ret
= (XtPointer
) False
;
1681 pixel
= WhitePixelOfScreen (screen
);
1683 else if (strcmp (color_name
, XtDefaultForeground
) == 0)
1685 *closure_ret
= (XtPointer
) False
;
1686 pixel
= BlackPixelOfScreen (screen
);
1688 else if (XParseColor (dpy
, cmap
, color_name
, &color
)
1689 && x_alloc_nearest_color_1 (dpy
, cmap
, &color
))
1691 pixel
= color
.pixel
;
1692 *closure_ret
= (XtPointer
) True
;
1697 Cardinal nparams
= 1;
1699 params
[0] = color_name
;
1700 XtAppWarningMsg (XtDisplayToApplicationContext (dpy
),
1701 "badValue", "cvt_string_to_pixel",
1702 "XtToolkitError", "Invalid color `%s'",
1707 if (to
->addr
!= NULL
)
1709 if (to
->size
< sizeof (Pixel
))
1711 to
->size
= sizeof (Pixel
);
1715 *(Pixel
*) to
->addr
= pixel
;
1719 cvt_string_to_pixel_value
= pixel
;
1720 to
->addr
= (XtPointer
) &cvt_string_to_pixel_value
;
1723 to
->size
= sizeof (Pixel
);
1728 /* Free a pixel color which was previously allocated via
1729 cvt_string_to_pixel. This is registered as the destructor
1730 for this type of resource via XtSetTypeConverter.
1732 APP is the application context in which we work.
1734 TO is a pointer to an XrmValue holding the color to free.
1735 CLOSURE is the value we stored in CLOSURE_RET for this color
1736 in cvt_string_to_pixel.
1738 ARGS and NARGS are like for cvt_string_to_pixel. */
1741 cvt_pixel_dtor (app
, to
, closure
, args
, nargs
)
1750 XtAppWarningMsg (app
, "wrongParameters", "cvt_pixel_dtor",
1752 "Screen and colormap arguments required",
1755 else if (closure
!= NULL
)
1757 /* We did allocate the pixel, so free it. */
1758 Screen
*screen
= *(Screen
**) args
[0].addr
;
1759 Colormap cmap
= *(Colormap
*) args
[1].addr
;
1760 x_free_dpy_colors (DisplayOfScreen (screen
), screen
, cmap
,
1761 (Pixel
*) to
->addr
, 1);
1766 #endif /* USE_X_TOOLKIT */
1769 /* Value is an array of XColor structures for the contents of the
1770 color map of display DPY. Set *NCELLS to the size of the array.
1771 Note that this probably shouldn't be called for large color maps,
1772 say a 24-bit TrueColor map. */
1774 static const XColor
*
1775 x_color_cells (dpy
, ncells
)
1779 struct x_display_info
*dpyinfo
= x_display_info_for_display (dpy
);
1781 if (dpyinfo
->color_cells
== NULL
)
1783 Screen
*screen
= dpyinfo
->screen
;
1786 dpyinfo
->ncolor_cells
1787 = XDisplayCells (dpy
, XScreenNumberOfScreen (screen
));
1788 dpyinfo
->color_cells
1789 = (XColor
*) xmalloc (dpyinfo
->ncolor_cells
1790 * sizeof *dpyinfo
->color_cells
);
1792 for (i
= 0; i
< dpyinfo
->ncolor_cells
; ++i
)
1793 dpyinfo
->color_cells
[i
].pixel
= i
;
1795 XQueryColors (dpy
, dpyinfo
->cmap
,
1796 dpyinfo
->color_cells
, dpyinfo
->ncolor_cells
);
1799 *ncells
= dpyinfo
->ncolor_cells
;
1800 return dpyinfo
->color_cells
;
1804 /* On frame F, translate pixel colors to RGB values for the NCOLORS
1805 colors in COLORS. Use cached information, if available. */
1808 x_query_colors (f
, colors
, ncolors
)
1813 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
1815 if (dpyinfo
->color_cells
)
1818 for (i
= 0; i
< ncolors
; ++i
)
1820 unsigned long pixel
= colors
[i
].pixel
;
1821 xassert (pixel
< dpyinfo
->ncolor_cells
);
1822 xassert (dpyinfo
->color_cells
[pixel
].pixel
== pixel
);
1823 colors
[i
] = dpyinfo
->color_cells
[pixel
];
1827 XQueryColors (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), colors
, ncolors
);
1831 /* On frame F, translate pixel color to RGB values for the color in
1832 COLOR. Use cached information, if available. */
1835 x_query_color (f
, color
)
1839 x_query_colors (f
, color
, 1);
1843 /* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP. If an
1844 exact match can't be allocated, try the nearest color available.
1845 Value is non-zero if successful. Set *COLOR to the color
1849 x_alloc_nearest_color_1 (dpy
, cmap
, color
)
1856 rc
= XAllocColor (dpy
, cmap
, color
);
1859 /* If we got to this point, the colormap is full, so we're going
1860 to try to get the next closest color. The algorithm used is
1861 a least-squares matching, which is what X uses for closest
1862 color matching with StaticColor visuals. */
1864 unsigned long nearest_delta
= ~0;
1866 const XColor
*cells
= x_color_cells (dpy
, &ncells
);
1868 for (nearest
= i
= 0; i
< ncells
; ++i
)
1870 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
1871 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
1872 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
1873 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
1875 if (delta
< nearest_delta
)
1878 nearest_delta
= delta
;
1882 color
->red
= cells
[nearest
].red
;
1883 color
->green
= cells
[nearest
].green
;
1884 color
->blue
= cells
[nearest
].blue
;
1885 rc
= XAllocColor (dpy
, cmap
, color
);
1889 /* If allocation succeeded, and the allocated pixel color is not
1890 equal to a cached pixel color recorded earlier, there was a
1891 change in the colormap, so clear the color cache. */
1892 struct x_display_info
*dpyinfo
= x_display_info_for_display (dpy
);
1893 XColor
*cached_color
;
1895 if (dpyinfo
->color_cells
1896 && (cached_color
= &dpyinfo
->color_cells
[color
->pixel
],
1897 (cached_color
->red
!= color
->red
1898 || cached_color
->blue
!= color
->blue
1899 || cached_color
->green
!= color
->green
)))
1901 xfree (dpyinfo
->color_cells
);
1902 dpyinfo
->color_cells
= NULL
;
1903 dpyinfo
->ncolor_cells
= 0;
1907 #ifdef DEBUG_X_COLORS
1909 register_color (color
->pixel
);
1910 #endif /* DEBUG_X_COLORS */
1916 /* Allocate the color COLOR->pixel on frame F, colormap CMAP. If an
1917 exact match can't be allocated, try the nearest color available.
1918 Value is non-zero if successful. Set *COLOR to the color
1922 x_alloc_nearest_color (f
, cmap
, color
)
1927 gamma_correct (f
, color
);
1928 return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f
), cmap
, color
);
1932 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
1933 It's necessary to do this instead of just using PIXEL directly to
1934 get color reference counts right. */
1937 x_copy_color (f
, pixel
)
1939 unsigned long pixel
;
1943 color
.pixel
= pixel
;
1945 x_query_color (f
, &color
);
1946 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
1948 #ifdef DEBUG_X_COLORS
1949 register_color (pixel
);
1955 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
1956 It's necessary to do this instead of just using PIXEL directly to
1957 get color reference counts right. */
1960 x_copy_dpy_color (dpy
, cmap
, pixel
)
1963 unsigned long pixel
;
1967 color
.pixel
= pixel
;
1969 XQueryColor (dpy
, cmap
, &color
);
1970 XAllocColor (dpy
, cmap
, &color
);
1972 #ifdef DEBUG_X_COLORS
1973 register_color (pixel
);
1979 /* Brightness beyond which a color won't have its highlight brightness
1982 Nominally, highlight colors for `3d' faces are calculated by
1983 brightening an object's color by a constant scale factor, but this
1984 doesn't yield good results for dark colors, so for colors who's
1985 brightness is less than this value (on a scale of 0-65535) have an
1986 use an additional additive factor.
1988 The value here is set so that the default menu-bar/mode-line color
1989 (grey75) will not have its highlights changed at all. */
1990 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
1993 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
1994 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1995 If this produces the same color as PIXEL, try a color where all RGB
1996 values have DELTA added. Return the allocated color in *PIXEL.
1997 DISPLAY is the X display, CMAP is the colormap to operate on.
1998 Value is non-zero if successful. */
2001 x_alloc_lighter_color (f
, display
, cmap
, pixel
, factor
, delta
)
2005 unsigned long *pixel
;
2013 /* Get RGB color values. */
2014 color
.pixel
= *pixel
;
2015 x_query_color (f
, &color
);
2017 /* Change RGB values by specified FACTOR. Avoid overflow! */
2018 xassert (factor
>= 0);
2019 new.red
= min (0xffff, factor
* color
.red
);
2020 new.green
= min (0xffff, factor
* color
.green
);
2021 new.blue
= min (0xffff, factor
* color
.blue
);
2023 /* Calculate brightness of COLOR. */
2024 bright
= (2 * color
.red
+ 3 * color
.green
+ color
.blue
) / 6;
2026 /* We only boost colors that are darker than
2027 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2028 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
2029 /* Make an additive adjustment to NEW, because it's dark enough so
2030 that scaling by FACTOR alone isn't enough. */
2032 /* How far below the limit this color is (0 - 1, 1 being darker). */
2033 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
2034 /* The additive adjustment. */
2035 int min_delta
= delta
* dimness
* factor
/ 2;
2039 new.red
= max (0, new.red
- min_delta
);
2040 new.green
= max (0, new.green
- min_delta
);
2041 new.blue
= max (0, new.blue
- min_delta
);
2045 new.red
= min (0xffff, min_delta
+ new.red
);
2046 new.green
= min (0xffff, min_delta
+ new.green
);
2047 new.blue
= min (0xffff, min_delta
+ new.blue
);
2051 /* Try to allocate the color. */
2052 success_p
= x_alloc_nearest_color (f
, cmap
, &new);
2055 if (new.pixel
== *pixel
)
2057 /* If we end up with the same color as before, try adding
2058 delta to the RGB values. */
2059 x_free_colors (f
, &new.pixel
, 1);
2061 new.red
= min (0xffff, delta
+ color
.red
);
2062 new.green
= min (0xffff, delta
+ color
.green
);
2063 new.blue
= min (0xffff, delta
+ color
.blue
);
2064 success_p
= x_alloc_nearest_color (f
, cmap
, &new);
2075 /* Set up the foreground color for drawing relief lines of glyph
2076 string S. RELIEF is a pointer to a struct relief containing the GC
2077 with which lines will be drawn. Use a color that is FACTOR or
2078 DELTA lighter or darker than the relief's background which is found
2079 in S->f->output_data.x->relief_background. If such a color cannot
2080 be allocated, use DEFAULT_PIXEL, instead. */
2083 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
2085 struct relief
*relief
;
2088 unsigned long default_pixel
;
2091 struct x_output
*di
= f
->output_data
.x
;
2092 unsigned long mask
= GCForeground
| GCLineWidth
| GCGraphicsExposures
;
2093 unsigned long pixel
;
2094 unsigned long background
= di
->relief_background
;
2095 Colormap cmap
= FRAME_X_COLORMAP (f
);
2096 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
2097 Display
*dpy
= FRAME_X_DISPLAY (f
);
2099 xgcv
.graphics_exposures
= False
;
2100 xgcv
.line_width
= 1;
2102 /* Free previously allocated color. The color cell will be reused
2103 when it has been freed as many times as it was allocated, so this
2104 doesn't affect faces using the same colors. */
2106 && relief
->allocated_p
)
2108 x_free_colors (f
, &relief
->pixel
, 1);
2109 relief
->allocated_p
= 0;
2112 /* Allocate new color. */
2113 xgcv
.foreground
= default_pixel
;
2115 if (dpyinfo
->n_planes
!= 1
2116 && x_alloc_lighter_color (f
, dpy
, cmap
, &pixel
, factor
, delta
))
2118 relief
->allocated_p
= 1;
2119 xgcv
.foreground
= relief
->pixel
= pixel
;
2122 if (relief
->gc
== 0)
2124 xgcv
.stipple
= dpyinfo
->gray
;
2126 relief
->gc
= XCreateGC (dpy
, FRAME_X_WINDOW (f
), mask
, &xgcv
);
2129 XChangeGC (dpy
, relief
->gc
, mask
, &xgcv
);
2133 /* Set up colors for the relief lines around glyph string S. */
2136 x_setup_relief_colors (s
)
2137 struct glyph_string
*s
;
2139 struct x_output
*di
= s
->f
->output_data
.x
;
2140 unsigned long color
;
2142 if (s
->face
->use_box_color_for_shadows_p
)
2143 color
= s
->face
->box_color
;
2144 else if (s
->first_glyph
->type
== IMAGE_GLYPH
2146 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
2147 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
2152 /* Get the background color of the face. */
2153 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
2154 color
= xgcv
.background
;
2157 if (di
->white_relief
.gc
== 0
2158 || color
!= di
->relief_background
)
2160 di
->relief_background
= color
;
2161 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
2162 WHITE_PIX_DEFAULT (s
->f
));
2163 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
2164 BLACK_PIX_DEFAULT (s
->f
));
2169 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2170 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2171 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2172 relief. LEFT_P non-zero means draw a relief on the left side of
2173 the rectangle. RIGHT_P non-zero means draw a relief on the right
2174 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2178 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
2179 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
2181 int left_x
, top_y
, right_x
, bottom_y
, width
;
2182 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
2183 XRectangle
*clip_rect
;
2185 Display
*dpy
= FRAME_X_DISPLAY (f
);
2186 Window window
= FRAME_X_WINDOW (f
);
2191 gc
= f
->output_data
.x
->white_relief
.gc
;
2193 gc
= f
->output_data
.x
->black_relief
.gc
;
2194 XSetClipRectangles (dpy
, gc
, 0, 0, clip_rect
, 1, Unsorted
);
2198 for (i
= 0; i
< width
; ++i
)
2199 XDrawLine (dpy
, window
, gc
,
2200 left_x
+ i
* left_p
, top_y
+ i
,
2201 right_x
+ 1 - i
* right_p
, top_y
+ i
);
2205 for (i
= 0; i
< width
; ++i
)
2206 XDrawLine (dpy
, window
, gc
,
2207 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
+ 1);
2209 XSetClipMask (dpy
, gc
, None
);
2211 gc
= f
->output_data
.x
->black_relief
.gc
;
2213 gc
= f
->output_data
.x
->white_relief
.gc
;
2214 XSetClipRectangles (dpy
, gc
, 0, 0, clip_rect
, 1, Unsorted
);
2218 for (i
= 0; i
< width
; ++i
)
2219 XDrawLine (dpy
, window
, gc
,
2220 left_x
+ i
* left_p
, bottom_y
- i
,
2221 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
2225 for (i
= 0; i
< width
; ++i
)
2226 XDrawLine (dpy
, window
, gc
,
2227 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
2229 XSetClipMask (dpy
, gc
, None
);
2233 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2234 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2235 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2236 left side of the rectangle. RIGHT_P non-zero means draw a line
2237 on the right side of the rectangle. CLIP_RECT is the clipping
2238 rectangle to use when drawing. */
2241 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2242 left_p
, right_p
, clip_rect
)
2243 struct glyph_string
*s
;
2244 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
2245 XRectangle
*clip_rect
;
2249 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2250 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
2251 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, clip_rect
, 1, Unsorted
);
2254 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2255 left_x
, top_y
, right_x
- left_x
+ 1, width
);
2259 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2260 left_x
, top_y
, width
, bottom_y
- top_y
+ 1);
2263 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2264 left_x
, bottom_y
- width
+ 1, right_x
- left_x
+ 1, width
);
2268 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2269 right_x
- width
+ 1, top_y
, width
, bottom_y
- top_y
+ 1);
2271 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2272 XSetClipMask (s
->display
, s
->gc
, None
);
2276 /* Draw a box around glyph string S. */
2279 x_draw_glyph_string_box (s
)
2280 struct glyph_string
*s
;
2282 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
2283 int left_p
, right_p
;
2284 struct glyph
*last_glyph
;
2285 XRectangle clip_rect
;
2287 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
2288 ? WINDOW_RIGHT_EDGE_X (s
->w
)
2289 : window_box_right (s
->w
, s
->area
));
2291 /* The glyph that may have a right box line. */
2292 last_glyph
= (s
->cmp
|| s
->img
2294 : s
->first_glyph
+ s
->nchars
- 1);
2296 width
= abs (s
->face
->box_line_width
);
2297 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
2299 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2301 : min (last_x
, s
->x
+ s
->background_width
) - 1);
2303 bottom_y
= top_y
+ s
->height
- 1;
2305 left_p
= (s
->first_glyph
->left_box_line_p
2306 || (s
->hl
== DRAW_MOUSE_FACE
2308 || s
->prev
->hl
!= s
->hl
)));
2309 right_p
= (last_glyph
->right_box_line_p
2310 || (s
->hl
== DRAW_MOUSE_FACE
2312 || s
->next
->hl
!= s
->hl
)));
2314 get_glyph_string_clip_rect (s
, &clip_rect
);
2316 if (s
->face
->box
== FACE_SIMPLE_BOX
)
2317 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2318 left_p
, right_p
, &clip_rect
);
2321 x_setup_relief_colors (s
);
2322 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
2323 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
2328 /* Draw foreground of image glyph string S. */
2331 x_draw_image_foreground (s
)
2332 struct glyph_string
*s
;
2335 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2337 /* If first glyph of S has a left box line, start drawing it to the
2338 right of that line. */
2339 if (s
->face
->box
!= FACE_NO_BOX
2340 && s
->first_glyph
->left_box_line_p
2342 x
+= abs (s
->face
->box_line_width
);
2344 /* If there is a margin around the image, adjust x- and y-position
2346 if (s
->slice
.x
== 0)
2347 x
+= s
->img
->hmargin
;
2348 if (s
->slice
.y
== 0)
2349 y
+= s
->img
->vmargin
;
2355 /* We can't set both a clip mask and use XSetClipRectangles
2356 because the latter also sets a clip mask. We also can't
2357 trust on the shape extension to be available
2358 (XShapeCombineRegion). So, compute the rectangle to draw
2360 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
2363 XRectangle clip_rect
, image_rect
, r
;
2365 xgcv
.clip_mask
= s
->img
->mask
;
2366 xgcv
.clip_x_origin
= x
;
2367 xgcv
.clip_y_origin
= y
;
2368 xgcv
.function
= GXcopy
;
2369 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
2371 get_glyph_string_clip_rect (s
, &clip_rect
);
2374 image_rect
.width
= s
->slice
.width
;
2375 image_rect
.height
= s
->slice
.height
;
2376 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
2377 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
2378 s
->slice
.x
+ r
.x
- x
, s
->slice
.y
+ r
.y
- y
,
2379 r
.width
, r
.height
, r
.x
, r
.y
);
2383 XRectangle clip_rect
, image_rect
, r
;
2385 get_glyph_string_clip_rect (s
, &clip_rect
);
2388 image_rect
.width
= s
->slice
.width
;
2389 image_rect
.height
= s
->slice
.height
;
2390 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
2391 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
2392 s
->slice
.x
+ r
.x
- x
, s
->slice
.y
+ r
.y
- y
,
2393 r
.width
, r
.height
, r
.x
, r
.y
);
2395 /* When the image has a mask, we can expect that at
2396 least part of a mouse highlight or a block cursor will
2397 be visible. If the image doesn't have a mask, make
2398 a block cursor visible by drawing a rectangle around
2399 the image. I believe it's looking better if we do
2400 nothing here for mouse-face. */
2401 if (s
->hl
== DRAW_CURSOR
)
2403 int r
= s
->img
->relief
;
2405 XDrawRectangle (s
->display
, s
->window
, s
->gc
,
2407 s
->slice
.width
+ r
*2 - 1,
2408 s
->slice
.height
+ r
*2 - 1);
2413 /* Draw a rectangle if image could not be loaded. */
2414 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
2415 s
->slice
.width
- 1, s
->slice
.height
- 1);
2419 /* Draw a relief around the image glyph string S. */
2422 x_draw_image_relief (s
)
2423 struct glyph_string
*s
;
2425 int x0
, y0
, x1
, y1
, thick
, raised_p
;
2428 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2430 /* If first glyph of S has a left box line, start drawing it to the
2431 right of that line. */
2432 if (s
->face
->box
!= FACE_NO_BOX
2433 && s
->first_glyph
->left_box_line_p
2435 x
+= abs (s
->face
->box_line_width
);
2437 /* If there is a margin around the image, adjust x- and y-position
2439 if (s
->slice
.x
== 0)
2440 x
+= s
->img
->hmargin
;
2441 if (s
->slice
.y
== 0)
2442 y
+= s
->img
->vmargin
;
2444 if (s
->hl
== DRAW_IMAGE_SUNKEN
2445 || s
->hl
== DRAW_IMAGE_RAISED
)
2447 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
2448 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
2452 thick
= abs (s
->img
->relief
);
2453 raised_p
= s
->img
->relief
> 0;
2458 x1
= x
+ s
->slice
.width
+ thick
- 1;
2459 y1
= y
+ s
->slice
.height
+ thick
- 1;
2461 x_setup_relief_colors (s
);
2462 get_glyph_string_clip_rect (s
, &r
);
2463 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
2465 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
2467 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
2472 /* Draw the foreground of image glyph string S to PIXMAP. */
2475 x_draw_image_foreground_1 (s
, pixmap
)
2476 struct glyph_string
*s
;
2480 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2482 /* If first glyph of S has a left box line, start drawing it to the
2483 right of that line. */
2484 if (s
->face
->box
!= FACE_NO_BOX
2485 && s
->first_glyph
->left_box_line_p
2487 x
+= abs (s
->face
->box_line_width
);
2489 /* If there is a margin around the image, adjust x- and y-position
2491 if (s
->slice
.x
== 0)
2492 x
+= s
->img
->hmargin
;
2493 if (s
->slice
.y
== 0)
2494 y
+= s
->img
->vmargin
;
2500 /* We can't set both a clip mask and use XSetClipRectangles
2501 because the latter also sets a clip mask. We also can't
2502 trust on the shape extension to be available
2503 (XShapeCombineRegion). So, compute the rectangle to draw
2505 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
2509 xgcv
.clip_mask
= s
->img
->mask
;
2510 xgcv
.clip_x_origin
= x
- s
->slice
.x
;
2511 xgcv
.clip_y_origin
= y
- s
->slice
.y
;
2512 xgcv
.function
= GXcopy
;
2513 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
2515 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
2516 s
->slice
.x
, s
->slice
.y
,
2517 s
->slice
.width
, s
->slice
.height
, x
, y
);
2518 XSetClipMask (s
->display
, s
->gc
, None
);
2522 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
2523 s
->slice
.x
, s
->slice
.y
,
2524 s
->slice
.width
, s
->slice
.height
, x
, y
);
2526 /* When the image has a mask, we can expect that at
2527 least part of a mouse highlight or a block cursor will
2528 be visible. If the image doesn't have a mask, make
2529 a block cursor visible by drawing a rectangle around
2530 the image. I believe it's looking better if we do
2531 nothing here for mouse-face. */
2532 if (s
->hl
== DRAW_CURSOR
)
2534 int r
= s
->img
->relief
;
2536 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
- r
, y
- r
,
2537 s
->slice
.width
+ r
*2 - 1,
2538 s
->slice
.height
+ r
*2 - 1);
2543 /* Draw a rectangle if image could not be loaded. */
2544 XDrawRectangle (s
->display
, pixmap
, s
->gc
, x
, y
,
2545 s
->slice
.width
- 1, s
->slice
.height
- 1);
2549 /* Draw part of the background of glyph string S. X, Y, W, and H
2550 give the rectangle to draw. */
2553 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
2554 struct glyph_string
*s
;
2559 /* Fill background with a stipple pattern. */
2560 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2561 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
2562 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2565 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
2569 /* Draw image glyph string S.
2572 s->x +-------------------------
2575 | +-------------------------
2578 | | +-------------------
2584 x_draw_image_glyph_string (s
)
2585 struct glyph_string
*s
;
2587 int box_line_hwidth
= abs (s
->face
->box_line_width
);
2588 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
2590 Pixmap pixmap
= None
;
2593 if (s
->slice
.y
== 0)
2594 height
-= box_line_vwidth
;
2595 if (s
->slice
.y
+ s
->slice
.height
>= s
->img
->height
)
2596 height
-= box_line_vwidth
;
2598 /* Fill background with face under the image. Do it only if row is
2599 taller than image or if image has a clip mask to reduce
2601 s
->stippled_p
= s
->face
->stipple
!= 0;
2602 if (height
> s
->slice
.height
2606 || s
->img
->pixmap
== 0
2607 || s
->width
!= s
->background_width
)
2611 /* Create a pixmap as large as the glyph string. Fill it
2612 with the background color. Copy the image to it, using
2613 its mask. Copy the temporary pixmap to the display. */
2614 Screen
*screen
= FRAME_X_SCREEN (s
->f
);
2615 int depth
= DefaultDepthOfScreen (screen
);
2617 /* Create a pixmap as large as the glyph string. */
2618 pixmap
= XCreatePixmap (s
->display
, s
->window
,
2619 s
->background_width
,
2622 /* Don't clip in the following because we're working on the
2624 XSetClipMask (s
->display
, s
->gc
, None
);
2626 /* Fill the pixmap with the background color/stipple. */
2629 /* Fill background with a stipple pattern. */
2630 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2631 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2632 0, 0, s
->background_width
, s
->height
);
2633 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2638 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
2640 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
2641 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2642 0, 0, s
->background_width
, s
->height
);
2643 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2651 if (s
->first_glyph
->left_box_line_p
2653 x
+= box_line_hwidth
;
2655 if (s
->slice
.y
== 0)
2656 y
+= box_line_vwidth
;
2658 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
2661 s
->background_filled_p
= 1;
2664 /* Draw the foreground. */
2667 x_draw_image_foreground_1 (s
, pixmap
);
2668 x_set_glyph_string_clipping (s
);
2669 XCopyArea (s
->display
, pixmap
, s
->window
, s
->gc
,
2670 0, 0, s
->background_width
, s
->height
, s
->x
, s
->y
);
2671 XFreePixmap (s
->display
, pixmap
);
2674 x_draw_image_foreground (s
);
2676 /* If we must draw a relief around the image, do it. */
2678 || s
->hl
== DRAW_IMAGE_RAISED
2679 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2680 x_draw_image_relief (s
);
2684 /* Draw stretch glyph string S. */
2687 x_draw_stretch_glyph_string (s
)
2688 struct glyph_string
*s
;
2690 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
2691 s
->stippled_p
= s
->face
->stipple
!= 0;
2693 if (s
->hl
== DRAW_CURSOR
2694 && !x_stretch_cursor_p
)
2696 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
2697 as wide as the stretch glyph. */
2698 int width
, background_width
= s
->background_width
;
2699 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
2703 background_width
-= left_x
- x
;
2706 width
= min (FRAME_COLUMN_WIDTH (s
->f
), background_width
);
2709 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, width
, s
->height
);
2711 /* Clear rest using the GC of the original non-cursor face. */
2712 if (width
< background_width
)
2715 int w
= background_width
- width
, h
= s
->height
;
2720 if (s
->row
->mouse_face_p
2721 && cursor_in_mouse_face_p (s
->w
))
2723 x_set_mouse_face_gc (s
);
2729 get_glyph_string_clip_rect (s
, &r
);
2730 XSetClipRectangles (s
->display
, gc
, 0, 0, &r
, 1, Unsorted
);
2732 if (s
->face
->stipple
)
2734 /* Fill background with a stipple pattern. */
2735 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
2736 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
2737 XSetFillStyle (s
->display
, gc
, FillSolid
);
2742 XGetGCValues (s
->display
, gc
, GCForeground
| GCBackground
, &xgcv
);
2743 XSetForeground (s
->display
, gc
, xgcv
.background
);
2744 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
2745 XSetForeground (s
->display
, gc
, xgcv
.foreground
);
2749 else if (!s
->background_filled_p
)
2751 int background_width
= s
->background_width
;
2752 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
2754 /* Don't draw into left margin, fringe or scrollbar area
2755 except for header line and mode line. */
2756 if (x
< left_x
&& !s
->row
->mode_line_p
)
2758 background_width
-= left_x
- x
;
2761 if (background_width
> 0)
2762 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, background_width
, s
->height
);
2765 s
->background_filled_p
= 1;
2769 /* Draw glyph string S. */
2772 x_draw_glyph_string (s
)
2773 struct glyph_string
*s
;
2775 int relief_drawn_p
= 0;
2777 /* If S draws into the background of its successors, draw the
2778 background of the successors first so that S can draw into it.
2779 This makes S->next use XDrawString instead of XDrawImageString. */
2780 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
)
2783 struct glyph_string
*next
;
2785 for (width
= 0, next
= s
->next
; next
;
2786 width
+= next
->width
, next
= next
->next
)
2787 if (next
->first_glyph
->type
!= IMAGE_GLYPH
)
2789 x_set_glyph_string_gc (next
);
2790 x_set_glyph_string_clipping (next
);
2791 x_draw_glyph_string_background (next
, 1);
2792 #ifdef USE_FONT_BACKEND
2793 next
->clip_width
= 0;
2794 #endif /* USE_FONT_BACKEND */
2798 /* Set up S->gc, set clipping and draw S. */
2799 x_set_glyph_string_gc (s
);
2801 /* Draw relief (if any) in advance for char/composition so that the
2802 glyph string can be drawn over it. */
2803 if (!s
->for_overlaps
2804 && s
->face
->box
!= FACE_NO_BOX
2805 && (s
->first_glyph
->type
== CHAR_GLYPH
2806 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
2809 x_set_glyph_string_clipping (s
);
2810 x_draw_glyph_string_background (s
, 1);
2811 x_draw_glyph_string_box (s
);
2812 x_set_glyph_string_clipping (s
);
2815 else if ((s
->prev
&& s
->prev
->hl
!= s
->hl
&& s
->left_overhang
)
2816 || (s
->next
&& s
->next
->hl
!= s
->hl
&& s
->right_overhang
))
2817 /* We must clip just this glyph. left_overhang part has already
2818 drawn when s->prev was drawn, and right_overhang part will be
2819 drawn later when s->next is drawn. */
2820 x_set_glyph_string_clipping_exactly (s
, s
);
2822 x_set_glyph_string_clipping (s
);
2824 switch (s
->first_glyph
->type
)
2827 x_draw_image_glyph_string (s
);
2831 x_draw_stretch_glyph_string (s
);
2835 if (s
->for_overlaps
)
2836 s
->background_filled_p
= 1;
2838 x_draw_glyph_string_background (s
, 0);
2839 x_draw_glyph_string_foreground (s
);
2842 case COMPOSITE_GLYPH
:
2843 if (s
->for_overlaps
|| s
->gidx
> 0)
2844 s
->background_filled_p
= 1;
2846 x_draw_glyph_string_background (s
, 1);
2847 x_draw_composite_glyph_string_foreground (s
);
2854 if (!s
->for_overlaps
)
2856 /* Draw underline. */
2857 if (s
->face
->underline_p
)
2859 unsigned long tem
, h
;
2862 /* Get the underline thickness. Default is 1 pixel. */
2863 #ifdef USE_FONT_BACKEND
2864 if (enable_font_backend
)
2865 /* In the future, we must use information of font. */
2868 #endif /* USE_FONT_BACKEND */
2869 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_THICKNESS
, &h
))
2872 #ifdef USE_FONT_BACKEND
2873 if (enable_font_backend
)
2876 /* In the future, we must use information of font. */
2877 y
= s
->ybase
+ (s
->face
->font
->max_bounds
.descent
+ 1) / 2;
2879 y
= s
->y
+ s
->height
- h
;
2884 y
= s
->y
+ s
->height
- h
;
2885 if (!x_underline_at_descent_line
)
2887 /* Get the underline position. This is the recommended
2888 vertical offset in pixels from the baseline to the top of
2889 the underline. This is a signed value according to the
2890 specs, and its default is
2892 ROUND ((maximum descent) / 2), with
2893 ROUND(x) = floor (x + 0.5) */
2895 if (x_use_underline_position_properties
2896 && XGetFontProperty (s
->font
, XA_UNDERLINE_POSITION
, &tem
))
2897 y
= s
->ybase
+ (long) tem
;
2898 else if (s
->face
->font
)
2899 y
= s
->ybase
+ (s
->face
->font
->max_bounds
.descent
+ 1) / 2;
2903 if (s
->face
->underline_defaulted_p
)
2904 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2905 s
->x
, y
, s
->background_width
, h
);
2909 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2910 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
2911 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2912 s
->x
, y
, s
->background_width
, h
);
2913 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2917 /* Draw overline. */
2918 if (s
->face
->overline_p
)
2920 unsigned long dy
= 0, h
= 1;
2922 if (s
->face
->overline_color_defaulted_p
)
2923 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2924 s
->background_width
, h
);
2928 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2929 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
2930 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2931 s
->background_width
, h
);
2932 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2936 /* Draw strike-through. */
2937 if (s
->face
->strike_through_p
)
2939 unsigned long h
= 1;
2940 unsigned long dy
= (s
->height
- h
) / 2;
2942 if (s
->face
->strike_through_color_defaulted_p
)
2943 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2948 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2949 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
2950 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2952 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2956 /* Draw relief if not yet drawn. */
2957 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
2958 x_draw_glyph_string_box (s
);
2962 struct glyph_string
*prev
;
2964 for (prev
= s
->prev
; prev
; prev
= prev
->prev
)
2965 if (prev
->hl
!= s
->hl
2966 && prev
->x
+ prev
->width
+ prev
->right_overhang
> s
->x
)
2968 /* As prev was drawn while clipped to its own area, we
2969 must draw the right_overhang part using s->hl now. */
2970 enum draw_glyphs_face save
= prev
->hl
;
2973 x_set_glyph_string_gc (prev
);
2974 x_set_glyph_string_clipping_exactly (s
, prev
);
2975 if (prev
->first_glyph
->type
== CHAR_GLYPH
)
2976 x_draw_glyph_string_foreground (prev
);
2978 x_draw_composite_glyph_string_foreground (prev
);
2979 XSetClipMask (prev
->display
, prev
->gc
, None
);
2981 #ifdef USE_FONT_BACKEND
2982 prev
->clip_width
= 0;
2983 #endif /* USE_FONT_BACKEND */
2989 struct glyph_string
*next
;
2991 for (next
= s
->next
; next
; next
= next
->next
)
2992 if (next
->hl
!= s
->hl
2993 && next
->x
- next
->left_overhang
< s
->x
+ s
->width
)
2995 /* As next will be drawn while clipped to its own area,
2996 we must draw the left_overhang part using s->hl now. */
2997 enum draw_glyphs_face save
= next
->hl
;
3000 x_set_glyph_string_gc (next
);
3001 x_set_glyph_string_clipping_exactly (s
, next
);
3002 if (next
->first_glyph
->type
== CHAR_GLYPH
)
3003 x_draw_glyph_string_foreground (next
);
3005 x_draw_composite_glyph_string_foreground (next
);
3006 XSetClipMask (next
->display
, next
->gc
, None
);
3008 #ifdef USE_FONT_BACKEND
3009 next
->clip_width
= 0;
3010 #endif /* USE_FONT_BACKEND */
3015 /* Reset clipping. */
3016 XSetClipMask (s
->display
, s
->gc
, None
);
3017 #ifdef USE_FONT_BACKEND
3019 #endif /* USE_FONT_BACKEND */
3022 /* Shift display to make room for inserted glyphs. */
3025 x_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
3027 int x
, y
, width
, height
, shift_by
;
3029 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
3030 f
->output_data
.x
->normal_gc
,
3031 x
, y
, width
, height
,
3035 /* Delete N glyphs at the nominal cursor position. Not implemented
3046 /* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
3047 If they are <= 0, this is probably an error. */
3050 x_clear_area (dpy
, window
, x
, y
, width
, height
, exposures
)
3057 xassert (width
> 0 && height
> 0);
3058 XClearArea (dpy
, window
, x
, y
, width
, height
, exposures
);
3062 /* Clear entire frame. If updating_frame is non-null, clear that
3063 frame. Otherwise clear the selected frame. */
3073 f
= SELECTED_FRAME ();
3075 /* Clearing the frame will erase any cursor, so mark them all as no
3077 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3078 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3079 output_cursor
.x
= -1;
3081 /* We don't set the output cursor here because there will always
3082 follow an explicit cursor_to. */
3084 XClearWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
3086 /* We have to clear the scroll bars, too. If we have changed
3087 colors or something like that, then they should be notified. */
3088 x_scroll_bar_clear (f
);
3090 XFlush (FRAME_X_DISPLAY (f
));
3097 /* Invert the middle quarter of the frame for .15 sec. */
3099 /* We use the select system call to do the waiting, so we have to make
3100 sure it's available. If it isn't, we just won't do visual bells. */
3102 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3105 /* Subtract the `struct timeval' values X and Y, storing the result in
3106 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3109 timeval_subtract (result
, x
, y
)
3110 struct timeval
*result
, x
, y
;
3112 /* Perform the carry for the later subtraction by updating y. This
3113 is safer because on some systems the tv_sec member is unsigned. */
3114 if (x
.tv_usec
< y
.tv_usec
)
3116 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
3117 y
.tv_usec
-= 1000000 * nsec
;
3121 if (x
.tv_usec
- y
.tv_usec
> 1000000)
3123 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
3124 y
.tv_usec
+= 1000000 * nsec
;
3128 /* Compute the time remaining to wait. tv_usec is certainly
3130 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
3131 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
3133 /* Return indication of whether the result should be considered
3135 return x
.tv_sec
< y
.tv_sec
;
3147 /* Create a GC that will use the GXxor function to flip foreground
3148 pixels into background pixels. */
3152 values
.function
= GXxor
;
3153 values
.foreground
= (f
->output_data
.x
->foreground_pixel
3154 ^ f
->output_data
.x
->background_pixel
);
3156 gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3157 GCFunction
| GCForeground
, &values
);
3161 /* Get the height not including a menu bar widget. */
3162 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
3163 /* Height of each line to flash. */
3164 int flash_height
= FRAME_LINE_HEIGHT (f
);
3165 /* These will be the left and right margins of the rectangles. */
3166 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
3167 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
3171 /* Don't flash the area between a scroll bar and the frame
3172 edge it is next to. */
3173 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
3175 case vertical_scroll_bar_left
:
3176 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3179 case vertical_scroll_bar_right
:
3180 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3187 width
= flash_right
- flash_left
;
3189 /* If window is tall, flash top and bottom line. */
3190 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3192 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3194 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3195 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
3196 width
, flash_height
);
3197 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3199 (height
- flash_height
3200 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3201 width
, flash_height
);
3204 /* If it is short, flash it all. */
3205 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3206 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3207 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3212 struct timeval wakeup
;
3214 EMACS_GET_TIME (wakeup
);
3216 /* Compute time to wait until, propagating carry from usecs. */
3217 wakeup
.tv_usec
+= 150000;
3218 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
3219 wakeup
.tv_usec
%= 1000000;
3221 /* Keep waiting until past the time wakeup or any input gets
3223 while (! detect_input_pending ())
3225 struct timeval current
;
3226 struct timeval timeout
;
3228 EMACS_GET_TIME (current
);
3230 /* Break if result would be negative. */
3231 if (timeval_subtract (¤t
, wakeup
, current
))
3234 /* How long `select' should wait. */
3236 timeout
.tv_usec
= 10000;
3238 /* Try to wait that long--but we might wake up sooner. */
3239 select (0, NULL
, NULL
, NULL
, &timeout
);
3243 /* If window is tall, flash top and bottom line. */
3244 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3246 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3248 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3249 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
3250 width
, flash_height
);
3251 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3253 (height
- flash_height
3254 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3255 width
, flash_height
);
3258 /* If it is short, flash it all. */
3259 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3260 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3261 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3263 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
3271 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3274 /* Make audible bell. */
3279 struct frame
*f
= SELECTED_FRAME ();
3281 if (FRAME_X_DISPLAY (f
))
3283 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3290 XBell (FRAME_X_DISPLAY (f
), 0);
3291 XFlush (FRAME_X_DISPLAY (f
));
3298 /* Specify how many text lines, from the top of the window,
3299 should be affected by insert-lines and delete-lines operations.
3300 This, and those operations, are used only within an update
3301 that is bounded by calls to x_update_begin and x_update_end. */
3304 XTset_terminal_window (n
)
3307 /* This function intentionally left blank. */
3312 /***********************************************************************
3314 ***********************************************************************/
3316 /* Perform an insert-lines or delete-lines operation, inserting N
3317 lines or deleting -N lines at vertical position VPOS. */
3320 x_ins_del_lines (vpos
, n
)
3327 /* Scroll part of the display as described by RUN. */
3330 x_scroll_run (w
, run
)
3334 struct frame
*f
= XFRAME (w
->frame
);
3335 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
3337 /* Get frame-relative bounding box of the text display area of W,
3338 without mode lines. Include in this box the left and right
3340 window_box (w
, -1, &x
, &y
, &width
, &height
);
3342 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
3343 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
3344 bottom_y
= y
+ height
;
3348 /* Scrolling up. Make sure we don't copy part of the mode
3349 line at the bottom. */
3350 if (from_y
+ run
->height
> bottom_y
)
3351 height
= bottom_y
- from_y
;
3353 height
= run
->height
;
3357 /* Scolling down. Make sure we don't copy over the mode line.
3359 if (to_y
+ run
->height
> bottom_y
)
3360 height
= bottom_y
- to_y
;
3362 height
= run
->height
;
3367 /* Cursor off. Will be switched on again in x_update_window_end. */
3371 XCopyArea (FRAME_X_DISPLAY (f
),
3372 FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
3373 f
->output_data
.x
->normal_gc
,
3383 /***********************************************************************
3385 ***********************************************************************/
3392 /* We used to only do this if Vx_no_window_manager was non-nil, but
3393 the ICCCM (section 4.1.6) says that the window's border pixmap
3394 and border pixel are window attributes which are "private to the
3395 client", so we can always change it to whatever we want. */
3397 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3398 f
->output_data
.x
->border_pixel
);
3400 x_update_cursor (f
, 1);
3404 frame_unhighlight (f
)
3407 /* We used to only do this if Vx_no_window_manager was non-nil, but
3408 the ICCCM (section 4.1.6) says that the window's border pixmap
3409 and border pixel are window attributes which are "private to the
3410 client", so we can always change it to whatever we want. */
3412 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3413 f
->output_data
.x
->border_tile
);
3415 x_update_cursor (f
, 1);
3418 /* The focus has changed. Update the frames as necessary to reflect
3419 the new situation. Note that we can't change the selected frame
3420 here, because the Lisp code we are interrupting might become confused.
3421 Each event gets marked with the frame in which it occurred, so the
3422 Lisp code can tell when the switch took place by examining the events. */
3425 x_new_focus_frame (dpyinfo
, frame
)
3426 struct x_display_info
*dpyinfo
;
3427 struct frame
*frame
;
3429 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
3431 if (frame
!= dpyinfo
->x_focus_frame
)
3433 /* Set this before calling other routines, so that they see
3434 the correct value of x_focus_frame. */
3435 dpyinfo
->x_focus_frame
= frame
;
3437 if (old_focus
&& old_focus
->auto_lower
)
3438 x_lower_frame (old_focus
);
3441 selected_frame
= frame
;
3442 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
3444 Fselect_window (selected_frame
->selected_window
, Qnil
);
3445 choose_minibuf_frame ();
3448 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
3449 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
3451 pending_autoraise_frame
= 0;
3454 x_frame_rehighlight (dpyinfo
);
3457 /* Handle FocusIn and FocusOut state changes for FRAME.
3458 If FRAME has focus and there exists more than one frame, puts
3459 a FOCUS_IN_EVENT into *BUFP. */
3462 x_focus_changed (type
, state
, dpyinfo
, frame
, bufp
)
3465 struct x_display_info
*dpyinfo
;
3466 struct frame
*frame
;
3467 struct input_event
*bufp
;
3469 if (type
== FocusIn
)
3471 if (dpyinfo
->x_focus_event_frame
!= frame
)
3473 x_new_focus_frame (dpyinfo
, frame
);
3474 dpyinfo
->x_focus_event_frame
= frame
;
3476 /* Don't stop displaying the initial startup message
3477 for a switch-frame event we don't need. */
3478 if (GC_NILP (Vterminal_frame
)
3479 && GC_CONSP (Vframe_list
)
3480 && !GC_NILP (XCDR (Vframe_list
)))
3482 bufp
->kind
= FOCUS_IN_EVENT
;
3483 XSETFRAME (bufp
->frame_or_window
, frame
);
3487 frame
->output_data
.x
->focus_state
|= state
;
3490 if (FRAME_XIC (frame
))
3491 XSetICFocus (FRAME_XIC (frame
));
3494 else if (type
== FocusOut
)
3496 frame
->output_data
.x
->focus_state
&= ~state
;
3498 if (dpyinfo
->x_focus_event_frame
== frame
)
3500 dpyinfo
->x_focus_event_frame
= 0;
3501 x_new_focus_frame (dpyinfo
, 0);
3505 if (FRAME_XIC (frame
))
3506 XUnsetICFocus (FRAME_XIC (frame
));
3511 /* The focus may have changed. Figure out if it is a real focus change,
3512 by checking both FocusIn/Out and Enter/LeaveNotify events.
3514 Returns FOCUS_IN_EVENT event in *BUFP. */
3517 x_detect_focus_change (dpyinfo
, event
, bufp
)
3518 struct x_display_info
*dpyinfo
;
3520 struct input_event
*bufp
;
3522 struct frame
*frame
;
3524 frame
= x_any_window_to_frame (dpyinfo
, event
->xany
.window
);
3528 switch (event
->type
)
3533 struct frame
*focus_frame
= dpyinfo
->x_focus_event_frame
;
3535 = focus_frame
? focus_frame
->output_data
.x
->focus_state
: 0;
3537 if (event
->xcrossing
.detail
!= NotifyInferior
3538 && event
->xcrossing
.focus
3539 && ! (focus_state
& FOCUS_EXPLICIT
))
3540 x_focus_changed ((event
->type
== EnterNotify
? FocusIn
: FocusOut
),
3542 dpyinfo
, frame
, bufp
);
3548 x_focus_changed (event
->type
,
3549 (event
->xfocus
.detail
== NotifyPointer
?
3550 FOCUS_IMPLICIT
: FOCUS_EXPLICIT
),
3551 dpyinfo
, frame
, bufp
);
3557 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3560 x_mouse_leave (dpyinfo
)
3561 struct x_display_info
*dpyinfo
;
3563 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
3566 /* The focus has changed, or we have redirected a frame's focus to
3567 another frame (this happens when a frame uses a surrogate
3568 mini-buffer frame). Shift the highlight as appropriate.
3570 The FRAME argument doesn't necessarily have anything to do with which
3571 frame is being highlighted or un-highlighted; we only use it to find
3572 the appropriate X display info. */
3575 XTframe_rehighlight (frame
)
3576 struct frame
*frame
;
3578 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
3582 x_frame_rehighlight (dpyinfo
)
3583 struct x_display_info
*dpyinfo
;
3585 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
3587 if (dpyinfo
->x_focus_frame
)
3589 dpyinfo
->x_highlight_frame
3590 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
3591 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
3592 : dpyinfo
->x_focus_frame
);
3593 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
3595 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
3596 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
3600 dpyinfo
->x_highlight_frame
= 0;
3602 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
3605 frame_unhighlight (old_highlight
);
3606 if (dpyinfo
->x_highlight_frame
)
3607 frame_highlight (dpyinfo
->x_highlight_frame
);
3613 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3615 /* Initialize mode_switch_bit and modifier_meaning. */
3617 x_find_modifier_meanings (dpyinfo
)
3618 struct x_display_info
*dpyinfo
;
3620 int min_code
, max_code
;
3623 XModifierKeymap
*mods
;
3625 dpyinfo
->meta_mod_mask
= 0;
3626 dpyinfo
->shift_lock_mask
= 0;
3627 dpyinfo
->alt_mod_mask
= 0;
3628 dpyinfo
->super_mod_mask
= 0;
3629 dpyinfo
->hyper_mod_mask
= 0;
3632 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
3634 min_code
= dpyinfo
->display
->min_keycode
;
3635 max_code
= dpyinfo
->display
->max_keycode
;
3638 syms
= XGetKeyboardMapping (dpyinfo
->display
,
3639 min_code
, max_code
- min_code
+ 1,
3641 mods
= XGetModifierMapping (dpyinfo
->display
);
3643 /* Scan the modifier table to see which modifier bits the Meta and
3644 Alt keysyms are on. */
3646 int row
, col
; /* The row and column in the modifier table. */
3647 int found_alt_or_meta
;
3649 for (row
= 3; row
< 8; row
++)
3651 found_alt_or_meta
= 0;
3652 for (col
= 0; col
< mods
->max_keypermod
; col
++)
3654 KeyCode code
= mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
3656 /* Zeroes are used for filler. Skip them. */
3660 /* Are any of this keycode's keysyms a meta key? */
3664 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
3666 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
3672 found_alt_or_meta
= 1;
3673 dpyinfo
->meta_mod_mask
|= (1 << row
);
3678 found_alt_or_meta
= 1;
3679 dpyinfo
->alt_mod_mask
|= (1 << row
);
3684 if (!found_alt_or_meta
)
3685 dpyinfo
->hyper_mod_mask
|= (1 << row
);
3686 code_col
= syms_per_code
;
3687 col
= mods
->max_keypermod
;
3692 if (!found_alt_or_meta
)
3693 dpyinfo
->super_mod_mask
|= (1 << row
);
3694 code_col
= syms_per_code
;
3695 col
= mods
->max_keypermod
;
3699 /* Ignore this if it's not on the lock modifier. */
3700 if (!found_alt_or_meta
&& ((1 << row
) == LockMask
))
3701 dpyinfo
->shift_lock_mask
= LockMask
;
3702 code_col
= syms_per_code
;
3703 col
= mods
->max_keypermod
;
3712 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3713 if (! dpyinfo
->meta_mod_mask
)
3715 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
3716 dpyinfo
->alt_mod_mask
= 0;
3719 /* If some keys are both alt and meta,
3720 make them just meta, not alt. */
3721 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
3723 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
3726 XFree ((char *) syms
);
3727 XFreeModifiermap (mods
);
3730 /* Convert between the modifier bits X uses and the modifier bits
3734 x_x_to_emacs_modifiers (dpyinfo
, state
)
3735 struct x_display_info
*dpyinfo
;
3738 EMACS_UINT mod_meta
= meta_modifier
;
3739 EMACS_UINT mod_alt
= alt_modifier
;
3740 EMACS_UINT mod_hyper
= hyper_modifier
;
3741 EMACS_UINT mod_super
= super_modifier
;
3744 tem
= Fget (Vx_alt_keysym
, Qmodifier_value
);
3745 if (! EQ (tem
, Qnil
)) mod_alt
= XUINT (tem
);
3746 tem
= Fget (Vx_meta_keysym
, Qmodifier_value
);
3747 if (! EQ (tem
, Qnil
)) mod_meta
= XUINT (tem
);
3748 tem
= Fget (Vx_hyper_keysym
, Qmodifier_value
);
3749 if (! EQ (tem
, Qnil
)) mod_hyper
= XUINT (tem
);
3750 tem
= Fget (Vx_super_keysym
, Qmodifier_value
);
3751 if (! EQ (tem
, Qnil
)) mod_super
= XUINT (tem
);
3754 return ( ((state
& (ShiftMask
| dpyinfo
->shift_lock_mask
)) ? shift_modifier
: 0)
3755 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
3756 | ((state
& dpyinfo
->meta_mod_mask
) ? mod_meta
: 0)
3757 | ((state
& dpyinfo
->alt_mod_mask
) ? mod_alt
: 0)
3758 | ((state
& dpyinfo
->super_mod_mask
) ? mod_super
: 0)
3759 | ((state
& dpyinfo
->hyper_mod_mask
) ? mod_hyper
: 0));
3763 x_emacs_to_x_modifiers (dpyinfo
, state
)
3764 struct x_display_info
*dpyinfo
;
3767 EMACS_UINT mod_meta
= meta_modifier
;
3768 EMACS_UINT mod_alt
= alt_modifier
;
3769 EMACS_UINT mod_hyper
= hyper_modifier
;
3770 EMACS_UINT mod_super
= super_modifier
;
3774 tem
= Fget (Vx_alt_keysym
, Qmodifier_value
);
3775 if (! EQ (tem
, Qnil
)) mod_alt
= XUINT (tem
);
3776 tem
= Fget (Vx_meta_keysym
, Qmodifier_value
);
3777 if (! EQ (tem
, Qnil
)) mod_meta
= XUINT (tem
);
3778 tem
= Fget (Vx_hyper_keysym
, Qmodifier_value
);
3779 if (! EQ (tem
, Qnil
)) mod_hyper
= XUINT (tem
);
3780 tem
= Fget (Vx_super_keysym
, Qmodifier_value
);
3781 if (! EQ (tem
, Qnil
)) mod_super
= XUINT (tem
);
3784 return ( ((state
& mod_alt
) ? dpyinfo
->alt_mod_mask
: 0)
3785 | ((state
& mod_super
) ? dpyinfo
->super_mod_mask
: 0)
3786 | ((state
& mod_hyper
) ? dpyinfo
->hyper_mod_mask
: 0)
3787 | ((state
& shift_modifier
) ? ShiftMask
: 0)
3788 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
3789 | ((state
& mod_meta
) ? dpyinfo
->meta_mod_mask
: 0));
3792 /* Convert a keysym to its name. */
3795 x_get_keysym_name (keysym
)
3801 value
= XKeysymToString (keysym
);
3809 /* Mouse clicks and mouse movement. Rah. */
3811 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3813 If the event is a button press, then note that we have grabbed
3817 construct_mouse_click (result
, event
, f
)
3818 struct input_event
*result
;
3819 XButtonEvent
*event
;
3822 /* Make the event type NO_EVENT; we'll change that when we decide
3824 result
->kind
= MOUSE_CLICK_EVENT
;
3825 result
->code
= event
->button
- Button1
;
3826 result
->timestamp
= event
->time
;
3827 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
3829 | (event
->type
== ButtonRelease
3833 XSETINT (result
->x
, event
->x
);
3834 XSETINT (result
->y
, event
->y
);
3835 XSETFRAME (result
->frame_or_window
, f
);
3841 /* Function to report a mouse movement to the mainstream Emacs code.
3842 The input handler calls this.
3844 We have received a mouse movement event, which is given in *event.
3845 If the mouse is over a different glyph than it was last time, tell
3846 the mainstream emacs code by setting mouse_moved. If not, ask for
3847 another motion event, so we can check again the next time it moves. */
3849 static XMotionEvent last_mouse_motion_event
;
3850 static Lisp_Object last_mouse_motion_frame
;
3853 note_mouse_movement (frame
, event
)
3855 XMotionEvent
*event
;
3857 last_mouse_movement_time
= event
->time
;
3858 last_mouse_motion_event
= *event
;
3859 XSETFRAME (last_mouse_motion_frame
, frame
);
3861 if (!FRAME_X_OUTPUT (frame
))
3864 if (event
->window
!= FRAME_X_WINDOW (frame
))
3866 frame
->mouse_moved
= 1;
3867 last_mouse_scroll_bar
= Qnil
;
3868 note_mouse_highlight (frame
, -1, -1);
3869 last_mouse_glyph_frame
= 0;
3874 /* Has the mouse moved off the glyph it was on at the last sighting? */
3875 if (frame
!= last_mouse_glyph_frame
3876 || event
->x
< last_mouse_glyph
.x
3877 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
3878 || event
->y
< last_mouse_glyph
.y
3879 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
3881 frame
->mouse_moved
= 1;
3882 last_mouse_scroll_bar
= Qnil
;
3883 note_mouse_highlight (frame
, event
->x
, event
->y
);
3884 /* Remember which glyph we're now on. */
3885 remember_mouse_glyph (frame
, event
->x
, event
->y
, &last_mouse_glyph
);
3886 last_mouse_glyph_frame
= frame
;
3894 /************************************************************************
3896 ************************************************************************/
3899 redo_mouse_highlight ()
3901 if (!NILP (last_mouse_motion_frame
)
3902 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
3903 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
3904 last_mouse_motion_event
.x
,
3905 last_mouse_motion_event
.y
);
3910 /* Return the current position of the mouse.
3911 *FP should be a frame which indicates which display to ask about.
3913 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
3914 and *PART to the frame, window, and scroll bar part that the mouse
3915 is over. Set *X and *Y to the portion and whole of the mouse's
3916 position on the scroll bar.
3918 If the mouse movement started elsewhere, set *FP to the frame the
3919 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
3922 Set *TIME to the server time-stamp for the time at which the mouse
3923 was at this position.
3925 Don't store anything if we don't have a valid set of values to report.
3927 This clears the mouse_moved flag, so we can wait for the next mouse
3931 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
3934 Lisp_Object
*bar_window
;
3935 enum scroll_bar_part
*part
;
3937 unsigned long *time
;
3943 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
3944 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
3950 Window dummy_window
;
3953 Lisp_Object frame
, tail
;
3955 /* Clear the mouse-moved flag for every frame on this display. */
3956 FOR_EACH_FRAME (tail
, frame
)
3957 if (FRAME_X_DISPLAY (XFRAME (frame
)) == FRAME_X_DISPLAY (*fp
))
3958 XFRAME (frame
)->mouse_moved
= 0;
3960 last_mouse_scroll_bar
= Qnil
;
3962 /* Figure out which root window we're on. */
3963 XQueryPointer (FRAME_X_DISPLAY (*fp
),
3964 DefaultRootWindow (FRAME_X_DISPLAY (*fp
)),
3966 /* The root window which contains the pointer. */
3969 /* Trash which we can't trust if the pointer is on
3970 a different screen. */
3973 /* The position on that root window. */
3976 /* More trash we can't trust. */
3979 /* Modifier keys and pointer buttons, about which
3981 (unsigned int *) &dummy
);
3983 /* Now we have a position on the root; find the innermost window
3984 containing the pointer. */
3988 int parent_x
= 0, parent_y
= 0;
3992 /* XTranslateCoordinates can get errors if the window
3993 structure is changing at the same time this function
3994 is running. So at least we must not crash from them. */
3996 x_catch_errors (FRAME_X_DISPLAY (*fp
));
3998 if (FRAME_X_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
3999 && FRAME_LIVE_P (last_mouse_frame
))
4001 /* If mouse was grabbed on a frame, give coords for that frame
4002 even if the mouse is now outside it. */
4003 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
4005 /* From-window, to-window. */
4006 root
, FRAME_X_WINDOW (last_mouse_frame
),
4008 /* From-position, to-position. */
4009 root_x
, root_y
, &win_x
, &win_y
,
4013 f1
= last_mouse_frame
;
4019 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
4021 /* From-window, to-window. */
4024 /* From-position, to-position. */
4025 root_x
, root_y
, &win_x
, &win_y
,
4030 if (child
== None
|| child
== win
)
4038 /* Now we know that:
4039 win is the innermost window containing the pointer
4040 (XTC says it has no child containing the pointer),
4041 win_x and win_y are the pointer's position in it
4042 (XTC did this the last time through), and
4043 parent_x and parent_y are the pointer's position in win's parent.
4044 (They are what win_x and win_y were when win was child.
4045 If win is the root window, it has no parent, and
4046 parent_{x,y} are invalid, but that's okay, because we'll
4047 never use them in that case.) */
4049 /* Is win one of our frames? */
4050 f1
= x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp
), win
);
4052 #ifdef USE_X_TOOLKIT
4053 /* If we end up with the menu bar window, say it's not
4056 && f1
->output_data
.x
->menubar_widget
4057 && win
== XtWindow (f1
->output_data
.x
->menubar_widget
))
4059 #endif /* USE_X_TOOLKIT */
4062 if (x_had_errors_p (FRAME_X_DISPLAY (*fp
)))
4065 x_uncatch_errors ();
4067 /* If not, is it one of our scroll bars? */
4070 struct scroll_bar
*bar
;
4072 bar
= x_window_to_scroll_bar (FRAME_X_DISPLAY (*fp
), win
);
4076 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4082 if (f1
== 0 && insist
> 0)
4083 f1
= SELECTED_FRAME ();
4087 /* Ok, we found a frame. Store all the values.
4088 last_mouse_glyph is a rectangle used to reduce the
4089 generation of mouse events. To not miss any motion
4090 events, we must divide the frame into rectangles of the
4091 size of the smallest character that could be displayed
4092 on it, i.e. into the same rectangles that matrices on
4093 the frame are divided into. */
4095 remember_mouse_glyph (f1
, win_x
, win_y
, &last_mouse_glyph
);
4096 last_mouse_glyph_frame
= f1
;
4101 XSETINT (*x
, win_x
);
4102 XSETINT (*y
, win_y
);
4103 *time
= last_mouse_movement_time
;
4113 /***********************************************************************
4115 ***********************************************************************/
4117 /* Scroll bar support. */
4119 /* Given an X window ID and a DISPLAY, find the struct scroll_bar which
4121 This can be called in GC, so we have to make sure to strip off mark
4124 static struct scroll_bar
*
4125 x_window_to_scroll_bar (display
, window_id
)
4131 #if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
4132 window_id
= (Window
) xg_get_scroll_id_for_window (display
, window_id
);
4133 #endif /* USE_GTK && USE_TOOLKIT_SCROLL_BARS */
4135 for (tail
= Vframe_list
;
4136 XGCTYPE (tail
) == Lisp_Cons
;
4139 Lisp_Object frame
, bar
, condemned
;
4141 frame
= XCAR (tail
);
4142 /* All elements of Vframe_list should be frames. */
4143 if (! GC_FRAMEP (frame
))
4146 /* Scan this frame's scroll bar list for a scroll bar with the
4148 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
4149 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
4150 /* This trick allows us to search both the ordinary and
4151 condemned scroll bar lists with one loop. */
4152 ! GC_NILP (bar
) || (bar
= condemned
,
4155 bar
= XSCROLL_BAR (bar
)->next
)
4156 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
&&
4157 FRAME_X_DISPLAY (XFRAME (frame
)) == display
)
4158 return XSCROLL_BAR (bar
);
4165 #if defined USE_LUCID
4167 /* Return the Lucid menu bar WINDOW is part of. Return null
4168 if WINDOW is not part of a menu bar. */
4171 x_window_to_menu_bar (window
)
4176 for (tail
= Vframe_list
;
4177 XGCTYPE (tail
) == Lisp_Cons
;
4180 Lisp_Object frame
= XCAR (tail
);
4181 Widget menu_bar
= XFRAME (frame
)->output_data
.x
->menubar_widget
;
4183 if (menu_bar
&& xlwmenu_window_p (menu_bar
, window
))
4190 #endif /* USE_LUCID */
4193 /************************************************************************
4195 ************************************************************************/
4197 #ifdef USE_TOOLKIT_SCROLL_BARS
4199 static void x_scroll_bar_to_input_event
P_ ((XEvent
*, struct input_event
*));
4200 static void x_send_scroll_bar_event
P_ ((Lisp_Object
, int, int, int));
4201 static void x_create_toolkit_scroll_bar
P_ ((struct frame
*,
4202 struct scroll_bar
*));
4203 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4207 /* Lisp window being scrolled. Set when starting to interact with
4208 a toolkit scroll bar, reset to nil when ending the interaction. */
4210 static Lisp_Object window_being_scrolled
;
4212 /* Last scroll bar part sent in xm_scroll_callback. */
4214 static int last_scroll_bar_part
;
4216 /* Whether this is an Xaw with arrow-scrollbars. This should imply
4217 that movements of 1/20 of the screen size are mapped to up/down. */
4220 /* Id of action hook installed for scroll bars. */
4222 static XtActionHookId action_hook_id
;
4224 static Boolean xaw3d_arrow_scroll
;
4226 /* Whether the drag scrolling maintains the mouse at the top of the
4227 thumb. If not, resizing the thumb needs to be done more carefully
4228 to avoid jerkyness. */
4230 static Boolean xaw3d_pick_top
;
4232 /* Action hook installed via XtAppAddActionHook when toolkit scroll
4233 bars are used.. The hook is responsible for detecting when
4234 the user ends an interaction with the scroll bar, and generates
4235 a `end-scroll' SCROLL_BAR_CLICK_EVENT' event if so. */
4238 xt_action_hook (widget
, client_data
, action_name
, event
, params
,
4241 XtPointer client_data
;
4245 Cardinal
*num_params
;
4251 scroll_bar_p
= XmIsScrollBar (widget
);
4252 end_action
= "Release";
4253 #else /* !USE_MOTIF i.e. use Xaw */
4254 scroll_bar_p
= XtIsSubclass (widget
, scrollbarWidgetClass
);
4255 end_action
= "EndScroll";
4256 #endif /* USE_MOTIF */
4259 && strcmp (action_name
, end_action
) == 0
4260 && WINDOWP (window_being_scrolled
))
4264 x_send_scroll_bar_event (window_being_scrolled
,
4265 scroll_bar_end_scroll
, 0, 0);
4266 w
= XWINDOW (window_being_scrolled
);
4268 if (!NILP (XSCROLL_BAR (w
->vertical_scroll_bar
)->dragging
))
4270 XSCROLL_BAR (w
->vertical_scroll_bar
)->dragging
= Qnil
;
4271 /* The thumb size is incorrect while dragging: fix it. */
4272 set_vertical_scroll_bar (w
);
4274 window_being_scrolled
= Qnil
;
4275 last_scroll_bar_part
= -1;
4277 /* Xt timeouts no longer needed. */
4278 toolkit_scroll_bar_interaction
= 0;
4281 #endif /* not USE_GTK */
4283 /* A vector of windows used for communication between
4284 x_send_scroll_bar_event and x_scroll_bar_to_input_event. */
4286 static struct window
**scroll_bar_windows
;
4287 static int scroll_bar_windows_size
;
4290 /* Send a client message with message type Xatom_Scrollbar for a
4291 scroll action to the frame of WINDOW. PART is a value identifying
4292 the part of the scroll bar that was clicked on. PORTION is the
4293 amount to scroll of a whole of WHOLE. */
4296 x_send_scroll_bar_event (window
, part
, portion
, whole
)
4298 int part
, portion
, whole
;
4301 XClientMessageEvent
*ev
= (XClientMessageEvent
*) &event
;
4302 struct window
*w
= XWINDOW (window
);
4303 struct frame
*f
= XFRAME (w
->frame
);
4308 /* Construct a ClientMessage event to send to the frame. */
4309 ev
->type
= ClientMessage
;
4310 ev
->message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_Scrollbar
;
4311 ev
->display
= FRAME_X_DISPLAY (f
);
4312 ev
->window
= FRAME_X_WINDOW (f
);
4315 /* We can only transfer 32 bits in the XClientMessageEvent, which is
4316 not enough to store a pointer or Lisp_Object on a 64 bit system.
4317 So, store the window in scroll_bar_windows and pass the index
4318 into that array in the event. */
4319 for (i
= 0; i
< scroll_bar_windows_size
; ++i
)
4320 if (scroll_bar_windows
[i
] == NULL
)
4323 if (i
== scroll_bar_windows_size
)
4325 int new_size
= max (10, 2 * scroll_bar_windows_size
);
4326 size_t nbytes
= new_size
* sizeof *scroll_bar_windows
;
4327 size_t old_nbytes
= scroll_bar_windows_size
* sizeof *scroll_bar_windows
;
4329 scroll_bar_windows
= (struct window
**) xrealloc (scroll_bar_windows
,
4331 bzero (&scroll_bar_windows
[i
], nbytes
- old_nbytes
);
4332 scroll_bar_windows_size
= new_size
;
4335 scroll_bar_windows
[i
] = w
;
4336 ev
->data
.l
[0] = (long) i
;
4337 ev
->data
.l
[1] = (long) part
;
4338 ev
->data
.l
[2] = (long) 0;
4339 ev
->data
.l
[3] = (long) portion
;
4340 ev
->data
.l
[4] = (long) whole
;
4342 /* Make Xt timeouts work while the scroll bar is active. */
4343 toolkit_scroll_bar_interaction
= 1;
4344 #ifdef USE_X_TOOLKIT
4345 x_activate_timeout_atimer ();
4348 /* Setting the event mask to zero means that the message will
4349 be sent to the client that created the window, and if that
4350 window no longer exists, no event will be sent. */
4351 XSendEvent (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), False
, 0, &event
);
4356 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
4360 x_scroll_bar_to_input_event (event
, ievent
)
4362 struct input_event
*ievent
;
4364 XClientMessageEvent
*ev
= (XClientMessageEvent
*) event
;
4369 w
= scroll_bar_windows
[ev
->data
.l
[0]];
4370 scroll_bar_windows
[ev
->data
.l
[0]] = NULL
;
4372 XSETWINDOW (window
, w
);
4373 f
= XFRAME (w
->frame
);
4375 ievent
->kind
= SCROLL_BAR_CLICK_EVENT
;
4376 ievent
->frame_or_window
= window
;
4379 ievent
->timestamp
= CurrentTime
;
4381 ievent
->timestamp
= XtLastTimestampProcessed (FRAME_X_DISPLAY (f
));
4383 ievent
->part
= ev
->data
.l
[1];
4384 ievent
->code
= ev
->data
.l
[2];
4385 ievent
->x
= make_number ((int) ev
->data
.l
[3]);
4386 ievent
->y
= make_number ((int) ev
->data
.l
[4]);
4387 ievent
->modifiers
= 0;
4393 /* Minimum and maximum values used for Motif scroll bars. */
4395 #define XM_SB_MAX 10000000
4398 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
4399 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
4400 CALL_DATA is a pointer to a XmScrollBarCallbackStruct. */
4403 xm_scroll_callback (widget
, client_data
, call_data
)
4405 XtPointer client_data
, call_data
;
4407 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
4408 XmScrollBarCallbackStruct
*cs
= (XmScrollBarCallbackStruct
*) call_data
;
4409 int part
= -1, whole
= 0, portion
= 0;
4413 case XmCR_DECREMENT
:
4414 bar
->dragging
= Qnil
;
4415 part
= scroll_bar_up_arrow
;
4418 case XmCR_INCREMENT
:
4419 bar
->dragging
= Qnil
;
4420 part
= scroll_bar_down_arrow
;
4423 case XmCR_PAGE_DECREMENT
:
4424 bar
->dragging
= Qnil
;
4425 part
= scroll_bar_above_handle
;
4428 case XmCR_PAGE_INCREMENT
:
4429 bar
->dragging
= Qnil
;
4430 part
= scroll_bar_below_handle
;
4434 bar
->dragging
= Qnil
;
4435 part
= scroll_bar_to_top
;
4438 case XmCR_TO_BOTTOM
:
4439 bar
->dragging
= Qnil
;
4440 part
= scroll_bar_to_bottom
;
4447 /* Get the slider size. */
4449 XtVaGetValues (widget
, XmNsliderSize
, &slider_size
, NULL
);
4452 whole
= XM_SB_MAX
- slider_size
;
4453 portion
= min (cs
->value
, whole
);
4454 part
= scroll_bar_handle
;
4455 bar
->dragging
= make_number (cs
->value
);
4459 case XmCR_VALUE_CHANGED
:
4465 window_being_scrolled
= bar
->window
;
4466 last_scroll_bar_part
= part
;
4467 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
4472 #else /* !USE_MOTIF, i.e. Xaw or GTK */
4474 /* Scroll bar callback for GTK scroll bars. WIDGET is the scroll
4475 bar widget. DATA is a pointer to the scroll_bar structure. */
4478 xg_scroll_callback (widget
, data
)
4482 struct scroll_bar
*bar
= (struct scroll_bar
*) data
;
4488 int part
= -1, whole
= 0, portion
= 0;
4489 GtkAdjustment
*adj
= GTK_ADJUSTMENT (gtk_range_get_adjustment (widget
));
4491 position
= gtk_adjustment_get_value (adj
);
4493 p
= g_object_get_data (G_OBJECT (widget
), XG_LAST_SB_DATA
);
4496 p
= (gdouble
*) xmalloc (sizeof (gdouble
));
4498 g_object_set_data (G_OBJECT (widget
), XG_LAST_SB_DATA
, p
);
4504 if (xg_ignore_gtk_scrollbar
) return;
4506 diff
= (int) (position
- previous
);
4508 if (diff
== (int) adj
->step_increment
)
4510 part
= scroll_bar_down_arrow
;
4511 bar
->dragging
= Qnil
;
4513 else if (-diff
== (int) adj
->step_increment
)
4515 part
= scroll_bar_up_arrow
;
4516 bar
->dragging
= Qnil
;
4518 else if (diff
== (int) adj
->page_increment
)
4520 part
= scroll_bar_below_handle
;
4521 bar
->dragging
= Qnil
;
4523 else if (-diff
== (int) adj
->page_increment
)
4525 part
= scroll_bar_above_handle
;
4526 bar
->dragging
= Qnil
;
4530 part
= scroll_bar_handle
;
4531 whole
= adj
->upper
- adj
->page_size
;
4532 portion
= min ((int)position
, whole
);
4533 bar
->dragging
= make_number ((int)portion
);
4538 window_being_scrolled
= bar
->window
;
4539 last_scroll_bar_part
= part
;
4540 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
4544 #else /* not USE_GTK */
4546 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
4547 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
4548 scroll bar struct. CALL_DATA is a pointer to a float saying where
4552 xaw_jump_callback (widget
, client_data
, call_data
)
4554 XtPointer client_data
, call_data
;
4556 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
4557 float top
= *(float *) call_data
;
4559 int whole
, portion
, height
;
4562 /* Get the size of the thumb, a value between 0 and 1. */
4564 XtVaGetValues (widget
, XtNshown
, &shown
, XtNheight
, &height
, NULL
);
4568 portion
= shown
< 1 ? top
* whole
: 0;
4570 if (shown
< 1 && (abs (top
+ shown
- 1) < 1.0/height
))
4571 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
4572 the bottom, so we force the scrolling whenever we see that we're
4573 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
4574 we try to ensure that we always stay two pixels away from the
4576 part
= scroll_bar_down_arrow
;
4578 part
= scroll_bar_handle
;
4580 window_being_scrolled
= bar
->window
;
4581 bar
->dragging
= make_number (portion
);
4582 last_scroll_bar_part
= part
;
4583 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
4587 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
4588 i.e. line or page up or down. WIDGET is the Xaw scroll bar
4589 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
4590 the scroll bar. CALL_DATA is an integer specifying the action that
4591 has taken place. Its magnitude is in the range 0..height of the
4592 scroll bar. Negative values mean scroll towards buffer start.
4593 Values < height of scroll bar mean line-wise movement. */
4596 xaw_scroll_callback (widget
, client_data
, call_data
)
4598 XtPointer client_data
, call_data
;
4600 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
4601 /* The position really is stored cast to a pointer. */
4602 int position
= (long) call_data
;
4606 /* Get the height of the scroll bar. */
4608 XtVaGetValues (widget
, XtNheight
, &height
, NULL
);
4611 if (abs (position
) >= height
)
4612 part
= (position
< 0) ? scroll_bar_above_handle
: scroll_bar_below_handle
;
4614 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
4615 it maps line-movement to call_data = max(5, height/20). */
4616 else if (xaw3d_arrow_scroll
&& abs (position
) <= max (5, height
/ 20))
4617 part
= (position
< 0) ? scroll_bar_up_arrow
: scroll_bar_down_arrow
;
4619 part
= scroll_bar_move_ratio
;
4621 window_being_scrolled
= bar
->window
;
4622 bar
->dragging
= Qnil
;
4623 last_scroll_bar_part
= part
;
4624 x_send_scroll_bar_event (bar
->window
, part
, position
, height
);
4627 #endif /* not USE_GTK */
4628 #endif /* not USE_MOTIF */
4630 #define SCROLL_BAR_NAME "verticalScrollBar"
4632 /* Create the widget for scroll bar BAR on frame F. Record the widget
4633 and X window of the scroll bar in BAR. */
4637 x_create_toolkit_scroll_bar (f
, bar
)
4639 struct scroll_bar
*bar
;
4641 char *scroll_bar_name
= SCROLL_BAR_NAME
;
4644 xg_create_scroll_bar (f
, bar
, G_CALLBACK (xg_scroll_callback
),
4649 #else /* not USE_GTK */
4652 x_create_toolkit_scroll_bar (f
, bar
)
4654 struct scroll_bar
*bar
;
4660 char *scroll_bar_name
= SCROLL_BAR_NAME
;
4661 unsigned long pixel
;
4666 /* Set resources. Create the widget. */
4667 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
4668 XtSetArg (av
[ac
], XmNminimum
, 0); ++ac
;
4669 XtSetArg (av
[ac
], XmNmaximum
, XM_SB_MAX
); ++ac
;
4670 XtSetArg (av
[ac
], XmNorientation
, XmVERTICAL
); ++ac
;
4671 XtSetArg (av
[ac
], XmNprocessingDirection
, XmMAX_ON_BOTTOM
), ++ac
;
4672 XtSetArg (av
[ac
], XmNincrement
, 1); ++ac
;
4673 XtSetArg (av
[ac
], XmNpageIncrement
, 1); ++ac
;
4675 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
4678 XtSetArg (av
[ac
], XmNforeground
, pixel
);
4682 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4685 XtSetArg (av
[ac
], XmNbackground
, pixel
);
4689 widget
= XmCreateScrollBar (f
->output_data
.x
->edit_widget
,
4690 scroll_bar_name
, av
, ac
);
4692 /* Add one callback for everything that can happen. */
4693 XtAddCallback (widget
, XmNdecrementCallback
, xm_scroll_callback
,
4695 XtAddCallback (widget
, XmNdragCallback
, xm_scroll_callback
,
4697 XtAddCallback (widget
, XmNincrementCallback
, xm_scroll_callback
,
4699 XtAddCallback (widget
, XmNpageDecrementCallback
, xm_scroll_callback
,
4701 XtAddCallback (widget
, XmNpageIncrementCallback
, xm_scroll_callback
,
4703 XtAddCallback (widget
, XmNtoBottomCallback
, xm_scroll_callback
,
4705 XtAddCallback (widget
, XmNtoTopCallback
, xm_scroll_callback
,
4708 /* Realize the widget. Only after that is the X window created. */
4709 XtRealizeWidget (widget
);
4711 /* Set the cursor to an arrow. I didn't find a resource to do that.
4712 And I'm wondering why it hasn't an arrow cursor by default. */
4713 XDefineCursor (XtDisplay (widget
), XtWindow (widget
),
4714 f
->output_data
.x
->nontext_cursor
);
4716 #else /* !USE_MOTIF i.e. use Xaw */
4718 /* Set resources. Create the widget. The background of the
4719 Xaw3d scroll bar widget is a little bit light for my taste.
4720 We don't alter it here to let users change it according
4721 to their taste with `emacs*verticalScrollBar.background: xxx'. */
4722 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
4723 XtSetArg (av
[ac
], XtNorientation
, XtorientVertical
); ++ac
;
4724 /* For smoother scrolling with Xaw3d -sm */
4725 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
4727 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
4730 XtSetArg (av
[ac
], XtNforeground
, pixel
);
4734 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4737 XtSetArg (av
[ac
], XtNbackground
, pixel
);
4741 /* Top/bottom shadow colors. */
4743 /* Allocate them, if necessary. */
4744 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
== -1)
4746 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4747 if (!x_alloc_lighter_color (f
, FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
4748 &pixel
, 1.2, 0x8000))
4750 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= pixel
;
4752 if (f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
== -1)
4754 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4755 if (!x_alloc_lighter_color (f
, FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
4756 &pixel
, 0.6, 0x4000))
4758 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= pixel
;
4761 #ifdef XtNbeNiceToColormap
4762 /* Tell the toolkit about them. */
4763 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
== -1
4764 || f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
== -1)
4765 /* We tried to allocate a color for the top/bottom shadow, and
4766 failed, so tell Xaw3d to use dithering instead. */
4768 XtSetArg (av
[ac
], XtNbeNiceToColormap
, True
);
4772 /* Tell what colors Xaw3d should use for the top/bottom shadow, to
4773 be more consistent with other emacs 3d colors, and since Xaw3d is
4774 not good at dealing with allocation failure. */
4776 /* This tells Xaw3d to use real colors instead of dithering for
4778 XtSetArg (av
[ac
], XtNbeNiceToColormap
, False
);
4781 /* Specify the colors. */
4782 pixel
= f
->output_data
.x
->scroll_bar_top_shadow_pixel
;
4785 XtSetArg (av
[ac
], XtNtopShadowPixel
, pixel
);
4788 pixel
= f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
;
4791 XtSetArg (av
[ac
], XtNbottomShadowPixel
, pixel
);
4797 widget
= XtCreateWidget (scroll_bar_name
, scrollbarWidgetClass
,
4798 f
->output_data
.x
->edit_widget
, av
, ac
);
4802 char *val
= initial
;
4803 XtVaGetValues (widget
, XtNscrollVCursor
, (XtPointer
) &val
,
4804 #ifdef XtNarrowScrollbars
4805 XtNarrowScrollbars
, (XtPointer
) &xaw3d_arrow_scroll
,
4807 XtNpickTop
, (XtPointer
) &xaw3d_pick_top
, NULL
);
4808 if (xaw3d_arrow_scroll
|| val
== initial
)
4809 { /* ARROW_SCROLL */
4810 xaw3d_arrow_scroll
= True
;
4811 /* Isn't that just a personal preference ? --Stef */
4812 XtVaSetValues (widget
, XtNcursorName
, "top_left_arrow", NULL
);
4816 /* Define callbacks. */
4817 XtAddCallback (widget
, XtNjumpProc
, xaw_jump_callback
, (XtPointer
) bar
);
4818 XtAddCallback (widget
, XtNscrollProc
, xaw_scroll_callback
,
4821 /* Realize the widget. Only after that is the X window created. */
4822 XtRealizeWidget (widget
);
4824 #endif /* !USE_MOTIF */
4826 /* Install an action hook that lets us detect when the user
4827 finishes interacting with a scroll bar. */
4828 if (action_hook_id
== 0)
4829 action_hook_id
= XtAppAddActionHook (Xt_app_con
, xt_action_hook
, 0);
4831 /* Remember X window and widget in the scroll bar vector. */
4832 SET_SCROLL_BAR_X_WIDGET (bar
, widget
);
4833 xwindow
= XtWindow (widget
);
4834 SET_SCROLL_BAR_X_WINDOW (bar
, xwindow
);
4838 #endif /* not USE_GTK */
4841 /* Set the thumb size and position of scroll bar BAR. We are currently
4842 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4846 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4847 struct scroll_bar
*bar
;
4848 int portion
, position
, whole
;
4850 xg_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
4853 #else /* not USE_GTK */
4855 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4856 struct scroll_bar
*bar
;
4857 int portion
, position
, whole
;
4859 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4860 Widget widget
= SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
);
4867 /* We use an estimate of 30 chars per line rather than the real
4868 `portion' value. This has the disadvantage that the thumb size
4869 is not very representative, but it makes our life a lot easier.
4870 Otherwise, we have to constantly adjust the thumb size, which
4871 we can't always do quickly enough: while dragging, the size of
4872 the thumb might prevent the user from dragging the thumb all the
4873 way to the end. but Motif and some versions of Xaw3d don't allow
4874 updating the thumb size while dragging. Also, even if we can update
4875 its size, the update will often happen too late.
4876 If you don't believe it, check out revision 1.650 of xterm.c to see
4877 what hoops we were going through and the still poor behavior we got. */
4878 portion
= WINDOW_TOTAL_LINES (XWINDOW (bar
->window
)) * 30;
4879 /* When the thumb is at the bottom, position == whole.
4880 So we need to increase `whole' to make space for the thumb. */
4887 top
= (float) position
/ whole
;
4888 shown
= (float) portion
/ whole
;
4891 if (NILP (bar
->dragging
))
4895 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
4896 is the scroll bar's maximum and MIN is the scroll bar's minimum
4898 size
= shown
* XM_SB_MAX
;
4899 size
= min (size
, XM_SB_MAX
);
4900 size
= max (size
, 1);
4902 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
4903 value
= top
* XM_SB_MAX
;
4904 value
= min (value
, XM_SB_MAX
- size
);
4906 XmScrollBarSetValues (widget
, value
, size
, 0, 0, False
);
4908 #else /* !USE_MOTIF i.e. use Xaw */
4914 top
= (float) position
/ whole
;
4915 shown
= (float) portion
/ whole
;
4919 float old_top
, old_shown
;
4921 XtVaGetValues (widget
,
4922 XtNtopOfThumb
, &old_top
,
4923 XtNshown
, &old_shown
,
4927 /* Massage the top+shown values. */
4928 if (NILP (bar
->dragging
) || last_scroll_bar_part
== scroll_bar_down_arrow
)
4929 top
= max (0, min (1, top
));
4932 /* Keep two pixels available for moving the thumb down. */
4933 shown
= max (0, min (1 - top
- (2.0 / height
), shown
));
4935 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
4936 check that your system's configuration file contains a define
4937 for `NARROWPROTO'. See s/freebsd.h for an example. */
4938 if (top
!= old_top
|| shown
!= old_shown
)
4940 if (NILP (bar
->dragging
))
4941 XawScrollbarSetThumb (widget
, top
, shown
);
4944 /* Try to make the scrolling a tad smoother. */
4945 if (!xaw3d_pick_top
)
4946 shown
= min (shown
, old_shown
);
4948 XawScrollbarSetThumb (widget
, top
, shown
);
4952 #endif /* !USE_MOTIF */
4956 #endif /* not USE_GTK */
4958 #endif /* USE_TOOLKIT_SCROLL_BARS */
4962 /************************************************************************
4963 Scroll bars, general
4964 ************************************************************************/
4966 /* Create a scroll bar and return the scroll bar vector for it. W is
4967 the Emacs window on which to create the scroll bar. TOP, LEFT,
4968 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4971 static struct scroll_bar
*
4972 x_scroll_bar_create (w
, top
, left
, width
, height
)
4974 int top
, left
, width
, height
;
4976 struct frame
*f
= XFRAME (w
->frame
);
4977 struct scroll_bar
*bar
4978 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4982 #ifdef USE_TOOLKIT_SCROLL_BARS
4983 x_create_toolkit_scroll_bar (f
, bar
);
4984 #else /* not USE_TOOLKIT_SCROLL_BARS */
4986 XSetWindowAttributes a
;
4990 a
.background_pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4991 if (a
.background_pixel
== -1)
4992 a
.background_pixel
= f
->output_data
.x
->background_pixel
;
4994 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
4995 | ButtonMotionMask
| PointerMotionHintMask
4997 a
.cursor
= FRAME_X_DISPLAY_INFO (f
)->vertical_scroll_bar_cursor
;
4999 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
5001 /* Clear the area of W that will serve as a scroll bar. This is
5002 for the case that a window has been split horizontally. In
5003 this case, no clear_frame is generated to reduce flickering. */
5004 if (width
> 0 && height
> 0)
5005 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5007 window_box_height (w
), False
);
5009 window
= XCreateWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5010 /* Position and size of scroll bar. */
5011 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5013 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5015 /* Border width, depth, class, and visual. */
5022 SET_SCROLL_BAR_X_WINDOW (bar
, window
);
5024 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5026 XSETWINDOW (bar
->window
, w
);
5027 XSETINT (bar
->top
, top
);
5028 XSETINT (bar
->left
, left
);
5029 XSETINT (bar
->width
, width
);
5030 XSETINT (bar
->height
, height
);
5031 XSETINT (bar
->start
, 0);
5032 XSETINT (bar
->end
, 0);
5033 bar
->dragging
= Qnil
;
5035 /* Add bar to its frame's list of scroll bars. */
5036 bar
->next
= FRAME_SCROLL_BARS (f
);
5038 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5039 if (!NILP (bar
->next
))
5040 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5042 /* Map the window/widget. */
5043 #ifdef USE_TOOLKIT_SCROLL_BARS
5046 xg_update_scrollbar_pos (f
,
5047 SCROLL_BAR_X_WINDOW (bar
),
5049 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5050 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5052 xg_show_scroll_bar (SCROLL_BAR_X_WINDOW (bar
));
5053 #else /* not USE_GTK */
5054 Widget scroll_bar
= SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
);
5055 XtConfigureWidget (scroll_bar
,
5056 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5058 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5059 max (height
, 1), 0);
5060 XtMapWidget (scroll_bar
);
5061 #endif /* not USE_GTK */
5063 #else /* not USE_TOOLKIT_SCROLL_BARS */
5064 XMapRaised (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
5065 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5072 /* Draw BAR's handle in the proper position.
5074 If the handle is already drawn from START to END, don't bother
5075 redrawing it, unless REBUILD is non-zero; in that case, always
5076 redraw it. (REBUILD is handy for drawing the handle after expose
5079 Normally, we want to constrain the start and end of the handle to
5080 fit inside its rectangle, but if the user is dragging the scroll
5081 bar handle, we want to let them drag it down all the way, so that
5082 the bar's top is as far down as it goes; otherwise, there's no way
5083 to move to the very end of the buffer. */
5085 #ifndef USE_TOOLKIT_SCROLL_BARS
5088 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
5089 struct scroll_bar
*bar
;
5093 int dragging
= ! NILP (bar
->dragging
);
5094 Window w
= SCROLL_BAR_X_WINDOW (bar
);
5095 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5096 GC gc
= f
->output_data
.x
->normal_gc
;
5098 /* If the display is already accurate, do nothing. */
5100 && start
== XINT (bar
->start
)
5101 && end
== XINT (bar
->end
))
5107 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f
, XINT (bar
->width
));
5108 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
5109 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5111 /* Make sure the values are reasonable, and try to preserve
5112 the distance between start and end. */
5114 int length
= end
- start
;
5118 else if (start
> top_range
)
5120 end
= start
+ length
;
5124 else if (end
> top_range
&& ! dragging
)
5128 /* Store the adjusted setting in the scroll bar. */
5129 XSETINT (bar
->start
, start
);
5130 XSETINT (bar
->end
, end
);
5132 /* Clip the end position, just for display. */
5133 if (end
> top_range
)
5136 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
5137 below top positions, to make sure the handle is always at least
5138 that many pixels tall. */
5139 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
5141 /* Draw the empty space above the handle. Note that we can't clear
5142 zero-height areas; that means "clear to end of window." */
5144 x_clear_area (FRAME_X_DISPLAY (f
), w
,
5145 /* x, y, width, height, and exposures. */
5146 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
5147 VERTICAL_SCROLL_BAR_TOP_BORDER
,
5148 inside_width
, start
,
5151 /* Change to proper foreground color if one is specified. */
5152 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
5153 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
5154 f
->output_data
.x
->scroll_bar_foreground_pixel
);
5156 /* Draw the handle itself. */
5157 XFillRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
5158 /* x, y, width, height */
5159 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
5160 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
5161 inside_width
, end
- start
);
5163 /* Restore the foreground color of the GC if we changed it above. */
5164 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
5165 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
5166 f
->output_data
.x
->foreground_pixel
);
5168 /* Draw the empty space below the handle. Note that we can't
5169 clear zero-height areas; that means "clear to end of window." */
5170 if (end
< inside_height
)
5171 x_clear_area (FRAME_X_DISPLAY (f
), w
,
5172 /* x, y, width, height, and exposures. */
5173 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
5174 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
5175 inside_width
, inside_height
- end
,
5183 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5185 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5189 x_scroll_bar_remove (bar
)
5190 struct scroll_bar
*bar
;
5192 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5195 #ifdef USE_TOOLKIT_SCROLL_BARS
5197 xg_remove_scroll_bar (f
, SCROLL_BAR_X_WINDOW (bar
));
5198 #else /* not USE_GTK */
5199 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
));
5200 #endif /* not USE_GTK */
5202 XDestroyWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
5205 /* Disassociate this scroll bar from its window. */
5206 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
5212 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5213 that we are displaying PORTION characters out of a total of WHOLE
5214 characters, starting at POSITION. If WINDOW has no scroll bar,
5218 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
5220 int portion
, whole
, position
;
5222 struct frame
*f
= XFRAME (w
->frame
);
5223 struct scroll_bar
*bar
;
5224 int top
, height
, left
, sb_left
, width
, sb_width
;
5225 int window_y
, window_height
;
5227 /* Get window dimensions. */
5228 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
5230 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
5231 height
= window_height
;
5233 /* Compute the left edge of the scroll bar area. */
5234 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
5236 /* Compute the width of the scroll bar which might be less than
5237 the width of the area reserved for the scroll bar. */
5238 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
5239 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
5243 /* Compute the left edge of the scroll bar. */
5244 #ifdef USE_TOOLKIT_SCROLL_BARS
5245 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
5247 (WINDOW_RIGHTMOST_P (w
)
5248 ? width
- sb_width
- (width
- sb_width
) / 2
5252 (WINDOW_LEFTMOST_P (w
)
5253 ? (width
- sb_width
) / 2
5254 : width
- sb_width
));
5256 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
5257 sb_left
= left
+ width
- sb_width
;
5262 /* Does the scroll bar exist yet? */
5263 if (NILP (w
->vertical_scroll_bar
))
5265 if (width
> 0 && height
> 0)
5268 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5269 left
, top
, width
, height
, False
);
5273 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
);
5277 /* It may just need to be moved and resized. */
5278 unsigned int mask
= 0;
5280 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
5284 if (sb_left
!= XINT (bar
->left
))
5286 if (top
!= XINT (bar
->top
))
5288 if (sb_width
!= XINT (bar
->width
))
5290 if (height
!= XINT (bar
->height
))
5293 #ifdef USE_TOOLKIT_SCROLL_BARS
5295 /* Move/size the scroll bar widget. */
5298 /* Since toolkit scroll bars are smaller than the space reserved
5299 for them on the frame, we have to clear "under" them. */
5300 if (width
> 0 && height
> 0)
5301 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5302 left
, top
, width
, height
, False
);
5304 xg_update_scrollbar_pos (f
,
5305 SCROLL_BAR_X_WINDOW (bar
),
5307 sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5308 sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
*2,
5310 #else /* not USE_GTK */
5311 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
),
5312 sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5314 sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5315 max (height
, 1), 0);
5316 #endif /* not USE_GTK */
5318 #else /* not USE_TOOLKIT_SCROLL_BARS */
5320 /* Clear areas not covered by the scroll bar because of
5321 VERTICAL_SCROLL_BAR_WIDTH_TRIM. */
5322 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM
)
5324 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5325 left
, top
, VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5327 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5328 left
+ width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5329 top
, VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5333 /* Clear areas not covered by the scroll bar because it's not as
5334 wide as the area reserved for it. This makes sure a
5335 previous mode line display is cleared after C-x 2 C-x 1, for
5338 int area_width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
5339 int rest
= area_width
- sb_width
;
5340 if (rest
> 0 && height
> 0)
5342 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
5343 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5344 left
+ area_width
- rest
, top
,
5345 rest
, height
, False
);
5347 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5348 left
, top
, rest
, height
, False
);
5352 /* Move/size the scroll bar window. */
5357 wc
.x
= sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
5359 wc
.width
= sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2;
5361 XConfigureWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
),
5365 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5367 /* Remember new settings. */
5368 XSETINT (bar
->left
, sb_left
);
5369 XSETINT (bar
->top
, top
);
5370 XSETINT (bar
->width
, sb_width
);
5371 XSETINT (bar
->height
, height
);
5376 #ifdef USE_TOOLKIT_SCROLL_BARS
5377 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
5378 #else /* not USE_TOOLKIT_SCROLL_BARS */
5379 /* Set the scroll bar's current state, unless we're currently being
5381 if (NILP (bar
->dragging
))
5383 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
5386 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
5389 int start
= ((double) position
* top_range
) / whole
;
5390 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
5391 x_scroll_bar_set_handle (bar
, start
, end
, 0);
5394 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5396 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
5400 /* The following three hooks are used when we're doing a thorough
5401 redisplay of the frame. We don't explicitly know which scroll bars
5402 are going to be deleted, because keeping track of when windows go
5403 away is a real pain - "Can you say set-window-configuration, boys
5404 and girls?" Instead, we just assert at the beginning of redisplay
5405 that *all* scroll bars are to be removed, and then save a scroll bar
5406 from the fiery pit when we actually redisplay its window. */
5408 /* Arrange for all scroll bars on FRAME to be removed at the next call
5409 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5410 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5413 XTcondemn_scroll_bars (frame
)
5416 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5417 while (! NILP (FRAME_SCROLL_BARS (frame
)))
5420 bar
= FRAME_SCROLL_BARS (frame
);
5421 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
5422 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
5423 XSCROLL_BAR (bar
)->prev
= Qnil
;
5424 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
5425 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
5426 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
5431 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5432 Note that WINDOW isn't necessarily condemned at all. */
5435 XTredeem_scroll_bar (window
)
5436 struct window
*window
;
5438 struct scroll_bar
*bar
;
5441 /* We can't redeem this window's scroll bar if it doesn't have one. */
5442 if (NILP (window
->vertical_scroll_bar
))
5445 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
5447 /* Unlink it from the condemned list. */
5448 f
= XFRAME (WINDOW_FRAME (window
));
5449 if (NILP (bar
->prev
))
5451 /* If the prev pointer is nil, it must be the first in one of
5453 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
5454 /* It's not condemned. Everything's fine. */
5456 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
5457 window
->vertical_scroll_bar
))
5458 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
5460 /* If its prev pointer is nil, it must be at the front of
5461 one or the other! */
5465 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
5467 if (! NILP (bar
->next
))
5468 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
5470 bar
->next
= FRAME_SCROLL_BARS (f
);
5472 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5473 if (! NILP (bar
->next
))
5474 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5477 /* Remove all scroll bars on FRAME that haven't been saved since the
5478 last call to `*condemn_scroll_bars_hook'. */
5481 XTjudge_scroll_bars (f
)
5484 Lisp_Object bar
, next
;
5486 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
5488 /* Clear out the condemned list now so we won't try to process any
5489 more events on the hapless scroll bars. */
5490 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
5492 for (; ! NILP (bar
); bar
= next
)
5494 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
5496 x_scroll_bar_remove (b
);
5499 b
->next
= b
->prev
= Qnil
;
5502 /* Now there should be no references to the condemned scroll bars,
5503 and they should get garbage-collected. */
5507 #ifndef USE_TOOLKIT_SCROLL_BARS
5508 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
5509 is a no-op when using toolkit scroll bars.
5511 This may be called from a signal handler, so we have to ignore GC
5515 x_scroll_bar_expose (bar
, event
)
5516 struct scroll_bar
*bar
;
5519 Window w
= SCROLL_BAR_X_WINDOW (bar
);
5520 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5521 GC gc
= f
->output_data
.x
->normal_gc
;
5522 int width_trim
= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
5526 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
5528 /* Switch to scroll bar foreground color. */
5529 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
5530 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
5531 f
->output_data
.x
->scroll_bar_foreground_pixel
);
5533 /* Draw a one-pixel border just inside the edges of the scroll bar. */
5534 XDrawRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
5536 /* x, y, width, height */
5538 XINT (bar
->width
) - 1 - width_trim
- width_trim
,
5539 XINT (bar
->height
) - 1);
5541 /* Restore the foreground color of the GC if we changed it above. */
5542 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
5543 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
5544 f
->output_data
.x
->foreground_pixel
);
5549 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5551 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5552 is set to something other than NO_EVENT, it is enqueued.
5554 This may be called from a signal handler, so we have to ignore GC
5559 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
5560 struct scroll_bar
*bar
;
5562 struct input_event
*emacs_event
;
5564 if (! GC_WINDOWP (bar
->window
))
5567 emacs_event
->kind
= SCROLL_BAR_CLICK_EVENT
;
5568 emacs_event
->code
= event
->xbutton
.button
- Button1
;
5569 emacs_event
->modifiers
5570 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
5571 (XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))),
5572 event
->xbutton
.state
)
5573 | (event
->type
== ButtonRelease
5576 emacs_event
->frame_or_window
= bar
->window
;
5577 emacs_event
->arg
= Qnil
;
5578 emacs_event
->timestamp
= event
->xbutton
.time
;
5581 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5583 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
5586 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5587 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
5590 if (y
> top_range
) y
= top_range
;
5592 if (y
< XINT (bar
->start
))
5593 emacs_event
->part
= scroll_bar_above_handle
;
5594 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5595 emacs_event
->part
= scroll_bar_handle
;
5597 emacs_event
->part
= scroll_bar_below_handle
;
5599 /* Just because the user has clicked on the handle doesn't mean
5600 they want to drag it. Lisp code needs to be able to decide
5601 whether or not we're dragging. */
5603 /* If the user has just clicked on the handle, record where they're
5605 if (event
->type
== ButtonPress
5606 && emacs_event
->part
== scroll_bar_handle
)
5607 XSETINT (bar
->dragging
, y
- XINT (bar
->start
));
5610 #ifndef USE_TOOLKIT_SCROLL_BARS
5611 /* If the user has released the handle, set it to its final position. */
5612 if (event
->type
== ButtonRelease
5613 && ! NILP (bar
->dragging
))
5615 int new_start
= y
- XINT (bar
->dragging
);
5616 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5618 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5619 bar
->dragging
= Qnil
;
5623 /* Same deal here as the other #if 0. */
5625 /* Clicks on the handle are always reported as occurring at the top of
5627 if (emacs_event
->part
== scroll_bar_handle
)
5628 emacs_event
->x
= bar
->start
;
5630 XSETINT (emacs_event
->x
, y
);
5632 XSETINT (emacs_event
->x
, y
);
5635 XSETINT (emacs_event
->y
, top_range
);
5639 #ifndef USE_TOOLKIT_SCROLL_BARS
5641 /* Handle some mouse motion while someone is dragging the scroll bar.
5643 This may be called from a signal handler, so we have to ignore GC
5647 x_scroll_bar_note_movement (bar
, event
)
5648 struct scroll_bar
*bar
;
5651 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5653 last_mouse_movement_time
= event
->xmotion
.time
;
5656 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5658 /* If we're dragging the bar, display it. */
5659 if (! GC_NILP (bar
->dragging
))
5661 /* Where should the handle be now? */
5662 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
5664 if (new_start
!= XINT (bar
->start
))
5666 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5668 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5673 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5675 /* Return information to the user about the current position of the mouse
5676 on the scroll bar. */
5679 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5681 Lisp_Object
*bar_window
;
5682 enum scroll_bar_part
*part
;
5684 unsigned long *time
;
5686 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5687 Window w
= SCROLL_BAR_X_WINDOW (bar
);
5688 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5690 Window dummy_window
;
5692 unsigned int dummy_mask
;
5696 /* Get the mouse's position relative to the scroll bar window, and
5698 if (! XQueryPointer (FRAME_X_DISPLAY (f
), w
,
5700 /* Root, child, root x and root y. */
5701 &dummy_window
, &dummy_window
,
5702 &dummy_coord
, &dummy_coord
,
5704 /* Position relative to scroll bar. */
5707 /* Mouse buttons and modifier keys. */
5714 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
5717 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5719 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5721 if (! NILP (bar
->dragging
))
5722 win_y
-= XINT (bar
->dragging
);
5726 if (win_y
> top_range
)
5730 *bar_window
= bar
->window
;
5732 if (! NILP (bar
->dragging
))
5733 *part
= scroll_bar_handle
;
5734 else if (win_y
< XINT (bar
->start
))
5735 *part
= scroll_bar_above_handle
;
5736 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5737 *part
= scroll_bar_handle
;
5739 *part
= scroll_bar_below_handle
;
5741 XSETINT (*x
, win_y
);
5742 XSETINT (*y
, top_range
);
5745 last_mouse_scroll_bar
= Qnil
;
5748 *time
= last_mouse_movement_time
;
5754 /* The screen has been cleared so we may have changed foreground or
5755 background colors, and the scroll bars may need to be redrawn.
5756 Clear out the scroll bars, and ask for expose events, so we can
5760 x_scroll_bar_clear (f
)
5763 #ifndef USE_TOOLKIT_SCROLL_BARS
5766 /* We can have scroll bars even if this is 0,
5767 if we just turned off scroll bar mode.
5768 But in that case we should not clear them. */
5769 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5770 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
5771 bar
= XSCROLL_BAR (bar
)->next
)
5772 XClearArea (FRAME_X_DISPLAY (f
),
5773 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
5775 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5779 /* The main X event-reading loop - XTread_socket. */
5782 /* Time stamp of enter window event. This is only used by XTread_socket,
5783 but we have to put it out here, since static variables within functions
5784 sometimes don't work. */
5786 static Time enter_timestamp
;
5789 /* This holds the state XLookupString needs to implement dead keys
5790 and other tricks known as "compose processing". _X Window System_
5791 says that a portable program can't use this, but Stephen Gildea assures
5792 me that letting the compiler initialize it to zeros will work okay.
5794 This must be defined outside of XTread_socket, for the same reasons
5795 given for enter_timestamp, above. */
5797 static XComposeStatus compose_status
;
5799 /* Record the last 100 characters stored
5800 to help debug the loss-of-chars-during-GC problem. */
5802 static int temp_index
;
5803 static short temp_buffer
[100];
5805 #define STORE_KEYSYM_FOR_DEBUG(keysym) \
5806 if (temp_index == sizeof temp_buffer / sizeof (short)) \
5808 temp_buffer[temp_index++] = (keysym)
5810 /* Set this to nonzero to fake an "X I/O error"
5811 on a particular display. */
5813 struct x_display_info
*XTread_socket_fake_io_error
;
5815 /* When we find no input here, we occasionally do a no-op command
5816 to verify that the X server is still running and we can still talk with it.
5817 We try all the open displays, one by one.
5818 This variable is used for cycling thru the displays. */
5820 static struct x_display_info
*next_noop_dpyinfo
;
5822 #define SET_SAVED_MENU_EVENT(size) \
5825 if (f->output_data.x->saved_menu_event == 0) \
5826 f->output_data.x->saved_menu_event \
5827 = (XEvent *) xmalloc (sizeof (XEvent)); \
5828 bcopy (&event, f->output_data.x->saved_menu_event, size); \
5829 inev.ie.kind = MENU_BAR_ACTIVATE_EVENT; \
5830 XSETFRAME (inev.ie.frame_or_window, f); \
5834 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
5835 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
5845 /* Filter events for the current X input method.
5846 DPYINFO is the display this event is for.
5847 EVENT is the X event to filter.
5849 Returns non-zero if the event was filtered, caller shall not process
5851 Returns zero if event is wasn't filtered. */
5855 x_filter_event (dpyinfo
, event
)
5856 struct x_display_info
*dpyinfo
;
5859 /* XFilterEvent returns non-zero if the input method has
5860 consumed the event. We pass the frame's X window to
5861 XFilterEvent because that's the one for which the IC
5864 struct frame
*f1
= x_any_window_to_frame (dpyinfo
,
5865 event
->xclient
.window
);
5867 return XFilterEvent (event
, f1
? FRAME_X_WINDOW (f1
) : None
);
5872 static int current_count
;
5873 static int current_finish
;
5874 static struct input_event
*current_hold_quit
;
5876 /* This is the filter function invoked by the GTK event loop.
5877 It is invoked before the XEvent is translated to a GdkEvent,
5878 so we have a chance to act on the event before GTK. */
5879 static GdkFilterReturn
5880 event_handler_gdk (gxev
, ev
, data
)
5885 XEvent
*xev
= (XEvent
*) gxev
;
5887 if (current_count
>= 0)
5889 struct x_display_info
*dpyinfo
;
5891 dpyinfo
= x_display_info_for_display (xev
->xany
.display
);
5894 /* Filter events for the current X input method.
5895 GTK calls XFilterEvent but not for key press and release,
5896 so we do it here. */
5897 if (xev
->type
== KeyPress
|| xev
->type
== KeyRelease
)
5898 if (dpyinfo
&& x_filter_event (dpyinfo
, xev
))
5899 return GDK_FILTER_REMOVE
;
5903 current_finish
= X_EVENT_NORMAL
;
5907 handle_one_xevent (dpyinfo
, xev
, ¤t_finish
,
5912 current_finish
= x_dispatch_event (xev
, xev
->xany
.display
);
5914 if (current_finish
== X_EVENT_GOTO_OUT
|| current_finish
== X_EVENT_DROP
)
5915 return GDK_FILTER_REMOVE
;
5917 return GDK_FILTER_CONTINUE
;
5919 #endif /* USE_GTK */
5922 /* Handles the XEvent EVENT on display DPYINFO.
5924 *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
5925 *FINISH is zero if caller should continue reading events.
5926 *FINISH is X_EVENT_DROP if event should not be passed to the toolkit.
5928 We return the number of characters stored into the buffer. */
5931 handle_one_xevent (dpyinfo
, eventp
, finish
, hold_quit
)
5932 struct x_display_info
*dpyinfo
;
5935 struct input_event
*hold_quit
;
5938 struct input_event ie
;
5939 struct selection_input_event sie
;
5945 struct coding_system coding
;
5946 XEvent event
= *eventp
;
5948 *finish
= X_EVENT_NORMAL
;
5950 EVENT_INIT (inev
.ie
);
5951 inev
.ie
.kind
= NO_EVENT
;
5958 if (event
.xclient
.message_type
5959 == dpyinfo
->Xatom_wm_protocols
5960 && event
.xclient
.format
== 32)
5962 if (event
.xclient
.data
.l
[0]
5963 == dpyinfo
->Xatom_wm_take_focus
)
5965 /* Use x_any_window_to_frame because this
5966 could be the shell widget window
5967 if the frame has no title bar. */
5968 f
= x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
5970 /* Not quite sure this is needed -pd */
5971 if (f
&& FRAME_XIC (f
))
5972 XSetICFocus (FRAME_XIC (f
));
5974 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
5975 instructs the WM to set the input focus automatically for
5976 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
5977 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
5978 it has set the focus. So, XSetInputFocus below is not
5981 The call to XSetInputFocus below has also caused trouble. In
5982 cases where the XSetInputFocus done by the WM and the one
5983 below are temporally close (on a fast machine), the call
5984 below can generate additional FocusIn events which confuse
5987 /* Since we set WM_TAKE_FOCUS, we must call
5988 XSetInputFocus explicitly. But not if f is null,
5989 since that might be an event for a deleted frame. */
5992 Display
*d
= event
.xclient
.display
;
5993 /* Catch and ignore errors, in case window has been
5994 iconified by a window manager such as GWM. */
5996 XSetInputFocus (d
, event
.xclient
.window
,
5997 /* The ICCCM says this is
5998 the only valid choice. */
6000 event
.xclient
.data
.l
[1]);
6001 /* This is needed to detect the error
6002 if there is an error. */
6004 x_uncatch_errors ();
6006 /* Not certain about handling scroll bars here */
6011 if (event
.xclient
.data
.l
[0]
6012 == dpyinfo
->Xatom_wm_save_yourself
)
6014 /* Save state modify the WM_COMMAND property to
6015 something which can reinstate us. This notifies
6016 the session manager, who's looking for such a
6017 PropertyNotify. Can restart processing when
6018 a keyboard or mouse event arrives. */
6019 /* If we have a session manager, don't set this.
6020 KDE will then start two Emacsen, one for the
6021 session manager and one for this. */
6023 if (! x_session_have_connection ())
6026 f
= x_top_window_to_frame (dpyinfo
,
6027 event
.xclient
.window
);
6028 /* This is just so we only give real data once
6029 for a single Emacs process. */
6030 if (f
== SELECTED_FRAME ())
6031 XSetCommand (FRAME_X_DISPLAY (f
),
6032 event
.xclient
.window
,
6033 initial_argv
, initial_argc
);
6035 XSetCommand (FRAME_X_DISPLAY (f
),
6036 event
.xclient
.window
,
6042 if (event
.xclient
.data
.l
[0]
6043 == dpyinfo
->Xatom_wm_delete_window
)
6045 f
= x_any_window_to_frame (dpyinfo
,
6046 event
.xclient
.window
);
6048 goto OTHER
; /* May be a dialog that is to be removed */
6050 inev
.ie
.kind
= DELETE_WINDOW_EVENT
;
6051 XSETFRAME (inev
.ie
.frame_or_window
, f
);
6058 if (event
.xclient
.message_type
6059 == dpyinfo
->Xatom_wm_configure_denied
)
6064 if (event
.xclient
.message_type
6065 == dpyinfo
->Xatom_wm_window_moved
)
6068 f
= x_window_to_frame (dpyinfo
, event
.xclient
.window
);
6070 new_x
= event
.xclient
.data
.s
[0];
6071 new_y
= event
.xclient
.data
.s
[1];
6075 f
->left_pos
= new_x
;
6082 if (event
.xclient
.message_type
6083 == dpyinfo
->Xatom_editres
)
6085 f
= x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
6087 _XEditResCheckMessages (f
->output_data
.x
->widget
, NULL
,
6091 #endif /* HACK_EDITRES */
6093 if ((event
.xclient
.message_type
6094 == dpyinfo
->Xatom_DONE
)
6095 || (event
.xclient
.message_type
6096 == dpyinfo
->Xatom_PAGE
))
6098 /* Ghostview job completed. Kill it. We could
6099 reply with "Next" if we received "Page", but we
6100 currently never do because we are interested in
6101 images, only, which should have 1 page. */
6102 Pixmap pixmap
= (Pixmap
) event
.xclient
.data
.l
[1];
6103 f
= x_window_to_frame (dpyinfo
, event
.xclient
.window
);
6106 x_kill_gs_process (pixmap
, f
);
6107 expose_frame (f
, 0, 0, 0, 0);
6111 #ifdef USE_TOOLKIT_SCROLL_BARS
6112 /* Scroll bar callbacks send a ClientMessage from which
6113 we construct an input_event. */
6114 if (event
.xclient
.message_type
6115 == dpyinfo
->Xatom_Scrollbar
)
6117 x_scroll_bar_to_input_event (&event
, &inev
.ie
);
6118 *finish
= X_EVENT_GOTO_OUT
;
6121 #endif /* USE_TOOLKIT_SCROLL_BARS */
6123 f
= x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
6126 if (x_handle_dnd_message (f
, &event
.xclient
, dpyinfo
, &inev
.ie
))
6127 *finish
= X_EVENT_DROP
;
6131 case SelectionNotify
:
6132 last_user_time
= event
.xselection
.time
;
6133 #ifdef USE_X_TOOLKIT
6134 if (! x_window_to_frame (dpyinfo
, event
.xselection
.requestor
))
6136 #endif /* not USE_X_TOOLKIT */
6137 x_handle_selection_notify (&event
.xselection
);
6140 case SelectionClear
: /* Someone has grabbed ownership. */
6141 last_user_time
= event
.xselectionclear
.time
;
6142 #ifdef USE_X_TOOLKIT
6143 if (! x_window_to_frame (dpyinfo
, event
.xselectionclear
.window
))
6145 #endif /* USE_X_TOOLKIT */
6147 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
6149 inev
.ie
.kind
= SELECTION_CLEAR_EVENT
;
6150 SELECTION_EVENT_DISPLAY (&inev
.sie
) = eventp
->display
;
6151 SELECTION_EVENT_SELECTION (&inev
.sie
) = eventp
->selection
;
6152 SELECTION_EVENT_TIME (&inev
.sie
) = eventp
->time
;
6153 inev
.ie
.frame_or_window
= Qnil
;
6157 case SelectionRequest
: /* Someone wants our selection. */
6158 last_user_time
= event
.xselectionrequest
.time
;
6159 #ifdef USE_X_TOOLKIT
6160 if (!x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
))
6162 #endif /* USE_X_TOOLKIT */
6164 XSelectionRequestEvent
*eventp
6165 = (XSelectionRequestEvent
*) &event
;
6167 inev
.ie
.kind
= SELECTION_REQUEST_EVENT
;
6168 SELECTION_EVENT_DISPLAY (&inev
.sie
) = eventp
->display
;
6169 SELECTION_EVENT_REQUESTOR (&inev
.sie
) = eventp
->requestor
;
6170 SELECTION_EVENT_SELECTION (&inev
.sie
) = eventp
->selection
;
6171 SELECTION_EVENT_TARGET (&inev
.sie
) = eventp
->target
;
6172 SELECTION_EVENT_PROPERTY (&inev
.sie
) = eventp
->property
;
6173 SELECTION_EVENT_TIME (&inev
.sie
) = eventp
->time
;
6174 inev
.ie
.frame_or_window
= Qnil
;
6178 case PropertyNotify
:
6179 last_user_time
= event
.xproperty
.time
;
6180 #if 0 /* This is plain wrong. In the case that we are waiting for a
6181 PropertyNotify used as an ACK in incremental selection
6182 transfer, the property will be on the receiver's window. */
6183 #if defined USE_X_TOOLKIT
6184 if (!x_any_window_to_frame (dpyinfo
, event
.xproperty
.window
))
6188 x_handle_property_notify (&event
.xproperty
);
6191 case ReparentNotify
:
6192 f
= x_top_window_to_frame (dpyinfo
, event
.xreparent
.window
);
6196 f
->output_data
.x
->parent_desc
= event
.xreparent
.parent
;
6197 x_real_positions (f
, &x
, &y
);
6201 /* Perhaps reparented due to a WM restart. Reset this. */
6202 FRAME_X_DISPLAY_INFO (f
)->wm_type
= X_WMTYPE_UNKNOWN
;
6203 FRAME_X_DISPLAY_INFO (f
)->net_supported_window
= 0;
6208 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
6211 x_check_fullscreen (f
);
6214 /* This seems to be needed for GTK 2.6. */
6215 x_clear_area (event
.xexpose
.display
,
6216 event
.xexpose
.window
,
6217 event
.xexpose
.x
, event
.xexpose
.y
,
6218 event
.xexpose
.width
, event
.xexpose
.height
,
6221 if (f
->async_visible
== 0)
6223 f
->async_visible
= 1;
6224 f
->async_iconified
= 0;
6225 f
->output_data
.x
->has_been_visible
= 1;
6226 SET_FRAME_GARBAGED (f
);
6230 event
.xexpose
.x
, event
.xexpose
.y
,
6231 event
.xexpose
.width
, event
.xexpose
.height
);
6235 #ifndef USE_TOOLKIT_SCROLL_BARS
6236 struct scroll_bar
*bar
;
6238 #if defined USE_LUCID
6239 /* Submenus of the Lucid menu bar aren't widgets
6240 themselves, so there's no way to dispatch events
6241 to them. Recognize this case separately. */
6244 = x_window_to_menu_bar (event
.xexpose
.window
);
6246 xlwmenu_redisplay (widget
);
6248 #endif /* USE_LUCID */
6250 #ifdef USE_TOOLKIT_SCROLL_BARS
6251 /* Dispatch event to the widget. */
6253 #else /* not USE_TOOLKIT_SCROLL_BARS */
6254 bar
= x_window_to_scroll_bar (event
.xexpose
.display
,
6255 event
.xexpose
.window
);
6258 x_scroll_bar_expose (bar
, &event
);
6259 #ifdef USE_X_TOOLKIT
6262 #endif /* USE_X_TOOLKIT */
6263 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6267 case GraphicsExpose
: /* This occurs when an XCopyArea's
6268 source area was obscured or not
6270 f
= x_window_to_frame (dpyinfo
, event
.xgraphicsexpose
.drawable
);
6274 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
6275 event
.xgraphicsexpose
.width
,
6276 event
.xgraphicsexpose
.height
);
6278 #ifdef USE_X_TOOLKIT
6281 #endif /* USE_X_TOOLKIT */
6284 case NoExpose
: /* This occurs when an XCopyArea's
6285 source area was completely
6290 /* Redo the mouse-highlight after the tooltip has gone. */
6291 if (event
.xmap
.window
== tip_window
)
6294 redo_mouse_highlight ();
6297 f
= x_top_window_to_frame (dpyinfo
, event
.xunmap
.window
);
6298 if (f
) /* F may no longer exist if
6299 the frame was deleted. */
6301 /* While a frame is unmapped, display generation is
6302 disabled; you don't want to spend time updating a
6303 display that won't ever be seen. */
6304 f
->async_visible
= 0;
6305 /* We can't distinguish, from the event, whether the window
6306 has become iconified or invisible. So assume, if it
6307 was previously visible, than now it is iconified.
6308 But x_make_frame_invisible clears both
6309 the visible flag and the iconified flag;
6310 and that way, we know the window is not iconified now. */
6311 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
6313 f
->async_iconified
= 1;
6315 inev
.ie
.kind
= ICONIFY_EVENT
;
6316 XSETFRAME (inev
.ie
.frame_or_window
, f
);
6322 if (event
.xmap
.window
== tip_window
)
6323 /* The tooltip has been drawn already. Avoid
6324 the SET_FRAME_GARBAGED below. */
6327 /* We use x_top_window_to_frame because map events can
6328 come for sub-windows and they don't mean that the
6329 frame is visible. */
6330 f
= x_top_window_to_frame (dpyinfo
, event
.xmap
.window
);
6333 /* wait_reading_process_output will notice this and update
6334 the frame's display structures.
6335 If we where iconified, we should not set garbaged,
6336 because that stops redrawing on Expose events. This looks
6337 bad if we are called from a recursive event loop
6338 (x_dispatch_event), for example when a dialog is up. */
6339 if (! f
->async_iconified
)
6340 SET_FRAME_GARBAGED (f
);
6342 f
->async_visible
= 1;
6343 f
->async_iconified
= 0;
6344 f
->output_data
.x
->has_been_visible
= 1;
6348 inev
.ie
.kind
= DEICONIFY_EVENT
;
6349 XSETFRAME (inev
.ie
.frame_or_window
, f
);
6351 else if (! NILP (Vframe_list
)
6352 && ! NILP (XCDR (Vframe_list
)))
6353 /* Force a redisplay sooner or later
6354 to update the frame titles
6355 in case this is the second frame. */
6356 record_asynch_buffer_change ();
6362 last_user_time
= event
.xkey
.time
;
6363 ignore_next_mouse_click_timeout
= 0;
6365 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6366 /* Dispatch KeyPress events when in menu. */
6367 if (popup_activated ())
6371 f
= x_any_window_to_frame (dpyinfo
, event
.xkey
.window
);
6373 /* If mouse-highlight is an integer, input clears out
6374 mouse highlighting. */
6375 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
)
6377 || !EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
)))
6379 clear_mouse_face (dpyinfo
);
6380 dpyinfo
->mouse_face_hidden
= 1;
6383 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
6386 /* Scroll bars consume key events, but we want
6387 the keys to go to the scroll bar's frame. */
6388 Widget widget
= XtWindowToWidget (dpyinfo
->display
,
6390 if (widget
&& XmIsScrollBar (widget
))
6392 widget
= XtParent (widget
);
6393 f
= x_any_window_to_frame (dpyinfo
, XtWindow (widget
));
6396 #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
6400 KeySym keysym
, orig_keysym
;
6401 /* al%imercury@uunet.uu.net says that making this 81
6402 instead of 80 fixed a bug whereby meta chars made
6405 It seems that some version of XmbLookupString has
6406 a bug of not returning XBufferOverflow in
6407 status_return even if the input is too long to
6408 fit in 81 bytes. So, we must prepare sufficient
6409 bytes for copy_buffer. 513 bytes (256 chars for
6410 two-byte character set) seems to be a fairly good
6411 approximation. -- 2000.8.10 handa@etl.go.jp */
6412 unsigned char copy_buffer
[513];
6413 unsigned char *copy_bufptr
= copy_buffer
;
6414 int copy_bufsiz
= sizeof (copy_buffer
);
6416 Lisp_Object coding_system
= Qlatin_1
;
6420 /* Don't pass keys to GTK. A Tab will shift focus to the
6421 tool bar in GTK 2.4. Keys will still go to menus and
6422 dialogs because in that case popup_activated is TRUE
6424 *finish
= X_EVENT_DROP
;
6428 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f
),
6429 extra_keyboard_modifiers
);
6430 modifiers
= event
.xkey
.state
;
6432 /* This will have to go some day... */
6434 /* make_lispy_event turns chars into control chars.
6435 Don't do it here because XLookupString is too eager. */
6436 event
.xkey
.state
&= ~ControlMask
;
6437 event
.xkey
.state
&= ~(dpyinfo
->meta_mod_mask
6438 | dpyinfo
->super_mod_mask
6439 | dpyinfo
->hyper_mod_mask
6440 | dpyinfo
->alt_mod_mask
);
6442 /* In case Meta is ComposeCharacter,
6443 clear its status. According to Markus Ehrnsperger
6444 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
6445 this enables ComposeCharacter to work whether or
6446 not it is combined with Meta. */
6447 if (modifiers
& dpyinfo
->meta_mod_mask
)
6448 bzero (&compose_status
, sizeof (compose_status
));
6453 Status status_return
;
6455 coding_system
= Vlocale_coding_system
;
6456 nbytes
= XmbLookupString (FRAME_XIC (f
),
6457 &event
.xkey
, copy_bufptr
,
6458 copy_bufsiz
, &keysym
,
6460 if (status_return
== XBufferOverflow
)
6462 copy_bufsiz
= nbytes
+ 1;
6463 copy_bufptr
= (unsigned char *) alloca (copy_bufsiz
);
6464 nbytes
= XmbLookupString (FRAME_XIC (f
),
6465 &event
.xkey
, copy_bufptr
,
6466 copy_bufsiz
, &keysym
,
6469 /* Xutf8LookupString is a new but already deprecated interface. -stef */
6470 #if 0 && defined X_HAVE_UTF8_STRING
6471 else if (status_return
== XLookupKeySym
)
6472 { /* Try again but with utf-8. */
6473 coding_system
= Qutf_8
;
6474 nbytes
= Xutf8LookupString (FRAME_XIC (f
),
6475 &event
.xkey
, copy_bufptr
,
6476 copy_bufsiz
, &keysym
,
6478 if (status_return
== XBufferOverflow
)
6480 copy_bufsiz
= nbytes
+ 1;
6481 copy_bufptr
= (unsigned char *) alloca (copy_bufsiz
);
6482 nbytes
= Xutf8LookupString (FRAME_XIC (f
),
6485 copy_bufsiz
, &keysym
,
6491 if (status_return
== XLookupNone
)
6493 else if (status_return
== XLookupChars
)
6498 else if (status_return
!= XLookupKeySym
6499 && status_return
!= XLookupBoth
)
6503 nbytes
= XLookupString (&event
.xkey
, copy_bufptr
,
6504 copy_bufsiz
, &keysym
,
6507 nbytes
= XLookupString (&event
.xkey
, copy_bufptr
,
6508 copy_bufsiz
, &keysym
,
6512 /* If not using XIM/XIC, and a compose sequence is in progress,
6513 we break here. Otherwise, chars_matched is always 0. */
6514 if (compose_status
.chars_matched
> 0 && nbytes
== 0)
6517 bzero (&compose_status
, sizeof (compose_status
));
6518 orig_keysym
= keysym
;
6520 /* Common for all keysym input events. */
6521 XSETFRAME (inev
.ie
.frame_or_window
, f
);
6523 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
), modifiers
);
6524 inev
.ie
.timestamp
= event
.xkey
.time
;
6526 /* First deal with keysyms which have defined
6527 translations to characters. */
6528 if (keysym
>= 32 && keysym
< 128)
6529 /* Avoid explicitly decoding each ASCII character. */
6531 inev
.ie
.kind
= ASCII_KEYSTROKE_EVENT
;
6532 inev
.ie
.code
= keysym
;
6536 /* Keysyms directly mapped to Unicode characters. */
6537 if (keysym
>= 0x01000000 && keysym
<= 0x0110FFFF)
6539 if (keysym
< 0x01000080)
6540 inev
.ie
.kind
= ASCII_KEYSTROKE_EVENT
;
6542 inev
.ie
.kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
6543 inev
.ie
.code
= keysym
& 0xFFFFFF;
6547 /* Now non-ASCII. */
6548 if (HASH_TABLE_P (Vx_keysym_table
)
6549 && (NATNUMP (c
= Fgethash (make_number (keysym
),
6553 inev
.ie
.kind
= (SINGLE_BYTE_CHAR_P (XFASTINT (c
))
6554 ? ASCII_KEYSTROKE_EVENT
6555 : MULTIBYTE_CHAR_KEYSTROKE_EVENT
);
6556 inev
.ie
.code
= XFASTINT (c
);
6560 /* Random non-modifier sorts of keysyms. */
6561 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
6562 || keysym
== XK_Delete
6563 #ifdef XK_ISO_Left_Tab
6564 || (keysym
>= XK_ISO_Left_Tab
6565 && keysym
<= XK_ISO_Enter
)
6567 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
6568 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
6570 /* This recognizes the "extended function
6571 keys". It seems there's no cleaner way.
6572 Test IsModifierKey to avoid handling
6573 mode_switch incorrectly. */
6574 || ((unsigned) (keysym
) >= XK_Select
6575 && (unsigned)(keysym
) < XK_KP_Space
)
6577 #ifdef XK_dead_circumflex
6578 || orig_keysym
== XK_dead_circumflex
6580 #ifdef XK_dead_grave
6581 || orig_keysym
== XK_dead_grave
6583 #ifdef XK_dead_tilde
6584 || orig_keysym
== XK_dead_tilde
6586 #ifdef XK_dead_diaeresis
6587 || orig_keysym
== XK_dead_diaeresis
6589 #ifdef XK_dead_macron
6590 || orig_keysym
== XK_dead_macron
6592 #ifdef XK_dead_degree
6593 || orig_keysym
== XK_dead_degree
6595 #ifdef XK_dead_acute
6596 || orig_keysym
== XK_dead_acute
6598 #ifdef XK_dead_cedilla
6599 || orig_keysym
== XK_dead_cedilla
6601 #ifdef XK_dead_breve
6602 || orig_keysym
== XK_dead_breve
6604 #ifdef XK_dead_ogonek
6605 || orig_keysym
== XK_dead_ogonek
6607 #ifdef XK_dead_caron
6608 || orig_keysym
== XK_dead_caron
6610 #ifdef XK_dead_doubleacute
6611 || orig_keysym
== XK_dead_doubleacute
6613 #ifdef XK_dead_abovedot
6614 || orig_keysym
== XK_dead_abovedot
6616 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
6617 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
6618 /* Any "vendor-specific" key is ok. */
6619 || (orig_keysym
& (1 << 28))
6620 || (keysym
!= NoSymbol
&& nbytes
== 0))
6621 && ! (IsModifierKey (orig_keysym
)
6623 #ifdef XK_Mode_switch
6624 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
6627 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
6629 #endif /* not HAVE_X11R5 */
6630 /* The symbols from XK_ISO_Lock
6631 to XK_ISO_Last_Group_Lock
6632 don't have real modifiers but
6633 should be treated similarly to
6634 Mode_switch by Emacs. */
6635 #if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
6636 || ((unsigned)(orig_keysym
)
6638 && (unsigned)(orig_keysym
)
6639 <= XK_ISO_Last_Group_Lock
)
6643 STORE_KEYSYM_FOR_DEBUG (keysym
);
6644 /* make_lispy_event will convert this to a symbolic
6646 inev
.ie
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
6647 inev
.ie
.code
= keysym
;
6651 { /* Raw bytes, not keysym. */
6656 for (i
= 0, nchars
= 0; i
< nbytes
; i
++)
6658 if (ASCII_BYTE_P (copy_bufptr
[i
]))
6660 STORE_KEYSYM_FOR_DEBUG (copy_bufptr
[i
]);
6663 if (nchars
< nbytes
)
6665 /* Decode the input data. */
6669 /* The input should be decoded with `coding_system'
6670 which depends on which X*LookupString function
6671 we used just above and the locale. */
6672 setup_coding_system (coding_system
, &coding
);
6673 coding
.src_multibyte
= 0;
6674 coding
.dst_multibyte
= 1;
6675 /* The input is converted to events, thus we can't
6676 handle composition. Anyway, there's no XIM that
6677 gives us composition information. */
6678 coding
.common_flags
&= ~CODING_ANNOTATION_MASK
;
6680 require
= MAX_MULTIBYTE_LENGTH
* nbytes
;
6681 coding
.destination
= alloca (require
);
6682 coding
.dst_bytes
= require
;
6683 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6684 decode_coding_c_string (&coding
, copy_bufptr
, nbytes
, Qnil
);
6685 nbytes
= coding
.produced
;
6686 nchars
= coding
.produced_char
;
6687 copy_bufptr
= coding
.destination
;
6690 /* Convert the input data to a sequence of
6691 character events. */
6692 for (i
= 0; i
< nbytes
; i
+= len
)
6694 if (nchars
== nbytes
)
6695 c
= copy_bufptr
[i
], len
= 1;
6697 c
= STRING_CHAR_AND_LENGTH (copy_bufptr
+ i
,
6699 inev
.ie
.kind
= (SINGLE_BYTE_CHAR_P (c
)
6700 ? ASCII_KEYSTROKE_EVENT
6701 : MULTIBYTE_CHAR_KEYSTROKE_EVENT
);
6703 kbd_buffer_store_event_hold (&inev
.ie
, hold_quit
);
6706 /* Previous code updated count by nchars rather than nbytes,
6707 but that seems bogus to me. ++kfs */
6710 inev
.ie
.kind
= NO_EVENT
; /* Already stored above. */
6712 if (keysym
== NoSymbol
)
6718 /* Don't dispatch this event since XtDispatchEvent calls
6719 XFilterEvent, and two calls in a row may freeze the
6727 last_user_time
= event
.xkey
.time
;
6729 /* Don't dispatch this event since XtDispatchEvent calls
6730 XFilterEvent, and two calls in a row may freeze the
6738 last_user_time
= event
.xcrossing
.time
;
6739 x_detect_focus_change (dpyinfo
, &event
, &inev
.ie
);
6741 f
= x_any_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
6743 if (f
&& x_mouse_click_focus_ignore_position
)
6744 ignore_next_mouse_click_timeout
= event
.xmotion
.time
+ 200;
6747 if (event
.xcrossing
.focus
)
6749 /* Avoid nasty pop/raise loops. */
6750 if (f
&& (!(f
->auto_raise
)
6752 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
6754 x_new_focus_frame (dpyinfo
, f
);
6755 enter_timestamp
= event
.xcrossing
.time
;
6758 else if (f
== dpyinfo
->x_focus_frame
)
6759 x_new_focus_frame (dpyinfo
, 0);
6762 /* EnterNotify counts as mouse movement,
6763 so update things that depend on mouse position. */
6764 if (f
&& !f
->output_data
.x
->hourglass_p
)
6765 note_mouse_movement (f
, &event
.xmotion
);
6767 /* We may get an EnterNotify on the buttons in the toolbar. In that
6768 case we moved out of any highlighted area and need to note this. */
6769 if (!f
&& last_mouse_glyph_frame
)
6770 note_mouse_movement (last_mouse_glyph_frame
, &event
);
6775 x_detect_focus_change (dpyinfo
, &event
, &inev
.ie
);
6779 last_user_time
= event
.xcrossing
.time
;
6780 x_detect_focus_change (dpyinfo
, &event
, &inev
.ie
);
6782 f
= x_top_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
6785 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6787 /* If we move outside the frame, then we're
6788 certainly no longer on any text in the frame. */
6789 clear_mouse_face (dpyinfo
);
6790 dpyinfo
->mouse_face_mouse_frame
= 0;
6793 /* Generate a nil HELP_EVENT to cancel a help-echo.
6794 Do it only if there's something to cancel.
6795 Otherwise, the startup message is cleared when
6796 the mouse leaves the frame. */
6797 if (any_help_event_p
)
6801 /* See comment in EnterNotify above */
6802 else if (last_mouse_glyph_frame
)
6803 note_mouse_movement (last_mouse_glyph_frame
, &event
);
6808 x_detect_focus_change (dpyinfo
, &event
, &inev
.ie
);
6813 last_user_time
= event
.xmotion
.time
;
6814 previous_help_echo_string
= help_echo_string
;
6815 help_echo_string
= Qnil
;
6817 if (dpyinfo
->grabbed
&& last_mouse_frame
6818 && FRAME_LIVE_P (last_mouse_frame
))
6819 f
= last_mouse_frame
;
6821 f
= x_window_to_frame (dpyinfo
, event
.xmotion
.window
);
6823 if (dpyinfo
->mouse_face_hidden
)
6825 dpyinfo
->mouse_face_hidden
= 0;
6826 clear_mouse_face (dpyinfo
);
6832 /* Generate SELECT_WINDOW_EVENTs when needed. */
6833 if (!NILP (Vmouse_autoselect_window
))
6837 window
= window_from_coordinates (f
,
6838 event
.xmotion
.x
, event
.xmotion
.y
,
6841 /* Window will be selected only when it is not selected now and
6842 last mouse movement event was not in it. Minibuffer window
6843 will be selected iff it is active. */
6844 if (WINDOWP (window
)
6845 && !EQ (window
, last_window
)
6846 && !EQ (window
, selected_window
))
6848 inev
.ie
.kind
= SELECT_WINDOW_EVENT
;
6849 inev
.ie
.frame_or_window
= window
;
6854 if (!note_mouse_movement (f
, &event
.xmotion
))
6855 help_echo_string
= previous_help_echo_string
;
6859 #ifndef USE_TOOLKIT_SCROLL_BARS
6860 struct scroll_bar
*bar
6861 = x_window_to_scroll_bar (event
.xmotion
.display
,
6862 event
.xmotion
.window
);
6865 x_scroll_bar_note_movement (bar
, &event
);
6866 #endif /* USE_TOOLKIT_SCROLL_BARS */
6868 /* If we move outside the frame, then we're
6869 certainly no longer on any text in the frame. */
6870 clear_mouse_face (dpyinfo
);
6873 /* If the contents of the global variable help_echo_string
6874 has changed, generate a HELP_EVENT. */
6875 if (!NILP (help_echo_string
)
6876 || !NILP (previous_help_echo_string
))
6881 case ConfigureNotify
:
6882 f
= x_top_window_to_frame (dpyinfo
, event
.xconfigure
.window
);
6885 #ifndef USE_X_TOOLKIT
6887 xg_resize_widgets (f
, event
.xconfigure
.width
,
6888 event
.xconfigure
.height
);
6889 #else /* not USE_GTK */
6890 /* If there is a pending resize for fullscreen, don't
6891 do this one, the right one will come later.
6892 The toolkit version doesn't seem to need this, but we
6893 need to reset it below. */
6895 = ((f
->want_fullscreen
& FULLSCREEN_WAIT
)
6896 && f
->new_text_cols
!= 0);
6897 int rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, event
.xconfigure
.height
);
6898 int columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, event
.xconfigure
.width
);
6903 /* In the toolkit version, change_frame_size
6904 is called by the code that handles resizing
6905 of the EmacsFrame widget. */
6907 /* Even if the number of character rows and columns has
6908 not changed, the font size may have changed, so we need
6909 to check the pixel dimensions as well. */
6910 if (columns
!= FRAME_COLS (f
)
6911 || rows
!= FRAME_LINES (f
)
6912 || event
.xconfigure
.width
!= FRAME_PIXEL_WIDTH (f
)
6913 || event
.xconfigure
.height
!= FRAME_PIXEL_HEIGHT (f
))
6915 change_frame_size (f
, rows
, columns
, 0, 1, 0);
6916 SET_FRAME_GARBAGED (f
);
6917 cancel_mouse_face (f
);
6919 #endif /* not USE_GTK */
6922 FRAME_PIXEL_WIDTH (f
) = event
.xconfigure
.width
;
6923 FRAME_PIXEL_HEIGHT (f
) = event
.xconfigure
.height
;
6926 /* GTK creates windows but doesn't map them.
6927 Only get real positions and check fullscreen when mapped. */
6928 if (FRAME_GTK_OUTER_WIDGET (f
)
6929 && GTK_WIDGET_MAPPED (FRAME_GTK_OUTER_WIDGET (f
)))
6932 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
6934 if (f
->want_fullscreen
& FULLSCREEN_WAIT
)
6935 f
->want_fullscreen
&= ~(FULLSCREEN_WAIT
|FULLSCREEN_BOTH
);
6939 if (FRAME_XIC (f
) && (FRAME_XIC_STYLE (f
) & XIMStatusArea
))
6940 xic_set_statusarea (f
);
6943 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
6945 /* Since the WM decorations come below top_pos now,
6946 we must put them below top_pos in the future. */
6947 f
->win_gravity
= NorthWestGravity
;
6948 x_wm_set_size_hint (f
, (long) 0, 0);
6956 /* If we decide we want to generate an event to be seen
6957 by the rest of Emacs, we put it here. */
6960 bzero (&compose_status
, sizeof (compose_status
));
6961 last_mouse_glyph_frame
= 0;
6962 last_user_time
= event
.xbutton
.time
;
6964 if (dpyinfo
->grabbed
6966 && FRAME_LIVE_P (last_mouse_frame
))
6967 f
= last_mouse_frame
;
6969 f
= x_window_to_frame (dpyinfo
, event
.xbutton
.window
);
6973 /* Is this in the tool-bar? */
6974 if (WINDOWP (f
->tool_bar_window
)
6975 && WINDOW_TOTAL_LINES (XWINDOW (f
->tool_bar_window
)))
6978 int x
= event
.xbutton
.x
;
6979 int y
= event
.xbutton
.y
;
6981 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
6982 if (EQ (window
, f
->tool_bar_window
))
6984 if (event
.xbutton
.type
== ButtonPress
)
6985 handle_tool_bar_click (f
, x
, y
, 1, 0);
6987 handle_tool_bar_click (f
, x
, y
, 0,
6988 x_x_to_emacs_modifiers (dpyinfo
,
6989 event
.xbutton
.state
));
6995 if (!dpyinfo
->x_focus_frame
6996 || f
== dpyinfo
->x_focus_frame
)
6998 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6999 if (! popup_activated ())
7002 if (ignore_next_mouse_click_timeout
)
7004 if (event
.type
== ButtonPress
7005 && (int)(event
.xbutton
.time
- ignore_next_mouse_click_timeout
) > 0)
7007 ignore_next_mouse_click_timeout
= 0;
7008 construct_mouse_click (&inev
.ie
, &event
.xbutton
, f
);
7010 if (event
.type
== ButtonRelease
)
7011 ignore_next_mouse_click_timeout
= 0;
7014 construct_mouse_click (&inev
.ie
, &event
.xbutton
, f
);
7020 struct scroll_bar
*bar
7021 = x_window_to_scroll_bar (event
.xbutton
.display
,
7022 event
.xbutton
.window
);
7024 #ifdef USE_TOOLKIT_SCROLL_BARS
7025 /* Make the "Ctrl-Mouse-2 splits window" work for toolkit
7027 if (bar
&& event
.xbutton
.state
& ControlMask
)
7029 x_scroll_bar_handle_click (bar
, &event
, &inev
.ie
);
7030 *finish
= X_EVENT_DROP
;
7032 #else /* not USE_TOOLKIT_SCROLL_BARS */
7034 x_scroll_bar_handle_click (bar
, &event
, &inev
.ie
);
7035 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7038 if (event
.type
== ButtonPress
)
7040 dpyinfo
->grabbed
|= (1 << event
.xbutton
.button
);
7041 last_mouse_frame
= f
;
7044 last_tool_bar_item
= -1;
7047 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
7049 /* Ignore any mouse motion that happened before this event;
7050 any subsequent mouse-movement Emacs events should reflect
7051 only motion after the ButtonPress/Release. */
7055 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
7056 f
= x_menubar_window_to_frame (dpyinfo
, event
.xbutton
.window
);
7057 /* For a down-event in the menu bar,
7058 don't pass it to Xt right now.
7059 Instead, save it away
7060 and we will pass it to Xt from kbd_buffer_get_event.
7061 That way, we can run some Lisp code first. */
7064 ! popup_activated ()
7067 f
&& event
.type
== ButtonPress
7068 /* Verify the event is really within the menu bar
7069 and not just sent to it due to grabbing. */
7070 && event
.xbutton
.x
>= 0
7071 && event
.xbutton
.x
< FRAME_PIXEL_WIDTH (f
)
7072 && event
.xbutton
.y
>= 0
7073 && event
.xbutton
.y
< f
->output_data
.x
->menubar_height
7074 && event
.xbutton
.same_screen
)
7076 SET_SAVED_BUTTON_EVENT
;
7077 XSETFRAME (last_mouse_press_frame
, f
);
7079 *finish
= X_EVENT_DROP
;
7082 else if (event
.type
== ButtonPress
)
7084 last_mouse_press_frame
= Qnil
;
7088 #ifdef USE_MOTIF /* This should do not harm for Lucid,
7089 but I am trying to be cautious. */
7090 else if (event
.type
== ButtonRelease
)
7092 if (!NILP (last_mouse_press_frame
))
7094 f
= XFRAME (last_mouse_press_frame
);
7095 if (f
->output_data
.x
)
7096 SET_SAVED_BUTTON_EVENT
;
7101 #endif /* USE_MOTIF */
7104 #endif /* USE_X_TOOLKIT || USE_GTK */
7108 case CirculateNotify
:
7111 case CirculateRequest
:
7114 case VisibilityNotify
:
7118 /* Someone has changed the keyboard mapping - update the
7120 switch (event
.xmapping
.request
)
7122 case MappingModifier
:
7123 x_find_modifier_meanings (dpyinfo
);
7124 /* This is meant to fall through. */
7125 case MappingKeyboard
:
7126 XRefreshKeyboardMapping (&event
.xmapping
);
7132 #ifdef USE_X_TOOLKIT
7134 if (*finish
!= X_EVENT_DROP
)
7135 XtDispatchEvent (&event
);
7137 #endif /* USE_X_TOOLKIT */
7142 if (inev
.ie
.kind
!= NO_EVENT
)
7144 kbd_buffer_store_event_hold (&inev
.ie
, hold_quit
);
7149 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
7154 XSETFRAME (frame
, f
);
7160 any_help_event_p
= 1;
7161 gen_help_event (help_echo_string
, frame
, help_echo_window
,
7162 help_echo_object
, help_echo_pos
);
7166 help_echo_string
= Qnil
;
7167 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
7177 /* Handles the XEvent EVENT on display DISPLAY.
7178 This is used for event loops outside the normal event handling,
7179 i.e. looping while a popup menu or a dialog is posted.
7181 Returns the value handle_one_xevent sets in the finish argument. */
7183 x_dispatch_event (event
, display
)
7187 struct x_display_info
*dpyinfo
;
7188 int finish
= X_EVENT_NORMAL
;
7190 dpyinfo
= x_display_info_for_display (display
);
7193 handle_one_xevent (dpyinfo
, event
, &finish
, 0);
7199 /* Read events coming from the X server.
7200 This routine is called by the SIGIO handler.
7201 We return as soon as there are no more events to be read.
7203 We return the number of characters stored into the buffer,
7204 thus pretending to be `read'.
7206 EXPECTED is nonzero if the caller knows input is available. */
7209 XTread_socket (sd
, expected
, hold_quit
)
7212 struct input_event
*hold_quit
;
7216 int event_found
= 0;
7217 struct x_display_info
*dpyinfo
;
7219 if (interrupt_input_blocked
)
7221 interrupt_input_pending
= 1;
7225 interrupt_input_pending
= 0;
7228 /* So people can tell when we have read the available input. */
7229 input_signal_count
++;
7233 /* Find the display we are supposed to read input for.
7234 It's the one communicating on descriptor SD. */
7235 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
7237 #if 0 /* This ought to be unnecessary; let's verify it. */
7239 /* If available, Xlib uses FIOSNBIO to make the socket
7240 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
7241 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
7242 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
7243 fcntl (dpyinfo
->connection
, F_SETFL
, 0);
7244 #endif /* ! defined (FIOSNBIO) */
7247 #if 0 /* This code can't be made to work, with multiple displays,
7248 and appears not to be used on any system any more.
7249 Also keyboard.c doesn't turn O_NDELAY on and off
7250 for X connections. */
7253 if (! (fcntl (dpyinfo
->connection
, F_GETFL
, 0) & O_NDELAY
))
7255 extern int read_alarm_should_throw
;
7256 read_alarm_should_throw
= 1;
7257 XPeekEvent (dpyinfo
->display
, &event
);
7258 read_alarm_should_throw
= 0;
7260 #endif /* HAVE_SELECT */
7264 /* For debugging, this gives a way to fake an I/O error. */
7265 if (dpyinfo
== XTread_socket_fake_io_error
)
7267 XTread_socket_fake_io_error
= 0;
7268 x_io_error_quitter (dpyinfo
->display
);
7273 struct input_event inev
;
7275 /* We don't need to EVENT_INIT (inev) here, as
7276 x_session_check_input copies an entire input_event. */
7277 if (x_session_check_input (&inev
))
7279 kbd_buffer_store_event_hold (&inev
, hold_quit
);
7287 while (XPending (dpyinfo
->display
))
7291 XNextEvent (dpyinfo
->display
, &event
);
7294 /* Filter events for the current X input method. */
7295 if (x_filter_event (dpyinfo
, &event
))
7300 count
+= handle_one_xevent (dpyinfo
, &event
, &finish
, hold_quit
);
7302 if (finish
== X_EVENT_GOTO_OUT
)
7305 #endif /* not USE_GTK */
7310 /* For GTK we must use the GTK event loop. But XEvents gets passed
7311 to our filter function above, and then to the big event switch.
7312 We use a bunch of globals to communicate with our filter function,
7313 that is kind of ugly, but it works.
7315 There is no way to do one display at the time, GTK just does events
7316 from all displays. */
7318 while (gtk_events_pending ())
7320 current_count
= count
;
7321 current_hold_quit
= hold_quit
;
7323 gtk_main_iteration ();
7325 count
= current_count
;
7327 current_hold_quit
= 0;
7329 if (current_finish
== X_EVENT_GOTO_OUT
)
7332 #endif /* USE_GTK */
7336 /* On some systems, an X bug causes Emacs to get no more events
7337 when the window is destroyed. Detect that. (1994.) */
7340 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
7341 One XNOOP in 100 loops will make Emacs terminate.
7342 B. Bretthauer, 1994 */
7344 if (x_noop_count
>= 100)
7348 if (next_noop_dpyinfo
== 0)
7349 next_noop_dpyinfo
= x_display_list
;
7351 XNoOp (next_noop_dpyinfo
->display
);
7353 /* Each time we get here, cycle through the displays now open. */
7354 next_noop_dpyinfo
= next_noop_dpyinfo
->next
;
7358 /* If the focus was just given to an auto-raising frame,
7360 /* ??? This ought to be able to handle more than one such frame. */
7361 if (pending_autoraise_frame
)
7363 x_raise_frame (pending_autoraise_frame
);
7364 pending_autoraise_frame
= 0;
7376 /***********************************************************************
7378 ***********************************************************************/
7380 /* Set clipping for output in glyph row ROW. W is the window in which
7381 we operate. GC is the graphics context to set clipping in.
7383 ROW may be a text row or, e.g., a mode line. Text rows must be
7384 clipped to the interior of the window dedicated to text display,
7385 mode lines must be clipped to the whole window. */
7388 x_clip_to_row (w
, row
, area
, gc
)
7390 struct glyph_row
*row
;
7394 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
7395 XRectangle clip_rect
;
7396 int window_x
, window_y
, window_width
;
7398 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
7400 clip_rect
.x
= window_x
;
7401 clip_rect
.y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, row
->y
));
7402 clip_rect
.y
= max (clip_rect
.y
, window_y
);
7403 clip_rect
.width
= window_width
;
7404 clip_rect
.height
= row
->visible_height
;
7406 XSetClipRectangles (FRAME_X_DISPLAY (f
), gc
, 0, 0, &clip_rect
, 1, Unsorted
);
7410 /* Draw a hollow box cursor on window W in glyph row ROW. */
7413 x_draw_hollow_cursor (w
, row
)
7415 struct glyph_row
*row
;
7417 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
7418 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7419 Display
*dpy
= FRAME_X_DISPLAY (f
);
7422 struct glyph
*cursor_glyph
;
7425 /* Get the glyph the cursor is on. If we can't tell because
7426 the current matrix is invalid or such, give up. */
7427 cursor_glyph
= get_phys_cursor_glyph (w
);
7428 if (cursor_glyph
== NULL
)
7431 /* Compute frame-relative coordinates for phys cursor. */
7432 get_phys_cursor_geometry (w
, row
, cursor_glyph
, &x
, &y
, &h
);
7433 wd
= w
->phys_cursor_width
;
7435 /* The foreground of cursor_gc is typically the same as the normal
7436 background color, which can cause the cursor box to be invisible. */
7437 xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
7438 if (dpyinfo
->scratch_cursor_gc
)
7439 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
7441 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_X_WINDOW (f
),
7442 GCForeground
, &xgcv
);
7443 gc
= dpyinfo
->scratch_cursor_gc
;
7445 /* Set clipping, draw the rectangle, and reset clipping again. */
7446 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
7447 XDrawRectangle (dpy
, FRAME_X_WINDOW (f
), gc
, x
, y
, wd
, h
- 1);
7448 XSetClipMask (dpy
, gc
, None
);
7452 /* Draw a bar cursor on window W in glyph row ROW.
7454 Implementation note: One would like to draw a bar cursor with an
7455 angle equal to the one given by the font property XA_ITALIC_ANGLE.
7456 Unfortunately, I didn't find a font yet that has this property set.
7460 x_draw_bar_cursor (w
, row
, width
, kind
)
7462 struct glyph_row
*row
;
7464 enum text_cursor_kinds kind
;
7466 struct frame
*f
= XFRAME (w
->frame
);
7467 struct glyph
*cursor_glyph
;
7469 /* If cursor is out of bounds, don't draw garbage. This can happen
7470 in mini-buffer windows when switching between echo area glyphs
7472 cursor_glyph
= get_phys_cursor_glyph (w
);
7473 if (cursor_glyph
== NULL
)
7476 /* If on an image, draw like a normal cursor. That's usually better
7477 visible than drawing a bar, esp. if the image is large so that
7478 the bar might not be in the window. */
7479 if (cursor_glyph
->type
== IMAGE_GLYPH
)
7481 struct glyph_row
*row
;
7482 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
7483 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
7487 Display
*dpy
= FRAME_X_DISPLAY (f
);
7488 Window window
= FRAME_X_WINDOW (f
);
7489 GC gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
7490 unsigned long mask
= GCForeground
| GCBackground
| GCGraphicsExposures
;
7491 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
7494 /* If the glyph's background equals the color we normally draw
7495 the bar cursor in, the bar cursor in its normal color is
7496 invisible. Use the glyph's foreground color instead in this
7497 case, on the assumption that the glyph's colors are chosen so
7498 that the glyph is legible. */
7499 if (face
->background
== f
->output_data
.x
->cursor_pixel
)
7500 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
7502 xgcv
.background
= xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
7503 xgcv
.graphics_exposures
= 0;
7506 XChangeGC (dpy
, gc
, mask
, &xgcv
);
7509 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
7510 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
7514 width
= FRAME_CURSOR_WIDTH (f
);
7515 width
= min (cursor_glyph
->pixel_width
, width
);
7517 w
->phys_cursor_width
= width
;
7518 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
7520 if (kind
== BAR_CURSOR
)
7521 XFillRectangle (dpy
, window
, gc
,
7522 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
7523 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
7524 width
, row
->height
);
7526 XFillRectangle (dpy
, window
, gc
,
7527 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
7528 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
7529 row
->height
- width
),
7530 cursor_glyph
->pixel_width
,
7533 XSetClipMask (dpy
, gc
, None
);
7538 /* RIF: Define cursor CURSOR on frame F. */
7541 x_define_frame_cursor (f
, cursor
)
7545 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), cursor
);
7549 /* RIF: Clear area on frame F. */
7552 x_clear_frame_area (f
, x
, y
, width
, height
)
7554 int x
, y
, width
, height
;
7556 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7557 x
, y
, width
, height
, False
);
7561 /* RIF: Draw cursor on window W. */
7564 x_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
7566 struct glyph_row
*glyph_row
;
7568 int cursor_type
, cursor_width
;
7571 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
7575 w
->phys_cursor_type
= cursor_type
;
7576 w
->phys_cursor_on_p
= 1;
7578 if (glyph_row
->exact_window_width_line_p
7579 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
7581 glyph_row
->cursor_in_fringe_p
= 1;
7582 draw_fringe_bitmap (w
, glyph_row
, 0);
7585 switch (cursor_type
)
7587 case HOLLOW_BOX_CURSOR
:
7588 x_draw_hollow_cursor (w
, glyph_row
);
7591 case FILLED_BOX_CURSOR
:
7592 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
7596 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
7600 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
7604 w
->phys_cursor_width
= 0;
7612 if (w
== XWINDOW (f
->selected_window
))
7613 if (FRAME_XIC (f
) && (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
))
7614 xic_set_preeditarea (w
, x
, y
);
7619 if (updating_frame
!= f
)
7620 XFlush (FRAME_X_DISPLAY (f
));
7627 /* Make the x-window of frame F use the gnu icon bitmap. */
7630 x_bitmap_icon (f
, file
)
7636 if (FRAME_X_WINDOW (f
) == 0)
7639 /* Free up our existing icon bitmap and mask if any. */
7640 if (f
->output_data
.x
->icon_bitmap
> 0)
7641 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
7642 f
->output_data
.x
->icon_bitmap
= 0;
7647 /* Use gtk_window_set_icon_from_file () if available,
7648 It's not restricted to bitmaps */
7649 if (xg_set_icon (f
, file
))
7651 #endif /* USE_GTK */
7652 bitmap_id
= x_create_bitmap_from_file (f
, file
);
7653 x_create_bitmap_mask (f
, bitmap_id
);
7657 /* Create the GNU bitmap and mask if necessary. */
7658 if (FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
7662 #if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
7664 if (xg_set_icon_from_xpm_data (f
, gnu_xpm_bits
))
7667 rc
= x_create_bitmap_from_xpm_data (f
, gnu_xpm_bits
);
7669 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
= rc
;
7670 #endif /* USE_GTK */
7671 #endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
7673 /* If all else fails, use the (black and white) xbm image. */
7676 rc
= x_create_bitmap_from_data (f
, gnu_xbm_bits
,
7677 gnu_xbm_width
, gnu_xbm_height
);
7681 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
= rc
;
7682 x_create_bitmap_mask (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
7686 /* The first time we create the GNU bitmap and mask,
7687 this increments the ref-count one extra time.
7688 As a result, the GNU bitmap and mask are never freed.
7689 That way, we don't have to worry about allocating it again. */
7690 x_reference_bitmap (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
7692 bitmap_id
= FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
;
7695 x_wm_set_icon_pixmap (f
, bitmap_id
);
7696 f
->output_data
.x
->icon_bitmap
= bitmap_id
;
7702 /* Make the x-window of frame F use a rectangle with text.
7703 Use ICON_NAME as the text. */
7706 x_text_icon (f
, icon_name
)
7710 if (FRAME_X_WINDOW (f
) == 0)
7716 text
.value
= (unsigned char *) icon_name
;
7717 text
.encoding
= XA_STRING
;
7719 text
.nitems
= strlen (icon_name
);
7720 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
), &text
);
7722 #else /* not HAVE_X11R4 */
7723 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
), icon_name
);
7724 #endif /* not HAVE_X11R4 */
7726 if (f
->output_data
.x
->icon_bitmap
> 0)
7727 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
7728 f
->output_data
.x
->icon_bitmap
= 0;
7729 x_wm_set_icon_pixmap (f
, 0);
7734 #define X_ERROR_MESSAGE_SIZE 200
7736 /* If non-nil, this should be a string.
7737 It means catch X errors and store the error message in this string.
7739 The reason we use a stack is that x_catch_error/x_uncatch_error can
7740 be called from a signal handler.
7743 struct x_error_message_stack
{
7744 char string
[X_ERROR_MESSAGE_SIZE
];
7746 struct x_error_message_stack
*prev
;
7748 static struct x_error_message_stack
*x_error_message
;
7750 /* An X error handler which stores the error message in
7751 *x_error_message. This is called from x_error_handler if
7752 x_catch_errors is in effect. */
7755 x_error_catcher (display
, error
)
7759 XGetErrorText (display
, error
->error_code
,
7760 x_error_message
->string
,
7761 X_ERROR_MESSAGE_SIZE
);
7764 /* Begin trapping X errors for display DPY. Actually we trap X errors
7765 for all displays, but DPY should be the display you are actually
7768 After calling this function, X protocol errors no longer cause
7769 Emacs to exit; instead, they are recorded in the string
7770 stored in *x_error_message.
7772 Calling x_check_errors signals an Emacs error if an X error has
7773 occurred since the last call to x_catch_errors or x_check_errors.
7775 Calling x_uncatch_errors resumes the normal error handling. */
7777 void x_check_errors ();
7780 x_catch_errors (dpy
)
7783 struct x_error_message_stack
*data
= xmalloc (sizeof (*data
));
7785 /* Make sure any errors from previous requests have been dealt with. */
7789 data
->string
[0] = 0;
7790 data
->prev
= x_error_message
;
7791 x_error_message
= data
;
7794 /* Undo the last x_catch_errors call.
7795 DPY should be the display that was passed to x_catch_errors. */
7800 struct x_error_message_stack
*tmp
;
7804 /* The display may have been closed before this function is called.
7805 Check if it is still open before calling XSync. */
7806 if (x_display_info_for_display (x_error_message
->dpy
) != 0)
7807 XSync (x_error_message
->dpy
, False
);
7809 tmp
= x_error_message
;
7810 x_error_message
= x_error_message
->prev
;
7815 /* If any X protocol errors have arrived since the last call to
7816 x_catch_errors or x_check_errors, signal an Emacs error using
7817 sprintf (a buffer, FORMAT, the x error message text) as the text. */
7820 x_check_errors (dpy
, format
)
7824 /* Make sure to catch any errors incurred so far. */
7827 if (x_error_message
->string
[0])
7829 char string
[X_ERROR_MESSAGE_SIZE
];
7830 bcopy (x_error_message
->string
, string
, X_ERROR_MESSAGE_SIZE
);
7831 x_uncatch_errors ();
7832 error (format
, string
);
7836 /* Nonzero if we had any X protocol errors
7837 since we did x_catch_errors on DPY. */
7840 x_had_errors_p (dpy
)
7843 /* Make sure to catch any errors incurred so far. */
7846 return x_error_message
->string
[0] != 0;
7849 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
7852 x_clear_errors (dpy
)
7855 x_error_message
->string
[0] = 0;
7858 /* Close off all unclosed x_catch_errors calls. */
7861 x_fully_uncatch_errors ()
7863 while (x_error_message
)
7864 x_uncatch_errors ();
7867 /* Nonzero if x_catch_errors has been done and not yet canceled. */
7870 x_catching_errors ()
7872 return x_error_message
!= 0;
7876 static unsigned int x_wire_count
;
7879 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
7884 /* Handle SIGPIPE, which can happen when the connection to a server
7885 simply goes away. SIGPIPE is handled by x_connection_signal.
7886 Don't need to do anything, because the write which caused the
7887 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
7888 which will do the appropriate cleanup for us. */
7891 x_connection_signal (signalnum
) /* If we don't have an argument, */
7892 int signalnum
; /* some compilers complain in signal calls. */
7895 /* USG systems forget handlers when they are used;
7896 must reestablish each time */
7897 signal (signalnum
, x_connection_signal
);
7902 /************************************************************************
7904 ************************************************************************/
7906 /* Error message passed to x_connection_closed. */
7908 static char *error_msg
;
7910 /* Function installed as fatal_error_signal_hook in
7911 x_connection_closed. Print the X error message, and exit normally,
7912 instead of dumping core when XtCloseDisplay fails. */
7915 x_fatal_error_signal ()
7917 fprintf (stderr
, "%s\n", error_msg
);
7921 /* Handle the loss of connection to display DPY. ERROR_MESSAGE is
7922 the text of an error message that lead to the connection loss. */
7925 x_connection_closed (dpy
, error_message
)
7927 char *error_message
;
7929 struct x_display_info
*dpyinfo
= x_display_info_for_display (dpy
);
7930 Lisp_Object frame
, tail
;
7932 error_msg
= (char *) alloca (strlen (error_message
) + 1);
7933 strcpy (error_msg
, error_message
);
7934 handling_signal
= 0;
7936 /* Prevent being called recursively because of an error condition
7937 below. Otherwise, we might end up with printing ``can't find per
7938 display information'' in the recursive call instead of printing
7939 the original message here. */
7940 x_catch_errors (dpy
);
7942 /* We have to close the display to inform Xt that it doesn't
7943 exist anymore. If we don't, Xt will continue to wait for
7944 events from the display. As a consequence, a sequence of
7946 M-x make-frame-on-display RET :1 RET
7947 ...kill the new frame, so that we get an IO error...
7948 M-x make-frame-on-display RET :1 RET
7950 will indefinitely wait in Xt for events for display `:1', opened
7951 in the first class to make-frame-on-display.
7953 Closing the display is reported to lead to a bus error on
7954 OpenWindows in certain situations. I suspect that is a bug
7955 in OpenWindows. I don't know how to cicumvent it here. */
7957 #ifdef USE_X_TOOLKIT
7958 /* If DPYINFO is null, this means we didn't open the display
7959 in the first place, so don't try to close it. */
7962 extern void (*fatal_error_signal_hook
) P_ ((void));
7963 fatal_error_signal_hook
= x_fatal_error_signal
;
7964 XtCloseDisplay (dpy
);
7965 fatal_error_signal_hook
= NULL
;
7971 xg_display_close (dpyinfo
->display
);
7974 /* Indicate that this display is dead. */
7976 dpyinfo
->display
= 0;
7978 /* First delete frames whose mini-buffers are on frames
7979 that are on the dead display. */
7980 FOR_EACH_FRAME (tail
, frame
)
7982 Lisp_Object minibuf_frame
;
7984 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
7985 if (FRAME_X_P (XFRAME (frame
))
7986 && FRAME_X_P (XFRAME (minibuf_frame
))
7987 && ! EQ (frame
, minibuf_frame
)
7988 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame
)) == dpyinfo
)
7989 Fdelete_frame (frame
, Qt
);
7992 /* Now delete all remaining frames on the dead display.
7993 We are now sure none of these is used as the mini-buffer
7994 for another frame that we need to delete. */
7995 FOR_EACH_FRAME (tail
, frame
)
7996 if (FRAME_X_P (XFRAME (frame
))
7997 && FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
7999 /* Set this to t so that Fdelete_frame won't get confused
8000 trying to find a replacement. */
8001 FRAME_KBOARD (XFRAME (frame
))->Vdefault_minibuffer_frame
= Qt
;
8002 Fdelete_frame (frame
, Qt
);
8006 x_delete_display (dpyinfo
);
8008 x_uncatch_errors ();
8010 if (x_display_list
== 0)
8012 fprintf (stderr
, "%s\n", error_msg
);
8013 shut_down_emacs (0, 0, Qnil
);
8017 /* Ordinary stack unwind doesn't deal with these. */
8019 sigunblock (sigmask (SIGIO
));
8021 sigunblock (sigmask (SIGALRM
));
8022 TOTALLY_UNBLOCK_INPUT
;
8024 clear_waiting_for_input ();
8025 error ("%s", error_msg
);
8028 /* We specifically use it before defining it, so that gcc doesn't inline it,
8029 otherwise gdb doesn't know how to properly put a breakpoint on it. */
8030 static void x_error_quitter
P_ ((Display
*, XErrorEvent
*));
8032 /* This is the first-level handler for X protocol errors.
8033 It calls x_error_quitter or x_error_catcher. */
8036 x_error_handler (display
, error
)
8040 if (x_error_message
)
8041 x_error_catcher (display
, error
);
8043 x_error_quitter (display
, error
);
8047 /* This is the usual handler for X protocol errors.
8048 It kills all frames on the display that we got the error for.
8049 If that was the only one, it prints an error message and kills Emacs. */
8051 /* .gdbinit puts a breakpoint here, so make sure it is not inlined. */
8053 #if __GNUC__ >= 3 /* On GCC 3.0 we might get a warning. */
8054 #define NO_INLINE __attribute__((noinline))
8059 /* Some versions of GNU/Linux define noinline in their headers. */
8065 /* On older GCC versions, just putting x_error_quitter
8066 after x_error_handler prevents inlining into the former. */
8068 static void NO_INLINE
8069 x_error_quitter (display
, error
)
8073 char buf
[256], buf1
[356];
8075 /* Ignore BadName errors. They can happen because of fonts
8076 or colors that are not defined. */
8078 if (error
->error_code
== BadName
)
8081 /* Note that there is no real way portable across R3/R4 to get the
8082 original error handler. */
8084 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
8085 sprintf (buf1
, "X protocol error: %s on protocol request %d",
8086 buf
, error
->request_code
);
8087 x_connection_closed (display
, buf1
);
8091 /* This is the handler for X IO errors, always.
8092 It kills all frames on the display that we lost touch with.
8093 If that was the only one, it prints an error message and kills Emacs. */
8096 x_io_error_quitter (display
)
8101 sprintf (buf
, "Connection lost to X server `%s'", DisplayString (display
));
8102 x_connection_closed (display
, buf
);
8106 /* Changing the font of the frame. */
8108 /* Give frame F the font named FONTNAME as its default font, and
8109 return the full name of that font. FONTNAME may be a wildcard
8110 pattern; in that case, we choose some font that fits the pattern.
8111 The return value shows which font we chose. */
8114 x_new_font (f
, fontname
)
8116 register char *fontname
;
8118 struct font_info
*fontp
8119 = FS_LOAD_FONT (f
, fontname
);
8124 if (FRAME_FONT (f
) == (XFontStruct
*) (fontp
->font
))
8125 /* This font is already set in frame F. There's nothing more to
8127 return build_string (fontp
->full_name
);
8129 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
8130 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
8131 FRAME_FONTSET (f
) = -1;
8133 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
8134 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
8135 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
8137 compute_fringe_widths (f
, 1);
8139 /* Compute the scroll bar width in character columns. */
8140 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
8142 int wid
= FRAME_COLUMN_WIDTH (f
);
8143 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
8144 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
8148 int wid
= FRAME_COLUMN_WIDTH (f
);
8149 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
8152 /* Now make the frame display the given font. */
8153 if (FRAME_X_WINDOW (f
) != 0)
8155 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
8156 FRAME_FONT (f
)->fid
);
8157 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
8158 FRAME_FONT (f
)->fid
);
8159 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
8160 FRAME_FONT (f
)->fid
);
8162 /* Don't change the size of a tip frame; there's no point in
8163 doing it because it's done in Fx_show_tip, and it leads to
8164 problems because the tip frame has no widget. */
8165 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
8166 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
8169 return build_string (fontp
->full_name
);
8172 /* Give frame F the fontset named FONTSETNAME as its default fontset,
8173 and return the full name of that fontset. FONTSETNAME may be a
8174 wildcard pattern; in that case, we choose some fontset that fits
8175 the pattern. FONTSETNAME may be a font name for ASCII characters;
8176 in that case, we create a fontset from that font name.
8178 The return value shows which fontset we chose.
8179 If FONTSETNAME specifies the default fontset, return Qt.
8180 If an ASCII font in the specified fontset can't be loaded, return
8184 x_new_fontset (f
, fontsetname
)
8186 Lisp_Object fontsetname
;
8188 int fontset
= fs_query_fontset (fontsetname
, 0);
8191 if (fontset
> 0 && f
->output_data
.x
->fontset
== fontset
)
8192 /* This fontset is already set in frame F. There's nothing more
8194 return fontset_name (fontset
);
8195 else if (fontset
== 0)
8196 /* The default fontset can't be the default font. */
8200 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
8202 result
= x_new_font (f
, SDATA (fontsetname
));
8204 if (!STRINGP (result
))
8205 /* Can't load ASCII font. */
8209 fontset
= new_fontset_from_font_name (result
);
8211 /* Since x_new_font doesn't update any fontset information, do it now. */
8212 FRAME_FONTSET (f
) = fontset
;
8216 && (FRAME_XIC_STYLE (f
) & (XIMPreeditPosition
| XIMStatusArea
)))
8217 xic_set_xfontset (f
, SDATA (fontset_ascii (fontset
)));
8220 return fontset_name (fontset
);
8223 #ifdef USE_FONT_BACKEND
8225 x_new_fontset2 (f
, fontset
, font_object
)
8228 Lisp_Object font_object
;
8230 struct font
*font
= XSAVE_VALUE (font_object
)->pointer
;
8232 if (FRAME_FONT_OBJECT (f
) == font
)
8233 /* This font is already set in frame F. There's nothing more to
8235 return fontset_name (fontset
);
8239 FRAME_FONT_OBJECT (f
) = font
;
8240 FRAME_FONT (f
) = font
->font
.font
;
8241 FRAME_BASELINE_OFFSET (f
) = font
->font
.baseline_offset
;
8242 FRAME_FONTSET (f
) = fontset
;
8244 FRAME_COLUMN_WIDTH (f
) = font
->font
.average_width
;
8245 FRAME_SPACE_WIDTH (f
) = font
->font
.space_width
;
8246 FRAME_LINE_HEIGHT (f
) = font
->font
.height
;
8248 compute_fringe_widths (f
, 1);
8250 /* Compute the scroll bar width in character columns. */
8251 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
8253 int wid
= FRAME_COLUMN_WIDTH (f
);
8254 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
8255 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
- 1) / wid
;
8259 int wid
= FRAME_COLUMN_WIDTH (f
);
8260 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
8263 /* Now make the frame display the given font. */
8264 if (FRAME_X_WINDOW (f
) != 0)
8266 /* Don't change the size of a tip frame; there's no point in
8267 doing it because it's done in Fx_show_tip, and it leads to
8268 problems because the tip frame has no widget. */
8269 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
8270 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
8275 && (FRAME_XIC_STYLE (f
) & (XIMPreeditPosition
| XIMStatusArea
)))
8276 xic_set_xfontset (f
, SDATA (fontset_ascii (fontset
)));
8281 return fontset_name (fontset
);
8283 #endif /* USE_FONT_BACKEND */
8286 /***********************************************************************
8288 ***********************************************************************/
8294 /* XIM destroy callback function, which is called whenever the
8295 connection to input method XIM dies. CLIENT_DATA contains a
8296 pointer to the x_display_info structure corresponding to XIM. */
8299 xim_destroy_callback (xim
, client_data
, call_data
)
8301 XPointer client_data
;
8304 struct x_display_info
*dpyinfo
= (struct x_display_info
*) client_data
;
8305 Lisp_Object frame
, tail
;
8309 /* No need to call XDestroyIC.. */
8310 FOR_EACH_FRAME (tail
, frame
)
8312 struct frame
*f
= XFRAME (frame
);
8313 if (FRAME_X_DISPLAY_INFO (f
) == dpyinfo
)
8315 FRAME_XIC (f
) = NULL
;
8316 xic_free_xfontset (f
);
8320 /* No need to call XCloseIM. */
8321 dpyinfo
->xim
= NULL
;
8322 XFree (dpyinfo
->xim_styles
);
8326 #endif /* HAVE_X11R6 */
8329 /* This isn't prototyped in OSF 5.0 or 5.1a. */
8330 extern char *XSetIMValues
P_ ((XIM
, ...));
8333 /* Open the connection to the XIM server on display DPYINFO.
8334 RESOURCE_NAME is the resource name Emacs uses. */
8337 xim_open_dpy (dpyinfo
, resource_name
)
8338 struct x_display_info
*dpyinfo
;
8339 char *resource_name
;
8346 xim
= XOpenIM (dpyinfo
->display
, dpyinfo
->xrdb
, resource_name
,
8353 XIMCallback destroy
;
8356 /* Get supported styles and XIM values. */
8357 XGetIMValues (xim
, XNQueryInputStyle
, &dpyinfo
->xim_styles
, NULL
);
8360 destroy
.callback
= xim_destroy_callback
;
8361 destroy
.client_data
= (XPointer
)dpyinfo
;
8362 XSetIMValues (xim
, XNDestroyCallback
, &destroy
, NULL
);
8368 #endif /* HAVE_XIM */
8369 dpyinfo
->xim
= NULL
;
8373 #ifdef HAVE_X11R6_XIM
8377 struct x_display_info
*dpyinfo
;
8378 char *resource_name
;
8381 /* XIM instantiate callback function, which is called whenever an XIM
8382 server is available. DISPLAY is the display of the XIM.
8383 CLIENT_DATA contains a pointer to an xim_inst_t structure created
8384 when the callback was registered. */
8387 xim_instantiate_callback (display
, client_data
, call_data
)
8389 XPointer client_data
;
8392 struct xim_inst_t
*xim_inst
= (struct xim_inst_t
*) client_data
;
8393 struct x_display_info
*dpyinfo
= xim_inst
->dpyinfo
;
8395 /* We don't support multiple XIM connections. */
8399 xim_open_dpy (dpyinfo
, xim_inst
->resource_name
);
8401 /* Create XIC for the existing frames on the same display, as long
8402 as they have no XIC. */
8403 if (dpyinfo
->xim
&& dpyinfo
->reference_count
> 0)
8405 Lisp_Object tail
, frame
;
8408 FOR_EACH_FRAME (tail
, frame
)
8410 struct frame
*f
= XFRAME (frame
);
8412 if (FRAME_X_DISPLAY_INFO (f
) == xim_inst
->dpyinfo
)
8413 if (FRAME_XIC (f
) == NULL
)
8415 create_frame_xic (f
);
8416 if (FRAME_XIC_STYLE (f
) & XIMStatusArea
)
8417 xic_set_statusarea (f
);
8418 if (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
)
8420 struct window
*w
= XWINDOW (f
->selected_window
);
8421 xic_set_preeditarea (w
, w
->cursor
.x
, w
->cursor
.y
);
8430 #endif /* HAVE_X11R6_XIM */
8433 /* Open a connection to the XIM server on display DPYINFO.
8434 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
8435 connection only at the first time. On X11R6, open the connection
8436 in the XIM instantiate callback function. */
8439 xim_initialize (dpyinfo
, resource_name
)
8440 struct x_display_info
*dpyinfo
;
8441 char *resource_name
;
8446 #ifdef HAVE_X11R6_XIM
8447 struct xim_inst_t
*xim_inst
;
8450 dpyinfo
->xim
= NULL
;
8451 xim_inst
= (struct xim_inst_t
*) xmalloc (sizeof (struct xim_inst_t
));
8452 xim_inst
->dpyinfo
= dpyinfo
;
8453 len
= strlen (resource_name
);
8454 xim_inst
->resource_name
= (char *) xmalloc (len
+ 1);
8455 bcopy (resource_name
, xim_inst
->resource_name
, len
+ 1);
8456 XRegisterIMInstantiateCallback (dpyinfo
->display
, dpyinfo
->xrdb
,
8457 resource_name
, EMACS_CLASS
,
8458 xim_instantiate_callback
,
8459 /* This is XPointer in XFree86
8460 but (XPointer *) on Tru64, at
8461 least, hence the configure test. */
8462 (XRegisterIMInstantiateCallback_arg6
) xim_inst
);
8463 #else /* not HAVE_X11R6_XIM */
8464 dpyinfo
->xim
= NULL
;
8465 xim_open_dpy (dpyinfo
, resource_name
);
8466 #endif /* not HAVE_X11R6_XIM */
8470 #endif /* HAVE_XIM */
8471 dpyinfo
->xim
= NULL
;
8475 /* Close the connection to the XIM server on display DPYINFO. */
8478 xim_close_dpy (dpyinfo
)
8479 struct x_display_info
*dpyinfo
;
8484 #ifdef HAVE_X11R6_XIM
8485 if (dpyinfo
->display
)
8486 XUnregisterIMInstantiateCallback (dpyinfo
->display
, dpyinfo
->xrdb
,
8488 xim_instantiate_callback
, NULL
);
8489 #endif /* not HAVE_X11R6_XIM */
8490 if (dpyinfo
->display
)
8491 XCloseIM (dpyinfo
->xim
);
8492 dpyinfo
->xim
= NULL
;
8493 XFree (dpyinfo
->xim_styles
);
8495 #endif /* HAVE_XIM */
8498 #endif /* not HAVE_X11R6_XIM */
8502 /* Calculate the absolute position in frame F
8503 from its current recorded position values and gravity. */
8506 x_calc_absolute_position (f
)
8509 int flags
= f
->size_hint_flags
;
8511 /* We have nothing to do if the current position
8512 is already for the top-left corner. */
8513 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
8516 /* Treat negative positions as relative to the leftmost bottommost
8517 position that fits on the screen. */
8518 if (flags
& XNegative
)
8519 f
->left_pos
= (FRAME_X_DISPLAY_INFO (f
)->width
8520 - FRAME_PIXEL_WIDTH (f
) + f
->left_pos
);
8523 int height
= FRAME_PIXEL_HEIGHT (f
);
8525 #if defined USE_X_TOOLKIT && defined USE_MOTIF
8526 /* Something is fishy here. When using Motif, starting Emacs with
8527 `-g -0-0', the frame appears too low by a few pixels.
8529 This seems to be so because initially, while Emacs is starting,
8530 the column widget's height and the frame's pixel height are
8531 different. The column widget's height is the right one. In
8532 later invocations, when Emacs is up, the frame's pixel height
8535 It's not obvious where the initial small difference comes from.
8536 2000-12-01, gerd. */
8538 XtVaGetValues (f
->output_data
.x
->column_widget
, XtNheight
, &height
, NULL
);
8541 if (flags
& YNegative
)
8542 f
->top_pos
= (FRAME_X_DISPLAY_INFO (f
)->height
- height
+ f
->top_pos
);
8545 /* The left_pos and top_pos
8546 are now relative to the top and left screen edges,
8547 so the flags should correspond. */
8548 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
8551 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
8552 to really change the position, and 0 when calling from
8553 x_make_frame_visible (in that case, XOFF and YOFF are the current
8554 position values). It is -1 when calling from x_set_frame_parameters,
8555 which means, do adjust for borders but don't change the gravity. */
8558 x_set_offset (f
, xoff
, yoff
, change_gravity
)
8560 register int xoff
, yoff
;
8563 int modified_top
, modified_left
;
8565 if (change_gravity
!= 0)
8567 FRAME_X_OUTPUT (f
)->left_before_move
= f
->left_pos
;
8568 FRAME_X_OUTPUT (f
)->top_before_move
= f
->top_pos
;
8572 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
8574 f
->size_hint_flags
|= XNegative
;
8576 f
->size_hint_flags
|= YNegative
;
8577 f
->win_gravity
= NorthWestGravity
;
8579 x_calc_absolute_position (f
);
8582 x_wm_set_size_hint (f
, (long) 0, 0);
8584 modified_left
= f
->left_pos
;
8585 modified_top
= f
->top_pos
;
8587 if (change_gravity
!= 0 && FRAME_X_DISPLAY_INFO (f
)->wm_type
== X_WMTYPE_A
)
8589 /* Some WMs (twm, wmaker at least) has an offset that is smaller
8590 than the WM decorations. So we use the calculated offset instead
8591 of the WM decoration sizes here (x/y_pixels_outer_diff). */
8592 modified_left
+= FRAME_X_OUTPUT (f
)->move_offset_left
;
8593 modified_top
+= FRAME_X_OUTPUT (f
)->move_offset_top
;
8596 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
8597 modified_left
, modified_top
);
8599 x_sync_with_move (f
, f
->left_pos
, f
->top_pos
,
8600 FRAME_X_DISPLAY_INFO (f
)->wm_type
== X_WMTYPE_UNKNOWN
8603 /* change_gravity is non-zero when this function is called from Lisp to
8604 programmatically move a frame. In that case, we call
8605 x_check_expected_move to discover if we have a "Type A" or "Type B"
8606 window manager, and, for a "Type A" window manager, adjust the position
8609 We call x_check_expected_move if a programmatic move occurred, and
8610 either the window manager type (A/B) is unknown or it is Type A but we
8611 need to compute the top/left offset adjustment for this frame. */
8613 if (change_gravity
!= 0 &&
8614 (FRAME_X_DISPLAY_INFO (f
)->wm_type
== X_WMTYPE_UNKNOWN
8615 || (FRAME_X_DISPLAY_INFO (f
)->wm_type
== X_WMTYPE_A
8616 && (FRAME_X_OUTPUT (f
)->move_offset_left
== 0
8617 && FRAME_X_OUTPUT (f
)->move_offset_top
== 0))))
8618 x_check_expected_move (f
, modified_left
, modified_top
);
8623 /* Return non-zero if _NET_SUPPORTING_WM_CHECK window exists and _NET_SUPPORTED
8624 on the root window for frame F contains ATOMNAME.
8625 This is how a WM check shall be done according to the Window Manager
8626 Specification/Extended Window Manager Hints at
8627 http://freedesktop.org/wiki/Standards_2fwm_2dspec. */
8630 wm_supports (f
, atomname
)
8632 const char *atomname
;
8635 unsigned long actual_size
, bytes_remaining
;
8636 int i
, rc
, actual_format
;
8638 Window wmcheck_window
;
8639 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
8640 Window target_window
= dpyinfo
->root_window
;
8641 long max_len
= 65536;
8642 Display
*dpy
= FRAME_X_DISPLAY (f
);
8643 unsigned char *tmp_data
= NULL
;
8644 Atom target_type
= XA_WINDOW
;
8649 prop_atom
= XInternAtom (dpy
, "_NET_SUPPORTING_WM_CHECK", False
);
8651 x_catch_errors (dpy
);
8652 rc
= XGetWindowProperty (dpy
, target_window
,
8653 prop_atom
, 0, max_len
, False
, target_type
,
8654 &actual_type
, &actual_format
, &actual_size
,
8655 &bytes_remaining
, &tmp_data
);
8657 if (rc
!= Success
|| actual_type
!= XA_WINDOW
|| x_had_errors_p (dpy
))
8659 if (tmp_data
) XFree (tmp_data
);
8660 x_uncatch_errors ();
8665 wmcheck_window
= *(Window
*) tmp_data
;
8668 /* Check if window exists. */
8669 XSelectInput (dpy
, wmcheck_window
, StructureNotifyMask
);
8671 if (x_had_errors_p (dpy
))
8673 x_uncatch_errors ();
8678 if (dpyinfo
->net_supported_window
!= wmcheck_window
)
8680 /* Window changed, reload atoms */
8681 if (dpyinfo
->net_supported_atoms
!= NULL
)
8682 XFree (dpyinfo
->net_supported_atoms
);
8683 dpyinfo
->net_supported_atoms
= NULL
;
8684 dpyinfo
->nr_net_supported_atoms
= 0;
8685 dpyinfo
->net_supported_window
= 0;
8687 target_type
= XA_ATOM
;
8688 prop_atom
= XInternAtom (dpy
, "_NET_SUPPORTED", False
);
8690 rc
= XGetWindowProperty (dpy
, target_window
,
8691 prop_atom
, 0, max_len
, False
, target_type
,
8692 &actual_type
, &actual_format
, &actual_size
,
8693 &bytes_remaining
, &tmp_data
);
8695 if (rc
!= Success
|| actual_type
!= XA_ATOM
|| x_had_errors_p (dpy
))
8697 if (tmp_data
) XFree (tmp_data
);
8698 x_uncatch_errors ();
8703 dpyinfo
->net_supported_atoms
= (Atom
*)tmp_data
;
8704 dpyinfo
->nr_net_supported_atoms
= actual_size
;
8705 dpyinfo
->net_supported_window
= wmcheck_window
;
8709 want_atom
= XInternAtom (dpy
, atomname
, False
);
8711 for (i
= 0; rc
== 0 && i
< dpyinfo
->nr_net_supported_atoms
; ++i
)
8712 rc
= dpyinfo
->net_supported_atoms
[i
] == want_atom
;
8714 x_uncatch_errors ();
8720 /* Do fullscreen as specified in extended window manager hints */
8723 do_ewmh_fullscreen (f
)
8726 int have_net_atom
= wm_supports (f
, "_NET_WM_STATE");
8728 /* Some window managers don't say they support _NET_WM_STATE, but they do say
8729 they support _NET_WM_STATE_FULLSCREEN. Try that also. */
8731 have_net_atom
= wm_supports (f
, "_NET_WM_STATE_FULLSCREEN");
8736 const char *atom
= "_NET_WM_STATE";
8737 const char *fs
= "_NET_WM_STATE_FULLSCREEN";
8738 const char *fw
= "_NET_WM_STATE_MAXIMIZED_HORZ";
8739 const char *fh
= "_NET_WM_STATE_MAXIMIZED_VERT";
8740 const char *what
= NULL
;
8742 XSETFRAME (frame
, f
);
8744 /* If there are _NET_ atoms we assume we have extended window manager
8746 switch (f
->want_fullscreen
)
8748 case FULLSCREEN_BOTH
:
8751 case FULLSCREEN_WIDTH
:
8754 case FULLSCREEN_HEIGHT
:
8759 if (what
!= NULL
&& !wm_supports (f
, what
)) return 0;
8762 Fx_send_client_event (frame
, make_number (0), frame
,
8763 make_unibyte_string (atom
, strlen (atom
)),
8765 Fcons (make_number (0), /* Remove */
8767 (make_unibyte_string (fs
,
8770 Fx_send_client_event (frame
, make_number (0), frame
,
8771 make_unibyte_string (atom
, strlen (atom
)),
8773 Fcons (make_number (0), /* Remove */
8775 (make_unibyte_string (fh
,
8778 Fx_send_client_event (frame
, make_number (0), frame
,
8779 make_unibyte_string (atom
, strlen (atom
)),
8781 Fcons (make_number (0), /* Remove */
8783 (make_unibyte_string (fw
,
8786 f
->want_fullscreen
= FULLSCREEN_NONE
;
8788 Fx_send_client_event (frame
, make_number (0), frame
,
8789 make_unibyte_string (atom
, strlen (atom
)),
8791 Fcons (make_number (1), /* Add */
8793 (make_unibyte_string (what
,
8798 return have_net_atom
;
8802 XTfullscreen_hook (f
)
8805 if (f
->async_visible
)
8808 do_ewmh_fullscreen (f
);
8815 /* Check if we need to resize the frame due to a fullscreen request.
8816 If so needed, resize the frame. */
8818 x_check_fullscreen (f
)
8821 if (f
->want_fullscreen
& FULLSCREEN_BOTH
)
8823 int width
, height
, ign
;
8825 if (do_ewmh_fullscreen (f
))
8828 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
8830 x_fullscreen_adjust (f
, &width
, &height
, &ign
, &ign
);
8832 /* We do not need to move the window, it shall be taken care of
8833 when setting WM manager hints.
8834 If the frame is visible already, the position is checked by
8835 x_check_expected_move. */
8836 if (FRAME_COLS (f
) != width
|| FRAME_LINES (f
) != height
)
8838 change_frame_size (f
, height
, width
, 0, 1, 0);
8839 SET_FRAME_GARBAGED (f
);
8840 cancel_mouse_face (f
);
8842 /* Wait for the change of frame size to occur */
8843 f
->want_fullscreen
|= FULLSCREEN_WAIT
;
8848 /* This function is called by x_set_offset to determine whether the window
8849 manager interfered with the positioning of the frame. Type A window
8850 managers position the surrounding window manager decorations a small
8851 amount above and left of the user-supplied position. Type B window
8852 managers position the surrounding window manager decorations at the
8853 user-specified position. If we detect a Type A window manager, we
8854 compensate by moving the window right and down by the proper amount. */
8857 x_check_expected_move (f
, expected_left
, expected_top
)
8862 int current_left
= 0, current_top
= 0;
8864 /* x_real_positions returns the left and top offsets of the outermost
8865 window manager window around the frame. */
8867 x_real_positions (f
, ¤t_left
, ¤t_top
);
8869 if (current_left
!= expected_left
|| current_top
!= expected_top
)
8871 /* It's a "Type A" window manager. */
8876 FRAME_X_DISPLAY_INFO (f
)->wm_type
= X_WMTYPE_A
;
8877 FRAME_X_OUTPUT (f
)->move_offset_left
= expected_left
- current_left
;
8878 FRAME_X_OUTPUT (f
)->move_offset_top
= expected_top
- current_top
;
8880 /* Now fix the mispositioned frame's location. */
8882 adjusted_left
= expected_left
+ FRAME_X_OUTPUT (f
)->move_offset_left
;
8883 adjusted_top
= expected_top
+ FRAME_X_OUTPUT (f
)->move_offset_top
;
8885 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
8886 adjusted_left
, adjusted_top
);
8888 x_sync_with_move (f
, expected_left
, expected_top
, 0);
8891 /* It's a "Type B" window manager. We don't have to adjust the
8892 frame's position. */
8894 FRAME_X_DISPLAY_INFO (f
)->wm_type
= X_WMTYPE_B
;
8898 /* Wait for XGetGeometry to return up-to-date position information for a
8899 recently-moved frame. Call this immediately after calling XMoveWindow.
8900 If FUZZY is non-zero, then LEFT and TOP are just estimates of where the
8901 frame has been moved to, so we use a fuzzy position comparison instead
8902 of an exact comparison. */
8905 x_sync_with_move (f
, left
, top
, fuzzy
)
8907 int left
, top
, fuzzy
;
8911 while (count
++ < 50)
8913 int current_left
= 0, current_top
= 0;
8915 /* In theory, this call to XSync only needs to happen once, but in
8916 practice, it doesn't seem to work, hence the need for the surrounding
8919 XSync (FRAME_X_DISPLAY (f
), False
);
8920 x_real_positions (f
, ¤t_left
, ¤t_top
);
8924 /* The left fuzz-factor is 10 pixels. The top fuzz-factor is 40
8927 if (abs (current_left
- left
) <= 10 && abs (current_top
- top
) <= 40)
8930 else if (current_left
== left
&& current_top
== top
)
8934 /* As a last resort, just wait 0.5 seconds and hope that XGetGeometry
8935 will then return up-to-date position info. */
8937 wait_reading_process_output (0, 500000, 0, 0, Qnil
, NULL
, 0);
8941 /* Change the size of frame F's X window to COLS/ROWS in the case F
8942 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
8943 top-left-corner window gravity for this size change and subsequent
8944 size changes. Otherwise we leave the window gravity unchanged. */
8947 x_set_window_size_1 (f
, change_gravity
, cols
, rows
)
8952 int pixelwidth
, pixelheight
;
8954 check_frame_size (f
, &rows
, &cols
);
8955 f
->scroll_bar_actual_width
8956 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
8958 : FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0
8959 ? FRAME_CONFIG_SCROLL_BAR_WIDTH (f
)
8960 : (FRAME_CONFIG_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
)));
8962 compute_fringe_widths (f
, 0);
8964 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
8965 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
8967 f
->win_gravity
= NorthWestGravity
;
8968 x_wm_set_size_hint (f
, (long) 0, 0);
8970 XSync (FRAME_X_DISPLAY (f
), False
);
8971 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8972 pixelwidth
, pixelheight
);
8974 /* Now, strictly speaking, we can't be sure that this is accurate,
8975 but the window manager will get around to dealing with the size
8976 change request eventually, and we'll hear how it went when the
8977 ConfigureNotify event gets here.
8979 We could just not bother storing any of this information here,
8980 and let the ConfigureNotify event set everything up, but that
8981 might be kind of confusing to the Lisp code, since size changes
8982 wouldn't be reported in the frame parameters until some random
8983 point in the future when the ConfigureNotify event arrives.
8985 We pass 1 for DELAY since we can't run Lisp code inside of
8987 change_frame_size (f
, rows
, cols
, 0, 1, 0);
8988 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
8989 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
8991 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
8992 receive in the ConfigureNotify event; if we get what we asked
8993 for, then the event won't cause the screen to become garbaged, so
8994 we have to make sure to do it here. */
8995 SET_FRAME_GARBAGED (f
);
8997 XFlush (FRAME_X_DISPLAY (f
));
9001 /* Call this to change the size of frame F's x-window.
9002 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
9003 for this size change and subsequent size changes.
9004 Otherwise we leave the window gravity unchanged. */
9007 x_set_window_size (f
, change_gravity
, cols
, rows
)
9015 if (FRAME_GTK_WIDGET (f
))
9016 xg_frame_set_char_size (f
, cols
, rows
);
9018 x_set_window_size_1 (f
, change_gravity
, cols
, rows
);
9021 if (f
->output_data
.x
->widget
!= NULL
)
9023 /* The x and y position of the widget is clobbered by the
9024 call to XtSetValues within EmacsFrameSetCharSize.
9025 This is a real kludge, but I don't understand Xt so I can't
9026 figure out a correct fix. Can anyone else tell me? -- rms. */
9027 int xpos
= f
->output_data
.x
->widget
->core
.x
;
9028 int ypos
= f
->output_data
.x
->widget
->core
.y
;
9029 EmacsFrameSetCharSize (f
->output_data
.x
->edit_widget
, cols
, rows
);
9030 f
->output_data
.x
->widget
->core
.x
= xpos
;
9031 f
->output_data
.x
->widget
->core
.y
= ypos
;
9034 x_set_window_size_1 (f
, change_gravity
, cols
, rows
);
9036 #else /* not USE_X_TOOLKIT */
9038 x_set_window_size_1 (f
, change_gravity
, cols
, rows
);
9040 #endif /* not USE_X_TOOLKIT */
9042 /* If cursor was outside the new size, mark it as off. */
9043 mark_window_cursors_off (XWINDOW (f
->root_window
));
9045 /* Clear out any recollection of where the mouse highlighting was,
9046 since it might be in a place that's outside the new frame size.
9047 Actually checking whether it is outside is a pain in the neck,
9048 so don't try--just let the highlighting be done afresh with new size. */
9049 cancel_mouse_face (f
);
9054 /* Mouse warping. */
9057 x_set_mouse_position (f
, x
, y
)
9063 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
9064 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
9066 if (pix_x
< 0) pix_x
= 0;
9067 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
9069 if (pix_y
< 0) pix_y
= 0;
9070 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
9074 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
9075 0, 0, 0, 0, pix_x
, pix_y
);
9079 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
9082 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
9088 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
9089 0, 0, 0, 0, pix_x
, pix_y
);
9093 /* focus shifting, raising and lowering. */
9096 x_focus_on_frame (f
)
9099 #if 0 /* This proves to be unpleasant. */
9103 /* I don't think that the ICCCM allows programs to do things like this
9104 without the interaction of the window manager. Whatever you end up
9105 doing with this code, do it to x_unfocus_frame too. */
9106 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9107 RevertToPointerRoot
, CurrentTime
);
9116 /* Look at the remarks in x_focus_on_frame. */
9117 if (FRAME_X_DISPLAY_INFO (f
)->x_focus_frame
== f
)
9118 XSetInputFocus (FRAME_X_DISPLAY (f
), PointerRoot
,
9119 RevertToPointerRoot
, CurrentTime
);
9123 /* Raise frame F. */
9130 if (f
->async_visible
)
9131 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
));
9133 XFlush (FRAME_X_DISPLAY (f
));
9137 /* Lower frame F. */
9143 if (f
->async_visible
)
9146 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
));
9147 XFlush (FRAME_X_DISPLAY (f
));
9153 XTframe_raise_lower (f
, raise_flag
)
9159 /* The following code is needed for `raise-frame' to work on
9160 some versions of metacity; see Window Manager
9161 Specification/Extended Window Manager Hints at
9162 http://freedesktop.org/wiki/Standards_2fwm_2dspec */
9165 /* However, on other versions (metacity 2.17.2-1.fc7), it
9166 reportedly causes hangs when resizing frames. */
9168 const char *atom
= "_NET_ACTIVE_WINDOW";
9169 if (f
->async_visible
&& wm_supports (f
, atom
))
9172 XSETFRAME (frame
, f
);
9173 Fx_send_client_event (frame
, make_number (0), frame
,
9174 make_unibyte_string (atom
, strlen (atom
)),
9176 Fcons (make_number (1),
9177 Fcons (make_number (last_user_time
),
9188 /* Change of visibility. */
9190 /* This tries to wait until the frame is really visible.
9191 However, if the window manager asks the user where to position
9192 the frame, this will return before the user finishes doing that.
9193 The frame will not actually be visible at that time,
9194 but it will become visible later when the window manager
9195 finishes with it. */
9198 x_make_frame_visible (f
)
9202 int original_top
, original_left
;
9203 int retry_count
= 2;
9209 type
= x_icon_type (f
);
9211 x_bitmap_icon (f
, type
);
9213 if (! FRAME_VISIBLE_P (f
))
9215 /* We test FRAME_GARBAGED_P here to make sure we don't
9216 call x_set_offset a second time
9217 if we get to x_make_frame_visible a second time
9218 before the window gets really visible. */
9219 if (! FRAME_ICONIFIED_P (f
)
9220 && ! f
->output_data
.x
->asked_for_visible
)
9221 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
9223 f
->output_data
.x
->asked_for_visible
= 1;
9225 if (! EQ (Vx_no_window_manager
, Qt
))
9226 x_wm_set_window_state (f
, NormalState
);
9227 #ifdef USE_X_TOOLKIT
9228 /* This was XtPopup, but that did nothing for an iconified frame. */
9229 XtMapWidget (f
->output_data
.x
->widget
);
9230 #else /* not USE_X_TOOLKIT */
9232 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f
));
9233 gtk_window_deiconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f
)));
9235 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
9236 #endif /* not USE_GTK */
9237 #endif /* not USE_X_TOOLKIT */
9238 #if 0 /* This seems to bring back scroll bars in the wrong places
9239 if the window configuration has changed. They seem
9240 to come back ok without this. */
9241 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
9242 XMapSubwindows (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
9246 XFlush (FRAME_X_DISPLAY (f
));
9248 /* Synchronize to ensure Emacs knows the frame is visible
9249 before we do anything else. We do this loop with input not blocked
9250 so that incoming events are handled. */
9254 /* This must be before UNBLOCK_INPUT
9255 since events that arrive in response to the actions above
9256 will set it when they are handled. */
9257 int previously_visible
= f
->output_data
.x
->has_been_visible
;
9259 original_left
= f
->left_pos
;
9260 original_top
= f
->top_pos
;
9262 /* This must come after we set COUNT. */
9265 /* We unblock here so that arriving X events are processed. */
9267 /* Now move the window back to where it was "supposed to be".
9268 But don't do it if the gravity is negative.
9269 When the gravity is negative, this uses a position
9270 that is 3 pixels too low. Perhaps that's really the border width.
9272 Don't do this if the window has never been visible before,
9273 because the window manager may choose the position
9274 and we don't want to override it. */
9276 if (! FRAME_VISIBLE_P (f
) && ! FRAME_ICONIFIED_P (f
)
9277 && f
->win_gravity
== NorthWestGravity
9278 && previously_visible
)
9282 unsigned int width
, height
, border
, depth
;
9286 /* On some window managers (such as FVWM) moving an existing
9287 window, even to the same place, causes the window manager
9288 to introduce an offset. This can cause the window to move
9289 to an unexpected location. Check the geometry (a little
9290 slow here) and then verify that the window is in the right
9291 place. If the window is not in the right place, move it
9292 there, and take the potential window manager hit. */
9293 XGetGeometry (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
9294 &rootw
, &x
, &y
, &width
, &height
, &border
, &depth
);
9296 if (original_left
!= x
|| original_top
!= y
)
9297 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
9298 original_left
, original_top
);
9303 XSETFRAME (frame
, f
);
9305 /* Wait until the frame is visible. Process X events until a
9306 MapNotify event has been seen, or until we think we won't get a
9307 MapNotify at all.. */
9308 for (count
= input_signal_count
+ 10;
9309 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
9311 /* Force processing of queued events. */
9314 /* Machines that do polling rather than SIGIO have been
9315 observed to go into a busy-wait here. So we'll fake an
9316 alarm signal to let the handler know that there's something
9317 to be read. We used to raise a real alarm, but it seems
9318 that the handler isn't always enabled here. This is
9320 if (input_polling_used ())
9322 /* It could be confusing if a real alarm arrives while
9323 processing the fake one. Turn it off and let the
9324 handler reset it. */
9325 extern void poll_for_input_1
P_ ((void));
9326 int old_poll_suppress_count
= poll_suppress_count
;
9327 poll_suppress_count
= 1;
9328 poll_for_input_1 ();
9329 poll_suppress_count
= old_poll_suppress_count
;
9332 /* See if a MapNotify event has been processed. */
9333 FRAME_SAMPLE_VISIBILITY (f
);
9338 (let ((f (selected-frame)))
9342 the frame is not raised with various window managers on
9343 FreeBSD, GNU/Linux and Solaris. It turns out that, for some
9344 unknown reason, the call to XtMapWidget is completely ignored.
9345 Mapping the widget a second time works. */
9347 if (!FRAME_VISIBLE_P (f
) && --retry_count
> 0)
9352 /* Change from mapped state to withdrawn state. */
9354 /* Make the frame visible (mapped and not iconified). */
9357 x_make_frame_invisible (f
)
9362 /* Use the frame's outermost window, not the one we normally draw on. */
9363 window
= FRAME_OUTER_WINDOW (f
);
9365 /* Don't keep the highlight on an invisible frame. */
9366 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
9367 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
9369 #if 0/* This might add unreliability; I don't trust it -- rms. */
9370 if (! f
->async_visible
&& ! f
->async_iconified
)
9376 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
9377 that the current position of the window is user-specified, rather than
9378 program-specified, so that when the window is mapped again, it will be
9379 placed at the same location, without forcing the user to position it
9380 by hand again (they have already done that once for this window.) */
9381 x_wm_set_size_hint (f
, (long) 0, 1);
9384 if (FRAME_GTK_OUTER_WIDGET (f
))
9385 gtk_widget_hide (FRAME_GTK_OUTER_WIDGET (f
));
9391 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
9392 DefaultScreen (FRAME_X_DISPLAY (f
))))
9394 UNBLOCK_INPUT_RESIGNAL
;
9395 error ("Can't notify window manager of window withdrawal");
9397 #else /* ! defined (HAVE_X11R4) */
9399 /* Tell the window manager what we're going to do. */
9400 if (! EQ (Vx_no_window_manager
, Qt
))
9404 unmap
.xunmap
.type
= UnmapNotify
;
9405 unmap
.xunmap
.window
= window
;
9406 unmap
.xunmap
.event
= DefaultRootWindow (FRAME_X_DISPLAY (f
));
9407 unmap
.xunmap
.from_configure
= False
;
9408 if (! XSendEvent (FRAME_X_DISPLAY (f
),
9409 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
9411 SubstructureRedirectMaskSubstructureNotifyMask
,
9414 UNBLOCK_INPUT_RESIGNAL
;
9415 error ("Can't notify window manager of withdrawal");
9419 /* Unmap the window ourselves. Cheeky! */
9420 XUnmapWindow (FRAME_X_DISPLAY (f
), window
);
9421 #endif /* ! defined (HAVE_X11R4) */
9424 /* We can't distinguish this from iconification
9425 just by the event that we get from the server.
9426 So we can't win using the usual strategy of letting
9427 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
9428 and synchronize with the server to make sure we agree. */
9430 FRAME_ICONIFIED_P (f
) = 0;
9431 f
->async_visible
= 0;
9432 f
->async_iconified
= 0;
9439 /* Change window state from mapped to iconified. */
9448 /* Don't keep the highlight on an invisible frame. */
9449 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
9450 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
9452 if (f
->async_iconified
)
9457 FRAME_SAMPLE_VISIBILITY (f
);
9459 type
= x_icon_type (f
);
9461 x_bitmap_icon (f
, type
);
9464 if (FRAME_GTK_OUTER_WIDGET (f
))
9466 if (! FRAME_VISIBLE_P (f
))
9467 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f
));
9469 gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f
)));
9472 f
->async_iconified
= 1;
9473 f
->async_visible
= 0;
9479 #ifdef USE_X_TOOLKIT
9481 if (! FRAME_VISIBLE_P (f
))
9483 if (! EQ (Vx_no_window_manager
, Qt
))
9484 x_wm_set_window_state (f
, IconicState
);
9485 /* This was XtPopup, but that did nothing for an iconified frame. */
9486 XtMapWidget (f
->output_data
.x
->widget
);
9487 /* The server won't give us any event to indicate
9488 that an invisible frame was changed to an icon,
9489 so we have to record it here. */
9492 f
->async_iconified
= 1;
9493 f
->async_visible
= 0;
9498 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
9499 XtWindow (f
->output_data
.x
->widget
),
9500 DefaultScreen (FRAME_X_DISPLAY (f
)));
9504 error ("Can't notify window manager of iconification");
9506 f
->async_iconified
= 1;
9507 f
->async_visible
= 0;
9511 XFlush (FRAME_X_DISPLAY (f
));
9513 #else /* not USE_X_TOOLKIT */
9515 /* Make sure the X server knows where the window should be positioned,
9516 in case the user deiconifies with the window manager. */
9517 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
9518 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
9520 /* Since we don't know which revision of X we're running, we'll use both
9521 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
9523 /* X11R4: send a ClientMessage to the window manager using the
9524 WM_CHANGE_STATE type. */
9528 message
.xclient
.window
= FRAME_X_WINDOW (f
);
9529 message
.xclient
.type
= ClientMessage
;
9530 message
.xclient
.message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
9531 message
.xclient
.format
= 32;
9532 message
.xclient
.data
.l
[0] = IconicState
;
9534 if (! XSendEvent (FRAME_X_DISPLAY (f
),
9535 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
9537 SubstructureRedirectMask
| SubstructureNotifyMask
,
9540 UNBLOCK_INPUT_RESIGNAL
;
9541 error ("Can't notify window manager of iconification");
9545 /* X11R3: set the initial_state field of the window manager hints to
9547 x_wm_set_window_state (f
, IconicState
);
9549 if (!FRAME_VISIBLE_P (f
))
9551 /* If the frame was withdrawn, before, we must map it. */
9552 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
9555 f
->async_iconified
= 1;
9556 f
->async_visible
= 0;
9558 XFlush (FRAME_X_DISPLAY (f
));
9560 #endif /* not USE_X_TOOLKIT */
9564 /* Free X resources of frame F. */
9567 x_free_frame_resources (f
)
9570 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9572 struct scroll_bar
*b
;
9576 /* If a display connection is dead, don't try sending more
9577 commands to the X server. */
9578 if (dpyinfo
->display
)
9580 #ifdef USE_FONT_BACKEND
9581 /* We must free faces before destroying windows because some
9582 font-driver (e.g. xft) access a window while finishing a
9584 if (enable_font_backend
9585 && FRAME_FACE_CACHE (f
))
9586 free_frame_faces (f
);
9587 #endif /* USE_FONT_BACKEND */
9589 if (f
->output_data
.x
->icon_desc
)
9590 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->icon_desc
);
9592 #ifdef USE_X_TOOLKIT
9593 /* Explicitly destroy the scroll bars of the frame. Without
9594 this, we get "BadDrawable" errors from the toolkit later on,
9595 presumably from expose events generated for the disappearing
9596 toolkit scroll bars. */
9597 for (bar
= FRAME_SCROLL_BARS (f
); !NILP (bar
); bar
= b
->next
)
9599 b
= XSCROLL_BAR (bar
);
9600 x_scroll_bar_remove (b
);
9609 #ifdef USE_X_TOOLKIT
9610 if (f
->output_data
.x
->widget
)
9612 XtDestroyWidget (f
->output_data
.x
->widget
);
9613 f
->output_data
.x
->widget
= NULL
;
9615 /* Tooltips don't have widgets, only a simple X window, even if
9616 we are using a toolkit. */
9617 else if (FRAME_X_WINDOW (f
))
9618 XDestroyWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
9620 free_frame_menubar (f
);
9621 #else /* !USE_X_TOOLKIT */
9624 /* In the GTK version, tooltips are normal X
9625 frames. We must check and free both types. */
9626 if (FRAME_GTK_OUTER_WIDGET (f
))
9628 gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f
));
9629 FRAME_X_WINDOW (f
) = 0; /* Set to avoid XDestroyWindow below */
9630 FRAME_GTK_OUTER_WIDGET (f
) = 0;
9632 #endif /* USE_GTK */
9634 if (FRAME_X_WINDOW (f
))
9635 XDestroyWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
9636 #endif /* !USE_X_TOOLKIT */
9638 unload_color (f
, f
->output_data
.x
->foreground_pixel
);
9639 unload_color (f
, f
->output_data
.x
->background_pixel
);
9640 unload_color (f
, f
->output_data
.x
->cursor_pixel
);
9641 unload_color (f
, f
->output_data
.x
->cursor_foreground_pixel
);
9642 unload_color (f
, f
->output_data
.x
->border_pixel
);
9643 unload_color (f
, f
->output_data
.x
->mouse_pixel
);
9645 if (f
->output_data
.x
->scroll_bar_background_pixel
!= -1)
9646 unload_color (f
, f
->output_data
.x
->scroll_bar_background_pixel
);
9647 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
9648 unload_color (f
, f
->output_data
.x
->scroll_bar_foreground_pixel
);
9649 #ifdef USE_TOOLKIT_SCROLL_BARS
9650 /* Scrollbar shadow colors. */
9651 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
!= -1)
9652 unload_color (f
, f
->output_data
.x
->scroll_bar_top_shadow_pixel
);
9653 if (f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
!= -1)
9654 unload_color (f
, f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
);
9655 #endif /* USE_TOOLKIT_SCROLL_BARS */
9656 if (f
->output_data
.x
->white_relief
.allocated_p
)
9657 unload_color (f
, f
->output_data
.x
->white_relief
.pixel
);
9658 if (f
->output_data
.x
->black_relief
.allocated_p
)
9659 unload_color (f
, f
->output_data
.x
->black_relief
.pixel
);
9661 if (FRAME_FACE_CACHE (f
))
9662 free_frame_faces (f
);
9665 XFlush (FRAME_X_DISPLAY (f
));
9668 if (f
->output_data
.x
->saved_menu_event
)
9669 xfree (f
->output_data
.x
->saved_menu_event
);
9671 xfree (f
->output_data
.x
);
9672 f
->output_data
.x
= NULL
;
9674 if (f
== dpyinfo
->x_focus_frame
)
9675 dpyinfo
->x_focus_frame
= 0;
9676 if (f
== dpyinfo
->x_focus_event_frame
)
9677 dpyinfo
->x_focus_event_frame
= 0;
9678 if (f
== dpyinfo
->x_highlight_frame
)
9679 dpyinfo
->x_highlight_frame
= 0;
9681 if (f
== dpyinfo
->mouse_face_mouse_frame
)
9683 dpyinfo
->mouse_face_beg_row
9684 = dpyinfo
->mouse_face_beg_col
= -1;
9685 dpyinfo
->mouse_face_end_row
9686 = dpyinfo
->mouse_face_end_col
= -1;
9687 dpyinfo
->mouse_face_window
= Qnil
;
9688 dpyinfo
->mouse_face_deferred_gc
= 0;
9689 dpyinfo
->mouse_face_mouse_frame
= 0;
9696 /* Destroy the X window of frame F. */
9699 x_destroy_window (f
)
9702 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9704 /* If a display connection is dead, don't try sending more
9705 commands to the X server. */
9706 if (dpyinfo
->display
!= 0)
9707 x_free_frame_resources (f
);
9709 dpyinfo
->reference_count
--;
9713 /* Setting window manager hints. */
9715 /* Set the normal size hints for the window manager, for frame F.
9716 FLAGS is the flags word to use--or 0 meaning preserve the flags
9717 that the window now has.
9718 If USER_POSITION is nonzero, we set the USPosition
9719 flag (this is useful when FLAGS is 0).
9720 The GTK version is in gtkutils.c */
9724 x_wm_set_size_hint (f
, flags
, user_position
)
9729 XSizeHints size_hints
;
9731 #ifdef USE_X_TOOLKIT
9734 Dimension widget_width
, widget_height
;
9737 Window window
= FRAME_OUTER_WINDOW (f
);
9739 /* Setting PMaxSize caused various problems. */
9740 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
9742 size_hints
.x
= f
->left_pos
;
9743 size_hints
.y
= f
->top_pos
;
9745 #ifdef USE_X_TOOLKIT
9746 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
9747 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
9748 XtGetValues (f
->output_data
.x
->widget
, al
, ac
);
9749 size_hints
.height
= widget_height
;
9750 size_hints
.width
= widget_width
;
9751 #else /* not USE_X_TOOLKIT */
9752 size_hints
.height
= FRAME_PIXEL_HEIGHT (f
);
9753 size_hints
.width
= FRAME_PIXEL_WIDTH (f
);
9754 #endif /* not USE_X_TOOLKIT */
9756 size_hints
.width_inc
= FRAME_COLUMN_WIDTH (f
);
9757 size_hints
.height_inc
= FRAME_LINE_HEIGHT (f
);
9758 size_hints
.max_width
9759 = FRAME_X_DISPLAY_INFO (f
)->width
- FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
9760 size_hints
.max_height
9761 = FRAME_X_DISPLAY_INFO (f
)->height
- FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
9763 /* Calculate the base and minimum sizes.
9765 (When we use the X toolkit, we don't do it here.
9766 Instead we copy the values that the widgets are using, below.) */
9767 #ifndef USE_X_TOOLKIT
9769 int base_width
, base_height
;
9770 int min_rows
= 0, min_cols
= 0;
9772 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
9773 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
9775 check_frame_size (f
, &min_rows
, &min_cols
);
9777 /* The window manager uses the base width hints to calculate the
9778 current number of rows and columns in the frame while
9779 resizing; min_width and min_height aren't useful for this
9780 purpose, since they might not give the dimensions for a
9781 zero-row, zero-column frame.
9783 We use the base_width and base_height members if we have
9784 them; otherwise, we set the min_width and min_height members
9785 to the size for a zero x zero frame. */
9788 size_hints
.flags
|= PBaseSize
;
9789 size_hints
.base_width
= base_width
;
9790 size_hints
.base_height
= base_height
;
9791 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
9792 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
9794 size_hints
.min_width
= base_width
;
9795 size_hints
.min_height
= base_height
;
9799 /* If we don't need the old flags, we don't need the old hint at all. */
9802 size_hints
.flags
|= flags
;
9805 #endif /* not USE_X_TOOLKIT */
9808 XSizeHints hints
; /* Sometimes I hate X Windows... */
9809 long supplied_return
;
9813 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
9816 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
9819 #ifdef USE_X_TOOLKIT
9820 size_hints
.base_height
= hints
.base_height
;
9821 size_hints
.base_width
= hints
.base_width
;
9822 size_hints
.min_height
= hints
.min_height
;
9823 size_hints
.min_width
= hints
.min_width
;
9827 size_hints
.flags
|= flags
;
9832 if (hints
.flags
& PSize
)
9833 size_hints
.flags
|= PSize
;
9834 if (hints
.flags
& PPosition
)
9835 size_hints
.flags
|= PPosition
;
9836 if (hints
.flags
& USPosition
)
9837 size_hints
.flags
|= USPosition
;
9838 if (hints
.flags
& USSize
)
9839 size_hints
.flags
|= USSize
;
9843 #ifndef USE_X_TOOLKIT
9848 size_hints
.win_gravity
= f
->win_gravity
;
9849 size_hints
.flags
|= PWinGravity
;
9853 size_hints
.flags
&= ~ PPosition
;
9854 size_hints
.flags
|= USPosition
;
9856 #endif /* PWinGravity */
9859 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
9861 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
9864 #endif /* not USE_GTK */
9866 /* Used for IconicState or NormalState */
9869 x_wm_set_window_state (f
, state
)
9873 #ifdef USE_X_TOOLKIT
9876 XtSetArg (al
[0], XtNinitialState
, state
);
9877 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
9878 #else /* not USE_X_TOOLKIT */
9879 Window window
= FRAME_X_WINDOW (f
);
9881 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
9882 f
->output_data
.x
->wm_hints
.initial_state
= state
;
9884 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
9885 #endif /* not USE_X_TOOLKIT */
9889 x_wm_set_icon_pixmap (f
, pixmap_id
)
9893 Pixmap icon_pixmap
, icon_mask
;
9895 #ifndef USE_X_TOOLKIT
9896 Window window
= FRAME_OUTER_WINDOW (f
);
9901 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
9902 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
9903 icon_mask
= x_bitmap_mask (f
, pixmap_id
);
9904 f
->output_data
.x
->wm_hints
.icon_mask
= icon_mask
;
9908 /* It seems there is no way to turn off use of an icon pixmap.
9909 The following line does it, only if no icon has yet been created,
9910 for some window managers. But with mwm it crashes.
9911 Some people say it should clear the IconPixmapHint bit in this case,
9912 but that doesn't work, and the X consortium said it isn't the
9913 right thing at all. Since there is no way to win,
9914 best to explicitly give up. */
9916 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
9917 f
->output_data
.x
->wm_hints
.icon_mask
= None
;
9926 xg_set_frame_icon (f
, icon_pixmap
, icon_mask
);
9930 #elif defined (USE_X_TOOLKIT) /* same as in x_wm_set_window_state. */
9934 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
9935 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
9936 XtSetArg (al
[0], XtNiconMask
, icon_mask
);
9937 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
9940 #else /* not USE_X_TOOLKIT && not USE_GTK */
9942 f
->output_data
.x
->wm_hints
.flags
|= (IconPixmapHint
| IconMaskHint
);
9943 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
9945 #endif /* not USE_X_TOOLKIT && not USE_GTK */
9949 x_wm_set_icon_position (f
, icon_x
, icon_y
)
9953 Window window
= FRAME_OUTER_WINDOW (f
);
9955 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
9956 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
9957 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
9959 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
9963 /***********************************************************************
9965 ***********************************************************************/
9967 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
9970 x_get_font_info (f
, font_idx
)
9974 return (FRAME_X_FONT_TABLE (f
) + font_idx
);
9978 /* Return a list of names of available fonts matching PATTERN on frame F.
9980 If SIZE is > 0, it is the size (maximum bounds width) of fonts
9983 SIZE < 0 means include auto scaled fonts.
9985 Frame F null means we have not yet created any frame on X, and
9986 consult the first display in x_display_list. MAXNAMES sets a limit
9987 on how many fonts to match. */
9990 x_list_fonts (f
, pattern
, size
, maxnames
)
9992 Lisp_Object pattern
;
9996 Lisp_Object list
= Qnil
, patterns
, newlist
= Qnil
, key
= Qnil
;
9997 Lisp_Object tem
, second_best
;
9998 struct x_display_info
*dpyinfo
9999 = f
? FRAME_X_DISPLAY_INFO (f
) : x_display_list
;
10000 Display
*dpy
= dpyinfo
->display
;
10001 int try_XLoadQueryFont
= 0;
10002 int allow_auto_scaled_font
= 0;
10006 allow_auto_scaled_font
= 1;
10010 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
10011 if (NILP (patterns
))
10012 patterns
= Fcons (pattern
, Qnil
);
10014 if (maxnames
== 1 && !size
)
10015 /* We can return any single font matching PATTERN. */
10016 try_XLoadQueryFont
= 1;
10018 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
10021 char **names
= NULL
;
10023 pattern
= XCAR (patterns
);
10024 /* See if we cached the result for this particular query.
10025 The cache is an alist of the form:
10026 ((((PATTERN . MAXNAMES) . SCALABLE) (FONTNAME . WIDTH) ...) ...) */
10027 tem
= XCDR (dpyinfo
->name_list_element
);
10028 key
= Fcons (Fcons (pattern
, make_number (maxnames
)),
10029 allow_auto_scaled_font
? Qt
: Qnil
);
10030 list
= Fassoc (key
, tem
);
10033 list
= Fcdr_safe (list
);
10034 /* We have a cashed list. Don't have to get the list again. */
10038 /* At first, put PATTERN in the cache. */
10041 x_catch_errors (dpy
);
10043 if (try_XLoadQueryFont
)
10046 unsigned long value
;
10048 font
= XLoadQueryFont (dpy
, SDATA (pattern
));
10049 if (x_had_errors_p (dpy
))
10051 /* This error is perhaps due to insufficient memory on X
10052 server. Let's just ignore it. */
10054 x_clear_errors (dpy
);
10058 && XGetFontProperty (font
, XA_FONT
, &value
))
10060 char *name
= (char *) XGetAtomName (dpy
, (Atom
) value
);
10061 int len
= strlen (name
);
10064 /* If DXPC (a Differential X Protocol Compressor)
10065 Ver.3.7 is running, XGetAtomName will return null
10066 string. We must avoid such a name. */
10068 try_XLoadQueryFont
= 0;
10072 names
= (char **) alloca (sizeof (char *));
10073 /* Some systems only allow alloca assigned to a
10075 tmp
= (char *) alloca (len
+ 1); names
[0] = tmp
;
10076 bcopy (name
, names
[0], len
+ 1);
10081 try_XLoadQueryFont
= 0;
10084 XFreeFont (dpy
, font
);
10087 if (!try_XLoadQueryFont
)
10089 /* We try at least 10 fonts because XListFonts will return
10090 auto-scaled fonts at the head. */
10095 for (limit
= 500;;)
10097 names
= XListFonts (dpy
, SDATA (pattern
), limit
, &num_fonts
);
10098 if (num_fonts
== limit
)
10101 XFreeFontNames (names
);
10110 names
= XListFonts (dpy
, SDATA (pattern
), max (maxnames
, 10),
10113 if (x_had_errors_p (dpy
))
10115 /* This error is perhaps due to insufficient memory on X
10116 server. Let's just ignore it. */
10118 x_clear_errors (dpy
);
10122 x_uncatch_errors ();
10129 /* Make a list of all the fonts we got back.
10130 Store that in the font cache for the display. */
10131 for (i
= 0; i
< num_fonts
; i
++)
10134 char *p
= names
[i
];
10135 int average_width
= -1, resx
= 0, dashes
= 0;
10137 /* Count the number of dashes in NAMES[I]. If there are
10138 14 dashes, the field value following 9th dash
10139 (RESOLUTION_X) is nonzero, and the field value
10140 following 12th dash (AVERAGE_WIDTH) is 0, this is a
10141 auto-scaled font which is usually too ugly to be used
10142 for editing. Let's ignore it. */
10147 if (dashes
== 7) /* PIXEL_SIZE field */
10149 else if (dashes
== 9)
10151 else if (dashes
== 12) /* AVERAGE_WIDTH field */
10152 average_width
= atoi (p
);
10155 if (allow_auto_scaled_font
10156 || dashes
< 14 || average_width
!= 0 || resx
== 0)
10158 tem
= build_string (names
[i
]);
10159 if (NILP (Fassoc (tem
, list
)))
10161 if (STRINGP (Vx_pixel_size_width_font_regexp
)
10162 && ((fast_c_string_match_ignore_case
10163 (Vx_pixel_size_width_font_regexp
, names
[i
]))
10165 /* We can set the value of PIXEL_SIZE to the
10166 width of this font. */
10167 list
= Fcons (Fcons (tem
, make_number (width
)), list
);
10169 /* For the moment, width is not known. */
10170 list
= Fcons (Fcons (tem
, Qnil
), list
);
10175 if (!try_XLoadQueryFont
)
10178 XFreeFontNames (names
);
10183 /* Now store the result in the cache. */
10184 XSETCDR (dpyinfo
->name_list_element
,
10185 Fcons (Fcons (key
, list
), XCDR (dpyinfo
->name_list_element
)));
10188 if (NILP (list
)) continue; /* Try the remaining alternatives. */
10190 newlist
= second_best
= Qnil
;
10191 /* Make a list of the fonts that have the right width. */
10192 for (; CONSP (list
); list
= XCDR (list
))
10198 if (!CONSP (tem
) || NILP (XCAR (tem
)))
10202 newlist
= Fcons (XCAR (tem
), newlist
);
10206 if (!INTEGERP (XCDR (tem
)))
10208 /* Since we have not yet known the size of this font, we
10209 must try slow function call XLoadQueryFont. */
10210 XFontStruct
*thisinfo
;
10213 x_catch_errors (dpy
);
10214 thisinfo
= XLoadQueryFont (dpy
,
10215 SDATA (XCAR (tem
)));
10216 if (x_had_errors_p (dpy
))
10218 /* This error is perhaps due to insufficient memory on X
10219 server. Let's just ignore it. */
10221 x_clear_errors (dpy
);
10223 x_uncatch_errors ();
10229 (thisinfo
->min_bounds
.width
== 0
10231 : make_number (thisinfo
->max_bounds
.width
)));
10233 XFreeFont (dpy
, thisinfo
);
10237 /* For unknown reason, the previous call of XListFont had
10238 returned a font which can't be opened. Record the size
10239 as 0 not to try to open it again. */
10240 XSETCDR (tem
, make_number (0));
10243 found_size
= XINT (XCDR (tem
));
10244 if (found_size
== size
)
10245 newlist
= Fcons (XCAR (tem
), newlist
);
10246 else if (found_size
> 0)
10248 if (NILP (second_best
))
10250 else if (found_size
< size
)
10252 if (XINT (XCDR (second_best
)) > size
10253 || XINT (XCDR (second_best
)) < found_size
)
10258 if (XINT (XCDR (second_best
)) > size
10259 && XINT (XCDR (second_best
)) > found_size
)
10264 if (!NILP (newlist
))
10266 else if (!NILP (second_best
))
10268 newlist
= Fcons (XCAR (second_best
), Qnil
);
10279 /* Check that FONT is valid on frame F. It is if it can be found in F's
10283 x_check_font (f
, font
)
10288 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
10290 xassert (font
!= NULL
);
10292 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
10293 if (dpyinfo
->font_table
[i
].name
10294 && font
== dpyinfo
->font_table
[i
].font
)
10297 xassert (i
< dpyinfo
->n_fonts
);
10300 #endif /* GLYPH_DEBUG != 0 */
10302 /* Set *W to the minimum width, *H to the minimum font height of FONT.
10303 Note: There are (broken) X fonts out there with invalid XFontStruct
10304 min_bounds contents. For example, handa@etl.go.jp reports that
10305 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
10306 have font->min_bounds.width == 0. */
10309 x_font_min_bounds (font
, w
, h
)
10313 *h
= FONT_HEIGHT (font
);
10314 *w
= font
->min_bounds
.width
;
10316 /* Try to handle the case where FONT->min_bounds has invalid
10317 contents. Since the only font known to have invalid min_bounds
10318 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
10320 *w
= font
->max_bounds
.width
;
10324 /* Compute the smallest character width and smallest font height over
10325 all fonts available on frame F. Set the members smallest_char_width
10326 and smallest_font_height in F's x_display_info structure to
10327 the values computed. Value is non-zero if smallest_font_height or
10328 smallest_char_width become smaller than they were before. */
10331 x_compute_min_glyph_bounds (f
)
10335 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
10337 int old_width
= dpyinfo
->smallest_char_width
;
10338 int old_height
= dpyinfo
->smallest_font_height
;
10340 dpyinfo
->smallest_font_height
= 100000;
10341 dpyinfo
->smallest_char_width
= 100000;
10343 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
10344 if (dpyinfo
->font_table
[i
].name
)
10346 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
10349 font
= (XFontStruct
*) fontp
->font
;
10350 xassert (font
!= (XFontStruct
*) ~0);
10351 x_font_min_bounds (font
, &w
, &h
);
10353 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
10354 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
10357 xassert (dpyinfo
->smallest_char_width
> 0
10358 && dpyinfo
->smallest_font_height
> 0);
10360 return (dpyinfo
->n_fonts
== 1
10361 || dpyinfo
->smallest_char_width
< old_width
10362 || dpyinfo
->smallest_font_height
< old_height
);
10366 /* Load font named FONTNAME of the size SIZE for frame F, and return a
10367 pointer to the structure font_info while allocating it dynamically.
10368 If SIZE is 0, load any size of font.
10369 If loading is failed, return NULL. */
10372 x_load_font (f
, fontname
, size
)
10374 register char *fontname
;
10377 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
10378 Lisp_Object font_names
;
10380 /* Get a list of all the fonts that match this name. Once we
10381 have a list of matching fonts, we compare them against the fonts
10382 we already have by comparing names. */
10383 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
10385 if (!NILP (font_names
))
10390 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
10391 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
10392 if (dpyinfo
->font_table
[i
].name
10393 && (!strcmp (dpyinfo
->font_table
[i
].name
,
10394 SDATA (XCAR (tail
)))
10395 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
10396 SDATA (XCAR (tail
)))))
10397 return (dpyinfo
->font_table
+ i
);
10400 /* Load the font and add it to the table. */
10404 struct font_info
*fontp
;
10405 unsigned long value
;
10408 /* If we have found fonts by x_list_font, load one of them. If
10409 not, we still try to load a font by the name given as FONTNAME
10410 because XListFonts (called in x_list_font) of some X server has
10411 a bug of not finding a font even if the font surely exists and
10412 is loadable by XLoadQueryFont. */
10413 if (size
> 0 && !NILP (font_names
))
10414 fontname
= (char *) SDATA (XCAR (font_names
));
10417 x_catch_errors (FRAME_X_DISPLAY (f
));
10418 font
= (XFontStruct
*) XLoadQueryFont (FRAME_X_DISPLAY (f
), fontname
);
10419 if (x_had_errors_p (FRAME_X_DISPLAY (f
)))
10421 /* This error is perhaps due to insufficient memory on X
10422 server. Let's just ignore it. */
10424 x_clear_errors (FRAME_X_DISPLAY (f
));
10426 x_uncatch_errors ();
10431 /* Find a free slot in the font table. */
10432 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
10433 if (dpyinfo
->font_table
[i
].name
== NULL
)
10436 /* If no free slot found, maybe enlarge the font table. */
10437 if (i
== dpyinfo
->n_fonts
10438 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
10441 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
10442 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
10443 dpyinfo
->font_table
10444 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
10447 fontp
= dpyinfo
->font_table
+ i
;
10448 if (i
== dpyinfo
->n_fonts
)
10449 ++dpyinfo
->n_fonts
;
10451 /* Now fill in the slots of *FONTP. */
10453 bzero (fontp
, sizeof (*fontp
));
10454 fontp
->font
= font
;
10455 fontp
->font_idx
= i
;
10456 fontp
->charset
= -1; /* fs_load_font sets it. */
10457 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
10458 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
10460 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
10462 /* Fixed width font. */
10463 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
10470 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
10471 pcm
= x_per_char_metric (font
, &char2b
, 0);
10473 fontp
->space_width
= pcm
->width
;
10475 fontp
->space_width
= FONT_WIDTH (font
);
10477 fontp
->average_width
10478 = (XGetFontProperty (font
, dpyinfo
->Xatom_AVERAGE_WIDTH
, &value
)
10479 ? (long) value
/ 10 : 0);
10480 if (fontp
->average_width
< 0)
10481 fontp
->average_width
= - fontp
->average_width
;
10482 if (fontp
->average_width
== 0)
10486 int width
= pcm
->width
;
10487 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
10488 if ((pcm
= x_per_char_metric (font
, &char2b
, 0)) != NULL
)
10489 width
+= pcm
->width
;
10490 fontp
->average_width
= width
/ 95;
10493 fontp
->average_width
= FONT_WIDTH (font
);
10497 /* Try to get the full name of FONT. Put it in FULL_NAME. */
10499 if (XGetFontProperty (font
, XA_FONT
, &value
))
10501 char *name
= (char *) XGetAtomName (FRAME_X_DISPLAY (f
), (Atom
) value
);
10505 /* Count the number of dashes in the "full name".
10506 If it is too few, this isn't really the font's full name,
10508 In X11R4, the fonts did not come with their canonical names
10519 full_name
= (char *) xmalloc (p
- name
+ 1);
10520 bcopy (name
, full_name
, p
- name
+ 1);
10526 if (full_name
!= 0)
10527 fontp
->full_name
= full_name
;
10529 fontp
->full_name
= fontp
->name
;
10531 fontp
->size
= font
->max_bounds
.width
;
10532 fontp
->height
= FONT_HEIGHT (font
);
10534 if (NILP (font_names
))
10536 /* We come here because of a bug of XListFonts mentioned at
10537 the head of this block. Let's store this information in
10538 the cache for x_list_fonts. */
10539 Lisp_Object lispy_name
= build_string (fontname
);
10540 Lisp_Object lispy_full_name
= build_string (fontp
->full_name
);
10541 Lisp_Object key
= Fcons (Fcons (lispy_name
, make_number (256)),
10544 XSETCDR (dpyinfo
->name_list_element
,
10546 Fcons (Fcons (lispy_full_name
,
10547 make_number (fontp
->size
)),
10549 XCDR (dpyinfo
->name_list_element
)));
10552 key
= Fcons (Fcons (lispy_full_name
, make_number (256)),
10554 XSETCDR (dpyinfo
->name_list_element
,
10556 Fcons (Fcons (lispy_full_name
,
10557 make_number (fontp
->size
)),
10559 XCDR (dpyinfo
->name_list_element
)));
10563 /* The slot `encoding' specifies how to map a character
10564 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
10565 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
10566 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
10567 2:0xA020..0xFF7F). For the moment, we don't know which charset
10568 uses this font. So, we set information in fontp->encoding_type
10569 which is never used by any charset. If mapping can't be
10570 decided, set FONT_ENCODING_NOT_DECIDED. */
10571 fontp
->encoding_type
10572 = (font
->max_byte1
== 0
10574 ? (font
->min_char_or_byte2
< 0x80
10575 ? (font
->max_char_or_byte2
< 0x80
10576 ? 0 /* 0x20..0x7F */
10577 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
10578 : 1) /* 0xA0..0xFF */
10580 : (font
->min_byte1
< 0x80
10581 ? (font
->max_byte1
< 0x80
10582 ? (font
->min_char_or_byte2
< 0x80
10583 ? (font
->max_char_or_byte2
< 0x80
10584 ? 0 /* 0x2020..0x7F7F */
10585 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
10586 : 3) /* 0x20A0..0x7FFF */
10587 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
10588 : (font
->min_char_or_byte2
< 0x80
10589 ? (font
->max_char_or_byte2
< 0x80
10590 ? 2 /* 0xA020..0xFF7F */
10591 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
10592 : 1))); /* 0xA0A0..0xFFFF */
10594 fontp
->baseline_offset
10595 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
10596 ? (long) value
: 0);
10597 fontp
->relative_compose
10598 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
10599 ? (long) value
: 0);
10600 fontp
->default_ascent
10601 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
10602 ? (long) value
: 0);
10604 /* Set global flag fonts_changed_p to non-zero if the font loaded
10605 has a character with a smaller width than any other character
10606 before, or if the font loaded has a smaller height than any
10607 other font loaded before. If this happens, it will make a
10608 glyph matrix reallocation necessary. */
10609 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
10616 /* Return a pointer to struct font_info of a font named FONTNAME for
10617 frame F. If no such font is loaded, return NULL. */
10620 x_query_font (f
, fontname
)
10622 register char *fontname
;
10624 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
10627 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
10628 if (dpyinfo
->font_table
[i
].name
10629 && (!xstricmp (dpyinfo
->font_table
[i
].name
, fontname
)
10630 || !xstricmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
10631 return (dpyinfo
->font_table
+ i
);
10636 /* Find a CCL program for a font specified by FONTP, and set the member
10637 `encoder' of the structure. */
10640 x_find_ccl_program (fontp
)
10641 struct font_info
*fontp
;
10643 Lisp_Object list
, elt
;
10646 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
10650 && STRINGP (XCAR (elt
))
10651 && ((fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
10653 || (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->full_name
)
10660 struct ccl_program
*ccl
10661 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
10663 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
10666 fontp
->font_encoder
= ccl
;
10671 /* Return a char-table whose elements are t if the font FONT_INFO
10672 contains a glyph for the corresponding character, and nil if
10676 x_get_font_repertory (f
, font_info
)
10678 struct font_info
*font_info
;
10680 XFontStruct
*font
= (XFontStruct
*) font_info
->font
;
10682 int min_byte1
, max_byte1
, min_byte2
, max_byte2
;
10684 struct charset
*charset
= CHARSET_FROM_ID (font_info
->charset
);
10685 int offset
= CHARSET_OFFSET (charset
);
10687 table
= Fmake_char_table (Qnil
, Qnil
);
10689 min_byte1
= font
->min_byte1
;
10690 max_byte1
= font
->max_byte1
;
10691 min_byte2
= font
->min_char_or_byte2
;
10692 max_byte2
= font
->max_char_or_byte2
;
10693 if (min_byte1
== 0 && max_byte1
== 0)
10695 if (! font
->per_char
|| font
->all_chars_exist
== True
)
10698 char_table_set_range (table
, offset
+ min_byte2
,
10699 offset
+ max_byte2
, Qt
);
10701 for (; min_byte2
<= max_byte2
; min_byte2
++)
10703 c
= DECODE_CHAR (charset
, min_byte2
);
10704 CHAR_TABLE_SET (table
, c
, Qt
);
10709 XCharStruct
*pcm
= font
->per_char
;
10713 for (i
= min_byte2
; i
<= max_byte2
; i
++, pcm
++)
10715 if (pcm
->width
== 0 && pcm
->rbearing
== pcm
->lbearing
)
10720 char_table_set_range (table
, offset
+ from
,
10721 offset
+ i
- 1, Qt
);
10723 for (; from
< i
; from
++)
10725 c
= DECODE_CHAR (charset
, from
);
10726 CHAR_TABLE_SET (table
, c
, Qt
);
10737 char_table_set_range (table
, offset
+ from
, offset
+ i
- 1,
10740 for (; from
< i
; from
++)
10742 c
= DECODE_CHAR (charset
, from
);
10743 CHAR_TABLE_SET (table
, c
, Qt
);
10750 if (! font
->per_char
|| font
->all_chars_exist
== True
)
10755 for (i
= min_byte1
; i
<= max_byte1
; i
++)
10756 char_table_set_range
10757 (table
, offset
+ ((i
<< 8) | min_byte2
),
10758 offset
+ ((i
<< 8) | max_byte2
), Qt
);
10760 for (i
= min_byte1
; i
<= max_byte1
; i
++)
10761 for (j
= min_byte2
; j
<= max_byte2
; j
++)
10763 unsigned code
= (i
<< 8) | j
;
10764 c
= DECODE_CHAR (charset
, code
);
10765 CHAR_TABLE_SET (table
, c
, Qt
);
10770 XCharStruct
*pcm
= font
->per_char
;
10773 for (i
= min_byte1
; i
<= max_byte1
; i
++)
10778 for (j
= min_byte2
; j
<= max_byte2
; j
++, pcm
++)
10780 if (pcm
->width
== 0 && pcm
->rbearing
== pcm
->lbearing
)
10785 char_table_set_range
10786 (table
, offset
+ ((i
<< 8) | from
),
10787 offset
+ ((i
<< 8) | (j
- 1)), Qt
);
10790 for (; from
< j
; from
++)
10792 unsigned code
= (i
<< 8) | from
;
10793 c
= ENCODE_CHAR (charset
, code
);
10794 CHAR_TABLE_SET (table
, c
, Qt
);
10806 char_table_set_range
10807 (table
, offset
+ ((i
<< 8) | from
),
10808 offset
+ ((i
<< 8) | (j
- 1)), Qt
);
10811 for (; from
< j
; from
++)
10813 unsigned code
= (i
<< 8) | from
;
10814 c
= DECODE_CHAR (charset
, code
);
10815 CHAR_TABLE_SET (table
, c
, Qt
);
10826 /***********************************************************************
10828 ***********************************************************************/
10830 #ifdef USE_X_TOOLKIT
10831 static XrmOptionDescRec emacs_options
[] = {
10832 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
10833 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
10835 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
10836 XrmoptionSepArg
, NULL
},
10837 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
10839 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
10840 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
10841 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
10842 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
10843 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
10844 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
10845 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
10848 /* Whether atimer for Xt timeouts is activated or not. */
10850 static int x_timeout_atimer_activated_flag
;
10852 #endif /* USE_X_TOOLKIT */
10854 static int x_initialized
;
10857 static int x_session_initialized
;
10860 #ifdef MULTI_KBOARD
10861 /* Test whether two display-name strings agree up to the dot that separates
10862 the screen number from the server number. */
10864 same_x_server (name1
, name2
)
10865 const char *name1
, *name2
;
10867 int seen_colon
= 0;
10868 const unsigned char *system_name
= SDATA (Vsystem_name
);
10869 int system_name_length
= strlen (system_name
);
10870 int length_until_period
= 0;
10872 while (system_name
[length_until_period
] != 0
10873 && system_name
[length_until_period
] != '.')
10874 length_until_period
++;
10876 /* Treat `unix' like an empty host name. */
10877 if (! strncmp (name1
, "unix:", 5))
10879 if (! strncmp (name2
, "unix:", 5))
10881 /* Treat this host's name like an empty host name. */
10882 if (! strncmp (name1
, system_name
, system_name_length
)
10883 && name1
[system_name_length
] == ':')
10884 name1
+= system_name_length
;
10885 if (! strncmp (name2
, system_name
, system_name_length
)
10886 && name2
[system_name_length
] == ':')
10887 name2
+= system_name_length
;
10888 /* Treat this host's domainless name like an empty host name. */
10889 if (! strncmp (name1
, system_name
, length_until_period
)
10890 && name1
[length_until_period
] == ':')
10891 name1
+= length_until_period
;
10892 if (! strncmp (name2
, system_name
, length_until_period
)
10893 && name2
[length_until_period
] == ':')
10894 name2
+= length_until_period
;
10896 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
10900 if (seen_colon
&& *name1
== '.')
10904 && (*name1
== '.' || *name1
== '\0')
10905 && (*name2
== '.' || *name2
== '\0'));
10909 /* Count number of set bits in mask and number of bits to shift to
10910 get to the first bit. With MASK 0x7e0, *BITS is set to 6, and *OFFSET
10913 get_bits_and_offset (mask
, bits
, offset
)
10914 unsigned long mask
;
10921 while (!(mask
& 1))
10938 x_display_ok (display
)
10939 const char * display
;
10944 dpy
= XOpenDisplay (display
);
10946 XCloseDisplay (dpy
);
10952 struct x_display_info
*
10953 x_term_init (display_name
, xrm_option
, resource_name
)
10954 Lisp_Object display_name
;
10956 char *resource_name
;
10960 struct x_display_info
*dpyinfo
;
10965 if (!x_initialized
)
10973 #define NUM_ARGV 10
10975 char *argv
[NUM_ARGV
];
10976 char **argv2
= argv
;
10979 if (x_initialized
++ > 1)
10981 /* Opening another display. If xg_display_open returns less
10982 than zero, we are probably on GTK 2.0, which can only handle
10983 one display. GTK 2.2 or later can handle more than one. */
10984 if (xg_display_open (SDATA (display_name
), &dpy
) < 0)
10985 error ("Sorry, this version of GTK can only handle one display");
10989 for (argc
= 0; argc
< NUM_ARGV
; ++argc
)
10993 argv
[argc
++] = initial_argv
[0];
10995 if (! NILP (display_name
))
10997 argv
[argc
++] = "--display";
10998 argv
[argc
++] = SDATA (display_name
);
11001 argv
[argc
++] = "--name";
11002 argv
[argc
++] = resource_name
;
11005 XSetLocaleModifiers ("");
11008 gtk_init (&argc
, &argv2
);
11010 /* gtk_init does set_locale. We must fix locale after calling it. */
11014 dpy
= GDK_DISPLAY ();
11016 /* NULL window -> events for all windows go to our function */
11017 gdk_window_add_filter (NULL
, event_handler_gdk
, NULL
);
11019 /* Load our own gtkrc if it exists. */
11021 char *file
= "~/.emacs.d/gtkrc";
11022 Lisp_Object s
, abs_file
;
11024 s
= make_string (file
, strlen (file
));
11025 abs_file
= Fexpand_file_name (s
, Qnil
);
11027 if (! NILP (abs_file
) && !NILP (Ffile_readable_p (abs_file
)))
11028 gtk_rc_parse (SDATA (abs_file
));
11031 XSetErrorHandler (x_error_handler
);
11032 XSetIOErrorHandler (x_io_error_quitter
);
11035 #else /* not USE_GTK */
11036 #ifdef USE_X_TOOLKIT
11037 /* weiner@footloose.sps.mot.com reports that this causes
11039 X protocol error: BadAtom (invalid Atom parameter)
11040 on protocol request 18skiloaf.
11041 So let's not use it until R6. */
11042 #ifdef HAVE_X11XTR6
11043 XtSetLanguageProc (NULL
, NULL
, NULL
);
11054 argv
[argc
++] = "-xrm";
11055 argv
[argc
++] = xrm_option
;
11057 turn_on_atimers (0);
11058 dpy
= XtOpenDisplay (Xt_app_con
, SDATA (display_name
),
11059 resource_name
, EMACS_CLASS
,
11060 emacs_options
, XtNumber (emacs_options
),
11062 turn_on_atimers (1);
11064 #ifdef HAVE_X11XTR6
11065 /* I think this is to compensate for XtSetLanguageProc. */
11070 #else /* not USE_X_TOOLKIT */
11072 XSetLocaleModifiers ("");
11074 dpy
= XOpenDisplay (SDATA (display_name
));
11075 #endif /* not USE_X_TOOLKIT */
11076 #endif /* not USE_GTK*/
11078 /* Detect failure. */
11085 /* We have definitely succeeded. Record the new connection. */
11087 dpyinfo
= (struct x_display_info
*) xmalloc (sizeof (struct x_display_info
));
11088 bzero (dpyinfo
, sizeof *dpyinfo
);
11090 #ifdef MULTI_KBOARD
11092 struct x_display_info
*share
;
11095 for (share
= x_display_list
, tail
= x_display_name_list
; share
;
11096 share
= share
->next
, tail
= XCDR (tail
))
11097 if (same_x_server (SDATA (XCAR (XCAR (tail
))),
11098 SDATA (display_name
)))
11101 dpyinfo
->kboard
= share
->kboard
;
11104 dpyinfo
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
11105 init_kboard (dpyinfo
->kboard
);
11106 if (!EQ (XSYMBOL (Qvendor_specific_keysyms
)->function
, Qunbound
))
11108 char *vendor
= ServerVendor (dpy
);
11110 dpyinfo
->kboard
->Vsystem_key_alist
11111 = call1 (Qvendor_specific_keysyms
,
11112 build_string (vendor
? vendor
: ""));
11116 dpyinfo
->kboard
->next_kboard
= all_kboards
;
11117 all_kboards
= dpyinfo
->kboard
;
11118 /* Don't let the initial kboard remain current longer than necessary.
11119 That would cause problems if a file loaded on startup tries to
11120 prompt in the mini-buffer. */
11121 if (current_kboard
== initial_kboard
)
11122 current_kboard
= dpyinfo
->kboard
;
11124 dpyinfo
->kboard
->reference_count
++;
11128 /* Put this display on the chain. */
11129 dpyinfo
->next
= x_display_list
;
11130 x_display_list
= dpyinfo
;
11132 /* Put it on x_display_name_list as well, to keep them parallel. */
11133 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
11134 x_display_name_list
);
11135 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
11137 dpyinfo
->display
= dpy
;
11140 XSetAfterFunction (x_current_display
, x_trace_wire
);
11144 = (char *) xmalloc (SBYTES (Vinvocation_name
)
11145 + SBYTES (Vsystem_name
)
11147 sprintf (dpyinfo
->x_id_name
, "%s@%s",
11148 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
11150 /* Figure out which modifier bits mean what. */
11151 x_find_modifier_meanings (dpyinfo
);
11153 /* Get the scroll bar cursor. */
11155 /* We must create a GTK cursor, it is required for GTK widgets. */
11156 dpyinfo
->xg_cursor
= xg_create_default_cursor (dpyinfo
->display
);
11157 #endif /* USE_GTK */
11159 dpyinfo
->vertical_scroll_bar_cursor
11160 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
11162 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
11163 resource_name
, EMACS_CLASS
);
11164 #ifdef HAVE_XRMSETDATABASE
11165 XrmSetDatabase (dpyinfo
->display
, xrdb
);
11167 dpyinfo
->display
->db
= xrdb
;
11169 /* Put the rdb where we can find it in a way that works on
11171 dpyinfo
->xrdb
= xrdb
;
11173 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
11174 DefaultScreen (dpyinfo
->display
));
11175 select_visual (dpyinfo
);
11176 dpyinfo
->cmap
= DefaultColormapOfScreen (dpyinfo
->screen
);
11177 dpyinfo
->height
= HeightOfScreen (dpyinfo
->screen
);
11178 dpyinfo
->width
= WidthOfScreen (dpyinfo
->screen
);
11179 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
11180 dpyinfo
->client_leader_window
= 0;
11181 dpyinfo
->grabbed
= 0;
11182 dpyinfo
->reference_count
= 0;
11183 dpyinfo
->icon_bitmap_id
= -1;
11184 dpyinfo
->font_table
= NULL
;
11185 dpyinfo
->n_fonts
= 0;
11186 dpyinfo
->font_table_size
= 0;
11187 dpyinfo
->bitmaps
= 0;
11188 dpyinfo
->bitmaps_size
= 0;
11189 dpyinfo
->bitmaps_last
= 0;
11190 dpyinfo
->scratch_cursor_gc
= 0;
11191 dpyinfo
->mouse_face_mouse_frame
= 0;
11192 dpyinfo
->mouse_face_deferred_gc
= 0;
11193 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
11194 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
11195 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
11196 dpyinfo
->mouse_face_window
= Qnil
;
11197 dpyinfo
->mouse_face_overlay
= Qnil
;
11198 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
11199 dpyinfo
->mouse_face_defer
= 0;
11200 dpyinfo
->mouse_face_hidden
= 0;
11201 dpyinfo
->x_focus_frame
= 0;
11202 dpyinfo
->x_focus_event_frame
= 0;
11203 dpyinfo
->x_highlight_frame
= 0;
11204 dpyinfo
->image_cache
= make_image_cache ();
11205 dpyinfo
->wm_type
= X_WMTYPE_UNKNOWN
;
11207 /* See if we can construct pixel values from RGB values. */
11208 dpyinfo
->red_bits
= dpyinfo
->blue_bits
= dpyinfo
->green_bits
= 0;
11209 dpyinfo
->red_offset
= dpyinfo
->blue_offset
= dpyinfo
->green_offset
= 0;
11211 if (dpyinfo
->visual
->class == TrueColor
)
11213 get_bits_and_offset (dpyinfo
->visual
->red_mask
,
11214 &dpyinfo
->red_bits
, &dpyinfo
->red_offset
);
11215 get_bits_and_offset (dpyinfo
->visual
->blue_mask
,
11216 &dpyinfo
->blue_bits
, &dpyinfo
->blue_offset
);
11217 get_bits_and_offset (dpyinfo
->visual
->green_mask
,
11218 &dpyinfo
->green_bits
, &dpyinfo
->green_offset
);
11221 /* See if a private colormap is requested. */
11222 if (dpyinfo
->visual
== DefaultVisualOfScreen (dpyinfo
->screen
))
11224 if (dpyinfo
->visual
->class == PseudoColor
)
11227 value
= display_x_get_resource (dpyinfo
,
11228 build_string ("privateColormap"),
11229 build_string ("PrivateColormap"),
11231 if (STRINGP (value
)
11232 && (!strcmp (SDATA (value
), "true")
11233 || !strcmp (SDATA (value
), "on")))
11234 dpyinfo
->cmap
= XCopyColormapAndFree (dpyinfo
->display
, dpyinfo
->cmap
);
11238 dpyinfo
->cmap
= XCreateColormap (dpyinfo
->display
, dpyinfo
->root_window
,
11239 dpyinfo
->visual
, AllocNone
);
11242 int screen_number
= XScreenNumberOfScreen (dpyinfo
->screen
);
11243 double pixels
= DisplayHeight (dpyinfo
->display
, screen_number
);
11244 double mm
= DisplayHeightMM (dpyinfo
->display
, screen_number
);
11245 /* Mac OS X 10.3's Xserver sometimes reports 0.0mm. */
11246 dpyinfo
->resy
= (mm
< 1) ? 100 : pixels
* 25.4 / mm
;
11247 pixels
= DisplayWidth (dpyinfo
->display
, screen_number
);
11248 /* Mac OS X 10.3's Xserver sometimes reports 0.0mm. */
11249 mm
= DisplayWidthMM (dpyinfo
->display
, screen_number
);
11250 dpyinfo
->resx
= (mm
< 1) ? 100 : pixels
* 25.4 / mm
;
11253 dpyinfo
->Xatom_wm_protocols
11254 = XInternAtom (dpyinfo
->display
, "WM_PROTOCOLS", False
);
11255 dpyinfo
->Xatom_wm_take_focus
11256 = XInternAtom (dpyinfo
->display
, "WM_TAKE_FOCUS", False
);
11257 dpyinfo
->Xatom_wm_save_yourself
11258 = XInternAtom (dpyinfo
->display
, "WM_SAVE_YOURSELF", False
);
11259 dpyinfo
->Xatom_wm_delete_window
11260 = XInternAtom (dpyinfo
->display
, "WM_DELETE_WINDOW", False
);
11261 dpyinfo
->Xatom_wm_change_state
11262 = XInternAtom (dpyinfo
->display
, "WM_CHANGE_STATE", False
);
11263 dpyinfo
->Xatom_wm_configure_denied
11264 = XInternAtom (dpyinfo
->display
, "WM_CONFIGURE_DENIED", False
);
11265 dpyinfo
->Xatom_wm_window_moved
11266 = XInternAtom (dpyinfo
->display
, "WM_MOVED", False
);
11267 dpyinfo
->Xatom_wm_client_leader
11268 = XInternAtom (dpyinfo
->display
, "WM_CLIENT_LEADER", False
);
11269 dpyinfo
->Xatom_editres
11270 = XInternAtom (dpyinfo
->display
, "Editres", False
);
11271 dpyinfo
->Xatom_CLIPBOARD
11272 = XInternAtom (dpyinfo
->display
, "CLIPBOARD", False
);
11273 dpyinfo
->Xatom_TIMESTAMP
11274 = XInternAtom (dpyinfo
->display
, "TIMESTAMP", False
);
11275 dpyinfo
->Xatom_TEXT
11276 = XInternAtom (dpyinfo
->display
, "TEXT", False
);
11277 dpyinfo
->Xatom_COMPOUND_TEXT
11278 = XInternAtom (dpyinfo
->display
, "COMPOUND_TEXT", False
);
11279 dpyinfo
->Xatom_UTF8_STRING
11280 = XInternAtom (dpyinfo
->display
, "UTF8_STRING", False
);
11281 dpyinfo
->Xatom_DELETE
11282 = XInternAtom (dpyinfo
->display
, "DELETE", False
);
11283 dpyinfo
->Xatom_MULTIPLE
11284 = XInternAtom (dpyinfo
->display
, "MULTIPLE", False
);
11285 dpyinfo
->Xatom_INCR
11286 = XInternAtom (dpyinfo
->display
, "INCR", False
);
11287 dpyinfo
->Xatom_EMACS_TMP
11288 = XInternAtom (dpyinfo
->display
, "_EMACS_TMP_", False
);
11289 dpyinfo
->Xatom_TARGETS
11290 = XInternAtom (dpyinfo
->display
, "TARGETS", False
);
11291 dpyinfo
->Xatom_NULL
11292 = XInternAtom (dpyinfo
->display
, "NULL", False
);
11293 dpyinfo
->Xatom_ATOM_PAIR
11294 = XInternAtom (dpyinfo
->display
, "ATOM_PAIR", False
);
11295 /* For properties of font. */
11296 dpyinfo
->Xatom_PIXEL_SIZE
11297 = XInternAtom (dpyinfo
->display
, "PIXEL_SIZE", False
);
11298 dpyinfo
->Xatom_AVERAGE_WIDTH
11299 = XInternAtom (dpyinfo
->display
, "AVERAGE_WIDTH", False
);
11300 dpyinfo
->Xatom_MULE_BASELINE_OFFSET
11301 = XInternAtom (dpyinfo
->display
, "_MULE_BASELINE_OFFSET", False
);
11302 dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
11303 = XInternAtom (dpyinfo
->display
, "_MULE_RELATIVE_COMPOSE", False
);
11304 dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
11305 = XInternAtom (dpyinfo
->display
, "_MULE_DEFAULT_ASCENT", False
);
11307 /* Ghostscript support. */
11308 dpyinfo
->Xatom_PAGE
= XInternAtom (dpyinfo
->display
, "PAGE", False
);
11309 dpyinfo
->Xatom_DONE
= XInternAtom (dpyinfo
->display
, "DONE", False
);
11311 dpyinfo
->Xatom_Scrollbar
= XInternAtom (dpyinfo
->display
, "SCROLLBAR",
11314 dpyinfo
->cut_buffers_initialized
= 0;
11316 dpyinfo
->x_dnd_atoms_size
= 8;
11317 dpyinfo
->x_dnd_atoms_length
= 0;
11318 dpyinfo
->x_dnd_atoms
= xmalloc (sizeof (*dpyinfo
->x_dnd_atoms
)
11319 * dpyinfo
->x_dnd_atoms_size
);
11321 dpyinfo
->net_supported_atoms
= NULL
;
11322 dpyinfo
->nr_net_supported_atoms
= 0;
11323 dpyinfo
->net_supported_window
= 0;
11325 connection
= ConnectionNumber (dpyinfo
->display
);
11326 dpyinfo
->connection
= connection
;
11331 null_bits
[0] = 0x00;
11333 dpyinfo
->null_pixel
11334 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
11335 null_bits
, 1, 1, (long) 0, (long) 0,
11340 extern int gray_bitmap_width
, gray_bitmap_height
;
11341 extern char *gray_bitmap_bits
;
11343 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
11345 gray_bitmap_width
, gray_bitmap_height
,
11346 (unsigned long) 1, (unsigned long) 0, 1);
11350 xim_initialize (dpyinfo
, resource_name
);
11353 #ifdef subprocesses
11354 /* This is only needed for distinguishing keyboard and process input. */
11355 if (connection
!= 0)
11356 add_keyboard_wait_descriptor (connection
);
11359 #ifndef F_SETOWN_BUG
11361 #ifdef F_SETOWN_SOCK_NEG
11362 /* stdin is a socket here */
11363 fcntl (connection
, F_SETOWN
, -getpid ());
11364 #else /* ! defined (F_SETOWN_SOCK_NEG) */
11365 fcntl (connection
, F_SETOWN
, getpid ());
11366 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
11367 #endif /* ! defined (F_SETOWN) */
11368 #endif /* F_SETOWN_BUG */
11371 if (interrupt_input
)
11372 init_sigio (connection
);
11373 #endif /* ! defined (SIGIO) */
11376 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
11377 /* Make sure that we have a valid font for dialog boxes
11378 so that Xt does not crash. */
11380 Display
*dpy
= dpyinfo
->display
;
11381 XrmValue d
, fr
, to
;
11384 d
.addr
= (XPointer
)&dpy
;
11385 d
.size
= sizeof (Display
*);
11386 fr
.addr
= XtDefaultFont
;
11387 fr
.size
= sizeof (XtDefaultFont
);
11388 to
.size
= sizeof (Font
*);
11389 to
.addr
= (XPointer
)&font
;
11390 x_catch_errors (dpy
);
11391 if (!XtCallConverter (dpy
, XtCvtStringToFont
, &d
, 1, &fr
, &to
, NULL
))
11393 if (x_had_errors_p (dpy
) || !XQueryFont (dpy
, font
))
11394 XrmPutLineResource (&xrdb
, "Emacs.dialog.*.font: 9x15");
11395 x_uncatch_errors ();
11400 /* See if we should run in synchronous mode. This is useful
11401 for debugging X code. */
11404 value
= display_x_get_resource (dpyinfo
,
11405 build_string ("synchronous"),
11406 build_string ("Synchronous"),
11408 if (STRINGP (value
)
11409 && (!strcmp (SDATA (value
), "true")
11410 || !strcmp (SDATA (value
), "on")))
11411 XSynchronize (dpyinfo
->display
, True
);
11416 value
= display_x_get_resource (dpyinfo
,
11417 build_string ("useXIM"),
11418 build_string ("UseXIM"),
11421 if (STRINGP (value
)
11422 && (!strcmp (XSTRING (value
)->data
, "false")
11423 || !strcmp (XSTRING (value
)->data
, "off")))
11426 if (STRINGP (value
)
11427 && (!strcmp (XSTRING (value
)->data
, "true")
11428 || !strcmp (XSTRING (value
)->data
, "on")))
11434 /* Only do this for the first display. */
11435 if (!x_session_initialized
++)
11436 x_session_initialize (dpyinfo
);
11444 /* Get rid of display DPYINFO, assuming all frames are already gone,
11445 and without sending any more commands to the X server. */
11448 x_delete_display (dpyinfo
)
11449 struct x_display_info
*dpyinfo
;
11453 delete_keyboard_wait_descriptor (dpyinfo
->connection
);
11455 /* Discard this display from x_display_name_list and x_display_list.
11456 We can't use Fdelq because that can quit. */
11457 if (! NILP (x_display_name_list
)
11458 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
11459 x_display_name_list
= XCDR (x_display_name_list
);
11464 tail
= x_display_name_list
;
11465 while (CONSP (tail
) && CONSP (XCDR (tail
)))
11467 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
11469 XSETCDR (tail
, XCDR (XCDR (tail
)));
11472 tail
= XCDR (tail
);
11476 if (next_noop_dpyinfo
== dpyinfo
)
11477 next_noop_dpyinfo
= dpyinfo
->next
;
11479 if (x_display_list
== dpyinfo
)
11480 x_display_list
= dpyinfo
->next
;
11483 struct x_display_info
*tail
;
11485 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
11486 if (tail
->next
== dpyinfo
)
11487 tail
->next
= tail
->next
->next
;
11490 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
11491 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
11492 XrmDestroyDatabase (dpyinfo
->xrdb
);
11495 #ifdef MULTI_KBOARD
11496 if (--dpyinfo
->kboard
->reference_count
== 0)
11497 delete_kboard (dpyinfo
->kboard
);
11501 xim_close_dpy (dpyinfo
);
11504 /* Free the font names in the font table. */
11505 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
11506 if (dpyinfo
->font_table
[i
].name
)
11508 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
11509 xfree (dpyinfo
->font_table
[i
].full_name
);
11510 xfree (dpyinfo
->font_table
[i
].name
);
11513 if (dpyinfo
->font_table
)
11515 if (dpyinfo
->font_table
->font_encoder
)
11516 xfree (dpyinfo
->font_table
->font_encoder
);
11517 xfree (dpyinfo
->font_table
);
11519 if (dpyinfo
->x_id_name
)
11520 xfree (dpyinfo
->x_id_name
);
11521 if (dpyinfo
->color_cells
)
11522 xfree (dpyinfo
->color_cells
);
11526 #ifdef USE_X_TOOLKIT
11528 /* Atimer callback function for TIMER. Called every 0.1s to process
11529 Xt timeouts, if needed. We must avoid calling XtAppPending as
11530 much as possible because that function does an implicit XFlush
11531 that slows us down. */
11534 x_process_timeouts (timer
)
11535 struct atimer
*timer
;
11538 x_timeout_atimer_activated_flag
= 0;
11539 if (toolkit_scroll_bar_interaction
|| popup_activated ())
11541 while (XtAppPending (Xt_app_con
) & XtIMTimer
)
11542 XtAppProcessEvent (Xt_app_con
, XtIMTimer
);
11543 /* Reactivate the atimer for next time. */
11544 x_activate_timeout_atimer ();
11549 /* Install an asynchronous timer that processes Xt timeout events
11550 every 0.1s as long as either `toolkit_scroll_bar_interaction' or
11551 `popup_activated_flag' (in xmenu.c) is set. Make sure to call this
11552 function whenever these variables are set. This is necessary
11553 because some widget sets use timeouts internally, for example the
11554 LessTif menu bar, or the Xaw3d scroll bar. When Xt timeouts aren't
11555 processed, these widgets don't behave normally. */
11558 x_activate_timeout_atimer ()
11561 if (!x_timeout_atimer_activated_flag
)
11563 EMACS_TIME interval
;
11565 EMACS_SET_SECS_USECS (interval
, 0, 100000);
11566 start_atimer (ATIMER_RELATIVE
, interval
, x_process_timeouts
, 0);
11567 x_timeout_atimer_activated_flag
= 1;
11572 #endif /* USE_X_TOOLKIT */
11575 /* Set up use of X before we make the first connection. */
11577 extern frame_parm_handler x_frame_parm_handlers
[];
11579 static struct redisplay_interface x_redisplay_interface
=
11581 x_frame_parm_handlers
,
11585 x_clear_end_of_line
,
11587 x_after_update_window_line
,
11588 x_update_window_begin
,
11589 x_update_window_end
,
11595 0, /* flush_display_optional */
11597 x_clear_window_mouse_face
,
11598 x_get_glyph_overhangs
,
11599 x_fix_overlapping_area
,
11600 x_draw_fringe_bitmap
,
11601 0, /* define_fringe_bitmap */
11602 0, /* destroy_fringe_bitmap */
11605 x_compute_glyph_string_overhangs
,
11606 x_draw_glyph_string
,
11607 x_define_frame_cursor
,
11608 x_clear_frame_area
,
11609 x_draw_window_cursor
,
11610 x_draw_vertical_window_border
,
11611 x_shift_glyphs_for_insert
11617 rif
= &x_redisplay_interface
;
11619 clear_frame_hook
= x_clear_frame
;
11620 ins_del_lines_hook
= x_ins_del_lines
;
11621 delete_glyphs_hook
= x_delete_glyphs
;
11622 ring_bell_hook
= XTring_bell
;
11623 reset_terminal_modes_hook
= XTreset_terminal_modes
;
11624 set_terminal_modes_hook
= XTset_terminal_modes
;
11625 update_begin_hook
= x_update_begin
;
11626 update_end_hook
= x_update_end
;
11627 set_terminal_window_hook
= XTset_terminal_window
;
11628 read_socket_hook
= XTread_socket
;
11629 frame_up_to_date_hook
= XTframe_up_to_date
;
11630 mouse_position_hook
= XTmouse_position
;
11631 frame_rehighlight_hook
= XTframe_rehighlight
;
11632 frame_raise_lower_hook
= XTframe_raise_lower
;
11633 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
11634 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
11635 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
11636 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
11637 fullscreen_hook
= XTfullscreen_hook
;
11639 scroll_region_ok
= 1; /* we'll scroll partial frames */
11640 char_ins_del_ok
= 1;
11641 line_ins_del_ok
= 1; /* we'll just blt 'em */
11642 fast_clear_end_of_line
= 1; /* X does this well */
11643 memory_below_frame
= 0; /* we don't remember what scrolls
11648 last_tool_bar_item
= -1;
11649 any_help_event_p
= 0;
11650 ignore_next_mouse_click_timeout
= 0;
11652 x_session_initialized
= 0;
11656 current_count
= -1;
11659 /* Try to use interrupt input; if we can't, then start polling. */
11660 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
11662 #ifdef USE_X_TOOLKIT
11663 XtToolkitInitialize ();
11665 Xt_app_con
= XtCreateApplicationContext ();
11667 /* Register a converter from strings to pixels, which uses
11668 Emacs' color allocation infrastructure. */
11669 XtAppSetTypeConverter (Xt_app_con
,
11670 XtRString
, XtRPixel
, cvt_string_to_pixel
,
11671 cvt_string_to_pixel_args
,
11672 XtNumber (cvt_string_to_pixel_args
),
11673 XtCacheByDisplay
, cvt_pixel_dtor
);
11675 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
11678 #ifdef USE_TOOLKIT_SCROLL_BARS
11680 xaw3d_arrow_scroll
= False
;
11681 xaw3d_pick_top
= True
;
11685 /* Note that there is no real way portable across R3/R4 to get the
11686 original error handler. */
11687 XSetErrorHandler (x_error_handler
);
11688 XSetIOErrorHandler (x_io_error_quitter
);
11690 /* Disable Window Change signals; they are handled by X events. */
11692 signal (SIGWINCH
, SIG_DFL
);
11693 #endif /* SIGWINCH */
11695 signal (SIGPIPE
, x_connection_signal
);
11702 x_error_message
= NULL
;
11704 staticpro (&x_display_name_list
);
11705 x_display_name_list
= Qnil
;
11707 staticpro (&last_mouse_scroll_bar
);
11708 last_mouse_scroll_bar
= Qnil
;
11710 staticpro (&Qvendor_specific_keysyms
);
11711 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
11713 staticpro (&Qlatin_1
);
11714 Qlatin_1
= intern ("latin-1");
11716 staticpro (&last_mouse_press_frame
);
11717 last_mouse_press_frame
= Qnil
;
11719 DEFVAR_BOOL ("x-use-underline-position-properties",
11720 &x_use_underline_position_properties
,
11721 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
11722 A value of nil means ignore them. If you encounter fonts with bogus
11723 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
11724 to 4.1, set this to nil. */);
11725 x_use_underline_position_properties
= 1;
11727 DEFVAR_BOOL ("x-underline-at-descent-line",
11728 &x_underline_at_descent_line
,
11729 doc
: /* *Non-nil means to draw the underline at the same place as the descent line.
11730 A value of nil means to draw the underline according to the value of the
11731 variable `x-use-underline-position-properties', which is usually at the
11732 baseline level. The default value is nil. */);
11733 x_underline_at_descent_line
= 0;
11735 DEFVAR_BOOL ("x-mouse-click-focus-ignore-position",
11736 &x_mouse_click_focus_ignore_position
,
11737 doc
: /* Non-nil means that a mouse click to focus a frame does not move point.
11738 This variable is only used when the window manager requires that you
11739 click on a frame to select it (give it focus). In that case, a value
11740 of nil, means that the selected window and cursor position changes to
11741 reflect the mouse click position, while a non-nil value means that the
11742 selected window or cursor position is preserved. */);
11743 x_mouse_click_focus_ignore_position
= 0;
11745 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
11746 doc
: /* What X toolkit scroll bars Emacs uses.
11747 A value of nil means Emacs doesn't use X toolkit scroll bars.
11748 Otherwise, value is a symbol describing the X toolkit. */);
11749 #ifdef USE_TOOLKIT_SCROLL_BARS
11751 Vx_toolkit_scroll_bars
= intern ("motif");
11752 #elif defined HAVE_XAW3D
11753 Vx_toolkit_scroll_bars
= intern ("xaw3d");
11755 Vx_toolkit_scroll_bars
= intern ("gtk");
11757 Vx_toolkit_scroll_bars
= intern ("xaw");
11760 Vx_toolkit_scroll_bars
= Qnil
;
11763 staticpro (&last_mouse_motion_frame
);
11764 last_mouse_motion_frame
= Qnil
;
11766 Qmodifier_value
= intern ("modifier-value");
11767 Qalt
= intern ("alt");
11768 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
11769 Qhyper
= intern ("hyper");
11770 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
11771 Qmeta
= intern ("meta");
11772 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
11773 Qsuper
= intern ("super");
11774 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
11776 DEFVAR_LISP ("x-alt-keysym", &Vx_alt_keysym
,
11777 doc
: /* Which keys Emacs uses for the alt modifier.
11778 This should be one of the symbols `alt', `hyper', `meta', `super'.
11779 For example, `alt' means use the Alt_L and Alt_R keysyms. The default
11780 is nil, which is the same as `alt'. */);
11781 Vx_alt_keysym
= Qnil
;
11783 DEFVAR_LISP ("x-hyper-keysym", &Vx_hyper_keysym
,
11784 doc
: /* Which keys Emacs uses for the hyper modifier.
11785 This should be one of the symbols `alt', `hyper', `meta', `super'.
11786 For example, `hyper' means use the Hyper_L and Hyper_R keysyms. The
11787 default is nil, which is the same as `hyper'. */);
11788 Vx_hyper_keysym
= Qnil
;
11790 DEFVAR_LISP ("x-meta-keysym", &Vx_meta_keysym
,
11791 doc
: /* Which keys Emacs uses for the meta modifier.
11792 This should be one of the symbols `alt', `hyper', `meta', `super'.
11793 For example, `meta' means use the Meta_L and Meta_R keysyms. The
11794 default is nil, which is the same as `meta'. */);
11795 Vx_meta_keysym
= Qnil
;
11797 DEFVAR_LISP ("x-super-keysym", &Vx_super_keysym
,
11798 doc
: /* Which keys Emacs uses for the super modifier.
11799 This should be one of the symbols `alt', `hyper', `meta', `super'.
11800 For example, `super' means use the Super_L and Super_R keysyms. The
11801 default is nil, which is the same as `super'. */);
11802 Vx_super_keysym
= Qnil
;
11804 DEFVAR_LISP ("x-keysym-table", &Vx_keysym_table
,
11805 doc
: /* Hash table of character codes indexed by X keysym codes. */);
11806 Vx_keysym_table
= make_hash_table (Qeql
, make_number (900),
11807 make_float (DEFAULT_REHASH_SIZE
),
11808 make_float (DEFAULT_REHASH_THRESHOLD
),
11812 #endif /* HAVE_X_WINDOWS */
11814 /* arch-tag: 6d4e4cb7-abc1-4302-9585-d84dcfb09d0f
11815 (do not change this comment) */