Misc doc fixes for Dired.
[emacs.git] / src / xterm.c
blobfec661625f2bd65e163f0f02d018d5389ad83353
1 /* X Communication module for terminals which understand the X protocol.
3 Copyright (C) 1989, 1993-2012 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20 /* New display code by Gerd Moellmann <gerd@gnu.org>. */
21 /* Xt features made by Fred Pierresteguy. */
23 #include <config.h>
24 #include <signal.h>
25 #include <stdio.h>
26 #include <setjmp.h>
28 #ifdef HAVE_X_WINDOWS
30 #include "lisp.h"
31 #include "blockinput.h"
33 /* Need syssignal.h for various externs and definitions that may be required
34 by some configurations for calls to signal later in this source file. */
35 #include "syssignal.h"
37 /* This may include sys/types.h, and that somehow loses
38 if this is not done before the other system files. */
39 #include "xterm.h"
40 #include <X11/cursorfont.h>
42 /* Load sys/types.h if not already loaded.
43 In some systems loading it twice is suicidal. */
44 #ifndef makedev
45 #include <sys/types.h>
46 #endif /* makedev */
48 #include <sys/ioctl.h>
50 #include "systime.h"
52 #include <fcntl.h>
53 #include <ctype.h>
54 #include <errno.h>
55 #include <setjmp.h>
56 #include <sys/stat.h>
57 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
58 /* #include <sys/param.h> */
60 #include "charset.h"
61 #include "character.h"
62 #include "coding.h"
63 #include "frame.h"
64 #include "dispextern.h"
65 #include "fontset.h"
66 #include "termhooks.h"
67 #include "termopts.h"
68 #include "termchar.h"
69 #include "emacs-icon.h"
70 #include "disptab.h"
71 #include "buffer.h"
72 #include "window.h"
73 #include "keyboard.h"
74 #include "intervals.h"
75 #include "process.h"
76 #include "atimer.h"
77 #include "keymap.h"
78 #include "font.h"
79 #include "fontset.h"
80 #include "xsettings.h"
81 #include "xgselect.h"
82 #include "sysselect.h"
84 #ifdef USE_X_TOOLKIT
85 #include <X11/Shell.h>
86 #endif
88 #ifdef HAVE_SYS_TIME_H
89 #include <sys/time.h>
90 #endif
92 #include <unistd.h>
94 #ifdef USE_GTK
95 #include "gtkutil.h"
96 #ifdef HAVE_GTK3
97 #include <X11/Xproto.h>
98 #endif
99 #endif
101 #ifdef USE_LUCID
102 #include "../lwlib/xlwmenu.h"
103 #endif
105 #ifdef USE_X_TOOLKIT
106 #if !defined (NO_EDITRES)
107 #define HACK_EDITRES
108 extern void _XEditResCheckMessages (Widget, XtPointer, XEvent *, Boolean *);
109 #endif /* not NO_EDITRES */
111 /* Include toolkit specific headers for the scroll bar widget. */
113 #ifdef USE_TOOLKIT_SCROLL_BARS
114 #if defined USE_MOTIF
115 #include <Xm/Xm.h> /* for LESSTIF_VERSION */
116 #include <Xm/ScrollBar.h>
117 #else /* !USE_MOTIF i.e. use Xaw */
119 #ifdef HAVE_XAW3D
120 #include <X11/Xaw3d/Simple.h>
121 #include <X11/Xaw3d/Scrollbar.h>
122 #include <X11/Xaw3d/ThreeD.h>
123 #else /* !HAVE_XAW3D */
124 #include <X11/Xaw/Simple.h>
125 #include <X11/Xaw/Scrollbar.h>
126 #endif /* !HAVE_XAW3D */
127 #ifndef XtNpickTop
128 #define XtNpickTop "pickTop"
129 #endif /* !XtNpickTop */
130 #endif /* !USE_MOTIF */
131 #endif /* USE_TOOLKIT_SCROLL_BARS */
133 #endif /* USE_X_TOOLKIT */
135 #ifdef USE_X_TOOLKIT
136 #include "widget.h"
137 #ifndef XtNinitialState
138 #define XtNinitialState "initialState"
139 #endif
140 #endif
142 #include "bitmaps/gray.xbm"
144 /* Default to using XIM if available. */
145 #ifdef USE_XIM
146 int use_xim = 1;
147 #else
148 int use_xim = 0; /* configure --without-xim */
149 #endif
153 /* Non-zero means that a HELP_EVENT has been generated since Emacs
154 start. */
156 static int any_help_event_p;
158 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
159 static Lisp_Object last_window;
161 /* This is a chain of structures for all the X displays currently in
162 use. */
164 struct x_display_info *x_display_list;
166 /* This is a list of cons cells, each of the form (NAME
167 . FONT-LIST-CACHE), one for each element of x_display_list and in
168 the same order. NAME is the name of the frame. FONT-LIST-CACHE
169 records previous values returned by x-list-fonts. */
171 Lisp_Object x_display_name_list;
173 /* Frame being updated by update_frame. This is declared in term.c.
174 This is set by update_begin and looked at by all the XT functions.
175 It is zero while not inside an update. In that case, the XT
176 functions assume that `selected_frame' is the frame to apply to. */
178 extern struct frame *updating_frame;
180 /* This is a frame waiting to be auto-raised, within XTread_socket. */
182 static struct frame *pending_autoraise_frame;
184 /* This is a frame waiting for an event matching mask, within XTread_socket. */
186 static struct {
187 struct frame *f;
188 int eventtype;
189 } pending_event_wait;
191 #ifdef USE_X_TOOLKIT
192 /* The application context for Xt use. */
193 XtAppContext Xt_app_con;
194 static String Xt_default_resources[] = {0};
196 /* Non-zero means user is interacting with a toolkit scroll bar. */
198 static int toolkit_scroll_bar_interaction;
199 #endif /* USE_X_TOOLKIT */
201 /* Non-zero timeout value means ignore next mouse click if it arrives
202 before that timeout elapses (i.e. as part of the same sequence of
203 events resulting from clicking on a frame to select it). */
205 static unsigned long ignore_next_mouse_click_timeout;
207 /* Mouse movement.
209 Formerly, we used PointerMotionHintMask (in standard_event_mask)
210 so that we would have to call XQueryPointer after each MotionNotify
211 event to ask for another such event. However, this made mouse tracking
212 slow, and there was a bug that made it eventually stop.
214 Simply asking for MotionNotify all the time seems to work better.
216 In order to avoid asking for motion events and then throwing most
217 of them away or busy-polling the server for mouse positions, we ask
218 the server for pointer motion hints. This means that we get only
219 one event per group of mouse movements. "Groups" are delimited by
220 other kinds of events (focus changes and button clicks, for
221 example), or by XQueryPointer calls; when one of these happens, we
222 get another MotionNotify event the next time the mouse moves. This
223 is at least as efficient as getting motion events when mouse
224 tracking is on, and I suspect only negligibly worse when tracking
225 is off. */
227 /* Where the mouse was last time we reported a mouse event. */
229 static XRectangle last_mouse_glyph;
230 static FRAME_PTR last_mouse_glyph_frame;
231 static Lisp_Object last_mouse_press_frame;
233 /* The scroll bar in which the last X motion event occurred.
235 If the last X motion event occurred in a scroll bar, we set this so
236 XTmouse_position can know whether to report a scroll bar motion or
237 an ordinary motion.
239 If the last X motion event didn't occur in a scroll bar, we set
240 this to Qnil, to tell XTmouse_position to return an ordinary motion
241 event. */
243 static Lisp_Object last_mouse_scroll_bar;
245 /* This is a hack. We would really prefer that XTmouse_position would
246 return the time associated with the position it returns, but there
247 doesn't seem to be any way to wrest the time-stamp from the server
248 along with the position query. So, we just keep track of the time
249 of the last movement we received, and return that in hopes that
250 it's somewhat accurate. */
252 static Time last_mouse_movement_time;
254 /* Time for last user interaction as returned in X events. */
256 static Time last_user_time;
258 /* Incremented by XTread_socket whenever it really tries to read
259 events. */
261 static int volatile input_signal_count;
263 /* Used locally within XTread_socket. */
265 static int x_noop_count;
267 static Lisp_Object Qalt, Qhyper, Qmeta, Qsuper, Qmodifier_value;
269 static Lisp_Object Qvendor_specific_keysyms;
270 static Lisp_Object Qlatin_1;
272 #ifdef USE_GTK
273 /* The name of the Emacs icon file. */
274 static Lisp_Object xg_default_icon_file;
276 /* Used in gtkutil.c. */
277 Lisp_Object Qx_gtk_map_stock;
278 #endif
280 /* Some functions take this as char *, not const char *. */
281 static char emacs_class[] = EMACS_CLASS;
283 enum xembed_info
285 XEMBED_MAPPED = 1 << 0
288 enum xembed_message
290 XEMBED_EMBEDDED_NOTIFY = 0,
291 XEMBED_WINDOW_ACTIVATE = 1,
292 XEMBED_WINDOW_DEACTIVATE = 2,
293 XEMBED_REQUEST_FOCUS = 3,
294 XEMBED_FOCUS_IN = 4,
295 XEMBED_FOCUS_OUT = 5,
296 XEMBED_FOCUS_NEXT = 6,
297 XEMBED_FOCUS_PREV = 7,
299 XEMBED_MODALITY_ON = 10,
300 XEMBED_MODALITY_OFF = 11,
301 XEMBED_REGISTER_ACCELERATOR = 12,
302 XEMBED_UNREGISTER_ACCELERATOR = 13,
303 XEMBED_ACTIVATE_ACCELERATOR = 14
306 /* Used in x_flush. */
308 static int x_alloc_nearest_color_1 (Display *, Colormap, XColor *);
309 static void x_set_window_size_1 (struct frame *, int, int, int);
310 static void x_raise_frame (struct frame *);
311 static void x_lower_frame (struct frame *);
312 static const XColor *x_color_cells (Display *, int *);
313 static void x_update_window_end (struct window *, int, int);
315 static int x_io_error_quitter (Display *);
316 static struct terminal *x_create_terminal (struct x_display_info *);
317 void x_delete_terminal (struct terminal *);
318 static void x_update_end (struct frame *);
319 static void XTframe_up_to_date (struct frame *);
320 static void XTset_terminal_modes (struct terminal *);
321 static void XTreset_terminal_modes (struct terminal *);
322 static void x_clear_frame (struct frame *);
323 static void x_ins_del_lines (struct frame *, int, int) NO_RETURN;
324 static void frame_highlight (struct frame *);
325 static void frame_unhighlight (struct frame *);
326 static void x_new_focus_frame (struct x_display_info *, struct frame *);
327 static void x_focus_changed (int, int, struct x_display_info *,
328 struct frame *, struct input_event *);
329 static void x_detect_focus_change (struct x_display_info *,
330 XEvent *, struct input_event *);
331 static void XTframe_rehighlight (struct frame *);
332 static void x_frame_rehighlight (struct x_display_info *);
333 static void x_draw_hollow_cursor (struct window *, struct glyph_row *);
334 static void x_draw_bar_cursor (struct window *, struct glyph_row *, int,
335 enum text_cursor_kinds);
337 static void x_clip_to_row (struct window *, struct glyph_row *, int, GC);
338 static void x_flush (struct frame *f);
339 static void x_update_begin (struct frame *);
340 static void x_update_window_begin (struct window *);
341 static void x_after_update_window_line (struct glyph_row *);
342 static struct scroll_bar *x_window_to_scroll_bar (Display *, Window);
343 static void x_scroll_bar_report_motion (struct frame **, Lisp_Object *,
344 enum scroll_bar_part *,
345 Lisp_Object *, Lisp_Object *,
346 Time *);
347 static int x_handle_net_wm_state (struct frame *, XPropertyEvent *);
348 static void x_check_fullscreen (struct frame *);
349 static void x_check_expected_move (struct frame *, int, int);
350 static void x_sync_with_move (struct frame *, int, int, int);
351 static int handle_one_xevent (struct x_display_info *, XEvent *,
352 int *, struct input_event *);
353 #ifdef USE_GTK
354 static int x_dispatch_event (XEvent *, Display *);
355 #endif
356 /* Don't declare this NO_RETURN because we want no
357 interference with debugging failing X calls. */
358 static void x_connection_closed (Display *, const char *);
359 static void x_wm_set_window_state (struct frame *, int);
360 static void x_wm_set_icon_pixmap (struct frame *, ptrdiff_t);
361 static void x_initialize (void);
364 /* Flush display of frame F, or of all frames if F is null. */
366 static void
367 x_flush (struct frame *f)
369 /* Don't call XFlush when it is not safe to redisplay; the X
370 connection may be broken. */
371 if (!NILP (Vinhibit_redisplay))
372 return;
374 BLOCK_INPUT;
375 if (f == NULL)
377 Lisp_Object rest, frame;
378 FOR_EACH_FRAME (rest, frame)
379 if (FRAME_X_P (XFRAME (frame)))
380 x_flush (XFRAME (frame));
382 else if (FRAME_X_P (f))
383 XFlush (FRAME_X_DISPLAY (f));
384 UNBLOCK_INPUT;
388 /* Remove calls to XFlush by defining XFlush to an empty replacement.
389 Calls to XFlush should be unnecessary because the X output buffer
390 is flushed automatically as needed by calls to XPending,
391 XNextEvent, or XWindowEvent according to the XFlush man page.
392 XTread_socket calls XPending. Removing XFlush improves
393 performance. */
395 #define XFlush(DISPLAY) (void) 0
398 /***********************************************************************
399 Debugging
400 ***********************************************************************/
402 #if 0
404 /* This is a function useful for recording debugging information about
405 the sequence of occurrences in this file. */
407 struct record
409 char *locus;
410 int type;
413 struct record event_record[100];
415 int event_record_index;
417 void
418 record_event (char *locus, int type)
420 if (event_record_index == sizeof (event_record) / sizeof (struct record))
421 event_record_index = 0;
423 event_record[event_record_index].locus = locus;
424 event_record[event_record_index].type = type;
425 event_record_index++;
428 #endif /* 0 */
432 /* Return the struct x_display_info corresponding to DPY. */
434 struct x_display_info *
435 x_display_info_for_display (Display *dpy)
437 struct x_display_info *dpyinfo;
439 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
440 if (dpyinfo->display == dpy)
441 return dpyinfo;
443 return 0;
446 static Window
447 x_find_topmost_parent (struct frame *f)
449 struct x_output *x = f->output_data.x;
450 Window win = None, wi = x->parent_desc;
451 Display *dpy = FRAME_X_DISPLAY (f);
453 while (wi != FRAME_X_DISPLAY_INFO (f)->root_window)
455 Window root;
456 Window *children;
457 unsigned int nchildren;
459 win = wi;
460 XQueryTree (dpy, win, &root, &wi, &children, &nchildren);
461 XFree (children);
464 return win;
467 #define OPAQUE 0xffffffff
469 void
470 x_set_frame_alpha (struct frame *f)
472 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
473 Display *dpy = FRAME_X_DISPLAY (f);
474 Window win = FRAME_OUTER_WINDOW (f);
475 double alpha = 1.0;
476 double alpha_min = 1.0;
477 unsigned long opac;
478 Window parent;
480 if (dpyinfo->x_highlight_frame == f)
481 alpha = f->alpha[0];
482 else
483 alpha = f->alpha[1];
485 if (FLOATP (Vframe_alpha_lower_limit))
486 alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit);
487 else if (INTEGERP (Vframe_alpha_lower_limit))
488 alpha_min = (XINT (Vframe_alpha_lower_limit)) / 100.0;
490 if (alpha < 0.0)
491 return;
492 else if (alpha > 1.0)
493 alpha = 1.0;
494 else if (0.0 <= alpha && alpha < alpha_min && alpha_min <= 1.0)
495 alpha = alpha_min;
497 opac = alpha * OPAQUE;
499 x_catch_errors (dpy);
501 /* If there is a parent from the window manager, put the property there
502 also, to work around broken window managers that fail to do that.
503 Do this unconditionally as this function is called on reparent when
504 alpha has not changed on the frame. */
506 parent = x_find_topmost_parent (f);
507 if (parent != None)
508 XChangeProperty (dpy, parent, dpyinfo->Xatom_net_wm_window_opacity,
509 XA_CARDINAL, 32, PropModeReplace,
510 (unsigned char *) &opac, 1L);
512 /* return unless necessary */
514 unsigned char *data;
515 Atom actual;
516 int rc, format;
517 unsigned long n, left;
519 rc = XGetWindowProperty (dpy, win, dpyinfo->Xatom_net_wm_window_opacity,
520 0L, 1L, False, XA_CARDINAL,
521 &actual, &format, &n, &left,
522 &data);
524 if (rc == Success && actual != None)
526 unsigned long value = *(unsigned long *)data;
527 XFree ((void *) data);
528 if (value == opac)
530 x_uncatch_errors ();
531 return;
536 XChangeProperty (dpy, win, dpyinfo->Xatom_net_wm_window_opacity,
537 XA_CARDINAL, 32, PropModeReplace,
538 (unsigned char *) &opac, 1L);
539 x_uncatch_errors ();
543 x_display_pixel_height (struct x_display_info *dpyinfo)
545 return HeightOfScreen (dpyinfo->screen);
549 x_display_pixel_width (struct x_display_info *dpyinfo)
551 return WidthOfScreen (dpyinfo->screen);
555 /***********************************************************************
556 Starting and ending an update
557 ***********************************************************************/
559 /* Start an update of frame F. This function is installed as a hook
560 for update_begin, i.e. it is called when update_begin is called.
561 This function is called prior to calls to x_update_window_begin for
562 each window being updated. Currently, there is nothing to do here
563 because all interesting stuff is done on a window basis. */
565 static void
566 x_update_begin (struct frame *f)
568 /* Nothing to do. */
572 /* Start update of window W. Set the global variable updated_window
573 to the window being updated and set output_cursor to the cursor
574 position of W. */
576 static void
577 x_update_window_begin (struct window *w)
579 struct frame *f = XFRAME (WINDOW_FRAME (w));
580 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
582 updated_window = w;
583 set_output_cursor (&w->cursor);
585 BLOCK_INPUT;
587 if (f == hlinfo->mouse_face_mouse_frame)
589 /* Don't do highlighting for mouse motion during the update. */
590 hlinfo->mouse_face_defer = 1;
592 /* If F needs to be redrawn, simply forget about any prior mouse
593 highlighting. */
594 if (FRAME_GARBAGED_P (f))
595 hlinfo->mouse_face_window = Qnil;
598 UNBLOCK_INPUT;
602 /* Draw a vertical window border from (x,y0) to (x,y1) */
604 static void
605 x_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
607 struct frame *f = XFRAME (WINDOW_FRAME (w));
608 struct face *face;
610 face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
611 if (face)
612 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
613 face->foreground);
615 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
616 f->output_data.x->normal_gc, x, y0, x, y1);
619 /* End update of window W (which is equal to updated_window).
621 Draw vertical borders between horizontally adjacent windows, and
622 display W's cursor if CURSOR_ON_P is non-zero.
624 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
625 glyphs in mouse-face were overwritten. In that case we have to
626 make sure that the mouse-highlight is properly redrawn.
628 W may be a menu bar pseudo-window in case we don't have X toolkit
629 support. Such windows don't have a cursor, so don't display it
630 here. */
632 static void
633 x_update_window_end (struct window *w, int cursor_on_p, int mouse_face_overwritten_p)
635 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
637 if (!w->pseudo_window_p)
639 BLOCK_INPUT;
641 if (cursor_on_p)
642 display_and_set_cursor (w, 1, output_cursor.hpos,
643 output_cursor.vpos,
644 output_cursor.x, output_cursor.y);
646 if (draw_window_fringes (w, 1))
647 x_draw_vertical_border (w);
649 UNBLOCK_INPUT;
652 /* If a row with mouse-face was overwritten, arrange for
653 XTframe_up_to_date to redisplay the mouse highlight. */
654 if (mouse_face_overwritten_p)
656 hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
657 hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
658 hlinfo->mouse_face_window = Qnil;
661 updated_window = NULL;
665 /* End update of frame F. This function is installed as a hook in
666 update_end. */
668 static void
669 x_update_end (struct frame *f)
671 /* Mouse highlight may be displayed again. */
672 MOUSE_HL_INFO (f)->mouse_face_defer = 0;
674 #ifndef XFlush
675 BLOCK_INPUT;
676 XFlush (FRAME_X_DISPLAY (f));
677 UNBLOCK_INPUT;
678 #endif
682 /* This function is called from various places in xdisp.c whenever a
683 complete update has been performed. The global variable
684 updated_window is not available here. */
686 static void
687 XTframe_up_to_date (struct frame *f)
689 if (FRAME_X_P (f))
691 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
693 if (hlinfo->mouse_face_deferred_gc
694 || f == hlinfo->mouse_face_mouse_frame)
696 BLOCK_INPUT;
697 if (hlinfo->mouse_face_mouse_frame)
698 note_mouse_highlight (hlinfo->mouse_face_mouse_frame,
699 hlinfo->mouse_face_mouse_x,
700 hlinfo->mouse_face_mouse_y);
701 hlinfo->mouse_face_deferred_gc = 0;
702 UNBLOCK_INPUT;
708 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
709 arrow bitmaps, or clear the fringes if no bitmaps are required
710 before DESIRED_ROW is made current. The window being updated is
711 found in updated_window. This function It is called from
712 update_window_line only if it is known that there are differences
713 between bitmaps to be drawn between current row and DESIRED_ROW. */
715 static void
716 x_after_update_window_line (struct glyph_row *desired_row)
718 struct window *w = updated_window;
719 struct frame *f;
720 int width, height;
722 xassert (w);
724 if (!desired_row->mode_line_p && !w->pseudo_window_p)
725 desired_row->redraw_fringe_bitmaps_p = 1;
727 /* When a window has disappeared, make sure that no rest of
728 full-width rows stays visible in the internal border. Could
729 check here if updated_window is the leftmost/rightmost window,
730 but I guess it's not worth doing since vertically split windows
731 are almost never used, internal border is rarely set, and the
732 overhead is very small. */
733 if (windows_or_buffers_changed
734 && desired_row->full_width_p
735 && (f = XFRAME (w->frame),
736 width = FRAME_INTERNAL_BORDER_WIDTH (f),
737 width != 0)
738 && (height = desired_row->visible_height,
739 height > 0))
741 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
743 BLOCK_INPUT;
744 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
745 0, y, width, height, False);
746 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
747 FRAME_PIXEL_WIDTH (f) - width,
748 y, width, height, False);
749 UNBLOCK_INPUT;
753 static void
754 x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fringe_bitmap_params *p)
756 struct frame *f = XFRAME (WINDOW_FRAME (w));
757 Display *display = FRAME_X_DISPLAY (f);
758 Window window = FRAME_X_WINDOW (f);
759 GC gc = f->output_data.x->normal_gc;
760 struct face *face = p->face;
762 /* Must clip because of partially visible lines. */
763 x_clip_to_row (w, row, -1, gc);
765 if (!p->overlay_p)
767 int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
769 /* In case the same realized face is used for fringes and
770 for something displayed in the text (e.g. face `region' on
771 mono-displays, the fill style may have been changed to
772 FillSolid in x_draw_glyph_string_background. */
773 if (face->stipple)
774 XSetFillStyle (display, face->gc, FillOpaqueStippled);
775 else
776 XSetForeground (display, face->gc, face->background);
778 #ifdef USE_TOOLKIT_SCROLL_BARS
779 /* If the fringe is adjacent to the left (right) scroll bar of a
780 leftmost (rightmost, respectively) window, then extend its
781 background to the gap between the fringe and the bar. */
782 if ((WINDOW_LEFTMOST_P (w)
783 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
784 || (WINDOW_RIGHTMOST_P (w)
785 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
787 int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
789 if (sb_width > 0)
791 int bar_area_x = WINDOW_SCROLL_BAR_AREA_X (w);
792 int bar_area_width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
793 * FRAME_COLUMN_WIDTH (f));
795 if (bx < 0)
797 /* Bitmap fills the fringe. */
798 if (bar_area_x + bar_area_width == p->x)
799 bx = bar_area_x + sb_width;
800 else if (p->x + p->wd == bar_area_x)
801 bx = bar_area_x;
802 if (bx >= 0)
804 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
806 nx = bar_area_width - sb_width;
807 by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
808 row->y));
809 ny = row->visible_height;
812 else
814 if (bar_area_x + bar_area_width == bx)
816 bx = bar_area_x + sb_width;
817 nx += bar_area_width - sb_width;
819 else if (bx + nx == bar_area_x)
820 nx += bar_area_width - sb_width;
824 #endif
825 if (bx >= 0 && nx > 0)
826 XFillRectangle (display, window, face->gc, bx, by, nx, ny);
828 if (!face->stipple)
829 XSetForeground (display, face->gc, face->foreground);
832 if (p->which)
834 char *bits;
835 Pixmap pixmap, clipmask = (Pixmap) 0;
836 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
837 XGCValues gcv;
839 if (p->wd > 8)
840 bits = (char *) (p->bits + p->dh);
841 else
842 bits = (char *) p->bits + p->dh;
844 /* Draw the bitmap. I believe these small pixmaps can be cached
845 by the server. */
846 pixmap = XCreatePixmapFromBitmapData (display, window, bits, p->wd, p->h,
847 (p->cursor_p
848 ? (p->overlay_p ? face->background
849 : f->output_data.x->cursor_pixel)
850 : face->foreground),
851 face->background, depth);
853 if (p->overlay_p)
855 clipmask = XCreatePixmapFromBitmapData (display,
856 FRAME_X_DISPLAY_INFO (f)->root_window,
857 bits, p->wd, p->h,
858 1, 0, 1);
859 gcv.clip_mask = clipmask;
860 gcv.clip_x_origin = p->x;
861 gcv.clip_y_origin = p->y;
862 XChangeGC (display, gc, GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv);
865 XCopyArea (display, pixmap, window, gc, 0, 0,
866 p->wd, p->h, p->x, p->y);
867 XFreePixmap (display, pixmap);
869 if (p->overlay_p)
871 gcv.clip_mask = (Pixmap) 0;
872 XChangeGC (display, gc, GCClipMask, &gcv);
873 XFreePixmap (display, clipmask);
877 XSetClipMask (display, gc, None);
882 /* This is called when starting Emacs and when restarting after
883 suspend. When starting Emacs, no X window is mapped. And nothing
884 must be done to Emacs's own window if it is suspended (though that
885 rarely happens). */
887 static void
888 XTset_terminal_modes (struct terminal *terminal)
892 /* This is called when exiting or suspending Emacs. Exiting will make
893 the X-windows go away, and suspending requires no action. */
895 static void
896 XTreset_terminal_modes (struct terminal *terminal)
901 /***********************************************************************
902 Glyph display
903 ***********************************************************************/
907 static void x_set_glyph_string_clipping (struct glyph_string *);
908 static void x_set_glyph_string_gc (struct glyph_string *);
909 static void x_draw_glyph_string_background (struct glyph_string *,
910 int);
911 static void x_draw_glyph_string_foreground (struct glyph_string *);
912 static void x_draw_composite_glyph_string_foreground (struct glyph_string *);
913 static void x_draw_glyph_string_box (struct glyph_string *);
914 static void x_draw_glyph_string (struct glyph_string *);
915 static void x_delete_glyphs (struct frame *, int) NO_RETURN;
916 static void x_compute_glyph_string_overhangs (struct glyph_string *);
917 static void x_set_cursor_gc (struct glyph_string *);
918 static void x_set_mode_line_face_gc (struct glyph_string *);
919 static void x_set_mouse_face_gc (struct glyph_string *);
920 static int x_alloc_lighter_color (struct frame *, Display *, Colormap,
921 unsigned long *, double, int);
922 static void x_setup_relief_color (struct frame *, struct relief *,
923 double, int, unsigned long);
924 static void x_setup_relief_colors (struct glyph_string *);
925 static void x_draw_image_glyph_string (struct glyph_string *);
926 static void x_draw_image_relief (struct glyph_string *);
927 static void x_draw_image_foreground (struct glyph_string *);
928 static void x_draw_image_foreground_1 (struct glyph_string *, Pixmap);
929 static void x_clear_glyph_string_rect (struct glyph_string *, int,
930 int, int, int);
931 static void x_draw_relief_rect (struct frame *, int, int, int, int,
932 int, int, int, int, int, int,
933 XRectangle *);
934 static void x_draw_box_rect (struct glyph_string *, int, int, int, int,
935 int, int, int, XRectangle *);
936 static void x_scroll_bar_clear (struct frame *);
938 #if GLYPH_DEBUG
939 static void x_check_font (struct frame *, struct font *);
940 #endif
943 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
944 face. */
946 static void
947 x_set_cursor_gc (struct glyph_string *s)
949 if (s->font == FRAME_FONT (s->f)
950 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
951 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
952 && !s->cmp)
953 s->gc = s->f->output_data.x->cursor_gc;
954 else
956 /* Cursor on non-default face: must merge. */
957 XGCValues xgcv;
958 unsigned long mask;
960 xgcv.background = s->f->output_data.x->cursor_pixel;
961 xgcv.foreground = s->face->background;
963 /* If the glyph would be invisible, try a different foreground. */
964 if (xgcv.foreground == xgcv.background)
965 xgcv.foreground = s->face->foreground;
966 if (xgcv.foreground == xgcv.background)
967 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
968 if (xgcv.foreground == xgcv.background)
969 xgcv.foreground = s->face->foreground;
971 /* Make sure the cursor is distinct from text in this face. */
972 if (xgcv.background == s->face->background
973 && xgcv.foreground == s->face->foreground)
975 xgcv.background = s->face->foreground;
976 xgcv.foreground = s->face->background;
979 IF_DEBUG (x_check_font (s->f, s->font));
980 xgcv.graphics_exposures = False;
981 mask = GCForeground | GCBackground | GCGraphicsExposures;
983 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
984 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
985 mask, &xgcv);
986 else
987 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
988 = XCreateGC (s->display, s->window, mask, &xgcv);
990 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
995 /* Set up S->gc of glyph string S for drawing text in mouse face. */
997 static void
998 x_set_mouse_face_gc (struct glyph_string *s)
1000 int face_id;
1001 struct face *face;
1003 /* What face has to be used last for the mouse face? */
1004 face_id = MOUSE_HL_INFO (s->f)->mouse_face_face_id;
1005 face = FACE_FROM_ID (s->f, face_id);
1006 if (face == NULL)
1007 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
1009 if (s->first_glyph->type == CHAR_GLYPH)
1010 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch, -1, Qnil);
1011 else
1012 face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil);
1013 s->face = FACE_FROM_ID (s->f, face_id);
1014 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1016 if (s->font == s->face->font)
1017 s->gc = s->face->gc;
1018 else
1020 /* Otherwise construct scratch_cursor_gc with values from FACE
1021 except for FONT. */
1022 XGCValues xgcv;
1023 unsigned long mask;
1025 xgcv.background = s->face->background;
1026 xgcv.foreground = s->face->foreground;
1027 xgcv.graphics_exposures = False;
1028 mask = GCForeground | GCBackground | GCGraphicsExposures;
1030 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1031 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1032 mask, &xgcv);
1033 else
1034 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
1035 = XCreateGC (s->display, s->window, mask, &xgcv);
1037 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1040 xassert (s->gc != 0);
1044 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1045 Faces to use in the mode line have already been computed when the
1046 matrix was built, so there isn't much to do, here. */
1048 static inline void
1049 x_set_mode_line_face_gc (struct glyph_string *s)
1051 s->gc = s->face->gc;
1055 /* Set S->gc of glyph string S for drawing that glyph string. Set
1056 S->stippled_p to a non-zero value if the face of S has a stipple
1057 pattern. */
1059 static inline void
1060 x_set_glyph_string_gc (struct glyph_string *s)
1062 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1064 if (s->hl == DRAW_NORMAL_TEXT)
1066 s->gc = s->face->gc;
1067 s->stippled_p = s->face->stipple != 0;
1069 else if (s->hl == DRAW_INVERSE_VIDEO)
1071 x_set_mode_line_face_gc (s);
1072 s->stippled_p = s->face->stipple != 0;
1074 else if (s->hl == DRAW_CURSOR)
1076 x_set_cursor_gc (s);
1077 s->stippled_p = 0;
1079 else if (s->hl == DRAW_MOUSE_FACE)
1081 x_set_mouse_face_gc (s);
1082 s->stippled_p = s->face->stipple != 0;
1084 else if (s->hl == DRAW_IMAGE_RAISED
1085 || s->hl == DRAW_IMAGE_SUNKEN)
1087 s->gc = s->face->gc;
1088 s->stippled_p = s->face->stipple != 0;
1090 else
1092 s->gc = s->face->gc;
1093 s->stippled_p = s->face->stipple != 0;
1096 /* GC must have been set. */
1097 xassert (s->gc != 0);
1101 /* Set clipping for output of glyph string S. S may be part of a mode
1102 line or menu if we don't have X toolkit support. */
1104 static inline void
1105 x_set_glyph_string_clipping (struct glyph_string *s)
1107 XRectangle *r = s->clip;
1108 int n = get_glyph_string_clip_rects (s, r, 2);
1110 if (n > 0)
1111 XSetClipRectangles (s->display, s->gc, 0, 0, r, n, Unsorted);
1112 s->num_clips = n;
1116 /* Set SRC's clipping for output of glyph string DST. This is called
1117 when we are drawing DST's left_overhang or right_overhang only in
1118 the area of SRC. */
1120 static void
1121 x_set_glyph_string_clipping_exactly (struct glyph_string *src, struct glyph_string *dst)
1123 XRectangle r;
1125 r.x = src->x;
1126 r.width = src->width;
1127 r.y = src->y;
1128 r.height = src->height;
1129 dst->clip[0] = r;
1130 dst->num_clips = 1;
1131 XSetClipRectangles (dst->display, dst->gc, 0, 0, &r, 1, Unsorted);
1135 /* RIF:
1136 Compute left and right overhang of glyph string S. */
1138 static void
1139 x_compute_glyph_string_overhangs (struct glyph_string *s)
1141 if (s->cmp == NULL
1142 && (s->first_glyph->type == CHAR_GLYPH
1143 || s->first_glyph->type == COMPOSITE_GLYPH))
1145 struct font_metrics metrics;
1147 if (s->first_glyph->type == CHAR_GLYPH)
1149 unsigned *code = alloca (sizeof (unsigned) * s->nchars);
1150 struct font *font = s->font;
1151 int i;
1153 for (i = 0; i < s->nchars; i++)
1154 code[i] = (s->char2b[i].byte1 << 8) | s->char2b[i].byte2;
1155 font->driver->text_extents (font, code, s->nchars, &metrics);
1157 else
1159 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
1161 composition_gstring_width (gstring, s->cmp_from, s->cmp_to, &metrics);
1163 s->right_overhang = (metrics.rbearing > metrics.width
1164 ? metrics.rbearing - metrics.width : 0);
1165 s->left_overhang = metrics.lbearing < 0 ? - metrics.lbearing : 0;
1167 else if (s->cmp)
1169 s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width;
1170 s->left_overhang = - s->cmp->lbearing;
1175 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1177 static inline void
1178 x_clear_glyph_string_rect (struct glyph_string *s, int x, int y, int w, int h)
1180 XGCValues xgcv;
1181 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
1182 XSetForeground (s->display, s->gc, xgcv.background);
1183 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
1184 XSetForeground (s->display, s->gc, xgcv.foreground);
1188 /* Draw the background of glyph_string S. If S->background_filled_p
1189 is non-zero don't draw it. FORCE_P non-zero means draw the
1190 background even if it wouldn't be drawn normally. This is used
1191 when a string preceding S draws into the background of S, or S
1192 contains the first component of a composition. */
1194 static void
1195 x_draw_glyph_string_background (struct glyph_string *s, int force_p)
1197 /* Nothing to do if background has already been drawn or if it
1198 shouldn't be drawn in the first place. */
1199 if (!s->background_filled_p)
1201 int box_line_width = max (s->face->box_line_width, 0);
1203 if (s->stippled_p)
1205 /* Fill background with a stipple pattern. */
1206 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
1207 XFillRectangle (s->display, s->window, s->gc, s->x,
1208 s->y + box_line_width,
1209 s->background_width,
1210 s->height - 2 * box_line_width);
1211 XSetFillStyle (s->display, s->gc, FillSolid);
1212 s->background_filled_p = 1;
1214 else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
1215 || s->font_not_found_p
1216 || s->extends_to_end_of_line_p
1217 || force_p)
1219 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
1220 s->background_width,
1221 s->height - 2 * box_line_width);
1222 s->background_filled_p = 1;
1228 /* Draw the foreground of glyph string S. */
1230 static void
1231 x_draw_glyph_string_foreground (struct glyph_string *s)
1233 int i, x;
1235 /* If first glyph of S has a left box line, start drawing the text
1236 of S to the right of that box line. */
1237 if (s->face->box != FACE_NO_BOX
1238 && s->first_glyph->left_box_line_p)
1239 x = s->x + eabs (s->face->box_line_width);
1240 else
1241 x = s->x;
1243 /* Draw characters of S as rectangles if S's font could not be
1244 loaded. */
1245 if (s->font_not_found_p)
1247 for (i = 0; i < s->nchars; ++i)
1249 struct glyph *g = s->first_glyph + i;
1250 XDrawRectangle (s->display, s->window,
1251 s->gc, x, s->y, g->pixel_width - 1,
1252 s->height - 1);
1253 x += g->pixel_width;
1256 else
1258 struct font *font = s->font;
1259 int boff = font->baseline_offset;
1260 int y;
1262 if (font->vertical_centering)
1263 boff = VCENTER_BASELINE_OFFSET (font, s->f) - boff;
1265 y = s->ybase - boff;
1266 if (s->for_overlaps
1267 || (s->background_filled_p && s->hl != DRAW_CURSOR))
1268 font->driver->draw (s, 0, s->nchars, x, y, 0);
1269 else
1270 font->driver->draw (s, 0, s->nchars, x, y, 1);
1271 if (s->face->overstrike)
1272 font->driver->draw (s, 0, s->nchars, x + 1, y, 0);
1276 /* Draw the foreground of composite glyph string S. */
1278 static void
1279 x_draw_composite_glyph_string_foreground (struct glyph_string *s)
1281 int i, j, x;
1282 struct font *font = s->font;
1284 /* If first glyph of S has a left box line, start drawing the text
1285 of S to the right of that box line. */
1286 if (s->face && s->face->box != FACE_NO_BOX
1287 && s->first_glyph->left_box_line_p)
1288 x = s->x + eabs (s->face->box_line_width);
1289 else
1290 x = s->x;
1292 /* S is a glyph string for a composition. S->cmp_from is the index
1293 of the first character drawn for glyphs of this composition.
1294 S->cmp_from == 0 means we are drawing the very first character of
1295 this composition. */
1297 /* Draw a rectangle for the composition if the font for the very
1298 first character of the composition could not be loaded. */
1299 if (s->font_not_found_p)
1301 if (s->cmp_from == 0)
1302 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
1303 s->width - 1, s->height - 1);
1305 else if (! s->first_glyph->u.cmp.automatic)
1307 int y = s->ybase;
1309 for (i = 0, j = s->cmp_from; i < s->nchars; i++, j++)
1310 /* TAB in a composition means display glyphs with padding
1311 space on the left or right. */
1312 if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
1314 int xx = x + s->cmp->offsets[j * 2];
1315 int yy = y - s->cmp->offsets[j * 2 + 1];
1317 font->driver->draw (s, j, j + 1, xx, yy, 0);
1318 if (s->face->overstrike)
1319 font->driver->draw (s, j, j + 1, xx + 1, yy, 0);
1322 else
1324 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
1325 Lisp_Object glyph;
1326 int y = s->ybase;
1327 int width = 0;
1329 for (i = j = s->cmp_from; i < s->cmp_to; i++)
1331 glyph = LGSTRING_GLYPH (gstring, i);
1332 if (NILP (LGLYPH_ADJUSTMENT (glyph)))
1333 width += LGLYPH_WIDTH (glyph);
1334 else
1336 int xoff, yoff, wadjust;
1338 if (j < i)
1340 font->driver->draw (s, j, i, x, y, 0);
1341 if (s->face->overstrike)
1342 font->driver->draw (s, j, i, x + 1, y, 0);
1343 x += width;
1345 xoff = LGLYPH_XOFF (glyph);
1346 yoff = LGLYPH_YOFF (glyph);
1347 wadjust = LGLYPH_WADJUST (glyph);
1348 font->driver->draw (s, i, i + 1, x + xoff, y + yoff, 0);
1349 if (s->face->overstrike)
1350 font->driver->draw (s, i, i + 1, x + xoff + 1, y + yoff, 0);
1351 x += wadjust;
1352 j = i + 1;
1353 width = 0;
1356 if (j < i)
1358 font->driver->draw (s, j, i, x, y, 0);
1359 if (s->face->overstrike)
1360 font->driver->draw (s, j, i, x + 1, y, 0);
1366 /* Draw the foreground of glyph string S for glyphless characters. */
1368 static void
1369 x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
1371 struct glyph *glyph = s->first_glyph;
1372 XChar2b char2b[8];
1373 int x, i, j;
1375 /* If first glyph of S has a left box line, start drawing the text
1376 of S to the right of that box line. */
1377 if (s->face && s->face->box != FACE_NO_BOX
1378 && s->first_glyph->left_box_line_p)
1379 x = s->x + eabs (s->face->box_line_width);
1380 else
1381 x = s->x;
1383 s->char2b = char2b;
1385 for (i = 0; i < s->nchars; i++, glyph++)
1387 char buf[7], *str = NULL;
1388 int len = glyph->u.glyphless.len;
1390 if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM)
1392 if (len > 0
1393 && CHAR_TABLE_P (Vglyphless_char_display)
1394 && (CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display))
1395 >= 1))
1397 Lisp_Object acronym
1398 = (! glyph->u.glyphless.for_no_font
1399 ? CHAR_TABLE_REF (Vglyphless_char_display,
1400 glyph->u.glyphless.ch)
1401 : XCHAR_TABLE (Vglyphless_char_display)->extras[0]);
1402 if (STRINGP (acronym))
1403 str = SSDATA (acronym);
1406 else if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE)
1408 sprintf ((char *) buf, "%0*X",
1409 glyph->u.glyphless.ch < 0x10000 ? 4 : 6,
1410 glyph->u.glyphless.ch);
1411 str = buf;
1414 if (str)
1416 int upper_len = (len + 1) / 2;
1417 unsigned code;
1419 /* It is assured that all LEN characters in STR is ASCII. */
1420 for (j = 0; j < len; j++)
1422 code = s->font->driver->encode_char (s->font, str[j]);
1423 STORE_XCHAR2B (char2b + j, code >> 8, code & 0xFF);
1425 s->font->driver->draw (s, 0, upper_len,
1426 x + glyph->slice.glyphless.upper_xoff,
1427 s->ybase + glyph->slice.glyphless.upper_yoff,
1429 s->font->driver->draw (s, upper_len, len,
1430 x + glyph->slice.glyphless.lower_xoff,
1431 s->ybase + glyph->slice.glyphless.lower_yoff,
1434 if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE)
1435 XDrawRectangle (s->display, s->window, s->gc,
1436 x, s->ybase - glyph->ascent,
1437 glyph->pixel_width - 1,
1438 glyph->ascent + glyph->descent - 1);
1439 x += glyph->pixel_width;
1443 #ifdef USE_X_TOOLKIT
1445 static struct frame *x_frame_of_widget (Widget);
1446 static Boolean cvt_string_to_pixel (Display *, XrmValue *, Cardinal *,
1447 XrmValue *, XrmValue *, XtPointer *);
1448 static void cvt_pixel_dtor (XtAppContext, XrmValue *, XtPointer,
1449 XrmValue *, Cardinal *);
1452 /* Return the frame on which widget WIDGET is used.. Abort if frame
1453 cannot be determined. */
1455 static struct frame *
1456 x_frame_of_widget (Widget widget)
1458 struct x_display_info *dpyinfo;
1459 Lisp_Object tail;
1460 struct frame *f;
1462 dpyinfo = x_display_info_for_display (XtDisplay (widget));
1464 /* Find the top-level shell of the widget. Note that this function
1465 can be called when the widget is not yet realized, so XtWindow
1466 (widget) == 0. That's the reason we can't simply use
1467 x_any_window_to_frame. */
1468 while (!XtIsTopLevelShell (widget))
1469 widget = XtParent (widget);
1471 /* Look for a frame with that top-level widget. Allocate the color
1472 on that frame to get the right gamma correction value. */
1473 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1474 if (FRAMEP (XCAR (tail))
1475 && (f = XFRAME (XCAR (tail)),
1476 (FRAME_X_P (f)
1477 && f->output_data.nothing != 1
1478 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
1479 && f->output_data.x->widget == widget)
1480 return f;
1482 abort ();
1486 #ifdef USE_LUCID
1488 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
1489 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1490 If this produces the same color as PIXEL, try a color where all RGB
1491 values have DELTA added. Return the allocated color in *PIXEL.
1492 DISPLAY is the X display, CMAP is the colormap to operate on.
1493 Value is non-zero if successful. */
1496 x_alloc_lighter_color_for_widget (Widget widget, Display *display, Colormap cmap,
1497 unsigned long *pixel, double factor, int delta)
1499 struct frame *f = x_frame_of_widget (widget);
1500 return x_alloc_lighter_color (f, display, cmap, pixel, factor, delta);
1503 #endif
1506 /* Structure specifying which arguments should be passed by Xt to
1507 cvt_string_to_pixel. We want the widget's screen and colormap. */
1509 static XtConvertArgRec cvt_string_to_pixel_args[] =
1511 {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.screen),
1512 sizeof (Screen *)},
1513 {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.colormap),
1514 sizeof (Colormap)}
1518 /* The address of this variable is returned by
1519 cvt_string_to_pixel. */
1521 static Pixel cvt_string_to_pixel_value;
1524 /* Convert a color name to a pixel color.
1526 DPY is the display we are working on.
1528 ARGS is an array of *NARGS XrmValue structures holding additional
1529 information about the widget for which the conversion takes place.
1530 The contents of this array are determined by the specification
1531 in cvt_string_to_pixel_args.
1533 FROM is a pointer to an XrmValue which points to the color name to
1534 convert. TO is an XrmValue in which to return the pixel color.
1536 CLOSURE_RET is a pointer to user-data, in which we record if
1537 we allocated the color or not.
1539 Value is True if successful, False otherwise. */
1541 static Boolean
1542 cvt_string_to_pixel (Display *dpy, XrmValue *args, Cardinal *nargs,
1543 XrmValue *from, XrmValue *to,
1544 XtPointer *closure_ret)
1546 Screen *screen;
1547 Colormap cmap;
1548 Pixel pixel;
1549 String color_name;
1550 XColor color;
1552 if (*nargs != 2)
1554 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
1555 "wrongParameters", "cvt_string_to_pixel",
1556 "XtToolkitError",
1557 "Screen and colormap args required", NULL, NULL);
1558 return False;
1561 screen = *(Screen **) args[0].addr;
1562 cmap = *(Colormap *) args[1].addr;
1563 color_name = (String) from->addr;
1565 if (strcmp (color_name, XtDefaultBackground) == 0)
1567 *closure_ret = (XtPointer) False;
1568 pixel = WhitePixelOfScreen (screen);
1570 else if (strcmp (color_name, XtDefaultForeground) == 0)
1572 *closure_ret = (XtPointer) False;
1573 pixel = BlackPixelOfScreen (screen);
1575 else if (XParseColor (dpy, cmap, color_name, &color)
1576 && x_alloc_nearest_color_1 (dpy, cmap, &color))
1578 pixel = color.pixel;
1579 *closure_ret = (XtPointer) True;
1581 else
1583 String params[1];
1584 Cardinal nparams = 1;
1586 params[0] = color_name;
1587 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
1588 "badValue", "cvt_string_to_pixel",
1589 "XtToolkitError", "Invalid color `%s'",
1590 params, &nparams);
1591 return False;
1594 if (to->addr != NULL)
1596 if (to->size < sizeof (Pixel))
1598 to->size = sizeof (Pixel);
1599 return False;
1602 *(Pixel *) to->addr = pixel;
1604 else
1606 cvt_string_to_pixel_value = pixel;
1607 to->addr = (XtPointer) &cvt_string_to_pixel_value;
1610 to->size = sizeof (Pixel);
1611 return True;
1615 /* Free a pixel color which was previously allocated via
1616 cvt_string_to_pixel. This is registered as the destructor
1617 for this type of resource via XtSetTypeConverter.
1619 APP is the application context in which we work.
1621 TO is a pointer to an XrmValue holding the color to free.
1622 CLOSURE is the value we stored in CLOSURE_RET for this color
1623 in cvt_string_to_pixel.
1625 ARGS and NARGS are like for cvt_string_to_pixel. */
1627 static void
1628 cvt_pixel_dtor (XtAppContext app, XrmValuePtr to, XtPointer closure, XrmValuePtr args,
1629 Cardinal *nargs)
1631 if (*nargs != 2)
1633 XtAppWarningMsg (app, "wrongParameters", "cvt_pixel_dtor",
1634 "XtToolkitError",
1635 "Screen and colormap arguments required",
1636 NULL, NULL);
1638 else if (closure != NULL)
1640 /* We did allocate the pixel, so free it. */
1641 Screen *screen = *(Screen **) args[0].addr;
1642 Colormap cmap = *(Colormap *) args[1].addr;
1643 x_free_dpy_colors (DisplayOfScreen (screen), screen, cmap,
1644 (Pixel *) to->addr, 1);
1649 #endif /* USE_X_TOOLKIT */
1652 /* Value is an array of XColor structures for the contents of the
1653 color map of display DPY. Set *NCELLS to the size of the array.
1654 Note that this probably shouldn't be called for large color maps,
1655 say a 24-bit TrueColor map. */
1657 static const XColor *
1658 x_color_cells (Display *dpy, int *ncells)
1660 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
1662 if (dpyinfo->color_cells == NULL)
1664 Screen *screen = dpyinfo->screen;
1665 int ncolor_cells = XDisplayCells (dpy, XScreenNumberOfScreen (screen));
1666 int i;
1668 dpyinfo->color_cells = xnmalloc (ncolor_cells,
1669 sizeof *dpyinfo->color_cells);
1670 dpyinfo->ncolor_cells = ncolor_cells;
1672 for (i = 0; i < ncolor_cells; ++i)
1673 dpyinfo->color_cells[i].pixel = i;
1675 XQueryColors (dpy, dpyinfo->cmap,
1676 dpyinfo->color_cells, ncolor_cells);
1679 *ncells = dpyinfo->ncolor_cells;
1680 return dpyinfo->color_cells;
1684 /* On frame F, translate pixel colors to RGB values for the NCOLORS
1685 colors in COLORS. Use cached information, if available. */
1687 void
1688 x_query_colors (struct frame *f, XColor *colors, int ncolors)
1690 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
1692 if (dpyinfo->color_cells)
1694 int i;
1695 for (i = 0; i < ncolors; ++i)
1697 unsigned long pixel = colors[i].pixel;
1698 xassert (pixel < dpyinfo->ncolor_cells);
1699 xassert (dpyinfo->color_cells[pixel].pixel == pixel);
1700 colors[i] = dpyinfo->color_cells[pixel];
1703 else
1704 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
1708 /* On frame F, translate pixel color to RGB values for the color in
1709 COLOR. Use cached information, if available. */
1711 void
1712 x_query_color (struct frame *f, XColor *color)
1714 x_query_colors (f, color, 1);
1718 /* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP. If an
1719 exact match can't be allocated, try the nearest color available.
1720 Value is non-zero if successful. Set *COLOR to the color
1721 allocated. */
1723 static int
1724 x_alloc_nearest_color_1 (Display *dpy, Colormap cmap, XColor *color)
1726 int rc;
1728 rc = XAllocColor (dpy, cmap, color);
1729 if (rc == 0)
1731 /* If we got to this point, the colormap is full, so we're going
1732 to try to get the next closest color. The algorithm used is
1733 a least-squares matching, which is what X uses for closest
1734 color matching with StaticColor visuals. */
1735 int nearest, i;
1736 int max_color_delta = 255;
1737 int max_delta = 3 * max_color_delta;
1738 int nearest_delta = max_delta + 1;
1739 int ncells;
1740 const XColor *cells = x_color_cells (dpy, &ncells);
1742 for (nearest = i = 0; i < ncells; ++i)
1744 int dred = (color->red >> 8) - (cells[i].red >> 8);
1745 int dgreen = (color->green >> 8) - (cells[i].green >> 8);
1746 int dblue = (color->blue >> 8) - (cells[i].blue >> 8);
1747 int delta = dred * dred + dgreen * dgreen + dblue * dblue;
1749 if (delta < nearest_delta)
1751 nearest = i;
1752 nearest_delta = delta;
1756 color->red = cells[nearest].red;
1757 color->green = cells[nearest].green;
1758 color->blue = cells[nearest].blue;
1759 rc = XAllocColor (dpy, cmap, color);
1761 else
1763 /* If allocation succeeded, and the allocated pixel color is not
1764 equal to a cached pixel color recorded earlier, there was a
1765 change in the colormap, so clear the color cache. */
1766 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
1767 XColor *cached_color;
1769 if (dpyinfo->color_cells
1770 && (cached_color = &dpyinfo->color_cells[color->pixel],
1771 (cached_color->red != color->red
1772 || cached_color->blue != color->blue
1773 || cached_color->green != color->green)))
1775 xfree (dpyinfo->color_cells);
1776 dpyinfo->color_cells = NULL;
1777 dpyinfo->ncolor_cells = 0;
1781 #ifdef DEBUG_X_COLORS
1782 if (rc)
1783 register_color (color->pixel);
1784 #endif /* DEBUG_X_COLORS */
1786 return rc;
1790 /* Allocate the color COLOR->pixel on frame F, colormap CMAP. If an
1791 exact match can't be allocated, try the nearest color available.
1792 Value is non-zero if successful. Set *COLOR to the color
1793 allocated. */
1796 x_alloc_nearest_color (struct frame *f, Colormap cmap, XColor *color)
1798 gamma_correct (f, color);
1799 return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f), cmap, color);
1803 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
1804 It's necessary to do this instead of just using PIXEL directly to
1805 get color reference counts right. */
1807 unsigned long
1808 x_copy_color (struct frame *f, long unsigned int pixel)
1810 XColor color;
1812 color.pixel = pixel;
1813 BLOCK_INPUT;
1814 x_query_color (f, &color);
1815 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
1816 UNBLOCK_INPUT;
1817 #ifdef DEBUG_X_COLORS
1818 register_color (pixel);
1819 #endif
1820 return color.pixel;
1824 /* Brightness beyond which a color won't have its highlight brightness
1825 boosted.
1827 Nominally, highlight colors for `3d' faces are calculated by
1828 brightening an object's color by a constant scale factor, but this
1829 doesn't yield good results for dark colors, so for colors who's
1830 brightness is less than this value (on a scale of 0-65535) have an
1831 use an additional additive factor.
1833 The value here is set so that the default menu-bar/mode-line color
1834 (grey75) will not have its highlights changed at all. */
1835 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
1838 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
1839 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1840 If this produces the same color as PIXEL, try a color where all RGB
1841 values have DELTA added. Return the allocated color in *PIXEL.
1842 DISPLAY is the X display, CMAP is the colormap to operate on.
1843 Value is non-zero if successful. */
1845 static int
1846 x_alloc_lighter_color (struct frame *f, Display *display, Colormap cmap, long unsigned int *pixel, double factor, int delta)
1848 XColor color, new;
1849 long bright;
1850 int success_p;
1852 /* Get RGB color values. */
1853 color.pixel = *pixel;
1854 x_query_color (f, &color);
1856 /* Change RGB values by specified FACTOR. Avoid overflow! */
1857 xassert (factor >= 0);
1858 new.red = min (0xffff, factor * color.red);
1859 new.green = min (0xffff, factor * color.green);
1860 new.blue = min (0xffff, factor * color.blue);
1862 /* Calculate brightness of COLOR. */
1863 bright = (2 * color.red + 3 * color.green + color.blue) / 6;
1865 /* We only boost colors that are darker than
1866 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
1867 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
1868 /* Make an additive adjustment to NEW, because it's dark enough so
1869 that scaling by FACTOR alone isn't enough. */
1871 /* How far below the limit this color is (0 - 1, 1 being darker). */
1872 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
1873 /* The additive adjustment. */
1874 int min_delta = delta * dimness * factor / 2;
1876 if (factor < 1)
1878 new.red = max (0, new.red - min_delta);
1879 new.green = max (0, new.green - min_delta);
1880 new.blue = max (0, new.blue - min_delta);
1882 else
1884 new.red = min (0xffff, min_delta + new.red);
1885 new.green = min (0xffff, min_delta + new.green);
1886 new.blue = min (0xffff, min_delta + new.blue);
1890 /* Try to allocate the color. */
1891 success_p = x_alloc_nearest_color (f, cmap, &new);
1892 if (success_p)
1894 if (new.pixel == *pixel)
1896 /* If we end up with the same color as before, try adding
1897 delta to the RGB values. */
1898 x_free_colors (f, &new.pixel, 1);
1900 new.red = min (0xffff, delta + color.red);
1901 new.green = min (0xffff, delta + color.green);
1902 new.blue = min (0xffff, delta + color.blue);
1903 success_p = x_alloc_nearest_color (f, cmap, &new);
1905 else
1906 success_p = 1;
1907 *pixel = new.pixel;
1910 return success_p;
1914 /* Set up the foreground color for drawing relief lines of glyph
1915 string S. RELIEF is a pointer to a struct relief containing the GC
1916 with which lines will be drawn. Use a color that is FACTOR or
1917 DELTA lighter or darker than the relief's background which is found
1918 in S->f->output_data.x->relief_background. If such a color cannot
1919 be allocated, use DEFAULT_PIXEL, instead. */
1921 static void
1922 x_setup_relief_color (struct frame *f, struct relief *relief, double factor, int delta, long unsigned int default_pixel)
1924 XGCValues xgcv;
1925 struct x_output *di = f->output_data.x;
1926 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
1927 unsigned long pixel;
1928 unsigned long background = di->relief_background;
1929 Colormap cmap = FRAME_X_COLORMAP (f);
1930 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
1931 Display *dpy = FRAME_X_DISPLAY (f);
1933 xgcv.graphics_exposures = False;
1934 xgcv.line_width = 1;
1936 /* Free previously allocated color. The color cell will be reused
1937 when it has been freed as many times as it was allocated, so this
1938 doesn't affect faces using the same colors. */
1939 if (relief->gc
1940 && relief->allocated_p)
1942 x_free_colors (f, &relief->pixel, 1);
1943 relief->allocated_p = 0;
1946 /* Allocate new color. */
1947 xgcv.foreground = default_pixel;
1948 pixel = background;
1949 if (dpyinfo->n_planes != 1
1950 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
1952 relief->allocated_p = 1;
1953 xgcv.foreground = relief->pixel = pixel;
1956 if (relief->gc == 0)
1958 xgcv.stipple = dpyinfo->gray;
1959 mask |= GCStipple;
1960 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
1962 else
1963 XChangeGC (dpy, relief->gc, mask, &xgcv);
1967 /* Set up colors for the relief lines around glyph string S. */
1969 static void
1970 x_setup_relief_colors (struct glyph_string *s)
1972 struct x_output *di = s->f->output_data.x;
1973 unsigned long color;
1975 if (s->face->use_box_color_for_shadows_p)
1976 color = s->face->box_color;
1977 else if (s->first_glyph->type == IMAGE_GLYPH
1978 && s->img->pixmap
1979 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
1980 color = IMAGE_BACKGROUND (s->img, s->f, 0);
1981 else
1983 XGCValues xgcv;
1985 /* Get the background color of the face. */
1986 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
1987 color = xgcv.background;
1990 if (di->white_relief.gc == 0
1991 || color != di->relief_background)
1993 di->relief_background = color;
1994 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
1995 WHITE_PIX_DEFAULT (s->f));
1996 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
1997 BLACK_PIX_DEFAULT (s->f));
2002 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2003 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2004 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2005 relief. LEFT_P non-zero means draw a relief on the left side of
2006 the rectangle. RIGHT_P non-zero means draw a relief on the right
2007 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2008 when drawing. */
2010 static void
2011 x_draw_relief_rect (struct frame *f,
2012 int left_x, int top_y, int right_x, int bottom_y, int width,
2013 int raised_p, int top_p, int bot_p, int left_p, int right_p,
2014 XRectangle *clip_rect)
2016 Display *dpy = FRAME_X_DISPLAY (f);
2017 Window window = FRAME_X_WINDOW (f);
2018 int i;
2019 GC gc;
2021 if (raised_p)
2022 gc = f->output_data.x->white_relief.gc;
2023 else
2024 gc = f->output_data.x->black_relief.gc;
2025 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
2027 /* This code is more complicated than it has to be, because of two
2028 minor hacks to make the boxes look nicer: (i) if width > 1, draw
2029 the outermost line using the black relief. (ii) Omit the four
2030 corner pixels. */
2032 /* Top. */
2033 if (top_p)
2035 if (width == 1)
2036 XDrawLine (dpy, window, gc,
2037 left_x + (left_p ? 1 : 0), top_y,
2038 right_x + (right_p ? 0 : 1), top_y);
2040 for (i = 1; i < width; ++i)
2041 XDrawLine (dpy, window, gc,
2042 left_x + i * left_p, top_y + i,
2043 right_x + 1 - i * right_p, top_y + i);
2046 /* Left. */
2047 if (left_p)
2049 if (width == 1)
2050 XDrawLine (dpy, window, gc, left_x, top_y + 1, left_x, bottom_y);
2052 XClearArea (dpy, window, left_x, top_y, 1, 1, False);
2053 XClearArea (dpy, window, left_x, bottom_y, 1, 1, False);
2055 for (i = (width > 1 ? 1 : 0); i < width; ++i)
2056 XDrawLine (dpy, window, gc,
2057 left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
2060 XSetClipMask (dpy, gc, None);
2061 if (raised_p)
2062 gc = f->output_data.x->black_relief.gc;
2063 else
2064 gc = f->output_data.x->white_relief.gc;
2065 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
2067 if (width > 1)
2069 /* Outermost top line. */
2070 if (top_p)
2071 XDrawLine (dpy, window, gc,
2072 left_x + (left_p ? 1 : 0), top_y,
2073 right_x + (right_p ? 0 : 1), top_y);
2075 /* Outermost left line. */
2076 if (left_p)
2077 XDrawLine (dpy, window, gc, left_x, top_y + 1, left_x, bottom_y);
2080 /* Bottom. */
2081 if (bot_p)
2083 XDrawLine (dpy, window, gc,
2084 left_x + (left_p ? 1 : 0), bottom_y,
2085 right_x + (right_p ? 0 : 1), bottom_y);
2086 for (i = 1; i < width; ++i)
2087 XDrawLine (dpy, window, gc,
2088 left_x + i * left_p, bottom_y - i,
2089 right_x + 1 - i * right_p, bottom_y - i);
2092 /* Right. */
2093 if (right_p)
2095 XClearArea (dpy, window, right_x, top_y, 1, 1, False);
2096 XClearArea (dpy, window, right_x, bottom_y, 1, 1, False);
2097 for (i = 0; i < width; ++i)
2098 XDrawLine (dpy, window, gc,
2099 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
2102 XSetClipMask (dpy, gc, None);
2106 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2107 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2108 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2109 left side of the rectangle. RIGHT_P non-zero means draw a line
2110 on the right side of the rectangle. CLIP_RECT is the clipping
2111 rectangle to use when drawing. */
2113 static void
2114 x_draw_box_rect (struct glyph_string *s,
2115 int left_x, int top_y, int right_x, int bottom_y, int width,
2116 int left_p, int right_p, XRectangle *clip_rect)
2118 XGCValues xgcv;
2120 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2121 XSetForeground (s->display, s->gc, s->face->box_color);
2122 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
2124 /* Top. */
2125 XFillRectangle (s->display, s->window, s->gc,
2126 left_x, top_y, right_x - left_x + 1, width);
2128 /* Left. */
2129 if (left_p)
2130 XFillRectangle (s->display, s->window, s->gc,
2131 left_x, top_y, width, bottom_y - top_y + 1);
2133 /* Bottom. */
2134 XFillRectangle (s->display, s->window, s->gc,
2135 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
2137 /* Right. */
2138 if (right_p)
2139 XFillRectangle (s->display, s->window, s->gc,
2140 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
2142 XSetForeground (s->display, s->gc, xgcv.foreground);
2143 XSetClipMask (s->display, s->gc, None);
2147 /* Draw a box around glyph string S. */
2149 static void
2150 x_draw_glyph_string_box (struct glyph_string *s)
2152 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
2153 int left_p, right_p;
2154 struct glyph *last_glyph;
2155 XRectangle clip_rect;
2157 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
2158 ? WINDOW_RIGHT_EDGE_X (s->w)
2159 : window_box_right (s->w, s->area));
2161 /* The glyph that may have a right box line. */
2162 last_glyph = (s->cmp || s->img
2163 ? s->first_glyph
2164 : s->first_glyph + s->nchars - 1);
2166 width = eabs (s->face->box_line_width);
2167 raised_p = s->face->box == FACE_RAISED_BOX;
2168 left_x = s->x;
2169 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
2170 ? last_x - 1
2171 : min (last_x, s->x + s->background_width) - 1);
2172 top_y = s->y;
2173 bottom_y = top_y + s->height - 1;
2175 left_p = (s->first_glyph->left_box_line_p
2176 || (s->hl == DRAW_MOUSE_FACE
2177 && (s->prev == NULL
2178 || s->prev->hl != s->hl)));
2179 right_p = (last_glyph->right_box_line_p
2180 || (s->hl == DRAW_MOUSE_FACE
2181 && (s->next == NULL
2182 || s->next->hl != s->hl)));
2184 get_glyph_string_clip_rect (s, &clip_rect);
2186 if (s->face->box == FACE_SIMPLE_BOX)
2187 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2188 left_p, right_p, &clip_rect);
2189 else
2191 x_setup_relief_colors (s);
2192 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
2193 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
2198 /* Draw foreground of image glyph string S. */
2200 static void
2201 x_draw_image_foreground (struct glyph_string *s)
2203 int x = s->x;
2204 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2206 /* If first glyph of S has a left box line, start drawing it to the
2207 right of that line. */
2208 if (s->face->box != FACE_NO_BOX
2209 && s->first_glyph->left_box_line_p
2210 && s->slice.x == 0)
2211 x += eabs (s->face->box_line_width);
2213 /* If there is a margin around the image, adjust x- and y-position
2214 by that margin. */
2215 if (s->slice.x == 0)
2216 x += s->img->hmargin;
2217 if (s->slice.y == 0)
2218 y += s->img->vmargin;
2220 if (s->img->pixmap)
2222 if (s->img->mask)
2224 /* We can't set both a clip mask and use XSetClipRectangles
2225 because the latter also sets a clip mask. We also can't
2226 trust on the shape extension to be available
2227 (XShapeCombineRegion). So, compute the rectangle to draw
2228 manually. */
2229 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
2230 | GCFunction);
2231 XGCValues xgcv;
2232 XRectangle clip_rect, image_rect, r;
2234 xgcv.clip_mask = s->img->mask;
2235 xgcv.clip_x_origin = x;
2236 xgcv.clip_y_origin = y;
2237 xgcv.function = GXcopy;
2238 XChangeGC (s->display, s->gc, mask, &xgcv);
2240 get_glyph_string_clip_rect (s, &clip_rect);
2241 image_rect.x = x;
2242 image_rect.y = y;
2243 image_rect.width = s->slice.width;
2244 image_rect.height = s->slice.height;
2245 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
2246 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
2247 s->slice.x + r.x - x, s->slice.y + r.y - y,
2248 r.width, r.height, r.x, r.y);
2250 else
2252 XRectangle clip_rect, image_rect, r;
2254 get_glyph_string_clip_rect (s, &clip_rect);
2255 image_rect.x = x;
2256 image_rect.y = y;
2257 image_rect.width = s->slice.width;
2258 image_rect.height = s->slice.height;
2259 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
2260 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
2261 s->slice.x + r.x - x, s->slice.y + r.y - y,
2262 r.width, r.height, r.x, r.y);
2264 /* When the image has a mask, we can expect that at
2265 least part of a mouse highlight or a block cursor will
2266 be visible. If the image doesn't have a mask, make
2267 a block cursor visible by drawing a rectangle around
2268 the image. I believe it's looking better if we do
2269 nothing here for mouse-face. */
2270 if (s->hl == DRAW_CURSOR)
2272 int relief = s->img->relief;
2273 if (relief < 0) relief = -relief;
2274 XDrawRectangle (s->display, s->window, s->gc,
2275 x - relief, y - relief,
2276 s->slice.width + relief*2 - 1,
2277 s->slice.height + relief*2 - 1);
2281 else
2282 /* Draw a rectangle if image could not be loaded. */
2283 XDrawRectangle (s->display, s->window, s->gc, x, y,
2284 s->slice.width - 1, s->slice.height - 1);
2288 /* Draw a relief around the image glyph string S. */
2290 static void
2291 x_draw_image_relief (struct glyph_string *s)
2293 int x0, y0, x1, y1, thick, raised_p;
2294 int extra_x, extra_y;
2295 XRectangle r;
2296 int x = s->x;
2297 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2299 /* If first glyph of S has a left box line, start drawing it to the
2300 right of that line. */
2301 if (s->face->box != FACE_NO_BOX
2302 && s->first_glyph->left_box_line_p
2303 && s->slice.x == 0)
2304 x += eabs (s->face->box_line_width);
2306 /* If there is a margin around the image, adjust x- and y-position
2307 by that margin. */
2308 if (s->slice.x == 0)
2309 x += s->img->hmargin;
2310 if (s->slice.y == 0)
2311 y += s->img->vmargin;
2313 if (s->hl == DRAW_IMAGE_SUNKEN
2314 || s->hl == DRAW_IMAGE_RAISED)
2316 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
2317 raised_p = s->hl == DRAW_IMAGE_RAISED;
2319 else
2321 thick = eabs (s->img->relief);
2322 raised_p = s->img->relief > 0;
2325 extra_x = extra_y = 0;
2326 if (s->face->id == TOOL_BAR_FACE_ID)
2328 if (CONSP (Vtool_bar_button_margin)
2329 && INTEGERP (XCAR (Vtool_bar_button_margin))
2330 && INTEGERP (XCDR (Vtool_bar_button_margin)))
2332 extra_x = XINT (XCAR (Vtool_bar_button_margin));
2333 extra_y = XINT (XCDR (Vtool_bar_button_margin));
2335 else if (INTEGERP (Vtool_bar_button_margin))
2336 extra_x = extra_y = XINT (Vtool_bar_button_margin);
2339 x0 = x - thick - extra_x;
2340 y0 = y - thick - extra_y;
2341 x1 = x + s->slice.width + thick - 1 + extra_x;
2342 y1 = y + s->slice.height + thick - 1 + extra_y;
2344 x_setup_relief_colors (s);
2345 get_glyph_string_clip_rect (s, &r);
2346 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
2347 s->slice.y == 0,
2348 s->slice.y + s->slice.height == s->img->height,
2349 s->slice.x == 0,
2350 s->slice.x + s->slice.width == s->img->width,
2351 &r);
2355 /* Draw the foreground of image glyph string S to PIXMAP. */
2357 static void
2358 x_draw_image_foreground_1 (struct glyph_string *s, Pixmap pixmap)
2360 int x = 0;
2361 int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
2363 /* If first glyph of S has a left box line, start drawing it to the
2364 right of that line. */
2365 if (s->face->box != FACE_NO_BOX
2366 && s->first_glyph->left_box_line_p
2367 && s->slice.x == 0)
2368 x += eabs (s->face->box_line_width);
2370 /* If there is a margin around the image, adjust x- and y-position
2371 by that margin. */
2372 if (s->slice.x == 0)
2373 x += s->img->hmargin;
2374 if (s->slice.y == 0)
2375 y += s->img->vmargin;
2377 if (s->img->pixmap)
2379 if (s->img->mask)
2381 /* We can't set both a clip mask and use XSetClipRectangles
2382 because the latter also sets a clip mask. We also can't
2383 trust on the shape extension to be available
2384 (XShapeCombineRegion). So, compute the rectangle to draw
2385 manually. */
2386 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
2387 | GCFunction);
2388 XGCValues xgcv;
2390 xgcv.clip_mask = s->img->mask;
2391 xgcv.clip_x_origin = x - s->slice.x;
2392 xgcv.clip_y_origin = y - s->slice.y;
2393 xgcv.function = GXcopy;
2394 XChangeGC (s->display, s->gc, mask, &xgcv);
2396 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
2397 s->slice.x, s->slice.y,
2398 s->slice.width, s->slice.height, x, y);
2399 XSetClipMask (s->display, s->gc, None);
2401 else
2403 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
2404 s->slice.x, s->slice.y,
2405 s->slice.width, s->slice.height, x, y);
2407 /* When the image has a mask, we can expect that at
2408 least part of a mouse highlight or a block cursor will
2409 be visible. If the image doesn't have a mask, make
2410 a block cursor visible by drawing a rectangle around
2411 the image. I believe it's looking better if we do
2412 nothing here for mouse-face. */
2413 if (s->hl == DRAW_CURSOR)
2415 int r = s->img->relief;
2416 if (r < 0) r = -r;
2417 XDrawRectangle (s->display, s->window, s->gc, x - r, y - r,
2418 s->slice.width + r*2 - 1,
2419 s->slice.height + r*2 - 1);
2423 else
2424 /* Draw a rectangle if image could not be loaded. */
2425 XDrawRectangle (s->display, pixmap, s->gc, x, y,
2426 s->slice.width - 1, s->slice.height - 1);
2430 /* Draw part of the background of glyph string S. X, Y, W, and H
2431 give the rectangle to draw. */
2433 static void
2434 x_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w, int h)
2436 if (s->stippled_p)
2438 /* Fill background with a stipple pattern. */
2439 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2440 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
2441 XSetFillStyle (s->display, s->gc, FillSolid);
2443 else
2444 x_clear_glyph_string_rect (s, x, y, w, h);
2448 /* Draw image glyph string S.
2450 s->y
2451 s->x +-------------------------
2452 | s->face->box
2454 | +-------------------------
2455 | | s->img->margin
2457 | | +-------------------
2458 | | | the image
2462 static void
2463 x_draw_image_glyph_string (struct glyph_string *s)
2465 int box_line_hwidth = eabs (s->face->box_line_width);
2466 int box_line_vwidth = max (s->face->box_line_width, 0);
2467 int height;
2468 Pixmap pixmap = None;
2470 height = s->height;
2471 if (s->slice.y == 0)
2472 height -= box_line_vwidth;
2473 if (s->slice.y + s->slice.height >= s->img->height)
2474 height -= box_line_vwidth;
2476 /* Fill background with face under the image. Do it only if row is
2477 taller than image or if image has a clip mask to reduce
2478 flickering. */
2479 s->stippled_p = s->face->stipple != 0;
2480 if (height > s->slice.height
2481 || s->img->hmargin
2482 || s->img->vmargin
2483 || s->img->mask
2484 || s->img->pixmap == 0
2485 || s->width != s->background_width)
2487 if (s->img->mask)
2489 /* Create a pixmap as large as the glyph string. Fill it
2490 with the background color. Copy the image to it, using
2491 its mask. Copy the temporary pixmap to the display. */
2492 Screen *screen = FRAME_X_SCREEN (s->f);
2493 int depth = DefaultDepthOfScreen (screen);
2495 /* Create a pixmap as large as the glyph string. */
2496 pixmap = XCreatePixmap (s->display, s->window,
2497 s->background_width,
2498 s->height, depth);
2500 /* Don't clip in the following because we're working on the
2501 pixmap. */
2502 XSetClipMask (s->display, s->gc, None);
2504 /* Fill the pixmap with the background color/stipple. */
2505 if (s->stippled_p)
2507 /* Fill background with a stipple pattern. */
2508 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2509 XSetTSOrigin (s->display, s->gc, - s->x, - s->y);
2510 XFillRectangle (s->display, pixmap, s->gc,
2511 0, 0, s->background_width, s->height);
2512 XSetFillStyle (s->display, s->gc, FillSolid);
2513 XSetTSOrigin (s->display, s->gc, 0, 0);
2515 else
2517 XGCValues xgcv;
2518 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
2519 &xgcv);
2520 XSetForeground (s->display, s->gc, xgcv.background);
2521 XFillRectangle (s->display, pixmap, s->gc,
2522 0, 0, s->background_width, s->height);
2523 XSetForeground (s->display, s->gc, xgcv.foreground);
2526 else
2528 int x = s->x;
2529 int y = s->y;
2531 if (s->first_glyph->left_box_line_p
2532 && s->slice.x == 0)
2533 x += box_line_hwidth;
2535 if (s->slice.y == 0)
2536 y += box_line_vwidth;
2538 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
2541 s->background_filled_p = 1;
2544 /* Draw the foreground. */
2545 if (pixmap != None)
2547 x_draw_image_foreground_1 (s, pixmap);
2548 x_set_glyph_string_clipping (s);
2549 XCopyArea (s->display, pixmap, s->window, s->gc,
2550 0, 0, s->background_width, s->height, s->x, s->y);
2551 XFreePixmap (s->display, pixmap);
2553 else
2554 x_draw_image_foreground (s);
2556 /* If we must draw a relief around the image, do it. */
2557 if (s->img->relief
2558 || s->hl == DRAW_IMAGE_RAISED
2559 || s->hl == DRAW_IMAGE_SUNKEN)
2560 x_draw_image_relief (s);
2564 /* Draw stretch glyph string S. */
2566 static void
2567 x_draw_stretch_glyph_string (struct glyph_string *s)
2569 xassert (s->first_glyph->type == STRETCH_GLYPH);
2571 if (s->hl == DRAW_CURSOR
2572 && !x_stretch_cursor_p)
2574 /* If `x-stretch-cursor' is nil, don't draw a block cursor as
2575 wide as the stretch glyph. */
2576 int width, background_width = s->background_width;
2577 int x = s->x;
2579 if (!s->row->reversed_p)
2581 int left_x = window_box_left_offset (s->w, TEXT_AREA);
2583 if (x < left_x)
2585 background_width -= left_x - x;
2586 x = left_x;
2589 else
2591 /* In R2L rows, draw the cursor on the right edge of the
2592 stretch glyph. */
2593 int right_x = window_box_right_offset (s->w, TEXT_AREA);
2595 if (x + background_width > right_x)
2596 background_width -= x - right_x;
2597 x += background_width;
2599 width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
2600 if (s->row->reversed_p)
2601 x -= width;
2603 /* Draw cursor. */
2604 x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
2606 /* Clear rest using the GC of the original non-cursor face. */
2607 if (width < background_width)
2609 int y = s->y;
2610 int w = background_width - width, h = s->height;
2611 XRectangle r;
2612 GC gc;
2614 if (!s->row->reversed_p)
2615 x += width;
2616 else
2617 x = s->x;
2618 if (s->row->mouse_face_p
2619 && cursor_in_mouse_face_p (s->w))
2621 x_set_mouse_face_gc (s);
2622 gc = s->gc;
2624 else
2625 gc = s->face->gc;
2627 get_glyph_string_clip_rect (s, &r);
2628 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
2630 if (s->face->stipple)
2632 /* Fill background with a stipple pattern. */
2633 XSetFillStyle (s->display, gc, FillOpaqueStippled);
2634 XFillRectangle (s->display, s->window, gc, x, y, w, h);
2635 XSetFillStyle (s->display, gc, FillSolid);
2637 else
2639 XGCValues xgcv;
2640 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
2641 XSetForeground (s->display, gc, xgcv.background);
2642 XFillRectangle (s->display, s->window, gc, x, y, w, h);
2643 XSetForeground (s->display, gc, xgcv.foreground);
2647 else if (!s->background_filled_p)
2649 int background_width = s->background_width;
2650 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
2652 /* Don't draw into left margin, fringe or scrollbar area
2653 except for header line and mode line. */
2654 if (x < left_x && !s->row->mode_line_p)
2656 background_width -= left_x - x;
2657 x = left_x;
2659 if (background_width > 0)
2660 x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
2663 s->background_filled_p = 1;
2667 Draw a wavy line under S. The wave fills wave_height pixels from y0.
2669 x0 wave_length = 2
2671 y0 * * * * *
2672 |* * * * * * * * *
2673 wave_height = 3 | * * * *
2677 static void
2678 x_draw_underwave (struct glyph_string *s)
2680 int wave_height = 2, wave_length = 3;
2681 int dx, dy, x0, y0, width, x1, y1, x2, y2, odd, xmax;
2682 XRectangle wave_clip, string_clip, final_clip;
2684 dx = wave_length;
2685 dy = wave_height - 1;
2686 x0 = s->x;
2687 y0 = s->ybase + 1;
2688 width = s->width;
2689 xmax = x0 + width;
2691 /* Find and set clipping rectangle */
2693 wave_clip = (XRectangle){ x0, y0, width, wave_height };
2694 get_glyph_string_clip_rect (s, &string_clip);
2696 if (!x_intersect_rectangles (&wave_clip, &string_clip, &final_clip))
2697 return;
2699 XSetClipRectangles (s->display, s->gc, 0, 0, &final_clip, 1, Unsorted);
2701 /* Draw the waves */
2703 x1 = x0 - (x0 % dx);
2704 x2 = x1 + dx;
2705 odd = (x1/dx) % 2;
2706 y1 = y2 = y0;
2708 if (odd)
2709 y1 += dy;
2710 else
2711 y2 += dy;
2713 if (INT_MAX - dx < xmax)
2714 abort ();
2716 while (x1 <= xmax)
2718 XDrawLine (s->display, s->window, s->gc, x1, y1, x2, y2);
2719 x1 = x2, y1 = y2;
2720 x2 += dx, y2 = y0 + odd*dy;
2721 odd = !odd;
2724 /* Restore previous clipping rectangle(s) */
2725 XSetClipRectangles (s->display, s->gc, 0, 0, s->clip, s->num_clips, Unsorted);
2729 /* Draw glyph string S. */
2731 static void
2732 x_draw_glyph_string (struct glyph_string *s)
2734 int relief_drawn_p = 0;
2736 /* If S draws into the background of its successors, draw the
2737 background of the successors first so that S can draw into it.
2738 This makes S->next use XDrawString instead of XDrawImageString. */
2739 if (s->next && s->right_overhang && !s->for_overlaps)
2741 int width;
2742 struct glyph_string *next;
2744 for (width = 0, next = s->next;
2745 next && width < s->right_overhang;
2746 width += next->width, next = next->next)
2747 if (next->first_glyph->type != IMAGE_GLYPH)
2749 x_set_glyph_string_gc (next);
2750 x_set_glyph_string_clipping (next);
2751 if (next->first_glyph->type == STRETCH_GLYPH)
2752 x_draw_stretch_glyph_string (next);
2753 else
2754 x_draw_glyph_string_background (next, 1);
2755 next->num_clips = 0;
2759 /* Set up S->gc, set clipping and draw S. */
2760 x_set_glyph_string_gc (s);
2762 /* Draw relief (if any) in advance for char/composition so that the
2763 glyph string can be drawn over it. */
2764 if (!s->for_overlaps
2765 && s->face->box != FACE_NO_BOX
2766 && (s->first_glyph->type == CHAR_GLYPH
2767 || s->first_glyph->type == COMPOSITE_GLYPH))
2770 x_set_glyph_string_clipping (s);
2771 x_draw_glyph_string_background (s, 1);
2772 x_draw_glyph_string_box (s);
2773 x_set_glyph_string_clipping (s);
2774 relief_drawn_p = 1;
2776 else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */
2777 && !s->clip_tail
2778 && ((s->prev && s->prev->hl != s->hl && s->left_overhang)
2779 || (s->next && s->next->hl != s->hl && s->right_overhang)))
2780 /* We must clip just this glyph. left_overhang part has already
2781 drawn when s->prev was drawn, and right_overhang part will be
2782 drawn later when s->next is drawn. */
2783 x_set_glyph_string_clipping_exactly (s, s);
2784 else
2785 x_set_glyph_string_clipping (s);
2787 switch (s->first_glyph->type)
2789 case IMAGE_GLYPH:
2790 x_draw_image_glyph_string (s);
2791 break;
2793 case STRETCH_GLYPH:
2794 x_draw_stretch_glyph_string (s);
2795 break;
2797 case CHAR_GLYPH:
2798 if (s->for_overlaps)
2799 s->background_filled_p = 1;
2800 else
2801 x_draw_glyph_string_background (s, 0);
2802 x_draw_glyph_string_foreground (s);
2803 break;
2805 case COMPOSITE_GLYPH:
2806 if (s->for_overlaps || (s->cmp_from > 0
2807 && ! s->first_glyph->u.cmp.automatic))
2808 s->background_filled_p = 1;
2809 else
2810 x_draw_glyph_string_background (s, 1);
2811 x_draw_composite_glyph_string_foreground (s);
2812 break;
2814 case GLYPHLESS_GLYPH:
2815 if (s->for_overlaps)
2816 s->background_filled_p = 1;
2817 else
2818 x_draw_glyph_string_background (s, 1);
2819 x_draw_glyphless_glyph_string_foreground (s);
2820 break;
2822 default:
2823 abort ();
2826 if (!s->for_overlaps)
2828 /* Draw underline. */
2829 if (s->face->underline_p)
2831 if (s->face->underline_type == FACE_UNDER_WAVE)
2833 if (s->face->underline_defaulted_p)
2834 x_draw_underwave (s);
2835 else
2837 XGCValues xgcv;
2838 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2839 XSetForeground (s->display, s->gc, s->face->underline_color);
2840 x_draw_underwave (s);
2841 XSetForeground (s->display, s->gc, xgcv.foreground);
2844 else if (s->face->underline_type == FACE_UNDER_LINE)
2846 unsigned long thickness, position;
2847 int y;
2849 if (s->prev && s->prev->face->underline_p)
2851 /* We use the same underline style as the previous one. */
2852 thickness = s->prev->underline_thickness;
2853 position = s->prev->underline_position;
2855 else
2857 /* Get the underline thickness. Default is 1 pixel. */
2858 if (s->font && s->font->underline_thickness > 0)
2859 thickness = s->font->underline_thickness;
2860 else
2861 thickness = 1;
2862 if (x_underline_at_descent_line)
2863 position = (s->height - thickness) - (s->ybase - s->y);
2864 else
2866 /* Get the underline position. This is the recommended
2867 vertical offset in pixels from the baseline to the top of
2868 the underline. This is a signed value according to the
2869 specs, and its default is
2871 ROUND ((maximum descent) / 2), with
2872 ROUND(x) = floor (x + 0.5) */
2874 if (x_use_underline_position_properties
2875 && s->font && s->font->underline_position >= 0)
2876 position = s->font->underline_position;
2877 else if (s->font)
2878 position = (s->font->descent + 1) / 2;
2879 else
2880 position = underline_minimum_offset;
2882 position = max (position, underline_minimum_offset);
2884 /* Check the sanity of thickness and position. We should
2885 avoid drawing underline out of the current line area. */
2886 if (s->y + s->height <= s->ybase + position)
2887 position = (s->height - 1) - (s->ybase - s->y);
2888 if (s->y + s->height < s->ybase + position + thickness)
2889 thickness = (s->y + s->height) - (s->ybase + position);
2890 s->underline_thickness = thickness;
2891 s->underline_position = position;
2892 y = s->ybase + position;
2893 if (s->face->underline_defaulted_p)
2894 XFillRectangle (s->display, s->window, s->gc,
2895 s->x, y, s->width, thickness);
2896 else
2898 XGCValues xgcv;
2899 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2900 XSetForeground (s->display, s->gc, s->face->underline_color);
2901 XFillRectangle (s->display, s->window, s->gc,
2902 s->x, y, s->width, thickness);
2903 XSetForeground (s->display, s->gc, xgcv.foreground);
2907 /* Draw overline. */
2908 if (s->face->overline_p)
2910 unsigned long dy = 0, h = 1;
2912 if (s->face->overline_color_defaulted_p)
2913 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2914 s->width, h);
2915 else
2917 XGCValues xgcv;
2918 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2919 XSetForeground (s->display, s->gc, s->face->overline_color);
2920 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2921 s->width, h);
2922 XSetForeground (s->display, s->gc, xgcv.foreground);
2926 /* Draw strike-through. */
2927 if (s->face->strike_through_p)
2929 unsigned long h = 1;
2930 unsigned long dy = (s->height - h) / 2;
2932 if (s->face->strike_through_color_defaulted_p)
2933 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2934 s->width, h);
2935 else
2937 XGCValues xgcv;
2938 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2939 XSetForeground (s->display, s->gc, s->face->strike_through_color);
2940 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2941 s->width, h);
2942 XSetForeground (s->display, s->gc, xgcv.foreground);
2946 /* Draw relief if not yet drawn. */
2947 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
2948 x_draw_glyph_string_box (s);
2950 if (s->prev)
2952 struct glyph_string *prev;
2954 for (prev = s->prev; prev; prev = prev->prev)
2955 if (prev->hl != s->hl
2956 && prev->x + prev->width + prev->right_overhang > s->x)
2958 /* As prev was drawn while clipped to its own area, we
2959 must draw the right_overhang part using s->hl now. */
2960 enum draw_glyphs_face save = prev->hl;
2962 prev->hl = s->hl;
2963 x_set_glyph_string_gc (prev);
2964 x_set_glyph_string_clipping_exactly (s, prev);
2965 if (prev->first_glyph->type == CHAR_GLYPH)
2966 x_draw_glyph_string_foreground (prev);
2967 else
2968 x_draw_composite_glyph_string_foreground (prev);
2969 XSetClipMask (prev->display, prev->gc, None);
2970 prev->hl = save;
2971 prev->num_clips = 0;
2975 if (s->next)
2977 struct glyph_string *next;
2979 for (next = s->next; next; next = next->next)
2980 if (next->hl != s->hl
2981 && next->x - next->left_overhang < s->x + s->width)
2983 /* As next will be drawn while clipped to its own area,
2984 we must draw the left_overhang part using s->hl now. */
2985 enum draw_glyphs_face save = next->hl;
2987 next->hl = s->hl;
2988 x_set_glyph_string_gc (next);
2989 x_set_glyph_string_clipping_exactly (s, next);
2990 if (next->first_glyph->type == CHAR_GLYPH)
2991 x_draw_glyph_string_foreground (next);
2992 else
2993 x_draw_composite_glyph_string_foreground (next);
2994 XSetClipMask (next->display, next->gc, None);
2995 next->hl = save;
2996 next->num_clips = 0;
3001 /* Reset clipping. */
3002 XSetClipMask (s->display, s->gc, None);
3003 s->num_clips = 0;
3006 /* Shift display to make room for inserted glyphs. */
3008 static void
3009 x_shift_glyphs_for_insert (struct frame *f, int x, int y, int width, int height, int shift_by)
3011 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
3012 f->output_data.x->normal_gc,
3013 x, y, width, height,
3014 x + shift_by, y);
3017 /* Delete N glyphs at the nominal cursor position. Not implemented
3018 for X frames. */
3020 static void
3021 x_delete_glyphs (struct frame *f, register int n)
3023 abort ();
3027 /* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
3028 If they are <= 0, this is probably an error. */
3030 void
3031 x_clear_area (Display *dpy, Window window, int x, int y, int width, int height, int exposures)
3033 xassert (width > 0 && height > 0);
3034 XClearArea (dpy, window, x, y, width, height, exposures);
3038 /* Clear an entire frame. */
3040 static void
3041 x_clear_frame (struct frame *f)
3043 /* Clearing the frame will erase any cursor, so mark them all as no
3044 longer visible. */
3045 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
3046 output_cursor.hpos = output_cursor.vpos = 0;
3047 output_cursor.x = -1;
3049 /* We don't set the output cursor here because there will always
3050 follow an explicit cursor_to. */
3051 BLOCK_INPUT;
3053 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3055 /* We have to clear the scroll bars. If we have changed colors or
3056 something like that, then they should be notified. */
3057 x_scroll_bar_clear (f);
3059 #if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
3060 /* Make sure scroll bars are redrawn. As they aren't redrawn by
3061 redisplay, do it here. */
3062 if (FRAME_GTK_WIDGET (f))
3063 gtk_widget_queue_draw (FRAME_GTK_WIDGET (f));
3064 #endif
3066 XFlush (FRAME_X_DISPLAY (f));
3068 UNBLOCK_INPUT;
3073 /* Invert the middle quarter of the frame for .15 sec. */
3075 /* We use the select system call to do the waiting, so we have to make
3076 sure it's available. If it isn't, we just won't do visual bells. */
3078 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3081 /* Subtract the `struct timeval' values X and Y, storing the result in
3082 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3084 static int
3085 timeval_subtract (struct timeval *result, struct timeval x, struct timeval y)
3087 /* Perform the carry for the later subtraction by updating y. This
3088 is safer because on some systems the tv_sec member is unsigned. */
3089 if (x.tv_usec < y.tv_usec)
3091 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
3092 y.tv_usec -= 1000000 * nsec;
3093 y.tv_sec += nsec;
3096 if (x.tv_usec - y.tv_usec > 1000000)
3098 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
3099 y.tv_usec += 1000000 * nsec;
3100 y.tv_sec -= nsec;
3103 /* Compute the time remaining to wait. tv_usec is certainly
3104 positive. */
3105 result->tv_sec = x.tv_sec - y.tv_sec;
3106 result->tv_usec = x.tv_usec - y.tv_usec;
3108 /* Return indication of whether the result should be considered
3109 negative. */
3110 return x.tv_sec < y.tv_sec;
3113 static void
3114 XTflash (struct frame *f)
3116 BLOCK_INPUT;
3119 #ifdef USE_GTK
3120 /* Use Gdk routines to draw. This way, we won't draw over scroll bars
3121 when the scroll bars and the edit widget share the same X window. */
3122 GdkWindow *window = gtk_widget_get_window (FRAME_GTK_WIDGET (f));
3123 #ifdef HAVE_GTK3
3124 cairo_t *cr = gdk_cairo_create (window);
3125 cairo_set_source_rgb (cr, 1, 1, 1);
3126 cairo_set_operator (cr, CAIRO_OPERATOR_DIFFERENCE);
3127 #define XFillRectangle(d, win, gc, x, y, w, h) \
3128 do { \
3129 cairo_rectangle (cr, x, y, w, h); \
3130 cairo_fill (cr); \
3132 while (0)
3133 #else /* ! HAVE_GTK3 */
3134 GdkGCValues vals;
3135 GdkGC *gc;
3136 vals.foreground.pixel = (FRAME_FOREGROUND_PIXEL (f)
3137 ^ FRAME_BACKGROUND_PIXEL (f));
3138 vals.function = GDK_XOR;
3139 gc = gdk_gc_new_with_values (window,
3140 &vals, GDK_GC_FUNCTION | GDK_GC_FOREGROUND);
3141 #define XFillRectangle(d, win, gc, x, y, w, h) \
3142 gdk_draw_rectangle (window, gc, TRUE, x, y, w, h)
3143 #endif /* ! HAVE_GTK3 */
3144 #else /* ! USE_GTK */
3145 GC gc;
3147 /* Create a GC that will use the GXxor function to flip foreground
3148 pixels into background pixels. */
3150 XGCValues values;
3152 values.function = GXxor;
3153 values.foreground = (FRAME_FOREGROUND_PIXEL (f)
3154 ^ FRAME_BACKGROUND_PIXEL (f));
3156 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3157 GCFunction | GCForeground, &values);
3159 #endif
3161 /* Get the height not including a menu bar widget. */
3162 int height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f));
3163 /* Height of each line to flash. */
3164 int flash_height = FRAME_LINE_HEIGHT (f);
3165 /* These will be the left and right margins of the rectangles. */
3166 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
3167 int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
3169 int width;
3171 /* Don't flash the area between a scroll bar and the frame
3172 edge it is next to. */
3173 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
3175 case vertical_scroll_bar_left:
3176 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
3177 break;
3179 case vertical_scroll_bar_right:
3180 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
3181 break;
3183 default:
3184 break;
3187 width = flash_right - flash_left;
3189 /* If window is tall, flash top and bottom line. */
3190 if (height > 3 * FRAME_LINE_HEIGHT (f))
3192 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3193 flash_left,
3194 (FRAME_INTERNAL_BORDER_WIDTH (f)
3195 + FRAME_TOP_MARGIN_HEIGHT (f)),
3196 width, flash_height);
3197 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3198 flash_left,
3199 (height - flash_height
3200 - FRAME_INTERNAL_BORDER_WIDTH (f)),
3201 width, flash_height);
3204 else
3205 /* If it is short, flash it all. */
3206 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3207 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
3208 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
3210 x_flush (f);
3213 struct timeval wakeup;
3215 EMACS_GET_TIME (wakeup);
3217 /* Compute time to wait until, propagating carry from usecs. */
3218 wakeup.tv_usec += 150000;
3219 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
3220 wakeup.tv_usec %= 1000000;
3222 /* Keep waiting until past the time wakeup or any input gets
3223 available. */
3224 while (! detect_input_pending ())
3226 struct timeval current;
3227 struct timeval timeout;
3229 EMACS_GET_TIME (current);
3231 /* Break if result would be negative. */
3232 if (timeval_subtract (&current, wakeup, current))
3233 break;
3235 /* How long `select' should wait. */
3236 timeout.tv_sec = 0;
3237 timeout.tv_usec = 10000;
3239 /* Try to wait that long--but we might wake up sooner. */
3240 select (0, NULL, NULL, NULL, &timeout);
3244 /* If window is tall, flash top and bottom line. */
3245 if (height > 3 * FRAME_LINE_HEIGHT (f))
3247 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3248 flash_left,
3249 (FRAME_INTERNAL_BORDER_WIDTH (f)
3250 + FRAME_TOP_MARGIN_HEIGHT (f)),
3251 width, flash_height);
3252 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3253 flash_left,
3254 (height - flash_height
3255 - FRAME_INTERNAL_BORDER_WIDTH (f)),
3256 width, flash_height);
3258 else
3259 /* If it is short, flash it all. */
3260 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3261 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
3262 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
3264 #ifdef USE_GTK
3265 #ifdef HAVE_GTK3
3266 cairo_destroy (cr);
3267 #else
3268 g_object_unref (G_OBJECT (gc));
3269 #endif
3270 #undef XFillRectangle
3271 #else
3272 XFreeGC (FRAME_X_DISPLAY (f), gc);
3273 #endif
3274 x_flush (f);
3278 UNBLOCK_INPUT;
3281 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3284 static void
3285 XTtoggle_invisible_pointer (FRAME_PTR f, int invisible)
3287 BLOCK_INPUT;
3288 if (invisible)
3290 if (FRAME_X_DISPLAY_INFO (f)->invisible_cursor != 0)
3291 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3292 FRAME_X_DISPLAY_INFO (f)->invisible_cursor);
3294 else
3295 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3296 f->output_data.x->current_cursor);
3297 f->pointer_invisible = invisible;
3298 UNBLOCK_INPUT;
3302 /* Make audible bell. */
3304 static void
3305 XTring_bell (struct frame *f)
3307 if (FRAME_X_DISPLAY (f))
3309 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3310 if (visible_bell)
3311 XTflash (f);
3312 else
3313 #endif
3315 BLOCK_INPUT;
3316 XBell (FRAME_X_DISPLAY (f), 0);
3317 XFlush (FRAME_X_DISPLAY (f));
3318 UNBLOCK_INPUT;
3324 /* Specify how many text lines, from the top of the window,
3325 should be affected by insert-lines and delete-lines operations.
3326 This, and those operations, are used only within an update
3327 that is bounded by calls to x_update_begin and x_update_end. */
3329 static void
3330 XTset_terminal_window (struct frame *f, int n)
3332 /* This function intentionally left blank. */
3337 /***********************************************************************
3338 Line Dance
3339 ***********************************************************************/
3341 /* Perform an insert-lines or delete-lines operation, inserting N
3342 lines or deleting -N lines at vertical position VPOS. */
3344 static void
3345 x_ins_del_lines (struct frame *f, int vpos, int n)
3347 abort ();
3351 /* Scroll part of the display as described by RUN. */
3353 static void
3354 x_scroll_run (struct window *w, struct run *run)
3356 struct frame *f = XFRAME (w->frame);
3357 int x, y, width, height, from_y, to_y, bottom_y;
3359 /* Get frame-relative bounding box of the text display area of W,
3360 without mode lines. Include in this box the left and right
3361 fringe of W. */
3362 window_box (w, -1, &x, &y, &width, &height);
3364 #ifdef USE_TOOLKIT_SCROLL_BARS
3365 /* If the fringe is adjacent to the left (right) scroll bar of a
3366 leftmost (rightmost, respectively) window, then extend its
3367 background to the gap between the fringe and the bar. */
3368 if ((WINDOW_LEFTMOST_P (w)
3369 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
3370 || (WINDOW_RIGHTMOST_P (w)
3371 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
3373 int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
3375 if (sb_width > 0)
3377 int bar_area_x = WINDOW_SCROLL_BAR_AREA_X (w);
3378 int bar_area_width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
3379 * FRAME_COLUMN_WIDTH (f));
3381 if (bar_area_x + bar_area_width == x)
3383 x = bar_area_x + sb_width;
3384 width += bar_area_width - sb_width;
3386 else if (x + width == bar_area_x)
3387 width += bar_area_width - sb_width;
3390 #endif
3392 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
3393 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
3394 bottom_y = y + height;
3396 if (to_y < from_y)
3398 /* Scrolling up. Make sure we don't copy part of the mode
3399 line at the bottom. */
3400 if (from_y + run->height > bottom_y)
3401 height = bottom_y - from_y;
3402 else
3403 height = run->height;
3405 else
3407 /* Scrolling down. Make sure we don't copy over the mode line.
3408 at the bottom. */
3409 if (to_y + run->height > bottom_y)
3410 height = bottom_y - to_y;
3411 else
3412 height = run->height;
3415 BLOCK_INPUT;
3417 /* Cursor off. Will be switched on again in x_update_window_end. */
3418 updated_window = w;
3419 x_clear_cursor (w);
3421 XCopyArea (FRAME_X_DISPLAY (f),
3422 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
3423 f->output_data.x->normal_gc,
3424 x, from_y,
3425 width, height,
3426 x, to_y);
3428 UNBLOCK_INPUT;
3433 /***********************************************************************
3434 Exposure Events
3435 ***********************************************************************/
3438 static void
3439 frame_highlight (struct frame *f)
3441 /* We used to only do this if Vx_no_window_manager was non-nil, but
3442 the ICCCM (section 4.1.6) says that the window's border pixmap
3443 and border pixel are window attributes which are "private to the
3444 client", so we can always change it to whatever we want. */
3445 BLOCK_INPUT;
3446 /* I recently started to get errors in this XSetWindowBorder, depending on
3447 the window-manager in use, tho something more is at play since I've been
3448 using that same window-manager binary for ever. Let's not crash just
3449 because of this (bug#9310). */
3450 x_catch_errors (FRAME_X_DISPLAY (f));
3451 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3452 f->output_data.x->border_pixel);
3453 x_uncatch_errors ();
3454 UNBLOCK_INPUT;
3455 x_update_cursor (f, 1);
3456 x_set_frame_alpha (f);
3459 static void
3460 frame_unhighlight (struct frame *f)
3462 /* We used to only do this if Vx_no_window_manager was non-nil, but
3463 the ICCCM (section 4.1.6) says that the window's border pixmap
3464 and border pixel are window attributes which are "private to the
3465 client", so we can always change it to whatever we want. */
3466 BLOCK_INPUT;
3467 /* Same as above for XSetWindowBorder (bug#9310). */
3468 x_catch_errors (FRAME_X_DISPLAY (f));
3469 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3470 f->output_data.x->border_tile);
3471 x_uncatch_errors ();
3472 UNBLOCK_INPUT;
3473 x_update_cursor (f, 1);
3474 x_set_frame_alpha (f);
3477 /* The focus has changed. Update the frames as necessary to reflect
3478 the new situation. Note that we can't change the selected frame
3479 here, because the Lisp code we are interrupting might become confused.
3480 Each event gets marked with the frame in which it occurred, so the
3481 Lisp code can tell when the switch took place by examining the events. */
3483 static void
3484 x_new_focus_frame (struct x_display_info *dpyinfo, struct frame *frame)
3486 struct frame *old_focus = dpyinfo->x_focus_frame;
3488 if (frame != dpyinfo->x_focus_frame)
3490 /* Set this before calling other routines, so that they see
3491 the correct value of x_focus_frame. */
3492 dpyinfo->x_focus_frame = frame;
3494 if (old_focus && old_focus->auto_lower)
3495 x_lower_frame (old_focus);
3497 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
3498 pending_autoraise_frame = dpyinfo->x_focus_frame;
3499 else
3500 pending_autoraise_frame = 0;
3503 x_frame_rehighlight (dpyinfo);
3506 /* Handle FocusIn and FocusOut state changes for FRAME.
3507 If FRAME has focus and there exists more than one frame, puts
3508 a FOCUS_IN_EVENT into *BUFP. */
3510 static void
3511 x_focus_changed (int type, int state, struct x_display_info *dpyinfo, struct frame *frame, struct input_event *bufp)
3513 if (type == FocusIn)
3515 if (dpyinfo->x_focus_event_frame != frame)
3517 x_new_focus_frame (dpyinfo, frame);
3518 dpyinfo->x_focus_event_frame = frame;
3520 /* Don't stop displaying the initial startup message
3521 for a switch-frame event we don't need. */
3522 if (NILP (Vterminal_frame)
3523 && CONSP (Vframe_list)
3524 && !NILP (XCDR (Vframe_list)))
3526 bufp->kind = FOCUS_IN_EVENT;
3527 XSETFRAME (bufp->frame_or_window, frame);
3531 frame->output_data.x->focus_state |= state;
3533 #ifdef HAVE_X_I18N
3534 if (FRAME_XIC (frame))
3535 XSetICFocus (FRAME_XIC (frame));
3536 #endif
3538 else if (type == FocusOut)
3540 frame->output_data.x->focus_state &= ~state;
3542 if (dpyinfo->x_focus_event_frame == frame)
3544 dpyinfo->x_focus_event_frame = 0;
3545 x_new_focus_frame (dpyinfo, 0);
3548 #ifdef HAVE_X_I18N
3549 if (FRAME_XIC (frame))
3550 XUnsetICFocus (FRAME_XIC (frame));
3551 #endif
3552 if (frame->pointer_invisible)
3553 XTtoggle_invisible_pointer (frame, 0);
3557 /* The focus may have changed. Figure out if it is a real focus change,
3558 by checking both FocusIn/Out and Enter/LeaveNotify events.
3560 Returns FOCUS_IN_EVENT event in *BUFP. */
3562 static void
3563 x_detect_focus_change (struct x_display_info *dpyinfo, XEvent *event, struct input_event *bufp)
3565 struct frame *frame;
3567 frame = x_any_window_to_frame (dpyinfo, event->xany.window);
3568 if (! frame)
3569 return;
3571 switch (event->type)
3573 case EnterNotify:
3574 case LeaveNotify:
3576 struct frame *focus_frame = dpyinfo->x_focus_event_frame;
3577 int focus_state
3578 = focus_frame ? focus_frame->output_data.x->focus_state : 0;
3580 if (event->xcrossing.detail != NotifyInferior
3581 && event->xcrossing.focus
3582 && ! (focus_state & FOCUS_EXPLICIT))
3583 x_focus_changed ((event->type == EnterNotify ? FocusIn : FocusOut),
3584 FOCUS_IMPLICIT,
3585 dpyinfo, frame, bufp);
3587 break;
3589 case FocusIn:
3590 case FocusOut:
3591 x_focus_changed (event->type,
3592 (event->xfocus.detail == NotifyPointer ?
3593 FOCUS_IMPLICIT : FOCUS_EXPLICIT),
3594 dpyinfo, frame, bufp);
3595 break;
3597 case ClientMessage:
3598 if (event->xclient.message_type == dpyinfo->Xatom_XEMBED)
3600 enum xembed_message msg = event->xclient.data.l[1];
3601 x_focus_changed ((msg == XEMBED_FOCUS_IN ? FocusIn : FocusOut),
3602 FOCUS_EXPLICIT, dpyinfo, frame, bufp);
3604 break;
3609 #if defined HAVE_MENUS && !defined USE_X_TOOLKIT && !defined USE_GTK
3610 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3612 void
3613 x_mouse_leave (struct x_display_info *dpyinfo)
3615 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
3617 #endif
3619 /* The focus has changed, or we have redirected a frame's focus to
3620 another frame (this happens when a frame uses a surrogate
3621 mini-buffer frame). Shift the highlight as appropriate.
3623 The FRAME argument doesn't necessarily have anything to do with which
3624 frame is being highlighted or un-highlighted; we only use it to find
3625 the appropriate X display info. */
3627 static void
3628 XTframe_rehighlight (struct frame *frame)
3630 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
3633 static void
3634 x_frame_rehighlight (struct x_display_info *dpyinfo)
3636 struct frame *old_highlight = dpyinfo->x_highlight_frame;
3638 if (dpyinfo->x_focus_frame)
3640 dpyinfo->x_highlight_frame
3641 = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
3642 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
3643 : dpyinfo->x_focus_frame);
3644 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
3646 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
3647 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
3650 else
3651 dpyinfo->x_highlight_frame = 0;
3653 if (dpyinfo->x_highlight_frame != old_highlight)
3655 if (old_highlight)
3656 frame_unhighlight (old_highlight);
3657 if (dpyinfo->x_highlight_frame)
3658 frame_highlight (dpyinfo->x_highlight_frame);
3664 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3666 /* Initialize mode_switch_bit and modifier_meaning. */
3667 static void
3668 x_find_modifier_meanings (struct x_display_info *dpyinfo)
3670 int min_code, max_code;
3671 KeySym *syms;
3672 int syms_per_code;
3673 XModifierKeymap *mods;
3675 dpyinfo->meta_mod_mask = 0;
3676 dpyinfo->shift_lock_mask = 0;
3677 dpyinfo->alt_mod_mask = 0;
3678 dpyinfo->super_mod_mask = 0;
3679 dpyinfo->hyper_mod_mask = 0;
3681 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
3683 syms = XGetKeyboardMapping (dpyinfo->display,
3684 min_code, max_code - min_code + 1,
3685 &syms_per_code);
3686 mods = XGetModifierMapping (dpyinfo->display);
3688 /* Scan the modifier table to see which modifier bits the Meta and
3689 Alt keysyms are on. */
3691 int row, col; /* The row and column in the modifier table. */
3692 int found_alt_or_meta;
3694 for (row = 3; row < 8; row++)
3696 found_alt_or_meta = 0;
3697 for (col = 0; col < mods->max_keypermod; col++)
3699 KeyCode code = mods->modifiermap[(row * mods->max_keypermod) + col];
3701 /* Zeroes are used for filler. Skip them. */
3702 if (code == 0)
3703 continue;
3705 /* Are any of this keycode's keysyms a meta key? */
3707 int code_col;
3709 for (code_col = 0; code_col < syms_per_code; code_col++)
3711 int sym = syms[((code - min_code) * syms_per_code) + code_col];
3713 switch (sym)
3715 case XK_Meta_L:
3716 case XK_Meta_R:
3717 found_alt_or_meta = 1;
3718 dpyinfo->meta_mod_mask |= (1 << row);
3719 break;
3721 case XK_Alt_L:
3722 case XK_Alt_R:
3723 found_alt_or_meta = 1;
3724 dpyinfo->alt_mod_mask |= (1 << row);
3725 break;
3727 case XK_Hyper_L:
3728 case XK_Hyper_R:
3729 if (!found_alt_or_meta)
3730 dpyinfo->hyper_mod_mask |= (1 << row);
3731 code_col = syms_per_code;
3732 col = mods->max_keypermod;
3733 break;
3735 case XK_Super_L:
3736 case XK_Super_R:
3737 if (!found_alt_or_meta)
3738 dpyinfo->super_mod_mask |= (1 << row);
3739 code_col = syms_per_code;
3740 col = mods->max_keypermod;
3741 break;
3743 case XK_Shift_Lock:
3744 /* Ignore this if it's not on the lock modifier. */
3745 if (!found_alt_or_meta && ((1 << row) == LockMask))
3746 dpyinfo->shift_lock_mask = LockMask;
3747 code_col = syms_per_code;
3748 col = mods->max_keypermod;
3749 break;
3757 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3758 if (! dpyinfo->meta_mod_mask)
3760 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
3761 dpyinfo->alt_mod_mask = 0;
3764 /* If some keys are both alt and meta,
3765 make them just meta, not alt. */
3766 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
3768 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
3771 XFree ((char *) syms);
3772 XFreeModifiermap (mods);
3775 /* Convert between the modifier bits X uses and the modifier bits
3776 Emacs uses. */
3779 x_x_to_emacs_modifiers (struct x_display_info *dpyinfo, int state)
3781 int mod_meta = meta_modifier;
3782 int mod_alt = alt_modifier;
3783 int mod_hyper = hyper_modifier;
3784 int mod_super = super_modifier;
3785 Lisp_Object tem;
3787 tem = Fget (Vx_alt_keysym, Qmodifier_value);
3788 if (INTEGERP (tem)) mod_alt = XINT (tem) & INT_MAX;
3789 tem = Fget (Vx_meta_keysym, Qmodifier_value);
3790 if (INTEGERP (tem)) mod_meta = XINT (tem) & INT_MAX;
3791 tem = Fget (Vx_hyper_keysym, Qmodifier_value);
3792 if (INTEGERP (tem)) mod_hyper = XINT (tem) & INT_MAX;
3793 tem = Fget (Vx_super_keysym, Qmodifier_value);
3794 if (INTEGERP (tem)) mod_super = XINT (tem) & INT_MAX;
3796 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
3797 | ((state & ControlMask) ? ctrl_modifier : 0)
3798 | ((state & dpyinfo->meta_mod_mask) ? mod_meta : 0)
3799 | ((state & dpyinfo->alt_mod_mask) ? mod_alt : 0)
3800 | ((state & dpyinfo->super_mod_mask) ? mod_super : 0)
3801 | ((state & dpyinfo->hyper_mod_mask) ? mod_hyper : 0));
3804 static int
3805 x_emacs_to_x_modifiers (struct x_display_info *dpyinfo, EMACS_INT state)
3807 EMACS_INT mod_meta = meta_modifier;
3808 EMACS_INT mod_alt = alt_modifier;
3809 EMACS_INT mod_hyper = hyper_modifier;
3810 EMACS_INT mod_super = super_modifier;
3812 Lisp_Object tem;
3814 tem = Fget (Vx_alt_keysym, Qmodifier_value);
3815 if (INTEGERP (tem)) mod_alt = XINT (tem);
3816 tem = Fget (Vx_meta_keysym, Qmodifier_value);
3817 if (INTEGERP (tem)) mod_meta = XINT (tem);
3818 tem = Fget (Vx_hyper_keysym, Qmodifier_value);
3819 if (INTEGERP (tem)) mod_hyper = XINT (tem);
3820 tem = Fget (Vx_super_keysym, Qmodifier_value);
3821 if (INTEGERP (tem)) mod_super = XINT (tem);
3824 return ( ((state & mod_alt) ? dpyinfo->alt_mod_mask : 0)
3825 | ((state & mod_super) ? dpyinfo->super_mod_mask : 0)
3826 | ((state & mod_hyper) ? dpyinfo->hyper_mod_mask : 0)
3827 | ((state & shift_modifier) ? ShiftMask : 0)
3828 | ((state & ctrl_modifier) ? ControlMask : 0)
3829 | ((state & mod_meta) ? dpyinfo->meta_mod_mask : 0));
3832 /* Convert a keysym to its name. */
3834 char *
3835 x_get_keysym_name (int keysym)
3837 char *value;
3839 BLOCK_INPUT;
3840 value = XKeysymToString (keysym);
3841 UNBLOCK_INPUT;
3843 return value;
3848 /* Mouse clicks and mouse movement. Rah. */
3850 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3852 If the event is a button press, then note that we have grabbed
3853 the mouse. */
3855 static Lisp_Object
3856 construct_mouse_click (struct input_event *result, XButtonEvent *event, struct frame *f)
3858 /* Make the event type NO_EVENT; we'll change that when we decide
3859 otherwise. */
3860 result->kind = MOUSE_CLICK_EVENT;
3861 result->code = event->button - Button1;
3862 result->timestamp = event->time;
3863 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
3864 event->state)
3865 | (event->type == ButtonRelease
3866 ? up_modifier
3867 : down_modifier));
3869 XSETINT (result->x, event->x);
3870 XSETINT (result->y, event->y);
3871 XSETFRAME (result->frame_or_window, f);
3872 result->arg = Qnil;
3873 return Qnil;
3877 /* Function to report a mouse movement to the mainstream Emacs code.
3878 The input handler calls this.
3880 We have received a mouse movement event, which is given in *event.
3881 If the mouse is over a different glyph than it was last time, tell
3882 the mainstream emacs code by setting mouse_moved. If not, ask for
3883 another motion event, so we can check again the next time it moves. */
3885 static XMotionEvent last_mouse_motion_event;
3886 static Lisp_Object last_mouse_motion_frame;
3888 static int
3889 note_mouse_movement (FRAME_PTR frame, XMotionEvent *event)
3891 last_mouse_movement_time = event->time;
3892 last_mouse_motion_event = *event;
3893 XSETFRAME (last_mouse_motion_frame, frame);
3895 if (!FRAME_X_OUTPUT (frame))
3896 return 0;
3898 if (event->window != FRAME_X_WINDOW (frame))
3900 frame->mouse_moved = 1;
3901 last_mouse_scroll_bar = Qnil;
3902 note_mouse_highlight (frame, -1, -1);
3903 last_mouse_glyph_frame = 0;
3904 return 1;
3908 /* Has the mouse moved off the glyph it was on at the last sighting? */
3909 if (frame != last_mouse_glyph_frame
3910 || event->x < last_mouse_glyph.x
3911 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
3912 || event->y < last_mouse_glyph.y
3913 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
3915 frame->mouse_moved = 1;
3916 last_mouse_scroll_bar = Qnil;
3917 note_mouse_highlight (frame, event->x, event->y);
3918 /* Remember which glyph we're now on. */
3919 remember_mouse_glyph (frame, event->x, event->y, &last_mouse_glyph);
3920 last_mouse_glyph_frame = frame;
3921 return 1;
3924 return 0;
3928 /************************************************************************
3929 Mouse Face
3930 ************************************************************************/
3932 static void
3933 redo_mouse_highlight (void)
3935 if (!NILP (last_mouse_motion_frame)
3936 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
3937 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
3938 last_mouse_motion_event.x,
3939 last_mouse_motion_event.y);
3944 /* Return the current position of the mouse.
3945 *FP should be a frame which indicates which display to ask about.
3947 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
3948 and *PART to the frame, window, and scroll bar part that the mouse
3949 is over. Set *X and *Y to the portion and whole of the mouse's
3950 position on the scroll bar.
3952 If the mouse movement started elsewhere, set *FP to the frame the
3953 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
3954 the mouse is over.
3956 Set *TIMESTAMP to the server time-stamp for the time at which the mouse
3957 was at this position.
3959 Don't store anything if we don't have a valid set of values to report.
3961 This clears the mouse_moved flag, so we can wait for the next mouse
3962 movement. */
3964 static void
3965 XTmouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
3966 enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
3967 Time *timestamp)
3969 FRAME_PTR f1;
3971 BLOCK_INPUT;
3973 if (! NILP (last_mouse_scroll_bar) && insist == 0)
3974 x_scroll_bar_report_motion (fp, bar_window, part, x, y, timestamp);
3975 else
3977 Window root;
3978 int root_x, root_y;
3980 Window dummy_window;
3981 int dummy;
3983 Lisp_Object frame, tail;
3985 /* Clear the mouse-moved flag for every frame on this display. */
3986 FOR_EACH_FRAME (tail, frame)
3987 if (FRAME_X_P (XFRAME (frame))
3988 && FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
3989 XFRAME (frame)->mouse_moved = 0;
3991 last_mouse_scroll_bar = Qnil;
3993 /* Figure out which root window we're on. */
3994 XQueryPointer (FRAME_X_DISPLAY (*fp),
3995 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
3997 /* The root window which contains the pointer. */
3998 &root,
4000 /* Trash which we can't trust if the pointer is on
4001 a different screen. */
4002 &dummy_window,
4004 /* The position on that root window. */
4005 &root_x, &root_y,
4007 /* More trash we can't trust. */
4008 &dummy, &dummy,
4010 /* Modifier keys and pointer buttons, about which
4011 we don't care. */
4012 (unsigned int *) &dummy);
4014 /* Now we have a position on the root; find the innermost window
4015 containing the pointer. */
4017 Window win, child;
4018 int win_x, win_y;
4019 int parent_x = 0, parent_y = 0;
4021 win = root;
4023 /* XTranslateCoordinates can get errors if the window
4024 structure is changing at the same time this function
4025 is running. So at least we must not crash from them. */
4027 x_catch_errors (FRAME_X_DISPLAY (*fp));
4029 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
4030 && FRAME_LIVE_P (last_mouse_frame))
4032 /* If mouse was grabbed on a frame, give coords for that frame
4033 even if the mouse is now outside it. */
4034 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
4036 /* From-window, to-window. */
4037 root, FRAME_X_WINDOW (last_mouse_frame),
4039 /* From-position, to-position. */
4040 root_x, root_y, &win_x, &win_y,
4042 /* Child of win. */
4043 &child);
4044 f1 = last_mouse_frame;
4046 else
4048 while (1)
4050 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
4052 /* From-window, to-window. */
4053 root, win,
4055 /* From-position, to-position. */
4056 root_x, root_y, &win_x, &win_y,
4058 /* Child of win. */
4059 &child);
4061 if (child == None || child == win)
4062 break;
4063 #ifdef USE_GTK
4064 /* We don't wan't to know the innermost window. We
4065 want the edit window. For non-Gtk+ the innermost
4066 window is the edit window. For Gtk+ it might not
4067 be. It might be the tool bar for example. */
4068 if (x_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win))
4069 break;
4070 #endif
4071 win = child;
4072 parent_x = win_x;
4073 parent_y = win_y;
4076 /* Now we know that:
4077 win is the innermost window containing the pointer
4078 (XTC says it has no child containing the pointer),
4079 win_x and win_y are the pointer's position in it
4080 (XTC did this the last time through), and
4081 parent_x and parent_y are the pointer's position in win's parent.
4082 (They are what win_x and win_y were when win was child.
4083 If win is the root window, it has no parent, and
4084 parent_{x,y} are invalid, but that's okay, because we'll
4085 never use them in that case.) */
4087 #ifdef USE_GTK
4088 /* We don't wan't to know the innermost window. We
4089 want the edit window. */
4090 f1 = x_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
4091 #else
4092 /* Is win one of our frames? */
4093 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
4094 #endif
4096 #ifdef USE_X_TOOLKIT
4097 /* If we end up with the menu bar window, say it's not
4098 on the frame. */
4099 if (f1 != NULL
4100 && f1->output_data.x->menubar_widget
4101 && win == XtWindow (f1->output_data.x->menubar_widget))
4102 f1 = NULL;
4103 #endif /* USE_X_TOOLKIT */
4106 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
4107 f1 = 0;
4109 x_uncatch_errors ();
4111 /* If not, is it one of our scroll bars? */
4112 if (! f1)
4114 struct scroll_bar *bar;
4116 bar = x_window_to_scroll_bar (FRAME_X_DISPLAY (*fp), win);
4118 if (bar)
4120 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4121 win_x = parent_x;
4122 win_y = parent_y;
4126 if (f1 == 0 && insist > 0)
4127 f1 = SELECTED_FRAME ();
4129 if (f1)
4131 /* Ok, we found a frame. Store all the values.
4132 last_mouse_glyph is a rectangle used to reduce the
4133 generation of mouse events. To not miss any motion
4134 events, we must divide the frame into rectangles of the
4135 size of the smallest character that could be displayed
4136 on it, i.e. into the same rectangles that matrices on
4137 the frame are divided into. */
4139 remember_mouse_glyph (f1, win_x, win_y, &last_mouse_glyph);
4140 last_mouse_glyph_frame = f1;
4142 *bar_window = Qnil;
4143 *part = 0;
4144 *fp = f1;
4145 XSETINT (*x, win_x);
4146 XSETINT (*y, win_y);
4147 *timestamp = last_mouse_movement_time;
4152 UNBLOCK_INPUT;
4157 /***********************************************************************
4158 Scroll bars
4159 ***********************************************************************/
4161 /* Scroll bar support. */
4163 /* Given an X window ID and a DISPLAY, find the struct scroll_bar which
4164 manages it.
4165 This can be called in GC, so we have to make sure to strip off mark
4166 bits. */
4168 static struct scroll_bar *
4169 x_window_to_scroll_bar (Display *display, Window window_id)
4171 Lisp_Object tail;
4173 #if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
4174 window_id = (Window) xg_get_scroll_id_for_window (display, window_id);
4175 #endif /* USE_GTK && USE_TOOLKIT_SCROLL_BARS */
4177 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
4179 Lisp_Object frame, bar, condemned;
4181 frame = XCAR (tail);
4182 /* All elements of Vframe_list should be frames. */
4183 if (! FRAMEP (frame))
4184 abort ();
4186 if (! FRAME_X_P (XFRAME (frame)))
4187 continue;
4189 /* Scan this frame's scroll bar list for a scroll bar with the
4190 right window ID. */
4191 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
4192 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
4193 /* This trick allows us to search both the ordinary and
4194 condemned scroll bar lists with one loop. */
4195 ! NILP (bar) || (bar = condemned,
4196 condemned = Qnil,
4197 ! NILP (bar));
4198 bar = XSCROLL_BAR (bar)->next)
4199 if (XSCROLL_BAR (bar)->x_window == window_id &&
4200 FRAME_X_DISPLAY (XFRAME (frame)) == display)
4201 return XSCROLL_BAR (bar);
4204 return NULL;
4208 #if defined USE_LUCID
4210 /* Return the Lucid menu bar WINDOW is part of. Return null
4211 if WINDOW is not part of a menu bar. */
4213 static Widget
4214 x_window_to_menu_bar (Window window)
4216 Lisp_Object tail;
4218 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
4220 if (FRAME_X_P (XFRAME (XCAR (tail))))
4222 Lisp_Object frame = XCAR (tail);
4223 Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
4225 if (menu_bar && xlwmenu_window_p (menu_bar, window))
4226 return menu_bar;
4230 return NULL;
4233 #endif /* USE_LUCID */
4236 /************************************************************************
4237 Toolkit scroll bars
4238 ************************************************************************/
4240 #ifdef USE_TOOLKIT_SCROLL_BARS
4242 static void x_scroll_bar_to_input_event (XEvent *, struct input_event *);
4243 static void x_send_scroll_bar_event (Lisp_Object, int, int, int);
4244 static void x_create_toolkit_scroll_bar (struct frame *,
4245 struct scroll_bar *);
4246 static void x_set_toolkit_scroll_bar_thumb (struct scroll_bar *,
4247 int, int, int);
4250 /* Lisp window being scrolled. Set when starting to interact with
4251 a toolkit scroll bar, reset to nil when ending the interaction. */
4253 static Lisp_Object window_being_scrolled;
4255 /* Last scroll bar part sent in xm_scroll_callback. */
4257 static int last_scroll_bar_part;
4259 /* Whether this is an Xaw with arrow-scrollbars. This should imply
4260 that movements of 1/20 of the screen size are mapped to up/down. */
4262 #ifndef USE_GTK
4263 /* Id of action hook installed for scroll bars. */
4265 static XtActionHookId action_hook_id;
4267 static Boolean xaw3d_arrow_scroll;
4269 /* Whether the drag scrolling maintains the mouse at the top of the
4270 thumb. If not, resizing the thumb needs to be done more carefully
4271 to avoid jerkiness. */
4273 static Boolean xaw3d_pick_top;
4275 /* Action hook installed via XtAppAddActionHook when toolkit scroll
4276 bars are used.. The hook is responsible for detecting when
4277 the user ends an interaction with the scroll bar, and generates
4278 a `end-scroll' SCROLL_BAR_CLICK_EVENT' event if so. */
4280 static void
4281 xt_action_hook (Widget widget, XtPointer client_data, String action_name,
4282 XEvent *event, String *params, Cardinal *num_params)
4284 int scroll_bar_p;
4285 const char *end_action;
4287 #ifdef USE_MOTIF
4288 scroll_bar_p = XmIsScrollBar (widget);
4289 end_action = "Release";
4290 #else /* !USE_MOTIF i.e. use Xaw */
4291 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
4292 end_action = "EndScroll";
4293 #endif /* USE_MOTIF */
4295 if (scroll_bar_p
4296 && strcmp (action_name, end_action) == 0
4297 && WINDOWP (window_being_scrolled))
4299 struct window *w;
4301 x_send_scroll_bar_event (window_being_scrolled,
4302 scroll_bar_end_scroll, 0, 0);
4303 w = XWINDOW (window_being_scrolled);
4305 if (!NILP (XSCROLL_BAR (w->vertical_scroll_bar)->dragging))
4307 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
4308 /* The thumb size is incorrect while dragging: fix it. */
4309 set_vertical_scroll_bar (w);
4311 window_being_scrolled = Qnil;
4312 last_scroll_bar_part = -1;
4314 /* Xt timeouts no longer needed. */
4315 toolkit_scroll_bar_interaction = 0;
4318 #endif /* not USE_GTK */
4320 /* A vector of windows used for communication between
4321 x_send_scroll_bar_event and x_scroll_bar_to_input_event. */
4323 static struct window **scroll_bar_windows;
4324 static ptrdiff_t scroll_bar_windows_size;
4327 /* Send a client message with message type Xatom_Scrollbar for a
4328 scroll action to the frame of WINDOW. PART is a value identifying
4329 the part of the scroll bar that was clicked on. PORTION is the
4330 amount to scroll of a whole of WHOLE. */
4332 static void
4333 x_send_scroll_bar_event (Lisp_Object window, int part, int portion, int whole)
4335 XEvent event;
4336 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
4337 struct window *w = XWINDOW (window);
4338 struct frame *f = XFRAME (w->frame);
4339 ptrdiff_t i;
4341 BLOCK_INPUT;
4343 /* Construct a ClientMessage event to send to the frame. */
4344 ev->type = ClientMessage;
4345 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
4346 ev->display = FRAME_X_DISPLAY (f);
4347 ev->window = FRAME_X_WINDOW (f);
4348 ev->format = 32;
4350 /* We can only transfer 32 bits in the XClientMessageEvent, which is
4351 not enough to store a pointer or Lisp_Object on a 64 bit system.
4352 So, store the window in scroll_bar_windows and pass the index
4353 into that array in the event. */
4354 for (i = 0; i < scroll_bar_windows_size; ++i)
4355 if (scroll_bar_windows[i] == NULL)
4356 break;
4358 if (i == scroll_bar_windows_size)
4360 ptrdiff_t old_nbytes =
4361 scroll_bar_windows_size * sizeof *scroll_bar_windows;
4362 ptrdiff_t nbytes;
4363 enum { XClientMessageEvent_MAX = 0x7fffffff };
4364 scroll_bar_windows =
4365 xpalloc (scroll_bar_windows, &scroll_bar_windows_size, 1,
4366 XClientMessageEvent_MAX, sizeof *scroll_bar_windows);
4367 nbytes = scroll_bar_windows_size * sizeof *scroll_bar_windows;
4368 memset (&scroll_bar_windows[i], 0, nbytes - old_nbytes);
4371 scroll_bar_windows[i] = w;
4372 ev->data.l[0] = (long) i;
4373 ev->data.l[1] = (long) part;
4374 ev->data.l[2] = (long) 0;
4375 ev->data.l[3] = (long) portion;
4376 ev->data.l[4] = (long) whole;
4378 /* Make Xt timeouts work while the scroll bar is active. */
4379 #ifdef USE_X_TOOLKIT
4380 toolkit_scroll_bar_interaction = 1;
4381 x_activate_timeout_atimer ();
4382 #endif
4384 /* Setting the event mask to zero means that the message will
4385 be sent to the client that created the window, and if that
4386 window no longer exists, no event will be sent. */
4387 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
4388 UNBLOCK_INPUT;
4392 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
4393 in *IEVENT. */
4395 static void
4396 x_scroll_bar_to_input_event (XEvent *event, struct input_event *ievent)
4398 XClientMessageEvent *ev = (XClientMessageEvent *) event;
4399 Lisp_Object window;
4400 struct window *w;
4402 w = scroll_bar_windows[ev->data.l[0]];
4403 scroll_bar_windows[ev->data.l[0]] = NULL;
4405 XSETWINDOW (window, w);
4407 ievent->kind = SCROLL_BAR_CLICK_EVENT;
4408 ievent->frame_or_window = window;
4409 ievent->arg = Qnil;
4410 #ifdef USE_GTK
4411 ievent->timestamp = CurrentTime;
4412 #else
4413 ievent->timestamp =
4414 XtLastTimestampProcessed (FRAME_X_DISPLAY (XFRAME (w->frame)));
4415 #endif
4416 ievent->part = ev->data.l[1];
4417 ievent->code = ev->data.l[2];
4418 ievent->x = make_number ((int) ev->data.l[3]);
4419 ievent->y = make_number ((int) ev->data.l[4]);
4420 ievent->modifiers = 0;
4424 #ifdef USE_MOTIF
4426 /* Minimum and maximum values used for Motif scroll bars. */
4428 #define XM_SB_MAX 10000000
4431 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
4432 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
4433 CALL_DATA is a pointer to a XmScrollBarCallbackStruct. */
4435 static void
4436 xm_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data)
4438 struct scroll_bar *bar = (struct scroll_bar *) client_data;
4439 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
4440 int part = -1, whole = 0, portion = 0;
4442 switch (cs->reason)
4444 case XmCR_DECREMENT:
4445 bar->dragging = Qnil;
4446 part = scroll_bar_up_arrow;
4447 break;
4449 case XmCR_INCREMENT:
4450 bar->dragging = Qnil;
4451 part = scroll_bar_down_arrow;
4452 break;
4454 case XmCR_PAGE_DECREMENT:
4455 bar->dragging = Qnil;
4456 part = scroll_bar_above_handle;
4457 break;
4459 case XmCR_PAGE_INCREMENT:
4460 bar->dragging = Qnil;
4461 part = scroll_bar_below_handle;
4462 break;
4464 case XmCR_TO_TOP:
4465 bar->dragging = Qnil;
4466 part = scroll_bar_to_top;
4467 break;
4469 case XmCR_TO_BOTTOM:
4470 bar->dragging = Qnil;
4471 part = scroll_bar_to_bottom;
4472 break;
4474 case XmCR_DRAG:
4476 int slider_size;
4478 /* Get the slider size. */
4479 BLOCK_INPUT;
4480 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
4481 UNBLOCK_INPUT;
4483 whole = XM_SB_MAX - slider_size;
4484 portion = min (cs->value, whole);
4485 part = scroll_bar_handle;
4486 bar->dragging = make_number (cs->value);
4488 break;
4490 case XmCR_VALUE_CHANGED:
4491 break;
4494 if (part >= 0)
4496 window_being_scrolled = bar->window;
4497 last_scroll_bar_part = part;
4498 x_send_scroll_bar_event (bar->window, part, portion, whole);
4502 #elif defined USE_GTK
4504 /* Scroll bar callback for GTK scroll bars. WIDGET is the scroll
4505 bar widget. DATA is a pointer to the scroll_bar structure. */
4507 static gboolean
4508 xg_scroll_callback (GtkRange *range,
4509 GtkScrollType scroll,
4510 gdouble value,
4511 gpointer user_data)
4513 struct scroll_bar *bar = (struct scroll_bar *) user_data;
4514 gdouble position;
4515 int part = -1, whole = 0, portion = 0;
4516 GtkAdjustment *adj = GTK_ADJUSTMENT (gtk_range_get_adjustment (range));
4517 FRAME_PTR f = (FRAME_PTR) g_object_get_data (G_OBJECT (range), XG_FRAME_DATA);
4519 if (xg_ignore_gtk_scrollbar) return FALSE;
4520 position = gtk_adjustment_get_value (adj);
4523 switch (scroll)
4525 case GTK_SCROLL_JUMP:
4526 /* Buttons 1 2 or 3 must be grabbed. */
4527 if (FRAME_X_DISPLAY_INFO (f)->grabbed != 0
4528 && FRAME_X_DISPLAY_INFO (f)->grabbed < (1 << 4))
4530 part = scroll_bar_handle;
4531 whole = gtk_adjustment_get_upper (adj) -
4532 gtk_adjustment_get_page_size (adj);
4533 portion = min ((int)position, whole);
4534 bar->dragging = make_number ((int)portion);
4536 break;
4537 case GTK_SCROLL_STEP_BACKWARD:
4538 part = scroll_bar_up_arrow;
4539 bar->dragging = Qnil;
4540 break;
4541 case GTK_SCROLL_STEP_FORWARD:
4542 part = scroll_bar_down_arrow;
4543 bar->dragging = Qnil;
4544 break;
4545 case GTK_SCROLL_PAGE_BACKWARD:
4546 part = scroll_bar_above_handle;
4547 bar->dragging = Qnil;
4548 break;
4549 case GTK_SCROLL_PAGE_FORWARD:
4550 part = scroll_bar_below_handle;
4551 bar->dragging = Qnil;
4552 break;
4555 if (part >= 0)
4557 window_being_scrolled = bar->window;
4558 last_scroll_bar_part = part;
4559 x_send_scroll_bar_event (bar->window, part, portion, whole);
4562 return FALSE;
4565 /* Callback for button release. Sets dragging to Qnil when dragging is done. */
4567 static gboolean
4568 xg_end_scroll_callback (GtkWidget *widget,
4569 GdkEventButton *event,
4570 gpointer user_data)
4572 struct scroll_bar *bar = (struct scroll_bar *) user_data;
4573 bar->dragging = Qnil;
4574 if (WINDOWP (window_being_scrolled))
4576 x_send_scroll_bar_event (window_being_scrolled,
4577 scroll_bar_end_scroll, 0, 0);
4578 window_being_scrolled = Qnil;
4581 return FALSE;
4585 #else /* not USE_GTK and not USE_MOTIF */
4587 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
4588 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
4589 scroll bar struct. CALL_DATA is a pointer to a float saying where
4590 the thumb is. */
4592 static void
4593 xaw_jump_callback (Widget widget, XtPointer client_data, XtPointer call_data)
4595 struct scroll_bar *bar = (struct scroll_bar *) client_data;
4596 float top = *(float *) call_data;
4597 float shown;
4598 int whole, portion, height;
4599 int part;
4601 /* Get the size of the thumb, a value between 0 and 1. */
4602 BLOCK_INPUT;
4603 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
4604 UNBLOCK_INPUT;
4606 whole = 10000000;
4607 portion = shown < 1 ? top * whole : 0;
4609 if (shown < 1 && (eabs (top + shown - 1) < 1.0f / height))
4610 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
4611 the bottom, so we force the scrolling whenever we see that we're
4612 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
4613 we try to ensure that we always stay two pixels away from the
4614 bottom). */
4615 part = scroll_bar_down_arrow;
4616 else
4617 part = scroll_bar_handle;
4619 window_being_scrolled = bar->window;
4620 bar->dragging = make_number (portion);
4621 last_scroll_bar_part = part;
4622 x_send_scroll_bar_event (bar->window, part, portion, whole);
4626 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
4627 i.e. line or page up or down. WIDGET is the Xaw scroll bar
4628 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
4629 the scroll bar. CALL_DATA is an integer specifying the action that
4630 has taken place. Its magnitude is in the range 0..height of the
4631 scroll bar. Negative values mean scroll towards buffer start.
4632 Values < height of scroll bar mean line-wise movement. */
4634 static void
4635 xaw_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data)
4637 struct scroll_bar *bar = (struct scroll_bar *) client_data;
4638 /* The position really is stored cast to a pointer. */
4639 int position = (long) call_data;
4640 Dimension height;
4641 int part;
4643 /* Get the height of the scroll bar. */
4644 BLOCK_INPUT;
4645 XtVaGetValues (widget, XtNheight, &height, NULL);
4646 UNBLOCK_INPUT;
4648 if (eabs (position) >= height)
4649 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
4651 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
4652 it maps line-movement to call_data = max(5, height/20). */
4653 else if (xaw3d_arrow_scroll && eabs (position) <= max (5, height / 20))
4654 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
4655 else
4656 part = scroll_bar_move_ratio;
4658 window_being_scrolled = bar->window;
4659 bar->dragging = Qnil;
4660 last_scroll_bar_part = part;
4661 x_send_scroll_bar_event (bar->window, part, position, height);
4664 #endif /* not USE_GTK and not USE_MOTIF */
4666 #define SCROLL_BAR_NAME "verticalScrollBar"
4668 /* Create the widget for scroll bar BAR on frame F. Record the widget
4669 and X window of the scroll bar in BAR. */
4671 #ifdef USE_GTK
4672 static void
4673 x_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
4675 const char *scroll_bar_name = SCROLL_BAR_NAME;
4677 BLOCK_INPUT;
4678 xg_create_scroll_bar (f, bar, G_CALLBACK (xg_scroll_callback),
4679 G_CALLBACK (xg_end_scroll_callback),
4680 scroll_bar_name);
4681 UNBLOCK_INPUT;
4684 #else /* not USE_GTK */
4686 static void
4687 x_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
4689 Window xwindow;
4690 Widget widget;
4691 Arg av[20];
4692 int ac = 0;
4693 char const *scroll_bar_name = SCROLL_BAR_NAME;
4694 unsigned long pixel;
4696 BLOCK_INPUT;
4698 #ifdef USE_MOTIF
4699 /* Set resources. Create the widget. */
4700 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
4701 XtSetArg (av[ac], XmNminimum, 0); ++ac;
4702 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
4703 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
4704 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
4705 XtSetArg (av[ac], XmNincrement, 1); ++ac;
4706 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
4708 pixel = f->output_data.x->scroll_bar_foreground_pixel;
4709 if (pixel != -1)
4711 XtSetArg (av[ac], XmNforeground, pixel);
4712 ++ac;
4715 pixel = f->output_data.x->scroll_bar_background_pixel;
4716 if (pixel != -1)
4718 XtSetArg (av[ac], XmNbackground, pixel);
4719 ++ac;
4722 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
4723 scroll_bar_name, av, ac);
4725 /* Add one callback for everything that can happen. */
4726 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
4727 (XtPointer) bar);
4728 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
4729 (XtPointer) bar);
4730 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
4731 (XtPointer) bar);
4732 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
4733 (XtPointer) bar);
4734 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
4735 (XtPointer) bar);
4736 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
4737 (XtPointer) bar);
4738 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
4739 (XtPointer) bar);
4741 /* Realize the widget. Only after that is the X window created. */
4742 XtRealizeWidget (widget);
4744 /* Set the cursor to an arrow. I didn't find a resource to do that.
4745 And I'm wondering why it hasn't an arrow cursor by default. */
4746 XDefineCursor (XtDisplay (widget), XtWindow (widget),
4747 f->output_data.x->nontext_cursor);
4749 #else /* !USE_MOTIF i.e. use Xaw */
4751 /* Set resources. Create the widget. The background of the
4752 Xaw3d scroll bar widget is a little bit light for my taste.
4753 We don't alter it here to let users change it according
4754 to their taste with `emacs*verticalScrollBar.background: xxx'. */
4755 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
4756 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
4757 /* For smoother scrolling with Xaw3d -sm */
4758 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
4760 pixel = f->output_data.x->scroll_bar_foreground_pixel;
4761 if (pixel != -1)
4763 XtSetArg (av[ac], XtNforeground, pixel);
4764 ++ac;
4767 pixel = f->output_data.x->scroll_bar_background_pixel;
4768 if (pixel != -1)
4770 XtSetArg (av[ac], XtNbackground, pixel);
4771 ++ac;
4774 /* Top/bottom shadow colors. */
4776 /* Allocate them, if necessary. */
4777 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1)
4779 pixel = f->output_data.x->scroll_bar_background_pixel;
4780 if (pixel != -1)
4782 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
4783 FRAME_X_COLORMAP (f),
4784 &pixel, 1.2, 0x8000))
4785 pixel = -1;
4786 f->output_data.x->scroll_bar_top_shadow_pixel = pixel;
4789 if (f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
4791 pixel = f->output_data.x->scroll_bar_background_pixel;
4792 if (pixel != -1)
4794 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
4795 FRAME_X_COLORMAP (f),
4796 &pixel, 0.6, 0x4000))
4797 pixel = -1;
4798 f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
4802 #ifdef XtNbeNiceToColormap
4803 /* Tell the toolkit about them. */
4804 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1
4805 || f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
4806 /* We tried to allocate a color for the top/bottom shadow, and
4807 failed, so tell Xaw3d to use dithering instead. */
4808 /* But only if we have a small colormap. Xaw3d can allocate nice
4809 colors itself. */
4811 XtSetArg (av[ac], XtNbeNiceToColormap,
4812 DefaultDepthOfScreen (FRAME_X_SCREEN (f)) < 16);
4813 ++ac;
4815 else
4816 /* Tell what colors Xaw3d should use for the top/bottom shadow, to
4817 be more consistent with other emacs 3d colors, and since Xaw3d is
4818 not good at dealing with allocation failure. */
4820 /* This tells Xaw3d to use real colors instead of dithering for
4821 the shadows. */
4822 XtSetArg (av[ac], XtNbeNiceToColormap, False);
4823 ++ac;
4825 /* Specify the colors. */
4826 pixel = f->output_data.x->scroll_bar_top_shadow_pixel;
4827 if (pixel != -1)
4829 XtSetArg (av[ac], XtNtopShadowPixel, pixel);
4830 ++ac;
4832 pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel;
4833 if (pixel != -1)
4835 XtSetArg (av[ac], XtNbottomShadowPixel, pixel);
4836 ++ac;
4839 #endif
4841 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
4842 f->output_data.x->edit_widget, av, ac);
4845 char const *initial = "";
4846 char const *val = initial;
4847 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
4848 #ifdef XtNarrowScrollbars
4849 XtNarrowScrollbars, (XtPointer) &xaw3d_arrow_scroll,
4850 #endif
4851 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
4852 if (xaw3d_arrow_scroll || val == initial)
4853 { /* ARROW_SCROLL */
4854 xaw3d_arrow_scroll = True;
4855 /* Isn't that just a personal preference ? --Stef */
4856 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
4860 /* Define callbacks. */
4861 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
4862 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
4863 (XtPointer) bar);
4865 /* Realize the widget. Only after that is the X window created. */
4866 XtRealizeWidget (widget);
4868 #endif /* !USE_MOTIF */
4870 /* Install an action hook that lets us detect when the user
4871 finishes interacting with a scroll bar. */
4872 if (action_hook_id == 0)
4873 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
4875 /* Remember X window and widget in the scroll bar vector. */
4876 SET_SCROLL_BAR_X_WIDGET (bar, widget);
4877 xwindow = XtWindow (widget);
4878 bar->x_window = xwindow;
4880 UNBLOCK_INPUT;
4882 #endif /* not USE_GTK */
4885 /* Set the thumb size and position of scroll bar BAR. We are currently
4886 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4888 #ifdef USE_GTK
4889 static void
4890 x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position, int whole)
4892 xg_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
4895 #else /* not USE_GTK */
4896 static void
4897 x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position,
4898 int whole)
4900 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4901 Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
4902 float top, shown;
4904 BLOCK_INPUT;
4906 #ifdef USE_MOTIF
4908 /* We use an estimate of 30 chars per line rather than the real
4909 `portion' value. This has the disadvantage that the thumb size
4910 is not very representative, but it makes our life a lot easier.
4911 Otherwise, we have to constantly adjust the thumb size, which
4912 we can't always do quickly enough: while dragging, the size of
4913 the thumb might prevent the user from dragging the thumb all the
4914 way to the end. but Motif and some versions of Xaw3d don't allow
4915 updating the thumb size while dragging. Also, even if we can update
4916 its size, the update will often happen too late.
4917 If you don't believe it, check out revision 1.650 of xterm.c to see
4918 what hoops we were going through and the still poor behavior we got. */
4919 portion = WINDOW_TOTAL_LINES (XWINDOW (bar->window)) * 30;
4920 /* When the thumb is at the bottom, position == whole.
4921 So we need to increase `whole' to make space for the thumb. */
4922 whole += portion;
4924 if (whole <= 0)
4925 top = 0, shown = 1;
4926 else
4928 top = (float) position / whole;
4929 shown = (float) portion / whole;
4932 if (NILP (bar->dragging))
4934 int size, value;
4936 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
4937 is the scroll bar's maximum and MIN is the scroll bar's minimum
4938 value. */
4939 size = shown * XM_SB_MAX;
4940 size = min (size, XM_SB_MAX);
4941 size = max (size, 1);
4943 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
4944 value = top * XM_SB_MAX;
4945 value = min (value, XM_SB_MAX - size);
4947 XmScrollBarSetValues (widget, value, size, 0, 0, False);
4949 #else /* !USE_MOTIF i.e. use Xaw */
4951 if (whole == 0)
4952 top = 0, shown = 1;
4953 else
4955 top = (float) position / whole;
4956 shown = (float) portion / whole;
4960 float old_top, old_shown;
4961 Dimension height;
4962 XtVaGetValues (widget,
4963 XtNtopOfThumb, &old_top,
4964 XtNshown, &old_shown,
4965 XtNheight, &height,
4966 NULL);
4968 /* Massage the top+shown values. */
4969 if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow)
4970 top = max (0, min (1, top));
4971 else
4972 top = old_top;
4973 /* Keep two pixels available for moving the thumb down. */
4974 shown = max (0, min (1 - top - (2.0f / height), shown));
4976 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
4977 check that your system's configuration file contains a define
4978 for `NARROWPROTO'. See s/freebsd.h for an example. */
4979 if (top != old_top || shown != old_shown)
4981 if (NILP (bar->dragging))
4982 XawScrollbarSetThumb (widget, top, shown);
4983 else
4985 /* Try to make the scrolling a tad smoother. */
4986 if (!xaw3d_pick_top)
4987 shown = min (shown, old_shown);
4989 XawScrollbarSetThumb (widget, top, shown);
4993 #endif /* !USE_MOTIF */
4995 UNBLOCK_INPUT;
4997 #endif /* not USE_GTK */
4999 #endif /* USE_TOOLKIT_SCROLL_BARS */
5003 /************************************************************************
5004 Scroll bars, general
5005 ************************************************************************/
5007 /* Create a scroll bar and return the scroll bar vector for it. W is
5008 the Emacs window on which to create the scroll bar. TOP, LEFT,
5009 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
5010 scroll bar. */
5012 static struct scroll_bar *
5013 x_scroll_bar_create (struct window *w, int top, int left, int width, int height)
5015 struct frame *f = XFRAME (w->frame);
5016 struct scroll_bar *bar
5017 = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, x_window, PVEC_OTHER);
5019 BLOCK_INPUT;
5021 #ifdef USE_TOOLKIT_SCROLL_BARS
5022 x_create_toolkit_scroll_bar (f, bar);
5023 #else /* not USE_TOOLKIT_SCROLL_BARS */
5025 XSetWindowAttributes a;
5026 unsigned long mask;
5027 Window window;
5029 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
5030 if (a.background_pixel == -1)
5031 a.background_pixel = FRAME_BACKGROUND_PIXEL (f);
5033 a.event_mask = (ButtonPressMask | ButtonReleaseMask
5034 | ButtonMotionMask | PointerMotionHintMask
5035 | ExposureMask);
5036 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
5038 mask = (CWBackPixel | CWEventMask | CWCursor);
5040 /* Clear the area of W that will serve as a scroll bar. This is
5041 for the case that a window has been split horizontally. In
5042 this case, no clear_frame is generated to reduce flickering. */
5043 if (width > 0 && height > 0)
5044 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5045 left, top, width,
5046 window_box_height (w), False);
5048 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5049 /* Position and size of scroll bar. */
5050 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
5051 top,
5052 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
5053 height,
5054 /* Border width, depth, class, and visual. */
5056 CopyFromParent,
5057 CopyFromParent,
5058 CopyFromParent,
5059 /* Attributes. */
5060 mask, &a);
5061 bar->x_window = window;
5063 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5065 XSETWINDOW (bar->window, w);
5066 bar->top = top;
5067 bar->left = left;
5068 bar->width = width;
5069 bar->height = height;
5070 bar->start = 0;
5071 bar->end = 0;
5072 bar->dragging = Qnil;
5073 bar->fringe_extended_p = 0;
5075 /* Add bar to its frame's list of scroll bars. */
5076 bar->next = FRAME_SCROLL_BARS (f);
5077 bar->prev = Qnil;
5078 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
5079 if (!NILP (bar->next))
5080 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
5082 /* Map the window/widget. */
5083 #ifdef USE_TOOLKIT_SCROLL_BARS
5085 #ifdef USE_GTK
5086 xg_update_scrollbar_pos (f,
5087 bar->x_window,
5088 top,
5089 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
5090 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
5091 max (height, 1));
5092 #else /* not USE_GTK */
5093 Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
5094 XtConfigureWidget (scroll_bar,
5095 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
5096 top,
5097 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
5098 max (height, 1), 0);
5099 XtMapWidget (scroll_bar);
5100 #endif /* not USE_GTK */
5102 #else /* not USE_TOOLKIT_SCROLL_BARS */
5103 XMapRaised (FRAME_X_DISPLAY (f), bar->x_window);
5104 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5106 UNBLOCK_INPUT;
5107 return bar;
5111 #ifndef USE_TOOLKIT_SCROLL_BARS
5113 /* Draw BAR's handle in the proper position.
5115 If the handle is already drawn from START to END, don't bother
5116 redrawing it, unless REBUILD is non-zero; in that case, always
5117 redraw it. (REBUILD is handy for drawing the handle after expose
5118 events.)
5120 Normally, we want to constrain the start and end of the handle to
5121 fit inside its rectangle, but if the user is dragging the scroll
5122 bar handle, we want to let them drag it down all the way, so that
5123 the bar's top is as far down as it goes; otherwise, there's no way
5124 to move to the very end of the buffer. */
5126 static void
5127 x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end, int rebuild)
5129 int dragging = ! NILP (bar->dragging);
5130 Window w = bar->x_window;
5131 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5132 GC gc = f->output_data.x->normal_gc;
5134 /* If the display is already accurate, do nothing. */
5135 if (! rebuild
5136 && start == bar->start
5137 && end == bar->end)
5138 return;
5140 BLOCK_INPUT;
5143 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, bar->width);
5144 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, bar->height);
5145 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
5147 /* Make sure the values are reasonable, and try to preserve
5148 the distance between start and end. */
5150 int length = end - start;
5152 if (start < 0)
5153 start = 0;
5154 else if (start > top_range)
5155 start = top_range;
5156 end = start + length;
5158 if (end < start)
5159 end = start;
5160 else if (end > top_range && ! dragging)
5161 end = top_range;
5164 /* Store the adjusted setting in the scroll bar. */
5165 bar->start = start;
5166 bar->end = end;
5168 /* Clip the end position, just for display. */
5169 if (end > top_range)
5170 end = top_range;
5172 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
5173 below top positions, to make sure the handle is always at least
5174 that many pixels tall. */
5175 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
5177 /* Draw the empty space above the handle. Note that we can't clear
5178 zero-height areas; that means "clear to end of window." */
5179 if (0 < start)
5180 x_clear_area (FRAME_X_DISPLAY (f), w,
5181 /* x, y, width, height, and exposures. */
5182 VERTICAL_SCROLL_BAR_LEFT_BORDER,
5183 VERTICAL_SCROLL_BAR_TOP_BORDER,
5184 inside_width, start,
5185 False);
5187 /* Change to proper foreground color if one is specified. */
5188 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
5189 XSetForeground (FRAME_X_DISPLAY (f), gc,
5190 f->output_data.x->scroll_bar_foreground_pixel);
5192 /* Draw the handle itself. */
5193 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
5194 /* x, y, width, height */
5195 VERTICAL_SCROLL_BAR_LEFT_BORDER,
5196 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
5197 inside_width, end - start);
5199 /* Restore the foreground color of the GC if we changed it above. */
5200 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
5201 XSetForeground (FRAME_X_DISPLAY (f), gc,
5202 FRAME_FOREGROUND_PIXEL (f));
5204 /* Draw the empty space below the handle. Note that we can't
5205 clear zero-height areas; that means "clear to end of window." */
5206 if (end < inside_height)
5207 x_clear_area (FRAME_X_DISPLAY (f), w,
5208 /* x, y, width, height, and exposures. */
5209 VERTICAL_SCROLL_BAR_LEFT_BORDER,
5210 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
5211 inside_width, inside_height - end,
5212 False);
5216 UNBLOCK_INPUT;
5219 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5221 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5222 nil. */
5224 static void
5225 x_scroll_bar_remove (struct scroll_bar *bar)
5227 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5228 BLOCK_INPUT;
5230 #ifdef USE_TOOLKIT_SCROLL_BARS
5231 #ifdef USE_GTK
5232 xg_remove_scroll_bar (f, bar->x_window);
5233 #else /* not USE_GTK */
5234 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));
5235 #endif /* not USE_GTK */
5236 #else
5237 XDestroyWindow (FRAME_X_DISPLAY (f), bar->x_window);
5238 #endif
5240 /* Dissociate this scroll bar from its window. */
5241 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
5243 UNBLOCK_INPUT;
5247 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5248 that we are displaying PORTION characters out of a total of WHOLE
5249 characters, starting at POSITION. If WINDOW has no scroll bar,
5250 create one. */
5252 static void
5253 XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int position)
5255 struct frame *f = XFRAME (w->frame);
5256 struct scroll_bar *bar;
5257 int top, height, left, sb_left, width, sb_width;
5258 int window_y, window_height;
5259 #ifdef USE_TOOLKIT_SCROLL_BARS
5260 int fringe_extended_p;
5261 #endif
5263 /* Get window dimensions. */
5264 window_box (w, -1, 0, &window_y, 0, &window_height);
5265 top = window_y;
5266 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
5267 height = window_height;
5269 /* Compute the left edge of the scroll bar area. */
5270 left = WINDOW_SCROLL_BAR_AREA_X (w);
5272 /* Compute the width of the scroll bar which might be less than
5273 the width of the area reserved for the scroll bar. */
5274 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
5275 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
5276 else
5277 sb_width = width;
5279 /* Compute the left edge of the scroll bar. */
5280 #ifdef USE_TOOLKIT_SCROLL_BARS
5281 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
5282 sb_left = left + (WINDOW_RIGHTMOST_P (w) ? width - sb_width : 0);
5283 else
5284 sb_left = left + (WINDOW_LEFTMOST_P (w) ? 0 : width - sb_width);
5285 #else
5286 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
5287 sb_left = left + width - sb_width;
5288 else
5289 sb_left = left;
5290 #endif
5292 #ifdef USE_TOOLKIT_SCROLL_BARS
5293 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
5294 fringe_extended_p = (WINDOW_LEFTMOST_P (w)
5295 && WINDOW_LEFT_FRINGE_WIDTH (w)
5296 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
5297 || WINDOW_LEFT_MARGIN_COLS (w) == 0));
5298 else
5299 fringe_extended_p = (WINDOW_RIGHTMOST_P (w)
5300 && WINDOW_RIGHT_FRINGE_WIDTH (w)
5301 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
5302 || WINDOW_RIGHT_MARGIN_COLS (w) == 0));
5303 #endif
5305 /* Does the scroll bar exist yet? */
5306 if (NILP (w->vertical_scroll_bar))
5308 if (width > 0 && height > 0)
5310 BLOCK_INPUT;
5311 #ifdef USE_TOOLKIT_SCROLL_BARS
5312 if (fringe_extended_p)
5313 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5314 sb_left, top, sb_width, height, False);
5315 else
5316 #endif
5317 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5318 left, top, width, height, False);
5319 UNBLOCK_INPUT;
5322 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
5324 else
5326 /* It may just need to be moved and resized. */
5327 unsigned int mask = 0;
5329 bar = XSCROLL_BAR (w->vertical_scroll_bar);
5331 BLOCK_INPUT;
5333 if (sb_left != bar->left)
5334 mask |= CWX;
5335 if (top != bar->top)
5336 mask |= CWY;
5337 if (sb_width != bar->width)
5338 mask |= CWWidth;
5339 if (height != bar->height)
5340 mask |= CWHeight;
5342 #ifdef USE_TOOLKIT_SCROLL_BARS
5344 /* Move/size the scroll bar widget. */
5345 if (mask || bar->fringe_extended_p != fringe_extended_p)
5347 /* Since toolkit scroll bars are smaller than the space reserved
5348 for them on the frame, we have to clear "under" them. */
5349 if (width > 0 && height > 0)
5351 if (fringe_extended_p)
5352 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5353 sb_left, top, sb_width, height, False);
5354 else
5355 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5356 left, top, width, height, False);
5358 #ifdef USE_GTK
5359 xg_update_scrollbar_pos (f,
5360 bar->x_window,
5361 top,
5362 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
5363 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM *2,
5364 max (height, 1));
5365 #else /* not USE_GTK */
5366 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
5367 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
5368 top,
5369 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
5370 max (height, 1), 0);
5371 #endif /* not USE_GTK */
5373 #else /* not USE_TOOLKIT_SCROLL_BARS */
5375 /* Clear areas not covered by the scroll bar because of
5376 VERTICAL_SCROLL_BAR_WIDTH_TRIM. */
5377 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
5379 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5380 left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
5381 height, False);
5382 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5383 left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
5384 top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
5385 height, False);
5388 /* Clear areas not covered by the scroll bar because it's not as
5389 wide as the area reserved for it. This makes sure a
5390 previous mode line display is cleared after C-x 2 C-x 1, for
5391 example. */
5393 int area_width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
5394 int rest = area_width - sb_width;
5395 if (rest > 0 && height > 0)
5397 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
5398 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5399 left + area_width - rest, top,
5400 rest, height, False);
5401 else
5402 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5403 left, top, rest, height, False);
5407 /* Move/size the scroll bar window. */
5408 if (mask)
5410 XWindowChanges wc;
5412 wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5413 wc.y = top;
5414 wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
5415 wc.height = height;
5416 XConfigureWindow (FRAME_X_DISPLAY (f), bar->x_window,
5417 mask, &wc);
5420 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5422 /* Remember new settings. */
5423 bar->left = sb_left;
5424 bar->top = top;
5425 bar->width = sb_width;
5426 bar->height = height;
5428 UNBLOCK_INPUT;
5431 #ifdef USE_TOOLKIT_SCROLL_BARS
5432 bar->fringe_extended_p = fringe_extended_p;
5434 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
5435 #else /* not USE_TOOLKIT_SCROLL_BARS */
5436 /* Set the scroll bar's current state, unless we're currently being
5437 dragged. */
5438 if (NILP (bar->dragging))
5440 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
5442 if (whole == 0)
5443 x_scroll_bar_set_handle (bar, 0, top_range, 0);
5444 else
5446 int start = ((double) position * top_range) / whole;
5447 int end = ((double) (position + portion) * top_range) / whole;
5448 x_scroll_bar_set_handle (bar, start, end, 0);
5451 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5453 XSETVECTOR (w->vertical_scroll_bar, bar);
5457 /* The following three hooks are used when we're doing a thorough
5458 redisplay of the frame. We don't explicitly know which scroll bars
5459 are going to be deleted, because keeping track of when windows go
5460 away is a real pain - "Can you say set-window-configuration, boys
5461 and girls?" Instead, we just assert at the beginning of redisplay
5462 that *all* scroll bars are to be removed, and then save a scroll bar
5463 from the fiery pit when we actually redisplay its window. */
5465 /* Arrange for all scroll bars on FRAME to be removed at the next call
5466 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5467 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5469 static void
5470 XTcondemn_scroll_bars (FRAME_PTR frame)
5472 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5473 while (! NILP (FRAME_SCROLL_BARS (frame)))
5475 Lisp_Object bar;
5476 bar = FRAME_SCROLL_BARS (frame);
5477 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
5478 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
5479 XSCROLL_BAR (bar)->prev = Qnil;
5480 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
5481 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
5482 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
5487 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5488 Note that WINDOW isn't necessarily condemned at all. */
5490 static void
5491 XTredeem_scroll_bar (struct window *window)
5493 struct scroll_bar *bar;
5494 struct frame *f;
5496 /* We can't redeem this window's scroll bar if it doesn't have one. */
5497 if (NILP (window->vertical_scroll_bar))
5498 abort ();
5500 bar = XSCROLL_BAR (window->vertical_scroll_bar);
5502 /* Unlink it from the condemned list. */
5503 f = XFRAME (WINDOW_FRAME (window));
5504 if (NILP (bar->prev))
5506 /* If the prev pointer is nil, it must be the first in one of
5507 the lists. */
5508 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
5509 /* It's not condemned. Everything's fine. */
5510 return;
5511 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
5512 window->vertical_scroll_bar))
5513 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
5514 else
5515 /* If its prev pointer is nil, it must be at the front of
5516 one or the other! */
5517 abort ();
5519 else
5520 XSCROLL_BAR (bar->prev)->next = bar->next;
5522 if (! NILP (bar->next))
5523 XSCROLL_BAR (bar->next)->prev = bar->prev;
5525 bar->next = FRAME_SCROLL_BARS (f);
5526 bar->prev = Qnil;
5527 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
5528 if (! NILP (bar->next))
5529 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
5532 /* Remove all scroll bars on FRAME that haven't been saved since the
5533 last call to `*condemn_scroll_bars_hook'. */
5535 static void
5536 XTjudge_scroll_bars (FRAME_PTR f)
5538 Lisp_Object bar, next;
5540 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
5542 /* Clear out the condemned list now so we won't try to process any
5543 more events on the hapless scroll bars. */
5544 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
5546 for (; ! NILP (bar); bar = next)
5548 struct scroll_bar *b = XSCROLL_BAR (bar);
5550 x_scroll_bar_remove (b);
5552 next = b->next;
5553 b->next = b->prev = Qnil;
5556 /* Now there should be no references to the condemned scroll bars,
5557 and they should get garbage-collected. */
5561 #ifndef USE_TOOLKIT_SCROLL_BARS
5562 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
5563 is a no-op when using toolkit scroll bars.
5565 This may be called from a signal handler, so we have to ignore GC
5566 mark bits. */
5568 static void
5569 x_scroll_bar_expose (struct scroll_bar *bar, XEvent *event)
5571 Window w = bar->x_window;
5572 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5573 GC gc = f->output_data.x->normal_gc;
5574 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5576 BLOCK_INPUT;
5578 x_scroll_bar_set_handle (bar, bar->start, bar->end, 1);
5580 /* Switch to scroll bar foreground color. */
5581 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
5582 XSetForeground (FRAME_X_DISPLAY (f), gc,
5583 f->output_data.x->scroll_bar_foreground_pixel);
5585 /* Draw a one-pixel border just inside the edges of the scroll bar. */
5586 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
5588 /* x, y, width, height */
5589 0, 0,
5590 bar->width - 1 - width_trim - width_trim,
5591 bar->height - 1);
5593 /* Restore the foreground color of the GC if we changed it above. */
5594 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
5595 XSetForeground (FRAME_X_DISPLAY (f), gc,
5596 FRAME_FOREGROUND_PIXEL (f));
5598 UNBLOCK_INPUT;
5601 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5603 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5604 is set to something other than NO_EVENT, it is enqueued.
5606 This may be called from a signal handler, so we have to ignore GC
5607 mark bits. */
5610 static void
5611 x_scroll_bar_handle_click (struct scroll_bar *bar, XEvent *event, struct input_event *emacs_event)
5613 if (! WINDOWP (bar->window))
5614 abort ();
5616 emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
5617 emacs_event->code = event->xbutton.button - Button1;
5618 emacs_event->modifiers
5619 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
5620 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
5621 event->xbutton.state)
5622 | (event->type == ButtonRelease
5623 ? up_modifier
5624 : down_modifier));
5625 emacs_event->frame_or_window = bar->window;
5626 emacs_event->arg = Qnil;
5627 emacs_event->timestamp = event->xbutton.time;
5629 int top_range
5630 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
5631 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
5633 if (y < 0) y = 0;
5634 if (y > top_range) y = top_range;
5636 if (y < bar->start)
5637 emacs_event->part = scroll_bar_above_handle;
5638 else if (y < bar->end + VERTICAL_SCROLL_BAR_MIN_HANDLE)
5639 emacs_event->part = scroll_bar_handle;
5640 else
5641 emacs_event->part = scroll_bar_below_handle;
5643 #ifndef USE_TOOLKIT_SCROLL_BARS
5644 /* If the user has released the handle, set it to its final position. */
5645 if (event->type == ButtonRelease
5646 && ! NILP (bar->dragging))
5648 int new_start = y - XINT (bar->dragging);
5649 int new_end = new_start + bar->end - bar->start;
5651 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
5652 bar->dragging = Qnil;
5654 #endif
5656 XSETINT (emacs_event->x, y);
5657 XSETINT (emacs_event->y, top_range);
5661 #ifndef USE_TOOLKIT_SCROLL_BARS
5663 /* Handle some mouse motion while someone is dragging the scroll bar.
5665 This may be called from a signal handler, so we have to ignore GC
5666 mark bits. */
5668 static void
5669 x_scroll_bar_note_movement (struct scroll_bar *bar, XEvent *event)
5671 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
5673 last_mouse_movement_time = event->xmotion.time;
5675 f->mouse_moved = 1;
5676 XSETVECTOR (last_mouse_scroll_bar, bar);
5678 /* If we're dragging the bar, display it. */
5679 if (! NILP (bar->dragging))
5681 /* Where should the handle be now? */
5682 int new_start = event->xmotion.y - XINT (bar->dragging);
5684 if (new_start != bar->start)
5686 int new_end = new_start + bar->end - bar->start;
5688 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
5693 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5695 /* Return information to the user about the current position of the mouse
5696 on the scroll bar. */
5698 static void
5699 x_scroll_bar_report_motion (FRAME_PTR *fp, Lisp_Object *bar_window,
5700 enum scroll_bar_part *part, Lisp_Object *x,
5701 Lisp_Object *y, Time *timestamp)
5703 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
5704 Window w = bar->x_window;
5705 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5706 int win_x, win_y;
5707 Window dummy_window;
5708 int dummy_coord;
5709 unsigned int dummy_mask;
5711 BLOCK_INPUT;
5713 /* Get the mouse's position relative to the scroll bar window, and
5714 report that. */
5715 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
5717 /* Root, child, root x and root y. */
5718 &dummy_window, &dummy_window,
5719 &dummy_coord, &dummy_coord,
5721 /* Position relative to scroll bar. */
5722 &win_x, &win_y,
5724 /* Mouse buttons and modifier keys. */
5725 &dummy_mask))
5727 else
5729 int top_range
5730 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
5732 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
5734 if (! NILP (bar->dragging))
5735 win_y -= XINT (bar->dragging);
5737 if (win_y < 0)
5738 win_y = 0;
5739 if (win_y > top_range)
5740 win_y = top_range;
5742 *fp = f;
5743 *bar_window = bar->window;
5745 if (! NILP (bar->dragging))
5746 *part = scroll_bar_handle;
5747 else if (win_y < bar->start)
5748 *part = scroll_bar_above_handle;
5749 else if (win_y < bar->end + VERTICAL_SCROLL_BAR_MIN_HANDLE)
5750 *part = scroll_bar_handle;
5751 else
5752 *part = scroll_bar_below_handle;
5754 XSETINT (*x, win_y);
5755 XSETINT (*y, top_range);
5757 f->mouse_moved = 0;
5758 last_mouse_scroll_bar = Qnil;
5761 *timestamp = last_mouse_movement_time;
5763 UNBLOCK_INPUT;
5767 /* The screen has been cleared so we may have changed foreground or
5768 background colors, and the scroll bars may need to be redrawn.
5769 Clear out the scroll bars, and ask for expose events, so we can
5770 redraw them. */
5772 static void
5773 x_scroll_bar_clear (FRAME_PTR f)
5775 #ifndef USE_TOOLKIT_SCROLL_BARS
5776 Lisp_Object bar;
5778 /* We can have scroll bars even if this is 0,
5779 if we just turned off scroll bar mode.
5780 But in that case we should not clear them. */
5781 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5782 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
5783 bar = XSCROLL_BAR (bar)->next)
5784 XClearArea (FRAME_X_DISPLAY (f),
5785 XSCROLL_BAR (bar)->x_window,
5786 0, 0, 0, 0, True);
5787 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5791 /* The main X event-reading loop - XTread_socket. */
5793 /* This holds the state XLookupString needs to implement dead keys
5794 and other tricks known as "compose processing". _X Window System_
5795 says that a portable program can't use this, but Stephen Gildea assures
5796 me that letting the compiler initialize it to zeros will work okay.
5798 This must be defined outside of XTread_socket, for the same reasons
5799 given for enter_timestamp, above. */
5801 static XComposeStatus compose_status;
5803 /* Record the last 100 characters stored
5804 to help debug the loss-of-chars-during-GC problem. */
5806 static int temp_index;
5807 static short temp_buffer[100];
5809 #define STORE_KEYSYM_FOR_DEBUG(keysym) \
5810 if (temp_index == sizeof temp_buffer / sizeof (short)) \
5811 temp_index = 0; \
5812 temp_buffer[temp_index++] = (keysym)
5814 /* Set this to nonzero to fake an "X I/O error"
5815 on a particular display. */
5817 static struct x_display_info *XTread_socket_fake_io_error;
5819 /* When we find no input here, we occasionally do a no-op command
5820 to verify that the X server is still running and we can still talk with it.
5821 We try all the open displays, one by one.
5822 This variable is used for cycling thru the displays. */
5824 static struct x_display_info *next_noop_dpyinfo;
5826 #if defined USE_X_TOOLKIT || defined USE_GTK
5827 #define SET_SAVED_BUTTON_EVENT \
5828 do \
5830 if (f->output_data.x->saved_menu_event == 0) \
5831 f->output_data.x->saved_menu_event \
5832 = (XEvent *) xmalloc (sizeof (XEvent)); \
5833 *f->output_data.x->saved_menu_event = event; \
5834 inev.ie.kind = MENU_BAR_ACTIVATE_EVENT; \
5835 XSETFRAME (inev.ie.frame_or_window, f); \
5837 while (0)
5838 #endif
5840 enum
5842 X_EVENT_NORMAL,
5843 X_EVENT_GOTO_OUT,
5844 X_EVENT_DROP
5847 /* Filter events for the current X input method.
5848 DPYINFO is the display this event is for.
5849 EVENT is the X event to filter.
5851 Returns non-zero if the event was filtered, caller shall not process
5852 this event further.
5853 Returns zero if event is wasn't filtered. */
5855 #ifdef HAVE_X_I18N
5856 static int
5857 x_filter_event (struct x_display_info *dpyinfo, XEvent *event)
5859 /* XFilterEvent returns non-zero if the input method has
5860 consumed the event. We pass the frame's X window to
5861 XFilterEvent because that's the one for which the IC
5862 was created. */
5864 struct frame *f1 = x_any_window_to_frame (dpyinfo,
5865 event->xclient.window);
5867 return XFilterEvent (event, f1 ? FRAME_X_WINDOW (f1) : None);
5869 #endif
5871 #ifdef USE_GTK
5872 static int current_count;
5873 static int current_finish;
5874 static struct input_event *current_hold_quit;
5876 /* This is the filter function invoked by the GTK event loop.
5877 It is invoked before the XEvent is translated to a GdkEvent,
5878 so we have a chance to act on the event before GTK. */
5879 static GdkFilterReturn
5880 event_handler_gdk (GdkXEvent *gxev, GdkEvent *ev, gpointer data)
5882 XEvent *xev = (XEvent *) gxev;
5884 BLOCK_INPUT;
5885 if (current_count >= 0)
5887 struct x_display_info *dpyinfo;
5889 dpyinfo = x_display_info_for_display (xev->xany.display);
5891 #ifdef HAVE_X_I18N
5892 /* Filter events for the current X input method.
5893 GTK calls XFilterEvent but not for key press and release,
5894 so we do it here. */
5895 if ((xev->type == KeyPress || xev->type == KeyRelease)
5896 && dpyinfo
5897 && x_filter_event (dpyinfo, xev))
5899 UNBLOCK_INPUT;
5900 return GDK_FILTER_REMOVE;
5902 #endif
5904 if (! dpyinfo)
5905 current_finish = X_EVENT_NORMAL;
5906 else
5907 current_count +=
5908 handle_one_xevent (dpyinfo, xev, &current_finish,
5909 current_hold_quit);
5911 else
5912 current_finish = x_dispatch_event (xev, xev->xany.display);
5914 UNBLOCK_INPUT;
5916 if (current_finish == X_EVENT_GOTO_OUT || current_finish == X_EVENT_DROP)
5917 return GDK_FILTER_REMOVE;
5919 return GDK_FILTER_CONTINUE;
5921 #endif /* USE_GTK */
5924 static void xembed_send_message (struct frame *f, Time,
5925 enum xembed_message,
5926 long detail, long data1, long data2);
5928 /* Handles the XEvent EVENT on display DPYINFO.
5930 *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
5931 *FINISH is zero if caller should continue reading events.
5932 *FINISH is X_EVENT_DROP if event should not be passed to the toolkit.
5934 We return the number of characters stored into the buffer. */
5936 static int
5937 handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
5938 int *finish, struct input_event *hold_quit)
5940 union {
5941 struct input_event ie;
5942 struct selection_input_event sie;
5943 } inev;
5944 int count = 0;
5945 int do_help = 0;
5946 ptrdiff_t nbytes = 0;
5947 struct frame *f = NULL;
5948 struct coding_system coding;
5949 XEvent event = *eventptr;
5950 Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
5951 USE_SAFE_ALLOCA;
5953 *finish = X_EVENT_NORMAL;
5955 EVENT_INIT (inev.ie);
5956 inev.ie.kind = NO_EVENT;
5957 inev.ie.arg = Qnil;
5959 if (pending_event_wait.eventtype == event.type)
5960 pending_event_wait.eventtype = 0; /* Indicates we got it. */
5962 switch (event.type)
5964 case ClientMessage:
5966 if (event.xclient.message_type
5967 == dpyinfo->Xatom_wm_protocols
5968 && event.xclient.format == 32)
5970 if (event.xclient.data.l[0]
5971 == dpyinfo->Xatom_wm_take_focus)
5973 /* Use x_any_window_to_frame because this
5974 could be the shell widget window
5975 if the frame has no title bar. */
5976 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
5977 #ifdef HAVE_X_I18N
5978 /* Not quite sure this is needed -pd */
5979 if (f && FRAME_XIC (f))
5980 XSetICFocus (FRAME_XIC (f));
5981 #endif
5982 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
5983 instructs the WM to set the input focus automatically for
5984 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
5985 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
5986 it has set the focus. So, XSetInputFocus below is not
5987 needed.
5989 The call to XSetInputFocus below has also caused trouble. In
5990 cases where the XSetInputFocus done by the WM and the one
5991 below are temporally close (on a fast machine), the call
5992 below can generate additional FocusIn events which confuse
5993 Emacs. */
5995 /* Since we set WM_TAKE_FOCUS, we must call
5996 XSetInputFocus explicitly. But not if f is null,
5997 since that might be an event for a deleted frame. */
5998 if (f)
6000 Display *d = event.xclient.display;
6001 /* Catch and ignore errors, in case window has been
6002 iconified by a window manager such as GWM. */
6003 x_catch_errors (d);
6004 XSetInputFocus (d, event.xclient.window,
6005 /* The ICCCM says this is
6006 the only valid choice. */
6007 RevertToParent,
6008 event.xclient.data.l[1]);
6009 /* This is needed to detect the error
6010 if there is an error. */
6011 XSync (d, False);
6012 x_uncatch_errors ();
6014 /* Not certain about handling scroll bars here */
6015 #endif /* 0 */
6016 goto done;
6019 if (event.xclient.data.l[0]
6020 == dpyinfo->Xatom_wm_save_yourself)
6022 /* Save state modify the WM_COMMAND property to
6023 something which can reinstate us. This notifies
6024 the session manager, who's looking for such a
6025 PropertyNotify. Can restart processing when
6026 a keyboard or mouse event arrives. */
6027 /* If we have a session manager, don't set this.
6028 KDE will then start two Emacsen, one for the
6029 session manager and one for this. */
6030 #ifdef HAVE_X_SM
6031 if (! x_session_have_connection ())
6032 #endif
6034 f = x_top_window_to_frame (dpyinfo,
6035 event.xclient.window);
6036 /* This is just so we only give real data once
6037 for a single Emacs process. */
6038 if (f == SELECTED_FRAME ())
6039 XSetCommand (FRAME_X_DISPLAY (f),
6040 event.xclient.window,
6041 initial_argv, initial_argc);
6042 else if (f)
6043 XSetCommand (FRAME_X_DISPLAY (f),
6044 event.xclient.window,
6045 0, 0);
6047 goto done;
6050 if (event.xclient.data.l[0]
6051 == dpyinfo->Xatom_wm_delete_window)
6053 f = x_any_window_to_frame (dpyinfo,
6054 event.xclient.window);
6055 if (!f)
6056 goto OTHER; /* May be a dialog that is to be removed */
6058 inev.ie.kind = DELETE_WINDOW_EVENT;
6059 XSETFRAME (inev.ie.frame_or_window, f);
6060 goto done;
6063 goto done;
6066 if (event.xclient.message_type
6067 == dpyinfo->Xatom_wm_configure_denied)
6069 goto done;
6072 if (event.xclient.message_type
6073 == dpyinfo->Xatom_wm_window_moved)
6075 int new_x, new_y;
6076 f = x_window_to_frame (dpyinfo, event.xclient.window);
6078 new_x = event.xclient.data.s[0];
6079 new_y = event.xclient.data.s[1];
6081 if (f)
6083 f->left_pos = new_x;
6084 f->top_pos = new_y;
6086 goto done;
6089 #ifdef HACK_EDITRES
6090 if (event.xclient.message_type
6091 == dpyinfo->Xatom_editres)
6093 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
6094 if (f)
6095 _XEditResCheckMessages (f->output_data.x->widget, NULL,
6096 &event, NULL);
6097 goto done;
6099 #endif /* HACK_EDITRES */
6101 if ((event.xclient.message_type
6102 == dpyinfo->Xatom_DONE)
6103 || (event.xclient.message_type
6104 == dpyinfo->Xatom_PAGE))
6106 /* Ghostview job completed. Kill it. We could
6107 reply with "Next" if we received "Page", but we
6108 currently never do because we are interested in
6109 images, only, which should have 1 page. */
6110 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
6111 f = x_window_to_frame (dpyinfo, event.xclient.window);
6112 if (!f)
6113 goto OTHER;
6114 x_kill_gs_process (pixmap, f);
6115 expose_frame (f, 0, 0, 0, 0);
6116 goto done;
6119 #ifdef USE_TOOLKIT_SCROLL_BARS
6120 /* Scroll bar callbacks send a ClientMessage from which
6121 we construct an input_event. */
6122 if (event.xclient.message_type
6123 == dpyinfo->Xatom_Scrollbar)
6125 x_scroll_bar_to_input_event (&event, &inev.ie);
6126 *finish = X_EVENT_GOTO_OUT;
6127 goto done;
6129 #endif /* USE_TOOLKIT_SCROLL_BARS */
6131 /* XEmbed messages from the embedder (if any). */
6132 if (event.xclient.message_type
6133 == dpyinfo->Xatom_XEMBED)
6135 enum xembed_message msg = event.xclient.data.l[1];
6136 if (msg == XEMBED_FOCUS_IN || msg == XEMBED_FOCUS_OUT)
6137 x_detect_focus_change (dpyinfo, &event, &inev.ie);
6139 *finish = X_EVENT_GOTO_OUT;
6140 goto done;
6143 xft_settings_event (dpyinfo, &event);
6145 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
6146 if (!f)
6147 goto OTHER;
6148 if (x_handle_dnd_message (f, &event.xclient, dpyinfo, &inev.ie))
6149 *finish = X_EVENT_DROP;
6151 break;
6153 case SelectionNotify:
6154 last_user_time = event.xselection.time;
6155 #ifdef USE_X_TOOLKIT
6156 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
6157 goto OTHER;
6158 #endif /* not USE_X_TOOLKIT */
6159 x_handle_selection_notify (&event.xselection);
6160 break;
6162 case SelectionClear: /* Someone has grabbed ownership. */
6163 last_user_time = event.xselectionclear.time;
6164 #ifdef USE_X_TOOLKIT
6165 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
6166 goto OTHER;
6167 #endif /* USE_X_TOOLKIT */
6169 XSelectionClearEvent *eventp = &(event.xselectionclear);
6171 inev.ie.kind = SELECTION_CLEAR_EVENT;
6172 SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display;
6173 SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
6174 SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
6175 inev.ie.frame_or_window = Qnil;
6177 break;
6179 case SelectionRequest: /* Someone wants our selection. */
6180 last_user_time = event.xselectionrequest.time;
6181 #ifdef USE_X_TOOLKIT
6182 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
6183 goto OTHER;
6184 #endif /* USE_X_TOOLKIT */
6186 XSelectionRequestEvent *eventp = &(event.xselectionrequest);
6188 inev.ie.kind = SELECTION_REQUEST_EVENT;
6189 SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display;
6190 SELECTION_EVENT_REQUESTOR (&inev.sie) = eventp->requestor;
6191 SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
6192 SELECTION_EVENT_TARGET (&inev.sie) = eventp->target;
6193 SELECTION_EVENT_PROPERTY (&inev.sie) = eventp->property;
6194 SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
6195 inev.ie.frame_or_window = Qnil;
6197 break;
6199 case PropertyNotify:
6200 last_user_time = event.xproperty.time;
6201 f = x_top_window_to_frame (dpyinfo, event.xproperty.window);
6202 if (f && event.xproperty.atom == dpyinfo->Xatom_net_wm_state)
6203 if (x_handle_net_wm_state (f, &event.xproperty) && f->iconified
6204 && f->output_data.x->net_wm_state_hidden_seen)
6206 /* Gnome shell does not iconify us when C-z is pressed. It hides
6207 the frame. So if our state says we aren't hidden anymore,
6208 treat it as deiconified. */
6209 if (! f->async_iconified)
6210 SET_FRAME_GARBAGED (f);
6211 f->async_visible = 1;
6212 f->async_iconified = 0;
6213 f->output_data.x->has_been_visible = 1;
6214 f->output_data.x->net_wm_state_hidden_seen = 0;
6215 inev.ie.kind = DEICONIFY_EVENT;
6216 XSETFRAME (inev.ie.frame_or_window, f);
6219 x_handle_property_notify (&event.xproperty);
6220 xft_settings_event (dpyinfo, &event);
6221 goto OTHER;
6223 case ReparentNotify:
6224 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
6225 if (f)
6227 int x, y;
6228 f->output_data.x->parent_desc = event.xreparent.parent;
6229 x_real_positions (f, &x, &y);
6230 f->left_pos = x;
6231 f->top_pos = y;
6233 /* Perhaps reparented due to a WM restart. Reset this. */
6234 FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN;
6235 FRAME_X_DISPLAY_INFO (f)->net_supported_window = 0;
6237 x_set_frame_alpha (f);
6239 goto OTHER;
6241 case Expose:
6242 f = x_window_to_frame (dpyinfo, event.xexpose.window);
6243 if (f)
6245 #ifdef USE_GTK
6246 /* This seems to be needed for GTK 2.6. */
6247 x_clear_area (event.xexpose.display,
6248 event.xexpose.window,
6249 event.xexpose.x, event.xexpose.y,
6250 event.xexpose.width, event.xexpose.height,
6251 FALSE);
6252 #endif
6253 if (f->async_visible == 0)
6255 f->async_visible = 1;
6256 f->async_iconified = 0;
6257 f->output_data.x->has_been_visible = 1;
6258 SET_FRAME_GARBAGED (f);
6260 else
6261 expose_frame (f,
6262 event.xexpose.x, event.xexpose.y,
6263 event.xexpose.width, event.xexpose.height);
6265 else
6267 #ifndef USE_TOOLKIT_SCROLL_BARS
6268 struct scroll_bar *bar;
6269 #endif
6270 #if defined USE_LUCID
6271 /* Submenus of the Lucid menu bar aren't widgets
6272 themselves, so there's no way to dispatch events
6273 to them. Recognize this case separately. */
6275 Widget widget
6276 = x_window_to_menu_bar (event.xexpose.window);
6277 if (widget)
6278 xlwmenu_redisplay (widget);
6280 #endif /* USE_LUCID */
6282 #ifdef USE_TOOLKIT_SCROLL_BARS
6283 /* Dispatch event to the widget. */
6284 goto OTHER;
6285 #else /* not USE_TOOLKIT_SCROLL_BARS */
6286 bar = x_window_to_scroll_bar (event.xexpose.display,
6287 event.xexpose.window);
6289 if (bar)
6290 x_scroll_bar_expose (bar, &event);
6291 #ifdef USE_X_TOOLKIT
6292 else
6293 goto OTHER;
6294 #endif /* USE_X_TOOLKIT */
6295 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6297 break;
6299 case GraphicsExpose: /* This occurs when an XCopyArea's
6300 source area was obscured or not
6301 available. */
6302 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
6303 if (f)
6305 expose_frame (f,
6306 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
6307 event.xgraphicsexpose.width,
6308 event.xgraphicsexpose.height);
6310 #ifdef USE_X_TOOLKIT
6311 else
6312 goto OTHER;
6313 #endif /* USE_X_TOOLKIT */
6314 break;
6316 case NoExpose: /* This occurs when an XCopyArea's
6317 source area was completely
6318 available. */
6319 break;
6321 case UnmapNotify:
6322 /* Redo the mouse-highlight after the tooltip has gone. */
6323 if (event.xmap.window == tip_window)
6325 tip_window = 0;
6326 redo_mouse_highlight ();
6329 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
6330 if (f) /* F may no longer exist if
6331 the frame was deleted. */
6333 /* While a frame is unmapped, display generation is
6334 disabled; you don't want to spend time updating a
6335 display that won't ever be seen. */
6336 f->async_visible = 0;
6337 /* We can't distinguish, from the event, whether the window
6338 has become iconified or invisible. So assume, if it
6339 was previously visible, than now it is iconified.
6340 But x_make_frame_invisible clears both
6341 the visible flag and the iconified flag;
6342 and that way, we know the window is not iconified now. */
6343 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
6345 f->async_iconified = 1;
6347 inev.ie.kind = ICONIFY_EVENT;
6348 XSETFRAME (inev.ie.frame_or_window, f);
6351 goto OTHER;
6353 case MapNotify:
6354 if (event.xmap.window == tip_window)
6355 /* The tooltip has been drawn already. Avoid
6356 the SET_FRAME_GARBAGED below. */
6357 goto OTHER;
6359 /* We use x_top_window_to_frame because map events can
6360 come for sub-windows and they don't mean that the
6361 frame is visible. */
6362 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
6363 if (f)
6365 /* wait_reading_process_output will notice this and update
6366 the frame's display structures.
6367 If we where iconified, we should not set garbaged,
6368 because that stops redrawing on Expose events. This looks
6369 bad if we are called from a recursive event loop
6370 (x_dispatch_event), for example when a dialog is up. */
6371 if (! f->async_iconified)
6372 SET_FRAME_GARBAGED (f);
6374 /* Check if fullscreen was specified before we where mapped the
6375 first time, i.e. from the command line. */
6376 if (!f->output_data.x->has_been_visible)
6377 x_check_fullscreen (f);
6379 f->async_visible = 1;
6380 f->async_iconified = 0;
6381 f->output_data.x->has_been_visible = 1;
6383 if (f->iconified)
6385 inev.ie.kind = DEICONIFY_EVENT;
6386 XSETFRAME (inev.ie.frame_or_window, f);
6388 else if (! NILP (Vframe_list)
6389 && ! NILP (XCDR (Vframe_list)))
6390 /* Force a redisplay sooner or later
6391 to update the frame titles
6392 in case this is the second frame. */
6393 record_asynch_buffer_change ();
6395 #ifdef USE_GTK
6396 xg_frame_resized (f, -1, -1);
6397 #endif
6399 goto OTHER;
6401 case KeyPress:
6403 last_user_time = event.xkey.time;
6404 ignore_next_mouse_click_timeout = 0;
6406 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6407 /* Dispatch KeyPress events when in menu. */
6408 if (popup_activated ())
6409 goto OTHER;
6410 #endif
6412 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
6414 /* If mouse-highlight is an integer, input clears out
6415 mouse highlighting. */
6416 if (!hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
6417 && (f == 0
6418 || !EQ (f->tool_bar_window, hlinfo->mouse_face_window)))
6420 clear_mouse_face (hlinfo);
6421 hlinfo->mouse_face_hidden = 1;
6424 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
6425 if (f == 0)
6427 /* Scroll bars consume key events, but we want
6428 the keys to go to the scroll bar's frame. */
6429 Widget widget = XtWindowToWidget (dpyinfo->display,
6430 event.xkey.window);
6431 if (widget && XmIsScrollBar (widget))
6433 widget = XtParent (widget);
6434 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
6437 #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
6439 if (f != 0)
6441 KeySym keysym, orig_keysym;
6442 /* al%imercury@uunet.uu.net says that making this 81
6443 instead of 80 fixed a bug whereby meta chars made
6444 his Emacs hang.
6446 It seems that some version of XmbLookupString has
6447 a bug of not returning XBufferOverflow in
6448 status_return even if the input is too long to
6449 fit in 81 bytes. So, we must prepare sufficient
6450 bytes for copy_buffer. 513 bytes (256 chars for
6451 two-byte character set) seems to be a fairly good
6452 approximation. -- 2000.8.10 handa@etl.go.jp */
6453 unsigned char copy_buffer[513];
6454 unsigned char *copy_bufptr = copy_buffer;
6455 int copy_bufsiz = sizeof (copy_buffer);
6456 int modifiers;
6457 Lisp_Object coding_system = Qlatin_1;
6458 Lisp_Object c;
6460 #ifdef USE_GTK
6461 /* Don't pass keys to GTK. A Tab will shift focus to the
6462 tool bar in GTK 2.4. Keys will still go to menus and
6463 dialogs because in that case popup_activated is TRUE
6464 (see above). */
6465 *finish = X_EVENT_DROP;
6466 #endif
6468 event.xkey.state
6469 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
6470 extra_keyboard_modifiers);
6471 modifiers = event.xkey.state;
6473 /* This will have to go some day... */
6475 /* make_lispy_event turns chars into control chars.
6476 Don't do it here because XLookupString is too eager. */
6477 event.xkey.state &= ~ControlMask;
6478 event.xkey.state &= ~(dpyinfo->meta_mod_mask
6479 | dpyinfo->super_mod_mask
6480 | dpyinfo->hyper_mod_mask
6481 | dpyinfo->alt_mod_mask);
6483 /* In case Meta is ComposeCharacter,
6484 clear its status. According to Markus Ehrnsperger
6485 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
6486 this enables ComposeCharacter to work whether or
6487 not it is combined with Meta. */
6488 if (modifiers & dpyinfo->meta_mod_mask)
6489 memset (&compose_status, 0, sizeof (compose_status));
6491 #ifdef HAVE_X_I18N
6492 if (FRAME_XIC (f))
6494 Status status_return;
6496 coding_system = Vlocale_coding_system;
6497 nbytes = XmbLookupString (FRAME_XIC (f),
6498 &event.xkey, (char *) copy_bufptr,
6499 copy_bufsiz, &keysym,
6500 &status_return);
6501 if (status_return == XBufferOverflow)
6503 copy_bufsiz = nbytes + 1;
6504 copy_bufptr = (unsigned char *) alloca (copy_bufsiz);
6505 nbytes = XmbLookupString (FRAME_XIC (f),
6506 &event.xkey, (char *) copy_bufptr,
6507 copy_bufsiz, &keysym,
6508 &status_return);
6510 /* Xutf8LookupString is a new but already deprecated interface. -stef */
6511 if (status_return == XLookupNone)
6512 break;
6513 else if (status_return == XLookupChars)
6515 keysym = NoSymbol;
6516 modifiers = 0;
6518 else if (status_return != XLookupKeySym
6519 && status_return != XLookupBoth)
6520 abort ();
6522 else
6523 nbytes = XLookupString (&event.xkey, (char *) copy_bufptr,
6524 copy_bufsiz, &keysym,
6525 &compose_status);
6526 #else
6527 nbytes = XLookupString (&event.xkey, (char *) copy_bufptr,
6528 copy_bufsiz, &keysym,
6529 &compose_status);
6530 #endif
6532 /* If not using XIM/XIC, and a compose sequence is in progress,
6533 we break here. Otherwise, chars_matched is always 0. */
6534 if (compose_status.chars_matched > 0 && nbytes == 0)
6535 break;
6537 memset (&compose_status, 0, sizeof (compose_status));
6538 orig_keysym = keysym;
6540 /* Common for all keysym input events. */
6541 XSETFRAME (inev.ie.frame_or_window, f);
6542 inev.ie.modifiers
6543 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), modifiers);
6544 inev.ie.timestamp = event.xkey.time;
6546 /* First deal with keysyms which have defined
6547 translations to characters. */
6548 if (keysym >= 32 && keysym < 128)
6549 /* Avoid explicitly decoding each ASCII character. */
6551 inev.ie.kind = ASCII_KEYSTROKE_EVENT;
6552 inev.ie.code = keysym;
6553 goto done_keysym;
6556 /* Keysyms directly mapped to Unicode characters. */
6557 if (keysym >= 0x01000000 && keysym <= 0x0110FFFF)
6559 if (keysym < 0x01000080)
6560 inev.ie.kind = ASCII_KEYSTROKE_EVENT;
6561 else
6562 inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
6563 inev.ie.code = keysym & 0xFFFFFF;
6564 goto done_keysym;
6567 /* Now non-ASCII. */
6568 if (HASH_TABLE_P (Vx_keysym_table)
6569 && (c = Fgethash (make_number (keysym),
6570 Vx_keysym_table,
6571 Qnil),
6572 NATNUMP (c)))
6574 inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
6575 ? ASCII_KEYSTROKE_EVENT
6576 : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
6577 inev.ie.code = XFASTINT (c);
6578 goto done_keysym;
6581 /* Random non-modifier sorts of keysyms. */
6582 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
6583 || keysym == XK_Delete
6584 #ifdef XK_ISO_Left_Tab
6585 || (keysym >= XK_ISO_Left_Tab
6586 && keysym <= XK_ISO_Enter)
6587 #endif
6588 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
6589 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
6590 #ifdef HPUX
6591 /* This recognizes the "extended function
6592 keys". It seems there's no cleaner way.
6593 Test IsModifierKey to avoid handling
6594 mode_switch incorrectly. */
6595 || (XK_Select <= keysym && keysym < XK_KP_Space)
6596 #endif
6597 #ifdef XK_dead_circumflex
6598 || orig_keysym == XK_dead_circumflex
6599 #endif
6600 #ifdef XK_dead_grave
6601 || orig_keysym == XK_dead_grave
6602 #endif
6603 #ifdef XK_dead_tilde
6604 || orig_keysym == XK_dead_tilde
6605 #endif
6606 #ifdef XK_dead_diaeresis
6607 || orig_keysym == XK_dead_diaeresis
6608 #endif
6609 #ifdef XK_dead_macron
6610 || orig_keysym == XK_dead_macron
6611 #endif
6612 #ifdef XK_dead_degree
6613 || orig_keysym == XK_dead_degree
6614 #endif
6615 #ifdef XK_dead_acute
6616 || orig_keysym == XK_dead_acute
6617 #endif
6618 #ifdef XK_dead_cedilla
6619 || orig_keysym == XK_dead_cedilla
6620 #endif
6621 #ifdef XK_dead_breve
6622 || orig_keysym == XK_dead_breve
6623 #endif
6624 #ifdef XK_dead_ogonek
6625 || orig_keysym == XK_dead_ogonek
6626 #endif
6627 #ifdef XK_dead_caron
6628 || orig_keysym == XK_dead_caron
6629 #endif
6630 #ifdef XK_dead_doubleacute
6631 || orig_keysym == XK_dead_doubleacute
6632 #endif
6633 #ifdef XK_dead_abovedot
6634 || orig_keysym == XK_dead_abovedot
6635 #endif
6636 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
6637 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
6638 /* Any "vendor-specific" key is ok. */
6639 || (orig_keysym & (1 << 28))
6640 || (keysym != NoSymbol && nbytes == 0))
6641 && ! (IsModifierKey (orig_keysym)
6642 /* The symbols from XK_ISO_Lock
6643 to XK_ISO_Last_Group_Lock
6644 don't have real modifiers but
6645 should be treated similarly to
6646 Mode_switch by Emacs. */
6647 #if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
6648 || (XK_ISO_Lock <= orig_keysym
6649 && orig_keysym <= XK_ISO_Last_Group_Lock)
6650 #endif
6653 STORE_KEYSYM_FOR_DEBUG (keysym);
6654 /* make_lispy_event will convert this to a symbolic
6655 key. */
6656 inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
6657 inev.ie.code = keysym;
6658 goto done_keysym;
6661 { /* Raw bytes, not keysym. */
6662 ptrdiff_t i;
6663 int nchars, len;
6665 for (i = 0, nchars = 0; i < nbytes; i++)
6667 if (ASCII_BYTE_P (copy_bufptr[i]))
6668 nchars++;
6669 STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]);
6672 if (nchars < nbytes)
6674 /* Decode the input data. */
6676 /* The input should be decoded with `coding_system'
6677 which depends on which X*LookupString function
6678 we used just above and the locale. */
6679 setup_coding_system (coding_system, &coding);
6680 coding.src_multibyte = 0;
6681 coding.dst_multibyte = 1;
6682 /* The input is converted to events, thus we can't
6683 handle composition. Anyway, there's no XIM that
6684 gives us composition information. */
6685 coding.common_flags &= ~CODING_ANNOTATION_MASK;
6687 SAFE_NALLOCA (coding.destination, MAX_MULTIBYTE_LENGTH,
6688 nbytes);
6689 coding.dst_bytes = MAX_MULTIBYTE_LENGTH * nbytes;
6690 coding.mode |= CODING_MODE_LAST_BLOCK;
6691 decode_coding_c_string (&coding, copy_bufptr, nbytes, Qnil);
6692 nbytes = coding.produced;
6693 nchars = coding.produced_char;
6694 copy_bufptr = coding.destination;
6697 /* Convert the input data to a sequence of
6698 character events. */
6699 for (i = 0; i < nbytes; i += len)
6701 int ch;
6702 if (nchars == nbytes)
6703 ch = copy_bufptr[i], len = 1;
6704 else
6705 ch = STRING_CHAR_AND_LENGTH (copy_bufptr + i, len);
6706 inev.ie.kind = (SINGLE_BYTE_CHAR_P (ch)
6707 ? ASCII_KEYSTROKE_EVENT
6708 : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
6709 inev.ie.code = ch;
6710 kbd_buffer_store_event_hold (&inev.ie, hold_quit);
6713 count += nchars;
6715 inev.ie.kind = NO_EVENT; /* Already stored above. */
6717 if (keysym == NoSymbol)
6718 break;
6721 done_keysym:
6722 #ifdef HAVE_X_I18N
6723 /* Don't dispatch this event since XtDispatchEvent calls
6724 XFilterEvent, and two calls in a row may freeze the
6725 client. */
6726 break;
6727 #else
6728 goto OTHER;
6729 #endif
6731 case KeyRelease:
6732 last_user_time = event.xkey.time;
6733 #ifdef HAVE_X_I18N
6734 /* Don't dispatch this event since XtDispatchEvent calls
6735 XFilterEvent, and two calls in a row may freeze the
6736 client. */
6737 break;
6738 #else
6739 goto OTHER;
6740 #endif
6742 case EnterNotify:
6743 last_user_time = event.xcrossing.time;
6744 x_detect_focus_change (dpyinfo, &event, &inev.ie);
6746 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
6748 if (f && x_mouse_click_focus_ignore_position)
6749 ignore_next_mouse_click_timeout = event.xmotion.time + 200;
6751 /* EnterNotify counts as mouse movement,
6752 so update things that depend on mouse position. */
6753 if (f && !f->output_data.x->hourglass_p)
6754 note_mouse_movement (f, &event.xmotion);
6755 #ifdef USE_GTK
6756 /* We may get an EnterNotify on the buttons in the toolbar. In that
6757 case we moved out of any highlighted area and need to note this. */
6758 if (!f && last_mouse_glyph_frame)
6759 note_mouse_movement (last_mouse_glyph_frame, &event.xmotion);
6760 #endif
6761 goto OTHER;
6763 case FocusIn:
6764 x_detect_focus_change (dpyinfo, &event, &inev.ie);
6765 goto OTHER;
6767 case LeaveNotify:
6768 last_user_time = event.xcrossing.time;
6769 x_detect_focus_change (dpyinfo, &event, &inev.ie);
6771 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
6772 if (f)
6774 if (f == hlinfo->mouse_face_mouse_frame)
6776 /* If we move outside the frame, then we're
6777 certainly no longer on any text in the frame. */
6778 clear_mouse_face (hlinfo);
6779 hlinfo->mouse_face_mouse_frame = 0;
6782 /* Generate a nil HELP_EVENT to cancel a help-echo.
6783 Do it only if there's something to cancel.
6784 Otherwise, the startup message is cleared when
6785 the mouse leaves the frame. */
6786 if (any_help_event_p)
6787 do_help = -1;
6789 #ifdef USE_GTK
6790 /* See comment in EnterNotify above */
6791 else if (last_mouse_glyph_frame)
6792 note_mouse_movement (last_mouse_glyph_frame, &event.xmotion);
6793 #endif
6794 goto OTHER;
6796 case FocusOut:
6797 x_detect_focus_change (dpyinfo, &event, &inev.ie);
6798 goto OTHER;
6800 case MotionNotify:
6802 last_user_time = event.xmotion.time;
6803 previous_help_echo_string = help_echo_string;
6804 help_echo_string = Qnil;
6806 if (dpyinfo->grabbed && last_mouse_frame
6807 && FRAME_LIVE_P (last_mouse_frame))
6808 f = last_mouse_frame;
6809 else
6810 f = x_window_to_frame (dpyinfo, event.xmotion.window);
6812 if (hlinfo->mouse_face_hidden)
6814 hlinfo->mouse_face_hidden = 0;
6815 clear_mouse_face (hlinfo);
6818 #ifdef USE_GTK
6819 if (f && xg_event_is_for_scrollbar (f, &event))
6820 f = 0;
6821 #endif
6822 if (f)
6825 /* Generate SELECT_WINDOW_EVENTs when needed.
6826 Don't let popup menus influence things (bug#1261). */
6827 if (!NILP (Vmouse_autoselect_window) && !popup_activated ())
6829 Lisp_Object window;
6831 window = window_from_coordinates (f,
6832 event.xmotion.x, event.xmotion.y,
6833 0, 0);
6835 /* Window will be selected only when it is not selected now and
6836 last mouse movement event was not in it. Minibuffer window
6837 will be selected only when it is active. */
6838 if (WINDOWP (window)
6839 && !EQ (window, last_window)
6840 && !EQ (window, selected_window)
6841 /* For click-to-focus window managers
6842 create event iff we don't leave the
6843 selected frame. */
6844 && (focus_follows_mouse
6845 || (EQ (XWINDOW (window)->frame,
6846 XWINDOW (selected_window)->frame))))
6848 inev.ie.kind = SELECT_WINDOW_EVENT;
6849 inev.ie.frame_or_window = window;
6852 last_window=window;
6854 if (!note_mouse_movement (f, &event.xmotion))
6855 help_echo_string = previous_help_echo_string;
6857 else
6859 #ifndef USE_TOOLKIT_SCROLL_BARS
6860 struct scroll_bar *bar
6861 = x_window_to_scroll_bar (event.xmotion.display,
6862 event.xmotion.window);
6864 if (bar)
6865 x_scroll_bar_note_movement (bar, &event);
6866 #endif /* USE_TOOLKIT_SCROLL_BARS */
6868 /* If we move outside the frame, then we're
6869 certainly no longer on any text in the frame. */
6870 clear_mouse_face (hlinfo);
6873 /* If the contents of the global variable help_echo_string
6874 has changed, generate a HELP_EVENT. */
6875 if (!NILP (help_echo_string)
6876 || !NILP (previous_help_echo_string))
6877 do_help = 1;
6878 goto OTHER;
6881 case ConfigureNotify:
6882 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
6883 #ifdef USE_GTK
6884 if (!f
6885 && (f = x_any_window_to_frame (dpyinfo, event.xconfigure.window))
6886 && event.xconfigure.window == FRAME_X_WINDOW (f))
6888 xg_frame_resized (f, event.xconfigure.width,
6889 event.xconfigure.height);
6890 f = 0;
6892 #endif
6893 if (f)
6895 #ifndef USE_X_TOOLKIT
6896 #ifndef USE_GTK
6897 int rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, event.xconfigure.height);
6898 int columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, event.xconfigure.width);
6900 /* In the toolkit version, change_frame_size
6901 is called by the code that handles resizing
6902 of the EmacsFrame widget. */
6904 /* Even if the number of character rows and columns has
6905 not changed, the font size may have changed, so we need
6906 to check the pixel dimensions as well. */
6907 if (columns != FRAME_COLS (f)
6908 || rows != FRAME_LINES (f)
6909 || event.xconfigure.width != FRAME_PIXEL_WIDTH (f)
6910 || event.xconfigure.height != FRAME_PIXEL_HEIGHT (f))
6912 change_frame_size (f, rows, columns, 0, 1, 0);
6913 SET_FRAME_GARBAGED (f);
6914 cancel_mouse_face (f);
6917 FRAME_PIXEL_WIDTH (f) = event.xconfigure.width;
6918 FRAME_PIXEL_HEIGHT (f) = event.xconfigure.height;
6919 #endif /* not USE_GTK */
6920 #endif
6922 #ifdef USE_GTK
6923 /* GTK creates windows but doesn't map them.
6924 Only get real positions when mapped. */
6925 if (FRAME_GTK_OUTER_WIDGET (f)
6926 && gtk_widget_get_mapped (FRAME_GTK_OUTER_WIDGET (f)))
6927 #endif
6929 x_real_positions (f, &f->left_pos, &f->top_pos);
6932 #ifdef HAVE_X_I18N
6933 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
6934 xic_set_statusarea (f);
6935 #endif
6938 goto OTHER;
6940 case ButtonRelease:
6941 case ButtonPress:
6943 /* If we decide we want to generate an event to be seen
6944 by the rest of Emacs, we put it here. */
6945 int tool_bar_p = 0;
6947 memset (&compose_status, 0, sizeof (compose_status));
6948 last_mouse_glyph_frame = 0;
6949 last_user_time = event.xbutton.time;
6951 if (dpyinfo->grabbed
6952 && last_mouse_frame
6953 && FRAME_LIVE_P (last_mouse_frame))
6954 f = last_mouse_frame;
6955 else
6956 f = x_window_to_frame (dpyinfo, event.xbutton.window);
6958 #ifdef USE_GTK
6959 if (f && xg_event_is_for_scrollbar (f, &event))
6960 f = 0;
6961 #endif
6962 if (f)
6964 /* Is this in the tool-bar? */
6965 if (WINDOWP (f->tool_bar_window)
6966 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
6968 Lisp_Object window;
6969 int x = event.xbutton.x;
6970 int y = event.xbutton.y;
6972 window = window_from_coordinates (f, x, y, 0, 1);
6973 tool_bar_p = EQ (window, f->tool_bar_window);
6975 if (tool_bar_p && event.xbutton.button < 4)
6977 handle_tool_bar_click (f, x, y,
6978 event.xbutton.type == ButtonPress,
6979 x_x_to_emacs_modifiers (dpyinfo,
6980 event.xbutton.state));
6984 if (!tool_bar_p)
6985 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6986 if (! popup_activated ())
6987 #endif
6989 if (ignore_next_mouse_click_timeout)
6991 if (event.type == ButtonPress
6992 && (int)(event.xbutton.time - ignore_next_mouse_click_timeout) > 0)
6994 ignore_next_mouse_click_timeout = 0;
6995 construct_mouse_click (&inev.ie, &event.xbutton, f);
6997 if (event.type == ButtonRelease)
6998 ignore_next_mouse_click_timeout = 0;
7000 else
7001 construct_mouse_click (&inev.ie, &event.xbutton, f);
7003 if (FRAME_X_EMBEDDED_P (f))
7004 xembed_send_message (f, event.xbutton.time,
7005 XEMBED_REQUEST_FOCUS, 0, 0, 0);
7007 else
7009 struct scroll_bar *bar
7010 = x_window_to_scroll_bar (event.xbutton.display,
7011 event.xbutton.window);
7013 #ifdef USE_TOOLKIT_SCROLL_BARS
7014 /* Make the "Ctrl-Mouse-2 splits window" work for toolkit
7015 scroll bars. */
7016 if (bar && event.xbutton.state & ControlMask)
7018 x_scroll_bar_handle_click (bar, &event, &inev.ie);
7019 *finish = X_EVENT_DROP;
7021 #else /* not USE_TOOLKIT_SCROLL_BARS */
7022 if (bar)
7023 x_scroll_bar_handle_click (bar, &event, &inev.ie);
7024 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7027 if (event.type == ButtonPress)
7029 dpyinfo->grabbed |= (1 << event.xbutton.button);
7030 last_mouse_frame = f;
7032 if (!tool_bar_p)
7033 last_tool_bar_item = -1;
7035 else
7036 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
7038 /* Ignore any mouse motion that happened before this event;
7039 any subsequent mouse-movement Emacs events should reflect
7040 only motion after the ButtonPress/Release. */
7041 if (f != 0)
7042 f->mouse_moved = 0;
7044 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
7045 f = x_menubar_window_to_frame (dpyinfo, &event);
7046 /* For a down-event in the menu bar,
7047 don't pass it to Xt right now.
7048 Instead, save it away
7049 and we will pass it to Xt from kbd_buffer_get_event.
7050 That way, we can run some Lisp code first. */
7051 if (! popup_activated ()
7052 #ifdef USE_GTK
7053 /* Gtk+ menus only react to the first three buttons. */
7054 && event.xbutton.button < 3
7055 #endif
7056 && f && event.type == ButtonPress
7057 /* Verify the event is really within the menu bar
7058 and not just sent to it due to grabbing. */
7059 && event.xbutton.x >= 0
7060 && event.xbutton.x < FRAME_PIXEL_WIDTH (f)
7061 && event.xbutton.y >= 0
7062 && event.xbutton.y < f->output_data.x->menubar_height
7063 && event.xbutton.same_screen)
7065 SET_SAVED_BUTTON_EVENT;
7066 XSETFRAME (last_mouse_press_frame, f);
7067 *finish = X_EVENT_DROP;
7069 else if (event.type == ButtonPress)
7071 last_mouse_press_frame = Qnil;
7072 goto OTHER;
7074 else
7075 goto OTHER;
7076 #endif /* USE_X_TOOLKIT || USE_GTK */
7078 break;
7080 case CirculateNotify:
7081 goto OTHER;
7083 case CirculateRequest:
7084 goto OTHER;
7086 case VisibilityNotify:
7087 goto OTHER;
7089 case MappingNotify:
7090 /* Someone has changed the keyboard mapping - update the
7091 local cache. */
7092 switch (event.xmapping.request)
7094 case MappingModifier:
7095 x_find_modifier_meanings (dpyinfo);
7096 /* This is meant to fall through. */
7097 case MappingKeyboard:
7098 XRefreshKeyboardMapping (&event.xmapping);
7100 goto OTHER;
7102 case DestroyNotify:
7103 xft_settings_event (dpyinfo, &event);
7104 break;
7106 default:
7107 OTHER:
7108 #ifdef USE_X_TOOLKIT
7109 BLOCK_INPUT;
7110 if (*finish != X_EVENT_DROP)
7111 XtDispatchEvent (&event);
7112 UNBLOCK_INPUT;
7113 #endif /* USE_X_TOOLKIT */
7114 break;
7117 done:
7118 if (inev.ie.kind != NO_EVENT)
7120 kbd_buffer_store_event_hold (&inev.ie, hold_quit);
7121 count++;
7124 if (do_help
7125 && !(hold_quit && hold_quit->kind != NO_EVENT))
7127 Lisp_Object frame;
7129 if (f)
7130 XSETFRAME (frame, f);
7131 else
7132 frame = Qnil;
7134 if (do_help > 0)
7136 any_help_event_p = 1;
7137 gen_help_event (help_echo_string, frame, help_echo_window,
7138 help_echo_object, help_echo_pos);
7140 else
7142 help_echo_string = Qnil;
7143 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
7145 count++;
7148 SAFE_FREE ();
7149 *eventptr = event;
7150 return count;
7153 #if defined USE_GTK || defined USE_X_TOOLKIT
7155 /* Handles the XEvent EVENT on display DISPLAY.
7156 This is used for event loops outside the normal event handling,
7157 i.e. looping while a popup menu or a dialog is posted.
7159 Returns the value handle_one_xevent sets in the finish argument. */
7161 x_dispatch_event (XEvent *event, Display *display)
7163 struct x_display_info *dpyinfo;
7164 int finish = X_EVENT_NORMAL;
7166 dpyinfo = x_display_info_for_display (display);
7168 if (dpyinfo)
7169 handle_one_xevent (dpyinfo, event, &finish, 0);
7171 return finish;
7173 #endif
7176 /* Read events coming from the X server.
7177 This routine is called by the SIGIO handler only if SYNC_INPUT is
7178 not defined.
7179 We return as soon as there are no more events to be read.
7181 We return the number of characters stored into the buffer,
7182 thus pretending to be `read' (except the characters we store
7183 in the keyboard buffer can be multibyte, so are not necessarily
7184 C chars).
7186 EXPECTED is nonzero if the caller knows input is available. */
7188 static int
7189 XTread_socket (struct terminal *terminal, int expected, struct input_event *hold_quit)
7191 int count = 0;
7192 int event_found = 0;
7194 if (interrupt_input_blocked)
7196 interrupt_input_pending = 1;
7197 #ifdef SYNC_INPUT
7198 pending_signals = 1;
7199 #endif
7200 return -1;
7203 interrupt_input_pending = 0;
7204 #ifdef SYNC_INPUT
7205 pending_signals = pending_atimers;
7206 #endif
7207 BLOCK_INPUT;
7209 /* So people can tell when we have read the available input. */
7210 input_signal_count++;
7212 #ifndef SYNC_INPUT
7213 ++handling_signal;
7214 #endif
7216 /* For debugging, this gives a way to fake an I/O error. */
7217 if (terminal->display_info.x == XTread_socket_fake_io_error)
7219 XTread_socket_fake_io_error = 0;
7220 x_io_error_quitter (terminal->display_info.x->display);
7223 #ifndef USE_GTK
7224 while (XPending (terminal->display_info.x->display))
7226 int finish;
7227 XEvent event;
7229 XNextEvent (terminal->display_info.x->display, &event);
7231 #ifdef HAVE_X_I18N
7232 /* Filter events for the current X input method. */
7233 if (x_filter_event (terminal->display_info.x, &event))
7234 continue;
7235 #endif
7236 event_found = 1;
7238 count += handle_one_xevent (terminal->display_info.x,
7239 &event, &finish, hold_quit);
7241 if (finish == X_EVENT_GOTO_OUT)
7242 goto out;
7245 out:;
7247 #else /* USE_GTK */
7249 /* For GTK we must use the GTK event loop. But XEvents gets passed
7250 to our filter function above, and then to the big event switch.
7251 We use a bunch of globals to communicate with our filter function,
7252 that is kind of ugly, but it works.
7254 There is no way to do one display at the time, GTK just does events
7255 from all displays. */
7257 while (gtk_events_pending ())
7259 current_count = count;
7260 current_hold_quit = hold_quit;
7262 gtk_main_iteration ();
7264 count = current_count;
7265 current_count = -1;
7266 current_hold_quit = 0;
7268 if (current_finish == X_EVENT_GOTO_OUT)
7269 break;
7271 #endif /* USE_GTK */
7273 /* On some systems, an X bug causes Emacs to get no more events
7274 when the window is destroyed. Detect that. (1994.) */
7275 if (! event_found)
7277 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
7278 One XNOOP in 100 loops will make Emacs terminate.
7279 B. Bretthauer, 1994 */
7280 x_noop_count++;
7281 if (x_noop_count >= 100)
7283 x_noop_count=0;
7285 if (next_noop_dpyinfo == 0)
7286 next_noop_dpyinfo = x_display_list;
7288 XNoOp (next_noop_dpyinfo->display);
7290 /* Each time we get here, cycle through the displays now open. */
7291 next_noop_dpyinfo = next_noop_dpyinfo->next;
7295 /* If the focus was just given to an auto-raising frame,
7296 raise it now. */
7297 /* ??? This ought to be able to handle more than one such frame. */
7298 if (pending_autoraise_frame)
7300 x_raise_frame (pending_autoraise_frame);
7301 pending_autoraise_frame = 0;
7304 #ifndef SYNC_INPUT
7305 --handling_signal;
7306 #endif
7307 UNBLOCK_INPUT;
7309 return count;
7315 /***********************************************************************
7316 Text Cursor
7317 ***********************************************************************/
7319 /* Set clipping for output in glyph row ROW. W is the window in which
7320 we operate. GC is the graphics context to set clipping in.
7322 ROW may be a text row or, e.g., a mode line. Text rows must be
7323 clipped to the interior of the window dedicated to text display,
7324 mode lines must be clipped to the whole window. */
7326 static void
7327 x_clip_to_row (struct window *w, struct glyph_row *row, int area, GC gc)
7329 struct frame *f = XFRAME (WINDOW_FRAME (w));
7330 XRectangle clip_rect;
7331 int window_x, window_y, window_width;
7333 window_box (w, area, &window_x, &window_y, &window_width, 0);
7335 clip_rect.x = window_x;
7336 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y));
7337 clip_rect.y = max (clip_rect.y, window_y);
7338 clip_rect.width = window_width;
7339 clip_rect.height = row->visible_height;
7341 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
7345 /* Draw a hollow box cursor on window W in glyph row ROW. */
7347 static void
7348 x_draw_hollow_cursor (struct window *w, struct glyph_row *row)
7350 struct frame *f = XFRAME (WINDOW_FRAME (w));
7351 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7352 Display *dpy = FRAME_X_DISPLAY (f);
7353 int x, y, wd, h;
7354 XGCValues xgcv;
7355 struct glyph *cursor_glyph;
7356 GC gc;
7358 /* Get the glyph the cursor is on. If we can't tell because
7359 the current matrix is invalid or such, give up. */
7360 cursor_glyph = get_phys_cursor_glyph (w);
7361 if (cursor_glyph == NULL)
7362 return;
7364 /* Compute frame-relative coordinates for phys cursor. */
7365 get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h);
7366 wd = w->phys_cursor_width;
7368 /* The foreground of cursor_gc is typically the same as the normal
7369 background color, which can cause the cursor box to be invisible. */
7370 xgcv.foreground = f->output_data.x->cursor_pixel;
7371 if (dpyinfo->scratch_cursor_gc)
7372 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
7373 else
7374 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
7375 GCForeground, &xgcv);
7376 gc = dpyinfo->scratch_cursor_gc;
7378 /* Set clipping, draw the rectangle, and reset clipping again. */
7379 x_clip_to_row (w, row, TEXT_AREA, gc);
7380 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h - 1);
7381 XSetClipMask (dpy, gc, None);
7385 /* Draw a bar cursor on window W in glyph row ROW.
7387 Implementation note: One would like to draw a bar cursor with an
7388 angle equal to the one given by the font property XA_ITALIC_ANGLE.
7389 Unfortunately, I didn't find a font yet that has this property set.
7390 --gerd. */
7392 static void
7393 x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text_cursor_kinds kind)
7395 struct frame *f = XFRAME (w->frame);
7396 struct glyph *cursor_glyph;
7398 /* If cursor is out of bounds, don't draw garbage. This can happen
7399 in mini-buffer windows when switching between echo area glyphs
7400 and mini-buffer. */
7401 cursor_glyph = get_phys_cursor_glyph (w);
7402 if (cursor_glyph == NULL)
7403 return;
7405 /* If on an image, draw like a normal cursor. That's usually better
7406 visible than drawing a bar, esp. if the image is large so that
7407 the bar might not be in the window. */
7408 if (cursor_glyph->type == IMAGE_GLYPH)
7410 struct glyph_row *r;
7411 r = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
7412 draw_phys_cursor_glyph (w, r, DRAW_CURSOR);
7414 else
7416 Display *dpy = FRAME_X_DISPLAY (f);
7417 Window window = FRAME_X_WINDOW (f);
7418 GC gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
7419 unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures;
7420 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
7421 XGCValues xgcv;
7423 /* If the glyph's background equals the color we normally draw
7424 the bars cursor in, the bar cursor in its normal color is
7425 invisible. Use the glyph's foreground color instead in this
7426 case, on the assumption that the glyph's colors are chosen so
7427 that the glyph is legible. */
7428 if (face->background == f->output_data.x->cursor_pixel)
7429 xgcv.background = xgcv.foreground = face->foreground;
7430 else
7431 xgcv.background = xgcv.foreground = f->output_data.x->cursor_pixel;
7432 xgcv.graphics_exposures = 0;
7434 if (gc)
7435 XChangeGC (dpy, gc, mask, &xgcv);
7436 else
7438 gc = XCreateGC (dpy, window, mask, &xgcv);
7439 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
7442 x_clip_to_row (w, row, TEXT_AREA, gc);
7444 if (kind == BAR_CURSOR)
7446 int x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
7448 if (width < 0)
7449 width = FRAME_CURSOR_WIDTH (f);
7450 width = min (cursor_glyph->pixel_width, width);
7452 w->phys_cursor_width = width;
7454 /* If the character under cursor is R2L, draw the bar cursor
7455 on the right of its glyph, rather than on the left. */
7456 if ((cursor_glyph->resolved_level & 1) != 0)
7457 x += cursor_glyph->pixel_width - width;
7459 XFillRectangle (dpy, window, gc, x,
7460 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
7461 width, row->height);
7463 else
7465 int dummy_x, dummy_y, dummy_h;
7467 if (width < 0)
7468 width = row->height;
7470 width = min (row->height, width);
7472 get_phys_cursor_geometry (w, row, cursor_glyph, &dummy_x,
7473 &dummy_y, &dummy_h);
7475 XFillRectangle (dpy, window, gc,
7476 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
7477 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
7478 row->height - width),
7479 w->phys_cursor_width, width);
7482 XSetClipMask (dpy, gc, None);
7487 /* RIF: Define cursor CURSOR on frame F. */
7489 static void
7490 x_define_frame_cursor (struct frame *f, Cursor cursor)
7492 if (!f->pointer_invisible
7493 && f->output_data.x->current_cursor != cursor)
7494 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
7495 f->output_data.x->current_cursor = cursor;
7499 /* RIF: Clear area on frame F. */
7501 static void
7502 x_clear_frame_area (struct frame *f, int x, int y, int width, int height)
7504 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7505 x, y, width, height, False);
7506 #ifdef USE_GTK
7507 /* Must queue a redraw, because scroll bars might have been cleared. */
7508 if (FRAME_GTK_WIDGET (f))
7509 gtk_widget_queue_draw (FRAME_GTK_WIDGET (f));
7510 #endif
7514 /* RIF: Draw cursor on window W. */
7516 static void
7517 x_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x, int y, int cursor_type, int cursor_width, int on_p, int active_p)
7519 struct frame *f = XFRAME (WINDOW_FRAME (w));
7521 if (on_p)
7523 w->phys_cursor_type = cursor_type;
7524 w->phys_cursor_on_p = 1;
7526 if (glyph_row->exact_window_width_line_p
7527 && (glyph_row->reversed_p
7528 ? (w->phys_cursor.hpos < 0)
7529 : (w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])))
7531 glyph_row->cursor_in_fringe_p = 1;
7532 draw_fringe_bitmap (w, glyph_row, glyph_row->reversed_p);
7534 else
7536 switch (cursor_type)
7538 case HOLLOW_BOX_CURSOR:
7539 x_draw_hollow_cursor (w, glyph_row);
7540 break;
7542 case FILLED_BOX_CURSOR:
7543 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
7544 break;
7546 case BAR_CURSOR:
7547 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
7548 break;
7550 case HBAR_CURSOR:
7551 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
7552 break;
7554 case NO_CURSOR:
7555 w->phys_cursor_width = 0;
7556 break;
7558 default:
7559 abort ();
7563 #ifdef HAVE_X_I18N
7564 if (w == XWINDOW (f->selected_window))
7565 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
7566 xic_set_preeditarea (w, x, y);
7567 #endif
7570 #ifndef XFlush
7571 XFlush (FRAME_X_DISPLAY (f));
7572 #endif
7576 /* Icons. */
7578 /* Make the x-window of frame F use the gnu icon bitmap. */
7581 x_bitmap_icon (struct frame *f, Lisp_Object file)
7583 ptrdiff_t bitmap_id;
7585 if (FRAME_X_WINDOW (f) == 0)
7586 return 1;
7588 /* Free up our existing icon bitmap and mask if any. */
7589 if (f->output_data.x->icon_bitmap > 0)
7590 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
7591 f->output_data.x->icon_bitmap = 0;
7593 if (STRINGP (file))
7595 #ifdef USE_GTK
7596 /* Use gtk_window_set_icon_from_file () if available,
7597 It's not restricted to bitmaps */
7598 if (xg_set_icon (f, file))
7599 return 0;
7600 #endif /* USE_GTK */
7601 bitmap_id = x_create_bitmap_from_file (f, file);
7602 x_create_bitmap_mask (f, bitmap_id);
7604 else
7606 /* Create the GNU bitmap and mask if necessary. */
7607 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
7609 ptrdiff_t rc = -1;
7611 #ifdef USE_GTK
7613 if (xg_set_icon (f, xg_default_icon_file)
7614 || xg_set_icon_from_xpm_data (f, gnu_xpm_bits))
7615 return 0;
7617 #elif defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
7619 rc = x_create_bitmap_from_xpm_data (f, gnu_xpm_bits);
7620 if (rc != -1)
7621 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id = rc;
7623 #endif
7625 /* If all else fails, use the (black and white) xbm image. */
7626 if (rc == -1)
7628 rc = x_create_bitmap_from_data (f, (char *) gnu_xbm_bits,
7629 gnu_xbm_width, gnu_xbm_height);
7630 if (rc == -1)
7631 return 1;
7633 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id = rc;
7634 x_create_bitmap_mask (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
7638 /* The first time we create the GNU bitmap and mask,
7639 this increments the ref-count one extra time.
7640 As a result, the GNU bitmap and mask are never freed.
7641 That way, we don't have to worry about allocating it again. */
7642 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
7644 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
7647 x_wm_set_icon_pixmap (f, bitmap_id);
7648 f->output_data.x->icon_bitmap = bitmap_id;
7650 return 0;
7654 /* Make the x-window of frame F use a rectangle with text.
7655 Use ICON_NAME as the text. */
7658 x_text_icon (struct frame *f, const char *icon_name)
7660 if (FRAME_X_WINDOW (f) == 0)
7661 return 1;
7664 XTextProperty text;
7665 text.value = (unsigned char *) icon_name;
7666 text.encoding = XA_STRING;
7667 text.format = 8;
7668 text.nitems = strlen (icon_name);
7669 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text);
7672 if (f->output_data.x->icon_bitmap > 0)
7673 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
7674 f->output_data.x->icon_bitmap = 0;
7675 x_wm_set_icon_pixmap (f, 0);
7677 return 0;
7680 #define X_ERROR_MESSAGE_SIZE 200
7682 /* If non-nil, this should be a string.
7683 It means catch X errors and store the error message in this string.
7685 The reason we use a stack is that x_catch_error/x_uncatch_error can
7686 be called from a signal handler.
7689 struct x_error_message_stack {
7690 char string[X_ERROR_MESSAGE_SIZE];
7691 Display *dpy;
7692 struct x_error_message_stack *prev;
7694 static struct x_error_message_stack *x_error_message;
7696 /* An X error handler which stores the error message in
7697 *x_error_message. This is called from x_error_handler if
7698 x_catch_errors is in effect. */
7700 static void
7701 x_error_catcher (Display *display, XErrorEvent *event)
7703 XGetErrorText (display, event->error_code,
7704 x_error_message->string,
7705 X_ERROR_MESSAGE_SIZE);
7708 /* Begin trapping X errors for display DPY. Actually we trap X errors
7709 for all displays, but DPY should be the display you are actually
7710 operating on.
7712 After calling this function, X protocol errors no longer cause
7713 Emacs to exit; instead, they are recorded in the string
7714 stored in *x_error_message.
7716 Calling x_check_errors signals an Emacs error if an X error has
7717 occurred since the last call to x_catch_errors or x_check_errors.
7719 Calling x_uncatch_errors resumes the normal error handling. */
7721 void
7722 x_catch_errors (Display *dpy)
7724 struct x_error_message_stack *data = xmalloc (sizeof (*data));
7726 /* Make sure any errors from previous requests have been dealt with. */
7727 XSync (dpy, False);
7729 data->dpy = dpy;
7730 data->string[0] = 0;
7731 data->prev = x_error_message;
7732 x_error_message = data;
7735 /* Undo the last x_catch_errors call.
7736 DPY should be the display that was passed to x_catch_errors. */
7738 void
7739 x_uncatch_errors (void)
7741 struct x_error_message_stack *tmp;
7743 BLOCK_INPUT;
7745 /* The display may have been closed before this function is called.
7746 Check if it is still open before calling XSync. */
7747 if (x_display_info_for_display (x_error_message->dpy) != 0)
7748 XSync (x_error_message->dpy, False);
7750 tmp = x_error_message;
7751 x_error_message = x_error_message->prev;
7752 xfree (tmp);
7753 UNBLOCK_INPUT;
7756 /* If any X protocol errors have arrived since the last call to
7757 x_catch_errors or x_check_errors, signal an Emacs error using
7758 sprintf (a buffer, FORMAT, the x error message text) as the text. */
7760 void
7761 x_check_errors (Display *dpy, const char *format)
7763 /* Make sure to catch any errors incurred so far. */
7764 XSync (dpy, False);
7766 if (x_error_message->string[0])
7768 char string[X_ERROR_MESSAGE_SIZE];
7769 memcpy (string, x_error_message->string, X_ERROR_MESSAGE_SIZE);
7770 x_uncatch_errors ();
7771 error (format, string);
7775 /* Nonzero if we had any X protocol errors
7776 since we did x_catch_errors on DPY. */
7779 x_had_errors_p (Display *dpy)
7781 /* Make sure to catch any errors incurred so far. */
7782 XSync (dpy, False);
7784 return x_error_message->string[0] != 0;
7787 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
7789 void
7790 x_clear_errors (Display *dpy)
7792 x_error_message->string[0] = 0;
7795 #if 0 /* See comment in unwind_to_catch why calling this is a bad
7796 * idea. --lorentey */
7797 /* Close off all unclosed x_catch_errors calls. */
7799 void
7800 x_fully_uncatch_errors (void)
7802 while (x_error_message)
7803 x_uncatch_errors ();
7805 #endif
7807 #if 0
7808 static unsigned int x_wire_count;
7809 x_trace_wire (void)
7811 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
7813 #endif /* ! 0 */
7816 /* Handle SIGPIPE, which can happen when the connection to a server
7817 simply goes away. SIGPIPE is handled by x_connection_signal.
7818 Don't need to do anything, because the write which caused the
7819 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
7820 which will do the appropriate cleanup for us. */
7822 static void
7823 x_connection_signal (int signalnum) /* If we don't have an argument, */
7824 /* some compilers complain in signal calls. */
7826 #ifdef USG
7827 /* USG systems forget handlers when they are used;
7828 must reestablish each time */
7829 signal (signalnum, x_connection_signal);
7830 #endif /* USG */
7834 /************************************************************************
7835 Handling X errors
7836 ************************************************************************/
7838 /* Error message passed to x_connection_closed. */
7840 static char *error_msg;
7842 /* Handle the loss of connection to display DPY. ERROR_MESSAGE is
7843 the text of an error message that lead to the connection loss. */
7845 static void
7846 x_connection_closed (Display *dpy, const char *error_message)
7848 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
7849 Lisp_Object frame, tail;
7850 ptrdiff_t idx = SPECPDL_INDEX ();
7852 error_msg = (char *) alloca (strlen (error_message) + 1);
7853 strcpy (error_msg, error_message);
7854 handling_signal = 0;
7856 /* Inhibit redisplay while frames are being deleted. */
7857 specbind (Qinhibit_redisplay, Qt);
7859 if (dpyinfo)
7861 /* Protect display from being closed when we delete the last
7862 frame on it. */
7863 dpyinfo->reference_count++;
7864 dpyinfo->terminal->reference_count++;
7867 /* First delete frames whose mini-buffers are on frames
7868 that are on the dead display. */
7869 FOR_EACH_FRAME (tail, frame)
7871 Lisp_Object minibuf_frame;
7872 minibuf_frame
7873 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
7874 if (FRAME_X_P (XFRAME (frame))
7875 && FRAME_X_P (XFRAME (minibuf_frame))
7876 && ! EQ (frame, minibuf_frame)
7877 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
7878 delete_frame (frame, Qnoelisp);
7881 /* Now delete all remaining frames on the dead display.
7882 We are now sure none of these is used as the mini-buffer
7883 for another frame that we need to delete. */
7884 FOR_EACH_FRAME (tail, frame)
7885 if (FRAME_X_P (XFRAME (frame))
7886 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
7888 /* Set this to t so that delete_frame won't get confused
7889 trying to find a replacement. */
7890 KVAR (FRAME_KBOARD (XFRAME (frame)), Vdefault_minibuffer_frame) = Qt;
7891 delete_frame (frame, Qnoelisp);
7894 /* If DPYINFO is null, this means we didn't open the display in the
7895 first place, so don't try to close it. */
7896 if (dpyinfo)
7898 /* We can not call XtCloseDisplay here because it calls XSync.
7899 XSync inside the error handler apparently hangs Emacs. On
7900 current Xt versions, this isn't needed either. */
7901 #ifdef USE_GTK
7902 /* A long-standing GTK bug prevents proper disconnect handling
7903 (https://bugzilla.gnome.org/show_bug.cgi?id=85715). Once,
7904 the resulting Glib error message loop filled a user's disk.
7905 To avoid this, kill Emacs unconditionally on disconnect. */
7906 shut_down_emacs (0, 0, Qnil);
7907 fprintf (stderr, "%s\n\
7908 When compiled with GTK, Emacs cannot recover from X disconnects.\n\
7909 This is a GTK bug: https://bugzilla.gnome.org/show_bug.cgi?id=85715\n\
7910 For details, see etc/PROBLEMS.\n",
7911 error_msg);
7912 abort ();
7913 #endif /* USE_GTK */
7915 /* Indicate that this display is dead. */
7916 dpyinfo->display = 0;
7918 dpyinfo->reference_count--;
7919 dpyinfo->terminal->reference_count--;
7920 if (dpyinfo->reference_count != 0)
7921 /* We have just closed all frames on this display. */
7922 abort ();
7925 Lisp_Object tmp;
7926 XSETTERMINAL (tmp, dpyinfo->terminal);
7927 Fdelete_terminal (tmp, Qnoelisp);
7931 if (terminal_list == 0)
7933 fprintf (stderr, "%s\n", error_msg);
7934 Fkill_emacs (make_number (70));
7935 /* NOTREACHED */
7938 /* Ordinary stack unwind doesn't deal with these. */
7939 #ifdef SIGIO
7940 sigunblock (sigmask (SIGIO));
7941 #endif
7942 sigunblock (sigmask (SIGALRM));
7943 TOTALLY_UNBLOCK_INPUT;
7945 unbind_to (idx, Qnil);
7946 clear_waiting_for_input ();
7948 /* Tell GCC not to suggest attribute 'noreturn' for this function. */
7949 IF_LINT (if (! terminal_list) return; )
7951 /* Here, we absolutely have to use a non-local exit (e.g. signal, throw,
7952 longjmp), because returning from this function would get us back into
7953 Xlib's code which will directly call `exit'. */
7954 error ("%s", error_msg);
7957 /* We specifically use it before defining it, so that gcc doesn't inline it,
7958 otherwise gdb doesn't know how to properly put a breakpoint on it. */
7959 static void x_error_quitter (Display *, XErrorEvent *);
7961 /* This is the first-level handler for X protocol errors.
7962 It calls x_error_quitter or x_error_catcher. */
7964 static int
7965 x_error_handler (Display *display, XErrorEvent *event)
7967 #ifdef HAVE_GTK3
7968 if (event->error_code == BadMatch
7969 && event->request_code == X_SetInputFocus
7970 && event->minor_code == 0)
7972 return 0;
7974 #endif
7976 if (x_error_message)
7977 x_error_catcher (display, event);
7978 else
7979 x_error_quitter (display, event);
7980 return 0;
7983 /* This is the usual handler for X protocol errors.
7984 It kills all frames on the display that we got the error for.
7985 If that was the only one, it prints an error message and kills Emacs. */
7987 /* .gdbinit puts a breakpoint here, so make sure it is not inlined. */
7989 /* On older GCC versions, just putting x_error_quitter
7990 after x_error_handler prevents inlining into the former. */
7992 static void NO_INLINE
7993 x_error_quitter (Display *display, XErrorEvent *event)
7995 char buf[256], buf1[356];
7997 /* Ignore BadName errors. They can happen because of fonts
7998 or colors that are not defined. */
8000 if (event->error_code == BadName)
8001 return;
8003 /* Note that there is no real way portable across R3/R4 to get the
8004 original error handler. */
8006 XGetErrorText (display, event->error_code, buf, sizeof (buf));
8007 sprintf (buf1, "X protocol error: %s on protocol request %d",
8008 buf, event->request_code);
8009 x_connection_closed (display, buf1);
8013 /* This is the handler for X IO errors, always.
8014 It kills all frames on the display that we lost touch with.
8015 If that was the only one, it prints an error message and kills Emacs. */
8017 static int
8018 x_io_error_quitter (Display *display)
8020 char buf[256];
8022 snprintf (buf, sizeof buf, "Connection lost to X server `%s'",
8023 DisplayString (display));
8024 x_connection_closed (display, buf);
8025 return 0;
8028 /* Changing the font of the frame. */
8030 /* Give frame F the font FONT-OBJECT as its default font. The return
8031 value is FONT-OBJECT. FONTSET is an ID of the fontset for the
8032 frame. If it is negative, generate a new fontset from
8033 FONT-OBJECT. */
8035 Lisp_Object
8036 x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
8038 struct font *font = XFONT_OBJECT (font_object);
8040 if (fontset < 0)
8041 fontset = fontset_from_font (font_object);
8042 FRAME_FONTSET (f) = fontset;
8043 if (FRAME_FONT (f) == font)
8044 /* This font is already set in frame F. There's nothing more to
8045 do. */
8046 return font_object;
8048 FRAME_FONT (f) = font;
8049 FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
8050 FRAME_COLUMN_WIDTH (f) = font->average_width;
8051 FRAME_SPACE_WIDTH (f) = font->space_width;
8052 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (font);
8054 compute_fringe_widths (f, 1);
8056 /* Compute the scroll bar width in character columns. */
8057 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
8059 int wid = FRAME_COLUMN_WIDTH (f);
8060 FRAME_CONFIG_SCROLL_BAR_COLS (f)
8061 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
8063 else
8065 int wid = FRAME_COLUMN_WIDTH (f);
8066 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
8069 if (FRAME_X_WINDOW (f) != 0)
8071 /* Don't change the size of a tip frame; there's no point in
8072 doing it because it's done in Fx_show_tip, and it leads to
8073 problems because the tip frame has no widget. */
8074 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
8075 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
8078 #ifdef HAVE_X_I18N
8079 if (FRAME_XIC (f)
8080 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
8082 BLOCK_INPUT;
8083 xic_set_xfontset (f, SSDATA (fontset_ascii (fontset)));
8084 UNBLOCK_INPUT;
8086 #endif
8088 return font_object;
8092 /***********************************************************************
8093 X Input Methods
8094 ***********************************************************************/
8096 #ifdef HAVE_X_I18N
8098 #ifdef HAVE_X11R6
8100 /* XIM destroy callback function, which is called whenever the
8101 connection to input method XIM dies. CLIENT_DATA contains a
8102 pointer to the x_display_info structure corresponding to XIM. */
8104 static void
8105 xim_destroy_callback (XIM xim, XPointer client_data, XPointer call_data)
8107 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
8108 Lisp_Object frame, tail;
8110 BLOCK_INPUT;
8112 /* No need to call XDestroyIC.. */
8113 FOR_EACH_FRAME (tail, frame)
8115 struct frame *f = XFRAME (frame);
8116 if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo)
8118 FRAME_XIC (f) = NULL;
8119 xic_free_xfontset (f);
8123 /* No need to call XCloseIM. */
8124 dpyinfo->xim = NULL;
8125 XFree (dpyinfo->xim_styles);
8126 UNBLOCK_INPUT;
8129 #endif /* HAVE_X11R6 */
8131 #ifdef HAVE_X11R6
8132 /* This isn't prototyped in OSF 5.0 or 5.1a. */
8133 extern char *XSetIMValues (XIM, ...);
8134 #endif
8136 /* Open the connection to the XIM server on display DPYINFO.
8137 RESOURCE_NAME is the resource name Emacs uses. */
8139 static void
8140 xim_open_dpy (struct x_display_info *dpyinfo, char *resource_name)
8142 XIM xim;
8144 #ifdef HAVE_XIM
8145 if (use_xim)
8147 if (dpyinfo->xim)
8148 XCloseIM (dpyinfo->xim);
8149 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name,
8150 emacs_class);
8151 dpyinfo->xim = xim;
8153 if (xim)
8155 #ifdef HAVE_X11R6
8156 XIMCallback destroy;
8157 #endif
8159 /* Get supported styles and XIM values. */
8160 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
8162 #ifdef HAVE_X11R6
8163 destroy.callback = xim_destroy_callback;
8164 destroy.client_data = (XPointer)dpyinfo;
8165 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
8166 #endif
8170 else
8171 #endif /* HAVE_XIM */
8172 dpyinfo->xim = NULL;
8176 #ifdef HAVE_X11R6_XIM
8178 /* XIM instantiate callback function, which is called whenever an XIM
8179 server is available. DISPLAY is the display of the XIM.
8180 CLIENT_DATA contains a pointer to an xim_inst_t structure created
8181 when the callback was registered. */
8183 static void
8184 xim_instantiate_callback (Display *display, XPointer client_data, XPointer call_data)
8186 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
8187 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
8189 /* We don't support multiple XIM connections. */
8190 if (dpyinfo->xim)
8191 return;
8193 xim_open_dpy (dpyinfo, xim_inst->resource_name);
8195 /* Create XIC for the existing frames on the same display, as long
8196 as they have no XIC. */
8197 if (dpyinfo->xim && dpyinfo->reference_count > 0)
8199 Lisp_Object tail, frame;
8201 BLOCK_INPUT;
8202 FOR_EACH_FRAME (tail, frame)
8204 struct frame *f = XFRAME (frame);
8206 if (FRAME_X_P (f)
8207 && FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
8208 if (FRAME_XIC (f) == NULL)
8210 create_frame_xic (f);
8211 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
8212 xic_set_statusarea (f);
8213 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
8215 struct window *w = XWINDOW (f->selected_window);
8216 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
8221 UNBLOCK_INPUT;
8225 #endif /* HAVE_X11R6_XIM */
8228 /* Open a connection to the XIM server on display DPYINFO.
8229 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
8230 connection only at the first time. On X11R6, open the connection
8231 in the XIM instantiate callback function. */
8233 static void
8234 xim_initialize (struct x_display_info *dpyinfo, char *resource_name)
8236 dpyinfo->xim = NULL;
8237 #ifdef HAVE_XIM
8238 if (use_xim)
8240 #ifdef HAVE_X11R6_XIM
8241 struct xim_inst_t *xim_inst;
8242 ptrdiff_t len;
8244 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
8245 dpyinfo->xim_callback_data = xim_inst;
8246 xim_inst->dpyinfo = dpyinfo;
8247 len = strlen (resource_name);
8248 xim_inst->resource_name = (char *) xmalloc (len + 1);
8249 memcpy (xim_inst->resource_name, resource_name, len + 1);
8250 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
8251 resource_name, emacs_class,
8252 xim_instantiate_callback,
8253 /* This is XPointer in XFree86
8254 but (XPointer *) on Tru64, at
8255 least, hence the configure test. */
8256 (XRegisterIMInstantiateCallback_arg6) xim_inst);
8257 #else /* not HAVE_X11R6_XIM */
8258 xim_open_dpy (dpyinfo, resource_name);
8259 #endif /* not HAVE_X11R6_XIM */
8261 #endif /* HAVE_XIM */
8265 /* Close the connection to the XIM server on display DPYINFO. */
8267 static void
8268 xim_close_dpy (struct x_display_info *dpyinfo)
8270 #ifdef HAVE_XIM
8271 if (use_xim)
8273 #ifdef HAVE_X11R6_XIM
8274 if (dpyinfo->display)
8275 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
8276 NULL, emacs_class,
8277 xim_instantiate_callback, NULL);
8278 xfree (dpyinfo->xim_callback_data->resource_name);
8279 xfree (dpyinfo->xim_callback_data);
8280 #endif /* HAVE_X11R6_XIM */
8281 if (dpyinfo->display)
8282 XCloseIM (dpyinfo->xim);
8283 dpyinfo->xim = NULL;
8284 XFree (dpyinfo->xim_styles);
8286 #endif /* HAVE_XIM */
8289 #endif /* not HAVE_X11R6_XIM */
8293 /* Calculate the absolute position in frame F
8294 from its current recorded position values and gravity. */
8296 static void
8297 x_calc_absolute_position (struct frame *f)
8299 int flags = f->size_hint_flags;
8301 /* We have nothing to do if the current position
8302 is already for the top-left corner. */
8303 if (! ((flags & XNegative) || (flags & YNegative)))
8304 return;
8306 /* Treat negative positions as relative to the leftmost bottommost
8307 position that fits on the screen. */
8308 if (flags & XNegative)
8309 f->left_pos = x_display_pixel_width (FRAME_X_DISPLAY_INFO (f))
8310 - FRAME_PIXEL_WIDTH (f) + f->left_pos;
8313 int height = FRAME_PIXEL_HEIGHT (f);
8315 #if defined USE_X_TOOLKIT && defined USE_MOTIF
8316 /* Something is fishy here. When using Motif, starting Emacs with
8317 `-g -0-0', the frame appears too low by a few pixels.
8319 This seems to be so because initially, while Emacs is starting,
8320 the column widget's height and the frame's pixel height are
8321 different. The column widget's height is the right one. In
8322 later invocations, when Emacs is up, the frame's pixel height
8323 is right, though.
8325 It's not obvious where the initial small difference comes from.
8326 2000-12-01, gerd. */
8328 XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
8329 #endif
8331 if (flags & YNegative)
8332 f->top_pos = x_display_pixel_height (FRAME_X_DISPLAY_INFO (f))
8333 - height + f->top_pos;
8336 /* The left_pos and top_pos
8337 are now relative to the top and left screen edges,
8338 so the flags should correspond. */
8339 f->size_hint_flags &= ~ (XNegative | YNegative);
8342 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
8343 to really change the position, and 0 when calling from
8344 x_make_frame_visible (in that case, XOFF and YOFF are the current
8345 position values). It is -1 when calling from x_set_frame_parameters,
8346 which means, do adjust for borders but don't change the gravity. */
8348 void
8349 x_set_offset (struct frame *f, register int xoff, register int yoff, int change_gravity)
8351 int modified_top, modified_left;
8353 if (change_gravity > 0)
8355 FRAME_X_OUTPUT (f)->left_before_move = f->left_pos;
8356 FRAME_X_OUTPUT (f)->top_before_move = f->top_pos;
8358 f->top_pos = yoff;
8359 f->left_pos = xoff;
8360 f->size_hint_flags &= ~ (XNegative | YNegative);
8361 if (xoff < 0)
8362 f->size_hint_flags |= XNegative;
8363 if (yoff < 0)
8364 f->size_hint_flags |= YNegative;
8365 f->win_gravity = NorthWestGravity;
8367 x_calc_absolute_position (f);
8369 BLOCK_INPUT;
8370 x_wm_set_size_hint (f, (long) 0, 0);
8372 modified_left = f->left_pos;
8373 modified_top = f->top_pos;
8375 if (change_gravity != 0 && FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A)
8377 /* Some WMs (twm, wmaker at least) has an offset that is smaller
8378 than the WM decorations. So we use the calculated offset instead
8379 of the WM decoration sizes here (x/y_pixels_outer_diff). */
8380 modified_left += FRAME_X_OUTPUT (f)->move_offset_left;
8381 modified_top += FRAME_X_OUTPUT (f)->move_offset_top;
8384 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
8385 modified_left, modified_top);
8387 x_sync_with_move (f, f->left_pos, f->top_pos,
8388 FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
8389 ? 1 : 0);
8391 /* change_gravity is non-zero when this function is called from Lisp to
8392 programmatically move a frame. In that case, we call
8393 x_check_expected_move to discover if we have a "Type A" or "Type B"
8394 window manager, and, for a "Type A" window manager, adjust the position
8395 of the frame.
8397 We call x_check_expected_move if a programmatic move occurred, and
8398 either the window manager type (A/B) is unknown or it is Type A but we
8399 need to compute the top/left offset adjustment for this frame. */
8401 if (change_gravity != 0 &&
8402 (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
8403 || (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A
8404 && (FRAME_X_OUTPUT (f)->move_offset_left == 0
8405 && FRAME_X_OUTPUT (f)->move_offset_top == 0))))
8406 x_check_expected_move (f, modified_left, modified_top);
8408 UNBLOCK_INPUT;
8411 /* Return non-zero if _NET_SUPPORTING_WM_CHECK window exists and _NET_SUPPORTED
8412 on the root window for frame F contains ATOMNAME.
8413 This is how a WM check shall be done according to the Window Manager
8414 Specification/Extended Window Manager Hints at
8415 http://freedesktop.org/wiki/Specifications/wm-spec. */
8417 static int
8418 wm_supports (struct frame *f, Atom want_atom)
8420 Atom actual_type;
8421 unsigned long actual_size, bytes_remaining;
8422 int i, rc, actual_format;
8423 Window wmcheck_window;
8424 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8425 Window target_window = dpyinfo->root_window;
8426 long max_len = 65536;
8427 Display *dpy = FRAME_X_DISPLAY (f);
8428 unsigned char *tmp_data = NULL;
8429 Atom target_type = XA_WINDOW;
8431 BLOCK_INPUT;
8433 x_catch_errors (dpy);
8434 rc = XGetWindowProperty (dpy, target_window,
8435 dpyinfo->Xatom_net_supporting_wm_check,
8436 0, max_len, False, target_type,
8437 &actual_type, &actual_format, &actual_size,
8438 &bytes_remaining, &tmp_data);
8440 if (rc != Success || actual_type != XA_WINDOW || x_had_errors_p (dpy))
8442 if (tmp_data) XFree (tmp_data);
8443 x_uncatch_errors ();
8444 UNBLOCK_INPUT;
8445 return 0;
8448 wmcheck_window = *(Window *) tmp_data;
8449 XFree (tmp_data);
8451 /* Check if window exists. */
8452 XSelectInput (dpy, wmcheck_window, StructureNotifyMask);
8453 x_sync (f);
8454 if (x_had_errors_p (dpy))
8456 x_uncatch_errors ();
8457 UNBLOCK_INPUT;
8458 return 0;
8461 if (dpyinfo->net_supported_window != wmcheck_window)
8463 /* Window changed, reload atoms */
8464 if (dpyinfo->net_supported_atoms != NULL)
8465 XFree (dpyinfo->net_supported_atoms);
8466 dpyinfo->net_supported_atoms = NULL;
8467 dpyinfo->nr_net_supported_atoms = 0;
8468 dpyinfo->net_supported_window = 0;
8470 target_type = XA_ATOM;
8471 tmp_data = NULL;
8472 rc = XGetWindowProperty (dpy, target_window,
8473 dpyinfo->Xatom_net_supported,
8474 0, max_len, False, target_type,
8475 &actual_type, &actual_format, &actual_size,
8476 &bytes_remaining, &tmp_data);
8478 if (rc != Success || actual_type != XA_ATOM || x_had_errors_p (dpy))
8480 if (tmp_data) XFree (tmp_data);
8481 x_uncatch_errors ();
8482 UNBLOCK_INPUT;
8483 return 0;
8486 dpyinfo->net_supported_atoms = (Atom *)tmp_data;
8487 dpyinfo->nr_net_supported_atoms = actual_size;
8488 dpyinfo->net_supported_window = wmcheck_window;
8491 rc = 0;
8493 for (i = 0; rc == 0 && i < dpyinfo->nr_net_supported_atoms; ++i)
8494 rc = dpyinfo->net_supported_atoms[i] == want_atom;
8496 x_uncatch_errors ();
8497 UNBLOCK_INPUT;
8499 return rc;
8502 static void
8503 set_wm_state (Lisp_Object frame, int add, Atom atom, Atom value)
8505 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (frame));
8507 x_send_client_event (frame, make_number (0), frame,
8508 dpyinfo->Xatom_net_wm_state,
8509 make_number (32),
8510 /* 1 = add, 0 = remove */
8511 Fcons
8512 (make_number (add ? 1 : 0),
8513 Fcons
8514 (make_fixnum_or_float (atom),
8515 value != 0
8516 ? Fcons (make_fixnum_or_float (value), Qnil)
8517 : Qnil)));
8520 void
8521 x_set_sticky (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
8523 Lisp_Object frame;
8524 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8526 XSETFRAME (frame, f);
8528 set_wm_state (frame, NILP (new_value) ? 0 : 1,
8529 dpyinfo->Xatom_net_wm_state_sticky, None);
8532 /* Return the current _NET_WM_STATE.
8533 SIZE_STATE is set to one of the FULLSCREEN_* values.
8534 STICKY is set to 1 if the sticky state is set, 0 if not.
8536 Return non-zero if we are not hidden, zero if we are. */
8538 static int
8539 get_current_wm_state (struct frame *f,
8540 Window window,
8541 int *size_state,
8542 int *sticky)
8544 Atom actual_type;
8545 unsigned long actual_size, bytes_remaining;
8546 int i, rc, actual_format, is_hidden = 0;
8547 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8548 long max_len = 65536;
8549 Display *dpy = FRAME_X_DISPLAY (f);
8550 unsigned char *tmp_data = NULL;
8551 Atom target_type = XA_ATOM;
8553 *sticky = 0;
8554 *size_state = FULLSCREEN_NONE;
8556 BLOCK_INPUT;
8557 x_catch_errors (dpy);
8558 rc = XGetWindowProperty (dpy, window, dpyinfo->Xatom_net_wm_state,
8559 0, max_len, False, target_type,
8560 &actual_type, &actual_format, &actual_size,
8561 &bytes_remaining, &tmp_data);
8563 if (rc != Success || actual_type != target_type || x_had_errors_p (dpy))
8565 if (tmp_data) XFree (tmp_data);
8566 x_uncatch_errors ();
8567 UNBLOCK_INPUT;
8568 return ! f->iconified;
8571 x_uncatch_errors ();
8573 for (i = 0; i < actual_size; ++i)
8575 Atom a = ((Atom*)tmp_data)[i];
8576 if (a == dpyinfo->Xatom_net_wm_state_hidden)
8578 is_hidden = 1;
8579 f->output_data.x->net_wm_state_hidden_seen = 1;
8581 else if (a == dpyinfo->Xatom_net_wm_state_maximized_horz)
8583 if (*size_state == FULLSCREEN_HEIGHT)
8584 *size_state = FULLSCREEN_MAXIMIZED;
8585 else
8586 *size_state = FULLSCREEN_WIDTH;
8588 else if (a == dpyinfo->Xatom_net_wm_state_maximized_vert)
8590 if (*size_state == FULLSCREEN_WIDTH)
8591 *size_state = FULLSCREEN_MAXIMIZED;
8592 else
8593 *size_state = FULLSCREEN_HEIGHT;
8595 else if (a == dpyinfo->Xatom_net_wm_state_fullscreen)
8596 *size_state = FULLSCREEN_BOTH;
8597 else if (a == dpyinfo->Xatom_net_wm_state_sticky)
8598 *sticky = 1;
8601 if (tmp_data) XFree (tmp_data);
8602 UNBLOCK_INPUT;
8603 return ! is_hidden;
8606 /* Do fullscreen as specified in extended window manager hints */
8608 static int
8609 do_ewmh_fullscreen (struct frame *f)
8611 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8612 int have_net_atom = wm_supports (f, dpyinfo->Xatom_net_wm_state);
8613 int cur, dummy;
8615 (void)get_current_wm_state (f, FRAME_OUTER_WINDOW (f), &cur, &dummy);
8617 /* Some window managers don't say they support _NET_WM_STATE, but they do say
8618 they support _NET_WM_STATE_FULLSCREEN. Try that also. */
8619 if (!have_net_atom)
8620 have_net_atom = wm_supports (f, dpyinfo->Xatom_net_wm_state_fullscreen);
8622 if (have_net_atom && cur != f->want_fullscreen)
8624 Lisp_Object frame;
8626 XSETFRAME (frame, f);
8628 /* Keep number of calls to set_wm_state as low as possible.
8629 Some window managers, or possible Gtk+, hangs when too many
8630 are sent at once. */
8631 switch (f->want_fullscreen)
8633 case FULLSCREEN_BOTH:
8634 if (cur == FULLSCREEN_WIDTH || cur == FULLSCREEN_MAXIMIZED
8635 || cur == FULLSCREEN_HEIGHT)
8636 set_wm_state (frame, 0, dpyinfo->Xatom_net_wm_state_maximized_horz,
8637 dpyinfo->Xatom_net_wm_state_maximized_vert);
8638 set_wm_state (frame, 1, dpyinfo->Xatom_net_wm_state_fullscreen, None);
8639 break;
8640 case FULLSCREEN_WIDTH:
8641 if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_HEIGHT
8642 || cur == FULLSCREEN_MAXIMIZED)
8643 set_wm_state (frame, 0, dpyinfo->Xatom_net_wm_state_fullscreen,
8644 dpyinfo->Xatom_net_wm_state_maximized_vert);
8645 if (cur != FULLSCREEN_MAXIMIZED)
8646 set_wm_state (frame, 1, dpyinfo->Xatom_net_wm_state_maximized_horz, None);
8647 break;
8648 case FULLSCREEN_HEIGHT:
8649 if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_WIDTH
8650 || cur == FULLSCREEN_MAXIMIZED)
8651 set_wm_state (frame, 0, dpyinfo->Xatom_net_wm_state_fullscreen,
8652 dpyinfo->Xatom_net_wm_state_maximized_horz);
8653 if (cur != FULLSCREEN_MAXIMIZED)
8654 set_wm_state (frame, 1, dpyinfo->Xatom_net_wm_state_maximized_vert, None);
8655 break;
8656 case FULLSCREEN_MAXIMIZED:
8657 if (cur == FULLSCREEN_BOTH)
8658 set_wm_state (frame, 0, dpyinfo->Xatom_net_wm_state_fullscreen, None);
8659 set_wm_state (frame, 1, dpyinfo->Xatom_net_wm_state_maximized_horz,
8660 dpyinfo->Xatom_net_wm_state_maximized_vert);
8661 break;
8662 case FULLSCREEN_NONE:
8663 if (cur == FULLSCREEN_BOTH)
8664 set_wm_state (frame, 0, dpyinfo->Xatom_net_wm_state_fullscreen, None);
8665 else
8666 set_wm_state (frame, 0, dpyinfo->Xatom_net_wm_state_maximized_horz,
8667 dpyinfo->Xatom_net_wm_state_maximized_vert);
8670 f->want_fullscreen = FULLSCREEN_NONE;
8674 return have_net_atom;
8677 static void
8678 XTfullscreen_hook (FRAME_PTR f)
8680 if (f->async_visible)
8682 BLOCK_INPUT;
8683 x_check_fullscreen (f);
8684 x_sync (f);
8685 UNBLOCK_INPUT;
8690 static int
8691 x_handle_net_wm_state (struct frame *f, XPropertyEvent *event)
8693 int value = FULLSCREEN_NONE;
8694 Lisp_Object lval;
8695 int sticky = 0;
8696 int not_hidden = get_current_wm_state (f, event->window, &value, &sticky);
8698 lval = Qnil;
8699 switch (value)
8701 case FULLSCREEN_WIDTH:
8702 lval = Qfullwidth;
8703 break;
8704 case FULLSCREEN_HEIGHT:
8705 lval = Qfullheight;
8706 break;
8707 case FULLSCREEN_BOTH:
8708 lval = Qfullboth;
8709 break;
8710 case FULLSCREEN_MAXIMIZED:
8711 lval = Qmaximized;
8712 break;
8715 store_frame_param (f, Qfullscreen, lval);
8716 store_frame_param (f, Qsticky, sticky ? Qt : Qnil);
8718 return not_hidden;
8721 /* Check if we need to resize the frame due to a fullscreen request.
8722 If so needed, resize the frame. */
8723 static void
8724 x_check_fullscreen (struct frame *f)
8726 if (do_ewmh_fullscreen (f))
8727 return;
8729 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
8730 return; /* Only fullscreen without WM or with EWM hints (above). */
8732 /* Setting fullscreen to nil doesn't do anything. We could save the
8733 last non-fullscreen size and restore it, but it seems like a
8734 lot of work for this unusual case (no window manager running). */
8736 if (f->want_fullscreen != FULLSCREEN_NONE)
8738 int width = FRAME_PIXEL_WIDTH (f), height = FRAME_PIXEL_HEIGHT (f);
8739 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8741 switch (f->want_fullscreen)
8743 /* No difference between these two when there is no WM */
8744 case FULLSCREEN_BOTH:
8745 case FULLSCREEN_MAXIMIZED:
8746 width = x_display_pixel_width (dpyinfo);
8747 height = x_display_pixel_height (dpyinfo);
8748 break;
8749 case FULLSCREEN_WIDTH:
8750 width = x_display_pixel_width (dpyinfo);
8751 break;
8752 case FULLSCREEN_HEIGHT:
8753 height = x_display_pixel_height (dpyinfo);
8756 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
8757 width, height);
8761 /* This function is called by x_set_offset to determine whether the window
8762 manager interfered with the positioning of the frame. Type A window
8763 managers position the surrounding window manager decorations a small
8764 amount above and left of the user-supplied position. Type B window
8765 managers position the surrounding window manager decorations at the
8766 user-specified position. If we detect a Type A window manager, we
8767 compensate by moving the window right and down by the proper amount. */
8769 static void
8770 x_check_expected_move (struct frame *f, int expected_left, int expected_top)
8772 int current_left = 0, current_top = 0;
8774 /* x_real_positions returns the left and top offsets of the outermost
8775 window manager window around the frame. */
8777 x_real_positions (f, &current_left, &current_top);
8779 if (current_left != expected_left || current_top != expected_top)
8781 /* It's a "Type A" window manager. */
8783 int adjusted_left;
8784 int adjusted_top;
8786 FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_A;
8787 FRAME_X_OUTPUT (f)->move_offset_left = expected_left - current_left;
8788 FRAME_X_OUTPUT (f)->move_offset_top = expected_top - current_top;
8790 /* Now fix the mispositioned frame's location. */
8792 adjusted_left = expected_left + FRAME_X_OUTPUT (f)->move_offset_left;
8793 adjusted_top = expected_top + FRAME_X_OUTPUT (f)->move_offset_top;
8795 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
8796 adjusted_left, adjusted_top);
8798 x_sync_with_move (f, expected_left, expected_top, 0);
8800 else
8801 /* It's a "Type B" window manager. We don't have to adjust the
8802 frame's position. */
8804 FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_B;
8808 /* Wait for XGetGeometry to return up-to-date position information for a
8809 recently-moved frame. Call this immediately after calling XMoveWindow.
8810 If FUZZY is non-zero, then LEFT and TOP are just estimates of where the
8811 frame has been moved to, so we use a fuzzy position comparison instead
8812 of an exact comparison. */
8814 static void
8815 x_sync_with_move (struct frame *f, int left, int top, int fuzzy)
8817 int count = 0;
8819 while (count++ < 50)
8821 int current_left = 0, current_top = 0;
8823 /* In theory, this call to XSync only needs to happen once, but in
8824 practice, it doesn't seem to work, hence the need for the surrounding
8825 loop. */
8827 XSync (FRAME_X_DISPLAY (f), False);
8828 x_real_positions (f, &current_left, &current_top);
8830 if (fuzzy)
8832 /* The left fuzz-factor is 10 pixels. The top fuzz-factor is 40
8833 pixels. */
8835 if (eabs (current_left - left) <= 10
8836 && eabs (current_top - top) <= 40)
8837 return;
8839 else if (current_left == left && current_top == top)
8840 return;
8843 /* As a last resort, just wait 0.5 seconds and hope that XGetGeometry
8844 will then return up-to-date position info. */
8846 wait_reading_process_output (0, 500000, 0, 0, Qnil, NULL, 0);
8850 /* Wait for an event on frame F matching EVENTTYPE. */
8851 void
8852 x_wait_for_event (struct frame *f, int eventtype)
8854 int level = interrupt_input_blocked;
8856 SELECT_TYPE fds;
8857 EMACS_TIME tmo, tmo_at, time_now;
8858 int fd = ConnectionNumber (FRAME_X_DISPLAY (f));
8860 pending_event_wait.f = f;
8861 pending_event_wait.eventtype = eventtype;
8863 /* Set timeout to 0.1 second. Hopefully not noticeable.
8864 Maybe it should be configurable. */
8865 EMACS_SET_SECS_USECS (tmo, 0, 100000);
8866 EMACS_GET_TIME (tmo_at);
8867 EMACS_ADD_TIME (tmo_at, tmo_at, tmo);
8869 while (pending_event_wait.eventtype)
8871 interrupt_input_pending = 1;
8872 TOTALLY_UNBLOCK_INPUT;
8873 /* XTread_socket is called after unblock. */
8874 BLOCK_INPUT;
8875 interrupt_input_blocked = level;
8877 FD_ZERO (&fds);
8878 FD_SET (fd, &fds);
8880 EMACS_GET_TIME (time_now);
8881 EMACS_SUB_TIME (tmo, tmo_at, time_now);
8883 if (EMACS_TIME_NEG_P (tmo) || select (fd+1, &fds, NULL, NULL, &tmo) == 0)
8884 break; /* Timeout */
8886 pending_event_wait.f = 0;
8887 pending_event_wait.eventtype = 0;
8891 /* Change the size of frame F's X window to COLS/ROWS in the case F
8892 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
8893 top-left-corner window gravity for this size change and subsequent
8894 size changes. Otherwise we leave the window gravity unchanged. */
8896 static void
8897 x_set_window_size_1 (struct frame *f, int change_gravity, int cols, int rows)
8899 int pixelwidth, pixelheight;
8901 check_frame_size (f, &rows, &cols);
8902 f->scroll_bar_actual_width
8903 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
8905 : FRAME_CONFIG_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f));
8907 compute_fringe_widths (f, 0);
8909 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols)
8910 + FRAME_TOOLBAR_WIDTH (f);
8911 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows)
8912 + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f);
8914 if (change_gravity) f->win_gravity = NorthWestGravity;
8915 x_wm_set_size_hint (f, (long) 0, 0);
8916 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
8917 pixelwidth, pixelheight);
8920 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
8921 receive in the ConfigureNotify event; if we get what we asked
8922 for, then the event won't cause the screen to become garbaged, so
8923 we have to make sure to do it here. */
8924 SET_FRAME_GARBAGED (f);
8926 /* Now, strictly speaking, we can't be sure that this is accurate,
8927 but the window manager will get around to dealing with the size
8928 change request eventually, and we'll hear how it went when the
8929 ConfigureNotify event gets here.
8931 We could just not bother storing any of this information here,
8932 and let the ConfigureNotify event set everything up, but that
8933 might be kind of confusing to the Lisp code, since size changes
8934 wouldn't be reported in the frame parameters until some random
8935 point in the future when the ConfigureNotify event arrives.
8937 We pass 1 for DELAY since we can't run Lisp code inside of
8938 a BLOCK_INPUT. */
8940 /* But the ConfigureNotify may in fact never arrive, and then this is
8941 not right if the frame is visible. Instead wait (with timeout)
8942 for the ConfigureNotify. */
8943 if (f->async_visible)
8944 x_wait_for_event (f, ConfigureNotify);
8945 else
8947 change_frame_size (f, rows, cols, 0, 1, 0);
8948 FRAME_PIXEL_WIDTH (f) = pixelwidth;
8949 FRAME_PIXEL_HEIGHT (f) = pixelheight;
8950 x_sync (f);
8955 /* Call this to change the size of frame F's x-window.
8956 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
8957 for this size change and subsequent size changes.
8958 Otherwise we leave the window gravity unchanged. */
8960 void
8961 x_set_window_size (struct frame *f, int change_gravity, int cols, int rows)
8963 BLOCK_INPUT;
8965 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
8967 int r, c;
8969 /* When the frame is maximized/fullscreen or running under for
8970 example Xmonad, x_set_window_size_1 will be a no-op.
8971 In that case, the right thing to do is extend rows/cols to
8972 the current frame size. We do that first if x_set_window_size_1
8973 turns out to not be a no-op (there is no way to know).
8974 The size will be adjusted again if the frame gets a
8975 ConfigureNotify event as a result of x_set_window_size. */
8976 int pixelh = FRAME_PIXEL_HEIGHT (f);
8977 #ifdef USE_X_TOOLKIT
8978 /* The menu bar is not part of text lines. The tool bar
8979 is however. */
8980 pixelh -= FRAME_MENUBAR_HEIGHT (f);
8981 #endif
8982 r = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixelh);
8983 /* Update f->scroll_bar_actual_width because it is used in
8984 FRAME_PIXEL_WIDTH_TO_TEXT_COLS. */
8985 f->scroll_bar_actual_width
8986 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
8987 c = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, FRAME_PIXEL_WIDTH (f));
8988 change_frame_size (f, r, c, 0, 1, 0);
8991 #ifdef USE_GTK
8992 if (FRAME_GTK_WIDGET (f))
8993 xg_frame_set_char_size (f, cols, rows);
8994 else
8995 x_set_window_size_1 (f, change_gravity, cols, rows);
8996 #else /* not USE_GTK */
8998 x_set_window_size_1 (f, change_gravity, cols, rows);
9000 #endif /* not USE_GTK */
9002 /* If cursor was outside the new size, mark it as off. */
9003 mark_window_cursors_off (XWINDOW (f->root_window));
9005 /* Clear out any recollection of where the mouse highlighting was,
9006 since it might be in a place that's outside the new frame size.
9007 Actually checking whether it is outside is a pain in the neck,
9008 so don't try--just let the highlighting be done afresh with new size. */
9009 cancel_mouse_face (f);
9011 UNBLOCK_INPUT;
9014 /* Mouse warping. */
9016 void
9017 x_set_mouse_position (struct frame *f, int x, int y)
9019 int pix_x, pix_y;
9021 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
9022 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
9024 if (pix_x < 0) pix_x = 0;
9025 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
9027 if (pix_y < 0) pix_y = 0;
9028 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
9030 BLOCK_INPUT;
9032 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
9033 0, 0, 0, 0, pix_x, pix_y);
9034 UNBLOCK_INPUT;
9037 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
9039 void
9040 x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
9042 BLOCK_INPUT;
9044 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
9045 0, 0, 0, 0, pix_x, pix_y);
9046 UNBLOCK_INPUT;
9049 /* Raise frame F. */
9051 void
9052 x_raise_frame (struct frame *f)
9054 BLOCK_INPUT;
9055 if (f->async_visible)
9056 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
9058 XFlush (FRAME_X_DISPLAY (f));
9059 UNBLOCK_INPUT;
9062 /* Lower frame F. */
9064 static void
9065 x_lower_frame (struct frame *f)
9067 if (f->async_visible)
9069 BLOCK_INPUT;
9070 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
9071 XFlush (FRAME_X_DISPLAY (f));
9072 UNBLOCK_INPUT;
9076 /* Request focus with XEmbed */
9078 void
9079 xembed_request_focus (FRAME_PTR f)
9081 /* See XEmbed Protocol Specification at
9082 http://freedesktop.org/wiki/Specifications/xembed-spec */
9083 if (f->async_visible)
9084 xembed_send_message (f, CurrentTime,
9085 XEMBED_REQUEST_FOCUS, 0, 0, 0);
9088 /* Activate frame with Extended Window Manager Hints */
9090 void
9091 x_ewmh_activate_frame (FRAME_PTR f)
9093 /* See Window Manager Specification/Extended Window Manager Hints at
9094 http://freedesktop.org/wiki/Specifications/wm-spec */
9096 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9097 if (f->async_visible && wm_supports (f, dpyinfo->Xatom_net_active_window))
9099 Lisp_Object frame;
9100 XSETFRAME (frame, f);
9101 x_send_client_event (frame, make_number (0), frame,
9102 dpyinfo->Xatom_net_active_window,
9103 make_number (32),
9104 Fcons (make_number (1),
9105 Fcons (make_number (last_user_time),
9106 Qnil)));
9110 static void
9111 XTframe_raise_lower (FRAME_PTR f, int raise_flag)
9113 if (raise_flag)
9114 x_raise_frame (f);
9115 else
9116 x_lower_frame (f);
9119 /* XEmbed implementation. */
9121 #if defined USE_X_TOOLKIT || ! defined USE_GTK
9123 /* XEmbed implementation. */
9125 #define XEMBED_VERSION 0
9127 static void
9128 xembed_set_info (struct frame *f, enum xembed_info flags)
9130 unsigned long data[2];
9131 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9133 data[0] = XEMBED_VERSION;
9134 data[1] = flags;
9136 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
9137 dpyinfo->Xatom_XEMBED_INFO, dpyinfo->Xatom_XEMBED_INFO,
9138 32, PropModeReplace, (unsigned char *) data, 2);
9140 #endif /* defined USE_X_TOOLKIT || ! defined USE_GTK */
9142 static void
9143 xembed_send_message (struct frame *f, Time t, enum xembed_message msg,
9144 long int detail, long int data1, long int data2)
9146 XEvent event;
9148 event.xclient.type = ClientMessage;
9149 event.xclient.window = FRAME_X_OUTPUT (f)->parent_desc;
9150 event.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_XEMBED;
9151 event.xclient.format = 32;
9152 event.xclient.data.l[0] = t;
9153 event.xclient.data.l[1] = msg;
9154 event.xclient.data.l[2] = detail;
9155 event.xclient.data.l[3] = data1;
9156 event.xclient.data.l[4] = data2;
9158 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_OUTPUT (f)->parent_desc,
9159 False, NoEventMask, &event);
9160 XSync (FRAME_X_DISPLAY (f), False);
9163 /* Change of visibility. */
9165 /* This tries to wait until the frame is really visible.
9166 However, if the window manager asks the user where to position
9167 the frame, this will return before the user finishes doing that.
9168 The frame will not actually be visible at that time,
9169 but it will become visible later when the window manager
9170 finishes with it. */
9172 void
9173 x_make_frame_visible (struct frame *f)
9175 Lisp_Object type;
9176 int original_top, original_left;
9177 int retry_count = 2;
9179 retry:
9181 BLOCK_INPUT;
9183 type = x_icon_type (f);
9184 if (!NILP (type))
9185 x_bitmap_icon (f, type);
9187 if (! FRAME_VISIBLE_P (f))
9189 /* We test FRAME_GARBAGED_P here to make sure we don't
9190 call x_set_offset a second time
9191 if we get to x_make_frame_visible a second time
9192 before the window gets really visible. */
9193 if (! FRAME_ICONIFIED_P (f)
9194 && ! FRAME_X_EMBEDDED_P (f)
9195 && ! f->output_data.x->asked_for_visible)
9196 x_set_offset (f, f->left_pos, f->top_pos, 0);
9198 f->output_data.x->asked_for_visible = 1;
9200 if (! EQ (Vx_no_window_manager, Qt))
9201 x_wm_set_window_state (f, NormalState);
9202 #ifdef USE_X_TOOLKIT
9203 if (FRAME_X_EMBEDDED_P (f))
9204 xembed_set_info (f, XEMBED_MAPPED);
9205 else
9207 /* This was XtPopup, but that did nothing for an iconified frame. */
9208 XtMapWidget (f->output_data.x->widget);
9210 #else /* not USE_X_TOOLKIT */
9211 #ifdef USE_GTK
9212 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
9213 gtk_window_deiconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
9214 #else
9215 if (FRAME_X_EMBEDDED_P (f))
9216 xembed_set_info (f, XEMBED_MAPPED);
9217 else
9218 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
9219 #endif /* not USE_GTK */
9220 #endif /* not USE_X_TOOLKIT */
9223 XFlush (FRAME_X_DISPLAY (f));
9225 /* Synchronize to ensure Emacs knows the frame is visible
9226 before we do anything else. We do this loop with input not blocked
9227 so that incoming events are handled. */
9229 Lisp_Object frame;
9230 int count;
9231 /* This must be before UNBLOCK_INPUT
9232 since events that arrive in response to the actions above
9233 will set it when they are handled. */
9234 int previously_visible = f->output_data.x->has_been_visible;
9236 original_left = f->left_pos;
9237 original_top = f->top_pos;
9239 /* This must come after we set COUNT. */
9240 UNBLOCK_INPUT;
9242 /* We unblock here so that arriving X events are processed. */
9244 /* Now move the window back to where it was "supposed to be".
9245 But don't do it if the gravity is negative.
9246 When the gravity is negative, this uses a position
9247 that is 3 pixels too low. Perhaps that's really the border width.
9249 Don't do this if the window has never been visible before,
9250 because the window manager may choose the position
9251 and we don't want to override it. */
9253 if (! FRAME_VISIBLE_P (f)
9254 && ! FRAME_ICONIFIED_P (f)
9255 && ! FRAME_X_EMBEDDED_P (f)
9256 && f->win_gravity == NorthWestGravity
9257 && previously_visible)
9259 Drawable rootw;
9260 int x, y;
9261 unsigned int width, height, border, depth;
9263 BLOCK_INPUT;
9265 /* On some window managers (such as FVWM) moving an existing
9266 window, even to the same place, causes the window manager
9267 to introduce an offset. This can cause the window to move
9268 to an unexpected location. Check the geometry (a little
9269 slow here) and then verify that the window is in the right
9270 place. If the window is not in the right place, move it
9271 there, and take the potential window manager hit. */
9272 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
9273 &rootw, &x, &y, &width, &height, &border, &depth);
9275 if (original_left != x || original_top != y)
9276 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
9277 original_left, original_top);
9279 UNBLOCK_INPUT;
9282 XSETFRAME (frame, f);
9284 /* Wait until the frame is visible. Process X events until a
9285 MapNotify event has been seen, or until we think we won't get a
9286 MapNotify at all.. */
9287 for (count = input_signal_count + 10;
9288 input_signal_count < count && !FRAME_VISIBLE_P (f);)
9290 /* Force processing of queued events. */
9291 x_sync (f);
9293 /* Machines that do polling rather than SIGIO have been
9294 observed to go into a busy-wait here. So we'll fake an
9295 alarm signal to let the handler know that there's something
9296 to be read. We used to raise a real alarm, but it seems
9297 that the handler isn't always enabled here. This is
9298 probably a bug. */
9299 if (input_polling_used ())
9301 /* It could be confusing if a real alarm arrives while
9302 processing the fake one. Turn it off and let the
9303 handler reset it. */
9304 int old_poll_suppress_count = poll_suppress_count;
9305 poll_suppress_count = 1;
9306 poll_for_input_1 ();
9307 poll_suppress_count = old_poll_suppress_count;
9310 /* See if a MapNotify event has been processed. */
9311 FRAME_SAMPLE_VISIBILITY (f);
9314 /* 2000-09-28: In
9316 (let ((f (selected-frame)))
9317 (iconify-frame f)
9318 (raise-frame f))
9320 the frame is not raised with various window managers on
9321 FreeBSD, GNU/Linux and Solaris. It turns out that, for some
9322 unknown reason, the call to XtMapWidget is completely ignored.
9323 Mapping the widget a second time works. */
9325 if (!FRAME_VISIBLE_P (f) && --retry_count != 0)
9326 goto retry;
9330 /* Change from mapped state to withdrawn state. */
9332 /* Make the frame visible (mapped and not iconified). */
9334 void
9335 x_make_frame_invisible (struct frame *f)
9337 Window window;
9339 /* Use the frame's outermost window, not the one we normally draw on. */
9340 window = FRAME_OUTER_WINDOW (f);
9342 /* Don't keep the highlight on an invisible frame. */
9343 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
9344 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9346 BLOCK_INPUT;
9348 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
9349 that the current position of the window is user-specified, rather than
9350 program-specified, so that when the window is mapped again, it will be
9351 placed at the same location, without forcing the user to position it
9352 by hand again (they have already done that once for this window.) */
9353 x_wm_set_size_hint (f, (long) 0, 1);
9355 #ifdef USE_GTK
9356 if (FRAME_GTK_OUTER_WIDGET (f))
9357 gtk_widget_hide (FRAME_GTK_OUTER_WIDGET (f));
9358 else
9359 #else
9360 if (FRAME_X_EMBEDDED_P (f))
9361 xembed_set_info (f, 0);
9362 else
9363 #endif
9366 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
9367 DefaultScreen (FRAME_X_DISPLAY (f))))
9369 UNBLOCK_INPUT_RESIGNAL;
9370 error ("Can't notify window manager of window withdrawal");
9374 /* We can't distinguish this from iconification
9375 just by the event that we get from the server.
9376 So we can't win using the usual strategy of letting
9377 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
9378 and synchronize with the server to make sure we agree. */
9379 f->visible = 0;
9380 FRAME_ICONIFIED_P (f) = 0;
9381 f->async_visible = 0;
9382 f->async_iconified = 0;
9384 x_sync (f);
9386 UNBLOCK_INPUT;
9389 /* Change window state from mapped to iconified. */
9391 void
9392 x_iconify_frame (struct frame *f)
9394 #ifdef USE_X_TOOLKIT
9395 int result;
9396 #endif
9397 Lisp_Object type;
9399 /* Don't keep the highlight on an invisible frame. */
9400 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
9401 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9403 if (f->async_iconified)
9404 return;
9406 BLOCK_INPUT;
9408 FRAME_SAMPLE_VISIBILITY (f);
9410 type = x_icon_type (f);
9411 if (!NILP (type))
9412 x_bitmap_icon (f, type);
9414 #if defined (USE_GTK)
9415 if (FRAME_GTK_OUTER_WIDGET (f))
9417 if (! FRAME_VISIBLE_P (f))
9418 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
9420 gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
9421 f->iconified = 1;
9422 f->visible = 1;
9423 f->async_iconified = 1;
9424 f->async_visible = 0;
9425 UNBLOCK_INPUT;
9426 return;
9428 #endif
9430 #ifdef USE_X_TOOLKIT
9432 if (! FRAME_VISIBLE_P (f))
9434 if (! EQ (Vx_no_window_manager, Qt))
9435 x_wm_set_window_state (f, IconicState);
9436 /* This was XtPopup, but that did nothing for an iconified frame. */
9437 XtMapWidget (f->output_data.x->widget);
9438 /* The server won't give us any event to indicate
9439 that an invisible frame was changed to an icon,
9440 so we have to record it here. */
9441 f->iconified = 1;
9442 f->visible = 1;
9443 f->async_iconified = 1;
9444 f->async_visible = 0;
9445 UNBLOCK_INPUT;
9446 return;
9449 result = XIconifyWindow (FRAME_X_DISPLAY (f),
9450 XtWindow (f->output_data.x->widget),
9451 DefaultScreen (FRAME_X_DISPLAY (f)));
9452 UNBLOCK_INPUT;
9454 if (!result)
9455 error ("Can't notify window manager of iconification");
9457 f->async_iconified = 1;
9458 f->async_visible = 0;
9461 BLOCK_INPUT;
9462 XFlush (FRAME_X_DISPLAY (f));
9463 UNBLOCK_INPUT;
9464 #else /* not USE_X_TOOLKIT */
9466 /* Make sure the X server knows where the window should be positioned,
9467 in case the user deiconifies with the window manager. */
9468 if (! FRAME_VISIBLE_P (f)
9469 && ! FRAME_ICONIFIED_P (f)
9470 && ! FRAME_X_EMBEDDED_P (f))
9471 x_set_offset (f, f->left_pos, f->top_pos, 0);
9473 /* Since we don't know which revision of X we're running, we'll use both
9474 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
9476 /* X11R4: send a ClientMessage to the window manager using the
9477 WM_CHANGE_STATE type. */
9479 XEvent msg;
9481 msg.xclient.window = FRAME_X_WINDOW (f);
9482 msg.xclient.type = ClientMessage;
9483 msg.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
9484 msg.xclient.format = 32;
9485 msg.xclient.data.l[0] = IconicState;
9487 if (! XSendEvent (FRAME_X_DISPLAY (f),
9488 DefaultRootWindow (FRAME_X_DISPLAY (f)),
9489 False,
9490 SubstructureRedirectMask | SubstructureNotifyMask,
9491 &msg))
9493 UNBLOCK_INPUT_RESIGNAL;
9494 error ("Can't notify window manager of iconification");
9498 /* X11R3: set the initial_state field of the window manager hints to
9499 IconicState. */
9500 x_wm_set_window_state (f, IconicState);
9502 if (!FRAME_VISIBLE_P (f))
9504 /* If the frame was withdrawn, before, we must map it. */
9505 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
9508 f->async_iconified = 1;
9509 f->async_visible = 0;
9511 XFlush (FRAME_X_DISPLAY (f));
9512 UNBLOCK_INPUT;
9513 #endif /* not USE_X_TOOLKIT */
9517 /* Free X resources of frame F. */
9519 void
9520 x_free_frame_resources (struct frame *f)
9522 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9523 Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
9524 #ifdef USE_X_TOOLKIT
9525 Lisp_Object bar;
9526 struct scroll_bar *b;
9527 #endif
9529 BLOCK_INPUT;
9531 /* If a display connection is dead, don't try sending more
9532 commands to the X server. */
9533 if (dpyinfo->display)
9535 /* We must free faces before destroying windows because some
9536 font-driver (e.g. xft) access a window while finishing a
9537 face. */
9538 if (FRAME_FACE_CACHE (f))
9539 free_frame_faces (f);
9541 if (f->output_data.x->icon_desc)
9542 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
9544 #ifdef USE_X_TOOLKIT
9545 /* Explicitly destroy the scroll bars of the frame. Without
9546 this, we get "BadDrawable" errors from the toolkit later on,
9547 presumably from expose events generated for the disappearing
9548 toolkit scroll bars. */
9549 for (bar = FRAME_SCROLL_BARS (f); !NILP (bar); bar = b->next)
9551 b = XSCROLL_BAR (bar);
9552 x_scroll_bar_remove (b);
9554 #endif
9556 #ifdef HAVE_X_I18N
9557 if (FRAME_XIC (f))
9558 free_frame_xic (f);
9559 #endif
9561 #ifdef USE_X_TOOLKIT
9562 if (f->output_data.x->widget)
9564 XtDestroyWidget (f->output_data.x->widget);
9565 f->output_data.x->widget = NULL;
9567 /* Tooltips don't have widgets, only a simple X window, even if
9568 we are using a toolkit. */
9569 else if (FRAME_X_WINDOW (f))
9570 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
9572 free_frame_menubar (f);
9573 #else /* !USE_X_TOOLKIT */
9575 #ifdef USE_GTK
9576 xg_free_frame_widgets (f);
9577 #endif /* USE_GTK */
9579 if (FRAME_X_WINDOW (f))
9580 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
9581 #endif /* !USE_X_TOOLKIT */
9583 unload_color (f, FRAME_FOREGROUND_PIXEL (f));
9584 unload_color (f, FRAME_BACKGROUND_PIXEL (f));
9585 unload_color (f, f->output_data.x->cursor_pixel);
9586 unload_color (f, f->output_data.x->cursor_foreground_pixel);
9587 unload_color (f, f->output_data.x->border_pixel);
9588 unload_color (f, f->output_data.x->mouse_pixel);
9590 if (f->output_data.x->scroll_bar_background_pixel != -1)
9591 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
9592 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
9593 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
9594 #ifdef USE_TOOLKIT_SCROLL_BARS
9595 /* Scrollbar shadow colors. */
9596 if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
9597 unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
9598 if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
9599 unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
9600 #endif /* USE_TOOLKIT_SCROLL_BARS */
9601 if (f->output_data.x->white_relief.allocated_p)
9602 unload_color (f, f->output_data.x->white_relief.pixel);
9603 if (f->output_data.x->black_relief.allocated_p)
9604 unload_color (f, f->output_data.x->black_relief.pixel);
9606 x_free_gcs (f);
9607 XFlush (FRAME_X_DISPLAY (f));
9610 xfree (f->output_data.x->saved_menu_event);
9611 xfree (f->output_data.x);
9612 f->output_data.x = NULL;
9614 if (f == dpyinfo->x_focus_frame)
9615 dpyinfo->x_focus_frame = 0;
9616 if (f == dpyinfo->x_focus_event_frame)
9617 dpyinfo->x_focus_event_frame = 0;
9618 if (f == dpyinfo->x_highlight_frame)
9619 dpyinfo->x_highlight_frame = 0;
9621 if (f == hlinfo->mouse_face_mouse_frame)
9623 hlinfo->mouse_face_beg_row
9624 = hlinfo->mouse_face_beg_col = -1;
9625 hlinfo->mouse_face_end_row
9626 = hlinfo->mouse_face_end_col = -1;
9627 hlinfo->mouse_face_window = Qnil;
9628 hlinfo->mouse_face_deferred_gc = 0;
9629 hlinfo->mouse_face_mouse_frame = 0;
9632 UNBLOCK_INPUT;
9636 /* Destroy the X window of frame F. */
9638 static void
9639 x_destroy_window (struct frame *f)
9641 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9643 /* If a display connection is dead, don't try sending more
9644 commands to the X server. */
9645 if (dpyinfo->display != 0)
9646 x_free_frame_resources (f);
9648 dpyinfo->reference_count--;
9652 /* Setting window manager hints. */
9654 /* Set the normal size hints for the window manager, for frame F.
9655 FLAGS is the flags word to use--or 0 meaning preserve the flags
9656 that the window now has.
9657 If USER_POSITION is nonzero, we set the USPosition
9658 flag (this is useful when FLAGS is 0).
9659 The GTK version is in gtkutils.c */
9661 #ifndef USE_GTK
9662 void
9663 x_wm_set_size_hint (struct frame *f, long flags, int user_position)
9665 XSizeHints size_hints;
9666 Window window = FRAME_OUTER_WINDOW (f);
9668 #ifdef USE_X_TOOLKIT
9669 if (f->output_data.x->widget)
9671 widget_update_wm_size_hints (f->output_data.x->widget);
9672 return;
9674 #endif
9676 /* Setting PMaxSize caused various problems. */
9677 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
9679 size_hints.x = f->left_pos;
9680 size_hints.y = f->top_pos;
9682 size_hints.height = FRAME_PIXEL_HEIGHT (f);
9683 size_hints.width = FRAME_PIXEL_WIDTH (f);
9685 size_hints.width_inc = FRAME_COLUMN_WIDTH (f);
9686 size_hints.height_inc = FRAME_LINE_HEIGHT (f);
9687 size_hints.max_width = x_display_pixel_width (FRAME_X_DISPLAY_INFO (f))
9688 - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
9689 size_hints.max_height = x_display_pixel_height (FRAME_X_DISPLAY_INFO (f))
9690 - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
9692 /* Calculate the base and minimum sizes. */
9694 int base_width, base_height;
9695 int min_rows = 0, min_cols = 0;
9697 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
9698 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
9700 check_frame_size (f, &min_rows, &min_cols);
9702 /* The window manager uses the base width hints to calculate the
9703 current number of rows and columns in the frame while
9704 resizing; min_width and min_height aren't useful for this
9705 purpose, since they might not give the dimensions for a
9706 zero-row, zero-column frame.
9708 We use the base_width and base_height members if we have
9709 them; otherwise, we set the min_width and min_height members
9710 to the size for a zero x zero frame. */
9712 size_hints.flags |= PBaseSize;
9713 size_hints.base_width = base_width;
9714 size_hints.base_height = base_height + FRAME_MENUBAR_HEIGHT (f);
9715 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
9716 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
9719 /* If we don't need the old flags, we don't need the old hint at all. */
9720 if (flags)
9722 size_hints.flags |= flags;
9723 goto no_read;
9727 XSizeHints hints; /* Sometimes I hate X Windows... */
9728 long supplied_return;
9729 int value;
9731 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
9732 &supplied_return);
9734 if (flags)
9735 size_hints.flags |= flags;
9736 else
9738 if (value == 0)
9739 hints.flags = 0;
9740 if (hints.flags & PSize)
9741 size_hints.flags |= PSize;
9742 if (hints.flags & PPosition)
9743 size_hints.flags |= PPosition;
9744 if (hints.flags & USPosition)
9745 size_hints.flags |= USPosition;
9746 if (hints.flags & USSize)
9747 size_hints.flags |= USSize;
9751 no_read:
9753 #ifdef PWinGravity
9754 size_hints.win_gravity = f->win_gravity;
9755 size_hints.flags |= PWinGravity;
9757 if (user_position)
9759 size_hints.flags &= ~ PPosition;
9760 size_hints.flags |= USPosition;
9762 #endif /* PWinGravity */
9764 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
9766 #endif /* not USE_GTK */
9768 /* Used for IconicState or NormalState */
9770 static void
9771 x_wm_set_window_state (struct frame *f, int state)
9773 #ifdef USE_X_TOOLKIT
9774 Arg al[1];
9776 XtSetArg (al[0], XtNinitialState, state);
9777 XtSetValues (f->output_data.x->widget, al, 1);
9778 #else /* not USE_X_TOOLKIT */
9779 Window window = FRAME_X_WINDOW (f);
9781 f->output_data.x->wm_hints.flags |= StateHint;
9782 f->output_data.x->wm_hints.initial_state = state;
9784 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
9785 #endif /* not USE_X_TOOLKIT */
9788 static void
9789 x_wm_set_icon_pixmap (struct frame *f, ptrdiff_t pixmap_id)
9791 Pixmap icon_pixmap, icon_mask;
9793 #if !defined USE_X_TOOLKIT && !defined USE_GTK
9794 Window window = FRAME_OUTER_WINDOW (f);
9795 #endif
9797 if (pixmap_id > 0)
9799 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
9800 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
9801 icon_mask = x_bitmap_mask (f, pixmap_id);
9802 f->output_data.x->wm_hints.icon_mask = icon_mask;
9804 else
9806 /* It seems there is no way to turn off use of an icon
9807 pixmap. */
9808 return;
9812 #ifdef USE_GTK
9814 xg_set_frame_icon (f, icon_pixmap, icon_mask);
9815 return;
9818 #elif defined (USE_X_TOOLKIT) /* same as in x_wm_set_window_state. */
9821 Arg al[1];
9822 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
9823 XtSetValues (f->output_data.x->widget, al, 1);
9824 XtSetArg (al[0], XtNiconMask, icon_mask);
9825 XtSetValues (f->output_data.x->widget, al, 1);
9828 #else /* not USE_X_TOOLKIT && not USE_GTK */
9830 f->output_data.x->wm_hints.flags |= (IconPixmapHint | IconMaskHint);
9831 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
9833 #endif /* not USE_X_TOOLKIT && not USE_GTK */
9836 void
9837 x_wm_set_icon_position (struct frame *f, int icon_x, int icon_y)
9839 Window window = FRAME_OUTER_WINDOW (f);
9841 f->output_data.x->wm_hints.flags |= IconPositionHint;
9842 f->output_data.x->wm_hints.icon_x = icon_x;
9843 f->output_data.x->wm_hints.icon_y = icon_y;
9845 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
9849 /***********************************************************************
9850 Fonts
9851 ***********************************************************************/
9853 #if GLYPH_DEBUG
9855 /* Check that FONT is valid on frame F. It is if it can be found in F's
9856 font table. */
9858 static void
9859 x_check_font (struct frame *f, struct font *font)
9861 xassert (font != NULL && ! NILP (font->props[FONT_TYPE_INDEX]));
9862 if (font->driver->check)
9863 xassert (font->driver->check (f, font) == 0);
9866 #endif /* GLYPH_DEBUG != 0 */
9869 /***********************************************************************
9870 Initialization
9871 ***********************************************************************/
9873 #ifdef USE_X_TOOLKIT
9874 static XrmOptionDescRec emacs_options[] = {
9875 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
9876 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
9878 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
9879 XrmoptionSepArg, NULL},
9880 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
9882 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
9883 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
9884 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
9885 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
9886 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
9887 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
9888 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
9891 /* Whether atimer for Xt timeouts is activated or not. */
9893 static int x_timeout_atimer_activated_flag;
9895 #endif /* USE_X_TOOLKIT */
9897 static int x_initialized;
9899 /* Test whether two display-name strings agree up to the dot that separates
9900 the screen number from the server number. */
9901 static int
9902 same_x_server (const char *name1, const char *name2)
9904 int seen_colon = 0;
9905 const char *system_name = SSDATA (Vsystem_name);
9906 ptrdiff_t system_name_length = SBYTES (Vsystem_name);
9907 ptrdiff_t length_until_period = 0;
9909 while (system_name[length_until_period] != 0
9910 && system_name[length_until_period] != '.')
9911 length_until_period++;
9913 /* Treat `unix' like an empty host name. */
9914 if (! strncmp (name1, "unix:", 5))
9915 name1 += 4;
9916 if (! strncmp (name2, "unix:", 5))
9917 name2 += 4;
9918 /* Treat this host's name like an empty host name. */
9919 if (! strncmp (name1, system_name, system_name_length)
9920 && name1[system_name_length] == ':')
9921 name1 += system_name_length;
9922 if (! strncmp (name2, system_name, system_name_length)
9923 && name2[system_name_length] == ':')
9924 name2 += system_name_length;
9925 /* Treat this host's domainless name like an empty host name. */
9926 if (! strncmp (name1, system_name, length_until_period)
9927 && name1[length_until_period] == ':')
9928 name1 += length_until_period;
9929 if (! strncmp (name2, system_name, length_until_period)
9930 && name2[length_until_period] == ':')
9931 name2 += length_until_period;
9933 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
9935 if (*name1 == ':')
9936 seen_colon = 1;
9937 if (seen_colon && *name1 == '.')
9938 return 1;
9940 return (seen_colon
9941 && (*name1 == '.' || *name1 == '\0')
9942 && (*name2 == '.' || *name2 == '\0'));
9945 /* Count number of set bits in mask and number of bits to shift to
9946 get to the first bit. With MASK 0x7e0, *BITS is set to 6, and *OFFSET
9947 to 5. */
9948 static void
9949 get_bits_and_offset (long unsigned int mask, int *bits, int *offset)
9951 int nr = 0;
9952 int off = 0;
9954 while (!(mask & 1))
9956 off++;
9957 mask >>= 1;
9960 while (mask & 1)
9962 nr++;
9963 mask >>= 1;
9966 *offset = off;
9967 *bits = nr;
9970 /* Return 1 if display DISPLAY is available for use, 0 otherwise.
9971 But don't permanently open it, just test its availability. */
9974 x_display_ok (const char *display)
9976 int dpy_ok = 1;
9977 Display *dpy;
9979 dpy = XOpenDisplay (display);
9980 if (dpy)
9981 XCloseDisplay (dpy);
9982 else
9983 dpy_ok = 0;
9984 return dpy_ok;
9987 #ifdef USE_GTK
9988 static void
9989 my_log_handler (const gchar *log_domain, GLogLevelFlags log_level,
9990 const gchar *msg, gpointer user_data)
9992 if (!strstr (msg, "g_set_prgname"))
9993 fprintf (stderr, "%s-WARNING **: %s\n", log_domain, msg);
9995 #endif
9997 /* Open a connection to X display DISPLAY_NAME, and return
9998 the structure that describes the open display.
9999 If we cannot contact the display, return null. */
10001 struct x_display_info *
10002 x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
10004 int connection;
10005 Display *dpy;
10006 struct terminal *terminal;
10007 struct x_display_info *dpyinfo;
10008 XrmDatabase xrdb;
10009 Mouse_HLInfo *hlinfo;
10010 ptrdiff_t lim;
10012 BLOCK_INPUT;
10014 if (!x_initialized)
10016 x_initialize ();
10017 ++x_initialized;
10020 if (! x_display_ok (SSDATA (display_name)))
10021 error ("Display %s can't be opened", SSDATA (display_name));
10023 #ifdef USE_GTK
10025 #define NUM_ARGV 10
10026 int argc;
10027 char *argv[NUM_ARGV];
10028 char **argv2 = argv;
10029 guint id;
10031 if (x_initialized++ > 1)
10033 xg_display_open (SSDATA (display_name), &dpy);
10035 else
10037 static char display_opt[] = "--display";
10038 static char name_opt[] = "--name";
10040 for (argc = 0; argc < NUM_ARGV; ++argc)
10041 argv[argc] = 0;
10043 argc = 0;
10044 argv[argc++] = initial_argv[0];
10046 if (! NILP (display_name))
10048 argv[argc++] = display_opt;
10049 argv[argc++] = SSDATA (display_name);
10052 argv[argc++] = name_opt;
10053 argv[argc++] = resource_name;
10055 XSetLocaleModifiers ("");
10057 /* Emacs can only handle core input events, so make sure
10058 Gtk doesn't use Xinput or Xinput2 extensions. */
10060 static char fix_events[] = "GDK_CORE_DEVICE_EVENTS=1";
10061 putenv (fix_events);
10064 /* Work around GLib bug that outputs a faulty warning. See
10065 https://bugzilla.gnome.org/show_bug.cgi?id=563627. */
10066 id = g_log_set_handler ("GLib", G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL
10067 | G_LOG_FLAG_RECURSION, my_log_handler, NULL);
10069 /* NULL window -> events for all windows go to our function.
10070 Call before gtk_init so Gtk+ event filters comes after our. */
10071 gdk_window_add_filter (NULL, event_handler_gdk, NULL);
10073 gtk_init (&argc, &argv2);
10074 g_log_remove_handler ("GLib", id);
10076 /* gtk_init does set_locale. We must fix locale after calling it. */
10077 fixup_locale ();
10078 xg_initialize ();
10080 dpy = DEFAULT_GDK_DISPLAY ();
10082 #if GTK_MAJOR_VERSION <= 2 && GTK_MINOR_VERSION <= 90
10083 /* Load our own gtkrc if it exists. */
10085 const char *file = "~/.emacs.d/gtkrc";
10086 Lisp_Object s, abs_file;
10088 s = make_string (file, strlen (file));
10089 abs_file = Fexpand_file_name (s, Qnil);
10091 if (! NILP (abs_file) && !NILP (Ffile_readable_p (abs_file)))
10092 gtk_rc_parse (SSDATA (abs_file));
10094 #endif
10096 XSetErrorHandler (x_error_handler);
10097 XSetIOErrorHandler (x_io_error_quitter);
10100 #else /* not USE_GTK */
10101 #ifdef USE_X_TOOLKIT
10102 /* weiner@footloose.sps.mot.com reports that this causes
10103 errors with X11R5:
10104 X protocol error: BadAtom (invalid Atom parameter)
10105 on protocol request 18skiloaf.
10106 So let's not use it until R6. */
10107 #ifdef HAVE_X11XTR6
10108 XtSetLanguageProc (NULL, NULL, NULL);
10109 #endif
10112 int argc = 0;
10113 char *argv[3];
10115 argv[0] = "";
10116 argc = 1;
10117 if (xrm_option)
10119 argv[argc++] = "-xrm";
10120 argv[argc++] = xrm_option;
10122 turn_on_atimers (0);
10123 dpy = XtOpenDisplay (Xt_app_con, SSDATA (display_name),
10124 resource_name, EMACS_CLASS,
10125 emacs_options, XtNumber (emacs_options),
10126 &argc, argv);
10127 turn_on_atimers (1);
10129 #ifdef HAVE_X11XTR6
10130 /* I think this is to compensate for XtSetLanguageProc. */
10131 fixup_locale ();
10132 #endif
10135 #else /* not USE_X_TOOLKIT */
10136 XSetLocaleModifiers ("");
10137 dpy = XOpenDisplay (SSDATA (display_name));
10138 #endif /* not USE_X_TOOLKIT */
10139 #endif /* not USE_GTK*/
10141 /* Detect failure. */
10142 if (dpy == 0)
10144 UNBLOCK_INPUT;
10145 return 0;
10148 /* We have definitely succeeded. Record the new connection. */
10150 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
10151 memset (dpyinfo, 0, sizeof *dpyinfo);
10152 hlinfo = &dpyinfo->mouse_highlight;
10154 terminal = x_create_terminal (dpyinfo);
10157 struct x_display_info *share;
10158 Lisp_Object tail;
10160 for (share = x_display_list, tail = x_display_name_list; share;
10161 share = share->next, tail = XCDR (tail))
10162 if (same_x_server (SSDATA (XCAR (XCAR (tail))),
10163 SSDATA (display_name)))
10164 break;
10165 if (share)
10166 terminal->kboard = share->terminal->kboard;
10167 else
10169 terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
10170 init_kboard (terminal->kboard);
10171 KVAR (terminal->kboard, Vwindow_system) = Qx;
10173 /* Add the keyboard to the list before running Lisp code (via
10174 Qvendor_specific_keysyms below), since these are not traced
10175 via terminals but only through all_kboards. */
10176 terminal->kboard->next_kboard = all_kboards;
10177 all_kboards = terminal->kboard;
10179 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
10181 char *vendor = ServerVendor (dpy);
10183 /* Protect terminal from GC before removing it from the
10184 list of terminals. */
10185 struct gcpro gcpro1;
10186 Lisp_Object gcpro_term;
10187 XSETTERMINAL (gcpro_term, terminal);
10188 GCPRO1 (gcpro_term);
10190 /* Temporarily hide the partially initialized terminal. */
10191 terminal_list = terminal->next_terminal;
10192 UNBLOCK_INPUT;
10193 KVAR (terminal->kboard, Vsystem_key_alist)
10194 = call1 (Qvendor_specific_keysyms,
10195 vendor ? build_string (vendor) : empty_unibyte_string);
10196 BLOCK_INPUT;
10197 terminal->next_terminal = terminal_list;
10198 terminal_list = terminal;
10199 UNGCPRO;
10202 /* Don't let the initial kboard remain current longer than necessary.
10203 That would cause problems if a file loaded on startup tries to
10204 prompt in the mini-buffer. */
10205 if (current_kboard == initial_kboard)
10206 current_kboard = terminal->kboard;
10208 terminal->kboard->reference_count++;
10211 /* Put this display on the chain. */
10212 dpyinfo->next = x_display_list;
10213 x_display_list = dpyinfo;
10215 /* Put it on x_display_name_list as well, to keep them parallel. */
10216 x_display_name_list = Fcons (Fcons (display_name, Qnil),
10217 x_display_name_list);
10218 dpyinfo->name_list_element = XCAR (x_display_name_list);
10220 dpyinfo->display = dpy;
10222 /* Set the name of the terminal. */
10223 terminal->name = (char *) xmalloc (SBYTES (display_name) + 1);
10224 memcpy (terminal->name, SSDATA (display_name), SBYTES (display_name));
10225 terminal->name[SBYTES (display_name)] = 0;
10227 #if 0
10228 XSetAfterFunction (x_current_display, x_trace_wire);
10229 #endif /* ! 0 */
10231 lim = min (PTRDIFF_MAX, SIZE_MAX) - sizeof "@";
10232 if (lim - SBYTES (Vinvocation_name) < SBYTES (Vsystem_name))
10233 memory_full (SIZE_MAX);
10234 dpyinfo->x_id_name
10235 = (char *) xmalloc (SBYTES (Vinvocation_name)
10236 + SBYTES (Vsystem_name)
10237 + 2);
10238 strcat (strcat (strcpy (dpyinfo->x_id_name, SSDATA (Vinvocation_name)), "@"),
10239 SSDATA (Vsystem_name));
10241 /* Figure out which modifier bits mean what. */
10242 x_find_modifier_meanings (dpyinfo);
10244 /* Get the scroll bar cursor. */
10245 #ifdef USE_GTK
10246 /* We must create a GTK cursor, it is required for GTK widgets. */
10247 dpyinfo->xg_cursor = xg_create_default_cursor (dpyinfo->display);
10248 #endif /* USE_GTK */
10250 dpyinfo->vertical_scroll_bar_cursor
10251 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
10253 xrdb = x_load_resources (dpyinfo->display, xrm_option,
10254 resource_name, EMACS_CLASS);
10255 #ifdef HAVE_XRMSETDATABASE
10256 XrmSetDatabase (dpyinfo->display, xrdb);
10257 #else
10258 dpyinfo->display->db = xrdb;
10259 #endif
10260 /* Put the rdb where we can find it in a way that works on
10261 all versions. */
10262 dpyinfo->xrdb = xrdb;
10264 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
10265 DefaultScreen (dpyinfo->display));
10266 select_visual (dpyinfo);
10267 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
10268 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
10269 dpyinfo->client_leader_window = 0;
10270 dpyinfo->grabbed = 0;
10271 dpyinfo->reference_count = 0;
10272 dpyinfo->icon_bitmap_id = -1;
10273 dpyinfo->n_fonts = 0;
10274 dpyinfo->bitmaps = 0;
10275 dpyinfo->bitmaps_size = 0;
10276 dpyinfo->bitmaps_last = 0;
10277 dpyinfo->scratch_cursor_gc = 0;
10278 hlinfo->mouse_face_mouse_frame = 0;
10279 hlinfo->mouse_face_deferred_gc = 0;
10280 hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
10281 hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
10282 hlinfo->mouse_face_face_id = DEFAULT_FACE_ID;
10283 hlinfo->mouse_face_window = Qnil;
10284 hlinfo->mouse_face_overlay = Qnil;
10285 hlinfo->mouse_face_mouse_x = hlinfo->mouse_face_mouse_y = 0;
10286 hlinfo->mouse_face_defer = 0;
10287 hlinfo->mouse_face_hidden = 0;
10288 dpyinfo->x_focus_frame = 0;
10289 dpyinfo->x_focus_event_frame = 0;
10290 dpyinfo->x_highlight_frame = 0;
10291 dpyinfo->wm_type = X_WMTYPE_UNKNOWN;
10293 /* See if we can construct pixel values from RGB values. */
10294 dpyinfo->red_bits = dpyinfo->blue_bits = dpyinfo->green_bits = 0;
10295 dpyinfo->red_offset = dpyinfo->blue_offset = dpyinfo->green_offset = 0;
10297 if (dpyinfo->visual->class == TrueColor)
10299 get_bits_and_offset (dpyinfo->visual->red_mask,
10300 &dpyinfo->red_bits, &dpyinfo->red_offset);
10301 get_bits_and_offset (dpyinfo->visual->blue_mask,
10302 &dpyinfo->blue_bits, &dpyinfo->blue_offset);
10303 get_bits_and_offset (dpyinfo->visual->green_mask,
10304 &dpyinfo->green_bits, &dpyinfo->green_offset);
10307 /* See if a private colormap is requested. */
10308 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
10310 if (dpyinfo->visual->class == PseudoColor)
10312 Lisp_Object value;
10313 value = display_x_get_resource (dpyinfo,
10314 build_string ("privateColormap"),
10315 build_string ("PrivateColormap"),
10316 Qnil, Qnil);
10317 if (STRINGP (value)
10318 && (!strcmp (SSDATA (value), "true")
10319 || !strcmp (SSDATA (value), "on")))
10320 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
10323 else
10324 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
10325 dpyinfo->visual, AllocNone);
10327 #ifdef HAVE_XFT
10329 /* If we are using Xft, check dpi value in X resources.
10330 It is better we use it as well, since Xft will use it, as will all
10331 Gnome applications. If our real DPI is smaller or larger than the
10332 one Xft uses, our font will look smaller or larger than other
10333 for other applications, even if it is the same font name (monospace-10
10334 for example). */
10335 char *v = XGetDefault (dpyinfo->display, "Xft", "dpi");
10336 double d;
10337 if (v != NULL && sscanf (v, "%lf", &d) == 1)
10338 dpyinfo->resy = dpyinfo->resx = d;
10340 #endif
10342 if (dpyinfo->resy < 1)
10344 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
10345 double pixels = DisplayHeight (dpyinfo->display, screen_number);
10346 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
10347 /* Mac OS X 10.3's Xserver sometimes reports 0.0mm. */
10348 dpyinfo->resy = (mm < 1) ? 100 : pixels * 25.4 / mm;
10349 pixels = DisplayWidth (dpyinfo->display, screen_number);
10350 mm = DisplayWidthMM (dpyinfo->display, screen_number);
10351 /* Mac OS X 10.3's Xserver sometimes reports 0.0mm. */
10352 dpyinfo->resx = (mm < 1) ? 100 : pixels * 25.4 / mm;
10356 const struct
10358 const char *name;
10359 Atom *atom;
10360 } atom_refs[] = {
10361 { "WM_PROTOCOLS", &dpyinfo->Xatom_wm_protocols },
10362 { "WM_TAKE_FOCUS", &dpyinfo->Xatom_wm_take_focus },
10363 { "WM_SAVE_YOURSELF", &dpyinfo->Xatom_wm_save_yourself },
10364 { "WM_DELETE_WINDOW", &dpyinfo->Xatom_wm_delete_window },
10365 { "WM_CHANGE_STATE", &dpyinfo->Xatom_wm_change_state },
10366 { "WM_CONFIGURE_DENIED", &dpyinfo->Xatom_wm_configure_denied },
10367 { "WM_MOVED", &dpyinfo->Xatom_wm_window_moved },
10368 { "WM_CLIENT_LEADER", &dpyinfo->Xatom_wm_client_leader },
10369 { "Editres", &dpyinfo->Xatom_editres },
10370 { "CLIPBOARD", &dpyinfo->Xatom_CLIPBOARD },
10371 { "TIMESTAMP", &dpyinfo->Xatom_TIMESTAMP },
10372 { "TEXT", &dpyinfo->Xatom_TEXT },
10373 { "COMPOUND_TEXT", &dpyinfo->Xatom_COMPOUND_TEXT },
10374 { "UTF8_STRING", &dpyinfo->Xatom_UTF8_STRING },
10375 { "DELETE", &dpyinfo->Xatom_DELETE },
10376 { "MULTIPLE", &dpyinfo->Xatom_MULTIPLE },
10377 { "INCR", &dpyinfo->Xatom_INCR },
10378 { "_EMACS_TMP_", &dpyinfo->Xatom_EMACS_TMP },
10379 { "TARGETS", &dpyinfo->Xatom_TARGETS },
10380 { "NULL", &dpyinfo->Xatom_NULL },
10381 { "ATOM", &dpyinfo->Xatom_ATOM },
10382 { "ATOM_PAIR", &dpyinfo->Xatom_ATOM_PAIR },
10383 { "CLIPBOARD_MANAGER", &dpyinfo->Xatom_CLIPBOARD_MANAGER },
10384 { "_XEMBED_INFO", &dpyinfo->Xatom_XEMBED_INFO },
10385 /* For properties of font. */
10386 { "PIXEL_SIZE", &dpyinfo->Xatom_PIXEL_SIZE },
10387 { "AVERAGE_WIDTH", &dpyinfo->Xatom_AVERAGE_WIDTH },
10388 { "_MULE_BASELINE_OFFSET", &dpyinfo->Xatom_MULE_BASELINE_OFFSET },
10389 { "_MULE_RELATIVE_COMPOSE", &dpyinfo->Xatom_MULE_RELATIVE_COMPOSE },
10390 { "_MULE_DEFAULT_ASCENT", &dpyinfo->Xatom_MULE_DEFAULT_ASCENT },
10391 /* Ghostscript support. */
10392 { "DONE", &dpyinfo->Xatom_DONE },
10393 { "PAGE", &dpyinfo->Xatom_PAGE },
10394 { "SCROLLBAR", &dpyinfo->Xatom_Scrollbar },
10395 { "_XEMBED", &dpyinfo->Xatom_XEMBED },
10396 /* EWMH */
10397 { "_NET_WM_STATE", &dpyinfo->Xatom_net_wm_state },
10398 { "_NET_WM_STATE_FULLSCREEN", &dpyinfo->Xatom_net_wm_state_fullscreen },
10399 { "_NET_WM_STATE_MAXIMIZED_HORZ",
10400 &dpyinfo->Xatom_net_wm_state_maximized_horz },
10401 { "_NET_WM_STATE_MAXIMIZED_VERT",
10402 &dpyinfo->Xatom_net_wm_state_maximized_vert },
10403 { "_NET_WM_STATE_STICKY", &dpyinfo->Xatom_net_wm_state_sticky },
10404 { "_NET_WM_STATE_HIDDEN", &dpyinfo->Xatom_net_wm_state_hidden },
10405 { "_NET_WM_WINDOW_TYPE", &dpyinfo->Xatom_net_window_type },
10406 { "_NET_WM_WINDOW_TYPE_TOOLTIP",
10407 &dpyinfo->Xatom_net_window_type_tooltip },
10408 { "_NET_WM_ICON_NAME", &dpyinfo->Xatom_net_wm_icon_name },
10409 { "_NET_WM_NAME", &dpyinfo->Xatom_net_wm_name },
10410 { "_NET_SUPPORTED", &dpyinfo->Xatom_net_supported },
10411 { "_NET_SUPPORTING_WM_CHECK", &dpyinfo->Xatom_net_supporting_wm_check },
10412 { "_NET_WM_WINDOW_OPACITY", &dpyinfo->Xatom_net_wm_window_opacity },
10413 { "_NET_ACTIVE_WINDOW", &dpyinfo->Xatom_net_active_window },
10414 { "_NET_FRAME_EXTENTS", &dpyinfo->Xatom_net_frame_extents },
10415 /* Session management */
10416 { "SM_CLIENT_ID", &dpyinfo->Xatom_SM_CLIENT_ID },
10417 { "_XSETTINGS_SETTINGS", &dpyinfo->Xatom_xsettings_prop },
10418 { "MANAGER", &dpyinfo->Xatom_xsettings_mgr },
10421 int i;
10422 const int atom_count = sizeof (atom_refs) / sizeof (atom_refs[0]);
10423 /* 1 for _XSETTINGS_SN */
10424 const int total_atom_count = 1 + atom_count;
10425 Atom *atoms_return = xmalloc (sizeof (Atom) * total_atom_count);
10426 char **atom_names = xmalloc (sizeof (char *) * total_atom_count);
10427 char xsettings_atom_name[64];
10429 for (i = 0; i < atom_count; i++)
10430 atom_names[i] = (char *) atom_refs[i].name;
10432 /* Build _XSETTINGS_SN atom name */
10433 snprintf (xsettings_atom_name, sizeof (xsettings_atom_name),
10434 "_XSETTINGS_S%d", XScreenNumberOfScreen (dpyinfo->screen));
10435 atom_names[i] = xsettings_atom_name;
10437 XInternAtoms (dpyinfo->display, atom_names, total_atom_count,
10438 False, atoms_return);
10440 for (i = 0; i < atom_count; i++)
10441 *atom_refs[i].atom = atoms_return[i];
10443 /* Manual copy of last atom */
10444 dpyinfo->Xatom_xsettings_sel = atoms_return[i];
10446 xfree (atom_names);
10447 xfree (atoms_return);
10450 dpyinfo->x_dnd_atoms_size = 8;
10451 dpyinfo->x_dnd_atoms_length = 0;
10452 dpyinfo->x_dnd_atoms = xmalloc (sizeof (*dpyinfo->x_dnd_atoms)
10453 * dpyinfo->x_dnd_atoms_size);
10455 dpyinfo->net_supported_atoms = NULL;
10456 dpyinfo->nr_net_supported_atoms = 0;
10457 dpyinfo->net_supported_window = 0;
10459 connection = ConnectionNumber (dpyinfo->display);
10460 dpyinfo->connection = connection;
10463 dpyinfo->gray
10464 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
10465 gray_bits, gray_width, gray_height,
10466 1, 0, 1);
10469 #ifdef HAVE_X_I18N
10470 xim_initialize (dpyinfo, resource_name);
10471 #endif
10473 xsettings_initialize (dpyinfo);
10475 /* This is only needed for distinguishing keyboard and process input. */
10476 if (connection != 0)
10477 add_keyboard_wait_descriptor (connection);
10479 #ifdef F_SETOWN
10480 fcntl (connection, F_SETOWN, getpid ());
10481 #endif /* ! defined (F_SETOWN) */
10483 #ifdef SIGIO
10484 if (interrupt_input)
10485 init_sigio (connection);
10486 #endif /* ! defined (SIGIO) */
10488 #ifdef USE_LUCID
10490 XrmValue d, fr, to;
10491 Font font;
10493 dpy = dpyinfo->display;
10494 d.addr = (XPointer)&dpy;
10495 d.size = sizeof (Display *);
10496 fr.addr = XtDefaultFont;
10497 fr.size = sizeof (XtDefaultFont);
10498 to.size = sizeof (Font *);
10499 to.addr = (XPointer)&font;
10500 x_catch_errors (dpy);
10501 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
10502 abort ();
10503 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
10504 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
10505 x_uncatch_errors ();
10507 #endif
10509 /* See if we should run in synchronous mode. This is useful
10510 for debugging X code. */
10512 Lisp_Object value;
10513 value = display_x_get_resource (dpyinfo,
10514 build_string ("synchronous"),
10515 build_string ("Synchronous"),
10516 Qnil, Qnil);
10517 if (STRINGP (value)
10518 && (!strcmp (SSDATA (value), "true")
10519 || !strcmp (SSDATA (value), "on")))
10520 XSynchronize (dpyinfo->display, True);
10524 Lisp_Object value;
10525 value = display_x_get_resource (dpyinfo,
10526 build_string ("useXIM"),
10527 build_string ("UseXIM"),
10528 Qnil, Qnil);
10529 #ifdef USE_XIM
10530 if (STRINGP (value)
10531 && (!strcmp (SSDATA (value), "false")
10532 || !strcmp (SSDATA (value), "off")))
10533 use_xim = 0;
10534 #else
10535 if (STRINGP (value)
10536 && (!strcmp (SSDATA (value), "true")
10537 || !strcmp (SSDATA (value), "on")))
10538 use_xim = 1;
10539 #endif
10542 #ifdef HAVE_X_SM
10543 /* Only do this for the very first display in the Emacs session.
10544 Ignore X session management when Emacs was first started on a
10545 tty. */
10546 if (terminal->id == 1)
10547 x_session_initialize (dpyinfo);
10548 #endif
10550 UNBLOCK_INPUT;
10552 return dpyinfo;
10555 /* Get rid of display DPYINFO, deleting all frames on it,
10556 and without sending any more commands to the X server. */
10558 static void
10559 x_delete_display (struct x_display_info *dpyinfo)
10561 struct terminal *t;
10563 /* Close all frames and delete the generic struct terminal for this
10564 X display. */
10565 for (t = terminal_list; t; t = t->next_terminal)
10566 if (t->type == output_x_window && t->display_info.x == dpyinfo)
10568 #ifdef HAVE_X_SM
10569 /* Close X session management when we close its display. */
10570 if (t->id == 1 && x_session_have_connection ())
10571 x_session_close ();
10572 #endif
10573 delete_terminal (t);
10574 break;
10577 delete_keyboard_wait_descriptor (dpyinfo->connection);
10579 /* Discard this display from x_display_name_list and x_display_list.
10580 We can't use Fdelq because that can quit. */
10581 if (! NILP (x_display_name_list)
10582 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
10583 x_display_name_list = XCDR (x_display_name_list);
10584 else
10586 Lisp_Object tail;
10588 tail = x_display_name_list;
10589 while (CONSP (tail) && CONSP (XCDR (tail)))
10591 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
10593 XSETCDR (tail, XCDR (XCDR (tail)));
10594 break;
10596 tail = XCDR (tail);
10600 if (next_noop_dpyinfo == dpyinfo)
10601 next_noop_dpyinfo = dpyinfo->next;
10603 if (x_display_list == dpyinfo)
10604 x_display_list = dpyinfo->next;
10605 else
10607 struct x_display_info *tail;
10609 for (tail = x_display_list; tail; tail = tail->next)
10610 if (tail->next == dpyinfo)
10611 tail->next = tail->next->next;
10614 xfree (dpyinfo->x_id_name);
10615 xfree (dpyinfo->x_dnd_atoms);
10616 xfree (dpyinfo->color_cells);
10617 xfree (dpyinfo);
10620 #ifdef USE_X_TOOLKIT
10622 /* Atimer callback function for TIMER. Called every 0.1s to process
10623 Xt timeouts, if needed. We must avoid calling XtAppPending as
10624 much as possible because that function does an implicit XFlush
10625 that slows us down. */
10627 static void
10628 x_process_timeouts (struct atimer *timer)
10630 BLOCK_INPUT;
10631 x_timeout_atimer_activated_flag = 0;
10632 if (toolkit_scroll_bar_interaction || popup_activated ())
10634 while (XtAppPending (Xt_app_con) & XtIMTimer)
10635 XtAppProcessEvent (Xt_app_con, XtIMTimer);
10636 /* Reactivate the atimer for next time. */
10637 x_activate_timeout_atimer ();
10639 UNBLOCK_INPUT;
10642 /* Install an asynchronous timer that processes Xt timeout events
10643 every 0.1s as long as either `toolkit_scroll_bar_interaction' or
10644 `popup_activated_flag' (in xmenu.c) is set. Make sure to call this
10645 function whenever these variables are set. This is necessary
10646 because some widget sets use timeouts internally, for example the
10647 LessTif menu bar, or the Xaw3d scroll bar. When Xt timeouts aren't
10648 processed, these widgets don't behave normally. */
10650 void
10651 x_activate_timeout_atimer (void)
10653 BLOCK_INPUT;
10654 if (!x_timeout_atimer_activated_flag)
10656 EMACS_TIME interval;
10658 EMACS_SET_SECS_USECS (interval, 0, 100000);
10659 start_atimer (ATIMER_RELATIVE, interval, x_process_timeouts, 0);
10660 x_timeout_atimer_activated_flag = 1;
10662 UNBLOCK_INPUT;
10665 #endif /* USE_X_TOOLKIT */
10668 /* Set up use of X before we make the first connection. */
10670 extern frame_parm_handler x_frame_parm_handlers[];
10672 static struct redisplay_interface x_redisplay_interface =
10674 x_frame_parm_handlers,
10675 x_produce_glyphs,
10676 x_write_glyphs,
10677 x_insert_glyphs,
10678 x_clear_end_of_line,
10679 x_scroll_run,
10680 x_after_update_window_line,
10681 x_update_window_begin,
10682 x_update_window_end,
10683 x_cursor_to,
10684 x_flush,
10685 #ifdef XFlush
10686 x_flush,
10687 #else
10688 0, /* flush_display_optional */
10689 #endif
10690 x_clear_window_mouse_face,
10691 x_get_glyph_overhangs,
10692 x_fix_overlapping_area,
10693 x_draw_fringe_bitmap,
10694 0, /* define_fringe_bitmap */
10695 0, /* destroy_fringe_bitmap */
10696 x_compute_glyph_string_overhangs,
10697 x_draw_glyph_string,
10698 x_define_frame_cursor,
10699 x_clear_frame_area,
10700 x_draw_window_cursor,
10701 x_draw_vertical_window_border,
10702 x_shift_glyphs_for_insert
10706 /* This function is called when the last frame on a display is deleted. */
10707 void
10708 x_delete_terminal (struct terminal *terminal)
10710 struct x_display_info *dpyinfo = terminal->display_info.x;
10712 /* Protect against recursive calls. delete_frame in
10713 delete_terminal calls us back when it deletes our last frame. */
10714 if (!terminal->name)
10715 return;
10717 BLOCK_INPUT;
10718 #ifdef HAVE_X_I18N
10719 /* We must close our connection to the XIM server before closing the
10720 X display. */
10721 if (dpyinfo->xim)
10722 xim_close_dpy (dpyinfo);
10723 #endif
10725 /* If called from x_connection_closed, the display may already be closed
10726 and dpyinfo->display was set to 0 to indicate that. */
10727 if (dpyinfo->display)
10729 x_destroy_all_bitmaps (dpyinfo);
10730 XSetCloseDownMode (dpyinfo->display, DestroyAll);
10732 /* Whether or not XCloseDisplay destroys the associated resource
10733 database depends on the version of libX11. To avoid both
10734 crash and memory leak, we dissociate the database from the
10735 display and then destroy dpyinfo->xrdb ourselves.
10737 Unfortunately, the above strategy does not work in some
10738 situations due to a bug in newer versions of libX11: because
10739 XrmSetDatabase doesn't clear the flag XlibDisplayDfltRMDB if
10740 dpy->db is NULL, XCloseDisplay destroys the associated
10741 database whereas it has not been created by XGetDefault
10742 (Bug#21974 in freedesktop.org Bugzilla). As a workaround, we
10743 don't destroy the database here in order to avoid the crash
10744 in the above situations for now, though that may cause memory
10745 leaks in other situations. */
10746 #if 0
10747 #ifdef HAVE_XRMSETDATABASE
10748 XrmSetDatabase (dpyinfo->display, NULL);
10749 #else
10750 dpyinfo->display->db = NULL;
10751 #endif
10752 /* We used to call XrmDestroyDatabase from x_delete_display, but
10753 some older versions of libX11 crash if we call it after
10754 closing all the displays. */
10755 XrmDestroyDatabase (dpyinfo->xrdb);
10756 #endif
10758 #ifdef USE_GTK
10759 xg_display_close (dpyinfo->display);
10760 #else
10761 #ifdef USE_X_TOOLKIT
10762 XtCloseDisplay (dpyinfo->display);
10763 #else
10764 XCloseDisplay (dpyinfo->display);
10765 #endif
10766 #endif /* ! USE_GTK */
10769 /* Mark as dead. */
10770 dpyinfo->display = NULL;
10771 x_delete_display (dpyinfo);
10772 UNBLOCK_INPUT;
10775 /* Create a struct terminal, initialize it with the X11 specific
10776 functions and make DISPLAY->TERMINAL point to it. */
10778 static struct terminal *
10779 x_create_terminal (struct x_display_info *dpyinfo)
10781 struct terminal *terminal;
10783 terminal = create_terminal ();
10785 terminal->type = output_x_window;
10786 terminal->display_info.x = dpyinfo;
10787 dpyinfo->terminal = terminal;
10789 /* kboard is initialized in x_term_init. */
10791 terminal->clear_frame_hook = x_clear_frame;
10792 terminal->ins_del_lines_hook = x_ins_del_lines;
10793 terminal->delete_glyphs_hook = x_delete_glyphs;
10794 terminal->ring_bell_hook = XTring_bell;
10795 terminal->toggle_invisible_pointer_hook = XTtoggle_invisible_pointer;
10796 terminal->reset_terminal_modes_hook = XTreset_terminal_modes;
10797 terminal->set_terminal_modes_hook = XTset_terminal_modes;
10798 terminal->update_begin_hook = x_update_begin;
10799 terminal->update_end_hook = x_update_end;
10800 terminal->set_terminal_window_hook = XTset_terminal_window;
10801 terminal->read_socket_hook = XTread_socket;
10802 terminal->frame_up_to_date_hook = XTframe_up_to_date;
10803 terminal->mouse_position_hook = XTmouse_position;
10804 terminal->frame_rehighlight_hook = XTframe_rehighlight;
10805 terminal->frame_raise_lower_hook = XTframe_raise_lower;
10806 terminal->fullscreen_hook = XTfullscreen_hook;
10807 terminal->set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
10808 terminal->condemn_scroll_bars_hook = XTcondemn_scroll_bars;
10809 terminal->redeem_scroll_bar_hook = XTredeem_scroll_bar;
10810 terminal->judge_scroll_bars_hook = XTjudge_scroll_bars;
10812 terminal->delete_frame_hook = x_destroy_window;
10813 terminal->delete_terminal_hook = x_delete_terminal;
10815 terminal->rif = &x_redisplay_interface;
10816 terminal->scroll_region_ok = 1; /* We'll scroll partial frames. */
10817 terminal->char_ins_del_ok = 1;
10818 terminal->line_ins_del_ok = 1; /* We'll just blt 'em. */
10819 terminal->fast_clear_end_of_line = 1; /* X does this well. */
10820 terminal->memory_below_frame = 0; /* We don't remember what scrolls
10821 off the bottom. */
10823 return terminal;
10826 void
10827 x_initialize (void)
10829 baud_rate = 19200;
10831 x_noop_count = 0;
10832 last_tool_bar_item = -1;
10833 any_help_event_p = 0;
10834 ignore_next_mouse_click_timeout = 0;
10836 #ifdef USE_GTK
10837 current_count = -1;
10838 #endif
10840 /* Try to use interrupt input; if we can't, then start polling. */
10841 Fset_input_interrupt_mode (Qt);
10843 #ifdef USE_X_TOOLKIT
10844 XtToolkitInitialize ();
10846 Xt_app_con = XtCreateApplicationContext ();
10848 /* Register a converter from strings to pixels, which uses
10849 Emacs' color allocation infrastructure. */
10850 XtAppSetTypeConverter (Xt_app_con,
10851 XtRString, XtRPixel, cvt_string_to_pixel,
10852 cvt_string_to_pixel_args,
10853 XtNumber (cvt_string_to_pixel_args),
10854 XtCacheByDisplay, cvt_pixel_dtor);
10856 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
10857 #endif
10859 #ifdef USE_TOOLKIT_SCROLL_BARS
10860 #ifndef USE_GTK
10861 xaw3d_arrow_scroll = False;
10862 xaw3d_pick_top = True;
10863 #endif
10864 #endif
10866 pending_autoraise_frame = 0;
10867 pending_event_wait.f = 0;
10868 pending_event_wait.eventtype = 0;
10870 /* Note that there is no real way portable across R3/R4 to get the
10871 original error handler. */
10872 XSetErrorHandler (x_error_handler);
10873 XSetIOErrorHandler (x_io_error_quitter);
10875 signal (SIGPIPE, x_connection_signal);
10877 xgselect_initialize ();
10881 void
10882 syms_of_xterm (void)
10884 x_error_message = NULL;
10886 staticpro (&x_display_name_list);
10887 x_display_name_list = Qnil;
10889 staticpro (&last_mouse_scroll_bar);
10890 last_mouse_scroll_bar = Qnil;
10892 DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms");
10893 DEFSYM (Qlatin_1, "latin-1");
10895 staticpro (&last_mouse_press_frame);
10896 last_mouse_press_frame = Qnil;
10898 #ifdef USE_GTK
10899 xg_default_icon_file = make_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg");
10900 staticpro (&xg_default_icon_file);
10902 DEFSYM (Qx_gtk_map_stock, "x-gtk-map-stock");
10903 #endif
10905 DEFVAR_BOOL ("x-use-underline-position-properties",
10906 x_use_underline_position_properties,
10907 doc: /* Non-nil means make use of UNDERLINE_POSITION font properties.
10908 A value of nil means ignore them. If you encounter fonts with bogus
10909 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
10910 to 4.1, set this to nil. You can also use `underline-minimum-offset'
10911 to override the font's UNDERLINE_POSITION for small font display
10912 sizes. */);
10913 x_use_underline_position_properties = 1;
10915 DEFVAR_BOOL ("x-underline-at-descent-line",
10916 x_underline_at_descent_line,
10917 doc: /* Non-nil means to draw the underline at the same place as the descent line.
10918 A value of nil means to draw the underline according to the value of the
10919 variable `x-use-underline-position-properties', which is usually at the
10920 baseline level. The default value is nil. */);
10921 x_underline_at_descent_line = 0;
10923 DEFVAR_BOOL ("x-mouse-click-focus-ignore-position",
10924 x_mouse_click_focus_ignore_position,
10925 doc: /* Non-nil means that a mouse click to focus a frame does not move point.
10926 This variable is only used when the window manager requires that you
10927 click on a frame to select it (give it focus). In that case, a value
10928 of nil, means that the selected window and cursor position changes to
10929 reflect the mouse click position, while a non-nil value means that the
10930 selected window or cursor position is preserved. */);
10931 x_mouse_click_focus_ignore_position = 0;
10933 DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
10934 doc: /* Which toolkit scroll bars Emacs uses, if any.
10935 A value of nil means Emacs doesn't use toolkit scroll bars.
10936 With the X Window system, the value is a symbol describing the
10937 X toolkit. Possible values are: gtk, motif, xaw, or xaw3d.
10938 With MS Windows or Nextstep, the value is t. */);
10939 #ifdef USE_TOOLKIT_SCROLL_BARS
10940 #ifdef USE_MOTIF
10941 Vx_toolkit_scroll_bars = intern_c_string ("motif");
10942 #elif defined HAVE_XAW3D
10943 Vx_toolkit_scroll_bars = intern_c_string ("xaw3d");
10944 #elif USE_GTK
10945 Vx_toolkit_scroll_bars = intern_c_string ("gtk");
10946 #else
10947 Vx_toolkit_scroll_bars = intern_c_string ("xaw");
10948 #endif
10949 #else
10950 Vx_toolkit_scroll_bars = Qnil;
10951 #endif
10953 staticpro (&last_mouse_motion_frame);
10954 last_mouse_motion_frame = Qnil;
10956 Qmodifier_value = intern_c_string ("modifier-value");
10957 Qalt = intern_c_string ("alt");
10958 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
10959 Qhyper = intern_c_string ("hyper");
10960 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
10961 Qmeta = intern_c_string ("meta");
10962 Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
10963 Qsuper = intern_c_string ("super");
10964 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
10966 DEFVAR_LISP ("x-alt-keysym", Vx_alt_keysym,
10967 doc: /* Which keys Emacs uses for the alt modifier.
10968 This should be one of the symbols `alt', `hyper', `meta', `super'.
10969 For example, `alt' means use the Alt_L and Alt_R keysyms. The default
10970 is nil, which is the same as `alt'. */);
10971 Vx_alt_keysym = Qnil;
10973 DEFVAR_LISP ("x-hyper-keysym", Vx_hyper_keysym,
10974 doc: /* Which keys Emacs uses for the hyper modifier.
10975 This should be one of the symbols `alt', `hyper', `meta', `super'.
10976 For example, `hyper' means use the Hyper_L and Hyper_R keysyms. The
10977 default is nil, which is the same as `hyper'. */);
10978 Vx_hyper_keysym = Qnil;
10980 DEFVAR_LISP ("x-meta-keysym", Vx_meta_keysym,
10981 doc: /* Which keys Emacs uses for the meta modifier.
10982 This should be one of the symbols `alt', `hyper', `meta', `super'.
10983 For example, `meta' means use the Meta_L and Meta_R keysyms. The
10984 default is nil, which is the same as `meta'. */);
10985 Vx_meta_keysym = Qnil;
10987 DEFVAR_LISP ("x-super-keysym", Vx_super_keysym,
10988 doc: /* Which keys Emacs uses for the super modifier.
10989 This should be one of the symbols `alt', `hyper', `meta', `super'.
10990 For example, `super' means use the Super_L and Super_R keysyms. The
10991 default is nil, which is the same as `super'. */);
10992 Vx_super_keysym = Qnil;
10994 DEFVAR_LISP ("x-keysym-table", Vx_keysym_table,
10995 doc: /* Hash table of character codes indexed by X keysym codes. */);
10996 Vx_keysym_table = make_hash_table (Qeql, make_number (900),
10997 make_float (DEFAULT_REHASH_SIZE),
10998 make_float (DEFAULT_REHASH_THRESHOLD),
10999 Qnil, Qnil, Qnil);
11002 #endif /* HAVE_X_WINDOWS */