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