(kermit-esc-char, kermit-clean-off): Doc fixes.
[emacs.git] / src / xterm.c
blob9f3ce1a660862207e0647ecb4b4a93a7b4d9122d
1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
3 2002, 2003, 2004, 2005, 2006, 2007, 2008
4 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
21 /* New display code by Gerd Moellmann <gerd@gnu.org>. */
22 /* Xt features made by Fred Pierresteguy. */
24 #include <config.h>
26 /* On 4.3 these lose if they come after xterm.h. */
27 /* Putting these at the beginning seems to be standard for other .c files. */
28 #include <signal.h>
30 #include <stdio.h>
32 #ifdef HAVE_X_WINDOWS
34 #include "lisp.h"
35 #include "blockinput.h"
37 /* Need syssignal.h for various externs and definitions that may be required
38 by some configurations for calls to signal later in this source file. */
39 #include "syssignal.h"
41 /* This may include sys/types.h, and that somehow loses
42 if this is not done before the other system files. */
43 #include "xterm.h"
44 #include <X11/cursorfont.h>
46 /* Load sys/types.h if not already loaded.
47 In some systems loading it twice is suicidal. */
48 #ifndef makedev
49 #include <sys/types.h>
50 #endif /* makedev */
52 #ifdef BSD_SYSTEM
53 #include <sys/ioctl.h>
54 #endif /* ! defined (BSD_SYSTEM) */
56 #include "systime.h"
58 #ifndef INCLUDED_FCNTL
59 #include <fcntl.h>
60 #endif
61 #include <ctype.h>
62 #include <errno.h>
63 #include <setjmp.h>
64 #include <sys/stat.h>
65 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
66 /* #include <sys/param.h> */
68 #include "charset.h"
69 #include "character.h"
70 #include "coding.h"
71 #include "frame.h"
72 #include "dispextern.h"
73 #include "fontset.h"
74 #include "termhooks.h"
75 #include "termopts.h"
76 #include "termchar.h"
77 #include "emacs-icon.h"
78 #include "disptab.h"
79 #include "buffer.h"
80 #include "window.h"
81 #include "keyboard.h"
82 #include "intervals.h"
83 #include "process.h"
84 #include "atimer.h"
85 #include "keymap.h"
86 #include "font.h"
88 #ifdef USE_X_TOOLKIT
89 #include <X11/Shell.h>
90 #endif
92 #ifdef HAVE_SYS_TIME_H
93 #include <sys/time.h>
94 #endif
95 #ifdef HAVE_UNISTD_H
96 #include <unistd.h>
97 #endif
99 #ifdef USE_GTK
100 #include "gtkutil.h"
101 #endif
103 #ifdef USE_LUCID
104 extern int xlwmenu_window_p P_ ((Widget w, Window window));
105 extern void xlwmenu_redisplay P_ ((Widget));
106 #endif
108 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
110 extern void free_frame_menubar P_ ((struct frame *));
111 extern struct frame *x_menubar_window_to_frame P_ ((struct x_display_info *,
112 int));
113 #endif
115 #ifdef USE_X_TOOLKIT
116 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
117 #define HACK_EDITRES
118 extern void _XEditResCheckMessages ();
119 #endif /* not NO_EDITRES */
121 /* Include toolkit specific headers for the scroll bar widget. */
123 #ifdef USE_TOOLKIT_SCROLL_BARS
124 #if defined USE_MOTIF
125 #include <Xm/Xm.h> /* for LESSTIF_VERSION */
126 #include <Xm/ScrollBar.h>
127 #else /* !USE_MOTIF i.e. use Xaw */
129 #ifdef HAVE_XAW3D
130 #include <X11/Xaw3d/Simple.h>
131 #include <X11/Xaw3d/Scrollbar.h>
132 #include <X11/Xaw3d/ThreeD.h>
133 #else /* !HAVE_XAW3D */
134 #include <X11/Xaw/Simple.h>
135 #include <X11/Xaw/Scrollbar.h>
136 #endif /* !HAVE_XAW3D */
137 #ifndef XtNpickTop
138 #define XtNpickTop "pickTop"
139 #endif /* !XtNpickTop */
140 #endif /* !USE_MOTIF */
141 #endif /* USE_TOOLKIT_SCROLL_BARS */
143 #endif /* USE_X_TOOLKIT */
145 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
146 #define x_any_window_to_frame x_window_to_frame
147 #define x_top_window_to_frame x_window_to_frame
148 #endif
150 #ifdef USE_X_TOOLKIT
151 #include "widget.h"
152 #ifndef XtNinitialState
153 #define XtNinitialState "initialState"
154 #endif
155 #endif
157 /* Default to using XIM if available. */
158 #ifdef USE_XIM
159 int use_xim = 1;
160 #else
161 int use_xim = 0; /* configure --without-xim */
162 #endif
166 /* Non-nil means Emacs uses toolkit scroll bars. */
168 Lisp_Object Vx_toolkit_scroll_bars;
170 /* Non-zero means that a HELP_EVENT has been generated since Emacs
171 start. */
173 static int any_help_event_p;
175 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
176 static Lisp_Object last_window;
178 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
180 int x_use_underline_position_properties;
182 /* Non-zero means to draw the underline at the same place as the descent line. */
184 int x_underline_at_descent_line;
186 /* This is a chain of structures for all the X displays currently in
187 use. */
189 struct x_display_info *x_display_list;
191 /* This is a list of cons cells, each of the form (NAME
192 . FONT-LIST-CACHE), one for each element of x_display_list and in
193 the same order. NAME is the name of the frame. FONT-LIST-CACHE
194 records previous values returned by x-list-fonts. */
196 Lisp_Object x_display_name_list;
198 /* Frame being updated by update_frame. This is declared in term.c.
199 This is set by update_begin and looked at by all the XT functions.
200 It is zero while not inside an update. In that case, the XT
201 functions assume that `selected_frame' is the frame to apply to. */
203 extern struct frame *updating_frame;
205 /* This is a frame waiting to be auto-raised, within XTread_socket. */
207 struct frame *pending_autoraise_frame;
209 #ifdef USE_X_TOOLKIT
210 /* The application context for Xt use. */
211 XtAppContext Xt_app_con;
212 static String Xt_default_resources[] = {0};
213 #endif /* USE_X_TOOLKIT */
215 /* Non-zero means user is interacting with a toolkit scroll bar. */
217 static int toolkit_scroll_bar_interaction;
219 /* Non-zero means to not move point as a result of clicking on a
220 frame to focus it (when focus-follows-mouse is nil). */
222 int x_mouse_click_focus_ignore_position;
224 /* Non-zero timeout value means ignore next mouse click if it arrives
225 before that timeout elapses (i.e. as part of the same sequence of
226 events resulting from clicking on a frame to select it). */
228 static unsigned long ignore_next_mouse_click_timeout;
230 /* Mouse movement.
232 Formerly, we used PointerMotionHintMask (in standard_event_mask)
233 so that we would have to call XQueryPointer after each MotionNotify
234 event to ask for another such event. However, this made mouse tracking
235 slow, and there was a bug that made it eventually stop.
237 Simply asking for MotionNotify all the time seems to work better.
239 In order to avoid asking for motion events and then throwing most
240 of them away or busy-polling the server for mouse positions, we ask
241 the server for pointer motion hints. This means that we get only
242 one event per group of mouse movements. "Groups" are delimited by
243 other kinds of events (focus changes and button clicks, for
244 example), or by XQueryPointer calls; when one of these happens, we
245 get another MotionNotify event the next time the mouse moves. This
246 is at least as efficient as getting motion events when mouse
247 tracking is on, and I suspect only negligibly worse when tracking
248 is off. */
250 /* Where the mouse was last time we reported a mouse event. */
252 static XRectangle last_mouse_glyph;
253 static FRAME_PTR last_mouse_glyph_frame;
254 static Lisp_Object last_mouse_press_frame;
256 /* The scroll bar in which the last X motion event occurred.
258 If the last X motion event occurred in a scroll bar, we set this so
259 XTmouse_position can know whether to report a scroll bar motion or
260 an ordinary motion.
262 If the last X motion event didn't occur in a scroll bar, we set
263 this to Qnil, to tell XTmouse_position to return an ordinary motion
264 event. */
266 static Lisp_Object last_mouse_scroll_bar;
268 /* This is a hack. We would really prefer that XTmouse_position would
269 return the time associated with the position it returns, but there
270 doesn't seem to be any way to wrest the time-stamp from the server
271 along with the position query. So, we just keep track of the time
272 of the last movement we received, and return that in hopes that
273 it's somewhat accurate. */
275 static Time last_mouse_movement_time;
277 /* Time for last user interaction as returned in X events. */
279 static Time last_user_time;
281 /* Incremented by XTread_socket whenever it really tries to read
282 events. */
284 #ifdef __STDC__
285 static int volatile input_signal_count;
286 #else
287 static int input_signal_count;
288 #endif
290 /* Used locally within XTread_socket. */
292 static int x_noop_count;
294 /* Initial values of argv and argc. */
296 extern char **initial_argv;
297 extern int initial_argc;
299 extern Lisp_Object Vcommand_line_args, Vsystem_name;
301 /* Tells if a window manager is present or not. */
303 extern Lisp_Object Vx_no_window_manager;
305 extern Lisp_Object Qeql;
307 extern int errno;
309 /* A mask of extra modifier bits to put into every keyboard char. */
311 extern EMACS_INT extra_keyboard_modifiers;
313 /* The keysyms to use for the various modifiers. */
315 Lisp_Object Vx_alt_keysym, Vx_hyper_keysym, Vx_meta_keysym, Vx_super_keysym;
316 Lisp_Object Vx_keysym_table;
317 static Lisp_Object Qalt, Qhyper, Qmeta, Qsuper, Qmodifier_value;
319 static Lisp_Object Qvendor_specific_keysyms;
320 static Lisp_Object Qlatin_1;
322 /* Used in x_flush. */
324 extern Lisp_Object Vinhibit_redisplay;
326 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
327 extern int x_bitmap_mask P_ ((FRAME_PTR, int));
329 static int x_alloc_nearest_color_1 P_ ((Display *, Colormap, XColor *));
330 static void x_set_window_size_1 P_ ((struct frame *, int, int, int));
331 static const XColor *x_color_cells P_ ((Display *, int *));
332 static void x_update_window_end P_ ((struct window *, int, int));
334 static int x_io_error_quitter P_ ((Display *));
335 static struct terminal *x_create_terminal P_ ((struct x_display_info *));
336 void x_delete_terminal P_ ((struct terminal *));
337 static void x_update_end P_ ((struct frame *));
338 static void XTframe_up_to_date P_ ((struct frame *));
339 static void XTset_terminal_modes P_ ((struct terminal *));
340 static void XTreset_terminal_modes P_ ((struct terminal *));
341 static void x_clear_frame P_ ((struct frame *));
342 static void frame_highlight P_ ((struct frame *));
343 static void frame_unhighlight P_ ((struct frame *));
344 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
345 static void x_focus_changed P_ ((int, int, struct x_display_info *,
346 struct frame *, struct input_event *));
347 static void x_detect_focus_change P_ ((struct x_display_info *,
348 XEvent *, struct input_event *));
349 static void XTframe_rehighlight P_ ((struct frame *));
350 static void x_frame_rehighlight P_ ((struct x_display_info *));
351 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
352 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
353 enum text_cursor_kinds));
355 static void x_clip_to_row P_ ((struct window *, struct glyph_row *, int, 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 *, int, int));
367 static void x_sync_with_move P_ ((struct frame *, int, int, int));
368 static int handle_one_xevent P_ ((struct x_display_info *, XEvent *,
369 int *, struct input_event *));
370 /* Don't declare this NO_RETURN because we want no
371 interference with debugging failing X calls. */
372 static SIGTYPE x_connection_closed P_ ((Display *, char *));
375 /* Flush display of frame F, or of all frames if F is null. */
377 static void
378 x_flush (f)
379 struct frame *f;
381 /* Don't call XFlush when it is not safe to redisplay; the X
382 connection may be broken. */
383 if (!NILP (Vinhibit_redisplay))
384 return;
386 BLOCK_INPUT;
387 if (f == NULL)
389 Lisp_Object rest, frame;
390 FOR_EACH_FRAME (rest, frame)
391 if (FRAME_X_P (XFRAME (frame)))
392 x_flush (XFRAME (frame));
394 else if (FRAME_X_P (f))
395 XFlush (FRAME_X_DISPLAY (f));
396 UNBLOCK_INPUT;
400 /* Remove calls to XFlush by defining XFlush to an empty replacement.
401 Calls to XFlush should be unnecessary because the X output buffer
402 is flushed automatically as needed by calls to XPending,
403 XNextEvent, or XWindowEvent according to the XFlush man page.
404 XTread_socket calls XPending. Removing XFlush improves
405 performance. */
407 #define XFlush(DISPLAY) (void) 0
410 /***********************************************************************
411 Debugging
412 ***********************************************************************/
414 #if 0
416 /* This is a function useful for recording debugging information about
417 the sequence of occurrences in this file. */
419 struct record
421 char *locus;
422 int type;
425 struct record event_record[100];
427 int event_record_index;
429 record_event (locus, type)
430 char *locus;
431 int type;
433 if (event_record_index == sizeof (event_record) / sizeof (struct record))
434 event_record_index = 0;
436 event_record[event_record_index].locus = locus;
437 event_record[event_record_index].type = type;
438 event_record_index++;
441 #endif /* 0 */
445 /* Return the struct x_display_info corresponding to DPY. */
447 struct x_display_info *
448 x_display_info_for_display (dpy)
449 Display *dpy;
451 struct x_display_info *dpyinfo;
453 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
454 if (dpyinfo->display == dpy)
455 return dpyinfo;
457 return 0;
460 #define OPAQUE 0xffffffff
461 #define OPACITY "_NET_WM_WINDOW_OPACITY"
463 void
464 x_set_frame_alpha (f)
465 struct frame *f;
467 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
468 Display *dpy = FRAME_X_DISPLAY (f);
469 Window win = FRAME_OUTER_WINDOW (f);
470 double alpha = 1.0;
471 double alpha_min = 1.0;
472 unsigned long opac;
474 if (FRAME_X_DISPLAY_INFO (f)->root_window != FRAME_X_OUTPUT (f)->parent_desc)
475 /* Since the WM decoration lies under the FRAME_OUTER_WINDOW,
476 we must treat the former instead of the latter. */
477 win = FRAME_X_OUTPUT(f)->parent_desc;
479 if (dpyinfo->x_highlight_frame == f)
480 alpha = f->alpha[0];
481 else
482 alpha = f->alpha[1];
484 if (FLOATP (Vframe_alpha_lower_limit))
485 alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit);
486 else if (INTEGERP (Vframe_alpha_lower_limit))
487 alpha_min = (XINT (Vframe_alpha_lower_limit)) / 100.0;
489 if (alpha < 0.0 || 1.0 < alpha)
490 alpha = 1.0;
491 else if (0.0 <= alpha && alpha < alpha_min && alpha_min <= 1.0)
492 alpha = alpha_min;
494 opac = alpha * OPAQUE;
496 /* return unless necessary */
498 unsigned char *data;
499 Atom actual;
500 int rc, format;
501 unsigned long n, left;
503 x_catch_errors (dpy);
504 rc = XGetWindowProperty(dpy, win, XInternAtom(dpy, OPACITY, False),
505 0L, 1L, False, XA_CARDINAL,
506 &actual, &format, &n, &left,
507 &data);
509 if (rc == Success && actual != None)
510 if (*(unsigned long *)data == opac)
512 XFree ((void *) data);
513 x_uncatch_errors ();
514 return;
516 else
517 XFree ((void *) data);
518 x_uncatch_errors ();
521 x_catch_errors (dpy);
522 XChangeProperty (dpy, win, XInternAtom (dpy, OPACITY, False),
523 XA_CARDINAL, 32, PropModeReplace,
524 (unsigned char *) &opac, 1L);
525 x_uncatch_errors ();
529 /***********************************************************************
530 Starting and ending an update
531 ***********************************************************************/
533 /* Start an update of frame F. This function is installed as a hook
534 for update_begin, i.e. it is called when update_begin is called.
535 This function is called prior to calls to x_update_window_begin for
536 each window being updated. Currently, there is nothing to do here
537 because all interesting stuff is done on a window basis. */
539 static void
540 x_update_begin (f)
541 struct frame *f;
543 /* Nothing to do. */
547 /* Start update of window W. Set the global variable updated_window
548 to the window being updated and set output_cursor to the cursor
549 position of W. */
551 static void
552 x_update_window_begin (w)
553 struct window *w;
555 struct frame *f = XFRAME (WINDOW_FRAME (w));
556 struct x_display_info *display_info = FRAME_X_DISPLAY_INFO (f);
558 updated_window = w;
559 set_output_cursor (&w->cursor);
561 BLOCK_INPUT;
563 if (f == display_info->mouse_face_mouse_frame)
565 /* Don't do highlighting for mouse motion during the update. */
566 display_info->mouse_face_defer = 1;
568 /* If F needs to be redrawn, simply forget about any prior mouse
569 highlighting. */
570 if (FRAME_GARBAGED_P (f))
571 display_info->mouse_face_window = Qnil;
573 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
574 their mouse_face_p flag set, which means that they are always
575 unequal to rows in a desired matrix which never have that
576 flag set. So, rows containing mouse-face glyphs are never
577 scrolled, and we don't have to switch the mouse highlight off
578 here to prevent it from being scrolled. */
580 /* Can we tell that this update does not affect the window
581 where the mouse highlight is? If so, no need to turn off.
582 Likewise, don't do anything if the frame is garbaged;
583 in that case, the frame's current matrix that we would use
584 is all wrong, and we will redisplay that line anyway. */
585 if (!NILP (display_info->mouse_face_window)
586 && w == XWINDOW (display_info->mouse_face_window))
588 int i;
590 for (i = 0; i < w->desired_matrix->nrows; ++i)
591 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
592 break;
594 if (i < w->desired_matrix->nrows)
595 clear_mouse_face (display_info);
597 #endif /* 0 */
600 UNBLOCK_INPUT;
604 /* Draw a vertical window border from (x,y0) to (x,y1) */
606 static void
607 x_draw_vertical_window_border (w, x, y0, y1)
608 struct window *w;
609 int x, y0, y1;
611 struct frame *f = XFRAME (WINDOW_FRAME (w));
612 struct face *face;
614 face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
615 if (face)
616 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
617 face->foreground);
619 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
620 f->output_data.x->normal_gc, x, y0, x, y1);
623 /* End update of window W (which is equal to updated_window).
625 Draw vertical borders between horizontally adjacent windows, and
626 display W's cursor if CURSOR_ON_P is non-zero.
628 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
629 glyphs in mouse-face were overwritten. In that case we have to
630 make sure that the mouse-highlight is properly redrawn.
632 W may be a menu bar pseudo-window in case we don't have X toolkit
633 support. Such windows don't have a cursor, so don't display it
634 here. */
636 static void
637 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
638 struct window *w;
639 int cursor_on_p, mouse_face_overwritten_p;
641 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
643 if (!w->pseudo_window_p)
645 BLOCK_INPUT;
647 if (cursor_on_p)
648 display_and_set_cursor (w, 1, output_cursor.hpos,
649 output_cursor.vpos,
650 output_cursor.x, output_cursor.y);
652 if (draw_window_fringes (w, 1))
653 x_draw_vertical_border (w);
655 UNBLOCK_INPUT;
658 /* If a row with mouse-face was overwritten, arrange for
659 XTframe_up_to_date to redisplay the mouse highlight. */
660 if (mouse_face_overwritten_p)
662 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
663 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
664 dpyinfo->mouse_face_window = Qnil;
667 updated_window = NULL;
671 /* End update of frame F. This function is installed as a hook in
672 update_end. */
674 static void
675 x_update_end (f)
676 struct frame *f;
678 /* Mouse highlight may be displayed again. */
679 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
681 #ifndef XFlush
682 BLOCK_INPUT;
683 XFlush (FRAME_X_DISPLAY (f));
684 UNBLOCK_INPUT;
685 #endif
689 /* This function is called from various places in xdisp.c whenever a
690 complete update has been performed. The global variable
691 updated_window is not available here. */
693 static void
694 XTframe_up_to_date (f)
695 struct frame *f;
697 if (FRAME_X_P (f))
699 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
701 if (dpyinfo->mouse_face_deferred_gc
702 || f == dpyinfo->mouse_face_mouse_frame)
704 BLOCK_INPUT;
705 if (dpyinfo->mouse_face_mouse_frame)
706 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
707 dpyinfo->mouse_face_mouse_x,
708 dpyinfo->mouse_face_mouse_y);
709 dpyinfo->mouse_face_deferred_gc = 0;
710 UNBLOCK_INPUT;
716 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
717 arrow bitmaps, or clear the fringes if no bitmaps are required
718 before DESIRED_ROW is made current. The window being updated is
719 found in updated_window. This function It is called from
720 update_window_line only if it is known that there are differences
721 between bitmaps to be drawn between current row and DESIRED_ROW. */
723 static void
724 x_after_update_window_line (desired_row)
725 struct glyph_row *desired_row;
727 struct window *w = updated_window;
728 struct frame *f;
729 int width, height;
731 xassert (w);
733 if (!desired_row->mode_line_p && !w->pseudo_window_p)
734 desired_row->redraw_fringe_bitmaps_p = 1;
736 /* When a window has disappeared, make sure that no rest of
737 full-width rows stays visible in the internal border. Could
738 check here if updated_window is the leftmost/rightmost window,
739 but I guess it's not worth doing since vertically split windows
740 are almost never used, internal border is rarely set, and the
741 overhead is very small. */
742 if (windows_or_buffers_changed
743 && desired_row->full_width_p
744 && (f = XFRAME (w->frame),
745 width = FRAME_INTERNAL_BORDER_WIDTH (f),
746 width != 0)
747 && (height = desired_row->visible_height,
748 height > 0))
750 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
752 /* Internal border is drawn below the tool bar. */
753 if (WINDOWP (f->tool_bar_window)
754 && w == XWINDOW (f->tool_bar_window))
755 y -= width;
757 BLOCK_INPUT;
758 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
759 0, y, width, height, False);
760 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
761 FRAME_PIXEL_WIDTH (f) - width,
762 y, width, height, False);
763 UNBLOCK_INPUT;
767 static void
768 x_draw_fringe_bitmap (w, row, p)
769 struct window *w;
770 struct glyph_row *row;
771 struct draw_fringe_bitmap_params *p;
773 struct frame *f = XFRAME (WINDOW_FRAME (w));
774 Display *display = FRAME_X_DISPLAY (f);
775 Window window = FRAME_X_WINDOW (f);
776 GC gc = f->output_data.x->normal_gc;
777 struct face *face = p->face;
778 int rowY;
780 /* Must clip because of partially visible lines. */
781 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
782 if (p->y < rowY)
784 /* Adjust position of "bottom aligned" bitmap on partially
785 visible last row. */
786 int oldY = row->y;
787 int oldVH = row->visible_height;
788 row->visible_height = p->h;
789 row->y -= rowY - p->y;
790 x_clip_to_row (w, row, -1, gc);
791 row->y = oldY;
792 row->visible_height = oldVH;
794 else
795 x_clip_to_row (w, row, -1, gc);
797 if (!p->overlay_p)
799 int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
801 /* In case the same realized face is used for fringes and
802 for something displayed in the text (e.g. face `region' on
803 mono-displays, the fill style may have been changed to
804 FillSolid in x_draw_glyph_string_background. */
805 if (face->stipple)
806 XSetFillStyle (display, face->gc, FillOpaqueStippled);
807 else
808 XSetForeground (display, face->gc, face->background);
810 #ifdef USE_TOOLKIT_SCROLL_BARS
811 /* If the fringe is adjacent to the left (right) scroll bar of a
812 leftmost (rightmost, respectively) window, then extend its
813 background to the gap between the fringe and the bar. */
814 if ((WINDOW_LEFTMOST_P (w)
815 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
816 || (WINDOW_RIGHTMOST_P (w)
817 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
819 int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
821 if (sb_width > 0)
823 int left = WINDOW_SCROLL_BAR_AREA_X (w);
824 int width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
825 * FRAME_COLUMN_WIDTH (f));
827 if (bx < 0)
829 /* Bitmap fills the fringe. */
830 if (left + width == p->x)
831 bx = left + sb_width;
832 else if (p->x + p->wd == left)
833 bx = left;
834 if (bx >= 0)
836 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
838 nx = width - sb_width;
839 by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
840 row->y));
841 ny = row->visible_height;
844 else
846 if (left + width == bx)
848 bx = left + sb_width;
849 nx += width - sb_width;
851 else if (bx + nx == left)
852 nx += width - sb_width;
856 #endif
857 if (bx >= 0 && nx > 0)
858 XFillRectangle (display, window, face->gc, bx, by, nx, ny);
860 if (!face->stipple)
861 XSetForeground (display, face->gc, face->foreground);
864 if (p->which)
866 unsigned char *bits;
867 Pixmap pixmap, clipmask = (Pixmap) 0;
868 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
869 XGCValues gcv;
871 if (p->wd > 8)
872 bits = (unsigned char *)(p->bits + p->dh);
873 else
874 bits = (unsigned char *)p->bits + p->dh;
876 /* Draw the bitmap. I believe these small pixmaps can be cached
877 by the server. */
878 pixmap = XCreatePixmapFromBitmapData (display, window, bits, p->wd, p->h,
879 (p->cursor_p
880 ? (p->overlay_p ? face->background
881 : f->output_data.x->cursor_pixel)
882 : face->foreground),
883 face->background, depth);
885 if (p->overlay_p)
887 clipmask = XCreatePixmapFromBitmapData (display,
888 FRAME_X_DISPLAY_INFO (f)->root_window,
889 bits, p->wd, p->h,
890 1, 0, 1);
891 gcv.clip_mask = clipmask;
892 gcv.clip_x_origin = p->x;
893 gcv.clip_y_origin = p->y;
894 XChangeGC (display, gc, GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv);
897 XCopyArea (display, pixmap, window, gc, 0, 0,
898 p->wd, p->h, p->x, p->y);
899 XFreePixmap (display, pixmap);
901 if (p->overlay_p)
903 gcv.clip_mask = (Pixmap) 0;
904 XChangeGC (display, gc, GCClipMask, &gcv);
905 XFreePixmap (display, clipmask);
909 XSetClipMask (display, gc, None);
914 /* This is called when starting Emacs and when restarting after
915 suspend. When starting Emacs, no X window is mapped. And nothing
916 must be done to Emacs's own window if it is suspended (though that
917 rarely happens). */
919 static void
920 XTset_terminal_modes (struct terminal *terminal)
924 /* This is called when exiting or suspending Emacs. Exiting will make
925 the X-windows go away, and suspending requires no action. */
927 static void
928 XTreset_terminal_modes (struct terminal *terminal)
933 /***********************************************************************
934 Glyph display
935 ***********************************************************************/
939 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
940 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
941 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
942 int));
943 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
944 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
945 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
946 static void x_draw_glyph_string P_ ((struct glyph_string *));
947 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
948 static void x_set_cursor_gc P_ ((struct glyph_string *));
949 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
950 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
951 static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
952 unsigned long *, double, int));
953 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
954 double, int, unsigned long));
955 static void x_setup_relief_colors P_ ((struct glyph_string *));
956 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
957 static void x_draw_image_relief P_ ((struct glyph_string *));
958 static void x_draw_image_foreground P_ ((struct glyph_string *));
959 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
960 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
961 int, int, int));
962 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
963 int, int, int, int, int, int,
964 XRectangle *));
965 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
966 int, int, int, XRectangle *));
968 #if GLYPH_DEBUG
969 static void x_check_font P_ ((struct frame *, struct font *));
970 #endif
973 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
974 face. */
976 static void
977 x_set_cursor_gc (s)
978 struct glyph_string *s;
980 if (s->font == FRAME_FONT (s->f)
981 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
982 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
983 && !s->cmp)
984 s->gc = s->f->output_data.x->cursor_gc;
985 else
987 /* Cursor on non-default face: must merge. */
988 XGCValues xgcv;
989 unsigned long mask;
991 xgcv.background = s->f->output_data.x->cursor_pixel;
992 xgcv.foreground = s->face->background;
994 /* If the glyph would be invisible, try a different foreground. */
995 if (xgcv.foreground == xgcv.background)
996 xgcv.foreground = s->face->foreground;
997 if (xgcv.foreground == xgcv.background)
998 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
999 if (xgcv.foreground == xgcv.background)
1000 xgcv.foreground = s->face->foreground;
1002 /* Make sure the cursor is distinct from text in this face. */
1003 if (xgcv.background == s->face->background
1004 && xgcv.foreground == s->face->foreground)
1006 xgcv.background = s->face->foreground;
1007 xgcv.foreground = s->face->background;
1010 IF_DEBUG (x_check_font (s->f, s->font));
1011 xgcv.graphics_exposures = False;
1012 mask = GCForeground | GCBackground | GCGraphicsExposures;
1014 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1015 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1016 mask, &xgcv);
1017 else
1018 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
1019 = XCreateGC (s->display, s->window, mask, &xgcv);
1021 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1026 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1028 static void
1029 x_set_mouse_face_gc (s)
1030 struct glyph_string *s;
1032 int face_id;
1033 struct face *face;
1035 /* What face has to be used last for the mouse face? */
1036 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
1037 face = FACE_FROM_ID (s->f, face_id);
1038 if (face == NULL)
1039 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
1041 if (s->first_glyph->type == CHAR_GLYPH)
1042 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch, -1, Qnil);
1043 else
1044 face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil);
1045 s->face = FACE_FROM_ID (s->f, face_id);
1046 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1048 if (s->font == s->face->font)
1049 s->gc = s->face->gc;
1050 else
1052 /* Otherwise construct scratch_cursor_gc with values from FACE
1053 except for FONT. */
1054 XGCValues xgcv;
1055 unsigned long mask;
1057 xgcv.background = s->face->background;
1058 xgcv.foreground = s->face->foreground;
1059 xgcv.graphics_exposures = False;
1060 mask = GCForeground | GCBackground | GCGraphicsExposures;
1062 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1063 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1064 mask, &xgcv);
1065 else
1066 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
1067 = XCreateGC (s->display, s->window, mask, &xgcv);
1069 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1072 xassert (s->gc != 0);
1076 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1077 Faces to use in the mode line have already been computed when the
1078 matrix was built, so there isn't much to do, here. */
1080 static INLINE void
1081 x_set_mode_line_face_gc (s)
1082 struct glyph_string *s;
1084 s->gc = s->face->gc;
1088 /* Set S->gc of glyph string S for drawing that glyph string. Set
1089 S->stippled_p to a non-zero value if the face of S has a stipple
1090 pattern. */
1092 static INLINE void
1093 x_set_glyph_string_gc (s)
1094 struct glyph_string *s;
1096 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1098 if (s->hl == DRAW_NORMAL_TEXT)
1100 s->gc = s->face->gc;
1101 s->stippled_p = s->face->stipple != 0;
1103 else if (s->hl == DRAW_INVERSE_VIDEO)
1105 x_set_mode_line_face_gc (s);
1106 s->stippled_p = s->face->stipple != 0;
1108 else if (s->hl == DRAW_CURSOR)
1110 x_set_cursor_gc (s);
1111 s->stippled_p = 0;
1113 else if (s->hl == DRAW_MOUSE_FACE)
1115 x_set_mouse_face_gc (s);
1116 s->stippled_p = s->face->stipple != 0;
1118 else if (s->hl == DRAW_IMAGE_RAISED
1119 || s->hl == DRAW_IMAGE_SUNKEN)
1121 s->gc = s->face->gc;
1122 s->stippled_p = s->face->stipple != 0;
1124 else
1126 s->gc = s->face->gc;
1127 s->stippled_p = s->face->stipple != 0;
1130 /* GC must have been set. */
1131 xassert (s->gc != 0);
1135 /* Set clipping for output of glyph string S. S may be part of a mode
1136 line or menu if we don't have X toolkit support. */
1138 static INLINE void
1139 x_set_glyph_string_clipping (s)
1140 struct glyph_string *s;
1142 XRectangle *r = s->clip;
1143 int n = get_glyph_string_clip_rects (s, r, 2);
1145 if (n > 0)
1146 XSetClipRectangles (s->display, s->gc, 0, 0, r, n, Unsorted);
1147 s->num_clips = n;
1151 /* Set SRC's clipping for output of glyph string DST. This is called
1152 when we are drawing DST's left_overhang or right_overhang only in
1153 the area of SRC. */
1155 static void
1156 x_set_glyph_string_clipping_exactly (src, dst)
1157 struct glyph_string *src, *dst;
1159 XRectangle r;
1161 r.x = src->x;
1162 r.width = src->width;
1163 r.y = src->y;
1164 r.height = src->height;
1165 dst->clip[0] = r;
1166 dst->num_clips = 1;
1167 XSetClipRectangles (dst->display, dst->gc, 0, 0, &r, 1, Unsorted);
1171 /* RIF:
1172 Compute left and right overhang of glyph string S. */
1174 static void
1175 x_compute_glyph_string_overhangs (s)
1176 struct glyph_string *s;
1178 if (s->cmp == NULL
1179 && s->first_glyph->type == CHAR_GLYPH)
1181 unsigned *code = alloca (sizeof (unsigned) * s->nchars);
1182 struct font *font = s->font;
1183 struct font_metrics metrics;
1184 int i;
1186 for (i = 0; i < s->nchars; i++)
1187 code[i] = (s->char2b[i].byte1 << 8) | s->char2b[i].byte2;
1188 font->driver->text_extents (font, code, s->nchars, &metrics);
1189 s->right_overhang = (metrics.rbearing > metrics.width
1190 ? metrics.rbearing - metrics.width : 0);
1191 s->left_overhang = metrics.lbearing < 0 ? - metrics.lbearing : 0;
1193 else if (s->cmp)
1195 s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width;
1196 s->left_overhang = - s->cmp->lbearing;
1201 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1203 static INLINE void
1204 x_clear_glyph_string_rect (s, x, y, w, h)
1205 struct glyph_string *s;
1206 int x, y, w, h;
1208 XGCValues xgcv;
1209 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
1210 XSetForeground (s->display, s->gc, xgcv.background);
1211 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
1212 XSetForeground (s->display, s->gc, xgcv.foreground);
1216 /* Draw the background of glyph_string S. If S->background_filled_p
1217 is non-zero don't draw it. FORCE_P non-zero means draw the
1218 background even if it wouldn't be drawn normally. This is used
1219 when a string preceding S draws into the background of S, or S
1220 contains the first component of a composition. */
1222 static void
1223 x_draw_glyph_string_background (s, force_p)
1224 struct glyph_string *s;
1225 int force_p;
1227 /* Nothing to do if background has already been drawn or if it
1228 shouldn't be drawn in the first place. */
1229 if (!s->background_filled_p)
1231 int box_line_width = max (s->face->box_line_width, 0);
1233 if (s->stippled_p)
1235 /* Fill background with a stipple pattern. */
1236 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
1237 XFillRectangle (s->display, s->window, s->gc, s->x,
1238 s->y + box_line_width,
1239 s->background_width,
1240 s->height - 2 * box_line_width);
1241 XSetFillStyle (s->display, s->gc, FillSolid);
1242 s->background_filled_p = 1;
1244 else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
1245 || s->font_not_found_p
1246 || s->extends_to_end_of_line_p
1247 || force_p)
1249 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
1250 s->background_width,
1251 s->height - 2 * box_line_width);
1252 s->background_filled_p = 1;
1258 /* Draw the foreground of glyph string S. */
1260 static void
1261 x_draw_glyph_string_foreground (s)
1262 struct glyph_string *s;
1264 int i, x;
1266 /* If first glyph of S has a left box line, start drawing the text
1267 of S to the right of that box line. */
1268 if (s->face->box != FACE_NO_BOX
1269 && s->first_glyph->left_box_line_p)
1270 x = s->x + eabs (s->face->box_line_width);
1271 else
1272 x = s->x;
1274 /* Draw characters of S as rectangles if S's font could not be
1275 loaded. */
1276 if (s->font_not_found_p)
1278 for (i = 0; i < s->nchars; ++i)
1280 struct glyph *g = s->first_glyph + i;
1281 XDrawRectangle (s->display, s->window,
1282 s->gc, x, s->y, g->pixel_width - 1,
1283 s->height - 1);
1284 x += g->pixel_width;
1287 else
1289 struct font *font = s->font;
1290 int boff = font->baseline_offset;
1291 int y;
1293 if (font->vertical_centering)
1294 boff = VCENTER_BASELINE_OFFSET (font, s->f) - boff;
1296 y = s->ybase - boff;
1297 if (s->for_overlaps
1298 || (s->background_filled_p && s->hl != DRAW_CURSOR))
1299 font->driver->draw (s, 0, s->nchars, x, y, 0);
1300 else
1301 font->driver->draw (s, 0, s->nchars, x, y, 1);
1302 if (s->face->overstrike)
1303 font->driver->draw (s, 0, s->nchars, x + 1, y, 0);
1307 /* Draw the foreground of composite glyph string S. */
1309 static void
1310 x_draw_composite_glyph_string_foreground (s)
1311 struct glyph_string *s;
1313 int i, j, x;
1315 /* If first glyph of S has a left box line, start drawing the text
1316 of S to the right of that box line. */
1317 if (s->face && s->face->box != FACE_NO_BOX
1318 && s->first_glyph->left_box_line_p)
1319 x = s->x + eabs (s->face->box_line_width);
1320 else
1321 x = s->x;
1323 /* S is a glyph string for a composition. S->gidx is the index of
1324 the first character drawn for glyphs of this composition.
1325 S->gidx == 0 means we are drawing the very first character of
1326 this composition. */
1328 /* Draw a rectangle for the composition if the font for the very
1329 first character of the composition could not be loaded. */
1330 if (s->font_not_found_p)
1332 if (s->gidx == 0)
1333 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
1334 s->width - 1, s->height - 1);
1336 else
1338 struct font *font = s->font;
1339 int y = s->ybase;
1340 int width = 0;
1342 if (s->cmp->method == COMPOSITION_WITH_GLYPH_STRING)
1344 Lisp_Object gstring = AREF (XHASH_TABLE (composition_hash_table)
1345 ->key_and_value,
1346 s->cmp->hash_index * 2);
1347 int from;
1349 for (i = from = 0; i < s->nchars; i++)
1351 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
1352 Lisp_Object adjustment = LGLYPH_ADJUSTMENT (g);
1353 int xoff, yoff, wadjust;
1355 if (! VECTORP (adjustment))
1357 width += LGLYPH_WIDTH (g);
1358 continue;
1360 if (from < i)
1362 font->driver->draw (s, from, i, x, y, 0);
1363 x += width;
1365 xoff = XINT (AREF (adjustment, 0));
1366 yoff = XINT (AREF (adjustment, 1));
1367 wadjust = XINT (AREF (adjustment, 2));
1369 font->driver->draw (s, i, i + 1, x + xoff, y + yoff, 0);
1370 x += wadjust;
1371 from = i + 1;
1372 width = 0;
1374 if (from < i)
1375 font->driver->draw (s, from, i, x, y, 0);
1377 else
1379 for (i = 0, j = s->gidx; i < s->nchars; i++, j++)
1380 if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
1382 int xx = x + s->cmp->offsets[j * 2];
1383 int yy = y - s->cmp->offsets[j * 2 + 1];
1385 font->driver->draw (s, j, j + 1, xx, yy, 0);
1386 if (s->face->overstrike)
1387 font->driver->draw (s, j, j + 1, xx + 1, yy, 0);
1394 #ifdef USE_X_TOOLKIT
1396 static struct frame *x_frame_of_widget P_ ((Widget));
1397 static Boolean cvt_string_to_pixel P_ ((Display *, XrmValue *, Cardinal *,
1398 XrmValue *, XrmValue *, XtPointer *));
1399 static void cvt_pixel_dtor P_ ((XtAppContext, XrmValue *, XtPointer,
1400 XrmValue *, Cardinal *));
1403 /* Return the frame on which widget WIDGET is used.. Abort if frame
1404 cannot be determined. */
1406 static struct frame *
1407 x_frame_of_widget (widget)
1408 Widget widget;
1410 struct x_display_info *dpyinfo;
1411 Lisp_Object tail;
1412 struct frame *f;
1414 dpyinfo = x_display_info_for_display (XtDisplay (widget));
1416 /* Find the top-level shell of the widget. Note that this function
1417 can be called when the widget is not yet realized, so XtWindow
1418 (widget) == 0. That's the reason we can't simply use
1419 x_any_window_to_frame. */
1420 while (!XtIsTopLevelShell (widget))
1421 widget = XtParent (widget);
1423 /* Look for a frame with that top-level widget. Allocate the color
1424 on that frame to get the right gamma correction value. */
1425 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1426 if (FRAMEP (XCAR (tail))
1427 && (f = XFRAME (XCAR (tail)),
1428 (FRAME_X_P (f)
1429 && f->output_data.nothing != 1
1430 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
1431 && f->output_data.x->widget == widget)
1432 return f;
1434 abort ();
1438 /* Allocate the color COLOR->pixel on the screen and display of
1439 widget WIDGET in colormap CMAP. If an exact match cannot be
1440 allocated, try the nearest color available. Value is non-zero
1441 if successful. This is called from lwlib. */
1444 x_alloc_nearest_color_for_widget (widget, cmap, color)
1445 Widget widget;
1446 Colormap cmap;
1447 XColor *color;
1449 struct frame *f = x_frame_of_widget (widget);
1450 return x_alloc_nearest_color (f, cmap, color);
1454 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
1455 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1456 If this produces the same color as PIXEL, try a color where all RGB
1457 values have DELTA added. Return the allocated color in *PIXEL.
1458 DISPLAY is the X display, CMAP is the colormap to operate on.
1459 Value is non-zero if successful. */
1462 x_alloc_lighter_color_for_widget (widget, display, cmap, pixel, factor, delta)
1463 Widget widget;
1464 Display *display;
1465 Colormap cmap;
1466 unsigned long *pixel;
1467 double factor;
1468 int delta;
1470 struct frame *f = x_frame_of_widget (widget);
1471 return x_alloc_lighter_color (f, display, cmap, pixel, factor, delta);
1475 /* Structure specifying which arguments should be passed by Xt to
1476 cvt_string_to_pixel. We want the widget's screen and colormap. */
1478 static XtConvertArgRec cvt_string_to_pixel_args[] =
1480 {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.screen),
1481 sizeof (Screen *)},
1482 {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.colormap),
1483 sizeof (Colormap)}
1487 /* The address of this variable is returned by
1488 cvt_string_to_pixel. */
1490 static Pixel cvt_string_to_pixel_value;
1493 /* Convert a color name to a pixel color.
1495 DPY is the display we are working on.
1497 ARGS is an array of *NARGS XrmValue structures holding additional
1498 information about the widget for which the conversion takes place.
1499 The contents of this array are determined by the specification
1500 in cvt_string_to_pixel_args.
1502 FROM is a pointer to an XrmValue which points to the color name to
1503 convert. TO is an XrmValue in which to return the pixel color.
1505 CLOSURE_RET is a pointer to user-data, in which we record if
1506 we allocated the color or not.
1508 Value is True if successful, False otherwise. */
1510 static Boolean
1511 cvt_string_to_pixel (dpy, args, nargs, from, to, closure_ret)
1512 Display *dpy;
1513 XrmValue *args;
1514 Cardinal *nargs;
1515 XrmValue *from, *to;
1516 XtPointer *closure_ret;
1518 Screen *screen;
1519 Colormap cmap;
1520 Pixel pixel;
1521 String color_name;
1522 XColor color;
1524 if (*nargs != 2)
1526 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
1527 "wrongParameters", "cvt_string_to_pixel",
1528 "XtToolkitError",
1529 "Screen and colormap args required", NULL, NULL);
1530 return False;
1533 screen = *(Screen **) args[0].addr;
1534 cmap = *(Colormap *) args[1].addr;
1535 color_name = (String) from->addr;
1537 if (strcmp (color_name, XtDefaultBackground) == 0)
1539 *closure_ret = (XtPointer) False;
1540 pixel = WhitePixelOfScreen (screen);
1542 else if (strcmp (color_name, XtDefaultForeground) == 0)
1544 *closure_ret = (XtPointer) False;
1545 pixel = BlackPixelOfScreen (screen);
1547 else if (XParseColor (dpy, cmap, color_name, &color)
1548 && x_alloc_nearest_color_1 (dpy, cmap, &color))
1550 pixel = color.pixel;
1551 *closure_ret = (XtPointer) True;
1553 else
1555 String params[1];
1556 Cardinal nparams = 1;
1558 params[0] = color_name;
1559 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
1560 "badValue", "cvt_string_to_pixel",
1561 "XtToolkitError", "Invalid color `%s'",
1562 params, &nparams);
1563 return False;
1566 if (to->addr != NULL)
1568 if (to->size < sizeof (Pixel))
1570 to->size = sizeof (Pixel);
1571 return False;
1574 *(Pixel *) to->addr = pixel;
1576 else
1578 cvt_string_to_pixel_value = pixel;
1579 to->addr = (XtPointer) &cvt_string_to_pixel_value;
1582 to->size = sizeof (Pixel);
1583 return True;
1587 /* Free a pixel color which was previously allocated via
1588 cvt_string_to_pixel. This is registered as the destructor
1589 for this type of resource via XtSetTypeConverter.
1591 APP is the application context in which we work.
1593 TO is a pointer to an XrmValue holding the color to free.
1594 CLOSURE is the value we stored in CLOSURE_RET for this color
1595 in cvt_string_to_pixel.
1597 ARGS and NARGS are like for cvt_string_to_pixel. */
1599 static void
1600 cvt_pixel_dtor (app, to, closure, args, nargs)
1601 XtAppContext app;
1602 XrmValuePtr to;
1603 XtPointer closure;
1604 XrmValuePtr args;
1605 Cardinal *nargs;
1607 if (*nargs != 2)
1609 XtAppWarningMsg (app, "wrongParameters", "cvt_pixel_dtor",
1610 "XtToolkitError",
1611 "Screen and colormap arguments required",
1612 NULL, NULL);
1614 else if (closure != NULL)
1616 /* We did allocate the pixel, so free it. */
1617 Screen *screen = *(Screen **) args[0].addr;
1618 Colormap cmap = *(Colormap *) args[1].addr;
1619 x_free_dpy_colors (DisplayOfScreen (screen), screen, cmap,
1620 (Pixel *) to->addr, 1);
1625 #endif /* USE_X_TOOLKIT */
1628 /* Value is an array of XColor structures for the contents of the
1629 color map of display DPY. Set *NCELLS to the size of the array.
1630 Note that this probably shouldn't be called for large color maps,
1631 say a 24-bit TrueColor map. */
1633 static const XColor *
1634 x_color_cells (dpy, ncells)
1635 Display *dpy;
1636 int *ncells;
1638 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
1640 if (dpyinfo->color_cells == NULL)
1642 Screen *screen = dpyinfo->screen;
1643 int i;
1645 dpyinfo->ncolor_cells
1646 = XDisplayCells (dpy, XScreenNumberOfScreen (screen));
1647 dpyinfo->color_cells
1648 = (XColor *) xmalloc (dpyinfo->ncolor_cells
1649 * sizeof *dpyinfo->color_cells);
1651 for (i = 0; i < dpyinfo->ncolor_cells; ++i)
1652 dpyinfo->color_cells[i].pixel = i;
1654 XQueryColors (dpy, dpyinfo->cmap,
1655 dpyinfo->color_cells, dpyinfo->ncolor_cells);
1658 *ncells = dpyinfo->ncolor_cells;
1659 return dpyinfo->color_cells;
1663 /* On frame F, translate pixel colors to RGB values for the NCOLORS
1664 colors in COLORS. Use cached information, if available. */
1666 void
1667 x_query_colors (f, colors, ncolors)
1668 struct frame *f;
1669 XColor *colors;
1670 int ncolors;
1672 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
1674 if (dpyinfo->color_cells)
1676 int i;
1677 for (i = 0; i < ncolors; ++i)
1679 unsigned long pixel = colors[i].pixel;
1680 xassert (pixel < dpyinfo->ncolor_cells);
1681 xassert (dpyinfo->color_cells[pixel].pixel == pixel);
1682 colors[i] = dpyinfo->color_cells[pixel];
1685 else
1686 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
1690 /* On frame F, translate pixel color to RGB values for the color in
1691 COLOR. Use cached information, if available. */
1693 void
1694 x_query_color (f, color)
1695 struct frame *f;
1696 XColor *color;
1698 x_query_colors (f, color, 1);
1702 /* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP. If an
1703 exact match can't be allocated, try the nearest color available.
1704 Value is non-zero if successful. Set *COLOR to the color
1705 allocated. */
1707 static int
1708 x_alloc_nearest_color_1 (dpy, cmap, color)
1709 Display *dpy;
1710 Colormap cmap;
1711 XColor *color;
1713 int rc;
1715 rc = XAllocColor (dpy, cmap, color);
1716 if (rc == 0)
1718 /* If we got to this point, the colormap is full, so we're going
1719 to try to get the next closest color. The algorithm used is
1720 a least-squares matching, which is what X uses for closest
1721 color matching with StaticColor visuals. */
1722 int nearest, i;
1723 unsigned long nearest_delta = ~0;
1724 int ncells;
1725 const XColor *cells = x_color_cells (dpy, &ncells);
1727 for (nearest = i = 0; i < ncells; ++i)
1729 long dred = (color->red >> 8) - (cells[i].red >> 8);
1730 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
1731 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
1732 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
1734 if (delta < nearest_delta)
1736 nearest = i;
1737 nearest_delta = delta;
1741 color->red = cells[nearest].red;
1742 color->green = cells[nearest].green;
1743 color->blue = cells[nearest].blue;
1744 rc = XAllocColor (dpy, cmap, color);
1746 else
1748 /* If allocation succeeded, and the allocated pixel color is not
1749 equal to a cached pixel color recorded earlier, there was a
1750 change in the colormap, so clear the color cache. */
1751 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
1752 XColor *cached_color;
1754 if (dpyinfo->color_cells
1755 && (cached_color = &dpyinfo->color_cells[color->pixel],
1756 (cached_color->red != color->red
1757 || cached_color->blue != color->blue
1758 || cached_color->green != color->green)))
1760 xfree (dpyinfo->color_cells);
1761 dpyinfo->color_cells = NULL;
1762 dpyinfo->ncolor_cells = 0;
1766 #ifdef DEBUG_X_COLORS
1767 if (rc)
1768 register_color (color->pixel);
1769 #endif /* DEBUG_X_COLORS */
1771 return rc;
1775 /* Allocate the color COLOR->pixel on frame F, colormap CMAP. If an
1776 exact match can't be allocated, try the nearest color available.
1777 Value is non-zero if successful. Set *COLOR to the color
1778 allocated. */
1781 x_alloc_nearest_color (f, cmap, color)
1782 struct frame *f;
1783 Colormap cmap;
1784 XColor *color;
1786 gamma_correct (f, color);
1787 return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f), cmap, color);
1791 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
1792 It's necessary to do this instead of just using PIXEL directly to
1793 get color reference counts right. */
1795 unsigned long
1796 x_copy_color (f, pixel)
1797 struct frame *f;
1798 unsigned long pixel;
1800 XColor color;
1802 color.pixel = pixel;
1803 BLOCK_INPUT;
1804 x_query_color (f, &color);
1805 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
1806 UNBLOCK_INPUT;
1807 #ifdef DEBUG_X_COLORS
1808 register_color (pixel);
1809 #endif
1810 return color.pixel;
1814 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
1815 It's necessary to do this instead of just using PIXEL directly to
1816 get color reference counts right. */
1818 unsigned long
1819 x_copy_dpy_color (dpy, cmap, pixel)
1820 Display *dpy;
1821 Colormap cmap;
1822 unsigned long pixel;
1824 XColor color;
1826 color.pixel = pixel;
1827 BLOCK_INPUT;
1828 XQueryColor (dpy, cmap, &color);
1829 XAllocColor (dpy, cmap, &color);
1830 UNBLOCK_INPUT;
1831 #ifdef DEBUG_X_COLORS
1832 register_color (pixel);
1833 #endif
1834 return color.pixel;
1838 /* Brightness beyond which a color won't have its highlight brightness
1839 boosted.
1841 Nominally, highlight colors for `3d' faces are calculated by
1842 brightening an object's color by a constant scale factor, but this
1843 doesn't yield good results for dark colors, so for colors who's
1844 brightness is less than this value (on a scale of 0-65535) have an
1845 use an additional additive factor.
1847 The value here is set so that the default menu-bar/mode-line color
1848 (grey75) will not have its highlights changed at all. */
1849 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
1852 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
1853 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1854 If this produces the same color as PIXEL, try a color where all RGB
1855 values have DELTA added. Return the allocated color in *PIXEL.
1856 DISPLAY is the X display, CMAP is the colormap to operate on.
1857 Value is non-zero if successful. */
1859 static int
1860 x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
1861 struct frame *f;
1862 Display *display;
1863 Colormap cmap;
1864 unsigned long *pixel;
1865 double factor;
1866 int delta;
1868 XColor color, new;
1869 long bright;
1870 int success_p;
1872 /* Get RGB color values. */
1873 color.pixel = *pixel;
1874 x_query_color (f, &color);
1876 /* Change RGB values by specified FACTOR. Avoid overflow! */
1877 xassert (factor >= 0);
1878 new.red = min (0xffff, factor * color.red);
1879 new.green = min (0xffff, factor * color.green);
1880 new.blue = min (0xffff, factor * color.blue);
1882 /* Calculate brightness of COLOR. */
1883 bright = (2 * color.red + 3 * color.green + color.blue) / 6;
1885 /* We only boost colors that are darker than
1886 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
1887 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
1888 /* Make an additive adjustment to NEW, because it's dark enough so
1889 that scaling by FACTOR alone isn't enough. */
1891 /* How far below the limit this color is (0 - 1, 1 being darker). */
1892 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
1893 /* The additive adjustment. */
1894 int min_delta = delta * dimness * factor / 2;
1896 if (factor < 1)
1898 new.red = max (0, new.red - min_delta);
1899 new.green = max (0, new.green - min_delta);
1900 new.blue = max (0, new.blue - min_delta);
1902 else
1904 new.red = min (0xffff, min_delta + new.red);
1905 new.green = min (0xffff, min_delta + new.green);
1906 new.blue = min (0xffff, min_delta + new.blue);
1910 /* Try to allocate the color. */
1911 success_p = x_alloc_nearest_color (f, cmap, &new);
1912 if (success_p)
1914 if (new.pixel == *pixel)
1916 /* If we end up with the same color as before, try adding
1917 delta to the RGB values. */
1918 x_free_colors (f, &new.pixel, 1);
1920 new.red = min (0xffff, delta + color.red);
1921 new.green = min (0xffff, delta + color.green);
1922 new.blue = min (0xffff, delta + color.blue);
1923 success_p = x_alloc_nearest_color (f, cmap, &new);
1925 else
1926 success_p = 1;
1927 *pixel = new.pixel;
1930 return success_p;
1934 /* Set up the foreground color for drawing relief lines of glyph
1935 string S. RELIEF is a pointer to a struct relief containing the GC
1936 with which lines will be drawn. Use a color that is FACTOR or
1937 DELTA lighter or darker than the relief's background which is found
1938 in S->f->output_data.x->relief_background. If such a color cannot
1939 be allocated, use DEFAULT_PIXEL, instead. */
1941 static void
1942 x_setup_relief_color (f, relief, factor, delta, default_pixel)
1943 struct frame *f;
1944 struct relief *relief;
1945 double factor;
1946 int delta;
1947 unsigned long default_pixel;
1949 XGCValues xgcv;
1950 struct x_output *di = f->output_data.x;
1951 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
1952 unsigned long pixel;
1953 unsigned long background = di->relief_background;
1954 Colormap cmap = FRAME_X_COLORMAP (f);
1955 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
1956 Display *dpy = FRAME_X_DISPLAY (f);
1958 xgcv.graphics_exposures = False;
1959 xgcv.line_width = 1;
1961 /* Free previously allocated color. The color cell will be reused
1962 when it has been freed as many times as it was allocated, so this
1963 doesn't affect faces using the same colors. */
1964 if (relief->gc
1965 && relief->allocated_p)
1967 x_free_colors (f, &relief->pixel, 1);
1968 relief->allocated_p = 0;
1971 /* Allocate new color. */
1972 xgcv.foreground = default_pixel;
1973 pixel = background;
1974 if (dpyinfo->n_planes != 1
1975 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
1977 relief->allocated_p = 1;
1978 xgcv.foreground = relief->pixel = pixel;
1981 if (relief->gc == 0)
1983 xgcv.stipple = dpyinfo->gray;
1984 mask |= GCStipple;
1985 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
1987 else
1988 XChangeGC (dpy, relief->gc, mask, &xgcv);
1992 /* Set up colors for the relief lines around glyph string S. */
1994 static void
1995 x_setup_relief_colors (s)
1996 struct glyph_string *s;
1998 struct x_output *di = s->f->output_data.x;
1999 unsigned long color;
2001 if (s->face->use_box_color_for_shadows_p)
2002 color = s->face->box_color;
2003 else if (s->first_glyph->type == IMAGE_GLYPH
2004 && s->img->pixmap
2005 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
2006 color = IMAGE_BACKGROUND (s->img, s->f, 0);
2007 else
2009 XGCValues xgcv;
2011 /* Get the background color of the face. */
2012 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
2013 color = xgcv.background;
2016 if (di->white_relief.gc == 0
2017 || color != di->relief_background)
2019 di->relief_background = color;
2020 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
2021 WHITE_PIX_DEFAULT (s->f));
2022 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
2023 BLACK_PIX_DEFAULT (s->f));
2028 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2029 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2030 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2031 relief. LEFT_P non-zero means draw a relief on the left side of
2032 the rectangle. RIGHT_P non-zero means draw a relief on the right
2033 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2034 when drawing. */
2036 static void
2037 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
2038 raised_p, top_p, bot_p, left_p, right_p, clip_rect)
2039 struct frame *f;
2040 int left_x, top_y, right_x, bottom_y, width;
2041 int top_p, bot_p, left_p, right_p, raised_p;
2042 XRectangle *clip_rect;
2044 Display *dpy = FRAME_X_DISPLAY (f);
2045 Window window = FRAME_X_WINDOW (f);
2046 int i;
2047 GC gc;
2049 if (raised_p)
2050 gc = f->output_data.x->white_relief.gc;
2051 else
2052 gc = f->output_data.x->black_relief.gc;
2053 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
2055 /* Top. */
2056 if (top_p)
2057 for (i = 0; i < width; ++i)
2058 XDrawLine (dpy, window, gc,
2059 left_x + i * left_p, top_y + i,
2060 right_x + 1 - i * right_p, top_y + i);
2062 /* Left. */
2063 if (left_p)
2064 for (i = 0; i < width; ++i)
2065 XDrawLine (dpy, window, gc,
2066 left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
2068 XSetClipMask (dpy, gc, None);
2069 if (raised_p)
2070 gc = f->output_data.x->black_relief.gc;
2071 else
2072 gc = f->output_data.x->white_relief.gc;
2073 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
2075 /* Bottom. */
2076 if (bot_p)
2077 for (i = 0; i < width; ++i)
2078 XDrawLine (dpy, window, gc,
2079 left_x + i * left_p, bottom_y - i,
2080 right_x + 1 - i * right_p, bottom_y - i);
2082 /* Right. */
2083 if (right_p)
2084 for (i = 0; i < width; ++i)
2085 XDrawLine (dpy, window, gc,
2086 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
2088 XSetClipMask (dpy, gc, None);
2092 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2093 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2094 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2095 left side of the rectangle. RIGHT_P non-zero means draw a line
2096 on the right side of the rectangle. CLIP_RECT is the clipping
2097 rectangle to use when drawing. */
2099 static void
2100 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2101 left_p, right_p, clip_rect)
2102 struct glyph_string *s;
2103 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
2104 XRectangle *clip_rect;
2106 XGCValues xgcv;
2108 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2109 XSetForeground (s->display, s->gc, s->face->box_color);
2110 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
2112 /* Top. */
2113 XFillRectangle (s->display, s->window, s->gc,
2114 left_x, top_y, right_x - left_x + 1, width);
2116 /* Left. */
2117 if (left_p)
2118 XFillRectangle (s->display, s->window, s->gc,
2119 left_x, top_y, width, bottom_y - top_y + 1);
2121 /* Bottom. */
2122 XFillRectangle (s->display, s->window, s->gc,
2123 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
2125 /* Right. */
2126 if (right_p)
2127 XFillRectangle (s->display, s->window, s->gc,
2128 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
2130 XSetForeground (s->display, s->gc, xgcv.foreground);
2131 XSetClipMask (s->display, s->gc, None);
2135 /* Draw a box around glyph string S. */
2137 static void
2138 x_draw_glyph_string_box (s)
2139 struct glyph_string *s;
2141 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
2142 int left_p, right_p;
2143 struct glyph *last_glyph;
2144 XRectangle clip_rect;
2146 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
2147 ? WINDOW_RIGHT_EDGE_X (s->w)
2148 : window_box_right (s->w, s->area));
2150 /* The glyph that may have a right box line. */
2151 last_glyph = (s->cmp || s->img
2152 ? s->first_glyph
2153 : s->first_glyph + s->nchars - 1);
2155 width = eabs (s->face->box_line_width);
2156 raised_p = s->face->box == FACE_RAISED_BOX;
2157 left_x = s->x;
2158 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
2159 ? last_x - 1
2160 : min (last_x, s->x + s->background_width) - 1);
2161 top_y = s->y;
2162 bottom_y = top_y + s->height - 1;
2164 left_p = (s->first_glyph->left_box_line_p
2165 || (s->hl == DRAW_MOUSE_FACE
2166 && (s->prev == NULL
2167 || s->prev->hl != s->hl)));
2168 right_p = (last_glyph->right_box_line_p
2169 || (s->hl == DRAW_MOUSE_FACE
2170 && (s->next == NULL
2171 || s->next->hl != s->hl)));
2173 get_glyph_string_clip_rect (s, &clip_rect);
2175 if (s->face->box == FACE_SIMPLE_BOX)
2176 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2177 left_p, right_p, &clip_rect);
2178 else
2180 x_setup_relief_colors (s);
2181 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
2182 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
2187 /* Draw foreground of image glyph string S. */
2189 static void
2190 x_draw_image_foreground (s)
2191 struct glyph_string *s;
2193 int x = s->x;
2194 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2196 /* If first glyph of S has a left box line, start drawing it to the
2197 right of that line. */
2198 if (s->face->box != FACE_NO_BOX
2199 && s->first_glyph->left_box_line_p
2200 && s->slice.x == 0)
2201 x += eabs (s->face->box_line_width);
2203 /* If there is a margin around the image, adjust x- and y-position
2204 by that margin. */
2205 if (s->slice.x == 0)
2206 x += s->img->hmargin;
2207 if (s->slice.y == 0)
2208 y += s->img->vmargin;
2210 if (s->img->pixmap)
2212 if (s->img->mask)
2214 /* We can't set both a clip mask and use XSetClipRectangles
2215 because the latter also sets a clip mask. We also can't
2216 trust on the shape extension to be available
2217 (XShapeCombineRegion). So, compute the rectangle to draw
2218 manually. */
2219 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
2220 | GCFunction);
2221 XGCValues xgcv;
2222 XRectangle clip_rect, image_rect, r;
2224 xgcv.clip_mask = s->img->mask;
2225 xgcv.clip_x_origin = x;
2226 xgcv.clip_y_origin = y;
2227 xgcv.function = GXcopy;
2228 XChangeGC (s->display, s->gc, mask, &xgcv);
2230 get_glyph_string_clip_rect (s, &clip_rect);
2231 image_rect.x = x;
2232 image_rect.y = y;
2233 image_rect.width = s->slice.width;
2234 image_rect.height = s->slice.height;
2235 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
2236 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
2237 s->slice.x + r.x - x, s->slice.y + r.y - y,
2238 r.width, r.height, r.x, r.y);
2240 else
2242 XRectangle clip_rect, image_rect, r;
2244 get_glyph_string_clip_rect (s, &clip_rect);
2245 image_rect.x = x;
2246 image_rect.y = y;
2247 image_rect.width = s->slice.width;
2248 image_rect.height = s->slice.height;
2249 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
2250 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
2251 s->slice.x + r.x - x, s->slice.y + r.y - y,
2252 r.width, r.height, r.x, r.y);
2254 /* When the image has a mask, we can expect that at
2255 least part of a mouse highlight or a block cursor will
2256 be visible. If the image doesn't have a mask, make
2257 a block cursor visible by drawing a rectangle around
2258 the image. I believe it's looking better if we do
2259 nothing here for mouse-face. */
2260 if (s->hl == DRAW_CURSOR)
2262 int r = s->img->relief;
2263 if (r < 0) r = -r;
2264 XDrawRectangle (s->display, s->window, s->gc,
2265 x - r, y - r,
2266 s->slice.width + r*2 - 1,
2267 s->slice.height + r*2 - 1);
2271 else
2272 /* Draw a rectangle if image could not be loaded. */
2273 XDrawRectangle (s->display, s->window, s->gc, x, y,
2274 s->slice.width - 1, s->slice.height - 1);
2278 /* Draw a relief around the image glyph string S. */
2280 static void
2281 x_draw_image_relief (s)
2282 struct glyph_string *s;
2284 int x0, y0, x1, y1, thick, raised_p;
2285 XRectangle r;
2286 int x = s->x;
2287 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2289 /* If first glyph of S has a left box line, start drawing it to the
2290 right of that line. */
2291 if (s->face->box != FACE_NO_BOX
2292 && s->first_glyph->left_box_line_p
2293 && s->slice.x == 0)
2294 x += eabs (s->face->box_line_width);
2296 /* If there is a margin around the image, adjust x- and y-position
2297 by that margin. */
2298 if (s->slice.x == 0)
2299 x += s->img->hmargin;
2300 if (s->slice.y == 0)
2301 y += s->img->vmargin;
2303 if (s->hl == DRAW_IMAGE_SUNKEN
2304 || s->hl == DRAW_IMAGE_RAISED)
2306 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
2307 raised_p = s->hl == DRAW_IMAGE_RAISED;
2309 else
2311 thick = eabs (s->img->relief);
2312 raised_p = s->img->relief > 0;
2315 x0 = x - thick;
2316 y0 = y - thick;
2317 x1 = x + s->slice.width + thick - 1;
2318 y1 = y + s->slice.height + thick - 1;
2320 x_setup_relief_colors (s);
2321 get_glyph_string_clip_rect (s, &r);
2322 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
2323 s->slice.y == 0,
2324 s->slice.y + s->slice.height == s->img->height,
2325 s->slice.x == 0,
2326 s->slice.x + s->slice.width == s->img->width,
2327 &r);
2331 /* Draw the foreground of image glyph string S to PIXMAP. */
2333 static void
2334 x_draw_image_foreground_1 (s, pixmap)
2335 struct glyph_string *s;
2336 Pixmap pixmap;
2338 int x = 0;
2339 int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
2341 /* If first glyph of S has a left box line, start drawing it to the
2342 right of that line. */
2343 if (s->face->box != FACE_NO_BOX
2344 && s->first_glyph->left_box_line_p
2345 && s->slice.x == 0)
2346 x += eabs (s->face->box_line_width);
2348 /* If there is a margin around the image, adjust x- and y-position
2349 by that margin. */
2350 if (s->slice.x == 0)
2351 x += s->img->hmargin;
2352 if (s->slice.y == 0)
2353 y += s->img->vmargin;
2355 if (s->img->pixmap)
2357 if (s->img->mask)
2359 /* We can't set both a clip mask and use XSetClipRectangles
2360 because the latter also sets a clip mask. We also can't
2361 trust on the shape extension to be available
2362 (XShapeCombineRegion). So, compute the rectangle to draw
2363 manually. */
2364 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
2365 | GCFunction);
2366 XGCValues xgcv;
2368 xgcv.clip_mask = s->img->mask;
2369 xgcv.clip_x_origin = x - s->slice.x;
2370 xgcv.clip_y_origin = y - s->slice.y;
2371 xgcv.function = GXcopy;
2372 XChangeGC (s->display, s->gc, mask, &xgcv);
2374 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
2375 s->slice.x, s->slice.y,
2376 s->slice.width, s->slice.height, x, y);
2377 XSetClipMask (s->display, s->gc, None);
2379 else
2381 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
2382 s->slice.x, s->slice.y,
2383 s->slice.width, s->slice.height, x, y);
2385 /* When the image has a mask, we can expect that at
2386 least part of a mouse highlight or a block cursor will
2387 be visible. If the image doesn't have a mask, make
2388 a block cursor visible by drawing a rectangle around
2389 the image. I believe it's looking better if we do
2390 nothing here for mouse-face. */
2391 if (s->hl == DRAW_CURSOR)
2393 int r = s->img->relief;
2394 if (r < 0) r = -r;
2395 XDrawRectangle (s->display, s->window, s->gc, x - r, y - r,
2396 s->slice.width + r*2 - 1,
2397 s->slice.height + r*2 - 1);
2401 else
2402 /* Draw a rectangle if image could not be loaded. */
2403 XDrawRectangle (s->display, pixmap, s->gc, x, y,
2404 s->slice.width - 1, s->slice.height - 1);
2408 /* Draw part of the background of glyph string S. X, Y, W, and H
2409 give the rectangle to draw. */
2411 static void
2412 x_draw_glyph_string_bg_rect (s, x, y, w, h)
2413 struct glyph_string *s;
2414 int x, y, w, h;
2416 if (s->stippled_p)
2418 /* Fill background with a stipple pattern. */
2419 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2420 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
2421 XSetFillStyle (s->display, s->gc, FillSolid);
2423 else
2424 x_clear_glyph_string_rect (s, x, y, w, h);
2428 /* Draw image glyph string S.
2430 s->y
2431 s->x +-------------------------
2432 | s->face->box
2434 | +-------------------------
2435 | | s->img->margin
2437 | | +-------------------
2438 | | | the image
2442 static void
2443 x_draw_image_glyph_string (s)
2444 struct glyph_string *s;
2446 int box_line_hwidth = eabs (s->face->box_line_width);
2447 int box_line_vwidth = max (s->face->box_line_width, 0);
2448 int height;
2449 Pixmap pixmap = None;
2451 height = s->height;
2452 if (s->slice.y == 0)
2453 height -= box_line_vwidth;
2454 if (s->slice.y + s->slice.height >= s->img->height)
2455 height -= box_line_vwidth;
2457 /* Fill background with face under the image. Do it only if row is
2458 taller than image or if image has a clip mask to reduce
2459 flickering. */
2460 s->stippled_p = s->face->stipple != 0;
2461 if (height > s->slice.height
2462 || s->img->hmargin
2463 || s->img->vmargin
2464 || s->img->mask
2465 || s->img->pixmap == 0
2466 || s->width != s->background_width)
2468 if (s->img->mask)
2470 /* Create a pixmap as large as the glyph string. Fill it
2471 with the background color. Copy the image to it, using
2472 its mask. Copy the temporary pixmap to the display. */
2473 Screen *screen = FRAME_X_SCREEN (s->f);
2474 int depth = DefaultDepthOfScreen (screen);
2476 /* Create a pixmap as large as the glyph string. */
2477 pixmap = XCreatePixmap (s->display, s->window,
2478 s->background_width,
2479 s->height, depth);
2481 /* Don't clip in the following because we're working on the
2482 pixmap. */
2483 XSetClipMask (s->display, s->gc, None);
2485 /* Fill the pixmap with the background color/stipple. */
2486 if (s->stippled_p)
2488 /* Fill background with a stipple pattern. */
2489 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2490 XSetTSOrigin (s->display, s->gc, - s->x, - s->y);
2491 XFillRectangle (s->display, pixmap, s->gc,
2492 0, 0, s->background_width, s->height);
2493 XSetFillStyle (s->display, s->gc, FillSolid);
2494 XSetTSOrigin (s->display, s->gc, 0, 0);
2496 else
2498 XGCValues xgcv;
2499 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
2500 &xgcv);
2501 XSetForeground (s->display, s->gc, xgcv.background);
2502 XFillRectangle (s->display, pixmap, s->gc,
2503 0, 0, s->background_width, s->height);
2504 XSetForeground (s->display, s->gc, xgcv.foreground);
2507 else
2509 int x = s->x;
2510 int y = s->y;
2512 if (s->first_glyph->left_box_line_p
2513 && s->slice.x == 0)
2514 x += box_line_hwidth;
2516 if (s->slice.y == 0)
2517 y += box_line_vwidth;
2519 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
2522 s->background_filled_p = 1;
2525 /* Draw the foreground. */
2526 if (pixmap != None)
2528 x_draw_image_foreground_1 (s, pixmap);
2529 x_set_glyph_string_clipping (s);
2530 XCopyArea (s->display, pixmap, s->window, s->gc,
2531 0, 0, s->background_width, s->height, s->x, s->y);
2532 XFreePixmap (s->display, pixmap);
2534 else
2535 x_draw_image_foreground (s);
2537 /* If we must draw a relief around the image, do it. */
2538 if (s->img->relief
2539 || s->hl == DRAW_IMAGE_RAISED
2540 || s->hl == DRAW_IMAGE_SUNKEN)
2541 x_draw_image_relief (s);
2545 /* Draw stretch glyph string S. */
2547 static void
2548 x_draw_stretch_glyph_string (s)
2549 struct glyph_string *s;
2551 xassert (s->first_glyph->type == STRETCH_GLYPH);
2553 if (s->hl == DRAW_CURSOR
2554 && !x_stretch_cursor_p)
2556 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
2557 as wide as the stretch glyph. */
2558 int width, background_width = s->background_width;
2559 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
2561 if (x < left_x)
2563 background_width -= left_x - x;
2564 x = left_x;
2566 width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
2568 /* Draw cursor. */
2569 x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
2571 /* Clear rest using the GC of the original non-cursor face. */
2572 if (width < background_width)
2574 int y = s->y;
2575 int w = background_width - width, h = s->height;
2576 XRectangle r;
2577 GC gc;
2579 x += width;
2580 if (s->row->mouse_face_p
2581 && cursor_in_mouse_face_p (s->w))
2583 x_set_mouse_face_gc (s);
2584 gc = s->gc;
2586 else
2587 gc = s->face->gc;
2589 get_glyph_string_clip_rect (s, &r);
2590 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
2592 if (s->face->stipple)
2594 /* Fill background with a stipple pattern. */
2595 XSetFillStyle (s->display, gc, FillOpaqueStippled);
2596 XFillRectangle (s->display, s->window, gc, x, y, w, h);
2597 XSetFillStyle (s->display, gc, FillSolid);
2599 else
2601 XGCValues xgcv;
2602 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
2603 XSetForeground (s->display, gc, xgcv.background);
2604 XFillRectangle (s->display, s->window, gc, x, y, w, h);
2605 XSetForeground (s->display, gc, xgcv.foreground);
2609 else if (!s->background_filled_p)
2611 int background_width = s->background_width;
2612 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
2614 /* Don't draw into left margin, fringe or scrollbar area
2615 except for header line and mode line. */
2616 if (x < left_x && !s->row->mode_line_p)
2618 background_width -= left_x - x;
2619 x = left_x;
2621 if (background_width > 0)
2622 x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
2625 s->background_filled_p = 1;
2629 /* Draw glyph string S. */
2631 static void
2632 x_draw_glyph_string (s)
2633 struct glyph_string *s;
2635 int relief_drawn_p = 0;
2637 /* If S draws into the background of its successors, draw the
2638 background of the successors first so that S can draw into it.
2639 This makes S->next use XDrawString instead of XDrawImageString. */
2640 if (s->next && s->right_overhang && !s->for_overlaps)
2642 int width;
2643 struct glyph_string *next;
2645 for (width = 0, next = s->next; next;
2646 width += next->width, next = next->next)
2647 if (next->first_glyph->type != IMAGE_GLYPH)
2649 x_set_glyph_string_gc (next);
2650 x_set_glyph_string_clipping (next);
2651 x_draw_glyph_string_background (next, 1);
2652 next->num_clips = 0;
2656 /* Set up S->gc, set clipping and draw S. */
2657 x_set_glyph_string_gc (s);
2659 /* Draw relief (if any) in advance for char/composition so that the
2660 glyph string can be drawn over it. */
2661 if (!s->for_overlaps
2662 && s->face->box != FACE_NO_BOX
2663 && (s->first_glyph->type == CHAR_GLYPH
2664 || s->first_glyph->type == COMPOSITE_GLYPH))
2667 x_set_glyph_string_clipping (s);
2668 x_draw_glyph_string_background (s, 1);
2669 x_draw_glyph_string_box (s);
2670 x_set_glyph_string_clipping (s);
2671 relief_drawn_p = 1;
2673 else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */
2674 && !s->clip_tail
2675 && ((s->prev && s->prev->hl != s->hl && s->left_overhang)
2676 || (s->next && s->next->hl != s->hl && s->right_overhang)))
2677 /* We must clip just this glyph. left_overhang part has already
2678 drawn when s->prev was drawn, and right_overhang part will be
2679 drawn later when s->next is drawn. */
2680 x_set_glyph_string_clipping_exactly (s, s);
2681 else
2682 x_set_glyph_string_clipping (s);
2684 switch (s->first_glyph->type)
2686 case IMAGE_GLYPH:
2687 x_draw_image_glyph_string (s);
2688 break;
2690 case STRETCH_GLYPH:
2691 x_draw_stretch_glyph_string (s);
2692 break;
2694 case CHAR_GLYPH:
2695 if (s->for_overlaps)
2696 s->background_filled_p = 1;
2697 else
2698 x_draw_glyph_string_background (s, 0);
2699 x_draw_glyph_string_foreground (s);
2700 break;
2702 case COMPOSITE_GLYPH:
2703 if (s->for_overlaps || s->gidx > 0)
2704 s->background_filled_p = 1;
2705 else
2706 x_draw_glyph_string_background (s, 1);
2707 x_draw_composite_glyph_string_foreground (s);
2708 break;
2710 default:
2711 abort ();
2714 if (!s->for_overlaps)
2716 /* Draw underline. */
2717 if (s->face->underline_p)
2719 unsigned long thickness, position;
2720 int y;
2722 if (s->prev && s->prev->face->underline_p)
2724 /* We use the same underline style as the previous one. */
2725 thickness = s->prev->underline_thickness;
2726 position = s->prev->underline_position;
2728 else
2730 /* Get the underline thickness. Default is 1 pixel. */
2731 if (s->font && s->font->underline_thickness > 0)
2732 thickness = s->font->underline_thickness;
2733 else
2734 thickness = 1;
2735 if (x_underline_at_descent_line)
2736 position = (s->height - thickness) - (s->ybase - s->y);
2737 else
2739 /* Get the underline position. This is the recommended
2740 vertical offset in pixels from the baseline to the top of
2741 the underline. This is a signed value according to the
2742 specs, and its default is
2744 ROUND ((maximum descent) / 2), with
2745 ROUND(x) = floor (x + 0.5) */
2747 if (x_use_underline_position_properties
2748 && s->font && s->font->underline_position >= 0)
2749 position = s->font->underline_position;
2750 else if (s->font)
2751 position = (s->font->descent + 1) / 2;
2753 position = max (position, underline_minimum_offset);
2755 /* Check the sanity of thickness and position. We should
2756 avoid drawing underline out of the current line area. */
2757 if (s->y + s->height <= s->ybase + position)
2758 position = (s->height - 1) - (s->ybase - s->y);
2759 if (s->y + s->height < s->ybase + position + thickness)
2760 thickness = (s->y + s->height) - (s->ybase + position);
2761 s->underline_thickness = thickness;
2762 s->underline_position = position;
2763 y = s->ybase + position;
2764 if (s->face->underline_defaulted_p)
2765 XFillRectangle (s->display, s->window, s->gc,
2766 s->x, y, s->background_width, thickness);
2767 else
2769 XGCValues xgcv;
2770 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2771 XSetForeground (s->display, s->gc, s->face->underline_color);
2772 XFillRectangle (s->display, s->window, s->gc,
2773 s->x, y, s->background_width, thickness);
2774 XSetForeground (s->display, s->gc, xgcv.foreground);
2778 /* Draw overline. */
2779 if (s->face->overline_p)
2781 unsigned long dy = 0, h = 1;
2783 if (s->face->overline_color_defaulted_p)
2784 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2785 s->background_width, h);
2786 else
2788 XGCValues xgcv;
2789 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2790 XSetForeground (s->display, s->gc, s->face->overline_color);
2791 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2792 s->background_width, h);
2793 XSetForeground (s->display, s->gc, xgcv.foreground);
2797 /* Draw strike-through. */
2798 if (s->face->strike_through_p)
2800 unsigned long h = 1;
2801 unsigned long dy = (s->height - h) / 2;
2803 if (s->face->strike_through_color_defaulted_p)
2804 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2805 s->width, h);
2806 else
2808 XGCValues xgcv;
2809 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2810 XSetForeground (s->display, s->gc, s->face->strike_through_color);
2811 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2812 s->width, h);
2813 XSetForeground (s->display, s->gc, xgcv.foreground);
2817 /* Draw relief if not yet drawn. */
2818 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
2819 x_draw_glyph_string_box (s);
2821 if (s->prev)
2823 struct glyph_string *prev;
2825 for (prev = s->prev; prev; prev = prev->prev)
2826 if (prev->hl != s->hl
2827 && prev->x + prev->width + prev->right_overhang > s->x)
2829 /* As prev was drawn while clipped to its own area, we
2830 must draw the right_overhang part using s->hl now. */
2831 enum draw_glyphs_face save = prev->hl;
2833 prev->hl = s->hl;
2834 x_set_glyph_string_gc (prev);
2835 x_set_glyph_string_clipping_exactly (s, prev);
2836 if (prev->first_glyph->type == CHAR_GLYPH)
2837 x_draw_glyph_string_foreground (prev);
2838 else
2839 x_draw_composite_glyph_string_foreground (prev);
2840 XSetClipMask (prev->display, prev->gc, None);
2841 prev->hl = save;
2842 prev->num_clips = 0;
2846 if (s->next)
2848 struct glyph_string *next;
2850 for (next = s->next; next; next = next->next)
2851 if (next->hl != s->hl
2852 && next->x - next->left_overhang < s->x + s->width)
2854 /* As next will be drawn while clipped to its own area,
2855 we must draw the left_overhang part using s->hl now. */
2856 enum draw_glyphs_face save = next->hl;
2858 next->hl = s->hl;
2859 x_set_glyph_string_gc (next);
2860 x_set_glyph_string_clipping_exactly (s, next);
2861 if (next->first_glyph->type == CHAR_GLYPH)
2862 x_draw_glyph_string_foreground (next);
2863 else
2864 x_draw_composite_glyph_string_foreground (next);
2865 XSetClipMask (next->display, next->gc, None);
2866 next->hl = save;
2867 next->num_clips = 0;
2872 /* Reset clipping. */
2873 XSetClipMask (s->display, s->gc, None);
2874 s->num_clips = 0;
2877 /* Shift display to make room for inserted glyphs. */
2879 void
2880 x_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
2881 struct frame *f;
2882 int x, y, width, height, shift_by;
2884 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
2885 f->output_data.x->normal_gc,
2886 x, y, width, height,
2887 x + shift_by, y);
2890 /* Delete N glyphs at the nominal cursor position. Not implemented
2891 for X frames. */
2893 static void
2894 x_delete_glyphs (f, n)
2895 struct frame *f;
2896 register int n;
2898 abort ();
2902 /* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
2903 If they are <= 0, this is probably an error. */
2905 void
2906 x_clear_area (dpy, window, x, y, width, height, exposures)
2907 Display *dpy;
2908 Window window;
2909 int x, y;
2910 int width, height;
2911 int exposures;
2913 xassert (width > 0 && height > 0);
2914 XClearArea (dpy, window, x, y, width, height, exposures);
2918 /* Clear an entire frame. */
2920 static void
2921 x_clear_frame (struct frame *f)
2923 /* Clearing the frame will erase any cursor, so mark them all as no
2924 longer visible. */
2925 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
2926 output_cursor.hpos = output_cursor.vpos = 0;
2927 output_cursor.x = -1;
2929 /* We don't set the output cursor here because there will always
2930 follow an explicit cursor_to. */
2931 BLOCK_INPUT;
2932 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
2934 /* We have to clear the scroll bars, too. If we have changed
2935 colors or something like that, then they should be notified. */
2936 x_scroll_bar_clear (f);
2938 XFlush (FRAME_X_DISPLAY (f));
2940 UNBLOCK_INPUT;
2945 /* Invert the middle quarter of the frame for .15 sec. */
2947 /* We use the select system call to do the waiting, so we have to make
2948 sure it's available. If it isn't, we just won't do visual bells. */
2950 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
2953 /* Subtract the `struct timeval' values X and Y, storing the result in
2954 *RESULT. Return 1 if the difference is negative, otherwise 0. */
2956 static int
2957 timeval_subtract (result, x, y)
2958 struct timeval *result, x, y;
2960 /* Perform the carry for the later subtraction by updating y. This
2961 is safer because on some systems the tv_sec member is unsigned. */
2962 if (x.tv_usec < y.tv_usec)
2964 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
2965 y.tv_usec -= 1000000 * nsec;
2966 y.tv_sec += nsec;
2969 if (x.tv_usec - y.tv_usec > 1000000)
2971 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
2972 y.tv_usec += 1000000 * nsec;
2973 y.tv_sec -= nsec;
2976 /* Compute the time remaining to wait. tv_usec is certainly
2977 positive. */
2978 result->tv_sec = x.tv_sec - y.tv_sec;
2979 result->tv_usec = x.tv_usec - y.tv_usec;
2981 /* Return indication of whether the result should be considered
2982 negative. */
2983 return x.tv_sec < y.tv_sec;
2986 void
2987 XTflash (f)
2988 struct frame *f;
2990 BLOCK_INPUT;
2993 GC gc;
2995 /* Create a GC that will use the GXxor function to flip foreground
2996 pixels into background pixels. */
2998 XGCValues values;
3000 values.function = GXxor;
3001 values.foreground = (FRAME_FOREGROUND_PIXEL (f)
3002 ^ FRAME_BACKGROUND_PIXEL (f));
3004 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3005 GCFunction | GCForeground, &values);
3009 /* Get the height not including a menu bar widget. */
3010 int height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f));
3011 /* Height of each line to flash. */
3012 int flash_height = FRAME_LINE_HEIGHT (f);
3013 /* These will be the left and right margins of the rectangles. */
3014 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
3015 int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
3017 int width;
3019 /* Don't flash the area between a scroll bar and the frame
3020 edge it is next to. */
3021 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
3023 case vertical_scroll_bar_left:
3024 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
3025 break;
3027 case vertical_scroll_bar_right:
3028 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
3029 break;
3031 default:
3032 break;
3035 width = flash_right - flash_left;
3037 /* If window is tall, flash top and bottom line. */
3038 if (height > 3 * FRAME_LINE_HEIGHT (f))
3040 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3041 flash_left,
3042 (FRAME_INTERNAL_BORDER_WIDTH (f)
3043 + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
3044 width, flash_height);
3045 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3046 flash_left,
3047 (height - flash_height
3048 - FRAME_INTERNAL_BORDER_WIDTH (f)),
3049 width, flash_height);
3051 else
3052 /* If it is short, flash it all. */
3053 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3054 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
3055 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
3057 x_flush (f);
3060 struct timeval wakeup;
3062 EMACS_GET_TIME (wakeup);
3064 /* Compute time to wait until, propagating carry from usecs. */
3065 wakeup.tv_usec += 150000;
3066 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
3067 wakeup.tv_usec %= 1000000;
3069 /* Keep waiting until past the time wakeup or any input gets
3070 available. */
3071 while (! detect_input_pending ())
3073 struct timeval current;
3074 struct timeval timeout;
3076 EMACS_GET_TIME (current);
3078 /* Break if result would be negative. */
3079 if (timeval_subtract (&current, wakeup, current))
3080 break;
3082 /* How long `select' should wait. */
3083 timeout.tv_sec = 0;
3084 timeout.tv_usec = 10000;
3086 /* Try to wait that long--but we might wake up sooner. */
3087 select (0, NULL, NULL, NULL, &timeout);
3091 /* If window is tall, flash top and bottom line. */
3092 if (height > 3 * FRAME_LINE_HEIGHT (f))
3094 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3095 flash_left,
3096 (FRAME_INTERNAL_BORDER_WIDTH (f)
3097 + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
3098 width, flash_height);
3099 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3100 flash_left,
3101 (height - flash_height
3102 - FRAME_INTERNAL_BORDER_WIDTH (f)),
3103 width, flash_height);
3105 else
3106 /* If it is short, flash it all. */
3107 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3108 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
3109 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
3111 XFreeGC (FRAME_X_DISPLAY (f), gc);
3112 x_flush (f);
3116 UNBLOCK_INPUT;
3119 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3122 /* Make audible bell. */
3124 void
3125 XTring_bell ()
3127 struct frame *f = SELECTED_FRAME ();
3129 if (FRAME_X_DISPLAY (f))
3131 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3132 if (visible_bell)
3133 XTflash (f);
3134 else
3135 #endif
3137 BLOCK_INPUT;
3138 XBell (FRAME_X_DISPLAY (f), 0);
3139 XFlush (FRAME_X_DISPLAY (f));
3140 UNBLOCK_INPUT;
3146 /* Specify how many text lines, from the top of the window,
3147 should be affected by insert-lines and delete-lines operations.
3148 This, and those operations, are used only within an update
3149 that is bounded by calls to x_update_begin and x_update_end. */
3151 static void
3152 XTset_terminal_window (n)
3153 register int n;
3155 /* This function intentionally left blank. */
3160 /***********************************************************************
3161 Line Dance
3162 ***********************************************************************/
3164 /* Perform an insert-lines or delete-lines operation, inserting N
3165 lines or deleting -N lines at vertical position VPOS. */
3167 static void
3168 x_ins_del_lines (f, vpos, n)
3169 struct frame *f;
3170 int vpos, n;
3172 abort ();
3176 /* Scroll part of the display as described by RUN. */
3178 static void
3179 x_scroll_run (w, run)
3180 struct window *w;
3181 struct run *run;
3183 struct frame *f = XFRAME (w->frame);
3184 int x, y, width, height, from_y, to_y, bottom_y;
3186 /* Get frame-relative bounding box of the text display area of W,
3187 without mode lines. Include in this box the left and right
3188 fringe of W. */
3189 window_box (w, -1, &x, &y, &width, &height);
3191 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
3192 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
3193 bottom_y = y + height;
3195 if (to_y < from_y)
3197 /* Scrolling up. Make sure we don't copy part of the mode
3198 line at the bottom. */
3199 if (from_y + run->height > bottom_y)
3200 height = bottom_y - from_y;
3201 else
3202 height = run->height;
3204 else
3206 /* Scolling down. Make sure we don't copy over the mode line.
3207 at the bottom. */
3208 if (to_y + run->height > bottom_y)
3209 height = bottom_y - to_y;
3210 else
3211 height = run->height;
3214 BLOCK_INPUT;
3216 /* Cursor off. Will be switched on again in x_update_window_end. */
3217 updated_window = w;
3218 x_clear_cursor (w);
3220 XCopyArea (FRAME_X_DISPLAY (f),
3221 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
3222 f->output_data.x->normal_gc,
3223 x, from_y,
3224 width, height,
3225 x, to_y);
3227 UNBLOCK_INPUT;
3232 /***********************************************************************
3233 Exposure Events
3234 ***********************************************************************/
3237 static void
3238 frame_highlight (f)
3239 struct frame *f;
3241 /* We used to only do this if Vx_no_window_manager was non-nil, but
3242 the ICCCM (section 4.1.6) says that the window's border pixmap
3243 and border pixel are window attributes which are "private to the
3244 client", so we can always change it to whatever we want. */
3245 BLOCK_INPUT;
3246 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3247 f->output_data.x->border_pixel);
3248 UNBLOCK_INPUT;
3249 x_update_cursor (f, 1);
3250 x_set_frame_alpha (f);
3253 static void
3254 frame_unhighlight (f)
3255 struct frame *f;
3257 /* We used to only do this if Vx_no_window_manager was non-nil, but
3258 the ICCCM (section 4.1.6) says that the window's border pixmap
3259 and border pixel are window attributes which are "private to the
3260 client", so we can always change it to whatever we want. */
3261 BLOCK_INPUT;
3262 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3263 f->output_data.x->border_tile);
3264 UNBLOCK_INPUT;
3265 x_update_cursor (f, 1);
3266 x_set_frame_alpha (f);
3269 /* The focus has changed. Update the frames as necessary to reflect
3270 the new situation. Note that we can't change the selected frame
3271 here, because the Lisp code we are interrupting might become confused.
3272 Each event gets marked with the frame in which it occurred, so the
3273 Lisp code can tell when the switch took place by examining the events. */
3275 static void
3276 x_new_focus_frame (dpyinfo, frame)
3277 struct x_display_info *dpyinfo;
3278 struct frame *frame;
3280 struct frame *old_focus = dpyinfo->x_focus_frame;
3282 if (frame != dpyinfo->x_focus_frame)
3284 /* Set this before calling other routines, so that they see
3285 the correct value of x_focus_frame. */
3286 dpyinfo->x_focus_frame = frame;
3288 if (old_focus && old_focus->auto_lower)
3289 x_lower_frame (old_focus);
3291 #if 0
3292 selected_frame = frame;
3293 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
3294 selected_frame);
3295 Fselect_window (selected_frame->selected_window, Qnil);
3296 choose_minibuf_frame ();
3297 #endif /* ! 0 */
3299 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
3300 pending_autoraise_frame = dpyinfo->x_focus_frame;
3301 else
3302 pending_autoraise_frame = 0;
3305 x_frame_rehighlight (dpyinfo);
3308 /* Handle FocusIn and FocusOut state changes for FRAME.
3309 If FRAME has focus and there exists more than one frame, puts
3310 a FOCUS_IN_EVENT into *BUFP. */
3312 static void
3313 x_focus_changed (type, state, dpyinfo, frame, bufp)
3314 int type;
3315 int state;
3316 struct x_display_info *dpyinfo;
3317 struct frame *frame;
3318 struct input_event *bufp;
3320 if (type == FocusIn)
3322 if (dpyinfo->x_focus_event_frame != frame)
3324 x_new_focus_frame (dpyinfo, frame);
3325 dpyinfo->x_focus_event_frame = frame;
3327 /* Don't stop displaying the initial startup message
3328 for a switch-frame event we don't need. */
3329 if (NILP (Vterminal_frame)
3330 && CONSP (Vframe_list)
3331 && !NILP (XCDR (Vframe_list)))
3333 bufp->kind = FOCUS_IN_EVENT;
3334 XSETFRAME (bufp->frame_or_window, frame);
3338 frame->output_data.x->focus_state |= state;
3340 #ifdef HAVE_X_I18N
3341 if (FRAME_XIC (frame))
3342 XSetICFocus (FRAME_XIC (frame));
3343 #endif
3345 else if (type == FocusOut)
3347 frame->output_data.x->focus_state &= ~state;
3349 if (dpyinfo->x_focus_event_frame == frame)
3351 dpyinfo->x_focus_event_frame = 0;
3352 x_new_focus_frame (dpyinfo, 0);
3355 #ifdef HAVE_X_I18N
3356 if (FRAME_XIC (frame))
3357 XUnsetICFocus (FRAME_XIC (frame));
3358 #endif
3362 /* The focus may have changed. Figure out if it is a real focus change,
3363 by checking both FocusIn/Out and Enter/LeaveNotify events.
3365 Returns FOCUS_IN_EVENT event in *BUFP. */
3367 static void
3368 x_detect_focus_change (dpyinfo, event, bufp)
3369 struct x_display_info *dpyinfo;
3370 XEvent *event;
3371 struct input_event *bufp;
3373 struct frame *frame;
3375 frame = x_any_window_to_frame (dpyinfo, event->xany.window);
3376 if (! frame)
3377 return;
3379 switch (event->type)
3381 case EnterNotify:
3382 case LeaveNotify:
3384 struct frame *focus_frame = dpyinfo->x_focus_event_frame;
3385 int focus_state
3386 = focus_frame ? focus_frame->output_data.x->focus_state : 0;
3388 if (event->xcrossing.detail != NotifyInferior
3389 && event->xcrossing.focus
3390 && ! (focus_state & FOCUS_EXPLICIT))
3391 x_focus_changed ((event->type == EnterNotify ? FocusIn : FocusOut),
3392 FOCUS_IMPLICIT,
3393 dpyinfo, frame, bufp);
3395 break;
3397 case FocusIn:
3398 case FocusOut:
3399 x_focus_changed (event->type,
3400 (event->xfocus.detail == NotifyPointer ?
3401 FOCUS_IMPLICIT : FOCUS_EXPLICIT),
3402 dpyinfo, frame, bufp);
3403 break;
3405 case ClientMessage:
3406 if (event->xclient.message_type == dpyinfo->Xatom_XEMBED)
3408 enum xembed_message msg = event->xclient.data.l[1];
3409 x_focus_changed ((msg == XEMBED_FOCUS_IN ? FocusIn : FocusOut),
3410 FOCUS_EXPLICIT, dpyinfo, frame, bufp);
3412 break;
3417 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3419 void
3420 x_mouse_leave (dpyinfo)
3421 struct x_display_info *dpyinfo;
3423 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
3426 /* The focus has changed, or we have redirected a frame's focus to
3427 another frame (this happens when a frame uses a surrogate
3428 mini-buffer frame). Shift the highlight as appropriate.
3430 The FRAME argument doesn't necessarily have anything to do with which
3431 frame is being highlighted or un-highlighted; we only use it to find
3432 the appropriate X display info. */
3434 static void
3435 XTframe_rehighlight (frame)
3436 struct frame *frame;
3438 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
3441 static void
3442 x_frame_rehighlight (dpyinfo)
3443 struct x_display_info *dpyinfo;
3445 struct frame *old_highlight = dpyinfo->x_highlight_frame;
3447 if (dpyinfo->x_focus_frame)
3449 dpyinfo->x_highlight_frame
3450 = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
3451 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
3452 : dpyinfo->x_focus_frame);
3453 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
3455 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
3456 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
3459 else
3460 dpyinfo->x_highlight_frame = 0;
3462 if (dpyinfo->x_highlight_frame != old_highlight)
3464 if (old_highlight)
3465 frame_unhighlight (old_highlight);
3466 if (dpyinfo->x_highlight_frame)
3467 frame_highlight (dpyinfo->x_highlight_frame);
3473 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3475 /* Initialize mode_switch_bit and modifier_meaning. */
3476 static void
3477 x_find_modifier_meanings (dpyinfo)
3478 struct x_display_info *dpyinfo;
3480 int min_code, max_code;
3481 KeySym *syms;
3482 int syms_per_code;
3483 XModifierKeymap *mods;
3485 dpyinfo->meta_mod_mask = 0;
3486 dpyinfo->shift_lock_mask = 0;
3487 dpyinfo->alt_mod_mask = 0;
3488 dpyinfo->super_mod_mask = 0;
3489 dpyinfo->hyper_mod_mask = 0;
3491 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
3493 syms = XGetKeyboardMapping (dpyinfo->display,
3494 min_code, max_code - min_code + 1,
3495 &syms_per_code);
3496 mods = XGetModifierMapping (dpyinfo->display);
3498 /* Scan the modifier table to see which modifier bits the Meta and
3499 Alt keysyms are on. */
3501 int row, col; /* The row and column in the modifier table. */
3502 int found_alt_or_meta;
3504 for (row = 3; row < 8; row++)
3506 found_alt_or_meta = 0;
3507 for (col = 0; col < mods->max_keypermod; col++)
3509 KeyCode code = mods->modifiermap[(row * mods->max_keypermod) + col];
3511 /* Zeroes are used for filler. Skip them. */
3512 if (code == 0)
3513 continue;
3515 /* Are any of this keycode's keysyms a meta key? */
3517 int code_col;
3519 for (code_col = 0; code_col < syms_per_code; code_col++)
3521 int sym = syms[((code - min_code) * syms_per_code) + code_col];
3523 switch (sym)
3525 case XK_Meta_L:
3526 case XK_Meta_R:
3527 found_alt_or_meta = 1;
3528 dpyinfo->meta_mod_mask |= (1 << row);
3529 break;
3531 case XK_Alt_L:
3532 case XK_Alt_R:
3533 found_alt_or_meta = 1;
3534 dpyinfo->alt_mod_mask |= (1 << row);
3535 break;
3537 case XK_Hyper_L:
3538 case XK_Hyper_R:
3539 if (!found_alt_or_meta)
3540 dpyinfo->hyper_mod_mask |= (1 << row);
3541 code_col = syms_per_code;
3542 col = mods->max_keypermod;
3543 break;
3545 case XK_Super_L:
3546 case XK_Super_R:
3547 if (!found_alt_or_meta)
3548 dpyinfo->super_mod_mask |= (1 << row);
3549 code_col = syms_per_code;
3550 col = mods->max_keypermod;
3551 break;
3553 case XK_Shift_Lock:
3554 /* Ignore this if it's not on the lock modifier. */
3555 if (!found_alt_or_meta && ((1 << row) == LockMask))
3556 dpyinfo->shift_lock_mask = LockMask;
3557 code_col = syms_per_code;
3558 col = mods->max_keypermod;
3559 break;
3567 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3568 if (! dpyinfo->meta_mod_mask)
3570 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
3571 dpyinfo->alt_mod_mask = 0;
3574 /* If some keys are both alt and meta,
3575 make them just meta, not alt. */
3576 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
3578 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
3581 XFree ((char *) syms);
3582 XFreeModifiermap (mods);
3585 /* Convert between the modifier bits X uses and the modifier bits
3586 Emacs uses. */
3588 unsigned int
3589 x_x_to_emacs_modifiers (dpyinfo, state)
3590 struct x_display_info *dpyinfo;
3591 unsigned int state;
3593 EMACS_UINT mod_meta = meta_modifier;
3594 EMACS_UINT mod_alt = alt_modifier;
3595 EMACS_UINT mod_hyper = hyper_modifier;
3596 EMACS_UINT mod_super = super_modifier;
3597 Lisp_Object tem;
3599 tem = Fget (Vx_alt_keysym, Qmodifier_value);
3600 if (! EQ (tem, Qnil)) mod_alt = XUINT (tem);
3601 tem = Fget (Vx_meta_keysym, Qmodifier_value);
3602 if (! EQ (tem, Qnil)) mod_meta = XUINT (tem);
3603 tem = Fget (Vx_hyper_keysym, Qmodifier_value);
3604 if (! EQ (tem, Qnil)) mod_hyper = XUINT (tem);
3605 tem = Fget (Vx_super_keysym, Qmodifier_value);
3606 if (! EQ (tem, Qnil)) mod_super = XUINT (tem);
3609 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
3610 | ((state & ControlMask) ? ctrl_modifier : 0)
3611 | ((state & dpyinfo->meta_mod_mask) ? mod_meta : 0)
3612 | ((state & dpyinfo->alt_mod_mask) ? mod_alt : 0)
3613 | ((state & dpyinfo->super_mod_mask) ? mod_super : 0)
3614 | ((state & dpyinfo->hyper_mod_mask) ? mod_hyper : 0));
3617 static unsigned int
3618 x_emacs_to_x_modifiers (dpyinfo, state)
3619 struct x_display_info *dpyinfo;
3620 unsigned int state;
3622 EMACS_UINT mod_meta = meta_modifier;
3623 EMACS_UINT mod_alt = alt_modifier;
3624 EMACS_UINT mod_hyper = hyper_modifier;
3625 EMACS_UINT mod_super = super_modifier;
3627 Lisp_Object tem;
3629 tem = Fget (Vx_alt_keysym, Qmodifier_value);
3630 if (! EQ (tem, Qnil)) mod_alt = XUINT (tem);
3631 tem = Fget (Vx_meta_keysym, Qmodifier_value);
3632 if (! EQ (tem, Qnil)) mod_meta = XUINT (tem);
3633 tem = Fget (Vx_hyper_keysym, Qmodifier_value);
3634 if (! EQ (tem, Qnil)) mod_hyper = XUINT (tem);
3635 tem = Fget (Vx_super_keysym, Qmodifier_value);
3636 if (! EQ (tem, Qnil)) mod_super = XUINT (tem);
3639 return ( ((state & mod_alt) ? dpyinfo->alt_mod_mask : 0)
3640 | ((state & mod_super) ? dpyinfo->super_mod_mask : 0)
3641 | ((state & mod_hyper) ? dpyinfo->hyper_mod_mask : 0)
3642 | ((state & shift_modifier) ? ShiftMask : 0)
3643 | ((state & ctrl_modifier) ? ControlMask : 0)
3644 | ((state & mod_meta) ? dpyinfo->meta_mod_mask : 0));
3647 /* Convert a keysym to its name. */
3649 char *
3650 x_get_keysym_name (keysym)
3651 KeySym keysym;
3653 char *value;
3655 BLOCK_INPUT;
3656 value = XKeysymToString (keysym);
3657 UNBLOCK_INPUT;
3659 return value;
3664 /* Mouse clicks and mouse movement. Rah. */
3666 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3668 If the event is a button press, then note that we have grabbed
3669 the mouse. */
3671 static Lisp_Object
3672 construct_mouse_click (result, event, f)
3673 struct input_event *result;
3674 XButtonEvent *event;
3675 struct frame *f;
3677 /* Make the event type NO_EVENT; we'll change that when we decide
3678 otherwise. */
3679 result->kind = MOUSE_CLICK_EVENT;
3680 result->code = event->button - Button1;
3681 result->timestamp = event->time;
3682 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
3683 event->state)
3684 | (event->type == ButtonRelease
3685 ? up_modifier
3686 : down_modifier));
3688 XSETINT (result->x, event->x);
3689 XSETINT (result->y, event->y);
3690 XSETFRAME (result->frame_or_window, f);
3691 result->arg = Qnil;
3692 return Qnil;
3696 /* Function to report a mouse movement to the mainstream Emacs code.
3697 The input handler calls this.
3699 We have received a mouse movement event, which is given in *event.
3700 If the mouse is over a different glyph than it was last time, tell
3701 the mainstream emacs code by setting mouse_moved. If not, ask for
3702 another motion event, so we can check again the next time it moves. */
3704 static XMotionEvent last_mouse_motion_event;
3705 static Lisp_Object last_mouse_motion_frame;
3707 static int
3708 note_mouse_movement (frame, event)
3709 FRAME_PTR frame;
3710 XMotionEvent *event;
3712 last_mouse_movement_time = event->time;
3713 last_mouse_motion_event = *event;
3714 XSETFRAME (last_mouse_motion_frame, frame);
3716 if (!FRAME_X_OUTPUT (frame))
3717 return 0;
3719 if (event->window != FRAME_X_WINDOW (frame))
3721 frame->mouse_moved = 1;
3722 last_mouse_scroll_bar = Qnil;
3723 note_mouse_highlight (frame, -1, -1);
3724 last_mouse_glyph_frame = 0;
3725 return 1;
3729 /* Has the mouse moved off the glyph it was on at the last sighting? */
3730 if (frame != last_mouse_glyph_frame
3731 || event->x < last_mouse_glyph.x
3732 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
3733 || event->y < last_mouse_glyph.y
3734 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
3736 frame->mouse_moved = 1;
3737 last_mouse_scroll_bar = Qnil;
3738 note_mouse_highlight (frame, event->x, event->y);
3739 /* Remember which glyph we're now on. */
3740 remember_mouse_glyph (frame, event->x, event->y, &last_mouse_glyph);
3741 last_mouse_glyph_frame = frame;
3742 return 1;
3745 return 0;
3749 /************************************************************************
3750 Mouse Face
3751 ************************************************************************/
3753 static void
3754 redo_mouse_highlight ()
3756 if (!NILP (last_mouse_motion_frame)
3757 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
3758 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
3759 last_mouse_motion_event.x,
3760 last_mouse_motion_event.y);
3765 /* Return the current position of the mouse.
3766 *FP should be a frame which indicates which display to ask about.
3768 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
3769 and *PART to the frame, window, and scroll bar part that the mouse
3770 is over. Set *X and *Y to the portion and whole of the mouse's
3771 position on the scroll bar.
3773 If the mouse movement started elsewhere, set *FP to the frame the
3774 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
3775 the mouse is over.
3777 Set *TIME to the server time-stamp for the time at which the mouse
3778 was at this position.
3780 Don't store anything if we don't have a valid set of values to report.
3782 This clears the mouse_moved flag, so we can wait for the next mouse
3783 movement. */
3785 static void
3786 XTmouse_position (fp, insist, bar_window, part, x, y, time)
3787 FRAME_PTR *fp;
3788 int insist;
3789 Lisp_Object *bar_window;
3790 enum scroll_bar_part *part;
3791 Lisp_Object *x, *y;
3792 unsigned long *time;
3794 FRAME_PTR f1;
3796 BLOCK_INPUT;
3798 if (! NILP (last_mouse_scroll_bar) && insist == 0)
3799 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
3800 else
3802 Window root;
3803 int root_x, root_y;
3805 Window dummy_window;
3806 int dummy;
3808 Lisp_Object frame, tail;
3810 /* Clear the mouse-moved flag for every frame on this display. */
3811 FOR_EACH_FRAME (tail, frame)
3812 if (FRAME_X_P (XFRAME (frame))
3813 && FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
3814 XFRAME (frame)->mouse_moved = 0;
3816 last_mouse_scroll_bar = Qnil;
3818 /* Figure out which root window we're on. */
3819 XQueryPointer (FRAME_X_DISPLAY (*fp),
3820 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
3822 /* The root window which contains the pointer. */
3823 &root,
3825 /* Trash which we can't trust if the pointer is on
3826 a different screen. */
3827 &dummy_window,
3829 /* The position on that root window. */
3830 &root_x, &root_y,
3832 /* More trash we can't trust. */
3833 &dummy, &dummy,
3835 /* Modifier keys and pointer buttons, about which
3836 we don't care. */
3837 (unsigned int *) &dummy);
3839 /* Now we have a position on the root; find the innermost window
3840 containing the pointer. */
3842 Window win, child;
3843 int win_x, win_y;
3844 int parent_x = 0, parent_y = 0;
3846 win = root;
3848 /* XTranslateCoordinates can get errors if the window
3849 structure is changing at the same time this function
3850 is running. So at least we must not crash from them. */
3852 x_catch_errors (FRAME_X_DISPLAY (*fp));
3854 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
3855 && FRAME_LIVE_P (last_mouse_frame))
3857 /* If mouse was grabbed on a frame, give coords for that frame
3858 even if the mouse is now outside it. */
3859 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
3861 /* From-window, to-window. */
3862 root, FRAME_X_WINDOW (last_mouse_frame),
3864 /* From-position, to-position. */
3865 root_x, root_y, &win_x, &win_y,
3867 /* Child of win. */
3868 &child);
3869 f1 = last_mouse_frame;
3871 else
3873 while (1)
3875 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
3877 /* From-window, to-window. */
3878 root, win,
3880 /* From-position, to-position. */
3881 root_x, root_y, &win_x, &win_y,
3883 /* Child of win. */
3884 &child);
3886 if (child == None || child == win)
3887 break;
3889 win = child;
3890 parent_x = win_x;
3891 parent_y = win_y;
3894 /* Now we know that:
3895 win is the innermost window containing the pointer
3896 (XTC says it has no child containing the pointer),
3897 win_x and win_y are the pointer's position in it
3898 (XTC did this the last time through), and
3899 parent_x and parent_y are the pointer's position in win's parent.
3900 (They are what win_x and win_y were when win was child.
3901 If win is the root window, it has no parent, and
3902 parent_{x,y} are invalid, but that's okay, because we'll
3903 never use them in that case.) */
3905 /* Is win one of our frames? */
3906 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
3908 #ifdef USE_X_TOOLKIT
3909 /* If we end up with the menu bar window, say it's not
3910 on the frame. */
3911 if (f1 != NULL
3912 && f1->output_data.x->menubar_widget
3913 && win == XtWindow (f1->output_data.x->menubar_widget))
3914 f1 = NULL;
3915 #endif /* USE_X_TOOLKIT */
3918 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
3919 f1 = 0;
3921 x_uncatch_errors ();
3923 /* If not, is it one of our scroll bars? */
3924 if (! f1)
3926 struct scroll_bar *bar;
3928 bar = x_window_to_scroll_bar (FRAME_X_DISPLAY (*fp), win);
3930 if (bar)
3932 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
3933 win_x = parent_x;
3934 win_y = parent_y;
3938 if (f1 == 0 && insist > 0)
3939 f1 = SELECTED_FRAME ();
3941 if (f1)
3943 /* Ok, we found a frame. Store all the values.
3944 last_mouse_glyph is a rectangle used to reduce the
3945 generation of mouse events. To not miss any motion
3946 events, we must divide the frame into rectangles of the
3947 size of the smallest character that could be displayed
3948 on it, i.e. into the same rectangles that matrices on
3949 the frame are divided into. */
3951 remember_mouse_glyph (f1, win_x, win_y, &last_mouse_glyph);
3952 last_mouse_glyph_frame = f1;
3954 *bar_window = Qnil;
3955 *part = 0;
3956 *fp = f1;
3957 XSETINT (*x, win_x);
3958 XSETINT (*y, win_y);
3959 *time = last_mouse_movement_time;
3964 UNBLOCK_INPUT;
3969 /***********************************************************************
3970 Scroll bars
3971 ***********************************************************************/
3973 /* Scroll bar support. */
3975 /* Given an X window ID and a DISPLAY, find the struct scroll_bar which
3976 manages it.
3977 This can be called in GC, so we have to make sure to strip off mark
3978 bits. */
3980 static struct scroll_bar *
3981 x_window_to_scroll_bar (display, window_id)
3982 Display *display;
3983 Window window_id;
3985 Lisp_Object tail;
3987 #if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
3988 window_id = (Window) xg_get_scroll_id_for_window (display, window_id);
3989 #endif /* USE_GTK && USE_TOOLKIT_SCROLL_BARS */
3991 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
3993 Lisp_Object frame, bar, condemned;
3995 frame = XCAR (tail);
3996 /* All elements of Vframe_list should be frames. */
3997 if (! FRAMEP (frame))
3998 abort ();
4000 if (! FRAME_X_P (XFRAME (frame)))
4001 continue;
4003 /* Scan this frame's scroll bar list for a scroll bar with the
4004 right window ID. */
4005 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
4006 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
4007 /* This trick allows us to search both the ordinary and
4008 condemned scroll bar lists with one loop. */
4009 ! NILP (bar) || (bar = condemned,
4010 condemned = Qnil,
4011 ! NILP (bar));
4012 bar = XSCROLL_BAR (bar)->next)
4013 if (XSCROLL_BAR (bar)->x_window == window_id &&
4014 FRAME_X_DISPLAY (XFRAME (frame)) == display)
4015 return XSCROLL_BAR (bar);
4018 return 0;
4022 #if defined USE_LUCID
4024 /* Return the Lucid menu bar WINDOW is part of. Return null
4025 if WINDOW is not part of a menu bar. */
4027 static Widget
4028 x_window_to_menu_bar (window)
4029 Window window;
4031 Lisp_Object tail;
4033 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
4035 if (FRAME_X_P (XFRAME (XCAR (tail))))
4037 Lisp_Object frame = XCAR (tail);
4038 Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
4040 if (menu_bar && xlwmenu_window_p (menu_bar, window))
4041 return menu_bar;
4045 return NULL;
4048 #endif /* USE_LUCID */
4051 /************************************************************************
4052 Toolkit scroll bars
4053 ************************************************************************/
4055 #ifdef USE_TOOLKIT_SCROLL_BARS
4057 static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *));
4058 static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int));
4059 static void x_create_toolkit_scroll_bar P_ ((struct frame *,
4060 struct scroll_bar *));
4061 static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
4062 int, int, int));
4065 /* Lisp window being scrolled. Set when starting to interact with
4066 a toolkit scroll bar, reset to nil when ending the interaction. */
4068 static Lisp_Object window_being_scrolled;
4070 /* Last scroll bar part sent in xm_scroll_callback. */
4072 static int last_scroll_bar_part;
4074 /* Whether this is an Xaw with arrow-scrollbars. This should imply
4075 that movements of 1/20 of the screen size are mapped to up/down. */
4077 #ifndef USE_GTK
4078 /* Id of action hook installed for scroll bars. */
4080 static XtActionHookId action_hook_id;
4082 static Boolean xaw3d_arrow_scroll;
4084 /* Whether the drag scrolling maintains the mouse at the top of the
4085 thumb. If not, resizing the thumb needs to be done more carefully
4086 to avoid jerkyness. */
4088 static Boolean xaw3d_pick_top;
4090 /* Action hook installed via XtAppAddActionHook when toolkit scroll
4091 bars are used.. The hook is responsible for detecting when
4092 the user ends an interaction with the scroll bar, and generates
4093 a `end-scroll' SCROLL_BAR_CLICK_EVENT' event if so. */
4095 static void
4096 xt_action_hook (widget, client_data, action_name, event, params,
4097 num_params)
4098 Widget widget;
4099 XtPointer client_data;
4100 String action_name;
4101 XEvent *event;
4102 String *params;
4103 Cardinal *num_params;
4105 int scroll_bar_p;
4106 char *end_action;
4108 #ifdef USE_MOTIF
4109 scroll_bar_p = XmIsScrollBar (widget);
4110 end_action = "Release";
4111 #else /* !USE_MOTIF i.e. use Xaw */
4112 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
4113 end_action = "EndScroll";
4114 #endif /* USE_MOTIF */
4116 if (scroll_bar_p
4117 && strcmp (action_name, end_action) == 0
4118 && WINDOWP (window_being_scrolled))
4120 struct window *w;
4122 x_send_scroll_bar_event (window_being_scrolled,
4123 scroll_bar_end_scroll, 0, 0);
4124 w = XWINDOW (window_being_scrolled);
4126 if (!NILP (XSCROLL_BAR (w->vertical_scroll_bar)->dragging))
4128 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
4129 /* The thumb size is incorrect while dragging: fix it. */
4130 set_vertical_scroll_bar (w);
4132 window_being_scrolled = Qnil;
4133 last_scroll_bar_part = -1;
4135 /* Xt timeouts no longer needed. */
4136 toolkit_scroll_bar_interaction = 0;
4139 #endif /* not USE_GTK */
4141 /* A vector of windows used for communication between
4142 x_send_scroll_bar_event and x_scroll_bar_to_input_event. */
4144 static struct window **scroll_bar_windows;
4145 static int scroll_bar_windows_size;
4148 /* Send a client message with message type Xatom_Scrollbar for a
4149 scroll action to the frame of WINDOW. PART is a value identifying
4150 the part of the scroll bar that was clicked on. PORTION is the
4151 amount to scroll of a whole of WHOLE. */
4153 static void
4154 x_send_scroll_bar_event (window, part, portion, whole)
4155 Lisp_Object window;
4156 int part, portion, whole;
4158 XEvent event;
4159 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
4160 struct window *w = XWINDOW (window);
4161 struct frame *f = XFRAME (w->frame);
4162 int i;
4164 BLOCK_INPUT;
4166 /* Construct a ClientMessage event to send to the frame. */
4167 ev->type = ClientMessage;
4168 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
4169 ev->display = FRAME_X_DISPLAY (f);
4170 ev->window = FRAME_X_WINDOW (f);
4171 ev->format = 32;
4173 /* We can only transfer 32 bits in the XClientMessageEvent, which is
4174 not enough to store a pointer or Lisp_Object on a 64 bit system.
4175 So, store the window in scroll_bar_windows and pass the index
4176 into that array in the event. */
4177 for (i = 0; i < scroll_bar_windows_size; ++i)
4178 if (scroll_bar_windows[i] == NULL)
4179 break;
4181 if (i == scroll_bar_windows_size)
4183 int new_size = max (10, 2 * scroll_bar_windows_size);
4184 size_t nbytes = new_size * sizeof *scroll_bar_windows;
4185 size_t old_nbytes = scroll_bar_windows_size * sizeof *scroll_bar_windows;
4187 scroll_bar_windows = (struct window **) xrealloc (scroll_bar_windows,
4188 nbytes);
4189 bzero (&scroll_bar_windows[i], nbytes - old_nbytes);
4190 scroll_bar_windows_size = new_size;
4193 scroll_bar_windows[i] = w;
4194 ev->data.l[0] = (long) i;
4195 ev->data.l[1] = (long) part;
4196 ev->data.l[2] = (long) 0;
4197 ev->data.l[3] = (long) portion;
4198 ev->data.l[4] = (long) whole;
4200 /* Make Xt timeouts work while the scroll bar is active. */
4201 toolkit_scroll_bar_interaction = 1;
4202 #ifdef USE_X_TOOLKIT
4203 x_activate_timeout_atimer ();
4204 #endif
4206 /* Setting the event mask to zero means that the message will
4207 be sent to the client that created the window, and if that
4208 window no longer exists, no event will be sent. */
4209 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
4210 UNBLOCK_INPUT;
4214 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
4215 in *IEVENT. */
4217 static void
4218 x_scroll_bar_to_input_event (event, ievent)
4219 XEvent *event;
4220 struct input_event *ievent;
4222 XClientMessageEvent *ev = (XClientMessageEvent *) event;
4223 Lisp_Object window;
4224 struct frame *f;
4225 struct window *w;
4227 w = scroll_bar_windows[ev->data.l[0]];
4228 scroll_bar_windows[ev->data.l[0]] = NULL;
4230 XSETWINDOW (window, w);
4231 f = XFRAME (w->frame);
4233 ievent->kind = SCROLL_BAR_CLICK_EVENT;
4234 ievent->frame_or_window = window;
4235 ievent->arg = Qnil;
4236 #ifdef USE_GTK
4237 ievent->timestamp = CurrentTime;
4238 #else
4239 ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
4240 #endif
4241 ievent->part = ev->data.l[1];
4242 ievent->code = ev->data.l[2];
4243 ievent->x = make_number ((int) ev->data.l[3]);
4244 ievent->y = make_number ((int) ev->data.l[4]);
4245 ievent->modifiers = 0;
4249 #ifdef USE_MOTIF
4251 /* Minimum and maximum values used for Motif scroll bars. */
4253 #define XM_SB_MAX 10000000
4256 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
4257 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
4258 CALL_DATA is a pointer to a XmScrollBarCallbackStruct. */
4260 static void
4261 xm_scroll_callback (widget, client_data, call_data)
4262 Widget widget;
4263 XtPointer client_data, call_data;
4265 struct scroll_bar *bar = (struct scroll_bar *) client_data;
4266 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
4267 int part = -1, whole = 0, portion = 0;
4269 switch (cs->reason)
4271 case XmCR_DECREMENT:
4272 bar->dragging = Qnil;
4273 part = scroll_bar_up_arrow;
4274 break;
4276 case XmCR_INCREMENT:
4277 bar->dragging = Qnil;
4278 part = scroll_bar_down_arrow;
4279 break;
4281 case XmCR_PAGE_DECREMENT:
4282 bar->dragging = Qnil;
4283 part = scroll_bar_above_handle;
4284 break;
4286 case XmCR_PAGE_INCREMENT:
4287 bar->dragging = Qnil;
4288 part = scroll_bar_below_handle;
4289 break;
4291 case XmCR_TO_TOP:
4292 bar->dragging = Qnil;
4293 part = scroll_bar_to_top;
4294 break;
4296 case XmCR_TO_BOTTOM:
4297 bar->dragging = Qnil;
4298 part = scroll_bar_to_bottom;
4299 break;
4301 case XmCR_DRAG:
4303 int slider_size;
4305 /* Get the slider size. */
4306 BLOCK_INPUT;
4307 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
4308 UNBLOCK_INPUT;
4310 whole = XM_SB_MAX - slider_size;
4311 portion = min (cs->value, whole);
4312 part = scroll_bar_handle;
4313 bar->dragging = make_number (cs->value);
4315 break;
4317 case XmCR_VALUE_CHANGED:
4318 break;
4321 if (part >= 0)
4323 window_being_scrolled = bar->window;
4324 last_scroll_bar_part = part;
4325 x_send_scroll_bar_event (bar->window, part, portion, whole);
4329 #elif defined USE_GTK
4331 /* Scroll bar callback for GTK scroll bars. WIDGET is the scroll
4332 bar widget. DATA is a pointer to the scroll_bar structure. */
4334 static void
4335 xg_scroll_callback (widget, data)
4336 GtkRange *widget;
4337 gpointer data;
4339 struct scroll_bar *bar = (struct scroll_bar *) data;
4340 gdouble previous;
4341 gdouble position;
4342 gdouble *p;
4343 int diff;
4345 int part = -1, whole = 0, portion = 0;
4346 GtkAdjustment *adj = GTK_ADJUSTMENT (gtk_range_get_adjustment (widget));
4348 position = gtk_adjustment_get_value (adj);
4350 p = g_object_get_data (G_OBJECT (widget), XG_LAST_SB_DATA);
4351 if (! p)
4353 p = (gdouble*) xmalloc (sizeof (gdouble));
4354 *p = XG_SB_MIN;
4355 g_object_set_data (G_OBJECT (widget), XG_LAST_SB_DATA, p);
4358 previous = *p;
4359 *p = position;
4361 if (xg_ignore_gtk_scrollbar) return;
4363 diff = (int) (position - previous);
4365 if (diff == (int) adj->step_increment)
4367 part = scroll_bar_down_arrow;
4368 bar->dragging = Qnil;
4370 else if (-diff == (int) adj->step_increment)
4372 part = scroll_bar_up_arrow;
4373 bar->dragging = Qnil;
4375 else if (diff == (int) adj->page_increment)
4377 part = scroll_bar_below_handle;
4378 bar->dragging = Qnil;
4380 else if (-diff == (int) adj->page_increment)
4382 part = scroll_bar_above_handle;
4383 bar->dragging = Qnil;
4385 else
4387 part = scroll_bar_handle;
4388 whole = adj->upper - adj->page_size;
4389 portion = min ((int)position, whole);
4390 bar->dragging = make_number ((int)portion);
4393 if (part >= 0)
4395 window_being_scrolled = bar->window;
4396 last_scroll_bar_part = part;
4397 x_send_scroll_bar_event (bar->window, part, portion, whole);
4401 #else /* not USE_GTK and not USE_MOTIF */
4403 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
4404 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
4405 scroll bar struct. CALL_DATA is a pointer to a float saying where
4406 the thumb is. */
4408 static void
4409 xaw_jump_callback (widget, client_data, call_data)
4410 Widget widget;
4411 XtPointer client_data, call_data;
4413 struct scroll_bar *bar = (struct scroll_bar *) client_data;
4414 float top = *(float *) call_data;
4415 float shown;
4416 int whole, portion, height;
4417 int part;
4419 /* Get the size of the thumb, a value between 0 and 1. */
4420 BLOCK_INPUT;
4421 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
4422 UNBLOCK_INPUT;
4424 whole = 10000000;
4425 portion = shown < 1 ? top * whole : 0;
4427 if (shown < 1 && (eabs (top + shown - 1) < 1.0/height))
4428 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
4429 the bottom, so we force the scrolling whenever we see that we're
4430 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
4431 we try to ensure that we always stay two pixels away from the
4432 bottom). */
4433 part = scroll_bar_down_arrow;
4434 else
4435 part = scroll_bar_handle;
4437 window_being_scrolled = bar->window;
4438 bar->dragging = make_number (portion);
4439 last_scroll_bar_part = part;
4440 x_send_scroll_bar_event (bar->window, part, portion, whole);
4444 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
4445 i.e. line or page up or down. WIDGET is the Xaw scroll bar
4446 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
4447 the scroll bar. CALL_DATA is an integer specifying the action that
4448 has taken place. Its magnitude is in the range 0..height of the
4449 scroll bar. Negative values mean scroll towards buffer start.
4450 Values < height of scroll bar mean line-wise movement. */
4452 static void
4453 xaw_scroll_callback (widget, client_data, call_data)
4454 Widget widget;
4455 XtPointer client_data, call_data;
4457 struct scroll_bar *bar = (struct scroll_bar *) client_data;
4458 /* The position really is stored cast to a pointer. */
4459 int position = (long) call_data;
4460 Dimension height;
4461 int part;
4463 /* Get the height of the scroll bar. */
4464 BLOCK_INPUT;
4465 XtVaGetValues (widget, XtNheight, &height, NULL);
4466 UNBLOCK_INPUT;
4468 if (eabs (position) >= height)
4469 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
4471 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
4472 it maps line-movement to call_data = max(5, height/20). */
4473 else if (xaw3d_arrow_scroll && eabs (position) <= max (5, height / 20))
4474 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
4475 else
4476 part = scroll_bar_move_ratio;
4478 window_being_scrolled = bar->window;
4479 bar->dragging = Qnil;
4480 last_scroll_bar_part = part;
4481 x_send_scroll_bar_event (bar->window, part, position, height);
4484 #endif /* not USE_GTK and not USE_MOTIF */
4486 #define SCROLL_BAR_NAME "verticalScrollBar"
4488 /* Create the widget for scroll bar BAR on frame F. Record the widget
4489 and X window of the scroll bar in BAR. */
4491 #ifdef USE_GTK
4492 static void
4493 x_create_toolkit_scroll_bar (f, bar)
4494 struct frame *f;
4495 struct scroll_bar *bar;
4497 char *scroll_bar_name = SCROLL_BAR_NAME;
4499 BLOCK_INPUT;
4500 xg_create_scroll_bar (f, bar, G_CALLBACK (xg_scroll_callback),
4501 scroll_bar_name);
4502 UNBLOCK_INPUT;
4505 #else /* not USE_GTK */
4507 static void
4508 x_create_toolkit_scroll_bar (f, bar)
4509 struct frame *f;
4510 struct scroll_bar *bar;
4512 Window xwindow;
4513 Widget widget;
4514 Arg av[20];
4515 int ac = 0;
4516 char *scroll_bar_name = SCROLL_BAR_NAME;
4517 unsigned long pixel;
4519 BLOCK_INPUT;
4521 #ifdef USE_MOTIF
4522 /* Set resources. Create the widget. */
4523 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
4524 XtSetArg (av[ac], XmNminimum, 0); ++ac;
4525 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
4526 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
4527 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
4528 XtSetArg (av[ac], XmNincrement, 1); ++ac;
4529 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
4531 pixel = f->output_data.x->scroll_bar_foreground_pixel;
4532 if (pixel != -1)
4534 XtSetArg (av[ac], XmNforeground, pixel);
4535 ++ac;
4538 pixel = f->output_data.x->scroll_bar_background_pixel;
4539 if (pixel != -1)
4541 XtSetArg (av[ac], XmNbackground, pixel);
4542 ++ac;
4545 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
4546 scroll_bar_name, av, ac);
4548 /* Add one callback for everything that can happen. */
4549 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
4550 (XtPointer) bar);
4551 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
4552 (XtPointer) bar);
4553 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
4554 (XtPointer) bar);
4555 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
4556 (XtPointer) bar);
4557 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
4558 (XtPointer) bar);
4559 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
4560 (XtPointer) bar);
4561 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
4562 (XtPointer) bar);
4564 /* Realize the widget. Only after that is the X window created. */
4565 XtRealizeWidget (widget);
4567 /* Set the cursor to an arrow. I didn't find a resource to do that.
4568 And I'm wondering why it hasn't an arrow cursor by default. */
4569 XDefineCursor (XtDisplay (widget), XtWindow (widget),
4570 f->output_data.x->nontext_cursor);
4572 #else /* !USE_MOTIF i.e. use Xaw */
4574 /* Set resources. Create the widget. The background of the
4575 Xaw3d scroll bar widget is a little bit light for my taste.
4576 We don't alter it here to let users change it according
4577 to their taste with `emacs*verticalScrollBar.background: xxx'. */
4578 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
4579 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
4580 /* For smoother scrolling with Xaw3d -sm */
4581 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
4583 pixel = f->output_data.x->scroll_bar_foreground_pixel;
4584 if (pixel != -1)
4586 XtSetArg (av[ac], XtNforeground, pixel);
4587 ++ac;
4590 pixel = f->output_data.x->scroll_bar_background_pixel;
4591 if (pixel != -1)
4593 XtSetArg (av[ac], XtNbackground, pixel);
4594 ++ac;
4597 /* Top/bottom shadow colors. */
4599 /* Allocate them, if necessary. */
4600 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1)
4602 pixel = f->output_data.x->scroll_bar_background_pixel;
4603 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
4604 &pixel, 1.2, 0x8000))
4605 pixel = -1;
4606 f->output_data.x->scroll_bar_top_shadow_pixel = pixel;
4608 if (f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
4610 pixel = f->output_data.x->scroll_bar_background_pixel;
4611 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
4612 &pixel, 0.6, 0x4000))
4613 pixel = -1;
4614 f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
4617 #ifdef XtNbeNiceToColormap
4618 /* Tell the toolkit about them. */
4619 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1
4620 || f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
4621 /* We tried to allocate a color for the top/bottom shadow, and
4622 failed, so tell Xaw3d to use dithering instead. */
4624 XtSetArg (av[ac], XtNbeNiceToColormap, True);
4625 ++ac;
4627 else
4628 /* Tell what colors Xaw3d should use for the top/bottom shadow, to
4629 be more consistent with other emacs 3d colors, and since Xaw3d is
4630 not good at dealing with allocation failure. */
4632 /* This tells Xaw3d to use real colors instead of dithering for
4633 the shadows. */
4634 XtSetArg (av[ac], XtNbeNiceToColormap, False);
4635 ++ac;
4637 /* Specify the colors. */
4638 pixel = f->output_data.x->scroll_bar_top_shadow_pixel;
4639 if (pixel != -1)
4641 XtSetArg (av[ac], XtNtopShadowPixel, pixel);
4642 ++ac;
4644 pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel;
4645 if (pixel != -1)
4647 XtSetArg (av[ac], XtNbottomShadowPixel, pixel);
4648 ++ac;
4651 #endif
4653 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
4654 f->output_data.x->edit_widget, av, ac);
4657 char *initial = "";
4658 char *val = initial;
4659 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
4660 #ifdef XtNarrowScrollbars
4661 XtNarrowScrollbars, (XtPointer) &xaw3d_arrow_scroll,
4662 #endif
4663 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
4664 if (xaw3d_arrow_scroll || val == initial)
4665 { /* ARROW_SCROLL */
4666 xaw3d_arrow_scroll = True;
4667 /* Isn't that just a personal preference ? --Stef */
4668 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
4672 /* Define callbacks. */
4673 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
4674 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
4675 (XtPointer) bar);
4677 /* Realize the widget. Only after that is the X window created. */
4678 XtRealizeWidget (widget);
4680 #endif /* !USE_MOTIF */
4682 /* Install an action hook that lets us detect when the user
4683 finishes interacting with a scroll bar. */
4684 if (action_hook_id == 0)
4685 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
4687 /* Remember X window and widget in the scroll bar vector. */
4688 SET_SCROLL_BAR_X_WIDGET (bar, widget);
4689 xwindow = XtWindow (widget);
4690 bar->x_window = xwindow;
4692 UNBLOCK_INPUT;
4694 #endif /* not USE_GTK */
4697 /* Set the thumb size and position of scroll bar BAR. We are currently
4698 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4700 #ifdef USE_GTK
4701 static void
4702 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
4703 struct scroll_bar *bar;
4704 int portion, position, whole;
4706 xg_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
4709 #else /* not USE_GTK */
4710 static void
4711 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
4712 struct scroll_bar *bar;
4713 int portion, position, whole;
4715 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4716 Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
4717 float top, shown;
4719 BLOCK_INPUT;
4721 #ifdef USE_MOTIF
4723 /* We use an estimate of 30 chars per line rather than the real
4724 `portion' value. This has the disadvantage that the thumb size
4725 is not very representative, but it makes our life a lot easier.
4726 Otherwise, we have to constantly adjust the thumb size, which
4727 we can't always do quickly enough: while dragging, the size of
4728 the thumb might prevent the user from dragging the thumb all the
4729 way to the end. but Motif and some versions of Xaw3d don't allow
4730 updating the thumb size while dragging. Also, even if we can update
4731 its size, the update will often happen too late.
4732 If you don't believe it, check out revision 1.650 of xterm.c to see
4733 what hoops we were going through and the still poor behavior we got. */
4734 portion = WINDOW_TOTAL_LINES (XWINDOW (bar->window)) * 30;
4735 /* When the thumb is at the bottom, position == whole.
4736 So we need to increase `whole' to make space for the thumb. */
4737 whole += portion;
4739 if (whole <= 0)
4740 top = 0, shown = 1;
4741 else
4743 top = (float) position / whole;
4744 shown = (float) portion / whole;
4747 if (NILP (bar->dragging))
4749 int size, value;
4751 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
4752 is the scroll bar's maximum and MIN is the scroll bar's minimum
4753 value. */
4754 size = shown * XM_SB_MAX;
4755 size = min (size, XM_SB_MAX);
4756 size = max (size, 1);
4758 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
4759 value = top * XM_SB_MAX;
4760 value = min (value, XM_SB_MAX - size);
4762 XmScrollBarSetValues (widget, value, size, 0, 0, False);
4764 #else /* !USE_MOTIF i.e. use Xaw */
4766 if (whole == 0)
4767 top = 0, shown = 1;
4768 else
4770 top = (float) position / whole;
4771 shown = (float) portion / whole;
4775 float old_top, old_shown;
4776 Dimension height;
4777 XtVaGetValues (widget,
4778 XtNtopOfThumb, &old_top,
4779 XtNshown, &old_shown,
4780 XtNheight, &height,
4781 NULL);
4783 /* Massage the top+shown values. */
4784 if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow)
4785 top = max (0, min (1, top));
4786 else
4787 top = old_top;
4788 /* Keep two pixels available for moving the thumb down. */
4789 shown = max (0, min (1 - top - (2.0 / height), shown));
4791 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
4792 check that your system's configuration file contains a define
4793 for `NARROWPROTO'. See s/freebsd.h for an example. */
4794 if (top != old_top || shown != old_shown)
4796 if (NILP (bar->dragging))
4797 XawScrollbarSetThumb (widget, top, shown);
4798 else
4800 /* Try to make the scrolling a tad smoother. */
4801 if (!xaw3d_pick_top)
4802 shown = min (shown, old_shown);
4804 XawScrollbarSetThumb (widget, top, shown);
4808 #endif /* !USE_MOTIF */
4810 UNBLOCK_INPUT;
4812 #endif /* not USE_GTK */
4814 #endif /* USE_TOOLKIT_SCROLL_BARS */
4818 /************************************************************************
4819 Scroll bars, general
4820 ************************************************************************/
4822 /* Create a scroll bar and return the scroll bar vector for it. W is
4823 the Emacs window on which to create the scroll bar. TOP, LEFT,
4824 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4825 scroll bar. */
4827 static struct scroll_bar *
4828 x_scroll_bar_create (w, top, left, width, height)
4829 struct window *w;
4830 int top, left, width, height;
4832 struct frame *f = XFRAME (w->frame);
4833 struct scroll_bar *bar
4834 = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, x_window, PVEC_OTHER);
4836 BLOCK_INPUT;
4838 #ifdef USE_TOOLKIT_SCROLL_BARS
4839 x_create_toolkit_scroll_bar (f, bar);
4840 #else /* not USE_TOOLKIT_SCROLL_BARS */
4842 XSetWindowAttributes a;
4843 unsigned long mask;
4844 Window window;
4846 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
4847 if (a.background_pixel == -1)
4848 a.background_pixel = FRAME_BACKGROUND_PIXEL (f);
4850 a.event_mask = (ButtonPressMask | ButtonReleaseMask
4851 | ButtonMotionMask | PointerMotionHintMask
4852 | ExposureMask);
4853 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
4855 mask = (CWBackPixel | CWEventMask | CWCursor);
4857 /* Clear the area of W that will serve as a scroll bar. This is
4858 for the case that a window has been split horizontally. In
4859 this case, no clear_frame is generated to reduce flickering. */
4860 if (width > 0 && height > 0)
4861 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4862 left, top, width,
4863 window_box_height (w), False);
4865 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4866 /* Position and size of scroll bar. */
4867 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
4868 top,
4869 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
4870 height,
4871 /* Border width, depth, class, and visual. */
4873 CopyFromParent,
4874 CopyFromParent,
4875 CopyFromParent,
4876 /* Attributes. */
4877 mask, &a);
4878 bar->x_window = window;
4880 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4882 XSETWINDOW (bar->window, w);
4883 bar->top = top;
4884 bar->left = left;
4885 bar->width = width;
4886 bar->height = height;
4887 bar->start = 0;
4888 bar->end = 0;
4889 bar->dragging = Qnil;
4890 bar->fringe_extended_p = 0;
4892 /* Add bar to its frame's list of scroll bars. */
4893 bar->next = FRAME_SCROLL_BARS (f);
4894 bar->prev = Qnil;
4895 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4896 if (!NILP (bar->next))
4897 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4899 /* Map the window/widget. */
4900 #ifdef USE_TOOLKIT_SCROLL_BARS
4902 #ifdef USE_GTK
4903 xg_update_scrollbar_pos (f,
4904 bar->x_window,
4905 top,
4906 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
4907 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
4908 max (height, 1));
4909 xg_show_scroll_bar (bar->x_window);
4910 #else /* not USE_GTK */
4911 Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
4912 XtConfigureWidget (scroll_bar,
4913 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
4914 top,
4915 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
4916 max (height, 1), 0);
4917 XtMapWidget (scroll_bar);
4918 #endif /* not USE_GTK */
4920 #else /* not USE_TOOLKIT_SCROLL_BARS */
4921 XMapRaised (FRAME_X_DISPLAY (f), bar->x_window);
4922 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4924 UNBLOCK_INPUT;
4925 return bar;
4929 #ifndef USE_TOOLKIT_SCROLL_BARS
4931 /* Draw BAR's handle in the proper position.
4933 If the handle is already drawn from START to END, don't bother
4934 redrawing it, unless REBUILD is non-zero; in that case, always
4935 redraw it. (REBUILD is handy for drawing the handle after expose
4936 events.)
4938 Normally, we want to constrain the start and end of the handle to
4939 fit inside its rectangle, but if the user is dragging the scroll
4940 bar handle, we want to let them drag it down all the way, so that
4941 the bar's top is as far down as it goes; otherwise, there's no way
4942 to move to the very end of the buffer. */
4944 static void
4945 x_scroll_bar_set_handle (bar, start, end, rebuild)
4946 struct scroll_bar *bar;
4947 int start, end;
4948 int rebuild;
4950 int dragging = ! NILP (bar->dragging);
4951 Window w = bar->x_window;
4952 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4953 GC gc = f->output_data.x->normal_gc;
4955 /* If the display is already accurate, do nothing. */
4956 if (! rebuild
4957 && start == bar->start
4958 && end == bar->end)
4959 return;
4961 BLOCK_INPUT;
4964 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, bar->width);
4965 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, bar->height);
4966 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
4968 /* Make sure the values are reasonable, and try to preserve
4969 the distance between start and end. */
4971 int length = end - start;
4973 if (start < 0)
4974 start = 0;
4975 else if (start > top_range)
4976 start = top_range;
4977 end = start + length;
4979 if (end < start)
4980 end = start;
4981 else if (end > top_range && ! dragging)
4982 end = top_range;
4985 /* Store the adjusted setting in the scroll bar. */
4986 bar->start = start;
4987 bar->end = end;
4989 /* Clip the end position, just for display. */
4990 if (end > top_range)
4991 end = top_range;
4993 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
4994 below top positions, to make sure the handle is always at least
4995 that many pixels tall. */
4996 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
4998 /* Draw the empty space above the handle. Note that we can't clear
4999 zero-height areas; that means "clear to end of window." */
5000 if (0 < start)
5001 x_clear_area (FRAME_X_DISPLAY (f), w,
5002 /* x, y, width, height, and exposures. */
5003 VERTICAL_SCROLL_BAR_LEFT_BORDER,
5004 VERTICAL_SCROLL_BAR_TOP_BORDER,
5005 inside_width, start,
5006 False);
5008 /* Change to proper foreground color if one is specified. */
5009 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
5010 XSetForeground (FRAME_X_DISPLAY (f), gc,
5011 f->output_data.x->scroll_bar_foreground_pixel);
5013 /* Draw the handle itself. */
5014 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
5015 /* x, y, width, height */
5016 VERTICAL_SCROLL_BAR_LEFT_BORDER,
5017 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
5018 inside_width, end - start);
5020 /* Restore the foreground color of the GC if we changed it above. */
5021 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
5022 XSetForeground (FRAME_X_DISPLAY (f), gc,
5023 FRAME_FOREGROUND_PIXEL (f));
5025 /* Draw the empty space below the handle. Note that we can't
5026 clear zero-height areas; that means "clear to end of window." */
5027 if (end < inside_height)
5028 x_clear_area (FRAME_X_DISPLAY (f), w,
5029 /* x, y, width, height, and exposures. */
5030 VERTICAL_SCROLL_BAR_LEFT_BORDER,
5031 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
5032 inside_width, inside_height - end,
5033 False);
5037 UNBLOCK_INPUT;
5040 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5042 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5043 nil. */
5045 static void
5046 x_scroll_bar_remove (bar)
5047 struct scroll_bar *bar;
5049 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5050 BLOCK_INPUT;
5052 #ifdef USE_TOOLKIT_SCROLL_BARS
5053 #ifdef USE_GTK
5054 xg_remove_scroll_bar (f, bar->x_window);
5055 #else /* not USE_GTK */
5056 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));
5057 #endif /* not USE_GTK */
5058 #else
5059 XDestroyWindow (FRAME_X_DISPLAY (f), bar->x_window);
5060 #endif
5062 /* Disassociate this scroll bar from its window. */
5063 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
5065 UNBLOCK_INPUT;
5069 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5070 that we are displaying PORTION characters out of a total of WHOLE
5071 characters, starting at POSITION. If WINDOW has no scroll bar,
5072 create one. */
5074 static void
5075 XTset_vertical_scroll_bar (w, portion, whole, position)
5076 struct window *w;
5077 int portion, whole, position;
5079 struct frame *f = XFRAME (w->frame);
5080 struct scroll_bar *bar;
5081 int top, height, left, sb_left, width, sb_width;
5082 int window_y, window_height;
5083 #ifdef USE_TOOLKIT_SCROLL_BARS
5084 int fringe_extended_p;
5085 #endif
5087 /* Get window dimensions. */
5088 window_box (w, -1, 0, &window_y, 0, &window_height);
5089 top = window_y;
5090 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
5091 height = window_height;
5093 /* Compute the left edge of the scroll bar area. */
5094 left = WINDOW_SCROLL_BAR_AREA_X (w);
5096 /* Compute the width of the scroll bar which might be less than
5097 the width of the area reserved for the scroll bar. */
5098 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
5099 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
5100 else
5101 sb_width = width;
5103 /* Compute the left edge of the scroll bar. */
5104 #ifdef USE_TOOLKIT_SCROLL_BARS
5105 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
5106 sb_left = left + (WINDOW_RIGHTMOST_P (w) ? width - sb_width : 0);
5107 else
5108 sb_left = left + (WINDOW_LEFTMOST_P (w) ? 0 : width - sb_width);
5109 #else
5110 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
5111 sb_left = left + width - sb_width;
5112 else
5113 sb_left = left;
5114 #endif
5116 #ifdef USE_TOOLKIT_SCROLL_BARS
5117 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
5118 fringe_extended_p = (WINDOW_LEFTMOST_P (w)
5119 && WINDOW_LEFT_FRINGE_WIDTH (w)
5120 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
5121 || WINDOW_LEFT_MARGIN_COLS (w) == 0));
5122 else
5123 fringe_extended_p = (WINDOW_RIGHTMOST_P (w)
5124 && WINDOW_RIGHT_FRINGE_WIDTH (w)
5125 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
5126 || WINDOW_RIGHT_MARGIN_COLS (w) == 0));
5127 #endif
5129 /* Does the scroll bar exist yet? */
5130 if (NILP (w->vertical_scroll_bar))
5132 if (width > 0 && height > 0)
5134 BLOCK_INPUT;
5135 #ifdef USE_TOOLKIT_SCROLL_BARS
5136 if (fringe_extended_p)
5137 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5138 sb_left, top, sb_width, height, False);
5139 else
5140 #endif
5141 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5142 left, top, width, height, False);
5143 UNBLOCK_INPUT;
5146 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
5148 else
5150 /* It may just need to be moved and resized. */
5151 unsigned int mask = 0;
5153 bar = XSCROLL_BAR (w->vertical_scroll_bar);
5155 BLOCK_INPUT;
5157 if (sb_left != bar->left)
5158 mask |= CWX;
5159 if (top != bar->top)
5160 mask |= CWY;
5161 if (sb_width != bar->width)
5162 mask |= CWWidth;
5163 if (height != bar->height)
5164 mask |= CWHeight;
5166 #ifdef USE_TOOLKIT_SCROLL_BARS
5168 /* Move/size the scroll bar widget. */
5169 if (mask || bar->fringe_extended_p != fringe_extended_p)
5171 /* Since toolkit scroll bars are smaller than the space reserved
5172 for them on the frame, we have to clear "under" them. */
5173 if (width > 0 && height > 0)
5175 if (fringe_extended_p)
5176 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5177 sb_left, top, sb_width, height, False);
5178 else
5179 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5180 left, top, width, height, False);
5182 #ifdef USE_GTK
5183 xg_update_scrollbar_pos (f,
5184 bar->x_window,
5185 top,
5186 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
5187 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM *2,
5188 max (height, 1));
5189 #else /* not USE_GTK */
5190 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
5191 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
5192 top,
5193 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
5194 max (height, 1), 0);
5195 #endif /* not USE_GTK */
5197 #else /* not USE_TOOLKIT_SCROLL_BARS */
5199 /* Clear areas not covered by the scroll bar because of
5200 VERTICAL_SCROLL_BAR_WIDTH_TRIM. */
5201 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
5203 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5204 left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
5205 height, False);
5206 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5207 left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
5208 top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
5209 height, False);
5212 /* Clear areas not covered by the scroll bar because it's not as
5213 wide as the area reserved for it. This makes sure a
5214 previous mode line display is cleared after C-x 2 C-x 1, for
5215 example. */
5217 int area_width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
5218 int rest = area_width - sb_width;
5219 if (rest > 0 && height > 0)
5221 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
5222 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5223 left + area_width - rest, top,
5224 rest, height, False);
5225 else
5226 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5227 left, top, rest, height, False);
5231 /* Move/size the scroll bar window. */
5232 if (mask)
5234 XWindowChanges wc;
5236 wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5237 wc.y = top;
5238 wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
5239 wc.height = height;
5240 XConfigureWindow (FRAME_X_DISPLAY (f), bar->x_window,
5241 mask, &wc);
5244 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5246 /* Remember new settings. */
5247 bar->left = sb_left;
5248 bar->top = top;
5249 bar->width = sb_width;
5250 bar->height = height;
5252 UNBLOCK_INPUT;
5255 #ifdef USE_TOOLKIT_SCROLL_BARS
5256 bar->fringe_extended_p = fringe_extended_p;
5258 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
5259 #else /* not USE_TOOLKIT_SCROLL_BARS */
5260 /* Set the scroll bar's current state, unless we're currently being
5261 dragged. */
5262 if (NILP (bar->dragging))
5264 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
5266 if (whole == 0)
5267 x_scroll_bar_set_handle (bar, 0, top_range, 0);
5268 else
5270 int start = ((double) position * top_range) / whole;
5271 int end = ((double) (position + portion) * top_range) / whole;
5272 x_scroll_bar_set_handle (bar, start, end, 0);
5275 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5277 XSETVECTOR (w->vertical_scroll_bar, bar);
5281 /* The following three hooks are used when we're doing a thorough
5282 redisplay of the frame. We don't explicitly know which scroll bars
5283 are going to be deleted, because keeping track of when windows go
5284 away is a real pain - "Can you say set-window-configuration, boys
5285 and girls?" Instead, we just assert at the beginning of redisplay
5286 that *all* scroll bars are to be removed, and then save a scroll bar
5287 from the fiery pit when we actually redisplay its window. */
5289 /* Arrange for all scroll bars on FRAME to be removed at the next call
5290 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5291 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5293 static void
5294 XTcondemn_scroll_bars (frame)
5295 FRAME_PTR frame;
5297 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5298 while (! NILP (FRAME_SCROLL_BARS (frame)))
5300 Lisp_Object bar;
5301 bar = FRAME_SCROLL_BARS (frame);
5302 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
5303 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
5304 XSCROLL_BAR (bar)->prev = Qnil;
5305 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
5306 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
5307 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
5312 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5313 Note that WINDOW isn't necessarily condemned at all. */
5315 static void
5316 XTredeem_scroll_bar (window)
5317 struct window *window;
5319 struct scroll_bar *bar;
5320 struct frame *f;
5322 /* We can't redeem this window's scroll bar if it doesn't have one. */
5323 if (NILP (window->vertical_scroll_bar))
5324 abort ();
5326 bar = XSCROLL_BAR (window->vertical_scroll_bar);
5328 /* Unlink it from the condemned list. */
5329 f = XFRAME (WINDOW_FRAME (window));
5330 if (NILP (bar->prev))
5332 /* If the prev pointer is nil, it must be the first in one of
5333 the lists. */
5334 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
5335 /* It's not condemned. Everything's fine. */
5336 return;
5337 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
5338 window->vertical_scroll_bar))
5339 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
5340 else
5341 /* If its prev pointer is nil, it must be at the front of
5342 one or the other! */
5343 abort ();
5345 else
5346 XSCROLL_BAR (bar->prev)->next = bar->next;
5348 if (! NILP (bar->next))
5349 XSCROLL_BAR (bar->next)->prev = bar->prev;
5351 bar->next = FRAME_SCROLL_BARS (f);
5352 bar->prev = Qnil;
5353 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
5354 if (! NILP (bar->next))
5355 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
5358 /* Remove all scroll bars on FRAME that haven't been saved since the
5359 last call to `*condemn_scroll_bars_hook'. */
5361 static void
5362 XTjudge_scroll_bars (f)
5363 FRAME_PTR f;
5365 Lisp_Object bar, next;
5367 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
5369 /* Clear out the condemned list now so we won't try to process any
5370 more events on the hapless scroll bars. */
5371 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
5373 for (; ! NILP (bar); bar = next)
5375 struct scroll_bar *b = XSCROLL_BAR (bar);
5377 x_scroll_bar_remove (b);
5379 next = b->next;
5380 b->next = b->prev = Qnil;
5383 /* Now there should be no references to the condemned scroll bars,
5384 and they should get garbage-collected. */
5388 #ifndef USE_TOOLKIT_SCROLL_BARS
5389 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
5390 is a no-op when using toolkit scroll bars.
5392 This may be called from a signal handler, so we have to ignore GC
5393 mark bits. */
5395 static void
5396 x_scroll_bar_expose (bar, event)
5397 struct scroll_bar *bar;
5398 XEvent *event;
5400 Window w = bar->x_window;
5401 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5402 GC gc = f->output_data.x->normal_gc;
5403 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5405 BLOCK_INPUT;
5407 x_scroll_bar_set_handle (bar, bar->start, bar->end, 1);
5409 /* Switch to scroll bar foreground color. */
5410 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
5411 XSetForeground (FRAME_X_DISPLAY (f), gc,
5412 f->output_data.x->scroll_bar_foreground_pixel);
5414 /* Draw a one-pixel border just inside the edges of the scroll bar. */
5415 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
5417 /* x, y, width, height */
5418 0, 0,
5419 bar->width - 1 - width_trim - width_trim,
5420 bar->height - 1);
5422 /* Restore the foreground color of the GC if we changed it above. */
5423 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
5424 XSetForeground (FRAME_X_DISPLAY (f), gc,
5425 FRAME_FOREGROUND_PIXEL (f));
5427 UNBLOCK_INPUT;
5430 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5432 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5433 is set to something other than NO_EVENT, it is enqueued.
5435 This may be called from a signal handler, so we have to ignore GC
5436 mark bits. */
5439 static void
5440 x_scroll_bar_handle_click (bar, event, emacs_event)
5441 struct scroll_bar *bar;
5442 XEvent *event;
5443 struct input_event *emacs_event;
5445 if (! WINDOWP (bar->window))
5446 abort ();
5448 emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
5449 emacs_event->code = event->xbutton.button - Button1;
5450 emacs_event->modifiers
5451 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
5452 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
5453 event->xbutton.state)
5454 | (event->type == ButtonRelease
5455 ? up_modifier
5456 : down_modifier));
5457 emacs_event->frame_or_window = bar->window;
5458 emacs_event->arg = Qnil;
5459 emacs_event->timestamp = event->xbutton.time;
5461 #if 0
5462 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5463 int internal_height
5464 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, bar->height);
5465 #endif
5466 int top_range
5467 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
5468 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
5470 if (y < 0) y = 0;
5471 if (y > top_range) y = top_range;
5473 if (y < bar->start)
5474 emacs_event->part = scroll_bar_above_handle;
5475 else if (y < bar->end + VERTICAL_SCROLL_BAR_MIN_HANDLE)
5476 emacs_event->part = scroll_bar_handle;
5477 else
5478 emacs_event->part = scroll_bar_below_handle;
5480 /* Just because the user has clicked on the handle doesn't mean
5481 they want to drag it. Lisp code needs to be able to decide
5482 whether or not we're dragging. */
5483 #if 0
5484 /* If the user has just clicked on the handle, record where they're
5485 holding it. */
5486 if (event->type == ButtonPress
5487 && emacs_event->part == scroll_bar_handle)
5488 XSETINT (bar->dragging, y - bar->start);
5489 #endif
5491 #ifndef USE_TOOLKIT_SCROLL_BARS
5492 /* If the user has released the handle, set it to its final position. */
5493 if (event->type == ButtonRelease
5494 && ! NILP (bar->dragging))
5496 int new_start = y - XINT (bar->dragging);
5497 int new_end = new_start + bar->end - bar->start;
5499 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
5500 bar->dragging = Qnil;
5502 #endif
5504 /* Same deal here as the other #if 0. */
5505 #if 0
5506 /* Clicks on the handle are always reported as occurring at the top of
5507 the handle. */
5508 if (emacs_event->part == scroll_bar_handle)
5509 emacs_event->x = bar->start;
5510 else
5511 XSETINT (emacs_event->x, y);
5512 #else
5513 XSETINT (emacs_event->x, y);
5514 #endif
5516 XSETINT (emacs_event->y, top_range);
5520 #ifndef USE_TOOLKIT_SCROLL_BARS
5522 /* Handle some mouse motion while someone is dragging the scroll bar.
5524 This may be called from a signal handler, so we have to ignore GC
5525 mark bits. */
5527 static void
5528 x_scroll_bar_note_movement (bar, event)
5529 struct scroll_bar *bar;
5530 XEvent *event;
5532 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
5534 last_mouse_movement_time = event->xmotion.time;
5536 f->mouse_moved = 1;
5537 XSETVECTOR (last_mouse_scroll_bar, bar);
5539 /* If we're dragging the bar, display it. */
5540 if (! NILP (bar->dragging))
5542 /* Where should the handle be now? */
5543 int new_start = event->xmotion.y - XINT (bar->dragging);
5545 if (new_start != bar->start)
5547 int new_end = new_start + bar->end - bar->start;
5549 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
5554 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5556 /* Return information to the user about the current position of the mouse
5557 on the scroll bar. */
5559 static void
5560 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
5561 FRAME_PTR *fp;
5562 Lisp_Object *bar_window;
5563 enum scroll_bar_part *part;
5564 Lisp_Object *x, *y;
5565 unsigned long *time;
5567 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
5568 Window w = bar->x_window;
5569 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5570 int win_x, win_y;
5571 Window dummy_window;
5572 int dummy_coord;
5573 unsigned int dummy_mask;
5575 BLOCK_INPUT;
5577 /* Get the mouse's position relative to the scroll bar window, and
5578 report that. */
5579 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
5581 /* Root, child, root x and root y. */
5582 &dummy_window, &dummy_window,
5583 &dummy_coord, &dummy_coord,
5585 /* Position relative to scroll bar. */
5586 &win_x, &win_y,
5588 /* Mouse buttons and modifier keys. */
5589 &dummy_mask))
5591 else
5593 #if 0
5594 int inside_height
5595 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, bar->height);
5596 #endif
5597 int top_range
5598 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
5600 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
5602 if (! NILP (bar->dragging))
5603 win_y -= XINT (bar->dragging);
5605 if (win_y < 0)
5606 win_y = 0;
5607 if (win_y > top_range)
5608 win_y = top_range;
5610 *fp = f;
5611 *bar_window = bar->window;
5613 if (! NILP (bar->dragging))
5614 *part = scroll_bar_handle;
5615 else if (win_y < bar->start)
5616 *part = scroll_bar_above_handle;
5617 else if (win_y < bar->end + VERTICAL_SCROLL_BAR_MIN_HANDLE)
5618 *part = scroll_bar_handle;
5619 else
5620 *part = scroll_bar_below_handle;
5622 XSETINT (*x, win_y);
5623 XSETINT (*y, top_range);
5625 f->mouse_moved = 0;
5626 last_mouse_scroll_bar = Qnil;
5629 *time = last_mouse_movement_time;
5631 UNBLOCK_INPUT;
5635 /* The screen has been cleared so we may have changed foreground or
5636 background colors, and the scroll bars may need to be redrawn.
5637 Clear out the scroll bars, and ask for expose events, so we can
5638 redraw them. */
5640 void
5641 x_scroll_bar_clear (f)
5642 FRAME_PTR f;
5644 #ifndef USE_TOOLKIT_SCROLL_BARS
5645 Lisp_Object bar;
5647 /* We can have scroll bars even if this is 0,
5648 if we just turned off scroll bar mode.
5649 But in that case we should not clear them. */
5650 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5651 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
5652 bar = XSCROLL_BAR (bar)->next)
5653 XClearArea (FRAME_X_DISPLAY (f),
5654 XSCROLL_BAR (bar)->x_window,
5655 0, 0, 0, 0, True);
5656 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5660 /* The main X event-reading loop - XTread_socket. */
5662 #if 0
5663 /* Time stamp of enter window event. This is only used by XTread_socket,
5664 but we have to put it out here, since static variables within functions
5665 sometimes don't work. */
5667 static Time enter_timestamp;
5668 #endif
5670 /* This holds the state XLookupString needs to implement dead keys
5671 and other tricks known as "compose processing". _X Window System_
5672 says that a portable program can't use this, but Stephen Gildea assures
5673 me that letting the compiler initialize it to zeros will work okay.
5675 This must be defined outside of XTread_socket, for the same reasons
5676 given for enter_timestamp, above. */
5678 static XComposeStatus compose_status;
5680 /* Record the last 100 characters stored
5681 to help debug the loss-of-chars-during-GC problem. */
5683 static int temp_index;
5684 static short temp_buffer[100];
5686 #define STORE_KEYSYM_FOR_DEBUG(keysym) \
5687 if (temp_index == sizeof temp_buffer / sizeof (short)) \
5688 temp_index = 0; \
5689 temp_buffer[temp_index++] = (keysym)
5691 /* Set this to nonzero to fake an "X I/O error"
5692 on a particular display. */
5694 struct x_display_info *XTread_socket_fake_io_error;
5696 /* When we find no input here, we occasionally do a no-op command
5697 to verify that the X server is still running and we can still talk with it.
5698 We try all the open displays, one by one.
5699 This variable is used for cycling thru the displays. */
5701 static struct x_display_info *next_noop_dpyinfo;
5703 #define SET_SAVED_MENU_EVENT(size) \
5704 do \
5706 if (f->output_data.x->saved_menu_event == 0) \
5707 f->output_data.x->saved_menu_event \
5708 = (XEvent *) xmalloc (sizeof (XEvent)); \
5709 bcopy (&event, f->output_data.x->saved_menu_event, size); \
5710 inev.ie.kind = MENU_BAR_ACTIVATE_EVENT; \
5711 XSETFRAME (inev.ie.frame_or_window, f); \
5713 while (0)
5715 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
5716 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
5719 enum
5721 X_EVENT_NORMAL,
5722 X_EVENT_GOTO_OUT,
5723 X_EVENT_DROP
5726 /* Filter events for the current X input method.
5727 DPYINFO is the display this event is for.
5728 EVENT is the X event to filter.
5730 Returns non-zero if the event was filtered, caller shall not process
5731 this event further.
5732 Returns zero if event is wasn't filtered. */
5734 #ifdef HAVE_X_I18N
5735 static int
5736 x_filter_event (dpyinfo, event)
5737 struct x_display_info *dpyinfo;
5738 XEvent *event;
5740 /* XFilterEvent returns non-zero if the input method has
5741 consumed the event. We pass the frame's X window to
5742 XFilterEvent because that's the one for which the IC
5743 was created. */
5745 struct frame *f1 = x_any_window_to_frame (dpyinfo,
5746 event->xclient.window);
5748 return XFilterEvent (event, f1 ? FRAME_X_WINDOW (f1) : None);
5750 #endif
5752 #ifdef USE_GTK
5753 static int current_count;
5754 static int current_finish;
5755 static struct input_event *current_hold_quit;
5757 /* This is the filter function invoked by the GTK event loop.
5758 It is invoked before the XEvent is translated to a GdkEvent,
5759 so we have a chance to act on the event before GTK. */
5760 static GdkFilterReturn
5761 event_handler_gdk (gxev, ev, data)
5762 GdkXEvent *gxev;
5763 GdkEvent *ev;
5764 gpointer data;
5766 XEvent *xev = (XEvent *) gxev;
5768 if (current_count >= 0)
5770 struct x_display_info *dpyinfo;
5772 dpyinfo = x_display_info_for_display (xev->xany.display);
5774 #ifdef HAVE_X_I18N
5775 /* Filter events for the current X input method.
5776 GTK calls XFilterEvent but not for key press and release,
5777 so we do it here. */
5778 if (xev->type == KeyPress || xev->type == KeyRelease)
5779 if (dpyinfo && x_filter_event (dpyinfo, xev))
5780 return GDK_FILTER_REMOVE;
5781 #endif
5783 if (! dpyinfo)
5784 current_finish = X_EVENT_NORMAL;
5785 else
5787 current_count +=
5788 handle_one_xevent (dpyinfo, xev, &current_finish,
5789 current_hold_quit);
5792 else
5793 current_finish = x_dispatch_event (xev, xev->xany.display);
5795 if (current_finish == X_EVENT_GOTO_OUT || current_finish == X_EVENT_DROP)
5796 return GDK_FILTER_REMOVE;
5798 return GDK_FILTER_CONTINUE;
5800 #endif /* USE_GTK */
5803 /* Handles the XEvent EVENT on display DPYINFO.
5805 *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
5806 *FINISH is zero if caller should continue reading events.
5807 *FINISH is X_EVENT_DROP if event should not be passed to the toolkit.
5809 We return the number of characters stored into the buffer. */
5811 static int
5812 handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
5813 struct x_display_info *dpyinfo;
5814 XEvent *eventp;
5815 int *finish;
5816 struct input_event *hold_quit;
5818 union {
5819 struct input_event ie;
5820 struct selection_input_event sie;
5821 } inev;
5822 int count = 0;
5823 int do_help = 0;
5824 int nbytes = 0;
5825 struct frame *f = NULL;
5826 struct coding_system coding;
5827 XEvent event = *eventp;
5829 *finish = X_EVENT_NORMAL;
5831 EVENT_INIT (inev.ie);
5832 inev.ie.kind = NO_EVENT;
5833 inev.ie.arg = Qnil;
5835 switch (event.type)
5837 case ClientMessage:
5839 if (event.xclient.message_type
5840 == dpyinfo->Xatom_wm_protocols
5841 && event.xclient.format == 32)
5843 if (event.xclient.data.l[0]
5844 == dpyinfo->Xatom_wm_take_focus)
5846 /* Use x_any_window_to_frame because this
5847 could be the shell widget window
5848 if the frame has no title bar. */
5849 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
5850 #ifdef HAVE_X_I18N
5851 /* Not quite sure this is needed -pd */
5852 if (f && FRAME_XIC (f))
5853 XSetICFocus (FRAME_XIC (f));
5854 #endif
5855 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
5856 instructs the WM to set the input focus automatically for
5857 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
5858 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
5859 it has set the focus. So, XSetInputFocus below is not
5860 needed.
5862 The call to XSetInputFocus below has also caused trouble. In
5863 cases where the XSetInputFocus done by the WM and the one
5864 below are temporally close (on a fast machine), the call
5865 below can generate additional FocusIn events which confuse
5866 Emacs. */
5868 /* Since we set WM_TAKE_FOCUS, we must call
5869 XSetInputFocus explicitly. But not if f is null,
5870 since that might be an event for a deleted frame. */
5871 if (f)
5873 Display *d = event.xclient.display;
5874 /* Catch and ignore errors, in case window has been
5875 iconified by a window manager such as GWM. */
5876 x_catch_errors (d);
5877 XSetInputFocus (d, event.xclient.window,
5878 /* The ICCCM says this is
5879 the only valid choice. */
5880 RevertToParent,
5881 event.xclient.data.l[1]);
5882 /* This is needed to detect the error
5883 if there is an error. */
5884 XSync (d, False);
5885 x_uncatch_errors ();
5887 /* Not certain about handling scroll bars here */
5888 #endif /* 0 */
5889 goto done;
5892 if (event.xclient.data.l[0]
5893 == dpyinfo->Xatom_wm_save_yourself)
5895 /* Save state modify the WM_COMMAND property to
5896 something which can reinstate us. This notifies
5897 the session manager, who's looking for such a
5898 PropertyNotify. Can restart processing when
5899 a keyboard or mouse event arrives. */
5900 /* If we have a session manager, don't set this.
5901 KDE will then start two Emacsen, one for the
5902 session manager and one for this. */
5903 #ifdef HAVE_X_SM
5904 if (! x_session_have_connection ())
5905 #endif
5907 f = x_top_window_to_frame (dpyinfo,
5908 event.xclient.window);
5909 /* This is just so we only give real data once
5910 for a single Emacs process. */
5911 if (f == SELECTED_FRAME ())
5912 XSetCommand (FRAME_X_DISPLAY (f),
5913 event.xclient.window,
5914 initial_argv, initial_argc);
5915 else if (f)
5916 XSetCommand (FRAME_X_DISPLAY (f),
5917 event.xclient.window,
5918 0, 0);
5920 goto done;
5923 if (event.xclient.data.l[0]
5924 == dpyinfo->Xatom_wm_delete_window)
5926 f = x_any_window_to_frame (dpyinfo,
5927 event.xclient.window);
5928 if (!f)
5929 goto OTHER; /* May be a dialog that is to be removed */
5931 inev.ie.kind = DELETE_WINDOW_EVENT;
5932 XSETFRAME (inev.ie.frame_or_window, f);
5933 goto done;
5936 goto done;
5939 if (event.xclient.message_type
5940 == dpyinfo->Xatom_wm_configure_denied)
5942 goto done;
5945 if (event.xclient.message_type
5946 == dpyinfo->Xatom_wm_window_moved)
5948 int new_x, new_y;
5949 f = x_window_to_frame (dpyinfo, event.xclient.window);
5951 new_x = event.xclient.data.s[0];
5952 new_y = event.xclient.data.s[1];
5954 if (f)
5956 f->left_pos = new_x;
5957 f->top_pos = new_y;
5959 goto done;
5962 #ifdef HACK_EDITRES
5963 if (event.xclient.message_type
5964 == dpyinfo->Xatom_editres)
5966 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
5967 if (f)
5968 _XEditResCheckMessages (f->output_data.x->widget, NULL,
5969 &event, NULL);
5970 goto done;
5972 #endif /* HACK_EDITRES */
5974 if ((event.xclient.message_type
5975 == dpyinfo->Xatom_DONE)
5976 || (event.xclient.message_type
5977 == dpyinfo->Xatom_PAGE))
5979 /* Ghostview job completed. Kill it. We could
5980 reply with "Next" if we received "Page", but we
5981 currently never do because we are interested in
5982 images, only, which should have 1 page. */
5983 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
5984 f = x_window_to_frame (dpyinfo, event.xclient.window);
5985 if (!f)
5986 goto OTHER;
5987 x_kill_gs_process (pixmap, f);
5988 expose_frame (f, 0, 0, 0, 0);
5989 goto done;
5992 #ifdef USE_TOOLKIT_SCROLL_BARS
5993 /* Scroll bar callbacks send a ClientMessage from which
5994 we construct an input_event. */
5995 if (event.xclient.message_type
5996 == dpyinfo->Xatom_Scrollbar)
5998 x_scroll_bar_to_input_event (&event, &inev.ie);
5999 *finish = X_EVENT_GOTO_OUT;
6000 goto done;
6002 #endif /* USE_TOOLKIT_SCROLL_BARS */
6004 /* XEmbed messages from the embedder (if any). */
6005 if (event.xclient.message_type
6006 == dpyinfo->Xatom_XEMBED)
6008 enum xembed_message msg = event.xclient.data.l[1];
6009 if (msg == XEMBED_FOCUS_IN || msg == XEMBED_FOCUS_OUT)
6010 x_detect_focus_change (dpyinfo, &event, &inev.ie);
6012 *finish = X_EVENT_GOTO_OUT;
6013 goto done;
6016 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
6017 if (!f)
6018 goto OTHER;
6019 if (x_handle_dnd_message (f, &event.xclient, dpyinfo, &inev.ie))
6020 *finish = X_EVENT_DROP;
6022 break;
6024 case SelectionNotify:
6025 last_user_time = event.xselection.time;
6026 #ifdef USE_X_TOOLKIT
6027 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
6028 goto OTHER;
6029 #endif /* not USE_X_TOOLKIT */
6030 x_handle_selection_notify (&event.xselection);
6031 break;
6033 case SelectionClear: /* Someone has grabbed ownership. */
6034 last_user_time = event.xselectionclear.time;
6035 #ifdef USE_X_TOOLKIT
6036 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
6037 goto OTHER;
6038 #endif /* USE_X_TOOLKIT */
6040 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
6042 inev.ie.kind = SELECTION_CLEAR_EVENT;
6043 SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display;
6044 SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
6045 SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
6046 inev.ie.frame_or_window = Qnil;
6048 break;
6050 case SelectionRequest: /* Someone wants our selection. */
6051 last_user_time = event.xselectionrequest.time;
6052 #ifdef USE_X_TOOLKIT
6053 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
6054 goto OTHER;
6055 #endif /* USE_X_TOOLKIT */
6057 XSelectionRequestEvent *eventp
6058 = (XSelectionRequestEvent *) &event;
6060 inev.ie.kind = SELECTION_REQUEST_EVENT;
6061 SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display;
6062 SELECTION_EVENT_REQUESTOR (&inev.sie) = eventp->requestor;
6063 SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
6064 SELECTION_EVENT_TARGET (&inev.sie) = eventp->target;
6065 SELECTION_EVENT_PROPERTY (&inev.sie) = eventp->property;
6066 SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
6067 inev.ie.frame_or_window = Qnil;
6069 break;
6071 case PropertyNotify:
6072 last_user_time = event.xproperty.time;
6073 #if 0 /* This is plain wrong. In the case that we are waiting for a
6074 PropertyNotify used as an ACK in incremental selection
6075 transfer, the property will be on the receiver's window. */
6076 #if defined USE_X_TOOLKIT
6077 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
6078 goto OTHER;
6079 #endif
6080 #endif
6081 x_handle_property_notify (&event.xproperty);
6082 goto OTHER;
6084 case ReparentNotify:
6085 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
6086 if (f)
6088 int x, y;
6089 f->output_data.x->parent_desc = event.xreparent.parent;
6090 x_real_positions (f, &x, &y);
6091 f->left_pos = x;
6092 f->top_pos = y;
6094 /* Perhaps reparented due to a WM restart. Reset this. */
6095 FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN;
6096 FRAME_X_DISPLAY_INFO (f)->net_supported_window = 0;
6098 goto OTHER;
6100 case Expose:
6101 f = x_window_to_frame (dpyinfo, event.xexpose.window);
6102 if (f)
6104 x_check_fullscreen (f);
6106 #ifdef USE_GTK
6107 /* This seems to be needed for GTK 2.6. */
6108 x_clear_area (event.xexpose.display,
6109 event.xexpose.window,
6110 event.xexpose.x, event.xexpose.y,
6111 event.xexpose.width, event.xexpose.height,
6112 FALSE);
6113 #endif
6114 if (f->async_visible == 0)
6116 f->async_visible = 1;
6117 f->async_iconified = 0;
6118 f->output_data.x->has_been_visible = 1;
6119 SET_FRAME_GARBAGED (f);
6121 else
6122 expose_frame (f,
6123 event.xexpose.x, event.xexpose.y,
6124 event.xexpose.width, event.xexpose.height);
6126 else
6128 #ifndef USE_TOOLKIT_SCROLL_BARS
6129 struct scroll_bar *bar;
6130 #endif
6131 #if defined USE_LUCID
6132 /* Submenus of the Lucid menu bar aren't widgets
6133 themselves, so there's no way to dispatch events
6134 to them. Recognize this case separately. */
6136 Widget widget
6137 = x_window_to_menu_bar (event.xexpose.window);
6138 if (widget)
6139 xlwmenu_redisplay (widget);
6141 #endif /* USE_LUCID */
6143 #ifdef USE_TOOLKIT_SCROLL_BARS
6144 /* Dispatch event to the widget. */
6145 goto OTHER;
6146 #else /* not USE_TOOLKIT_SCROLL_BARS */
6147 bar = x_window_to_scroll_bar (event.xexpose.display,
6148 event.xexpose.window);
6150 if (bar)
6151 x_scroll_bar_expose (bar, &event);
6152 #ifdef USE_X_TOOLKIT
6153 else
6154 goto OTHER;
6155 #endif /* USE_X_TOOLKIT */
6156 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6158 break;
6160 case GraphicsExpose: /* This occurs when an XCopyArea's
6161 source area was obscured or not
6162 available. */
6163 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
6164 if (f)
6166 expose_frame (f,
6167 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
6168 event.xgraphicsexpose.width,
6169 event.xgraphicsexpose.height);
6171 #ifdef USE_X_TOOLKIT
6172 else
6173 goto OTHER;
6174 #endif /* USE_X_TOOLKIT */
6175 break;
6177 case NoExpose: /* This occurs when an XCopyArea's
6178 source area was completely
6179 available. */
6180 break;
6182 case UnmapNotify:
6183 /* Redo the mouse-highlight after the tooltip has gone. */
6184 if (event.xmap.window == tip_window)
6186 tip_window = 0;
6187 redo_mouse_highlight ();
6190 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
6191 if (f) /* F may no longer exist if
6192 the frame was deleted. */
6194 /* While a frame is unmapped, display generation is
6195 disabled; you don't want to spend time updating a
6196 display that won't ever be seen. */
6197 f->async_visible = 0;
6198 /* We can't distinguish, from the event, whether the window
6199 has become iconified or invisible. So assume, if it
6200 was previously visible, than now it is iconified.
6201 But x_make_frame_invisible clears both
6202 the visible flag and the iconified flag;
6203 and that way, we know the window is not iconified now. */
6204 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
6206 f->async_iconified = 1;
6208 inev.ie.kind = ICONIFY_EVENT;
6209 XSETFRAME (inev.ie.frame_or_window, f);
6212 goto OTHER;
6214 case MapNotify:
6215 if (event.xmap.window == tip_window)
6216 /* The tooltip has been drawn already. Avoid
6217 the SET_FRAME_GARBAGED below. */
6218 goto OTHER;
6220 /* We use x_top_window_to_frame because map events can
6221 come for sub-windows and they don't mean that the
6222 frame is visible. */
6223 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
6224 if (f)
6226 /* wait_reading_process_output will notice this and update
6227 the frame's display structures.
6228 If we where iconified, we should not set garbaged,
6229 because that stops redrawing on Expose events. This looks
6230 bad if we are called from a recursive event loop
6231 (x_dispatch_event), for example when a dialog is up. */
6232 if (! f->async_iconified)
6233 SET_FRAME_GARBAGED (f);
6235 f->async_visible = 1;
6236 f->async_iconified = 0;
6237 f->output_data.x->has_been_visible = 1;
6239 if (f->iconified)
6241 inev.ie.kind = DEICONIFY_EVENT;
6242 XSETFRAME (inev.ie.frame_or_window, f);
6244 else if (! NILP (Vframe_list)
6245 && ! NILP (XCDR (Vframe_list)))
6246 /* Force a redisplay sooner or later
6247 to update the frame titles
6248 in case this is the second frame. */
6249 record_asynch_buffer_change ();
6251 goto OTHER;
6253 case KeyPress:
6255 last_user_time = event.xkey.time;
6256 ignore_next_mouse_click_timeout = 0;
6258 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6259 /* Dispatch KeyPress events when in menu. */
6260 if (popup_activated ())
6261 goto OTHER;
6262 #endif
6264 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
6266 /* If mouse-highlight is an integer, input clears out
6267 mouse highlighting. */
6268 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
6269 && (f == 0
6270 || !EQ (f->tool_bar_window, dpyinfo->mouse_face_window)))
6272 clear_mouse_face (dpyinfo);
6273 dpyinfo->mouse_face_hidden = 1;
6276 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
6277 if (f == 0)
6279 /* Scroll bars consume key events, but we want
6280 the keys to go to the scroll bar's frame. */
6281 Widget widget = XtWindowToWidget (dpyinfo->display,
6282 event.xkey.window);
6283 if (widget && XmIsScrollBar (widget))
6285 widget = XtParent (widget);
6286 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
6289 #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
6291 if (f != 0)
6293 KeySym keysym, orig_keysym;
6294 /* al%imercury@uunet.uu.net says that making this 81
6295 instead of 80 fixed a bug whereby meta chars made
6296 his Emacs hang.
6298 It seems that some version of XmbLookupString has
6299 a bug of not returning XBufferOverflow in
6300 status_return even if the input is too long to
6301 fit in 81 bytes. So, we must prepare sufficient
6302 bytes for copy_buffer. 513 bytes (256 chars for
6303 two-byte character set) seems to be a fairly good
6304 approximation. -- 2000.8.10 handa@etl.go.jp */
6305 unsigned char copy_buffer[513];
6306 unsigned char *copy_bufptr = copy_buffer;
6307 int copy_bufsiz = sizeof (copy_buffer);
6308 int modifiers;
6309 Lisp_Object coding_system = Qlatin_1;
6310 Lisp_Object c;
6312 #ifdef USE_GTK
6313 /* Don't pass keys to GTK. A Tab will shift focus to the
6314 tool bar in GTK 2.4. Keys will still go to menus and
6315 dialogs because in that case popup_activated is TRUE
6316 (see above). */
6317 *finish = X_EVENT_DROP;
6318 #endif
6320 event.xkey.state
6321 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
6322 extra_keyboard_modifiers);
6323 modifiers = event.xkey.state;
6325 /* This will have to go some day... */
6327 /* make_lispy_event turns chars into control chars.
6328 Don't do it here because XLookupString is too eager. */
6329 event.xkey.state &= ~ControlMask;
6330 event.xkey.state &= ~(dpyinfo->meta_mod_mask
6331 | dpyinfo->super_mod_mask
6332 | dpyinfo->hyper_mod_mask
6333 | dpyinfo->alt_mod_mask);
6335 /* In case Meta is ComposeCharacter,
6336 clear its status. According to Markus Ehrnsperger
6337 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
6338 this enables ComposeCharacter to work whether or
6339 not it is combined with Meta. */
6340 if (modifiers & dpyinfo->meta_mod_mask)
6341 bzero (&compose_status, sizeof (compose_status));
6343 #ifdef HAVE_X_I18N
6344 if (FRAME_XIC (f))
6346 Status status_return;
6348 coding_system = Vlocale_coding_system;
6349 nbytes = XmbLookupString (FRAME_XIC (f),
6350 &event.xkey, copy_bufptr,
6351 copy_bufsiz, &keysym,
6352 &status_return);
6353 if (status_return == XBufferOverflow)
6355 copy_bufsiz = nbytes + 1;
6356 copy_bufptr = (unsigned char *) alloca (copy_bufsiz);
6357 nbytes = XmbLookupString (FRAME_XIC (f),
6358 &event.xkey, copy_bufptr,
6359 copy_bufsiz, &keysym,
6360 &status_return);
6362 /* Xutf8LookupString is a new but already deprecated interface. -stef */
6363 #if 0 && defined X_HAVE_UTF8_STRING
6364 else if (status_return == XLookupKeySym)
6365 { /* Try again but with utf-8. */
6366 coding_system = Qutf_8;
6367 nbytes = Xutf8LookupString (FRAME_XIC (f),
6368 &event.xkey, copy_bufptr,
6369 copy_bufsiz, &keysym,
6370 &status_return);
6371 if (status_return == XBufferOverflow)
6373 copy_bufsiz = nbytes + 1;
6374 copy_bufptr = (unsigned char *) alloca (copy_bufsiz);
6375 nbytes = Xutf8LookupString (FRAME_XIC (f),
6376 &event.xkey,
6377 copy_bufptr,
6378 copy_bufsiz, &keysym,
6379 &status_return);
6382 #endif
6384 if (status_return == XLookupNone)
6385 break;
6386 else if (status_return == XLookupChars)
6388 keysym = NoSymbol;
6389 modifiers = 0;
6391 else if (status_return != XLookupKeySym
6392 && status_return != XLookupBoth)
6393 abort ();
6395 else
6396 nbytes = XLookupString (&event.xkey, copy_bufptr,
6397 copy_bufsiz, &keysym,
6398 &compose_status);
6399 #else
6400 nbytes = XLookupString (&event.xkey, copy_bufptr,
6401 copy_bufsiz, &keysym,
6402 &compose_status);
6403 #endif
6405 /* If not using XIM/XIC, and a compose sequence is in progress,
6406 we break here. Otherwise, chars_matched is always 0. */
6407 if (compose_status.chars_matched > 0 && nbytes == 0)
6408 break;
6410 bzero (&compose_status, sizeof (compose_status));
6411 orig_keysym = keysym;
6413 /* Common for all keysym input events. */
6414 XSETFRAME (inev.ie.frame_or_window, f);
6415 inev.ie.modifiers
6416 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), modifiers);
6417 inev.ie.timestamp = event.xkey.time;
6419 /* First deal with keysyms which have defined
6420 translations to characters. */
6421 if (keysym >= 32 && keysym < 128)
6422 /* Avoid explicitly decoding each ASCII character. */
6424 inev.ie.kind = ASCII_KEYSTROKE_EVENT;
6425 inev.ie.code = keysym;
6426 goto done_keysym;
6429 /* Keysyms directly mapped to Unicode characters. */
6430 if (keysym >= 0x01000000 && keysym <= 0x0110FFFF)
6432 if (keysym < 0x01000080)
6433 inev.ie.kind = ASCII_KEYSTROKE_EVENT;
6434 else
6435 inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
6436 inev.ie.code = keysym & 0xFFFFFF;
6437 goto done_keysym;
6440 /* Now non-ASCII. */
6441 if (HASH_TABLE_P (Vx_keysym_table)
6442 && (NATNUMP (c = Fgethash (make_number (keysym),
6443 Vx_keysym_table,
6444 Qnil))))
6446 inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
6447 ? ASCII_KEYSTROKE_EVENT
6448 : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
6449 inev.ie.code = XFASTINT (c);
6450 goto done_keysym;
6453 /* Random non-modifier sorts of keysyms. */
6454 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
6455 || keysym == XK_Delete
6456 #ifdef XK_ISO_Left_Tab
6457 || (keysym >= XK_ISO_Left_Tab
6458 && keysym <= XK_ISO_Enter)
6459 #endif
6460 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
6461 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
6462 #ifdef HPUX
6463 /* This recognizes the "extended function
6464 keys". It seems there's no cleaner way.
6465 Test IsModifierKey to avoid handling
6466 mode_switch incorrectly. */
6467 || ((unsigned) (keysym) >= XK_Select
6468 && (unsigned)(keysym) < XK_KP_Space)
6469 #endif
6470 #ifdef XK_dead_circumflex
6471 || orig_keysym == XK_dead_circumflex
6472 #endif
6473 #ifdef XK_dead_grave
6474 || orig_keysym == XK_dead_grave
6475 #endif
6476 #ifdef XK_dead_tilde
6477 || orig_keysym == XK_dead_tilde
6478 #endif
6479 #ifdef XK_dead_diaeresis
6480 || orig_keysym == XK_dead_diaeresis
6481 #endif
6482 #ifdef XK_dead_macron
6483 || orig_keysym == XK_dead_macron
6484 #endif
6485 #ifdef XK_dead_degree
6486 || orig_keysym == XK_dead_degree
6487 #endif
6488 #ifdef XK_dead_acute
6489 || orig_keysym == XK_dead_acute
6490 #endif
6491 #ifdef XK_dead_cedilla
6492 || orig_keysym == XK_dead_cedilla
6493 #endif
6494 #ifdef XK_dead_breve
6495 || orig_keysym == XK_dead_breve
6496 #endif
6497 #ifdef XK_dead_ogonek
6498 || orig_keysym == XK_dead_ogonek
6499 #endif
6500 #ifdef XK_dead_caron
6501 || orig_keysym == XK_dead_caron
6502 #endif
6503 #ifdef XK_dead_doubleacute
6504 || orig_keysym == XK_dead_doubleacute
6505 #endif
6506 #ifdef XK_dead_abovedot
6507 || orig_keysym == XK_dead_abovedot
6508 #endif
6509 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
6510 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
6511 /* Any "vendor-specific" key is ok. */
6512 || (orig_keysym & (1 << 28))
6513 || (keysym != NoSymbol && nbytes == 0))
6514 && ! (IsModifierKey (orig_keysym)
6515 /* The symbols from XK_ISO_Lock
6516 to XK_ISO_Last_Group_Lock
6517 don't have real modifiers but
6518 should be treated similarly to
6519 Mode_switch by Emacs. */
6520 #if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
6521 || ((unsigned)(orig_keysym)
6522 >= XK_ISO_Lock
6523 && (unsigned)(orig_keysym)
6524 <= XK_ISO_Last_Group_Lock)
6525 #endif
6528 STORE_KEYSYM_FOR_DEBUG (keysym);
6529 /* make_lispy_event will convert this to a symbolic
6530 key. */
6531 inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
6532 inev.ie.code = keysym;
6533 goto done_keysym;
6536 { /* Raw bytes, not keysym. */
6537 register int i;
6538 register int c;
6539 int nchars, len;
6541 for (i = 0, nchars = 0; i < nbytes; i++)
6543 if (ASCII_BYTE_P (copy_bufptr[i]))
6544 nchars++;
6545 STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]);
6548 if (nchars < nbytes)
6550 /* Decode the input data. */
6551 int require;
6552 unsigned char *p;
6554 /* The input should be decoded with `coding_system'
6555 which depends on which X*LookupString function
6556 we used just above and the locale. */
6557 setup_coding_system (coding_system, &coding);
6558 coding.src_multibyte = 0;
6559 coding.dst_multibyte = 1;
6560 /* The input is converted to events, thus we can't
6561 handle composition. Anyway, there's no XIM that
6562 gives us composition information. */
6563 coding.common_flags &= ~CODING_ANNOTATION_MASK;
6565 require = MAX_MULTIBYTE_LENGTH * nbytes;
6566 coding.destination = alloca (require);
6567 coding.dst_bytes = require;
6568 coding.mode |= CODING_MODE_LAST_BLOCK;
6569 decode_coding_c_string (&coding, copy_bufptr, nbytes, Qnil);
6570 nbytes = coding.produced;
6571 nchars = coding.produced_char;
6572 copy_bufptr = coding.destination;
6575 /* Convert the input data to a sequence of
6576 character events. */
6577 for (i = 0; i < nbytes; i += len)
6579 if (nchars == nbytes)
6580 c = copy_bufptr[i], len = 1;
6581 else
6582 c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
6583 nbytes - i, len);
6584 inev.ie.kind = (SINGLE_BYTE_CHAR_P (c)
6585 ? ASCII_KEYSTROKE_EVENT
6586 : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
6587 inev.ie.code = c;
6588 kbd_buffer_store_event_hold (&inev.ie, hold_quit);
6591 count += nchars;
6593 inev.ie.kind = NO_EVENT; /* Already stored above. */
6595 if (keysym == NoSymbol)
6596 break;
6599 done_keysym:
6600 #ifdef HAVE_X_I18N
6601 /* Don't dispatch this event since XtDispatchEvent calls
6602 XFilterEvent, and two calls in a row may freeze the
6603 client. */
6604 break;
6605 #else
6606 goto OTHER;
6607 #endif
6609 case KeyRelease:
6610 last_user_time = event.xkey.time;
6611 #ifdef HAVE_X_I18N
6612 /* Don't dispatch this event since XtDispatchEvent calls
6613 XFilterEvent, and two calls in a row may freeze the
6614 client. */
6615 break;
6616 #else
6617 goto OTHER;
6618 #endif
6620 case EnterNotify:
6621 last_user_time = event.xcrossing.time;
6622 x_detect_focus_change (dpyinfo, &event, &inev.ie);
6624 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
6626 if (f && x_mouse_click_focus_ignore_position)
6627 ignore_next_mouse_click_timeout = event.xmotion.time + 200;
6629 #if 0
6630 if (event.xcrossing.focus)
6632 /* Avoid nasty pop/raise loops. */
6633 if (f && (!(f->auto_raise)
6634 || !(f->auto_lower)
6635 || (event.xcrossing.time - enter_timestamp) > 500))
6637 x_new_focus_frame (dpyinfo, f);
6638 enter_timestamp = event.xcrossing.time;
6641 else if (f == dpyinfo->x_focus_frame)
6642 x_new_focus_frame (dpyinfo, 0);
6643 #endif
6645 /* EnterNotify counts as mouse movement,
6646 so update things that depend on mouse position. */
6647 if (f && !f->output_data.x->hourglass_p)
6648 note_mouse_movement (f, &event.xmotion);
6649 #ifdef USE_GTK
6650 /* We may get an EnterNotify on the buttons in the toolbar. In that
6651 case we moved out of any highlighted area and need to note this. */
6652 if (!f && last_mouse_glyph_frame)
6653 note_mouse_movement (last_mouse_glyph_frame, &event.xmotion);
6654 #endif
6655 goto OTHER;
6657 case FocusIn:
6658 x_detect_focus_change (dpyinfo, &event, &inev.ie);
6659 goto OTHER;
6661 case LeaveNotify:
6662 last_user_time = event.xcrossing.time;
6663 x_detect_focus_change (dpyinfo, &event, &inev.ie);
6665 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
6666 if (f)
6668 if (f == dpyinfo->mouse_face_mouse_frame)
6670 /* If we move outside the frame, then we're
6671 certainly no longer on any text in the frame. */
6672 clear_mouse_face (dpyinfo);
6673 dpyinfo->mouse_face_mouse_frame = 0;
6676 /* Generate a nil HELP_EVENT to cancel a help-echo.
6677 Do it only if there's something to cancel.
6678 Otherwise, the startup message is cleared when
6679 the mouse leaves the frame. */
6680 if (any_help_event_p)
6681 do_help = -1;
6683 #ifdef USE_GTK
6684 /* See comment in EnterNotify above */
6685 else if (last_mouse_glyph_frame)
6686 note_mouse_movement (last_mouse_glyph_frame, &event.xmotion);
6687 #endif
6688 goto OTHER;
6690 case FocusOut:
6691 x_detect_focus_change (dpyinfo, &event, &inev.ie);
6692 goto OTHER;
6694 case MotionNotify:
6696 last_user_time = event.xmotion.time;
6697 previous_help_echo_string = help_echo_string;
6698 help_echo_string = Qnil;
6700 if (dpyinfo->grabbed && last_mouse_frame
6701 && FRAME_LIVE_P (last_mouse_frame))
6702 f = last_mouse_frame;
6703 else
6704 f = x_window_to_frame (dpyinfo, event.xmotion.window);
6706 if (dpyinfo->mouse_face_hidden)
6708 dpyinfo->mouse_face_hidden = 0;
6709 clear_mouse_face (dpyinfo);
6712 if (f)
6715 /* Generate SELECT_WINDOW_EVENTs when needed. */
6716 if (!NILP (Vmouse_autoselect_window))
6718 Lisp_Object window;
6720 window = window_from_coordinates (f,
6721 event.xmotion.x, event.xmotion.y,
6722 0, 0, 0, 0);
6724 /* Window will be selected only when it is not selected now and
6725 last mouse movement event was not in it. Minibuffer window
6726 will be selected only when it is active. */
6727 if (WINDOWP (window)
6728 && !EQ (window, last_window)
6729 && !EQ (window, selected_window)
6730 /* For click-to-focus window managers
6731 create event iff we don't leave the
6732 selected frame. */
6733 && (focus_follows_mouse
6734 || (EQ (XWINDOW (window)->frame,
6735 XWINDOW (selected_window)->frame))))
6737 inev.ie.kind = SELECT_WINDOW_EVENT;
6738 inev.ie.frame_or_window = window;
6741 last_window=window;
6743 if (!note_mouse_movement (f, &event.xmotion))
6744 help_echo_string = previous_help_echo_string;
6746 else
6748 #ifndef USE_TOOLKIT_SCROLL_BARS
6749 struct scroll_bar *bar
6750 = x_window_to_scroll_bar (event.xmotion.display,
6751 event.xmotion.window);
6753 if (bar)
6754 x_scroll_bar_note_movement (bar, &event);
6755 #endif /* USE_TOOLKIT_SCROLL_BARS */
6757 /* If we move outside the frame, then we're
6758 certainly no longer on any text in the frame. */
6759 clear_mouse_face (dpyinfo);
6762 /* If the contents of the global variable help_echo_string
6763 has changed, generate a HELP_EVENT. */
6764 if (!NILP (help_echo_string)
6765 || !NILP (previous_help_echo_string))
6766 do_help = 1;
6767 goto OTHER;
6770 case ConfigureNotify:
6771 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
6772 #ifdef USE_GTK
6773 if (!f
6774 && (f = x_any_window_to_frame (dpyinfo, event.xconfigure.window))
6775 && event.xconfigure.window == FRAME_X_WINDOW (f))
6777 xg_frame_resized (f, event.xconfigure.width,
6778 event.xconfigure.height);
6779 f = 0;
6781 #endif
6782 if (f)
6784 #ifndef USE_X_TOOLKIT
6785 #ifndef USE_GTK
6786 /* If there is a pending resize for fullscreen, don't
6787 do this one, the right one will come later.
6788 The toolkit version doesn't seem to need this, but we
6789 need to reset it below. */
6790 int dont_resize
6791 = ((f->want_fullscreen & FULLSCREEN_WAIT)
6792 && f->new_text_cols != 0);
6793 int rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, event.xconfigure.height);
6794 int columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, event.xconfigure.width);
6796 if (dont_resize)
6797 goto OTHER;
6799 /* In the toolkit version, change_frame_size
6800 is called by the code that handles resizing
6801 of the EmacsFrame widget. */
6803 /* Even if the number of character rows and columns has
6804 not changed, the font size may have changed, so we need
6805 to check the pixel dimensions as well. */
6806 if (columns != FRAME_COLS (f)
6807 || rows != FRAME_LINES (f)
6808 || event.xconfigure.width != FRAME_PIXEL_WIDTH (f)
6809 || event.xconfigure.height != FRAME_PIXEL_HEIGHT (f))
6811 change_frame_size (f, rows, columns, 0, 1, 0);
6812 SET_FRAME_GARBAGED (f);
6813 cancel_mouse_face (f);
6816 FRAME_PIXEL_WIDTH (f) = event.xconfigure.width;
6817 FRAME_PIXEL_HEIGHT (f) = event.xconfigure.height;
6818 #endif /* not USE_GTK */
6819 #endif
6821 #ifdef USE_GTK
6822 /* GTK creates windows but doesn't map them.
6823 Only get real positions and check fullscreen when mapped. */
6824 if (FRAME_GTK_OUTER_WIDGET (f)
6825 && GTK_WIDGET_MAPPED (FRAME_GTK_OUTER_WIDGET (f)))
6826 #endif
6828 x_real_positions (f, &f->left_pos, &f->top_pos);
6830 if (f->want_fullscreen & FULLSCREEN_WAIT)
6831 f->want_fullscreen &= ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
6834 #ifdef HAVE_X_I18N
6835 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
6836 xic_set_statusarea (f);
6837 #endif
6839 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
6841 /* Since the WM decorations come below top_pos now,
6842 we must put them below top_pos in the future. */
6843 f->win_gravity = NorthWestGravity;
6844 x_wm_set_size_hint (f, (long) 0, 0);
6847 goto OTHER;
6849 case ButtonRelease:
6850 case ButtonPress:
6852 /* If we decide we want to generate an event to be seen
6853 by the rest of Emacs, we put it here. */
6854 int tool_bar_p = 0;
6856 bzero (&compose_status, sizeof (compose_status));
6857 last_mouse_glyph_frame = 0;
6858 last_user_time = event.xbutton.time;
6860 if (dpyinfo->grabbed
6861 && last_mouse_frame
6862 && FRAME_LIVE_P (last_mouse_frame))
6863 f = last_mouse_frame;
6864 else
6865 f = x_window_to_frame (dpyinfo, event.xbutton.window);
6867 if (f)
6869 /* Is this in the tool-bar? */
6870 if (WINDOWP (f->tool_bar_window)
6871 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
6873 Lisp_Object window;
6874 int x = event.xbutton.x;
6875 int y = event.xbutton.y;
6877 window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
6878 tool_bar_p = EQ (window, f->tool_bar_window);
6880 if (tool_bar_p && event.xbutton.button < 4)
6882 handle_tool_bar_click (f, x, y,
6883 event.xbutton.type == ButtonPress,
6884 x_x_to_emacs_modifiers (dpyinfo,
6885 event.xbutton.state));
6889 if (!tool_bar_p)
6890 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6891 if (! popup_activated ())
6892 #endif
6894 if (ignore_next_mouse_click_timeout)
6896 if (event.type == ButtonPress
6897 && (int)(event.xbutton.time - ignore_next_mouse_click_timeout) > 0)
6899 ignore_next_mouse_click_timeout = 0;
6900 construct_mouse_click (&inev.ie, &event.xbutton, f);
6902 if (event.type == ButtonRelease)
6903 ignore_next_mouse_click_timeout = 0;
6905 else
6906 construct_mouse_click (&inev.ie, &event.xbutton, f);
6908 if (FRAME_X_EMBEDDED_P (f))
6909 xembed_send_message (f, event.xbutton.time,
6910 XEMBED_REQUEST_FOCUS, 0, 0, 0);
6912 else
6914 struct scroll_bar *bar
6915 = x_window_to_scroll_bar (event.xbutton.display,
6916 event.xbutton.window);
6918 #ifdef USE_TOOLKIT_SCROLL_BARS
6919 /* Make the "Ctrl-Mouse-2 splits window" work for toolkit
6920 scroll bars. */
6921 if (bar && event.xbutton.state & ControlMask)
6923 x_scroll_bar_handle_click (bar, &event, &inev.ie);
6924 *finish = X_EVENT_DROP;
6926 #else /* not USE_TOOLKIT_SCROLL_BARS */
6927 if (bar)
6928 x_scroll_bar_handle_click (bar, &event, &inev.ie);
6929 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6932 if (event.type == ButtonPress)
6934 dpyinfo->grabbed |= (1 << event.xbutton.button);
6935 last_mouse_frame = f;
6937 if (!tool_bar_p)
6938 last_tool_bar_item = -1;
6940 else
6941 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
6943 /* Ignore any mouse motion that happened before this event;
6944 any subsequent mouse-movement Emacs events should reflect
6945 only motion after the ButtonPress/Release. */
6946 if (f != 0)
6947 f->mouse_moved = 0;
6949 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6950 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
6951 /* For a down-event in the menu bar,
6952 don't pass it to Xt right now.
6953 Instead, save it away
6954 and we will pass it to Xt from kbd_buffer_get_event.
6955 That way, we can run some Lisp code first. */
6956 if (
6957 #ifdef USE_GTK
6958 ! popup_activated ()
6959 /* Gtk+ menus only react to the first three buttons. */
6960 && event.xbutton.button < 3
6962 #endif
6963 f && event.type == ButtonPress
6964 /* Verify the event is really within the menu bar
6965 and not just sent to it due to grabbing. */
6966 && event.xbutton.x >= 0
6967 && event.xbutton.x < FRAME_PIXEL_WIDTH (f)
6968 && event.xbutton.y >= 0
6969 && event.xbutton.y < f->output_data.x->menubar_height
6970 && event.xbutton.same_screen)
6972 SET_SAVED_BUTTON_EVENT;
6973 XSETFRAME (last_mouse_press_frame, f);
6974 #ifdef USE_GTK
6975 *finish = X_EVENT_DROP;
6976 #endif
6978 else if (event.type == ButtonPress)
6980 last_mouse_press_frame = Qnil;
6981 goto OTHER;
6984 #ifdef USE_MOTIF /* This should do not harm for Lucid,
6985 but I am trying to be cautious. */
6986 else if (event.type == ButtonRelease)
6988 if (!NILP (last_mouse_press_frame))
6990 f = XFRAME (last_mouse_press_frame);
6991 if (f->output_data.x)
6992 SET_SAVED_BUTTON_EVENT;
6994 else
6995 goto OTHER;
6997 #endif /* USE_MOTIF */
6998 else
6999 goto OTHER;
7000 #endif /* USE_X_TOOLKIT || USE_GTK */
7002 break;
7004 case CirculateNotify:
7005 goto OTHER;
7007 case CirculateRequest:
7008 goto OTHER;
7010 case VisibilityNotify:
7011 goto OTHER;
7013 case MappingNotify:
7014 /* Someone has changed the keyboard mapping - update the
7015 local cache. */
7016 switch (event.xmapping.request)
7018 case MappingModifier:
7019 x_find_modifier_meanings (dpyinfo);
7020 /* This is meant to fall through. */
7021 case MappingKeyboard:
7022 XRefreshKeyboardMapping (&event.xmapping);
7024 goto OTHER;
7026 default:
7027 OTHER:
7028 #ifdef USE_X_TOOLKIT
7029 BLOCK_INPUT;
7030 if (*finish != X_EVENT_DROP)
7031 XtDispatchEvent (&event);
7032 UNBLOCK_INPUT;
7033 #endif /* USE_X_TOOLKIT */
7034 break;
7037 done:
7038 if (inev.ie.kind != NO_EVENT)
7040 kbd_buffer_store_event_hold (&inev.ie, hold_quit);
7041 count++;
7044 if (do_help
7045 && !(hold_quit && hold_quit->kind != NO_EVENT))
7047 Lisp_Object frame;
7049 if (f)
7050 XSETFRAME (frame, f);
7051 else
7052 frame = Qnil;
7054 if (do_help > 0)
7056 any_help_event_p = 1;
7057 gen_help_event (help_echo_string, frame, help_echo_window,
7058 help_echo_object, help_echo_pos);
7060 else
7062 help_echo_string = Qnil;
7063 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
7065 count++;
7068 *eventp = event;
7069 return count;
7073 /* Handles the XEvent EVENT on display DISPLAY.
7074 This is used for event loops outside the normal event handling,
7075 i.e. looping while a popup menu or a dialog is posted.
7077 Returns the value handle_one_xevent sets in the finish argument. */
7079 x_dispatch_event (event, display)
7080 XEvent *event;
7081 Display *display;
7083 struct x_display_info *dpyinfo;
7084 int finish = X_EVENT_NORMAL;
7086 dpyinfo = x_display_info_for_display (display);
7088 if (dpyinfo)
7089 handle_one_xevent (dpyinfo, event, &finish, 0);
7091 return finish;
7095 /* Read events coming from the X server.
7096 This routine is called by the SIGIO handler.
7097 We return as soon as there are no more events to be read.
7099 We return the number of characters stored into the buffer,
7100 thus pretending to be `read' (except the characters we store
7101 in the keyboard buffer can be multibyte, so are not necessarily
7102 C chars).
7104 EXPECTED is nonzero if the caller knows input is available. */
7106 static int
7107 XTread_socket (terminal, expected, hold_quit)
7108 struct terminal *terminal;
7109 int expected;
7110 struct input_event *hold_quit;
7112 int count = 0;
7113 XEvent event;
7114 int event_found = 0;
7115 #if 0
7116 struct x_display_info *dpyinfo;
7117 #endif
7119 if (interrupt_input_blocked)
7121 interrupt_input_pending = 1;
7122 return -1;
7125 interrupt_input_pending = 0;
7126 BLOCK_INPUT;
7128 /* So people can tell when we have read the available input. */
7129 input_signal_count++;
7131 ++handling_signal;
7133 #ifdef HAVE_X_SM
7134 /* Only check session manager input for the primary display. */
7135 if (terminal->id == 1 && x_session_have_connection ())
7137 struct input_event inev;
7138 BLOCK_INPUT;
7139 /* We don't need to EVENT_INIT (inev) here, as
7140 x_session_check_input copies an entire input_event. */
7141 if (x_session_check_input (&inev))
7143 kbd_buffer_store_event_hold (&inev, hold_quit);
7144 count++;
7146 UNBLOCK_INPUT;
7148 #endif
7150 /* For debugging, this gives a way to fake an I/O error. */
7151 if (terminal->display_info.x == XTread_socket_fake_io_error)
7153 XTread_socket_fake_io_error = 0;
7154 x_io_error_quitter (terminal->display_info.x->display);
7157 #if 0 /* This loop is a noop now. */
7158 /* Find the display we are supposed to read input for.
7159 It's the one communicating on descriptor SD. */
7160 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
7162 #if 0 /* This ought to be unnecessary; let's verify it. */
7163 #ifdef FIOSNBIO
7164 /* If available, Xlib uses FIOSNBIO to make the socket
7165 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
7166 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
7167 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
7168 fcntl (dpyinfo->connection, F_SETFL, 0);
7169 #endif /* ! defined (FIOSNBIO) */
7170 #endif
7172 #if 0 /* This code can't be made to work, with multiple displays,
7173 and appears not to be used on any system any more.
7174 Also keyboard.c doesn't turn O_NDELAY on and off
7175 for X connections. */
7176 #ifndef SIGIO
7177 #ifndef HAVE_SELECT
7178 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
7180 extern int read_alarm_should_throw;
7181 read_alarm_should_throw = 1;
7182 XPeekEvent (dpyinfo->display, &event);
7183 read_alarm_should_throw = 0;
7185 #endif /* HAVE_SELECT */
7186 #endif /* SIGIO */
7187 #endif
7189 #endif
7191 #ifndef USE_GTK
7192 while (XPending (terminal->display_info.x->display))
7194 int finish;
7196 XNextEvent (terminal->display_info.x->display, &event);
7198 #ifdef HAVE_X_I18N
7199 /* Filter events for the current X input method. */
7200 if (x_filter_event (terminal->display_info.x, &event))
7201 break;
7202 #endif
7203 event_found = 1;
7205 count += handle_one_xevent (terminal->display_info.x,
7206 &event, &finish, hold_quit);
7208 if (finish == X_EVENT_GOTO_OUT)
7209 goto out;
7212 #else /* USE_GTK */
7214 /* For GTK we must use the GTK event loop. But XEvents gets passed
7215 to our filter function above, and then to the big event switch.
7216 We use a bunch of globals to communicate with our filter function,
7217 that is kind of ugly, but it works.
7219 There is no way to do one display at the time, GTK just does events
7220 from all displays. */
7222 while (gtk_events_pending ())
7224 current_count = count;
7225 current_hold_quit = hold_quit;
7227 gtk_main_iteration ();
7229 count = current_count;
7230 current_count = -1;
7231 current_hold_quit = 0;
7233 if (current_finish == X_EVENT_GOTO_OUT)
7234 break;
7236 #endif /* USE_GTK */
7238 out:;
7240 /* On some systems, an X bug causes Emacs to get no more events
7241 when the window is destroyed. Detect that. (1994.) */
7242 if (! event_found)
7244 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
7245 One XNOOP in 100 loops will make Emacs terminate.
7246 B. Bretthauer, 1994 */
7247 x_noop_count++;
7248 if (x_noop_count >= 100)
7250 x_noop_count=0;
7252 if (next_noop_dpyinfo == 0)
7253 next_noop_dpyinfo = x_display_list;
7255 XNoOp (next_noop_dpyinfo->display);
7257 /* Each time we get here, cycle through the displays now open. */
7258 next_noop_dpyinfo = next_noop_dpyinfo->next;
7262 /* If the focus was just given to an auto-raising frame,
7263 raise it now. */
7264 /* ??? This ought to be able to handle more than one such frame. */
7265 if (pending_autoraise_frame)
7267 x_raise_frame (pending_autoraise_frame);
7268 pending_autoraise_frame = 0;
7271 --handling_signal;
7272 UNBLOCK_INPUT;
7274 return count;
7280 /***********************************************************************
7281 Text Cursor
7282 ***********************************************************************/
7284 /* Set clipping for output in glyph row ROW. W is the window in which
7285 we operate. GC is the graphics context to set clipping in.
7287 ROW may be a text row or, e.g., a mode line. Text rows must be
7288 clipped to the interior of the window dedicated to text display,
7289 mode lines must be clipped to the whole window. */
7291 static void
7292 x_clip_to_row (w, row, area, gc)
7293 struct window *w;
7294 struct glyph_row *row;
7295 int area;
7296 GC gc;
7298 struct frame *f = XFRAME (WINDOW_FRAME (w));
7299 XRectangle clip_rect;
7300 int window_x, window_y, window_width;
7302 window_box (w, area, &window_x, &window_y, &window_width, 0);
7304 clip_rect.x = window_x;
7305 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y));
7306 clip_rect.y = max (clip_rect.y, window_y);
7307 clip_rect.width = window_width;
7308 clip_rect.height = row->visible_height;
7310 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
7314 /* Draw a hollow box cursor on window W in glyph row ROW. */
7316 static void
7317 x_draw_hollow_cursor (w, row)
7318 struct window *w;
7319 struct glyph_row *row;
7321 struct frame *f = XFRAME (WINDOW_FRAME (w));
7322 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7323 Display *dpy = FRAME_X_DISPLAY (f);
7324 int x, y, wd, h;
7325 XGCValues xgcv;
7326 struct glyph *cursor_glyph;
7327 GC gc;
7329 /* Get the glyph the cursor is on. If we can't tell because
7330 the current matrix is invalid or such, give up. */
7331 cursor_glyph = get_phys_cursor_glyph (w);
7332 if (cursor_glyph == NULL)
7333 return;
7335 /* Compute frame-relative coordinates for phys cursor. */
7336 get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h);
7337 wd = w->phys_cursor_width;
7339 /* The foreground of cursor_gc is typically the same as the normal
7340 background color, which can cause the cursor box to be invisible. */
7341 xgcv.foreground = f->output_data.x->cursor_pixel;
7342 if (dpyinfo->scratch_cursor_gc)
7343 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
7344 else
7345 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
7346 GCForeground, &xgcv);
7347 gc = dpyinfo->scratch_cursor_gc;
7349 /* Set clipping, draw the rectangle, and reset clipping again. */
7350 x_clip_to_row (w, row, TEXT_AREA, gc);
7351 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h - 1);
7352 XSetClipMask (dpy, gc, None);
7356 /* Draw a bar cursor on window W in glyph row ROW.
7358 Implementation note: One would like to draw a bar cursor with an
7359 angle equal to the one given by the font property XA_ITALIC_ANGLE.
7360 Unfortunately, I didn't find a font yet that has this property set.
7361 --gerd. */
7363 static void
7364 x_draw_bar_cursor (w, row, width, kind)
7365 struct window *w;
7366 struct glyph_row *row;
7367 int width;
7368 enum text_cursor_kinds kind;
7370 struct frame *f = XFRAME (w->frame);
7371 struct glyph *cursor_glyph;
7373 /* If cursor is out of bounds, don't draw garbage. This can happen
7374 in mini-buffer windows when switching between echo area glyphs
7375 and mini-buffer. */
7376 cursor_glyph = get_phys_cursor_glyph (w);
7377 if (cursor_glyph == NULL)
7378 return;
7380 /* If on an image, draw like a normal cursor. That's usually better
7381 visible than drawing a bar, esp. if the image is large so that
7382 the bar might not be in the window. */
7383 if (cursor_glyph->type == IMAGE_GLYPH)
7385 struct glyph_row *row;
7386 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
7387 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
7389 else
7391 Display *dpy = FRAME_X_DISPLAY (f);
7392 Window window = FRAME_X_WINDOW (f);
7393 GC gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
7394 unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures;
7395 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
7396 XGCValues xgcv;
7398 /* If the glyph's background equals the color we normally draw
7399 the bar cursor in, the bar cursor in its normal color is
7400 invisible. Use the glyph's foreground color instead in this
7401 case, on the assumption that the glyph's colors are chosen so
7402 that the glyph is legible. */
7403 if (face->background == f->output_data.x->cursor_pixel)
7404 xgcv.background = xgcv.foreground = face->foreground;
7405 else
7406 xgcv.background = xgcv.foreground = f->output_data.x->cursor_pixel;
7407 xgcv.graphics_exposures = 0;
7409 if (gc)
7410 XChangeGC (dpy, gc, mask, &xgcv);
7411 else
7413 gc = XCreateGC (dpy, window, mask, &xgcv);
7414 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
7417 if (width < 0)
7418 width = FRAME_CURSOR_WIDTH (f);
7419 width = min (cursor_glyph->pixel_width, width);
7421 w->phys_cursor_width = width;
7422 x_clip_to_row (w, row, TEXT_AREA, gc);
7424 if (kind == BAR_CURSOR)
7425 XFillRectangle (dpy, window, gc,
7426 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
7427 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
7428 width, row->height);
7429 else
7430 XFillRectangle (dpy, window, gc,
7431 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
7432 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
7433 row->height - width),
7434 cursor_glyph->pixel_width,
7435 width);
7437 XSetClipMask (dpy, gc, None);
7442 /* RIF: Define cursor CURSOR on frame F. */
7444 static void
7445 x_define_frame_cursor (f, cursor)
7446 struct frame *f;
7447 Cursor cursor;
7449 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
7453 /* RIF: Clear area on frame F. */
7455 static void
7456 x_clear_frame_area (f, x, y, width, height)
7457 struct frame *f;
7458 int x, y, width, height;
7460 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7461 x, y, width, height, False);
7465 /* RIF: Draw cursor on window W. */
7467 static void
7468 x_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
7469 struct window *w;
7470 struct glyph_row *glyph_row;
7471 int x, y;
7472 int cursor_type, cursor_width;
7473 int on_p, active_p;
7475 struct frame *f = XFRAME (WINDOW_FRAME (w));
7477 if (on_p)
7479 w->phys_cursor_type = cursor_type;
7480 w->phys_cursor_on_p = 1;
7482 if (glyph_row->exact_window_width_line_p
7483 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
7485 glyph_row->cursor_in_fringe_p = 1;
7486 draw_fringe_bitmap (w, glyph_row, 0);
7488 else
7489 switch (cursor_type)
7491 case HOLLOW_BOX_CURSOR:
7492 x_draw_hollow_cursor (w, glyph_row);
7493 break;
7495 case FILLED_BOX_CURSOR:
7496 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
7497 break;
7499 case BAR_CURSOR:
7500 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
7501 break;
7503 case HBAR_CURSOR:
7504 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
7505 break;
7507 case NO_CURSOR:
7508 w->phys_cursor_width = 0;
7509 break;
7511 default:
7512 abort ();
7515 #ifdef HAVE_X_I18N
7516 if (w == XWINDOW (f->selected_window))
7517 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
7518 xic_set_preeditarea (w, x, y);
7519 #endif
7522 #ifndef XFlush
7523 XFlush (FRAME_X_DISPLAY (f));
7524 #endif
7528 /* Icons. */
7530 /* Make the x-window of frame F use the gnu icon bitmap. */
7533 x_bitmap_icon (f, file)
7534 struct frame *f;
7535 Lisp_Object file;
7537 int bitmap_id;
7539 if (FRAME_X_WINDOW (f) == 0)
7540 return 1;
7542 /* Free up our existing icon bitmap and mask if any. */
7543 if (f->output_data.x->icon_bitmap > 0)
7544 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
7545 f->output_data.x->icon_bitmap = 0;
7547 if (STRINGP (file))
7549 #ifdef USE_GTK
7550 /* Use gtk_window_set_icon_from_file () if available,
7551 It's not restricted to bitmaps */
7552 if (xg_set_icon (f, file))
7553 return 0;
7554 #endif /* USE_GTK */
7555 bitmap_id = x_create_bitmap_from_file (f, file);
7556 x_create_bitmap_mask (f, bitmap_id);
7558 else
7560 /* Create the GNU bitmap and mask if necessary. */
7561 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
7563 int rc = -1;
7565 #if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
7566 #ifdef USE_GTK
7567 if (xg_set_icon_from_xpm_data (f, gnu_xpm_bits))
7568 return 0;
7569 #else
7570 rc = x_create_bitmap_from_xpm_data (f, gnu_xpm_bits);
7571 if (rc != -1)
7572 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id = rc;
7573 #endif /* USE_GTK */
7574 #endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
7576 /* If all else fails, use the (black and white) xbm image. */
7577 if (rc == -1)
7579 rc = x_create_bitmap_from_data (f, gnu_xbm_bits,
7580 gnu_xbm_width, gnu_xbm_height);
7581 if (rc == -1)
7582 return 1;
7584 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id = rc;
7585 x_create_bitmap_mask (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
7589 /* The first time we create the GNU bitmap and mask,
7590 this increments the ref-count one extra time.
7591 As a result, the GNU bitmap and mask are never freed.
7592 That way, we don't have to worry about allocating it again. */
7593 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
7595 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
7598 x_wm_set_icon_pixmap (f, bitmap_id);
7599 f->output_data.x->icon_bitmap = bitmap_id;
7601 return 0;
7605 /* Make the x-window of frame F use a rectangle with text.
7606 Use ICON_NAME as the text. */
7609 x_text_icon (f, icon_name)
7610 struct frame *f;
7611 char *icon_name;
7613 if (FRAME_X_WINDOW (f) == 0)
7614 return 1;
7617 XTextProperty text;
7618 text.value = (unsigned char *) icon_name;
7619 text.encoding = XA_STRING;
7620 text.format = 8;
7621 text.nitems = strlen (icon_name);
7622 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text);
7625 if (f->output_data.x->icon_bitmap > 0)
7626 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
7627 f->output_data.x->icon_bitmap = 0;
7628 x_wm_set_icon_pixmap (f, 0);
7630 return 0;
7633 #define X_ERROR_MESSAGE_SIZE 200
7635 /* If non-nil, this should be a string.
7636 It means catch X errors and store the error message in this string.
7638 The reason we use a stack is that x_catch_error/x_uncatch_error can
7639 be called from a signal handler.
7642 struct x_error_message_stack {
7643 char string[X_ERROR_MESSAGE_SIZE];
7644 Display *dpy;
7645 struct x_error_message_stack *prev;
7647 static struct x_error_message_stack *x_error_message;
7649 /* An X error handler which stores the error message in
7650 *x_error_message. This is called from x_error_handler if
7651 x_catch_errors is in effect. */
7653 static void
7654 x_error_catcher (display, error)
7655 Display *display;
7656 XErrorEvent *error;
7658 XGetErrorText (display, error->error_code,
7659 x_error_message->string,
7660 X_ERROR_MESSAGE_SIZE);
7663 /* Begin trapping X errors for display DPY. Actually we trap X errors
7664 for all displays, but DPY should be the display you are actually
7665 operating on.
7667 After calling this function, X protocol errors no longer cause
7668 Emacs to exit; instead, they are recorded in the string
7669 stored in *x_error_message.
7671 Calling x_check_errors signals an Emacs error if an X error has
7672 occurred since the last call to x_catch_errors or x_check_errors.
7674 Calling x_uncatch_errors resumes the normal error handling. */
7676 void x_check_errors ();
7678 void
7679 x_catch_errors (dpy)
7680 Display *dpy;
7682 struct x_error_message_stack *data = xmalloc (sizeof (*data));
7684 /* Make sure any errors from previous requests have been dealt with. */
7685 XSync (dpy, False);
7687 data->dpy = dpy;
7688 data->string[0] = 0;
7689 data->prev = x_error_message;
7690 x_error_message = data;
7693 /* Undo the last x_catch_errors call.
7694 DPY should be the display that was passed to x_catch_errors. */
7696 void
7697 x_uncatch_errors ()
7699 struct x_error_message_stack *tmp;
7701 BLOCK_INPUT;
7703 /* The display may have been closed before this function is called.
7704 Check if it is still open before calling XSync. */
7705 if (x_display_info_for_display (x_error_message->dpy) != 0)
7706 XSync (x_error_message->dpy, False);
7708 tmp = x_error_message;
7709 x_error_message = x_error_message->prev;
7710 xfree (tmp);
7711 UNBLOCK_INPUT;
7714 /* If any X protocol errors have arrived since the last call to
7715 x_catch_errors or x_check_errors, signal an Emacs error using
7716 sprintf (a buffer, FORMAT, the x error message text) as the text. */
7718 void
7719 x_check_errors (dpy, format)
7720 Display *dpy;
7721 char *format;
7723 /* Make sure to catch any errors incurred so far. */
7724 XSync (dpy, False);
7726 if (x_error_message->string[0])
7728 char string[X_ERROR_MESSAGE_SIZE];
7729 bcopy (x_error_message->string, string, X_ERROR_MESSAGE_SIZE);
7730 x_uncatch_errors ();
7731 error (format, string);
7735 /* Nonzero if we had any X protocol errors
7736 since we did x_catch_errors on DPY. */
7739 x_had_errors_p (dpy)
7740 Display *dpy;
7742 /* Make sure to catch any errors incurred so far. */
7743 XSync (dpy, False);
7745 return x_error_message->string[0] != 0;
7748 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
7750 void
7751 x_clear_errors (dpy)
7752 Display *dpy;
7754 x_error_message->string[0] = 0;
7757 #if 0 /* See comment in unwind_to_catch why calling this is a bad
7758 * idea. --lorentey */
7759 /* Close off all unclosed x_catch_errors calls. */
7761 void
7762 x_fully_uncatch_errors ()
7764 while (x_error_message)
7765 x_uncatch_errors ();
7767 #endif
7769 /* Nonzero if x_catch_errors has been done and not yet canceled. */
7772 x_catching_errors ()
7774 return x_error_message != 0;
7777 #if 0
7778 static unsigned int x_wire_count;
7779 x_trace_wire ()
7781 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
7783 #endif /* ! 0 */
7786 /* Handle SIGPIPE, which can happen when the connection to a server
7787 simply goes away. SIGPIPE is handled by x_connection_signal.
7788 Don't need to do anything, because the write which caused the
7789 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
7790 which will do the appropriate cleanup for us. */
7792 static SIGTYPE
7793 x_connection_signal (signalnum) /* If we don't have an argument, */
7794 int signalnum; /* some compilers complain in signal calls. */
7796 #ifdef USG
7797 /* USG systems forget handlers when they are used;
7798 must reestablish each time */
7799 signal (signalnum, x_connection_signal);
7800 #endif /* USG */
7804 /************************************************************************
7805 Handling X errors
7806 ************************************************************************/
7808 /* Error message passed to x_connection_closed. */
7810 static char *error_msg;
7812 /* Function installed as fatal_error_signal_hook in
7813 x_connection_closed. Print the X error message, and exit normally,
7814 instead of dumping core when XtCloseDisplay fails. */
7816 static void
7817 x_fatal_error_signal ()
7819 fprintf (stderr, "%s\n", error_msg);
7820 exit (70);
7823 /* Handle the loss of connection to display DPY. ERROR_MESSAGE is
7824 the text of an error message that lead to the connection loss. */
7826 static SIGTYPE
7827 x_connection_closed (dpy, error_message)
7828 Display *dpy;
7829 char *error_message;
7831 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
7832 Lisp_Object frame, tail;
7833 int index = SPECPDL_INDEX ();
7835 error_msg = (char *) alloca (strlen (error_message) + 1);
7836 strcpy (error_msg, error_message);
7837 handling_signal = 0;
7839 /* Prevent being called recursively because of an error condition
7840 below. Otherwise, we might end up with printing ``can't find per
7841 display information'' in the recursive call instead of printing
7842 the original message here. */
7843 x_catch_errors (dpy);
7845 /* Inhibit redisplay while frames are being deleted. */
7846 specbind (Qinhibit_redisplay, Qt);
7848 if (dpyinfo)
7850 /* Protect display from being closed when we delete the last
7851 frame on it. */
7852 dpyinfo->reference_count++;
7853 dpyinfo->terminal->reference_count++;
7856 /* First delete frames whose mini-buffers are on frames
7857 that are on the dead display. */
7858 FOR_EACH_FRAME (tail, frame)
7860 Lisp_Object minibuf_frame;
7861 minibuf_frame
7862 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
7863 if (FRAME_X_P (XFRAME (frame))
7864 && FRAME_X_P (XFRAME (minibuf_frame))
7865 && ! EQ (frame, minibuf_frame)
7866 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
7867 Fdelete_frame (frame, Qnoelisp);
7870 /* Now delete all remaining frames on the dead display.
7871 We are now sure none of these is used as the mini-buffer
7872 for another frame that we need to delete. */
7873 FOR_EACH_FRAME (tail, frame)
7874 if (FRAME_X_P (XFRAME (frame))
7875 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
7877 /* Set this to t so that Fdelete_frame won't get confused
7878 trying to find a replacement. */
7879 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
7880 Fdelete_frame (frame, Qnoelisp);
7883 /* We have to close the display to inform Xt that it doesn't
7884 exist anymore. If we don't, Xt will continue to wait for
7885 events from the display. As a consequence, a sequence of
7887 M-x make-frame-on-display RET :1 RET
7888 ...kill the new frame, so that we get an IO error...
7889 M-x make-frame-on-display RET :1 RET
7891 will indefinitely wait in Xt for events for display `:1', opened
7892 in the first call to make-frame-on-display.
7894 Closing the display is reported to lead to a bus error on
7895 OpenWindows in certain situations. I suspect that is a bug
7896 in OpenWindows. I don't know how to circumvent it here. */
7898 if (dpyinfo)
7900 #ifdef USE_X_TOOLKIT
7901 /* If DPYINFO is null, this means we didn't open the display
7902 in the first place, so don't try to close it. */
7904 extern void (*fatal_error_signal_hook) P_ ((void));
7905 fatal_error_signal_hook = x_fatal_error_signal;
7906 XtCloseDisplay (dpy);
7907 fatal_error_signal_hook = NULL;
7909 #endif
7911 #ifdef USE_GTK
7912 /* Due to bugs in some Gtk+ versions, just exit here if this
7913 is the last display/terminal. */
7914 if (terminal_list->next_terminal == NULL)
7916 fprintf (stderr, "%s\n", error_msg);
7917 shut_down_emacs (0, 0, Qnil);
7918 exit (70);
7920 xg_display_close (dpyinfo->display);
7921 #endif
7923 /* Indicate that this display is dead. */
7924 dpyinfo->display = 0;
7926 dpyinfo->reference_count--;
7927 dpyinfo->terminal->reference_count--;
7928 if (dpyinfo->reference_count != 0)
7929 /* We have just closed all frames on this display. */
7930 abort ();
7933 Lisp_Object tmp;
7934 XSETTERMINAL (tmp, dpyinfo->terminal);
7935 Fdelete_terminal (tmp, Qnoelisp);
7939 x_uncatch_errors ();
7941 if (terminal_list == 0)
7943 fprintf (stderr, "%s\n", error_msg);
7944 shut_down_emacs (0, 0, Qnil);
7945 exit (70);
7948 /* Ordinary stack unwind doesn't deal with these. */
7949 #ifdef SIGIO
7950 sigunblock (sigmask (SIGIO));
7951 #endif
7952 sigunblock (sigmask (SIGALRM));
7953 TOTALLY_UNBLOCK_INPUT;
7955 unbind_to (index, Qnil);
7956 clear_waiting_for_input ();
7957 /* Here, we absolutely have to use a non-local exit (e.g. signal, throw,
7958 longjmp), because returning from this function would get us back into
7959 Xlib's code which will directly call `exit'. */
7960 error ("%s", error_msg);
7963 /* We specifically use it before defining it, so that gcc doesn't inline it,
7964 otherwise gdb doesn't know how to properly put a breakpoint on it. */
7965 static void x_error_quitter P_ ((Display *, XErrorEvent *));
7967 /* This is the first-level handler for X protocol errors.
7968 It calls x_error_quitter or x_error_catcher. */
7970 static int
7971 x_error_handler (display, error)
7972 Display *display;
7973 XErrorEvent *error;
7975 if (x_error_message)
7976 x_error_catcher (display, error);
7977 else
7978 x_error_quitter (display, error);
7979 return 0;
7982 /* This is the usual handler for X protocol errors.
7983 It kills all frames on the display that we got the error for.
7984 If that was the only one, it prints an error message and kills Emacs. */
7986 /* .gdbinit puts a breakpoint here, so make sure it is not inlined. */
7988 #if __GNUC__ >= 3 /* On GCC 3.0 we might get a warning. */
7989 #define NO_INLINE __attribute__((noinline))
7990 #else
7991 #define NO_INLINE
7992 #endif
7994 /* Some versions of GNU/Linux define noinline in their headers. */
7996 #ifdef noinline
7997 #undef noinline
7998 #endif
8000 /* On older GCC versions, just putting x_error_quitter
8001 after x_error_handler prevents inlining into the former. */
8003 static void NO_INLINE
8004 x_error_quitter (display, error)
8005 Display *display;
8006 XErrorEvent *error;
8008 char buf[256], buf1[356];
8010 /* Ignore BadName errors. They can happen because of fonts
8011 or colors that are not defined. */
8013 if (error->error_code == BadName)
8014 return;
8016 /* Note that there is no real way portable across R3/R4 to get the
8017 original error handler. */
8019 XGetErrorText (display, error->error_code, buf, sizeof (buf));
8020 sprintf (buf1, "X protocol error: %s on protocol request %d",
8021 buf, error->request_code);
8022 x_connection_closed (display, buf1);
8026 /* This is the handler for X IO errors, always.
8027 It kills all frames on the display that we lost touch with.
8028 If that was the only one, it prints an error message and kills Emacs. */
8030 static int
8031 x_io_error_quitter (display)
8032 Display *display;
8034 char buf[256];
8036 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
8037 x_connection_closed (display, buf);
8038 return 0;
8041 /* Changing the font of the frame. */
8043 /* Give frame F the font FONT-OBJECT as its default font. The return
8044 value is FONT-OBJECT. FONTSET is an ID of the fontset for the
8045 frame. If it is negative, generate a new fontset from
8046 FONT-OBJECT. */
8048 Lisp_Object
8049 x_new_font (f, font_object, fontset)
8050 struct frame *f;
8051 Lisp_Object font_object;
8052 int fontset;
8054 struct font *font = XFONT_OBJECT (font_object);
8056 if (fontset < 0)
8057 fontset = fontset_from_font (font_object);
8058 FRAME_FONTSET (f) = fontset;
8059 if (FRAME_FONT (f) == font)
8060 /* This font is already set in frame F. There's nothing more to
8061 do. */
8062 return font_object;
8064 FRAME_FONT (f) = font;
8065 FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
8066 FRAME_COLUMN_WIDTH (f) = font->average_width;
8067 FRAME_SPACE_WIDTH (f) = font->space_width;
8068 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (font);
8070 compute_fringe_widths (f, 1);
8072 /* Compute the scroll bar width in character columns. */
8073 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
8075 int wid = FRAME_COLUMN_WIDTH (f);
8076 FRAME_CONFIG_SCROLL_BAR_COLS (f)
8077 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
8079 else
8081 int wid = FRAME_COLUMN_WIDTH (f);
8082 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
8085 if (FRAME_X_WINDOW (f) != 0)
8087 /* Don't change the size of a tip frame; there's no point in
8088 doing it because it's done in Fx_show_tip, and it leads to
8089 problems because the tip frame has no widget. */
8090 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
8091 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
8094 #ifdef HAVE_X_I18N
8095 if (FRAME_XIC (f)
8096 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
8098 BLOCK_INPUT;
8099 xic_set_xfontset (f, SDATA (fontset_ascii (fontset)));
8100 UNBLOCK_INPUT;
8102 #endif
8104 return font_object;
8108 /***********************************************************************
8109 X Input Methods
8110 ***********************************************************************/
8112 #ifdef HAVE_X_I18N
8114 #ifdef HAVE_X11R6
8116 /* XIM destroy callback function, which is called whenever the
8117 connection to input method XIM dies. CLIENT_DATA contains a
8118 pointer to the x_display_info structure corresponding to XIM. */
8120 static void
8121 xim_destroy_callback (xim, client_data, call_data)
8122 XIM xim;
8123 XPointer client_data;
8124 XPointer call_data;
8126 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
8127 Lisp_Object frame, tail;
8129 BLOCK_INPUT;
8131 /* No need to call XDestroyIC.. */
8132 FOR_EACH_FRAME (tail, frame)
8134 struct frame *f = XFRAME (frame);
8135 if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo)
8137 FRAME_XIC (f) = NULL;
8138 xic_free_xfontset (f);
8142 /* No need to call XCloseIM. */
8143 dpyinfo->xim = NULL;
8144 XFree (dpyinfo->xim_styles);
8145 UNBLOCK_INPUT;
8148 #endif /* HAVE_X11R6 */
8150 #ifdef HAVE_X11R6
8151 /* This isn't prototyped in OSF 5.0 or 5.1a. */
8152 extern char *XSetIMValues P_ ((XIM, ...));
8153 #endif
8155 /* Open the connection to the XIM server on display DPYINFO.
8156 RESOURCE_NAME is the resource name Emacs uses. */
8158 static void
8159 xim_open_dpy (dpyinfo, resource_name)
8160 struct x_display_info *dpyinfo;
8161 char *resource_name;
8163 XIM xim;
8165 #ifdef HAVE_XIM
8166 if (use_xim)
8168 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name,
8169 EMACS_CLASS);
8170 dpyinfo->xim = xim;
8172 if (xim)
8174 #ifdef HAVE_X11R6
8175 XIMCallback destroy;
8176 #endif
8178 /* Get supported styles and XIM values. */
8179 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
8181 #ifdef HAVE_X11R6
8182 destroy.callback = xim_destroy_callback;
8183 destroy.client_data = (XPointer)dpyinfo;
8184 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
8185 #endif
8189 else
8190 #endif /* HAVE_XIM */
8191 dpyinfo->xim = NULL;
8195 #ifdef HAVE_X11R6_XIM
8197 struct xim_inst_t
8199 struct x_display_info *dpyinfo;
8200 char *resource_name;
8203 /* XIM instantiate callback function, which is called whenever an XIM
8204 server is available. DISPLAY is the display of the XIM.
8205 CLIENT_DATA contains a pointer to an xim_inst_t structure created
8206 when the callback was registered. */
8208 static void
8209 xim_instantiate_callback (display, client_data, call_data)
8210 Display *display;
8211 XPointer client_data;
8212 XPointer call_data;
8214 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
8215 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
8217 /* We don't support multiple XIM connections. */
8218 if (dpyinfo->xim)
8219 return;
8221 xim_open_dpy (dpyinfo, xim_inst->resource_name);
8223 /* Create XIC for the existing frames on the same display, as long
8224 as they have no XIC. */
8225 if (dpyinfo->xim && dpyinfo->reference_count > 0)
8227 Lisp_Object tail, frame;
8229 BLOCK_INPUT;
8230 FOR_EACH_FRAME (tail, frame)
8232 struct frame *f = XFRAME (frame);
8234 if (FRAME_X_P (f)
8235 && FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
8236 if (FRAME_XIC (f) == NULL)
8238 create_frame_xic (f);
8239 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
8240 xic_set_statusarea (f);
8241 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
8243 struct window *w = XWINDOW (f->selected_window);
8244 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
8249 UNBLOCK_INPUT;
8253 #endif /* HAVE_X11R6_XIM */
8256 /* Open a connection to the XIM server on display DPYINFO.
8257 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
8258 connection only at the first time. On X11R6, open the connection
8259 in the XIM instantiate callback function. */
8261 static void
8262 xim_initialize (dpyinfo, resource_name)
8263 struct x_display_info *dpyinfo;
8264 char *resource_name;
8266 #ifdef HAVE_XIM
8267 if (use_xim)
8269 #ifdef HAVE_X11R6_XIM
8270 struct xim_inst_t *xim_inst;
8271 int len;
8273 dpyinfo->xim = NULL;
8274 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
8275 xim_inst->dpyinfo = dpyinfo;
8276 len = strlen (resource_name);
8277 xim_inst->resource_name = (char *) xmalloc (len + 1);
8278 bcopy (resource_name, xim_inst->resource_name, len + 1);
8279 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
8280 resource_name, EMACS_CLASS,
8281 xim_instantiate_callback,
8282 /* This is XPointer in XFree86
8283 but (XPointer *) on Tru64, at
8284 least, hence the configure test. */
8285 (XRegisterIMInstantiateCallback_arg6) xim_inst);
8286 #else /* not HAVE_X11R6_XIM */
8287 dpyinfo->xim = NULL;
8288 xim_open_dpy (dpyinfo, resource_name);
8289 #endif /* not HAVE_X11R6_XIM */
8292 else
8293 #endif /* HAVE_XIM */
8294 dpyinfo->xim = NULL;
8298 /* Close the connection to the XIM server on display DPYINFO. */
8300 static void
8301 xim_close_dpy (dpyinfo)
8302 struct x_display_info *dpyinfo;
8304 #ifdef HAVE_XIM
8305 if (use_xim)
8307 #ifdef HAVE_X11R6_XIM
8308 if (dpyinfo->display)
8309 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
8310 NULL, EMACS_CLASS,
8311 xim_instantiate_callback, NULL);
8312 #endif /* not HAVE_X11R6_XIM */
8313 if (dpyinfo->display)
8314 XCloseIM (dpyinfo->xim);
8315 dpyinfo->xim = NULL;
8316 XFree (dpyinfo->xim_styles);
8318 #endif /* HAVE_XIM */
8321 #endif /* not HAVE_X11R6_XIM */
8325 /* Calculate the absolute position in frame F
8326 from its current recorded position values and gravity. */
8328 void
8329 x_calc_absolute_position (f)
8330 struct frame *f;
8332 int flags = f->size_hint_flags;
8334 /* We have nothing to do if the current position
8335 is already for the top-left corner. */
8336 if (! ((flags & XNegative) || (flags & YNegative)))
8337 return;
8339 /* Treat negative positions as relative to the leftmost bottommost
8340 position that fits on the screen. */
8341 if (flags & XNegative)
8342 f->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
8343 - FRAME_PIXEL_WIDTH (f) + f->left_pos);
8346 int height = FRAME_PIXEL_HEIGHT (f);
8348 #if defined USE_X_TOOLKIT && defined USE_MOTIF
8349 /* Something is fishy here. When using Motif, starting Emacs with
8350 `-g -0-0', the frame appears too low by a few pixels.
8352 This seems to be so because initially, while Emacs is starting,
8353 the column widget's height and the frame's pixel height are
8354 different. The column widget's height is the right one. In
8355 later invocations, when Emacs is up, the frame's pixel height
8356 is right, though.
8358 It's not obvious where the initial small difference comes from.
8359 2000-12-01, gerd. */
8361 XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
8362 #endif
8364 if (flags & YNegative)
8365 f->top_pos = (FRAME_X_DISPLAY_INFO (f)->height - height + f->top_pos);
8368 /* The left_pos and top_pos
8369 are now relative to the top and left screen edges,
8370 so the flags should correspond. */
8371 f->size_hint_flags &= ~ (XNegative | YNegative);
8374 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
8375 to really change the position, and 0 when calling from
8376 x_make_frame_visible (in that case, XOFF and YOFF are the current
8377 position values). It is -1 when calling from x_set_frame_parameters,
8378 which means, do adjust for borders but don't change the gravity. */
8380 void
8381 x_set_offset (f, xoff, yoff, change_gravity)
8382 struct frame *f;
8383 register int xoff, yoff;
8384 int change_gravity;
8386 int modified_top, modified_left;
8388 if (change_gravity > 0)
8390 FRAME_X_OUTPUT (f)->left_before_move = f->left_pos;
8391 FRAME_X_OUTPUT (f)->top_before_move = f->top_pos;
8393 f->top_pos = yoff;
8394 f->left_pos = xoff;
8395 f->size_hint_flags &= ~ (XNegative | YNegative);
8396 if (xoff < 0)
8397 f->size_hint_flags |= XNegative;
8398 if (yoff < 0)
8399 f->size_hint_flags |= YNegative;
8400 f->win_gravity = NorthWestGravity;
8402 x_calc_absolute_position (f);
8404 BLOCK_INPUT;
8405 x_wm_set_size_hint (f, (long) 0, 0);
8407 modified_left = f->left_pos;
8408 modified_top = f->top_pos;
8410 if (change_gravity != 0 && FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A)
8412 /* Some WMs (twm, wmaker at least) has an offset that is smaller
8413 than the WM decorations. So we use the calculated offset instead
8414 of the WM decoration sizes here (x/y_pixels_outer_diff). */
8415 modified_left += FRAME_X_OUTPUT (f)->move_offset_left;
8416 modified_top += FRAME_X_OUTPUT (f)->move_offset_top;
8419 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
8420 modified_left, modified_top);
8422 x_sync_with_move (f, f->left_pos, f->top_pos,
8423 FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
8424 ? 1 : 0);
8426 /* change_gravity is non-zero when this function is called from Lisp to
8427 programmatically move a frame. In that case, we call
8428 x_check_expected_move to discover if we have a "Type A" or "Type B"
8429 window manager, and, for a "Type A" window manager, adjust the position
8430 of the frame.
8432 We call x_check_expected_move if a programmatic move occurred, and
8433 either the window manager type (A/B) is unknown or it is Type A but we
8434 need to compute the top/left offset adjustment for this frame. */
8436 if (change_gravity != 0 &&
8437 (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
8438 || (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A
8439 && (FRAME_X_OUTPUT (f)->move_offset_left == 0
8440 && FRAME_X_OUTPUT (f)->move_offset_top == 0))))
8441 x_check_expected_move (f, modified_left, modified_top);
8443 UNBLOCK_INPUT;
8446 /* Return non-zero if _NET_SUPPORTING_WM_CHECK window exists and _NET_SUPPORTED
8447 on the root window for frame F contains ATOMNAME.
8448 This is how a WM check shall be done according to the Window Manager
8449 Specification/Extended Window Manager Hints at
8450 http://freedesktop.org/wiki/Specifications/wm-spec. */
8452 static int
8453 wm_supports (f, atomname)
8454 struct frame *f;
8455 const char *atomname;
8457 Atom actual_type;
8458 unsigned long actual_size, bytes_remaining;
8459 int i, rc, actual_format;
8460 Atom prop_atom;
8461 Window wmcheck_window;
8462 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8463 Window target_window = dpyinfo->root_window;
8464 long max_len = 65536;
8465 Display *dpy = FRAME_X_DISPLAY (f);
8466 unsigned char *tmp_data = NULL;
8467 Atom target_type = XA_WINDOW;
8468 Atom want_atom;
8470 BLOCK_INPUT;
8472 prop_atom = XInternAtom (dpy, "_NET_SUPPORTING_WM_CHECK", False);
8474 x_catch_errors (dpy);
8475 rc = XGetWindowProperty (dpy, target_window,
8476 prop_atom, 0, max_len, False, target_type,
8477 &actual_type, &actual_format, &actual_size,
8478 &bytes_remaining, &tmp_data);
8480 if (rc != Success || actual_type != XA_WINDOW || x_had_errors_p (dpy))
8482 if (tmp_data) XFree (tmp_data);
8483 x_uncatch_errors ();
8484 UNBLOCK_INPUT;
8485 return 0;
8488 wmcheck_window = *(Window *) tmp_data;
8489 XFree (tmp_data);
8491 /* Check if window exists. */
8492 XSelectInput (dpy, wmcheck_window, StructureNotifyMask);
8493 x_sync (f);
8494 if (x_had_errors_p (dpy))
8496 x_uncatch_errors ();
8497 UNBLOCK_INPUT;
8498 return 0;
8501 if (dpyinfo->net_supported_window != wmcheck_window)
8503 /* Window changed, reload atoms */
8504 if (dpyinfo->net_supported_atoms != NULL)
8505 XFree (dpyinfo->net_supported_atoms);
8506 dpyinfo->net_supported_atoms = NULL;
8507 dpyinfo->nr_net_supported_atoms = 0;
8508 dpyinfo->net_supported_window = 0;
8510 target_type = XA_ATOM;
8511 prop_atom = XInternAtom (dpy, "_NET_SUPPORTED", False);
8512 tmp_data = NULL;
8513 rc = XGetWindowProperty (dpy, target_window,
8514 prop_atom, 0, max_len, False, target_type,
8515 &actual_type, &actual_format, &actual_size,
8516 &bytes_remaining, &tmp_data);
8518 if (rc != Success || actual_type != XA_ATOM || x_had_errors_p (dpy))
8520 if (tmp_data) XFree (tmp_data);
8521 x_uncatch_errors ();
8522 UNBLOCK_INPUT;
8523 return 0;
8526 dpyinfo->net_supported_atoms = (Atom *)tmp_data;
8527 dpyinfo->nr_net_supported_atoms = actual_size;
8528 dpyinfo->net_supported_window = wmcheck_window;
8531 rc = 0;
8532 want_atom = XInternAtom (dpy, atomname, False);
8534 for (i = 0; rc == 0 && i < dpyinfo->nr_net_supported_atoms; ++i)
8535 rc = dpyinfo->net_supported_atoms[i] == want_atom;
8537 x_uncatch_errors ();
8538 UNBLOCK_INPUT;
8540 return rc;
8543 /* Do fullscreen as specified in extended window manager hints */
8545 static int
8546 do_ewmh_fullscreen (f)
8547 struct frame *f;
8549 int have_net_atom = wm_supports (f, "_NET_WM_STATE");
8551 /* Some window managers don't say they support _NET_WM_STATE, but they do say
8552 they support _NET_WM_STATE_FULLSCREEN. Try that also. */
8553 if (!have_net_atom)
8554 have_net_atom = wm_supports (f, "_NET_WM_STATE_FULLSCREEN");
8556 if (have_net_atom)
8558 Lisp_Object frame;
8559 const char *atom = "_NET_WM_STATE";
8560 const char *fs = "_NET_WM_STATE_FULLSCREEN";
8561 const char *fw = "_NET_WM_STATE_MAXIMIZED_HORZ";
8562 const char *fh = "_NET_WM_STATE_MAXIMIZED_VERT";
8563 const char *what = NULL;
8565 XSETFRAME (frame, f);
8567 /* If there are _NET_ atoms we assume we have extended window manager
8568 hints. */
8569 switch (f->want_fullscreen)
8571 case FULLSCREEN_BOTH:
8572 what = fs;
8573 break;
8574 case FULLSCREEN_WIDTH:
8575 what = fw;
8576 break;
8577 case FULLSCREEN_HEIGHT:
8578 what = fh;
8579 break;
8582 if (what != NULL && !wm_supports (f, what)) return 0;
8585 Fx_send_client_event (frame, make_number (0), frame,
8586 make_unibyte_string (atom, strlen (atom)),
8587 make_number (32),
8588 Fcons (make_number (0), /* Remove */
8589 Fcons
8590 (make_unibyte_string (fs,
8591 strlen (fs)),
8592 Qnil)));
8593 Fx_send_client_event (frame, make_number (0), frame,
8594 make_unibyte_string (atom, strlen (atom)),
8595 make_number (32),
8596 Fcons (make_number (0), /* Remove */
8597 Fcons
8598 (make_unibyte_string (fh,
8599 strlen (fh)),
8600 Qnil)));
8601 Fx_send_client_event (frame, make_number (0), frame,
8602 make_unibyte_string (atom, strlen (atom)),
8603 make_number (32),
8604 Fcons (make_number (0), /* Remove */
8605 Fcons
8606 (make_unibyte_string (fw,
8607 strlen (fw)),
8608 Qnil)));
8609 f->want_fullscreen = FULLSCREEN_NONE;
8610 if (what != NULL)
8611 Fx_send_client_event (frame, make_number (0), frame,
8612 make_unibyte_string (atom, strlen (atom)),
8613 make_number (32),
8614 Fcons (make_number (1), /* Add */
8615 Fcons
8616 (make_unibyte_string (what,
8617 strlen (what)),
8618 Qnil)));
8621 return have_net_atom;
8624 static void
8625 XTfullscreen_hook (f)
8626 FRAME_PTR f;
8628 if (f->async_visible)
8630 BLOCK_INPUT;
8631 do_ewmh_fullscreen (f);
8632 x_sync (f);
8633 UNBLOCK_INPUT;
8638 /* Check if we need to resize the frame due to a fullscreen request.
8639 If so needed, resize the frame. */
8640 static void
8641 x_check_fullscreen (f)
8642 struct frame *f;
8644 if (f->want_fullscreen & FULLSCREEN_BOTH)
8646 int width, height, ign;
8648 if (do_ewmh_fullscreen (f))
8649 return;
8651 x_real_positions (f, &f->left_pos, &f->top_pos);
8653 x_fullscreen_adjust (f, &width, &height, &ign, &ign);
8655 /* We do not need to move the window, it shall be taken care of
8656 when setting WM manager hints.
8657 If the frame is visible already, the position is checked by
8658 x_check_expected_move. */
8659 if (FRAME_COLS (f) != width || FRAME_LINES (f) != height)
8661 change_frame_size (f, height, width, 0, 1, 0);
8662 SET_FRAME_GARBAGED (f);
8663 cancel_mouse_face (f);
8665 /* Wait for the change of frame size to occur */
8666 f->want_fullscreen |= FULLSCREEN_WAIT;
8671 /* This function is called by x_set_offset to determine whether the window
8672 manager interfered with the positioning of the frame. Type A window
8673 managers position the surrounding window manager decorations a small
8674 amount above and left of the user-supplied position. Type B window
8675 managers position the surrounding window manager decorations at the
8676 user-specified position. If we detect a Type A window manager, we
8677 compensate by moving the window right and down by the proper amount. */
8679 static void
8680 x_check_expected_move (f, expected_left, expected_top)
8681 struct frame *f;
8682 int expected_left;
8683 int expected_top;
8685 int current_left = 0, current_top = 0;
8687 /* x_real_positions returns the left and top offsets of the outermost
8688 window manager window around the frame. */
8690 x_real_positions (f, &current_left, &current_top);
8692 if (current_left != expected_left || current_top != expected_top)
8694 /* It's a "Type A" window manager. */
8696 int adjusted_left;
8697 int adjusted_top;
8699 FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_A;
8700 FRAME_X_OUTPUT (f)->move_offset_left = expected_left - current_left;
8701 FRAME_X_OUTPUT (f)->move_offset_top = expected_top - current_top;
8703 /* Now fix the mispositioned frame's location. */
8705 adjusted_left = expected_left + FRAME_X_OUTPUT (f)->move_offset_left;
8706 adjusted_top = expected_top + FRAME_X_OUTPUT (f)->move_offset_top;
8708 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
8709 adjusted_left, adjusted_top);
8711 x_sync_with_move (f, expected_left, expected_top, 0);
8713 else
8714 /* It's a "Type B" window manager. We don't have to adjust the
8715 frame's position. */
8717 FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_B;
8721 /* Wait for XGetGeometry to return up-to-date position information for a
8722 recently-moved frame. Call this immediately after calling XMoveWindow.
8723 If FUZZY is non-zero, then LEFT and TOP are just estimates of where the
8724 frame has been moved to, so we use a fuzzy position comparison instead
8725 of an exact comparison. */
8727 static void
8728 x_sync_with_move (f, left, top, fuzzy)
8729 struct frame *f;
8730 int left, top, fuzzy;
8732 int count = 0;
8734 while (count++ < 50)
8736 int current_left = 0, current_top = 0;
8738 /* In theory, this call to XSync only needs to happen once, but in
8739 practice, it doesn't seem to work, hence the need for the surrounding
8740 loop. */
8742 XSync (FRAME_X_DISPLAY (f), False);
8743 x_real_positions (f, &current_left, &current_top);
8745 if (fuzzy)
8747 /* The left fuzz-factor is 10 pixels. The top fuzz-factor is 40
8748 pixels. */
8750 if (eabs (current_left - left) <= 10
8751 && eabs (current_top - top) <= 40)
8752 return;
8754 else if (current_left == left && current_top == top)
8755 return;
8758 /* As a last resort, just wait 0.5 seconds and hope that XGetGeometry
8759 will then return up-to-date position info. */
8761 wait_reading_process_output (0, 500000, 0, 0, Qnil, NULL, 0);
8765 /* Change the size of frame F's X window to COLS/ROWS in the case F
8766 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
8767 top-left-corner window gravity for this size change and subsequent
8768 size changes. Otherwise we leave the window gravity unchanged. */
8770 static void
8771 x_set_window_size_1 (f, change_gravity, cols, rows)
8772 struct frame *f;
8773 int change_gravity;
8774 int cols, rows;
8776 int pixelwidth, pixelheight;
8778 check_frame_size (f, &rows, &cols);
8779 f->scroll_bar_actual_width
8780 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
8782 : FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0
8783 ? FRAME_CONFIG_SCROLL_BAR_WIDTH (f)
8784 : (FRAME_CONFIG_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f)));
8786 compute_fringe_widths (f, 0);
8788 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
8789 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
8791 f->win_gravity = NorthWestGravity;
8792 x_wm_set_size_hint (f, (long) 0, 0);
8794 XSync (FRAME_X_DISPLAY (f), False);
8795 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8796 pixelwidth, pixelheight);
8798 /* Now, strictly speaking, we can't be sure that this is accurate,
8799 but the window manager will get around to dealing with the size
8800 change request eventually, and we'll hear how it went when the
8801 ConfigureNotify event gets here.
8803 We could just not bother storing any of this information here,
8804 and let the ConfigureNotify event set everything up, but that
8805 might be kind of confusing to the Lisp code, since size changes
8806 wouldn't be reported in the frame parameters until some random
8807 point in the future when the ConfigureNotify event arrives.
8809 We pass 1 for DELAY since we can't run Lisp code inside of
8810 a BLOCK_INPUT. */
8811 change_frame_size (f, rows, cols, 0, 1, 0);
8812 FRAME_PIXEL_WIDTH (f) = pixelwidth;
8813 FRAME_PIXEL_HEIGHT (f) = pixelheight;
8815 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
8816 receive in the ConfigureNotify event; if we get what we asked
8817 for, then the event won't cause the screen to become garbaged, so
8818 we have to make sure to do it here. */
8819 SET_FRAME_GARBAGED (f);
8821 XFlush (FRAME_X_DISPLAY (f));
8825 /* Call this to change the size of frame F's x-window.
8826 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
8827 for this size change and subsequent size changes.
8828 Otherwise we leave the window gravity unchanged. */
8830 void
8831 x_set_window_size (f, change_gravity, cols, rows)
8832 struct frame *f;
8833 int change_gravity;
8834 int cols, rows;
8836 BLOCK_INPUT;
8838 #ifdef USE_GTK
8839 if (FRAME_GTK_WIDGET (f))
8840 xg_frame_set_char_size (f, cols, rows);
8841 else
8842 x_set_window_size_1 (f, change_gravity, cols, rows);
8843 #elif USE_X_TOOLKIT
8845 if (f->output_data.x->widget != NULL)
8847 /* The x and y position of the widget is clobbered by the
8848 call to XtSetValues within EmacsFrameSetCharSize.
8849 This is a real kludge, but I don't understand Xt so I can't
8850 figure out a correct fix. Can anyone else tell me? -- rms. */
8851 int xpos = f->output_data.x->widget->core.x;
8852 int ypos = f->output_data.x->widget->core.y;
8853 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
8854 f->output_data.x->widget->core.x = xpos;
8855 f->output_data.x->widget->core.y = ypos;
8857 else
8858 x_set_window_size_1 (f, change_gravity, cols, rows);
8860 #else /* not USE_X_TOOLKIT */
8862 x_set_window_size_1 (f, change_gravity, cols, rows);
8864 #endif /* not USE_X_TOOLKIT */
8866 /* If cursor was outside the new size, mark it as off. */
8867 mark_window_cursors_off (XWINDOW (f->root_window));
8869 /* Clear out any recollection of where the mouse highlighting was,
8870 since it might be in a place that's outside the new frame size.
8871 Actually checking whether it is outside is a pain in the neck,
8872 so don't try--just let the highlighting be done afresh with new size. */
8873 cancel_mouse_face (f);
8875 UNBLOCK_INPUT;
8878 /* Mouse warping. */
8880 void
8881 x_set_mouse_position (f, x, y)
8882 struct frame *f;
8883 int x, y;
8885 int pix_x, pix_y;
8887 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
8888 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
8890 if (pix_x < 0) pix_x = 0;
8891 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
8893 if (pix_y < 0) pix_y = 0;
8894 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
8896 BLOCK_INPUT;
8898 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
8899 0, 0, 0, 0, pix_x, pix_y);
8900 UNBLOCK_INPUT;
8903 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
8905 void
8906 x_set_mouse_pixel_position (f, pix_x, pix_y)
8907 struct frame *f;
8908 int pix_x, pix_y;
8910 BLOCK_INPUT;
8912 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
8913 0, 0, 0, 0, pix_x, pix_y);
8914 UNBLOCK_INPUT;
8917 /* focus shifting, raising and lowering. */
8919 void
8920 x_focus_on_frame (f)
8921 struct frame *f;
8923 #if 0 /* This proves to be unpleasant. */
8924 x_raise_frame (f);
8925 #endif
8926 #if 0
8927 /* I don't think that the ICCCM allows programs to do things like this
8928 without the interaction of the window manager. Whatever you end up
8929 doing with this code, do it to x_unfocus_frame too. */
8930 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8931 RevertToPointerRoot, CurrentTime);
8932 #endif /* ! 0 */
8935 void
8936 x_unfocus_frame (f)
8937 struct frame *f;
8939 #if 0
8940 /* Look at the remarks in x_focus_on_frame. */
8941 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
8942 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
8943 RevertToPointerRoot, CurrentTime);
8944 #endif /* ! 0 */
8947 /* Raise frame F. */
8949 void
8950 x_raise_frame (f)
8951 struct frame *f;
8953 BLOCK_INPUT;
8954 if (f->async_visible)
8955 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
8957 XFlush (FRAME_X_DISPLAY (f));
8958 UNBLOCK_INPUT;
8961 /* Lower frame F. */
8963 void
8964 x_lower_frame (f)
8965 struct frame *f;
8967 if (f->async_visible)
8969 BLOCK_INPUT;
8970 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
8971 XFlush (FRAME_X_DISPLAY (f));
8972 UNBLOCK_INPUT;
8976 /* Activate frame with Extended Window Manager Hints */
8978 void
8979 x_ewmh_activate_frame (f)
8980 FRAME_PTR f;
8982 /* See Window Manager Specification/Extended Window Manager Hints at
8983 http://freedesktop.org/wiki/Specifications/wm-spec */
8985 const char *atom = "_NET_ACTIVE_WINDOW";
8986 if (f->async_visible && wm_supports (f, atom))
8988 Lisp_Object frame;
8989 XSETFRAME (frame, f);
8990 Fx_send_client_event (frame, make_number (0), frame,
8991 make_unibyte_string (atom, strlen (atom)),
8992 make_number (32),
8993 Fcons (make_number (1),
8994 Fcons (make_number (last_user_time),
8995 Qnil)));
8999 static void
9000 XTframe_raise_lower (f, raise_flag)
9001 FRAME_PTR f;
9002 int raise_flag;
9004 if (raise_flag)
9005 x_raise_frame (f);
9006 else
9007 x_lower_frame (f);
9010 /* XEmbed implementation. */
9012 void
9013 xembed_set_info (f, flags)
9014 struct frame *f;
9015 enum xembed_info flags;
9017 Atom atom;
9018 unsigned long data[2];
9020 atom = XInternAtom (FRAME_X_DISPLAY (f), "_XEMBED_INFO", False);
9022 data[0] = XEMBED_VERSION;
9023 data[1] = flags;
9025 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), atom, atom,
9026 32, PropModeReplace, (unsigned char *) data, 2);
9029 void
9030 xembed_send_message (f, time, message, detail, data1, data2)
9031 struct frame *f;
9032 Time time;
9033 enum xembed_message message;
9034 long detail;
9035 long data1;
9036 long data2;
9038 XEvent event;
9040 event.xclient.type = ClientMessage;
9041 event.xclient.window = FRAME_X_OUTPUT (f)->parent_desc;
9042 event.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_XEMBED;
9043 event.xclient.format = 32;
9044 event.xclient.data.l[0] = time;
9045 event.xclient.data.l[1] = message;
9046 event.xclient.data.l[2] = detail;
9047 event.xclient.data.l[3] = data1;
9048 event.xclient.data.l[4] = data2;
9050 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_OUTPUT (f)->parent_desc,
9051 False, NoEventMask, &event);
9052 XSync (FRAME_X_DISPLAY (f), False);
9055 /* Change of visibility. */
9057 /* This tries to wait until the frame is really visible.
9058 However, if the window manager asks the user where to position
9059 the frame, this will return before the user finishes doing that.
9060 The frame will not actually be visible at that time,
9061 but it will become visible later when the window manager
9062 finishes with it. */
9064 void
9065 x_make_frame_visible (f)
9066 struct frame *f;
9068 Lisp_Object type;
9069 int original_top, original_left;
9070 int retry_count = 2;
9072 retry:
9074 BLOCK_INPUT;
9076 type = x_icon_type (f);
9077 if (!NILP (type))
9078 x_bitmap_icon (f, type);
9080 if (! FRAME_VISIBLE_P (f))
9082 /* We test FRAME_GARBAGED_P here to make sure we don't
9083 call x_set_offset a second time
9084 if we get to x_make_frame_visible a second time
9085 before the window gets really visible. */
9086 if (! FRAME_ICONIFIED_P (f)
9087 && ! FRAME_X_EMBEDDED_P (f)
9088 && ! f->output_data.x->asked_for_visible)
9089 x_set_offset (f, f->left_pos, f->top_pos, 0);
9091 f->output_data.x->asked_for_visible = 1;
9093 if (! EQ (Vx_no_window_manager, Qt))
9094 x_wm_set_window_state (f, NormalState);
9095 #ifdef USE_X_TOOLKIT
9096 if (FRAME_X_EMBEDDED_P (f))
9097 xembed_set_info (f, XEMBED_MAPPED);
9098 else
9100 /* This was XtPopup, but that did nothing for an iconified frame. */
9101 XtMapWidget (f->output_data.x->widget);
9103 #else /* not USE_X_TOOLKIT */
9104 #ifdef USE_GTK
9105 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
9106 gtk_window_deiconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
9107 #else
9108 if (FRAME_X_EMBEDDED_P (f))
9109 xembed_set_info (f, XEMBED_MAPPED);
9110 else
9111 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
9112 #endif /* not USE_GTK */
9113 #endif /* not USE_X_TOOLKIT */
9114 #if 0 /* This seems to bring back scroll bars in the wrong places
9115 if the window configuration has changed. They seem
9116 to come back ok without this. */
9117 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
9118 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
9119 #endif
9122 XFlush (FRAME_X_DISPLAY (f));
9124 /* Synchronize to ensure Emacs knows the frame is visible
9125 before we do anything else. We do this loop with input not blocked
9126 so that incoming events are handled. */
9128 Lisp_Object frame;
9129 int count;
9130 /* This must be before UNBLOCK_INPUT
9131 since events that arrive in response to the actions above
9132 will set it when they are handled. */
9133 int previously_visible = f->output_data.x->has_been_visible;
9135 original_left = f->left_pos;
9136 original_top = f->top_pos;
9138 /* This must come after we set COUNT. */
9139 UNBLOCK_INPUT;
9141 /* We unblock here so that arriving X events are processed. */
9143 /* Now move the window back to where it was "supposed to be".
9144 But don't do it if the gravity is negative.
9145 When the gravity is negative, this uses a position
9146 that is 3 pixels too low. Perhaps that's really the border width.
9148 Don't do this if the window has never been visible before,
9149 because the window manager may choose the position
9150 and we don't want to override it. */
9152 if (! FRAME_VISIBLE_P (f)
9153 && ! FRAME_ICONIFIED_P (f)
9154 && ! FRAME_X_EMBEDDED_P (f)
9155 && f->win_gravity == NorthWestGravity
9156 && previously_visible)
9158 Drawable rootw;
9159 int x, y;
9160 unsigned int width, height, border, depth;
9162 BLOCK_INPUT;
9164 /* On some window managers (such as FVWM) moving an existing
9165 window, even to the same place, causes the window manager
9166 to introduce an offset. This can cause the window to move
9167 to an unexpected location. Check the geometry (a little
9168 slow here) and then verify that the window is in the right
9169 place. If the window is not in the right place, move it
9170 there, and take the potential window manager hit. */
9171 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
9172 &rootw, &x, &y, &width, &height, &border, &depth);
9174 if (original_left != x || original_top != y)
9175 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
9176 original_left, original_top);
9178 UNBLOCK_INPUT;
9181 XSETFRAME (frame, f);
9183 /* Wait until the frame is visible. Process X events until a
9184 MapNotify event has been seen, or until we think we won't get a
9185 MapNotify at all.. */
9186 for (count = input_signal_count + 10;
9187 input_signal_count < count && !FRAME_VISIBLE_P (f);)
9189 /* Force processing of queued events. */
9190 x_sync (f);
9192 /* Machines that do polling rather than SIGIO have been
9193 observed to go into a busy-wait here. So we'll fake an
9194 alarm signal to let the handler know that there's something
9195 to be read. We used to raise a real alarm, but it seems
9196 that the handler isn't always enabled here. This is
9197 probably a bug. */
9198 if (input_polling_used ())
9200 /* It could be confusing if a real alarm arrives while
9201 processing the fake one. Turn it off and let the
9202 handler reset it. */
9203 extern void poll_for_input_1 P_ ((void));
9204 int old_poll_suppress_count = poll_suppress_count;
9205 poll_suppress_count = 1;
9206 poll_for_input_1 ();
9207 poll_suppress_count = old_poll_suppress_count;
9210 /* See if a MapNotify event has been processed. */
9211 FRAME_SAMPLE_VISIBILITY (f);
9214 /* 2000-09-28: In
9216 (let ((f (selected-frame)))
9217 (iconify-frame f)
9218 (raise-frame f))
9220 the frame is not raised with various window managers on
9221 FreeBSD, GNU/Linux and Solaris. It turns out that, for some
9222 unknown reason, the call to XtMapWidget is completely ignored.
9223 Mapping the widget a second time works. */
9225 if (!FRAME_VISIBLE_P (f) && --retry_count > 0)
9226 goto retry;
9230 /* Change from mapped state to withdrawn state. */
9232 /* Make the frame visible (mapped and not iconified). */
9234 void
9235 x_make_frame_invisible (f)
9236 struct frame *f;
9238 Window window;
9240 /* Use the frame's outermost window, not the one we normally draw on. */
9241 window = FRAME_OUTER_WINDOW (f);
9243 /* Don't keep the highlight on an invisible frame. */
9244 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
9245 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9247 #if 0/* This might add unreliability; I don't trust it -- rms. */
9248 if (! f->async_visible && ! f->async_iconified)
9249 return;
9250 #endif
9252 BLOCK_INPUT;
9254 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
9255 that the current position of the window is user-specified, rather than
9256 program-specified, so that when the window is mapped again, it will be
9257 placed at the same location, without forcing the user to position it
9258 by hand again (they have already done that once for this window.) */
9259 x_wm_set_size_hint (f, (long) 0, 1);
9261 #ifdef USE_GTK
9262 if (FRAME_GTK_OUTER_WIDGET (f))
9263 gtk_widget_hide (FRAME_GTK_OUTER_WIDGET (f));
9264 else
9265 #else
9266 if (FRAME_X_EMBEDDED_P (f))
9267 xembed_set_info (f, 0);
9268 else
9269 #endif
9272 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
9273 DefaultScreen (FRAME_X_DISPLAY (f))))
9275 UNBLOCK_INPUT_RESIGNAL;
9276 error ("Can't notify window manager of window withdrawal");
9280 /* We can't distinguish this from iconification
9281 just by the event that we get from the server.
9282 So we can't win using the usual strategy of letting
9283 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
9284 and synchronize with the server to make sure we agree. */
9285 f->visible = 0;
9286 FRAME_ICONIFIED_P (f) = 0;
9287 f->async_visible = 0;
9288 f->async_iconified = 0;
9290 x_sync (f);
9292 UNBLOCK_INPUT;
9295 /* Change window state from mapped to iconified. */
9297 void
9298 x_iconify_frame (f)
9299 struct frame *f;
9301 int result;
9302 Lisp_Object type;
9304 /* Don't keep the highlight on an invisible frame. */
9305 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
9306 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9308 if (f->async_iconified)
9309 return;
9311 BLOCK_INPUT;
9313 FRAME_SAMPLE_VISIBILITY (f);
9315 type = x_icon_type (f);
9316 if (!NILP (type))
9317 x_bitmap_icon (f, type);
9319 #ifdef USE_GTK
9320 if (FRAME_GTK_OUTER_WIDGET (f))
9322 if (! FRAME_VISIBLE_P (f))
9323 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
9325 gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
9326 f->iconified = 1;
9327 f->visible = 1;
9328 f->async_iconified = 1;
9329 f->async_visible = 0;
9330 UNBLOCK_INPUT;
9331 return;
9333 #endif
9335 #ifdef USE_X_TOOLKIT
9337 if (! FRAME_VISIBLE_P (f))
9339 if (! EQ (Vx_no_window_manager, Qt))
9340 x_wm_set_window_state (f, IconicState);
9341 /* This was XtPopup, but that did nothing for an iconified frame. */
9342 XtMapWidget (f->output_data.x->widget);
9343 /* The server won't give us any event to indicate
9344 that an invisible frame was changed to an icon,
9345 so we have to record it here. */
9346 f->iconified = 1;
9347 f->visible = 1;
9348 f->async_iconified = 1;
9349 f->async_visible = 0;
9350 UNBLOCK_INPUT;
9351 return;
9354 result = XIconifyWindow (FRAME_X_DISPLAY (f),
9355 XtWindow (f->output_data.x->widget),
9356 DefaultScreen (FRAME_X_DISPLAY (f)));
9357 UNBLOCK_INPUT;
9359 if (!result)
9360 error ("Can't notify window manager of iconification");
9362 f->async_iconified = 1;
9363 f->async_visible = 0;
9366 BLOCK_INPUT;
9367 XFlush (FRAME_X_DISPLAY (f));
9368 UNBLOCK_INPUT;
9369 #else /* not USE_X_TOOLKIT */
9371 /* Make sure the X server knows where the window should be positioned,
9372 in case the user deiconifies with the window manager. */
9373 if (! FRAME_VISIBLE_P (f)
9374 && ! FRAME_ICONIFIED_P (f)
9375 && ! FRAME_X_EMBEDDED_P (f))
9376 x_set_offset (f, f->left_pos, f->top_pos, 0);
9378 /* Since we don't know which revision of X we're running, we'll use both
9379 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
9381 /* X11R4: send a ClientMessage to the window manager using the
9382 WM_CHANGE_STATE type. */
9384 XEvent message;
9386 message.xclient.window = FRAME_X_WINDOW (f);
9387 message.xclient.type = ClientMessage;
9388 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
9389 message.xclient.format = 32;
9390 message.xclient.data.l[0] = IconicState;
9392 if (! XSendEvent (FRAME_X_DISPLAY (f),
9393 DefaultRootWindow (FRAME_X_DISPLAY (f)),
9394 False,
9395 SubstructureRedirectMask | SubstructureNotifyMask,
9396 &message))
9398 UNBLOCK_INPUT_RESIGNAL;
9399 error ("Can't notify window manager of iconification");
9403 /* X11R3: set the initial_state field of the window manager hints to
9404 IconicState. */
9405 x_wm_set_window_state (f, IconicState);
9407 if (!FRAME_VISIBLE_P (f))
9409 /* If the frame was withdrawn, before, we must map it. */
9410 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
9413 f->async_iconified = 1;
9414 f->async_visible = 0;
9416 XFlush (FRAME_X_DISPLAY (f));
9417 UNBLOCK_INPUT;
9418 #endif /* not USE_X_TOOLKIT */
9422 /* Free X resources of frame F. */
9424 void
9425 x_free_frame_resources (f)
9426 struct frame *f;
9428 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9429 Lisp_Object bar;
9430 struct scroll_bar *b;
9432 BLOCK_INPUT;
9434 /* If a display connection is dead, don't try sending more
9435 commands to the X server. */
9436 if (dpyinfo->display)
9438 /* We must free faces before destroying windows because some
9439 font-driver (e.g. xft) access a window while finishing a
9440 face. */
9441 if (FRAME_FACE_CACHE (f))
9442 free_frame_faces (f);
9444 if (f->output_data.x->icon_desc)
9445 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
9447 #ifdef USE_X_TOOLKIT
9448 /* Explicitly destroy the scroll bars of the frame. Without
9449 this, we get "BadDrawable" errors from the toolkit later on,
9450 presumably from expose events generated for the disappearing
9451 toolkit scroll bars. */
9452 for (bar = FRAME_SCROLL_BARS (f); !NILP (bar); bar = b->next)
9454 b = XSCROLL_BAR (bar);
9455 x_scroll_bar_remove (b);
9457 #endif
9459 #ifdef HAVE_X_I18N
9460 if (FRAME_XIC (f))
9461 free_frame_xic (f);
9462 #endif
9464 #ifdef USE_X_TOOLKIT
9465 if (f->output_data.x->widget)
9467 XtDestroyWidget (f->output_data.x->widget);
9468 f->output_data.x->widget = NULL;
9470 /* Tooltips don't have widgets, only a simple X window, even if
9471 we are using a toolkit. */
9472 else if (FRAME_X_WINDOW (f))
9473 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
9475 free_frame_menubar (f);
9476 #else /* !USE_X_TOOLKIT */
9478 #ifdef USE_GTK
9479 /* In the GTK version, tooltips are normal X
9480 frames. We must check and free both types. */
9481 if (FRAME_GTK_OUTER_WIDGET (f))
9483 gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f));
9484 FRAME_X_WINDOW (f) = 0; /* Set to avoid XDestroyWindow below */
9485 FRAME_GTK_OUTER_WIDGET (f) = 0;
9487 #endif /* USE_GTK */
9489 if (FRAME_X_WINDOW (f))
9490 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
9491 #endif /* !USE_X_TOOLKIT */
9493 unload_color (f, FRAME_FOREGROUND_PIXEL (f));
9494 unload_color (f, FRAME_BACKGROUND_PIXEL (f));
9495 unload_color (f, f->output_data.x->cursor_pixel);
9496 unload_color (f, f->output_data.x->cursor_foreground_pixel);
9497 unload_color (f, f->output_data.x->border_pixel);
9498 unload_color (f, f->output_data.x->mouse_pixel);
9500 if (f->output_data.x->scroll_bar_background_pixel != -1)
9501 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
9502 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
9503 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
9504 #ifdef USE_TOOLKIT_SCROLL_BARS
9505 /* Scrollbar shadow colors. */
9506 if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
9507 unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
9508 if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
9509 unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
9510 #endif /* USE_TOOLKIT_SCROLL_BARS */
9511 if (f->output_data.x->white_relief.allocated_p)
9512 unload_color (f, f->output_data.x->white_relief.pixel);
9513 if (f->output_data.x->black_relief.allocated_p)
9514 unload_color (f, f->output_data.x->black_relief.pixel);
9516 if (FRAME_FACE_CACHE (f))
9517 free_frame_faces (f);
9519 x_free_gcs (f);
9520 XFlush (FRAME_X_DISPLAY (f));
9523 xfree (f->output_data.x->saved_menu_event);
9524 xfree (f->output_data.x);
9525 f->output_data.x = NULL;
9527 if (f == dpyinfo->x_focus_frame)
9528 dpyinfo->x_focus_frame = 0;
9529 if (f == dpyinfo->x_focus_event_frame)
9530 dpyinfo->x_focus_event_frame = 0;
9531 if (f == dpyinfo->x_highlight_frame)
9532 dpyinfo->x_highlight_frame = 0;
9534 if (f == dpyinfo->mouse_face_mouse_frame)
9536 dpyinfo->mouse_face_beg_row
9537 = dpyinfo->mouse_face_beg_col = -1;
9538 dpyinfo->mouse_face_end_row
9539 = dpyinfo->mouse_face_end_col = -1;
9540 dpyinfo->mouse_face_window = Qnil;
9541 dpyinfo->mouse_face_deferred_gc = 0;
9542 dpyinfo->mouse_face_mouse_frame = 0;
9545 UNBLOCK_INPUT;
9549 /* Destroy the X window of frame F. */
9551 void
9552 x_destroy_window (f)
9553 struct frame *f;
9555 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9557 /* If a display connection is dead, don't try sending more
9558 commands to the X server. */
9559 if (dpyinfo->display != 0)
9560 x_free_frame_resources (f);
9562 dpyinfo->reference_count--;
9566 /* Setting window manager hints. */
9568 /* Set the normal size hints for the window manager, for frame F.
9569 FLAGS is the flags word to use--or 0 meaning preserve the flags
9570 that the window now has.
9571 If USER_POSITION is nonzero, we set the USPosition
9572 flag (this is useful when FLAGS is 0).
9573 The GTK version is in gtkutils.c */
9575 #ifndef USE_GTK
9576 void
9577 x_wm_set_size_hint (f, flags, user_position)
9578 struct frame *f;
9579 long flags;
9580 int user_position;
9582 XSizeHints size_hints;
9584 #ifdef USE_X_TOOLKIT
9585 Arg al[2];
9586 int ac = 0;
9587 Dimension widget_width, widget_height;
9588 #endif
9590 Window window = FRAME_OUTER_WINDOW (f);
9592 /* Setting PMaxSize caused various problems. */
9593 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
9595 size_hints.x = f->left_pos;
9596 size_hints.y = f->top_pos;
9598 #ifdef USE_X_TOOLKIT
9599 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
9600 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
9601 XtGetValues (f->output_data.x->widget, al, ac);
9602 size_hints.height = widget_height;
9603 size_hints.width = widget_width;
9604 #else /* not USE_X_TOOLKIT */
9605 size_hints.height = FRAME_PIXEL_HEIGHT (f);
9606 size_hints.width = FRAME_PIXEL_WIDTH (f);
9607 #endif /* not USE_X_TOOLKIT */
9609 size_hints.width_inc = FRAME_COLUMN_WIDTH (f);
9610 size_hints.height_inc = FRAME_LINE_HEIGHT (f);
9611 size_hints.max_width
9612 = FRAME_X_DISPLAY_INFO (f)->width - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
9613 size_hints.max_height
9614 = FRAME_X_DISPLAY_INFO (f)->height - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
9616 /* Calculate the base and minimum sizes.
9618 (When we use the X toolkit, we don't do it here.
9619 Instead we copy the values that the widgets are using, below.) */
9620 #ifndef USE_X_TOOLKIT
9622 int base_width, base_height;
9623 int min_rows = 0, min_cols = 0;
9625 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
9626 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
9628 check_frame_size (f, &min_rows, &min_cols);
9630 /* The window manager uses the base width hints to calculate the
9631 current number of rows and columns in the frame while
9632 resizing; min_width and min_height aren't useful for this
9633 purpose, since they might not give the dimensions for a
9634 zero-row, zero-column frame.
9636 We use the base_width and base_height members if we have
9637 them; otherwise, we set the min_width and min_height members
9638 to the size for a zero x zero frame. */
9640 size_hints.flags |= PBaseSize;
9641 size_hints.base_width = base_width;
9642 size_hints.base_height = base_height;
9643 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
9644 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
9647 /* If we don't need the old flags, we don't need the old hint at all. */
9648 if (flags)
9650 size_hints.flags |= flags;
9651 goto no_read;
9653 #endif /* not USE_X_TOOLKIT */
9656 XSizeHints hints; /* Sometimes I hate X Windows... */
9657 long supplied_return;
9658 int value;
9660 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
9661 &supplied_return);
9663 #ifdef USE_X_TOOLKIT
9664 size_hints.base_height = hints.base_height;
9665 size_hints.base_width = hints.base_width;
9666 size_hints.min_height = hints.min_height;
9667 size_hints.min_width = hints.min_width;
9668 #endif
9670 if (flags)
9671 size_hints.flags |= flags;
9672 else
9674 if (value == 0)
9675 hints.flags = 0;
9676 if (hints.flags & PSize)
9677 size_hints.flags |= PSize;
9678 if (hints.flags & PPosition)
9679 size_hints.flags |= PPosition;
9680 if (hints.flags & USPosition)
9681 size_hints.flags |= USPosition;
9682 if (hints.flags & USSize)
9683 size_hints.flags |= USSize;
9687 #ifndef USE_X_TOOLKIT
9688 no_read:
9689 #endif
9691 #ifdef PWinGravity
9692 size_hints.win_gravity = f->win_gravity;
9693 size_hints.flags |= PWinGravity;
9695 if (user_position)
9697 size_hints.flags &= ~ PPosition;
9698 size_hints.flags |= USPosition;
9700 #endif /* PWinGravity */
9702 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
9704 #endif /* not USE_GTK */
9706 /* Used for IconicState or NormalState */
9708 void
9709 x_wm_set_window_state (f, state)
9710 struct frame *f;
9711 int state;
9713 #ifdef USE_X_TOOLKIT
9714 Arg al[1];
9716 XtSetArg (al[0], XtNinitialState, state);
9717 XtSetValues (f->output_data.x->widget, al, 1);
9718 #else /* not USE_X_TOOLKIT */
9719 Window window = FRAME_X_WINDOW (f);
9721 f->output_data.x->wm_hints.flags |= StateHint;
9722 f->output_data.x->wm_hints.initial_state = state;
9724 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
9725 #endif /* not USE_X_TOOLKIT */
9728 void
9729 x_wm_set_icon_pixmap (f, pixmap_id)
9730 struct frame *f;
9731 int pixmap_id;
9733 Pixmap icon_pixmap, icon_mask;
9735 #ifndef USE_X_TOOLKIT
9736 Window window = FRAME_OUTER_WINDOW (f);
9737 #endif
9739 if (pixmap_id > 0)
9741 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
9742 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
9743 icon_mask = x_bitmap_mask (f, pixmap_id);
9744 f->output_data.x->wm_hints.icon_mask = icon_mask;
9746 else
9748 /* It seems there is no way to turn off use of an icon pixmap.
9749 The following line does it, only if no icon has yet been created,
9750 for some window managers. But with mwm it crashes.
9751 Some people say it should clear the IconPixmapHint bit in this case,
9752 but that doesn't work, and the X consortium said it isn't the
9753 right thing at all. Since there is no way to win,
9754 best to explicitly give up. */
9755 #if 0
9756 f->output_data.x->wm_hints.icon_pixmap = None;
9757 f->output_data.x->wm_hints.icon_mask = None;
9758 #else
9759 return;
9760 #endif
9764 #ifdef USE_GTK
9766 xg_set_frame_icon (f, icon_pixmap, icon_mask);
9767 return;
9770 #elif defined (USE_X_TOOLKIT) /* same as in x_wm_set_window_state. */
9773 Arg al[1];
9774 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
9775 XtSetValues (f->output_data.x->widget, al, 1);
9776 XtSetArg (al[0], XtNiconMask, icon_mask);
9777 XtSetValues (f->output_data.x->widget, al, 1);
9780 #else /* not USE_X_TOOLKIT && not USE_GTK */
9782 f->output_data.x->wm_hints.flags |= (IconPixmapHint | IconMaskHint);
9783 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
9785 #endif /* not USE_X_TOOLKIT && not USE_GTK */
9788 void
9789 x_wm_set_icon_position (f, icon_x, icon_y)
9790 struct frame *f;
9791 int icon_x, icon_y;
9793 Window window = FRAME_OUTER_WINDOW (f);
9795 f->output_data.x->wm_hints.flags |= IconPositionHint;
9796 f->output_data.x->wm_hints.icon_x = icon_x;
9797 f->output_data.x->wm_hints.icon_y = icon_y;
9799 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
9803 /***********************************************************************
9804 Fonts
9805 ***********************************************************************/
9807 #if GLYPH_DEBUG
9809 /* Check that FONT is valid on frame F. It is if it can be found in F's
9810 font table. */
9812 static void
9813 x_check_font (f, font)
9814 struct frame *f;
9815 struct font *font;
9817 Lisp_Object frame;
9819 xassert (font != NULL && ! NILP (font->props[FONT_TYPE_INDEX]));
9820 if (font->driver->check)
9821 xassert (font->driver->check (f, font) == 0);
9824 #endif /* GLYPH_DEBUG != 0 */
9827 /***********************************************************************
9828 Initialization
9829 ***********************************************************************/
9831 #ifdef USE_X_TOOLKIT
9832 static XrmOptionDescRec emacs_options[] = {
9833 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
9834 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
9836 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
9837 XrmoptionSepArg, NULL},
9838 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
9840 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
9841 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
9842 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
9843 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
9844 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
9845 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
9846 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
9849 /* Whether atimer for Xt timeouts is activated or not. */
9851 static int x_timeout_atimer_activated_flag;
9853 #endif /* USE_X_TOOLKIT */
9855 static int x_initialized;
9857 #ifdef HAVE_X_SM
9858 static int x_session_initialized;
9859 #endif
9861 #ifdef MULTI_KBOARD
9862 /* Test whether two display-name strings agree up to the dot that separates
9863 the screen number from the server number. */
9864 static int
9865 same_x_server (name1, name2)
9866 const char *name1, *name2;
9868 int seen_colon = 0;
9869 const unsigned char *system_name = SDATA (Vsystem_name);
9870 int system_name_length = strlen (system_name);
9871 int length_until_period = 0;
9873 while (system_name[length_until_period] != 0
9874 && system_name[length_until_period] != '.')
9875 length_until_period++;
9877 /* Treat `unix' like an empty host name. */
9878 if (! strncmp (name1, "unix:", 5))
9879 name1 += 4;
9880 if (! strncmp (name2, "unix:", 5))
9881 name2 += 4;
9882 /* Treat this host's name like an empty host name. */
9883 if (! strncmp (name1, system_name, system_name_length)
9884 && name1[system_name_length] == ':')
9885 name1 += system_name_length;
9886 if (! strncmp (name2, system_name, system_name_length)
9887 && name2[system_name_length] == ':')
9888 name2 += system_name_length;
9889 /* Treat this host's domainless name like an empty host name. */
9890 if (! strncmp (name1, system_name, length_until_period)
9891 && name1[length_until_period] == ':')
9892 name1 += length_until_period;
9893 if (! strncmp (name2, system_name, length_until_period)
9894 && name2[length_until_period] == ':')
9895 name2 += length_until_period;
9897 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
9899 if (*name1 == ':')
9900 seen_colon++;
9901 if (seen_colon && *name1 == '.')
9902 return 1;
9904 return (seen_colon
9905 && (*name1 == '.' || *name1 == '\0')
9906 && (*name2 == '.' || *name2 == '\0'));
9908 #endif
9910 /* Count number of set bits in mask and number of bits to shift to
9911 get to the first bit. With MASK 0x7e0, *BITS is set to 6, and *OFFSET
9912 to 5. */
9913 static void
9914 get_bits_and_offset (mask, bits, offset)
9915 unsigned long mask;
9916 int *bits;
9917 int *offset;
9919 int nr = 0;
9920 int off = 0;
9922 while (!(mask & 1))
9924 off++;
9925 mask >>= 1;
9928 while (mask & 1)
9930 nr++;
9931 mask >>= 1;
9934 *offset = off;
9935 *bits = nr;
9938 /* Return 1 if display DISPLAY is available for use, 0 otherwise.
9939 But don't permanently open it, just test its availability. */
9942 x_display_ok (display)
9943 const char *display;
9945 int dpy_ok = 1;
9946 Display *dpy;
9948 dpy = XOpenDisplay (display);
9949 if (dpy)
9950 XCloseDisplay (dpy);
9951 else
9952 dpy_ok = 0;
9953 return dpy_ok;
9956 /* Open a connection to X display DISPLAY_NAME, and return
9957 the structure that describes the open display.
9958 If we cannot contact the display, return null. */
9960 struct x_display_info *
9961 x_term_init (display_name, xrm_option, resource_name)
9962 Lisp_Object display_name;
9963 char *xrm_option;
9964 char *resource_name;
9966 int connection;
9967 Display *dpy;
9968 struct terminal *terminal;
9969 struct x_display_info *dpyinfo;
9970 XrmDatabase xrdb;
9972 BLOCK_INPUT;
9974 if (!x_initialized)
9976 x_initialize ();
9977 ++x_initialized;
9980 if (! x_display_ok (SDATA (display_name)))
9981 error ("Display %s can't be opened", SDATA (display_name));
9983 #ifdef USE_GTK
9985 #define NUM_ARGV 10
9986 int argc;
9987 char *argv[NUM_ARGV];
9988 char **argv2 = argv;
9989 GdkAtom atom;
9991 #ifndef HAVE_GTK_MULTIDISPLAY
9992 if (!EQ (Vinitial_window_system, intern ("x")))
9993 error ("Sorry, you cannot connect to X servers with the GTK toolkit");
9994 #endif
9996 if (x_initialized++ > 1)
9998 #ifdef HAVE_GTK_MULTIDISPLAY
9999 /* Opening another display. If xg_display_open returns less
10000 than zero, we are probably on GTK 2.0, which can only handle
10001 one display. GTK 2.2 or later can handle more than one. */
10002 if (xg_display_open (SDATA (display_name), &dpy) < 0)
10003 #endif
10004 error ("Sorry, this version of GTK can only handle one display");
10006 else
10008 for (argc = 0; argc < NUM_ARGV; ++argc)
10009 argv[argc] = 0;
10011 argc = 0;
10012 argv[argc++] = initial_argv[0];
10014 if (! NILP (display_name))
10016 argv[argc++] = "--display";
10017 argv[argc++] = SDATA (display_name);
10020 argv[argc++] = "--name";
10021 argv[argc++] = resource_name;
10023 XSetLocaleModifiers ("");
10025 gtk_init (&argc, &argv2);
10027 /* gtk_init does set_locale. We must fix locale after calling it. */
10028 fixup_locale ();
10029 xg_initialize ();
10031 dpy = GDK_DISPLAY ();
10033 /* NULL window -> events for all windows go to our function */
10034 gdk_window_add_filter (NULL, event_handler_gdk, NULL);
10036 /* Load our own gtkrc if it exists. */
10038 char *file = "~/.emacs.d/gtkrc";
10039 Lisp_Object s, abs_file;
10041 s = make_string (file, strlen (file));
10042 abs_file = Fexpand_file_name (s, Qnil);
10044 if (! NILP (abs_file) && !NILP (Ffile_readable_p (abs_file)))
10045 gtk_rc_parse (SDATA (abs_file));
10048 XSetErrorHandler (x_error_handler);
10049 XSetIOErrorHandler (x_io_error_quitter);
10052 #else /* not USE_GTK */
10053 #ifdef USE_X_TOOLKIT
10054 /* weiner@footloose.sps.mot.com reports that this causes
10055 errors with X11R5:
10056 X protocol error: BadAtom (invalid Atom parameter)
10057 on protocol request 18skiloaf.
10058 So let's not use it until R6. */
10059 #ifdef HAVE_X11XTR6
10060 XtSetLanguageProc (NULL, NULL, NULL);
10061 #endif
10064 int argc = 0;
10065 char *argv[3];
10067 argv[0] = "";
10068 argc = 1;
10069 if (xrm_option)
10071 argv[argc++] = "-xrm";
10072 argv[argc++] = xrm_option;
10074 turn_on_atimers (0);
10075 dpy = XtOpenDisplay (Xt_app_con, SDATA (display_name),
10076 resource_name, EMACS_CLASS,
10077 emacs_options, XtNumber (emacs_options),
10078 &argc, argv);
10079 turn_on_atimers (1);
10081 #ifdef HAVE_X11XTR6
10082 /* I think this is to compensate for XtSetLanguageProc. */
10083 fixup_locale ();
10084 #endif
10087 #else /* not USE_X_TOOLKIT */
10088 XSetLocaleModifiers ("");
10089 dpy = XOpenDisplay (SDATA (display_name));
10090 #endif /* not USE_X_TOOLKIT */
10091 #endif /* not USE_GTK*/
10093 /* Detect failure. */
10094 if (dpy == 0)
10096 UNBLOCK_INPUT;
10097 return 0;
10100 /* We have definitely succeeded. Record the new connection. */
10102 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
10103 bzero (dpyinfo, sizeof *dpyinfo);
10105 terminal = x_create_terminal (dpyinfo);
10107 #ifdef MULTI_KBOARD
10109 struct x_display_info *share;
10110 Lisp_Object tail;
10112 for (share = x_display_list, tail = x_display_name_list; share;
10113 share = share->next, tail = XCDR (tail))
10114 if (same_x_server (SDATA (XCAR (XCAR (tail))),
10115 SDATA (display_name)))
10116 break;
10117 if (share)
10118 terminal->kboard = share->terminal->kboard;
10119 else
10121 terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
10122 init_kboard (terminal->kboard);
10123 terminal->kboard->Vwindow_system = intern ("x");
10124 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
10126 char *vendor = ServerVendor (dpy);
10127 UNBLOCK_INPUT;
10128 terminal->kboard->Vsystem_key_alist
10129 = call1 (Qvendor_specific_keysyms,
10130 vendor ? build_string (vendor) : empty_unibyte_string);
10131 BLOCK_INPUT;
10134 terminal->kboard->next_kboard = all_kboards;
10135 all_kboards = terminal->kboard;
10136 /* Don't let the initial kboard remain current longer than necessary.
10137 That would cause problems if a file loaded on startup tries to
10138 prompt in the mini-buffer. */
10139 if (current_kboard == initial_kboard)
10140 current_kboard = terminal->kboard;
10142 terminal->kboard->reference_count++;
10144 #endif
10146 /* Put this display on the chain. */
10147 dpyinfo->next = x_display_list;
10148 x_display_list = dpyinfo;
10150 /* Put it on x_display_name_list as well, to keep them parallel. */
10151 x_display_name_list = Fcons (Fcons (display_name, Qnil),
10152 x_display_name_list);
10153 dpyinfo->name_list_element = XCAR (x_display_name_list);
10155 dpyinfo->display = dpy;
10157 /* Set the name of the terminal. */
10158 terminal->name = (char *) xmalloc (SBYTES (display_name) + 1);
10159 strncpy (terminal->name, SDATA (display_name), SBYTES (display_name));
10160 terminal->name[SBYTES (display_name)] = 0;
10162 #if 0
10163 XSetAfterFunction (x_current_display, x_trace_wire);
10164 #endif /* ! 0 */
10166 dpyinfo->x_id_name
10167 = (char *) xmalloc (SBYTES (Vinvocation_name)
10168 + SBYTES (Vsystem_name)
10169 + 2);
10170 sprintf (dpyinfo->x_id_name, "%s@%s",
10171 SDATA (Vinvocation_name), SDATA (Vsystem_name));
10173 /* Figure out which modifier bits mean what. */
10174 x_find_modifier_meanings (dpyinfo);
10176 /* Get the scroll bar cursor. */
10177 #ifdef USE_GTK
10178 /* We must create a GTK cursor, it is required for GTK widgets. */
10179 dpyinfo->xg_cursor = xg_create_default_cursor (dpyinfo->display);
10180 #endif /* USE_GTK */
10182 dpyinfo->vertical_scroll_bar_cursor
10183 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
10185 xrdb = x_load_resources (dpyinfo->display, xrm_option,
10186 resource_name, EMACS_CLASS);
10187 #ifdef HAVE_XRMSETDATABASE
10188 XrmSetDatabase (dpyinfo->display, xrdb);
10189 #else
10190 dpyinfo->display->db = xrdb;
10191 #endif
10192 /* Put the rdb where we can find it in a way that works on
10193 all versions. */
10194 dpyinfo->xrdb = xrdb;
10196 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
10197 DefaultScreen (dpyinfo->display));
10198 select_visual (dpyinfo);
10199 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
10200 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
10201 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
10202 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
10203 dpyinfo->client_leader_window = 0;
10204 dpyinfo->grabbed = 0;
10205 dpyinfo->reference_count = 0;
10206 dpyinfo->icon_bitmap_id = -1;
10207 dpyinfo->n_fonts = 0;
10208 dpyinfo->bitmaps = 0;
10209 dpyinfo->bitmaps_size = 0;
10210 dpyinfo->bitmaps_last = 0;
10211 dpyinfo->scratch_cursor_gc = 0;
10212 dpyinfo->mouse_face_mouse_frame = 0;
10213 dpyinfo->mouse_face_deferred_gc = 0;
10214 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
10215 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
10216 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
10217 dpyinfo->mouse_face_window = Qnil;
10218 dpyinfo->mouse_face_overlay = Qnil;
10219 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
10220 dpyinfo->mouse_face_defer = 0;
10221 dpyinfo->mouse_face_hidden = 0;
10222 dpyinfo->x_focus_frame = 0;
10223 dpyinfo->x_focus_event_frame = 0;
10224 dpyinfo->x_highlight_frame = 0;
10225 dpyinfo->terminal->image_cache = make_image_cache ();
10226 dpyinfo->wm_type = X_WMTYPE_UNKNOWN;
10228 /* See if we can construct pixel values from RGB values. */
10229 dpyinfo->red_bits = dpyinfo->blue_bits = dpyinfo->green_bits = 0;
10230 dpyinfo->red_offset = dpyinfo->blue_offset = dpyinfo->green_offset = 0;
10232 if (dpyinfo->visual->class == TrueColor)
10234 get_bits_and_offset (dpyinfo->visual->red_mask,
10235 &dpyinfo->red_bits, &dpyinfo->red_offset);
10236 get_bits_and_offset (dpyinfo->visual->blue_mask,
10237 &dpyinfo->blue_bits, &dpyinfo->blue_offset);
10238 get_bits_and_offset (dpyinfo->visual->green_mask,
10239 &dpyinfo->green_bits, &dpyinfo->green_offset);
10242 /* See if a private colormap is requested. */
10243 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
10245 if (dpyinfo->visual->class == PseudoColor)
10247 Lisp_Object value;
10248 value = display_x_get_resource (dpyinfo,
10249 build_string ("privateColormap"),
10250 build_string ("PrivateColormap"),
10251 Qnil, Qnil);
10252 if (STRINGP (value)
10253 && (!strcmp (SDATA (value), "true")
10254 || !strcmp (SDATA (value), "on")))
10255 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
10258 else
10259 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
10260 dpyinfo->visual, AllocNone);
10263 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
10264 double pixels = DisplayHeight (dpyinfo->display, screen_number);
10265 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
10266 /* Mac OS X 10.3's Xserver sometimes reports 0.0mm. */
10267 dpyinfo->resy = (mm < 1) ? 100 : pixels * 25.4 / mm;
10268 pixels = DisplayWidth (dpyinfo->display, screen_number);
10269 mm = DisplayWidthMM (dpyinfo->display, screen_number);
10270 /* Mac OS X 10.3's Xserver sometimes reports 0.0mm. */
10271 dpyinfo->resx = (mm < 1) ? 100 : pixels * 25.4 / mm;
10274 dpyinfo->Xatom_wm_protocols
10275 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
10276 dpyinfo->Xatom_wm_take_focus
10277 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
10278 dpyinfo->Xatom_wm_save_yourself
10279 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
10280 dpyinfo->Xatom_wm_delete_window
10281 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
10282 dpyinfo->Xatom_wm_change_state
10283 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
10284 dpyinfo->Xatom_wm_configure_denied
10285 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
10286 dpyinfo->Xatom_wm_window_moved
10287 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
10288 dpyinfo->Xatom_wm_client_leader
10289 = XInternAtom (dpyinfo->display, "WM_CLIENT_LEADER", False);
10290 dpyinfo->Xatom_editres
10291 = XInternAtom (dpyinfo->display, "Editres", False);
10292 dpyinfo->Xatom_CLIPBOARD
10293 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
10294 dpyinfo->Xatom_TIMESTAMP
10295 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
10296 dpyinfo->Xatom_TEXT
10297 = XInternAtom (dpyinfo->display, "TEXT", False);
10298 dpyinfo->Xatom_COMPOUND_TEXT
10299 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
10300 dpyinfo->Xatom_UTF8_STRING
10301 = XInternAtom (dpyinfo->display, "UTF8_STRING", False);
10302 dpyinfo->Xatom_DELETE
10303 = XInternAtom (dpyinfo->display, "DELETE", False);
10304 dpyinfo->Xatom_MULTIPLE
10305 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
10306 dpyinfo->Xatom_INCR
10307 = XInternAtom (dpyinfo->display, "INCR", False);
10308 dpyinfo->Xatom_EMACS_TMP
10309 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
10310 dpyinfo->Xatom_TARGETS
10311 = XInternAtom (dpyinfo->display, "TARGETS", False);
10312 dpyinfo->Xatom_NULL
10313 = XInternAtom (dpyinfo->display, "NULL", False);
10314 dpyinfo->Xatom_ATOM_PAIR
10315 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
10316 /* For properties of font. */
10317 dpyinfo->Xatom_PIXEL_SIZE
10318 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
10319 dpyinfo->Xatom_AVERAGE_WIDTH
10320 = XInternAtom (dpyinfo->display, "AVERAGE_WIDTH", False);
10321 dpyinfo->Xatom_MULE_BASELINE_OFFSET
10322 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
10323 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
10324 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
10325 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
10326 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
10328 /* Ghostscript support. */
10329 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
10330 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
10332 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
10333 False);
10335 dpyinfo->Xatom_XEMBED = XInternAtom (dpyinfo->display, "_XEMBED",
10336 False);
10338 dpyinfo->cut_buffers_initialized = 0;
10340 dpyinfo->x_dnd_atoms_size = 8;
10341 dpyinfo->x_dnd_atoms_length = 0;
10342 dpyinfo->x_dnd_atoms = xmalloc (sizeof (*dpyinfo->x_dnd_atoms)
10343 * dpyinfo->x_dnd_atoms_size);
10345 dpyinfo->net_supported_atoms = NULL;
10346 dpyinfo->nr_net_supported_atoms = 0;
10347 dpyinfo->net_supported_window = 0;
10349 connection = ConnectionNumber (dpyinfo->display);
10350 dpyinfo->connection = connection;
10353 char null_bits[1];
10355 null_bits[0] = 0x00;
10357 dpyinfo->null_pixel
10358 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
10359 null_bits, 1, 1, (long) 0, (long) 0,
10364 extern int gray_bitmap_width, gray_bitmap_height;
10365 extern char *gray_bitmap_bits;
10366 dpyinfo->gray
10367 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
10368 gray_bitmap_bits,
10369 gray_bitmap_width, gray_bitmap_height,
10370 (unsigned long) 1, (unsigned long) 0, 1);
10373 #ifdef HAVE_X_I18N
10374 xim_initialize (dpyinfo, resource_name);
10375 #endif
10377 #ifdef subprocesses
10378 /* This is only needed for distinguishing keyboard and process input. */
10379 if (connection != 0)
10380 add_keyboard_wait_descriptor (connection);
10381 #endif
10383 #ifdef F_SETOWN
10384 fcntl (connection, F_SETOWN, getpid ());
10385 #endif /* ! defined (F_SETOWN) */
10387 #ifdef SIGIO
10388 if (interrupt_input)
10389 init_sigio (connection);
10390 #endif /* ! defined (SIGIO) */
10392 #ifdef USE_LUCID
10394 Display *dpy = dpyinfo->display;
10395 XrmValue d, fr, to;
10396 Font font;
10398 d.addr = (XPointer)&dpy;
10399 d.size = sizeof (Display *);
10400 fr.addr = XtDefaultFont;
10401 fr.size = sizeof (XtDefaultFont);
10402 to.size = sizeof (Font *);
10403 to.addr = (XPointer)&font;
10404 x_catch_errors (dpy);
10405 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
10406 abort ();
10407 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
10408 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
10409 x_uncatch_errors ();
10411 #endif
10413 /* See if we should run in synchronous mode. This is useful
10414 for debugging X code. */
10416 Lisp_Object value;
10417 value = display_x_get_resource (dpyinfo,
10418 build_string ("synchronous"),
10419 build_string ("Synchronous"),
10420 Qnil, Qnil);
10421 if (STRINGP (value)
10422 && (!strcmp (SDATA (value), "true")
10423 || !strcmp (SDATA (value), "on")))
10424 XSynchronize (dpyinfo->display, True);
10428 Lisp_Object value;
10429 value = display_x_get_resource (dpyinfo,
10430 build_string ("useXIM"),
10431 build_string ("UseXIM"),
10432 Qnil, Qnil);
10433 #ifdef USE_XIM
10434 if (STRINGP (value)
10435 && (!strcmp (SDATA (value), "false")
10436 || !strcmp (SDATA (value), "off")))
10437 use_xim = 0;
10438 #else
10439 if (STRINGP (value)
10440 && (!strcmp (SDATA (value), "true")
10441 || !strcmp (SDATA (value), "on")))
10442 use_xim = 1;
10443 #endif
10446 #ifdef HAVE_X_SM
10447 /* Only do this for the very first display in the Emacs session.
10448 Ignore X session management when Emacs was first started on a
10449 tty. */
10450 if (terminal->id == 1)
10451 x_session_initialize (dpyinfo);
10452 #endif
10454 UNBLOCK_INPUT;
10456 return dpyinfo;
10459 /* Get rid of display DPYINFO, deleting all frames on it,
10460 and without sending any more commands to the X server. */
10462 void
10463 x_delete_display (dpyinfo)
10464 struct x_display_info *dpyinfo;
10466 int i;
10467 struct terminal *t;
10469 /* Close all frames and delete the generic struct terminal for this
10470 X display. */
10471 for (t = terminal_list; t; t = t->next_terminal)
10472 if (t->type == output_x_window && t->display_info.x == dpyinfo)
10474 #ifdef HAVE_X_SM
10475 /* Close X session management when we close its display. */
10476 if (t->id == 1 && x_session_have_connection ())
10477 x_session_close();
10478 #endif
10479 delete_terminal (t);
10480 break;
10483 delete_keyboard_wait_descriptor (dpyinfo->connection);
10485 /* Discard this display from x_display_name_list and x_display_list.
10486 We can't use Fdelq because that can quit. */
10487 if (! NILP (x_display_name_list)
10488 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
10489 x_display_name_list = XCDR (x_display_name_list);
10490 else
10492 Lisp_Object tail;
10494 tail = x_display_name_list;
10495 while (CONSP (tail) && CONSP (XCDR (tail)))
10497 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
10499 XSETCDR (tail, XCDR (XCDR (tail)));
10500 break;
10502 tail = XCDR (tail);
10506 if (next_noop_dpyinfo == dpyinfo)
10507 next_noop_dpyinfo = dpyinfo->next;
10509 if (x_display_list == dpyinfo)
10510 x_display_list = dpyinfo->next;
10511 else
10513 struct x_display_info *tail;
10515 for (tail = x_display_list; tail; tail = tail->next)
10516 if (tail->next == dpyinfo)
10517 tail->next = tail->next->next;
10520 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
10521 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
10522 XrmDestroyDatabase (dpyinfo->xrdb);
10523 #endif
10524 #endif
10525 #ifdef HAVE_X_I18N
10526 if (dpyinfo->xim)
10527 xim_close_dpy (dpyinfo);
10528 #endif
10530 xfree (dpyinfo->x_id_name);
10531 xfree (dpyinfo->color_cells);
10532 xfree (dpyinfo);
10535 #ifdef USE_X_TOOLKIT
10537 /* Atimer callback function for TIMER. Called every 0.1s to process
10538 Xt timeouts, if needed. We must avoid calling XtAppPending as
10539 much as possible because that function does an implicit XFlush
10540 that slows us down. */
10542 static void
10543 x_process_timeouts (timer)
10544 struct atimer *timer;
10546 BLOCK_INPUT;
10547 x_timeout_atimer_activated_flag = 0;
10548 if (toolkit_scroll_bar_interaction || popup_activated ())
10550 while (XtAppPending (Xt_app_con) & XtIMTimer)
10551 XtAppProcessEvent (Xt_app_con, XtIMTimer);
10552 /* Reactivate the atimer for next time. */
10553 x_activate_timeout_atimer ();
10555 UNBLOCK_INPUT;
10558 /* Install an asynchronous timer that processes Xt timeout events
10559 every 0.1s as long as either `toolkit_scroll_bar_interaction' or
10560 `popup_activated_flag' (in xmenu.c) is set. Make sure to call this
10561 function whenever these variables are set. This is necessary
10562 because some widget sets use timeouts internally, for example the
10563 LessTif menu bar, or the Xaw3d scroll bar. When Xt timeouts aren't
10564 processed, these widgets don't behave normally. */
10566 void
10567 x_activate_timeout_atimer ()
10569 BLOCK_INPUT;
10570 if (!x_timeout_atimer_activated_flag)
10572 EMACS_TIME interval;
10574 EMACS_SET_SECS_USECS (interval, 0, 100000);
10575 start_atimer (ATIMER_RELATIVE, interval, x_process_timeouts, 0);
10576 x_timeout_atimer_activated_flag = 1;
10578 UNBLOCK_INPUT;
10581 #endif /* USE_X_TOOLKIT */
10584 /* Set up use of X before we make the first connection. */
10586 extern frame_parm_handler x_frame_parm_handlers[];
10588 static struct redisplay_interface x_redisplay_interface =
10590 x_frame_parm_handlers,
10591 x_produce_glyphs,
10592 x_write_glyphs,
10593 x_insert_glyphs,
10594 x_clear_end_of_line,
10595 x_scroll_run,
10596 x_after_update_window_line,
10597 x_update_window_begin,
10598 x_update_window_end,
10599 x_cursor_to,
10600 x_flush,
10601 #ifdef XFlush
10602 x_flush,
10603 #else
10604 0, /* flush_display_optional */
10605 #endif
10606 x_clear_window_mouse_face,
10607 x_get_glyph_overhangs,
10608 x_fix_overlapping_area,
10609 x_draw_fringe_bitmap,
10610 0, /* define_fringe_bitmap */
10611 0, /* destroy_fringe_bitmap */
10612 x_compute_glyph_string_overhangs,
10613 x_draw_glyph_string,
10614 x_define_frame_cursor,
10615 x_clear_frame_area,
10616 x_draw_window_cursor,
10617 x_draw_vertical_window_border,
10618 x_shift_glyphs_for_insert
10622 /* This function is called when the last frame on a display is deleted. */
10623 void
10624 x_delete_terminal (struct terminal *terminal)
10626 struct x_display_info *dpyinfo = terminal->display_info.x;
10627 int i;
10629 /* Protect against recursive calls. Fdelete_frame in
10630 delete_terminal calls us back when it deletes our last frame. */
10631 if (!terminal->name)
10632 return;
10634 BLOCK_INPUT;
10635 /* If called from x_connection_closed, the display may already be closed
10636 and dpyinfo->display was set to 0 to indicate that. */
10637 if (dpyinfo->display)
10639 x_destroy_all_bitmaps (dpyinfo);
10640 XSetCloseDownMode (dpyinfo->display, DestroyAll);
10642 #ifdef USE_GTK
10643 xg_display_close (dpyinfo->display);
10644 #else
10645 #ifdef USE_X_TOOLKIT
10646 XtCloseDisplay (dpyinfo->display);
10647 #else
10648 XCloseDisplay (dpyinfo->display);
10649 #endif
10650 #endif /* ! USE_GTK */
10653 x_delete_display (dpyinfo);
10654 UNBLOCK_INPUT;
10657 /* Create a struct terminal, initialize it with the X11 specific
10658 functions and make DISPLAY->TERMINAL point to it. */
10660 static struct terminal *
10661 x_create_terminal (struct x_display_info *dpyinfo)
10663 struct terminal *terminal;
10665 terminal = create_terminal ();
10667 terminal->type = output_x_window;
10668 terminal->display_info.x = dpyinfo;
10669 dpyinfo->terminal = terminal;
10671 /* kboard is initialized in x_term_init. */
10673 terminal->clear_frame_hook = x_clear_frame;
10674 terminal->ins_del_lines_hook = x_ins_del_lines;
10675 terminal->delete_glyphs_hook = x_delete_glyphs;
10676 terminal->ring_bell_hook = XTring_bell;
10677 terminal->reset_terminal_modes_hook = XTreset_terminal_modes;
10678 terminal->set_terminal_modes_hook = XTset_terminal_modes;
10679 terminal->update_begin_hook = x_update_begin;
10680 terminal->update_end_hook = x_update_end;
10681 terminal->set_terminal_window_hook = XTset_terminal_window;
10682 terminal->read_socket_hook = XTread_socket;
10683 terminal->frame_up_to_date_hook = XTframe_up_to_date;
10684 terminal->mouse_position_hook = XTmouse_position;
10685 terminal->frame_rehighlight_hook = XTframe_rehighlight;
10686 terminal->frame_raise_lower_hook = XTframe_raise_lower;
10687 terminal->fullscreen_hook = XTfullscreen_hook;
10688 terminal->set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
10689 terminal->condemn_scroll_bars_hook = XTcondemn_scroll_bars;
10690 terminal->redeem_scroll_bar_hook = XTredeem_scroll_bar;
10691 terminal->judge_scroll_bars_hook = XTjudge_scroll_bars;
10693 terminal->delete_frame_hook = x_destroy_window;
10694 terminal->delete_terminal_hook = x_delete_terminal;
10696 terminal->rif = &x_redisplay_interface;
10697 terminal->scroll_region_ok = 1; /* We'll scroll partial frames. */
10698 terminal->char_ins_del_ok = 1;
10699 terminal->line_ins_del_ok = 1; /* We'll just blt 'em. */
10700 terminal->fast_clear_end_of_line = 1; /* X does this well. */
10701 terminal->memory_below_frame = 0; /* We don't remember what scrolls
10702 off the bottom. */
10704 return terminal;
10707 void
10708 x_initialize ()
10710 baud_rate = 19200;
10712 x_noop_count = 0;
10713 last_tool_bar_item = -1;
10714 any_help_event_p = 0;
10715 ignore_next_mouse_click_timeout = 0;
10716 #ifdef HAVE_X_SM
10717 x_session_initialized = 0;
10718 #endif
10720 #ifdef USE_GTK
10721 current_count = -1;
10722 #endif
10724 /* Try to use interrupt input; if we can't, then start polling. */
10725 Fset_input_interrupt_mode (Qt);
10727 #ifdef USE_X_TOOLKIT
10728 XtToolkitInitialize ();
10730 Xt_app_con = XtCreateApplicationContext ();
10732 /* Register a converter from strings to pixels, which uses
10733 Emacs' color allocation infrastructure. */
10734 XtAppSetTypeConverter (Xt_app_con,
10735 XtRString, XtRPixel, cvt_string_to_pixel,
10736 cvt_string_to_pixel_args,
10737 XtNumber (cvt_string_to_pixel_args),
10738 XtCacheByDisplay, cvt_pixel_dtor);
10740 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
10741 #endif
10743 #ifdef USE_TOOLKIT_SCROLL_BARS
10744 #ifndef USE_GTK
10745 xaw3d_arrow_scroll = False;
10746 xaw3d_pick_top = True;
10747 #endif
10748 #endif
10750 /* Note that there is no real way portable across R3/R4 to get the
10751 original error handler. */
10752 XSetErrorHandler (x_error_handler);
10753 XSetIOErrorHandler (x_io_error_quitter);
10755 /* Disable Window Change signals; they are handled by X events. */
10756 #if 0 /* Don't. We may want to open tty frames later. */
10757 #ifdef SIGWINCH
10758 signal (SIGWINCH, SIG_DFL);
10759 #endif /* SIGWINCH */
10760 #endif
10762 signal (SIGPIPE, x_connection_signal);
10766 void
10767 syms_of_xterm ()
10769 x_error_message = NULL;
10771 staticpro (&x_display_name_list);
10772 x_display_name_list = Qnil;
10774 staticpro (&last_mouse_scroll_bar);
10775 last_mouse_scroll_bar = Qnil;
10777 staticpro (&Qvendor_specific_keysyms);
10778 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
10780 staticpro (&Qlatin_1);
10781 Qlatin_1 = intern ("latin-1");
10783 staticpro (&last_mouse_press_frame);
10784 last_mouse_press_frame = Qnil;
10786 DEFVAR_BOOL ("x-use-underline-position-properties",
10787 &x_use_underline_position_properties,
10788 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
10789 A value of nil means ignore them. If you encounter fonts with bogus
10790 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
10791 to 4.1, set this to nil. You can also use `underline-minimum-offset'
10792 to override the font's UNDERLINE_POSITION for small font display
10793 sizes. */);
10794 x_use_underline_position_properties = 1;
10796 DEFVAR_BOOL ("x-underline-at-descent-line",
10797 &x_underline_at_descent_line,
10798 doc: /* *Non-nil means to draw the underline at the same place as the descent line.
10799 A value of nil means to draw the underline according to the value of the
10800 variable `x-use-underline-position-properties', which is usually at the
10801 baseline level. The default value is nil. */);
10802 x_underline_at_descent_line = 0;
10804 DEFVAR_BOOL ("x-mouse-click-focus-ignore-position",
10805 &x_mouse_click_focus_ignore_position,
10806 doc: /* Non-nil means that a mouse click to focus a frame does not move point.
10807 This variable is only used when the window manager requires that you
10808 click on a frame to select it (give it focus). In that case, a value
10809 of nil, means that the selected window and cursor position changes to
10810 reflect the mouse click position, while a non-nil value means that the
10811 selected window or cursor position is preserved. */);
10812 x_mouse_click_focus_ignore_position = 0;
10814 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
10815 doc: /* What X toolkit scroll bars Emacs uses.
10816 A value of nil means Emacs doesn't use X toolkit scroll bars.
10817 Otherwise, value is a symbol describing the X toolkit. */);
10818 #ifdef USE_TOOLKIT_SCROLL_BARS
10819 #ifdef USE_MOTIF
10820 Vx_toolkit_scroll_bars = intern ("motif");
10821 #elif defined HAVE_XAW3D
10822 Vx_toolkit_scroll_bars = intern ("xaw3d");
10823 #elif USE_GTK
10824 Vx_toolkit_scroll_bars = intern ("gtk");
10825 #else
10826 Vx_toolkit_scroll_bars = intern ("xaw");
10827 #endif
10828 #else
10829 Vx_toolkit_scroll_bars = Qnil;
10830 #endif
10832 staticpro (&last_mouse_motion_frame);
10833 last_mouse_motion_frame = Qnil;
10835 Qmodifier_value = intern ("modifier-value");
10836 Qalt = intern ("alt");
10837 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
10838 Qhyper = intern ("hyper");
10839 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
10840 Qmeta = intern ("meta");
10841 Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
10842 Qsuper = intern ("super");
10843 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
10845 DEFVAR_LISP ("x-alt-keysym", &Vx_alt_keysym,
10846 doc: /* Which keys Emacs uses for the alt modifier.
10847 This should be one of the symbols `alt', `hyper', `meta', `super'.
10848 For example, `alt' means use the Alt_L and Alt_R keysyms. The default
10849 is nil, which is the same as `alt'. */);
10850 Vx_alt_keysym = Qnil;
10852 DEFVAR_LISP ("x-hyper-keysym", &Vx_hyper_keysym,
10853 doc: /* Which keys Emacs uses for the hyper modifier.
10854 This should be one of the symbols `alt', `hyper', `meta', `super'.
10855 For example, `hyper' means use the Hyper_L and Hyper_R keysyms. The
10856 default is nil, which is the same as `hyper'. */);
10857 Vx_hyper_keysym = Qnil;
10859 DEFVAR_LISP ("x-meta-keysym", &Vx_meta_keysym,
10860 doc: /* Which keys Emacs uses for the meta modifier.
10861 This should be one of the symbols `alt', `hyper', `meta', `super'.
10862 For example, `meta' means use the Meta_L and Meta_R keysyms. The
10863 default is nil, which is the same as `meta'. */);
10864 Vx_meta_keysym = Qnil;
10866 DEFVAR_LISP ("x-super-keysym", &Vx_super_keysym,
10867 doc: /* Which keys Emacs uses for the super modifier.
10868 This should be one of the symbols `alt', `hyper', `meta', `super'.
10869 For example, `super' means use the Super_L and Super_R keysyms. The
10870 default is nil, which is the same as `super'. */);
10871 Vx_super_keysym = Qnil;
10873 DEFVAR_LISP ("x-keysym-table", &Vx_keysym_table,
10874 doc: /* Hash table of character codes indexed by X keysym codes. */);
10875 Vx_keysym_table = make_hash_table (Qeql, make_number (900),
10876 make_float (DEFAULT_REHASH_SIZE),
10877 make_float (DEFAULT_REHASH_THRESHOLD),
10878 Qnil, Qnil, Qnil);
10881 #endif /* HAVE_X_WINDOWS */
10883 /* arch-tag: 6d4e4cb7-abc1-4302-9585-d84dcfb09d0f
10884 (do not change this comment) */