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