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