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