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