Convert (most) functions in src to standard C.
[bpt/emacs.git] / src / xterm.c
1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
3 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
4 Free Software Foundation, Inc.
5
6 This file is part of GNU Emacs.
7
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20
21 /* New display code by Gerd Moellmann <gerd@gnu.org>. */
22 /* Xt features made by Fred Pierresteguy. */
23
24 #include <config.h>
25
26 /* On 4.3 these lose if they come after xterm.h. */
27 /* Putting these at the beginning seems to be standard for other .c files. */
28 #include <signal.h>
29
30 #include <stdio.h>
31 #include <setjmp.h>
32
33 #ifdef HAVE_X_WINDOWS
34
35 #include "lisp.h"
36 #include "blockinput.h"
37
38 /* Need syssignal.h for various externs and definitions that may be required
39 by some configurations for calls to signal later in this source file. */
40 #include "syssignal.h"
41
42 /* This may include sys/types.h, and that somehow loses
43 if this is not done before the other system files. */
44 #include "xterm.h"
45 #include <X11/cursorfont.h>
46
47 /* Load sys/types.h if not already loaded.
48 In some systems loading it twice is suicidal. */
49 #ifndef makedev
50 #include <sys/types.h>
51 #endif /* makedev */
52
53 #ifdef HAVE_SYS_IOCTL_H
54 #include <sys/ioctl.h>
55 #endif /* ! defined (HAVE_SYS_IOCTL_H) */
56
57 #include "systime.h"
58
59 #include <fcntl.h>
60 #include <ctype.h>
61 #include <errno.h>
62 #include <setjmp.h>
63 #include <sys/stat.h>
64 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
65 /* #include <sys/param.h> */
66
67 #include "charset.h"
68 #include "character.h"
69 #include "coding.h"
70 #include "frame.h"
71 #include "dispextern.h"
72 #include "fontset.h"
73 #include "termhooks.h"
74 #include "termopts.h"
75 #include "termchar.h"
76 #include "emacs-icon.h"
77 #include "disptab.h"
78 #include "buffer.h"
79 #include "window.h"
80 #include "keyboard.h"
81 #include "intervals.h"
82 #include "process.h"
83 #include "atimer.h"
84 #include "keymap.h"
85 #include "font.h"
86 #include "fontset.h"
87 #include "xsettings.h"
88 #include "xgselect.h"
89 #include "sysselect.h"
90
91 #ifdef USE_X_TOOLKIT
92 #include <X11/Shell.h>
93 #endif
94
95 #ifdef HAVE_SYS_TIME_H
96 #include <sys/time.h>
97 #endif
98 #ifdef HAVE_UNISTD_H
99 #include <unistd.h>
100 #endif
101
102 #ifdef USE_GTK
103 #include "gtkutil.h"
104 #endif
105
106 #ifdef USE_LUCID
107 extern int xlwmenu_window_p (Widget w, Window window);
108 extern void xlwmenu_redisplay (Widget);
109 #endif
110
111 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
112
113 extern void free_frame_menubar (struct frame *);
114 #endif
115
116 #ifdef USE_X_TOOLKIT
117 #if !defined(NO_EDITRES)
118 #define HACK_EDITRES
119 extern void _XEditResCheckMessages ();
120 #endif /* not NO_EDITRES */
121
122 /* Include toolkit specific headers for the scroll bar widget. */
123
124 #ifdef USE_TOOLKIT_SCROLL_BARS
125 #if defined USE_MOTIF
126 #include <Xm/Xm.h> /* for LESSTIF_VERSION */
127 #include <Xm/ScrollBar.h>
128 #else /* !USE_MOTIF i.e. use Xaw */
129
130 #ifdef HAVE_XAW3D
131 #include <X11/Xaw3d/Simple.h>
132 #include <X11/Xaw3d/Scrollbar.h>
133 #include <X11/Xaw3d/ThreeD.h>
134 #else /* !HAVE_XAW3D */
135 #include <X11/Xaw/Simple.h>
136 #include <X11/Xaw/Scrollbar.h>
137 #endif /* !HAVE_XAW3D */
138 #ifndef XtNpickTop
139 #define XtNpickTop "pickTop"
140 #endif /* !XtNpickTop */
141 #endif /* !USE_MOTIF */
142 #endif /* USE_TOOLKIT_SCROLL_BARS */
143
144 #endif /* USE_X_TOOLKIT */
145
146 #ifdef USE_X_TOOLKIT
147 #include "widget.h"
148 #ifndef XtNinitialState
149 #define XtNinitialState "initialState"
150 #endif
151 #endif
152
153 /* Default to using XIM if available. */
154 #ifdef USE_XIM
155 int use_xim = 1;
156 #else
157 int use_xim = 0; /* configure --without-xim */
158 #endif
159
160 \f
161
162 /* Non-nil means Emacs uses toolkit scroll bars. */
163
164 Lisp_Object Vx_toolkit_scroll_bars;
165
166 /* Non-zero means that a HELP_EVENT has been generated since Emacs
167 start. */
168
169 static int any_help_event_p;
170
171 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
172 static Lisp_Object last_window;
173
174 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
175
176 int x_use_underline_position_properties;
177
178 /* Non-zero means to draw the underline at the same place as the descent line. */
179
180 int x_underline_at_descent_line;
181
182 /* This is a chain of structures for all the X displays currently in
183 use. */
184
185 struct x_display_info *x_display_list;
186
187 /* This is a list of cons cells, each of the form (NAME
188 . FONT-LIST-CACHE), one for each element of x_display_list and in
189 the same order. NAME is the name of the frame. FONT-LIST-CACHE
190 records previous values returned by x-list-fonts. */
191
192 Lisp_Object x_display_name_list;
193
194 /* Frame being updated by update_frame. This is declared in term.c.
195 This is set by update_begin and looked at by all the XT functions.
196 It is zero while not inside an update. In that case, the XT
197 functions assume that `selected_frame' is the frame to apply to. */
198
199 extern struct frame *updating_frame;
200
201 /* This is a frame waiting to be auto-raised, within XTread_socket. */
202
203 static struct frame *pending_autoraise_frame;
204
205 /* This is a frame waiting for an event matching mask, within XTread_socket. */
206
207 static struct {
208 struct frame *f;
209 int eventtype;
210 } pending_event_wait;
211
212 #ifdef USE_X_TOOLKIT
213 /* The application context for Xt use. */
214 XtAppContext Xt_app_con;
215 static String Xt_default_resources[] = {0};
216 #endif /* USE_X_TOOLKIT */
217
218 /* Non-zero means user is interacting with a toolkit scroll bar. */
219
220 static int toolkit_scroll_bar_interaction;
221
222 /* Non-zero means to not move point as a result of clicking on a
223 frame to focus it (when focus-follows-mouse is nil). */
224
225 int x_mouse_click_focus_ignore_position;
226
227 /* Non-zero timeout value means ignore next mouse click if it arrives
228 before that timeout elapses (i.e. as part of the same sequence of
229 events resulting from clicking on a frame to select it). */
230
231 static unsigned long ignore_next_mouse_click_timeout;
232
233 /* Mouse movement.
234
235 Formerly, we used PointerMotionHintMask (in standard_event_mask)
236 so that we would have to call XQueryPointer after each MotionNotify
237 event to ask for another such event. However, this made mouse tracking
238 slow, and there was a bug that made it eventually stop.
239
240 Simply asking for MotionNotify all the time seems to work better.
241
242 In order to avoid asking for motion events and then throwing most
243 of them away or busy-polling the server for mouse positions, we ask
244 the server for pointer motion hints. This means that we get only
245 one event per group of mouse movements. "Groups" are delimited by
246 other kinds of events (focus changes and button clicks, for
247 example), or by XQueryPointer calls; when one of these happens, we
248 get another MotionNotify event the next time the mouse moves. This
249 is at least as efficient as getting motion events when mouse
250 tracking is on, and I suspect only negligibly worse when tracking
251 is off. */
252
253 /* Where the mouse was last time we reported a mouse event. */
254
255 static XRectangle last_mouse_glyph;
256 static FRAME_PTR last_mouse_glyph_frame;
257 static Lisp_Object last_mouse_press_frame;
258
259 /* The scroll bar in which the last X motion event occurred.
260
261 If the last X motion event occurred in a scroll bar, we set this so
262 XTmouse_position can know whether to report a scroll bar motion or
263 an ordinary motion.
264
265 If the last X motion event didn't occur in a scroll bar, we set
266 this to Qnil, to tell XTmouse_position to return an ordinary motion
267 event. */
268
269 static Lisp_Object last_mouse_scroll_bar;
270
271 /* This is a hack. We would really prefer that XTmouse_position would
272 return the time associated with the position it returns, but there
273 doesn't seem to be any way to wrest the time-stamp from the server
274 along with the position query. So, we just keep track of the time
275 of the last movement we received, and return that in hopes that
276 it's somewhat accurate. */
277
278 static Time last_mouse_movement_time;
279
280 /* Time for last user interaction as returned in X events. */
281
282 static Time last_user_time;
283
284 /* Incremented by XTread_socket whenever it really tries to read
285 events. */
286
287 #ifdef __STDC__
288 static int volatile input_signal_count;
289 #else
290 static int input_signal_count;
291 #endif
292
293 /* Used locally within XTread_socket. */
294
295 static int x_noop_count;
296
297 /* Initial values of argv and argc. */
298
299 extern char **initial_argv;
300 extern int initial_argc;
301
302 extern Lisp_Object Vcommand_line_args, Vsystem_name;
303
304 /* Tells if a window manager is present or not. */
305
306 extern Lisp_Object Vx_no_window_manager;
307
308 extern Lisp_Object Qeql;
309
310 /* A mask of extra modifier bits to put into every keyboard char. */
311
312 extern EMACS_INT extra_keyboard_modifiers;
313
314 /* The keysyms to use for the various modifiers. */
315
316 Lisp_Object Vx_alt_keysym, Vx_hyper_keysym, Vx_meta_keysym, Vx_super_keysym;
317 Lisp_Object Vx_keysym_table;
318 static Lisp_Object Qalt, Qhyper, Qmeta, Qsuper, Qmodifier_value;
319
320 static Lisp_Object Qvendor_specific_keysyms;
321 static Lisp_Object Qlatin_1;
322
323 #ifdef USE_GTK
324 /* The name of the Emacs icon file. */
325 static Lisp_Object xg_default_icon_file;
326
327 /* Used in gtkutil.c. */
328 Lisp_Object Qx_gtk_map_stock;
329 #endif
330
331 /* Used in x_flush. */
332
333 extern Lisp_Object Vinhibit_redisplay;
334
335 extern XrmDatabase x_load_resources (Display *, char *, char *, char *);
336 extern int x_bitmap_mask (FRAME_PTR, int);
337
338 static int x_alloc_nearest_color_1 (Display *, Colormap, XColor *);
339 static void x_set_window_size_1 (struct frame *, int, int, int);
340 static const XColor *x_color_cells (Display *, int *);
341 static void x_update_window_end (struct window *, int, int);
342
343 static int x_io_error_quitter (Display *);
344 static struct terminal *x_create_terminal (struct x_display_info *);
345 void x_delete_terminal (struct terminal *);
346 static void x_update_end (struct frame *);
347 static void XTframe_up_to_date (struct frame *);
348 static void XTset_terminal_modes (struct terminal *);
349 static void XTreset_terminal_modes (struct terminal *);
350 static void x_clear_frame (struct frame *);
351 static void frame_highlight (struct frame *);
352 static void frame_unhighlight (struct frame *);
353 static void x_new_focus_frame (struct x_display_info *, struct frame *);
354 static void x_focus_changed (int, int, struct x_display_info *,
355 struct frame *, struct input_event *);
356 static void x_detect_focus_change (struct x_display_info *,
357 XEvent *, struct input_event *);
358 static void XTframe_rehighlight (struct frame *);
359 static void x_frame_rehighlight (struct x_display_info *);
360 static void x_draw_hollow_cursor (struct window *, struct glyph_row *);
361 static void x_draw_bar_cursor (struct window *, struct glyph_row *, int,
362 enum text_cursor_kinds);
363
364 static void x_clip_to_row (struct window *, struct glyph_row *, int, GC);
365 static void x_flush (struct frame *f);
366 static void x_update_begin (struct frame *);
367 static void x_update_window_begin (struct window *);
368 static void x_after_update_window_line (struct glyph_row *);
369 static struct scroll_bar *x_window_to_scroll_bar (Display *, Window);
370 static void x_scroll_bar_report_motion (struct frame **, Lisp_Object *,
371 enum scroll_bar_part *,
372 Lisp_Object *, Lisp_Object *,
373 unsigned long *);
374 static void x_handle_net_wm_state (struct frame *, XPropertyEvent *);
375 static void x_check_fullscreen (struct frame *);
376 static void x_check_expected_move (struct frame *, int, int);
377 static void x_sync_with_move (struct frame *, int, int, int);
378 static int handle_one_xevent (struct x_display_info *, XEvent *,
379 int *, struct input_event *);
380 /* Don't declare this NO_RETURN because we want no
381 interference with debugging failing X calls. */
382 static SIGTYPE x_connection_closed (Display *, char *);
383
384
385 /* Flush display of frame F, or of all frames if F is null. */
386
387 static void
388 x_flush (struct frame *f)
389 {
390 /* Don't call XFlush when it is not safe to redisplay; the X
391 connection may be broken. */
392 if (!NILP (Vinhibit_redisplay))
393 return;
394
395 BLOCK_INPUT;
396 if (f == NULL)
397 {
398 Lisp_Object rest, frame;
399 FOR_EACH_FRAME (rest, frame)
400 if (FRAME_X_P (XFRAME (frame)))
401 x_flush (XFRAME (frame));
402 }
403 else if (FRAME_X_P (f))
404 XFlush (FRAME_X_DISPLAY (f));
405 UNBLOCK_INPUT;
406 }
407
408
409 /* Remove calls to XFlush by defining XFlush to an empty replacement.
410 Calls to XFlush should be unnecessary because the X output buffer
411 is flushed automatically as needed by calls to XPending,
412 XNextEvent, or XWindowEvent according to the XFlush man page.
413 XTread_socket calls XPending. Removing XFlush improves
414 performance. */
415
416 #define XFlush(DISPLAY) (void) 0
417
418 \f
419 /***********************************************************************
420 Debugging
421 ***********************************************************************/
422
423 #if 0
424
425 /* This is a function useful for recording debugging information about
426 the sequence of occurrences in this file. */
427
428 struct record
429 {
430 char *locus;
431 int type;
432 };
433
434 struct record event_record[100];
435
436 int event_record_index;
437
438 record_event (locus, type)
439 char *locus;
440 int type;
441 {
442 if (event_record_index == sizeof (event_record) / sizeof (struct record))
443 event_record_index = 0;
444
445 event_record[event_record_index].locus = locus;
446 event_record[event_record_index].type = type;
447 event_record_index++;
448 }
449
450 #endif /* 0 */
451
452
453 \f
454 /* Return the struct x_display_info corresponding to DPY. */
455
456 struct x_display_info *
457 x_display_info_for_display (Display *dpy)
458 {
459 struct x_display_info *dpyinfo;
460
461 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
462 if (dpyinfo->display == dpy)
463 return dpyinfo;
464
465 return 0;
466 }
467
468 #define OPAQUE 0xffffffff
469 #define OPACITY "_NET_WM_WINDOW_OPACITY"
470
471 void
472 x_set_frame_alpha (struct frame *f)
473 {
474 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
475 Display *dpy = FRAME_X_DISPLAY (f);
476 Window win = FRAME_OUTER_WINDOW (f);
477 double alpha = 1.0;
478 double alpha_min = 1.0;
479 unsigned long opac;
480
481 if (FRAME_X_DISPLAY_INFO (f)->root_window != FRAME_X_OUTPUT (f)->parent_desc)
482 /* Since the WM decoration lies under the FRAME_OUTER_WINDOW,
483 we must treat the former instead of the latter. */
484 win = FRAME_X_OUTPUT(f)->parent_desc;
485
486 if (dpyinfo->x_highlight_frame == f)
487 alpha = f->alpha[0];
488 else
489 alpha = f->alpha[1];
490
491 if (FLOATP (Vframe_alpha_lower_limit))
492 alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit);
493 else if (INTEGERP (Vframe_alpha_lower_limit))
494 alpha_min = (XINT (Vframe_alpha_lower_limit)) / 100.0;
495
496 if (alpha < 0.0)
497 return;
498 else if (alpha > 1.0)
499 alpha = 1.0;
500 else if (0.0 <= alpha && alpha < alpha_min && alpha_min <= 1.0)
501 alpha = alpha_min;
502
503 opac = alpha * OPAQUE;
504
505 /* return unless necessary */
506 {
507 unsigned char *data;
508 Atom actual;
509 int rc, format;
510 unsigned long n, left;
511
512 x_catch_errors (dpy);
513 rc = XGetWindowProperty(dpy, win, XInternAtom(dpy, OPACITY, False),
514 0L, 1L, False, XA_CARDINAL,
515 &actual, &format, &n, &left,
516 &data);
517
518 if (rc == Success && actual != None)
519 if (*(unsigned long *)data == opac)
520 {
521 XFree ((void *) data);
522 x_uncatch_errors ();
523 return;
524 }
525 else
526 XFree ((void *) data);
527 x_uncatch_errors ();
528 }
529
530 x_catch_errors (dpy);
531 XChangeProperty (dpy, win, XInternAtom (dpy, OPACITY, False),
532 XA_CARDINAL, 32, PropModeReplace,
533 (unsigned char *) &opac, 1L);
534 x_uncatch_errors ();
535 }
536
537 int
538 x_display_pixel_height (struct x_display_info *dpyinfo)
539 {
540 return HeightOfScreen (dpyinfo->screen);
541 }
542
543 int
544 x_display_pixel_width (struct x_display_info *dpyinfo)
545 {
546 return WidthOfScreen (dpyinfo->screen);
547 }
548
549 \f
550 /***********************************************************************
551 Starting and ending an update
552 ***********************************************************************/
553
554 /* Start an update of frame F. This function is installed as a hook
555 for update_begin, i.e. it is called when update_begin is called.
556 This function is called prior to calls to x_update_window_begin for
557 each window being updated. Currently, there is nothing to do here
558 because all interesting stuff is done on a window basis. */
559
560 static void
561 x_update_begin (struct frame *f)
562 {
563 /* Nothing to do. */
564 }
565
566
567 /* Start update of window W. Set the global variable updated_window
568 to the window being updated and set output_cursor to the cursor
569 position of W. */
570
571 static void
572 x_update_window_begin (struct window *w)
573 {
574 struct frame *f = XFRAME (WINDOW_FRAME (w));
575 struct x_display_info *display_info = FRAME_X_DISPLAY_INFO (f);
576
577 updated_window = w;
578 set_output_cursor (&w->cursor);
579
580 BLOCK_INPUT;
581
582 if (f == display_info->mouse_face_mouse_frame)
583 {
584 /* Don't do highlighting for mouse motion during the update. */
585 display_info->mouse_face_defer = 1;
586
587 /* If F needs to be redrawn, simply forget about any prior mouse
588 highlighting. */
589 if (FRAME_GARBAGED_P (f))
590 display_info->mouse_face_window = Qnil;
591 }
592
593 UNBLOCK_INPUT;
594 }
595
596
597 /* Draw a vertical window border from (x,y0) to (x,y1) */
598
599 static void
600 x_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
601 {
602 struct frame *f = XFRAME (WINDOW_FRAME (w));
603 struct face *face;
604
605 face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
606 if (face)
607 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
608 face->foreground);
609
610 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
611 f->output_data.x->normal_gc, x, y0, x, y1);
612 }
613
614 /* End update of window W (which is equal to updated_window).
615
616 Draw vertical borders between horizontally adjacent windows, and
617 display W's cursor if CURSOR_ON_P is non-zero.
618
619 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
620 glyphs in mouse-face were overwritten. In that case we have to
621 make sure that the mouse-highlight is properly redrawn.
622
623 W may be a menu bar pseudo-window in case we don't have X toolkit
624 support. Such windows don't have a cursor, so don't display it
625 here. */
626
627 static void
628 x_update_window_end (struct window *w, int cursor_on_p, int mouse_face_overwritten_p)
629 {
630 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
631
632 if (!w->pseudo_window_p)
633 {
634 BLOCK_INPUT;
635
636 if (cursor_on_p)
637 display_and_set_cursor (w, 1, output_cursor.hpos,
638 output_cursor.vpos,
639 output_cursor.x, output_cursor.y);
640
641 if (draw_window_fringes (w, 1))
642 x_draw_vertical_border (w);
643
644 UNBLOCK_INPUT;
645 }
646
647 /* If a row with mouse-face was overwritten, arrange for
648 XTframe_up_to_date to redisplay the mouse highlight. */
649 if (mouse_face_overwritten_p)
650 {
651 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
652 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
653 dpyinfo->mouse_face_window = Qnil;
654 }
655
656 updated_window = NULL;
657 }
658
659
660 /* End update of frame F. This function is installed as a hook in
661 update_end. */
662
663 static void
664 x_update_end (struct frame *f)
665 {
666 /* Mouse highlight may be displayed again. */
667 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
668
669 #ifndef XFlush
670 BLOCK_INPUT;
671 XFlush (FRAME_X_DISPLAY (f));
672 UNBLOCK_INPUT;
673 #endif
674 }
675
676
677 /* This function is called from various places in xdisp.c whenever a
678 complete update has been performed. The global variable
679 updated_window is not available here. */
680
681 static void
682 XTframe_up_to_date (struct frame *f)
683 {
684 if (FRAME_X_P (f))
685 {
686 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
687
688 if (dpyinfo->mouse_face_deferred_gc
689 || f == dpyinfo->mouse_face_mouse_frame)
690 {
691 BLOCK_INPUT;
692 if (dpyinfo->mouse_face_mouse_frame)
693 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
694 dpyinfo->mouse_face_mouse_x,
695 dpyinfo->mouse_face_mouse_y);
696 dpyinfo->mouse_face_deferred_gc = 0;
697 UNBLOCK_INPUT;
698 }
699 }
700 }
701
702
703 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
704 arrow bitmaps, or clear the fringes if no bitmaps are required
705 before DESIRED_ROW is made current. The window being updated is
706 found in updated_window. This function It is called from
707 update_window_line only if it is known that there are differences
708 between bitmaps to be drawn between current row and DESIRED_ROW. */
709
710 static void
711 x_after_update_window_line (struct glyph_row *desired_row)
712 {
713 struct window *w = updated_window;
714 struct frame *f;
715 int width, height;
716
717 xassert (w);
718
719 if (!desired_row->mode_line_p && !w->pseudo_window_p)
720 desired_row->redraw_fringe_bitmaps_p = 1;
721
722 /* When a window has disappeared, make sure that no rest of
723 full-width rows stays visible in the internal border. Could
724 check here if updated_window is the leftmost/rightmost window,
725 but I guess it's not worth doing since vertically split windows
726 are almost never used, internal border is rarely set, and the
727 overhead is very small. */
728 if (windows_or_buffers_changed
729 && desired_row->full_width_p
730 && (f = XFRAME (w->frame),
731 width = FRAME_INTERNAL_BORDER_WIDTH (f),
732 width != 0)
733 && (height = desired_row->visible_height,
734 height > 0))
735 {
736 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
737
738 BLOCK_INPUT;
739 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
740 0, y, width, height, False);
741 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
742 FRAME_PIXEL_WIDTH (f) - width,
743 y, width, height, False);
744 UNBLOCK_INPUT;
745 }
746 }
747
748 static void
749 x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fringe_bitmap_params *p)
750 {
751 struct frame *f = XFRAME (WINDOW_FRAME (w));
752 Display *display = FRAME_X_DISPLAY (f);
753 Window window = FRAME_X_WINDOW (f);
754 GC gc = f->output_data.x->normal_gc;
755 struct face *face = p->face;
756 int rowY;
757
758 /* Must clip because of partially visible lines. */
759 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
760 if (p->y < rowY)
761 {
762 /* Adjust position of "bottom aligned" bitmap on partially
763 visible last row. */
764 int oldY = row->y;
765 int oldVH = row->visible_height;
766 row->visible_height = p->h;
767 row->y -= rowY - p->y;
768 x_clip_to_row (w, row, -1, gc);
769 row->y = oldY;
770 row->visible_height = oldVH;
771 }
772 else
773 x_clip_to_row (w, row, -1, gc);
774
775 if (!p->overlay_p)
776 {
777 int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
778
779 /* In case the same realized face is used for fringes and
780 for something displayed in the text (e.g. face `region' on
781 mono-displays, the fill style may have been changed to
782 FillSolid in x_draw_glyph_string_background. */
783 if (face->stipple)
784 XSetFillStyle (display, face->gc, FillOpaqueStippled);
785 else
786 XSetForeground (display, face->gc, face->background);
787
788 #ifdef USE_TOOLKIT_SCROLL_BARS
789 /* If the fringe is adjacent to the left (right) scroll bar of a
790 leftmost (rightmost, respectively) window, then extend its
791 background to the gap between the fringe and the bar. */
792 if ((WINDOW_LEFTMOST_P (w)
793 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
794 || (WINDOW_RIGHTMOST_P (w)
795 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
796 {
797 int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
798
799 if (sb_width > 0)
800 {
801 int left = WINDOW_SCROLL_BAR_AREA_X (w);
802 int width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
803 * FRAME_COLUMN_WIDTH (f));
804
805 if (bx < 0)
806 {
807 /* Bitmap fills the fringe. */
808 if (left + width == p->x)
809 bx = left + sb_width;
810 else if (p->x + p->wd == left)
811 bx = left;
812 if (bx >= 0)
813 {
814 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
815
816 nx = width - sb_width;
817 by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
818 row->y));
819 ny = row->visible_height;
820 }
821 }
822 else
823 {
824 if (left + width == bx)
825 {
826 bx = left + sb_width;
827 nx += width - sb_width;
828 }
829 else if (bx + nx == left)
830 nx += width - sb_width;
831 }
832 }
833 }
834 #endif
835 if (bx >= 0 && nx > 0)
836 XFillRectangle (display, window, face->gc, bx, by, nx, ny);
837
838 if (!face->stipple)
839 XSetForeground (display, face->gc, face->foreground);
840 }
841
842 if (p->which)
843 {
844 unsigned char *bits;
845 Pixmap pixmap, clipmask = (Pixmap) 0;
846 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
847 XGCValues gcv;
848
849 if (p->wd > 8)
850 bits = (unsigned char *)(p->bits + p->dh);
851 else
852 bits = (unsigned char *)p->bits + p->dh;
853
854 /* Draw the bitmap. I believe these small pixmaps can be cached
855 by the server. */
856 pixmap = XCreatePixmapFromBitmapData (display, window, bits, p->wd, p->h,
857 (p->cursor_p
858 ? (p->overlay_p ? face->background
859 : f->output_data.x->cursor_pixel)
860 : face->foreground),
861 face->background, depth);
862
863 if (p->overlay_p)
864 {
865 clipmask = XCreatePixmapFromBitmapData (display,
866 FRAME_X_DISPLAY_INFO (f)->root_window,
867 bits, p->wd, p->h,
868 1, 0, 1);
869 gcv.clip_mask = clipmask;
870 gcv.clip_x_origin = p->x;
871 gcv.clip_y_origin = p->y;
872 XChangeGC (display, gc, GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv);
873 }
874
875 XCopyArea (display, pixmap, window, gc, 0, 0,
876 p->wd, p->h, p->x, p->y);
877 XFreePixmap (display, pixmap);
878
879 if (p->overlay_p)
880 {
881 gcv.clip_mask = (Pixmap) 0;
882 XChangeGC (display, gc, GCClipMask, &gcv);
883 XFreePixmap (display, clipmask);
884 }
885 }
886
887 XSetClipMask (display, gc, None);
888 }
889
890 \f
891
892 /* This is called when starting Emacs and when restarting after
893 suspend. When starting Emacs, no X window is mapped. And nothing
894 must be done to Emacs's own window if it is suspended (though that
895 rarely happens). */
896
897 static void
898 XTset_terminal_modes (struct terminal *terminal)
899 {
900 }
901
902 /* This is called when exiting or suspending Emacs. Exiting will make
903 the X-windows go away, and suspending requires no action. */
904
905 static void
906 XTreset_terminal_modes (struct terminal *terminal)
907 {
908 }
909
910 \f
911 /***********************************************************************
912 Glyph display
913 ***********************************************************************/
914
915
916
917 static void x_set_glyph_string_clipping (struct glyph_string *);
918 static void x_set_glyph_string_gc (struct glyph_string *);
919 static void x_draw_glyph_string_background (struct glyph_string *,
920 int);
921 static void x_draw_glyph_string_foreground (struct glyph_string *);
922 static void x_draw_composite_glyph_string_foreground (struct glyph_string *);
923 static void x_draw_glyph_string_box (struct glyph_string *);
924 static void x_draw_glyph_string (struct glyph_string *);
925 static void x_compute_glyph_string_overhangs (struct glyph_string *);
926 static void x_set_cursor_gc (struct glyph_string *);
927 static void x_set_mode_line_face_gc (struct glyph_string *);
928 static void x_set_mouse_face_gc (struct glyph_string *);
929 static int x_alloc_lighter_color (struct frame *, Display *, Colormap,
930 unsigned long *, double, int);
931 static void x_setup_relief_color (struct frame *, struct relief *,
932 double, int, unsigned long);
933 static void x_setup_relief_colors (struct glyph_string *);
934 static void x_draw_image_glyph_string (struct glyph_string *);
935 static void x_draw_image_relief (struct glyph_string *);
936 static void x_draw_image_foreground (struct glyph_string *);
937 static void x_draw_image_foreground_1 (struct glyph_string *, Pixmap);
938 static void x_clear_glyph_string_rect (struct glyph_string *, int,
939 int, int, int);
940 static void x_draw_relief_rect (struct frame *, int, int, int, int,
941 int, int, int, int, int, int,
942 XRectangle *);
943 static void x_draw_box_rect (struct glyph_string *, int, int, int, int,
944 int, int, int, XRectangle *);
945
946 #if GLYPH_DEBUG
947 static void x_check_font (struct frame *, struct font *);
948 #endif
949
950
951 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
952 face. */
953
954 static void
955 x_set_cursor_gc (struct glyph_string *s)
956 {
957 if (s->font == FRAME_FONT (s->f)
958 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
959 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
960 && !s->cmp)
961 s->gc = s->f->output_data.x->cursor_gc;
962 else
963 {
964 /* Cursor on non-default face: must merge. */
965 XGCValues xgcv;
966 unsigned long mask;
967
968 xgcv.background = s->f->output_data.x->cursor_pixel;
969 xgcv.foreground = s->face->background;
970
971 /* If the glyph would be invisible, try a different foreground. */
972 if (xgcv.foreground == xgcv.background)
973 xgcv.foreground = s->face->foreground;
974 if (xgcv.foreground == xgcv.background)
975 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
976 if (xgcv.foreground == xgcv.background)
977 xgcv.foreground = s->face->foreground;
978
979 /* Make sure the cursor is distinct from text in this face. */
980 if (xgcv.background == s->face->background
981 && xgcv.foreground == s->face->foreground)
982 {
983 xgcv.background = s->face->foreground;
984 xgcv.foreground = s->face->background;
985 }
986
987 IF_DEBUG (x_check_font (s->f, s->font));
988 xgcv.graphics_exposures = False;
989 mask = GCForeground | GCBackground | GCGraphicsExposures;
990
991 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
992 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
993 mask, &xgcv);
994 else
995 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
996 = XCreateGC (s->display, s->window, mask, &xgcv);
997
998 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
999 }
1000 }
1001
1002
1003 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1004
1005 static void
1006 x_set_mouse_face_gc (struct glyph_string *s)
1007 {
1008 int face_id;
1009 struct face *face;
1010
1011 /* What face has to be used last for the mouse face? */
1012 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
1013 face = FACE_FROM_ID (s->f, face_id);
1014 if (face == NULL)
1015 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
1016
1017 if (s->first_glyph->type == CHAR_GLYPH)
1018 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch, -1, Qnil);
1019 else
1020 face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil);
1021 s->face = FACE_FROM_ID (s->f, face_id);
1022 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1023
1024 if (s->font == s->face->font)
1025 s->gc = s->face->gc;
1026 else
1027 {
1028 /* Otherwise construct scratch_cursor_gc with values from FACE
1029 except for FONT. */
1030 XGCValues xgcv;
1031 unsigned long mask;
1032
1033 xgcv.background = s->face->background;
1034 xgcv.foreground = s->face->foreground;
1035 xgcv.graphics_exposures = False;
1036 mask = GCForeground | GCBackground | GCGraphicsExposures;
1037
1038 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1039 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1040 mask, &xgcv);
1041 else
1042 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
1043 = XCreateGC (s->display, s->window, mask, &xgcv);
1044
1045 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1046
1047 }
1048 xassert (s->gc != 0);
1049 }
1050
1051
1052 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1053 Faces to use in the mode line have already been computed when the
1054 matrix was built, so there isn't much to do, here. */
1055
1056 static INLINE void
1057 x_set_mode_line_face_gc (struct glyph_string *s)
1058 {
1059 s->gc = s->face->gc;
1060 }
1061
1062
1063 /* Set S->gc of glyph string S for drawing that glyph string. Set
1064 S->stippled_p to a non-zero value if the face of S has a stipple
1065 pattern. */
1066
1067 static INLINE void
1068 x_set_glyph_string_gc (struct glyph_string *s)
1069 {
1070 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1071
1072 if (s->hl == DRAW_NORMAL_TEXT)
1073 {
1074 s->gc = s->face->gc;
1075 s->stippled_p = s->face->stipple != 0;
1076 }
1077 else if (s->hl == DRAW_INVERSE_VIDEO)
1078 {
1079 x_set_mode_line_face_gc (s);
1080 s->stippled_p = s->face->stipple != 0;
1081 }
1082 else if (s->hl == DRAW_CURSOR)
1083 {
1084 x_set_cursor_gc (s);
1085 s->stippled_p = 0;
1086 }
1087 else if (s->hl == DRAW_MOUSE_FACE)
1088 {
1089 x_set_mouse_face_gc (s);
1090 s->stippled_p = s->face->stipple != 0;
1091 }
1092 else if (s->hl == DRAW_IMAGE_RAISED
1093 || s->hl == DRAW_IMAGE_SUNKEN)
1094 {
1095 s->gc = s->face->gc;
1096 s->stippled_p = s->face->stipple != 0;
1097 }
1098 else
1099 {
1100 s->gc = s->face->gc;
1101 s->stippled_p = s->face->stipple != 0;
1102 }
1103
1104 /* GC must have been set. */
1105 xassert (s->gc != 0);
1106 }
1107
1108
1109 /* Set clipping for output of glyph string S. S may be part of a mode
1110 line or menu if we don't have X toolkit support. */
1111
1112 static INLINE void
1113 x_set_glyph_string_clipping (struct glyph_string *s)
1114 {
1115 XRectangle *r = s->clip;
1116 int n = get_glyph_string_clip_rects (s, r, 2);
1117
1118 if (n > 0)
1119 XSetClipRectangles (s->display, s->gc, 0, 0, r, n, Unsorted);
1120 s->num_clips = n;
1121 }
1122
1123
1124 /* Set SRC's clipping for output of glyph string DST. This is called
1125 when we are drawing DST's left_overhang or right_overhang only in
1126 the area of SRC. */
1127
1128 static void
1129 x_set_glyph_string_clipping_exactly (struct glyph_string *src, struct glyph_string *dst)
1130 {
1131 XRectangle r;
1132
1133 r.x = src->x;
1134 r.width = src->width;
1135 r.y = src->y;
1136 r.height = src->height;
1137 dst->clip[0] = r;
1138 dst->num_clips = 1;
1139 XSetClipRectangles (dst->display, dst->gc, 0, 0, &r, 1, Unsorted);
1140 }
1141
1142
1143 /* RIF:
1144 Compute left and right overhang of glyph string S. */
1145
1146 static void
1147 x_compute_glyph_string_overhangs (struct glyph_string *s)
1148 {
1149 if (s->cmp == NULL
1150 && (s->first_glyph->type == CHAR_GLYPH
1151 || s->first_glyph->type == COMPOSITE_GLYPH))
1152 {
1153 struct font_metrics metrics;
1154
1155 if (s->first_glyph->type == CHAR_GLYPH)
1156 {
1157 unsigned *code = alloca (sizeof (unsigned) * s->nchars);
1158 struct font *font = s->font;
1159 int i;
1160
1161 for (i = 0; i < s->nchars; i++)
1162 code[i] = (s->char2b[i].byte1 << 8) | s->char2b[i].byte2;
1163 font->driver->text_extents (font, code, s->nchars, &metrics);
1164 }
1165 else
1166 {
1167 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
1168
1169 composition_gstring_width (gstring, s->cmp_from, s->cmp_to, &metrics);
1170 }
1171 s->right_overhang = (metrics.rbearing > metrics.width
1172 ? metrics.rbearing - metrics.width : 0);
1173 s->left_overhang = metrics.lbearing < 0 ? - metrics.lbearing : 0;
1174 }
1175 else if (s->cmp)
1176 {
1177 s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width;
1178 s->left_overhang = - s->cmp->lbearing;
1179 }
1180 }
1181
1182
1183 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1184
1185 static INLINE void
1186 x_clear_glyph_string_rect (struct glyph_string *s, int x, int y, int w, int h)
1187 {
1188 XGCValues xgcv;
1189 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
1190 XSetForeground (s->display, s->gc, xgcv.background);
1191 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
1192 XSetForeground (s->display, s->gc, xgcv.foreground);
1193 }
1194
1195
1196 /* Draw the background of glyph_string S. If S->background_filled_p
1197 is non-zero don't draw it. FORCE_P non-zero means draw the
1198 background even if it wouldn't be drawn normally. This is used
1199 when a string preceding S draws into the background of S, or S
1200 contains the first component of a composition. */
1201
1202 static void
1203 x_draw_glyph_string_background (struct glyph_string *s, int force_p)
1204 {
1205 /* Nothing to do if background has already been drawn or if it
1206 shouldn't be drawn in the first place. */
1207 if (!s->background_filled_p)
1208 {
1209 int box_line_width = max (s->face->box_line_width, 0);
1210
1211 if (s->stippled_p)
1212 {
1213 /* Fill background with a stipple pattern. */
1214 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
1215 XFillRectangle (s->display, s->window, s->gc, s->x,
1216 s->y + box_line_width,
1217 s->background_width,
1218 s->height - 2 * box_line_width);
1219 XSetFillStyle (s->display, s->gc, FillSolid);
1220 s->background_filled_p = 1;
1221 }
1222 else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
1223 || s->font_not_found_p
1224 || s->extends_to_end_of_line_p
1225 || force_p)
1226 {
1227 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
1228 s->background_width,
1229 s->height - 2 * box_line_width);
1230 s->background_filled_p = 1;
1231 }
1232 }
1233 }
1234
1235
1236 /* Draw the foreground of glyph string S. */
1237
1238 static void
1239 x_draw_glyph_string_foreground (struct glyph_string *s)
1240 {
1241 int i, x;
1242
1243 /* If first glyph of S has a left box line, start drawing the text
1244 of S to the right of that box line. */
1245 if (s->face->box != FACE_NO_BOX
1246 && s->first_glyph->left_box_line_p)
1247 x = s->x + eabs (s->face->box_line_width);
1248 else
1249 x = s->x;
1250
1251 /* Draw characters of S as rectangles if S's font could not be
1252 loaded. */
1253 if (s->font_not_found_p)
1254 {
1255 for (i = 0; i < s->nchars; ++i)
1256 {
1257 struct glyph *g = s->first_glyph + i;
1258 XDrawRectangle (s->display, s->window,
1259 s->gc, x, s->y, g->pixel_width - 1,
1260 s->height - 1);
1261 x += g->pixel_width;
1262 }
1263 }
1264 else
1265 {
1266 struct font *font = s->font;
1267 int boff = font->baseline_offset;
1268 int y;
1269
1270 if (font->vertical_centering)
1271 boff = VCENTER_BASELINE_OFFSET (font, s->f) - boff;
1272
1273 y = s->ybase - boff;
1274 if (s->for_overlaps
1275 || (s->background_filled_p && s->hl != DRAW_CURSOR))
1276 font->driver->draw (s, 0, s->nchars, x, y, 0);
1277 else
1278 font->driver->draw (s, 0, s->nchars, x, y, 1);
1279 if (s->face->overstrike)
1280 font->driver->draw (s, 0, s->nchars, x + 1, y, 0);
1281 }
1282 }
1283
1284 /* Draw the foreground of composite glyph string S. */
1285
1286 static void
1287 x_draw_composite_glyph_string_foreground (struct glyph_string *s)
1288 {
1289 int i, j, x;
1290 struct font *font = s->font;
1291
1292 /* If first glyph of S has a left box line, start drawing the text
1293 of S to the right of that box line. */
1294 if (s->face && s->face->box != FACE_NO_BOX
1295 && s->first_glyph->left_box_line_p)
1296 x = s->x + eabs (s->face->box_line_width);
1297 else
1298 x = s->x;
1299
1300 /* S is a glyph string for a composition. S->cmp_from is the index
1301 of the first character drawn for glyphs of this composition.
1302 S->cmp_from == 0 means we are drawing the very first character of
1303 this composition. */
1304
1305 /* Draw a rectangle for the composition if the font for the very
1306 first character of the composition could not be loaded. */
1307 if (s->font_not_found_p)
1308 {
1309 if (s->cmp_from == 0)
1310 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
1311 s->width - 1, s->height - 1);
1312 }
1313 else if (! s->first_glyph->u.cmp.automatic)
1314 {
1315 int y = s->ybase;
1316
1317 for (i = 0, j = s->cmp_from; i < s->nchars; i++, j++)
1318 if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
1319 {
1320 int xx = x + s->cmp->offsets[j * 2];
1321 int yy = y - s->cmp->offsets[j * 2 + 1];
1322
1323 font->driver->draw (s, j, j + 1, xx, yy, 0);
1324 if (s->face->overstrike)
1325 font->driver->draw (s, j, j + 1, xx + 1, yy, 0);
1326 }
1327 }
1328 else
1329 {
1330 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
1331 Lisp_Object glyph;
1332 int y = s->ybase;
1333 int width = 0;
1334
1335 for (i = j = s->cmp_from; i < s->cmp_to; i++)
1336 {
1337 glyph = LGSTRING_GLYPH (gstring, i);
1338 if (NILP (LGLYPH_ADJUSTMENT (glyph)))
1339 width += LGLYPH_WIDTH (glyph);
1340 else
1341 {
1342 int xoff, yoff, wadjust;
1343
1344 if (j < i)
1345 {
1346 font->driver->draw (s, j, i, x, y, 0);
1347 if (s->face->overstrike)
1348 font->driver->draw (s, j, i, x + 1, y, 0);
1349 x += width;
1350 }
1351 xoff = LGLYPH_XOFF (glyph);
1352 yoff = LGLYPH_YOFF (glyph);
1353 wadjust = LGLYPH_WADJUST (glyph);
1354 font->driver->draw (s, i, i + 1, x + xoff, y + yoff, 0);
1355 if (s->face->overstrike)
1356 font->driver->draw (s, i, i + 1, x + xoff + 1, y + yoff, 0);
1357 x += wadjust;
1358 j = i + 1;
1359 width = 0;
1360 }
1361 }
1362 if (j < i)
1363 {
1364 font->driver->draw (s, j, i, x, y, 0);
1365 if (s->face->overstrike)
1366 font->driver->draw (s, j, i, x + 1, y, 0);
1367 }
1368 }
1369 }
1370
1371
1372 #ifdef USE_X_TOOLKIT
1373
1374 static struct frame *x_frame_of_widget (Widget);
1375 static Boolean cvt_string_to_pixel (Display *, XrmValue *, Cardinal *,
1376 XrmValue *, XrmValue *, XtPointer *);
1377 static void cvt_pixel_dtor (XtAppContext, XrmValue *, XtPointer,
1378 XrmValue *, Cardinal *);
1379
1380
1381 /* Return the frame on which widget WIDGET is used.. Abort if frame
1382 cannot be determined. */
1383
1384 static struct frame *
1385 x_frame_of_widget (widget)
1386 Widget widget;
1387 {
1388 struct x_display_info *dpyinfo;
1389 Lisp_Object tail;
1390 struct frame *f;
1391
1392 dpyinfo = x_display_info_for_display (XtDisplay (widget));
1393
1394 /* Find the top-level shell of the widget. Note that this function
1395 can be called when the widget is not yet realized, so XtWindow
1396 (widget) == 0. That's the reason we can't simply use
1397 x_any_window_to_frame. */
1398 while (!XtIsTopLevelShell (widget))
1399 widget = XtParent (widget);
1400
1401 /* Look for a frame with that top-level widget. Allocate the color
1402 on that frame to get the right gamma correction value. */
1403 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1404 if (FRAMEP (XCAR (tail))
1405 && (f = XFRAME (XCAR (tail)),
1406 (FRAME_X_P (f)
1407 && f->output_data.nothing != 1
1408 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
1409 && f->output_data.x->widget == widget)
1410 return f;
1411
1412 abort ();
1413 }
1414
1415
1416 /* Allocate the color COLOR->pixel on the screen and display of
1417 widget WIDGET in colormap CMAP. If an exact match cannot be
1418 allocated, try the nearest color available. Value is non-zero
1419 if successful. This is called from lwlib. */
1420
1421 int
1422 x_alloc_nearest_color_for_widget (widget, cmap, color)
1423 Widget widget;
1424 Colormap cmap;
1425 XColor *color;
1426 {
1427 struct frame *f = x_frame_of_widget (widget);
1428 return x_alloc_nearest_color (f, cmap, color);
1429 }
1430
1431
1432 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
1433 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1434 If this produces the same color as PIXEL, try a color where all RGB
1435 values have DELTA added. Return the allocated color in *PIXEL.
1436 DISPLAY is the X display, CMAP is the colormap to operate on.
1437 Value is non-zero if successful. */
1438
1439 int
1440 x_alloc_lighter_color_for_widget (widget, display, cmap, pixel, factor, delta)
1441 Widget widget;
1442 Display *display;
1443 Colormap cmap;
1444 unsigned long *pixel;
1445 double factor;
1446 int delta;
1447 {
1448 struct frame *f = x_frame_of_widget (widget);
1449 return x_alloc_lighter_color (f, display, cmap, pixel, factor, delta);
1450 }
1451
1452
1453 /* Structure specifying which arguments should be passed by Xt to
1454 cvt_string_to_pixel. We want the widget's screen and colormap. */
1455
1456 static XtConvertArgRec cvt_string_to_pixel_args[] =
1457 {
1458 {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.screen),
1459 sizeof (Screen *)},
1460 {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.colormap),
1461 sizeof (Colormap)}
1462 };
1463
1464
1465 /* The address of this variable is returned by
1466 cvt_string_to_pixel. */
1467
1468 static Pixel cvt_string_to_pixel_value;
1469
1470
1471 /* Convert a color name to a pixel color.
1472
1473 DPY is the display we are working on.
1474
1475 ARGS is an array of *NARGS XrmValue structures holding additional
1476 information about the widget for which the conversion takes place.
1477 The contents of this array are determined by the specification
1478 in cvt_string_to_pixel_args.
1479
1480 FROM is a pointer to an XrmValue which points to the color name to
1481 convert. TO is an XrmValue in which to return the pixel color.
1482
1483 CLOSURE_RET is a pointer to user-data, in which we record if
1484 we allocated the color or not.
1485
1486 Value is True if successful, False otherwise. */
1487
1488 static Boolean
1489 cvt_string_to_pixel (dpy, args, nargs, from, to, closure_ret)
1490 Display *dpy;
1491 XrmValue *args;
1492 Cardinal *nargs;
1493 XrmValue *from, *to;
1494 XtPointer *closure_ret;
1495 {
1496 Screen *screen;
1497 Colormap cmap;
1498 Pixel pixel;
1499 String color_name;
1500 XColor color;
1501
1502 if (*nargs != 2)
1503 {
1504 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
1505 "wrongParameters", "cvt_string_to_pixel",
1506 "XtToolkitError",
1507 "Screen and colormap args required", NULL, NULL);
1508 return False;
1509 }
1510
1511 screen = *(Screen **) args[0].addr;
1512 cmap = *(Colormap *) args[1].addr;
1513 color_name = (String) from->addr;
1514
1515 if (strcmp (color_name, XtDefaultBackground) == 0)
1516 {
1517 *closure_ret = (XtPointer) False;
1518 pixel = WhitePixelOfScreen (screen);
1519 }
1520 else if (strcmp (color_name, XtDefaultForeground) == 0)
1521 {
1522 *closure_ret = (XtPointer) False;
1523 pixel = BlackPixelOfScreen (screen);
1524 }
1525 else if (XParseColor (dpy, cmap, color_name, &color)
1526 && x_alloc_nearest_color_1 (dpy, cmap, &color))
1527 {
1528 pixel = color.pixel;
1529 *closure_ret = (XtPointer) True;
1530 }
1531 else
1532 {
1533 String params[1];
1534 Cardinal nparams = 1;
1535
1536 params[0] = color_name;
1537 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
1538 "badValue", "cvt_string_to_pixel",
1539 "XtToolkitError", "Invalid color `%s'",
1540 params, &nparams);
1541 return False;
1542 }
1543
1544 if (to->addr != NULL)
1545 {
1546 if (to->size < sizeof (Pixel))
1547 {
1548 to->size = sizeof (Pixel);
1549 return False;
1550 }
1551
1552 *(Pixel *) to->addr = pixel;
1553 }
1554 else
1555 {
1556 cvt_string_to_pixel_value = pixel;
1557 to->addr = (XtPointer) &cvt_string_to_pixel_value;
1558 }
1559
1560 to->size = sizeof (Pixel);
1561 return True;
1562 }
1563
1564
1565 /* Free a pixel color which was previously allocated via
1566 cvt_string_to_pixel. This is registered as the destructor
1567 for this type of resource via XtSetTypeConverter.
1568
1569 APP is the application context in which we work.
1570
1571 TO is a pointer to an XrmValue holding the color to free.
1572 CLOSURE is the value we stored in CLOSURE_RET for this color
1573 in cvt_string_to_pixel.
1574
1575 ARGS and NARGS are like for cvt_string_to_pixel. */
1576
1577 static void
1578 cvt_pixel_dtor (app, to, closure, args, nargs)
1579 XtAppContext app;
1580 XrmValuePtr to;
1581 XtPointer closure;
1582 XrmValuePtr args;
1583 Cardinal *nargs;
1584 {
1585 if (*nargs != 2)
1586 {
1587 XtAppWarningMsg (app, "wrongParameters", "cvt_pixel_dtor",
1588 "XtToolkitError",
1589 "Screen and colormap arguments required",
1590 NULL, NULL);
1591 }
1592 else if (closure != NULL)
1593 {
1594 /* We did allocate the pixel, so free it. */
1595 Screen *screen = *(Screen **) args[0].addr;
1596 Colormap cmap = *(Colormap *) args[1].addr;
1597 x_free_dpy_colors (DisplayOfScreen (screen), screen, cmap,
1598 (Pixel *) to->addr, 1);
1599 }
1600 }
1601
1602
1603 #endif /* USE_X_TOOLKIT */
1604
1605
1606 /* Value is an array of XColor structures for the contents of the
1607 color map of display DPY. Set *NCELLS to the size of the array.
1608 Note that this probably shouldn't be called for large color maps,
1609 say a 24-bit TrueColor map. */
1610
1611 static const XColor *
1612 x_color_cells (Display *dpy, int *ncells)
1613 {
1614 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
1615
1616 if (dpyinfo->color_cells == NULL)
1617 {
1618 Screen *screen = dpyinfo->screen;
1619 int i;
1620
1621 dpyinfo->ncolor_cells
1622 = XDisplayCells (dpy, XScreenNumberOfScreen (screen));
1623 dpyinfo->color_cells
1624 = (XColor *) xmalloc (dpyinfo->ncolor_cells
1625 * sizeof *dpyinfo->color_cells);
1626
1627 for (i = 0; i < dpyinfo->ncolor_cells; ++i)
1628 dpyinfo->color_cells[i].pixel = i;
1629
1630 XQueryColors (dpy, dpyinfo->cmap,
1631 dpyinfo->color_cells, dpyinfo->ncolor_cells);
1632 }
1633
1634 *ncells = dpyinfo->ncolor_cells;
1635 return dpyinfo->color_cells;
1636 }
1637
1638
1639 /* On frame F, translate pixel colors to RGB values for the NCOLORS
1640 colors in COLORS. Use cached information, if available. */
1641
1642 void
1643 x_query_colors (struct frame *f, XColor *colors, int ncolors)
1644 {
1645 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
1646
1647 if (dpyinfo->color_cells)
1648 {
1649 int i;
1650 for (i = 0; i < ncolors; ++i)
1651 {
1652 unsigned long pixel = colors[i].pixel;
1653 xassert (pixel < dpyinfo->ncolor_cells);
1654 xassert (dpyinfo->color_cells[pixel].pixel == pixel);
1655 colors[i] = dpyinfo->color_cells[pixel];
1656 }
1657 }
1658 else
1659 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
1660 }
1661
1662
1663 /* On frame F, translate pixel color to RGB values for the color in
1664 COLOR. Use cached information, if available. */
1665
1666 void
1667 x_query_color (struct frame *f, XColor *color)
1668 {
1669 x_query_colors (f, color, 1);
1670 }
1671
1672
1673 /* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP. If an
1674 exact match can't be allocated, try the nearest color available.
1675 Value is non-zero if successful. Set *COLOR to the color
1676 allocated. */
1677
1678 static int
1679 x_alloc_nearest_color_1 (Display *dpy, Colormap cmap, XColor *color)
1680 {
1681 int rc;
1682
1683 rc = XAllocColor (dpy, cmap, color);
1684 if (rc == 0)
1685 {
1686 /* If we got to this point, the colormap is full, so we're going
1687 to try to get the next closest color. The algorithm used is
1688 a least-squares matching, which is what X uses for closest
1689 color matching with StaticColor visuals. */
1690 int nearest, i;
1691 unsigned long nearest_delta = ~0;
1692 int ncells;
1693 const XColor *cells = x_color_cells (dpy, &ncells);
1694
1695 for (nearest = i = 0; i < ncells; ++i)
1696 {
1697 long dred = (color->red >> 8) - (cells[i].red >> 8);
1698 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
1699 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
1700 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
1701
1702 if (delta < nearest_delta)
1703 {
1704 nearest = i;
1705 nearest_delta = delta;
1706 }
1707 }
1708
1709 color->red = cells[nearest].red;
1710 color->green = cells[nearest].green;
1711 color->blue = cells[nearest].blue;
1712 rc = XAllocColor (dpy, cmap, color);
1713 }
1714 else
1715 {
1716 /* If allocation succeeded, and the allocated pixel color is not
1717 equal to a cached pixel color recorded earlier, there was a
1718 change in the colormap, so clear the color cache. */
1719 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
1720 XColor *cached_color;
1721
1722 if (dpyinfo->color_cells
1723 && (cached_color = &dpyinfo->color_cells[color->pixel],
1724 (cached_color->red != color->red
1725 || cached_color->blue != color->blue
1726 || cached_color->green != color->green)))
1727 {
1728 xfree (dpyinfo->color_cells);
1729 dpyinfo->color_cells = NULL;
1730 dpyinfo->ncolor_cells = 0;
1731 }
1732 }
1733
1734 #ifdef DEBUG_X_COLORS
1735 if (rc)
1736 register_color (color->pixel);
1737 #endif /* DEBUG_X_COLORS */
1738
1739 return rc;
1740 }
1741
1742
1743 /* Allocate the color COLOR->pixel on frame F, colormap CMAP. If an
1744 exact match can't be allocated, try the nearest color available.
1745 Value is non-zero if successful. Set *COLOR to the color
1746 allocated. */
1747
1748 int
1749 x_alloc_nearest_color (struct frame *f, Colormap cmap, XColor *color)
1750 {
1751 gamma_correct (f, color);
1752 return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f), cmap, color);
1753 }
1754
1755
1756 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
1757 It's necessary to do this instead of just using PIXEL directly to
1758 get color reference counts right. */
1759
1760 unsigned long
1761 x_copy_color (struct frame *f, long unsigned int pixel)
1762 {
1763 XColor color;
1764
1765 color.pixel = pixel;
1766 BLOCK_INPUT;
1767 x_query_color (f, &color);
1768 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
1769 UNBLOCK_INPUT;
1770 #ifdef DEBUG_X_COLORS
1771 register_color (pixel);
1772 #endif
1773 return color.pixel;
1774 }
1775
1776
1777 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
1778 It's necessary to do this instead of just using PIXEL directly to
1779 get color reference counts right. */
1780
1781 unsigned long
1782 x_copy_dpy_color (Display *dpy, Colormap cmap, long unsigned int pixel)
1783 {
1784 XColor color;
1785
1786 color.pixel = pixel;
1787 BLOCK_INPUT;
1788 XQueryColor (dpy, cmap, &color);
1789 XAllocColor (dpy, cmap, &color);
1790 UNBLOCK_INPUT;
1791 #ifdef DEBUG_X_COLORS
1792 register_color (pixel);
1793 #endif
1794 return color.pixel;
1795 }
1796
1797
1798 /* Brightness beyond which a color won't have its highlight brightness
1799 boosted.
1800
1801 Nominally, highlight colors for `3d' faces are calculated by
1802 brightening an object's color by a constant scale factor, but this
1803 doesn't yield good results for dark colors, so for colors who's
1804 brightness is less than this value (on a scale of 0-65535) have an
1805 use an additional additive factor.
1806
1807 The value here is set so that the default menu-bar/mode-line color
1808 (grey75) will not have its highlights changed at all. */
1809 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
1810
1811
1812 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
1813 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1814 If this produces the same color as PIXEL, try a color where all RGB
1815 values have DELTA added. Return the allocated color in *PIXEL.
1816 DISPLAY is the X display, CMAP is the colormap to operate on.
1817 Value is non-zero if successful. */
1818
1819 static int
1820 x_alloc_lighter_color (struct frame *f, Display *display, Colormap cmap, long unsigned int *pixel, double factor, int delta)
1821 {
1822 XColor color, new;
1823 long bright;
1824 int success_p;
1825
1826 /* Get RGB color values. */
1827 color.pixel = *pixel;
1828 x_query_color (f, &color);
1829
1830 /* Change RGB values by specified FACTOR. Avoid overflow! */
1831 xassert (factor >= 0);
1832 new.red = min (0xffff, factor * color.red);
1833 new.green = min (0xffff, factor * color.green);
1834 new.blue = min (0xffff, factor * color.blue);
1835
1836 /* Calculate brightness of COLOR. */
1837 bright = (2 * color.red + 3 * color.green + color.blue) / 6;
1838
1839 /* We only boost colors that are darker than
1840 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
1841 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
1842 /* Make an additive adjustment to NEW, because it's dark enough so
1843 that scaling by FACTOR alone isn't enough. */
1844 {
1845 /* How far below the limit this color is (0 - 1, 1 being darker). */
1846 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
1847 /* The additive adjustment. */
1848 int min_delta = delta * dimness * factor / 2;
1849
1850 if (factor < 1)
1851 {
1852 new.red = max (0, new.red - min_delta);
1853 new.green = max (0, new.green - min_delta);
1854 new.blue = max (0, new.blue - min_delta);
1855 }
1856 else
1857 {
1858 new.red = min (0xffff, min_delta + new.red);
1859 new.green = min (0xffff, min_delta + new.green);
1860 new.blue = min (0xffff, min_delta + new.blue);
1861 }
1862 }
1863
1864 /* Try to allocate the color. */
1865 success_p = x_alloc_nearest_color (f, cmap, &new);
1866 if (success_p)
1867 {
1868 if (new.pixel == *pixel)
1869 {
1870 /* If we end up with the same color as before, try adding
1871 delta to the RGB values. */
1872 x_free_colors (f, &new.pixel, 1);
1873
1874 new.red = min (0xffff, delta + color.red);
1875 new.green = min (0xffff, delta + color.green);
1876 new.blue = min (0xffff, delta + color.blue);
1877 success_p = x_alloc_nearest_color (f, cmap, &new);
1878 }
1879 else
1880 success_p = 1;
1881 *pixel = new.pixel;
1882 }
1883
1884 return success_p;
1885 }
1886
1887
1888 /* Set up the foreground color for drawing relief lines of glyph
1889 string S. RELIEF is a pointer to a struct relief containing the GC
1890 with which lines will be drawn. Use a color that is FACTOR or
1891 DELTA lighter or darker than the relief's background which is found
1892 in S->f->output_data.x->relief_background. If such a color cannot
1893 be allocated, use DEFAULT_PIXEL, instead. */
1894
1895 static void
1896 x_setup_relief_color (struct frame *f, struct relief *relief, double factor, int delta, long unsigned int default_pixel)
1897 {
1898 XGCValues xgcv;
1899 struct x_output *di = f->output_data.x;
1900 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
1901 unsigned long pixel;
1902 unsigned long background = di->relief_background;
1903 Colormap cmap = FRAME_X_COLORMAP (f);
1904 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
1905 Display *dpy = FRAME_X_DISPLAY (f);
1906
1907 xgcv.graphics_exposures = False;
1908 xgcv.line_width = 1;
1909
1910 /* Free previously allocated color. The color cell will be reused
1911 when it has been freed as many times as it was allocated, so this
1912 doesn't affect faces using the same colors. */
1913 if (relief->gc
1914 && relief->allocated_p)
1915 {
1916 x_free_colors (f, &relief->pixel, 1);
1917 relief->allocated_p = 0;
1918 }
1919
1920 /* Allocate new color. */
1921 xgcv.foreground = default_pixel;
1922 pixel = background;
1923 if (dpyinfo->n_planes != 1
1924 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
1925 {
1926 relief->allocated_p = 1;
1927 xgcv.foreground = relief->pixel = pixel;
1928 }
1929
1930 if (relief->gc == 0)
1931 {
1932 xgcv.stipple = dpyinfo->gray;
1933 mask |= GCStipple;
1934 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
1935 }
1936 else
1937 XChangeGC (dpy, relief->gc, mask, &xgcv);
1938 }
1939
1940
1941 /* Set up colors for the relief lines around glyph string S. */
1942
1943 static void
1944 x_setup_relief_colors (struct glyph_string *s)
1945 {
1946 struct x_output *di = s->f->output_data.x;
1947 unsigned long color;
1948
1949 if (s->face->use_box_color_for_shadows_p)
1950 color = s->face->box_color;
1951 else if (s->first_glyph->type == IMAGE_GLYPH
1952 && s->img->pixmap
1953 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
1954 color = IMAGE_BACKGROUND (s->img, s->f, 0);
1955 else
1956 {
1957 XGCValues xgcv;
1958
1959 /* Get the background color of the face. */
1960 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
1961 color = xgcv.background;
1962 }
1963
1964 if (di->white_relief.gc == 0
1965 || color != di->relief_background)
1966 {
1967 di->relief_background = color;
1968 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
1969 WHITE_PIX_DEFAULT (s->f));
1970 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
1971 BLACK_PIX_DEFAULT (s->f));
1972 }
1973 }
1974
1975
1976 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
1977 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
1978 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
1979 relief. LEFT_P non-zero means draw a relief on the left side of
1980 the rectangle. RIGHT_P non-zero means draw a relief on the right
1981 side of the rectangle. CLIP_RECT is the clipping rectangle to use
1982 when drawing. */
1983
1984 static void
1985 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
1986 raised_p, top_p, bot_p, left_p, right_p, clip_rect)
1987 struct frame *f;
1988 int left_x, top_y, right_x, bottom_y, width;
1989 int top_p, bot_p, left_p, right_p, raised_p;
1990 XRectangle *clip_rect;
1991 {
1992 Display *dpy = FRAME_X_DISPLAY (f);
1993 Window window = FRAME_X_WINDOW (f);
1994 int i;
1995 GC gc;
1996
1997 if (raised_p)
1998 gc = f->output_data.x->white_relief.gc;
1999 else
2000 gc = f->output_data.x->black_relief.gc;
2001 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
2002
2003 /* Top. */
2004 if (top_p)
2005 for (i = 0; i < width; ++i)
2006 XDrawLine (dpy, window, gc,
2007 left_x + i * left_p, top_y + i,
2008 right_x + 1 - i * right_p, top_y + i);
2009
2010 /* Left. */
2011 if (left_p)
2012 for (i = 0; i < width; ++i)
2013 XDrawLine (dpy, window, gc,
2014 left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
2015
2016 XSetClipMask (dpy, gc, None);
2017 if (raised_p)
2018 gc = f->output_data.x->black_relief.gc;
2019 else
2020 gc = f->output_data.x->white_relief.gc;
2021 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
2022
2023 /* Bottom. */
2024 if (bot_p)
2025 for (i = 0; i < width; ++i)
2026 XDrawLine (dpy, window, gc,
2027 left_x + i * left_p, bottom_y - i,
2028 right_x + 1 - i * right_p, bottom_y - i);
2029
2030 /* Right. */
2031 if (right_p)
2032 for (i = 0; i < width; ++i)
2033 XDrawLine (dpy, window, gc,
2034 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
2035
2036 XSetClipMask (dpy, gc, None);
2037 }
2038
2039
2040 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2041 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2042 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2043 left side of the rectangle. RIGHT_P non-zero means draw a line
2044 on the right side of the rectangle. CLIP_RECT is the clipping
2045 rectangle to use when drawing. */
2046
2047 static void
2048 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2049 left_p, right_p, clip_rect)
2050 struct glyph_string *s;
2051 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
2052 XRectangle *clip_rect;
2053 {
2054 XGCValues xgcv;
2055
2056 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2057 XSetForeground (s->display, s->gc, s->face->box_color);
2058 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
2059
2060 /* Top. */
2061 XFillRectangle (s->display, s->window, s->gc,
2062 left_x, top_y, right_x - left_x + 1, width);
2063
2064 /* Left. */
2065 if (left_p)
2066 XFillRectangle (s->display, s->window, s->gc,
2067 left_x, top_y, width, bottom_y - top_y + 1);
2068
2069 /* Bottom. */
2070 XFillRectangle (s->display, s->window, s->gc,
2071 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
2072
2073 /* Right. */
2074 if (right_p)
2075 XFillRectangle (s->display, s->window, s->gc,
2076 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
2077
2078 XSetForeground (s->display, s->gc, xgcv.foreground);
2079 XSetClipMask (s->display, s->gc, None);
2080 }
2081
2082
2083 /* Draw a box around glyph string S. */
2084
2085 static void
2086 x_draw_glyph_string_box (struct glyph_string *s)
2087 {
2088 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
2089 int left_p, right_p;
2090 struct glyph *last_glyph;
2091 XRectangle clip_rect;
2092
2093 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
2094 ? WINDOW_RIGHT_EDGE_X (s->w)
2095 : window_box_right (s->w, s->area));
2096
2097 /* The glyph that may have a right box line. */
2098 last_glyph = (s->cmp || s->img
2099 ? s->first_glyph
2100 : s->first_glyph + s->nchars - 1);
2101
2102 width = eabs (s->face->box_line_width);
2103 raised_p = s->face->box == FACE_RAISED_BOX;
2104 left_x = s->x;
2105 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
2106 ? last_x - 1
2107 : min (last_x, s->x + s->background_width) - 1);
2108 top_y = s->y;
2109 bottom_y = top_y + s->height - 1;
2110
2111 left_p = (s->first_glyph->left_box_line_p
2112 || (s->hl == DRAW_MOUSE_FACE
2113 && (s->prev == NULL
2114 || s->prev->hl != s->hl)));
2115 right_p = (last_glyph->right_box_line_p
2116 || (s->hl == DRAW_MOUSE_FACE
2117 && (s->next == NULL
2118 || s->next->hl != s->hl)));
2119
2120 get_glyph_string_clip_rect (s, &clip_rect);
2121
2122 if (s->face->box == FACE_SIMPLE_BOX)
2123 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2124 left_p, right_p, &clip_rect);
2125 else
2126 {
2127 x_setup_relief_colors (s);
2128 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
2129 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
2130 }
2131 }
2132
2133
2134 /* Draw foreground of image glyph string S. */
2135
2136 static void
2137 x_draw_image_foreground (struct glyph_string *s)
2138 {
2139 int x = s->x;
2140 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2141
2142 /* If first glyph of S has a left box line, start drawing it to the
2143 right of that line. */
2144 if (s->face->box != FACE_NO_BOX
2145 && s->first_glyph->left_box_line_p
2146 && s->slice.x == 0)
2147 x += eabs (s->face->box_line_width);
2148
2149 /* If there is a margin around the image, adjust x- and y-position
2150 by that margin. */
2151 if (s->slice.x == 0)
2152 x += s->img->hmargin;
2153 if (s->slice.y == 0)
2154 y += s->img->vmargin;
2155
2156 if (s->img->pixmap)
2157 {
2158 if (s->img->mask)
2159 {
2160 /* We can't set both a clip mask and use XSetClipRectangles
2161 because the latter also sets a clip mask. We also can't
2162 trust on the shape extension to be available
2163 (XShapeCombineRegion). So, compute the rectangle to draw
2164 manually. */
2165 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
2166 | GCFunction);
2167 XGCValues xgcv;
2168 XRectangle clip_rect, image_rect, r;
2169
2170 xgcv.clip_mask = s->img->mask;
2171 xgcv.clip_x_origin = x;
2172 xgcv.clip_y_origin = y;
2173 xgcv.function = GXcopy;
2174 XChangeGC (s->display, s->gc, mask, &xgcv);
2175
2176 get_glyph_string_clip_rect (s, &clip_rect);
2177 image_rect.x = x;
2178 image_rect.y = y;
2179 image_rect.width = s->slice.width;
2180 image_rect.height = s->slice.height;
2181 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
2182 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
2183 s->slice.x + r.x - x, s->slice.y + r.y - y,
2184 r.width, r.height, r.x, r.y);
2185 }
2186 else
2187 {
2188 XRectangle clip_rect, image_rect, r;
2189
2190 get_glyph_string_clip_rect (s, &clip_rect);
2191 image_rect.x = x;
2192 image_rect.y = y;
2193 image_rect.width = s->slice.width;
2194 image_rect.height = s->slice.height;
2195 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
2196 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
2197 s->slice.x + r.x - x, s->slice.y + r.y - y,
2198 r.width, r.height, r.x, r.y);
2199
2200 /* When the image has a mask, we can expect that at
2201 least part of a mouse highlight or a block cursor will
2202 be visible. If the image doesn't have a mask, make
2203 a block cursor visible by drawing a rectangle around
2204 the image. I believe it's looking better if we do
2205 nothing here for mouse-face. */
2206 if (s->hl == DRAW_CURSOR)
2207 {
2208 int r = s->img->relief;
2209 if (r < 0) r = -r;
2210 XDrawRectangle (s->display, s->window, s->gc,
2211 x - r, y - r,
2212 s->slice.width + r*2 - 1,
2213 s->slice.height + r*2 - 1);
2214 }
2215 }
2216 }
2217 else
2218 /* Draw a rectangle if image could not be loaded. */
2219 XDrawRectangle (s->display, s->window, s->gc, x, y,
2220 s->slice.width - 1, s->slice.height - 1);
2221 }
2222
2223
2224 /* Draw a relief around the image glyph string S. */
2225
2226 static void
2227 x_draw_image_relief (struct glyph_string *s)
2228 {
2229 int x0, y0, x1, y1, thick, raised_p, extra;
2230 XRectangle r;
2231 int x = s->x;
2232 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2233
2234 /* If first glyph of S has a left box line, start drawing it to the
2235 right of that line. */
2236 if (s->face->box != FACE_NO_BOX
2237 && s->first_glyph->left_box_line_p
2238 && s->slice.x == 0)
2239 x += eabs (s->face->box_line_width);
2240
2241 /* If there is a margin around the image, adjust x- and y-position
2242 by that margin. */
2243 if (s->slice.x == 0)
2244 x += s->img->hmargin;
2245 if (s->slice.y == 0)
2246 y += s->img->vmargin;
2247
2248 if (s->hl == DRAW_IMAGE_SUNKEN
2249 || s->hl == DRAW_IMAGE_RAISED)
2250 {
2251 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
2252 raised_p = s->hl == DRAW_IMAGE_RAISED;
2253 }
2254 else
2255 {
2256 thick = eabs (s->img->relief);
2257 raised_p = s->img->relief > 0;
2258 }
2259
2260 extra = s->face->id == TOOL_BAR_FACE_ID
2261 ? XINT (Vtool_bar_button_margin) : 0;
2262
2263 x0 = x - thick - extra;
2264 y0 = y - thick - extra;
2265 x1 = x + s->slice.width + thick - 1 + extra;
2266 y1 = y + s->slice.height + thick - 1 + extra;
2267
2268 x_setup_relief_colors (s);
2269 get_glyph_string_clip_rect (s, &r);
2270 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
2271 s->slice.y == 0,
2272 s->slice.y + s->slice.height == s->img->height,
2273 s->slice.x == 0,
2274 s->slice.x + s->slice.width == s->img->width,
2275 &r);
2276 }
2277
2278
2279 /* Draw the foreground of image glyph string S to PIXMAP. */
2280
2281 static void
2282 x_draw_image_foreground_1 (struct glyph_string *s, Pixmap pixmap)
2283 {
2284 int x = 0;
2285 int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
2286
2287 /* If first glyph of S has a left box line, start drawing it to the
2288 right of that line. */
2289 if (s->face->box != FACE_NO_BOX
2290 && s->first_glyph->left_box_line_p
2291 && s->slice.x == 0)
2292 x += eabs (s->face->box_line_width);
2293
2294 /* If there is a margin around the image, adjust x- and y-position
2295 by that margin. */
2296 if (s->slice.x == 0)
2297 x += s->img->hmargin;
2298 if (s->slice.y == 0)
2299 y += s->img->vmargin;
2300
2301 if (s->img->pixmap)
2302 {
2303 if (s->img->mask)
2304 {
2305 /* We can't set both a clip mask and use XSetClipRectangles
2306 because the latter also sets a clip mask. We also can't
2307 trust on the shape extension to be available
2308 (XShapeCombineRegion). So, compute the rectangle to draw
2309 manually. */
2310 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
2311 | GCFunction);
2312 XGCValues xgcv;
2313
2314 xgcv.clip_mask = s->img->mask;
2315 xgcv.clip_x_origin = x - s->slice.x;
2316 xgcv.clip_y_origin = y - s->slice.y;
2317 xgcv.function = GXcopy;
2318 XChangeGC (s->display, s->gc, mask, &xgcv);
2319
2320 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
2321 s->slice.x, s->slice.y,
2322 s->slice.width, s->slice.height, x, y);
2323 XSetClipMask (s->display, s->gc, None);
2324 }
2325 else
2326 {
2327 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
2328 s->slice.x, s->slice.y,
2329 s->slice.width, s->slice.height, x, y);
2330
2331 /* When the image has a mask, we can expect that at
2332 least part of a mouse highlight or a block cursor will
2333 be visible. If the image doesn't have a mask, make
2334 a block cursor visible by drawing a rectangle around
2335 the image. I believe it's looking better if we do
2336 nothing here for mouse-face. */
2337 if (s->hl == DRAW_CURSOR)
2338 {
2339 int r = s->img->relief;
2340 if (r < 0) r = -r;
2341 XDrawRectangle (s->display, s->window, s->gc, x - r, y - r,
2342 s->slice.width + r*2 - 1,
2343 s->slice.height + r*2 - 1);
2344 }
2345 }
2346 }
2347 else
2348 /* Draw a rectangle if image could not be loaded. */
2349 XDrawRectangle (s->display, pixmap, s->gc, x, y,
2350 s->slice.width - 1, s->slice.height - 1);
2351 }
2352
2353
2354 /* Draw part of the background of glyph string S. X, Y, W, and H
2355 give the rectangle to draw. */
2356
2357 static void
2358 x_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w, int h)
2359 {
2360 if (s->stippled_p)
2361 {
2362 /* Fill background with a stipple pattern. */
2363 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2364 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
2365 XSetFillStyle (s->display, s->gc, FillSolid);
2366 }
2367 else
2368 x_clear_glyph_string_rect (s, x, y, w, h);
2369 }
2370
2371
2372 /* Draw image glyph string S.
2373
2374 s->y
2375 s->x +-------------------------
2376 | s->face->box
2377 |
2378 | +-------------------------
2379 | | s->img->margin
2380 | |
2381 | | +-------------------
2382 | | | the image
2383
2384 */
2385
2386 static void
2387 x_draw_image_glyph_string (struct glyph_string *s)
2388 {
2389 int box_line_hwidth = eabs (s->face->box_line_width);
2390 int box_line_vwidth = max (s->face->box_line_width, 0);
2391 int height;
2392 Pixmap pixmap = None;
2393
2394 height = s->height;
2395 if (s->slice.y == 0)
2396 height -= box_line_vwidth;
2397 if (s->slice.y + s->slice.height >= s->img->height)
2398 height -= box_line_vwidth;
2399
2400 /* Fill background with face under the image. Do it only if row is
2401 taller than image or if image has a clip mask to reduce
2402 flickering. */
2403 s->stippled_p = s->face->stipple != 0;
2404 if (height > s->slice.height
2405 || s->img->hmargin
2406 || s->img->vmargin
2407 || s->img->mask
2408 || s->img->pixmap == 0
2409 || s->width != s->background_width)
2410 {
2411 if (s->img->mask)
2412 {
2413 /* Create a pixmap as large as the glyph string. Fill it
2414 with the background color. Copy the image to it, using
2415 its mask. Copy the temporary pixmap to the display. */
2416 Screen *screen = FRAME_X_SCREEN (s->f);
2417 int depth = DefaultDepthOfScreen (screen);
2418
2419 /* Create a pixmap as large as the glyph string. */
2420 pixmap = XCreatePixmap (s->display, s->window,
2421 s->background_width,
2422 s->height, depth);
2423
2424 /* Don't clip in the following because we're working on the
2425 pixmap. */
2426 XSetClipMask (s->display, s->gc, None);
2427
2428 /* Fill the pixmap with the background color/stipple. */
2429 if (s->stippled_p)
2430 {
2431 /* Fill background with a stipple pattern. */
2432 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2433 XSetTSOrigin (s->display, s->gc, - s->x, - s->y);
2434 XFillRectangle (s->display, pixmap, s->gc,
2435 0, 0, s->background_width, s->height);
2436 XSetFillStyle (s->display, s->gc, FillSolid);
2437 XSetTSOrigin (s->display, s->gc, 0, 0);
2438 }
2439 else
2440 {
2441 XGCValues xgcv;
2442 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
2443 &xgcv);
2444 XSetForeground (s->display, s->gc, xgcv.background);
2445 XFillRectangle (s->display, pixmap, s->gc,
2446 0, 0, s->background_width, s->height);
2447 XSetForeground (s->display, s->gc, xgcv.foreground);
2448 }
2449 }
2450 else
2451 {
2452 int x = s->x;
2453 int y = s->y;
2454
2455 if (s->first_glyph->left_box_line_p
2456 && s->slice.x == 0)
2457 x += box_line_hwidth;
2458
2459 if (s->slice.y == 0)
2460 y += box_line_vwidth;
2461
2462 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
2463 }
2464
2465 s->background_filled_p = 1;
2466 }
2467
2468 /* Draw the foreground. */
2469 if (pixmap != None)
2470 {
2471 x_draw_image_foreground_1 (s, pixmap);
2472 x_set_glyph_string_clipping (s);
2473 XCopyArea (s->display, pixmap, s->window, s->gc,
2474 0, 0, s->background_width, s->height, s->x, s->y);
2475 XFreePixmap (s->display, pixmap);
2476 }
2477 else
2478 x_draw_image_foreground (s);
2479
2480 /* If we must draw a relief around the image, do it. */
2481 if (s->img->relief
2482 || s->hl == DRAW_IMAGE_RAISED
2483 || s->hl == DRAW_IMAGE_SUNKEN)
2484 x_draw_image_relief (s);
2485 }
2486
2487
2488 /* Draw stretch glyph string S. */
2489
2490 static void
2491 x_draw_stretch_glyph_string (struct glyph_string *s)
2492 {
2493 xassert (s->first_glyph->type == STRETCH_GLYPH);
2494
2495 if (s->hl == DRAW_CURSOR
2496 && !x_stretch_cursor_p)
2497 {
2498 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
2499 as wide as the stretch glyph. */
2500 int width, background_width = s->background_width;
2501 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
2502
2503 if (x < left_x)
2504 {
2505 background_width -= left_x - x;
2506 x = left_x;
2507 }
2508 width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
2509
2510 /* Draw cursor. */
2511 x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
2512
2513 /* Clear rest using the GC of the original non-cursor face. */
2514 if (width < background_width)
2515 {
2516 int y = s->y;
2517 int w = background_width - width, h = s->height;
2518 XRectangle r;
2519 GC gc;
2520
2521 x += width;
2522 if (s->row->mouse_face_p
2523 && cursor_in_mouse_face_p (s->w))
2524 {
2525 x_set_mouse_face_gc (s);
2526 gc = s->gc;
2527 }
2528 else
2529 gc = s->face->gc;
2530
2531 get_glyph_string_clip_rect (s, &r);
2532 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
2533
2534 if (s->face->stipple)
2535 {
2536 /* Fill background with a stipple pattern. */
2537 XSetFillStyle (s->display, gc, FillOpaqueStippled);
2538 XFillRectangle (s->display, s->window, gc, x, y, w, h);
2539 XSetFillStyle (s->display, gc, FillSolid);
2540 }
2541 else
2542 {
2543 XGCValues xgcv;
2544 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
2545 XSetForeground (s->display, gc, xgcv.background);
2546 XFillRectangle (s->display, s->window, gc, x, y, w, h);
2547 XSetForeground (s->display, gc, xgcv.foreground);
2548 }
2549 }
2550 }
2551 else if (!s->background_filled_p)
2552 {
2553 int background_width = s->background_width;
2554 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
2555
2556 /* Don't draw into left margin, fringe or scrollbar area
2557 except for header line and mode line. */
2558 if (x < left_x && !s->row->mode_line_p)
2559 {
2560 background_width -= left_x - x;
2561 x = left_x;
2562 }
2563 if (background_width > 0)
2564 x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
2565 }
2566
2567 s->background_filled_p = 1;
2568 }
2569
2570
2571 /* Draw glyph string S. */
2572
2573 static void
2574 x_draw_glyph_string (struct glyph_string *s)
2575 {
2576 int relief_drawn_p = 0;
2577
2578 /* If S draws into the background of its successors, draw the
2579 background of the successors first so that S can draw into it.
2580 This makes S->next use XDrawString instead of XDrawImageString. */
2581 if (s->next && s->right_overhang && !s->for_overlaps)
2582 {
2583 int width;
2584 struct glyph_string *next;
2585
2586 for (width = 0, next = s->next;
2587 next && width < s->right_overhang;
2588 width += next->width, next = next->next)
2589 if (next->first_glyph->type != IMAGE_GLYPH)
2590 {
2591 x_set_glyph_string_gc (next);
2592 x_set_glyph_string_clipping (next);
2593 if (next->first_glyph->type == STRETCH_GLYPH)
2594 x_draw_stretch_glyph_string (next);
2595 else
2596 x_draw_glyph_string_background (next, 1);
2597 next->num_clips = 0;
2598 }
2599 }
2600
2601 /* Set up S->gc, set clipping and draw S. */
2602 x_set_glyph_string_gc (s);
2603
2604 /* Draw relief (if any) in advance for char/composition so that the
2605 glyph string can be drawn over it. */
2606 if (!s->for_overlaps
2607 && s->face->box != FACE_NO_BOX
2608 && (s->first_glyph->type == CHAR_GLYPH
2609 || s->first_glyph->type == COMPOSITE_GLYPH))
2610
2611 {
2612 x_set_glyph_string_clipping (s);
2613 x_draw_glyph_string_background (s, 1);
2614 x_draw_glyph_string_box (s);
2615 x_set_glyph_string_clipping (s);
2616 relief_drawn_p = 1;
2617 }
2618 else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */
2619 && !s->clip_tail
2620 && ((s->prev && s->prev->hl != s->hl && s->left_overhang)
2621 || (s->next && s->next->hl != s->hl && s->right_overhang)))
2622 /* We must clip just this glyph. left_overhang part has already
2623 drawn when s->prev was drawn, and right_overhang part will be
2624 drawn later when s->next is drawn. */
2625 x_set_glyph_string_clipping_exactly (s, s);
2626 else
2627 x_set_glyph_string_clipping (s);
2628
2629 switch (s->first_glyph->type)
2630 {
2631 case IMAGE_GLYPH:
2632 x_draw_image_glyph_string (s);
2633 break;
2634
2635 case STRETCH_GLYPH:
2636 x_draw_stretch_glyph_string (s);
2637 break;
2638
2639 case CHAR_GLYPH:
2640 if (s->for_overlaps)
2641 s->background_filled_p = 1;
2642 else
2643 x_draw_glyph_string_background (s, 0);
2644 x_draw_glyph_string_foreground (s);
2645 break;
2646
2647 case COMPOSITE_GLYPH:
2648 if (s->for_overlaps || (s->cmp_from > 0
2649 && ! s->first_glyph->u.cmp.automatic))
2650 s->background_filled_p = 1;
2651 else
2652 x_draw_glyph_string_background (s, 1);
2653 x_draw_composite_glyph_string_foreground (s);
2654 break;
2655
2656 default:
2657 abort ();
2658 }
2659
2660 if (!s->for_overlaps)
2661 {
2662 /* Draw underline. */
2663 if (s->face->underline_p)
2664 {
2665 unsigned long thickness, position;
2666 int y;
2667
2668 if (s->prev && s->prev->face->underline_p)
2669 {
2670 /* We use the same underline style as the previous one. */
2671 thickness = s->prev->underline_thickness;
2672 position = s->prev->underline_position;
2673 }
2674 else
2675 {
2676 /* Get the underline thickness. Default is 1 pixel. */
2677 if (s->font && s->font->underline_thickness > 0)
2678 thickness = s->font->underline_thickness;
2679 else
2680 thickness = 1;
2681 if (x_underline_at_descent_line)
2682 position = (s->height - thickness) - (s->ybase - s->y);
2683 else
2684 {
2685 /* Get the underline position. This is the recommended
2686 vertical offset in pixels from the baseline to the top of
2687 the underline. This is a signed value according to the
2688 specs, and its default is
2689
2690 ROUND ((maximum descent) / 2), with
2691 ROUND(x) = floor (x + 0.5) */
2692
2693 if (x_use_underline_position_properties
2694 && s->font && s->font->underline_position >= 0)
2695 position = s->font->underline_position;
2696 else if (s->font)
2697 position = (s->font->descent + 1) / 2;
2698 else
2699 position = underline_minimum_offset;
2700 }
2701 position = max (position, underline_minimum_offset);
2702 }
2703 /* Check the sanity of thickness and position. We should
2704 avoid drawing underline out of the current line area. */
2705 if (s->y + s->height <= s->ybase + position)
2706 position = (s->height - 1) - (s->ybase - s->y);
2707 if (s->y + s->height < s->ybase + position + thickness)
2708 thickness = (s->y + s->height) - (s->ybase + position);
2709 s->underline_thickness = thickness;
2710 s->underline_position = position;
2711 y = s->ybase + position;
2712 if (s->face->underline_defaulted_p)
2713 XFillRectangle (s->display, s->window, s->gc,
2714 s->x, y, s->width, thickness);
2715 else
2716 {
2717 XGCValues xgcv;
2718 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2719 XSetForeground (s->display, s->gc, s->face->underline_color);
2720 XFillRectangle (s->display, s->window, s->gc,
2721 s->x, y, s->width, thickness);
2722 XSetForeground (s->display, s->gc, xgcv.foreground);
2723 }
2724 }
2725
2726 /* Draw overline. */
2727 if (s->face->overline_p)
2728 {
2729 unsigned long dy = 0, h = 1;
2730
2731 if (s->face->overline_color_defaulted_p)
2732 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2733 s->width, h);
2734 else
2735 {
2736 XGCValues xgcv;
2737 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2738 XSetForeground (s->display, s->gc, s->face->overline_color);
2739 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2740 s->width, h);
2741 XSetForeground (s->display, s->gc, xgcv.foreground);
2742 }
2743 }
2744
2745 /* Draw strike-through. */
2746 if (s->face->strike_through_p)
2747 {
2748 unsigned long h = 1;
2749 unsigned long dy = (s->height - h) / 2;
2750
2751 if (s->face->strike_through_color_defaulted_p)
2752 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2753 s->width, h);
2754 else
2755 {
2756 XGCValues xgcv;
2757 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2758 XSetForeground (s->display, s->gc, s->face->strike_through_color);
2759 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2760 s->width, h);
2761 XSetForeground (s->display, s->gc, xgcv.foreground);
2762 }
2763 }
2764
2765 /* Draw relief if not yet drawn. */
2766 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
2767 x_draw_glyph_string_box (s);
2768
2769 if (s->prev)
2770 {
2771 struct glyph_string *prev;
2772
2773 for (prev = s->prev; prev; prev = prev->prev)
2774 if (prev->hl != s->hl
2775 && prev->x + prev->width + prev->right_overhang > s->x)
2776 {
2777 /* As prev was drawn while clipped to its own area, we
2778 must draw the right_overhang part using s->hl now. */
2779 enum draw_glyphs_face save = prev->hl;
2780
2781 prev->hl = s->hl;
2782 x_set_glyph_string_gc (prev);
2783 x_set_glyph_string_clipping_exactly (s, prev);
2784 if (prev->first_glyph->type == CHAR_GLYPH)
2785 x_draw_glyph_string_foreground (prev);
2786 else
2787 x_draw_composite_glyph_string_foreground (prev);
2788 XSetClipMask (prev->display, prev->gc, None);
2789 prev->hl = save;
2790 prev->num_clips = 0;
2791 }
2792 }
2793
2794 if (s->next)
2795 {
2796 struct glyph_string *next;
2797
2798 for (next = s->next; next; next = next->next)
2799 if (next->hl != s->hl
2800 && next->x - next->left_overhang < s->x + s->width)
2801 {
2802 /* As next will be drawn while clipped to its own area,
2803 we must draw the left_overhang part using s->hl now. */
2804 enum draw_glyphs_face save = next->hl;
2805
2806 next->hl = s->hl;
2807 x_set_glyph_string_gc (next);
2808 x_set_glyph_string_clipping_exactly (s, next);
2809 if (next->first_glyph->type == CHAR_GLYPH)
2810 x_draw_glyph_string_foreground (next);
2811 else
2812 x_draw_composite_glyph_string_foreground (next);
2813 XSetClipMask (next->display, next->gc, None);
2814 next->hl = save;
2815 next->num_clips = 0;
2816 }
2817 }
2818 }
2819
2820 /* Reset clipping. */
2821 XSetClipMask (s->display, s->gc, None);
2822 s->num_clips = 0;
2823 }
2824
2825 /* Shift display to make room for inserted glyphs. */
2826
2827 void
2828 x_shift_glyphs_for_insert (struct frame *f, int x, int y, int width, int height, int shift_by)
2829 {
2830 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
2831 f->output_data.x->normal_gc,
2832 x, y, width, height,
2833 x + shift_by, y);
2834 }
2835
2836 /* Delete N glyphs at the nominal cursor position. Not implemented
2837 for X frames. */
2838
2839 static void
2840 x_delete_glyphs (struct frame *f, register int n)
2841 {
2842 abort ();
2843 }
2844
2845
2846 /* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
2847 If they are <= 0, this is probably an error. */
2848
2849 void
2850 x_clear_area (Display *dpy, Window window, int x, int y, int width, int height, int exposures)
2851 {
2852 xassert (width > 0 && height > 0);
2853 XClearArea (dpy, window, x, y, width, height, exposures);
2854 }
2855
2856
2857 /* Clear an entire frame. */
2858
2859 static void
2860 x_clear_frame (struct frame *f)
2861 {
2862 /* Clearing the frame will erase any cursor, so mark them all as no
2863 longer visible. */
2864 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
2865 output_cursor.hpos = output_cursor.vpos = 0;
2866 output_cursor.x = -1;
2867
2868 /* We don't set the output cursor here because there will always
2869 follow an explicit cursor_to. */
2870 BLOCK_INPUT;
2871 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
2872
2873 /* We have to clear the scroll bars, too. If we have changed
2874 colors or something like that, then they should be notified. */
2875 x_scroll_bar_clear (f);
2876
2877 #if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
2878 /* Make sure scroll bars are redrawn. As they aren't redrawn by
2879 redisplay, do it here. */
2880 gtk_widget_queue_draw (FRAME_GTK_WIDGET (f));
2881 #endif
2882
2883 XFlush (FRAME_X_DISPLAY (f));
2884
2885 UNBLOCK_INPUT;
2886 }
2887
2888
2889 \f
2890 /* Invert the middle quarter of the frame for .15 sec. */
2891
2892 /* We use the select system call to do the waiting, so we have to make
2893 sure it's available. If it isn't, we just won't do visual bells. */
2894
2895 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
2896
2897
2898 /* Subtract the `struct timeval' values X and Y, storing the result in
2899 *RESULT. Return 1 if the difference is negative, otherwise 0. */
2900
2901 static int
2902 timeval_subtract (struct timeval *result, struct timeval x, struct timeval y)
2903 {
2904 /* Perform the carry for the later subtraction by updating y. This
2905 is safer because on some systems the tv_sec member is unsigned. */
2906 if (x.tv_usec < y.tv_usec)
2907 {
2908 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
2909 y.tv_usec -= 1000000 * nsec;
2910 y.tv_sec += nsec;
2911 }
2912
2913 if (x.tv_usec - y.tv_usec > 1000000)
2914 {
2915 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
2916 y.tv_usec += 1000000 * nsec;
2917 y.tv_sec -= nsec;
2918 }
2919
2920 /* Compute the time remaining to wait. tv_usec is certainly
2921 positive. */
2922 result->tv_sec = x.tv_sec - y.tv_sec;
2923 result->tv_usec = x.tv_usec - y.tv_usec;
2924
2925 /* Return indication of whether the result should be considered
2926 negative. */
2927 return x.tv_sec < y.tv_sec;
2928 }
2929
2930 void
2931 XTflash (struct frame *f)
2932 {
2933 BLOCK_INPUT;
2934
2935 {
2936 #ifdef USE_GTK
2937 /* Use Gdk routines to draw. This way, we won't draw over scroll bars
2938 when the scroll bars and the edit widget share the same X window. */
2939 GdkWindow *window = gtk_widget_get_window (FRAME_GTK_WIDGET (f));
2940 GdkGCValues vals;
2941 GdkGC *gc;
2942 vals.foreground.pixel = (FRAME_FOREGROUND_PIXEL (f)
2943 ^ FRAME_BACKGROUND_PIXEL (f));
2944 vals.function = GDK_XOR;
2945 gc = gdk_gc_new_with_values (window,
2946 &vals, GDK_GC_FUNCTION | GDK_GC_FOREGROUND);
2947 #define XFillRectangle(d, win, gc, x, y, w, h) \
2948 gdk_draw_rectangle (window, gc, TRUE, x, y, w, h)
2949 #else
2950 GC gc;
2951
2952 /* Create a GC that will use the GXxor function to flip foreground
2953 pixels into background pixels. */
2954 {
2955 XGCValues values;
2956
2957 values.function = GXxor;
2958 values.foreground = (FRAME_FOREGROUND_PIXEL (f)
2959 ^ FRAME_BACKGROUND_PIXEL (f));
2960
2961 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2962 GCFunction | GCForeground, &values);
2963 }
2964 #endif
2965 {
2966 /* Get the height not including a menu bar widget. */
2967 int height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f));
2968 /* Height of each line to flash. */
2969 int flash_height = FRAME_LINE_HEIGHT (f);
2970 /* These will be the left and right margins of the rectangles. */
2971 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
2972 int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
2973
2974 int width;
2975
2976 /* Don't flash the area between a scroll bar and the frame
2977 edge it is next to. */
2978 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
2979 {
2980 case vertical_scroll_bar_left:
2981 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
2982 break;
2983
2984 case vertical_scroll_bar_right:
2985 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
2986 break;
2987
2988 default:
2989 break;
2990 }
2991
2992 width = flash_right - flash_left;
2993
2994 /* If window is tall, flash top and bottom line. */
2995 if (height > 3 * FRAME_LINE_HEIGHT (f))
2996 {
2997 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
2998 flash_left,
2999 (FRAME_INTERNAL_BORDER_WIDTH (f)
3000 + FRAME_TOP_MARGIN_HEIGHT (f)),
3001 width, flash_height);
3002 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3003 flash_left,
3004 (height - flash_height
3005 - FRAME_INTERNAL_BORDER_WIDTH (f)),
3006 width, flash_height);
3007
3008 }
3009 else
3010 /* If it is short, flash it all. */
3011 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3012 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
3013 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
3014
3015 x_flush (f);
3016
3017 {
3018 struct timeval wakeup;
3019
3020 EMACS_GET_TIME (wakeup);
3021
3022 /* Compute time to wait until, propagating carry from usecs. */
3023 wakeup.tv_usec += 150000;
3024 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
3025 wakeup.tv_usec %= 1000000;
3026
3027 /* Keep waiting until past the time wakeup or any input gets
3028 available. */
3029 while (! detect_input_pending ())
3030 {
3031 struct timeval current;
3032 struct timeval timeout;
3033
3034 EMACS_GET_TIME (current);
3035
3036 /* Break if result would be negative. */
3037 if (timeval_subtract (&current, wakeup, current))
3038 break;
3039
3040 /* How long `select' should wait. */
3041 timeout.tv_sec = 0;
3042 timeout.tv_usec = 10000;
3043
3044 /* Try to wait that long--but we might wake up sooner. */
3045 select (0, NULL, NULL, NULL, &timeout);
3046 }
3047 }
3048
3049 /* If window is tall, flash top and bottom line. */
3050 if (height > 3 * FRAME_LINE_HEIGHT (f))
3051 {
3052 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3053 flash_left,
3054 (FRAME_INTERNAL_BORDER_WIDTH (f)
3055 + FRAME_TOP_MARGIN_HEIGHT (f)),
3056 width, flash_height);
3057 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3058 flash_left,
3059 (height - flash_height
3060 - FRAME_INTERNAL_BORDER_WIDTH (f)),
3061 width, flash_height);
3062 }
3063 else
3064 /* If it is short, flash it all. */
3065 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3066 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
3067 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
3068
3069 #ifdef USE_GTK
3070 g_object_unref (G_OBJECT (gc));
3071 #undef XFillRectangle
3072 #else
3073 XFreeGC (FRAME_X_DISPLAY (f), gc);
3074 #endif
3075 x_flush (f);
3076 }
3077 }
3078
3079 UNBLOCK_INPUT;
3080 }
3081
3082 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3083
3084
3085 static void
3086 XTtoggle_invisible_pointer (FRAME_PTR f, int invisible)
3087 {
3088 BLOCK_INPUT;
3089 if (invisible)
3090 {
3091 if (FRAME_X_DISPLAY_INFO (f)->invisible_cursor != 0)
3092 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3093 FRAME_X_DISPLAY_INFO (f)->invisible_cursor);
3094 }
3095 else
3096 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3097 f->output_data.x->current_cursor);
3098 f->pointer_invisible = invisible;
3099 UNBLOCK_INPUT;
3100 }
3101
3102
3103 /* Make audible bell. */
3104
3105 void
3106 XTring_bell (void)
3107 {
3108 struct frame *f = SELECTED_FRAME ();
3109
3110 if (FRAME_X_DISPLAY (f))
3111 {
3112 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3113 if (visible_bell)
3114 XTflash (f);
3115 else
3116 #endif
3117 {
3118 BLOCK_INPUT;
3119 XBell (FRAME_X_DISPLAY (f), 0);
3120 XFlush (FRAME_X_DISPLAY (f));
3121 UNBLOCK_INPUT;
3122 }
3123 }
3124 }
3125
3126 \f
3127 /* Specify how many text lines, from the top of the window,
3128 should be affected by insert-lines and delete-lines operations.
3129 This, and those operations, are used only within an update
3130 that is bounded by calls to x_update_begin and x_update_end. */
3131
3132 static void
3133 XTset_terminal_window (register int n)
3134 {
3135 /* This function intentionally left blank. */
3136 }
3137
3138
3139 \f
3140 /***********************************************************************
3141 Line Dance
3142 ***********************************************************************/
3143
3144 /* Perform an insert-lines or delete-lines operation, inserting N
3145 lines or deleting -N lines at vertical position VPOS. */
3146
3147 static void
3148 x_ins_del_lines (struct frame *f, int vpos, int n)
3149 {
3150 abort ();
3151 }
3152
3153
3154 /* Scroll part of the display as described by RUN. */
3155
3156 static void
3157 x_scroll_run (struct window *w, struct run *run)
3158 {
3159 struct frame *f = XFRAME (w->frame);
3160 int x, y, width, height, from_y, to_y, bottom_y;
3161
3162 /* Get frame-relative bounding box of the text display area of W,
3163 without mode lines. Include in this box the left and right
3164 fringe of W. */
3165 window_box (w, -1, &x, &y, &width, &height);
3166
3167 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
3168 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
3169 bottom_y = y + height;
3170
3171 if (to_y < from_y)
3172 {
3173 /* Scrolling up. Make sure we don't copy part of the mode
3174 line at the bottom. */
3175 if (from_y + run->height > bottom_y)
3176 height = bottom_y - from_y;
3177 else
3178 height = run->height;
3179 }
3180 else
3181 {
3182 /* Scolling down. Make sure we don't copy over the mode line.
3183 at the bottom. */
3184 if (to_y + run->height > bottom_y)
3185 height = bottom_y - to_y;
3186 else
3187 height = run->height;
3188 }
3189
3190 BLOCK_INPUT;
3191
3192 /* Cursor off. Will be switched on again in x_update_window_end. */
3193 updated_window = w;
3194 x_clear_cursor (w);
3195
3196 XCopyArea (FRAME_X_DISPLAY (f),
3197 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
3198 f->output_data.x->normal_gc,
3199 x, from_y,
3200 width, height,
3201 x, to_y);
3202
3203 UNBLOCK_INPUT;
3204 }
3205
3206
3207 \f
3208 /***********************************************************************
3209 Exposure Events
3210 ***********************************************************************/
3211
3212 \f
3213 static void
3214 frame_highlight (struct frame *f)
3215 {
3216 /* We used to only do this if Vx_no_window_manager was non-nil, but
3217 the ICCCM (section 4.1.6) says that the window's border pixmap
3218 and border pixel are window attributes which are "private to the
3219 client", so we can always change it to whatever we want. */
3220 BLOCK_INPUT;
3221 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3222 f->output_data.x->border_pixel);
3223 UNBLOCK_INPUT;
3224 x_update_cursor (f, 1);
3225 x_set_frame_alpha (f);
3226 }
3227
3228 static void
3229 frame_unhighlight (struct frame *f)
3230 {
3231 /* We used to only do this if Vx_no_window_manager was non-nil, but
3232 the ICCCM (section 4.1.6) says that the window's border pixmap
3233 and border pixel are window attributes which are "private to the
3234 client", so we can always change it to whatever we want. */
3235 BLOCK_INPUT;
3236 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3237 f->output_data.x->border_tile);
3238 UNBLOCK_INPUT;
3239 x_update_cursor (f, 1);
3240 x_set_frame_alpha (f);
3241 }
3242
3243 /* The focus has changed. Update the frames as necessary to reflect
3244 the new situation. Note that we can't change the selected frame
3245 here, because the Lisp code we are interrupting might become confused.
3246 Each event gets marked with the frame in which it occurred, so the
3247 Lisp code can tell when the switch took place by examining the events. */
3248
3249 static void
3250 x_new_focus_frame (struct x_display_info *dpyinfo, struct frame *frame)
3251 {
3252 struct frame *old_focus = dpyinfo->x_focus_frame;
3253
3254 if (frame != dpyinfo->x_focus_frame)
3255 {
3256 /* Set this before calling other routines, so that they see
3257 the correct value of x_focus_frame. */
3258 dpyinfo->x_focus_frame = frame;
3259
3260 if (old_focus && old_focus->auto_lower)
3261 x_lower_frame (old_focus);
3262
3263 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
3264 pending_autoraise_frame = dpyinfo->x_focus_frame;
3265 else
3266 pending_autoraise_frame = 0;
3267 }
3268
3269 x_frame_rehighlight (dpyinfo);
3270 }
3271
3272 /* Handle FocusIn and FocusOut state changes for FRAME.
3273 If FRAME has focus and there exists more than one frame, puts
3274 a FOCUS_IN_EVENT into *BUFP. */
3275
3276 static void
3277 x_focus_changed (int type, int state, struct x_display_info *dpyinfo, struct frame *frame, struct input_event *bufp)
3278 {
3279 if (type == FocusIn)
3280 {
3281 if (dpyinfo->x_focus_event_frame != frame)
3282 {
3283 x_new_focus_frame (dpyinfo, frame);
3284 dpyinfo->x_focus_event_frame = frame;
3285
3286 /* Don't stop displaying the initial startup message
3287 for a switch-frame event we don't need. */
3288 if (NILP (Vterminal_frame)
3289 && CONSP (Vframe_list)
3290 && !NILP (XCDR (Vframe_list)))
3291 {
3292 bufp->kind = FOCUS_IN_EVENT;
3293 XSETFRAME (bufp->frame_or_window, frame);
3294 }
3295 }
3296
3297 frame->output_data.x->focus_state |= state;
3298
3299 #ifdef HAVE_X_I18N
3300 if (FRAME_XIC (frame))
3301 XSetICFocus (FRAME_XIC (frame));
3302 #endif
3303 }
3304 else if (type == FocusOut)
3305 {
3306 frame->output_data.x->focus_state &= ~state;
3307
3308 if (dpyinfo->x_focus_event_frame == frame)
3309 {
3310 dpyinfo->x_focus_event_frame = 0;
3311 x_new_focus_frame (dpyinfo, 0);
3312 }
3313
3314 #ifdef HAVE_X_I18N
3315 if (FRAME_XIC (frame))
3316 XUnsetICFocus (FRAME_XIC (frame));
3317 #endif
3318 if (frame->pointer_invisible)
3319 XTtoggle_invisible_pointer (frame, 0);
3320 }
3321 }
3322
3323 /* The focus may have changed. Figure out if it is a real focus change,
3324 by checking both FocusIn/Out and Enter/LeaveNotify events.
3325
3326 Returns FOCUS_IN_EVENT event in *BUFP. */
3327
3328 static void
3329 x_detect_focus_change (struct x_display_info *dpyinfo, XEvent *event, struct input_event *bufp)
3330 {
3331 struct frame *frame;
3332
3333 frame = x_any_window_to_frame (dpyinfo, event->xany.window);
3334 if (! frame)
3335 return;
3336
3337 switch (event->type)
3338 {
3339 case EnterNotify:
3340 case LeaveNotify:
3341 {
3342 struct frame *focus_frame = dpyinfo->x_focus_event_frame;
3343 int focus_state
3344 = focus_frame ? focus_frame->output_data.x->focus_state : 0;
3345
3346 if (event->xcrossing.detail != NotifyInferior
3347 && event->xcrossing.focus
3348 && ! (focus_state & FOCUS_EXPLICIT))
3349 x_focus_changed ((event->type == EnterNotify ? FocusIn : FocusOut),
3350 FOCUS_IMPLICIT,
3351 dpyinfo, frame, bufp);
3352 }
3353 break;
3354
3355 case FocusIn:
3356 case FocusOut:
3357 x_focus_changed (event->type,
3358 (event->xfocus.detail == NotifyPointer ?
3359 FOCUS_IMPLICIT : FOCUS_EXPLICIT),
3360 dpyinfo, frame, bufp);
3361 break;
3362
3363 case ClientMessage:
3364 if (event->xclient.message_type == dpyinfo->Xatom_XEMBED)
3365 {
3366 enum xembed_message msg = event->xclient.data.l[1];
3367 x_focus_changed ((msg == XEMBED_FOCUS_IN ? FocusIn : FocusOut),
3368 FOCUS_EXPLICIT, dpyinfo, frame, bufp);
3369 }
3370 break;
3371 }
3372 }
3373
3374
3375 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3376
3377 void
3378 x_mouse_leave (struct x_display_info *dpyinfo)
3379 {
3380 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
3381 }
3382
3383 /* The focus has changed, or we have redirected a frame's focus to
3384 another frame (this happens when a frame uses a surrogate
3385 mini-buffer frame). Shift the highlight as appropriate.
3386
3387 The FRAME argument doesn't necessarily have anything to do with which
3388 frame is being highlighted or un-highlighted; we only use it to find
3389 the appropriate X display info. */
3390
3391 static void
3392 XTframe_rehighlight (struct frame *frame)
3393 {
3394 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
3395 }
3396
3397 static void
3398 x_frame_rehighlight (struct x_display_info *dpyinfo)
3399 {
3400 struct frame *old_highlight = dpyinfo->x_highlight_frame;
3401
3402 if (dpyinfo->x_focus_frame)
3403 {
3404 dpyinfo->x_highlight_frame
3405 = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
3406 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
3407 : dpyinfo->x_focus_frame);
3408 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
3409 {
3410 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
3411 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
3412 }
3413 }
3414 else
3415 dpyinfo->x_highlight_frame = 0;
3416
3417 if (dpyinfo->x_highlight_frame != old_highlight)
3418 {
3419 if (old_highlight)
3420 frame_unhighlight (old_highlight);
3421 if (dpyinfo->x_highlight_frame)
3422 frame_highlight (dpyinfo->x_highlight_frame);
3423 }
3424 }
3425
3426
3427 \f
3428 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3429
3430 /* Initialize mode_switch_bit and modifier_meaning. */
3431 static void
3432 x_find_modifier_meanings (struct x_display_info *dpyinfo)
3433 {
3434 int min_code, max_code;
3435 KeySym *syms;
3436 int syms_per_code;
3437 XModifierKeymap *mods;
3438
3439 dpyinfo->meta_mod_mask = 0;
3440 dpyinfo->shift_lock_mask = 0;
3441 dpyinfo->alt_mod_mask = 0;
3442 dpyinfo->super_mod_mask = 0;
3443 dpyinfo->hyper_mod_mask = 0;
3444
3445 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
3446
3447 syms = XGetKeyboardMapping (dpyinfo->display,
3448 min_code, max_code - min_code + 1,
3449 &syms_per_code);
3450 mods = XGetModifierMapping (dpyinfo->display);
3451
3452 /* Scan the modifier table to see which modifier bits the Meta and
3453 Alt keysyms are on. */
3454 {
3455 int row, col; /* The row and column in the modifier table. */
3456 int found_alt_or_meta;
3457
3458 for (row = 3; row < 8; row++)
3459 {
3460 found_alt_or_meta = 0;
3461 for (col = 0; col < mods->max_keypermod; col++)
3462 {
3463 KeyCode code = mods->modifiermap[(row * mods->max_keypermod) + col];
3464
3465 /* Zeroes are used for filler. Skip them. */
3466 if (code == 0)
3467 continue;
3468
3469 /* Are any of this keycode's keysyms a meta key? */
3470 {
3471 int code_col;
3472
3473 for (code_col = 0; code_col < syms_per_code; code_col++)
3474 {
3475 int sym = syms[((code - min_code) * syms_per_code) + code_col];
3476
3477 switch (sym)
3478 {
3479 case XK_Meta_L:
3480 case XK_Meta_R:
3481 found_alt_or_meta = 1;
3482 dpyinfo->meta_mod_mask |= (1 << row);
3483 break;
3484
3485 case XK_Alt_L:
3486 case XK_Alt_R:
3487 found_alt_or_meta = 1;
3488 dpyinfo->alt_mod_mask |= (1 << row);
3489 break;
3490
3491 case XK_Hyper_L:
3492 case XK_Hyper_R:
3493 if (!found_alt_or_meta)
3494 dpyinfo->hyper_mod_mask |= (1 << row);
3495 code_col = syms_per_code;
3496 col = mods->max_keypermod;
3497 break;
3498
3499 case XK_Super_L:
3500 case XK_Super_R:
3501 if (!found_alt_or_meta)
3502 dpyinfo->super_mod_mask |= (1 << row);
3503 code_col = syms_per_code;
3504 col = mods->max_keypermod;
3505 break;
3506
3507 case XK_Shift_Lock:
3508 /* Ignore this if it's not on the lock modifier. */
3509 if (!found_alt_or_meta && ((1 << row) == LockMask))
3510 dpyinfo->shift_lock_mask = LockMask;
3511 code_col = syms_per_code;
3512 col = mods->max_keypermod;
3513 break;
3514 }
3515 }
3516 }
3517 }
3518 }
3519 }
3520
3521 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3522 if (! dpyinfo->meta_mod_mask)
3523 {
3524 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
3525 dpyinfo->alt_mod_mask = 0;
3526 }
3527
3528 /* If some keys are both alt and meta,
3529 make them just meta, not alt. */
3530 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
3531 {
3532 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
3533 }
3534
3535 XFree ((char *) syms);
3536 XFreeModifiermap (mods);
3537 }
3538
3539 /* Convert between the modifier bits X uses and the modifier bits
3540 Emacs uses. */
3541
3542 unsigned int
3543 x_x_to_emacs_modifiers (struct x_display_info *dpyinfo, unsigned int state)
3544 {
3545 EMACS_UINT mod_meta = meta_modifier;
3546 EMACS_UINT mod_alt = alt_modifier;
3547 EMACS_UINT mod_hyper = hyper_modifier;
3548 EMACS_UINT mod_super = super_modifier;
3549 Lisp_Object tem;
3550
3551 tem = Fget (Vx_alt_keysym, Qmodifier_value);
3552 if (! EQ (tem, Qnil)) mod_alt = XUINT (tem);
3553 tem = Fget (Vx_meta_keysym, Qmodifier_value);
3554 if (! EQ (tem, Qnil)) mod_meta = XUINT (tem);
3555 tem = Fget (Vx_hyper_keysym, Qmodifier_value);
3556 if (! EQ (tem, Qnil)) mod_hyper = XUINT (tem);
3557 tem = Fget (Vx_super_keysym, Qmodifier_value);
3558 if (! EQ (tem, Qnil)) mod_super = XUINT (tem);
3559
3560
3561 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
3562 | ((state & ControlMask) ? ctrl_modifier : 0)
3563 | ((state & dpyinfo->meta_mod_mask) ? mod_meta : 0)
3564 | ((state & dpyinfo->alt_mod_mask) ? mod_alt : 0)
3565 | ((state & dpyinfo->super_mod_mask) ? mod_super : 0)
3566 | ((state & dpyinfo->hyper_mod_mask) ? mod_hyper : 0));
3567 }
3568
3569 static unsigned int
3570 x_emacs_to_x_modifiers (struct x_display_info *dpyinfo, unsigned int state)
3571 {
3572 EMACS_UINT mod_meta = meta_modifier;
3573 EMACS_UINT mod_alt = alt_modifier;
3574 EMACS_UINT mod_hyper = hyper_modifier;
3575 EMACS_UINT mod_super = super_modifier;
3576
3577 Lisp_Object tem;
3578
3579 tem = Fget (Vx_alt_keysym, Qmodifier_value);
3580 if (! EQ (tem, Qnil)) mod_alt = XUINT (tem);
3581 tem = Fget (Vx_meta_keysym, Qmodifier_value);
3582 if (! EQ (tem, Qnil)) mod_meta = XUINT (tem);
3583 tem = Fget (Vx_hyper_keysym, Qmodifier_value);
3584 if (! EQ (tem, Qnil)) mod_hyper = XUINT (tem);
3585 tem = Fget (Vx_super_keysym, Qmodifier_value);
3586 if (! EQ (tem, Qnil)) mod_super = XUINT (tem);
3587
3588
3589 return ( ((state & mod_alt) ? dpyinfo->alt_mod_mask : 0)
3590 | ((state & mod_super) ? dpyinfo->super_mod_mask : 0)
3591 | ((state & mod_hyper) ? dpyinfo->hyper_mod_mask : 0)
3592 | ((state & shift_modifier) ? ShiftMask : 0)
3593 | ((state & ctrl_modifier) ? ControlMask : 0)
3594 | ((state & mod_meta) ? dpyinfo->meta_mod_mask : 0));
3595 }
3596
3597 /* Convert a keysym to its name. */
3598
3599 char *
3600 x_get_keysym_name (KeySym keysym)
3601 {
3602 char *value;
3603
3604 BLOCK_INPUT;
3605 value = XKeysymToString (keysym);
3606 UNBLOCK_INPUT;
3607
3608 return value;
3609 }
3610
3611
3612 \f
3613 /* Mouse clicks and mouse movement. Rah. */
3614
3615 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3616
3617 If the event is a button press, then note that we have grabbed
3618 the mouse. */
3619
3620 static Lisp_Object
3621 construct_mouse_click (struct input_event *result, XButtonEvent *event, struct frame *f)
3622 {
3623 /* Make the event type NO_EVENT; we'll change that when we decide
3624 otherwise. */
3625 result->kind = MOUSE_CLICK_EVENT;
3626 result->code = event->button - Button1;
3627 result->timestamp = event->time;
3628 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
3629 event->state)
3630 | (event->type == ButtonRelease
3631 ? up_modifier
3632 : down_modifier));
3633
3634 XSETINT (result->x, event->x);
3635 XSETINT (result->y, event->y);
3636 XSETFRAME (result->frame_or_window, f);
3637 result->arg = Qnil;
3638 return Qnil;
3639 }
3640
3641 \f
3642 /* Function to report a mouse movement to the mainstream Emacs code.
3643 The input handler calls this.
3644
3645 We have received a mouse movement event, which is given in *event.
3646 If the mouse is over a different glyph than it was last time, tell
3647 the mainstream emacs code by setting mouse_moved. If not, ask for
3648 another motion event, so we can check again the next time it moves. */
3649
3650 static XMotionEvent last_mouse_motion_event;
3651 static Lisp_Object last_mouse_motion_frame;
3652
3653 static int
3654 note_mouse_movement (FRAME_PTR frame, XMotionEvent *event)
3655 {
3656 last_mouse_movement_time = event->time;
3657 last_mouse_motion_event = *event;
3658 XSETFRAME (last_mouse_motion_frame, frame);
3659
3660 if (!FRAME_X_OUTPUT (frame))
3661 return 0;
3662
3663 if (event->window != FRAME_X_WINDOW (frame))
3664 {
3665 frame->mouse_moved = 1;
3666 last_mouse_scroll_bar = Qnil;
3667 note_mouse_highlight (frame, -1, -1);
3668 last_mouse_glyph_frame = 0;
3669 return 1;
3670 }
3671
3672
3673 /* Has the mouse moved off the glyph it was on at the last sighting? */
3674 if (frame != last_mouse_glyph_frame
3675 || event->x < last_mouse_glyph.x
3676 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
3677 || event->y < last_mouse_glyph.y
3678 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
3679 {
3680 frame->mouse_moved = 1;
3681 last_mouse_scroll_bar = Qnil;
3682 note_mouse_highlight (frame, event->x, event->y);
3683 /* Remember which glyph we're now on. */
3684 remember_mouse_glyph (frame, event->x, event->y, &last_mouse_glyph);
3685 last_mouse_glyph_frame = frame;
3686 return 1;
3687 }
3688
3689 return 0;
3690 }
3691
3692 \f
3693 /************************************************************************
3694 Mouse Face
3695 ************************************************************************/
3696
3697 static void
3698 redo_mouse_highlight (void)
3699 {
3700 if (!NILP (last_mouse_motion_frame)
3701 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
3702 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
3703 last_mouse_motion_event.x,
3704 last_mouse_motion_event.y);
3705 }
3706
3707
3708
3709 /* Return the current position of the mouse.
3710 *FP should be a frame which indicates which display to ask about.
3711
3712 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
3713 and *PART to the frame, window, and scroll bar part that the mouse
3714 is over. Set *X and *Y to the portion and whole of the mouse's
3715 position on the scroll bar.
3716
3717 If the mouse movement started elsewhere, set *FP to the frame the
3718 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
3719 the mouse is over.
3720
3721 Set *TIME to the server time-stamp for the time at which the mouse
3722 was at this position.
3723
3724 Don't store anything if we don't have a valid set of values to report.
3725
3726 This clears the mouse_moved flag, so we can wait for the next mouse
3727 movement. */
3728
3729 static void
3730 XTmouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window, enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y, long unsigned int *time)
3731 {
3732 FRAME_PTR f1;
3733
3734 BLOCK_INPUT;
3735
3736 if (! NILP (last_mouse_scroll_bar) && insist == 0)
3737 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
3738 else
3739 {
3740 Window root;
3741 int root_x, root_y;
3742
3743 Window dummy_window;
3744 int dummy;
3745
3746 Lisp_Object frame, tail;
3747
3748 /* Clear the mouse-moved flag for every frame on this display. */
3749 FOR_EACH_FRAME (tail, frame)
3750 if (FRAME_X_P (XFRAME (frame))
3751 && FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
3752 XFRAME (frame)->mouse_moved = 0;
3753
3754 last_mouse_scroll_bar = Qnil;
3755
3756 /* Figure out which root window we're on. */
3757 XQueryPointer (FRAME_X_DISPLAY (*fp),
3758 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
3759
3760 /* The root window which contains the pointer. */
3761 &root,
3762
3763 /* Trash which we can't trust if the pointer is on
3764 a different screen. */
3765 &dummy_window,
3766
3767 /* The position on that root window. */
3768 &root_x, &root_y,
3769
3770 /* More trash we can't trust. */
3771 &dummy, &dummy,
3772
3773 /* Modifier keys and pointer buttons, about which
3774 we don't care. */
3775 (unsigned int *) &dummy);
3776
3777 /* Now we have a position on the root; find the innermost window
3778 containing the pointer. */
3779 {
3780 Window win, child;
3781 int win_x, win_y;
3782 int parent_x = 0, parent_y = 0;
3783
3784 win = root;
3785
3786 /* XTranslateCoordinates can get errors if the window
3787 structure is changing at the same time this function
3788 is running. So at least we must not crash from them. */
3789
3790 x_catch_errors (FRAME_X_DISPLAY (*fp));
3791
3792 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
3793 && FRAME_LIVE_P (last_mouse_frame))
3794 {
3795 /* If mouse was grabbed on a frame, give coords for that frame
3796 even if the mouse is now outside it. */
3797 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
3798
3799 /* From-window, to-window. */
3800 root, FRAME_X_WINDOW (last_mouse_frame),
3801
3802 /* From-position, to-position. */
3803 root_x, root_y, &win_x, &win_y,
3804
3805 /* Child of win. */
3806 &child);
3807 f1 = last_mouse_frame;
3808 }
3809 else
3810 {
3811 while (1)
3812 {
3813 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
3814
3815 /* From-window, to-window. */
3816 root, win,
3817
3818 /* From-position, to-position. */
3819 root_x, root_y, &win_x, &win_y,
3820
3821 /* Child of win. */
3822 &child);
3823
3824 if (child == None || child == win)
3825 break;
3826 #ifdef USE_GTK
3827 /* We don't wan't to know the innermost window. We
3828 want the edit window. For non-Gtk+ the innermost
3829 window is the edit window. For Gtk+ it might not
3830 be. It might be the tool bar for example. */
3831 if (x_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win))
3832 break;
3833 #endif
3834 win = child;
3835 parent_x = win_x;
3836 parent_y = win_y;
3837 }
3838
3839 /* Now we know that:
3840 win is the innermost window containing the pointer
3841 (XTC says it has no child containing the pointer),
3842 win_x and win_y are the pointer's position in it
3843 (XTC did this the last time through), and
3844 parent_x and parent_y are the pointer's position in win's parent.
3845 (They are what win_x and win_y were when win was child.
3846 If win is the root window, it has no parent, and
3847 parent_{x,y} are invalid, but that's okay, because we'll
3848 never use them in that case.) */
3849
3850 #ifdef USE_GTK
3851 /* We don't wan't to know the innermost window. We
3852 want the edit window. */
3853 f1 = x_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
3854 #else
3855 /* Is win one of our frames? */
3856 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
3857 #endif
3858
3859 #ifdef USE_X_TOOLKIT
3860 /* If we end up with the menu bar window, say it's not
3861 on the frame. */
3862 if (f1 != NULL
3863 && f1->output_data.x->menubar_widget
3864 && win == XtWindow (f1->output_data.x->menubar_widget))
3865 f1 = NULL;
3866 #endif /* USE_X_TOOLKIT */
3867 }
3868
3869 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
3870 f1 = 0;
3871
3872 x_uncatch_errors ();
3873
3874 /* If not, is it one of our scroll bars? */
3875 if (! f1)
3876 {
3877 struct scroll_bar *bar;
3878
3879 bar = x_window_to_scroll_bar (FRAME_X_DISPLAY (*fp), win);
3880
3881 if (bar)
3882 {
3883 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
3884 win_x = parent_x;
3885 win_y = parent_y;
3886 }
3887 }
3888
3889 if (f1 == 0 && insist > 0)
3890 f1 = SELECTED_FRAME ();
3891
3892 if (f1)
3893 {
3894 /* Ok, we found a frame. Store all the values.
3895 last_mouse_glyph is a rectangle used to reduce the
3896 generation of mouse events. To not miss any motion
3897 events, we must divide the frame into rectangles of the
3898 size of the smallest character that could be displayed
3899 on it, i.e. into the same rectangles that matrices on
3900 the frame are divided into. */
3901
3902 remember_mouse_glyph (f1, win_x, win_y, &last_mouse_glyph);
3903 last_mouse_glyph_frame = f1;
3904
3905 *bar_window = Qnil;
3906 *part = 0;
3907 *fp = f1;
3908 XSETINT (*x, win_x);
3909 XSETINT (*y, win_y);
3910 *time = last_mouse_movement_time;
3911 }
3912 }
3913 }
3914
3915 UNBLOCK_INPUT;
3916 }
3917
3918
3919 \f
3920 /***********************************************************************
3921 Scroll bars
3922 ***********************************************************************/
3923
3924 /* Scroll bar support. */
3925
3926 /* Given an X window ID and a DISPLAY, find the struct scroll_bar which
3927 manages it.
3928 This can be called in GC, so we have to make sure to strip off mark
3929 bits. */
3930
3931 static struct scroll_bar *
3932 x_window_to_scroll_bar (Display *display, Window window_id)
3933 {
3934 Lisp_Object tail;
3935
3936 #if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
3937 window_id = (Window) xg_get_scroll_id_for_window (display, window_id);
3938 #endif /* USE_GTK && USE_TOOLKIT_SCROLL_BARS */
3939
3940 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
3941 {
3942 Lisp_Object frame, bar, condemned;
3943
3944 frame = XCAR (tail);
3945 /* All elements of Vframe_list should be frames. */
3946 if (! FRAMEP (frame))
3947 abort ();
3948
3949 if (! FRAME_X_P (XFRAME (frame)))
3950 continue;
3951
3952 /* Scan this frame's scroll bar list for a scroll bar with the
3953 right window ID. */
3954 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
3955 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
3956 /* This trick allows us to search both the ordinary and
3957 condemned scroll bar lists with one loop. */
3958 ! NILP (bar) || (bar = condemned,
3959 condemned = Qnil,
3960 ! NILP (bar));
3961 bar = XSCROLL_BAR (bar)->next)
3962 if (XSCROLL_BAR (bar)->x_window == window_id &&
3963 FRAME_X_DISPLAY (XFRAME (frame)) == display)
3964 return XSCROLL_BAR (bar);
3965 }
3966
3967 return 0;
3968 }
3969
3970
3971 #if defined USE_LUCID
3972
3973 /* Return the Lucid menu bar WINDOW is part of. Return null
3974 if WINDOW is not part of a menu bar. */
3975
3976 static Widget
3977 x_window_to_menu_bar (window)
3978 Window window;
3979 {
3980 Lisp_Object tail;
3981
3982 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
3983 {
3984 if (FRAME_X_P (XFRAME (XCAR (tail))))
3985 {
3986 Lisp_Object frame = XCAR (tail);
3987 Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
3988
3989 if (menu_bar && xlwmenu_window_p (menu_bar, window))
3990 return menu_bar;
3991 }
3992 }
3993
3994 return NULL;
3995 }
3996
3997 #endif /* USE_LUCID */
3998
3999 \f
4000 /************************************************************************
4001 Toolkit scroll bars
4002 ************************************************************************/
4003
4004 #ifdef USE_TOOLKIT_SCROLL_BARS
4005
4006 static void x_scroll_bar_to_input_event (XEvent *, struct input_event *);
4007 static void x_send_scroll_bar_event (Lisp_Object, int, int, int);
4008 static void x_create_toolkit_scroll_bar (struct frame *,
4009 struct scroll_bar *);
4010 static void x_set_toolkit_scroll_bar_thumb (struct scroll_bar *,
4011 int, int, int);
4012
4013
4014 /* Lisp window being scrolled. Set when starting to interact with
4015 a toolkit scroll bar, reset to nil when ending the interaction. */
4016
4017 static Lisp_Object window_being_scrolled;
4018
4019 /* Last scroll bar part sent in xm_scroll_callback. */
4020
4021 static int last_scroll_bar_part;
4022
4023 /* Whether this is an Xaw with arrow-scrollbars. This should imply
4024 that movements of 1/20 of the screen size are mapped to up/down. */
4025
4026 #ifndef USE_GTK
4027 /* Id of action hook installed for scroll bars. */
4028
4029 static XtActionHookId action_hook_id;
4030
4031 static Boolean xaw3d_arrow_scroll;
4032
4033 /* Whether the drag scrolling maintains the mouse at the top of the
4034 thumb. If not, resizing the thumb needs to be done more carefully
4035 to avoid jerkyness. */
4036
4037 static Boolean xaw3d_pick_top;
4038
4039 /* Action hook installed via XtAppAddActionHook when toolkit scroll
4040 bars are used.. The hook is responsible for detecting when
4041 the user ends an interaction with the scroll bar, and generates
4042 a `end-scroll' SCROLL_BAR_CLICK_EVENT' event if so. */
4043
4044 static void
4045 xt_action_hook (widget, client_data, action_name, event, params,
4046 num_params)
4047 Widget widget;
4048 XtPointer client_data;
4049 String action_name;
4050 XEvent *event;
4051 String *params;
4052 Cardinal *num_params;
4053 {
4054 int scroll_bar_p;
4055 char *end_action;
4056
4057 #ifdef USE_MOTIF
4058 scroll_bar_p = XmIsScrollBar (widget);
4059 end_action = "Release";
4060 #else /* !USE_MOTIF i.e. use Xaw */
4061 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
4062 end_action = "EndScroll";
4063 #endif /* USE_MOTIF */
4064
4065 if (scroll_bar_p
4066 && strcmp (action_name, end_action) == 0
4067 && WINDOWP (window_being_scrolled))
4068 {
4069 struct window *w;
4070
4071 x_send_scroll_bar_event (window_being_scrolled,
4072 scroll_bar_end_scroll, 0, 0);
4073 w = XWINDOW (window_being_scrolled);
4074
4075 if (!NILP (XSCROLL_BAR (w->vertical_scroll_bar)->dragging))
4076 {
4077 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
4078 /* The thumb size is incorrect while dragging: fix it. */
4079 set_vertical_scroll_bar (w);
4080 }
4081 window_being_scrolled = Qnil;
4082 last_scroll_bar_part = -1;
4083
4084 /* Xt timeouts no longer needed. */
4085 toolkit_scroll_bar_interaction = 0;
4086 }
4087 }
4088 #endif /* not USE_GTK */
4089
4090 /* A vector of windows used for communication between
4091 x_send_scroll_bar_event and x_scroll_bar_to_input_event. */
4092
4093 static struct window **scroll_bar_windows;
4094 static int scroll_bar_windows_size;
4095
4096
4097 /* Send a client message with message type Xatom_Scrollbar for a
4098 scroll action to the frame of WINDOW. PART is a value identifying
4099 the part of the scroll bar that was clicked on. PORTION is the
4100 amount to scroll of a whole of WHOLE. */
4101
4102 static void
4103 x_send_scroll_bar_event (Lisp_Object window, int part, int portion, int whole)
4104 {
4105 XEvent event;
4106 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
4107 struct window *w = XWINDOW (window);
4108 struct frame *f = XFRAME (w->frame);
4109 int i;
4110
4111 BLOCK_INPUT;
4112
4113 /* Construct a ClientMessage event to send to the frame. */
4114 ev->type = ClientMessage;
4115 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
4116 ev->display = FRAME_X_DISPLAY (f);
4117 ev->window = FRAME_X_WINDOW (f);
4118 ev->format = 32;
4119
4120 /* We can only transfer 32 bits in the XClientMessageEvent, which is
4121 not enough to store a pointer or Lisp_Object on a 64 bit system.
4122 So, store the window in scroll_bar_windows and pass the index
4123 into that array in the event. */
4124 for (i = 0; i < scroll_bar_windows_size; ++i)
4125 if (scroll_bar_windows[i] == NULL)
4126 break;
4127
4128 if (i == scroll_bar_windows_size)
4129 {
4130 int new_size = max (10, 2 * scroll_bar_windows_size);
4131 size_t nbytes = new_size * sizeof *scroll_bar_windows;
4132 size_t old_nbytes = scroll_bar_windows_size * sizeof *scroll_bar_windows;
4133
4134 scroll_bar_windows = (struct window **) xrealloc (scroll_bar_windows,
4135 nbytes);
4136 bzero (&scroll_bar_windows[i], nbytes - old_nbytes);
4137 scroll_bar_windows_size = new_size;
4138 }
4139
4140 scroll_bar_windows[i] = w;
4141 ev->data.l[0] = (long) i;
4142 ev->data.l[1] = (long) part;
4143 ev->data.l[2] = (long) 0;
4144 ev->data.l[3] = (long) portion;
4145 ev->data.l[4] = (long) whole;
4146
4147 /* Make Xt timeouts work while the scroll bar is active. */
4148 toolkit_scroll_bar_interaction = 1;
4149 #ifdef USE_X_TOOLKIT
4150 x_activate_timeout_atimer ();
4151 #endif
4152
4153 /* Setting the event mask to zero means that the message will
4154 be sent to the client that created the window, and if that
4155 window no longer exists, no event will be sent. */
4156 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
4157 UNBLOCK_INPUT;
4158 }
4159
4160
4161 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
4162 in *IEVENT. */
4163
4164 static void
4165 x_scroll_bar_to_input_event (XEvent *event, struct input_event *ievent)
4166 {
4167 XClientMessageEvent *ev = (XClientMessageEvent *) event;
4168 Lisp_Object window;
4169 struct frame *f;
4170 struct window *w;
4171
4172 w = scroll_bar_windows[ev->data.l[0]];
4173 scroll_bar_windows[ev->data.l[0]] = NULL;
4174
4175 XSETWINDOW (window, w);
4176 f = XFRAME (w->frame);
4177
4178 ievent->kind = SCROLL_BAR_CLICK_EVENT;
4179 ievent->frame_or_window = window;
4180 ievent->arg = Qnil;
4181 #ifdef USE_GTK
4182 ievent->timestamp = CurrentTime;
4183 #else
4184 ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
4185 #endif
4186 ievent->part = ev->data.l[1];
4187 ievent->code = ev->data.l[2];
4188 ievent->x = make_number ((int) ev->data.l[3]);
4189 ievent->y = make_number ((int) ev->data.l[4]);
4190 ievent->modifiers = 0;
4191 }
4192
4193
4194 #ifdef USE_MOTIF
4195
4196 /* Minimum and maximum values used for Motif scroll bars. */
4197
4198 #define XM_SB_MAX 10000000
4199
4200
4201 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
4202 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
4203 CALL_DATA is a pointer to a XmScrollBarCallbackStruct. */
4204
4205 static void
4206 xm_scroll_callback (widget, client_data, call_data)
4207 Widget widget;
4208 XtPointer client_data, call_data;
4209 {
4210 struct scroll_bar *bar = (struct scroll_bar *) client_data;
4211 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
4212 int part = -1, whole = 0, portion = 0;
4213
4214 switch (cs->reason)
4215 {
4216 case XmCR_DECREMENT:
4217 bar->dragging = Qnil;
4218 part = scroll_bar_up_arrow;
4219 break;
4220
4221 case XmCR_INCREMENT:
4222 bar->dragging = Qnil;
4223 part = scroll_bar_down_arrow;
4224 break;
4225
4226 case XmCR_PAGE_DECREMENT:
4227 bar->dragging = Qnil;
4228 part = scroll_bar_above_handle;
4229 break;
4230
4231 case XmCR_PAGE_INCREMENT:
4232 bar->dragging = Qnil;
4233 part = scroll_bar_below_handle;
4234 break;
4235
4236 case XmCR_TO_TOP:
4237 bar->dragging = Qnil;
4238 part = scroll_bar_to_top;
4239 break;
4240
4241 case XmCR_TO_BOTTOM:
4242 bar->dragging = Qnil;
4243 part = scroll_bar_to_bottom;
4244 break;
4245
4246 case XmCR_DRAG:
4247 {
4248 int slider_size;
4249
4250 /* Get the slider size. */
4251 BLOCK_INPUT;
4252 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
4253 UNBLOCK_INPUT;
4254
4255 whole = XM_SB_MAX - slider_size;
4256 portion = min (cs->value, whole);
4257 part = scroll_bar_handle;
4258 bar->dragging = make_number (cs->value);
4259 }
4260 break;
4261
4262 case XmCR_VALUE_CHANGED:
4263 break;
4264 };
4265
4266 if (part >= 0)
4267 {
4268 window_being_scrolled = bar->window;
4269 last_scroll_bar_part = part;
4270 x_send_scroll_bar_event (bar->window, part, portion, whole);
4271 }
4272 }
4273
4274 #elif defined USE_GTK
4275
4276 /* Scroll bar callback for GTK scroll bars. WIDGET is the scroll
4277 bar widget. DATA is a pointer to the scroll_bar structure. */
4278
4279 static gboolean
4280 xg_scroll_callback (GtkRange *range,
4281 GtkScrollType scroll,
4282 gdouble value,
4283 gpointer user_data)
4284 {
4285 struct scroll_bar *bar = (struct scroll_bar *) user_data;
4286 gdouble position;
4287 int part = -1, whole = 0, portion = 0;
4288 GtkAdjustment *adj = GTK_ADJUSTMENT (gtk_range_get_adjustment (range));
4289 FRAME_PTR f = (FRAME_PTR) g_object_get_data (G_OBJECT (range), XG_FRAME_DATA);
4290
4291 if (xg_ignore_gtk_scrollbar) return FALSE;
4292 position = gtk_adjustment_get_value (adj);
4293
4294
4295 switch (scroll)
4296 {
4297 case GTK_SCROLL_JUMP:
4298 /* Buttons 1 2 or 3 must be grabbed. */
4299 if (FRAME_X_DISPLAY_INFO (f)->grabbed != 0
4300 && FRAME_X_DISPLAY_INFO (f)->grabbed < (1 << 4))
4301 {
4302 part = scroll_bar_handle;
4303 whole = gtk_adjustment_get_upper (adj) -
4304 gtk_adjustment_get_page_size (adj);
4305 portion = min ((int)position, whole);
4306 bar->dragging = make_number ((int)portion);
4307 }
4308 break;
4309 case GTK_SCROLL_STEP_BACKWARD:
4310 part = scroll_bar_up_arrow;
4311 bar->dragging = Qnil;
4312 break;
4313 case GTK_SCROLL_STEP_FORWARD:
4314 part = scroll_bar_down_arrow;
4315 bar->dragging = Qnil;
4316 break;
4317 case GTK_SCROLL_PAGE_BACKWARD:
4318 part = scroll_bar_above_handle;
4319 bar->dragging = Qnil;
4320 break;
4321 case GTK_SCROLL_PAGE_FORWARD:
4322 part = scroll_bar_below_handle;
4323 bar->dragging = Qnil;
4324 break;
4325 }
4326
4327 if (part >= 0)
4328 {
4329 window_being_scrolled = bar->window;
4330 last_scroll_bar_part = part;
4331 x_send_scroll_bar_event (bar->window, part, portion, whole);
4332 }
4333
4334 return FALSE;
4335 }
4336
4337 /* Callback for button release. Sets dragging to Qnil when dragging is done. */
4338
4339 static gboolean
4340 xg_end_scroll_callback (GtkWidget *widget,
4341 GdkEventButton *event,
4342 gpointer user_data)
4343 {
4344 struct scroll_bar *bar = (struct scroll_bar *) user_data;
4345 bar->dragging = Qnil;
4346 if (WINDOWP (window_being_scrolled))
4347 {
4348 x_send_scroll_bar_event (window_being_scrolled,
4349 scroll_bar_end_scroll, 0, 0);
4350 window_being_scrolled = Qnil;
4351 }
4352
4353 return FALSE;
4354 }
4355
4356
4357 #else /* not USE_GTK and not USE_MOTIF */
4358
4359 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
4360 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
4361 scroll bar struct. CALL_DATA is a pointer to a float saying where
4362 the thumb is. */
4363
4364 static void
4365 xaw_jump_callback (widget, client_data, call_data)
4366 Widget widget;
4367 XtPointer client_data, call_data;
4368 {
4369 struct scroll_bar *bar = (struct scroll_bar *) client_data;
4370 float top = *(float *) call_data;
4371 float shown;
4372 int whole, portion, height;
4373 int part;
4374
4375 /* Get the size of the thumb, a value between 0 and 1. */
4376 BLOCK_INPUT;
4377 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
4378 UNBLOCK_INPUT;
4379
4380 whole = 10000000;
4381 portion = shown < 1 ? top * whole : 0;
4382
4383 if (shown < 1 && (eabs (top + shown - 1) < 1.0/height))
4384 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
4385 the bottom, so we force the scrolling whenever we see that we're
4386 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
4387 we try to ensure that we always stay two pixels away from the
4388 bottom). */
4389 part = scroll_bar_down_arrow;
4390 else
4391 part = scroll_bar_handle;
4392
4393 window_being_scrolled = bar->window;
4394 bar->dragging = make_number (portion);
4395 last_scroll_bar_part = part;
4396 x_send_scroll_bar_event (bar->window, part, portion, whole);
4397 }
4398
4399
4400 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
4401 i.e. line or page up or down. WIDGET is the Xaw scroll bar
4402 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
4403 the scroll bar. CALL_DATA is an integer specifying the action that
4404 has taken place. Its magnitude is in the range 0..height of the
4405 scroll bar. Negative values mean scroll towards buffer start.
4406 Values < height of scroll bar mean line-wise movement. */
4407
4408 static void
4409 xaw_scroll_callback (widget, client_data, call_data)
4410 Widget widget;
4411 XtPointer client_data, call_data;
4412 {
4413 struct scroll_bar *bar = (struct scroll_bar *) client_data;
4414 /* The position really is stored cast to a pointer. */
4415 int position = (long) call_data;
4416 Dimension height;
4417 int part;
4418
4419 /* Get the height of the scroll bar. */
4420 BLOCK_INPUT;
4421 XtVaGetValues (widget, XtNheight, &height, NULL);
4422 UNBLOCK_INPUT;
4423
4424 if (eabs (position) >= height)
4425 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
4426
4427 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
4428 it maps line-movement to call_data = max(5, height/20). */
4429 else if (xaw3d_arrow_scroll && eabs (position) <= max (5, height / 20))
4430 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
4431 else
4432 part = scroll_bar_move_ratio;
4433
4434 window_being_scrolled = bar->window;
4435 bar->dragging = Qnil;
4436 last_scroll_bar_part = part;
4437 x_send_scroll_bar_event (bar->window, part, position, height);
4438 }
4439
4440 #endif /* not USE_GTK and not USE_MOTIF */
4441
4442 #define SCROLL_BAR_NAME "verticalScrollBar"
4443
4444 /* Create the widget for scroll bar BAR on frame F. Record the widget
4445 and X window of the scroll bar in BAR. */
4446
4447 #ifdef USE_GTK
4448 static void
4449 x_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
4450 {
4451 char *scroll_bar_name = SCROLL_BAR_NAME;
4452
4453 BLOCK_INPUT;
4454 xg_create_scroll_bar (f, bar, G_CALLBACK (xg_scroll_callback),
4455 G_CALLBACK (xg_end_scroll_callback),
4456 scroll_bar_name);
4457 UNBLOCK_INPUT;
4458 }
4459
4460 #else /* not USE_GTK */
4461
4462 static void
4463 x_create_toolkit_scroll_bar (f, bar)
4464 struct frame *f;
4465 struct scroll_bar *bar;
4466 {
4467 Window xwindow;
4468 Widget widget;
4469 Arg av[20];
4470 int ac = 0;
4471 char *scroll_bar_name = SCROLL_BAR_NAME;
4472 unsigned long pixel;
4473
4474 BLOCK_INPUT;
4475
4476 #ifdef USE_MOTIF
4477 /* Set resources. Create the widget. */
4478 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
4479 XtSetArg (av[ac], XmNminimum, 0); ++ac;
4480 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
4481 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
4482 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
4483 XtSetArg (av[ac], XmNincrement, 1); ++ac;
4484 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
4485
4486 pixel = f->output_data.x->scroll_bar_foreground_pixel;
4487 if (pixel != -1)
4488 {
4489 XtSetArg (av[ac], XmNforeground, pixel);
4490 ++ac;
4491 }
4492
4493 pixel = f->output_data.x->scroll_bar_background_pixel;
4494 if (pixel != -1)
4495 {
4496 XtSetArg (av[ac], XmNbackground, pixel);
4497 ++ac;
4498 }
4499
4500 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
4501 scroll_bar_name, av, ac);
4502
4503 /* Add one callback for everything that can happen. */
4504 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
4505 (XtPointer) bar);
4506 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
4507 (XtPointer) bar);
4508 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
4509 (XtPointer) bar);
4510 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
4511 (XtPointer) bar);
4512 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
4513 (XtPointer) bar);
4514 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
4515 (XtPointer) bar);
4516 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
4517 (XtPointer) bar);
4518
4519 /* Realize the widget. Only after that is the X window created. */
4520 XtRealizeWidget (widget);
4521
4522 /* Set the cursor to an arrow. I didn't find a resource to do that.
4523 And I'm wondering why it hasn't an arrow cursor by default. */
4524 XDefineCursor (XtDisplay (widget), XtWindow (widget),
4525 f->output_data.x->nontext_cursor);
4526
4527 #else /* !USE_MOTIF i.e. use Xaw */
4528
4529 /* Set resources. Create the widget. The background of the
4530 Xaw3d scroll bar widget is a little bit light for my taste.
4531 We don't alter it here to let users change it according
4532 to their taste with `emacs*verticalScrollBar.background: xxx'. */
4533 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
4534 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
4535 /* For smoother scrolling with Xaw3d -sm */
4536 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
4537
4538 pixel = f->output_data.x->scroll_bar_foreground_pixel;
4539 if (pixel != -1)
4540 {
4541 XtSetArg (av[ac], XtNforeground, pixel);
4542 ++ac;
4543 }
4544
4545 pixel = f->output_data.x->scroll_bar_background_pixel;
4546 if (pixel != -1)
4547 {
4548 XtSetArg (av[ac], XtNbackground, pixel);
4549 ++ac;
4550 }
4551
4552 /* Top/bottom shadow colors. */
4553
4554 /* Allocate them, if necessary. */
4555 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1)
4556 {
4557 pixel = f->output_data.x->scroll_bar_background_pixel;
4558 if (pixel != -1)
4559 {
4560 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
4561 FRAME_X_COLORMAP (f),
4562 &pixel, 1.2, 0x8000))
4563 pixel = -1;
4564 f->output_data.x->scroll_bar_top_shadow_pixel = pixel;
4565 }
4566 }
4567 if (f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
4568 {
4569 pixel = f->output_data.x->scroll_bar_background_pixel;
4570 if (pixel != -1)
4571 {
4572 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
4573 FRAME_X_COLORMAP (f),
4574 &pixel, 0.6, 0x4000))
4575 pixel = -1;
4576 f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
4577 }
4578 }
4579
4580 #ifdef XtNbeNiceToColormap
4581 /* Tell the toolkit about them. */
4582 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1
4583 || f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
4584 /* We tried to allocate a color for the top/bottom shadow, and
4585 failed, so tell Xaw3d to use dithering instead. */
4586 {
4587 XtSetArg (av[ac], XtNbeNiceToColormap, True);
4588 ++ac;
4589 }
4590 else
4591 /* Tell what colors Xaw3d should use for the top/bottom shadow, to
4592 be more consistent with other emacs 3d colors, and since Xaw3d is
4593 not good at dealing with allocation failure. */
4594 {
4595 /* This tells Xaw3d to use real colors instead of dithering for
4596 the shadows. */
4597 XtSetArg (av[ac], XtNbeNiceToColormap, False);
4598 ++ac;
4599
4600 /* Specify the colors. */
4601 pixel = f->output_data.x->scroll_bar_top_shadow_pixel;
4602 if (pixel != -1)
4603 {
4604 XtSetArg (av[ac], XtNtopShadowPixel, pixel);
4605 ++ac;
4606 }
4607 pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel;
4608 if (pixel != -1)
4609 {
4610 XtSetArg (av[ac], XtNbottomShadowPixel, pixel);
4611 ++ac;
4612 }
4613 }
4614 #endif
4615
4616 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
4617 f->output_data.x->edit_widget, av, ac);
4618
4619 {
4620 char *initial = "";
4621 char *val = initial;
4622 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
4623 #ifdef XtNarrowScrollbars
4624 XtNarrowScrollbars, (XtPointer) &xaw3d_arrow_scroll,
4625 #endif
4626 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
4627 if (xaw3d_arrow_scroll || val == initial)
4628 { /* ARROW_SCROLL */
4629 xaw3d_arrow_scroll = True;
4630 /* Isn't that just a personal preference ? --Stef */
4631 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
4632 }
4633 }
4634
4635 /* Define callbacks. */
4636 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
4637 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
4638 (XtPointer) bar);
4639
4640 /* Realize the widget. Only after that is the X window created. */
4641 XtRealizeWidget (widget);
4642
4643 #endif /* !USE_MOTIF */
4644
4645 /* Install an action hook that lets us detect when the user
4646 finishes interacting with a scroll bar. */
4647 if (action_hook_id == 0)
4648 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
4649
4650 /* Remember X window and widget in the scroll bar vector. */
4651 SET_SCROLL_BAR_X_WIDGET (bar, widget);
4652 xwindow = XtWindow (widget);
4653 bar->x_window = xwindow;
4654
4655 UNBLOCK_INPUT;
4656 }
4657 #endif /* not USE_GTK */
4658
4659
4660 /* Set the thumb size and position of scroll bar BAR. We are currently
4661 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4662
4663 #ifdef USE_GTK
4664 static void
4665 x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position, int whole)
4666 {
4667 xg_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
4668 }
4669
4670 #else /* not USE_GTK */
4671 static void
4672 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
4673 struct scroll_bar *bar;
4674 int portion, position, whole;
4675 {
4676 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4677 Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
4678 float top, shown;
4679
4680 BLOCK_INPUT;
4681
4682 #ifdef USE_MOTIF
4683
4684 /* We use an estimate of 30 chars per line rather than the real
4685 `portion' value. This has the disadvantage that the thumb size
4686 is not very representative, but it makes our life a lot easier.
4687 Otherwise, we have to constantly adjust the thumb size, which
4688 we can't always do quickly enough: while dragging, the size of
4689 the thumb might prevent the user from dragging the thumb all the
4690 way to the end. but Motif and some versions of Xaw3d don't allow
4691 updating the thumb size while dragging. Also, even if we can update
4692 its size, the update will often happen too late.
4693 If you don't believe it, check out revision 1.650 of xterm.c to see
4694 what hoops we were going through and the still poor behavior we got. */
4695 portion = WINDOW_TOTAL_LINES (XWINDOW (bar->window)) * 30;
4696 /* When the thumb is at the bottom, position == whole.
4697 So we need to increase `whole' to make space for the thumb. */
4698 whole += portion;
4699
4700 if (whole <= 0)
4701 top = 0, shown = 1;
4702 else
4703 {
4704 top = (float) position / whole;
4705 shown = (float) portion / whole;
4706 }
4707
4708 if (NILP (bar->dragging))
4709 {
4710 int size, value;
4711
4712 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
4713 is the scroll bar's maximum and MIN is the scroll bar's minimum
4714 value. */
4715 size = shown * XM_SB_MAX;
4716 size = min (size, XM_SB_MAX);
4717 size = max (size, 1);
4718
4719 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
4720 value = top * XM_SB_MAX;
4721 value = min (value, XM_SB_MAX - size);
4722
4723 XmScrollBarSetValues (widget, value, size, 0, 0, False);
4724 }
4725 #else /* !USE_MOTIF i.e. use Xaw */
4726
4727 if (whole == 0)
4728 top = 0, shown = 1;
4729 else
4730 {
4731 top = (float) position / whole;
4732 shown = (float) portion / whole;
4733 }
4734
4735 {
4736 float old_top, old_shown;
4737 Dimension height;
4738 XtVaGetValues (widget,
4739 XtNtopOfThumb, &old_top,
4740 XtNshown, &old_shown,
4741 XtNheight, &height,
4742 NULL);
4743
4744 /* Massage the top+shown values. */
4745 if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow)
4746 top = max (0, min (1, top));
4747 else
4748 top = old_top;
4749 /* Keep two pixels available for moving the thumb down. */
4750 shown = max (0, min (1 - top - (2.0 / height), shown));
4751
4752 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
4753 check that your system's configuration file contains a define
4754 for `NARROWPROTO'. See s/freebsd.h for an example. */
4755 if (top != old_top || shown != old_shown)
4756 {
4757 if (NILP (bar->dragging))
4758 XawScrollbarSetThumb (widget, top, shown);
4759 else
4760 {
4761 /* Try to make the scrolling a tad smoother. */
4762 if (!xaw3d_pick_top)
4763 shown = min (shown, old_shown);
4764
4765 XawScrollbarSetThumb (widget, top, shown);
4766 }
4767 }
4768 }
4769 #endif /* !USE_MOTIF */
4770
4771 UNBLOCK_INPUT;
4772 }
4773 #endif /* not USE_GTK */
4774
4775 #endif /* USE_TOOLKIT_SCROLL_BARS */
4776
4777
4778 \f
4779 /************************************************************************
4780 Scroll bars, general
4781 ************************************************************************/
4782
4783 /* Create a scroll bar and return the scroll bar vector for it. W is
4784 the Emacs window on which to create the scroll bar. TOP, LEFT,
4785 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4786 scroll bar. */
4787
4788 static struct scroll_bar *
4789 x_scroll_bar_create (struct window *w, int top, int left, int width, int height)
4790 {
4791 struct frame *f = XFRAME (w->frame);
4792 struct scroll_bar *bar
4793 = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, x_window, PVEC_OTHER);
4794
4795 BLOCK_INPUT;
4796
4797 #ifdef USE_TOOLKIT_SCROLL_BARS
4798 x_create_toolkit_scroll_bar (f, bar);
4799 #else /* not USE_TOOLKIT_SCROLL_BARS */
4800 {
4801 XSetWindowAttributes a;
4802 unsigned long mask;
4803 Window window;
4804
4805 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
4806 if (a.background_pixel == -1)
4807 a.background_pixel = FRAME_BACKGROUND_PIXEL (f);
4808
4809 a.event_mask = (ButtonPressMask | ButtonReleaseMask
4810 | ButtonMotionMask | PointerMotionHintMask
4811 | ExposureMask);
4812 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
4813
4814 mask = (CWBackPixel | CWEventMask | CWCursor);
4815
4816 /* Clear the area of W that will serve as a scroll bar. This is
4817 for the case that a window has been split horizontally. In
4818 this case, no clear_frame is generated to reduce flickering. */
4819 if (width > 0 && height > 0)
4820 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4821 left, top, width,
4822 window_box_height (w), False);
4823
4824 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4825 /* Position and size of scroll bar. */
4826 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
4827 top,
4828 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
4829 height,
4830 /* Border width, depth, class, and visual. */
4831 0,
4832 CopyFromParent,
4833 CopyFromParent,
4834 CopyFromParent,
4835 /* Attributes. */
4836 mask, &a);
4837 bar->x_window = window;
4838 }
4839 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4840
4841 XSETWINDOW (bar->window, w);
4842 bar->top = top;
4843 bar->left = left;
4844 bar->width = width;
4845 bar->height = height;
4846 bar->start = 0;
4847 bar->end = 0;
4848 bar->dragging = Qnil;
4849 bar->fringe_extended_p = 0;
4850
4851 /* Add bar to its frame's list of scroll bars. */
4852 bar->next = FRAME_SCROLL_BARS (f);
4853 bar->prev = Qnil;
4854 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4855 if (!NILP (bar->next))
4856 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4857
4858 /* Map the window/widget. */
4859 #ifdef USE_TOOLKIT_SCROLL_BARS
4860 {
4861 #ifdef USE_GTK
4862 xg_update_scrollbar_pos (f,
4863 bar->x_window,
4864 top,
4865 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
4866 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
4867 max (height, 1));
4868 #else /* not USE_GTK */
4869 Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
4870 XtConfigureWidget (scroll_bar,
4871 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
4872 top,
4873 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
4874 max (height, 1), 0);
4875 XtMapWidget (scroll_bar);
4876 #endif /* not USE_GTK */
4877 }
4878 #else /* not USE_TOOLKIT_SCROLL_BARS */
4879 XMapRaised (FRAME_X_DISPLAY (f), bar->x_window);
4880 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4881
4882 UNBLOCK_INPUT;
4883 return bar;
4884 }
4885
4886
4887 #ifndef USE_TOOLKIT_SCROLL_BARS
4888
4889 /* Draw BAR's handle in the proper position.
4890
4891 If the handle is already drawn from START to END, don't bother
4892 redrawing it, unless REBUILD is non-zero; in that case, always
4893 redraw it. (REBUILD is handy for drawing the handle after expose
4894 events.)
4895
4896 Normally, we want to constrain the start and end of the handle to
4897 fit inside its rectangle, but if the user is dragging the scroll
4898 bar handle, we want to let them drag it down all the way, so that
4899 the bar's top is as far down as it goes; otherwise, there's no way
4900 to move to the very end of the buffer. */
4901
4902 static void
4903 x_scroll_bar_set_handle (bar, start, end, rebuild)
4904 struct scroll_bar *bar;
4905 int start, end;
4906 int rebuild;
4907 {
4908 int dragging = ! NILP (bar->dragging);
4909 Window w = bar->x_window;
4910 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4911 GC gc = f->output_data.x->normal_gc;
4912
4913 /* If the display is already accurate, do nothing. */
4914 if (! rebuild
4915 && start == bar->start
4916 && end == bar->end)
4917 return;
4918
4919 BLOCK_INPUT;
4920
4921 {
4922 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, bar->width);
4923 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, bar->height);
4924 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
4925
4926 /* Make sure the values are reasonable, and try to preserve
4927 the distance between start and end. */
4928 {
4929 int length = end - start;
4930
4931 if (start < 0)
4932 start = 0;
4933 else if (start > top_range)
4934 start = top_range;
4935 end = start + length;
4936
4937 if (end < start)
4938 end = start;
4939 else if (end > top_range && ! dragging)
4940 end = top_range;
4941 }
4942
4943 /* Store the adjusted setting in the scroll bar. */
4944 bar->start = start;
4945 bar->end = end;
4946
4947 /* Clip the end position, just for display. */
4948 if (end > top_range)
4949 end = top_range;
4950
4951 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
4952 below top positions, to make sure the handle is always at least
4953 that many pixels tall. */
4954 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
4955
4956 /* Draw the empty space above the handle. Note that we can't clear
4957 zero-height areas; that means "clear to end of window." */
4958 if (0 < start)
4959 x_clear_area (FRAME_X_DISPLAY (f), w,
4960 /* x, y, width, height, and exposures. */
4961 VERTICAL_SCROLL_BAR_LEFT_BORDER,
4962 VERTICAL_SCROLL_BAR_TOP_BORDER,
4963 inside_width, start,
4964 False);
4965
4966 /* Change to proper foreground color if one is specified. */
4967 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
4968 XSetForeground (FRAME_X_DISPLAY (f), gc,
4969 f->output_data.x->scroll_bar_foreground_pixel);
4970
4971 /* Draw the handle itself. */
4972 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
4973 /* x, y, width, height */
4974 VERTICAL_SCROLL_BAR_LEFT_BORDER,
4975 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
4976 inside_width, end - start);
4977
4978 /* Restore the foreground color of the GC if we changed it above. */
4979 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
4980 XSetForeground (FRAME_X_DISPLAY (f), gc,
4981 FRAME_FOREGROUND_PIXEL (f));
4982
4983 /* Draw the empty space below the handle. Note that we can't
4984 clear zero-height areas; that means "clear to end of window." */
4985 if (end < inside_height)
4986 x_clear_area (FRAME_X_DISPLAY (f), w,
4987 /* x, y, width, height, and exposures. */
4988 VERTICAL_SCROLL_BAR_LEFT_BORDER,
4989 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
4990 inside_width, inside_height - end,
4991 False);
4992
4993 }
4994
4995 UNBLOCK_INPUT;
4996 }
4997
4998 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4999
5000 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5001 nil. */
5002
5003 static void
5004 x_scroll_bar_remove (struct scroll_bar *bar)
5005 {
5006 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5007 BLOCK_INPUT;
5008
5009 #ifdef USE_TOOLKIT_SCROLL_BARS
5010 #ifdef USE_GTK
5011 xg_remove_scroll_bar (f, bar->x_window);
5012 #else /* not USE_GTK */
5013 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));
5014 #endif /* not USE_GTK */
5015 #else
5016 XDestroyWindow (FRAME_X_DISPLAY (f), bar->x_window);
5017 #endif
5018
5019 /* Disassociate this scroll bar from its window. */
5020 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
5021
5022 UNBLOCK_INPUT;
5023 }
5024
5025
5026 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5027 that we are displaying PORTION characters out of a total of WHOLE
5028 characters, starting at POSITION. If WINDOW has no scroll bar,
5029 create one. */
5030
5031 static void
5032 XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int position)
5033 {
5034 struct frame *f = XFRAME (w->frame);
5035 struct scroll_bar *bar;
5036 int top, height, left, sb_left, width, sb_width;
5037 int window_y, window_height;
5038 #ifdef USE_TOOLKIT_SCROLL_BARS
5039 int fringe_extended_p;
5040 #endif
5041
5042 /* Get window dimensions. */
5043 window_box (w, -1, 0, &window_y, 0, &window_height);
5044 top = window_y;
5045 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
5046 height = window_height;
5047
5048 /* Compute the left edge of the scroll bar area. */
5049 left = WINDOW_SCROLL_BAR_AREA_X (w);
5050
5051 /* Compute the width of the scroll bar which might be less than
5052 the width of the area reserved for the scroll bar. */
5053 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
5054 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
5055 else
5056 sb_width = width;
5057
5058 /* Compute the left edge of the scroll bar. */
5059 #ifdef USE_TOOLKIT_SCROLL_BARS
5060 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
5061 sb_left = left + (WINDOW_RIGHTMOST_P (w) ? width - sb_width : 0);
5062 else
5063 sb_left = left + (WINDOW_LEFTMOST_P (w) ? 0 : width - sb_width);
5064 #else
5065 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
5066 sb_left = left + width - sb_width;
5067 else
5068 sb_left = left;
5069 #endif
5070
5071 #ifdef USE_TOOLKIT_SCROLL_BARS
5072 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
5073 fringe_extended_p = (WINDOW_LEFTMOST_P (w)
5074 && WINDOW_LEFT_FRINGE_WIDTH (w)
5075 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
5076 || WINDOW_LEFT_MARGIN_COLS (w) == 0));
5077 else
5078 fringe_extended_p = (WINDOW_RIGHTMOST_P (w)
5079 && WINDOW_RIGHT_FRINGE_WIDTH (w)
5080 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
5081 || WINDOW_RIGHT_MARGIN_COLS (w) == 0));
5082 #endif
5083
5084 /* Does the scroll bar exist yet? */
5085 if (NILP (w->vertical_scroll_bar))
5086 {
5087 if (width > 0 && height > 0)
5088 {
5089 BLOCK_INPUT;
5090 #ifdef USE_TOOLKIT_SCROLL_BARS
5091 if (fringe_extended_p)
5092 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5093 sb_left, top, sb_width, height, False);
5094 else
5095 #endif
5096 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5097 left, top, width, height, False);
5098 UNBLOCK_INPUT;
5099 }
5100
5101 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
5102 }
5103 else
5104 {
5105 /* It may just need to be moved and resized. */
5106 unsigned int mask = 0;
5107
5108 bar = XSCROLL_BAR (w->vertical_scroll_bar);
5109
5110 BLOCK_INPUT;
5111
5112 if (sb_left != bar->left)
5113 mask |= CWX;
5114 if (top != bar->top)
5115 mask |= CWY;
5116 if (sb_width != bar->width)
5117 mask |= CWWidth;
5118 if (height != bar->height)
5119 mask |= CWHeight;
5120
5121 #ifdef USE_TOOLKIT_SCROLL_BARS
5122
5123 /* Move/size the scroll bar widget. */
5124 if (mask || bar->fringe_extended_p != fringe_extended_p)
5125 {
5126 /* Since toolkit scroll bars are smaller than the space reserved
5127 for them on the frame, we have to clear "under" them. */
5128 if (width > 0 && height > 0)
5129 {
5130 if (fringe_extended_p)
5131 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5132 sb_left, top, sb_width, height, False);
5133 else
5134 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5135 left, top, width, height, False);
5136 }
5137 #ifdef USE_GTK
5138 xg_update_scrollbar_pos (f,
5139 bar->x_window,
5140 top,
5141 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
5142 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM *2,
5143 max (height, 1));
5144 #else /* not USE_GTK */
5145 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
5146 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
5147 top,
5148 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
5149 max (height, 1), 0);
5150 #endif /* not USE_GTK */
5151 }
5152 #else /* not USE_TOOLKIT_SCROLL_BARS */
5153
5154 /* Clear areas not covered by the scroll bar because of
5155 VERTICAL_SCROLL_BAR_WIDTH_TRIM. */
5156 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
5157 {
5158 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5159 left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
5160 height, False);
5161 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5162 left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
5163 top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
5164 height, False);
5165 }
5166
5167 /* Clear areas not covered by the scroll bar because it's not as
5168 wide as the area reserved for it. This makes sure a
5169 previous mode line display is cleared after C-x 2 C-x 1, for
5170 example. */
5171 {
5172 int area_width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
5173 int rest = area_width - sb_width;
5174 if (rest > 0 && height > 0)
5175 {
5176 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
5177 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5178 left + area_width - rest, top,
5179 rest, height, False);
5180 else
5181 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5182 left, top, rest, height, False);
5183 }
5184 }
5185
5186 /* Move/size the scroll bar window. */
5187 if (mask)
5188 {
5189 XWindowChanges wc;
5190
5191 wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5192 wc.y = top;
5193 wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
5194 wc.height = height;
5195 XConfigureWindow (FRAME_X_DISPLAY (f), bar->x_window,
5196 mask, &wc);
5197 }
5198
5199 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5200
5201 /* Remember new settings. */
5202 bar->left = sb_left;
5203 bar->top = top;
5204 bar->width = sb_width;
5205 bar->height = height;
5206
5207 UNBLOCK_INPUT;
5208 }
5209
5210 #ifdef USE_TOOLKIT_SCROLL_BARS
5211 bar->fringe_extended_p = fringe_extended_p;
5212
5213 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
5214 #else /* not USE_TOOLKIT_SCROLL_BARS */
5215 /* Set the scroll bar's current state, unless we're currently being
5216 dragged. */
5217 if (NILP (bar->dragging))
5218 {
5219 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
5220
5221 if (whole == 0)
5222 x_scroll_bar_set_handle (bar, 0, top_range, 0);
5223 else
5224 {
5225 int start = ((double) position * top_range) / whole;
5226 int end = ((double) (position + portion) * top_range) / whole;
5227 x_scroll_bar_set_handle (bar, start, end, 0);
5228 }
5229 }
5230 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5231
5232 XSETVECTOR (w->vertical_scroll_bar, bar);
5233 }
5234
5235
5236 /* The following three hooks are used when we're doing a thorough
5237 redisplay of the frame. We don't explicitly know which scroll bars
5238 are going to be deleted, because keeping track of when windows go
5239 away is a real pain - "Can you say set-window-configuration, boys
5240 and girls?" Instead, we just assert at the beginning of redisplay
5241 that *all* scroll bars are to be removed, and then save a scroll bar
5242 from the fiery pit when we actually redisplay its window. */
5243
5244 /* Arrange for all scroll bars on FRAME to be removed at the next call
5245 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5246 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5247
5248 static void
5249 XTcondemn_scroll_bars (FRAME_PTR frame)
5250 {
5251 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5252 while (! NILP (FRAME_SCROLL_BARS (frame)))
5253 {
5254 Lisp_Object bar;
5255 bar = FRAME_SCROLL_BARS (frame);
5256 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
5257 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
5258 XSCROLL_BAR (bar)->prev = Qnil;
5259 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
5260 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
5261 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
5262 }
5263 }
5264
5265
5266 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5267 Note that WINDOW isn't necessarily condemned at all. */
5268
5269 static void
5270 XTredeem_scroll_bar (struct window *window)
5271 {
5272 struct scroll_bar *bar;
5273 struct frame *f;
5274
5275 /* We can't redeem this window's scroll bar if it doesn't have one. */
5276 if (NILP (window->vertical_scroll_bar))
5277 abort ();
5278
5279 bar = XSCROLL_BAR (window->vertical_scroll_bar);
5280
5281 /* Unlink it from the condemned list. */
5282 f = XFRAME (WINDOW_FRAME (window));
5283 if (NILP (bar->prev))
5284 {
5285 /* If the prev pointer is nil, it must be the first in one of
5286 the lists. */
5287 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
5288 /* It's not condemned. Everything's fine. */
5289 return;
5290 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
5291 window->vertical_scroll_bar))
5292 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
5293 else
5294 /* If its prev pointer is nil, it must be at the front of
5295 one or the other! */
5296 abort ();
5297 }
5298 else
5299 XSCROLL_BAR (bar->prev)->next = bar->next;
5300
5301 if (! NILP (bar->next))
5302 XSCROLL_BAR (bar->next)->prev = bar->prev;
5303
5304 bar->next = FRAME_SCROLL_BARS (f);
5305 bar->prev = Qnil;
5306 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
5307 if (! NILP (bar->next))
5308 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
5309 }
5310
5311 /* Remove all scroll bars on FRAME that haven't been saved since the
5312 last call to `*condemn_scroll_bars_hook'. */
5313
5314 static void
5315 XTjudge_scroll_bars (FRAME_PTR f)
5316 {
5317 Lisp_Object bar, next;
5318
5319 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
5320
5321 /* Clear out the condemned list now so we won't try to process any
5322 more events on the hapless scroll bars. */
5323 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
5324
5325 for (; ! NILP (bar); bar = next)
5326 {
5327 struct scroll_bar *b = XSCROLL_BAR (bar);
5328
5329 x_scroll_bar_remove (b);
5330
5331 next = b->next;
5332 b->next = b->prev = Qnil;
5333 }
5334
5335 /* Now there should be no references to the condemned scroll bars,
5336 and they should get garbage-collected. */
5337 }
5338
5339
5340 #ifndef USE_TOOLKIT_SCROLL_BARS
5341 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
5342 is a no-op when using toolkit scroll bars.
5343
5344 This may be called from a signal handler, so we have to ignore GC
5345 mark bits. */
5346
5347 static void
5348 x_scroll_bar_expose (bar, event)
5349 struct scroll_bar *bar;
5350 XEvent *event;
5351 {
5352 Window w = bar->x_window;
5353 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5354 GC gc = f->output_data.x->normal_gc;
5355 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5356
5357 BLOCK_INPUT;
5358
5359 x_scroll_bar_set_handle (bar, bar->start, bar->end, 1);
5360
5361 /* Switch to scroll bar foreground color. */
5362 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
5363 XSetForeground (FRAME_X_DISPLAY (f), gc,
5364 f->output_data.x->scroll_bar_foreground_pixel);
5365
5366 /* Draw a one-pixel border just inside the edges of the scroll bar. */
5367 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
5368
5369 /* x, y, width, height */
5370 0, 0,
5371 bar->width - 1 - width_trim - width_trim,
5372 bar->height - 1);
5373
5374 /* Restore the foreground color of the GC if we changed it above. */
5375 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
5376 XSetForeground (FRAME_X_DISPLAY (f), gc,
5377 FRAME_FOREGROUND_PIXEL (f));
5378
5379 UNBLOCK_INPUT;
5380
5381 }
5382 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5383
5384 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5385 is set to something other than NO_EVENT, it is enqueued.
5386
5387 This may be called from a signal handler, so we have to ignore GC
5388 mark bits. */
5389
5390
5391 static void
5392 x_scroll_bar_handle_click (struct scroll_bar *bar, XEvent *event, struct input_event *emacs_event)
5393 {
5394 if (! WINDOWP (bar->window))
5395 abort ();
5396
5397 emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
5398 emacs_event->code = event->xbutton.button - Button1;
5399 emacs_event->modifiers
5400 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
5401 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
5402 event->xbutton.state)
5403 | (event->type == ButtonRelease
5404 ? up_modifier
5405 : down_modifier));
5406 emacs_event->frame_or_window = bar->window;
5407 emacs_event->arg = Qnil;
5408 emacs_event->timestamp = event->xbutton.time;
5409 {
5410 int top_range
5411 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
5412 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
5413
5414 if (y < 0) y = 0;
5415 if (y > top_range) y = top_range;
5416
5417 if (y < bar->start)
5418 emacs_event->part = scroll_bar_above_handle;
5419 else if (y < bar->end + VERTICAL_SCROLL_BAR_MIN_HANDLE)
5420 emacs_event->part = scroll_bar_handle;
5421 else
5422 emacs_event->part = scroll_bar_below_handle;
5423
5424 #ifndef USE_TOOLKIT_SCROLL_BARS
5425 /* If the user has released the handle, set it to its final position. */
5426 if (event->type == ButtonRelease
5427 && ! NILP (bar->dragging))
5428 {
5429 int new_start = y - XINT (bar->dragging);
5430 int new_end = new_start + bar->end - bar->start;
5431
5432 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
5433 bar->dragging = Qnil;
5434 }
5435 #endif
5436
5437 XSETINT (emacs_event->x, y);
5438 XSETINT (emacs_event->y, top_range);
5439 }
5440 }
5441
5442 #ifndef USE_TOOLKIT_SCROLL_BARS
5443
5444 /* Handle some mouse motion while someone is dragging the scroll bar.
5445
5446 This may be called from a signal handler, so we have to ignore GC
5447 mark bits. */
5448
5449 static void
5450 x_scroll_bar_note_movement (bar, event)
5451 struct scroll_bar *bar;
5452 XEvent *event;
5453 {
5454 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
5455
5456 last_mouse_movement_time = event->xmotion.time;
5457
5458 f->mouse_moved = 1;
5459 XSETVECTOR (last_mouse_scroll_bar, bar);
5460
5461 /* If we're dragging the bar, display it. */
5462 if (! NILP (bar->dragging))
5463 {
5464 /* Where should the handle be now? */
5465 int new_start = event->xmotion.y - XINT (bar->dragging);
5466
5467 if (new_start != bar->start)
5468 {
5469 int new_end = new_start + bar->end - bar->start;
5470
5471 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
5472 }
5473 }
5474 }
5475
5476 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5477
5478 /* Return information to the user about the current position of the mouse
5479 on the scroll bar. */
5480
5481 static void
5482 x_scroll_bar_report_motion (FRAME_PTR *fp, Lisp_Object *bar_window, enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y, long unsigned int *time)
5483 {
5484 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
5485 Window w = bar->x_window;
5486 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5487 int win_x, win_y;
5488 Window dummy_window;
5489 int dummy_coord;
5490 unsigned int dummy_mask;
5491
5492 BLOCK_INPUT;
5493
5494 /* Get the mouse's position relative to the scroll bar window, and
5495 report that. */
5496 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
5497
5498 /* Root, child, root x and root y. */
5499 &dummy_window, &dummy_window,
5500 &dummy_coord, &dummy_coord,
5501
5502 /* Position relative to scroll bar. */
5503 &win_x, &win_y,
5504
5505 /* Mouse buttons and modifier keys. */
5506 &dummy_mask))
5507 ;
5508 else
5509 {
5510 int top_range
5511 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
5512
5513 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
5514
5515 if (! NILP (bar->dragging))
5516 win_y -= XINT (bar->dragging);
5517
5518 if (win_y < 0)
5519 win_y = 0;
5520 if (win_y > top_range)
5521 win_y = top_range;
5522
5523 *fp = f;
5524 *bar_window = bar->window;
5525
5526 if (! NILP (bar->dragging))
5527 *part = scroll_bar_handle;
5528 else if (win_y < bar->start)
5529 *part = scroll_bar_above_handle;
5530 else if (win_y < bar->end + VERTICAL_SCROLL_BAR_MIN_HANDLE)
5531 *part = scroll_bar_handle;
5532 else
5533 *part = scroll_bar_below_handle;
5534
5535 XSETINT (*x, win_y);
5536 XSETINT (*y, top_range);
5537
5538 f->mouse_moved = 0;
5539 last_mouse_scroll_bar = Qnil;
5540 }
5541
5542 *time = last_mouse_movement_time;
5543
5544 UNBLOCK_INPUT;
5545 }
5546
5547
5548 /* The screen has been cleared so we may have changed foreground or
5549 background colors, and the scroll bars may need to be redrawn.
5550 Clear out the scroll bars, and ask for expose events, so we can
5551 redraw them. */
5552
5553 void
5554 x_scroll_bar_clear (FRAME_PTR f)
5555 {
5556 #ifndef USE_TOOLKIT_SCROLL_BARS
5557 Lisp_Object bar;
5558
5559 /* We can have scroll bars even if this is 0,
5560 if we just turned off scroll bar mode.
5561 But in that case we should not clear them. */
5562 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5563 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
5564 bar = XSCROLL_BAR (bar)->next)
5565 XClearArea (FRAME_X_DISPLAY (f),
5566 XSCROLL_BAR (bar)->x_window,
5567 0, 0, 0, 0, True);
5568 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5569 }
5570
5571 \f
5572 /* The main X event-reading loop - XTread_socket. */
5573
5574 /* This holds the state XLookupString needs to implement dead keys
5575 and other tricks known as "compose processing". _X Window System_
5576 says that a portable program can't use this, but Stephen Gildea assures
5577 me that letting the compiler initialize it to zeros will work okay.
5578
5579 This must be defined outside of XTread_socket, for the same reasons
5580 given for enter_timestamp, above. */
5581
5582 static XComposeStatus compose_status;
5583
5584 /* Record the last 100 characters stored
5585 to help debug the loss-of-chars-during-GC problem. */
5586
5587 static int temp_index;
5588 static short temp_buffer[100];
5589
5590 #define STORE_KEYSYM_FOR_DEBUG(keysym) \
5591 if (temp_index == sizeof temp_buffer / sizeof (short)) \
5592 temp_index = 0; \
5593 temp_buffer[temp_index++] = (keysym)
5594
5595 /* Set this to nonzero to fake an "X I/O error"
5596 on a particular display. */
5597
5598 struct x_display_info *XTread_socket_fake_io_error;
5599
5600 /* When we find no input here, we occasionally do a no-op command
5601 to verify that the X server is still running and we can still talk with it.
5602 We try all the open displays, one by one.
5603 This variable is used for cycling thru the displays. */
5604
5605 static struct x_display_info *next_noop_dpyinfo;
5606
5607 #define SET_SAVED_MENU_EVENT(size) \
5608 do \
5609 { \
5610 if (f->output_data.x->saved_menu_event == 0) \
5611 f->output_data.x->saved_menu_event \
5612 = (XEvent *) xmalloc (sizeof (XEvent)); \
5613 bcopy (&event, f->output_data.x->saved_menu_event, size); \
5614 inev.ie.kind = MENU_BAR_ACTIVATE_EVENT; \
5615 XSETFRAME (inev.ie.frame_or_window, f); \
5616 } \
5617 while (0)
5618
5619 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
5620 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
5621
5622
5623 enum
5624 {
5625 X_EVENT_NORMAL,
5626 X_EVENT_GOTO_OUT,
5627 X_EVENT_DROP
5628 };
5629
5630 /* Filter events for the current X input method.
5631 DPYINFO is the display this event is for.
5632 EVENT is the X event to filter.
5633
5634 Returns non-zero if the event was filtered, caller shall not process
5635 this event further.
5636 Returns zero if event is wasn't filtered. */
5637
5638 #ifdef HAVE_X_I18N
5639 static int
5640 x_filter_event (struct x_display_info *dpyinfo, XEvent *event)
5641 {
5642 /* XFilterEvent returns non-zero if the input method has
5643 consumed the event. We pass the frame's X window to
5644 XFilterEvent because that's the one for which the IC
5645 was created. */
5646
5647 struct frame *f1 = x_any_window_to_frame (dpyinfo,
5648 event->xclient.window);
5649
5650 return XFilterEvent (event, f1 ? FRAME_X_WINDOW (f1) : None);
5651 }
5652 #endif
5653
5654 #ifdef USE_GTK
5655 static int current_count;
5656 static int current_finish;
5657 static struct input_event *current_hold_quit;
5658
5659 /* This is the filter function invoked by the GTK event loop.
5660 It is invoked before the XEvent is translated to a GdkEvent,
5661 so we have a chance to act on the event before GTK. */
5662 static GdkFilterReturn
5663 event_handler_gdk (GdkXEvent *gxev, GdkEvent *ev, gpointer data)
5664 {
5665 XEvent *xev = (XEvent *) gxev;
5666
5667 BLOCK_INPUT;
5668 if (current_count >= 0)
5669 {
5670 struct x_display_info *dpyinfo;
5671
5672 dpyinfo = x_display_info_for_display (xev->xany.display);
5673
5674 #ifdef HAVE_X_I18N
5675 /* Filter events for the current X input method.
5676 GTK calls XFilterEvent but not for key press and release,
5677 so we do it here. */
5678 if ((xev->type == KeyPress || xev->type == KeyRelease)
5679 && dpyinfo
5680 && x_filter_event (dpyinfo, xev))
5681 {
5682 UNBLOCK_INPUT;
5683 return GDK_FILTER_REMOVE;
5684 }
5685 #endif
5686
5687 if (! dpyinfo)
5688 current_finish = X_EVENT_NORMAL;
5689 else
5690 current_count +=
5691 handle_one_xevent (dpyinfo, xev, &current_finish,
5692 current_hold_quit);
5693 }
5694 else
5695 current_finish = x_dispatch_event (xev, xev->xany.display);
5696
5697 UNBLOCK_INPUT;
5698
5699 if (current_finish == X_EVENT_GOTO_OUT || current_finish == X_EVENT_DROP)
5700 return GDK_FILTER_REMOVE;
5701
5702 return GDK_FILTER_CONTINUE;
5703 }
5704 #endif /* USE_GTK */
5705
5706
5707 /* Handles the XEvent EVENT on display DPYINFO.
5708
5709 *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
5710 *FINISH is zero if caller should continue reading events.
5711 *FINISH is X_EVENT_DROP if event should not be passed to the toolkit.
5712
5713 We return the number of characters stored into the buffer. */
5714
5715 static int
5716 handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventp, int *finish, struct input_event *hold_quit)
5717 {
5718 union {
5719 struct input_event ie;
5720 struct selection_input_event sie;
5721 } inev;
5722 int count = 0;
5723 int do_help = 0;
5724 int nbytes = 0;
5725 struct frame *f = NULL;
5726 struct coding_system coding;
5727 XEvent event = *eventp;
5728
5729 *finish = X_EVENT_NORMAL;
5730
5731 EVENT_INIT (inev.ie);
5732 inev.ie.kind = NO_EVENT;
5733 inev.ie.arg = Qnil;
5734
5735 if (pending_event_wait.eventtype == event.type)
5736 pending_event_wait.eventtype = 0; /* Indicates we got it. */
5737
5738 switch (event.type)
5739 {
5740 case ClientMessage:
5741 {
5742 if (event.xclient.message_type
5743 == dpyinfo->Xatom_wm_protocols
5744 && event.xclient.format == 32)
5745 {
5746 if (event.xclient.data.l[0]
5747 == dpyinfo->Xatom_wm_take_focus)
5748 {
5749 /* Use x_any_window_to_frame because this
5750 could be the shell widget window
5751 if the frame has no title bar. */
5752 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
5753 #ifdef HAVE_X_I18N
5754 /* Not quite sure this is needed -pd */
5755 if (f && FRAME_XIC (f))
5756 XSetICFocus (FRAME_XIC (f));
5757 #endif
5758 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
5759 instructs the WM to set the input focus automatically for
5760 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
5761 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
5762 it has set the focus. So, XSetInputFocus below is not
5763 needed.
5764
5765 The call to XSetInputFocus below has also caused trouble. In
5766 cases where the XSetInputFocus done by the WM and the one
5767 below are temporally close (on a fast machine), the call
5768 below can generate additional FocusIn events which confuse
5769 Emacs. */
5770
5771 /* Since we set WM_TAKE_FOCUS, we must call
5772 XSetInputFocus explicitly. But not if f is null,
5773 since that might be an event for a deleted frame. */
5774 if (f)
5775 {
5776 Display *d = event.xclient.display;
5777 /* Catch and ignore errors, in case window has been
5778 iconified by a window manager such as GWM. */
5779 x_catch_errors (d);
5780 XSetInputFocus (d, event.xclient.window,
5781 /* The ICCCM says this is
5782 the only valid choice. */
5783 RevertToParent,
5784 event.xclient.data.l[1]);
5785 /* This is needed to detect the error
5786 if there is an error. */
5787 XSync (d, False);
5788 x_uncatch_errors ();
5789 }
5790 /* Not certain about handling scroll bars here */
5791 #endif /* 0 */
5792 goto done;
5793 }
5794
5795 if (event.xclient.data.l[0]
5796 == dpyinfo->Xatom_wm_save_yourself)
5797 {
5798 /* Save state modify the WM_COMMAND property to
5799 something which can reinstate us. This notifies
5800 the session manager, who's looking for such a
5801 PropertyNotify. Can restart processing when
5802 a keyboard or mouse event arrives. */
5803 /* If we have a session manager, don't set this.
5804 KDE will then start two Emacsen, one for the
5805 session manager and one for this. */
5806 #ifdef HAVE_X_SM
5807 if (! x_session_have_connection ())
5808 #endif
5809 {
5810 f = x_top_window_to_frame (dpyinfo,
5811 event.xclient.window);
5812 /* This is just so we only give real data once
5813 for a single Emacs process. */
5814 if (f == SELECTED_FRAME ())
5815 XSetCommand (FRAME_X_DISPLAY (f),
5816 event.xclient.window,
5817 initial_argv, initial_argc);
5818 else if (f)
5819 XSetCommand (FRAME_X_DISPLAY (f),
5820 event.xclient.window,
5821 0, 0);
5822 }
5823 goto done;
5824 }
5825
5826 if (event.xclient.data.l[0]
5827 == dpyinfo->Xatom_wm_delete_window)
5828 {
5829 f = x_any_window_to_frame (dpyinfo,
5830 event.xclient.window);
5831 if (!f)
5832 goto OTHER; /* May be a dialog that is to be removed */
5833
5834 inev.ie.kind = DELETE_WINDOW_EVENT;
5835 XSETFRAME (inev.ie.frame_or_window, f);
5836 goto done;
5837 }
5838
5839 goto done;
5840 }
5841
5842 if (event.xclient.message_type
5843 == dpyinfo->Xatom_wm_configure_denied)
5844 {
5845 goto done;
5846 }
5847
5848 if (event.xclient.message_type
5849 == dpyinfo->Xatom_wm_window_moved)
5850 {
5851 int new_x, new_y;
5852 f = x_window_to_frame (dpyinfo, event.xclient.window);
5853
5854 new_x = event.xclient.data.s[0];
5855 new_y = event.xclient.data.s[1];
5856
5857 if (f)
5858 {
5859 f->left_pos = new_x;
5860 f->top_pos = new_y;
5861 }
5862 goto done;
5863 }
5864
5865 #ifdef HACK_EDITRES
5866 if (event.xclient.message_type
5867 == dpyinfo->Xatom_editres)
5868 {
5869 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
5870 if (f)
5871 _XEditResCheckMessages (f->output_data.x->widget, NULL,
5872 &event, NULL);
5873 goto done;
5874 }
5875 #endif /* HACK_EDITRES */
5876
5877 if ((event.xclient.message_type
5878 == dpyinfo->Xatom_DONE)
5879 || (event.xclient.message_type
5880 == dpyinfo->Xatom_PAGE))
5881 {
5882 /* Ghostview job completed. Kill it. We could
5883 reply with "Next" if we received "Page", but we
5884 currently never do because we are interested in
5885 images, only, which should have 1 page. */
5886 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
5887 f = x_window_to_frame (dpyinfo, event.xclient.window);
5888 if (!f)
5889 goto OTHER;
5890 x_kill_gs_process (pixmap, f);
5891 expose_frame (f, 0, 0, 0, 0);
5892 goto done;
5893 }
5894
5895 #ifdef USE_TOOLKIT_SCROLL_BARS
5896 /* Scroll bar callbacks send a ClientMessage from which
5897 we construct an input_event. */
5898 if (event.xclient.message_type
5899 == dpyinfo->Xatom_Scrollbar)
5900 {
5901 x_scroll_bar_to_input_event (&event, &inev.ie);
5902 *finish = X_EVENT_GOTO_OUT;
5903 goto done;
5904 }
5905 #endif /* USE_TOOLKIT_SCROLL_BARS */
5906
5907 /* XEmbed messages from the embedder (if any). */
5908 if (event.xclient.message_type
5909 == dpyinfo->Xatom_XEMBED)
5910 {
5911 enum xembed_message msg = event.xclient.data.l[1];
5912 if (msg == XEMBED_FOCUS_IN || msg == XEMBED_FOCUS_OUT)
5913 x_detect_focus_change (dpyinfo, &event, &inev.ie);
5914
5915 *finish = X_EVENT_GOTO_OUT;
5916 goto done;
5917 }
5918
5919 xft_settings_event (dpyinfo, &event);
5920
5921 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
5922 if (!f)
5923 goto OTHER;
5924 if (x_handle_dnd_message (f, &event.xclient, dpyinfo, &inev.ie))
5925 *finish = X_EVENT_DROP;
5926 }
5927 break;
5928
5929 case SelectionNotify:
5930 last_user_time = event.xselection.time;
5931 #ifdef USE_X_TOOLKIT
5932 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
5933 goto OTHER;
5934 #endif /* not USE_X_TOOLKIT */
5935 x_handle_selection_notify (&event.xselection);
5936 break;
5937
5938 case SelectionClear: /* Someone has grabbed ownership. */
5939 last_user_time = event.xselectionclear.time;
5940 #ifdef USE_X_TOOLKIT
5941 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
5942 goto OTHER;
5943 #endif /* USE_X_TOOLKIT */
5944 {
5945 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
5946
5947 inev.ie.kind = SELECTION_CLEAR_EVENT;
5948 SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display;
5949 SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
5950 SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
5951 inev.ie.frame_or_window = Qnil;
5952 }
5953 break;
5954
5955 case SelectionRequest: /* Someone wants our selection. */
5956 last_user_time = event.xselectionrequest.time;
5957 #ifdef USE_X_TOOLKIT
5958 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
5959 goto OTHER;
5960 #endif /* USE_X_TOOLKIT */
5961 {
5962 XSelectionRequestEvent *eventp
5963 = (XSelectionRequestEvent *) &event;
5964
5965 inev.ie.kind = SELECTION_REQUEST_EVENT;
5966 SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display;
5967 SELECTION_EVENT_REQUESTOR (&inev.sie) = eventp->requestor;
5968 SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
5969 SELECTION_EVENT_TARGET (&inev.sie) = eventp->target;
5970 SELECTION_EVENT_PROPERTY (&inev.sie) = eventp->property;
5971 SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
5972 inev.ie.frame_or_window = Qnil;
5973 }
5974 break;
5975
5976 case PropertyNotify:
5977 last_user_time = event.xproperty.time;
5978 f = x_top_window_to_frame (dpyinfo, event.xproperty.window);
5979 if (f && event.xproperty.atom == dpyinfo->Xatom_net_wm_state)
5980 x_handle_net_wm_state (f, &event.xproperty);
5981
5982 x_handle_property_notify (&event.xproperty);
5983 xft_settings_event (dpyinfo, &event);
5984 goto OTHER;
5985
5986 case ReparentNotify:
5987 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
5988 if (f)
5989 {
5990 int x, y;
5991 f->output_data.x->parent_desc = event.xreparent.parent;
5992 x_real_positions (f, &x, &y);
5993 f->left_pos = x;
5994 f->top_pos = y;
5995
5996 /* Perhaps reparented due to a WM restart. Reset this. */
5997 FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN;
5998 FRAME_X_DISPLAY_INFO (f)->net_supported_window = 0;
5999 }
6000 goto OTHER;
6001
6002 case Expose:
6003 f = x_window_to_frame (dpyinfo, event.xexpose.window);
6004 if (f)
6005 {
6006 #ifdef USE_GTK
6007 /* This seems to be needed for GTK 2.6. */
6008 x_clear_area (event.xexpose.display,
6009 event.xexpose.window,
6010 event.xexpose.x, event.xexpose.y,
6011 event.xexpose.width, event.xexpose.height,
6012 FALSE);
6013 #endif
6014 if (f->async_visible == 0)
6015 {
6016 f->async_visible = 1;
6017 f->async_iconified = 0;
6018 f->output_data.x->has_been_visible = 1;
6019 SET_FRAME_GARBAGED (f);
6020 }
6021 else
6022 expose_frame (f,
6023 event.xexpose.x, event.xexpose.y,
6024 event.xexpose.width, event.xexpose.height);
6025 }
6026 else
6027 {
6028 #ifndef USE_TOOLKIT_SCROLL_BARS
6029 struct scroll_bar *bar;
6030 #endif
6031 #if defined USE_LUCID
6032 /* Submenus of the Lucid menu bar aren't widgets
6033 themselves, so there's no way to dispatch events
6034 to them. Recognize this case separately. */
6035 {
6036 Widget widget
6037 = x_window_to_menu_bar (event.xexpose.window);
6038 if (widget)
6039 xlwmenu_redisplay (widget);
6040 }
6041 #endif /* USE_LUCID */
6042
6043 #ifdef USE_TOOLKIT_SCROLL_BARS
6044 /* Dispatch event to the widget. */
6045 goto OTHER;
6046 #else /* not USE_TOOLKIT_SCROLL_BARS */
6047 bar = x_window_to_scroll_bar (event.xexpose.display,
6048 event.xexpose.window);
6049
6050 if (bar)
6051 x_scroll_bar_expose (bar, &event);
6052 #ifdef USE_X_TOOLKIT
6053 else
6054 goto OTHER;
6055 #endif /* USE_X_TOOLKIT */
6056 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6057 }
6058 break;
6059
6060 case GraphicsExpose: /* This occurs when an XCopyArea's
6061 source area was obscured or not
6062 available. */
6063 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
6064 if (f)
6065 {
6066 expose_frame (f,
6067 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
6068 event.xgraphicsexpose.width,
6069 event.xgraphicsexpose.height);
6070 }
6071 #ifdef USE_X_TOOLKIT
6072 else
6073 goto OTHER;
6074 #endif /* USE_X_TOOLKIT */
6075 break;
6076
6077 case NoExpose: /* This occurs when an XCopyArea's
6078 source area was completely
6079 available. */
6080 break;
6081
6082 case UnmapNotify:
6083 /* Redo the mouse-highlight after the tooltip has gone. */
6084 if (event.xmap.window == tip_window)
6085 {
6086 tip_window = 0;
6087 redo_mouse_highlight ();
6088 }
6089
6090 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
6091 if (f) /* F may no longer exist if
6092 the frame was deleted. */
6093 {
6094 /* While a frame is unmapped, display generation is
6095 disabled; you don't want to spend time updating a
6096 display that won't ever be seen. */
6097 f->async_visible = 0;
6098 /* We can't distinguish, from the event, whether the window
6099 has become iconified or invisible. So assume, if it
6100 was previously visible, than now it is iconified.
6101 But x_make_frame_invisible clears both
6102 the visible flag and the iconified flag;
6103 and that way, we know the window is not iconified now. */
6104 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
6105 {
6106 f->async_iconified = 1;
6107
6108 inev.ie.kind = ICONIFY_EVENT;
6109 XSETFRAME (inev.ie.frame_or_window, f);
6110 }
6111 }
6112 goto OTHER;
6113
6114 case MapNotify:
6115 if (event.xmap.window == tip_window)
6116 /* The tooltip has been drawn already. Avoid
6117 the SET_FRAME_GARBAGED below. */
6118 goto OTHER;
6119
6120 /* We use x_top_window_to_frame because map events can
6121 come for sub-windows and they don't mean that the
6122 frame is visible. */
6123 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
6124 if (f)
6125 {
6126 /* wait_reading_process_output will notice this and update
6127 the frame's display structures.
6128 If we where iconified, we should not set garbaged,
6129 because that stops redrawing on Expose events. This looks
6130 bad if we are called from a recursive event loop
6131 (x_dispatch_event), for example when a dialog is up. */
6132 if (! f->async_iconified)
6133 SET_FRAME_GARBAGED (f);
6134
6135 /* Check if fullscreen was specified before we where mapped the
6136 first time, i.e. from the command line. */
6137 if (!f->output_data.x->has_been_visible)
6138 x_check_fullscreen (f);
6139
6140 f->async_visible = 1;
6141 f->async_iconified = 0;
6142 f->output_data.x->has_been_visible = 1;
6143
6144 if (f->iconified)
6145 {
6146 inev.ie.kind = DEICONIFY_EVENT;
6147 XSETFRAME (inev.ie.frame_or_window, f);
6148 }
6149 else if (! NILP (Vframe_list)
6150 && ! NILP (XCDR (Vframe_list)))
6151 /* Force a redisplay sooner or later
6152 to update the frame titles
6153 in case this is the second frame. */
6154 record_asynch_buffer_change ();
6155
6156 #ifdef USE_GTK
6157 xg_frame_resized (f, -1, -1);
6158 #endif
6159 }
6160 goto OTHER;
6161
6162 case KeyPress:
6163
6164 last_user_time = event.xkey.time;
6165 ignore_next_mouse_click_timeout = 0;
6166
6167 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6168 /* Dispatch KeyPress events when in menu. */
6169 if (popup_activated ())
6170 goto OTHER;
6171 #endif
6172
6173 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
6174
6175 /* If mouse-highlight is an integer, input clears out
6176 mouse highlighting. */
6177 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
6178 && (f == 0
6179 || !EQ (f->tool_bar_window, dpyinfo->mouse_face_window)))
6180 {
6181 clear_mouse_face (dpyinfo);
6182 dpyinfo->mouse_face_hidden = 1;
6183 }
6184
6185 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
6186 if (f == 0)
6187 {
6188 /* Scroll bars consume key events, but we want
6189 the keys to go to the scroll bar's frame. */
6190 Widget widget = XtWindowToWidget (dpyinfo->display,
6191 event.xkey.window);
6192 if (widget && XmIsScrollBar (widget))
6193 {
6194 widget = XtParent (widget);
6195 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
6196 }
6197 }
6198 #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
6199
6200 if (f != 0)
6201 {
6202 KeySym keysym, orig_keysym;
6203 /* al%imercury@uunet.uu.net says that making this 81
6204 instead of 80 fixed a bug whereby meta chars made
6205 his Emacs hang.
6206
6207 It seems that some version of XmbLookupString has
6208 a bug of not returning XBufferOverflow in
6209 status_return even if the input is too long to
6210 fit in 81 bytes. So, we must prepare sufficient
6211 bytes for copy_buffer. 513 bytes (256 chars for
6212 two-byte character set) seems to be a fairly good
6213 approximation. -- 2000.8.10 handa@etl.go.jp */
6214 unsigned char copy_buffer[513];
6215 unsigned char *copy_bufptr = copy_buffer;
6216 int copy_bufsiz = sizeof (copy_buffer);
6217 int modifiers;
6218 Lisp_Object coding_system = Qlatin_1;
6219 Lisp_Object c;
6220
6221 #ifdef USE_GTK
6222 /* Don't pass keys to GTK. A Tab will shift focus to the
6223 tool bar in GTK 2.4. Keys will still go to menus and
6224 dialogs because in that case popup_activated is TRUE
6225 (see above). */
6226 *finish = X_EVENT_DROP;
6227 #endif
6228
6229 event.xkey.state
6230 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
6231 extra_keyboard_modifiers);
6232 modifiers = event.xkey.state;
6233
6234 /* This will have to go some day... */
6235
6236 /* make_lispy_event turns chars into control chars.
6237 Don't do it here because XLookupString is too eager. */
6238 event.xkey.state &= ~ControlMask;
6239 event.xkey.state &= ~(dpyinfo->meta_mod_mask
6240 | dpyinfo->super_mod_mask
6241 | dpyinfo->hyper_mod_mask
6242 | dpyinfo->alt_mod_mask);
6243
6244 /* In case Meta is ComposeCharacter,
6245 clear its status. According to Markus Ehrnsperger
6246 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
6247 this enables ComposeCharacter to work whether or
6248 not it is combined with Meta. */
6249 if (modifiers & dpyinfo->meta_mod_mask)
6250 bzero (&compose_status, sizeof (compose_status));
6251
6252 #ifdef HAVE_X_I18N
6253 if (FRAME_XIC (f))
6254 {
6255 Status status_return;
6256
6257 coding_system = Vlocale_coding_system;
6258 nbytes = XmbLookupString (FRAME_XIC (f),
6259 &event.xkey, copy_bufptr,
6260 copy_bufsiz, &keysym,
6261 &status_return);
6262 if (status_return == XBufferOverflow)
6263 {
6264 copy_bufsiz = nbytes + 1;
6265 copy_bufptr = (unsigned char *) alloca (copy_bufsiz);
6266 nbytes = XmbLookupString (FRAME_XIC (f),
6267 &event.xkey, copy_bufptr,
6268 copy_bufsiz, &keysym,
6269 &status_return);
6270 }
6271 /* Xutf8LookupString is a new but already deprecated interface. -stef */
6272 if (status_return == XLookupNone)
6273 break;
6274 else if (status_return == XLookupChars)
6275 {
6276 keysym = NoSymbol;
6277 modifiers = 0;
6278 }
6279 else if (status_return != XLookupKeySym
6280 && status_return != XLookupBoth)
6281 abort ();
6282 }
6283 else
6284 nbytes = XLookupString (&event.xkey, copy_bufptr,
6285 copy_bufsiz, &keysym,
6286 &compose_status);
6287 #else
6288 nbytes = XLookupString (&event.xkey, copy_bufptr,
6289 copy_bufsiz, &keysym,
6290 &compose_status);
6291 #endif
6292
6293 /* If not using XIM/XIC, and a compose sequence is in progress,
6294 we break here. Otherwise, chars_matched is always 0. */
6295 if (compose_status.chars_matched > 0 && nbytes == 0)
6296 break;
6297
6298 bzero (&compose_status, sizeof (compose_status));
6299 orig_keysym = keysym;
6300
6301 /* Common for all keysym input events. */
6302 XSETFRAME (inev.ie.frame_or_window, f);
6303 inev.ie.modifiers
6304 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), modifiers);
6305 inev.ie.timestamp = event.xkey.time;
6306
6307 /* First deal with keysyms which have defined
6308 translations to characters. */
6309 if (keysym >= 32 && keysym < 128)
6310 /* Avoid explicitly decoding each ASCII character. */
6311 {
6312 inev.ie.kind = ASCII_KEYSTROKE_EVENT;
6313 inev.ie.code = keysym;
6314 goto done_keysym;
6315 }
6316
6317 /* Keysyms directly mapped to Unicode characters. */
6318 if (keysym >= 0x01000000 && keysym <= 0x0110FFFF)
6319 {
6320 if (keysym < 0x01000080)
6321 inev.ie.kind = ASCII_KEYSTROKE_EVENT;
6322 else
6323 inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
6324 inev.ie.code = keysym & 0xFFFFFF;
6325 goto done_keysym;
6326 }
6327
6328 /* Now non-ASCII. */
6329 if (HASH_TABLE_P (Vx_keysym_table)
6330 && (NATNUMP (c = Fgethash (make_number (keysym),
6331 Vx_keysym_table,
6332 Qnil))))
6333 {
6334 inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
6335 ? ASCII_KEYSTROKE_EVENT
6336 : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
6337 inev.ie.code = XFASTINT (c);
6338 goto done_keysym;
6339 }
6340
6341 /* Random non-modifier sorts of keysyms. */
6342 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
6343 || keysym == XK_Delete
6344 #ifdef XK_ISO_Left_Tab
6345 || (keysym >= XK_ISO_Left_Tab
6346 && keysym <= XK_ISO_Enter)
6347 #endif
6348 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
6349 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
6350 #ifdef HPUX
6351 /* This recognizes the "extended function
6352 keys". It seems there's no cleaner way.
6353 Test IsModifierKey to avoid handling
6354 mode_switch incorrectly. */
6355 || ((unsigned) (keysym) >= XK_Select
6356 && (unsigned)(keysym) < XK_KP_Space)
6357 #endif
6358 #ifdef XK_dead_circumflex
6359 || orig_keysym == XK_dead_circumflex
6360 #endif
6361 #ifdef XK_dead_grave
6362 || orig_keysym == XK_dead_grave
6363 #endif
6364 #ifdef XK_dead_tilde
6365 || orig_keysym == XK_dead_tilde
6366 #endif
6367 #ifdef XK_dead_diaeresis
6368 || orig_keysym == XK_dead_diaeresis
6369 #endif
6370 #ifdef XK_dead_macron
6371 || orig_keysym == XK_dead_macron
6372 #endif
6373 #ifdef XK_dead_degree
6374 || orig_keysym == XK_dead_degree
6375 #endif
6376 #ifdef XK_dead_acute
6377 || orig_keysym == XK_dead_acute
6378 #endif
6379 #ifdef XK_dead_cedilla
6380 || orig_keysym == XK_dead_cedilla
6381 #endif
6382 #ifdef XK_dead_breve
6383 || orig_keysym == XK_dead_breve
6384 #endif
6385 #ifdef XK_dead_ogonek
6386 || orig_keysym == XK_dead_ogonek
6387 #endif
6388 #ifdef XK_dead_caron
6389 || orig_keysym == XK_dead_caron
6390 #endif
6391 #ifdef XK_dead_doubleacute
6392 || orig_keysym == XK_dead_doubleacute
6393 #endif
6394 #ifdef XK_dead_abovedot
6395 || orig_keysym == XK_dead_abovedot
6396 #endif
6397 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
6398 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
6399 /* Any "vendor-specific" key is ok. */
6400 || (orig_keysym & (1 << 28))
6401 || (keysym != NoSymbol && nbytes == 0))
6402 && ! (IsModifierKey (orig_keysym)
6403 /* The symbols from XK_ISO_Lock
6404 to XK_ISO_Last_Group_Lock
6405 don't have real modifiers but
6406 should be treated similarly to
6407 Mode_switch by Emacs. */
6408 #if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
6409 || ((unsigned)(orig_keysym)
6410 >= XK_ISO_Lock
6411 && (unsigned)(orig_keysym)
6412 <= XK_ISO_Last_Group_Lock)
6413 #endif
6414 ))
6415 {
6416 STORE_KEYSYM_FOR_DEBUG (keysym);
6417 /* make_lispy_event will convert this to a symbolic
6418 key. */
6419 inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
6420 inev.ie.code = keysym;
6421 goto done_keysym;
6422 }
6423
6424 { /* Raw bytes, not keysym. */
6425 register int i;
6426 register int c;
6427 int nchars, len;
6428
6429 for (i = 0, nchars = 0; i < nbytes; i++)
6430 {
6431 if (ASCII_BYTE_P (copy_bufptr[i]))
6432 nchars++;
6433 STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]);
6434 }
6435
6436 if (nchars < nbytes)
6437 {
6438 /* Decode the input data. */
6439 int require;
6440 unsigned char *p;
6441
6442 /* The input should be decoded with `coding_system'
6443 which depends on which X*LookupString function
6444 we used just above and the locale. */
6445 setup_coding_system (coding_system, &coding);
6446 coding.src_multibyte = 0;
6447 coding.dst_multibyte = 1;
6448 /* The input is converted to events, thus we can't
6449 handle composition. Anyway, there's no XIM that
6450 gives us composition information. */
6451 coding.common_flags &= ~CODING_ANNOTATION_MASK;
6452
6453 require = MAX_MULTIBYTE_LENGTH * nbytes;
6454 coding.destination = alloca (require);
6455 coding.dst_bytes = require;
6456 coding.mode |= CODING_MODE_LAST_BLOCK;
6457 decode_coding_c_string (&coding, copy_bufptr, nbytes, Qnil);
6458 nbytes = coding.produced;
6459 nchars = coding.produced_char;
6460 copy_bufptr = coding.destination;
6461 }
6462
6463 /* Convert the input data to a sequence of
6464 character events. */
6465 for (i = 0; i < nbytes; i += len)
6466 {
6467 if (nchars == nbytes)
6468 c = copy_bufptr[i], len = 1;
6469 else
6470 c = STRING_CHAR_AND_LENGTH (copy_bufptr + i, len);
6471 inev.ie.kind = (SINGLE_BYTE_CHAR_P (c)
6472 ? ASCII_KEYSTROKE_EVENT
6473 : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
6474 inev.ie.code = c;
6475 kbd_buffer_store_event_hold (&inev.ie, hold_quit);
6476 }
6477
6478 count += nchars;
6479
6480 inev.ie.kind = NO_EVENT; /* Already stored above. */
6481
6482 if (keysym == NoSymbol)
6483 break;
6484 }
6485 }
6486 done_keysym:
6487 #ifdef HAVE_X_I18N
6488 /* Don't dispatch this event since XtDispatchEvent calls
6489 XFilterEvent, and two calls in a row may freeze the
6490 client. */
6491 break;
6492 #else
6493 goto OTHER;
6494 #endif
6495
6496 case KeyRelease:
6497 last_user_time = event.xkey.time;
6498 #ifdef HAVE_X_I18N
6499 /* Don't dispatch this event since XtDispatchEvent calls
6500 XFilterEvent, and two calls in a row may freeze the
6501 client. */
6502 break;
6503 #else
6504 goto OTHER;
6505 #endif
6506
6507 case EnterNotify:
6508 last_user_time = event.xcrossing.time;
6509 x_detect_focus_change (dpyinfo, &event, &inev.ie);
6510
6511 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
6512
6513 if (f && x_mouse_click_focus_ignore_position)
6514 ignore_next_mouse_click_timeout = event.xmotion.time + 200;
6515
6516 /* EnterNotify counts as mouse movement,
6517 so update things that depend on mouse position. */
6518 if (f && !f->output_data.x->hourglass_p)
6519 note_mouse_movement (f, &event.xmotion);
6520 #ifdef USE_GTK
6521 /* We may get an EnterNotify on the buttons in the toolbar. In that
6522 case we moved out of any highlighted area and need to note this. */
6523 if (!f && last_mouse_glyph_frame)
6524 note_mouse_movement (last_mouse_glyph_frame, &event.xmotion);
6525 #endif
6526 goto OTHER;
6527
6528 case FocusIn:
6529 x_detect_focus_change (dpyinfo, &event, &inev.ie);
6530 goto OTHER;
6531
6532 case LeaveNotify:
6533 last_user_time = event.xcrossing.time;
6534 x_detect_focus_change (dpyinfo, &event, &inev.ie);
6535
6536 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
6537 if (f)
6538 {
6539 if (f == dpyinfo->mouse_face_mouse_frame)
6540 {
6541 /* If we move outside the frame, then we're
6542 certainly no longer on any text in the frame. */
6543 clear_mouse_face (dpyinfo);
6544 dpyinfo->mouse_face_mouse_frame = 0;
6545 }
6546
6547 /* Generate a nil HELP_EVENT to cancel a help-echo.
6548 Do it only if there's something to cancel.
6549 Otherwise, the startup message is cleared when
6550 the mouse leaves the frame. */
6551 if (any_help_event_p)
6552 do_help = -1;
6553 }
6554 #ifdef USE_GTK
6555 /* See comment in EnterNotify above */
6556 else if (last_mouse_glyph_frame)
6557 note_mouse_movement (last_mouse_glyph_frame, &event.xmotion);
6558 #endif
6559 goto OTHER;
6560
6561 case FocusOut:
6562 x_detect_focus_change (dpyinfo, &event, &inev.ie);
6563 goto OTHER;
6564
6565 case MotionNotify:
6566 {
6567 last_user_time = event.xmotion.time;
6568 previous_help_echo_string = help_echo_string;
6569 help_echo_string = Qnil;
6570
6571 if (dpyinfo->grabbed && last_mouse_frame
6572 && FRAME_LIVE_P (last_mouse_frame))
6573 f = last_mouse_frame;
6574 else
6575 f = x_window_to_frame (dpyinfo, event.xmotion.window);
6576
6577 if (dpyinfo->mouse_face_hidden)
6578 {
6579 dpyinfo->mouse_face_hidden = 0;
6580 clear_mouse_face (dpyinfo);
6581 }
6582
6583 #ifdef USE_GTK
6584 if (f && xg_event_is_for_scrollbar (f, &event))
6585 f = 0;
6586 #endif
6587 if (f)
6588 {
6589
6590 /* Generate SELECT_WINDOW_EVENTs when needed.
6591 Don't let popup menus influence things (bug#1261). */
6592 if (!NILP (Vmouse_autoselect_window) && !popup_activated ())
6593 {
6594 Lisp_Object window;
6595
6596 window = window_from_coordinates (f,
6597 event.xmotion.x, event.xmotion.y,
6598 0, 0, 0, 0);
6599
6600 /* Window will be selected only when it is not selected now and
6601 last mouse movement event was not in it. Minibuffer window
6602 will be selected only when it is active. */
6603 if (WINDOWP (window)
6604 && !EQ (window, last_window)
6605 && !EQ (window, selected_window)
6606 /* For click-to-focus window managers
6607 create event iff we don't leave the
6608 selected frame. */
6609 && (focus_follows_mouse
6610 || (EQ (XWINDOW (window)->frame,
6611 XWINDOW (selected_window)->frame))))
6612 {
6613 inev.ie.kind = SELECT_WINDOW_EVENT;
6614 inev.ie.frame_or_window = window;
6615 }
6616
6617 last_window=window;
6618 }
6619 if (!note_mouse_movement (f, &event.xmotion))
6620 help_echo_string = previous_help_echo_string;
6621 }
6622 else
6623 {
6624 #ifndef USE_TOOLKIT_SCROLL_BARS
6625 struct scroll_bar *bar
6626 = x_window_to_scroll_bar (event.xmotion.display,
6627 event.xmotion.window);
6628
6629 if (bar)
6630 x_scroll_bar_note_movement (bar, &event);
6631 #endif /* USE_TOOLKIT_SCROLL_BARS */
6632
6633 /* If we move outside the frame, then we're
6634 certainly no longer on any text in the frame. */
6635 clear_mouse_face (dpyinfo);
6636 }
6637
6638 /* If the contents of the global variable help_echo_string
6639 has changed, generate a HELP_EVENT. */
6640 if (!NILP (help_echo_string)
6641 || !NILP (previous_help_echo_string))
6642 do_help = 1;
6643 goto OTHER;
6644 }
6645
6646 case ConfigureNotify:
6647 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
6648 #ifdef USE_GTK
6649 if (!f
6650 && (f = x_any_window_to_frame (dpyinfo, event.xconfigure.window))
6651 && event.xconfigure.window == FRAME_X_WINDOW (f))
6652 {
6653 xg_frame_resized (f, event.xconfigure.width,
6654 event.xconfigure.height);
6655 f = 0;
6656 }
6657 #endif
6658 if (f)
6659 {
6660 #ifndef USE_X_TOOLKIT
6661 #ifndef USE_GTK
6662 int rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, event.xconfigure.height);
6663 int columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, event.xconfigure.width);
6664
6665 /* In the toolkit version, change_frame_size
6666 is called by the code that handles resizing
6667 of the EmacsFrame widget. */
6668
6669 /* Even if the number of character rows and columns has
6670 not changed, the font size may have changed, so we need
6671 to check the pixel dimensions as well. */
6672 if (columns != FRAME_COLS (f)
6673 || rows != FRAME_LINES (f)
6674 || event.xconfigure.width != FRAME_PIXEL_WIDTH (f)
6675 || event.xconfigure.height != FRAME_PIXEL_HEIGHT (f))
6676 {
6677 change_frame_size (f, rows, columns, 0, 1, 0);
6678 SET_FRAME_GARBAGED (f);
6679 cancel_mouse_face (f);
6680 }
6681
6682 FRAME_PIXEL_WIDTH (f) = event.xconfigure.width;
6683 FRAME_PIXEL_HEIGHT (f) = event.xconfigure.height;
6684 #endif /* not USE_GTK */
6685 #endif
6686
6687 #ifdef USE_GTK
6688 /* GTK creates windows but doesn't map them.
6689 Only get real positions when mapped. */
6690 if (FRAME_GTK_OUTER_WIDGET (f)
6691 && gtk_widget_get_mapped (FRAME_GTK_OUTER_WIDGET (f)))
6692 #endif
6693 {
6694 x_real_positions (f, &f->left_pos, &f->top_pos);
6695 }
6696
6697 #ifdef HAVE_X_I18N
6698 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
6699 xic_set_statusarea (f);
6700 #endif
6701
6702 }
6703 goto OTHER;
6704
6705 case ButtonRelease:
6706 case ButtonPress:
6707 {
6708 /* If we decide we want to generate an event to be seen
6709 by the rest of Emacs, we put it here. */
6710 int tool_bar_p = 0;
6711
6712 bzero (&compose_status, sizeof (compose_status));
6713 last_mouse_glyph_frame = 0;
6714 last_user_time = event.xbutton.time;
6715
6716 if (dpyinfo->grabbed
6717 && last_mouse_frame
6718 && FRAME_LIVE_P (last_mouse_frame))
6719 f = last_mouse_frame;
6720 else
6721 f = x_window_to_frame (dpyinfo, event.xbutton.window);
6722
6723 #ifdef USE_GTK
6724 if (f && xg_event_is_for_scrollbar (f, &event))
6725 f = 0;
6726 #endif
6727 if (f)
6728 {
6729 /* Is this in the tool-bar? */
6730 if (WINDOWP (f->tool_bar_window)
6731 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
6732 {
6733 Lisp_Object window;
6734 int x = event.xbutton.x;
6735 int y = event.xbutton.y;
6736
6737 window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
6738 tool_bar_p = EQ (window, f->tool_bar_window);
6739
6740 if (tool_bar_p && event.xbutton.button < 4)
6741 {
6742 handle_tool_bar_click (f, x, y,
6743 event.xbutton.type == ButtonPress,
6744 x_x_to_emacs_modifiers (dpyinfo,
6745 event.xbutton.state));
6746 }
6747 }
6748
6749 if (!tool_bar_p)
6750 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6751 if (! popup_activated ())
6752 #endif
6753 {
6754 if (ignore_next_mouse_click_timeout)
6755 {
6756 if (event.type == ButtonPress
6757 && (int)(event.xbutton.time - ignore_next_mouse_click_timeout) > 0)
6758 {
6759 ignore_next_mouse_click_timeout = 0;
6760 construct_mouse_click (&inev.ie, &event.xbutton, f);
6761 }
6762 if (event.type == ButtonRelease)
6763 ignore_next_mouse_click_timeout = 0;
6764 }
6765 else
6766 construct_mouse_click (&inev.ie, &event.xbutton, f);
6767 }
6768 if (FRAME_X_EMBEDDED_P (f))
6769 xembed_send_message (f, event.xbutton.time,
6770 XEMBED_REQUEST_FOCUS, 0, 0, 0);
6771 }
6772 else
6773 {
6774 struct scroll_bar *bar
6775 = x_window_to_scroll_bar (event.xbutton.display,
6776 event.xbutton.window);
6777
6778 #ifdef USE_TOOLKIT_SCROLL_BARS
6779 /* Make the "Ctrl-Mouse-2 splits window" work for toolkit
6780 scroll bars. */
6781 if (bar && event.xbutton.state & ControlMask)
6782 {
6783 x_scroll_bar_handle_click (bar, &event, &inev.ie);
6784 *finish = X_EVENT_DROP;
6785 }
6786 #else /* not USE_TOOLKIT_SCROLL_BARS */
6787 if (bar)
6788 x_scroll_bar_handle_click (bar, &event, &inev.ie);
6789 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6790 }
6791
6792 if (event.type == ButtonPress)
6793 {
6794 dpyinfo->grabbed |= (1 << event.xbutton.button);
6795 last_mouse_frame = f;
6796
6797 if (!tool_bar_p)
6798 last_tool_bar_item = -1;
6799 }
6800 else
6801 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
6802
6803 /* Ignore any mouse motion that happened before this event;
6804 any subsequent mouse-movement Emacs events should reflect
6805 only motion after the ButtonPress/Release. */
6806 if (f != 0)
6807 f->mouse_moved = 0;
6808
6809 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6810 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
6811 /* For a down-event in the menu bar,
6812 don't pass it to Xt right now.
6813 Instead, save it away
6814 and we will pass it to Xt from kbd_buffer_get_event.
6815 That way, we can run some Lisp code first. */
6816 if (
6817 #ifdef USE_GTK
6818 ! popup_activated ()
6819 /* Gtk+ menus only react to the first three buttons. */
6820 && event.xbutton.button < 3
6821 &&
6822 #endif
6823 f && event.type == ButtonPress
6824 /* Verify the event is really within the menu bar
6825 and not just sent to it due to grabbing. */
6826 && event.xbutton.x >= 0
6827 && event.xbutton.x < FRAME_PIXEL_WIDTH (f)
6828 && event.xbutton.y >= 0
6829 && event.xbutton.y < f->output_data.x->menubar_height
6830 && event.xbutton.same_screen)
6831 {
6832 SET_SAVED_BUTTON_EVENT;
6833 XSETFRAME (last_mouse_press_frame, f);
6834 #ifdef USE_GTK
6835 *finish = X_EVENT_DROP;
6836 #endif
6837 }
6838 else if (event.type == ButtonPress)
6839 {
6840 last_mouse_press_frame = Qnil;
6841 goto OTHER;
6842 }
6843
6844 #ifdef USE_MOTIF /* This should do not harm for Lucid,
6845 but I am trying to be cautious. */
6846 else if (event.type == ButtonRelease)
6847 {
6848 if (!NILP (last_mouse_press_frame))
6849 {
6850 f = XFRAME (last_mouse_press_frame);
6851 if (f->output_data.x)
6852 SET_SAVED_BUTTON_EVENT;
6853 }
6854 else
6855 goto OTHER;
6856 }
6857 #endif /* USE_MOTIF */
6858 else
6859 goto OTHER;
6860 #endif /* USE_X_TOOLKIT || USE_GTK */
6861 }
6862 break;
6863
6864 case CirculateNotify:
6865 goto OTHER;
6866
6867 case CirculateRequest:
6868 goto OTHER;
6869
6870 case VisibilityNotify:
6871 goto OTHER;
6872
6873 case MappingNotify:
6874 /* Someone has changed the keyboard mapping - update the
6875 local cache. */
6876 switch (event.xmapping.request)
6877 {
6878 case MappingModifier:
6879 x_find_modifier_meanings (dpyinfo);
6880 /* This is meant to fall through. */
6881 case MappingKeyboard:
6882 XRefreshKeyboardMapping (&event.xmapping);
6883 }
6884 goto OTHER;
6885
6886 case DestroyNotify:
6887 xft_settings_event (dpyinfo, &event);
6888 break;
6889
6890 default:
6891 OTHER:
6892 #ifdef USE_X_TOOLKIT
6893 BLOCK_INPUT;
6894 if (*finish != X_EVENT_DROP)
6895 XtDispatchEvent (&event);
6896 UNBLOCK_INPUT;
6897 #endif /* USE_X_TOOLKIT */
6898 break;
6899 }
6900
6901 done:
6902 if (inev.ie.kind != NO_EVENT)
6903 {
6904 kbd_buffer_store_event_hold (&inev.ie, hold_quit);
6905 count++;
6906 }
6907
6908 if (do_help
6909 && !(hold_quit && hold_quit->kind != NO_EVENT))
6910 {
6911 Lisp_Object frame;
6912
6913 if (f)
6914 XSETFRAME (frame, f);
6915 else
6916 frame = Qnil;
6917
6918 if (do_help > 0)
6919 {
6920 any_help_event_p = 1;
6921 gen_help_event (help_echo_string, frame, help_echo_window,
6922 help_echo_object, help_echo_pos);
6923 }
6924 else
6925 {
6926 help_echo_string = Qnil;
6927 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
6928 }
6929 count++;
6930 }
6931
6932 *eventp = event;
6933 return count;
6934 }
6935
6936
6937 /* Handles the XEvent EVENT on display DISPLAY.
6938 This is used for event loops outside the normal event handling,
6939 i.e. looping while a popup menu or a dialog is posted.
6940
6941 Returns the value handle_one_xevent sets in the finish argument. */
6942 int
6943 x_dispatch_event (XEvent *event, Display *display)
6944 {
6945 struct x_display_info *dpyinfo;
6946 int finish = X_EVENT_NORMAL;
6947
6948 dpyinfo = x_display_info_for_display (display);
6949
6950 if (dpyinfo)
6951 handle_one_xevent (dpyinfo, event, &finish, 0);
6952
6953 return finish;
6954 }
6955
6956
6957 /* Read events coming from the X server.
6958 This routine is called by the SIGIO handler.
6959 We return as soon as there are no more events to be read.
6960
6961 We return the number of characters stored into the buffer,
6962 thus pretending to be `read' (except the characters we store
6963 in the keyboard buffer can be multibyte, so are not necessarily
6964 C chars).
6965
6966 EXPECTED is nonzero if the caller knows input is available. */
6967
6968 static int
6969 XTread_socket (struct terminal *terminal, int expected, struct input_event *hold_quit)
6970 {
6971 int count = 0;
6972 XEvent event;
6973 int event_found = 0;
6974
6975 if (interrupt_input_blocked)
6976 {
6977 interrupt_input_pending = 1;
6978 #ifdef SYNC_INPUT
6979 pending_signals = 1;
6980 #endif
6981 return -1;
6982 }
6983
6984 interrupt_input_pending = 0;
6985 #ifdef SYNC_INPUT
6986 pending_signals = pending_atimers;
6987 #endif
6988 BLOCK_INPUT;
6989
6990 /* So people can tell when we have read the available input. */
6991 input_signal_count++;
6992
6993 ++handling_signal;
6994
6995 #ifdef HAVE_X_SM
6996 /* Only check session manager input for the primary display. */
6997 if (terminal->id == 1 && x_session_have_connection ())
6998 {
6999 struct input_event inev;
7000 BLOCK_INPUT;
7001 /* We don't need to EVENT_INIT (inev) here, as
7002 x_session_check_input copies an entire input_event. */
7003 if (x_session_check_input (&inev))
7004 {
7005 kbd_buffer_store_event_hold (&inev, hold_quit);
7006 count++;
7007 }
7008 UNBLOCK_INPUT;
7009 }
7010 #endif
7011
7012 /* For debugging, this gives a way to fake an I/O error. */
7013 if (terminal->display_info.x == XTread_socket_fake_io_error)
7014 {
7015 XTread_socket_fake_io_error = 0;
7016 x_io_error_quitter (terminal->display_info.x->display);
7017 }
7018
7019 #ifndef USE_GTK
7020 while (XPending (terminal->display_info.x->display))
7021 {
7022 int finish;
7023
7024 XNextEvent (terminal->display_info.x->display, &event);
7025
7026 #ifdef HAVE_X_I18N
7027 /* Filter events for the current X input method. */
7028 if (x_filter_event (terminal->display_info.x, &event))
7029 continue;
7030 #endif
7031 event_found = 1;
7032
7033 count += handle_one_xevent (terminal->display_info.x,
7034 &event, &finish, hold_quit);
7035
7036 if (finish == X_EVENT_GOTO_OUT)
7037 goto out;
7038 }
7039
7040 #else /* USE_GTK */
7041
7042 /* For GTK we must use the GTK event loop. But XEvents gets passed
7043 to our filter function above, and then to the big event switch.
7044 We use a bunch of globals to communicate with our filter function,
7045 that is kind of ugly, but it works.
7046
7047 There is no way to do one display at the time, GTK just does events
7048 from all displays. */
7049
7050 while (gtk_events_pending ())
7051 {
7052 current_count = count;
7053 current_hold_quit = hold_quit;
7054
7055 gtk_main_iteration ();
7056
7057 count = current_count;
7058 current_count = -1;
7059 current_hold_quit = 0;
7060
7061 if (current_finish == X_EVENT_GOTO_OUT)
7062 break;
7063 }
7064 #endif /* USE_GTK */
7065
7066 out:;
7067
7068 /* On some systems, an X bug causes Emacs to get no more events
7069 when the window is destroyed. Detect that. (1994.) */
7070 if (! event_found)
7071 {
7072 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
7073 One XNOOP in 100 loops will make Emacs terminate.
7074 B. Bretthauer, 1994 */
7075 x_noop_count++;
7076 if (x_noop_count >= 100)
7077 {
7078 x_noop_count=0;
7079
7080 if (next_noop_dpyinfo == 0)
7081 next_noop_dpyinfo = x_display_list;
7082
7083 XNoOp (next_noop_dpyinfo->display);
7084
7085 /* Each time we get here, cycle through the displays now open. */
7086 next_noop_dpyinfo = next_noop_dpyinfo->next;
7087 }
7088 }
7089
7090 /* If the focus was just given to an auto-raising frame,
7091 raise it now. */
7092 /* ??? This ought to be able to handle more than one such frame. */
7093 if (pending_autoraise_frame)
7094 {
7095 x_raise_frame (pending_autoraise_frame);
7096 pending_autoraise_frame = 0;
7097 }
7098
7099 --handling_signal;
7100 UNBLOCK_INPUT;
7101
7102 return count;
7103 }
7104
7105
7106
7107 \f
7108 /***********************************************************************
7109 Text Cursor
7110 ***********************************************************************/
7111
7112 /* Set clipping for output in glyph row ROW. W is the window in which
7113 we operate. GC is the graphics context to set clipping in.
7114
7115 ROW may be a text row or, e.g., a mode line. Text rows must be
7116 clipped to the interior of the window dedicated to text display,
7117 mode lines must be clipped to the whole window. */
7118
7119 static void
7120 x_clip_to_row (struct window *w, struct glyph_row *row, int area, GC gc)
7121 {
7122 struct frame *f = XFRAME (WINDOW_FRAME (w));
7123 XRectangle clip_rect;
7124 int window_x, window_y, window_width;
7125
7126 window_box (w, area, &window_x, &window_y, &window_width, 0);
7127
7128 clip_rect.x = window_x;
7129 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y));
7130 clip_rect.y = max (clip_rect.y, window_y);
7131 clip_rect.width = window_width;
7132 clip_rect.height = row->visible_height;
7133
7134 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
7135 }
7136
7137
7138 /* Draw a hollow box cursor on window W in glyph row ROW. */
7139
7140 static void
7141 x_draw_hollow_cursor (struct window *w, struct glyph_row *row)
7142 {
7143 struct frame *f = XFRAME (WINDOW_FRAME (w));
7144 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7145 Display *dpy = FRAME_X_DISPLAY (f);
7146 int x, y, wd, h;
7147 XGCValues xgcv;
7148 struct glyph *cursor_glyph;
7149 GC gc;
7150
7151 /* Get the glyph the cursor is on. If we can't tell because
7152 the current matrix is invalid or such, give up. */
7153 cursor_glyph = get_phys_cursor_glyph (w);
7154 if (cursor_glyph == NULL)
7155 return;
7156
7157 /* Compute frame-relative coordinates for phys cursor. */
7158 get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h);
7159 wd = w->phys_cursor_width;
7160
7161 /* The foreground of cursor_gc is typically the same as the normal
7162 background color, which can cause the cursor box to be invisible. */
7163 xgcv.foreground = f->output_data.x->cursor_pixel;
7164 if (dpyinfo->scratch_cursor_gc)
7165 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
7166 else
7167 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
7168 GCForeground, &xgcv);
7169 gc = dpyinfo->scratch_cursor_gc;
7170
7171 /* Set clipping, draw the rectangle, and reset clipping again. */
7172 x_clip_to_row (w, row, TEXT_AREA, gc);
7173 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h - 1);
7174 XSetClipMask (dpy, gc, None);
7175 }
7176
7177
7178 /* Draw a bar cursor on window W in glyph row ROW.
7179
7180 Implementation note: One would like to draw a bar cursor with an
7181 angle equal to the one given by the font property XA_ITALIC_ANGLE.
7182 Unfortunately, I didn't find a font yet that has this property set.
7183 --gerd. */
7184
7185 static void
7186 x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text_cursor_kinds kind)
7187 {
7188 struct frame *f = XFRAME (w->frame);
7189 struct glyph *cursor_glyph;
7190
7191 /* If cursor is out of bounds, don't draw garbage. This can happen
7192 in mini-buffer windows when switching between echo area glyphs
7193 and mini-buffer. */
7194 cursor_glyph = get_phys_cursor_glyph (w);
7195 if (cursor_glyph == NULL)
7196 return;
7197
7198 /* If on an image, draw like a normal cursor. That's usually better
7199 visible than drawing a bar, esp. if the image is large so that
7200 the bar might not be in the window. */
7201 if (cursor_glyph->type == IMAGE_GLYPH)
7202 {
7203 struct glyph_row *row;
7204 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
7205 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
7206 }
7207 else
7208 {
7209 Display *dpy = FRAME_X_DISPLAY (f);
7210 Window window = FRAME_X_WINDOW (f);
7211 GC gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
7212 unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures;
7213 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
7214 XGCValues xgcv;
7215
7216 /* If the glyph's background equals the color we normally draw
7217 the bars cursor in, the bar cursor in its normal color is
7218 invisible. Use the glyph's foreground color instead in this
7219 case, on the assumption that the glyph's colors are chosen so
7220 that the glyph is legible. */
7221 if (face->background == f->output_data.x->cursor_pixel)
7222 xgcv.background = xgcv.foreground = face->foreground;
7223 else
7224 xgcv.background = xgcv.foreground = f->output_data.x->cursor_pixel;
7225 xgcv.graphics_exposures = 0;
7226
7227 if (gc)
7228 XChangeGC (dpy, gc, mask, &xgcv);
7229 else
7230 {
7231 gc = XCreateGC (dpy, window, mask, &xgcv);
7232 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
7233 }
7234
7235 x_clip_to_row (w, row, TEXT_AREA, gc);
7236
7237 if (kind == BAR_CURSOR)
7238 {
7239 if (width < 0)
7240 width = FRAME_CURSOR_WIDTH (f);
7241 width = min (cursor_glyph->pixel_width, width);
7242
7243 w->phys_cursor_width = width;
7244
7245 XFillRectangle (dpy, window, gc,
7246 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
7247 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
7248 width, row->height);
7249 }
7250 else
7251 {
7252 int dummy_x, dummy_y, dummy_h;
7253
7254 if (width < 0)
7255 width = row->height;
7256
7257 width = min (row->height, width);
7258
7259 get_phys_cursor_geometry (w, row, cursor_glyph, &dummy_x,
7260 &dummy_y, &dummy_h);
7261
7262 XFillRectangle (dpy, window, gc,
7263 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
7264 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
7265 row->height - width),
7266 w->phys_cursor_width, width);
7267 }
7268
7269 XSetClipMask (dpy, gc, None);
7270 }
7271 }
7272
7273
7274 /* RIF: Define cursor CURSOR on frame F. */
7275
7276 static void
7277 x_define_frame_cursor (struct frame *f, Cursor cursor)
7278 {
7279 if (!f->pointer_invisible
7280 && f->output_data.x->current_cursor != cursor)
7281 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
7282 f->output_data.x->current_cursor = cursor;
7283 }
7284
7285
7286 /* RIF: Clear area on frame F. */
7287
7288 static void
7289 x_clear_frame_area (struct frame *f, int x, int y, int width, int height)
7290 {
7291 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7292 x, y, width, height, False);
7293 #ifdef USE_GTK
7294 /* Must queue a redraw, because scroll bars might have been cleared. */
7295 if (FRAME_GTK_WIDGET (f))
7296 gtk_widget_queue_draw (FRAME_GTK_WIDGET (f));
7297 #endif
7298 }
7299
7300
7301 /* RIF: Draw cursor on window W. */
7302
7303 static void
7304 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)
7305 {
7306 struct frame *f = XFRAME (WINDOW_FRAME (w));
7307
7308 if (on_p)
7309 {
7310 w->phys_cursor_type = cursor_type;
7311 w->phys_cursor_on_p = 1;
7312
7313 if (glyph_row->exact_window_width_line_p
7314 && (glyph_row->reversed_p
7315 ? (w->phys_cursor.hpos < 0)
7316 : (w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])))
7317 {
7318 glyph_row->cursor_in_fringe_p = 1;
7319 draw_fringe_bitmap (w, glyph_row, glyph_row->reversed_p);
7320 }
7321 else
7322 {
7323 switch (cursor_type)
7324 {
7325 case HOLLOW_BOX_CURSOR:
7326 x_draw_hollow_cursor (w, glyph_row);
7327 break;
7328
7329 case FILLED_BOX_CURSOR:
7330 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
7331 break;
7332
7333 case BAR_CURSOR:
7334 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
7335 break;
7336
7337 case HBAR_CURSOR:
7338 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
7339 break;
7340
7341 case NO_CURSOR:
7342 w->phys_cursor_width = 0;
7343 break;
7344
7345 default:
7346 abort ();
7347 }
7348 }
7349
7350 #ifdef HAVE_X_I18N
7351 if (w == XWINDOW (f->selected_window))
7352 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
7353 xic_set_preeditarea (w, x, y);
7354 #endif
7355 }
7356
7357 #ifndef XFlush
7358 XFlush (FRAME_X_DISPLAY (f));
7359 #endif
7360 }
7361
7362 \f
7363 /* Icons. */
7364
7365 /* Make the x-window of frame F use the gnu icon bitmap. */
7366
7367 int
7368 x_bitmap_icon (struct frame *f, Lisp_Object file)
7369 {
7370 int bitmap_id;
7371
7372 if (FRAME_X_WINDOW (f) == 0)
7373 return 1;
7374
7375 /* Free up our existing icon bitmap and mask if any. */
7376 if (f->output_data.x->icon_bitmap > 0)
7377 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
7378 f->output_data.x->icon_bitmap = 0;
7379
7380 if (STRINGP (file))
7381 {
7382 #ifdef USE_GTK
7383 /* Use gtk_window_set_icon_from_file () if available,
7384 It's not restricted to bitmaps */
7385 if (xg_set_icon (f, file))
7386 return 0;
7387 #endif /* USE_GTK */
7388 bitmap_id = x_create_bitmap_from_file (f, file);
7389 x_create_bitmap_mask (f, bitmap_id);
7390 }
7391 else
7392 {
7393 /* Create the GNU bitmap and mask if necessary. */
7394 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
7395 {
7396 int rc = -1;
7397
7398 #ifdef USE_GTK
7399
7400 if (xg_set_icon (f, xg_default_icon_file)
7401 || xg_set_icon_from_xpm_data (f, gnu_xpm_bits))
7402 return 0;
7403
7404 #elif defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
7405
7406 rc = x_create_bitmap_from_xpm_data (f, gnu_xpm_bits);
7407 if (rc != -1)
7408 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id = rc;
7409
7410 #endif
7411
7412 /* If all else fails, use the (black and white) xbm image. */
7413 if (rc == -1)
7414 {
7415 rc = x_create_bitmap_from_data (f, gnu_xbm_bits,
7416 gnu_xbm_width, gnu_xbm_height);
7417 if (rc == -1)
7418 return 1;
7419
7420 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id = rc;
7421 x_create_bitmap_mask (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
7422 }
7423 }
7424
7425 /* The first time we create the GNU bitmap and mask,
7426 this increments the ref-count one extra time.
7427 As a result, the GNU bitmap and mask are never freed.
7428 That way, we don't have to worry about allocating it again. */
7429 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
7430
7431 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
7432 }
7433
7434 x_wm_set_icon_pixmap (f, bitmap_id);
7435 f->output_data.x->icon_bitmap = bitmap_id;
7436
7437 return 0;
7438 }
7439
7440
7441 /* Make the x-window of frame F use a rectangle with text.
7442 Use ICON_NAME as the text. */
7443
7444 int
7445 x_text_icon (struct frame *f, char *icon_name)
7446 {
7447 if (FRAME_X_WINDOW (f) == 0)
7448 return 1;
7449
7450 {
7451 XTextProperty text;
7452 text.value = (unsigned char *) icon_name;
7453 text.encoding = XA_STRING;
7454 text.format = 8;
7455 text.nitems = strlen (icon_name);
7456 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text);
7457 }
7458
7459 if (f->output_data.x->icon_bitmap > 0)
7460 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
7461 f->output_data.x->icon_bitmap = 0;
7462 x_wm_set_icon_pixmap (f, 0);
7463
7464 return 0;
7465 }
7466 \f
7467 #define X_ERROR_MESSAGE_SIZE 200
7468
7469 /* If non-nil, this should be a string.
7470 It means catch X errors and store the error message in this string.
7471
7472 The reason we use a stack is that x_catch_error/x_uncatch_error can
7473 be called from a signal handler.
7474 */
7475
7476 struct x_error_message_stack {
7477 char string[X_ERROR_MESSAGE_SIZE];
7478 Display *dpy;
7479 struct x_error_message_stack *prev;
7480 };
7481 static struct x_error_message_stack *x_error_message;
7482
7483 /* An X error handler which stores the error message in
7484 *x_error_message. This is called from x_error_handler if
7485 x_catch_errors is in effect. */
7486
7487 static void
7488 x_error_catcher (Display *display, XErrorEvent *error)
7489 {
7490 XGetErrorText (display, error->error_code,
7491 x_error_message->string,
7492 X_ERROR_MESSAGE_SIZE);
7493 }
7494
7495 /* Begin trapping X errors for display DPY. Actually we trap X errors
7496 for all displays, but DPY should be the display you are actually
7497 operating on.
7498
7499 After calling this function, X protocol errors no longer cause
7500 Emacs to exit; instead, they are recorded in the string
7501 stored in *x_error_message.
7502
7503 Calling x_check_errors signals an Emacs error if an X error has
7504 occurred since the last call to x_catch_errors or x_check_errors.
7505
7506 Calling x_uncatch_errors resumes the normal error handling. */
7507
7508 void x_check_errors (Display *dpy, char *format);
7509
7510 void
7511 x_catch_errors (Display *dpy)
7512 {
7513 struct x_error_message_stack *data = xmalloc (sizeof (*data));
7514
7515 /* Make sure any errors from previous requests have been dealt with. */
7516 XSync (dpy, False);
7517
7518 data->dpy = dpy;
7519 data->string[0] = 0;
7520 data->prev = x_error_message;
7521 x_error_message = data;
7522 }
7523
7524 /* Undo the last x_catch_errors call.
7525 DPY should be the display that was passed to x_catch_errors. */
7526
7527 void
7528 x_uncatch_errors (void)
7529 {
7530 struct x_error_message_stack *tmp;
7531
7532 BLOCK_INPUT;
7533
7534 /* The display may have been closed before this function is called.
7535 Check if it is still open before calling XSync. */
7536 if (x_display_info_for_display (x_error_message->dpy) != 0)
7537 XSync (x_error_message->dpy, False);
7538
7539 tmp = x_error_message;
7540 x_error_message = x_error_message->prev;
7541 xfree (tmp);
7542 UNBLOCK_INPUT;
7543 }
7544
7545 /* If any X protocol errors have arrived since the last call to
7546 x_catch_errors or x_check_errors, signal an Emacs error using
7547 sprintf (a buffer, FORMAT, the x error message text) as the text. */
7548
7549 void
7550 x_check_errors (Display *dpy, char *format)
7551 {
7552 /* Make sure to catch any errors incurred so far. */
7553 XSync (dpy, False);
7554
7555 if (x_error_message->string[0])
7556 {
7557 char string[X_ERROR_MESSAGE_SIZE];
7558 bcopy (x_error_message->string, string, X_ERROR_MESSAGE_SIZE);
7559 x_uncatch_errors ();
7560 error (format, string);
7561 }
7562 }
7563
7564 /* Nonzero if we had any X protocol errors
7565 since we did x_catch_errors on DPY. */
7566
7567 int
7568 x_had_errors_p (Display *dpy)
7569 {
7570 /* Make sure to catch any errors incurred so far. */
7571 XSync (dpy, False);
7572
7573 return x_error_message->string[0] != 0;
7574 }
7575
7576 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
7577
7578 void
7579 x_clear_errors (Display *dpy)
7580 {
7581 x_error_message->string[0] = 0;
7582 }
7583
7584 #if 0 /* See comment in unwind_to_catch why calling this is a bad
7585 * idea. --lorentey */
7586 /* Close off all unclosed x_catch_errors calls. */
7587
7588 void
7589 x_fully_uncatch_errors ()
7590 {
7591 while (x_error_message)
7592 x_uncatch_errors ();
7593 }
7594 #endif
7595
7596 /* Nonzero if x_catch_errors has been done and not yet canceled. */
7597
7598 int
7599 x_catching_errors (void)
7600 {
7601 return x_error_message != 0;
7602 }
7603
7604 #if 0
7605 static unsigned int x_wire_count;
7606 x_trace_wire ()
7607 {
7608 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
7609 }
7610 #endif /* ! 0 */
7611
7612 \f
7613 /* Handle SIGPIPE, which can happen when the connection to a server
7614 simply goes away. SIGPIPE is handled by x_connection_signal.
7615 Don't need to do anything, because the write which caused the
7616 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
7617 which will do the appropriate cleanup for us. */
7618
7619 static SIGTYPE
7620 x_connection_signal (int signalnum) /* If we don't have an argument, */
7621 /* some compilers complain in signal calls. */
7622 {
7623 #ifdef USG
7624 /* USG systems forget handlers when they are used;
7625 must reestablish each time */
7626 signal (signalnum, x_connection_signal);
7627 #endif /* USG */
7628 }
7629
7630 \f
7631 /************************************************************************
7632 Handling X errors
7633 ************************************************************************/
7634
7635 /* Error message passed to x_connection_closed. */
7636
7637 static char *error_msg;
7638
7639 /* Function installed as fatal_error_signal_hook in
7640 x_connection_closed. Print the X error message, and exit normally,
7641 instead of dumping core when XtCloseDisplay fails. */
7642
7643 static void
7644 x_fatal_error_signal (void)
7645 {
7646 fprintf (stderr, "%s\n", error_msg);
7647 exit (70);
7648 }
7649
7650 /* Handle the loss of connection to display DPY. ERROR_MESSAGE is
7651 the text of an error message that lead to the connection loss. */
7652
7653 static SIGTYPE
7654 x_connection_closed (Display *dpy, char *error_message)
7655 {
7656 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
7657 Lisp_Object frame, tail;
7658 int index = SPECPDL_INDEX ();
7659
7660 error_msg = (char *) alloca (strlen (error_message) + 1);
7661 strcpy (error_msg, error_message);
7662 handling_signal = 0;
7663
7664 /* Prevent being called recursively because of an error condition
7665 below. Otherwise, we might end up with printing ``can't find per
7666 display information'' in the recursive call instead of printing
7667 the original message here. */
7668 x_catch_errors (dpy);
7669
7670 /* Inhibit redisplay while frames are being deleted. */
7671 specbind (Qinhibit_redisplay, Qt);
7672
7673 if (dpyinfo)
7674 {
7675 /* Protect display from being closed when we delete the last
7676 frame on it. */
7677 dpyinfo->reference_count++;
7678 dpyinfo->terminal->reference_count++;
7679 }
7680
7681 /* First delete frames whose mini-buffers are on frames
7682 that are on the dead display. */
7683 FOR_EACH_FRAME (tail, frame)
7684 {
7685 Lisp_Object minibuf_frame;
7686 minibuf_frame
7687 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
7688 if (FRAME_X_P (XFRAME (frame))
7689 && FRAME_X_P (XFRAME (minibuf_frame))
7690 && ! EQ (frame, minibuf_frame)
7691 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
7692 delete_frame (frame, Qnoelisp);
7693 }
7694
7695 /* Now delete all remaining frames on the dead display.
7696 We are now sure none of these is used as the mini-buffer
7697 for another frame that we need to delete. */
7698 FOR_EACH_FRAME (tail, frame)
7699 if (FRAME_X_P (XFRAME (frame))
7700 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
7701 {
7702 /* Set this to t so that delete_frame won't get confused
7703 trying to find a replacement. */
7704 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
7705 delete_frame (frame, Qnoelisp);
7706 }
7707
7708 /* We have to close the display to inform Xt that it doesn't
7709 exist anymore. If we don't, Xt will continue to wait for
7710 events from the display. As a consequence, a sequence of
7711
7712 M-x make-frame-on-display RET :1 RET
7713 ...kill the new frame, so that we get an IO error...
7714 M-x make-frame-on-display RET :1 RET
7715
7716 will indefinitely wait in Xt for events for display `:1', opened
7717 in the first call to make-frame-on-display.
7718
7719 Closing the display is reported to lead to a bus error on
7720 OpenWindows in certain situations. I suspect that is a bug
7721 in OpenWindows. I don't know how to circumvent it here. */
7722
7723 if (dpyinfo)
7724 {
7725 #ifdef USE_X_TOOLKIT
7726 /* If DPYINFO is null, this means we didn't open the display
7727 in the first place, so don't try to close it. */
7728 {
7729 extern void (*fatal_error_signal_hook) (void);
7730 fatal_error_signal_hook = x_fatal_error_signal;
7731 XtCloseDisplay (dpy);
7732 fatal_error_signal_hook = NULL;
7733 }
7734 #endif
7735
7736 #ifdef USE_GTK
7737 /* Due to bugs in some Gtk+ versions, just exit here if this
7738 is the last display/terminal. */
7739 if (terminal_list->next_terminal == NULL)
7740 {
7741 fprintf (stderr, "%s\n", error_msg);
7742 Fkill_emacs (make_number (70));
7743 /* NOTREACHED */
7744 }
7745 xg_display_close (dpyinfo->display);
7746 #endif
7747
7748 /* Indicate that this display is dead. */
7749 dpyinfo->display = 0;
7750
7751 dpyinfo->reference_count--;
7752 dpyinfo->terminal->reference_count--;
7753 if (dpyinfo->reference_count != 0)
7754 /* We have just closed all frames on this display. */
7755 abort ();
7756
7757 {
7758 Lisp_Object tmp;
7759 XSETTERMINAL (tmp, dpyinfo->terminal);
7760 Fdelete_terminal (tmp, Qnoelisp);
7761 }
7762 }
7763
7764 x_uncatch_errors ();
7765
7766 if (terminal_list == 0)
7767 {
7768 fprintf (stderr, "%s\n", error_msg);
7769 Fkill_emacs (make_number (70));
7770 /* NOTREACHED */
7771 }
7772
7773 /* Ordinary stack unwind doesn't deal with these. */
7774 #ifdef SIGIO
7775 sigunblock (sigmask (SIGIO));
7776 #endif
7777 sigunblock (sigmask (SIGALRM));
7778 TOTALLY_UNBLOCK_INPUT;
7779
7780 unbind_to (index, Qnil);
7781 clear_waiting_for_input ();
7782 /* Here, we absolutely have to use a non-local exit (e.g. signal, throw,
7783 longjmp), because returning from this function would get us back into
7784 Xlib's code which will directly call `exit'. */
7785 error ("%s", error_msg);
7786 }
7787
7788 /* We specifically use it before defining it, so that gcc doesn't inline it,
7789 otherwise gdb doesn't know how to properly put a breakpoint on it. */
7790 static void x_error_quitter (Display *, XErrorEvent *);
7791
7792 /* This is the first-level handler for X protocol errors.
7793 It calls x_error_quitter or x_error_catcher. */
7794
7795 static int
7796 x_error_handler (Display *display, XErrorEvent *error)
7797 {
7798 if (x_error_message)
7799 x_error_catcher (display, error);
7800 else
7801 x_error_quitter (display, error);
7802 return 0;
7803 }
7804
7805 /* This is the usual handler for X protocol errors.
7806 It kills all frames on the display that we got the error for.
7807 If that was the only one, it prints an error message and kills Emacs. */
7808
7809 /* .gdbinit puts a breakpoint here, so make sure it is not inlined. */
7810
7811 #if __GNUC__ >= 3 /* On GCC 3.0 we might get a warning. */
7812 #define NO_INLINE __attribute__((noinline))
7813 #else
7814 #define NO_INLINE
7815 #endif
7816
7817 /* Some versions of GNU/Linux define noinline in their headers. */
7818
7819 #ifdef noinline
7820 #undef noinline
7821 #endif
7822
7823 /* On older GCC versions, just putting x_error_quitter
7824 after x_error_handler prevents inlining into the former. */
7825
7826 static void NO_INLINE
7827 x_error_quitter (Display *display, XErrorEvent *error)
7828 {
7829 char buf[256], buf1[356];
7830
7831 /* Ignore BadName errors. They can happen because of fonts
7832 or colors that are not defined. */
7833
7834 if (error->error_code == BadName)
7835 return;
7836
7837 /* Note that there is no real way portable across R3/R4 to get the
7838 original error handler. */
7839
7840 XGetErrorText (display, error->error_code, buf, sizeof (buf));
7841 sprintf (buf1, "X protocol error: %s on protocol request %d",
7842 buf, error->request_code);
7843 x_connection_closed (display, buf1);
7844 }
7845
7846
7847 /* This is the handler for X IO errors, always.
7848 It kills all frames on the display that we lost touch with.
7849 If that was the only one, it prints an error message and kills Emacs. */
7850
7851 static int
7852 x_io_error_quitter (Display *display)
7853 {
7854 char buf[256];
7855
7856 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
7857 x_connection_closed (display, buf);
7858 return 0;
7859 }
7860 \f
7861 /* Changing the font of the frame. */
7862
7863 /* Give frame F the font FONT-OBJECT as its default font. The return
7864 value is FONT-OBJECT. FONTSET is an ID of the fontset for the
7865 frame. If it is negative, generate a new fontset from
7866 FONT-OBJECT. */
7867
7868 Lisp_Object
7869 x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
7870 {
7871 struct font *font = XFONT_OBJECT (font_object);
7872
7873 if (fontset < 0)
7874 fontset = fontset_from_font (font_object);
7875 FRAME_FONTSET (f) = fontset;
7876 if (FRAME_FONT (f) == font)
7877 /* This font is already set in frame F. There's nothing more to
7878 do. */
7879 return font_object;
7880
7881 FRAME_FONT (f) = font;
7882 FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
7883 FRAME_COLUMN_WIDTH (f) = font->average_width;
7884 FRAME_SPACE_WIDTH (f) = font->space_width;
7885 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (font);
7886
7887 compute_fringe_widths (f, 1);
7888
7889 /* Compute the scroll bar width in character columns. */
7890 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
7891 {
7892 int wid = FRAME_COLUMN_WIDTH (f);
7893 FRAME_CONFIG_SCROLL_BAR_COLS (f)
7894 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
7895 }
7896 else
7897 {
7898 int wid = FRAME_COLUMN_WIDTH (f);
7899 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
7900 }
7901
7902 if (FRAME_X_WINDOW (f) != 0)
7903 {
7904 /* Don't change the size of a tip frame; there's no point in
7905 doing it because it's done in Fx_show_tip, and it leads to
7906 problems because the tip frame has no widget. */
7907 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
7908 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
7909 }
7910
7911 #ifdef HAVE_X_I18N
7912 if (FRAME_XIC (f)
7913 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
7914 {
7915 BLOCK_INPUT;
7916 xic_set_xfontset (f, SDATA (fontset_ascii (fontset)));
7917 UNBLOCK_INPUT;
7918 }
7919 #endif
7920
7921 return font_object;
7922 }
7923
7924 \f
7925 /***********************************************************************
7926 X Input Methods
7927 ***********************************************************************/
7928
7929 #ifdef HAVE_X_I18N
7930
7931 #ifdef HAVE_X11R6
7932
7933 /* XIM destroy callback function, which is called whenever the
7934 connection to input method XIM dies. CLIENT_DATA contains a
7935 pointer to the x_display_info structure corresponding to XIM. */
7936
7937 static void
7938 xim_destroy_callback (XIM xim, XPointer client_data, XPointer call_data)
7939 {
7940 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
7941 Lisp_Object frame, tail;
7942
7943 BLOCK_INPUT;
7944
7945 /* No need to call XDestroyIC.. */
7946 FOR_EACH_FRAME (tail, frame)
7947 {
7948 struct frame *f = XFRAME (frame);
7949 if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo)
7950 {
7951 FRAME_XIC (f) = NULL;
7952 xic_free_xfontset (f);
7953 }
7954 }
7955
7956 /* No need to call XCloseIM. */
7957 dpyinfo->xim = NULL;
7958 XFree (dpyinfo->xim_styles);
7959 UNBLOCK_INPUT;
7960 }
7961
7962 #endif /* HAVE_X11R6 */
7963
7964 #ifdef HAVE_X11R6
7965 /* This isn't prototyped in OSF 5.0 or 5.1a. */
7966 extern char *XSetIMValues (XIM, ...);
7967 #endif
7968
7969 /* Open the connection to the XIM server on display DPYINFO.
7970 RESOURCE_NAME is the resource name Emacs uses. */
7971
7972 static void
7973 xim_open_dpy (struct x_display_info *dpyinfo, char *resource_name)
7974 {
7975 XIM xim;
7976
7977 #ifdef HAVE_XIM
7978 if (use_xim)
7979 {
7980 if (dpyinfo->xim)
7981 XCloseIM (dpyinfo->xim);
7982 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name,
7983 EMACS_CLASS);
7984 dpyinfo->xim = xim;
7985
7986 if (xim)
7987 {
7988 #ifdef HAVE_X11R6
7989 XIMCallback destroy;
7990 #endif
7991
7992 /* Get supported styles and XIM values. */
7993 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
7994
7995 #ifdef HAVE_X11R6
7996 destroy.callback = xim_destroy_callback;
7997 destroy.client_data = (XPointer)dpyinfo;
7998 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
7999 #endif
8000 }
8001 }
8002
8003 else
8004 #endif /* HAVE_XIM */
8005 dpyinfo->xim = NULL;
8006 }
8007
8008
8009 #ifdef HAVE_X11R6_XIM
8010
8011 /* XIM instantiate callback function, which is called whenever an XIM
8012 server is available. DISPLAY is the display of the XIM.
8013 CLIENT_DATA contains a pointer to an xim_inst_t structure created
8014 when the callback was registered. */
8015
8016 static void
8017 xim_instantiate_callback (Display *display, XPointer client_data, XPointer call_data)
8018 {
8019 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
8020 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
8021
8022 /* We don't support multiple XIM connections. */
8023 if (dpyinfo->xim)
8024 return;
8025
8026 xim_open_dpy (dpyinfo, xim_inst->resource_name);
8027
8028 /* Create XIC for the existing frames on the same display, as long
8029 as they have no XIC. */
8030 if (dpyinfo->xim && dpyinfo->reference_count > 0)
8031 {
8032 Lisp_Object tail, frame;
8033
8034 BLOCK_INPUT;
8035 FOR_EACH_FRAME (tail, frame)
8036 {
8037 struct frame *f = XFRAME (frame);
8038
8039 if (FRAME_X_P (f)
8040 && FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
8041 if (FRAME_XIC (f) == NULL)
8042 {
8043 create_frame_xic (f);
8044 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
8045 xic_set_statusarea (f);
8046 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
8047 {
8048 struct window *w = XWINDOW (f->selected_window);
8049 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
8050 }
8051 }
8052 }
8053
8054 UNBLOCK_INPUT;
8055 }
8056 }
8057
8058 #endif /* HAVE_X11R6_XIM */
8059
8060
8061 /* Open a connection to the XIM server on display DPYINFO.
8062 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
8063 connection only at the first time. On X11R6, open the connection
8064 in the XIM instantiate callback function. */
8065
8066 static void
8067 xim_initialize (struct x_display_info *dpyinfo, char *resource_name)
8068 {
8069 dpyinfo->xim = NULL;
8070 #ifdef HAVE_XIM
8071 if (use_xim)
8072 {
8073 #ifdef HAVE_X11R6_XIM
8074 struct xim_inst_t *xim_inst;
8075 int len;
8076
8077 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
8078 dpyinfo->xim_callback_data = xim_inst;
8079 xim_inst->dpyinfo = dpyinfo;
8080 len = strlen (resource_name);
8081 xim_inst->resource_name = (char *) xmalloc (len + 1);
8082 bcopy (resource_name, xim_inst->resource_name, len + 1);
8083 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
8084 resource_name, EMACS_CLASS,
8085 xim_instantiate_callback,
8086 /* This is XPointer in XFree86
8087 but (XPointer *) on Tru64, at
8088 least, hence the configure test. */
8089 (XRegisterIMInstantiateCallback_arg6) xim_inst);
8090 #else /* not HAVE_X11R6_XIM */
8091 xim_open_dpy (dpyinfo, resource_name);
8092 #endif /* not HAVE_X11R6_XIM */
8093 }
8094 #endif /* HAVE_XIM */
8095 }
8096
8097
8098 /* Close the connection to the XIM server on display DPYINFO. */
8099
8100 static void
8101 xim_close_dpy (struct x_display_info *dpyinfo)
8102 {
8103 #ifdef HAVE_XIM
8104 if (use_xim)
8105 {
8106 #ifdef HAVE_X11R6_XIM
8107 if (dpyinfo->display)
8108 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
8109 NULL, EMACS_CLASS,
8110 xim_instantiate_callback, NULL);
8111 xfree (dpyinfo->xim_callback_data->resource_name);
8112 xfree (dpyinfo->xim_callback_data);
8113 #endif /* HAVE_X11R6_XIM */
8114 if (dpyinfo->display)
8115 XCloseIM (dpyinfo->xim);
8116 dpyinfo->xim = NULL;
8117 XFree (dpyinfo->xim_styles);
8118 }
8119 #endif /* HAVE_XIM */
8120 }
8121
8122 #endif /* not HAVE_X11R6_XIM */
8123
8124
8125 \f
8126 /* Calculate the absolute position in frame F
8127 from its current recorded position values and gravity. */
8128
8129 void
8130 x_calc_absolute_position (struct frame *f)
8131 {
8132 int flags = f->size_hint_flags;
8133
8134 /* We have nothing to do if the current position
8135 is already for the top-left corner. */
8136 if (! ((flags & XNegative) || (flags & YNegative)))
8137 return;
8138
8139 /* Treat negative positions as relative to the leftmost bottommost
8140 position that fits on the screen. */
8141 if (flags & XNegative)
8142 f->left_pos = x_display_pixel_width (FRAME_X_DISPLAY_INFO (f))
8143 - FRAME_PIXEL_WIDTH (f) + f->left_pos;
8144
8145 {
8146 int height = FRAME_PIXEL_HEIGHT (f);
8147
8148 #if defined USE_X_TOOLKIT && defined USE_MOTIF
8149 /* Something is fishy here. When using Motif, starting Emacs with
8150 `-g -0-0', the frame appears too low by a few pixels.
8151
8152 This seems to be so because initially, while Emacs is starting,
8153 the column widget's height and the frame's pixel height are
8154 different. The column widget's height is the right one. In
8155 later invocations, when Emacs is up, the frame's pixel height
8156 is right, though.
8157
8158 It's not obvious where the initial small difference comes from.
8159 2000-12-01, gerd. */
8160
8161 XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
8162 #endif
8163
8164 if (flags & YNegative)
8165 f->top_pos = x_display_pixel_height (FRAME_X_DISPLAY_INFO (f))
8166 - height + f->top_pos;
8167 }
8168
8169 /* The left_pos and top_pos
8170 are now relative to the top and left screen edges,
8171 so the flags should correspond. */
8172 f->size_hint_flags &= ~ (XNegative | YNegative);
8173 }
8174
8175 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
8176 to really change the position, and 0 when calling from
8177 x_make_frame_visible (in that case, XOFF and YOFF are the current
8178 position values). It is -1 when calling from x_set_frame_parameters,
8179 which means, do adjust for borders but don't change the gravity. */
8180
8181 void
8182 x_set_offset (struct frame *f, register int xoff, register int yoff, int change_gravity)
8183 {
8184 int modified_top, modified_left;
8185
8186 if (change_gravity > 0)
8187 {
8188 FRAME_X_OUTPUT (f)->left_before_move = f->left_pos;
8189 FRAME_X_OUTPUT (f)->top_before_move = f->top_pos;
8190
8191 f->top_pos = yoff;
8192 f->left_pos = xoff;
8193 f->size_hint_flags &= ~ (XNegative | YNegative);
8194 if (xoff < 0)
8195 f->size_hint_flags |= XNegative;
8196 if (yoff < 0)
8197 f->size_hint_flags |= YNegative;
8198 f->win_gravity = NorthWestGravity;
8199 }
8200 x_calc_absolute_position (f);
8201
8202 BLOCK_INPUT;
8203 x_wm_set_size_hint (f, (long) 0, 0);
8204
8205 modified_left = f->left_pos;
8206 modified_top = f->top_pos;
8207
8208 if (change_gravity != 0 && FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A)
8209 {
8210 /* Some WMs (twm, wmaker at least) has an offset that is smaller
8211 than the WM decorations. So we use the calculated offset instead
8212 of the WM decoration sizes here (x/y_pixels_outer_diff). */
8213 modified_left += FRAME_X_OUTPUT (f)->move_offset_left;
8214 modified_top += FRAME_X_OUTPUT (f)->move_offset_top;
8215 }
8216
8217 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
8218 modified_left, modified_top);
8219
8220 x_sync_with_move (f, f->left_pos, f->top_pos,
8221 FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
8222 ? 1 : 0);
8223
8224 /* change_gravity is non-zero when this function is called from Lisp to
8225 programmatically move a frame. In that case, we call
8226 x_check_expected_move to discover if we have a "Type A" or "Type B"
8227 window manager, and, for a "Type A" window manager, adjust the position
8228 of the frame.
8229
8230 We call x_check_expected_move if a programmatic move occurred, and
8231 either the window manager type (A/B) is unknown or it is Type A but we
8232 need to compute the top/left offset adjustment for this frame. */
8233
8234 if (change_gravity != 0 &&
8235 (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
8236 || (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A
8237 && (FRAME_X_OUTPUT (f)->move_offset_left == 0
8238 && FRAME_X_OUTPUT (f)->move_offset_top == 0))))
8239 x_check_expected_move (f, modified_left, modified_top);
8240
8241 UNBLOCK_INPUT;
8242 }
8243
8244 /* Return non-zero if _NET_SUPPORTING_WM_CHECK window exists and _NET_SUPPORTED
8245 on the root window for frame F contains ATOMNAME.
8246 This is how a WM check shall be done according to the Window Manager
8247 Specification/Extended Window Manager Hints at
8248 http://freedesktop.org/wiki/Specifications/wm-spec. */
8249
8250 static int
8251 wm_supports (struct frame *f, const char *atomname)
8252 {
8253 Atom actual_type;
8254 unsigned long actual_size, bytes_remaining;
8255 int i, rc, actual_format;
8256 Atom prop_atom;
8257 Window wmcheck_window;
8258 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8259 Window target_window = dpyinfo->root_window;
8260 long max_len = 65536;
8261 Display *dpy = FRAME_X_DISPLAY (f);
8262 unsigned char *tmp_data = NULL;
8263 Atom target_type = XA_WINDOW;
8264 Atom want_atom;
8265
8266 BLOCK_INPUT;
8267
8268 prop_atom = XInternAtom (dpy, "_NET_SUPPORTING_WM_CHECK", False);
8269
8270 x_catch_errors (dpy);
8271 rc = XGetWindowProperty (dpy, target_window,
8272 prop_atom, 0, max_len, False, target_type,
8273 &actual_type, &actual_format, &actual_size,
8274 &bytes_remaining, &tmp_data);
8275
8276 if (rc != Success || actual_type != XA_WINDOW || x_had_errors_p (dpy))
8277 {
8278 if (tmp_data) XFree (tmp_data);
8279 x_uncatch_errors ();
8280 UNBLOCK_INPUT;
8281 return 0;
8282 }
8283
8284 wmcheck_window = *(Window *) tmp_data;
8285 XFree (tmp_data);
8286
8287 /* Check if window exists. */
8288 XSelectInput (dpy, wmcheck_window, StructureNotifyMask);
8289 x_sync (f);
8290 if (x_had_errors_p (dpy))
8291 {
8292 x_uncatch_errors ();
8293 UNBLOCK_INPUT;
8294 return 0;
8295 }
8296
8297 if (dpyinfo->net_supported_window != wmcheck_window)
8298 {
8299 /* Window changed, reload atoms */
8300 if (dpyinfo->net_supported_atoms != NULL)
8301 XFree (dpyinfo->net_supported_atoms);
8302 dpyinfo->net_supported_atoms = NULL;
8303 dpyinfo->nr_net_supported_atoms = 0;
8304 dpyinfo->net_supported_window = 0;
8305
8306 target_type = XA_ATOM;
8307 prop_atom = XInternAtom (dpy, "_NET_SUPPORTED", False);
8308 tmp_data = NULL;
8309 rc = XGetWindowProperty (dpy, target_window,
8310 prop_atom, 0, max_len, False, target_type,
8311 &actual_type, &actual_format, &actual_size,
8312 &bytes_remaining, &tmp_data);
8313
8314 if (rc != Success || actual_type != XA_ATOM || x_had_errors_p (dpy))
8315 {
8316 if (tmp_data) XFree (tmp_data);
8317 x_uncatch_errors ();
8318 UNBLOCK_INPUT;
8319 return 0;
8320 }
8321
8322 dpyinfo->net_supported_atoms = (Atom *)tmp_data;
8323 dpyinfo->nr_net_supported_atoms = actual_size;
8324 dpyinfo->net_supported_window = wmcheck_window;
8325 }
8326
8327 rc = 0;
8328 want_atom = XInternAtom (dpy, atomname, False);
8329
8330 for (i = 0; rc == 0 && i < dpyinfo->nr_net_supported_atoms; ++i)
8331 rc = dpyinfo->net_supported_atoms[i] == want_atom;
8332
8333 x_uncatch_errors ();
8334 UNBLOCK_INPUT;
8335
8336 return rc;
8337 }
8338
8339 static void
8340 set_wm_state (Lisp_Object frame, int add, const char *what, const char *what2)
8341 {
8342 const char *atom = "_NET_WM_STATE";
8343 Fx_send_client_event (frame, make_number (0), frame,
8344 make_unibyte_string (atom, strlen (atom)),
8345 make_number (32),
8346 /* 1 = add, 0 = remove */
8347 Fcons
8348 (make_number (add ? 1 : 0),
8349 Fcons
8350 (make_unibyte_string (what, strlen (what)),
8351 what2 != 0
8352 ? Fcons (make_unibyte_string (what2, strlen (what2)),
8353 Qnil)
8354 : Qnil)));
8355 }
8356
8357 void
8358 x_set_sticky (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
8359 {
8360 Lisp_Object frame;
8361
8362 XSETFRAME (frame, f);
8363 set_wm_state (frame, NILP (new_value) ? 0 : 1,
8364 "_NET_WM_STATE_STICKY", NULL);
8365 }
8366
8367 /* Do fullscreen as specified in extended window manager hints */
8368
8369 static int
8370 do_ewmh_fullscreen (struct frame *f)
8371 {
8372 int have_net_atom = wm_supports (f, "_NET_WM_STATE");
8373
8374 /* Some window managers don't say they support _NET_WM_STATE, but they do say
8375 they support _NET_WM_STATE_FULLSCREEN. Try that also. */
8376 if (!have_net_atom)
8377 have_net_atom = wm_supports (f, "_NET_WM_STATE_FULLSCREEN");
8378
8379 if (have_net_atom)
8380 {
8381 Lisp_Object frame;
8382 const char *fs = "_NET_WM_STATE_FULLSCREEN";
8383 const char *fw = "_NET_WM_STATE_MAXIMIZED_HORZ";
8384 const char *fh = "_NET_WM_STATE_MAXIMIZED_VERT";
8385
8386 XSETFRAME (frame, f);
8387
8388 set_wm_state (frame, 0, fs, NULL);
8389 set_wm_state (frame, 0, fh, NULL);
8390 set_wm_state (frame, 0, fw, NULL);
8391
8392 /* If there are _NET_ atoms we assume we have extended window manager
8393 hints. */
8394 switch (f->want_fullscreen)
8395 {
8396 case FULLSCREEN_BOTH:
8397 set_wm_state (frame, 1, fs, NULL);
8398 break;
8399 case FULLSCREEN_WIDTH:
8400 set_wm_state (frame, 1, fw, NULL);
8401 break;
8402 case FULLSCREEN_HEIGHT:
8403 set_wm_state (frame, 1, fh, NULL);
8404 break;
8405 case FULLSCREEN_MAXIMIZED:
8406 set_wm_state (frame, 1, fw, fh);
8407 break;
8408 }
8409
8410 f->want_fullscreen = FULLSCREEN_NONE;
8411
8412 }
8413
8414 return have_net_atom;
8415 }
8416
8417 static void
8418 XTfullscreen_hook (FRAME_PTR f)
8419 {
8420 if (f->async_visible)
8421 {
8422 BLOCK_INPUT;
8423 x_check_fullscreen (f);
8424 x_sync (f);
8425 UNBLOCK_INPUT;
8426 }
8427 }
8428
8429
8430 static void
8431 x_handle_net_wm_state (struct frame *f, XPropertyEvent *event)
8432 {
8433 Atom actual_type;
8434 unsigned long actual_size, bytes_remaining;
8435 int i, rc, actual_format, value = FULLSCREEN_NONE;
8436 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8437 long max_len = 65536;
8438 Display *dpy = FRAME_X_DISPLAY (f);
8439 unsigned char *tmp_data = NULL;
8440 Atom target_type = XA_ATOM;
8441 Lisp_Object lval;
8442 int sticky = 0;
8443
8444 BLOCK_INPUT;
8445 x_catch_errors (dpy);
8446 rc = XGetWindowProperty (dpy, event->window,
8447 event->atom, 0, max_len, False, target_type,
8448 &actual_type, &actual_format, &actual_size,
8449 &bytes_remaining, &tmp_data);
8450
8451 if (rc != Success || actual_type != target_type || x_had_errors_p (dpy))
8452 {
8453 if (tmp_data) XFree (tmp_data);
8454 x_uncatch_errors ();
8455 UNBLOCK_INPUT;
8456 return;
8457 }
8458
8459 x_uncatch_errors ();
8460
8461 for (i = 0; i < actual_size; ++i)
8462 {
8463 Atom a = ((Atom*)tmp_data)[i];
8464 if (a == dpyinfo->Xatom_net_wm_state_maximized_horz)
8465 {
8466 if (value == FULLSCREEN_HEIGHT)
8467 value = FULLSCREEN_MAXIMIZED;
8468 else
8469 value = FULLSCREEN_WIDTH;
8470 }
8471 else if (a == dpyinfo->Xatom_net_wm_state_maximized_vert)
8472 {
8473 if (value == FULLSCREEN_WIDTH)
8474 value = FULLSCREEN_MAXIMIZED;
8475 else
8476 value = FULLSCREEN_HEIGHT;
8477 }
8478 else if (a == dpyinfo->Xatom_net_wm_state_fullscreen_atom)
8479 value = FULLSCREEN_BOTH;
8480 else if (a == dpyinfo->Xatom_net_wm_state_sticky)
8481 sticky = 1;
8482 }
8483
8484 lval = Qnil;
8485 switch (value)
8486 {
8487 case FULLSCREEN_WIDTH:
8488 lval = Qfullwidth;
8489 break;
8490 case FULLSCREEN_HEIGHT:
8491 lval = Qfullheight;
8492 break;
8493 case FULLSCREEN_BOTH:
8494 lval = Qfullboth;
8495 break;
8496 case FULLSCREEN_MAXIMIZED:
8497 lval = Qmaximized;
8498 break;
8499 }
8500
8501 store_frame_param (f, Qfullscreen, lval);
8502 store_frame_param (f, Qsticky, sticky ? Qt : Qnil);
8503
8504 if (tmp_data) XFree (tmp_data);
8505 UNBLOCK_INPUT;
8506 }
8507
8508 /* Check if we need to resize the frame due to a fullscreen request.
8509 If so needed, resize the frame. */
8510 static void
8511 x_check_fullscreen (struct frame *f)
8512 {
8513 if (do_ewmh_fullscreen (f))
8514 return;
8515
8516 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
8517 return; /* Only fullscreen without WM or with EWM hints (above). */
8518
8519 if (f->want_fullscreen != FULLSCREEN_NONE)
8520 {
8521 int width = FRAME_COLS (f), height = FRAME_LINES (f);
8522 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8523
8524 switch (f->want_fullscreen)
8525 {
8526 /* No difference between these two when there is no WM */
8527 case FULLSCREEN_BOTH:
8528 case FULLSCREEN_MAXIMIZED:
8529 width = x_display_pixel_width (dpyinfo);
8530 height = x_display_pixel_height (dpyinfo);
8531 break;
8532 case FULLSCREEN_WIDTH:
8533 width = x_display_pixel_width (dpyinfo);
8534 break;
8535 case FULLSCREEN_HEIGHT:
8536 height = x_display_pixel_height (dpyinfo);
8537 }
8538
8539 if (FRAME_COLS (f) != width || FRAME_LINES (f) != height)
8540 {
8541 change_frame_size (f, height, width, 0, 1, 0);
8542 SET_FRAME_GARBAGED (f);
8543 cancel_mouse_face (f);
8544 }
8545 }
8546 }
8547
8548 /* This function is called by x_set_offset to determine whether the window
8549 manager interfered with the positioning of the frame. Type A window
8550 managers position the surrounding window manager decorations a small
8551 amount above and left of the user-supplied position. Type B window
8552 managers position the surrounding window manager decorations at the
8553 user-specified position. If we detect a Type A window manager, we
8554 compensate by moving the window right and down by the proper amount. */
8555
8556 static void
8557 x_check_expected_move (struct frame *f, int expected_left, int expected_top)
8558 {
8559 int current_left = 0, current_top = 0;
8560
8561 /* x_real_positions returns the left and top offsets of the outermost
8562 window manager window around the frame. */
8563
8564 x_real_positions (f, &current_left, &current_top);
8565
8566 if (current_left != expected_left || current_top != expected_top)
8567 {
8568 /* It's a "Type A" window manager. */
8569
8570 int adjusted_left;
8571 int adjusted_top;
8572
8573 FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_A;
8574 FRAME_X_OUTPUT (f)->move_offset_left = expected_left - current_left;
8575 FRAME_X_OUTPUT (f)->move_offset_top = expected_top - current_top;
8576
8577 /* Now fix the mispositioned frame's location. */
8578
8579 adjusted_left = expected_left + FRAME_X_OUTPUT (f)->move_offset_left;
8580 adjusted_top = expected_top + FRAME_X_OUTPUT (f)->move_offset_top;
8581
8582 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
8583 adjusted_left, adjusted_top);
8584
8585 x_sync_with_move (f, expected_left, expected_top, 0);
8586 }
8587 else
8588 /* It's a "Type B" window manager. We don't have to adjust the
8589 frame's position. */
8590
8591 FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_B;
8592 }
8593
8594
8595 /* Wait for XGetGeometry to return up-to-date position information for a
8596 recently-moved frame. Call this immediately after calling XMoveWindow.
8597 If FUZZY is non-zero, then LEFT and TOP are just estimates of where the
8598 frame has been moved to, so we use a fuzzy position comparison instead
8599 of an exact comparison. */
8600
8601 static void
8602 x_sync_with_move (struct frame *f, int left, int top, int fuzzy)
8603 {
8604 int count = 0;
8605
8606 while (count++ < 50)
8607 {
8608 int current_left = 0, current_top = 0;
8609
8610 /* In theory, this call to XSync only needs to happen once, but in
8611 practice, it doesn't seem to work, hence the need for the surrounding
8612 loop. */
8613
8614 XSync (FRAME_X_DISPLAY (f), False);
8615 x_real_positions (f, &current_left, &current_top);
8616
8617 if (fuzzy)
8618 {
8619 /* The left fuzz-factor is 10 pixels. The top fuzz-factor is 40
8620 pixels. */
8621
8622 if (eabs (current_left - left) <= 10
8623 && eabs (current_top - top) <= 40)
8624 return;
8625 }
8626 else if (current_left == left && current_top == top)
8627 return;
8628 }
8629
8630 /* As a last resort, just wait 0.5 seconds and hope that XGetGeometry
8631 will then return up-to-date position info. */
8632
8633 wait_reading_process_output (0, 500000, 0, 0, Qnil, NULL, 0);
8634 }
8635
8636
8637 /* Wait for an event on frame F matching EVENTTYPE. */
8638 void
8639 x_wait_for_event (struct frame *f, int eventtype)
8640 {
8641 int level = interrupt_input_blocked;
8642
8643 SELECT_TYPE fds;
8644 EMACS_TIME tmo, tmo_at, time_now;
8645 int fd = ConnectionNumber (FRAME_X_DISPLAY (f));
8646
8647 pending_event_wait.f = f;
8648 pending_event_wait.eventtype = eventtype;
8649
8650 /* Set timeout to 0.1 second. Hopefully not noticable.
8651 Maybe it should be configurable. */
8652 EMACS_SET_SECS_USECS (tmo, 0, 100000);
8653 EMACS_GET_TIME (tmo_at);
8654 EMACS_ADD_TIME (tmo_at, tmo_at, tmo);
8655
8656 while (pending_event_wait.eventtype)
8657 {
8658 interrupt_input_pending = 1;
8659 TOTALLY_UNBLOCK_INPUT;
8660 /* XTread_socket is called after unblock. */
8661 BLOCK_INPUT;
8662 interrupt_input_blocked = level;
8663
8664 FD_ZERO (&fds);
8665 FD_SET (fd, &fds);
8666
8667 EMACS_GET_TIME (time_now);
8668 EMACS_SUB_TIME (tmo, tmo_at, time_now);
8669
8670 if (EMACS_TIME_NEG_P (tmo) || select (fd+1, &fds, NULL, NULL, &tmo) == 0)
8671 break; /* Timeout */
8672 }
8673 pending_event_wait.f = 0;
8674 pending_event_wait.eventtype = 0;
8675 }
8676
8677
8678 /* Change the size of frame F's X window to COLS/ROWS in the case F
8679 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
8680 top-left-corner window gravity for this size change and subsequent
8681 size changes. Otherwise we leave the window gravity unchanged. */
8682
8683 static void
8684 x_set_window_size_1 (struct frame *f, int change_gravity, int cols, int rows)
8685 {
8686 int pixelwidth, pixelheight;
8687
8688 check_frame_size (f, &rows, &cols);
8689 f->scroll_bar_actual_width
8690 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
8691 ? 0
8692 : FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0
8693 ? FRAME_CONFIG_SCROLL_BAR_WIDTH (f)
8694 : (FRAME_CONFIG_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f)));
8695
8696 compute_fringe_widths (f, 0);
8697
8698 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
8699 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows)
8700 + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f);
8701
8702 if (change_gravity) f->win_gravity = NorthWestGravity;
8703 x_wm_set_size_hint (f, (long) 0, 0);
8704 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
8705 pixelwidth, pixelheight);
8706
8707
8708 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
8709 receive in the ConfigureNotify event; if we get what we asked
8710 for, then the event won't cause the screen to become garbaged, so
8711 we have to make sure to do it here. */
8712 SET_FRAME_GARBAGED (f);
8713
8714 /* Now, strictly speaking, we can't be sure that this is accurate,
8715 but the window manager will get around to dealing with the size
8716 change request eventually, and we'll hear how it went when the
8717 ConfigureNotify event gets here.
8718
8719 We could just not bother storing any of this information here,
8720 and let the ConfigureNotify event set everything up, but that
8721 might be kind of confusing to the Lisp code, since size changes
8722 wouldn't be reported in the frame parameters until some random
8723 point in the future when the ConfigureNotify event arrives.
8724
8725 We pass 1 for DELAY since we can't run Lisp code inside of
8726 a BLOCK_INPUT. */
8727
8728 /* But the ConfigureNotify may in fact never arrive, and then this is
8729 not right if the frame is visible. Instead wait (with timeout)
8730 for the ConfigureNotify. */
8731 if (f->async_visible)
8732 x_wait_for_event (f, ConfigureNotify);
8733 else
8734 {
8735 change_frame_size (f, rows, cols, 0, 1, 0);
8736 FRAME_PIXEL_WIDTH (f) = pixelwidth;
8737 FRAME_PIXEL_HEIGHT (f) = pixelheight;
8738 x_sync (f);
8739 }
8740 }
8741
8742
8743 /* Call this to change the size of frame F's x-window.
8744 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
8745 for this size change and subsequent size changes.
8746 Otherwise we leave the window gravity unchanged. */
8747
8748 void
8749 x_set_window_size (struct frame *f, int change_gravity, int cols, int rows)
8750 {
8751 BLOCK_INPUT;
8752
8753 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
8754 {
8755 int r, c;
8756
8757 /* When the frame is maximized/fullscreen or running under for
8758 example Xmonad, x_set_window_size_1 will be a no-op.
8759 In that case, the right thing to do is extend rows/cols to
8760 the current frame size. We do that first if x_set_window_size_1
8761 turns out to not be a no-op (there is no way to know).
8762 The size will be adjusted again if the frame gets a
8763 ConfigureNotify event as a result of x_set_window_size. */
8764 int pixelh = FRAME_PIXEL_HEIGHT (f);
8765 #ifdef USE_X_TOOLKIT
8766 /* The menu bar is not part of text lines. The tool bar
8767 is however. */
8768 pixelh -= FRAME_MENUBAR_HEIGHT (f);
8769 #endif
8770 r = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixelh);
8771 /* Update f->scroll_bar_actual_width because it is used in
8772 FRAME_PIXEL_WIDTH_TO_TEXT_COLS. */
8773 f->scroll_bar_actual_width
8774 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
8775 c = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, FRAME_PIXEL_WIDTH (f));
8776 change_frame_size (f, r, c, 0, 1, 0);
8777 }
8778
8779 #ifdef USE_GTK
8780 if (FRAME_GTK_WIDGET (f))
8781 xg_frame_set_char_size (f, cols, rows);
8782 else
8783 x_set_window_size_1 (f, change_gravity, cols, rows);
8784 #else /* not USE_GTK */
8785
8786 x_set_window_size_1 (f, change_gravity, cols, rows);
8787
8788 #endif /* not USE_GTK */
8789
8790 /* If cursor was outside the new size, mark it as off. */
8791 mark_window_cursors_off (XWINDOW (f->root_window));
8792
8793 /* Clear out any recollection of where the mouse highlighting was,
8794 since it might be in a place that's outside the new frame size.
8795 Actually checking whether it is outside is a pain in the neck,
8796 so don't try--just let the highlighting be done afresh with new size. */
8797 cancel_mouse_face (f);
8798
8799 UNBLOCK_INPUT;
8800 }
8801 \f
8802 /* Mouse warping. */
8803
8804 void
8805 x_set_mouse_position (struct frame *f, int x, int y)
8806 {
8807 int pix_x, pix_y;
8808
8809 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
8810 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
8811
8812 if (pix_x < 0) pix_x = 0;
8813 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
8814
8815 if (pix_y < 0) pix_y = 0;
8816 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
8817
8818 BLOCK_INPUT;
8819
8820 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
8821 0, 0, 0, 0, pix_x, pix_y);
8822 UNBLOCK_INPUT;
8823 }
8824
8825 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
8826
8827 void
8828 x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
8829 {
8830 BLOCK_INPUT;
8831
8832 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
8833 0, 0, 0, 0, pix_x, pix_y);
8834 UNBLOCK_INPUT;
8835 }
8836 \f
8837 /* focus shifting, raising and lowering. */
8838
8839 void
8840 x_focus_on_frame (struct frame *f)
8841 {
8842 #if 0
8843 /* I don't think that the ICCCM allows programs to do things like this
8844 without the interaction of the window manager. Whatever you end up
8845 doing with this code, do it to x_unfocus_frame too. */
8846 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8847 RevertToPointerRoot, CurrentTime);
8848 #endif /* ! 0 */
8849 }
8850
8851 void
8852 x_unfocus_frame (struct frame *f)
8853 {
8854 #if 0
8855 /* Look at the remarks in x_focus_on_frame. */
8856 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
8857 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
8858 RevertToPointerRoot, CurrentTime);
8859 #endif /* ! 0 */
8860 }
8861
8862 /* Raise frame F. */
8863
8864 void
8865 x_raise_frame (struct frame *f)
8866 {
8867 BLOCK_INPUT;
8868 if (f->async_visible)
8869 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
8870
8871 XFlush (FRAME_X_DISPLAY (f));
8872 UNBLOCK_INPUT;
8873 }
8874
8875 /* Lower frame F. */
8876
8877 void
8878 x_lower_frame (struct frame *f)
8879 {
8880 if (f->async_visible)
8881 {
8882 BLOCK_INPUT;
8883 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
8884 XFlush (FRAME_X_DISPLAY (f));
8885 UNBLOCK_INPUT;
8886 }
8887 }
8888
8889 /* Activate frame with Extended Window Manager Hints */
8890
8891 void
8892 x_ewmh_activate_frame (FRAME_PTR f)
8893 {
8894 /* See Window Manager Specification/Extended Window Manager Hints at
8895 http://freedesktop.org/wiki/Specifications/wm-spec */
8896
8897 const char *atom = "_NET_ACTIVE_WINDOW";
8898 if (f->async_visible && wm_supports (f, atom))
8899 {
8900 Lisp_Object frame;
8901 XSETFRAME (frame, f);
8902 Fx_send_client_event (frame, make_number (0), frame,
8903 make_unibyte_string (atom, strlen (atom)),
8904 make_number (32),
8905 Fcons (make_number (1),
8906 Fcons (make_number (last_user_time),
8907 Qnil)));
8908 }
8909 }
8910
8911 static void
8912 XTframe_raise_lower (FRAME_PTR f, int raise_flag)
8913 {
8914 if (raise_flag)
8915 x_raise_frame (f);
8916 else
8917 x_lower_frame (f);
8918 }
8919 \f
8920 /* XEmbed implementation. */
8921
8922 void
8923 xembed_set_info (struct frame *f, enum xembed_info flags)
8924 {
8925 Atom atom;
8926 unsigned long data[2];
8927
8928 atom = XInternAtom (FRAME_X_DISPLAY (f), "_XEMBED_INFO", False);
8929
8930 data[0] = XEMBED_VERSION;
8931 data[1] = flags;
8932
8933 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), atom, atom,
8934 32, PropModeReplace, (unsigned char *) data, 2);
8935 }
8936
8937 void
8938 xembed_send_message (struct frame *f, Time time, enum xembed_message message, long int detail, long int data1, long int data2)
8939 {
8940 XEvent event;
8941
8942 event.xclient.type = ClientMessage;
8943 event.xclient.window = FRAME_X_OUTPUT (f)->parent_desc;
8944 event.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_XEMBED;
8945 event.xclient.format = 32;
8946 event.xclient.data.l[0] = time;
8947 event.xclient.data.l[1] = message;
8948 event.xclient.data.l[2] = detail;
8949 event.xclient.data.l[3] = data1;
8950 event.xclient.data.l[4] = data2;
8951
8952 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_OUTPUT (f)->parent_desc,
8953 False, NoEventMask, &event);
8954 XSync (FRAME_X_DISPLAY (f), False);
8955 }
8956 \f
8957 /* Change of visibility. */
8958
8959 /* This tries to wait until the frame is really visible.
8960 However, if the window manager asks the user where to position
8961 the frame, this will return before the user finishes doing that.
8962 The frame will not actually be visible at that time,
8963 but it will become visible later when the window manager
8964 finishes with it. */
8965
8966 void
8967 x_make_frame_visible (struct frame *f)
8968 {
8969 Lisp_Object type;
8970 int original_top, original_left;
8971 int retry_count = 2;
8972
8973 retry:
8974
8975 BLOCK_INPUT;
8976
8977 type = x_icon_type (f);
8978 if (!NILP (type))
8979 x_bitmap_icon (f, type);
8980
8981 if (! FRAME_VISIBLE_P (f))
8982 {
8983 /* We test FRAME_GARBAGED_P here to make sure we don't
8984 call x_set_offset a second time
8985 if we get to x_make_frame_visible a second time
8986 before the window gets really visible. */
8987 if (! FRAME_ICONIFIED_P (f)
8988 && ! FRAME_X_EMBEDDED_P (f)
8989 && ! f->output_data.x->asked_for_visible)
8990 x_set_offset (f, f->left_pos, f->top_pos, 0);
8991
8992 f->output_data.x->asked_for_visible = 1;
8993
8994 if (! EQ (Vx_no_window_manager, Qt))
8995 x_wm_set_window_state (f, NormalState);
8996 #ifdef USE_X_TOOLKIT
8997 if (FRAME_X_EMBEDDED_P (f))
8998 xembed_set_info (f, XEMBED_MAPPED);
8999 else
9000 {
9001 /* This was XtPopup, but that did nothing for an iconified frame. */
9002 XtMapWidget (f->output_data.x->widget);
9003 }
9004 #else /* not USE_X_TOOLKIT */
9005 #ifdef USE_GTK
9006 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
9007 gtk_window_deiconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
9008 #else
9009 if (FRAME_X_EMBEDDED_P (f))
9010 xembed_set_info (f, XEMBED_MAPPED);
9011 else
9012 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
9013 #endif /* not USE_GTK */
9014 #endif /* not USE_X_TOOLKIT */
9015 }
9016
9017 XFlush (FRAME_X_DISPLAY (f));
9018
9019 /* Synchronize to ensure Emacs knows the frame is visible
9020 before we do anything else. We do this loop with input not blocked
9021 so that incoming events are handled. */
9022 {
9023 Lisp_Object frame;
9024 int count;
9025 /* This must be before UNBLOCK_INPUT
9026 since events that arrive in response to the actions above
9027 will set it when they are handled. */
9028 int previously_visible = f->output_data.x->has_been_visible;
9029
9030 original_left = f->left_pos;
9031 original_top = f->top_pos;
9032
9033 /* This must come after we set COUNT. */
9034 UNBLOCK_INPUT;
9035
9036 /* We unblock here so that arriving X events are processed. */
9037
9038 /* Now move the window back to where it was "supposed to be".
9039 But don't do it if the gravity is negative.
9040 When the gravity is negative, this uses a position
9041 that is 3 pixels too low. Perhaps that's really the border width.
9042
9043 Don't do this if the window has never been visible before,
9044 because the window manager may choose the position
9045 and we don't want to override it. */
9046
9047 if (! FRAME_VISIBLE_P (f)
9048 && ! FRAME_ICONIFIED_P (f)
9049 && ! FRAME_X_EMBEDDED_P (f)
9050 && f->win_gravity == NorthWestGravity
9051 && previously_visible)
9052 {
9053 Drawable rootw;
9054 int x, y;
9055 unsigned int width, height, border, depth;
9056
9057 BLOCK_INPUT;
9058
9059 /* On some window managers (such as FVWM) moving an existing
9060 window, even to the same place, causes the window manager
9061 to introduce an offset. This can cause the window to move
9062 to an unexpected location. Check the geometry (a little
9063 slow here) and then verify that the window is in the right
9064 place. If the window is not in the right place, move it
9065 there, and take the potential window manager hit. */
9066 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
9067 &rootw, &x, &y, &width, &height, &border, &depth);
9068
9069 if (original_left != x || original_top != y)
9070 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
9071 original_left, original_top);
9072
9073 UNBLOCK_INPUT;
9074 }
9075
9076 XSETFRAME (frame, f);
9077
9078 /* Wait until the frame is visible. Process X events until a
9079 MapNotify event has been seen, or until we think we won't get a
9080 MapNotify at all.. */
9081 for (count = input_signal_count + 10;
9082 input_signal_count < count && !FRAME_VISIBLE_P (f);)
9083 {
9084 /* Force processing of queued events. */
9085 x_sync (f);
9086
9087 /* Machines that do polling rather than SIGIO have been
9088 observed to go into a busy-wait here. So we'll fake an
9089 alarm signal to let the handler know that there's something
9090 to be read. We used to raise a real alarm, but it seems
9091 that the handler isn't always enabled here. This is
9092 probably a bug. */
9093 if (input_polling_used ())
9094 {
9095 /* It could be confusing if a real alarm arrives while
9096 processing the fake one. Turn it off and let the
9097 handler reset it. */
9098 extern void poll_for_input_1 (void);
9099 int old_poll_suppress_count = poll_suppress_count;
9100 poll_suppress_count = 1;
9101 poll_for_input_1 ();
9102 poll_suppress_count = old_poll_suppress_count;
9103 }
9104
9105 /* See if a MapNotify event has been processed. */
9106 FRAME_SAMPLE_VISIBILITY (f);
9107 }
9108
9109 /* 2000-09-28: In
9110
9111 (let ((f (selected-frame)))
9112 (iconify-frame f)
9113 (raise-frame f))
9114
9115 the frame is not raised with various window managers on
9116 FreeBSD, GNU/Linux and Solaris. It turns out that, for some
9117 unknown reason, the call to XtMapWidget is completely ignored.
9118 Mapping the widget a second time works. */
9119
9120 if (!FRAME_VISIBLE_P (f) && --retry_count > 0)
9121 goto retry;
9122 }
9123 }
9124
9125 /* Change from mapped state to withdrawn state. */
9126
9127 /* Make the frame visible (mapped and not iconified). */
9128
9129 void
9130 x_make_frame_invisible (struct frame *f)
9131 {
9132 Window window;
9133
9134 /* Use the frame's outermost window, not the one we normally draw on. */
9135 window = FRAME_OUTER_WINDOW (f);
9136
9137 /* Don't keep the highlight on an invisible frame. */
9138 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
9139 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9140
9141 BLOCK_INPUT;
9142
9143 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
9144 that the current position of the window is user-specified, rather than
9145 program-specified, so that when the window is mapped again, it will be
9146 placed at the same location, without forcing the user to position it
9147 by hand again (they have already done that once for this window.) */
9148 x_wm_set_size_hint (f, (long) 0, 1);
9149
9150 #ifdef USE_GTK
9151 if (FRAME_GTK_OUTER_WIDGET (f))
9152 gtk_widget_hide (FRAME_GTK_OUTER_WIDGET (f));
9153 else
9154 #else
9155 if (FRAME_X_EMBEDDED_P (f))
9156 xembed_set_info (f, 0);
9157 else
9158 #endif
9159 {
9160
9161 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
9162 DefaultScreen (FRAME_X_DISPLAY (f))))
9163 {
9164 UNBLOCK_INPUT_RESIGNAL;
9165 error ("Can't notify window manager of window withdrawal");
9166 }
9167 }
9168
9169 /* We can't distinguish this from iconification
9170 just by the event that we get from the server.
9171 So we can't win using the usual strategy of letting
9172 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
9173 and synchronize with the server to make sure we agree. */
9174 f->visible = 0;
9175 FRAME_ICONIFIED_P (f) = 0;
9176 f->async_visible = 0;
9177 f->async_iconified = 0;
9178
9179 x_sync (f);
9180
9181 UNBLOCK_INPUT;
9182 }
9183
9184 /* Change window state from mapped to iconified. */
9185
9186 void
9187 x_iconify_frame (struct frame *f)
9188 {
9189 int result;
9190 Lisp_Object type;
9191
9192 /* Don't keep the highlight on an invisible frame. */
9193 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
9194 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9195
9196 if (f->async_iconified)
9197 return;
9198
9199 BLOCK_INPUT;
9200
9201 FRAME_SAMPLE_VISIBILITY (f);
9202
9203 type = x_icon_type (f);
9204 if (!NILP (type))
9205 x_bitmap_icon (f, type);
9206
9207 #ifdef USE_GTK
9208 if (FRAME_GTK_OUTER_WIDGET (f))
9209 {
9210 if (! FRAME_VISIBLE_P (f))
9211 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
9212
9213 gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
9214 f->iconified = 1;
9215 f->visible = 1;
9216 f->async_iconified = 1;
9217 f->async_visible = 0;
9218 UNBLOCK_INPUT;
9219 return;
9220 }
9221 #endif
9222
9223 #ifdef USE_X_TOOLKIT
9224
9225 if (! FRAME_VISIBLE_P (f))
9226 {
9227 if (! EQ (Vx_no_window_manager, Qt))
9228 x_wm_set_window_state (f, IconicState);
9229 /* This was XtPopup, but that did nothing for an iconified frame. */
9230 XtMapWidget (f->output_data.x->widget);
9231 /* The server won't give us any event to indicate
9232 that an invisible frame was changed to an icon,
9233 so we have to record it here. */
9234 f->iconified = 1;
9235 f->visible = 1;
9236 f->async_iconified = 1;
9237 f->async_visible = 0;
9238 UNBLOCK_INPUT;
9239 return;
9240 }
9241
9242 result = XIconifyWindow (FRAME_X_DISPLAY (f),
9243 XtWindow (f->output_data.x->widget),
9244 DefaultScreen (FRAME_X_DISPLAY (f)));
9245 UNBLOCK_INPUT;
9246
9247 if (!result)
9248 error ("Can't notify window manager of iconification");
9249
9250 f->async_iconified = 1;
9251 f->async_visible = 0;
9252
9253
9254 BLOCK_INPUT;
9255 XFlush (FRAME_X_DISPLAY (f));
9256 UNBLOCK_INPUT;
9257 #else /* not USE_X_TOOLKIT */
9258
9259 /* Make sure the X server knows where the window should be positioned,
9260 in case the user deiconifies with the window manager. */
9261 if (! FRAME_VISIBLE_P (f)
9262 && ! FRAME_ICONIFIED_P (f)
9263 && ! FRAME_X_EMBEDDED_P (f))
9264 x_set_offset (f, f->left_pos, f->top_pos, 0);
9265
9266 /* Since we don't know which revision of X we're running, we'll use both
9267 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
9268
9269 /* X11R4: send a ClientMessage to the window manager using the
9270 WM_CHANGE_STATE type. */
9271 {
9272 XEvent message;
9273
9274 message.xclient.window = FRAME_X_WINDOW (f);
9275 message.xclient.type = ClientMessage;
9276 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
9277 message.xclient.format = 32;
9278 message.xclient.data.l[0] = IconicState;
9279
9280 if (! XSendEvent (FRAME_X_DISPLAY (f),
9281 DefaultRootWindow (FRAME_X_DISPLAY (f)),
9282 False,
9283 SubstructureRedirectMask | SubstructureNotifyMask,
9284 &message))
9285 {
9286 UNBLOCK_INPUT_RESIGNAL;
9287 error ("Can't notify window manager of iconification");
9288 }
9289 }
9290
9291 /* X11R3: set the initial_state field of the window manager hints to
9292 IconicState. */
9293 x_wm_set_window_state (f, IconicState);
9294
9295 if (!FRAME_VISIBLE_P (f))
9296 {
9297 /* If the frame was withdrawn, before, we must map it. */
9298 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
9299 }
9300
9301 f->async_iconified = 1;
9302 f->async_visible = 0;
9303
9304 XFlush (FRAME_X_DISPLAY (f));
9305 UNBLOCK_INPUT;
9306 #endif /* not USE_X_TOOLKIT */
9307 }
9308
9309 \f
9310 /* Free X resources of frame F. */
9311
9312 void
9313 x_free_frame_resources (struct frame *f)
9314 {
9315 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9316 Lisp_Object bar;
9317 struct scroll_bar *b;
9318
9319 BLOCK_INPUT;
9320
9321 /* If a display connection is dead, don't try sending more
9322 commands to the X server. */
9323 if (dpyinfo->display)
9324 {
9325 /* We must free faces before destroying windows because some
9326 font-driver (e.g. xft) access a window while finishing a
9327 face. */
9328 if (FRAME_FACE_CACHE (f))
9329 free_frame_faces (f);
9330
9331 if (f->output_data.x->icon_desc)
9332 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
9333
9334 #ifdef USE_X_TOOLKIT
9335 /* Explicitly destroy the scroll bars of the frame. Without
9336 this, we get "BadDrawable" errors from the toolkit later on,
9337 presumably from expose events generated for the disappearing
9338 toolkit scroll bars. */
9339 for (bar = FRAME_SCROLL_BARS (f); !NILP (bar); bar = b->next)
9340 {
9341 b = XSCROLL_BAR (bar);
9342 x_scroll_bar_remove (b);
9343 }
9344 #endif
9345
9346 #ifdef HAVE_X_I18N
9347 if (FRAME_XIC (f))
9348 free_frame_xic (f);
9349 #endif
9350
9351 #ifdef USE_X_TOOLKIT
9352 if (f->output_data.x->widget)
9353 {
9354 XtDestroyWidget (f->output_data.x->widget);
9355 f->output_data.x->widget = NULL;
9356 }
9357 /* Tooltips don't have widgets, only a simple X window, even if
9358 we are using a toolkit. */
9359 else if (FRAME_X_WINDOW (f))
9360 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
9361
9362 free_frame_menubar (f);
9363 #else /* !USE_X_TOOLKIT */
9364
9365 #ifdef USE_GTK
9366 /* In the GTK version, tooltips are normal X
9367 frames. We must check and free both types. */
9368 if (FRAME_GTK_OUTER_WIDGET (f))
9369 {
9370 gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f));
9371 FRAME_X_WINDOW (f) = 0; /* Set to avoid XDestroyWindow below */
9372 FRAME_GTK_OUTER_WIDGET (f) = 0;
9373 }
9374 #endif /* USE_GTK */
9375
9376 if (FRAME_X_WINDOW (f))
9377 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
9378 #endif /* !USE_X_TOOLKIT */
9379
9380 unload_color (f, FRAME_FOREGROUND_PIXEL (f));
9381 unload_color (f, FRAME_BACKGROUND_PIXEL (f));
9382 unload_color (f, f->output_data.x->cursor_pixel);
9383 unload_color (f, f->output_data.x->cursor_foreground_pixel);
9384 unload_color (f, f->output_data.x->border_pixel);
9385 unload_color (f, f->output_data.x->mouse_pixel);
9386
9387 if (f->output_data.x->scroll_bar_background_pixel != -1)
9388 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
9389 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
9390 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
9391 #ifdef USE_TOOLKIT_SCROLL_BARS
9392 /* Scrollbar shadow colors. */
9393 if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
9394 unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
9395 if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
9396 unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
9397 #endif /* USE_TOOLKIT_SCROLL_BARS */
9398 if (f->output_data.x->white_relief.allocated_p)
9399 unload_color (f, f->output_data.x->white_relief.pixel);
9400 if (f->output_data.x->black_relief.allocated_p)
9401 unload_color (f, f->output_data.x->black_relief.pixel);
9402
9403 x_free_gcs (f);
9404 XFlush (FRAME_X_DISPLAY (f));
9405 }
9406
9407 xfree (f->output_data.x->saved_menu_event);
9408 xfree (f->output_data.x);
9409 f->output_data.x = NULL;
9410
9411 if (f == dpyinfo->x_focus_frame)
9412 dpyinfo->x_focus_frame = 0;
9413 if (f == dpyinfo->x_focus_event_frame)
9414 dpyinfo->x_focus_event_frame = 0;
9415 if (f == dpyinfo->x_highlight_frame)
9416 dpyinfo->x_highlight_frame = 0;
9417
9418 if (f == dpyinfo->mouse_face_mouse_frame)
9419 {
9420 dpyinfo->mouse_face_beg_row
9421 = dpyinfo->mouse_face_beg_col = -1;
9422 dpyinfo->mouse_face_end_row
9423 = dpyinfo->mouse_face_end_col = -1;
9424 dpyinfo->mouse_face_window = Qnil;
9425 dpyinfo->mouse_face_deferred_gc = 0;
9426 dpyinfo->mouse_face_mouse_frame = 0;
9427 }
9428
9429 UNBLOCK_INPUT;
9430 }
9431
9432
9433 /* Destroy the X window of frame F. */
9434
9435 void
9436 x_destroy_window (struct frame *f)
9437 {
9438 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9439
9440 /* If a display connection is dead, don't try sending more
9441 commands to the X server. */
9442 if (dpyinfo->display != 0)
9443 x_free_frame_resources (f);
9444
9445 dpyinfo->reference_count--;
9446 }
9447
9448 \f
9449 /* Setting window manager hints. */
9450
9451 /* Set the normal size hints for the window manager, for frame F.
9452 FLAGS is the flags word to use--or 0 meaning preserve the flags
9453 that the window now has.
9454 If USER_POSITION is nonzero, we set the USPosition
9455 flag (this is useful when FLAGS is 0).
9456 The GTK version is in gtkutils.c */
9457
9458 #ifndef USE_GTK
9459 void
9460 x_wm_set_size_hint (f, flags, user_position)
9461 struct frame *f;
9462 long flags;
9463 int user_position;
9464 {
9465 XSizeHints size_hints;
9466 Window window = FRAME_OUTER_WINDOW (f);
9467
9468 /* Setting PMaxSize caused various problems. */
9469 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
9470
9471 size_hints.x = f->left_pos;
9472 size_hints.y = f->top_pos;
9473
9474 size_hints.height = FRAME_PIXEL_HEIGHT (f);
9475 size_hints.width = FRAME_PIXEL_WIDTH (f);
9476
9477 size_hints.width_inc = FRAME_COLUMN_WIDTH (f);
9478 size_hints.height_inc = FRAME_LINE_HEIGHT (f);
9479 size_hints.max_width = x_display_pixel_width (FRAME_X_DISPLAY_INFO (f))
9480 - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
9481 size_hints.max_height = x_display_pixel_height (FRAME_X_DISPLAY_INFO (f))
9482 - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
9483
9484 /* Calculate the base and minimum sizes. */
9485 {
9486 int base_width, base_height;
9487 int min_rows = 0, min_cols = 0;
9488
9489 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
9490 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
9491
9492 check_frame_size (f, &min_rows, &min_cols);
9493
9494 /* The window manager uses the base width hints to calculate the
9495 current number of rows and columns in the frame while
9496 resizing; min_width and min_height aren't useful for this
9497 purpose, since they might not give the dimensions for a
9498 zero-row, zero-column frame.
9499
9500 We use the base_width and base_height members if we have
9501 them; otherwise, we set the min_width and min_height members
9502 to the size for a zero x zero frame. */
9503
9504 size_hints.flags |= PBaseSize;
9505 size_hints.base_width = base_width;
9506 size_hints.base_height = base_height + FRAME_MENUBAR_HEIGHT (f);
9507 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
9508 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
9509 }
9510
9511 /* If we don't need the old flags, we don't need the old hint at all. */
9512 if (flags)
9513 {
9514 size_hints.flags |= flags;
9515 goto no_read;
9516 }
9517
9518 {
9519 XSizeHints hints; /* Sometimes I hate X Windows... */
9520 long supplied_return;
9521 int value;
9522
9523 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
9524 &supplied_return);
9525
9526 if (flags)
9527 size_hints.flags |= flags;
9528 else
9529 {
9530 if (value == 0)
9531 hints.flags = 0;
9532 if (hints.flags & PSize)
9533 size_hints.flags |= PSize;
9534 if (hints.flags & PPosition)
9535 size_hints.flags |= PPosition;
9536 if (hints.flags & USPosition)
9537 size_hints.flags |= USPosition;
9538 if (hints.flags & USSize)
9539 size_hints.flags |= USSize;
9540 }
9541 }
9542
9543 no_read:
9544
9545 #ifdef PWinGravity
9546 size_hints.win_gravity = f->win_gravity;
9547 size_hints.flags |= PWinGravity;
9548
9549 if (user_position)
9550 {
9551 size_hints.flags &= ~ PPosition;
9552 size_hints.flags |= USPosition;
9553 }
9554 #endif /* PWinGravity */
9555
9556 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
9557 }
9558 #endif /* not USE_GTK */
9559
9560 /* Used for IconicState or NormalState */
9561
9562 void
9563 x_wm_set_window_state (struct frame *f, int state)
9564 {
9565 #ifdef USE_X_TOOLKIT
9566 Arg al[1];
9567
9568 XtSetArg (al[0], XtNinitialState, state);
9569 XtSetValues (f->output_data.x->widget, al, 1);
9570 #else /* not USE_X_TOOLKIT */
9571 Window window = FRAME_X_WINDOW (f);
9572
9573 f->output_data.x->wm_hints.flags |= StateHint;
9574 f->output_data.x->wm_hints.initial_state = state;
9575
9576 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
9577 #endif /* not USE_X_TOOLKIT */
9578 }
9579
9580 void
9581 x_wm_set_icon_pixmap (struct frame *f, int pixmap_id)
9582 {
9583 Pixmap icon_pixmap, icon_mask;
9584
9585 #if !defined USE_X_TOOLKIT && !defined USE_GTK
9586 Window window = FRAME_OUTER_WINDOW (f);
9587 #endif
9588
9589 if (pixmap_id > 0)
9590 {
9591 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
9592 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
9593 icon_mask = x_bitmap_mask (f, pixmap_id);
9594 f->output_data.x->wm_hints.icon_mask = icon_mask;
9595 }
9596 else
9597 {
9598 /* It seems there is no way to turn off use of an icon
9599 pixmap. */
9600 return;
9601 }
9602
9603
9604 #ifdef USE_GTK
9605 {
9606 xg_set_frame_icon (f, icon_pixmap, icon_mask);
9607 return;
9608 }
9609
9610 #elif defined (USE_X_TOOLKIT) /* same as in x_wm_set_window_state. */
9611
9612 {
9613 Arg al[1];
9614 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
9615 XtSetValues (f->output_data.x->widget, al, 1);
9616 XtSetArg (al[0], XtNiconMask, icon_mask);
9617 XtSetValues (f->output_data.x->widget, al, 1);
9618 }
9619
9620 #else /* not USE_X_TOOLKIT && not USE_GTK */
9621
9622 f->output_data.x->wm_hints.flags |= (IconPixmapHint | IconMaskHint);
9623 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
9624
9625 #endif /* not USE_X_TOOLKIT && not USE_GTK */
9626 }
9627
9628 void
9629 x_wm_set_icon_position (struct frame *f, int icon_x, int icon_y)
9630 {
9631 Window window = FRAME_OUTER_WINDOW (f);
9632
9633 f->output_data.x->wm_hints.flags |= IconPositionHint;
9634 f->output_data.x->wm_hints.icon_x = icon_x;
9635 f->output_data.x->wm_hints.icon_y = icon_y;
9636
9637 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
9638 }
9639
9640 \f
9641 /***********************************************************************
9642 Fonts
9643 ***********************************************************************/
9644
9645 #if GLYPH_DEBUG
9646
9647 /* Check that FONT is valid on frame F. It is if it can be found in F's
9648 font table. */
9649
9650 static void
9651 x_check_font (f, font)
9652 struct frame *f;
9653 struct font *font;
9654 {
9655 Lisp_Object frame;
9656
9657 xassert (font != NULL && ! NILP (font->props[FONT_TYPE_INDEX]));
9658 if (font->driver->check)
9659 xassert (font->driver->check (f, font) == 0);
9660 }
9661
9662 #endif /* GLYPH_DEBUG != 0 */
9663
9664 \f
9665 /***********************************************************************
9666 Initialization
9667 ***********************************************************************/
9668
9669 #ifdef USE_X_TOOLKIT
9670 static XrmOptionDescRec emacs_options[] = {
9671 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
9672 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
9673
9674 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
9675 XrmoptionSepArg, NULL},
9676 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
9677
9678 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
9679 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
9680 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
9681 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
9682 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
9683 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
9684 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
9685 };
9686
9687 /* Whether atimer for Xt timeouts is activated or not. */
9688
9689 static int x_timeout_atimer_activated_flag;
9690
9691 #endif /* USE_X_TOOLKIT */
9692
9693 static int x_initialized;
9694
9695 #ifdef HAVE_X_SM
9696 static int x_session_initialized;
9697 #endif
9698
9699 /* Test whether two display-name strings agree up to the dot that separates
9700 the screen number from the server number. */
9701 static int
9702 same_x_server (const char *name1, const char *name2)
9703 {
9704 int seen_colon = 0;
9705 const unsigned char *system_name = SDATA (Vsystem_name);
9706 int system_name_length = strlen (system_name);
9707 int length_until_period = 0;
9708
9709 while (system_name[length_until_period] != 0
9710 && system_name[length_until_period] != '.')
9711 length_until_period++;
9712
9713 /* Treat `unix' like an empty host name. */
9714 if (! strncmp (name1, "unix:", 5))
9715 name1 += 4;
9716 if (! strncmp (name2, "unix:", 5))
9717 name2 += 4;
9718 /* Treat this host's name like an empty host name. */
9719 if (! strncmp (name1, system_name, system_name_length)
9720 && name1[system_name_length] == ':')
9721 name1 += system_name_length;
9722 if (! strncmp (name2, system_name, system_name_length)
9723 && name2[system_name_length] == ':')
9724 name2 += system_name_length;
9725 /* Treat this host's domainless name like an empty host name. */
9726 if (! strncmp (name1, system_name, length_until_period)
9727 && name1[length_until_period] == ':')
9728 name1 += length_until_period;
9729 if (! strncmp (name2, system_name, length_until_period)
9730 && name2[length_until_period] == ':')
9731 name2 += length_until_period;
9732
9733 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
9734 {
9735 if (*name1 == ':')
9736 seen_colon++;
9737 if (seen_colon && *name1 == '.')
9738 return 1;
9739 }
9740 return (seen_colon
9741 && (*name1 == '.' || *name1 == '\0')
9742 && (*name2 == '.' || *name2 == '\0'));
9743 }
9744
9745 /* Count number of set bits in mask and number of bits to shift to
9746 get to the first bit. With MASK 0x7e0, *BITS is set to 6, and *OFFSET
9747 to 5. */
9748 static void
9749 get_bits_and_offset (long unsigned int mask, int *bits, int *offset)
9750 {
9751 int nr = 0;
9752 int off = 0;
9753
9754 while (!(mask & 1))
9755 {
9756 off++;
9757 mask >>= 1;
9758 }
9759
9760 while (mask & 1)
9761 {
9762 nr++;
9763 mask >>= 1;
9764 }
9765
9766 *offset = off;
9767 *bits = nr;
9768 }
9769
9770 /* Return 1 if display DISPLAY is available for use, 0 otherwise.
9771 But don't permanently open it, just test its availability. */
9772
9773 int
9774 x_display_ok (const char *display)
9775 {
9776 int dpy_ok = 1;
9777 Display *dpy;
9778
9779 dpy = XOpenDisplay (display);
9780 if (dpy)
9781 XCloseDisplay (dpy);
9782 else
9783 dpy_ok = 0;
9784 return dpy_ok;
9785 }
9786
9787 #ifdef USE_GTK
9788 static void
9789 my_log_handler (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data)
9790 {
9791 if (!strstr (message, "g_set_prgname"))
9792 fprintf (stderr, "%s-WARNING **: %s\n", log_domain, message);
9793 }
9794 #endif
9795
9796 /* Open a connection to X display DISPLAY_NAME, and return
9797 the structure that describes the open display.
9798 If we cannot contact the display, return null. */
9799
9800 struct x_display_info *
9801 x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
9802 {
9803 int connection;
9804 Display *dpy;
9805 struct terminal *terminal;
9806 struct x_display_info *dpyinfo;
9807 XrmDatabase xrdb;
9808
9809 BLOCK_INPUT;
9810
9811 if (!x_initialized)
9812 {
9813 x_initialize ();
9814 ++x_initialized;
9815 }
9816
9817 if (! x_display_ok (SDATA (display_name)))
9818 error ("Display %s can't be opened", SDATA (display_name));
9819
9820 #ifdef USE_GTK
9821 {
9822 #define NUM_ARGV 10
9823 int argc;
9824 char *argv[NUM_ARGV];
9825 char **argv2 = argv;
9826 guint id;
9827
9828 if (x_initialized++ > 1)
9829 {
9830 xg_display_open (SDATA (display_name), &dpy);
9831 }
9832 else
9833 {
9834 for (argc = 0; argc < NUM_ARGV; ++argc)
9835 argv[argc] = 0;
9836
9837 argc = 0;
9838 argv[argc++] = initial_argv[0];
9839
9840 if (! NILP (display_name))
9841 {
9842 argv[argc++] = "--display";
9843 argv[argc++] = SDATA (display_name);
9844 }
9845
9846 argv[argc++] = "--name";
9847 argv[argc++] = resource_name;
9848
9849 XSetLocaleModifiers ("");
9850
9851 /* Work around GLib bug that outputs a faulty warning. See
9852 https://bugzilla.gnome.org/show_bug.cgi?id=563627. */
9853 id = g_log_set_handler ("GLib", G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL
9854 | G_LOG_FLAG_RECURSION, my_log_handler, NULL);
9855 gtk_init (&argc, &argv2);
9856 g_log_remove_handler ("GLib", id);
9857
9858 /* gtk_init does set_locale. We must fix locale after calling it. */
9859 fixup_locale ();
9860 xg_initialize ();
9861
9862 dpy = GDK_DISPLAY ();
9863
9864 /* NULL window -> events for all windows go to our function */
9865 gdk_window_add_filter (NULL, event_handler_gdk, NULL);
9866
9867 /* Load our own gtkrc if it exists. */
9868 {
9869 char *file = "~/.emacs.d/gtkrc";
9870 Lisp_Object s, abs_file;
9871
9872 s = make_string (file, strlen (file));
9873 abs_file = Fexpand_file_name (s, Qnil);
9874
9875 if (! NILP (abs_file) && !NILP (Ffile_readable_p (abs_file)))
9876 gtk_rc_parse (SDATA (abs_file));
9877 }
9878
9879 XSetErrorHandler (x_error_handler);
9880 XSetIOErrorHandler (x_io_error_quitter);
9881 }
9882 }
9883 #else /* not USE_GTK */
9884 #ifdef USE_X_TOOLKIT
9885 /* weiner@footloose.sps.mot.com reports that this causes
9886 errors with X11R5:
9887 X protocol error: BadAtom (invalid Atom parameter)
9888 on protocol request 18skiloaf.
9889 So let's not use it until R6. */
9890 #ifdef HAVE_X11XTR6
9891 XtSetLanguageProc (NULL, NULL, NULL);
9892 #endif
9893
9894 {
9895 int argc = 0;
9896 char *argv[3];
9897
9898 argv[0] = "";
9899 argc = 1;
9900 if (xrm_option)
9901 {
9902 argv[argc++] = "-xrm";
9903 argv[argc++] = xrm_option;
9904 }
9905 turn_on_atimers (0);
9906 dpy = XtOpenDisplay (Xt_app_con, SDATA (display_name),
9907 resource_name, EMACS_CLASS,
9908 emacs_options, XtNumber (emacs_options),
9909 &argc, argv);
9910 turn_on_atimers (1);
9911
9912 #ifdef HAVE_X11XTR6
9913 /* I think this is to compensate for XtSetLanguageProc. */
9914 fixup_locale ();
9915 #endif
9916 }
9917
9918 #else /* not USE_X_TOOLKIT */
9919 XSetLocaleModifiers ("");
9920 dpy = XOpenDisplay (SDATA (display_name));
9921 #endif /* not USE_X_TOOLKIT */
9922 #endif /* not USE_GTK*/
9923
9924 /* Detect failure. */
9925 if (dpy == 0)
9926 {
9927 UNBLOCK_INPUT;
9928 return 0;
9929 }
9930
9931 /* We have definitely succeeded. Record the new connection. */
9932
9933 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
9934 bzero (dpyinfo, sizeof *dpyinfo);
9935
9936 terminal = x_create_terminal (dpyinfo);
9937
9938 {
9939 struct x_display_info *share;
9940 Lisp_Object tail;
9941
9942 for (share = x_display_list, tail = x_display_name_list; share;
9943 share = share->next, tail = XCDR (tail))
9944 if (same_x_server (SDATA (XCAR (XCAR (tail))),
9945 SDATA (display_name)))
9946 break;
9947 if (share)
9948 terminal->kboard = share->terminal->kboard;
9949 else
9950 {
9951 terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
9952 init_kboard (terminal->kboard);
9953 terminal->kboard->Vwindow_system = Qx;
9954
9955 /* Add the keyboard to the list before running Lisp code (via
9956 Qvendor_specific_keysyms below), since these are not traced
9957 via terminals but only through all_kboards. */
9958 terminal->kboard->next_kboard = all_kboards;
9959 all_kboards = terminal->kboard;
9960
9961 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
9962 {
9963 char *vendor = ServerVendor (dpy);
9964
9965 /* Protect terminal from GC before removing it from the
9966 list of terminals. */
9967 struct gcpro gcpro1;
9968 Lisp_Object gcpro_term;
9969 XSETTERMINAL (gcpro_term, terminal);
9970 GCPRO1 (gcpro_term);
9971
9972 /* Temporarily hide the partially initialized terminal. */
9973 terminal_list = terminal->next_terminal;
9974 UNBLOCK_INPUT;
9975 terminal->kboard->Vsystem_key_alist
9976 = call1 (Qvendor_specific_keysyms,
9977 vendor ? build_string (vendor) : empty_unibyte_string);
9978 BLOCK_INPUT;
9979 terminal->next_terminal = terminal_list;
9980 terminal_list = terminal;
9981 UNGCPRO;
9982 }
9983
9984 /* Don't let the initial kboard remain current longer than necessary.
9985 That would cause problems if a file loaded on startup tries to
9986 prompt in the mini-buffer. */
9987 if (current_kboard == initial_kboard)
9988 current_kboard = terminal->kboard;
9989 }
9990 terminal->kboard->reference_count++;
9991 }
9992
9993 /* Put this display on the chain. */
9994 dpyinfo->next = x_display_list;
9995 x_display_list = dpyinfo;
9996
9997 /* Put it on x_display_name_list as well, to keep them parallel. */
9998 x_display_name_list = Fcons (Fcons (display_name, Qnil),
9999 x_display_name_list);
10000 dpyinfo->name_list_element = XCAR (x_display_name_list);
10001
10002 dpyinfo->display = dpy;
10003
10004 /* Set the name of the terminal. */
10005 terminal->name = (char *) xmalloc (SBYTES (display_name) + 1);
10006 strncpy (terminal->name, SDATA (display_name), SBYTES (display_name));
10007 terminal->name[SBYTES (display_name)] = 0;
10008
10009 #if 0
10010 XSetAfterFunction (x_current_display, x_trace_wire);
10011 #endif /* ! 0 */
10012
10013 dpyinfo->x_id_name
10014 = (char *) xmalloc (SBYTES (Vinvocation_name)
10015 + SBYTES (Vsystem_name)
10016 + 2);
10017 sprintf (dpyinfo->x_id_name, "%s@%s",
10018 SDATA (Vinvocation_name), SDATA (Vsystem_name));
10019
10020 /* Figure out which modifier bits mean what. */
10021 x_find_modifier_meanings (dpyinfo);
10022
10023 /* Get the scroll bar cursor. */
10024 #ifdef USE_GTK
10025 /* We must create a GTK cursor, it is required for GTK widgets. */
10026 dpyinfo->xg_cursor = xg_create_default_cursor (dpyinfo->display);
10027 #endif /* USE_GTK */
10028
10029 dpyinfo->vertical_scroll_bar_cursor
10030 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
10031
10032 xrdb = x_load_resources (dpyinfo->display, xrm_option,
10033 resource_name, EMACS_CLASS);
10034 #ifdef HAVE_XRMSETDATABASE
10035 XrmSetDatabase (dpyinfo->display, xrdb);
10036 #else
10037 dpyinfo->display->db = xrdb;
10038 #endif
10039 /* Put the rdb where we can find it in a way that works on
10040 all versions. */
10041 dpyinfo->xrdb = xrdb;
10042
10043 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
10044 DefaultScreen (dpyinfo->display));
10045 select_visual (dpyinfo);
10046 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
10047 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
10048 dpyinfo->client_leader_window = 0;
10049 dpyinfo->grabbed = 0;
10050 dpyinfo->reference_count = 0;
10051 dpyinfo->icon_bitmap_id = -1;
10052 dpyinfo->n_fonts = 0;
10053 dpyinfo->bitmaps = 0;
10054 dpyinfo->bitmaps_size = 0;
10055 dpyinfo->bitmaps_last = 0;
10056 dpyinfo->scratch_cursor_gc = 0;
10057 dpyinfo->mouse_face_mouse_frame = 0;
10058 dpyinfo->mouse_face_deferred_gc = 0;
10059 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
10060 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
10061 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
10062 dpyinfo->mouse_face_window = Qnil;
10063 dpyinfo->mouse_face_overlay = Qnil;
10064 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
10065 dpyinfo->mouse_face_defer = 0;
10066 dpyinfo->mouse_face_hidden = 0;
10067 dpyinfo->x_focus_frame = 0;
10068 dpyinfo->x_focus_event_frame = 0;
10069 dpyinfo->x_highlight_frame = 0;
10070 dpyinfo->wm_type = X_WMTYPE_UNKNOWN;
10071
10072 /* See if we can construct pixel values from RGB values. */
10073 dpyinfo->red_bits = dpyinfo->blue_bits = dpyinfo->green_bits = 0;
10074 dpyinfo->red_offset = dpyinfo->blue_offset = dpyinfo->green_offset = 0;
10075
10076 if (dpyinfo->visual->class == TrueColor)
10077 {
10078 get_bits_and_offset (dpyinfo->visual->red_mask,
10079 &dpyinfo->red_bits, &dpyinfo->red_offset);
10080 get_bits_and_offset (dpyinfo->visual->blue_mask,
10081 &dpyinfo->blue_bits, &dpyinfo->blue_offset);
10082 get_bits_and_offset (dpyinfo->visual->green_mask,
10083 &dpyinfo->green_bits, &dpyinfo->green_offset);
10084 }
10085
10086 /* See if a private colormap is requested. */
10087 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
10088 {
10089 if (dpyinfo->visual->class == PseudoColor)
10090 {
10091 Lisp_Object value;
10092 value = display_x_get_resource (dpyinfo,
10093 build_string ("privateColormap"),
10094 build_string ("PrivateColormap"),
10095 Qnil, Qnil);
10096 if (STRINGP (value)
10097 && (!strcmp (SDATA (value), "true")
10098 || !strcmp (SDATA (value), "on")))
10099 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
10100 }
10101 }
10102 else
10103 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
10104 dpyinfo->visual, AllocNone);
10105
10106 #ifdef HAVE_XFT
10107 {
10108 /* If we are using Xft, check dpi value in X resources.
10109 It is better we use it as well, since Xft will use it, as will all
10110 Gnome applications. If our real DPI is smaller or larger than the
10111 one Xft uses, our font will look smaller or larger than other
10112 for other applications, even if it is the same font name (monospace-10
10113 for example). */
10114 char *v = XGetDefault (dpyinfo->display, "Xft", "dpi");
10115 double d;
10116 if (v != NULL && sscanf (v, "%lf", &d) == 1)
10117 dpyinfo->resy = dpyinfo->resx = d;
10118 }
10119 #endif
10120
10121 if (dpyinfo->resy < 1)
10122 {
10123 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
10124 double pixels = DisplayHeight (dpyinfo->display, screen_number);
10125 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
10126 /* Mac OS X 10.3's Xserver sometimes reports 0.0mm. */
10127 dpyinfo->resy = (mm < 1) ? 100 : pixels * 25.4 / mm;
10128 pixels = DisplayWidth (dpyinfo->display, screen_number);
10129 mm = DisplayWidthMM (dpyinfo->display, screen_number);
10130 /* Mac OS X 10.3's Xserver sometimes reports 0.0mm. */
10131 dpyinfo->resx = (mm < 1) ? 100 : pixels * 25.4 / mm;
10132 }
10133
10134 dpyinfo->Xatom_wm_protocols
10135 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
10136 dpyinfo->Xatom_wm_take_focus
10137 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
10138 dpyinfo->Xatom_wm_save_yourself
10139 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
10140 dpyinfo->Xatom_wm_delete_window
10141 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
10142 dpyinfo->Xatom_wm_change_state
10143 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
10144 dpyinfo->Xatom_wm_configure_denied
10145 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
10146 dpyinfo->Xatom_wm_window_moved
10147 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
10148 dpyinfo->Xatom_wm_client_leader
10149 = XInternAtom (dpyinfo->display, "WM_CLIENT_LEADER", False);
10150 dpyinfo->Xatom_editres
10151 = XInternAtom (dpyinfo->display, "Editres", False);
10152 dpyinfo->Xatom_CLIPBOARD
10153 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
10154 dpyinfo->Xatom_TIMESTAMP
10155 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
10156 dpyinfo->Xatom_TEXT
10157 = XInternAtom (dpyinfo->display, "TEXT", False);
10158 dpyinfo->Xatom_COMPOUND_TEXT
10159 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
10160 dpyinfo->Xatom_UTF8_STRING
10161 = XInternAtom (dpyinfo->display, "UTF8_STRING", False);
10162 dpyinfo->Xatom_DELETE
10163 = XInternAtom (dpyinfo->display, "DELETE", False);
10164 dpyinfo->Xatom_MULTIPLE
10165 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
10166 dpyinfo->Xatom_INCR
10167 = XInternAtom (dpyinfo->display, "INCR", False);
10168 dpyinfo->Xatom_EMACS_TMP
10169 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
10170 dpyinfo->Xatom_TARGETS
10171 = XInternAtom (dpyinfo->display, "TARGETS", False);
10172 dpyinfo->Xatom_NULL
10173 = XInternAtom (dpyinfo->display, "NULL", False);
10174 dpyinfo->Xatom_ATOM_PAIR
10175 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
10176 /* For properties of font. */
10177 dpyinfo->Xatom_PIXEL_SIZE
10178 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
10179 dpyinfo->Xatom_AVERAGE_WIDTH
10180 = XInternAtom (dpyinfo->display, "AVERAGE_WIDTH", False);
10181 dpyinfo->Xatom_MULE_BASELINE_OFFSET
10182 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
10183 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
10184 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
10185 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
10186 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
10187
10188 /* Ghostscript support. */
10189 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
10190 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
10191
10192 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
10193 False);
10194
10195 dpyinfo->Xatom_XEMBED = XInternAtom (dpyinfo->display, "_XEMBED",
10196 False);
10197
10198 dpyinfo->Xatom_net_wm_state
10199 = XInternAtom (dpyinfo->display, "_NET_WM_STATE", False);
10200 dpyinfo->Xatom_net_wm_state_fullscreen_atom
10201 = XInternAtom (dpyinfo->display, "_NET_WM_STATE_FULLSCREEN", False);
10202 dpyinfo->Xatom_net_wm_state_maximized_horz
10203 = XInternAtom (dpyinfo->display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
10204 dpyinfo->Xatom_net_wm_state_maximized_vert
10205 = XInternAtom (dpyinfo->display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
10206 dpyinfo->Xatom_net_wm_state_sticky
10207 = XInternAtom (dpyinfo->display, "_NET_WM_STATE_STICKY", False);
10208 dpyinfo->Xatom_net_window_type
10209 = XInternAtom (dpyinfo->display, "_NET_WM_WINDOW_TYPE", False);
10210 dpyinfo->Xatom_net_window_type_tooltip
10211 = XInternAtom (dpyinfo->display, "_NET_WM_WINDOW_TYPE_TOOLTIP", False);
10212
10213 dpyinfo->cut_buffers_initialized = 0;
10214
10215 dpyinfo->x_dnd_atoms_size = 8;
10216 dpyinfo->x_dnd_atoms_length = 0;
10217 dpyinfo->x_dnd_atoms = xmalloc (sizeof (*dpyinfo->x_dnd_atoms)
10218 * dpyinfo->x_dnd_atoms_size);
10219
10220 dpyinfo->net_supported_atoms = NULL;
10221 dpyinfo->nr_net_supported_atoms = 0;
10222 dpyinfo->net_supported_window = 0;
10223
10224 connection = ConnectionNumber (dpyinfo->display);
10225 dpyinfo->connection = connection;
10226
10227 {
10228 extern int gray_bitmap_width, gray_bitmap_height;
10229 extern char *gray_bitmap_bits;
10230 dpyinfo->gray
10231 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
10232 gray_bitmap_bits,
10233 gray_bitmap_width, gray_bitmap_height,
10234 (unsigned long) 1, (unsigned long) 0, 1);
10235 }
10236
10237 #ifdef HAVE_X_I18N
10238 xim_initialize (dpyinfo, resource_name);
10239 #endif
10240
10241 xsettings_initialize (dpyinfo);
10242
10243 #ifdef subprocesses
10244 /* This is only needed for distinguishing keyboard and process input. */
10245 if (connection != 0)
10246 add_keyboard_wait_descriptor (connection);
10247 #endif
10248
10249 #ifdef F_SETOWN
10250 fcntl (connection, F_SETOWN, getpid ());
10251 #endif /* ! defined (F_SETOWN) */
10252
10253 #ifdef SIGIO
10254 if (interrupt_input)
10255 init_sigio (connection);
10256 #endif /* ! defined (SIGIO) */
10257
10258 #ifdef USE_LUCID
10259 {
10260 Display *dpy = dpyinfo->display;
10261 XrmValue d, fr, to;
10262 Font font;
10263
10264 d.addr = (XPointer)&dpy;
10265 d.size = sizeof (Display *);
10266 fr.addr = XtDefaultFont;
10267 fr.size = sizeof (XtDefaultFont);
10268 to.size = sizeof (Font *);
10269 to.addr = (XPointer)&font;
10270 x_catch_errors (dpy);
10271 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
10272 abort ();
10273 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
10274 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
10275 x_uncatch_errors ();
10276 }
10277 #endif
10278
10279 /* See if we should run in synchronous mode. This is useful
10280 for debugging X code. */
10281 {
10282 Lisp_Object value;
10283 value = display_x_get_resource (dpyinfo,
10284 build_string ("synchronous"),
10285 build_string ("Synchronous"),
10286 Qnil, Qnil);
10287 if (STRINGP (value)
10288 && (!strcmp (SDATA (value), "true")
10289 || !strcmp (SDATA (value), "on")))
10290 XSynchronize (dpyinfo->display, True);
10291 }
10292
10293 {
10294 Lisp_Object value;
10295 value = display_x_get_resource (dpyinfo,
10296 build_string ("useXIM"),
10297 build_string ("UseXIM"),
10298 Qnil, Qnil);
10299 #ifdef USE_XIM
10300 if (STRINGP (value)
10301 && (!strcmp (SDATA (value), "false")
10302 || !strcmp (SDATA (value), "off")))
10303 use_xim = 0;
10304 #else
10305 if (STRINGP (value)
10306 && (!strcmp (SDATA (value), "true")
10307 || !strcmp (SDATA (value), "on")))
10308 use_xim = 1;
10309 #endif
10310 }
10311
10312 #ifdef HAVE_X_SM
10313 /* Only do this for the very first display in the Emacs session.
10314 Ignore X session management when Emacs was first started on a
10315 tty. */
10316 if (terminal->id == 1)
10317 x_session_initialize (dpyinfo);
10318 #endif
10319
10320 UNBLOCK_INPUT;
10321
10322 return dpyinfo;
10323 }
10324 \f
10325 /* Get rid of display DPYINFO, deleting all frames on it,
10326 and without sending any more commands to the X server. */
10327
10328 void
10329 x_delete_display (struct x_display_info *dpyinfo)
10330 {
10331 struct terminal *t;
10332
10333 /* Close all frames and delete the generic struct terminal for this
10334 X display. */
10335 for (t = terminal_list; t; t = t->next_terminal)
10336 if (t->type == output_x_window && t->display_info.x == dpyinfo)
10337 {
10338 #ifdef HAVE_X_SM
10339 /* Close X session management when we close its display. */
10340 if (t->id == 1 && x_session_have_connection ())
10341 x_session_close();
10342 #endif
10343 delete_terminal (t);
10344 break;
10345 }
10346
10347 delete_keyboard_wait_descriptor (dpyinfo->connection);
10348
10349 /* Discard this display from x_display_name_list and x_display_list.
10350 We can't use Fdelq because that can quit. */
10351 if (! NILP (x_display_name_list)
10352 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
10353 x_display_name_list = XCDR (x_display_name_list);
10354 else
10355 {
10356 Lisp_Object tail;
10357
10358 tail = x_display_name_list;
10359 while (CONSP (tail) && CONSP (XCDR (tail)))
10360 {
10361 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
10362 {
10363 XSETCDR (tail, XCDR (XCDR (tail)));
10364 break;
10365 }
10366 tail = XCDR (tail);
10367 }
10368 }
10369
10370 if (next_noop_dpyinfo == dpyinfo)
10371 next_noop_dpyinfo = dpyinfo->next;
10372
10373 if (x_display_list == dpyinfo)
10374 x_display_list = dpyinfo->next;
10375 else
10376 {
10377 struct x_display_info *tail;
10378
10379 for (tail = x_display_list; tail; tail = tail->next)
10380 if (tail->next == dpyinfo)
10381 tail->next = tail->next->next;
10382 }
10383
10384 xfree (dpyinfo->x_id_name);
10385 xfree (dpyinfo->x_dnd_atoms);
10386 xfree (dpyinfo->color_cells);
10387 xfree (dpyinfo);
10388 }
10389
10390 #ifdef USE_X_TOOLKIT
10391
10392 /* Atimer callback function for TIMER. Called every 0.1s to process
10393 Xt timeouts, if needed. We must avoid calling XtAppPending as
10394 much as possible because that function does an implicit XFlush
10395 that slows us down. */
10396
10397 static void
10398 x_process_timeouts (timer)
10399 struct atimer *timer;
10400 {
10401 BLOCK_INPUT;
10402 x_timeout_atimer_activated_flag = 0;
10403 if (toolkit_scroll_bar_interaction || popup_activated ())
10404 {
10405 while (XtAppPending (Xt_app_con) & XtIMTimer)
10406 XtAppProcessEvent (Xt_app_con, XtIMTimer);
10407 /* Reactivate the atimer for next time. */
10408 x_activate_timeout_atimer ();
10409 }
10410 UNBLOCK_INPUT;
10411 }
10412
10413 /* Install an asynchronous timer that processes Xt timeout events
10414 every 0.1s as long as either `toolkit_scroll_bar_interaction' or
10415 `popup_activated_flag' (in xmenu.c) is set. Make sure to call this
10416 function whenever these variables are set. This is necessary
10417 because some widget sets use timeouts internally, for example the
10418 LessTif menu bar, or the Xaw3d scroll bar. When Xt timeouts aren't
10419 processed, these widgets don't behave normally. */
10420
10421 void
10422 x_activate_timeout_atimer ()
10423 {
10424 BLOCK_INPUT;
10425 if (!x_timeout_atimer_activated_flag)
10426 {
10427 EMACS_TIME interval;
10428
10429 EMACS_SET_SECS_USECS (interval, 0, 100000);
10430 start_atimer (ATIMER_RELATIVE, interval, x_process_timeouts, 0);
10431 x_timeout_atimer_activated_flag = 1;
10432 }
10433 UNBLOCK_INPUT;
10434 }
10435
10436 #endif /* USE_X_TOOLKIT */
10437
10438 \f
10439 /* Set up use of X before we make the first connection. */
10440
10441 extern frame_parm_handler x_frame_parm_handlers[];
10442
10443 static struct redisplay_interface x_redisplay_interface =
10444 {
10445 x_frame_parm_handlers,
10446 x_produce_glyphs,
10447 x_write_glyphs,
10448 x_insert_glyphs,
10449 x_clear_end_of_line,
10450 x_scroll_run,
10451 x_after_update_window_line,
10452 x_update_window_begin,
10453 x_update_window_end,
10454 x_cursor_to,
10455 x_flush,
10456 #ifdef XFlush
10457 x_flush,
10458 #else
10459 0, /* flush_display_optional */
10460 #endif
10461 x_clear_window_mouse_face,
10462 x_get_glyph_overhangs,
10463 x_fix_overlapping_area,
10464 x_draw_fringe_bitmap,
10465 0, /* define_fringe_bitmap */
10466 0, /* destroy_fringe_bitmap */
10467 x_compute_glyph_string_overhangs,
10468 x_draw_glyph_string,
10469 x_define_frame_cursor,
10470 x_clear_frame_area,
10471 x_draw_window_cursor,
10472 x_draw_vertical_window_border,
10473 x_shift_glyphs_for_insert
10474 };
10475
10476
10477 /* This function is called when the last frame on a display is deleted. */
10478 void
10479 x_delete_terminal (struct terminal *terminal)
10480 {
10481 struct x_display_info *dpyinfo = terminal->display_info.x;
10482
10483 /* Protect against recursive calls. delete_frame in
10484 delete_terminal calls us back when it deletes our last frame. */
10485 if (!terminal->name)
10486 return;
10487
10488 BLOCK_INPUT;
10489 #ifdef HAVE_X_I18N
10490 /* We must close our connection to the XIM server before closing the
10491 X display. */
10492 if (dpyinfo->xim)
10493 xim_close_dpy (dpyinfo);
10494 #endif
10495
10496 /* If called from x_connection_closed, the display may already be closed
10497 and dpyinfo->display was set to 0 to indicate that. */
10498 if (dpyinfo->display)
10499 {
10500 x_destroy_all_bitmaps (dpyinfo);
10501 XSetCloseDownMode (dpyinfo->display, DestroyAll);
10502
10503 /* Whether or not XCloseDisplay destroys the associated resource
10504 database depends on the version of libX11. To avoid both
10505 crash and memory leak, we dissociate the database from the
10506 display and then destroy dpyinfo->xrdb ourselves.
10507
10508 Unfortunately, the above strategy does not work in some
10509 situations due to a bug in newer versions of libX11: because
10510 XrmSetDatabase doesn't clear the flag XlibDisplayDfltRMDB if
10511 dpy->db is NULL, XCloseDisplay destroys the associated
10512 database whereas it has not been created by XGetDefault
10513 (Bug#21974 in freedesktop.org Bugzilla). As a workaround, we
10514 don't destroy the database here in order to avoid the crash
10515 in the above situations for now, though that may cause memory
10516 leaks in other situations. */
10517 #if 0
10518 #ifdef HAVE_XRMSETDATABASE
10519 XrmSetDatabase (dpyinfo->display, NULL);
10520 #else
10521 dpyinfo->display->db = NULL;
10522 #endif
10523 /* We used to call XrmDestroyDatabase from x_delete_display, but
10524 some older versions of libX11 crash if we call it after
10525 closing all the displays. */
10526 XrmDestroyDatabase (dpyinfo->xrdb);
10527 #endif
10528
10529 #ifdef USE_GTK
10530 xg_display_close (dpyinfo->display);
10531 #else
10532 #ifdef USE_X_TOOLKIT
10533 XtCloseDisplay (dpyinfo->display);
10534 #else
10535 XCloseDisplay (dpyinfo->display);
10536 #endif
10537 #endif /* ! USE_GTK */
10538 }
10539
10540 /* Mark as dead. */
10541 dpyinfo->display = NULL;
10542 x_delete_display (dpyinfo);
10543 UNBLOCK_INPUT;
10544 }
10545
10546 /* Create a struct terminal, initialize it with the X11 specific
10547 functions and make DISPLAY->TERMINAL point to it. */
10548
10549 static struct terminal *
10550 x_create_terminal (struct x_display_info *dpyinfo)
10551 {
10552 struct terminal *terminal;
10553
10554 terminal = create_terminal ();
10555
10556 terminal->type = output_x_window;
10557 terminal->display_info.x = dpyinfo;
10558 dpyinfo->terminal = terminal;
10559
10560 /* kboard is initialized in x_term_init. */
10561
10562 terminal->clear_frame_hook = x_clear_frame;
10563 terminal->ins_del_lines_hook = x_ins_del_lines;
10564 terminal->delete_glyphs_hook = x_delete_glyphs;
10565 terminal->ring_bell_hook = XTring_bell;
10566 terminal->toggle_invisible_pointer_hook = XTtoggle_invisible_pointer;
10567 terminal->reset_terminal_modes_hook = XTreset_terminal_modes;
10568 terminal->set_terminal_modes_hook = XTset_terminal_modes;
10569 terminal->update_begin_hook = x_update_begin;
10570 terminal->update_end_hook = x_update_end;
10571 terminal->set_terminal_window_hook = XTset_terminal_window;
10572 terminal->read_socket_hook = XTread_socket;
10573 terminal->frame_up_to_date_hook = XTframe_up_to_date;
10574 terminal->mouse_position_hook = XTmouse_position;
10575 terminal->frame_rehighlight_hook = XTframe_rehighlight;
10576 terminal->frame_raise_lower_hook = XTframe_raise_lower;
10577 terminal->fullscreen_hook = XTfullscreen_hook;
10578 terminal->set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
10579 terminal->condemn_scroll_bars_hook = XTcondemn_scroll_bars;
10580 terminal->redeem_scroll_bar_hook = XTredeem_scroll_bar;
10581 terminal->judge_scroll_bars_hook = XTjudge_scroll_bars;
10582
10583 terminal->delete_frame_hook = x_destroy_window;
10584 terminal->delete_terminal_hook = x_delete_terminal;
10585
10586 terminal->rif = &x_redisplay_interface;
10587 terminal->scroll_region_ok = 1; /* We'll scroll partial frames. */
10588 terminal->char_ins_del_ok = 1;
10589 terminal->line_ins_del_ok = 1; /* We'll just blt 'em. */
10590 terminal->fast_clear_end_of_line = 1; /* X does this well. */
10591 terminal->memory_below_frame = 0; /* We don't remember what scrolls
10592 off the bottom. */
10593
10594 return terminal;
10595 }
10596
10597 void
10598 x_initialize (void)
10599 {
10600 baud_rate = 19200;
10601
10602 x_noop_count = 0;
10603 last_tool_bar_item = -1;
10604 any_help_event_p = 0;
10605 ignore_next_mouse_click_timeout = 0;
10606 #ifdef HAVE_X_SM
10607 x_session_initialized = 0;
10608 #endif
10609
10610 #ifdef USE_GTK
10611 current_count = -1;
10612 #endif
10613
10614 /* Try to use interrupt input; if we can't, then start polling. */
10615 Fset_input_interrupt_mode (Qt);
10616
10617 #ifdef USE_X_TOOLKIT
10618 XtToolkitInitialize ();
10619
10620 Xt_app_con = XtCreateApplicationContext ();
10621
10622 /* Register a converter from strings to pixels, which uses
10623 Emacs' color allocation infrastructure. */
10624 XtAppSetTypeConverter (Xt_app_con,
10625 XtRString, XtRPixel, cvt_string_to_pixel,
10626 cvt_string_to_pixel_args,
10627 XtNumber (cvt_string_to_pixel_args),
10628 XtCacheByDisplay, cvt_pixel_dtor);
10629
10630 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
10631 #endif
10632
10633 #ifdef USE_TOOLKIT_SCROLL_BARS
10634 #ifndef USE_GTK
10635 xaw3d_arrow_scroll = False;
10636 xaw3d_pick_top = True;
10637 #endif
10638 #endif
10639
10640 pending_autoraise_frame = 0;
10641 pending_event_wait.f = 0;
10642 pending_event_wait.eventtype = 0;
10643
10644 /* Note that there is no real way portable across R3/R4 to get the
10645 original error handler. */
10646 XSetErrorHandler (x_error_handler);
10647 XSetIOErrorHandler (x_io_error_quitter);
10648
10649 signal (SIGPIPE, x_connection_signal);
10650
10651 xgselect_initialize ();
10652 }
10653
10654
10655 void
10656 syms_of_xterm (void)
10657 {
10658 x_error_message = NULL;
10659
10660 staticpro (&x_display_name_list);
10661 x_display_name_list = Qnil;
10662
10663 staticpro (&last_mouse_scroll_bar);
10664 last_mouse_scroll_bar = Qnil;
10665
10666 staticpro (&Qvendor_specific_keysyms);
10667 Qvendor_specific_keysyms = intern_c_string ("vendor-specific-keysyms");
10668
10669 staticpro (&Qlatin_1);
10670 Qlatin_1 = intern_c_string ("latin-1");
10671
10672 staticpro (&last_mouse_press_frame);
10673 last_mouse_press_frame = Qnil;
10674
10675 #ifdef USE_GTK
10676 xg_default_icon_file = make_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg");
10677 staticpro (&xg_default_icon_file);
10678
10679 Qx_gtk_map_stock = intern_c_string ("x-gtk-map-stock");
10680 staticpro (&Qx_gtk_map_stock);
10681 #endif
10682
10683 DEFVAR_BOOL ("x-use-underline-position-properties",
10684 &x_use_underline_position_properties,
10685 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
10686 A value of nil means ignore them. If you encounter fonts with bogus
10687 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
10688 to 4.1, set this to nil. You can also use `underline-minimum-offset'
10689 to override the font's UNDERLINE_POSITION for small font display
10690 sizes. */);
10691 x_use_underline_position_properties = 1;
10692
10693 DEFVAR_BOOL ("x-underline-at-descent-line",
10694 &x_underline_at_descent_line,
10695 doc: /* *Non-nil means to draw the underline at the same place as the descent line.
10696 A value of nil means to draw the underline according to the value of the
10697 variable `x-use-underline-position-properties', which is usually at the
10698 baseline level. The default value is nil. */);
10699 x_underline_at_descent_line = 0;
10700
10701 DEFVAR_BOOL ("x-mouse-click-focus-ignore-position",
10702 &x_mouse_click_focus_ignore_position,
10703 doc: /* Non-nil means that a mouse click to focus a frame does not move point.
10704 This variable is only used when the window manager requires that you
10705 click on a frame to select it (give it focus). In that case, a value
10706 of nil, means that the selected window and cursor position changes to
10707 reflect the mouse click position, while a non-nil value means that the
10708 selected window or cursor position is preserved. */);
10709 x_mouse_click_focus_ignore_position = 0;
10710
10711 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
10712 doc: /* What X toolkit scroll bars Emacs uses.
10713 A value of nil means Emacs doesn't use X toolkit scroll bars.
10714 Otherwise, value is a symbol describing the X toolkit. */);
10715 #ifdef USE_TOOLKIT_SCROLL_BARS
10716 #ifdef USE_MOTIF
10717 Vx_toolkit_scroll_bars = intern_c_string ("motif");
10718 #elif defined HAVE_XAW3D
10719 Vx_toolkit_scroll_bars = intern_c_string ("xaw3d");
10720 #elif USE_GTK
10721 Vx_toolkit_scroll_bars = intern_c_string ("gtk");
10722 #else
10723 Vx_toolkit_scroll_bars = intern_c_string ("xaw");
10724 #endif
10725 #else
10726 Vx_toolkit_scroll_bars = Qnil;
10727 #endif
10728
10729 staticpro (&last_mouse_motion_frame);
10730 last_mouse_motion_frame = Qnil;
10731
10732 Qmodifier_value = intern_c_string ("modifier-value");
10733 Qalt = intern_c_string ("alt");
10734 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
10735 Qhyper = intern_c_string ("hyper");
10736 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
10737 Qmeta = intern_c_string ("meta");
10738 Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
10739 Qsuper = intern_c_string ("super");
10740 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
10741
10742 DEFVAR_LISP ("x-alt-keysym", &Vx_alt_keysym,
10743 doc: /* Which keys Emacs uses for the alt modifier.
10744 This should be one of the symbols `alt', `hyper', `meta', `super'.
10745 For example, `alt' means use the Alt_L and Alt_R keysyms. The default
10746 is nil, which is the same as `alt'. */);
10747 Vx_alt_keysym = Qnil;
10748
10749 DEFVAR_LISP ("x-hyper-keysym", &Vx_hyper_keysym,
10750 doc: /* Which keys Emacs uses for the hyper modifier.
10751 This should be one of the symbols `alt', `hyper', `meta', `super'.
10752 For example, `hyper' means use the Hyper_L and Hyper_R keysyms. The
10753 default is nil, which is the same as `hyper'. */);
10754 Vx_hyper_keysym = Qnil;
10755
10756 DEFVAR_LISP ("x-meta-keysym", &Vx_meta_keysym,
10757 doc: /* Which keys Emacs uses for the meta modifier.
10758 This should be one of the symbols `alt', `hyper', `meta', `super'.
10759 For example, `meta' means use the Meta_L and Meta_R keysyms. The
10760 default is nil, which is the same as `meta'. */);
10761 Vx_meta_keysym = Qnil;
10762
10763 DEFVAR_LISP ("x-super-keysym", &Vx_super_keysym,
10764 doc: /* Which keys Emacs uses for the super modifier.
10765 This should be one of the symbols `alt', `hyper', `meta', `super'.
10766 For example, `super' means use the Super_L and Super_R keysyms. The
10767 default is nil, which is the same as `super'. */);
10768 Vx_super_keysym = Qnil;
10769
10770 DEFVAR_LISP ("x-keysym-table", &Vx_keysym_table,
10771 doc: /* Hash table of character codes indexed by X keysym codes. */);
10772 Vx_keysym_table = make_hash_table (Qeql, make_number (900),
10773 make_float (DEFAULT_REHASH_SIZE),
10774 make_float (DEFAULT_REHASH_THRESHOLD),
10775 Qnil, Qnil, Qnil);
10776 }
10777
10778 #endif /* HAVE_X_WINDOWS */
10779
10780 /* arch-tag: 6d4e4cb7-abc1-4302-9585-d84dcfb09d0f
10781 (do not change this comment) */