1 /* X Communication module for terminals which understand the X protocol.
2 
3 Copyright (C) 1989, 1993-2021 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 (at
10 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 <https://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 <stdlib.h>
25 #include <math.h>
26 
27 #include "lisp.h"
28 #include "blockinput.h"
29 #include "sysstdio.h"
30 
31 /* This may include sys/types.h, and that somehow loses
32    if this is not done before the other system files.  */
33 #include "xterm.h"
34 #include <X11/cursorfont.h>
35 
36 /* If we have Xfixes extension, use it for pointer blanking.  */
37 #ifdef HAVE_XFIXES
38 #include <X11/extensions/Xfixes.h>
39 #endif
40 
41 #ifdef HAVE_XDBE
42 #include <X11/extensions/Xdbe.h>
43 #endif
44 
45 /* Load sys/types.h if not already loaded.
46    In some systems loading it twice is suicidal.  */
47 #ifndef makedev
48 #include <sys/types.h>
49 #endif /* makedev */
50 
51 #include <sys/ioctl.h>
52 
53 #include "systime.h"
54 
55 #include <fcntl.h>
56 #include <errno.h>
57 #include <sys/stat.h>
58 #include "character.h"
59 #include "coding.h"
60 #include "composite.h"
61 #include "frame.h"
62 #include "dispextern.h"
63 #include "xwidget.h"
64 #include "fontset.h"
65 #include "termhooks.h"
66 #include "termopts.h"
67 #include "termchar.h"
68 #include "emacs-icon.h"
69 #include "buffer.h"
70 #include "window.h"
71 #include "keyboard.h"
72 #include "atimer.h"
73 #include "font.h"
74 #include "xsettings.h"
75 #include "sysselect.h"
76 #include "menu.h"
77 #include "pdumper.h"
78 
79 #ifdef USE_X_TOOLKIT
80 #include <X11/Shell.h>
81 #endif
82 
83 #include <unistd.h>
84 
85 #ifdef USE_GTK
86 #include "gtkutil.h"
87 #ifdef HAVE_GTK3
88 #include <X11/Xproto.h>
89 #endif
90 #endif
91 
92 #if defined (USE_LUCID) || defined (USE_MOTIF)
93 #include "../lwlib/xlwmenu.h"
94 #endif
95 
96 #ifdef USE_X_TOOLKIT
97 
98 /* Include toolkit specific headers for the scroll bar widget.  */
99 
100 #ifdef USE_TOOLKIT_SCROLL_BARS
101 #if defined USE_MOTIF
102 #include <Xm/Xm.h>		/* For LESSTIF_VERSION */
103 #include <Xm/ScrollBar.h>
104 #else /* !USE_MOTIF i.e. use Xaw */
105 
106 #ifdef HAVE_XAW3D
107 #include <X11/Xaw3d/Simple.h>
108 #include <X11/Xaw3d/Scrollbar.h>
109 #include <X11/Xaw3d/ThreeD.h>
110 #else /* !HAVE_XAW3D */
111 #include <X11/Xaw/Simple.h>
112 #include <X11/Xaw/Scrollbar.h>
113 #endif /* !HAVE_XAW3D */
114 #ifndef XtNpickTop
115 #define XtNpickTop "pickTop"
116 #endif /* !XtNpickTop */
117 #endif /* !USE_MOTIF */
118 #endif /* USE_TOOLKIT_SCROLL_BARS */
119 
120 #endif /* USE_X_TOOLKIT */
121 
122 #ifdef USE_X_TOOLKIT
123 #include "widget.h"
124 #ifndef XtNinitialState
125 #define XtNinitialState "initialState"
126 #endif
127 #endif
128 
129 #include "bitmaps/gray.xbm"
130 
131 #ifdef HAVE_XKB
132 #include <X11/XKBlib.h>
133 #endif
134 
135 /* Default to using XIM if available.  */
136 #ifdef USE_XIM
137 bool use_xim = true;
138 #else
139 bool use_xim = false;  /* configure --without-xim */
140 #endif
141 
142 /* Non-zero means that a HELP_EVENT has been generated since Emacs
143    start.  */
144 
145 static bool any_help_event_p;
146 
147 /* This is a chain of structures for all the X displays currently in
148    use.  */
149 
150 struct x_display_info *x_display_list;
151 
152 #ifdef USE_X_TOOLKIT
153 
154 /* The application context for Xt use.  */
155 XtAppContext Xt_app_con;
156 static String Xt_default_resources[] = {0};
157 
158 /* Non-zero means user is interacting with a toolkit scroll bar.  */
159 static bool toolkit_scroll_bar_interaction;
160 
161 #endif /* USE_X_TOOLKIT */
162 
163 /* Non-zero timeout value means ignore next mouse click if it arrives
164    before that timeout elapses (i.e. as part of the same sequence of
165    events resulting from clicking on a frame to select it).  */
166 
167 static Time ignore_next_mouse_click_timeout;
168 
169 /* Used locally within XTread_socket.  */
170 
171 static int x_noop_count;
172 
173 #ifdef USE_GTK
174 /* The name of the Emacs icon file.  */
175 static Lisp_Object xg_default_icon_file;
176 #endif
177 
178 /* Some functions take this as char *, not const char *.  */
179 static char emacs_class[] = EMACS_CLASS;
180 
181 enum xembed_info
182   {
183     XEMBED_MAPPED = 1 << 0
184   };
185 
186 enum xembed_message
187   {
188     XEMBED_EMBEDDED_NOTIFY        = 0,
189     XEMBED_WINDOW_ACTIVATE        = 1,
190     XEMBED_WINDOW_DEACTIVATE      = 2,
191     XEMBED_REQUEST_FOCUS          = 3,
192     XEMBED_FOCUS_IN               = 4,
193     XEMBED_FOCUS_OUT              = 5,
194     XEMBED_FOCUS_NEXT             = 6,
195     XEMBED_FOCUS_PREV             = 7,
196 
197     XEMBED_MODALITY_ON            = 10,
198     XEMBED_MODALITY_OFF           = 11,
199     XEMBED_REGISTER_ACCELERATOR   = 12,
200     XEMBED_UNREGISTER_ACCELERATOR = 13,
201     XEMBED_ACTIVATE_ACCELERATOR   = 14
202   };
203 
204 static bool x_alloc_nearest_color_1 (Display *, Colormap, XColor *);
205 static void x_raise_frame (struct frame *);
206 static void x_lower_frame (struct frame *);
207 static int x_io_error_quitter (Display *);
208 static struct terminal *x_create_terminal (struct x_display_info *);
209 static void x_frame_rehighlight (struct x_display_info *);
210 
211 static void x_clip_to_row (struct window *, struct glyph_row *,
212 			   enum glyph_row_area, GC);
213 static struct scroll_bar *x_window_to_scroll_bar (Display *, Window, int);
214 static void x_scroll_bar_report_motion (struct frame **, Lisp_Object *,
215                                         enum scroll_bar_part *,
216                                         Lisp_Object *, Lisp_Object *,
217                                         Time *);
218 static void x_horizontal_scroll_bar_report_motion (struct frame **, Lisp_Object *,
219 						   enum scroll_bar_part *,
220 						   Lisp_Object *, Lisp_Object *,
221 						   Time *);
222 static bool x_handle_net_wm_state (struct frame *, const XPropertyEvent *);
223 static void x_check_fullscreen (struct frame *);
224 static void x_check_expected_move (struct frame *, int, int);
225 static void x_sync_with_move (struct frame *, int, int, bool);
226 static int handle_one_xevent (struct x_display_info *,
227 			      const XEvent *, int *,
228 			      struct input_event *);
229 #if ! (defined USE_X_TOOLKIT || defined USE_MOTIF) && defined USE_GTK
230 static int x_dispatch_event (XEvent *, Display *);
231 #endif
232 static void x_wm_set_window_state (struct frame *, int);
233 static void x_wm_set_icon_pixmap (struct frame *, ptrdiff_t);
234 static void x_initialize (void);
235 
236 static bool x_get_current_wm_state (struct frame *, Window, int *, bool *);
237 
238 /* Flush display of frame F.  */
239 
240 static void
x_flush(struct frame * f)241 x_flush (struct frame *f)
242 {
243   eassert (f && FRAME_X_P (f));
244   /* Don't call XFlush when it is not safe to redisplay; the X
245      connection may be broken.  */
246   if (!NILP (Vinhibit_redisplay))
247     return;
248 
249   block_input ();
250   XFlush (FRAME_X_DISPLAY (f));
251   unblock_input ();
252 }
253 
254 
255 /* Remove calls to XFlush by defining XFlush to an empty replacement.
256    Calls to XFlush should be unnecessary because the X output buffer
257    is flushed automatically as needed by calls to XPending,
258    XNextEvent, or XWindowEvent according to the XFlush man page.
259    XTread_socket calls XPending.  Removing XFlush improves
260    performance.  */
261 
262 #define XFlush(DISPLAY)	(void) 0
263 
264 
265 /***********************************************************************
266 			      Debugging
267  ***********************************************************************/
268 
269 #if false
270 
271 /* This is a function useful for recording debugging information about
272    the sequence of occurrences in this file.  */
273 
274 struct record
275 {
276   char *locus;
277   int type;
278 };
279 
280 struct record event_record[100];
281 
282 int event_record_index;
283 
284 void
record_event(char * locus,int type)285 record_event (char *locus, int type)
286 {
287   if (event_record_index == ARRAYELTS (event_record))
288     event_record_index = 0;
289 
290   event_record[event_record_index].locus = locus;
291   event_record[event_record_index].type = type;
292   event_record_index++;
293 }
294 
295 #endif
296 
297 #ifdef USE_CAIRO
298 
299 #define FRAME_CR_CONTEXT(f)	((f)->output_data.x->cr_context)
300 #define FRAME_CR_SURFACE_DESIRED_WIDTH(f) \
301   ((f)->output_data.x->cr_surface_desired_width)
302 #define FRAME_CR_SURFACE_DESIRED_HEIGHT(f) \
303   ((f)->output_data.x->cr_surface_desired_height)
304 
305 static struct x_gc_ext_data *
x_gc_get_ext_data(struct frame * f,GC gc,int create_if_not_found_p)306 x_gc_get_ext_data (struct frame *f, GC gc, int create_if_not_found_p)
307 {
308   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
309   XEDataObject object;
310   XExtData **head, *ext_data;
311 
312   object.gc = gc;
313   head = XEHeadOfExtensionList (object);
314   ext_data = XFindOnExtensionList (head, dpyinfo->ext_codes->extension);
315   if (ext_data == NULL)
316     {
317       if (!create_if_not_found_p)
318 	return NULL;
319       else
320 	{
321 	  ext_data = xzalloc (sizeof (*ext_data));
322 	  ext_data->number = dpyinfo->ext_codes->extension;
323 	  ext_data->private_data = xzalloc (sizeof (struct x_gc_ext_data));
324 	  XAddToExtensionList (head, ext_data);
325 	}
326     }
327   return (struct x_gc_ext_data *) ext_data->private_data;
328 }
329 
330 static void
x_extension_initialize(struct x_display_info * dpyinfo)331 x_extension_initialize (struct x_display_info *dpyinfo)
332 {
333   XExtCodes *ext_codes = XAddExtension (dpyinfo->display);
334 
335   dpyinfo->ext_codes = ext_codes;
336 }
337 
338 void
x_cr_destroy_frame_context(struct frame * f)339 x_cr_destroy_frame_context (struct frame *f)
340 {
341   if (FRAME_CR_CONTEXT (f))
342     {
343       cairo_destroy (FRAME_CR_CONTEXT (f));
344       FRAME_CR_CONTEXT (f) = NULL;
345     }
346 }
347 
348 void
x_cr_update_surface_desired_size(struct frame * f,int width,int height)349 x_cr_update_surface_desired_size (struct frame *f, int width, int height)
350 {
351   if (FRAME_CR_SURFACE_DESIRED_WIDTH (f) != width
352       || FRAME_CR_SURFACE_DESIRED_HEIGHT (f) != height)
353     {
354       x_cr_destroy_frame_context (f);
355       FRAME_CR_SURFACE_DESIRED_WIDTH (f) = width;
356       FRAME_CR_SURFACE_DESIRED_HEIGHT (f) = height;
357     }
358 }
359 
360 static void
x_cr_gc_clip(cairo_t * cr,struct frame * f,GC gc)361 x_cr_gc_clip (cairo_t *cr, struct frame *f, GC gc)
362 {
363   if (gc)
364     {
365       struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 0);
366 
367       if (gc_ext && gc_ext->n_clip_rects)
368 	{
369 	  for (int i = 0; i < gc_ext->n_clip_rects; i++)
370 	    cairo_rectangle (cr, gc_ext->clip_rects[i].x,
371 			     gc_ext->clip_rects[i].y,
372 			     gc_ext->clip_rects[i].width,
373 			     gc_ext->clip_rects[i].height);
374 	  cairo_clip (cr);
375 	}
376     }
377 }
378 
379 cairo_t *
x_begin_cr_clip(struct frame * f,GC gc)380 x_begin_cr_clip (struct frame *f, GC gc)
381 {
382   cairo_t *cr = FRAME_CR_CONTEXT (f);
383 
384   if (!cr)
385     {
386       int width = FRAME_CR_SURFACE_DESIRED_WIDTH (f);
387       int height = FRAME_CR_SURFACE_DESIRED_HEIGHT (f);
388       cairo_surface_t *surface
389 	= cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
390 				     FRAME_X_RAW_DRAWABLE (f),
391 				     FRAME_X_VISUAL (f),
392 				     width, height);
393 
394       cr = FRAME_CR_CONTEXT (f) = cairo_create (surface);
395       cairo_surface_destroy (surface);
396     }
397   cairo_save (cr);
398   x_cr_gc_clip (cr, f, gc);
399 
400   return cr;
401 }
402 
403 void
x_end_cr_clip(struct frame * f)404 x_end_cr_clip (struct frame *f)
405 {
406   cairo_restore (FRAME_CR_CONTEXT (f));
407   if (FRAME_X_DOUBLE_BUFFERED_P (f))
408     x_mark_frame_dirty (f);
409 }
410 
411 void
x_set_cr_source_with_gc_foreground(struct frame * f,GC gc)412 x_set_cr_source_with_gc_foreground (struct frame *f, GC gc)
413 {
414   XGCValues xgcv;
415   XColor color;
416 
417   XGetGCValues (FRAME_X_DISPLAY (f), gc, GCForeground, &xgcv);
418   color.pixel = xgcv.foreground;
419   x_query_colors (f, &color, 1);
420   cairo_set_source_rgb (FRAME_CR_CONTEXT (f), color.red / 65535.0,
421 			color.green / 65535.0, color.blue / 65535.0);
422 }
423 
424 void
x_set_cr_source_with_gc_background(struct frame * f,GC gc)425 x_set_cr_source_with_gc_background (struct frame *f, GC gc)
426 {
427   XGCValues xgcv;
428   XColor color;
429 
430   XGetGCValues (FRAME_X_DISPLAY (f), gc, GCBackground, &xgcv);
431   color.pixel = xgcv.background;
432   x_query_colors (f, &color, 1);
433   cairo_set_source_rgb (FRAME_CR_CONTEXT (f), color.red / 65535.0,
434 			color.green / 65535.0, color.blue / 65535.0);
435 }
436 
437 static const cairo_user_data_key_t xlib_surface_key, saved_drawable_key;
438 
439 static void
x_cr_destroy_xlib_surface(cairo_surface_t * xlib_surface)440 x_cr_destroy_xlib_surface (cairo_surface_t *xlib_surface)
441 {
442   if (xlib_surface)
443     {
444       XFreePixmap (cairo_xlib_surface_get_display (xlib_surface),
445 		   cairo_xlib_surface_get_drawable (xlib_surface));
446       cairo_surface_destroy (xlib_surface);
447     }
448 }
449 
450 static bool
x_try_cr_xlib_drawable(struct frame * f,GC gc)451 x_try_cr_xlib_drawable (struct frame *f, GC gc)
452 {
453   cairo_t *cr = FRAME_CR_CONTEXT (f);
454   if (!cr)
455     return true;
456 
457   cairo_surface_t *surface = cairo_get_target (cr);
458   switch (cairo_surface_get_type (surface))
459     {
460     case CAIRO_SURFACE_TYPE_XLIB:
461       cairo_surface_flush (surface);
462       return true;
463 
464     case CAIRO_SURFACE_TYPE_IMAGE:
465       break;
466 
467     default:
468       return false;
469     }
470 
471   /* FRAME_CR_CONTEXT (f) is an image surface we can not draw into
472      directly with Xlib.  Set up a Pixmap so we can copy back the
473      result later in x_end_cr_xlib_drawable.  */
474   cairo_surface_t *xlib_surface = cairo_get_user_data (cr, &xlib_surface_key);
475   int width = FRAME_CR_SURFACE_DESIRED_WIDTH (f);
476   int height = FRAME_CR_SURFACE_DESIRED_HEIGHT (f);
477   Pixmap pixmap;
478   if (xlib_surface
479       && cairo_xlib_surface_get_width (xlib_surface) == width
480       && cairo_xlib_surface_get_height (xlib_surface) == height)
481     pixmap = cairo_xlib_surface_get_drawable (xlib_surface);
482   else
483     {
484       pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_RAW_DRAWABLE (f),
485 			      width, height,
486 			      DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
487       xlib_surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
488 						pixmap, FRAME_X_VISUAL (f),
489 						width, height);
490       cairo_set_user_data (cr, &xlib_surface_key, xlib_surface,
491 			   (cairo_destroy_func_t) x_cr_destroy_xlib_surface);
492     }
493 
494   cairo_t *buf = cairo_create (xlib_surface);
495   cairo_set_source_surface (buf, surface, 0, 0);
496   cairo_matrix_t matrix;
497   cairo_get_matrix (cr, &matrix);
498   cairo_pattern_set_matrix (cairo_get_source (cr), &matrix);
499   cairo_set_operator (buf, CAIRO_OPERATOR_SOURCE);
500   x_cr_gc_clip (buf, f, gc);
501   cairo_paint (buf);
502   cairo_destroy (buf);
503 
504   cairo_set_user_data (cr, &saved_drawable_key,
505 		       (void *) (uintptr_t) FRAME_X_RAW_DRAWABLE (f), NULL);
506   FRAME_X_RAW_DRAWABLE (f) = pixmap;
507   cairo_surface_flush (xlib_surface);
508 
509   return true;
510 }
511 
512 static void
x_end_cr_xlib_drawable(struct frame * f,GC gc)513 x_end_cr_xlib_drawable (struct frame *f, GC gc)
514 {
515   cairo_t *cr = FRAME_CR_CONTEXT (f);
516   if (!cr)
517     return;
518 
519   Drawable saved_drawable
520     = (uintptr_t) cairo_get_user_data (cr, &saved_drawable_key);
521   cairo_surface_t *surface = (saved_drawable
522 			      ? cairo_get_user_data (cr, &xlib_surface_key)
523 			      : cairo_get_target (cr));
524   struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 0);
525   if (gc_ext && gc_ext->n_clip_rects)
526     for (int i = 0; i < gc_ext->n_clip_rects; i++)
527       cairo_surface_mark_dirty_rectangle (surface, gc_ext->clip_rects[i].x,
528 					  gc_ext->clip_rects[i].y,
529 					  gc_ext->clip_rects[i].width,
530 					  gc_ext->clip_rects[i].height);
531   else
532     cairo_surface_mark_dirty (surface);
533   if (!saved_drawable)
534     return;
535 
536   cairo_save (cr);
537   cairo_set_source_surface (cr, surface, 0, 0);
538   cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
539   x_cr_gc_clip (cr, f, gc);
540   cairo_paint (cr);
541   cairo_restore (cr);
542 
543   FRAME_X_RAW_DRAWABLE (f) = saved_drawable;
544   cairo_set_user_data (cr, &saved_drawable_key, NULL, NULL);
545 }
546 
547 /* Fringe bitmaps.  */
548 
549 static int max_fringe_bmp = 0;
550 static cairo_pattern_t **fringe_bmp = 0;
551 
552 static void
x_cr_define_fringe_bitmap(int which,unsigned short * bits,int h,int wd)553 x_cr_define_fringe_bitmap (int which, unsigned short *bits, int h, int wd)
554 {
555   int i, stride;
556   cairo_surface_t *surface;
557   cairo_pattern_t *pattern;
558   unsigned char *data;
559 
560   if (which >= max_fringe_bmp)
561     {
562       i = max_fringe_bmp;
563       max_fringe_bmp = which + 20;
564       fringe_bmp = xrealloc (fringe_bmp, max_fringe_bmp * sizeof (*fringe_bmp));
565       while (i < max_fringe_bmp)
566 	fringe_bmp[i++] = 0;
567     }
568 
569   block_input ();
570 
571   surface = cairo_image_surface_create (CAIRO_FORMAT_A1, wd, h);
572   stride = cairo_image_surface_get_stride (surface);
573   data = cairo_image_surface_get_data (surface);
574 
575   for (i = 0; i < h; i++)
576     {
577       *((unsigned short *) data) = bits[i];
578       data += stride;
579     }
580 
581   cairo_surface_mark_dirty (surface);
582   pattern = cairo_pattern_create_for_surface (surface);
583   cairo_surface_destroy (surface);
584 
585   unblock_input ();
586 
587   fringe_bmp[which] = pattern;
588 }
589 
590 static void
x_cr_destroy_fringe_bitmap(int which)591 x_cr_destroy_fringe_bitmap (int which)
592 {
593   if (which >= max_fringe_bmp)
594     return;
595 
596   if (fringe_bmp[which])
597     {
598       block_input ();
599       cairo_pattern_destroy (fringe_bmp[which]);
600       unblock_input ();
601     }
602   fringe_bmp[which] = 0;
603 }
604 
605 static void
x_cr_draw_image(struct frame * f,GC gc,cairo_pattern_t * image,int src_x,int src_y,int width,int height,int dest_x,int dest_y,bool overlay_p)606 x_cr_draw_image (struct frame *f, GC gc, cairo_pattern_t *image,
607 		 int src_x, int src_y, int width, int height,
608 		 int dest_x, int dest_y, bool overlay_p)
609 {
610   cairo_t *cr = x_begin_cr_clip (f, gc);
611 
612   if (overlay_p)
613     cairo_rectangle (cr, dest_x, dest_y, width, height);
614   else
615     {
616       x_set_cr_source_with_gc_background (f, gc);
617       cairo_rectangle (cr, dest_x, dest_y, width, height);
618       cairo_fill_preserve (cr);
619     }
620 
621   cairo_translate (cr, dest_x - src_x, dest_y - src_y);
622 
623   cairo_surface_t *surface;
624   cairo_pattern_get_surface (image, &surface);
625   cairo_format_t format = cairo_image_surface_get_format (surface);
626   if (format != CAIRO_FORMAT_A8 && format != CAIRO_FORMAT_A1)
627     {
628       cairo_set_source (cr, image);
629       cairo_fill (cr);
630     }
631   else
632     {
633       x_set_cr_source_with_gc_foreground (f, gc);
634       cairo_clip (cr);
635       cairo_mask (cr, image);
636     }
637 
638   x_end_cr_clip (f);
639 }
640 
641 void
x_cr_draw_frame(cairo_t * cr,struct frame * f)642 x_cr_draw_frame (cairo_t *cr, struct frame *f)
643 {
644   int width, height;
645 
646   width = FRAME_PIXEL_WIDTH (f);
647   height = FRAME_PIXEL_HEIGHT (f);
648 
649   cairo_t *saved_cr = FRAME_CR_CONTEXT (f);
650   FRAME_CR_CONTEXT (f) = cr;
651   x_clear_area (f, 0, 0, width, height);
652   expose_frame (f, 0, 0, width, height);
653   FRAME_CR_CONTEXT (f) = saved_cr;
654 }
655 
656 static cairo_status_t
x_cr_accumulate_data(void * closure,const unsigned char * data,unsigned int length)657 x_cr_accumulate_data (void *closure, const unsigned char *data,
658 		      unsigned int length)
659 {
660   Lisp_Object *acc = (Lisp_Object *) closure;
661 
662   *acc = Fcons (make_unibyte_string ((char const *) data, length), *acc);
663 
664   return CAIRO_STATUS_SUCCESS;
665 }
666 
667 static void
x_cr_destroy(void * cr)668 x_cr_destroy (void *cr)
669 {
670   block_input ();
671   cairo_destroy (cr);
672   unblock_input ();
673 }
674 
675 Lisp_Object
x_cr_export_frames(Lisp_Object frames,cairo_surface_type_t surface_type)676 x_cr_export_frames (Lisp_Object frames, cairo_surface_type_t surface_type)
677 {
678   struct frame *f;
679   cairo_surface_t *surface;
680   cairo_t *cr;
681   int width, height;
682   void (*surface_set_size_func) (cairo_surface_t *, double, double) = NULL;
683   Lisp_Object acc = Qnil;
684   ptrdiff_t count = SPECPDL_INDEX ();
685 
686   specbind (Qredisplay_dont_pause, Qt);
687   redisplay_preserve_echo_area (31);
688 
689   f = XFRAME (XCAR (frames));
690   frames = XCDR (frames);
691   width = FRAME_PIXEL_WIDTH (f);
692   height = FRAME_PIXEL_HEIGHT (f);
693 
694   block_input ();
695 #ifdef CAIRO_HAS_PDF_SURFACE
696   if (surface_type == CAIRO_SURFACE_TYPE_PDF)
697     {
698       surface = cairo_pdf_surface_create_for_stream (x_cr_accumulate_data, &acc,
699 						     width, height);
700       surface_set_size_func = cairo_pdf_surface_set_size;
701     }
702   else
703 #endif
704 #ifdef CAIRO_HAS_PNG_FUNCTIONS
705   if (surface_type == CAIRO_SURFACE_TYPE_IMAGE)
706     surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height);
707   else
708 #endif
709 #ifdef CAIRO_HAS_PS_SURFACE
710   if (surface_type == CAIRO_SURFACE_TYPE_PS)
711     {
712       surface = cairo_ps_surface_create_for_stream (x_cr_accumulate_data, &acc,
713 						    width, height);
714       surface_set_size_func = cairo_ps_surface_set_size;
715     }
716   else
717 #endif
718 #ifdef CAIRO_HAS_SVG_SURFACE
719   if (surface_type == CAIRO_SURFACE_TYPE_SVG)
720     surface = cairo_svg_surface_create_for_stream (x_cr_accumulate_data, &acc,
721 						   width, height);
722   else
723 #endif
724     abort ();
725 
726   cr = cairo_create (surface);
727   cairo_surface_destroy (surface);
728   record_unwind_protect_ptr (x_cr_destroy, cr);
729 
730   while (1)
731     {
732       cairo_t *saved_cr = FRAME_CR_CONTEXT (f);
733       FRAME_CR_CONTEXT (f) = cr;
734       x_clear_area (f, 0, 0, width, height);
735       expose_frame (f, 0, 0, width, height);
736       FRAME_CR_CONTEXT (f) = saved_cr;
737 
738       if (NILP (frames))
739 	break;
740 
741       cairo_surface_show_page (surface);
742       f = XFRAME (XCAR (frames));
743       frames = XCDR (frames);
744       width = FRAME_PIXEL_WIDTH (f);
745       height = FRAME_PIXEL_HEIGHT (f);
746       if (surface_set_size_func)
747 	(*surface_set_size_func) (surface, width, height);
748 
749       unblock_input ();
750       maybe_quit ();
751       block_input ();
752     }
753 
754 #ifdef CAIRO_HAS_PNG_FUNCTIONS
755   if (surface_type == CAIRO_SURFACE_TYPE_IMAGE)
756     {
757       cairo_surface_flush (surface);
758       cairo_surface_write_to_png_stream (surface, x_cr_accumulate_data, &acc);
759     }
760 #endif
761   unblock_input ();
762 
763   unbind_to (count, Qnil);
764 
765   return CALLN (Fapply, intern ("concat"), Fnreverse (acc));
766 }
767 
768 #endif	/* USE_CAIRO */
769 
770 static void
x_set_clip_rectangles(struct frame * f,GC gc,XRectangle * rectangles,int n)771 x_set_clip_rectangles (struct frame *f, GC gc, XRectangle *rectangles, int n)
772 {
773   XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, rectangles, n, Unsorted);
774 #ifdef USE_CAIRO
775   eassert (n >= 0 && n <= MAX_CLIP_RECTS);
776 
777   {
778     struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 1);
779 
780     gc_ext->n_clip_rects = n;
781     memcpy (gc_ext->clip_rects, rectangles, sizeof (XRectangle) * n);
782   }
783 #endif
784 }
785 
786 static void
x_reset_clip_rectangles(struct frame * f,GC gc)787 x_reset_clip_rectangles (struct frame *f, GC gc)
788 {
789   XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
790 #ifdef USE_CAIRO
791   {
792     struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 0);
793 
794     if (gc_ext)
795       gc_ext->n_clip_rects = 0;
796   }
797 #endif
798 }
799 
800 static void
x_fill_rectangle(struct frame * f,GC gc,int x,int y,int width,int height)801 x_fill_rectangle (struct frame *f, GC gc, int x, int y, int width, int height)
802 {
803 #ifdef USE_CAIRO
804   Display *dpy = FRAME_X_DISPLAY (f);
805   cairo_t *cr;
806   XGCValues xgcv;
807 
808   cr = x_begin_cr_clip (f, gc);
809   XGetGCValues (dpy, gc, GCFillStyle | GCStipple, &xgcv);
810   if (xgcv.fill_style == FillSolid
811       /* Invalid resource ID (one or more of the three most
812 	 significant bits set to 1) is obtained if the GCStipple
813 	 component has never been explicitly set.  It should be
814 	 regarded as Pixmap of unspecified size filled with ones.  */
815       || (xgcv.stipple & ((Pixmap) 7 << (sizeof (Pixmap) * CHAR_BIT - 3))))
816     {
817       x_set_cr_source_with_gc_foreground (f, gc);
818       cairo_rectangle (cr, x, y, width, height);
819       cairo_fill (cr);
820     }
821   else
822     {
823       eassert (xgcv.fill_style == FillOpaqueStippled);
824       eassert (xgcv.stipple != None);
825       x_set_cr_source_with_gc_background (f, gc);
826       cairo_rectangle (cr, x, y, width, height);
827       cairo_fill_preserve (cr);
828 
829       cairo_pattern_t *pattern = x_bitmap_stipple (f, xgcv.stipple);
830       if (pattern)
831 	{
832 	  x_set_cr_source_with_gc_foreground (f, gc);
833 	  cairo_clip (cr);
834 	  cairo_mask (cr, pattern);
835 	}
836     }
837   x_end_cr_clip (f);
838 #else
839   XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
840 		  gc, x, y, width, height);
841 #endif
842 }
843 
844 static void
x_draw_rectangle(struct frame * f,GC gc,int x,int y,int width,int height)845 x_draw_rectangle (struct frame *f, GC gc, int x, int y, int width, int height)
846 {
847 #ifdef USE_CAIRO
848   cairo_t *cr;
849 
850   cr = x_begin_cr_clip (f, gc);
851   x_set_cr_source_with_gc_foreground (f, gc);
852   cairo_rectangle (cr, x + 0.5, y + 0.5, width, height);
853   cairo_set_line_width (cr, 1);
854   cairo_stroke (cr);
855   x_end_cr_clip (f);
856 #else
857   XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
858 		  gc, x, y, width, height);
859 #endif
860 }
861 
862 static void
x_clear_window(struct frame * f)863 x_clear_window (struct frame *f)
864 {
865 #ifdef USE_CAIRO
866   cairo_t *cr;
867 
868   cr = x_begin_cr_clip (f, NULL);
869   x_set_cr_source_with_gc_background (f, f->output_data.x->normal_gc);
870   cairo_paint (cr);
871   x_end_cr_clip (f);
872 #else
873   if (FRAME_X_DOUBLE_BUFFERED_P (f))
874     x_clear_area (f, 0, 0, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f));
875   else
876     XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
877 #endif
878 }
879 
880 #ifdef USE_CAIRO
881 static void
x_fill_trapezoid_for_relief(struct frame * f,GC gc,int x,int y,int width,int height,int top_p)882 x_fill_trapezoid_for_relief (struct frame *f, GC gc, int x, int y,
883 			     int width, int height, int top_p)
884 {
885   cairo_t *cr;
886 
887   cr = x_begin_cr_clip (f, gc);
888   x_set_cr_source_with_gc_foreground (f, gc);
889   cairo_move_to (cr, top_p ? x : x + height, y);
890   cairo_line_to (cr, x, y + height);
891   cairo_line_to (cr, top_p ? x + width - height : x + width, y + height);
892   cairo_line_to (cr, x + width, y);
893   cairo_fill (cr);
894   x_end_cr_clip (f);
895 }
896 
897 enum corners
898   {
899     CORNER_BOTTOM_RIGHT,	/* 0 -> pi/2 */
900     CORNER_BOTTOM_LEFT,		/* pi/2 -> pi */
901     CORNER_TOP_LEFT,		/* pi -> 3pi/2 */
902     CORNER_TOP_RIGHT,		/* 3pi/2 -> 2pi */
903     CORNER_LAST
904   };
905 
906 static void
x_erase_corners_for_relief(struct frame * f,GC gc,int x,int y,int width,int height,double radius,double margin,int corners)907 x_erase_corners_for_relief (struct frame *f, GC gc, int x, int y,
908 			    int width, int height,
909 			    double radius, double margin, int corners)
910 {
911   cairo_t *cr;
912   int i;
913 
914   cr = x_begin_cr_clip (f, gc);
915   x_set_cr_source_with_gc_background (f, gc);
916   for (i = 0; i < CORNER_LAST; i++)
917     if (corners & (1 << i))
918       {
919 	double xm, ym, xc, yc;
920 
921 	if (i == CORNER_TOP_LEFT || i == CORNER_BOTTOM_LEFT)
922 	  xm = x - margin, xc = xm + radius;
923 	else
924 	  xm = x + width + margin, xc = xm - radius;
925 	if (i == CORNER_TOP_LEFT || i == CORNER_TOP_RIGHT)
926 	  ym = y - margin, yc = ym + radius;
927 	else
928 	  ym = y + height + margin, yc = ym - radius;
929 
930 	cairo_move_to (cr, xm, ym);
931 	cairo_arc (cr, xc, yc, radius, i * M_PI_2, (i + 1) * M_PI_2);
932       }
933   cairo_clip (cr);
934   cairo_rectangle (cr, x, y, width, height);
935   cairo_fill (cr);
936   x_end_cr_clip (f);
937 }
938 
939 static void
x_draw_horizontal_wave(struct frame * f,GC gc,int x,int y,int width,int height,int wave_length)940 x_draw_horizontal_wave (struct frame *f, GC gc, int x, int y,
941 			int width, int height, int wave_length)
942 {
943   cairo_t *cr;
944   double dx = wave_length, dy = height - 1;
945   int xoffset, n;
946 
947   cr = x_begin_cr_clip (f, gc);
948   x_set_cr_source_with_gc_foreground (f, gc);
949   cairo_rectangle (cr, x, y, width, height);
950   cairo_clip (cr);
951 
952   if (x >= 0)
953     {
954       xoffset = x % (wave_length * 2);
955       if (xoffset == 0)
956 	xoffset = wave_length * 2;
957     }
958   else
959     xoffset = x % (wave_length * 2) + wave_length * 2;
960   n = (width + xoffset) / wave_length + 1;
961   if (xoffset > wave_length)
962     {
963       xoffset -= wave_length;
964       --n;
965       y += height - 1;
966       dy = -dy;
967     }
968 
969   cairo_move_to (cr, x - xoffset + 0.5, y + 0.5);
970   while (--n >= 0)
971     {
972       cairo_rel_line_to (cr, dx, dy);
973       dy = -dy;
974     }
975   cairo_set_line_width (cr, 1);
976   cairo_stroke (cr);
977   x_end_cr_clip (f);
978 }
979 #endif
980 
981 
982 /* Return the struct x_display_info corresponding to DPY.  */
983 
984 struct x_display_info *
x_display_info_for_display(Display * dpy)985 x_display_info_for_display (Display *dpy)
986 {
987   struct x_display_info *dpyinfo;
988 
989   for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
990     if (dpyinfo->display == dpy)
991       return dpyinfo;
992 
993   return 0;
994 }
995 
996 static Window
x_find_topmost_parent(struct frame * f)997 x_find_topmost_parent (struct frame *f)
998 {
999   struct x_output *x = f->output_data.x;
1000   Window win = None, wi = x->parent_desc;
1001   Display *dpy = FRAME_X_DISPLAY (f);
1002 
1003   while (wi != FRAME_DISPLAY_INFO (f)->root_window)
1004     {
1005       Window root;
1006       Window *children;
1007       unsigned int nchildren;
1008 
1009       win = wi;
1010       if (XQueryTree (dpy, win, &root, &wi, &children, &nchildren))
1011 	XFree (children);
1012       else
1013 	break;
1014     }
1015 
1016   return win;
1017 }
1018 
1019 #define OPAQUE  0xffffffff
1020 
1021 static void
x_set_frame_alpha(struct frame * f)1022 x_set_frame_alpha (struct frame *f)
1023 {
1024   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
1025   Display *dpy = FRAME_X_DISPLAY (f);
1026   Window win = FRAME_OUTER_WINDOW (f);
1027   double alpha = 1.0;
1028   double alpha_min = 1.0;
1029   unsigned long opac;
1030   Window parent;
1031 
1032   if (dpyinfo->highlight_frame == f)
1033     alpha = f->alpha[0];
1034   else
1035     alpha = f->alpha[1];
1036 
1037   if (alpha < 0.0)
1038     return;
1039 
1040   if (FLOATP (Vframe_alpha_lower_limit))
1041     alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit);
1042   else if (FIXNUMP (Vframe_alpha_lower_limit))
1043     alpha_min = (XFIXNUM (Vframe_alpha_lower_limit)) / 100.0;
1044 
1045   if (alpha > 1.0)
1046     alpha = 1.0;
1047   else if (alpha < alpha_min && alpha_min <= 1.0)
1048     alpha = alpha_min;
1049 
1050   opac = alpha * OPAQUE;
1051 
1052   x_catch_errors (dpy);
1053 
1054   /* If there is a parent from the window manager, put the property there
1055      also, to work around broken window managers that fail to do that.
1056      Do this unconditionally as this function is called on reparent when
1057      alpha has not changed on the frame.  */
1058 
1059   if (!FRAME_PARENT_FRAME (f))
1060     {
1061       parent = x_find_topmost_parent (f);
1062       if (parent != None)
1063 	XChangeProperty (dpy, parent, dpyinfo->Xatom_net_wm_window_opacity,
1064 			 XA_CARDINAL, 32, PropModeReplace,
1065 			 (unsigned char *) &opac, 1);
1066     }
1067 
1068   /* return unless necessary */
1069   {
1070     unsigned char *data;
1071     Atom actual;
1072     int rc, format;
1073     unsigned long n, left;
1074 
1075     rc = XGetWindowProperty (dpy, win, dpyinfo->Xatom_net_wm_window_opacity,
1076 			     0, 1, False, XA_CARDINAL,
1077 			     &actual, &format, &n, &left,
1078 			     &data);
1079 
1080     if (rc == Success && actual != None)
1081       {
1082         unsigned long value = *(unsigned long *)data;
1083 	XFree (data);
1084 	if (value == opac)
1085 	  {
1086 	    x_uncatch_errors ();
1087 	    return;
1088 	  }
1089       }
1090   }
1091 
1092   XChangeProperty (dpy, win, dpyinfo->Xatom_net_wm_window_opacity,
1093 		   XA_CARDINAL, 32, PropModeReplace,
1094 		   (unsigned char *) &opac, 1);
1095   x_uncatch_errors ();
1096 }
1097 
1098 /***********************************************************************
1099 		    Starting and ending an update
1100  ***********************************************************************/
1101 
1102 /* Start an update of frame F.  This function is installed as a hook
1103    for update_begin, i.e. it is called when update_begin is called.
1104    This function is called prior to calls to gui_update_window_begin for
1105    each window being updated.  Currently, there is nothing to do here
1106    because all interesting stuff is done on a window basis.  */
1107 
1108 static void
x_update_begin(struct frame * f)1109 x_update_begin (struct frame *f)
1110 {
1111   /* Nothing to do.  */
1112 }
1113 
1114 /* Draw a vertical window border from (x,y0) to (x,y1)  */
1115 
1116 static void
x_draw_vertical_window_border(struct window * w,int x,int y0,int y1)1117 x_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
1118 {
1119   struct frame *f = XFRAME (WINDOW_FRAME (w));
1120   struct face *face;
1121 
1122   face = FACE_FROM_ID_OR_NULL (f, VERTICAL_BORDER_FACE_ID);
1123   if (face)
1124     XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
1125 		    face->foreground);
1126 
1127 #ifdef USE_CAIRO
1128   x_fill_rectangle (f, f->output_data.x->normal_gc, x, y0, 1, y1 - y0);
1129 #else
1130   XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
1131 	     f->output_data.x->normal_gc, x, y0, x, y1);
1132 #endif
1133 }
1134 
1135 /* Draw a window divider from (x0,y0) to (x1,y1)  */
1136 
1137 static void
x_draw_window_divider(struct window * w,int x0,int x1,int y0,int y1)1138 x_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
1139 {
1140   struct frame *f = XFRAME (WINDOW_FRAME (w));
1141   struct face *face = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FACE_ID);
1142   struct face *face_first
1143     = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID);
1144   struct face *face_last
1145     = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_LAST_PIXEL_FACE_ID);
1146   unsigned long color = face ? face->foreground : FRAME_FOREGROUND_PIXEL (f);
1147   unsigned long color_first = (face_first
1148 			       ? face_first->foreground
1149 			       : FRAME_FOREGROUND_PIXEL (f));
1150   unsigned long color_last = (face_last
1151 			      ? face_last->foreground
1152 			      : FRAME_FOREGROUND_PIXEL (f));
1153   Display *display = FRAME_X_DISPLAY (f);
1154 
1155   if ((y1 - y0 > x1 - x0) && (x1 - x0 >= 3))
1156     /* A vertical divider, at least three pixels wide: Draw first and
1157        last pixels differently.  */
1158     {
1159       XSetForeground (display, f->output_data.x->normal_gc, color_first);
1160       x_fill_rectangle (f, f->output_data.x->normal_gc,
1161 			x0, y0, 1, y1 - y0);
1162       XSetForeground (display, f->output_data.x->normal_gc, color);
1163       x_fill_rectangle (f, f->output_data.x->normal_gc,
1164 			x0 + 1, y0, x1 - x0 - 2, y1 - y0);
1165       XSetForeground (display, f->output_data.x->normal_gc, color_last);
1166       x_fill_rectangle (f, f->output_data.x->normal_gc,
1167 			x1 - 1, y0, 1, y1 - y0);
1168     }
1169   else if ((x1 - x0 > y1 - y0) && (y1 - y0 >= 3))
1170     /* A horizontal divider, at least three pixels high: Draw first and
1171        last pixels differently.  */
1172     {
1173       XSetForeground (display, f->output_data.x->normal_gc, color_first);
1174       x_fill_rectangle (f, f->output_data.x->normal_gc,
1175 			x0, y0, x1 - x0, 1);
1176       XSetForeground (display, f->output_data.x->normal_gc, color);
1177       x_fill_rectangle (f, f->output_data.x->normal_gc,
1178 			x0, y0 + 1, x1 - x0, y1 - y0 - 2);
1179       XSetForeground (display, f->output_data.x->normal_gc, color_last);
1180       x_fill_rectangle (f, f->output_data.x->normal_gc,
1181 			x0, y1 - 1, x1 - x0, 1);
1182     }
1183   else
1184     {
1185     /* In any other case do not draw the first and last pixels
1186        differently.  */
1187       XSetForeground (display, f->output_data.x->normal_gc, color);
1188       x_fill_rectangle (f, f->output_data.x->normal_gc,
1189 			x0, y0, x1 - x0, y1 - y0);
1190     }
1191 }
1192 
1193 /* Show the frame back buffer.  If frame is double-buffered,
1194    atomically publish to the user's screen graphics updates made since
1195    the last call to show_back_buffer.  */
1196 static void
show_back_buffer(struct frame * f)1197 show_back_buffer (struct frame *f)
1198 {
1199   block_input ();
1200   if (FRAME_X_DOUBLE_BUFFERED_P (f))
1201     {
1202 #ifdef HAVE_XDBE
1203 #ifdef USE_CAIRO
1204       cairo_t *cr = FRAME_CR_CONTEXT (f);
1205       if (cr)
1206 	cairo_surface_flush (cairo_get_target (cr));
1207 #endif
1208       XdbeSwapInfo swap_info;
1209       memset (&swap_info, 0, sizeof (swap_info));
1210       swap_info.swap_window = FRAME_X_WINDOW (f);
1211       swap_info.swap_action = XdbeCopied;
1212       XdbeSwapBuffers (FRAME_X_DISPLAY (f), &swap_info, 1);
1213 #else
1214       eassert (!"should have back-buffer only with XDBE");
1215 #endif
1216     }
1217   FRAME_X_NEED_BUFFER_FLIP (f) = false;
1218   unblock_input ();
1219 }
1220 
1221 /* Updates back buffer and flushes changes to display.  Called from
1222    minibuf read code.  Note that we display the back buffer even if
1223    buffer flipping is blocked.  */
1224 static void
x_flip_and_flush(struct frame * f)1225 x_flip_and_flush (struct frame *f)
1226 {
1227   block_input ();
1228   if (FRAME_X_NEED_BUFFER_FLIP (f))
1229       show_back_buffer (f);
1230   x_flush (f);
1231   unblock_input ();
1232 }
1233 
1234 /* End update of frame F.  This function is installed as a hook in
1235    update_end.  */
1236 
1237 static void
x_update_end(struct frame * f)1238 x_update_end (struct frame *f)
1239 {
1240   /* Mouse highlight may be displayed again.  */
1241   MOUSE_HL_INFO (f)->mouse_face_defer = false;
1242 
1243 #ifdef USE_CAIRO
1244   if (!FRAME_X_DOUBLE_BUFFERED_P (f) && FRAME_CR_CONTEXT (f))
1245     {
1246       block_input ();
1247       cairo_surface_flush (cairo_get_target (FRAME_CR_CONTEXT (f)));
1248       unblock_input ();
1249     }
1250 #endif
1251 
1252 #ifndef XFlush
1253   block_input ();
1254   XFlush (FRAME_X_DISPLAY (f));
1255   unblock_input ();
1256 #endif
1257 }
1258 
1259 /* This function is called from various places in xdisp.c
1260    whenever a complete update has been performed.  */
1261 
1262 static void
XTframe_up_to_date(struct frame * f)1263 XTframe_up_to_date (struct frame *f)
1264 {
1265   eassert (FRAME_X_P (f));
1266   block_input ();
1267   FRAME_MOUSE_UPDATE (f);
1268   if (!buffer_flipping_blocked_p () && FRAME_X_NEED_BUFFER_FLIP (f))
1269     show_back_buffer (f);
1270   unblock_input ();
1271 }
1272 
1273 static void
XTbuffer_flipping_unblocked_hook(struct frame * f)1274 XTbuffer_flipping_unblocked_hook (struct frame *f)
1275 {
1276   if (FRAME_X_NEED_BUFFER_FLIP (f))
1277     show_back_buffer (f);
1278 }
1279 
1280 /**
1281  * x_clear_under_internal_border:
1282  *
1283  * Clear area of frame F's internal border.  If the internal border face
1284  * of F has been specified (is not null), fill the area with that face.
1285  */
1286 void
x_clear_under_internal_border(struct frame * f)1287 x_clear_under_internal_border (struct frame *f)
1288 {
1289   if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0)
1290     {
1291       int border = FRAME_INTERNAL_BORDER_WIDTH (f);
1292       int width = FRAME_PIXEL_WIDTH (f);
1293       int height = FRAME_PIXEL_HEIGHT (f);
1294       int margin = FRAME_TOP_MARGIN_HEIGHT (f);
1295       int face_id =
1296 	!NILP (Vface_remapping_alist)
1297 	? lookup_basic_face (NULL, f, INTERNAL_BORDER_FACE_ID)
1298 	: INTERNAL_BORDER_FACE_ID;
1299       struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
1300 
1301       block_input ();
1302 
1303       if (face)
1304 	{
1305 	  unsigned long color = face->background;
1306 	  Display *display = FRAME_X_DISPLAY (f);
1307 	  GC gc = f->output_data.x->normal_gc;
1308 
1309 	  XSetForeground (display, gc, color);
1310 	  x_fill_rectangle (f, gc, 0, margin, width, border);
1311 	  x_fill_rectangle (f, gc, 0, 0, border, height);
1312 	  x_fill_rectangle (f, gc, width - border, 0, border, height);
1313 	  x_fill_rectangle (f, gc, 0, height - border, width, border);
1314 	  XSetForeground (display, gc, FRAME_FOREGROUND_PIXEL (f));
1315 	}
1316       else
1317 	{
1318 	  x_clear_area (f, 0, 0, border, height);
1319 	  x_clear_area (f, 0, margin, width, border);
1320 	  x_clear_area (f, width - border, 0, border, height);
1321 	  x_clear_area (f, 0, height - border, width, border);
1322 	}
1323 
1324       unblock_input ();
1325     }
1326 }
1327 
1328 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1329    arrow bitmaps, or clear the fringes if no bitmaps are required
1330    before DESIRED_ROW is made current.  This function is called from
1331    update_window_line only if it is known that there are differences
1332    between bitmaps to be drawn between current row and DESIRED_ROW.  */
1333 
1334 static void
x_after_update_window_line(struct window * w,struct glyph_row * desired_row)1335 x_after_update_window_line (struct window *w, struct glyph_row *desired_row)
1336 {
1337   eassert (w);
1338 
1339   if (!desired_row->mode_line_p && !w->pseudo_window_p)
1340     desired_row->redraw_fringe_bitmaps_p = true;
1341 
1342 #ifdef USE_X_TOOLKIT
1343   /* When a window has disappeared, make sure that no rest of
1344      full-width rows stays visible in the internal border.  Could
1345      check here if updated window is the leftmost/rightmost window,
1346      but I guess it's not worth doing since vertically split windows
1347      are almost never used, internal border is rarely set, and the
1348      overhead is very small.  */
1349   {
1350     struct frame *f;
1351     int width, height;
1352 
1353     if (windows_or_buffers_changed
1354 	&& desired_row->full_width_p
1355 	&& (f = XFRAME (w->frame),
1356 	    width = FRAME_INTERNAL_BORDER_WIDTH (f),
1357 	    width != 0)
1358 	&& (height = desired_row->visible_height,
1359 	    height > 0))
1360       {
1361 	int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
1362 	int face_id =
1363 	  !NILP (Vface_remapping_alist)
1364 	  ? lookup_basic_face (NULL, f, INTERNAL_BORDER_FACE_ID)
1365 	  : INTERNAL_BORDER_FACE_ID;
1366 	struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
1367 
1368 	block_input ();
1369 	if (face)
1370 	  {
1371 	    unsigned long color = face->background;
1372 	    Display *display = FRAME_X_DISPLAY (f);
1373 	    GC gc = f->output_data.x->normal_gc;
1374 
1375 	    XSetForeground (display, gc, color);
1376 	    x_fill_rectangle (f, gc, 0, y, width, height);
1377 	    x_fill_rectangle (f, gc, FRAME_PIXEL_WIDTH (f) - width, y,
1378 			      width, height);
1379 	    XSetForeground (display, gc, FRAME_FOREGROUND_PIXEL (f));
1380 	  }
1381 	else
1382 	  {
1383 	    x_clear_area (f, 0, y, width, height);
1384 	    x_clear_area (f, FRAME_PIXEL_WIDTH (f) - width, y, width, height);
1385 	  }
1386 	unblock_input ();
1387       }
1388   }
1389 #endif
1390 }
1391 
1392 static void
x_draw_fringe_bitmap(struct window * w,struct glyph_row * row,struct draw_fringe_bitmap_params * p)1393 x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fringe_bitmap_params *p)
1394 {
1395   struct frame *f = XFRAME (WINDOW_FRAME (w));
1396   Display *display = FRAME_X_DISPLAY (f);
1397   GC gc = f->output_data.x->normal_gc;
1398   struct face *face = p->face;
1399 
1400   /* Must clip because of partially visible lines.  */
1401   x_clip_to_row (w, row, ANY_AREA, gc);
1402 
1403   if (p->bx >= 0 && !p->overlay_p)
1404     {
1405       /* In case the same realized face is used for fringes and
1406 	 for something displayed in the text (e.g. face `region' on
1407 	 mono-displays, the fill style may have been changed to
1408 	 FillSolid in x_draw_glyph_string_background.  */
1409       if (face->stipple)
1410 	XSetFillStyle (display, face->gc, FillOpaqueStippled);
1411       else
1412 	XSetForeground (display, face->gc, face->background);
1413 
1414       x_fill_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny);
1415 
1416       if (!face->stipple)
1417 	XSetForeground (display, face->gc, face->foreground);
1418     }
1419 
1420 #ifdef USE_CAIRO
1421   if (p->which && p->which < max_fringe_bmp)
1422     {
1423       XGCValues gcv;
1424 
1425       XGetGCValues (display, gc, GCForeground | GCBackground, &gcv);
1426       XSetForeground (display, gc, (p->cursor_p
1427 				    ? (p->overlay_p ? face->background
1428 				       : f->output_data.x->cursor_pixel)
1429 				    : face->foreground));
1430       XSetBackground (display, gc, face->background);
1431       x_cr_draw_image (f, gc, fringe_bmp[p->which], 0, p->dh,
1432 		       p->wd, p->h, p->x, p->y, p->overlay_p);
1433       XSetForeground (display, gc, gcv.foreground);
1434       XSetBackground (display, gc, gcv.background);
1435     }
1436 #else  /* not USE_CAIRO */
1437   if (p->which)
1438     {
1439       Drawable drawable = FRAME_X_DRAWABLE (f);
1440       char *bits;
1441       Pixmap pixmap, clipmask = (Pixmap) 0;
1442       int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
1443       XGCValues gcv;
1444 
1445       if (p->wd > 8)
1446 	bits = (char *) (p->bits + p->dh);
1447       else
1448 	bits = (char *) p->bits + p->dh;
1449 
1450       /* Draw the bitmap.  I believe these small pixmaps can be cached
1451 	 by the server.  */
1452       pixmap = XCreatePixmapFromBitmapData (display, drawable, bits, p->wd, p->h,
1453 					    (p->cursor_p
1454 					     ? (p->overlay_p ? face->background
1455 						: f->output_data.x->cursor_pixel)
1456 					     : face->foreground),
1457 					    face->background, depth);
1458 
1459       if (p->overlay_p)
1460 	{
1461 	  clipmask = XCreatePixmapFromBitmapData (display,
1462 						  FRAME_DISPLAY_INFO (f)->root_window,
1463 						  bits, p->wd, p->h,
1464 						  1, 0, 1);
1465 	  gcv.clip_mask = clipmask;
1466 	  gcv.clip_x_origin = p->x;
1467 	  gcv.clip_y_origin = p->y;
1468 	  XChangeGC (display, gc, GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv);
1469 	}
1470 
1471       XCopyArea (display, pixmap, drawable, gc, 0, 0,
1472 		 p->wd, p->h, p->x, p->y);
1473       XFreePixmap (display, pixmap);
1474 
1475       if (p->overlay_p)
1476 	{
1477 	  gcv.clip_mask = (Pixmap) 0;
1478 	  XChangeGC (display, gc, GCClipMask, &gcv);
1479 	  XFreePixmap (display, clipmask);
1480 	}
1481     }
1482 #endif  /* not USE_CAIRO */
1483 
1484   x_reset_clip_rectangles (f, gc);
1485 }
1486 
1487 /***********************************************************************
1488 			    Glyph display
1489  ***********************************************************************/
1490 
1491 static bool x_alloc_lighter_color (struct frame *, Display *, Colormap,
1492 				   unsigned long *, double, int);
1493 static void x_scroll_bar_clear (struct frame *);
1494 
1495 #ifdef GLYPH_DEBUG
1496 static void x_check_font (struct frame *, struct font *);
1497 #endif
1498 
1499 
1500 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1501    face.  */
1502 
1503 static void
x_set_cursor_gc(struct glyph_string * s)1504 x_set_cursor_gc (struct glyph_string *s)
1505 {
1506   if (s->font == FRAME_FONT (s->f)
1507       && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
1508       && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
1509       && !s->cmp)
1510     s->gc = s->f->output_data.x->cursor_gc;
1511   else
1512     {
1513       /* Cursor on non-default face: must merge.  */
1514       XGCValues xgcv;
1515       unsigned long mask;
1516       Display *display = FRAME_X_DISPLAY (s->f);
1517 
1518       xgcv.background = s->f->output_data.x->cursor_pixel;
1519       xgcv.foreground = s->face->background;
1520 
1521       /* If the glyph would be invisible, try a different foreground.  */
1522       if (xgcv.foreground == xgcv.background)
1523 	xgcv.foreground = s->face->foreground;
1524       if (xgcv.foreground == xgcv.background)
1525 	xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
1526       if (xgcv.foreground == xgcv.background)
1527 	xgcv.foreground = s->face->foreground;
1528 
1529       /* Make sure the cursor is distinct from text in this face.  */
1530       if (xgcv.background == s->face->background
1531 	  && xgcv.foreground == s->face->foreground)
1532 	{
1533 	  xgcv.background = s->face->foreground;
1534 	  xgcv.foreground = s->face->background;
1535 	}
1536 
1537       IF_DEBUG (x_check_font (s->f, s->font));
1538       xgcv.graphics_exposures = False;
1539       mask = GCForeground | GCBackground | GCGraphicsExposures;
1540 
1541       if (FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1542 	XChangeGC (display, FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1543 		   mask, &xgcv);
1544       else
1545 	FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc
1546           = XCreateGC (display, FRAME_X_DRAWABLE (s->f), mask, &xgcv);
1547 
1548       s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1549     }
1550 }
1551 
1552 
1553 /* Set up S->gc of glyph string S for drawing text in mouse face.  */
1554 
1555 static void
x_set_mouse_face_gc(struct glyph_string * s)1556 x_set_mouse_face_gc (struct glyph_string *s)
1557 {
1558   int face_id;
1559   struct face *face;
1560 
1561   /* What face has to be used last for the mouse face?  */
1562   face_id = MOUSE_HL_INFO (s->f)->mouse_face_face_id;
1563   face = FACE_FROM_ID_OR_NULL (s->f, face_id);
1564   if (face == NULL)
1565     face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
1566 
1567   if (s->first_glyph->type == CHAR_GLYPH)
1568     face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch, -1, Qnil);
1569   else
1570     face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil);
1571   s->face = FACE_FROM_ID (s->f, face_id);
1572   prepare_face_for_display (s->f, s->face);
1573 
1574   if (s->font == s->face->font)
1575     s->gc = s->face->gc;
1576   else
1577     {
1578       /* Otherwise construct scratch_cursor_gc with values from FACE
1579 	 except for FONT.  */
1580       XGCValues xgcv;
1581       unsigned long mask;
1582       Display *display = FRAME_X_DISPLAY (s->f);
1583 
1584       xgcv.background = s->face->background;
1585       xgcv.foreground = s->face->foreground;
1586       xgcv.graphics_exposures = False;
1587       mask = GCForeground | GCBackground | GCGraphicsExposures;
1588 
1589       if (FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1590 	XChangeGC (display, FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1591 		   mask, &xgcv);
1592       else
1593 	FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc
1594           = XCreateGC (display, FRAME_X_DRAWABLE (s->f), mask, &xgcv);
1595 
1596       s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1597 
1598     }
1599   eassert (s->gc != 0);
1600 }
1601 
1602 
1603 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1604    Faces to use in the mode line have already been computed when the
1605    matrix was built, so there isn't much to do, here.  */
1606 
1607 static void
x_set_mode_line_face_gc(struct glyph_string * s)1608 x_set_mode_line_face_gc (struct glyph_string *s)
1609 {
1610   s->gc = s->face->gc;
1611 }
1612 
1613 
1614 /* Set S->gc of glyph string S for drawing that glyph string.  Set
1615    S->stippled_p to a non-zero value if the face of S has a stipple
1616    pattern.  */
1617 
1618 static void
x_set_glyph_string_gc(struct glyph_string * s)1619 x_set_glyph_string_gc (struct glyph_string *s)
1620 {
1621   prepare_face_for_display (s->f, s->face);
1622 
1623   if (s->hl == DRAW_NORMAL_TEXT)
1624     {
1625       s->gc = s->face->gc;
1626       s->stippled_p = s->face->stipple != 0;
1627     }
1628   else if (s->hl == DRAW_INVERSE_VIDEO)
1629     {
1630       x_set_mode_line_face_gc (s);
1631       s->stippled_p = s->face->stipple != 0;
1632     }
1633   else if (s->hl == DRAW_CURSOR)
1634     {
1635       x_set_cursor_gc (s);
1636       s->stippled_p = false;
1637     }
1638   else if (s->hl == DRAW_MOUSE_FACE)
1639     {
1640       x_set_mouse_face_gc (s);
1641       s->stippled_p = s->face->stipple != 0;
1642     }
1643   else if (s->hl == DRAW_IMAGE_RAISED
1644 	   || s->hl == DRAW_IMAGE_SUNKEN)
1645     {
1646       s->gc = s->face->gc;
1647       s->stippled_p = s->face->stipple != 0;
1648     }
1649   else
1650     emacs_abort ();
1651 
1652   /* GC must have been set.  */
1653   eassert (s->gc != 0);
1654 }
1655 
1656 
1657 /* Set clipping for output of glyph string S.  S may be part of a mode
1658    line or menu if we don't have X toolkit support.  */
1659 
1660 static void
x_set_glyph_string_clipping(struct glyph_string * s)1661 x_set_glyph_string_clipping (struct glyph_string *s)
1662 {
1663   XRectangle *r = s->clip;
1664   int n = get_glyph_string_clip_rects (s, r, 2);
1665 
1666   if (n > 0)
1667     x_set_clip_rectangles (s->f, s->gc, r, n);
1668   s->num_clips = n;
1669 }
1670 
1671 
1672 /* Set SRC's clipping for output of glyph string DST.  This is called
1673    when we are drawing DST's left_overhang or right_overhang only in
1674    the area of SRC.  */
1675 
1676 static void
x_set_glyph_string_clipping_exactly(struct glyph_string * src,struct glyph_string * dst)1677 x_set_glyph_string_clipping_exactly (struct glyph_string *src, struct glyph_string *dst)
1678 {
1679   XRectangle r;
1680 
1681   r.x = src->x;
1682   r.width = src->width;
1683   r.y = src->y;
1684   r.height = src->height;
1685   dst->clip[0] = r;
1686   dst->num_clips = 1;
1687   x_set_clip_rectangles (dst->f, dst->gc, &r, 1);
1688 }
1689 
1690 
1691 /* RIF:
1692    Compute left and right overhang of glyph string S.  */
1693 
1694 static void
x_compute_glyph_string_overhangs(struct glyph_string * s)1695 x_compute_glyph_string_overhangs (struct glyph_string *s)
1696 {
1697   if (s->cmp == NULL
1698       && (s->first_glyph->type == CHAR_GLYPH
1699 	  || s->first_glyph->type == COMPOSITE_GLYPH))
1700     {
1701       struct font_metrics metrics;
1702 
1703       if (s->first_glyph->type == CHAR_GLYPH)
1704 	{
1705 	  struct font *font = s->font;
1706 	  font->driver->text_extents (font, s->char2b, s->nchars, &metrics);
1707 	}
1708       else
1709 	{
1710 	  Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
1711 
1712 	  composition_gstring_width (gstring, s->cmp_from, s->cmp_to, &metrics);
1713 	}
1714       s->right_overhang = (metrics.rbearing > metrics.width
1715 			   ? metrics.rbearing - metrics.width : 0);
1716       s->left_overhang = metrics.lbearing < 0 ? - metrics.lbearing : 0;
1717     }
1718   else if (s->cmp)
1719     {
1720       s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width;
1721       s->left_overhang = - s->cmp->lbearing;
1722     }
1723 }
1724 
1725 
1726 /* Fill rectangle X, Y, W, H with background color of glyph string S.  */
1727 
1728 static void
x_clear_glyph_string_rect(struct glyph_string * s,int x,int y,int w,int h)1729 x_clear_glyph_string_rect (struct glyph_string *s, int x, int y, int w, int h)
1730 {
1731   Display *display = FRAME_X_DISPLAY (s->f);
1732   XGCValues xgcv;
1733   XGetGCValues (display, s->gc, GCForeground | GCBackground, &xgcv);
1734   XSetForeground (display, s->gc, xgcv.background);
1735   x_fill_rectangle (s->f, s->gc, x, y, w, h);
1736   XSetForeground (display, s->gc, xgcv.foreground);
1737 }
1738 
1739 
1740 /* Draw the background of glyph_string S.  If S->background_filled_p
1741    is non-zero don't draw it.  FORCE_P non-zero means draw the
1742    background even if it wouldn't be drawn normally.  This is used
1743    when a string preceding S draws into the background of S, or S
1744    contains the first component of a composition.  */
1745 
1746 static void
x_draw_glyph_string_background(struct glyph_string * s,bool force_p)1747 x_draw_glyph_string_background (struct glyph_string *s, bool force_p)
1748 {
1749   /* Nothing to do if background has already been drawn or if it
1750      shouldn't be drawn in the first place.  */
1751   if (!s->background_filled_p)
1752     {
1753       int box_line_width = max (s->face->box_line_width, 0);
1754 
1755       if (s->stippled_p)
1756 	{
1757           Display *display = FRAME_X_DISPLAY (s->f);
1758 
1759 	  /* Fill background with a stipple pattern.  */
1760 	  XSetFillStyle (display, s->gc, FillOpaqueStippled);
1761 	  x_fill_rectangle (s->f, s->gc, s->x,
1762 			  s->y + box_line_width,
1763 			  s->background_width,
1764 			  s->height - 2 * box_line_width);
1765 	  XSetFillStyle (display, s->gc, FillSolid);
1766 	  s->background_filled_p = true;
1767 	}
1768       else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
1769 	       /* When xdisp.c ignores FONT_HEIGHT, we cannot trust
1770 		  font dimensions, since the actual glyphs might be
1771 		  much smaller.  So in that case we always clear the
1772 		  rectangle with background color.  */
1773 	       || FONT_TOO_HIGH (s->font)
1774 	       || s->font_not_found_p
1775 	       || s->extends_to_end_of_line_p
1776 	       || force_p)
1777 	{
1778 	  x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
1779 				     s->background_width,
1780 				     s->height - 2 * box_line_width);
1781 	  s->background_filled_p = true;
1782 	}
1783     }
1784 }
1785 
1786 
1787 /* Draw the foreground of glyph string S.  */
1788 
1789 static void
x_draw_glyph_string_foreground(struct glyph_string * s)1790 x_draw_glyph_string_foreground (struct glyph_string *s)
1791 {
1792   int i, x;
1793 
1794   /* If first glyph of S has a left box line, start drawing the text
1795      of S to the right of that box line.  */
1796   if (s->face->box != FACE_NO_BOX
1797       && s->first_glyph->left_box_line_p)
1798     x = s->x + eabs (s->face->box_line_width);
1799   else
1800     x = s->x;
1801 
1802   /* Draw characters of S as rectangles if S's font could not be
1803      loaded.  */
1804   if (s->font_not_found_p)
1805     {
1806       for (i = 0; i < s->nchars; ++i)
1807 	{
1808 	  struct glyph *g = s->first_glyph + i;
1809 	  x_draw_rectangle (s->f,
1810 			  s->gc, x, s->y, g->pixel_width - 1,
1811 			  s->height - 1);
1812 	  x += g->pixel_width;
1813 	}
1814     }
1815   else
1816     {
1817       struct font *font = s->font;
1818 #ifdef USE_CAIRO
1819       if (!EQ (font->driver->type, Qx)
1820 	  || x_try_cr_xlib_drawable (s->f, s->gc))
1821 	{
1822 #endif	/* USE_CAIRO */
1823 	  int boff = font->baseline_offset;
1824 	  int y;
1825 
1826 	  if (font->vertical_centering)
1827 	    boff = VCENTER_BASELINE_OFFSET (font, s->f) - boff;
1828 
1829 	  y = s->ybase - boff;
1830 	  if (s->for_overlaps
1831 	      || (s->background_filled_p && s->hl != DRAW_CURSOR))
1832 	    font->driver->draw (s, 0, s->nchars, x, y, false);
1833 	  else
1834 	    font->driver->draw (s, 0, s->nchars, x, y, true);
1835 	  if (s->face->overstrike)
1836 	    font->driver->draw (s, 0, s->nchars, x + 1, y, false);
1837 #ifdef USE_CAIRO
1838 	  if (EQ (font->driver->type, Qx))
1839 	    x_end_cr_xlib_drawable (s->f, s->gc);
1840 	}
1841       else
1842 	{
1843 	  /* Fallback for the case that no Xlib Drawable is available
1844 	     for drawing text with X core fonts.  */
1845 	  if (!(s->for_overlaps
1846 		|| (s->background_filled_p && s->hl != DRAW_CURSOR)))
1847 	    {
1848 	      int box_line_width = max (s->face->box_line_width, 0);
1849 
1850 	      if (s->stippled_p)
1851 		{
1852 		  Display *display = FRAME_X_DISPLAY (s->f);
1853 
1854 		  /* Fill background with a stipple pattern.  */
1855 		  XSetFillStyle (display, s->gc, FillOpaqueStippled);
1856 		  x_fill_rectangle (s->f, s->gc, s->x,
1857 				    s->y + box_line_width,
1858 				    s->background_width,
1859 				    s->height - 2 * box_line_width);
1860 		  XSetFillStyle (display, s->gc, FillSolid);
1861 		}
1862 	      else
1863 		x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
1864 					   s->background_width,
1865 					   s->height - 2 * box_line_width);
1866 	    }
1867 	  for (i = 0; i < s->nchars; ++i)
1868 	    {
1869 	      struct glyph *g = s->first_glyph + i;
1870 	      x_draw_rectangle (s->f,
1871 				s->gc, x, s->y, g->pixel_width - 1,
1872 				s->height - 1);
1873 	      x += g->pixel_width;
1874 	    }
1875 	}
1876 #endif	/* USE_CAIRO */
1877     }
1878 }
1879 
1880 /* Draw the foreground of composite glyph string S.  */
1881 
1882 static void
x_draw_composite_glyph_string_foreground(struct glyph_string * s)1883 x_draw_composite_glyph_string_foreground (struct glyph_string *s)
1884 {
1885   int i, j, x;
1886   struct font *font = s->font;
1887 
1888   /* If first glyph of S has a left box line, start drawing the text
1889      of S to the right of that box line.  */
1890   if (s->face && s->face->box != FACE_NO_BOX
1891       && s->first_glyph->left_box_line_p)
1892     x = s->x + eabs (s->face->box_line_width);
1893   else
1894     x = s->x;
1895 
1896   /* S is a glyph string for a composition.  S->cmp_from is the index
1897      of the first character drawn for glyphs of this composition.
1898      S->cmp_from == 0 means we are drawing the very first character of
1899      this composition.  */
1900 
1901   /* Draw a rectangle for the composition if the font for the very
1902      first character of the composition could not be loaded.  */
1903   if (s->font_not_found_p)
1904     {
1905       if (s->cmp_from == 0)
1906 	x_draw_rectangle (s->f, s->gc, x, s->y,
1907 			s->width - 1, s->height - 1);
1908     }
1909   else
1910 #ifdef USE_CAIRO
1911     if (!EQ (font->driver->type, Qx)
1912 	|| x_try_cr_xlib_drawable (s->f, s->gc))
1913       {
1914 #endif	/* USE_CAIRO */
1915 	if (! s->first_glyph->u.cmp.automatic)
1916 	  {
1917 	    int y = s->ybase;
1918 
1919 	    for (i = 0, j = s->cmp_from; i < s->nchars; i++, j++)
1920 	      /* TAB in a composition means display glyphs with
1921 		 padding space on the left or right.  */
1922 	      if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
1923 		{
1924 		  int xx = x + s->cmp->offsets[j * 2];
1925 		  int yy = y - s->cmp->offsets[j * 2 + 1];
1926 
1927 		  font->driver->draw (s, j, j + 1, xx, yy, false);
1928 		  if (s->face->overstrike)
1929 		    font->driver->draw (s, j, j + 1, xx + 1, yy, false);
1930 		}
1931 	  }
1932 	else
1933 	  {
1934 	    Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
1935 	    Lisp_Object glyph;
1936 	    int y = s->ybase;
1937 	    int width = 0;
1938 
1939 	    for (i = j = s->cmp_from; i < s->cmp_to; i++)
1940 	      {
1941 		glyph = LGSTRING_GLYPH (gstring, i);
1942 		if (NILP (LGLYPH_ADJUSTMENT (glyph)))
1943 		  width += LGLYPH_WIDTH (glyph);
1944 		else
1945 		  {
1946 		    int xoff, yoff, wadjust;
1947 
1948 		    if (j < i)
1949 		      {
1950 			font->driver->draw (s, j, i, x, y, false);
1951 			if (s->face->overstrike)
1952 			  font->driver->draw (s, j, i, x + 1, y, false);
1953 			x += width;
1954 		      }
1955 		    xoff = LGLYPH_XOFF (glyph);
1956 		    yoff = LGLYPH_YOFF (glyph);
1957 		    wadjust = LGLYPH_WADJUST (glyph);
1958 		    font->driver->draw (s, i, i + 1, x + xoff, y + yoff, false);
1959 		    if (s->face->overstrike)
1960 		      font->driver->draw (s, i, i + 1, x + xoff + 1, y + yoff,
1961 					  false);
1962 		    x += wadjust;
1963 		    j = i + 1;
1964 		    width = 0;
1965 		  }
1966 	      }
1967 	    if (j < i)
1968 	      {
1969 		font->driver->draw (s, j, i, x, y, false);
1970 		if (s->face->overstrike)
1971 		  font->driver->draw (s, j, i, x + 1, y, false);
1972 	      }
1973 	  }
1974 #ifdef USE_CAIRO
1975 	if (EQ (font->driver->type, Qx))
1976 	  x_end_cr_xlib_drawable (s->f, s->gc);
1977       }
1978     else
1979       {
1980 	/* Fallback for the case that no Xlib Drawable is available
1981 	   for drawing text with X core fonts.  */
1982 	if (s->cmp_from == 0)
1983 	  x_draw_rectangle (s->f, s->gc, x, s->y,
1984 			    s->width - 1, s->height - 1);
1985       }
1986 #endif	/* USE_CAIRO */
1987 }
1988 
1989 
1990 /* Draw the foreground of glyph string S for glyphless characters.  */
1991 
1992 static void
x_draw_glyphless_glyph_string_foreground(struct glyph_string * s)1993 x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
1994 {
1995   struct glyph *glyph = s->first_glyph;
1996   unsigned char2b[8];
1997   int x, i, j;
1998 
1999   /* If first glyph of S has a left box line, start drawing the text
2000      of S to the right of that box line.  */
2001   if (s->face && s->face->box != FACE_NO_BOX
2002       && s->first_glyph->left_box_line_p)
2003     x = s->x + eabs (s->face->box_line_width);
2004   else
2005     x = s->x;
2006 
2007   s->char2b = char2b;
2008 
2009   for (i = 0; i < s->nchars; i++, glyph++)
2010     {
2011 #ifdef GCC_LINT
2012       enum { PACIFY_GCC_BUG_81401 = 1 };
2013 #else
2014       enum { PACIFY_GCC_BUG_81401 = 0 };
2015 #endif
2016       char buf[7 + PACIFY_GCC_BUG_81401];
2017       char *str = NULL;
2018       int len = glyph->u.glyphless.len;
2019 
2020       if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM)
2021 	{
2022 	  if (len > 0
2023 	      && CHAR_TABLE_P (Vglyphless_char_display)
2024 	      && (CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display))
2025 		  >= 1))
2026 	    {
2027 	      Lisp_Object acronym
2028 		= (! glyph->u.glyphless.for_no_font
2029 		   ? CHAR_TABLE_REF (Vglyphless_char_display,
2030 				     glyph->u.glyphless.ch)
2031 		   : XCHAR_TABLE (Vglyphless_char_display)->extras[0]);
2032 	      if (STRINGP (acronym))
2033 		str = SSDATA (acronym);
2034 	    }
2035 	}
2036       else if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE)
2037 	{
2038 	  unsigned int ch = glyph->u.glyphless.ch;
2039 	  eassume (ch <= MAX_CHAR);
2040 	  sprintf (buf, "%0*X", ch < 0x10000 ? 4 : 6, ch);
2041 	  str = buf;
2042 	}
2043 
2044       if (str)
2045 	{
2046 	  int upper_len = (len + 1) / 2;
2047 
2048 	  /* It is assured that all LEN characters in STR is ASCII.  */
2049 	  for (j = 0; j < len; j++)
2050             char2b[j] = s->font->driver->encode_char (s->font, str[j]) & 0xFFFF;
2051 	  s->font->driver->draw (s, 0, upper_len,
2052 				 x + glyph->slice.glyphless.upper_xoff,
2053 				 s->ybase + glyph->slice.glyphless.upper_yoff,
2054 				 false);
2055 	  s->font->driver->draw (s, upper_len, len,
2056 				 x + glyph->slice.glyphless.lower_xoff,
2057 				 s->ybase + glyph->slice.glyphless.lower_yoff,
2058 				 false);
2059 	}
2060       if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE)
2061 	x_draw_rectangle (s->f, s->gc,
2062 			x, s->ybase - glyph->ascent,
2063 			glyph->pixel_width - 1,
2064 			glyph->ascent + glyph->descent - 1);
2065       x += glyph->pixel_width;
2066    }
2067 }
2068 
2069 #ifdef USE_X_TOOLKIT
2070 
2071 #ifdef USE_LUCID
2072 
2073 /* Return the frame on which widget WIDGET is used.. Abort if frame
2074    cannot be determined.  */
2075 
2076 static struct frame *
x_frame_of_widget(Widget widget)2077 x_frame_of_widget (Widget widget)
2078 {
2079   struct x_display_info *dpyinfo;
2080   Lisp_Object tail, frame;
2081   struct frame *f;
2082 
2083   dpyinfo = x_display_info_for_display (XtDisplay (widget));
2084 
2085   /* Find the top-level shell of the widget.  Note that this function
2086      can be called when the widget is not yet realized, so XtWindow
2087      (widget) == 0.  That's the reason we can't simply use
2088      x_any_window_to_frame.  */
2089   while (!XtIsTopLevelShell (widget))
2090     widget = XtParent (widget);
2091 
2092   /* Look for a frame with that top-level widget.  Allocate the color
2093      on that frame to get the right gamma correction value.  */
2094   FOR_EACH_FRAME (tail, frame)
2095     {
2096       f = XFRAME (frame);
2097       if (FRAME_X_P (f)
2098 	  && FRAME_DISPLAY_INFO (f) == dpyinfo
2099 	  && f->output_data.x->widget == widget)
2100 	return f;
2101     }
2102   emacs_abort ();
2103 }
2104 
2105 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
2106    or DELTA.  Try a color with RGB values multiplied by FACTOR first.
2107    If this produces the same color as PIXEL, try a color where all RGB
2108    values have DELTA added.  Return the allocated color in *PIXEL.
2109    DISPLAY is the X display, CMAP is the colormap to operate on.
2110    Value is true if successful.  */
2111 
2112 bool
x_alloc_lighter_color_for_widget(Widget widget,Display * display,Colormap cmap,unsigned long * pixel,double factor,int delta)2113 x_alloc_lighter_color_for_widget (Widget widget, Display *display, Colormap cmap,
2114 				  unsigned long *pixel, double factor, int delta)
2115 {
2116   struct frame *f = x_frame_of_widget (widget);
2117   return x_alloc_lighter_color (f, display, cmap, pixel, factor, delta);
2118 }
2119 
2120 #endif /* USE_LUCID */
2121 
2122 
2123 /* Structure specifying which arguments should be passed by Xt to
2124    cvt_string_to_pixel.  We want the widget's screen and colormap.  */
2125 
2126 static XtConvertArgRec cvt_string_to_pixel_args[] =
2127   {
2128     {XtWidgetBaseOffset, (XtPointer) offsetof (WidgetRec, core.screen),
2129      sizeof (Screen *)},
2130     {XtWidgetBaseOffset, (XtPointer) offsetof (WidgetRec, core.colormap),
2131      sizeof (Colormap)}
2132   };
2133 
2134 
2135 /* The address of this variable is returned by
2136    cvt_string_to_pixel.  */
2137 
2138 static Pixel cvt_string_to_pixel_value;
2139 
2140 
2141 /* Convert a color name to a pixel color.
2142 
2143    DPY is the display we are working on.
2144 
2145    ARGS is an array of *NARGS XrmValue structures holding additional
2146    information about the widget for which the conversion takes place.
2147    The contents of this array are determined by the specification
2148    in cvt_string_to_pixel_args.
2149 
2150    FROM is a pointer to an XrmValue which points to the color name to
2151    convert.  TO is an XrmValue in which to return the pixel color.
2152 
2153    CLOSURE_RET is a pointer to user-data, in which we record if
2154    we allocated the color or not.
2155 
2156    Value is True if successful, False otherwise.  */
2157 
2158 static Boolean
cvt_string_to_pixel(Display * dpy,XrmValue * args,Cardinal * nargs,XrmValue * from,XrmValue * to,XtPointer * closure_ret)2159 cvt_string_to_pixel (Display *dpy, XrmValue *args, Cardinal *nargs,
2160 		     XrmValue *from, XrmValue *to,
2161 		     XtPointer *closure_ret)
2162 {
2163   Screen *screen;
2164   Colormap cmap;
2165   Pixel pixel;
2166   String color_name;
2167   XColor color;
2168 
2169   if (*nargs != 2)
2170     {
2171       XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
2172 		       "wrongParameters", "cvt_string_to_pixel",
2173 		       "XtToolkitError",
2174 		       "Screen and colormap args required", NULL, NULL);
2175       return False;
2176     }
2177 
2178   screen = *(Screen **) args[0].addr;
2179   cmap = *(Colormap *) args[1].addr;
2180   color_name = (String) from->addr;
2181 
2182   if (strcmp (color_name, XtDefaultBackground) == 0)
2183     {
2184       *closure_ret = (XtPointer) False;
2185       pixel = WhitePixelOfScreen (screen);
2186     }
2187   else if (strcmp (color_name, XtDefaultForeground) == 0)
2188     {
2189       *closure_ret = (XtPointer) False;
2190       pixel = BlackPixelOfScreen (screen);
2191     }
2192   else if (XParseColor (dpy, cmap, color_name, &color)
2193 	   && x_alloc_nearest_color_1 (dpy, cmap, &color))
2194     {
2195       pixel = color.pixel;
2196       *closure_ret = (XtPointer) True;
2197     }
2198   else
2199     {
2200       String params[1];
2201       Cardinal nparams = 1;
2202 
2203       params[0] = color_name;
2204       XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
2205 		       "badValue", "cvt_string_to_pixel",
2206 		       "XtToolkitError", "Invalid color '%s'",
2207 		       params, &nparams);
2208       return False;
2209     }
2210 
2211   if (to->addr != NULL)
2212     {
2213       if (to->size < sizeof (Pixel))
2214 	{
2215 	  to->size = sizeof (Pixel);
2216 	  return False;
2217 	}
2218 
2219       *(Pixel *) to->addr = pixel;
2220     }
2221   else
2222     {
2223       cvt_string_to_pixel_value = pixel;
2224       to->addr = (XtPointer) &cvt_string_to_pixel_value;
2225     }
2226 
2227   to->size = sizeof (Pixel);
2228   return True;
2229 }
2230 
2231 
2232 /* Free a pixel color which was previously allocated via
2233    cvt_string_to_pixel.  This is registered as the destructor
2234    for this type of resource via XtSetTypeConverter.
2235 
2236    APP is the application context in which we work.
2237 
2238    TO is a pointer to an XrmValue holding the color to free.
2239    CLOSURE is the value we stored in CLOSURE_RET for this color
2240    in cvt_string_to_pixel.
2241 
2242    ARGS and NARGS are like for cvt_string_to_pixel.  */
2243 
2244 static void
cvt_pixel_dtor(XtAppContext app,XrmValuePtr to,XtPointer closure,XrmValuePtr args,Cardinal * nargs)2245 cvt_pixel_dtor (XtAppContext app, XrmValuePtr to, XtPointer closure, XrmValuePtr args,
2246 		Cardinal *nargs)
2247 {
2248   if (*nargs != 2)
2249     {
2250       XtAppWarningMsg (app, "wrongParameters", "cvt_pixel_dtor",
2251 		       "XtToolkitError",
2252 		       "Screen and colormap arguments required",
2253 		       NULL, NULL);
2254     }
2255   else if (closure != NULL)
2256     {
2257       /* We did allocate the pixel, so free it.  */
2258       Screen *screen = *(Screen **) args[0].addr;
2259       Colormap cmap = *(Colormap *) args[1].addr;
2260       x_free_dpy_colors (DisplayOfScreen (screen), screen, cmap,
2261 			 (Pixel *) to->addr, 1);
2262     }
2263 }
2264 
2265 
2266 #endif /* USE_X_TOOLKIT */
2267 
2268 
2269 /* Value is an array of XColor structures for the contents of the
2270    color map of display DPY.  Set *NCELLS to the size of the array.
2271    Note that this probably shouldn't be called for large color maps,
2272    say a 24-bit TrueColor map.  */
2273 
2274 static const XColor *
x_color_cells(Display * dpy,int * ncells)2275 x_color_cells (Display *dpy, int *ncells)
2276 {
2277   struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
2278   eassume (dpyinfo);
2279 
2280   if (dpyinfo->color_cells == NULL)
2281     {
2282       Screen *screen = dpyinfo->screen;
2283       int ncolor_cells = XDisplayCells (dpy, XScreenNumberOfScreen (screen));
2284       int i;
2285 
2286       dpyinfo->color_cells = xnmalloc (ncolor_cells,
2287 				       sizeof *dpyinfo->color_cells);
2288       dpyinfo->ncolor_cells = ncolor_cells;
2289 
2290       for (i = 0; i < ncolor_cells; ++i)
2291 	dpyinfo->color_cells[i].pixel = i;
2292 
2293       XQueryColors (dpy, dpyinfo->cmap,
2294 		    dpyinfo->color_cells, ncolor_cells);
2295     }
2296 
2297   *ncells = dpyinfo->ncolor_cells;
2298   return dpyinfo->color_cells;
2299 }
2300 
2301 
2302 /* On frame F, translate pixel colors to RGB values for the NCOLORS
2303    colors in COLORS.  Use cached information, if available.  */
2304 
2305 void
x_query_colors(struct frame * f,XColor * colors,int ncolors)2306 x_query_colors (struct frame *f, XColor *colors, int ncolors)
2307 {
2308   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
2309 
2310   if (dpyinfo->red_bits > 0)
2311     {
2312       /* For TrueColor displays, we can decompose the RGB value
2313 	 directly.  */
2314       int i;
2315       unsigned int rmult, gmult, bmult;
2316       unsigned int rmask, gmask, bmask;
2317 
2318       rmask = (1 << dpyinfo->red_bits) - 1;
2319       gmask = (1 << dpyinfo->green_bits) - 1;
2320       bmask = (1 << dpyinfo->blue_bits) - 1;
2321       /* If we're widening, for example, 8 bits in the pixel value to
2322 	 16 bits for the separate-color representation, we want to
2323 	 extrapolate the lower bits based on those bits available --
2324 	 in other words, we'd like 0xff to become 0xffff instead of
2325 	 the 0xff00 we'd get by just zero-filling the lower bits.
2326 
2327          We generate a 32-bit scaled-up value and shift it, in case
2328          the bit count doesn't divide 16 evenly (e.g., when dealing
2329          with a 3-3-2 bit RGB display), to get more of the lower bits
2330          correct.
2331 
2332          Should we cache the multipliers in dpyinfo?  Maybe
2333          special-case the 8-8-8 common case?  */
2334       rmult = 0xffffffff / rmask;
2335       gmult = 0xffffffff / gmask;
2336       bmult = 0xffffffff / bmask;
2337 
2338       for (i = 0; i < ncolors; ++i)
2339 	{
2340 	  unsigned int r, g, b;
2341 	  unsigned long pixel = colors[i].pixel;
2342 
2343 	  r = (pixel >> dpyinfo->red_offset) & rmask;
2344 	  g = (pixel >> dpyinfo->green_offset) & gmask;
2345 	  b = (pixel >> dpyinfo->blue_offset) & bmask;
2346 
2347 	  colors[i].red = (r * rmult) >> 16;
2348 	  colors[i].green = (g * gmult) >> 16;
2349 	  colors[i].blue = (b * bmult) >> 16;
2350 	}
2351       return;
2352     }
2353 
2354   if (dpyinfo->color_cells)
2355     {
2356       int i;
2357       for (i = 0; i < ncolors; ++i)
2358 	{
2359 	  unsigned long pixel = colors[i].pixel;
2360 	  eassert (pixel < dpyinfo->ncolor_cells);
2361 	  eassert (dpyinfo->color_cells[pixel].pixel == pixel);
2362 	  colors[i] = dpyinfo->color_cells[pixel];
2363 	}
2364       return;
2365     }
2366 
2367   XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
2368 }
2369 
2370 /* Store F's background color into *BGCOLOR.  */
2371 
2372 static void
x_query_frame_background_color(struct frame * f,XColor * bgcolor)2373 x_query_frame_background_color (struct frame *f, XColor *bgcolor)
2374 {
2375   bgcolor->pixel = FRAME_BACKGROUND_PIXEL (f);
2376   x_query_colors (f, bgcolor, 1);
2377 }
2378 
2379 #define HEX_COLOR_NAME_LENGTH 32
2380 
2381 /* On frame F, translate the color name to RGB values.  Use cached
2382    information, if possible.
2383 
2384    Note that there is currently no way to clean old entries out of the
2385    cache.  However, it is limited to names in the server's database,
2386    and names we've actually looked up; list-colors-display is probably
2387    the most color-intensive case we're likely to hit.  */
2388 
x_parse_color(struct frame * f,const char * color_name,XColor * color)2389 Status x_parse_color (struct frame *f, const char *color_name,
2390 		      XColor *color)
2391 {
2392   Display *dpy = FRAME_X_DISPLAY (f);
2393   Colormap cmap = FRAME_X_COLORMAP (f);
2394   struct color_name_cache_entry *cache_entry;
2395 
2396   if (color_name[0] == '#')
2397     {
2398       /* Don't pass #RGB strings directly to XParseColor, because that
2399 	 follows the X convention of zero-extending each channel
2400 	 value: #f00 means #f00000.  We want the convention of scaling
2401 	 channel values, so #f00 means #ff0000, just as it does for
2402 	 HTML, SVG, and CSS.
2403 
2404 	 So we translate #f00 to rgb:f/0/0, which X handles
2405 	 differently. */
2406       char rgb_color_name[HEX_COLOR_NAME_LENGTH];
2407       int len = strlen (color_name);
2408       int digits_per_channel;
2409       if (len == 4)
2410 	digits_per_channel = 1;
2411       else if (len == 7)
2412 	digits_per_channel = 2;
2413       else if (len == 10)
2414 	digits_per_channel = 3;
2415       else if (len == 13)
2416 	digits_per_channel = 4;
2417       else
2418 	return 0;
2419 
2420       snprintf (rgb_color_name, sizeof rgb_color_name, "rgb:%.*s/%.*s/%.*s",
2421 		digits_per_channel, color_name + 1,
2422 		digits_per_channel, color_name + digits_per_channel + 1,
2423 		digits_per_channel, color_name + 2 * digits_per_channel + 1);
2424 
2425       /* The rgb form is parsed directly by XParseColor without
2426 	 talking to the X server.  No need for caching.  */
2427       return XParseColor (dpy, cmap, rgb_color_name, color);
2428     }
2429 
2430   for (cache_entry = FRAME_DISPLAY_INFO (f)->color_names; cache_entry;
2431        cache_entry = cache_entry->next)
2432     {
2433       if (!xstrcasecmp(cache_entry->name, color_name))
2434 	{
2435 	  *color = cache_entry->rgb;
2436 	  return 1;
2437 	}
2438     }
2439 
2440   if (XParseColor (dpy, cmap, color_name, color) == 0)
2441     /* No caching of negative results, currently.  */
2442     return 0;
2443 
2444   cache_entry = xzalloc (sizeof *cache_entry);
2445   cache_entry->rgb = *color;
2446   cache_entry->name = xstrdup (color_name);
2447   cache_entry->next = FRAME_DISPLAY_INFO (f)->color_names;
2448   FRAME_DISPLAY_INFO (f)->color_names = cache_entry;
2449   return 1;
2450 }
2451 
2452 
2453 /* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP.  If an
2454    exact match can't be allocated, try the nearest color available.
2455    Value is true if successful.  Set *COLOR to the color
2456    allocated.  */
2457 
2458 static bool
x_alloc_nearest_color_1(Display * dpy,Colormap cmap,XColor * color)2459 x_alloc_nearest_color_1 (Display *dpy, Colormap cmap, XColor *color)
2460 {
2461   bool rc;
2462 
2463   rc = XAllocColor (dpy, cmap, color) != 0;
2464   if (rc == 0)
2465     {
2466       /* If we got to this point, the colormap is full, so we're going
2467 	 to try to get the next closest color.  The algorithm used is
2468 	 a least-squares matching, which is what X uses for closest
2469 	 color matching with StaticColor visuals.  */
2470       int nearest, i;
2471       int max_color_delta = 255;
2472       int max_delta = 3 * max_color_delta;
2473       int nearest_delta = max_delta + 1;
2474       int ncells;
2475       const XColor *cells = x_color_cells (dpy, &ncells);
2476 
2477       for (nearest = i = 0; i < ncells; ++i)
2478 	{
2479 	  int dred   = (color->red   >> 8) - (cells[i].red   >> 8);
2480 	  int dgreen = (color->green >> 8) - (cells[i].green >> 8);
2481 	  int dblue  = (color->blue  >> 8) - (cells[i].blue  >> 8);
2482 	  int delta = dred * dred + dgreen * dgreen + dblue * dblue;
2483 
2484 	  if (delta < nearest_delta)
2485 	    {
2486 	      nearest = i;
2487 	      nearest_delta = delta;
2488 	    }
2489 	}
2490 
2491       color->red   = cells[nearest].red;
2492       color->green = cells[nearest].green;
2493       color->blue  = cells[nearest].blue;
2494       rc = XAllocColor (dpy, cmap, color) != 0;
2495     }
2496   else
2497     {
2498       /* If allocation succeeded, and the allocated pixel color is not
2499          equal to a cached pixel color recorded earlier, there was a
2500          change in the colormap, so clear the color cache.  */
2501       struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
2502       eassume (dpyinfo);
2503 
2504       if (dpyinfo->color_cells)
2505 	{
2506 	  XColor *cached_color = &dpyinfo->color_cells[color->pixel];
2507 	  if (cached_color->red != color->red
2508 	      || cached_color->blue != color->blue
2509 	      || cached_color->green != color->green)
2510 	    {
2511 	      xfree (dpyinfo->color_cells);
2512 	      dpyinfo->color_cells = NULL;
2513 	      dpyinfo->ncolor_cells = 0;
2514 	    }
2515 	}
2516     }
2517 
2518 #ifdef DEBUG_X_COLORS
2519   if (rc)
2520     register_color (color->pixel);
2521 #endif /* DEBUG_X_COLORS */
2522 
2523   return rc;
2524 }
2525 
2526 
2527 /* Allocate the color COLOR->pixel on frame F, colormap CMAP, after
2528    gamma correction.  If an exact match can't be allocated, try the
2529    nearest color available.  Value is true if successful.  Set *COLOR
2530    to the color allocated.  */
2531 
2532 bool
x_alloc_nearest_color(struct frame * f,Colormap cmap,XColor * color)2533 x_alloc_nearest_color (struct frame *f, Colormap cmap, XColor *color)
2534 {
2535   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
2536 
2537   gamma_correct (f, color);
2538 
2539   if (dpyinfo->red_bits > 0)
2540     {
2541       color->pixel = x_make_truecolor_pixel (dpyinfo,
2542 					     color->red,
2543 					     color->green,
2544 					     color->blue);
2545       return true;
2546     }
2547 
2548   return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f), cmap, color);
2549 }
2550 
2551 
2552 /* Allocate color PIXEL on frame F.  PIXEL must already be allocated.
2553    It's necessary to do this instead of just using PIXEL directly to
2554    get color reference counts right.  */
2555 
2556 unsigned long
x_copy_color(struct frame * f,unsigned long pixel)2557 x_copy_color (struct frame *f, unsigned long pixel)
2558 {
2559   XColor color;
2560 
2561   /* If display has an immutable color map, freeing colors is not
2562      necessary and some servers don't allow it.  Since we won't free a
2563      color once we've allocated it, we don't need to re-allocate it to
2564      maintain the server's reference count.  */
2565   if (!x_mutable_colormap (FRAME_X_VISUAL (f)))
2566     return pixel;
2567 
2568   color.pixel = pixel;
2569   block_input ();
2570   /* The color could still be found in the color_cells array.  */
2571   x_query_colors (f, &color, 1);
2572   XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
2573   unblock_input ();
2574 #ifdef DEBUG_X_COLORS
2575   register_color (pixel);
2576 #endif
2577   return color.pixel;
2578 }
2579 
2580 
2581 /* Brightness beyond which a color won't have its highlight brightness
2582    boosted.
2583 
2584    Nominally, highlight colors for `3d' faces are calculated by
2585    brightening an object's color by a constant scale factor, but this
2586    doesn't yield good results for dark colors, so for colors who's
2587    brightness is less than this value (on a scale of 0-65535) have an
2588    use an additional additive factor.
2589 
2590    The value here is set so that the default menu-bar/mode-line color
2591    (grey75) will not have its highlights changed at all.  */
2592 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
2593 
2594 
2595 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
2596    or DELTA.  Try a color with RGB values multiplied by FACTOR first.
2597    If this produces the same color as PIXEL, try a color where all RGB
2598    values have DELTA added.  Return the allocated color in *PIXEL.
2599    DISPLAY is the X display, CMAP is the colormap to operate on.
2600    Value is non-zero if successful.  */
2601 
2602 static bool
x_alloc_lighter_color(struct frame * f,Display * display,Colormap cmap,unsigned long * pixel,double factor,int delta)2603 x_alloc_lighter_color (struct frame *f, Display *display, Colormap cmap,
2604 		       unsigned long *pixel, double factor, int delta)
2605 {
2606   XColor color, new;
2607   long bright;
2608   bool success_p;
2609 
2610   /* Get RGB color values.  */
2611   color.pixel = *pixel;
2612   x_query_colors (f, &color, 1);
2613 
2614   /* Change RGB values by specified FACTOR.  Avoid overflow!  */
2615   eassert (factor >= 0);
2616   new.red = min (0xffff, factor * color.red);
2617   new.green = min (0xffff, factor * color.green);
2618   new.blue = min (0xffff, factor * color.blue);
2619 
2620   /* Calculate brightness of COLOR.  */
2621   bright = (2 * color.red + 3 * color.green + color.blue) / 6;
2622 
2623   /* We only boost colors that are darker than
2624      HIGHLIGHT_COLOR_DARK_BOOST_LIMIT.  */
2625   if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
2626     /* Make an additive adjustment to NEW, because it's dark enough so
2627        that scaling by FACTOR alone isn't enough.  */
2628     {
2629       /* How far below the limit this color is (0 - 1, 1 being darker).  */
2630       double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
2631       /* The additive adjustment.  */
2632       int min_delta = delta * dimness * factor / 2;
2633 
2634       if (factor < 1)
2635 	{
2636 	  new.red =   max (0, new.red -   min_delta);
2637 	  new.green = max (0, new.green - min_delta);
2638 	  new.blue =  max (0, new.blue -  min_delta);
2639 	}
2640       else
2641 	{
2642 	  new.red =   min (0xffff, min_delta + new.red);
2643 	  new.green = min (0xffff, min_delta + new.green);
2644 	  new.blue =  min (0xffff, min_delta + new.blue);
2645 	}
2646     }
2647 
2648   /* Try to allocate the color.  */
2649   success_p = x_alloc_nearest_color (f, cmap, &new);
2650   if (success_p)
2651     {
2652       if (new.pixel == *pixel)
2653 	{
2654 	  /* If we end up with the same color as before, try adding
2655 	     delta to the RGB values.  */
2656 	  x_free_colors (f, &new.pixel, 1);
2657 
2658 	  new.red = min (0xffff, delta + color.red);
2659 	  new.green = min (0xffff, delta + color.green);
2660 	  new.blue = min (0xffff, delta + color.blue);
2661 	  success_p = x_alloc_nearest_color (f, cmap, &new);
2662 	}
2663       else
2664 	success_p = true;
2665       *pixel = new.pixel;
2666     }
2667 
2668   return success_p;
2669 }
2670 
2671 
2672 /* Set up the foreground color for drawing relief lines of glyph
2673    string S.  RELIEF is a pointer to a struct relief containing the GC
2674    with which lines will be drawn.  Use a color that is FACTOR or
2675    DELTA lighter or darker than the relief's background which is found
2676    in S->f->output_data.x->relief_background.  If such a color cannot
2677    be allocated, use DEFAULT_PIXEL, instead.  */
2678 
2679 static void
x_setup_relief_color(struct frame * f,struct relief * relief,double factor,int delta,unsigned long default_pixel)2680 x_setup_relief_color (struct frame *f, struct relief *relief, double factor,
2681 		      int delta, unsigned long default_pixel)
2682 {
2683   XGCValues xgcv;
2684   struct x_output *di = f->output_data.x;
2685   unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
2686   unsigned long pixel;
2687   unsigned long background = di->relief_background;
2688   Colormap cmap = FRAME_X_COLORMAP (f);
2689   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
2690   Display *dpy = FRAME_X_DISPLAY (f);
2691 
2692   xgcv.graphics_exposures = False;
2693   xgcv.line_width = 1;
2694 
2695   /* Free previously allocated color.  The color cell will be reused
2696      when it has been freed as many times as it was allocated, so this
2697      doesn't affect faces using the same colors.  */
2698   if (relief->gc && relief->pixel != -1)
2699     {
2700       x_free_colors (f, &relief->pixel, 1);
2701       relief->pixel = -1;
2702     }
2703 
2704   /* Allocate new color.  */
2705   xgcv.foreground = default_pixel;
2706   pixel = background;
2707   if (dpyinfo->n_planes != 1
2708       && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
2709     xgcv.foreground = relief->pixel = pixel;
2710 
2711   if (relief->gc == 0)
2712     {
2713       xgcv.stipple = dpyinfo->gray;
2714       mask |= GCStipple;
2715       relief->gc = XCreateGC (dpy, FRAME_X_DRAWABLE (f), mask, &xgcv);
2716     }
2717   else
2718     XChangeGC (dpy, relief->gc, mask, &xgcv);
2719 }
2720 
2721 
2722 /* Set up colors for the relief lines around glyph string S.  */
2723 
2724 static void
x_setup_relief_colors(struct glyph_string * s)2725 x_setup_relief_colors (struct glyph_string *s)
2726 {
2727   struct x_output *di = s->f->output_data.x;
2728   unsigned long color;
2729 
2730   if (s->face->use_box_color_for_shadows_p)
2731     color = s->face->box_color;
2732   else if (s->first_glyph->type == IMAGE_GLYPH
2733 	   && s->img->pixmap
2734 	   && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
2735     color = IMAGE_BACKGROUND (s->img, s->f, 0);
2736   else
2737     {
2738       XGCValues xgcv;
2739 
2740       /* Get the background color of the face.  */
2741       XGetGCValues (FRAME_X_DISPLAY (s->f), s->gc, GCBackground, &xgcv);
2742       color = xgcv.background;
2743     }
2744 
2745   if (di->white_relief.gc == 0
2746       || color != di->relief_background)
2747     {
2748       di->relief_background = color;
2749       x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
2750 			    WHITE_PIX_DEFAULT (s->f));
2751       x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
2752 			    BLACK_PIX_DEFAULT (s->f));
2753     }
2754 }
2755 
2756 
2757 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2758    TOP_Y, RIGHT_X, and BOTTOM_Y.  WIDTH is the thickness of the relief
2759    to draw, it must be >= 0.  RAISED_P means draw a raised
2760    relief.  LEFT_P means draw a relief on the left side of
2761    the rectangle.  RIGHT_P means draw a relief on the right
2762    side of the rectangle.  CLIP_RECT is the clipping rectangle to use
2763    when drawing.  */
2764 
2765 static void
x_draw_relief_rect(struct frame * f,int left_x,int top_y,int right_x,int bottom_y,int width,bool raised_p,bool top_p,bool bot_p,bool left_p,bool right_p,XRectangle * clip_rect)2766 x_draw_relief_rect (struct frame *f,
2767 		    int left_x, int top_y, int right_x, int bottom_y,
2768 		    int width, bool raised_p, bool top_p, bool bot_p,
2769 		    bool left_p, bool right_p,
2770 		    XRectangle *clip_rect)
2771 {
2772 #ifdef USE_CAIRO
2773   GC top_left_gc, bottom_right_gc;
2774   int corners = 0;
2775 
2776   if (raised_p)
2777     {
2778       top_left_gc = f->output_data.x->white_relief.gc;
2779       bottom_right_gc = f->output_data.x->black_relief.gc;
2780     }
2781   else
2782     {
2783       top_left_gc = f->output_data.x->black_relief.gc;
2784       bottom_right_gc = f->output_data.x->white_relief.gc;
2785     }
2786 
2787   x_set_clip_rectangles (f, top_left_gc, clip_rect, 1);
2788   x_set_clip_rectangles (f, bottom_right_gc, clip_rect, 1);
2789 
2790   if (left_p)
2791     {
2792       x_fill_rectangle (f, top_left_gc, left_x, top_y,
2793 			width, bottom_y + 1 - top_y);
2794       if (top_p)
2795 	corners |= 1 << CORNER_TOP_LEFT;
2796       if (bot_p)
2797 	corners |= 1 << CORNER_BOTTOM_LEFT;
2798     }
2799   if (right_p)
2800     {
2801       x_fill_rectangle (f, bottom_right_gc, right_x + 1 - width, top_y,
2802 			width, bottom_y + 1 - top_y);
2803       if (top_p)
2804 	corners |= 1 << CORNER_TOP_RIGHT;
2805       if (bot_p)
2806 	corners |= 1 << CORNER_BOTTOM_RIGHT;
2807     }
2808   if (top_p)
2809     {
2810       if (!right_p)
2811 	x_fill_rectangle (f, top_left_gc, left_x, top_y,
2812 			  right_x + 1 - left_x, width);
2813       else
2814 	x_fill_trapezoid_for_relief (f, top_left_gc, left_x, top_y,
2815 				     right_x + 1 - left_x, width, 1);
2816     }
2817   if (bot_p)
2818     {
2819       if (!left_p)
2820 	x_fill_rectangle (f, bottom_right_gc, left_x, bottom_y + 1 - width,
2821 			  right_x + 1 - left_x, width);
2822       else
2823 	x_fill_trapezoid_for_relief (f, bottom_right_gc,
2824 				     left_x, bottom_y + 1 - width,
2825 				     right_x + 1 - left_x, width, 0);
2826     }
2827   if (left_p && width != 1)
2828     x_fill_rectangle (f, bottom_right_gc, left_x, top_y,
2829 		      1, bottom_y + 1 - top_y);
2830   if (top_p && width != 1)
2831     x_fill_rectangle (f, bottom_right_gc, left_x, top_y,
2832 		      right_x + 1 - left_x, 1);
2833   if (corners)
2834     {
2835       XSetBackground (FRAME_X_DISPLAY (f), top_left_gc,
2836 		      FRAME_BACKGROUND_PIXEL (f));
2837       x_erase_corners_for_relief (f, top_left_gc, left_x, top_y,
2838 				  right_x - left_x + 1, bottom_y - top_y + 1,
2839 				  6, 1, corners);
2840     }
2841 
2842   x_reset_clip_rectangles (f, top_left_gc);
2843   x_reset_clip_rectangles (f, bottom_right_gc);
2844 #else
2845   Display *dpy = FRAME_X_DISPLAY (f);
2846   Drawable drawable = FRAME_X_DRAWABLE (f);
2847   int i;
2848   GC gc;
2849 
2850   if (raised_p)
2851     gc = f->output_data.x->white_relief.gc;
2852   else
2853     gc = f->output_data.x->black_relief.gc;
2854   XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
2855 
2856   /* This code is more complicated than it has to be, because of two
2857      minor hacks to make the boxes look nicer: (i) if width > 1, draw
2858      the outermost line using the black relief.  (ii) Omit the four
2859      corner pixels.  */
2860 
2861   /* Top.  */
2862   if (top_p)
2863     {
2864       if (width == 1)
2865         XDrawLine (dpy, drawable, gc,
2866 		   left_x + left_p, top_y,
2867 		   right_x + !right_p, top_y);
2868 
2869       for (i = 1; i < width; ++i)
2870         XDrawLine (dpy, drawable, gc,
2871 		   left_x  + i * left_p, top_y + i,
2872 		   right_x + 1 - i * right_p, top_y + i);
2873     }
2874 
2875   /* Left.  */
2876   if (left_p)
2877     {
2878       if (width == 1)
2879         XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y);
2880 
2881       x_clear_area(f, left_x, top_y, 1, 1);
2882       x_clear_area(f, left_x, bottom_y, 1, 1);
2883 
2884       for (i = (width > 1 ? 1 : 0); i < width; ++i)
2885         XDrawLine (dpy, drawable, gc,
2886 		   left_x + i, top_y + (i + 1) * top_p,
2887 		   left_x + i, bottom_y + 1 - (i + 1) * bot_p);
2888     }
2889 
2890   XSetClipMask (dpy, gc, None);
2891   if (raised_p)
2892     gc = f->output_data.x->black_relief.gc;
2893   else
2894     gc = f->output_data.x->white_relief.gc;
2895   XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
2896 
2897   if (width > 1)
2898     {
2899       /* Outermost top line.  */
2900       if (top_p)
2901         XDrawLine (dpy, drawable, gc,
2902 		   left_x  + left_p, top_y,
2903 		   right_x + !right_p, top_y);
2904 
2905       /* Outermost left line.  */
2906       if (left_p)
2907         XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y);
2908     }
2909 
2910   /* Bottom.  */
2911   if (bot_p)
2912     {
2913       XDrawLine (dpy, drawable, gc,
2914 		 left_x + left_p, bottom_y,
2915 		 right_x + !right_p, bottom_y);
2916       for (i = 1; i < width; ++i)
2917         XDrawLine (dpy, drawable, gc,
2918 		   left_x  + i * left_p, bottom_y - i,
2919 		   right_x + 1 - i * right_p, bottom_y - i);
2920     }
2921 
2922   /* Right.  */
2923   if (right_p)
2924     {
2925       x_clear_area(f, right_x, top_y, 1, 1);
2926       x_clear_area(f, right_x, bottom_y, 1, 1);
2927       for (i = 0; i < width; ++i)
2928         XDrawLine (dpy, drawable, gc,
2929 		   right_x - i, top_y + (i + 1) * top_p,
2930 		   right_x - i, bottom_y + 1 - (i + 1) * bot_p);
2931     }
2932 
2933   x_reset_clip_rectangles (f, gc);
2934 
2935 #endif
2936 }
2937 
2938 
2939 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2940    RIGHT_X, and BOTTOM_Y.  WIDTH is the thickness of the lines to
2941    draw, it must be >= 0.  LEFT_P means draw a line on the
2942    left side of the rectangle.  RIGHT_P means draw a line
2943    on the right side of the rectangle.  CLIP_RECT is the clipping
2944    rectangle to use when drawing.  */
2945 
2946 static void
x_draw_box_rect(struct glyph_string * s,int left_x,int top_y,int right_x,int bottom_y,int width,bool left_p,bool right_p,XRectangle * clip_rect)2947 x_draw_box_rect (struct glyph_string *s,
2948 		 int left_x, int top_y, int right_x, int bottom_y, int width,
2949 		 bool left_p, bool right_p, XRectangle *clip_rect)
2950 {
2951   Display *display = FRAME_X_DISPLAY (s->f);
2952   XGCValues xgcv;
2953 
2954   XGetGCValues (display, s->gc, GCForeground, &xgcv);
2955   XSetForeground (display, s->gc, s->face->box_color);
2956   x_set_clip_rectangles (s->f, s->gc, clip_rect, 1);
2957 
2958   /* Top.  */
2959   x_fill_rectangle (s->f, s->gc,
2960 		  left_x, top_y, right_x - left_x + 1, width);
2961 
2962   /* Left.  */
2963   if (left_p)
2964     x_fill_rectangle (s->f, s->gc,
2965 		    left_x, top_y, width, bottom_y - top_y + 1);
2966 
2967   /* Bottom.  */
2968   x_fill_rectangle (s->f, s->gc,
2969 		  left_x, bottom_y - width + 1, right_x - left_x + 1, width);
2970 
2971   /* Right.  */
2972   if (right_p)
2973     x_fill_rectangle (s->f, s->gc,
2974 		    right_x - width + 1, top_y, width, bottom_y - top_y + 1);
2975 
2976   XSetForeground (display, s->gc, xgcv.foreground);
2977   x_reset_clip_rectangles (s->f, s->gc);
2978 }
2979 
2980 
2981 /* Draw a box around glyph string S.  */
2982 
2983 static void
x_draw_glyph_string_box(struct glyph_string * s)2984 x_draw_glyph_string_box (struct glyph_string *s)
2985 {
2986   int width, left_x, right_x, top_y, bottom_y, last_x;
2987   bool raised_p, left_p, right_p;
2988   struct glyph *last_glyph;
2989   XRectangle clip_rect;
2990 
2991   last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
2992 	    ? WINDOW_RIGHT_EDGE_X (s->w)
2993 	    : window_box_right (s->w, s->area));
2994 
2995   /* The glyph that may have a right box line.  */
2996   last_glyph = (s->cmp || s->img
2997 		? s->first_glyph
2998 		: s->first_glyph + s->nchars - 1);
2999 
3000   width = eabs (s->face->box_line_width);
3001   raised_p = s->face->box == FACE_RAISED_BOX;
3002   left_x = s->x;
3003   right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
3004 	     ? last_x - 1
3005 	     : min (last_x, s->x + s->background_width) - 1);
3006   top_y = s->y;
3007   bottom_y = top_y + s->height - 1;
3008 
3009   left_p = (s->first_glyph->left_box_line_p
3010 	    || (s->hl == DRAW_MOUSE_FACE
3011 		&& (s->prev == NULL
3012 		    || s->prev->hl != s->hl)));
3013   right_p = (last_glyph->right_box_line_p
3014 	     || (s->hl == DRAW_MOUSE_FACE
3015 		 && (s->next == NULL
3016 		     || s->next->hl != s->hl)));
3017 
3018   get_glyph_string_clip_rect (s, &clip_rect);
3019 
3020   if (s->face->box == FACE_SIMPLE_BOX)
3021     x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3022 		     left_p, right_p, &clip_rect);
3023   else
3024     {
3025       x_setup_relief_colors (s);
3026       x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3027 			  width, raised_p, true, true, left_p, right_p,
3028 			  &clip_rect);
3029     }
3030 }
3031 
3032 
3033 #ifndef USE_CAIRO
3034 static void
x_composite_image(struct glyph_string * s,Pixmap dest,int srcX,int srcY,int dstX,int dstY,int width,int height)3035 x_composite_image (struct glyph_string *s, Pixmap dest,
3036                    int srcX, int srcY, int dstX, int dstY,
3037                    int width, int height)
3038 {
3039   Display *display = FRAME_X_DISPLAY (s->f);
3040 #ifdef HAVE_XRENDER
3041   if (s->img->picture)
3042     {
3043       Picture destination;
3044       XRenderPictFormat *default_format;
3045       XRenderPictureAttributes attr;
3046 
3047       default_format = XRenderFindVisualFormat (display,
3048                                                 DefaultVisual (display, 0));
3049       destination = XRenderCreatePicture (display, dest,
3050                                           default_format, 0, &attr);
3051 
3052       XRenderComposite (display, s->img->mask_picture ? PictOpOver : PictOpSrc,
3053                         s->img->picture, s->img->mask_picture, destination,
3054                         srcX, srcY,
3055                         srcX, srcY,
3056                         dstX, dstY,
3057                         width, height);
3058 
3059       XRenderFreePicture (display, destination);
3060       return;
3061     }
3062 #endif
3063 
3064   XCopyArea (display, s->img->pixmap,
3065 	     dest, s->gc,
3066 	     srcX, srcY,
3067 	     width, height, dstX, dstY);
3068 }
3069 #endif	/* !USE_CAIRO */
3070 
3071 
3072 /* Draw foreground of image glyph string S.  */
3073 
3074 static void
x_draw_image_foreground(struct glyph_string * s)3075 x_draw_image_foreground (struct glyph_string *s)
3076 {
3077   int x = s->x;
3078   int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
3079 
3080   /* If first glyph of S has a left box line, start drawing it to the
3081      right of that line.  */
3082   if (s->face->box != FACE_NO_BOX
3083       && s->first_glyph->left_box_line_p
3084       && s->slice.x == 0)
3085     x += eabs (s->face->box_line_width);
3086 
3087   /* If there is a margin around the image, adjust x- and y-position
3088      by that margin.  */
3089   if (s->slice.x == 0)
3090     x += s->img->hmargin;
3091   if (s->slice.y == 0)
3092     y += s->img->vmargin;
3093 
3094 #ifdef USE_CAIRO
3095   if (s->img->cr_data)
3096     {
3097       x_set_glyph_string_clipping (s);
3098       x_cr_draw_image (s->f, s->gc, s->img->cr_data,
3099 		       s->slice.x, s->slice.y, s->slice.width, s->slice.height,
3100 		       x, y, true);
3101       if (!s->img->mask)
3102 	{
3103 	  /* When the image has a mask, we can expect that at
3104 	     least part of a mouse highlight or a block cursor will
3105 	     be visible.  If the image doesn't have a mask, make
3106 	     a block cursor visible by drawing a rectangle around
3107 	     the image.  I believe it's looking better if we do
3108 	     nothing here for mouse-face.  */
3109 	  if (s->hl == DRAW_CURSOR)
3110 	    {
3111 	      int relief = eabs (s->img->relief);
3112 	      x_draw_rectangle (s->f, s->gc, x - relief, y - relief,
3113 				s->slice.width + relief*2 - 1,
3114 				s->slice.height + relief*2 - 1);
3115 	    }
3116 	}
3117     }
3118 #else  /* ! USE_CAIRO */
3119   if (s->img->pixmap)
3120     {
3121       if (s->img->mask)
3122 	{
3123 	  /* We can't set both a clip mask and use XSetClipRectangles
3124 	     because the latter also sets a clip mask.  We also can't
3125 	     trust on the shape extension to be available
3126 	     (XShapeCombineRegion).  So, compute the rectangle to draw
3127 	     manually.  */
3128           /* FIXME: Do we need to do this when using XRender compositing?  */
3129 	  unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3130 				| GCFunction);
3131 	  XGCValues xgcv;
3132 	  XRectangle clip_rect, image_rect, r;
3133 
3134 	  xgcv.clip_mask = s->img->mask;
3135 	  xgcv.clip_x_origin = x;
3136 	  xgcv.clip_y_origin = y;
3137 	  xgcv.function = GXcopy;
3138 	  XChangeGC (FRAME_X_DISPLAY (s->f), s->gc, mask, &xgcv);
3139 
3140 	  get_glyph_string_clip_rect (s, &clip_rect);
3141 	  image_rect.x = x;
3142 	  image_rect.y = y;
3143 	  image_rect.width = s->slice.width;
3144 	  image_rect.height = s->slice.height;
3145 	  if (gui_intersect_rectangles (&clip_rect, &image_rect, &r))
3146             x_composite_image (s, FRAME_X_DRAWABLE (s->f),
3147 			       s->slice.x + r.x - x, s->slice.y + r.y - y,
3148                                r.x, r.y, r.width, r.height);
3149 	}
3150       else
3151 	{
3152 	  XRectangle clip_rect, image_rect, r;
3153 
3154 	  get_glyph_string_clip_rect (s, &clip_rect);
3155 	  image_rect.x = x;
3156 	  image_rect.y = y;
3157 	  image_rect.width = s->slice.width;
3158 	  image_rect.height = s->slice.height;
3159 	  if (gui_intersect_rectangles (&clip_rect, &image_rect, &r))
3160             x_composite_image (s, FRAME_X_DRAWABLE (s->f), s->slice.x + r.x - x, s->slice.y + r.y - y,
3161                                r.x, r.y, r.width, r.height);
3162 
3163 	  /* When the image has a mask, we can expect that at
3164 	     least part of a mouse highlight or a block cursor will
3165 	     be visible.  If the image doesn't have a mask, make
3166 	     a block cursor visible by drawing a rectangle around
3167 	     the image.  I believe it's looking better if we do
3168 	     nothing here for mouse-face.  */
3169 	  if (s->hl == DRAW_CURSOR)
3170 	    {
3171 	      int relief = eabs (s->img->relief);
3172 	      x_draw_rectangle (s->f, s->gc,
3173 			      x - relief, y - relief,
3174 			      s->slice.width + relief*2 - 1,
3175 			      s->slice.height + relief*2 - 1);
3176 	    }
3177 	}
3178     }
3179 #endif	/* ! USE_CAIRO */
3180   else
3181     /* Draw a rectangle if image could not be loaded.  */
3182     x_draw_rectangle (s->f, s->gc, x, y,
3183 		    s->slice.width - 1, s->slice.height - 1);
3184 }
3185 
3186 
3187 /* Draw a relief around the image glyph string S.  */
3188 
3189 static void
x_draw_image_relief(struct glyph_string * s)3190 x_draw_image_relief (struct glyph_string *s)
3191 {
3192   int x1, y1, thick;
3193   bool raised_p, top_p, bot_p, left_p, right_p;
3194   int extra_x, extra_y;
3195   XRectangle r;
3196   int x = s->x;
3197   int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
3198 
3199   /* If first glyph of S has a left box line, start drawing it to the
3200      right of that line.  */
3201   if (s->face->box != FACE_NO_BOX
3202       && s->first_glyph->left_box_line_p
3203       && s->slice.x == 0)
3204     x += eabs (s->face->box_line_width);
3205 
3206   /* If there is a margin around the image, adjust x- and y-position
3207      by that margin.  */
3208   if (s->slice.x == 0)
3209     x += s->img->hmargin;
3210   if (s->slice.y == 0)
3211     y += s->img->vmargin;
3212 
3213   if (s->hl == DRAW_IMAGE_SUNKEN
3214       || s->hl == DRAW_IMAGE_RAISED)
3215     {
3216       thick = (tab_bar_button_relief < 0
3217 	       ? DEFAULT_TAB_BAR_BUTTON_RELIEF
3218 	       : (tool_bar_button_relief < 0
3219 		  ? DEFAULT_TOOL_BAR_BUTTON_RELIEF
3220 		  : min (tool_bar_button_relief, 1000000)));
3221       raised_p = s->hl == DRAW_IMAGE_RAISED;
3222     }
3223   else
3224     {
3225       thick = eabs (s->img->relief);
3226       raised_p = s->img->relief > 0;
3227     }
3228 
3229   x1 = x + s->slice.width - 1;
3230   y1 = y + s->slice.height - 1;
3231 
3232   extra_x = extra_y = 0;
3233   if (s->face->id == TAB_BAR_FACE_ID)
3234     {
3235       if (CONSP (Vtab_bar_button_margin)
3236 	  && FIXNUMP (XCAR (Vtab_bar_button_margin))
3237 	  && FIXNUMP (XCDR (Vtab_bar_button_margin)))
3238 	{
3239 	  extra_x = XFIXNUM (XCAR (Vtab_bar_button_margin));
3240 	  extra_y = XFIXNUM (XCDR (Vtab_bar_button_margin));
3241 	}
3242       else if (FIXNUMP (Vtab_bar_button_margin))
3243 	extra_x = extra_y = XFIXNUM (Vtab_bar_button_margin);
3244     }
3245 
3246   if (s->face->id == TOOL_BAR_FACE_ID)
3247     {
3248       if (CONSP (Vtool_bar_button_margin)
3249 	  && FIXNUMP (XCAR (Vtool_bar_button_margin))
3250 	  && FIXNUMP (XCDR (Vtool_bar_button_margin)))
3251 	{
3252 	  extra_x = XFIXNUM (XCAR (Vtool_bar_button_margin));
3253 	  extra_y = XFIXNUM (XCDR (Vtool_bar_button_margin));
3254 	}
3255       else if (FIXNUMP (Vtool_bar_button_margin))
3256 	extra_x = extra_y = XFIXNUM (Vtool_bar_button_margin);
3257     }
3258 
3259   top_p = bot_p = left_p = right_p = false;
3260 
3261   if (s->slice.x == 0)
3262     x -= thick + extra_x, left_p = true;
3263   if (s->slice.y == 0)
3264     y -= thick + extra_y, top_p = true;
3265   if (s->slice.x + s->slice.width == s->img->width)
3266     x1 += thick + extra_x, right_p = true;
3267   if (s->slice.y + s->slice.height == s->img->height)
3268     y1 += thick + extra_y, bot_p = true;
3269 
3270   x_setup_relief_colors (s);
3271   get_glyph_string_clip_rect (s, &r);
3272   x_draw_relief_rect (s->f, x, y, x1, y1, thick, raised_p,
3273 		      top_p, bot_p, left_p, right_p, &r);
3274 }
3275 
3276 
3277 #ifndef USE_CAIRO
3278 /* Draw the foreground of image glyph string S to PIXMAP.  */
3279 
3280 static void
x_draw_image_foreground_1(struct glyph_string * s,Pixmap pixmap)3281 x_draw_image_foreground_1 (struct glyph_string *s, Pixmap pixmap)
3282 {
3283   int x = 0;
3284   int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
3285 
3286   /* If first glyph of S has a left box line, start drawing it to the
3287      right of that line.  */
3288   if (s->face->box != FACE_NO_BOX
3289       && s->first_glyph->left_box_line_p
3290       && s->slice.x == 0)
3291     x += eabs (s->face->box_line_width);
3292 
3293   /* If there is a margin around the image, adjust x- and y-position
3294      by that margin.  */
3295   if (s->slice.x == 0)
3296     x += s->img->hmargin;
3297   if (s->slice.y == 0)
3298     y += s->img->vmargin;
3299 
3300   if (s->img->pixmap)
3301     {
3302       Display *display = FRAME_X_DISPLAY (s->f);
3303 
3304       if (s->img->mask)
3305 	{
3306 	  /* We can't set both a clip mask and use XSetClipRectangles
3307 	     because the latter also sets a clip mask.  We also can't
3308 	     trust on the shape extension to be available
3309 	     (XShapeCombineRegion).  So, compute the rectangle to draw
3310 	     manually.  */
3311           /* FIXME: Do we need to do this when using XRender compositing?  */
3312 	  unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3313 				| GCFunction);
3314 	  XGCValues xgcv;
3315 
3316 	  xgcv.clip_mask = s->img->mask;
3317 	  xgcv.clip_x_origin = x - s->slice.x;
3318 	  xgcv.clip_y_origin = y - s->slice.y;
3319 	  xgcv.function = GXcopy;
3320 	  XChangeGC (display, s->gc, mask, &xgcv);
3321 
3322 	  x_composite_image (s, pixmap,
3323                              s->slice.x, s->slice.y,
3324                              x, y, s->slice.width, s->slice.height);
3325 	  XSetClipMask (display, s->gc, None);
3326 	}
3327       else
3328 	{
3329 	  XCopyArea (display, s->img->pixmap, pixmap, s->gc,
3330 		     s->slice.x, s->slice.y,
3331 		     s->slice.width, s->slice.height, x, y);
3332 
3333 	  /* When the image has a mask, we can expect that at
3334 	     least part of a mouse highlight or a block cursor will
3335 	     be visible.  If the image doesn't have a mask, make
3336 	     a block cursor visible by drawing a rectangle around
3337 	     the image.  I believe it's looking better if we do
3338 	     nothing here for mouse-face.  */
3339 	  if (s->hl == DRAW_CURSOR)
3340 	    {
3341 	      int r = eabs (s->img->relief);
3342 	      x_draw_rectangle (s->f, s->gc, x - r, y - r,
3343 			      s->slice.width + r*2 - 1,
3344 			      s->slice.height + r*2 - 1);
3345 	    }
3346 	}
3347     }
3348   else
3349     /* Draw a rectangle if image could not be loaded.  */
3350     x_draw_rectangle (s->f, s->gc, x, y,
3351 		    s->slice.width - 1, s->slice.height - 1);
3352 }
3353 #endif	/* ! USE_CAIRO */
3354 
3355 
3356 /* Draw part of the background of glyph string S.  X, Y, W, and H
3357    give the rectangle to draw.  */
3358 
3359 static void
x_draw_glyph_string_bg_rect(struct glyph_string * s,int x,int y,int w,int h)3360 x_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w, int h)
3361 {
3362   if (s->stippled_p)
3363     {
3364       Display *display = FRAME_X_DISPLAY (s->f);
3365 
3366       /* Fill background with a stipple pattern.  */
3367       XSetFillStyle (display, s->gc, FillOpaqueStippled);
3368       x_fill_rectangle (s->f, s->gc, x, y, w, h);
3369       XSetFillStyle (display, s->gc, FillSolid);
3370     }
3371   else
3372     x_clear_glyph_string_rect (s, x, y, w, h);
3373 }
3374 
3375 
3376 /* Draw image glyph string S.
3377 
3378             s->y
3379    s->x      +-------------------------
3380 	     |   s->face->box
3381 	     |
3382 	     |     +-------------------------
3383 	     |     |  s->img->margin
3384 	     |     |
3385 	     |     |       +-------------------
3386 	     |     |       |  the image
3387 
3388  */
3389 
3390 static void
x_draw_image_glyph_string(struct glyph_string * s)3391 x_draw_image_glyph_string (struct glyph_string *s)
3392 {
3393   int box_line_hwidth = eabs (s->face->box_line_width);
3394   int box_line_vwidth = max (s->face->box_line_width, 0);
3395   int height;
3396 #ifndef USE_CAIRO
3397   Display *display = FRAME_X_DISPLAY (s->f);
3398   Pixmap pixmap = None;
3399 #endif
3400 
3401   height = s->height;
3402   if (s->slice.y == 0)
3403     height -= box_line_vwidth;
3404   if (s->slice.y + s->slice.height >= s->img->height)
3405     height -= box_line_vwidth;
3406 
3407   /* Fill background with face under the image.  Do it only if row is
3408      taller than image or if image has a clip mask to reduce
3409      flickering.  */
3410   s->stippled_p = s->face->stipple != 0;
3411   if (height > s->slice.height
3412       || s->img->hmargin
3413       || s->img->vmargin
3414       || s->img->mask
3415       || s->img->pixmap == 0
3416       || s->width != s->background_width)
3417     {
3418 #ifndef USE_CAIRO
3419       if (s->img->mask)
3420 	{
3421 	  /* Create a pixmap as large as the glyph string.  Fill it
3422 	     with the background color.  Copy the image to it, using
3423 	     its mask.  Copy the temporary pixmap to the display.  */
3424 	  Screen *screen = FRAME_X_SCREEN (s->f);
3425 	  int depth = DefaultDepthOfScreen (screen);
3426 
3427 	  /* Create a pixmap as large as the glyph string.  */
3428           pixmap = XCreatePixmap (display, FRAME_X_DRAWABLE (s->f),
3429 				  s->background_width,
3430 				  s->height, depth);
3431 
3432 	  /* Don't clip in the following because we're working on the
3433 	     pixmap.  */
3434 	  XSetClipMask (display, s->gc, None);
3435 
3436 	  /* Fill the pixmap with the background color/stipple.  */
3437 	  if (s->stippled_p)
3438 	    {
3439 	      /* Fill background with a stipple pattern.  */
3440 	      XSetFillStyle (display, s->gc, FillOpaqueStippled);
3441 	      XSetTSOrigin (display, s->gc, - s->x, - s->y);
3442 	      XFillRectangle (display, pixmap, s->gc,
3443 			      0, 0, s->background_width, s->height);
3444 	      XSetFillStyle (display, s->gc, FillSolid);
3445 	      XSetTSOrigin (display, s->gc, 0, 0);
3446 	    }
3447 	  else
3448 	    {
3449 	      XGCValues xgcv;
3450 	      XGetGCValues (display, s->gc, GCForeground | GCBackground,
3451 			    &xgcv);
3452 	      XSetForeground (display, s->gc, xgcv.background);
3453 	      XFillRectangle (display, pixmap, s->gc,
3454 			      0, 0, s->background_width, s->height);
3455 	      XSetForeground (display, s->gc, xgcv.foreground);
3456 	    }
3457 	}
3458       else
3459 #endif	/* ! USE_CAIRO */
3460 	{
3461 	  int x = s->x;
3462 	  int y = s->y;
3463 	  int width = s->background_width;
3464 
3465 	  if (s->first_glyph->left_box_line_p
3466 	      && s->slice.x == 0)
3467 	    {
3468 	      x += box_line_hwidth;
3469 	      width -= box_line_hwidth;
3470 	    }
3471 
3472 	  if (s->slice.y == 0)
3473 	    y += box_line_vwidth;
3474 
3475 	  x_draw_glyph_string_bg_rect (s, x, y, width, height);
3476 	}
3477 
3478       s->background_filled_p = true;
3479     }
3480 
3481   /* Draw the foreground.  */
3482 #ifndef USE_CAIRO
3483   if (pixmap != None)
3484     {
3485       x_draw_image_foreground_1 (s, pixmap);
3486       x_set_glyph_string_clipping (s);
3487       XCopyArea (display, pixmap, FRAME_X_DRAWABLE (s->f), s->gc,
3488 		 0, 0, s->background_width, s->height, s->x, s->y);
3489       XFreePixmap (display, pixmap);
3490     }
3491   else
3492 #endif	/* ! USE_CAIRO */
3493     x_draw_image_foreground (s);
3494 
3495   /* If we must draw a relief around the image, do it.  */
3496   if (s->img->relief
3497       || s->hl == DRAW_IMAGE_RAISED
3498       || s->hl == DRAW_IMAGE_SUNKEN)
3499     x_draw_image_relief (s);
3500 }
3501 
3502 
3503 /* Draw stretch glyph string S.  */
3504 
3505 static void
x_draw_stretch_glyph_string(struct glyph_string * s)3506 x_draw_stretch_glyph_string (struct glyph_string *s)
3507 {
3508   eassert (s->first_glyph->type == STRETCH_GLYPH);
3509 
3510   if (s->hl == DRAW_CURSOR
3511       && !x_stretch_cursor_p)
3512     {
3513       /* If `x-stretch-cursor' is nil, don't draw a block cursor as
3514 	 wide as the stretch glyph.  */
3515       int width, background_width = s->background_width;
3516       int x = s->x;
3517 
3518       if (!s->row->reversed_p)
3519 	{
3520 	  int left_x = window_box_left_offset (s->w, TEXT_AREA);
3521 
3522 	  if (x < left_x)
3523 	    {
3524 	      background_width -= left_x - x;
3525 	      x = left_x;
3526 	    }
3527 	}
3528       else
3529 	{
3530 	  /* In R2L rows, draw the cursor on the right edge of the
3531 	     stretch glyph.  */
3532 	  int right_x = window_box_right (s->w, TEXT_AREA);
3533 
3534 	  if (x + background_width > right_x)
3535 	    background_width -= x - right_x;
3536 	  x += background_width;
3537 	}
3538       width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
3539       if (s->row->reversed_p)
3540 	x -= width;
3541 
3542       /* Draw cursor.  */
3543       x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
3544 
3545       /* Clear rest using the GC of the original non-cursor face.  */
3546       if (width < background_width)
3547 	{
3548 	  int y = s->y;
3549 	  int w = background_width - width, h = s->height;
3550           Display *display = FRAME_X_DISPLAY (s->f);
3551 	  XRectangle r;
3552 	  GC gc;
3553 
3554 	  if (!s->row->reversed_p)
3555 	    x += width;
3556 	  else
3557 	    x = s->x;
3558 	  if (s->row->mouse_face_p
3559 	      && cursor_in_mouse_face_p (s->w))
3560 	    {
3561 	      x_set_mouse_face_gc (s);
3562 	      gc = s->gc;
3563 	    }
3564 	  else
3565 	    gc = s->face->gc;
3566 
3567 	  get_glyph_string_clip_rect (s, &r);
3568 	  x_set_clip_rectangles (s->f, gc, &r, 1);
3569 
3570 	  if (s->face->stipple)
3571 	    {
3572 	      /* Fill background with a stipple pattern.  */
3573 	      XSetFillStyle (display, gc, FillOpaqueStippled);
3574 	      x_fill_rectangle (s->f, gc, x, y, w, h);
3575 	      XSetFillStyle (display, gc, FillSolid);
3576 	    }
3577 	  else
3578 	    {
3579 	      XGCValues xgcv;
3580 	      XGetGCValues (display, gc, GCForeground | GCBackground, &xgcv);
3581 	      XSetForeground (display, gc, xgcv.background);
3582 	      x_fill_rectangle (s->f, gc, x, y, w, h);
3583 	      XSetForeground (display, gc, xgcv.foreground);
3584 	    }
3585 
3586 	  x_reset_clip_rectangles (s->f, gc);
3587 	}
3588     }
3589   else if (!s->background_filled_p)
3590     {
3591       int background_width = s->background_width;
3592       int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
3593 
3594       /* Don't draw into left margin, fringe or scrollbar area
3595          except for header line and mode line.  */
3596       if (x < left_x && !s->row->mode_line_p)
3597 	{
3598 	  background_width -= left_x - x;
3599 	  x = left_x;
3600 	}
3601       if (background_width > 0)
3602 	x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
3603     }
3604 
3605   s->background_filled_p = true;
3606 }
3607 
3608 static void
x_get_scale_factor(Display * disp,int * scale_x,int * scale_y)3609 x_get_scale_factor(Display *disp, int *scale_x, int *scale_y)
3610 {
3611   const int base_res = 96;
3612   struct x_display_info * dpyinfo = x_display_info_for_display (disp);
3613 
3614   *scale_x = *scale_y = 1;
3615 
3616   if (dpyinfo)
3617     {
3618       if (dpyinfo->resx > base_res)
3619 	*scale_x = floor (dpyinfo->resx / base_res);
3620       if (dpyinfo->resy > base_res)
3621 	*scale_y = floor (dpyinfo->resy / base_res);
3622     }
3623 }
3624 
3625 /*
3626    Draw a wavy line under S. The wave fills wave_height pixels from y0.
3627 
3628                     x0         wave_length = 2
3629                                  --
3630                 y0   *   *   *   *   *
3631                      |* * * * * * * * *
3632     wave_height = 3  | *   *   *   *
3633 
3634 */
3635 static void
x_draw_underwave(struct glyph_string * s)3636 x_draw_underwave (struct glyph_string *s)
3637 {
3638   Display *display = FRAME_X_DISPLAY (s->f);
3639 
3640   /* Adjust for scale/HiDPI.  */
3641   int scale_x, scale_y;
3642 
3643   x_get_scale_factor (display, &scale_x, &scale_y);
3644 
3645   int wave_height = 3 * scale_y, wave_length = 2 * scale_x;
3646 
3647 #ifdef USE_CAIRO
3648   x_draw_horizontal_wave (s->f, s->gc, s->x, s->ybase - wave_height + 3,
3649 			  s->width, wave_height, wave_length);
3650 #else  /* not USE_CAIRO */
3651   int dx, dy, x0, y0, width, x1, y1, x2, y2, xmax, thickness = scale_y;;
3652   bool odd;
3653   XRectangle wave_clip, string_clip, final_clip;
3654 
3655   dx = wave_length;
3656   dy = wave_height - 1;
3657   x0 = s->x;
3658   y0 = s->ybase + wave_height / 2 - scale_y;
3659   width = s->width;
3660   xmax = x0 + width;
3661 
3662   /* Find and set clipping rectangle */
3663 
3664   wave_clip.x = x0;
3665   wave_clip.y = y0;
3666   wave_clip.width = width;
3667   wave_clip.height = wave_height;
3668   get_glyph_string_clip_rect (s, &string_clip);
3669 
3670   if (!gui_intersect_rectangles (&wave_clip, &string_clip, &final_clip))
3671     return;
3672 
3673   XSetClipRectangles (display, s->gc, 0, 0, &final_clip, 1, Unsorted);
3674 
3675   /* Draw the waves */
3676 
3677   x1 = x0 - (x0 % dx);
3678   x2 = x1 + dx;
3679   odd = (x1 / dx) & 1;
3680   y1 = y2 = y0;
3681 
3682   if (odd)
3683     y1 += dy;
3684   else
3685     y2 += dy;
3686 
3687   if (INT_MAX - dx < xmax)
3688     emacs_abort ();
3689 
3690   while (x1 <= xmax)
3691     {
3692       XSetLineAttributes (display, s->gc, thickness, LineSolid, CapButt,
3693                           JoinRound);
3694       XDrawLine (display, FRAME_X_DRAWABLE (s->f), s->gc, x1, y1, x2, y2);
3695       x1  = x2, y1 = y2;
3696       x2 += dx, y2 = y0 + odd*dy;
3697       odd = !odd;
3698     }
3699 
3700   /* Restore previous clipping rectangle(s) */
3701   XSetClipRectangles (display, s->gc, 0, 0, s->clip, s->num_clips, Unsorted);
3702 #endif	/* not USE_CAIRO */
3703 }
3704 
3705 
3706 /* Draw glyph string S.  */
3707 
3708 static void
x_draw_glyph_string(struct glyph_string * s)3709 x_draw_glyph_string (struct glyph_string *s)
3710 {
3711   bool relief_drawn_p = false;
3712 
3713   /* If S draws into the background of its successors, draw the
3714      background of the successors first so that S can draw into it.
3715      This makes S->next use XDrawString instead of XDrawImageString.  */
3716   if (s->next && s->right_overhang && !s->for_overlaps)
3717     {
3718       int width;
3719       struct glyph_string *next;
3720 
3721       for (width = 0, next = s->next;
3722 	   next && width < s->right_overhang;
3723 	   width += next->width, next = next->next)
3724 	if (next->first_glyph->type != IMAGE_GLYPH)
3725 	  {
3726 	    x_set_glyph_string_gc (next);
3727 	    x_set_glyph_string_clipping (next);
3728 	    if (next->first_glyph->type == STRETCH_GLYPH)
3729 	      x_draw_stretch_glyph_string (next);
3730 	    else
3731 	      x_draw_glyph_string_background (next, true);
3732 	    next->num_clips = 0;
3733 	  }
3734     }
3735 
3736   /* Set up S->gc, set clipping and draw S.  */
3737   x_set_glyph_string_gc (s);
3738 
3739   /* Draw relief (if any) in advance for char/composition so that the
3740      glyph string can be drawn over it.  */
3741   if (!s->for_overlaps
3742       && s->face->box != FACE_NO_BOX
3743       && (s->first_glyph->type == CHAR_GLYPH
3744 	  || s->first_glyph->type == COMPOSITE_GLYPH))
3745 
3746     {
3747       x_set_glyph_string_clipping (s);
3748       x_draw_glyph_string_background (s, true);
3749       x_draw_glyph_string_box (s);
3750       x_set_glyph_string_clipping (s);
3751       relief_drawn_p = true;
3752     }
3753   else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */
3754 	   && !s->clip_tail
3755 	   && ((s->prev && s->prev->hl != s->hl && s->left_overhang)
3756 	       || (s->next && s->next->hl != s->hl && s->right_overhang)))
3757     /* We must clip just this glyph.  left_overhang part has already
3758        drawn when s->prev was drawn, and right_overhang part will be
3759        drawn later when s->next is drawn. */
3760     x_set_glyph_string_clipping_exactly (s, s);
3761   else
3762     x_set_glyph_string_clipping (s);
3763 
3764   switch (s->first_glyph->type)
3765     {
3766     case IMAGE_GLYPH:
3767       x_draw_image_glyph_string (s);
3768       break;
3769 
3770     case XWIDGET_GLYPH:
3771       x_draw_xwidget_glyph_string (s);
3772       break;
3773 
3774     case STRETCH_GLYPH:
3775       x_draw_stretch_glyph_string (s);
3776       break;
3777 
3778     case CHAR_GLYPH:
3779       if (s->for_overlaps)
3780 	s->background_filled_p = true;
3781       else
3782 	x_draw_glyph_string_background (s, false);
3783       x_draw_glyph_string_foreground (s);
3784       break;
3785 
3786     case COMPOSITE_GLYPH:
3787       if (s->for_overlaps || (s->cmp_from > 0
3788 			      && ! s->first_glyph->u.cmp.automatic))
3789 	s->background_filled_p = true;
3790       else
3791 	x_draw_glyph_string_background (s, true);
3792       x_draw_composite_glyph_string_foreground (s);
3793       break;
3794 
3795     case GLYPHLESS_GLYPH:
3796       if (s->for_overlaps)
3797 	s->background_filled_p = true;
3798       else
3799 	x_draw_glyph_string_background (s, true);
3800       x_draw_glyphless_glyph_string_foreground (s);
3801       break;
3802 
3803     default:
3804       emacs_abort ();
3805     }
3806 
3807   if (!s->for_overlaps)
3808     {
3809       /* Draw underline.  */
3810       if (s->face->underline)
3811         {
3812           if (s->face->underline == FACE_UNDER_WAVE)
3813             {
3814               if (s->face->underline_defaulted_p)
3815                 x_draw_underwave (s);
3816               else
3817                 {
3818                   Display *display = FRAME_X_DISPLAY (s->f);
3819                   XGCValues xgcv;
3820                   XGetGCValues (display, s->gc, GCForeground, &xgcv);
3821                   XSetForeground (display, s->gc, s->face->underline_color);
3822                   x_draw_underwave (s);
3823                   XSetForeground (display, s->gc, xgcv.foreground);
3824                 }
3825             }
3826           else if (s->face->underline == FACE_UNDER_LINE)
3827             {
3828               unsigned long thickness, position;
3829               int y;
3830 
3831               if (s->prev &&
3832 	          s->prev->face->underline == FACE_UNDER_LINE)
3833                 {
3834                   /* We use the same underline style as the previous one.  */
3835                   thickness = s->prev->underline_thickness;
3836                   position = s->prev->underline_position;
3837                 }
3838               else
3839                 {
3840 		  struct font *font = font_for_underline_metrics (s);
3841 		  unsigned long minimum_offset;
3842 		  bool underline_at_descent_line;
3843 		  bool use_underline_position_properties;
3844 		  Lisp_Object val = (WINDOW_BUFFER_LOCAL_VALUE
3845 				     (Qunderline_minimum_offset, s->w));
3846 
3847 		  if (FIXNUMP (val))
3848 		    minimum_offset = max (0, XFIXNUM (val));
3849 		  else
3850 		    minimum_offset = 1;
3851 
3852 		  val = (WINDOW_BUFFER_LOCAL_VALUE
3853 			 (Qx_underline_at_descent_line, s->w));
3854 		  underline_at_descent_line
3855 		    = !(NILP (val) || EQ (val, Qunbound));
3856 
3857 		  val = (WINDOW_BUFFER_LOCAL_VALUE
3858 			 (Qx_use_underline_position_properties, s->w));
3859 		  use_underline_position_properties
3860 		    = !(NILP (val) || EQ (val, Qunbound));
3861 
3862                   /* Get the underline thickness.  Default is 1 pixel.  */
3863                   if (font && font->underline_thickness > 0)
3864                     thickness = font->underline_thickness;
3865                   else
3866                     thickness = 1;
3867                   if (underline_at_descent_line)
3868                     position = (s->height - thickness) - (s->ybase - s->y);
3869                   else
3870                     {
3871                       /* Get the underline position.  This is the
3872                          recommended vertical offset in pixels from
3873                          the baseline to the top of the underline.
3874                          This is a signed value according to the
3875                          specs, and its default is
3876 
3877                          ROUND ((maximum descent) / 2), with
3878                          ROUND(x) = floor (x + 0.5)  */
3879 
3880                       if (use_underline_position_properties
3881                           && font && font->underline_position >= 0)
3882                         position = font->underline_position;
3883                       else if (font)
3884                         position = (font->descent + 1) / 2;
3885                       else
3886                         position = minimum_offset;
3887                     }
3888                   position = max (position, minimum_offset);
3889                 }
3890               /* Check the sanity of thickness and position.  We should
3891                  avoid drawing underline out of the current line area.  */
3892               if (s->y + s->height <= s->ybase + position)
3893                 position = (s->height - 1) - (s->ybase - s->y);
3894               if (s->y + s->height < s->ybase + position + thickness)
3895                 thickness = (s->y + s->height) - (s->ybase + position);
3896               s->underline_thickness = thickness;
3897               s->underline_position = position;
3898               y = s->ybase + position;
3899               if (s->face->underline_defaulted_p)
3900                 x_fill_rectangle (s->f, s->gc,
3901                                 s->x, y, s->width, thickness);
3902               else
3903                 {
3904                   Display *display = FRAME_X_DISPLAY (s->f);
3905                   XGCValues xgcv;
3906                   XGetGCValues (display, s->gc, GCForeground, &xgcv);
3907                   XSetForeground (display, s->gc, s->face->underline_color);
3908                   x_fill_rectangle (s->f, s->gc,
3909                                   s->x, y, s->width, thickness);
3910                   XSetForeground (display, s->gc, xgcv.foreground);
3911                 }
3912             }
3913         }
3914       /* Draw overline.  */
3915       if (s->face->overline_p)
3916 	{
3917 	  unsigned long dy = 0, h = 1;
3918 
3919 	  if (s->face->overline_color_defaulted_p)
3920 	    x_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3921 			    s->width, h);
3922 	  else
3923 	    {
3924               Display *display = FRAME_X_DISPLAY (s->f);
3925 	      XGCValues xgcv;
3926 	      XGetGCValues (display, s->gc, GCForeground, &xgcv);
3927 	      XSetForeground (display, s->gc, s->face->overline_color);
3928 	      x_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3929 			      s->width, h);
3930 	      XSetForeground (display, s->gc, xgcv.foreground);
3931 	    }
3932 	}
3933 
3934       /* Draw strike-through.  */
3935       if (s->face->strike_through_p)
3936 	{
3937 	  /* Y-coordinate and height of the glyph string's first
3938 	     glyph.  We cannot use s->y and s->height because those
3939 	     could be larger if there are taller display elements
3940 	     (e.g., characters displayed with a larger font) in the
3941 	     same glyph row.  */
3942 	  int glyph_y = s->ybase - s->first_glyph->ascent;
3943 	  int glyph_height = s->first_glyph->ascent + s->first_glyph->descent;
3944 	  /* Strike-through width and offset from the glyph string's
3945 	     top edge.  */
3946           unsigned long h = 1;
3947           unsigned long dy = (glyph_height - h) / 2;
3948 
3949 	  if (s->face->strike_through_color_defaulted_p)
3950 	    x_fill_rectangle (s->f, s->gc, s->x, glyph_y + dy,
3951 			    s->width, h);
3952 	  else
3953 	    {
3954               Display *display = FRAME_X_DISPLAY (s->f);
3955 	      XGCValues xgcv;
3956 	      XGetGCValues (display, s->gc, GCForeground, &xgcv);
3957 	      XSetForeground (display, s->gc, s->face->strike_through_color);
3958 	      x_fill_rectangle (s->f, s->gc, s->x, glyph_y + dy,
3959 			      s->width, h);
3960 	      XSetForeground (display, s->gc, xgcv.foreground);
3961 	    }
3962 	}
3963 
3964       /* Draw relief if not yet drawn.  */
3965       if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
3966 	x_draw_glyph_string_box (s);
3967 
3968       if (s->prev)
3969 	{
3970 	  struct glyph_string *prev;
3971 
3972 	  for (prev = s->prev; prev; prev = prev->prev)
3973 	    if (prev->hl != s->hl
3974 		&& prev->x + prev->width + prev->right_overhang > s->x)
3975 	      {
3976 		/* As prev was drawn while clipped to its own area, we
3977 		   must draw the right_overhang part using s->hl now.  */
3978 		enum draw_glyphs_face save = prev->hl;
3979 
3980 		prev->hl = s->hl;
3981 		x_set_glyph_string_gc (prev);
3982 		x_set_glyph_string_clipping_exactly (s, prev);
3983 		if (prev->first_glyph->type == CHAR_GLYPH)
3984 		  x_draw_glyph_string_foreground (prev);
3985 		else
3986 		  x_draw_composite_glyph_string_foreground (prev);
3987 		x_reset_clip_rectangles (prev->f, prev->gc);
3988 		prev->hl = save;
3989 		prev->num_clips = 0;
3990 	      }
3991 	}
3992 
3993       if (s->next)
3994 	{
3995 	  struct glyph_string *next;
3996 
3997 	  for (next = s->next; next; next = next->next)
3998 	    if (next->hl != s->hl
3999 		&& next->x - next->left_overhang < s->x + s->width)
4000 	      {
4001 		/* As next will be drawn while clipped to its own area,
4002 		   we must draw the left_overhang part using s->hl now.  */
4003 		enum draw_glyphs_face save = next->hl;
4004 
4005 		next->hl = s->hl;
4006 		x_set_glyph_string_gc (next);
4007 		x_set_glyph_string_clipping_exactly (s, next);
4008 		if (next->first_glyph->type == CHAR_GLYPH)
4009 		  x_draw_glyph_string_foreground (next);
4010 		else
4011 		  x_draw_composite_glyph_string_foreground (next);
4012 		x_reset_clip_rectangles (next->f, next->gc);
4013 		next->hl = save;
4014 		next->num_clips = 0;
4015 		next->clip_head = s->next;
4016 	      }
4017 	}
4018     }
4019 
4020   /* Reset clipping.  */
4021   x_reset_clip_rectangles (s->f, s->gc);
4022   s->num_clips = 0;
4023 }
4024 
4025 /* Shift display to make room for inserted glyphs.   */
4026 
4027 static void
x_shift_glyphs_for_insert(struct frame * f,int x,int y,int width,int height,int shift_by)4028 x_shift_glyphs_for_insert (struct frame *f, int x, int y, int width, int height, int shift_by)
4029 {
4030 /* Never called on a GUI frame, see
4031    https://lists.gnu.org/r/emacs-devel/2015-05/msg00456.html
4032 */
4033   XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), FRAME_X_DRAWABLE (f),
4034 	     f->output_data.x->normal_gc,
4035 	     x, y, width, height,
4036 	     x + shift_by, y);
4037 }
4038 
4039 /* Delete N glyphs at the nominal cursor position.  Not implemented
4040    for X frames.  */
4041 
4042 static void
x_delete_glyphs(struct frame * f,int n)4043 x_delete_glyphs (struct frame *f, int n)
4044 {
4045   emacs_abort ();
4046 }
4047 
4048 
4049 /* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
4050    If they are <= 0, this is probably an error.  */
4051 
4052 static ATTRIBUTE_UNUSED void
x_clear_area1(Display * dpy,Window window,int x,int y,int width,int height,int exposures)4053 x_clear_area1 (Display *dpy, Window window,
4054                int x, int y, int width, int height, int exposures)
4055 {
4056   eassert (width > 0 && height > 0);
4057   XClearArea (dpy, window, x, y, width, height, exposures);
4058 }
4059 
4060 void
x_clear_area(struct frame * f,int x,int y,int width,int height)4061 x_clear_area (struct frame *f, int x, int y, int width, int height)
4062 {
4063 #ifdef USE_CAIRO
4064   cairo_t *cr;
4065 
4066   eassert (width > 0 && height > 0);
4067 
4068   cr = x_begin_cr_clip (f, NULL);
4069   x_set_cr_source_with_gc_background (f, f->output_data.x->normal_gc);
4070   cairo_rectangle (cr, x, y, width, height);
4071   cairo_fill (cr);
4072   x_end_cr_clip (f);
4073 #else
4074   if (FRAME_X_DOUBLE_BUFFERED_P (f))
4075     XFillRectangle (FRAME_X_DISPLAY (f),
4076 		    FRAME_X_DRAWABLE (f),
4077 		    f->output_data.x->reverse_gc,
4078 		    x, y, width, height);
4079   else
4080     x_clear_area1 (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4081                    x, y, width, height, False);
4082 #endif
4083 }
4084 
4085 
4086 /* Clear an entire frame.  */
4087 
4088 static void
x_clear_frame(struct frame * f)4089 x_clear_frame (struct frame *f)
4090 {
4091   /* Clearing the frame will erase any cursor, so mark them all as no
4092      longer visible.  */
4093   mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
4094 
4095   block_input ();
4096 
4097   font_drop_xrender_surfaces (f);
4098   x_clear_window (f);
4099 
4100   /* We have to clear the scroll bars.  If we have changed colors or
4101      something like that, then they should be notified.  */
4102   x_scroll_bar_clear (f);
4103 
4104   XFlush (FRAME_X_DISPLAY (f));
4105 
4106   unblock_input ();
4107 }
4108 
4109 /* RIF: Show hourglass cursor on frame F.  */
4110 
4111 static void
x_show_hourglass(struct frame * f)4112 x_show_hourglass (struct frame *f)
4113 {
4114   Display *dpy = FRAME_X_DISPLAY (f);
4115 
4116   if (dpy)
4117     {
4118       struct x_output *x = FRAME_X_OUTPUT (f);
4119 #ifdef USE_X_TOOLKIT
4120       if (x->widget)
4121 #else
4122       if (FRAME_OUTER_WINDOW (f))
4123 #endif
4124        {
4125          x->hourglass_p = true;
4126 
4127          if (!x->hourglass_window)
4128            {
4129 	     unsigned long mask = CWCursor;
4130 	     XSetWindowAttributes attrs;
4131 #ifdef USE_GTK
4132              Window parent = FRAME_X_WINDOW (f);
4133 #else
4134              Window parent = FRAME_OUTER_WINDOW (f);
4135 #endif
4136 	     attrs.cursor = x->hourglass_cursor;
4137 
4138              x->hourglass_window = XCreateWindow
4139                (dpy, parent, 0, 0, 32000, 32000, 0, 0,
4140                 InputOnly, CopyFromParent, mask, &attrs);
4141            }
4142 
4143          XMapRaised (dpy, x->hourglass_window);
4144          XFlush (dpy);
4145        }
4146     }
4147 }
4148 
4149 /* RIF: Cancel hourglass cursor on frame F.  */
4150 
4151 static void
x_hide_hourglass(struct frame * f)4152 x_hide_hourglass (struct frame *f)
4153 {
4154   struct x_output *x = FRAME_X_OUTPUT (f);
4155 
4156   /* Watch out for newly created frames.  */
4157   if (x->hourglass_window)
4158     {
4159       XUnmapWindow (FRAME_X_DISPLAY (f), x->hourglass_window);
4160       /* Sync here because XTread_socket looks at the
4161 	 hourglass_p flag that is reset to zero below.  */
4162       XSync (FRAME_X_DISPLAY (f), False);
4163       x->hourglass_p = false;
4164     }
4165 }
4166 
4167 /* Invert the middle quarter of the frame for .15 sec.  */
4168 
4169 static void
XTflash(struct frame * f)4170 XTflash (struct frame *f)
4171 {
4172   block_input ();
4173 
4174   {
4175 #ifdef USE_GTK
4176     /* Use Gdk routines to draw.  This way, we won't draw over scroll bars
4177        when the scroll bars and the edit widget share the same X window.  */
4178     GdkWindow *window = gtk_widget_get_window (FRAME_GTK_WIDGET (f));
4179 #ifdef HAVE_GTK3
4180 #if GTK_CHECK_VERSION (3, 22, 0)
4181     cairo_region_t *region = gdk_window_get_visible_region (window);
4182     GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region);
4183     cairo_t *cr = gdk_drawing_context_get_cairo_context (context);
4184 #else
4185     cairo_t *cr = gdk_cairo_create (window);
4186 #endif
4187     cairo_set_source_rgb (cr, 1, 1, 1);
4188     cairo_set_operator (cr, CAIRO_OPERATOR_DIFFERENCE);
4189 #define XFillRectangle(d, win, gc, x, y, w, h) \
4190     do {                                       \
4191       cairo_rectangle (cr, x, y, w, h);        \
4192       cairo_fill (cr);                         \
4193     }                                          \
4194     while (false)
4195 #else /* ! HAVE_GTK3 */
4196     GdkGCValues vals;
4197     GdkGC *gc;
4198     vals.foreground.pixel = (FRAME_FOREGROUND_PIXEL (f)
4199                              ^ FRAME_BACKGROUND_PIXEL (f));
4200     vals.function = GDK_XOR;
4201     gc = gdk_gc_new_with_values (window,
4202                                  &vals, GDK_GC_FUNCTION | GDK_GC_FOREGROUND);
4203 #define XFillRectangle(d, win, gc, x, y, w, h) \
4204     gdk_draw_rectangle (window, gc, true, x, y, w, h)
4205 #endif /* ! HAVE_GTK3 */
4206 #else /* ! USE_GTK */
4207     GC gc;
4208 
4209     /* Create a GC that will use the GXxor function to flip foreground
4210        pixels into background pixels.  */
4211     {
4212       XGCValues values;
4213 
4214       values.function = GXxor;
4215       values.foreground = (FRAME_FOREGROUND_PIXEL (f)
4216 			   ^ FRAME_BACKGROUND_PIXEL (f));
4217 
4218       gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4219 		      GCFunction | GCForeground, &values);
4220     }
4221 #endif
4222     {
4223       /* Get the height not including a menu bar widget.  */
4224       int height = FRAME_PIXEL_HEIGHT (f);
4225       /* Height of each line to flash.  */
4226       int flash_height = FRAME_LINE_HEIGHT (f);
4227       /* These will be the left and right margins of the rectangles.  */
4228       int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
4229       int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
4230       int width = flash_right - flash_left;
4231 
4232       /* If window is tall, flash top and bottom line.  */
4233       if (height > 3 * FRAME_LINE_HEIGHT (f))
4234 	{
4235 	  XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
4236 			  flash_left,
4237 			  (FRAME_INTERNAL_BORDER_WIDTH (f)
4238 			   + FRAME_TOP_MARGIN_HEIGHT (f)),
4239 			  width, flash_height);
4240 	  XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
4241 			  flash_left,
4242 			  (height - flash_height
4243 			   - FRAME_INTERNAL_BORDER_WIDTH (f)),
4244 			  width, flash_height);
4245 
4246 	}
4247       else
4248 	/* If it is short, flash it all.  */
4249 	XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
4250 			flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
4251 			width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
4252 
4253       x_flush (f);
4254 
4255       {
4256 	struct timespec delay = make_timespec (0, 150 * 1000 * 1000);
4257 	struct timespec wakeup = timespec_add (current_timespec (), delay);
4258 
4259 	/* Keep waiting until past the time wakeup or any input gets
4260 	   available.  */
4261 	while (! detect_input_pending ())
4262 	  {
4263 	    struct timespec current = current_timespec ();
4264 	    struct timespec timeout;
4265 
4266 	    /* Break if result would not be positive.  */
4267 	    if (timespec_cmp (wakeup, current) <= 0)
4268 	      break;
4269 
4270 	    /* How long `select' should wait.  */
4271 	    timeout = make_timespec (0, 10 * 1000 * 1000);
4272 
4273 	    /* Try to wait that long--but we might wake up sooner.  */
4274 	    pselect (0, NULL, NULL, NULL, &timeout, NULL);
4275 	  }
4276       }
4277 
4278       /* If window is tall, flash top and bottom line.  */
4279       if (height > 3 * FRAME_LINE_HEIGHT (f))
4280 	{
4281 	  XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
4282 			  flash_left,
4283 			  (FRAME_INTERNAL_BORDER_WIDTH (f)
4284 			   + FRAME_TOP_MARGIN_HEIGHT (f)),
4285 			  width, flash_height);
4286 	  XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
4287 			  flash_left,
4288 			  (height - flash_height
4289 			   - FRAME_INTERNAL_BORDER_WIDTH (f)),
4290 			  width, flash_height);
4291 	}
4292       else
4293 	/* If it is short, flash it all.  */
4294 	XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
4295 			flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
4296 			width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
4297 
4298 #ifdef USE_GTK
4299 #ifdef HAVE_GTK3
4300 #if GTK_CHECK_VERSION (3, 22, 0)
4301       gdk_window_end_draw_frame (window, context);
4302       cairo_region_destroy (region);
4303 #else
4304       cairo_destroy (cr);
4305 #endif
4306 #else
4307       g_object_unref (G_OBJECT (gc));
4308 #endif
4309 #undef XFillRectangle
4310 #else
4311       XFreeGC (FRAME_X_DISPLAY (f), gc);
4312 #endif
4313       x_flush (f);
4314     }
4315   }
4316 
4317   unblock_input ();
4318 }
4319 
4320 
4321 static void
XTtoggle_invisible_pointer(struct frame * f,bool invisible)4322 XTtoggle_invisible_pointer (struct frame *f, bool invisible)
4323 {
4324   block_input ();
4325   FRAME_DISPLAY_INFO (f)->toggle_visible_pointer (f, invisible);
4326   unblock_input ();
4327 }
4328 
4329 
4330 /* Make audible bell.  */
4331 
4332 static void
XTring_bell(struct frame * f)4333 XTring_bell (struct frame *f)
4334 {
4335   if (FRAME_X_DISPLAY (f))
4336     {
4337       if (visible_bell)
4338 	XTflash (f);
4339       else
4340 	{
4341 	  block_input ();
4342 #ifdef HAVE_XKB
4343           XkbBell (FRAME_X_DISPLAY (f), None, 0, None);
4344 #else
4345 	  XBell (FRAME_X_DISPLAY (f), 0);
4346 #endif
4347 	  XFlush (FRAME_X_DISPLAY (f));
4348 	  unblock_input ();
4349 	}
4350     }
4351 }
4352 
4353 /***********************************************************************
4354 			      Line Dance
4355  ***********************************************************************/
4356 
4357 /* Perform an insert-lines or delete-lines operation, inserting N
4358    lines or deleting -N lines at vertical position VPOS.  */
4359 
4360 static void
x_ins_del_lines(struct frame * f,int vpos,int n)4361 x_ins_del_lines (struct frame *f, int vpos, int n)
4362 {
4363   emacs_abort ();
4364 }
4365 
4366 
4367 /* Scroll part of the display as described by RUN.  */
4368 
4369 static void
x_scroll_run(struct window * w,struct run * run)4370 x_scroll_run (struct window *w, struct run *run)
4371 {
4372   struct frame *f = XFRAME (w->frame);
4373   int x, y, width, height, from_y, to_y, bottom_y;
4374 
4375   /* Get frame-relative bounding box of the text display area of W,
4376      without mode lines.  Include in this box the left and right
4377      fringe of W.  */
4378   window_box (w, ANY_AREA, &x, &y, &width, &height);
4379 
4380   from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
4381   to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
4382   bottom_y = y + height;
4383 
4384   if (to_y < from_y)
4385     {
4386       /* Scrolling up.  Make sure we don't copy part of the mode
4387 	 line at the bottom.  */
4388       if (from_y + run->height > bottom_y)
4389 	height = bottom_y - from_y;
4390       else
4391 	height = run->height;
4392     }
4393   else
4394     {
4395       /* Scrolling down.  Make sure we don't copy over the mode line.
4396 	 at the bottom.  */
4397       if (to_y + run->height > bottom_y)
4398 	height = bottom_y - to_y;
4399       else
4400 	height = run->height;
4401     }
4402 
4403   block_input ();
4404 
4405   /* Cursor off.  Will be switched on again in gui_update_window_end.  */
4406   gui_clear_cursor (w);
4407 
4408 #ifdef USE_CAIRO
4409   if (FRAME_CR_CONTEXT (f))
4410     {
4411       cairo_surface_t *surface = cairo_get_target (FRAME_CR_CONTEXT (f));
4412       if (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_XLIB)
4413 	{
4414 	  eassert (cairo_xlib_surface_get_display (surface)
4415 		   == FRAME_X_DISPLAY (f));
4416 	  eassert (cairo_xlib_surface_get_drawable (surface)
4417 		   == FRAME_X_RAW_DRAWABLE (f));
4418 	  cairo_surface_flush (surface);
4419 	  XCopyArea (FRAME_X_DISPLAY (f),
4420 		     FRAME_X_DRAWABLE (f), FRAME_X_DRAWABLE (f),
4421 		     f->output_data.x->normal_gc,
4422 		     x, from_y,
4423 		     width, height,
4424 		     x, to_y);
4425 	  cairo_surface_mark_dirty_rectangle (surface, x, to_y, width, height);
4426 	}
4427       else
4428 	{
4429 	  cairo_surface_t *s
4430 	    = cairo_surface_create_similar (surface,
4431 					    cairo_surface_get_content (surface),
4432 					    width, height);
4433 	  cairo_t *cr = cairo_create (s);
4434 	  cairo_set_source_surface (cr, surface, -x, -from_y);
4435 	  cairo_paint (cr);
4436 	  cairo_destroy (cr);
4437 
4438 	  cr = FRAME_CR_CONTEXT (f);
4439 	  cairo_save (cr);
4440 	  cairo_set_source_surface (cr, s, x, to_y);
4441 	  cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
4442 	  cairo_rectangle (cr, x, to_y, width, height);
4443 	  cairo_fill (cr);
4444 	  cairo_restore (cr);
4445 	  cairo_surface_destroy (s);
4446 	}
4447     }
4448   else
4449 #endif	/* USE_CAIRO */
4450     XCopyArea (FRAME_X_DISPLAY (f),
4451 	       FRAME_X_DRAWABLE (f), FRAME_X_DRAWABLE (f),
4452 	       f->output_data.x->normal_gc,
4453 	       x, from_y,
4454 	       width, height,
4455 	       x, to_y);
4456 
4457   unblock_input ();
4458 }
4459 
4460 
4461 
4462 /***********************************************************************
4463 			   Exposure Events
4464  ***********************************************************************/
4465 
4466 
4467 static void
x_frame_highlight(struct frame * f)4468 x_frame_highlight (struct frame *f)
4469 {
4470   /* We used to only do this if Vx_no_window_manager was non-nil, but
4471      the ICCCM (section 4.1.6) says that the window's border pixmap
4472      and border pixel are window attributes which are "private to the
4473      client", so we can always change it to whatever we want.  */
4474   block_input ();
4475   /* I recently started to get errors in this XSetWindowBorder, depending on
4476      the window-manager in use, tho something more is at play since I've been
4477      using that same window-manager binary for ever.  Let's not crash just
4478      because of this (bug#9310).  */
4479   x_catch_errors (FRAME_X_DISPLAY (f));
4480   XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4481 		    f->output_data.x->border_pixel);
4482   x_uncatch_errors ();
4483   unblock_input ();
4484   gui_update_cursor (f, true);
4485   x_set_frame_alpha (f);
4486 }
4487 
4488 static void
x_frame_unhighlight(struct frame * f)4489 x_frame_unhighlight (struct frame *f)
4490 {
4491   /* We used to only do this if Vx_no_window_manager was non-nil, but
4492      the ICCCM (section 4.1.6) says that the window's border pixmap
4493      and border pixel are window attributes which are "private to the
4494      client", so we can always change it to whatever we want.  */
4495   block_input ();
4496   /* Same as above for XSetWindowBorder (bug#9310).  */
4497   x_catch_errors (FRAME_X_DISPLAY (f));
4498   XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4499 			  f->output_data.x->border_tile);
4500   x_uncatch_errors ();
4501   unblock_input ();
4502   gui_update_cursor (f, true);
4503   x_set_frame_alpha (f);
4504 }
4505 
4506 /* The focus has changed.  Update the frames as necessary to reflect
4507    the new situation.  Note that we can't change the selected frame
4508    here, because the Lisp code we are interrupting might become confused.
4509    Each event gets marked with the frame in which it occurred, so the
4510    Lisp code can tell when the switch took place by examining the events.  */
4511 
4512 static void
x_new_focus_frame(struct x_display_info * dpyinfo,struct frame * frame)4513 x_new_focus_frame (struct x_display_info *dpyinfo, struct frame *frame)
4514 {
4515   struct frame *old_focus = dpyinfo->x_focus_frame;
4516 
4517   if (frame != dpyinfo->x_focus_frame)
4518     {
4519       /* Set this before calling other routines, so that they see
4520 	 the correct value of x_focus_frame.  */
4521       dpyinfo->x_focus_frame = frame;
4522 
4523       if (old_focus && old_focus->auto_lower)
4524 	x_lower_frame (old_focus);
4525 
4526       if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
4527 	dpyinfo->x_pending_autoraise_frame = dpyinfo->x_focus_frame;
4528       else
4529 	dpyinfo->x_pending_autoraise_frame = NULL;
4530     }
4531 
4532   x_frame_rehighlight (dpyinfo);
4533 }
4534 
4535 /* Handle FocusIn and FocusOut state changes for FRAME.
4536    If FRAME has focus and there exists more than one frame, puts
4537    a FOCUS_IN_EVENT into *BUFP.  */
4538 
4539 static void
x_focus_changed(int type,int state,struct x_display_info * dpyinfo,struct frame * frame,struct input_event * bufp)4540 x_focus_changed (int type, int state, struct x_display_info *dpyinfo, struct frame *frame, struct input_event *bufp)
4541 {
4542   if (type == FocusIn)
4543     {
4544       if (dpyinfo->x_focus_event_frame != frame)
4545         {
4546           x_new_focus_frame (dpyinfo, frame);
4547           dpyinfo->x_focus_event_frame = frame;
4548           bufp->kind = FOCUS_IN_EVENT;
4549           XSETFRAME (bufp->frame_or_window, frame);
4550         }
4551 
4552       frame->output_data.x->focus_state |= state;
4553 
4554 #ifdef HAVE_X_I18N
4555       if (FRAME_XIC (frame))
4556         XSetICFocus (FRAME_XIC (frame));
4557 #endif
4558     }
4559   else if (type == FocusOut)
4560     {
4561       frame->output_data.x->focus_state &= ~state;
4562 
4563       if (dpyinfo->x_focus_event_frame == frame)
4564         {
4565           dpyinfo->x_focus_event_frame = 0;
4566           x_new_focus_frame (dpyinfo, 0);
4567 
4568           bufp->kind = FOCUS_OUT_EVENT;
4569           XSETFRAME (bufp->frame_or_window, frame);
4570         }
4571 
4572 #ifdef HAVE_X_I18N
4573       if (FRAME_XIC (frame))
4574         XUnsetICFocus (FRAME_XIC (frame));
4575 #endif
4576       if (frame->pointer_invisible)
4577         XTtoggle_invisible_pointer (frame, false);
4578     }
4579 }
4580 
4581 /* Return the Emacs frame-object corresponding to an X window.
4582    It could be the frame's main window or an icon window.  */
4583 
4584 static struct frame *
x_window_to_frame(struct x_display_info * dpyinfo,int wdesc)4585 x_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
4586 {
4587   Lisp_Object tail, frame;
4588   struct frame *f;
4589 
4590   if (wdesc == None)
4591     return NULL;
4592 
4593   FOR_EACH_FRAME (tail, frame)
4594     {
4595       f = XFRAME (frame);
4596       if (!FRAME_X_P (f) || FRAME_DISPLAY_INFO (f) != dpyinfo)
4597 	continue;
4598       if (f->output_data.x->hourglass_window == wdesc)
4599 	return f;
4600 #ifdef USE_X_TOOLKIT
4601       if ((f->output_data.x->edit_widget
4602 	   && XtWindow (f->output_data.x->edit_widget) == wdesc)
4603 	  /* A tooltip frame?  */
4604 	  || (!f->output_data.x->edit_widget
4605 	      && FRAME_X_WINDOW (f) == wdesc)
4606           || f->output_data.x->icon_desc == wdesc)
4607         return f;
4608 #else /* not USE_X_TOOLKIT */
4609 #ifdef USE_GTK
4610       if (f->output_data.x->edit_widget)
4611       {
4612         GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
4613         struct x_output *x = f->output_data.x;
4614         if (gwdesc != 0 && gwdesc == x->edit_widget)
4615           return f;
4616       }
4617 #endif /* USE_GTK */
4618       if (FRAME_X_WINDOW (f) == wdesc
4619           || f->output_data.x->icon_desc == wdesc)
4620         return f;
4621 #endif /* not USE_X_TOOLKIT */
4622     }
4623   return 0;
4624 }
4625 
4626 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
4627 
4628 /* Like x_window_to_frame but also compares the window with the widget's
4629    windows.  */
4630 
4631 static struct frame *
x_any_window_to_frame(struct x_display_info * dpyinfo,int wdesc)4632 x_any_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
4633 {
4634   Lisp_Object tail, frame;
4635   struct frame *f, *found = NULL;
4636   struct x_output *x;
4637 
4638   if (wdesc == None)
4639     return NULL;
4640 
4641   FOR_EACH_FRAME (tail, frame)
4642     {
4643       if (found)
4644         break;
4645       f = XFRAME (frame);
4646       if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) == dpyinfo)
4647 	{
4648 	  /* This frame matches if the window is any of its widgets.  */
4649 	  x = f->output_data.x;
4650 	  if (x->hourglass_window == wdesc)
4651 	    found = f;
4652 	  else if (x->widget)
4653 	    {
4654 #ifdef USE_GTK
4655               GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
4656               if (gwdesc != 0
4657                   && gtk_widget_get_toplevel (gwdesc) == x->widget)
4658                 found = f;
4659 #else
4660 	      if (wdesc == XtWindow (x->widget)
4661 		  || wdesc == XtWindow (x->column_widget)
4662 		  || wdesc == XtWindow (x->edit_widget))
4663 		found = f;
4664 	      /* Match if the window is this frame's menubar.  */
4665 	      else if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
4666 		found = f;
4667 #endif
4668 	    }
4669 	  else if (FRAME_X_WINDOW (f) == wdesc)
4670 	    /* A tooltip frame.  */
4671 	    found = f;
4672 	}
4673     }
4674 
4675   return found;
4676 }
4677 
4678 /* Likewise, but consider only the menu bar widget.  */
4679 
4680 static struct frame *
x_menubar_window_to_frame(struct x_display_info * dpyinfo,const XEvent * event)4681 x_menubar_window_to_frame (struct x_display_info *dpyinfo,
4682 			   const XEvent *event)
4683 {
4684   Window wdesc = event->xany.window;
4685   Lisp_Object tail, frame;
4686   struct frame *f;
4687   struct x_output *x;
4688 
4689   if (wdesc == None)
4690     return NULL;
4691 
4692   FOR_EACH_FRAME (tail, frame)
4693     {
4694       f = XFRAME (frame);
4695       if (!FRAME_X_P (f) || FRAME_DISPLAY_INFO (f) != dpyinfo)
4696 	continue;
4697       x = f->output_data.x;
4698 #ifdef USE_GTK
4699       if (x->menubar_widget && xg_event_is_for_menubar (f, event))
4700         return f;
4701 #else
4702       /* Match if the window is this frame's menubar.  */
4703       if (x->menubar_widget
4704 	  && lw_window_is_in_menubar (wdesc, x->menubar_widget))
4705 	return f;
4706 #endif
4707     }
4708   return 0;
4709 }
4710 
4711 /* Return the frame whose principal (outermost) window is WDESC.
4712    If WDESC is some other (smaller) window, we return 0.  */
4713 
4714 struct frame *
x_top_window_to_frame(struct x_display_info * dpyinfo,int wdesc)4715 x_top_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
4716 {
4717   Lisp_Object tail, frame;
4718   struct frame *f;
4719   struct x_output *x;
4720 
4721   if (wdesc == None)
4722     return NULL;
4723 
4724   FOR_EACH_FRAME (tail, frame)
4725     {
4726       f = XFRAME (frame);
4727       if (!FRAME_X_P (f) || FRAME_DISPLAY_INFO (f) != dpyinfo)
4728 	continue;
4729       x = f->output_data.x;
4730 
4731       if (x->widget)
4732 	{
4733 	  /* This frame matches if the window is its topmost widget.  */
4734 #ifdef USE_GTK
4735           GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
4736           if (gwdesc == x->widget)
4737             return f;
4738 #else
4739 	  if (wdesc == XtWindow (x->widget))
4740 	    return f;
4741 #endif
4742 	}
4743       else if (FRAME_X_WINDOW (f) == wdesc)
4744 	/* Tooltip frame.  */
4745 	return f;
4746     }
4747   return 0;
4748 }
4749 
4750 #else /* !USE_X_TOOLKIT && !USE_GTK */
4751 
4752 #define x_any_window_to_frame(d, i) x_window_to_frame (d, i)
4753 #define x_top_window_to_frame(d, i) x_window_to_frame (d, i)
4754 
4755 #endif /* USE_X_TOOLKIT || USE_GTK */
4756 
4757 /* The focus may have changed.  Figure out if it is a real focus change,
4758    by checking both FocusIn/Out and Enter/LeaveNotify events.
4759 
4760    Returns FOCUS_IN_EVENT event in *BUFP. */
4761 
4762 static void
x_detect_focus_change(struct x_display_info * dpyinfo,struct frame * frame,const XEvent * event,struct input_event * bufp)4763 x_detect_focus_change (struct x_display_info *dpyinfo, struct frame *frame,
4764 		       const XEvent *event, struct input_event *bufp)
4765 {
4766   if (!frame)
4767     return;
4768 
4769   switch (event->type)
4770     {
4771     case EnterNotify:
4772     case LeaveNotify:
4773       {
4774         struct frame *focus_frame = dpyinfo->x_focus_event_frame;
4775         int focus_state
4776           = focus_frame ? focus_frame->output_data.x->focus_state : 0;
4777 
4778         if (event->xcrossing.detail != NotifyInferior
4779             && event->xcrossing.focus
4780             && ! (focus_state & FOCUS_EXPLICIT))
4781           x_focus_changed ((event->type == EnterNotify ? FocusIn : FocusOut),
4782 			   FOCUS_IMPLICIT,
4783 			   dpyinfo, frame, bufp);
4784       }
4785       break;
4786 
4787     case FocusIn:
4788     case FocusOut:
4789       x_focus_changed (event->type,
4790 		       (event->xfocus.detail == NotifyPointer ?
4791 			FOCUS_IMPLICIT : FOCUS_EXPLICIT),
4792 		       dpyinfo, frame, bufp);
4793       break;
4794 
4795     case ClientMessage:
4796       if (event->xclient.message_type == dpyinfo->Xatom_XEMBED)
4797 	{
4798 	  enum xembed_message msg = event->xclient.data.l[1];
4799 	  x_focus_changed ((msg == XEMBED_FOCUS_IN ? FocusIn : FocusOut),
4800 			   FOCUS_EXPLICIT, dpyinfo, frame, bufp);
4801 	}
4802       break;
4803     }
4804 }
4805 
4806 
4807 #if !defined USE_X_TOOLKIT && !defined USE_GTK
4808 /* Handle an event saying the mouse has moved out of an Emacs frame.  */
4809 
4810 void
x_mouse_leave(struct x_display_info * dpyinfo)4811 x_mouse_leave (struct x_display_info *dpyinfo)
4812 {
4813   x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
4814 }
4815 #endif
4816 
4817 /* The focus has changed, or we have redirected a frame's focus to
4818    another frame (this happens when a frame uses a surrogate
4819    mini-buffer frame).  Shift the highlight as appropriate.
4820 
4821    The FRAME argument doesn't necessarily have anything to do with which
4822    frame is being highlighted or un-highlighted; we only use it to find
4823    the appropriate X display info.  */
4824 
4825 static void
XTframe_rehighlight(struct frame * frame)4826 XTframe_rehighlight (struct frame *frame)
4827 {
4828   x_frame_rehighlight (FRAME_DISPLAY_INFO (frame));
4829 }
4830 
4831 static void
x_frame_rehighlight(struct x_display_info * dpyinfo)4832 x_frame_rehighlight (struct x_display_info *dpyinfo)
4833 {
4834   struct frame *old_highlight = dpyinfo->highlight_frame;
4835 
4836   if (dpyinfo->x_focus_frame)
4837     {
4838       dpyinfo->highlight_frame
4839 	= ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
4840 	   ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
4841 	   : dpyinfo->x_focus_frame);
4842       if (! FRAME_LIVE_P (dpyinfo->highlight_frame))
4843 	{
4844 	  fset_focus_frame (dpyinfo->x_focus_frame, Qnil);
4845 	  dpyinfo->highlight_frame = dpyinfo->x_focus_frame;
4846 	}
4847     }
4848   else
4849     dpyinfo->highlight_frame = 0;
4850 
4851   if (dpyinfo->highlight_frame != old_highlight)
4852     {
4853       if (old_highlight)
4854 	x_frame_unhighlight (old_highlight);
4855       if (dpyinfo->highlight_frame)
4856 	x_frame_highlight (dpyinfo->highlight_frame);
4857     }
4858 }
4859 
4860 
4861 
4862 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc.  */
4863 
4864 /* Initialize mode_switch_bit and modifier_meaning.  */
4865 static void
x_find_modifier_meanings(struct x_display_info * dpyinfo)4866 x_find_modifier_meanings (struct x_display_info *dpyinfo)
4867 {
4868   int min_code, max_code;
4869   KeySym *syms;
4870   int syms_per_code;
4871   XModifierKeymap *mods;
4872 
4873   dpyinfo->meta_mod_mask = 0;
4874   dpyinfo->shift_lock_mask = 0;
4875   dpyinfo->alt_mod_mask = 0;
4876   dpyinfo->super_mod_mask = 0;
4877   dpyinfo->hyper_mod_mask = 0;
4878 
4879   XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
4880 
4881   syms = XGetKeyboardMapping (dpyinfo->display,
4882 			      min_code, max_code - min_code + 1,
4883 			      &syms_per_code);
4884   mods = XGetModifierMapping (dpyinfo->display);
4885 
4886   /* Scan the modifier table to see which modifier bits the Meta and
4887      Alt keysyms are on.  */
4888   {
4889     int row, col;	/* The row and column in the modifier table.  */
4890     bool found_alt_or_meta;
4891 
4892     for (row = 3; row < 8; row++)
4893     {
4894       found_alt_or_meta = false;
4895       for (col = 0; col < mods->max_keypermod; col++)
4896 	{
4897 	  KeyCode code = mods->modifiermap[(row * mods->max_keypermod) + col];
4898 
4899 	  /* Zeroes are used for filler.  Skip them.  */
4900 	  if (code == 0)
4901 	    continue;
4902 
4903 	  /* Are any of this keycode's keysyms a meta key?  */
4904 	  {
4905 	    int code_col;
4906 
4907 	    for (code_col = 0; code_col < syms_per_code; code_col++)
4908 	      {
4909 		int sym = syms[((code - min_code) * syms_per_code) + code_col];
4910 
4911 		switch (sym)
4912 		  {
4913 		  case XK_Meta_L:
4914 		  case XK_Meta_R:
4915 		    found_alt_or_meta = true;
4916 		    dpyinfo->meta_mod_mask |= (1 << row);
4917 		    break;
4918 
4919 		  case XK_Alt_L:
4920 		  case XK_Alt_R:
4921 		    found_alt_or_meta = true;
4922 		    dpyinfo->alt_mod_mask |= (1 << row);
4923 		    break;
4924 
4925 		  case XK_Hyper_L:
4926 		  case XK_Hyper_R:
4927 		    if (!found_alt_or_meta)
4928 		      dpyinfo->hyper_mod_mask |= (1 << row);
4929 		    code_col = syms_per_code;
4930 		    col = mods->max_keypermod;
4931 		    break;
4932 
4933 		  case XK_Super_L:
4934 		  case XK_Super_R:
4935 		    if (!found_alt_or_meta)
4936 		      dpyinfo->super_mod_mask |= (1 << row);
4937 		    code_col = syms_per_code;
4938 		    col = mods->max_keypermod;
4939 		    break;
4940 
4941 		  case XK_Shift_Lock:
4942 		    /* Ignore this if it's not on the lock modifier.  */
4943 		    if (!found_alt_or_meta && ((1 << row) == LockMask))
4944 		      dpyinfo->shift_lock_mask = LockMask;
4945 		    code_col = syms_per_code;
4946 		    col = mods->max_keypermod;
4947 		    break;
4948 		  }
4949 	      }
4950 	  }
4951 	}
4952     }
4953   }
4954 
4955   /* If we couldn't find any meta keys, accept any alt keys as meta keys.  */
4956   if (! dpyinfo->meta_mod_mask)
4957     {
4958       dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
4959       dpyinfo->alt_mod_mask = 0;
4960     }
4961 
4962   /* If some keys are both alt and meta,
4963      make them just meta, not alt.  */
4964   if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
4965     {
4966       dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
4967     }
4968 
4969   XFree (syms);
4970   XFreeModifiermap (mods);
4971 }
4972 
4973 /* Convert between the modifier bits X uses and the modifier bits
4974    Emacs uses.  */
4975 
4976 int
x_x_to_emacs_modifiers(struct x_display_info * dpyinfo,int state)4977 x_x_to_emacs_modifiers (struct x_display_info *dpyinfo, int state)
4978 {
4979   int mod_ctrl = ctrl_modifier;
4980   int mod_meta = meta_modifier;
4981   int mod_alt  = alt_modifier;
4982   int mod_hyper = hyper_modifier;
4983   int mod_super = super_modifier;
4984   Lisp_Object tem;
4985 
4986   tem = Fget (Vx_ctrl_keysym, Qmodifier_value);
4987   if (FIXNUMP (tem)) mod_ctrl = XFIXNUM (tem) & INT_MAX;
4988   tem = Fget (Vx_alt_keysym, Qmodifier_value);
4989   if (FIXNUMP (tem)) mod_alt = XFIXNUM (tem) & INT_MAX;
4990   tem = Fget (Vx_meta_keysym, Qmodifier_value);
4991   if (FIXNUMP (tem)) mod_meta = XFIXNUM (tem) & INT_MAX;
4992   tem = Fget (Vx_hyper_keysym, Qmodifier_value);
4993   if (FIXNUMP (tem)) mod_hyper = XFIXNUM (tem) & INT_MAX;
4994   tem = Fget (Vx_super_keysym, Qmodifier_value);
4995   if (FIXNUMP (tem)) mod_super = XFIXNUM (tem) & INT_MAX;
4996 
4997   return (  ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
4998             | ((state & ControlMask)			? mod_ctrl	: 0)
4999             | ((state & dpyinfo->meta_mod_mask)		? mod_meta	: 0)
5000             | ((state & dpyinfo->alt_mod_mask)		? mod_alt	: 0)
5001             | ((state & dpyinfo->super_mod_mask)	? mod_super	: 0)
5002             | ((state & dpyinfo->hyper_mod_mask)	? mod_hyper	: 0));
5003 }
5004 
5005 static int
x_emacs_to_x_modifiers(struct x_display_info * dpyinfo,intmax_t state)5006 x_emacs_to_x_modifiers (struct x_display_info *dpyinfo, intmax_t state)
5007 {
5008   EMACS_INT mod_ctrl = ctrl_modifier;
5009   EMACS_INT mod_meta = meta_modifier;
5010   EMACS_INT mod_alt  = alt_modifier;
5011   EMACS_INT mod_hyper = hyper_modifier;
5012   EMACS_INT mod_super = super_modifier;
5013 
5014   Lisp_Object tem;
5015 
5016   tem = Fget (Vx_ctrl_keysym, Qmodifier_value);
5017   if (FIXNUMP (tem)) mod_ctrl = XFIXNUM (tem);
5018   tem = Fget (Vx_alt_keysym, Qmodifier_value);
5019   if (FIXNUMP (tem)) mod_alt = XFIXNUM (tem);
5020   tem = Fget (Vx_meta_keysym, Qmodifier_value);
5021   if (FIXNUMP (tem)) mod_meta = XFIXNUM (tem);
5022   tem = Fget (Vx_hyper_keysym, Qmodifier_value);
5023   if (FIXNUMP (tem)) mod_hyper = XFIXNUM (tem);
5024   tem = Fget (Vx_super_keysym, Qmodifier_value);
5025   if (FIXNUMP (tem)) mod_super = XFIXNUM (tem);
5026 
5027 
5028   return (  ((state & mod_alt)		? dpyinfo->alt_mod_mask   : 0)
5029             | ((state & mod_super)	? dpyinfo->super_mod_mask : 0)
5030             | ((state & mod_hyper)	? dpyinfo->hyper_mod_mask : 0)
5031             | ((state & shift_modifier)	? ShiftMask        : 0)
5032             | ((state & mod_ctrl)	? ControlMask      : 0)
5033             | ((state & mod_meta)	? dpyinfo->meta_mod_mask  : 0));
5034 }
5035 
5036 /* Convert a keysym to its name.  */
5037 
5038 char *
get_keysym_name(int keysym)5039 get_keysym_name (int keysym)
5040 {
5041   char *value;
5042 
5043   block_input ();
5044   value = XKeysymToString (keysym);
5045   unblock_input ();
5046 
5047   return value;
5048 }
5049 
5050 /* Mouse clicks and mouse movement.  Rah.
5051 
5052    Formerly, we used PointerMotionHintMask (in standard_event_mask)
5053    so that we would have to call XQueryPointer after each MotionNotify
5054    event to ask for another such event.  However, this made mouse tracking
5055    slow, and there was a bug that made it eventually stop.
5056 
5057    Simply asking for MotionNotify all the time seems to work better.
5058 
5059    In order to avoid asking for motion events and then throwing most
5060    of them away or busy-polling the server for mouse positions, we ask
5061    the server for pointer motion hints.  This means that we get only
5062    one event per group of mouse movements.  "Groups" are delimited by
5063    other kinds of events (focus changes and button clicks, for
5064    example), or by XQueryPointer calls; when one of these happens, we
5065    get another MotionNotify event the next time the mouse moves.  This
5066    is at least as efficient as getting motion events when mouse
5067    tracking is on, and I suspect only negligibly worse when tracking
5068    is off.  */
5069 
5070 /* Prepare a mouse-event in *RESULT for placement in the input queue.
5071 
5072    If the event is a button press, then note that we have grabbed
5073    the mouse.  */
5074 
5075 static Lisp_Object
x_construct_mouse_click(struct input_event * result,const XButtonEvent * event,struct frame * f)5076 x_construct_mouse_click (struct input_event *result,
5077                          const XButtonEvent *event,
5078                          struct frame *f)
5079 {
5080   /* Make the event type NO_EVENT; we'll change that when we decide
5081      otherwise.  */
5082   result->kind = MOUSE_CLICK_EVENT;
5083   result->code = event->button - Button1;
5084   result->timestamp = event->time;
5085   result->modifiers = (x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO (f),
5086 					       event->state)
5087 		       | (event->type == ButtonRelease
5088 			  ? up_modifier
5089 			  : down_modifier));
5090 
5091   XSETINT (result->x, event->x);
5092   XSETINT (result->y, event->y);
5093   XSETFRAME (result->frame_or_window, f);
5094   result->arg = Qnil;
5095   return Qnil;
5096 }
5097 
5098 /* Function to report a mouse movement to the mainstream Emacs code.
5099    The input handler calls this.
5100 
5101    We have received a mouse movement event, which is given in *event.
5102    If the mouse is over a different glyph than it was last time, tell
5103    the mainstream emacs code by setting mouse_moved.  If not, ask for
5104    another motion event, so we can check again the next time it moves.  */
5105 
5106 static bool
x_note_mouse_movement(struct frame * frame,const XMotionEvent * event)5107 x_note_mouse_movement (struct frame *frame, const XMotionEvent *event)
5108 {
5109   XRectangle *r;
5110   struct x_display_info *dpyinfo;
5111 
5112   if (!FRAME_X_OUTPUT (frame))
5113     return false;
5114 
5115   dpyinfo = FRAME_DISPLAY_INFO (frame);
5116   dpyinfo->last_mouse_movement_time = event->time;
5117   dpyinfo->last_mouse_motion_frame = frame;
5118   dpyinfo->last_mouse_motion_x = event->x;
5119   dpyinfo->last_mouse_motion_y = event->y;
5120 
5121   if (event->window != FRAME_X_WINDOW (frame))
5122     {
5123       frame->mouse_moved = true;
5124       dpyinfo->last_mouse_scroll_bar = NULL;
5125       note_mouse_highlight (frame, -1, -1);
5126       dpyinfo->last_mouse_glyph_frame = NULL;
5127       return true;
5128     }
5129 
5130 
5131   /* Has the mouse moved off the glyph it was on at the last sighting?  */
5132   r = &dpyinfo->last_mouse_glyph;
5133   if (frame != dpyinfo->last_mouse_glyph_frame
5134       || event->x < r->x || event->x >= r->x + r->width
5135       || event->y < r->y || event->y >= r->y + r->height)
5136     {
5137       frame->mouse_moved = true;
5138       dpyinfo->last_mouse_scroll_bar = NULL;
5139       note_mouse_highlight (frame, event->x, event->y);
5140       /* Remember which glyph we're now on.  */
5141       remember_mouse_glyph (frame, event->x, event->y, r);
5142       dpyinfo->last_mouse_glyph_frame = frame;
5143       return true;
5144     }
5145 
5146   return false;
5147 }
5148 
5149 /* Return the current position of the mouse.
5150    *FP should be a frame which indicates which display to ask about.
5151 
5152    If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
5153    and *PART to the frame, window, and scroll bar part that the mouse
5154    is over.  Set *X and *Y to the portion and whole of the mouse's
5155    position on the scroll bar.
5156 
5157    If the mouse movement started elsewhere, set *FP to the frame the
5158    mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
5159    the mouse is over.
5160 
5161    Set *TIMESTAMP to the server time-stamp for the time at which the mouse
5162    was at this position.
5163 
5164    Don't store anything if we don't have a valid set of values to report.
5165 
5166    This clears the mouse_moved flag, so we can wait for the next mouse
5167    movement.  */
5168 
5169 static void
XTmouse_position(struct frame ** fp,int insist,Lisp_Object * bar_window,enum scroll_bar_part * part,Lisp_Object * x,Lisp_Object * y,Time * timestamp)5170 XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
5171 		  enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
5172 		  Time *timestamp)
5173 {
5174   struct frame *f1;
5175   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp);
5176 
5177   block_input ();
5178 
5179   if (dpyinfo->last_mouse_scroll_bar && insist == 0)
5180     {
5181       struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar;
5182 
5183       if (bar->horizontal)
5184 	x_horizontal_scroll_bar_report_motion (fp, bar_window, part, x, y, timestamp);
5185       else
5186 	x_scroll_bar_report_motion (fp, bar_window, part, x, y, timestamp);
5187     }
5188   else
5189     {
5190       Window root;
5191       int root_x, root_y;
5192 
5193       Window dummy_window;
5194       int dummy;
5195 
5196       Lisp_Object frame, tail;
5197 
5198       /* Clear the mouse-moved flag for every frame on this display.  */
5199       FOR_EACH_FRAME (tail, frame)
5200 	if (FRAME_X_P (XFRAME (frame))
5201             && FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
5202 	  XFRAME (frame)->mouse_moved = false;
5203 
5204       dpyinfo->last_mouse_scroll_bar = NULL;
5205 
5206       /* Figure out which root window we're on.  */
5207       XQueryPointer (FRAME_X_DISPLAY (*fp),
5208 		     DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
5209 		     /* The root window which contains the pointer.  */
5210 		     &root,
5211 		     /* Trash which we can't trust if the pointer is on
5212 			a different screen.  */
5213 		     &dummy_window,
5214 		     /* The position on that root window.  */
5215 		     &root_x, &root_y,
5216 		     /* More trash we can't trust.  */
5217 		     &dummy, &dummy,
5218 		     /* Modifier keys and pointer buttons, about which
5219 			we don't care.  */
5220 		     (unsigned int *) &dummy);
5221 
5222       /* Now we have a position on the root; find the innermost window
5223 	 containing the pointer.  */
5224       {
5225 	Window win, child;
5226 #ifdef USE_GTK
5227 	Window first_win = 0;
5228 #endif
5229 	int win_x, win_y;
5230 	int parent_x = 0, parent_y = 0;
5231 
5232 	win = root;
5233 
5234 	/* XTranslateCoordinates can get errors if the window
5235 	   structure is changing at the same time this function
5236 	   is running.  So at least we must not crash from them.  */
5237 
5238 	x_catch_errors (FRAME_X_DISPLAY (*fp));
5239 
5240 	if (gui_mouse_grabbed (dpyinfo) && !EQ (track_mouse, Qdropping))
5241 	  {
5242 	    /* If mouse was grabbed on a frame, give coords for that frame
5243 	       even if the mouse is now outside it.  */
5244 	    XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
5245 				   /* From-window.  */
5246 				   root,
5247 				   /* To-window.  */
5248 				   FRAME_X_WINDOW (dpyinfo->last_mouse_frame),
5249 				   /* From-position, to-position.  */
5250 				   root_x, root_y, &win_x, &win_y,
5251 				   /* Child of win.  */
5252 				   &child);
5253 	    f1 = dpyinfo->last_mouse_frame;
5254 	  }
5255 	else
5256 	  {
5257 	    while (true)
5258 	      {
5259 		XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
5260 				       /* From-window, to-window.  */
5261 				       root, win,
5262 				       /* From-position, to-position.  */
5263 				       root_x, root_y, &win_x, &win_y,
5264 				       /* Child of win.  */
5265 				       &child);
5266 		if (child == None || child == win)
5267 		  {
5268 #ifdef USE_GTK
5269 		    /* On GTK we have not inspected WIN yet.  If it has
5270 		       a frame and that frame has a parent, use it.  */
5271 		    struct frame *f = x_window_to_frame (dpyinfo, win);
5272 
5273 		    if (f && FRAME_PARENT_FRAME (f))
5274 		      first_win = win;
5275 #endif
5276 		    break;
5277 		  }
5278 #ifdef USE_GTK
5279 		/* We don't wan't to know the innermost window.  We
5280 		   want the edit window.  For non-Gtk+ the innermost
5281 		   window is the edit window.  For Gtk+ it might not
5282 		   be.  It might be the tool bar for example.  */
5283 		if (x_window_to_frame (dpyinfo, win))
5284 		  /* But don't hurry.  We might find a child frame
5285 		     beneath.  */
5286 		  first_win = win;
5287 #endif
5288 		win = child;
5289 		parent_x = win_x;
5290 		parent_y = win_y;
5291 	      }
5292 
5293 #ifdef USE_GTK
5294 	    if (first_win)
5295 	      win = first_win;
5296 #endif
5297 
5298 	    /* Now we know that:
5299 	       win is the innermost window containing the pointer
5300 	       (XTC says it has no child containing the pointer),
5301 	       win_x and win_y are the pointer's position in it
5302 	       (XTC did this the last time through), and
5303 	       parent_x and parent_y are the pointer's position in win's parent.
5304 	       (They are what win_x and win_y were when win was child.
5305 	       If win is the root window, it has no parent, and
5306 	       parent_{x,y} are invalid, but that's okay, because we'll
5307 	       never use them in that case.)  */
5308 
5309 #ifdef USE_GTK
5310 	    /* We don't wan't to know the innermost window.  We
5311 	       want the edit window.  */
5312 	    f1 = x_window_to_frame (dpyinfo, win);
5313 #else
5314 	    /* Is win one of our frames?  */
5315 	    f1 = x_any_window_to_frame (dpyinfo, win);
5316 #endif
5317 
5318 #ifdef USE_X_TOOLKIT
5319 	    /* If we end up with the menu bar window, say it's not
5320 	       on the frame.  */
5321 	    if (f1 != NULL
5322 		&& f1->output_data.x->menubar_widget
5323 		&& win == XtWindow (f1->output_data.x->menubar_widget))
5324 	      f1 = NULL;
5325 #endif /* USE_X_TOOLKIT */
5326 	  }
5327 
5328 	if ((!f1 || FRAME_TOOLTIP_P (f1))
5329 	    && EQ (track_mouse, Qdropping)
5330 	    && gui_mouse_grabbed (dpyinfo))
5331 	  {
5332 	    /* When dropping then if we didn't get a frame or only a
5333 	       tooltip frame and the mouse was grabbed on a frame,
5334 	       give coords for that frame even if the mouse is now
5335 	       outside it.  */
5336 	    XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
5337 				   /* From-window.  */
5338 				   root,
5339 				   /* To-window.  */
5340 				   FRAME_X_WINDOW (dpyinfo->last_mouse_frame),
5341 				   /* From-position, to-position.  */
5342 				   root_x, root_y, &win_x, &win_y,
5343 				   /* Child of win.  */
5344 				   &child);
5345 	    f1 = dpyinfo->last_mouse_frame;
5346 	  }
5347 	else if (f1 && FRAME_TOOLTIP_P (f1))
5348 	  f1 = NULL;
5349 
5350 	if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
5351 	  f1 = NULL;
5352 
5353 	x_uncatch_errors_after_check ();
5354 
5355 	/* If not, is it one of our scroll bars?  */
5356 	if (!f1)
5357 	  {
5358 	    struct scroll_bar *bar;
5359 
5360             bar = x_window_to_scroll_bar (FRAME_X_DISPLAY (*fp), win, 2);
5361 
5362 	    if (bar)
5363 	      {
5364 		f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5365 		win_x = parent_x;
5366 		win_y = parent_y;
5367 	      }
5368 	  }
5369 
5370 	if (!f1 && insist > 0)
5371 	  f1 = SELECTED_FRAME ();
5372 
5373 	if (f1)
5374 	  {
5375 	    /* Ok, we found a frame.  Store all the values.
5376 	       last_mouse_glyph is a rectangle used to reduce the
5377 	       generation of mouse events.  To not miss any motion
5378 	       events, we must divide the frame into rectangles of the
5379 	       size of the smallest character that could be displayed
5380 	       on it, i.e. into the same rectangles that matrices on
5381 	       the frame are divided into.  */
5382 
5383 	    /* FIXME: what if F1 is not an X frame?  */
5384 	    dpyinfo = FRAME_DISPLAY_INFO (f1);
5385 	    remember_mouse_glyph (f1, win_x, win_y, &dpyinfo->last_mouse_glyph);
5386 	    dpyinfo->last_mouse_glyph_frame = f1;
5387 
5388 	    *bar_window = Qnil;
5389 	    *part = 0;
5390 	    *fp = f1;
5391 	    XSETINT (*x, win_x);
5392 	    XSETINT (*y, win_y);
5393 	    *timestamp = dpyinfo->last_mouse_movement_time;
5394 	  }
5395       }
5396     }
5397 
5398   unblock_input ();
5399 }
5400 
5401 
5402 
5403 /***********************************************************************
5404 			       Scroll bars
5405  ***********************************************************************/
5406 
5407 /* Scroll bar support.  */
5408 
5409 /* Given an X window ID and a DISPLAY, find the struct scroll_bar which
5410    manages it.
5411    This can be called in GC, so we have to make sure to strip off mark
5412    bits.  */
5413 
5414 static struct scroll_bar *
x_window_to_scroll_bar(Display * display,Window window_id,int type)5415 x_window_to_scroll_bar (Display *display, Window window_id, int type)
5416 {
5417   Lisp_Object tail, frame;
5418 
5419 #if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
5420   window_id = (Window) xg_get_scroll_id_for_window (display, window_id);
5421 #endif /* USE_GTK  && USE_TOOLKIT_SCROLL_BARS */
5422 
5423   FOR_EACH_FRAME (tail, frame)
5424     {
5425       Lisp_Object bar, condemned;
5426 
5427       if (! FRAME_X_P (XFRAME (frame)))
5428         continue;
5429 
5430       /* Scan this frame's scroll bar list for a scroll bar with the
5431          right window ID.  */
5432       condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
5433       for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
5434 	   /* This trick allows us to search both the ordinary and
5435               condemned scroll bar lists with one loop.  */
5436 	   ! NILP (bar) || (bar = condemned,
5437 			       condemned = Qnil,
5438 			       ! NILP (bar));
5439 	   bar = XSCROLL_BAR (bar)->next)
5440 	if (XSCROLL_BAR (bar)->x_window == window_id
5441             && FRAME_X_DISPLAY (XFRAME (frame)) == display
5442 	    && (type == 2
5443 		|| (type == 1 && XSCROLL_BAR (bar)->horizontal)
5444 		|| (type == 0 && !XSCROLL_BAR (bar)->horizontal)))
5445 	  return XSCROLL_BAR (bar);
5446     }
5447 
5448   return NULL;
5449 }
5450 
5451 
5452 #if defined USE_LUCID
5453 
5454 /* Return the Lucid menu bar WINDOW is part of.  Return null
5455    if WINDOW is not part of a menu bar.  */
5456 
5457 static Widget
x_window_to_menu_bar(Window window)5458 x_window_to_menu_bar (Window window)
5459 {
5460   Lisp_Object tail, frame;
5461 
5462   FOR_EACH_FRAME (tail, frame)
5463     if (FRAME_X_P (XFRAME (frame)))
5464       {
5465 	Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
5466 
5467 	if (menu_bar && xlwmenu_window_p (menu_bar, window))
5468 	  return menu_bar;
5469       }
5470   return NULL;
5471 }
5472 
5473 #endif /* USE_LUCID */
5474 
5475 
5476 /************************************************************************
5477 			 Toolkit scroll bars
5478  ************************************************************************/
5479 
5480 #ifdef USE_TOOLKIT_SCROLL_BARS
5481 
5482 static void x_send_scroll_bar_event (Lisp_Object, enum scroll_bar_part,
5483                                      int, int, bool);
5484 
5485 /* Lisp window being scrolled.  Set when starting to interact with
5486    a toolkit scroll bar, reset to nil when ending the interaction.  */
5487 
5488 static Lisp_Object window_being_scrolled;
5489 
5490 /* Whether this is an Xaw with arrow-scrollbars.  This should imply
5491    that movements of 1/20 of the screen size are mapped to up/down.  */
5492 
5493 #ifndef USE_GTK
5494 /* Id of action hook installed for scroll bars.  */
5495 
5496 static XtActionHookId action_hook_id;
5497 static XtActionHookId horizontal_action_hook_id;
5498 
5499 static Boolean xaw3d_arrow_scroll;
5500 
5501 /* Whether the drag scrolling maintains the mouse at the top of the
5502    thumb.  If not, resizing the thumb needs to be done more carefully
5503    to avoid jerkiness.  */
5504 
5505 static Boolean xaw3d_pick_top;
5506 
5507 /* Action hook installed via XtAppAddActionHook when toolkit scroll
5508    bars are used..  The hook is responsible for detecting when
5509    the user ends an interaction with the scroll bar, and generates
5510    a `end-scroll' SCROLL_BAR_CLICK_EVENT' event if so.  */
5511 
5512 static void
xt_action_hook(Widget widget,XtPointer client_data,String action_name,XEvent * event,String * params,Cardinal * num_params)5513 xt_action_hook (Widget widget, XtPointer client_data, String action_name,
5514 		XEvent *event, String *params, Cardinal *num_params)
5515 {
5516   bool scroll_bar_p;
5517   const char *end_action;
5518 
5519 #ifdef USE_MOTIF
5520   scroll_bar_p = XmIsScrollBar (widget);
5521   end_action = "Release";
5522 #else /* !USE_MOTIF i.e. use Xaw */
5523   scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
5524   end_action = "EndScroll";
5525 #endif /* USE_MOTIF */
5526 
5527   if (scroll_bar_p
5528       && strcmp (action_name, end_action) == 0
5529       && WINDOWP (window_being_scrolled))
5530     {
5531       struct window *w;
5532       struct scroll_bar *bar;
5533 
5534       x_send_scroll_bar_event (window_being_scrolled,
5535 			       scroll_bar_end_scroll, 0, 0, false);
5536       w = XWINDOW (window_being_scrolled);
5537       bar = XSCROLL_BAR (w->vertical_scroll_bar);
5538 
5539       if (bar->dragging != -1)
5540 	{
5541 	  bar->dragging = -1;
5542 	  /* The thumb size is incorrect while dragging: fix it.  */
5543 	  set_vertical_scroll_bar (w);
5544 	}
5545       window_being_scrolled = Qnil;
5546 #if defined (USE_LUCID)
5547       bar->last_seen_part = scroll_bar_nowhere;
5548 #endif
5549       /* Xt timeouts no longer needed.  */
5550       toolkit_scroll_bar_interaction = false;
5551     }
5552 }
5553 
5554 
5555 static void
xt_horizontal_action_hook(Widget widget,XtPointer client_data,String action_name,XEvent * event,String * params,Cardinal * num_params)5556 xt_horizontal_action_hook (Widget widget, XtPointer client_data, String action_name,
5557 			   XEvent *event, String *params, Cardinal *num_params)
5558 {
5559   bool scroll_bar_p;
5560   const char *end_action;
5561 
5562 #ifdef USE_MOTIF
5563   scroll_bar_p = XmIsScrollBar (widget);
5564   end_action = "Release";
5565 #else /* !USE_MOTIF i.e. use Xaw */
5566   scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
5567   end_action = "EndScroll";
5568 #endif /* USE_MOTIF */
5569 
5570   if (scroll_bar_p
5571       && strcmp (action_name, end_action) == 0
5572       && WINDOWP (window_being_scrolled))
5573     {
5574       struct window *w;
5575       struct scroll_bar *bar;
5576 
5577       x_send_scroll_bar_event (window_being_scrolled,
5578 			       scroll_bar_end_scroll, 0, 0, true);
5579       w = XWINDOW (window_being_scrolled);
5580       if (!NILP (w->horizontal_scroll_bar))
5581 	{
5582 	  bar = XSCROLL_BAR (w->horizontal_scroll_bar);
5583 	  if (bar->dragging != -1)
5584 	    {
5585 	      bar->dragging = -1;
5586 	      /* The thumb size is incorrect while dragging: fix it.  */
5587 	      set_horizontal_scroll_bar (w);
5588 	    }
5589 	  window_being_scrolled = Qnil;
5590 #if defined (USE_LUCID)
5591 	  bar->last_seen_part = scroll_bar_nowhere;
5592 #endif
5593 	  /* Xt timeouts no longer needed.  */
5594 	  toolkit_scroll_bar_interaction = false;
5595 	}
5596     }
5597 }
5598 #endif /* not USE_GTK */
5599 
5600 /* Send a client message with message type Xatom_Scrollbar for a
5601    scroll action to the frame of WINDOW.  PART is a value identifying
5602    the part of the scroll bar that was clicked on.  PORTION is the
5603    amount to scroll of a whole of WHOLE.  */
5604 
5605 static void
x_send_scroll_bar_event(Lisp_Object window,enum scroll_bar_part part,int portion,int whole,bool horizontal)5606 x_send_scroll_bar_event (Lisp_Object window, enum scroll_bar_part part,
5607 			 int portion, int whole, bool horizontal)
5608 {
5609   XEvent event;
5610   XClientMessageEvent *ev = &event.xclient;
5611   struct window *w = XWINDOW (window);
5612   struct frame *f = XFRAME (w->frame);
5613   intptr_t iw = (intptr_t) w;
5614   verify (INTPTR_WIDTH <= 64);
5615   int sign_shift = INTPTR_WIDTH - 32;
5616 
5617   block_input ();
5618 
5619   /* Construct a ClientMessage event to send to the frame.  */
5620   ev->type = ClientMessage;
5621   ev->message_type = (horizontal
5622 		      ? FRAME_DISPLAY_INFO (f)->Xatom_Horizontal_Scrollbar
5623 		      : FRAME_DISPLAY_INFO (f)->Xatom_Scrollbar);
5624   ev->display = FRAME_X_DISPLAY (f);
5625   ev->window = FRAME_X_WINDOW (f);
5626   ev->format = 32;
5627 
5628   /* A 32-bit X client on a 64-bit X server can pass a window pointer
5629      as-is.  A 64-bit client on a 32-bit X server is in trouble
5630      because a pointer does not fit and would be truncated while
5631      passing through the server.  So use two slots and hope that X12
5632      will resolve such issues someday.  */
5633   ev->data.l[0] = iw >> 31 >> 1;
5634   ev->data.l[1] = sign_shift <= 0 ? iw : iw << sign_shift >> sign_shift;
5635   ev->data.l[2] = part;
5636   ev->data.l[3] = portion;
5637   ev->data.l[4] = whole;
5638 
5639   /* Make Xt timeouts work while the scroll bar is active.  */
5640 #ifdef USE_X_TOOLKIT
5641   toolkit_scroll_bar_interaction = true;
5642   x_activate_timeout_atimer ();
5643 #endif
5644 
5645   /* Setting the event mask to zero means that the message will
5646      be sent to the client that created the window, and if that
5647      window no longer exists, no event will be sent.  */
5648   XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
5649   unblock_input ();
5650 }
5651 
5652 
5653 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
5654    in *IEVENT.  */
5655 
5656 static void
x_scroll_bar_to_input_event(const XEvent * event,struct input_event * ievent)5657 x_scroll_bar_to_input_event (const XEvent *event,
5658 			     struct input_event *ievent)
5659 {
5660   const XClientMessageEvent *ev = &event->xclient;
5661   Lisp_Object window;
5662   struct window *w;
5663 
5664   /* See the comment in the function above.  */
5665   intptr_t iw0 = ev->data.l[0];
5666   intptr_t iw1 = ev->data.l[1];
5667   intptr_t iw = (iw0 << 31 << 1) + (iw1 & 0xffffffffu);
5668   w = (struct window *) iw;
5669 
5670   XSETWINDOW (window, w);
5671 
5672   ievent->kind = SCROLL_BAR_CLICK_EVENT;
5673   ievent->frame_or_window = window;
5674   ievent->arg = Qnil;
5675 #ifdef USE_GTK
5676   ievent->timestamp = CurrentTime;
5677 #else
5678   ievent->timestamp =
5679     XtLastTimestampProcessed (FRAME_X_DISPLAY (XFRAME (w->frame)));
5680 #endif
5681   ievent->code = 0;
5682   ievent->part = ev->data.l[2];
5683   ievent->x = make_fixnum (ev->data.l[3]);
5684   ievent->y = make_fixnum (ev->data.l[4]);
5685   ievent->modifiers = 0;
5686 }
5687 
5688 /* Transform a horizontal scroll bar ClientMessage EVENT to an Emacs
5689    input event in *IEVENT.  */
5690 
5691 static void
x_horizontal_scroll_bar_to_input_event(const XEvent * event,struct input_event * ievent)5692 x_horizontal_scroll_bar_to_input_event (const XEvent *event,
5693 					struct input_event *ievent)
5694 {
5695   const XClientMessageEvent *ev = &event->xclient;
5696   Lisp_Object window;
5697   struct window *w;
5698 
5699   /* See the comment in the function above.  */
5700   intptr_t iw0 = ev->data.l[0];
5701   intptr_t iw1 = ev->data.l[1];
5702   intptr_t iw = (iw0 << 31 << 1) + (iw1 & 0xffffffffu);
5703   w = (struct window *) iw;
5704 
5705   XSETWINDOW (window, w);
5706 
5707   ievent->kind = HORIZONTAL_SCROLL_BAR_CLICK_EVENT;
5708   ievent->frame_or_window = window;
5709   ievent->arg = Qnil;
5710 #ifdef USE_GTK
5711   ievent->timestamp = CurrentTime;
5712 #else
5713   ievent->timestamp =
5714     XtLastTimestampProcessed (FRAME_X_DISPLAY (XFRAME (w->frame)));
5715 #endif
5716   ievent->code = 0;
5717   ievent->part = ev->data.l[2];
5718   ievent->x = make_fixnum (ev->data.l[3]);
5719   ievent->y = make_fixnum (ev->data.l[4]);
5720   ievent->modifiers = 0;
5721 }
5722 
5723 
5724 #ifdef USE_MOTIF
5725 
5726 /* Minimum and maximum values used for Motif scroll bars.  */
5727 
5728 #define XM_SB_MAX 10000000
5729 
5730 /* Scroll bar callback for Motif scroll bars.  WIDGET is the scroll
5731    bar widget.  CLIENT_DATA is a pointer to the scroll_bar structure.
5732    CALL_DATA is a pointer to a XmScrollBarCallbackStruct.  */
5733 
5734 static void
xm_scroll_callback(Widget widget,XtPointer client_data,XtPointer call_data)5735 xm_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data)
5736 {
5737   struct scroll_bar *bar = client_data;
5738   XmScrollBarCallbackStruct *cs = call_data;
5739   enum scroll_bar_part part = scroll_bar_nowhere;
5740   bool horizontal = bar->horizontal;
5741   int whole = 0, portion = 0;
5742 
5743   switch (cs->reason)
5744     {
5745     case XmCR_DECREMENT:
5746       bar->dragging = -1;
5747       part = horizontal ? scroll_bar_left_arrow : scroll_bar_up_arrow;
5748       break;
5749 
5750     case XmCR_INCREMENT:
5751       bar->dragging = -1;
5752       part = horizontal ? scroll_bar_right_arrow : scroll_bar_down_arrow;
5753       break;
5754 
5755     case XmCR_PAGE_DECREMENT:
5756       bar->dragging = -1;
5757       part = horizontal ? scroll_bar_before_handle : scroll_bar_above_handle;
5758       break;
5759 
5760     case XmCR_PAGE_INCREMENT:
5761       bar->dragging = -1;
5762       part = horizontal ? scroll_bar_after_handle : scroll_bar_below_handle;
5763       break;
5764 
5765     case XmCR_TO_TOP:
5766       bar->dragging = -1;
5767       part = horizontal ? scroll_bar_to_leftmost : scroll_bar_to_top;
5768       break;
5769 
5770     case XmCR_TO_BOTTOM:
5771       bar->dragging = -1;
5772       part = horizontal ? scroll_bar_to_rightmost : scroll_bar_to_bottom;
5773       break;
5774 
5775     case XmCR_DRAG:
5776       {
5777 	int slider_size;
5778 
5779 	block_input ();
5780 	XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
5781 	unblock_input ();
5782 
5783 	if (horizontal)
5784 	  {
5785 	    portion = bar->whole * ((float)cs->value / XM_SB_MAX);
5786 	    whole = bar->whole * ((float)(XM_SB_MAX - slider_size) / XM_SB_MAX);
5787 	    portion = min (portion, whole);
5788 	    part = scroll_bar_horizontal_handle;
5789 	  }
5790 	else
5791 	  {
5792 	    whole = XM_SB_MAX - slider_size;
5793 	    portion = min (cs->value, whole);
5794 	    part = scroll_bar_handle;
5795 	  }
5796 
5797 	bar->dragging = cs->value;
5798       }
5799       break;
5800 
5801     case XmCR_VALUE_CHANGED:
5802       break;
5803     };
5804 
5805   if (part != scroll_bar_nowhere)
5806     {
5807       window_being_scrolled = bar->window;
5808       x_send_scroll_bar_event (bar->window, part, portion, whole,
5809 			       bar->horizontal);
5810     }
5811 }
5812 
5813 #elif defined USE_GTK
5814 
5815 /* Scroll bar callback for GTK scroll bars.  WIDGET is the scroll
5816    bar widget.  DATA is a pointer to the scroll_bar structure. */
5817 
5818 static gboolean
xg_scroll_callback(GtkRange * range,GtkScrollType scroll,gdouble value,gpointer user_data)5819 xg_scroll_callback (GtkRange     *range,
5820                     GtkScrollType scroll,
5821                     gdouble       value,
5822                     gpointer      user_data)
5823 {
5824   int whole = 0, portion = 0;
5825   struct scroll_bar *bar = user_data;
5826   enum scroll_bar_part part = scroll_bar_nowhere;
5827   GtkAdjustment *adj = GTK_ADJUSTMENT (gtk_range_get_adjustment (range));
5828   struct frame *f = g_object_get_data (G_OBJECT (range), XG_FRAME_DATA);
5829 
5830   if (xg_ignore_gtk_scrollbar) return false;
5831 
5832   switch (scroll)
5833     {
5834     case GTK_SCROLL_JUMP:
5835       /* Buttons 1 2 or 3 must be grabbed.  */
5836       if (FRAME_DISPLAY_INFO (f)->grabbed != 0
5837           && FRAME_DISPLAY_INFO (f)->grabbed < (1 << 4))
5838         {
5839 	  if (bar->horizontal)
5840 	    {
5841 	      part = scroll_bar_horizontal_handle;
5842 	      whole = (int)(gtk_adjustment_get_upper (adj) -
5843 			    gtk_adjustment_get_page_size (adj));
5844 	      portion = min ((int)value, whole);
5845 	      bar->dragging = portion;
5846 	    }
5847 	  else
5848 	    {
5849 	      part = scroll_bar_handle;
5850 	      whole = gtk_adjustment_get_upper (adj) -
5851 		gtk_adjustment_get_page_size (adj);
5852 	      portion = min ((int)value, whole);
5853 	      bar->dragging = portion;
5854 	    }
5855 	}
5856       break;
5857     case GTK_SCROLL_STEP_BACKWARD:
5858       part = (bar->horizontal
5859 	      ? scroll_bar_left_arrow : scroll_bar_up_arrow);
5860       bar->dragging = -1;
5861       break;
5862     case GTK_SCROLL_STEP_FORWARD:
5863       part = (bar->horizontal
5864 	      ? scroll_bar_right_arrow : scroll_bar_down_arrow);
5865       bar->dragging = -1;
5866       break;
5867     case GTK_SCROLL_PAGE_BACKWARD:
5868       part = (bar->horizontal
5869 	      ? scroll_bar_before_handle : scroll_bar_above_handle);
5870       bar->dragging = -1;
5871       break;
5872     case GTK_SCROLL_PAGE_FORWARD:
5873       part = (bar->horizontal
5874 	      ? scroll_bar_after_handle : scroll_bar_below_handle);
5875       bar->dragging = -1;
5876       break;
5877     default:
5878       break;
5879     }
5880 
5881   if (part != scroll_bar_nowhere)
5882     {
5883       window_being_scrolled = bar->window;
5884       x_send_scroll_bar_event (bar->window, part, portion, whole,
5885 			       bar->horizontal);
5886     }
5887 
5888   return false;
5889 }
5890 
5891 /* Callback for button release. Sets dragging to -1 when dragging is done.  */
5892 
5893 static gboolean
xg_end_scroll_callback(GtkWidget * widget,GdkEventButton * event,gpointer user_data)5894 xg_end_scroll_callback (GtkWidget *widget,
5895                         GdkEventButton *event,
5896                         gpointer user_data)
5897 {
5898   struct scroll_bar *bar = user_data;
5899   bar->dragging = -1;
5900   if (WINDOWP (window_being_scrolled))
5901     {
5902       x_send_scroll_bar_event (window_being_scrolled,
5903                                scroll_bar_end_scroll, 0, 0, bar->horizontal);
5904       window_being_scrolled = Qnil;
5905     }
5906 
5907   return false;
5908 }
5909 
5910 
5911 #else /* not USE_GTK and not USE_MOTIF */
5912 
5913 /* Xaw scroll bar callback.  Invoked when the thumb is dragged.
5914    WIDGET is the scroll bar widget.  CLIENT_DATA is a pointer to the
5915    scroll bar struct.  CALL_DATA is a pointer to a float saying where
5916    the thumb is.  */
5917 
5918 static void
xaw_jump_callback(Widget widget,XtPointer client_data,XtPointer call_data)5919 xaw_jump_callback (Widget widget, XtPointer client_data, XtPointer call_data)
5920 {
5921   struct scroll_bar *bar = client_data;
5922   float *top_addr = call_data;
5923   float top = *top_addr;
5924   float shown;
5925   int whole, portion, height, width;
5926   enum scroll_bar_part part;
5927   bool horizontal = bar->horizontal;
5928 
5929   if (horizontal)
5930     {
5931       /* Get the size of the thumb, a value between 0 and 1.  */
5932       block_input ();
5933       XtVaGetValues (widget, XtNshown, &shown, XtNwidth, &width, NULL);
5934       unblock_input ();
5935 
5936       if (shown < 1)
5937 	{
5938 	  whole = bar->whole - (shown * bar->whole);
5939 	  portion = min (top * bar->whole, whole);
5940 	}
5941       else
5942 	{
5943 	  whole = bar->whole;
5944 	  portion = 0;
5945 	}
5946 
5947       part = scroll_bar_horizontal_handle;
5948     }
5949   else
5950     {
5951       /* Get the size of the thumb, a value between 0 and 1.  */
5952       block_input ();
5953       XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
5954       unblock_input ();
5955 
5956       whole = 10000000;
5957       portion = shown < 1 ? top * whole : 0;
5958 
5959       if (shown < 1 && (eabs (top + shown - 1) < 1.0f / height))
5960 	/* Some derivatives of Xaw refuse to shrink the thumb when you reach
5961 	   the bottom, so we force the scrolling whenever we see that we're
5962 	   too close to the bottom (in x_set_toolkit_scroll_bar_thumb
5963 	   we try to ensure that we always stay two pixels away from the
5964 	   bottom).  */
5965 	part = scroll_bar_down_arrow;
5966       else
5967 	part = scroll_bar_handle;
5968     }
5969 
5970   window_being_scrolled = bar->window;
5971   bar->dragging = portion;
5972   bar->last_seen_part = part;
5973   x_send_scroll_bar_event (bar->window, part, portion, whole, bar->horizontal);
5974 }
5975 
5976 
5977 /* Xaw scroll bar callback.  Invoked for incremental scrolling.,
5978    i.e. line or page up or down.  WIDGET is the Xaw scroll bar
5979    widget.  CLIENT_DATA is a pointer to the scroll_bar structure for
5980    the scroll bar.  CALL_DATA is an integer specifying the action that
5981    has taken place.  Its magnitude is in the range 0..height of the
5982    scroll bar.  Negative values mean scroll towards buffer start.
5983    Values < height of scroll bar mean line-wise movement.  */
5984 
5985 static void
xaw_scroll_callback(Widget widget,XtPointer client_data,XtPointer call_data)5986 xaw_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data)
5987 {
5988   struct scroll_bar *bar = client_data;
5989   /* The position really is stored cast to a pointer.  */
5990   int position = (intptr_t) call_data;
5991   Dimension height, width;
5992   enum scroll_bar_part part;
5993 
5994   if (bar->horizontal)
5995     {
5996       /* Get the width of the scroll bar.  */
5997       block_input ();
5998       XtVaGetValues (widget, XtNwidth, &width, NULL);
5999       unblock_input ();
6000 
6001       if (eabs (position) >= width)
6002 	part = (position < 0) ? scroll_bar_before_handle : scroll_bar_after_handle;
6003 
6004       /* If Xaw3d was compiled with ARROW_SCROLLBAR,
6005 	 it maps line-movement to call_data = max(5, height/20).  */
6006       else if (xaw3d_arrow_scroll && eabs (position) <= max (5, width / 20))
6007 	part = (position < 0) ? scroll_bar_left_arrow : scroll_bar_right_arrow;
6008       else
6009 	part = scroll_bar_move_ratio;
6010 
6011       window_being_scrolled = bar->window;
6012       bar->dragging = -1;
6013       bar->last_seen_part = part;
6014       x_send_scroll_bar_event (bar->window, part, position, width,
6015 			       bar->horizontal);
6016     }
6017   else
6018     {
6019 
6020       /* Get the height of the scroll bar.  */
6021       block_input ();
6022       XtVaGetValues (widget, XtNheight, &height, NULL);
6023       unblock_input ();
6024 
6025       if (eabs (position) >= height)
6026 	part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
6027 
6028       /* If Xaw3d was compiled with ARROW_SCROLLBAR,
6029 	 it maps line-movement to call_data = max(5, height/20).  */
6030       else if (xaw3d_arrow_scroll && eabs (position) <= max (5, height / 20))
6031 	part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
6032       else
6033 	part = scroll_bar_move_ratio;
6034 
6035       window_being_scrolled = bar->window;
6036       bar->dragging = -1;
6037       bar->last_seen_part = part;
6038       x_send_scroll_bar_event (bar->window, part, position, height,
6039 			       bar->horizontal);
6040     }
6041 }
6042 
6043 #endif /* not USE_GTK and not USE_MOTIF */
6044 
6045 #define SCROLL_BAR_NAME "verticalScrollBar"
6046 #define SCROLL_BAR_HORIZONTAL_NAME "horizontalScrollBar"
6047 
6048 /* Create the widget for scroll bar BAR on frame F.  Record the widget
6049    and X window of the scroll bar in BAR.  */
6050 
6051 #ifdef USE_GTK
6052 static void
x_create_toolkit_scroll_bar(struct frame * f,struct scroll_bar * bar)6053 x_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
6054 {
6055   const char *scroll_bar_name = SCROLL_BAR_NAME;
6056 
6057   block_input ();
6058   xg_create_scroll_bar (f, bar, G_CALLBACK (xg_scroll_callback),
6059                         G_CALLBACK (xg_end_scroll_callback),
6060                         scroll_bar_name);
6061   unblock_input ();
6062 }
6063 
6064 static void
x_create_horizontal_toolkit_scroll_bar(struct frame * f,struct scroll_bar * bar)6065 x_create_horizontal_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
6066 {
6067   const char *scroll_bar_name = SCROLL_BAR_HORIZONTAL_NAME;
6068 
6069   block_input ();
6070   xg_create_horizontal_scroll_bar (f, bar, G_CALLBACK (xg_scroll_callback),
6071 				   G_CALLBACK (xg_end_scroll_callback),
6072 				   scroll_bar_name);
6073   unblock_input ();
6074 }
6075 
6076 #else /* not USE_GTK */
6077 
6078 static void
x_create_toolkit_scroll_bar(struct frame * f,struct scroll_bar * bar)6079 x_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
6080 {
6081   Window xwindow;
6082   Widget widget;
6083   Arg av[20];
6084   int ac = 0;
6085   const char *scroll_bar_name = SCROLL_BAR_NAME;
6086   unsigned long pixel;
6087 
6088   block_input ();
6089 
6090 #ifdef USE_MOTIF
6091   /* Set resources.  Create the widget.  */
6092   XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
6093   XtSetArg (av[ac], XmNminimum, 0); ++ac;
6094   XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
6095   XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
6096   XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
6097   XtSetArg (av[ac], XmNincrement, 1); ++ac;
6098   XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
6099 
6100   /* Note: "background" is the thumb color, and "trough" is the color behind
6101      everything. */
6102   pixel = f->output_data.x->scroll_bar_foreground_pixel;
6103   if (pixel != -1)
6104     {
6105       XtSetArg (av[ac], XmNbackground, pixel);
6106       ++ac;
6107     }
6108 
6109   pixel = f->output_data.x->scroll_bar_background_pixel;
6110   if (pixel != -1)
6111     {
6112       XtSetArg (av[ac], XmNtroughColor, pixel);
6113       ++ac;
6114     }
6115 
6116   widget = XmCreateScrollBar (f->output_data.x->edit_widget,
6117 			      (char *) scroll_bar_name, av, ac);
6118 
6119   /* Add one callback for everything that can happen.  */
6120   XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
6121 		 (XtPointer) bar);
6122   XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
6123 		 (XtPointer) bar);
6124   XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
6125 		 (XtPointer) bar);
6126   XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
6127 		 (XtPointer) bar);
6128   XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
6129 		 (XtPointer) bar);
6130   XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
6131 		 (XtPointer) bar);
6132   XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
6133 		 (XtPointer) bar);
6134 
6135   /* Realize the widget.  Only after that is the X window created.  */
6136   XtRealizeWidget (widget);
6137 
6138   /* Set the cursor to an arrow.  I didn't find a resource to do that.
6139      And I'm wondering why it hasn't an arrow cursor by default.  */
6140   XDefineCursor (XtDisplay (widget), XtWindow (widget),
6141                  f->output_data.x->nontext_cursor);
6142 
6143 #else /* !USE_MOTIF i.e. use Xaw */
6144 
6145   /* Set resources.  Create the widget.  The background of the
6146      Xaw3d scroll bar widget is a little bit light for my taste.
6147      We don't alter it here to let users change it according
6148      to their taste with `emacs*verticalScrollBar.background: xxx'.  */
6149   XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
6150   XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
6151   /* For smoother scrolling with Xaw3d   -sm */
6152   /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
6153 
6154   pixel = f->output_data.x->scroll_bar_foreground_pixel;
6155   if (pixel != -1)
6156     {
6157       XtSetArg (av[ac], XtNforeground, pixel);
6158       ++ac;
6159     }
6160 
6161   pixel = f->output_data.x->scroll_bar_background_pixel;
6162   if (pixel != -1)
6163     {
6164       XtSetArg (av[ac], XtNbackground, pixel);
6165       ++ac;
6166     }
6167 
6168   /* Top/bottom shadow colors.  */
6169 
6170   /* Allocate them, if necessary.  */
6171   if (f->output_data.x->scroll_bar_top_shadow_pixel == -1)
6172     {
6173       pixel = f->output_data.x->scroll_bar_background_pixel;
6174       if (pixel != -1)
6175         {
6176           if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
6177                                       FRAME_X_COLORMAP (f),
6178                                       &pixel, 1.2, 0x8000))
6179             pixel = -1;
6180           f->output_data.x->scroll_bar_top_shadow_pixel = pixel;
6181         }
6182     }
6183   if (f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
6184     {
6185       pixel = f->output_data.x->scroll_bar_background_pixel;
6186       if (pixel != -1)
6187         {
6188           if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
6189                                       FRAME_X_COLORMAP (f),
6190                                       &pixel, 0.6, 0x4000))
6191             pixel = -1;
6192           f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
6193         }
6194     }
6195 
6196 #ifdef XtNbeNiceToColormap
6197   /* Tell the toolkit about them.  */
6198   if (f->output_data.x->scroll_bar_top_shadow_pixel == -1
6199       || f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
6200     /* We tried to allocate a color for the top/bottom shadow, and
6201        failed, so tell Xaw3d to use dithering instead.   */
6202     /* But only if we have a small colormap.  Xaw3d can allocate nice
6203        colors itself.  */
6204     {
6205       XtSetArg (av[ac], XtNbeNiceToColormap,
6206                 DefaultDepthOfScreen (FRAME_X_SCREEN (f)) < 16);
6207       ++ac;
6208     }
6209   else
6210     /* Tell what colors Xaw3d should use for the top/bottom shadow, to
6211        be more consistent with other emacs 3d colors, and since Xaw3d is
6212        not good at dealing with allocation failure.  */
6213     {
6214       /* This tells Xaw3d to use real colors instead of dithering for
6215 	 the shadows.  */
6216       XtSetArg (av[ac], XtNbeNiceToColormap, False);
6217       ++ac;
6218 
6219       /* Specify the colors.  */
6220       pixel = f->output_data.x->scroll_bar_top_shadow_pixel;
6221       if (pixel != -1)
6222 	{
6223 	  XtSetArg (av[ac], XtNtopShadowPixel, pixel);
6224 	  ++ac;
6225 	}
6226       pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel;
6227       if (pixel != -1)
6228 	{
6229 	  XtSetArg (av[ac], XtNbottomShadowPixel, pixel);
6230 	  ++ac;
6231 	}
6232     }
6233 #endif
6234 
6235   widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
6236 			   f->output_data.x->edit_widget, av, ac);
6237 
6238   {
6239     char const *initial = "";
6240     char const *val = initial;
6241     XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
6242 #ifdef XtNarrowScrollbars
6243 		   XtNarrowScrollbars, (XtPointer) &xaw3d_arrow_scroll,
6244 #endif
6245 		   XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
6246     if (xaw3d_arrow_scroll || val == initial)
6247       {	/* ARROW_SCROLL */
6248 	xaw3d_arrow_scroll = True;
6249 	/* Isn't that just a personal preference ?   --Stef */
6250 	XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
6251       }
6252   }
6253 
6254   /* Define callbacks.  */
6255   XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
6256   XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
6257 		 (XtPointer) bar);
6258 
6259   /* Realize the widget.  Only after that is the X window created.  */
6260   XtRealizeWidget (widget);
6261 
6262 #endif /* !USE_MOTIF */
6263 
6264   /* Install an action hook that lets us detect when the user
6265      finishes interacting with a scroll bar.  */
6266   if (action_hook_id == 0)
6267     action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
6268 
6269   /* Remember X window and widget in the scroll bar vector.  */
6270   SET_SCROLL_BAR_X_WIDGET (bar, widget);
6271   xwindow = XtWindow (widget);
6272   bar->x_window = xwindow;
6273   bar->whole = 1;
6274   bar->horizontal = false;
6275 
6276   unblock_input ();
6277 }
6278 
6279 static void
x_create_horizontal_toolkit_scroll_bar(struct frame * f,struct scroll_bar * bar)6280 x_create_horizontal_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
6281 {
6282   Window xwindow;
6283   Widget widget;
6284   Arg av[20];
6285   int ac = 0;
6286   const char *scroll_bar_name = SCROLL_BAR_HORIZONTAL_NAME;
6287   unsigned long pixel;
6288 
6289   block_input ();
6290 
6291 #ifdef USE_MOTIF
6292   /* Set resources.  Create the widget.  */
6293   XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
6294   XtSetArg (av[ac], XmNminimum, 0); ++ac;
6295   XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
6296   XtSetArg (av[ac], XmNorientation, XmHORIZONTAL); ++ac;
6297   XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_RIGHT), ++ac;
6298   XtSetArg (av[ac], XmNincrement, 1); ++ac;
6299   XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
6300 
6301   /* Note: "background" is the thumb color, and "trough" is the color behind
6302      everything. */
6303   pixel = f->output_data.x->scroll_bar_foreground_pixel;
6304   if (pixel != -1)
6305     {
6306       XtSetArg (av[ac], XmNbackground, pixel);
6307       ++ac;
6308     }
6309 
6310   pixel = f->output_data.x->scroll_bar_background_pixel;
6311   if (pixel != -1)
6312     {
6313       XtSetArg (av[ac], XmNtroughColor, pixel);
6314       ++ac;
6315     }
6316 
6317   widget = XmCreateScrollBar (f->output_data.x->edit_widget,
6318 			      (char *) scroll_bar_name, av, ac);
6319 
6320   /* Add one callback for everything that can happen.  */
6321   XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
6322 		 (XtPointer) bar);
6323   XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
6324 		 (XtPointer) bar);
6325   XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
6326 		 (XtPointer) bar);
6327   XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
6328 		 (XtPointer) bar);
6329   XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
6330 		 (XtPointer) bar);
6331   XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
6332 		 (XtPointer) bar);
6333   XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
6334 		 (XtPointer) bar);
6335 
6336   /* Realize the widget.  Only after that is the X window created.  */
6337   XtRealizeWidget (widget);
6338 
6339   /* Set the cursor to an arrow.  I didn't find a resource to do that.
6340      And I'm wondering why it hasn't an arrow cursor by default.  */
6341   XDefineCursor (XtDisplay (widget), XtWindow (widget),
6342                  f->output_data.x->nontext_cursor);
6343 
6344 #else /* !USE_MOTIF i.e. use Xaw */
6345 
6346   /* Set resources.  Create the widget.  The background of the
6347      Xaw3d scroll bar widget is a little bit light for my taste.
6348      We don't alter it here to let users change it according
6349      to their taste with `emacs*verticalScrollBar.background: xxx'.  */
6350   XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
6351   XtSetArg (av[ac], XtNorientation, XtorientHorizontal); ++ac;
6352   /* For smoother scrolling with Xaw3d   -sm */
6353   /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
6354 
6355   pixel = f->output_data.x->scroll_bar_foreground_pixel;
6356   if (pixel != -1)
6357     {
6358       XtSetArg (av[ac], XtNforeground, pixel);
6359       ++ac;
6360     }
6361 
6362   pixel = f->output_data.x->scroll_bar_background_pixel;
6363   if (pixel != -1)
6364     {
6365       XtSetArg (av[ac], XtNbackground, pixel);
6366       ++ac;
6367     }
6368 
6369   /* Top/bottom shadow colors.  */
6370 
6371   /* Allocate them, if necessary.  */
6372   if (f->output_data.x->scroll_bar_top_shadow_pixel == -1)
6373     {
6374       pixel = f->output_data.x->scroll_bar_background_pixel;
6375       if (pixel != -1)
6376         {
6377           if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
6378                                       FRAME_X_COLORMAP (f),
6379                                       &pixel, 1.2, 0x8000))
6380             pixel = -1;
6381           f->output_data.x->scroll_bar_top_shadow_pixel = pixel;
6382         }
6383     }
6384   if (f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
6385     {
6386       pixel = f->output_data.x->scroll_bar_background_pixel;
6387       if (pixel != -1)
6388         {
6389           if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
6390                                       FRAME_X_COLORMAP (f),
6391                                       &pixel, 0.6, 0x4000))
6392             pixel = -1;
6393           f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
6394         }
6395     }
6396 
6397 #ifdef XtNbeNiceToColormap
6398   /* Tell the toolkit about them.  */
6399   if (f->output_data.x->scroll_bar_top_shadow_pixel == -1
6400       || f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
6401     /* We tried to allocate a color for the top/bottom shadow, and
6402        failed, so tell Xaw3d to use dithering instead.   */
6403     /* But only if we have a small colormap.  Xaw3d can allocate nice
6404        colors itself.  */
6405     {
6406       XtSetArg (av[ac], XtNbeNiceToColormap,
6407                 DefaultDepthOfScreen (FRAME_X_SCREEN (f)) < 16);
6408       ++ac;
6409     }
6410   else
6411     /* Tell what colors Xaw3d should use for the top/bottom shadow, to
6412        be more consistent with other emacs 3d colors, and since Xaw3d is
6413        not good at dealing with allocation failure.  */
6414     {
6415       /* This tells Xaw3d to use real colors instead of dithering for
6416 	 the shadows.  */
6417       XtSetArg (av[ac], XtNbeNiceToColormap, False);
6418       ++ac;
6419 
6420       /* Specify the colors.  */
6421       pixel = f->output_data.x->scroll_bar_top_shadow_pixel;
6422       if (pixel != -1)
6423 	{
6424 	  XtSetArg (av[ac], XtNtopShadowPixel, pixel);
6425 	  ++ac;
6426 	}
6427       pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel;
6428       if (pixel != -1)
6429 	{
6430 	  XtSetArg (av[ac], XtNbottomShadowPixel, pixel);
6431 	  ++ac;
6432 	}
6433     }
6434 #endif
6435 
6436   widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
6437 			   f->output_data.x->edit_widget, av, ac);
6438 
6439   {
6440     char const *initial = "";
6441     char const *val = initial;
6442     XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
6443 #ifdef XtNarrowScrollbars
6444 		   XtNarrowScrollbars, (XtPointer) &xaw3d_arrow_scroll,
6445 #endif
6446 		   XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
6447     if (xaw3d_arrow_scroll || val == initial)
6448       {	/* ARROW_SCROLL */
6449 	xaw3d_arrow_scroll = True;
6450 	/* Isn't that just a personal preference ?   --Stef */
6451 	XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
6452       }
6453   }
6454 
6455   /* Define callbacks.  */
6456   XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
6457   XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
6458 		 (XtPointer) bar);
6459 
6460   /* Realize the widget.  Only after that is the X window created.  */
6461   XtRealizeWidget (widget);
6462 
6463 #endif /* !USE_MOTIF */
6464 
6465   /* Install an action hook that lets us detect when the user
6466      finishes interacting with a scroll bar.  */
6467   if (horizontal_action_hook_id == 0)
6468    horizontal_action_hook_id
6469      = XtAppAddActionHook (Xt_app_con, xt_horizontal_action_hook, 0);
6470 
6471   /* Remember X window and widget in the scroll bar vector.  */
6472   SET_SCROLL_BAR_X_WIDGET (bar, widget);
6473   xwindow = XtWindow (widget);
6474   bar->x_window = xwindow;
6475   bar->whole = 1;
6476   bar->horizontal = true;
6477 
6478   unblock_input ();
6479 }
6480 #endif /* not USE_GTK */
6481 
6482 
6483 /* Set the thumb size and position of scroll bar BAR.  We are currently
6484    displaying PORTION out of a whole WHOLE, and our position POSITION.  */
6485 
6486 #ifdef USE_GTK
6487 static void
x_set_toolkit_scroll_bar_thumb(struct scroll_bar * bar,int portion,int position,int whole)6488 x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position, int whole)
6489 {
6490   xg_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
6491 }
6492 
6493 static void
x_set_toolkit_horizontal_scroll_bar_thumb(struct scroll_bar * bar,int portion,int position,int whole)6494 x_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position, int whole)
6495 {
6496   xg_set_toolkit_horizontal_scroll_bar_thumb (bar, portion, position, whole);
6497 }
6498 
6499 #else /* not USE_GTK */
6500 static void
x_set_toolkit_scroll_bar_thumb(struct scroll_bar * bar,int portion,int position,int whole)6501 x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position,
6502 				int whole)
6503 {
6504   struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
6505   Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
6506   float top, shown;
6507 
6508   block_input ();
6509 
6510 #ifdef USE_MOTIF
6511 
6512   if (scroll_bar_adjust_thumb_portion_p)
6513     {
6514       /* We use an estimate of 30 chars per line rather than the real
6515          `portion' value.  This has the disadvantage that the thumb size
6516          is not very representative, but it makes our life a lot easier.
6517          Otherwise, we have to constantly adjust the thumb size, which
6518          we can't always do quickly enough: while dragging, the size of
6519          the thumb might prevent the user from dragging the thumb all the
6520          way to the end.  but Motif and some versions of Xaw3d don't allow
6521          updating the thumb size while dragging.  Also, even if we can update
6522          its size, the update will often happen too late.
6523          If you don't believe it, check out revision 1.650 of xterm.c to see
6524          what hoops we were going through and the still poor behavior we got.  */
6525       portion = WINDOW_TOTAL_LINES (XWINDOW (bar->window)) * 30;
6526       /* When the thumb is at the bottom, position == whole.
6527          So we need to increase `whole' to make space for the thumb.  */
6528       whole += portion;
6529     }
6530 
6531   if (whole <= 0)
6532     top = 0, shown = 1;
6533   else
6534     {
6535       top = (float) position / whole;
6536       shown = (float) portion / whole;
6537     }
6538 
6539   if (bar->dragging == -1)
6540     {
6541       int size, value;
6542 
6543       /* Slider size.  Must be in the range [1 .. MAX - MIN] where MAX
6544          is the scroll bar's maximum and MIN is the scroll bar's minimum
6545 	 value.  */
6546       size = clip_to_bounds (1, shown * XM_SB_MAX, XM_SB_MAX);
6547 
6548       /* Position.  Must be in the range [MIN .. MAX - SLIDER_SIZE].  */
6549       value = top * XM_SB_MAX;
6550       value = min (value, XM_SB_MAX - size);
6551 
6552       XmScrollBarSetValues (widget, value, size, 0, 0, False);
6553     }
6554 #else /* !USE_MOTIF i.e. use Xaw */
6555 
6556   if (whole == 0)
6557     top = 0, shown = 1;
6558   else
6559     {
6560       top = (float) position / whole;
6561       shown = (float) portion / whole;
6562     }
6563 
6564   {
6565     float old_top, old_shown;
6566     Dimension height;
6567     XtVaGetValues (widget,
6568 		   XtNtopOfThumb, &old_top,
6569 		   XtNshown, &old_shown,
6570 		   XtNheight, &height,
6571 		   NULL);
6572 
6573     /* Massage the top+shown values.  */
6574     if (bar->dragging == -1 || bar->last_seen_part == scroll_bar_down_arrow)
6575       top = max (0, min (1, top));
6576     else
6577       top = old_top;
6578 #if ! defined (HAVE_XAW3D)
6579     /* With Xaw, 'top' values too closer to 1.0 may
6580        cause the thumb to disappear.  Fix that.  */
6581     top = min (top, 0.99f);
6582 #endif
6583     /* Keep two pixels available for moving the thumb down.  */
6584     shown = max (0, min (1 - top - (2.0f / height), shown));
6585 #if ! defined (HAVE_XAW3D)
6586     /* Likewise with too small 'shown'.  */
6587     shown = max (shown, 0.01f);
6588 #endif
6589 
6590     /* If the call to XawScrollbarSetThumb below doesn't seem to
6591        work, check that 'NARROWPROTO' is defined in src/config.h.
6592        If this is not so, most likely you need to fix configure.  */
6593     if (top != old_top || shown != old_shown)
6594       {
6595 	if (bar->dragging == -1)
6596 	  XawScrollbarSetThumb (widget, top, shown);
6597 	else
6598 	  {
6599 	    /* Try to make the scrolling a tad smoother.  */
6600 	    if (!xaw3d_pick_top)
6601 	      shown = min (shown, old_shown);
6602 
6603 	    XawScrollbarSetThumb (widget, top, shown);
6604 	  }
6605       }
6606   }
6607 #endif /* !USE_MOTIF */
6608 
6609   unblock_input ();
6610 }
6611 
6612 static void
x_set_toolkit_horizontal_scroll_bar_thumb(struct scroll_bar * bar,int portion,int position,int whole)6613 x_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position,
6614 				int whole)
6615 {
6616   struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
6617   Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
6618   float top, shown;
6619 
6620   block_input ();
6621 
6622 #ifdef USE_MOTIF
6623   bar->whole = whole;
6624   shown = (float) portion / whole;
6625   top = (float) position / (whole - portion);
6626   {
6627     int size = clip_to_bounds (1, shown * XM_SB_MAX, XM_SB_MAX);
6628     int value = clip_to_bounds (0, top * (XM_SB_MAX - size), XM_SB_MAX - size);
6629 
6630     XmScrollBarSetValues (widget, value, size, 0, 0, False);
6631   }
6632 #else /* !USE_MOTIF i.e. use Xaw */
6633   bar->whole = whole;
6634   if (whole == 0)
6635     top = 0, shown = 1;
6636   else
6637     {
6638       top = (float) position / whole;
6639       shown = (float) portion / whole;
6640     }
6641 
6642   {
6643     float old_top, old_shown;
6644     Dimension height;
6645     XtVaGetValues (widget,
6646 		   XtNtopOfThumb, &old_top,
6647 		   XtNshown, &old_shown,
6648 		   XtNheight, &height,
6649 		   NULL);
6650 
6651 #if false
6652     /* Massage the top+shown values.  */
6653     if (bar->dragging == -1 || bar->last_seen_part == scroll_bar_down_arrow)
6654       top = max (0, min (1, top));
6655     else
6656       top = old_top;
6657 #if ! defined (HAVE_XAW3D)
6658     /* With Xaw, 'top' values too closer to 1.0 may
6659        cause the thumb to disappear.  Fix that.  */
6660     top = min (top, 0.99f);
6661 #endif
6662     /* Keep two pixels available for moving the thumb down.  */
6663     shown = max (0, min (1 - top - (2.0f / height), shown));
6664 #if ! defined (HAVE_XAW3D)
6665     /* Likewise with too small 'shown'.  */
6666     shown = max (shown, 0.01f);
6667 #endif
6668 #endif
6669 
6670     /* If the call to XawScrollbarSetThumb below doesn't seem to
6671        work, check that 'NARROWPROTO' is defined in src/config.h.
6672        If this is not so, most likely you need to fix configure.  */
6673     XawScrollbarSetThumb (widget, top, shown);
6674 #if false
6675     if (top != old_top || shown != old_shown)
6676       {
6677 	if (bar->dragging == -1)
6678 	  XawScrollbarSetThumb (widget, top, shown);
6679 	else
6680 	  {
6681 	    /* Try to make the scrolling a tad smoother.  */
6682 	    if (!xaw3d_pick_top)
6683 	      shown = min (shown, old_shown);
6684 
6685 	    XawScrollbarSetThumb (widget, top, shown);
6686 	  }
6687       }
6688 #endif
6689   }
6690 #endif /* !USE_MOTIF */
6691 
6692   unblock_input ();
6693 }
6694 #endif /* not USE_GTK */
6695 
6696 #endif /* USE_TOOLKIT_SCROLL_BARS */
6697 
6698 
6699 
6700 /************************************************************************
6701 			 Scroll bars, general
6702  ************************************************************************/
6703 
6704 /* Create a scroll bar and return the scroll bar vector for it.  W is
6705    the Emacs window on which to create the scroll bar. TOP, LEFT,
6706    WIDTH and HEIGHT are the pixel coordinates and dimensions of the
6707    scroll bar. */
6708 
6709 static struct scroll_bar *
x_scroll_bar_create(struct window * w,int top,int left,int width,int height,bool horizontal)6710 x_scroll_bar_create (struct window *w, int top, int left,
6711 		     int width, int height, bool horizontal)
6712 {
6713   struct frame *f = XFRAME (w->frame);
6714   struct scroll_bar *bar = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, prev,
6715 						  PVEC_OTHER);
6716   Lisp_Object barobj;
6717 
6718   block_input ();
6719 
6720 #ifdef USE_TOOLKIT_SCROLL_BARS
6721   if (horizontal)
6722     x_create_horizontal_toolkit_scroll_bar (f, bar);
6723   else
6724     x_create_toolkit_scroll_bar (f, bar);
6725 #else /* not USE_TOOLKIT_SCROLL_BARS */
6726   {
6727     XSetWindowAttributes a;
6728     unsigned long mask;
6729     Window window;
6730 
6731     a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
6732     if (a.background_pixel == -1)
6733       a.background_pixel = FRAME_BACKGROUND_PIXEL (f);
6734 
6735     a.event_mask = (ButtonPressMask | ButtonReleaseMask
6736 		    | ButtonMotionMask | PointerMotionHintMask
6737 		    | ExposureMask);
6738     a.cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
6739 
6740     mask = (CWBackPixel | CWEventMask | CWCursor);
6741 
6742     /* Clear the area of W that will serve as a scroll bar.  This is
6743        for the case that a window has been split horizontally.  In
6744        this case, no clear_frame is generated to reduce flickering.  */
6745     if (width > 0 && window_box_height (w) > 0)
6746       x_clear_area (f, left, top, width, window_box_height (w));
6747 
6748     window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6749 			    /* Position and size of scroll bar.  */
6750 			    left, top, width, height,
6751 			    /* Border width, depth, class, and visual.  */
6752 			    0,
6753 			    CopyFromParent,
6754 			    CopyFromParent,
6755 			    CopyFromParent,
6756 			     /* Attributes.  */
6757 			    mask, &a);
6758     bar->x_window = window;
6759   }
6760 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6761 
6762   XSETWINDOW (bar->window, w);
6763   bar->top = top;
6764   bar->left = left;
6765   bar->width = width;
6766   bar->height = height;
6767   bar->start = 0;
6768   bar->end = 0;
6769   bar->dragging = -1;
6770   bar->horizontal = horizontal;
6771 #if defined (USE_TOOLKIT_SCROLL_BARS) && defined (USE_LUCID)
6772   bar->last_seen_part = scroll_bar_nowhere;
6773 #endif
6774 
6775   /* Add bar to its frame's list of scroll bars.  */
6776   bar->next = FRAME_SCROLL_BARS (f);
6777   bar->prev = Qnil;
6778   XSETVECTOR (barobj, bar);
6779   fset_scroll_bars (f, barobj);
6780   if (!NILP (bar->next))
6781     XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
6782 
6783   /* Map the window/widget.  */
6784 #ifdef USE_TOOLKIT_SCROLL_BARS
6785   {
6786 #ifdef USE_GTK
6787     if (horizontal)
6788       xg_update_horizontal_scrollbar_pos (f, bar->x_window, top,
6789 					  left, width, max (height, 1));
6790     else
6791       xg_update_scrollbar_pos (f, bar->x_window, top,
6792 			       left, width, max (height, 1));
6793 #else /* not USE_GTK */
6794     Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
6795     XtConfigureWidget (scroll_bar, left, top, width, max (height, 1), 0);
6796     XtMapWidget (scroll_bar);
6797     /* Don't obscure any child frames.  */
6798     XLowerWindow (FRAME_X_DISPLAY (f), bar->x_window);
6799 #endif /* not USE_GTK */
6800     }
6801 #else /* not USE_TOOLKIT_SCROLL_BARS */
6802   XMapWindow (FRAME_X_DISPLAY (f), bar->x_window);
6803   /* Don't obscure any child frames.  */
6804   XLowerWindow (FRAME_X_DISPLAY (f), bar->x_window);
6805 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6806 
6807   unblock_input ();
6808   return bar;
6809 }
6810 
6811 
6812 #ifndef USE_TOOLKIT_SCROLL_BARS
6813 
6814 /* Draw BAR's handle in the proper position.
6815 
6816    If the handle is already drawn from START to END, don't bother
6817    redrawing it, unless REBUILD; in that case, always
6818    redraw it.  (REBUILD is handy for drawing the handle after expose
6819    events.)
6820 
6821    Normally, we want to constrain the start and end of the handle to
6822    fit inside its rectangle, but if the user is dragging the scroll
6823    bar handle, we want to let them drag it down all the way, so that
6824    the bar's top is as far down as it goes; otherwise, there's no way
6825    to move to the very end of the buffer.  */
6826 
6827 static void
x_scroll_bar_set_handle(struct scroll_bar * bar,int start,int end,bool rebuild)6828 x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end,
6829 			 bool rebuild)
6830 {
6831   bool dragging = bar->dragging != -1;
6832   Window w = bar->x_window;
6833   struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
6834   GC gc = f->output_data.x->normal_gc;
6835 
6836   /* If the display is already accurate, do nothing.  */
6837   if (! rebuild
6838       && start == bar->start
6839       && end == bar->end)
6840     return;
6841 
6842   block_input ();
6843 
6844   {
6845     int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, bar->width);
6846     int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, bar->height);
6847     int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
6848 
6849     /* Make sure the values are reasonable, and try to preserve
6850        the distance between start and end.  */
6851     {
6852       int length = end - start;
6853 
6854       if (start < 0)
6855 	start = 0;
6856       else if (start > top_range)
6857 	start = top_range;
6858       end = start + length;
6859 
6860       if (end < start)
6861 	end = start;
6862       else if (end > top_range && ! dragging)
6863 	end = top_range;
6864     }
6865 
6866     /* Store the adjusted setting in the scroll bar.  */
6867     bar->start = start;
6868     bar->end = end;
6869 
6870     /* Clip the end position, just for display.  */
6871     if (end > top_range)
6872       end = top_range;
6873 
6874     /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
6875        below top positions, to make sure the handle is always at least
6876        that many pixels tall.  */
6877     end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
6878 
6879     /* Draw the empty space above the handle.  Note that we can't clear
6880        zero-height areas; that means "clear to end of window."  */
6881     if ((inside_width > 0) && (start > 0))
6882       x_clear_area1 (FRAME_X_DISPLAY (f), w,
6883 		    VERTICAL_SCROLL_BAR_LEFT_BORDER,
6884 		    VERTICAL_SCROLL_BAR_TOP_BORDER,
6885 		    inside_width, start, False);
6886 
6887     /* Change to proper foreground color if one is specified.  */
6888     if (f->output_data.x->scroll_bar_foreground_pixel != -1)
6889       XSetForeground (FRAME_X_DISPLAY (f), gc,
6890 		      f->output_data.x->scroll_bar_foreground_pixel);
6891 
6892     /* Draw the handle itself.  */
6893     XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
6894 		    /* x, y, width, height */
6895 		    VERTICAL_SCROLL_BAR_LEFT_BORDER,
6896 		    VERTICAL_SCROLL_BAR_TOP_BORDER + start,
6897 		    inside_width, end - start);
6898 
6899     /* Restore the foreground color of the GC if we changed it above.  */
6900     if (f->output_data.x->scroll_bar_foreground_pixel != -1)
6901       XSetForeground (FRAME_X_DISPLAY (f), gc,
6902 		      FRAME_FOREGROUND_PIXEL (f));
6903 
6904     /* Draw the empty space below the handle.  Note that we can't
6905        clear zero-height areas; that means "clear to end of window." */
6906     if ((inside_width > 0) && (end < inside_height))
6907       x_clear_area1 (FRAME_X_DISPLAY (f), w,
6908 		    VERTICAL_SCROLL_BAR_LEFT_BORDER,
6909 		    VERTICAL_SCROLL_BAR_TOP_BORDER + end,
6910 		    inside_width, inside_height - end, False);
6911   }
6912 
6913   unblock_input ();
6914 }
6915 
6916 #endif /* !USE_TOOLKIT_SCROLL_BARS */
6917 
6918 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
6919    nil.  */
6920 
6921 static void
x_scroll_bar_remove(struct scroll_bar * bar)6922 x_scroll_bar_remove (struct scroll_bar *bar)
6923 {
6924   struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
6925   block_input ();
6926 
6927 #ifdef USE_TOOLKIT_SCROLL_BARS
6928 #ifdef USE_GTK
6929   xg_remove_scroll_bar (f, bar->x_window);
6930 #else /* not USE_GTK */
6931   XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));
6932 #endif /* not USE_GTK */
6933 #else
6934   XDestroyWindow (FRAME_X_DISPLAY (f), bar->x_window);
6935 #endif
6936 
6937   /* Dissociate this scroll bar from its window.  */
6938   if (bar->horizontal)
6939     wset_horizontal_scroll_bar (XWINDOW (bar->window), Qnil);
6940   else
6941     wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil);
6942 
6943   unblock_input ();
6944 }
6945 
6946 
6947 /* Set the handle of the vertical scroll bar for WINDOW to indicate
6948    that we are displaying PORTION characters out of a total of WHOLE
6949    characters, starting at POSITION.  If WINDOW has no scroll bar,
6950    create one.  */
6951 
6952 static void
XTset_vertical_scroll_bar(struct window * w,int portion,int whole,int position)6953 XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int position)
6954 {
6955   struct frame *f = XFRAME (w->frame);
6956   Lisp_Object barobj;
6957   struct scroll_bar *bar;
6958   int top, height, left, width;
6959   int window_y, window_height;
6960 
6961   /* Get window dimensions.  */
6962   window_box (w, ANY_AREA, 0, &window_y, 0, &window_height);
6963   top = window_y;
6964   height = window_height;
6965   left = WINDOW_SCROLL_BAR_AREA_X (w);
6966   width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
6967 
6968   /* Does the scroll bar exist yet?  */
6969   if (NILP (w->vertical_scroll_bar))
6970     {
6971       if (width > 0 && height > 0)
6972 	{
6973 	  block_input ();
6974           x_clear_area (f, left, top, width, height);
6975 	  unblock_input ();
6976 	}
6977 
6978       bar = x_scroll_bar_create (w, top, left, width, max (height, 1), false);
6979     }
6980   else
6981     {
6982       /* It may just need to be moved and resized.  */
6983       unsigned int mask = 0;
6984 
6985       bar = XSCROLL_BAR (w->vertical_scroll_bar);
6986 
6987       block_input ();
6988 
6989       if (left != bar->left)
6990 	mask |= CWX;
6991       if (top != bar->top)
6992 	mask |= CWY;
6993       if (width != bar->width)
6994 	mask |= CWWidth;
6995       if (height != bar->height)
6996 	mask |= CWHeight;
6997 
6998 #ifdef USE_TOOLKIT_SCROLL_BARS
6999 
7000       /* Move/size the scroll bar widget.  */
7001       if (mask)
7002 	{
7003 	  /* Since toolkit scroll bars are smaller than the space reserved
7004 	     for them on the frame, we have to clear "under" them.  */
7005 	  if (width > 0 && height > 0)
7006 	    x_clear_area (f, left, top, width, height);
7007 #ifdef USE_GTK
7008           xg_update_scrollbar_pos (f, bar->x_window, top,
7009 				   left, width, max (height, 1));
7010 #else /* not USE_GTK */
7011           XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
7012                              left, top, width, max (height, 1), 0);
7013 #endif /* not USE_GTK */
7014 	}
7015 #else /* not USE_TOOLKIT_SCROLL_BARS */
7016 
7017       /* Move/size the scroll bar window.  */
7018       if (mask)
7019 	{
7020 	  XWindowChanges wc;
7021 
7022 	  wc.x = left;
7023 	  wc.y = top;
7024 	  wc.width = width;
7025 	  wc.height = height;
7026 	  XConfigureWindow (FRAME_X_DISPLAY (f), bar->x_window,
7027 			    mask, &wc);
7028 	}
7029 
7030 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7031 
7032       /* Remember new settings.  */
7033       bar->left = left;
7034       bar->top = top;
7035       bar->width = width;
7036       bar->height = height;
7037 
7038       unblock_input ();
7039     }
7040 
7041 #ifdef USE_TOOLKIT_SCROLL_BARS
7042   x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
7043 #else /* not USE_TOOLKIT_SCROLL_BARS */
7044   /* Set the scroll bar's current state, unless we're currently being
7045      dragged.  */
7046   if (bar->dragging == -1)
7047     {
7048       int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
7049 
7050       if (whole == 0)
7051 	x_scroll_bar_set_handle (bar, 0, top_range, false);
7052       else
7053 	{
7054 	  int start = ((double) position * top_range) / whole;
7055 	  int end = ((double) (position + portion) * top_range) / whole;
7056 	  x_scroll_bar_set_handle (bar, start, end, false);
7057 	}
7058     }
7059 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7060 
7061   XSETVECTOR (barobj, bar);
7062   wset_vertical_scroll_bar (w, barobj);
7063 }
7064 
7065 
7066 static void
XTset_horizontal_scroll_bar(struct window * w,int portion,int whole,int position)7067 XTset_horizontal_scroll_bar (struct window *w, int portion, int whole, int position)
7068 {
7069   struct frame *f = XFRAME (w->frame);
7070   Lisp_Object barobj;
7071   struct scroll_bar *bar;
7072   int top, height, left, width;
7073   int window_x, window_width;
7074   int pixel_width = WINDOW_PIXEL_WIDTH (w);
7075 
7076   /* Get window dimensions.  */
7077   window_box (w, ANY_AREA, &window_x, 0, &window_width, 0);
7078   left = window_x;
7079   width = window_width;
7080   top = WINDOW_SCROLL_BAR_AREA_Y (w);
7081   height = WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
7082 
7083   /* Does the scroll bar exist yet?  */
7084   if (NILP (w->horizontal_scroll_bar))
7085     {
7086       if (width > 0 && height > 0)
7087 	{
7088 	  block_input ();
7089 
7090 	  /* Clear also part between window_width and
7091 	     WINDOW_PIXEL_WIDTH.  */
7092 	  x_clear_area (f, left, top, pixel_width, height);
7093 	  unblock_input ();
7094 	}
7095 
7096       bar = x_scroll_bar_create (w, top, left, width, height, true);
7097     }
7098   else
7099     {
7100       /* It may just need to be moved and resized.  */
7101       unsigned int mask = 0;
7102 
7103       bar = XSCROLL_BAR (w->horizontal_scroll_bar);
7104 
7105       block_input ();
7106 
7107       if (left != bar->left)
7108 	mask |= CWX;
7109       if (top != bar->top)
7110 	mask |= CWY;
7111       if (width != bar->width)
7112 	mask |= CWWidth;
7113       if (height != bar->height)
7114 	mask |= CWHeight;
7115 
7116 #ifdef USE_TOOLKIT_SCROLL_BARS
7117       /* Move/size the scroll bar widget.  */
7118       if (mask)
7119 	{
7120 	  /* Since toolkit scroll bars are smaller than the space reserved
7121 	     for them on the frame, we have to clear "under" them.  */
7122 	  if (width > 0 && height > 0)
7123 	    x_clear_area (f,
7124 			  WINDOW_LEFT_EDGE_X (w), top,
7125 			  pixel_width - WINDOW_RIGHT_DIVIDER_WIDTH (w), height);
7126 #ifdef USE_GTK
7127           xg_update_horizontal_scrollbar_pos (f, bar->x_window, top, left,
7128 					      width, height);
7129 #else /* not USE_GTK */
7130           XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
7131                              left, top, width, height, 0);
7132 #endif /* not USE_GTK */
7133 	}
7134 #else /* not USE_TOOLKIT_SCROLL_BARS */
7135 
7136       /* Clear areas not covered by the scroll bar because it's not as
7137 	 wide as the area reserved for it.  This makes sure a
7138 	 previous mode line display is cleared after C-x 2 C-x 1, for
7139 	 example.  */
7140       {
7141 	int area_height = WINDOW_CONFIG_SCROLL_BAR_HEIGHT (w);
7142 	int rest = area_height - height;
7143 	if (rest > 0 && width > 0)
7144 	  x_clear_area (f, left, top, width, rest);
7145       }
7146 
7147       /* Move/size the scroll bar window.  */
7148       if (mask)
7149 	{
7150 	  XWindowChanges wc;
7151 
7152 	  wc.x = left;
7153 	  wc.y = top;
7154 	  wc.width = width;
7155 	  wc.height = height;
7156 	  XConfigureWindow (FRAME_X_DISPLAY (f), bar->x_window,
7157 			    mask, &wc);
7158 	}
7159 
7160 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7161 
7162       /* Remember new settings.  */
7163       bar->left = left;
7164       bar->top = top;
7165       bar->width = width;
7166       bar->height = height;
7167 
7168       unblock_input ();
7169     }
7170 
7171 #ifdef USE_TOOLKIT_SCROLL_BARS
7172   x_set_toolkit_horizontal_scroll_bar_thumb (bar, portion, position, whole);
7173 #else /* not USE_TOOLKIT_SCROLL_BARS */
7174   /* Set the scroll bar's current state, unless we're currently being
7175      dragged.  */
7176   if (bar->dragging == -1)
7177     {
7178       int left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, width);
7179 
7180       if (whole == 0)
7181 	x_scroll_bar_set_handle (bar, 0, left_range, false);
7182       else
7183 	{
7184 	  int start = ((double) position * left_range) / whole;
7185 	  int end = ((double) (position + portion) * left_range) / whole;
7186 	  x_scroll_bar_set_handle (bar, start, end, false);
7187 	}
7188     }
7189 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7190 
7191   XSETVECTOR (barobj, bar);
7192   wset_horizontal_scroll_bar (w, barobj);
7193 }
7194 
7195 
7196 /* The following three hooks are used when we're doing a thorough
7197    redisplay of the frame.  We don't explicitly know which scroll bars
7198    are going to be deleted, because keeping track of when windows go
7199    away is a real pain - "Can you say set-window-configuration, boys
7200    and girls?"  Instead, we just assert at the beginning of redisplay
7201    that *all* scroll bars are to be removed, and then save a scroll bar
7202    from the fiery pit when we actually redisplay its window.  */
7203 
7204 /* Arrange for all scroll bars on FRAME to be removed at the next call
7205    to `*judge_scroll_bars_hook'.  A scroll bar may be spared if
7206    `*redeem_scroll_bar_hook' is applied to its window before the judgment.  */
7207 
7208 static void
XTcondemn_scroll_bars(struct frame * frame)7209 XTcondemn_scroll_bars (struct frame *frame)
7210 {
7211   if (!NILP (FRAME_SCROLL_BARS (frame)))
7212     {
7213       if (!NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
7214 	{
7215 	  /* Prepend scrollbars to already condemned ones.  */
7216 	  Lisp_Object last = FRAME_SCROLL_BARS (frame);
7217 
7218 	  while (!NILP (XSCROLL_BAR (last)->next))
7219 	    last = XSCROLL_BAR (last)->next;
7220 
7221 	  XSCROLL_BAR (last)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
7222 	  XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = last;
7223 	}
7224 
7225       fset_condemned_scroll_bars (frame, FRAME_SCROLL_BARS (frame));
7226       fset_scroll_bars (frame, Qnil);
7227     }
7228 }
7229 
7230 
7231 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
7232    Note that WINDOW isn't necessarily condemned at all.  */
7233 
7234 static void
XTredeem_scroll_bar(struct window * w)7235 XTredeem_scroll_bar (struct window *w)
7236 {
7237   struct scroll_bar *bar;
7238   Lisp_Object barobj;
7239   struct frame *f;
7240 
7241   /* We can't redeem this window's scroll bar if it doesn't have one.  */
7242   if (NILP (w->vertical_scroll_bar) && NILP (w->horizontal_scroll_bar))
7243     emacs_abort ();
7244 
7245   if (!NILP (w->vertical_scroll_bar) && WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
7246     {
7247       bar = XSCROLL_BAR (w->vertical_scroll_bar);
7248       /* Unlink it from the condemned list.  */
7249       f = XFRAME (WINDOW_FRAME (w));
7250       if (NILP (bar->prev))
7251 	{
7252 	  /* If the prev pointer is nil, it must be the first in one of
7253 	     the lists.  */
7254 	  if (EQ (FRAME_SCROLL_BARS (f), w->vertical_scroll_bar))
7255 	    /* It's not condemned.  Everything's fine.  */
7256 	    goto horizontal;
7257 	  else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
7258 		       w->vertical_scroll_bar))
7259 	    fset_condemned_scroll_bars (f, bar->next);
7260 	  else
7261 	    /* If its prev pointer is nil, it must be at the front of
7262 	       one or the other!  */
7263 	    emacs_abort ();
7264 	}
7265       else
7266 	XSCROLL_BAR (bar->prev)->next = bar->next;
7267 
7268       if (! NILP (bar->next))
7269 	XSCROLL_BAR (bar->next)->prev = bar->prev;
7270 
7271       bar->next = FRAME_SCROLL_BARS (f);
7272       bar->prev = Qnil;
7273       XSETVECTOR (barobj, bar);
7274       fset_scroll_bars (f, barobj);
7275       if (! NILP (bar->next))
7276 	XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
7277     }
7278 
7279  horizontal:
7280   if (!NILP (w->horizontal_scroll_bar) && WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
7281     {
7282       bar = XSCROLL_BAR (w->horizontal_scroll_bar);
7283       /* Unlink it from the condemned list.  */
7284       f = XFRAME (WINDOW_FRAME (w));
7285       if (NILP (bar->prev))
7286 	{
7287 	  /* If the prev pointer is nil, it must be the first in one of
7288 	     the lists.  */
7289 	  if (EQ (FRAME_SCROLL_BARS (f), w->horizontal_scroll_bar))
7290 	    /* It's not condemned.  Everything's fine.  */
7291 	    return;
7292 	  else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
7293 		       w->horizontal_scroll_bar))
7294 	    fset_condemned_scroll_bars (f, bar->next);
7295 	  else
7296 	    /* If its prev pointer is nil, it must be at the front of
7297 	       one or the other!  */
7298 	    emacs_abort ();
7299 	}
7300       else
7301 	XSCROLL_BAR (bar->prev)->next = bar->next;
7302 
7303       if (! NILP (bar->next))
7304 	XSCROLL_BAR (bar->next)->prev = bar->prev;
7305 
7306       bar->next = FRAME_SCROLL_BARS (f);
7307       bar->prev = Qnil;
7308       XSETVECTOR (barobj, bar);
7309       fset_scroll_bars (f, barobj);
7310       if (! NILP (bar->next))
7311 	XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
7312     }
7313 }
7314 
7315 /* Remove all scroll bars on FRAME that haven't been saved since the
7316    last call to `*condemn_scroll_bars_hook'.  */
7317 
7318 static void
XTjudge_scroll_bars(struct frame * f)7319 XTjudge_scroll_bars (struct frame *f)
7320 {
7321   Lisp_Object bar, next;
7322 
7323   bar = FRAME_CONDEMNED_SCROLL_BARS (f);
7324 
7325   /* Clear out the condemned list now so we won't try to process any
7326      more events on the hapless scroll bars.  */
7327   fset_condemned_scroll_bars (f, Qnil);
7328 
7329   for (; ! NILP (bar); bar = next)
7330     {
7331       struct scroll_bar *b = XSCROLL_BAR (bar);
7332 
7333       x_scroll_bar_remove (b);
7334 
7335       next = b->next;
7336       b->next = b->prev = Qnil;
7337     }
7338 
7339   /* Now there should be no references to the condemned scroll bars,
7340      and they should get garbage-collected.  */
7341 }
7342 
7343 
7344 #ifndef USE_TOOLKIT_SCROLL_BARS
7345 /* Handle an Expose or GraphicsExpose event on a scroll bar.  This
7346    is a no-op when using toolkit scroll bars.
7347 
7348    This may be called from a signal handler, so we have to ignore GC
7349    mark bits.  */
7350 
7351 static void
x_scroll_bar_expose(struct scroll_bar * bar,const XEvent * event)7352 x_scroll_bar_expose (struct scroll_bar *bar, const XEvent *event)
7353 {
7354   Window w = bar->x_window;
7355   struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7356   GC gc = f->output_data.x->normal_gc;
7357 
7358   block_input ();
7359 
7360   x_scroll_bar_set_handle (bar, bar->start, bar->end, true);
7361 
7362   /* Switch to scroll bar foreground color.  */
7363   if (f->output_data.x->scroll_bar_foreground_pixel != -1)
7364     XSetForeground (FRAME_X_DISPLAY (f), gc,
7365  		    f->output_data.x->scroll_bar_foreground_pixel);
7366 
7367   /* Draw a one-pixel border just inside the edges of the scroll bar.  */
7368   XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
7369 		  /* x, y, width, height */
7370 		  0, 0, bar->width - 1, bar->height - 1);
7371 
7372   /* Restore the foreground color of the GC if we changed it above.  */
7373   if (f->output_data.x->scroll_bar_foreground_pixel != -1)
7374     XSetForeground (FRAME_X_DISPLAY (f), gc,
7375 		    FRAME_FOREGROUND_PIXEL (f));
7376 
7377    unblock_input ();
7378 
7379 }
7380 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7381 
7382 /* Handle a mouse click on the scroll bar BAR.  If *EMACS_EVENT's kind
7383    is set to something other than NO_EVENT, it is enqueued.
7384 
7385    This may be called from a signal handler, so we have to ignore GC
7386    mark bits.  */
7387 
7388 
7389 static void
x_scroll_bar_handle_click(struct scroll_bar * bar,const XEvent * event,struct input_event * emacs_event)7390 x_scroll_bar_handle_click (struct scroll_bar *bar,
7391 			   const XEvent *event,
7392 			   struct input_event *emacs_event)
7393 {
7394   if (! WINDOWP (bar->window))
7395     emacs_abort ();
7396 
7397   emacs_event->kind = (bar->horizontal
7398 		       ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT
7399 		       : SCROLL_BAR_CLICK_EVENT);
7400   emacs_event->code = event->xbutton.button - Button1;
7401   emacs_event->modifiers
7402     = (x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO
7403 			       (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
7404 			       event->xbutton.state)
7405        | (event->type == ButtonRelease
7406 	  ? up_modifier
7407 	  : down_modifier));
7408   emacs_event->frame_or_window = bar->window;
7409   emacs_event->arg = Qnil;
7410   emacs_event->timestamp = event->xbutton.time;
7411   if (bar->horizontal)
7412     {
7413       int left_range
7414 	= HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width);
7415       int x = event->xbutton.x - HORIZONTAL_SCROLL_BAR_LEFT_BORDER;
7416 
7417       if (x < 0) x = 0;
7418       if (x > left_range) x = left_range;
7419 
7420       if (x < bar->start)
7421 	emacs_event->part = scroll_bar_before_handle;
7422       else if (x < bar->end + HORIZONTAL_SCROLL_BAR_MIN_HANDLE)
7423 	emacs_event->part = scroll_bar_horizontal_handle;
7424       else
7425 	emacs_event->part = scroll_bar_after_handle;
7426 
7427 #ifndef USE_TOOLKIT_SCROLL_BARS
7428       /* If the user has released the handle, set it to its final position.  */
7429       if (event->type == ButtonRelease && bar->dragging != -1)
7430 	{
7431 	  int new_start = - bar->dragging;
7432 	  int new_end = new_start + bar->end - bar->start;
7433 
7434 	  x_scroll_bar_set_handle (bar, new_start, new_end, false);
7435 	  bar->dragging = -1;
7436 	}
7437 #endif
7438 
7439       XSETINT (emacs_event->x, left_range);
7440       XSETINT (emacs_event->y, x);
7441     }
7442   else
7443     {
7444       int top_range
7445 	= VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
7446       int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
7447 
7448       if (y < 0) y = 0;
7449       if (y > top_range) y = top_range;
7450 
7451       if (y < bar->start)
7452 	emacs_event->part = scroll_bar_above_handle;
7453       else if (y < bar->end + VERTICAL_SCROLL_BAR_MIN_HANDLE)
7454 	emacs_event->part = scroll_bar_handle;
7455       else
7456 	emacs_event->part = scroll_bar_below_handle;
7457 
7458 #ifndef USE_TOOLKIT_SCROLL_BARS
7459       /* If the user has released the handle, set it to its final position.  */
7460       if (event->type == ButtonRelease && bar->dragging != -1)
7461 	{
7462 	  int new_start = y - bar->dragging;
7463 	  int new_end = new_start + bar->end - bar->start;
7464 
7465 	  x_scroll_bar_set_handle (bar, new_start, new_end, false);
7466 	  bar->dragging = -1;
7467 	}
7468 #endif
7469 
7470       XSETINT (emacs_event->x, y);
7471       XSETINT (emacs_event->y, top_range);
7472     }
7473 }
7474 
7475 #ifndef USE_TOOLKIT_SCROLL_BARS
7476 
7477 /* Handle some mouse motion while someone is dragging the scroll bar.
7478 
7479    This may be called from a signal handler, so we have to ignore GC
7480    mark bits.  */
7481 
7482 static void
x_scroll_bar_note_movement(struct scroll_bar * bar,const XMotionEvent * event)7483 x_scroll_bar_note_movement (struct scroll_bar *bar,
7484 			    const XMotionEvent *event)
7485 {
7486   struct frame *f = XFRAME (XWINDOW (bar->window)->frame);
7487   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
7488 
7489   dpyinfo->last_mouse_movement_time = event->time;
7490   dpyinfo->last_mouse_scroll_bar = bar;
7491   f->mouse_moved = true;
7492 
7493   /* If we're dragging the bar, display it.  */
7494   if (bar->dragging != -1)
7495     {
7496       /* Where should the handle be now?  */
7497       int new_start = event->y - bar->dragging;
7498 
7499       if (new_start != bar->start)
7500 	{
7501 	  int new_end = new_start + bar->end - bar->start;
7502 
7503 	  x_scroll_bar_set_handle (bar, new_start, new_end, false);
7504 	}
7505     }
7506 }
7507 
7508 #endif /* !USE_TOOLKIT_SCROLL_BARS */
7509 
7510 /* Return information to the user about the current position of the mouse
7511    on the scroll bar.  */
7512 
7513 static void
x_scroll_bar_report_motion(struct frame ** fp,Lisp_Object * bar_window,enum scroll_bar_part * part,Lisp_Object * x,Lisp_Object * y,Time * timestamp)7514 x_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
7515 			    enum scroll_bar_part *part, Lisp_Object *x,
7516 			    Lisp_Object *y, Time *timestamp)
7517 {
7518   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp);
7519   struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar;
7520   Window w = bar->x_window;
7521   struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7522   int win_x, win_y;
7523   Window dummy_window;
7524   int dummy_coord;
7525   unsigned int dummy_mask;
7526 
7527   block_input ();
7528 
7529   /* Get the mouse's position relative to the scroll bar window, and
7530      report that.  */
7531   if (XQueryPointer (FRAME_X_DISPLAY (f), w,
7532 
7533 		     /* Root, child, root x and root y.  */
7534 		     &dummy_window, &dummy_window,
7535 		     &dummy_coord, &dummy_coord,
7536 
7537 		     /* Position relative to scroll bar.  */
7538 		     &win_x, &win_y,
7539 
7540 		     /* Mouse buttons and modifier keys.  */
7541 		     &dummy_mask))
7542     {
7543       int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
7544 
7545       win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
7546 
7547       if (bar->dragging != -1)
7548 	win_y -= bar->dragging;
7549 
7550       if (win_y < 0)
7551 	win_y = 0;
7552       if (win_y > top_range)
7553 	win_y = top_range;
7554 
7555       *fp = f;
7556       *bar_window = bar->window;
7557 
7558       if (bar->dragging != -1)
7559 	*part = scroll_bar_handle;
7560       else if (win_y < bar->start)
7561 	*part = scroll_bar_above_handle;
7562       else if (win_y < bar->end + VERTICAL_SCROLL_BAR_MIN_HANDLE)
7563 	*part = scroll_bar_handle;
7564       else
7565 	*part = scroll_bar_below_handle;
7566 
7567       XSETINT (*x, win_y);
7568       XSETINT (*y, top_range);
7569 
7570       f->mouse_moved = false;
7571       dpyinfo->last_mouse_scroll_bar = NULL;
7572       *timestamp = dpyinfo->last_mouse_movement_time;
7573     }
7574 
7575   unblock_input ();
7576 }
7577 
7578 
7579 /* Return information to the user about the current position of the mouse
7580    on the scroll bar.  */
7581 
7582 static void
x_horizontal_scroll_bar_report_motion(struct frame ** fp,Lisp_Object * bar_window,enum scroll_bar_part * part,Lisp_Object * x,Lisp_Object * y,Time * timestamp)7583 x_horizontal_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
7584 				       enum scroll_bar_part *part, Lisp_Object *x,
7585 				       Lisp_Object *y, Time *timestamp)
7586 {
7587   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp);
7588   struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar;
7589   Window w = bar->x_window;
7590   struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7591   int win_x, win_y;
7592   Window dummy_window;
7593   int dummy_coord;
7594   unsigned int dummy_mask;
7595 
7596   block_input ();
7597 
7598   /* Get the mouse's position relative to the scroll bar window, and
7599      report that.  */
7600   if (XQueryPointer (FRAME_X_DISPLAY (f), w,
7601 
7602 		     /* Root, child, root x and root y.  */
7603 		     &dummy_window, &dummy_window,
7604 		     &dummy_coord, &dummy_coord,
7605 
7606 		     /* Position relative to scroll bar.  */
7607 		     &win_x, &win_y,
7608 
7609 		     /* Mouse buttons and modifier keys.  */
7610 		     &dummy_mask))
7611     {
7612       int left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width);
7613 
7614       win_x -= HORIZONTAL_SCROLL_BAR_LEFT_BORDER;
7615 
7616       if (bar->dragging != -1)
7617 	win_x -= bar->dragging;
7618 
7619       if (win_x < 0)
7620 	win_x = 0;
7621       if (win_x > left_range)
7622 	win_x = left_range;
7623 
7624       *fp = f;
7625       *bar_window = bar->window;
7626 
7627       if (bar->dragging != -1)
7628 	*part = scroll_bar_horizontal_handle;
7629       else if (win_x < bar->start)
7630 	*part = scroll_bar_before_handle;
7631       else if (win_x < bar->end + HORIZONTAL_SCROLL_BAR_MIN_HANDLE)
7632 	*part = scroll_bar_handle;
7633       else
7634 	*part = scroll_bar_after_handle;
7635 
7636       XSETINT (*y, win_x);
7637       XSETINT (*x, left_range);
7638 
7639       f->mouse_moved = false;
7640       dpyinfo->last_mouse_scroll_bar = NULL;
7641       *timestamp = dpyinfo->last_mouse_movement_time;
7642     }
7643 
7644   unblock_input ();
7645 }
7646 
7647 
7648 /* The screen has been cleared so we may have changed foreground or
7649    background colors, and the scroll bars may need to be redrawn.
7650    Clear out the scroll bars, and ask for expose events, so we can
7651    redraw them.  */
7652 
7653 static void
x_scroll_bar_clear(struct frame * f)7654 x_scroll_bar_clear (struct frame *f)
7655 {
7656 #ifndef USE_TOOLKIT_SCROLL_BARS
7657   Lisp_Object bar;
7658 
7659   /* We can have scroll bars even if this is 0,
7660      if we just turned off scroll bar mode.
7661      But in that case we should not clear them.  */
7662   if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
7663     for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
7664 	 bar = XSCROLL_BAR (bar)->next)
7665       XClearArea (FRAME_X_DISPLAY (f),
7666 		  XSCROLL_BAR (bar)->x_window,
7667 		  0, 0, 0, 0, True);
7668 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7669 }
7670 
7671 #ifdef ENABLE_CHECKING
7672 
7673 /* Record the last 100 characters stored
7674    to help debug the loss-of-chars-during-GC problem.  */
7675 
7676 static int temp_index;
7677 static short temp_buffer[100];
7678 
7679 #define STORE_KEYSYM_FOR_DEBUG(keysym)				\
7680   if (temp_index == ARRAYELTS (temp_buffer))			\
7681     temp_index = 0;						\
7682   temp_buffer[temp_index++] = (keysym)
7683 
7684 #else /* not ENABLE_CHECKING */
7685 
7686 #define STORE_KEYSYM_FOR_DEBUG(keysym) ((void)0)
7687 
7688 #endif /* ENABLE_CHECKING */
7689 
7690 /* Set this to nonzero to fake an "X I/O error"
7691    on a particular display.  */
7692 
7693 static struct x_display_info *XTread_socket_fake_io_error;
7694 
7695 /* When we find no input here, we occasionally do a no-op command
7696    to verify that the X server is still running and we can still talk with it.
7697    We try all the open displays, one by one.
7698    This variable is used for cycling thru the displays.  */
7699 
7700 static struct x_display_info *next_noop_dpyinfo;
7701 
7702 enum
7703 {
7704   X_EVENT_NORMAL,
7705   X_EVENT_GOTO_OUT,
7706   X_EVENT_DROP
7707 };
7708 
7709 /* Filter events for the current X input method.
7710    DPYINFO is the display this event is for.
7711    EVENT is the X event to filter.
7712 
7713    Returns non-zero if the event was filtered, caller shall not process
7714    this event further.
7715    Returns zero if event is wasn't filtered.  */
7716 
7717 #ifdef HAVE_X_I18N
7718 static int
x_filter_event(struct x_display_info * dpyinfo,XEvent * event)7719 x_filter_event (struct x_display_info *dpyinfo, XEvent *event)
7720 {
7721   /* XFilterEvent returns non-zero if the input method has
7722    consumed the event.  We pass the frame's X window to
7723    XFilterEvent because that's the one for which the IC
7724    was created.  */
7725 
7726   struct frame *f1 = x_any_window_to_frame (dpyinfo,
7727                                             event->xclient.window);
7728 
7729   return XFilterEvent (event, f1 ? FRAME_X_WINDOW (f1) : None);
7730 }
7731 #endif
7732 
7733 #ifdef USE_GTK
7734 static int current_count;
7735 static int current_finish;
7736 static struct input_event *current_hold_quit;
7737 
7738 /* This is the filter function invoked by the GTK event loop.
7739    It is invoked before the XEvent is translated to a GdkEvent,
7740    so we have a chance to act on the event before GTK.  */
7741 static GdkFilterReturn
event_handler_gdk(GdkXEvent * gxev,GdkEvent * ev,gpointer data)7742 event_handler_gdk (GdkXEvent *gxev, GdkEvent *ev, gpointer data)
7743 {
7744   XEvent *xev = (XEvent *) gxev;
7745 
7746   block_input ();
7747   if (current_count >= 0)
7748     {
7749       struct x_display_info *dpyinfo;
7750 
7751       dpyinfo = x_display_info_for_display (xev->xany.display);
7752 
7753 #ifdef HAVE_X_I18N
7754       /* Filter events for the current X input method.
7755          GTK calls XFilterEvent but not for key press and release,
7756          so we do it here.  */
7757       if ((xev->type == KeyPress || xev->type == KeyRelease)
7758 	  && dpyinfo
7759 	  && x_filter_event (dpyinfo, xev))
7760 	{
7761 	  unblock_input ();
7762 	  return GDK_FILTER_REMOVE;
7763 	}
7764 #endif
7765 
7766       if (! dpyinfo)
7767         current_finish = X_EVENT_NORMAL;
7768       else
7769 	current_count
7770 	  += handle_one_xevent (dpyinfo, xev, &current_finish,
7771 				current_hold_quit);
7772     }
7773   else
7774     current_finish = x_dispatch_event (xev, xev->xany.display);
7775 
7776   unblock_input ();
7777 
7778   if (current_finish == X_EVENT_GOTO_OUT || current_finish == X_EVENT_DROP)
7779     return GDK_FILTER_REMOVE;
7780 
7781   return GDK_FILTER_CONTINUE;
7782 }
7783 #endif /* USE_GTK */
7784 
7785 
7786 static void xembed_send_message (struct frame *f, Time,
7787                                  enum xembed_message,
7788                                  long detail, long data1, long data2);
7789 
7790 static void
x_net_wm_state(struct frame * f,Window window)7791 x_net_wm_state (struct frame *f, Window window)
7792 {
7793   int value = FULLSCREEN_NONE;
7794   Lisp_Object lval = Qnil;
7795   bool sticky = false;
7796 
7797   x_get_current_wm_state (f, window, &value, &sticky);
7798 
7799   switch (value)
7800     {
7801     case FULLSCREEN_WIDTH:
7802       lval = Qfullwidth;
7803       break;
7804     case FULLSCREEN_HEIGHT:
7805       lval = Qfullheight;
7806       break;
7807     case FULLSCREEN_BOTH:
7808       lval = Qfullboth;
7809       break;
7810     case FULLSCREEN_MAXIMIZED:
7811       lval = Qmaximized;
7812       break;
7813     }
7814 
7815   frame_size_history_add
7816     (f, Qx_net_wm_state, 0, 0,
7817      list2 (get_frame_param (f, Qfullscreen), lval));
7818 
7819   store_frame_param (f, Qfullscreen, lval);
7820 /**   store_frame_param (f, Qsticky, sticky ? Qt : Qnil); **/
7821 }
7822 
7823 /* Flip back buffers on any frames with undrawn content.  */
7824 static void
flush_dirty_back_buffers(void)7825 flush_dirty_back_buffers (void)
7826 {
7827   block_input ();
7828   Lisp_Object tail, frame;
7829   FOR_EACH_FRAME (tail, frame)
7830     {
7831       struct frame *f = XFRAME (frame);
7832       if (FRAME_LIVE_P (f) &&
7833           FRAME_X_P (f) &&
7834           FRAME_X_WINDOW (f) &&
7835           !FRAME_GARBAGED_P (f) &&
7836           !buffer_flipping_blocked_p () &&
7837           FRAME_X_NEED_BUFFER_FLIP (f))
7838         show_back_buffer (f);
7839     }
7840   unblock_input ();
7841 }
7842 
7843 /**
7844   mouse_or_wdesc_frame: When not dropping and the mouse was grabbed
7845   for DPYINFO, return the frame where the mouse was seen last.  If
7846   there's no such frame, return the frame according to WDESC.  When
7847   dropping, return the frame according to WDESC.  If there's no such
7848   frame and the mouse was grabbed for DPYINFO, return the frame where
7849   the mouse was seen last.  In either case, never return a tooltip
7850   frame.  */
7851 static struct frame *
mouse_or_wdesc_frame(struct x_display_info * dpyinfo,int wdesc)7852 mouse_or_wdesc_frame (struct x_display_info *dpyinfo, int wdesc)
7853 {
7854   struct frame *lm_f = (gui_mouse_grabbed (dpyinfo)
7855 			? dpyinfo->last_mouse_frame
7856 			: NULL);
7857 
7858   if (lm_f && !EQ (track_mouse, Qdropping))
7859     return lm_f;
7860   else
7861     {
7862       struct frame *w_f = x_window_to_frame (dpyinfo, wdesc);
7863 
7864       /* Do not return a tooltip frame.  */
7865       if (!w_f || FRAME_TOOLTIP_P (w_f))
7866 	return EQ (track_mouse, Qdropping) ? lm_f : NULL;
7867       else
7868 	/* When dropping it would be probably nice to raise w_f
7869 	   here.  */
7870 	return w_f;
7871     }
7872 }
7873 
7874 /* Handles the XEvent EVENT on display DPYINFO.
7875 
7876    *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
7877    *FINISH is zero if caller should continue reading events.
7878    *FINISH is X_EVENT_DROP if event should not be passed to the toolkit.
7879    *EVENT is unchanged unless we're processing KeyPress event.
7880 
7881    We return the number of characters stored into the buffer.  */
7882 
7883 static int
handle_one_xevent(struct x_display_info * dpyinfo,const XEvent * event,int * finish,struct input_event * hold_quit)7884 handle_one_xevent (struct x_display_info *dpyinfo,
7885 		   const XEvent *event,
7886 		   int *finish, struct input_event *hold_quit)
7887 {
7888   union buffered_input_event inev;
7889   int count = 0;
7890   int do_help = 0;
7891   ptrdiff_t nbytes = 0;
7892   struct frame *any, *f = NULL;
7893   struct coding_system coding;
7894   Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
7895   /* This holds the state XLookupString needs to implement dead keys
7896      and other tricks known as "compose processing".  _X Window System_
7897      says that a portable program can't use this, but Stephen Gildea assures
7898      me that letting the compiler initialize it to zeros will work okay.  */
7899   static XComposeStatus compose_status;
7900   XEvent configureEvent;
7901   XEvent next_event;
7902 
7903   USE_SAFE_ALLOCA;
7904 
7905   *finish = X_EVENT_NORMAL;
7906 
7907   EVENT_INIT (inev.ie);
7908   inev.ie.kind = NO_EVENT;
7909   inev.ie.arg = Qnil;
7910 
7911   any = x_any_window_to_frame (dpyinfo, event->xany.window);
7912 
7913   if (any && any->wait_event_type == event->type)
7914     any->wait_event_type = 0; /* Indicates we got it.  */
7915 
7916   switch (event->type)
7917     {
7918     case ClientMessage:
7919       {
7920         if (event->xclient.message_type == dpyinfo->Xatom_wm_protocols
7921             && event->xclient.format == 32)
7922           {
7923             if (event->xclient.data.l[0] == dpyinfo->Xatom_wm_take_focus)
7924               {
7925                 /* Use the value returned by x_any_window_to_frame
7926 		   because this could be the shell widget window
7927 		   if the frame has no title bar.  */
7928                 f = any;
7929 #ifdef HAVE_X_I18N
7930                 /* Not quite sure this is needed -pd */
7931                 if (f && FRAME_XIC (f))
7932                   XSetICFocus (FRAME_XIC (f));
7933 #endif
7934 #if false
7935       /* Emacs sets WM hints whose `input' field is `true'.  This
7936 	 instructs the WM to set the input focus automatically for
7937 	 Emacs with a call to XSetInputFocus.  Setting WM_TAKE_FOCUS
7938 	 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
7939 	 it has set the focus.  So, XSetInputFocus below is not
7940 	 needed.
7941 
7942 	 The call to XSetInputFocus below has also caused trouble.  In
7943 	 cases where the XSetInputFocus done by the WM and the one
7944 	 below are temporally close (on a fast machine), the call
7945 	 below can generate additional FocusIn events which confuse
7946 	 Emacs.  */
7947 
7948                 /* Since we set WM_TAKE_FOCUS, we must call
7949                    XSetInputFocus explicitly.  But not if f is null,
7950                    since that might be an event for a deleted frame.  */
7951                 if (f)
7952                   {
7953                     Display *d = event->xclient.display;
7954                     /* Catch and ignore errors, in case window has been
7955                        iconified by a window manager such as GWM.  */
7956                     x_catch_errors (d);
7957                     XSetInputFocus (d, event->xclient.window,
7958                                     /* The ICCCM says this is
7959                                        the only valid choice.  */
7960                                     RevertToParent,
7961                                     event->xclient.data.l[1]);
7962                     x_uncatch_errors ();
7963                   }
7964                 /* Not certain about handling scroll bars here */
7965 #endif
7966 		goto done;
7967               }
7968 
7969             if (event->xclient.data.l[0] == dpyinfo->Xatom_wm_save_yourself)
7970               {
7971                 /* Save state modify the WM_COMMAND property to
7972                    something which can reinstate us.  This notifies
7973                    the session manager, who's looking for such a
7974                    PropertyNotify.  Can restart processing when
7975                    a keyboard or mouse event arrives.  */
7976                 /* If we have a session manager, don't set this.
7977                    KDE will then start two Emacsen, one for the
7978                    session manager and one for this. */
7979 #ifdef HAVE_X_SM
7980                 if (! x_session_have_connection ())
7981 #endif
7982                   {
7983                     f = x_top_window_to_frame (dpyinfo,
7984                                                event->xclient.window);
7985                     /* This is just so we only give real data once
7986                        for a single Emacs process.  */
7987                     if (f == SELECTED_FRAME ())
7988                       XSetCommand (FRAME_X_DISPLAY (f),
7989                                    event->xclient.window,
7990                                    initial_argv, initial_argc);
7991                     else if (f)
7992                       XSetCommand (FRAME_X_DISPLAY (f),
7993                                    event->xclient.window,
7994                                    0, 0);
7995                   }
7996 		goto done;
7997               }
7998 
7999             if (event->xclient.data.l[0] == dpyinfo->Xatom_wm_delete_window)
8000               {
8001                 f = any;
8002                 if (!f)
8003 		  goto OTHER; /* May be a dialog that is to be removed  */
8004 
8005 		inev.ie.kind = DELETE_WINDOW_EVENT;
8006 		XSETFRAME (inev.ie.frame_or_window, f);
8007 		goto done;
8008               }
8009 
8010 	    goto done;
8011           }
8012 
8013         if (event->xclient.message_type == dpyinfo->Xatom_wm_configure_denied)
8014 	  goto done;
8015 
8016         if (event->xclient.message_type == dpyinfo->Xatom_wm_window_moved)
8017           {
8018             int new_x, new_y;
8019 	    f = x_window_to_frame (dpyinfo, event->xclient.window);
8020 
8021             new_x = event->xclient.data.s[0];
8022             new_y = event->xclient.data.s[1];
8023 
8024             if (f)
8025               {
8026                 f->left_pos = new_x;
8027                 f->top_pos = new_y;
8028               }
8029 	    goto done;
8030           }
8031 
8032 #ifdef X_TOOLKIT_EDITRES
8033         if (event->xclient.message_type == dpyinfo->Xatom_editres)
8034           {
8035 	    f = any;
8036 	    if (f)
8037               _XEditResCheckMessages (f->output_data.x->widget,
8038 				      NULL, (XEvent *) event, NULL);
8039 	    goto done;
8040           }
8041 #endif /* X_TOOLKIT_EDITRES */
8042 
8043         if (event->xclient.message_type == dpyinfo->Xatom_DONE
8044 	    || event->xclient.message_type == dpyinfo->Xatom_PAGE)
8045           {
8046             /* Ghostview job completed.  Kill it.  We could
8047                reply with "Next" if we received "Page", but we
8048                currently never do because we are interested in
8049                images, only, which should have 1 page.  */
8050 	    f = x_window_to_frame (dpyinfo, event->xclient.window);
8051 	    if (!f)
8052 	      goto OTHER;
8053 #ifndef USE_CAIRO
8054             Pixmap pixmap = (Pixmap) event->xclient.data.l[1];
8055             x_kill_gs_process (pixmap, f);
8056             expose_frame (f, 0, 0, 0, 0);
8057 #endif	/* !USE_CAIRO */
8058 	    goto done;
8059           }
8060 
8061 #ifdef USE_TOOLKIT_SCROLL_BARS
8062         /* Scroll bar callbacks send a ClientMessage from which
8063            we construct an input_event.  */
8064         if (event->xclient.message_type == dpyinfo->Xatom_Scrollbar)
8065           {
8066             x_scroll_bar_to_input_event (event, &inev.ie);
8067 	    *finish = X_EVENT_GOTO_OUT;
8068             goto done;
8069           }
8070         else if (event->xclient.message_type == dpyinfo->Xatom_Horizontal_Scrollbar)
8071           {
8072             x_horizontal_scroll_bar_to_input_event (event, &inev.ie);
8073 	    *finish = X_EVENT_GOTO_OUT;
8074             goto done;
8075           }
8076 #endif /* USE_TOOLKIT_SCROLL_BARS */
8077 
8078 	/* XEmbed messages from the embedder (if any).  */
8079         if (event->xclient.message_type == dpyinfo->Xatom_XEMBED)
8080           {
8081 	    enum xembed_message msg = event->xclient.data.l[1];
8082 	    if (msg == XEMBED_FOCUS_IN || msg == XEMBED_FOCUS_OUT)
8083 	      x_detect_focus_change (dpyinfo, any, event, &inev.ie);
8084 
8085 	    *finish = X_EVENT_GOTO_OUT;
8086             goto done;
8087           }
8088 
8089         xft_settings_event (dpyinfo, event);
8090 
8091 	f = any;
8092 	if (!f)
8093 	  goto OTHER;
8094 	if (x_handle_dnd_message (f, &event->xclient, dpyinfo, &inev.ie))
8095 	  *finish = X_EVENT_DROP;
8096       }
8097       break;
8098 
8099     case SelectionNotify:
8100       x_display_set_last_user_time (dpyinfo, event->xselection.time);
8101 #ifdef USE_X_TOOLKIT
8102       if (! x_window_to_frame (dpyinfo, event->xselection.requestor))
8103         goto OTHER;
8104 #endif /* not USE_X_TOOLKIT */
8105       x_handle_selection_notify (&event->xselection);
8106       break;
8107 
8108     case SelectionClear:	/* Someone has grabbed ownership.  */
8109       x_display_set_last_user_time (dpyinfo, event->xselectionclear.time);
8110 #ifdef USE_X_TOOLKIT
8111       if (! x_window_to_frame (dpyinfo, event->xselectionclear.window))
8112         goto OTHER;
8113 #endif /* USE_X_TOOLKIT */
8114       {
8115         const XSelectionClearEvent *eventp = &event->xselectionclear;
8116 
8117         inev.sie.kind = SELECTION_CLEAR_EVENT;
8118         SELECTION_EVENT_DPYINFO (&inev.sie) = dpyinfo;
8119         SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
8120         SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
8121       }
8122       break;
8123 
8124     case SelectionRequest:	/* Someone wants our selection.  */
8125       x_display_set_last_user_time (dpyinfo, event->xselectionrequest.time);
8126 #ifdef USE_X_TOOLKIT
8127       if (!x_window_to_frame (dpyinfo, event->xselectionrequest.owner))
8128         goto OTHER;
8129 #endif /* USE_X_TOOLKIT */
8130       {
8131 	const XSelectionRequestEvent *eventp = &event->xselectionrequest;
8132 
8133 	inev.sie.kind = SELECTION_REQUEST_EVENT;
8134 	SELECTION_EVENT_DPYINFO (&inev.sie) = dpyinfo;
8135 	SELECTION_EVENT_REQUESTOR (&inev.sie) = eventp->requestor;
8136 	SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
8137 	SELECTION_EVENT_TARGET (&inev.sie) = eventp->target;
8138 	SELECTION_EVENT_PROPERTY (&inev.sie) = eventp->property;
8139 	SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
8140       }
8141       break;
8142 
8143     case PropertyNotify:
8144       x_display_set_last_user_time (dpyinfo, event->xproperty.time);
8145       f = x_top_window_to_frame (dpyinfo, event->xproperty.window);
8146       if (f && event->xproperty.atom == dpyinfo->Xatom_net_wm_state)
8147 	{
8148           bool not_hidden = x_handle_net_wm_state (f, &event->xproperty);
8149 	  if (not_hidden && FRAME_ICONIFIED_P (f))
8150 	    {
8151 	      /* Gnome shell does not iconify us when C-z is pressed.
8152 		 It hides the frame.  So if our state says we aren't
8153 		 hidden anymore, treat it as deiconified.  */
8154 	      SET_FRAME_VISIBLE (f, 1);
8155 	      SET_FRAME_ICONIFIED (f, false);
8156 	      f->output_data.x->has_been_visible = true;
8157 	      inev.ie.kind = DEICONIFY_EVENT;
8158 	      XSETFRAME (inev.ie.frame_or_window, f);
8159 	    }
8160 	  else if (! not_hidden && ! FRAME_ICONIFIED_P (f))
8161 	    {
8162 	      SET_FRAME_VISIBLE (f, 0);
8163 	      SET_FRAME_ICONIFIED (f, true);
8164 	      inev.ie.kind = ICONIFY_EVENT;
8165 	      XSETFRAME (inev.ie.frame_or_window, f);
8166 	    }
8167 	}
8168 
8169       x_handle_property_notify (&event->xproperty);
8170       xft_settings_event (dpyinfo, event);
8171       goto OTHER;
8172 
8173     case ReparentNotify:
8174       f = x_top_window_to_frame (dpyinfo, event->xreparent.window);
8175       if (f)
8176         {
8177 	  /* Maybe we shouldn't set this for child frames ??  */
8178 	  f->output_data.x->parent_desc = event->xreparent.parent;
8179 	  if (!FRAME_PARENT_FRAME (f))
8180 	    x_real_positions (f, &f->left_pos, &f->top_pos);
8181 	  else
8182 	    {
8183 	      Window root;
8184 	      unsigned int dummy_uint;
8185 
8186 	      block_input ();
8187 	      XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
8188 			    &root, &f->left_pos, &f->top_pos,
8189 			    &dummy_uint, &dummy_uint, &dummy_uint, &dummy_uint);
8190 	      unblock_input ();
8191 	    }
8192 
8193           /* Perhaps reparented due to a WM restart.  Reset this.  */
8194           FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN;
8195           FRAME_DISPLAY_INFO (f)->net_supported_window = 0;
8196 
8197           x_set_frame_alpha (f);
8198         }
8199       goto OTHER;
8200 
8201     case Expose:
8202       f = x_window_to_frame (dpyinfo, event->xexpose.window);
8203       if (f)
8204         {
8205           if (!FRAME_VISIBLE_P (f))
8206             {
8207               block_input ();
8208               SET_FRAME_VISIBLE (f, 1);
8209               SET_FRAME_ICONIFIED (f, false);
8210               if (FRAME_X_DOUBLE_BUFFERED_P (f))
8211                 font_drop_xrender_surfaces (f);
8212               f->output_data.x->has_been_visible = true;
8213               SET_FRAME_GARBAGED (f);
8214               unblock_input ();
8215             }
8216           else if (FRAME_GARBAGED_P (f))
8217             {
8218 #ifdef USE_GTK
8219               /* Go around the back buffer and manually clear the
8220                  window the first time we show it.  This way, we avoid
8221                  showing users the sanity-defying horror of whatever
8222                  GtkWindow is rendering beneath us.  We've garbaged
8223                  the frame, so we'll redraw the whole thing on next
8224                  redisplay anyway.  Yuck.  */
8225               x_clear_area1 (
8226                 FRAME_X_DISPLAY (f),
8227                 FRAME_X_WINDOW (f),
8228                 event->xexpose.x, event->xexpose.y,
8229                 event->xexpose.width, event->xexpose.height,
8230                 0);
8231 	      x_clear_under_internal_border (f);
8232 #endif
8233             }
8234 
8235 
8236           if (!FRAME_GARBAGED_P (f))
8237             {
8238 #ifdef USE_GTK
8239               /* This seems to be needed for GTK 2.6 and later, see
8240                  https://debbugs.gnu.org/cgi/bugreport.cgi?bug=15398.  */
8241               x_clear_area (f,
8242                             event->xexpose.x, event->xexpose.y,
8243                             event->xexpose.width, event->xexpose.height);
8244 #endif
8245               expose_frame (f, event->xexpose.x, event->xexpose.y,
8246 			    event->xexpose.width, event->xexpose.height);
8247 #ifdef USE_GTK
8248 	      x_clear_under_internal_border (f);
8249 #endif
8250             }
8251 
8252           if (!FRAME_GARBAGED_P (f))
8253             show_back_buffer (f);
8254         }
8255       else
8256         {
8257 #ifndef USE_TOOLKIT_SCROLL_BARS
8258           struct scroll_bar *bar;
8259 #endif
8260 #if defined USE_LUCID
8261           /* Submenus of the Lucid menu bar aren't widgets
8262              themselves, so there's no way to dispatch events
8263              to them.  Recognize this case separately.  */
8264           {
8265             Widget widget = x_window_to_menu_bar (event->xexpose.window);
8266             if (widget)
8267               xlwmenu_redisplay (widget);
8268           }
8269 #endif /* USE_LUCID */
8270 
8271 #ifdef USE_TOOLKIT_SCROLL_BARS
8272           /* Dispatch event to the widget.  */
8273           goto OTHER;
8274 #else /* not USE_TOOLKIT_SCROLL_BARS */
8275           bar = x_window_to_scroll_bar (event->xexpose.display,
8276                                         event->xexpose.window, 2);
8277 
8278           if (bar)
8279             x_scroll_bar_expose (bar, event);
8280 #ifdef USE_X_TOOLKIT
8281           else
8282             goto OTHER;
8283 #endif /* USE_X_TOOLKIT */
8284 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8285         }
8286       break;
8287 
8288     case GraphicsExpose:	/* This occurs when an XCopyArea's
8289                                    source area was obscured or not
8290                                    available.  */
8291       f = x_window_to_frame (dpyinfo, event->xgraphicsexpose.drawable);
8292       if (f)
8293         {
8294           expose_frame (f, event->xgraphicsexpose.x,
8295                         event->xgraphicsexpose.y,
8296                         event->xgraphicsexpose.width,
8297                         event->xgraphicsexpose.height);
8298 #ifdef USE_GTK
8299 	  x_clear_under_internal_border (f);
8300 #endif
8301 	  show_back_buffer (f);
8302         }
8303 #ifdef USE_X_TOOLKIT
8304       else
8305         goto OTHER;
8306 #endif /* USE_X_TOOLKIT */
8307       break;
8308 
8309     case NoExpose:		/* This occurs when an XCopyArea's
8310                                    source area was completely
8311                                    available.  */
8312       break;
8313 
8314     case UnmapNotify:
8315       /* Redo the mouse-highlight after the tooltip has gone.  */
8316       if (event->xunmap.window == tip_window)
8317         {
8318           tip_window = None;
8319           gui_redo_mouse_highlight (dpyinfo);
8320         }
8321 
8322       f = x_top_window_to_frame (dpyinfo, event->xunmap.window);
8323       if (f)		/* F may no longer exist if
8324                            the frame was deleted.  */
8325         {
8326 	  bool visible = FRAME_VISIBLE_P (f);
8327           /* While a frame is unmapped, display generation is
8328              disabled; you don't want to spend time updating a
8329              display that won't ever be seen.  */
8330           SET_FRAME_VISIBLE (f, 0);
8331           /* We can't distinguish, from the event, whether the window
8332              has become iconified or invisible.  So assume, if it
8333              was previously visible, than now it is iconified.
8334              But x_make_frame_invisible clears both
8335              the visible flag and the iconified flag;
8336              and that way, we know the window is not iconified now.  */
8337           if (visible || FRAME_ICONIFIED_P (f))
8338             {
8339               SET_FRAME_ICONIFIED (f, true);
8340               inev.ie.kind = ICONIFY_EVENT;
8341               XSETFRAME (inev.ie.frame_or_window, f);
8342             }
8343         }
8344       goto OTHER;
8345 
8346     case MapNotify:
8347       /* We use x_top_window_to_frame because map events can
8348          come for sub-windows and they don't mean that the
8349          frame is visible.  */
8350       f = x_top_window_to_frame (dpyinfo, event->xmap.window);
8351       if (f)
8352         {
8353 	  bool iconified = FRAME_ICONIFIED_P (f);
8354 
8355           /* Check if fullscreen was specified before we where mapped the
8356              first time, i.e. from the command line.  */
8357           if (!f->output_data.x->has_been_visible)
8358 	    {
8359 
8360 	      x_check_fullscreen (f);
8361 #ifndef USE_GTK
8362 	      /* For systems that cannot synthesize `skip_taskbar' for
8363 		 unmapped windows do the following.  */
8364 	      if (FRAME_SKIP_TASKBAR (f))
8365 		x_set_skip_taskbar (f, Qt, Qnil);
8366 #endif /* Not USE_GTK */
8367 	    }
8368 
8369 	  if (!iconified)
8370 	    {
8371 	      /* The `z-group' is reset every time a frame becomes
8372 		 invisible.  Handle this here.  */
8373 	      if (FRAME_Z_GROUP (f) == z_group_above)
8374 		x_set_z_group (f, Qabove, Qnil);
8375 	      else if (FRAME_Z_GROUP (f) == z_group_below)
8376 		x_set_z_group (f, Qbelow, Qnil);
8377 	    }
8378 
8379           SET_FRAME_VISIBLE (f, 1);
8380           SET_FRAME_ICONIFIED (f, false);
8381           f->output_data.x->has_been_visible = true;
8382 
8383           if (iconified)
8384             {
8385               inev.ie.kind = DEICONIFY_EVENT;
8386               XSETFRAME (inev.ie.frame_or_window, f);
8387             }
8388           else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list)))
8389             /* Force a redisplay sooner or later to update the
8390 	       frame titles in case this is the second frame.  */
8391             record_asynch_buffer_change ();
8392         }
8393       goto OTHER;
8394 
8395     case KeyPress:
8396 
8397       x_display_set_last_user_time (dpyinfo, event->xkey.time);
8398       ignore_next_mouse_click_timeout = 0;
8399 
8400 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
8401       /* Dispatch KeyPress events when in menu.  */
8402       if (popup_activated ())
8403         goto OTHER;
8404 #endif
8405 
8406       f = any;
8407 
8408       /* If mouse-highlight is an integer, input clears out
8409 	 mouse highlighting.  */
8410       if (!hlinfo->mouse_face_hidden && FIXNUMP (Vmouse_highlight)
8411 	  && (f == 0
8412 #if ! defined (USE_GTK)
8413 	      || !EQ (f->tool_bar_window, hlinfo->mouse_face_window)
8414 #endif
8415 	      || !EQ (f->tab_bar_window, hlinfo->mouse_face_window))
8416 	  )
8417         {
8418           clear_mouse_face (hlinfo);
8419           hlinfo->mouse_face_hidden = true;
8420         }
8421 
8422 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
8423       if (f == 0)
8424         {
8425           /* Scroll bars consume key events, but we want
8426              the keys to go to the scroll bar's frame.  */
8427           Widget widget = XtWindowToWidget (dpyinfo->display,
8428                                             event->xkey.window);
8429           if (widget && XmIsScrollBar (widget))
8430             {
8431               widget = XtParent (widget);
8432               f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
8433             }
8434         }
8435 #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
8436 
8437       if (f != 0)
8438         {
8439           KeySym keysym, orig_keysym;
8440           /* al%imercury@uunet.uu.net says that making this 81
8441              instead of 80 fixed a bug whereby meta chars made
8442              his Emacs hang.
8443 
8444              It seems that some version of XmbLookupString has
8445              a bug of not returning XBufferOverflow in
8446              status_return even if the input is too long to
8447              fit in 81 bytes.  So, we must prepare sufficient
8448              bytes for copy_buffer.  513 bytes (256 chars for
8449              two-byte character set) seems to be a fairly good
8450              approximation.  -- 2000.8.10 handa@gnu.org  */
8451           unsigned char copy_buffer[513];
8452           unsigned char *copy_bufptr = copy_buffer;
8453           int copy_bufsiz = sizeof (copy_buffer);
8454           int modifiers;
8455           Lisp_Object coding_system = Qlatin_1;
8456 	  Lisp_Object c;
8457 	  /* Event will be modified.  */
8458 	  XKeyEvent xkey = event->xkey;
8459 
8460 #ifdef USE_GTK
8461           /* Don't pass keys to GTK.  A Tab will shift focus to the
8462              tool bar in GTK 2.4.  Keys will still go to menus and
8463              dialogs because in that case popup_activated is nonzero
8464              (see above).  */
8465           *finish = X_EVENT_DROP;
8466 #endif
8467 
8468           xkey.state |= x_emacs_to_x_modifiers (FRAME_DISPLAY_INFO (f),
8469 						extra_keyboard_modifiers);
8470           modifiers = xkey.state;
8471 
8472           /* This will have to go some day...  */
8473 
8474           /* make_lispy_event turns chars into control chars.
8475              Don't do it here because XLookupString is too eager.  */
8476           xkey.state &= ~ControlMask;
8477           xkey.state &= ~(dpyinfo->meta_mod_mask
8478 			  | dpyinfo->super_mod_mask
8479 			  | dpyinfo->hyper_mod_mask
8480 			  | dpyinfo->alt_mod_mask);
8481 
8482           /* In case Meta is ComposeCharacter,
8483              clear its status.  According to Markus Ehrnsperger
8484              Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
8485              this enables ComposeCharacter to work whether or
8486              not it is combined with Meta.  */
8487           if (modifiers & dpyinfo->meta_mod_mask)
8488             memset (&compose_status, 0, sizeof (compose_status));
8489 
8490 #ifdef HAVE_X_I18N
8491           if (FRAME_XIC (f))
8492             {
8493               Status status_return;
8494 
8495               coding_system = Vlocale_coding_system;
8496               nbytes = XmbLookupString (FRAME_XIC (f),
8497                                         &xkey, (char *) copy_bufptr,
8498                                         copy_bufsiz, &keysym,
8499                                         &status_return);
8500               if (status_return == XBufferOverflow)
8501                 {
8502                   copy_bufsiz = nbytes + 1;
8503                   copy_bufptr = alloca (copy_bufsiz);
8504                   nbytes = XmbLookupString (FRAME_XIC (f),
8505                                             &xkey, (char *) copy_bufptr,
8506                                             copy_bufsiz, &keysym,
8507                                             &status_return);
8508                 }
8509               /* Xutf8LookupString is a new but already deprecated interface.  -stef  */
8510               if (status_return == XLookupNone)
8511                 break;
8512               else if (status_return == XLookupChars)
8513                 {
8514                   keysym = NoSymbol;
8515                   modifiers = 0;
8516                 }
8517               else if (status_return != XLookupKeySym
8518                        && status_return != XLookupBoth)
8519                 emacs_abort ();
8520             }
8521           else
8522             nbytes = XLookupString (&xkey, (char *) copy_bufptr,
8523                                     copy_bufsiz, &keysym,
8524                                     &compose_status);
8525 #else
8526           nbytes = XLookupString (&xkey, (char *) copy_bufptr,
8527                                   copy_bufsiz, &keysym,
8528                                   &compose_status);
8529 #endif
8530 
8531           /* If not using XIM/XIC, and a compose sequence is in progress,
8532              we break here.  Otherwise, chars_matched is always 0.  */
8533           if (compose_status.chars_matched > 0 && nbytes == 0)
8534             break;
8535 
8536           memset (&compose_status, 0, sizeof (compose_status));
8537           orig_keysym = keysym;
8538 
8539  	  /* Common for all keysym input events.  */
8540  	  XSETFRAME (inev.ie.frame_or_window, f);
8541  	  inev.ie.modifiers
8542  	    = x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), modifiers);
8543  	  inev.ie.timestamp = xkey.time;
8544 
8545  	  /* First deal with keysyms which have defined
8546  	     translations to characters.  */
8547  	  if (keysym >= 32 && keysym < 128)
8548  	    /* Avoid explicitly decoding each ASCII character.  */
8549  	    {
8550  	      inev.ie.kind = ASCII_KEYSTROKE_EVENT;
8551  	      inev.ie.code = keysym;
8552 	      goto done_keysym;
8553 	    }
8554 
8555 	  /* Keysyms directly mapped to Unicode characters.  */
8556 	  if (keysym >= 0x01000000 && keysym <= 0x0110FFFF)
8557 	    {
8558 	      if (keysym < 0x01000080)
8559 		inev.ie.kind = ASCII_KEYSTROKE_EVENT;
8560 	      else
8561 		inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
8562 	      inev.ie.code = keysym & 0xFFFFFF;
8563 	      goto done_keysym;
8564 	    }
8565 
8566 	  /* Now non-ASCII.  */
8567 	  if (HASH_TABLE_P (Vx_keysym_table)
8568 	      && (c = Fgethash (make_fixnum (keysym),
8569 				Vx_keysym_table,
8570 				Qnil),
8571 		  FIXNATP (c)))
8572  	    {
8573 	      inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFIXNAT (c))
8574                               ? ASCII_KEYSTROKE_EVENT
8575                               : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
8576 	      inev.ie.code = XFIXNAT (c);
8577  	      goto done_keysym;
8578  	    }
8579 
8580  	  /* Random non-modifier sorts of keysyms.  */
8581  	  if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
8582                         || keysym == XK_Delete
8583 #ifdef XK_ISO_Left_Tab
8584                         || (keysym >= XK_ISO_Left_Tab
8585                             && keysym <= XK_ISO_Enter)
8586 #endif
8587                         || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
8588                         || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
8589 #ifdef HPUX
8590                         /* This recognizes the "extended function
8591                            keys".  It seems there's no cleaner way.
8592                            Test IsModifierKey to avoid handling
8593                            mode_switch incorrectly.  */
8594                         || (XK_Select <= keysym && keysym < XK_KP_Space)
8595 #endif
8596 #ifdef XK_dead_circumflex
8597                         || orig_keysym == XK_dead_circumflex
8598 #endif
8599 #ifdef XK_dead_grave
8600                         || orig_keysym == XK_dead_grave
8601 #endif
8602 #ifdef XK_dead_tilde
8603                         || orig_keysym == XK_dead_tilde
8604 #endif
8605 #ifdef XK_dead_diaeresis
8606                         || orig_keysym == XK_dead_diaeresis
8607 #endif
8608 #ifdef XK_dead_macron
8609                         || orig_keysym == XK_dead_macron
8610 #endif
8611 #ifdef XK_dead_degree
8612                         || orig_keysym == XK_dead_degree
8613 #endif
8614 #ifdef XK_dead_acute
8615                         || orig_keysym == XK_dead_acute
8616 #endif
8617 #ifdef XK_dead_cedilla
8618                         || orig_keysym == XK_dead_cedilla
8619 #endif
8620 #ifdef XK_dead_breve
8621                         || orig_keysym == XK_dead_breve
8622 #endif
8623 #ifdef XK_dead_ogonek
8624                         || orig_keysym == XK_dead_ogonek
8625 #endif
8626 #ifdef XK_dead_caron
8627                         || orig_keysym == XK_dead_caron
8628 #endif
8629 #ifdef XK_dead_doubleacute
8630                         || orig_keysym == XK_dead_doubleacute
8631 #endif
8632 #ifdef XK_dead_abovedot
8633                         || orig_keysym == XK_dead_abovedot
8634 #endif
8635                         || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
8636                         || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
8637                         /* Any "vendor-specific" key is ok.  */
8638                         || (orig_keysym & (1 << 28))
8639                         || (keysym != NoSymbol && nbytes == 0))
8640                        && ! (IsModifierKey (orig_keysym)
8641                              /* The symbols from XK_ISO_Lock
8642                                 to XK_ISO_Last_Group_Lock
8643                                 don't have real modifiers but
8644                                 should be treated similarly to
8645                                 Mode_switch by Emacs. */
8646 #if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
8647                              || (XK_ISO_Lock <= orig_keysym
8648 				 && orig_keysym <= XK_ISO_Last_Group_Lock)
8649 #endif
8650                              ))
8651 	    {
8652 	      STORE_KEYSYM_FOR_DEBUG (keysym);
8653 	      /* make_lispy_event will convert this to a symbolic
8654 		 key.  */
8655 	      inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
8656 	      inev.ie.code = keysym;
8657 	      goto done_keysym;
8658 	    }
8659 
8660 	  {	/* Raw bytes, not keysym.  */
8661 	    ptrdiff_t i;
8662 	    int nchars, len;
8663 
8664 	    for (i = 0, nchars = 0; i < nbytes; i++)
8665 	      {
8666 		if (ASCII_CHAR_P (copy_bufptr[i]))
8667 		  nchars++;
8668 		STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]);
8669 	      }
8670 
8671 	    if (nchars < nbytes)
8672 	      {
8673 		/* Decode the input data.  */
8674 
8675 		/* The input should be decoded with `coding_system'
8676 		   which depends on which X*LookupString function
8677 		   we used just above and the locale.  */
8678 		setup_coding_system (coding_system, &coding);
8679 		coding.src_multibyte = false;
8680 		coding.dst_multibyte = true;
8681 		/* The input is converted to events, thus we can't
8682 		   handle composition.  Anyway, there's no XIM that
8683 		   gives us composition information.  */
8684 		coding.common_flags &= ~CODING_ANNOTATION_MASK;
8685 
8686 		SAFE_NALLOCA (coding.destination, MAX_MULTIBYTE_LENGTH,
8687 			      nbytes);
8688 		coding.dst_bytes = MAX_MULTIBYTE_LENGTH * nbytes;
8689 		coding.mode |= CODING_MODE_LAST_BLOCK;
8690 		decode_coding_c_string (&coding, copy_bufptr, nbytes, Qnil);
8691 		nbytes = coding.produced;
8692 		nchars = coding.produced_char;
8693 		copy_bufptr = coding.destination;
8694 	      }
8695 
8696 	    /* Convert the input data to a sequence of
8697 	       character events.  */
8698 	    for (i = 0; i < nbytes; i += len)
8699 	      {
8700 		int ch;
8701 		if (nchars == nbytes)
8702 		  ch = copy_bufptr[i], len = 1;
8703 		else
8704 		  ch = STRING_CHAR_AND_LENGTH (copy_bufptr + i, len);
8705 		inev.ie.kind = (SINGLE_BYTE_CHAR_P (ch)
8706 				? ASCII_KEYSTROKE_EVENT
8707 				: MULTIBYTE_CHAR_KEYSTROKE_EVENT);
8708 		inev.ie.code = ch;
8709 		kbd_buffer_store_buffered_event (&inev, hold_quit);
8710 	      }
8711 
8712 	    count += nchars;
8713 
8714 	    inev.ie.kind = NO_EVENT;  /* Already stored above.  */
8715 
8716 	    if (keysym == NoSymbol)
8717 	      break;
8718 	  }
8719 	  /* FIXME: check side effects and remove this.  */
8720 	  ((XEvent *) event)->xkey = xkey;
8721         }
8722     done_keysym:
8723 #ifdef HAVE_X_I18N
8724       /* Don't dispatch this event since XtDispatchEvent calls
8725          XFilterEvent, and two calls in a row may freeze the
8726          client.  */
8727       break;
8728 #else
8729       goto OTHER;
8730 #endif
8731 
8732     case KeyRelease:
8733       x_display_set_last_user_time (dpyinfo, event->xkey.time);
8734 #ifdef HAVE_X_I18N
8735       /* Don't dispatch this event since XtDispatchEvent calls
8736          XFilterEvent, and two calls in a row may freeze the
8737          client.  */
8738       break;
8739 #else
8740       goto OTHER;
8741 #endif
8742 
8743     case EnterNotify:
8744       x_display_set_last_user_time (dpyinfo, event->xcrossing.time);
8745       x_detect_focus_change (dpyinfo, any, event, &inev.ie);
8746 
8747       f = any;
8748 
8749       if (f && x_mouse_click_focus_ignore_position)
8750 	ignore_next_mouse_click_timeout = event->xmotion.time + 200;
8751 
8752       /* EnterNotify counts as mouse movement,
8753 	 so update things that depend on mouse position.  */
8754       if (f && !f->output_data.x->hourglass_p)
8755 	x_note_mouse_movement (f, &event->xmotion);
8756 #ifdef USE_GTK
8757       /* We may get an EnterNotify on the buttons in the toolbar.  In that
8758          case we moved out of any highlighted area and need to note this.  */
8759       if (!f && dpyinfo->last_mouse_glyph_frame)
8760         x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &event->xmotion);
8761 #endif
8762       goto OTHER;
8763 
8764     case FocusIn:
8765       /* Some WMs (e.g. Mutter in Gnome Shell), don't unmap
8766          minimized/iconified windows; thus, for those WMs we won't get
8767          a MapNotify when unminimizing/deconifying.  Check here if we
8768          are deconizing a window (Bug42655). */
8769       f = any;
8770       if (f && FRAME_ICONIFIED_P (f))
8771 	{
8772           SET_FRAME_VISIBLE (f, 1);
8773           SET_FRAME_ICONIFIED (f, false);
8774           f->output_data.x->has_been_visible = true;
8775           inev.ie.kind = DEICONIFY_EVENT;
8776           XSETFRAME (inev.ie.frame_or_window, f);
8777         }
8778 
8779       x_detect_focus_change (dpyinfo, any, event, &inev.ie);
8780       goto OTHER;
8781 
8782     case LeaveNotify:
8783       x_display_set_last_user_time (dpyinfo, event->xcrossing.time);
8784       x_detect_focus_change (dpyinfo, any, event, &inev.ie);
8785 
8786       f = x_top_window_to_frame (dpyinfo, event->xcrossing.window);
8787       if (f)
8788         {
8789           if (f == hlinfo->mouse_face_mouse_frame)
8790             {
8791               /* If we move outside the frame, then we're
8792                  certainly no longer on any text in the frame.  */
8793               clear_mouse_face (hlinfo);
8794               hlinfo->mouse_face_mouse_frame = 0;
8795             }
8796 
8797           /* Generate a nil HELP_EVENT to cancel a help-echo.
8798              Do it only if there's something to cancel.
8799              Otherwise, the startup message is cleared when
8800              the mouse leaves the frame.  */
8801           if (any_help_event_p)
8802 	    do_help = -1;
8803         }
8804 #ifdef USE_GTK
8805       /* See comment in EnterNotify above */
8806       else if (dpyinfo->last_mouse_glyph_frame)
8807         x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &event->xmotion);
8808 #endif
8809       goto OTHER;
8810 
8811     case FocusOut:
8812       x_detect_focus_change (dpyinfo, any, event, &inev.ie);
8813       goto OTHER;
8814 
8815     case MotionNotify:
8816       {
8817         x_display_set_last_user_time (dpyinfo, event->xmotion.time);
8818         previous_help_echo_string = help_echo_string;
8819         help_echo_string = Qnil;
8820 
8821 	if (hlinfo->mouse_face_hidden)
8822           {
8823             hlinfo->mouse_face_hidden = false;
8824             clear_mouse_face (hlinfo);
8825           }
8826 
8827 	f = mouse_or_wdesc_frame (dpyinfo, event->xmotion.window);
8828 
8829 #ifdef USE_GTK
8830         if (f && xg_event_is_for_scrollbar (f, event))
8831           f = 0;
8832 #endif
8833         if (f)
8834           {
8835 	    /* Maybe generate a SELECT_WINDOW_EVENT for
8836 	       `mouse-autoselect-window' but don't let popup menus
8837 	       interfere with this (Bug#1261).  */
8838             if (!NILP (Vmouse_autoselect_window)
8839 		&& !popup_activated ()
8840 		/* Don't switch if we're currently in the minibuffer.
8841 		   This tries to work around problems where the
8842 		   minibuffer gets unselected unexpectedly, and where
8843 		   you then have to move your mouse all the way down to
8844 		   the minibuffer to select it.  */
8845 		&& !MINI_WINDOW_P (XWINDOW (selected_window))
8846 		/* With `focus-follows-mouse' non-nil create an event
8847 		   also when the target window is on another frame.  */
8848 		&& (f == XFRAME (selected_frame)
8849 		    || !NILP (focus_follows_mouse)))
8850 	      {
8851 		static Lisp_Object last_mouse_window;
8852 		Lisp_Object window = window_from_coordinates
8853 		  (f, event->xmotion.x, event->xmotion.y, 0, false, false);
8854 
8855 		/* A window will be autoselected only when it is not
8856 		   selected now and the last mouse movement event was
8857 		   not in it.  The remainder of the code is a bit vague
8858 		   wrt what a "window" is.  For immediate autoselection,
8859 		   the window is usually the entire window but for GTK
8860 		   where the scroll bars don't count.  For delayed
8861 		   autoselection the window is usually the window's text
8862 		   area including the margins.  */
8863 		if (WINDOWP (window)
8864 		    && !EQ (window, last_mouse_window)
8865 		    && !EQ (window, selected_window))
8866 		  {
8867 		    inev.ie.kind = SELECT_WINDOW_EVENT;
8868 		    inev.ie.frame_or_window = window;
8869 		  }
8870 
8871 		/* Remember the last window where we saw the mouse.  */
8872 		last_mouse_window = window;
8873 	      }
8874 
8875             if (!x_note_mouse_movement (f, &event->xmotion))
8876 	      help_echo_string = previous_help_echo_string;
8877           }
8878         else
8879           {
8880 #ifndef USE_TOOLKIT_SCROLL_BARS
8881             struct scroll_bar *bar
8882               = x_window_to_scroll_bar (event->xmotion.display,
8883                                         event->xmotion.window, 2);
8884 
8885             if (bar)
8886               x_scroll_bar_note_movement (bar, &event->xmotion);
8887 #endif /* USE_TOOLKIT_SCROLL_BARS */
8888 
8889             /* If we move outside the frame, then we're
8890                certainly no longer on any text in the frame.  */
8891             clear_mouse_face (hlinfo);
8892           }
8893 
8894         /* If the contents of the global variable help_echo_string
8895            has changed, generate a HELP_EVENT.  */
8896         if (!NILP (help_echo_string)
8897             || !NILP (previous_help_echo_string))
8898 	  do_help = 1;
8899         goto OTHER;
8900       }
8901 
8902     case ConfigureNotify:
8903       /* An opaque move can generate a stream of events as the window
8904          is dragged around.  If the connection round trip time isn't
8905          really short, they may come faster than we can respond to
8906          them, given the multiple queries we can do to check window
8907          manager state, translate coordinates, etc.
8908 
8909          So if this ConfigureNotify is immediately followed by another
8910          for the same window, use the info from the latest update, and
8911          consider the events all handled.  */
8912       /* Opaque resize may be trickier; ConfigureNotify events are
8913          mixed with Expose events for multiple windows.  */
8914       configureEvent = *event;
8915       while (XPending (dpyinfo->display))
8916         {
8917           XNextEvent (dpyinfo->display, &next_event);
8918           if (next_event.type != ConfigureNotify
8919               || next_event.xconfigure.window != event->xconfigure.window
8920               /* Skipping events with different sizes can lead to a
8921                  mispositioned mode line at initial window creation.
8922                  Only drop window motion events for now.  */
8923               || next_event.xconfigure.width != event->xconfigure.width
8924               || next_event.xconfigure.height != event->xconfigure.height)
8925             {
8926               XPutBackEvent (dpyinfo->display, &next_event);
8927               break;
8928             }
8929           else
8930 	    configureEvent = next_event;
8931         }
8932 
8933       f = x_top_window_to_frame (dpyinfo, configureEvent.xconfigure.window);
8934       /* Unfortunately, we need to call font_drop_xrender_surfaces for
8935          _all_ ConfigureNotify events, otherwise we miss some and
8936          flicker.  Don't try to optimize these calls by looking only
8937          for size changes: that's not sufficient.  We miss some
8938          surface invalidations and flicker.  */
8939       block_input ();
8940       if (f && FRAME_X_DOUBLE_BUFFERED_P (f))
8941         font_drop_xrender_surfaces (f);
8942       unblock_input ();
8943 #if defined USE_CAIRO && !defined USE_GTK
8944       if (f)
8945 	x_cr_update_surface_desired_size (f, configureEvent.xconfigure.width,
8946 					  configureEvent.xconfigure.height);
8947       else if (any && configureEvent.xconfigure.window == FRAME_X_WINDOW (any))
8948 	x_cr_update_surface_desired_size (any,
8949 					  configureEvent.xconfigure.width,
8950 					  configureEvent.xconfigure.height);
8951 #endif
8952 #ifdef USE_GTK
8953       if (!f
8954           && (f = any)
8955           && configureEvent.xconfigure.window == FRAME_X_WINDOW (f))
8956         {
8957           block_input ();
8958           if (FRAME_X_DOUBLE_BUFFERED_P (f))
8959             font_drop_xrender_surfaces (f);
8960           unblock_input ();
8961           xg_frame_resized (f, configureEvent.xconfigure.width,
8962                             configureEvent.xconfigure.height);
8963 #ifdef USE_CAIRO
8964 	  x_cr_update_surface_desired_size (f, configureEvent.xconfigure.width,
8965 					    configureEvent.xconfigure.height);
8966 #endif
8967           f = 0;
8968         }
8969 #endif
8970       if (f)
8971         {
8972 #ifdef USE_GTK
8973 	  /* For GTK+ don't call x_net_wm_state for the scroll bar
8974 	     window.  (Bug#24963, Bug#25887) */
8975 	  if (configureEvent.xconfigure.window == FRAME_X_WINDOW (f))
8976 #endif
8977 	    x_net_wm_state (f, configureEvent.xconfigure.window);
8978 
8979 #ifdef USE_X_TOOLKIT
8980           /* Tip frames are pure X window, set size for them.  */
8981           if (FRAME_TOOLTIP_P (f))
8982             {
8983               if (FRAME_PIXEL_HEIGHT (f) != configureEvent.xconfigure.height
8984                   || FRAME_PIXEL_WIDTH (f) != configureEvent.xconfigure.width)
8985                 {
8986                   SET_FRAME_GARBAGED (f);
8987                 }
8988               FRAME_PIXEL_HEIGHT (f) = configureEvent.xconfigure.height;
8989               FRAME_PIXEL_WIDTH (f) = configureEvent.xconfigure.width;
8990             }
8991 #endif
8992 
8993 #ifndef USE_X_TOOLKIT
8994 #ifndef USE_GTK
8995           int width =
8996 	    FRAME_PIXEL_TO_TEXT_WIDTH (f, configureEvent.xconfigure.width);
8997           int height =
8998 	    FRAME_PIXEL_TO_TEXT_HEIGHT (f, configureEvent.xconfigure.height);
8999 
9000           /* In the toolkit version, change_frame_size
9001              is called by the code that handles resizing
9002              of the EmacsFrame widget.  */
9003 
9004           /* Even if the number of character rows and columns has
9005              not changed, the font size may have changed, so we need
9006              to check the pixel dimensions as well.  */
9007           if (width != FRAME_TEXT_WIDTH (f)
9008               || height != FRAME_TEXT_HEIGHT (f)
9009               || configureEvent.xconfigure.width != FRAME_PIXEL_WIDTH (f)
9010               || configureEvent.xconfigure.height != FRAME_PIXEL_HEIGHT (f))
9011             {
9012               change_frame_size (f, width, height, false, true, false, true);
9013               x_clear_under_internal_border (f);
9014               SET_FRAME_GARBAGED (f);
9015               cancel_mouse_face (f);
9016             }
9017 #endif /* not USE_GTK */
9018 #endif
9019 
9020 #ifdef USE_GTK
9021           /* GTK creates windows but doesn't map them.
9022              Only get real positions when mapped.  */
9023           if (FRAME_GTK_OUTER_WIDGET (f)
9024               && gtk_widget_get_mapped (FRAME_GTK_OUTER_WIDGET (f)))
9025 #endif
9026 	    {
9027 	      int old_left = f->left_pos;
9028 	      int old_top = f->top_pos;
9029 	      Lisp_Object frame = Qnil;
9030 
9031 	      XSETFRAME (frame, f);
9032 
9033 	      if (!FRAME_PARENT_FRAME (f))
9034 		x_real_positions (f, &f->left_pos, &f->top_pos);
9035 	      else
9036 		{
9037 		  Window root;
9038 		  unsigned int dummy_uint;
9039 
9040 		  block_input ();
9041 		  XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
9042 				&root, &f->left_pos, &f->top_pos,
9043 				&dummy_uint, &dummy_uint, &dummy_uint, &dummy_uint);
9044 		  unblock_input ();
9045 		}
9046 
9047 	      if (!FRAME_TOOLTIP_P (f)
9048 		  && (old_left != f->left_pos || old_top != f->top_pos))
9049 		{
9050 		  inev.ie.kind = MOVE_FRAME_EVENT;
9051 		  XSETFRAME (inev.ie.frame_or_window, f);
9052 		}
9053 	    }
9054 
9055 
9056 #ifdef HAVE_X_I18N
9057           if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
9058             xic_set_statusarea (f);
9059 #endif
9060 
9061         }
9062       goto OTHER;
9063 
9064     case ButtonRelease:
9065     case ButtonPress:
9066       {
9067         /* If we decide we want to generate an event to be seen
9068            by the rest of Emacs, we put it here.  */
9069         bool tab_bar_p = false;
9070         bool tool_bar_p = false;
9071 
9072 	memset (&compose_status, 0, sizeof (compose_status));
9073 	dpyinfo->last_mouse_glyph_frame = NULL;
9074 	x_display_set_last_user_time (dpyinfo, event->xbutton.time);
9075 
9076 	f = mouse_or_wdesc_frame (dpyinfo, event->xmotion.window);
9077 	if (f && event->xbutton.type == ButtonPress
9078 	    && !popup_activated ()
9079 	    && !x_window_to_scroll_bar (event->xbutton.display,
9080 					event->xbutton.window, 2)
9081 	    && !FRAME_NO_ACCEPT_FOCUS (f))
9082 	  {
9083 	    /* When clicking into a child frame or when clicking
9084 	       into a parent frame with the child frame selected and
9085 	       `no-accept-focus' is not set, select the clicked
9086 	       frame.  */
9087 	    struct frame *hf = dpyinfo->highlight_frame;
9088 
9089 	    if (FRAME_PARENT_FRAME (f) || (hf && frame_ancestor_p (f, hf)))
9090 	      {
9091 		block_input ();
9092 		XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
9093 				RevertToParent, CurrentTime);
9094 		if (FRAME_PARENT_FRAME (f))
9095 		  XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
9096 		unblock_input ();
9097 	      }
9098 	  }
9099 
9100 #ifdef USE_GTK
9101         if (f && xg_event_is_for_scrollbar (f, event))
9102           f = 0;
9103 #endif
9104         if (f)
9105           {
9106             /* Is this in the tab-bar?  */
9107             if (WINDOWP (f->tab_bar_window)
9108                 && WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window)))
9109               {
9110                 Lisp_Object window;
9111                 int x = event->xbutton.x;
9112                 int y = event->xbutton.y;
9113 
9114                 window = window_from_coordinates (f, x, y, 0, true, true);
9115                 tab_bar_p = EQ (window, f->tab_bar_window);
9116 
9117                 if (tab_bar_p && event->xbutton.button < 4)
9118 		  handle_tab_bar_click
9119 		    (f, x, y, event->xbutton.type == ButtonPress,
9120 		     x_x_to_emacs_modifiers (dpyinfo, event->xbutton.state));
9121               }
9122 
9123 #if ! defined (USE_GTK)
9124             /* Is this in the tool-bar?  */
9125             if (WINDOWP (f->tool_bar_window)
9126                 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
9127               {
9128                 Lisp_Object window;
9129                 int x = event->xbutton.x;
9130                 int y = event->xbutton.y;
9131 
9132                 window = window_from_coordinates (f, x, y, 0, true, true);
9133                 tool_bar_p = EQ (window, f->tool_bar_window);
9134 
9135                 if (tool_bar_p && event->xbutton.button < 4)
9136 		  handle_tool_bar_click
9137 		    (f, x, y, event->xbutton.type == ButtonPress,
9138 		     x_x_to_emacs_modifiers (dpyinfo, event->xbutton.state));
9139               }
9140 #endif /* !USE_GTK */
9141 
9142             if (!tab_bar_p && !tool_bar_p)
9143 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
9144               if (! popup_activated ())
9145 #endif
9146                 {
9147                   if (ignore_next_mouse_click_timeout)
9148                     {
9149                       if (event->type == ButtonPress
9150                           && event->xbutton.time > ignore_next_mouse_click_timeout)
9151                         {
9152                           ignore_next_mouse_click_timeout = 0;
9153                           x_construct_mouse_click (&inev.ie, &event->xbutton, f);
9154                         }
9155                       if (event->type == ButtonRelease)
9156                         ignore_next_mouse_click_timeout = 0;
9157                     }
9158                   else
9159                     x_construct_mouse_click (&inev.ie, &event->xbutton, f);
9160                 }
9161             if (FRAME_X_EMBEDDED_P (f))
9162               xembed_send_message (f, event->xbutton.time,
9163                                    XEMBED_REQUEST_FOCUS, 0, 0, 0);
9164           }
9165         else
9166           {
9167             struct scroll_bar *bar
9168               = x_window_to_scroll_bar (event->xbutton.display,
9169                                         event->xbutton.window, 2);
9170 
9171 #ifdef USE_TOOLKIT_SCROLL_BARS
9172             /* Make the "Ctrl-Mouse-2 splits window" work for toolkit
9173                scroll bars.  */
9174             if (bar && event->xbutton.state & ControlMask)
9175               {
9176                 x_scroll_bar_handle_click (bar, event, &inev.ie);
9177                 *finish = X_EVENT_DROP;
9178               }
9179 #else /* not USE_TOOLKIT_SCROLL_BARS */
9180             if (bar)
9181               x_scroll_bar_handle_click (bar, event, &inev.ie);
9182 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9183           }
9184 
9185         if (event->type == ButtonPress)
9186           {
9187             dpyinfo->grabbed |= (1 << event->xbutton.button);
9188             dpyinfo->last_mouse_frame = f;
9189             if (f && !tab_bar_p)
9190               f->last_tab_bar_item = -1;
9191 #if ! defined (USE_GTK)
9192             if (f && !tool_bar_p)
9193               f->last_tool_bar_item = -1;
9194 #endif /* not USE_GTK */
9195           }
9196         else
9197           dpyinfo->grabbed &= ~(1 << event->xbutton.button);
9198 
9199 	/* Ignore any mouse motion that happened before this event;
9200 	   any subsequent mouse-movement Emacs events should reflect
9201 	   only motion after the ButtonPress/Release.  */
9202 	if (f != 0)
9203 	  f->mouse_moved = false;
9204 
9205 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
9206         f = x_menubar_window_to_frame (dpyinfo, event);
9207         /* For a down-event in the menu bar,
9208            don't pass it to Xt right now.
9209            Instead, save it away
9210            and we will pass it to Xt from kbd_buffer_get_event.
9211            That way, we can run some Lisp code first.  */
9212         if (! popup_activated ()
9213 #ifdef USE_GTK
9214             /* Gtk+ menus only react to the first three buttons. */
9215             && event->xbutton.button < 3
9216 #endif
9217             && f && event->type == ButtonPress
9218             /* Verify the event is really within the menu bar
9219                and not just sent to it due to grabbing.  */
9220             && event->xbutton.x >= 0
9221             && event->xbutton.x < FRAME_PIXEL_WIDTH (f)
9222             && event->xbutton.y >= 0
9223             && event->xbutton.y < FRAME_MENUBAR_HEIGHT (f)
9224             && event->xbutton.same_screen)
9225           {
9226 	    if (!f->output_data.x->saved_menu_event)
9227 	      f->output_data.x->saved_menu_event = xmalloc (sizeof *event);
9228 	    *f->output_data.x->saved_menu_event = *event;
9229 	    inev.ie.kind = MENU_BAR_ACTIVATE_EVENT;
9230 	    XSETFRAME (inev.ie.frame_or_window, f);
9231 	    *finish = X_EVENT_DROP;
9232           }
9233         else
9234           goto OTHER;
9235 #endif /* USE_X_TOOLKIT || USE_GTK */
9236       }
9237       break;
9238 
9239     case CirculateNotify:
9240       goto OTHER;
9241 
9242     case CirculateRequest:
9243       goto OTHER;
9244 
9245     case VisibilityNotify:
9246       goto OTHER;
9247 
9248     case MappingNotify:
9249       /* Someone has changed the keyboard mapping - update the
9250          local cache.  */
9251       switch (event->xmapping.request)
9252         {
9253         case MappingModifier:
9254           x_find_modifier_meanings (dpyinfo);
9255 	  FALLTHROUGH;
9256         case MappingKeyboard:
9257           XRefreshKeyboardMapping ((XMappingEvent *) &event->xmapping);
9258         }
9259       goto OTHER;
9260 
9261     case DestroyNotify:
9262       xft_settings_event (dpyinfo, event);
9263       break;
9264 
9265     default:
9266     OTHER:
9267 #ifdef USE_X_TOOLKIT
9268       block_input ();
9269     if (*finish != X_EVENT_DROP)
9270       XtDispatchEvent ((XEvent *) event);
9271     unblock_input ();
9272 #endif /* USE_X_TOOLKIT */
9273     break;
9274     }
9275 
9276  done:
9277   if (inev.ie.kind != NO_EVENT)
9278     {
9279       kbd_buffer_store_buffered_event (&inev, hold_quit);
9280       count++;
9281     }
9282 
9283   if (do_help
9284       && !(hold_quit && hold_quit->kind != NO_EVENT))
9285     {
9286       Lisp_Object frame;
9287 
9288       if (f)
9289 	XSETFRAME (frame, f);
9290       else
9291 	frame = Qnil;
9292 
9293       if (do_help > 0)
9294 	{
9295 	  any_help_event_p = true;
9296 	  gen_help_event (help_echo_string, frame, help_echo_window,
9297 			  help_echo_object, help_echo_pos);
9298 	}
9299       else
9300 	{
9301 	  help_echo_string = Qnil;
9302 	  gen_help_event (Qnil, frame, Qnil, Qnil, 0);
9303 	}
9304       count++;
9305     }
9306 
9307   /* Sometimes event processing draws to the frame outside redisplay.
9308      To ensure that these changes become visible, draw them here.  */
9309   flush_dirty_back_buffers ();
9310   SAFE_FREE ();
9311   return count;
9312 }
9313 
9314 #if defined USE_X_TOOLKIT || defined USE_MOTIF || defined USE_GTK
9315 
9316 /* Handles the XEvent EVENT on display DISPLAY.
9317    This is used for event loops outside the normal event handling,
9318    i.e. looping while a popup menu or a dialog is posted.
9319 
9320    Returns the value handle_one_xevent sets in the finish argument.  */
9321 int
x_dispatch_event(XEvent * event,Display * display)9322 x_dispatch_event (XEvent *event, Display *display)
9323 {
9324   struct x_display_info *dpyinfo;
9325   int finish = X_EVENT_NORMAL;
9326 
9327   dpyinfo = x_display_info_for_display (display);
9328 
9329   if (dpyinfo)
9330     handle_one_xevent (dpyinfo, event, &finish, 0);
9331 
9332   return finish;
9333 }
9334 #endif
9335 
9336 /* Read events coming from the X server.
9337    Return as soon as there are no more events to be read.
9338 
9339    Return the number of characters stored into the buffer,
9340    thus pretending to be `read' (except the characters we store
9341    in the keyboard buffer can be multibyte, so are not necessarily
9342    C chars).  */
9343 
9344 static int
XTread_socket(struct terminal * terminal,struct input_event * hold_quit)9345 XTread_socket (struct terminal *terminal, struct input_event *hold_quit)
9346 {
9347   int count = 0;
9348   bool event_found = false;
9349   struct x_display_info *dpyinfo = terminal->display_info.x;
9350 
9351   block_input ();
9352 
9353   /* For debugging, this gives a way to fake an I/O error.  */
9354   if (dpyinfo == XTread_socket_fake_io_error)
9355     {
9356       XTread_socket_fake_io_error = 0;
9357       x_io_error_quitter (dpyinfo->display);
9358     }
9359 
9360 #ifndef USE_GTK
9361   while (XPending (dpyinfo->display))
9362     {
9363       int finish;
9364       XEvent event;
9365 
9366       XNextEvent (dpyinfo->display, &event);
9367 
9368 #ifdef HAVE_X_I18N
9369       /* Filter events for the current X input method.  */
9370       if (x_filter_event (dpyinfo, &event))
9371         continue;
9372 #endif
9373       event_found = true;
9374 
9375       count += handle_one_xevent (dpyinfo, &event, &finish, hold_quit);
9376 
9377       if (finish == X_EVENT_GOTO_OUT)
9378 	break;
9379     }
9380 
9381 #else /* USE_GTK */
9382 
9383   /* For GTK we must use the GTK event loop.  But XEvents gets passed
9384      to our filter function above, and then to the big event switch.
9385      We use a bunch of globals to communicate with our filter function,
9386      that is kind of ugly, but it works.
9387 
9388      There is no way to do one display at the time, GTK just does events
9389      from all displays.  */
9390 
9391   while (gtk_events_pending ())
9392     {
9393       current_count = count;
9394       current_hold_quit = hold_quit;
9395 
9396       gtk_main_iteration ();
9397 
9398       count = current_count;
9399       current_count = -1;
9400       current_hold_quit = 0;
9401 
9402       if (current_finish == X_EVENT_GOTO_OUT)
9403         break;
9404     }
9405 #endif /* USE_GTK */
9406 
9407   /* On some systems, an X bug causes Emacs to get no more events
9408      when the window is destroyed.  Detect that.  (1994.)  */
9409   if (! event_found)
9410     {
9411       /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
9412 	 One XNOOP in 100 loops will make Emacs terminate.
9413 	 B. Bretthauer, 1994 */
9414       x_noop_count++;
9415       if (x_noop_count >= 100)
9416 	{
9417 	  x_noop_count=0;
9418 
9419 	  if (next_noop_dpyinfo == 0)
9420 	    next_noop_dpyinfo = x_display_list;
9421 
9422 	  XNoOp (next_noop_dpyinfo->display);
9423 
9424 	  /* Each time we get here, cycle through the displays now open.  */
9425 	  next_noop_dpyinfo = next_noop_dpyinfo->next;
9426 	}
9427     }
9428 
9429   /* If the focus was just given to an auto-raising frame,
9430      raise it now.  FIXME: handle more than one such frame.  */
9431   if (dpyinfo->x_pending_autoraise_frame)
9432     {
9433       x_raise_frame (dpyinfo->x_pending_autoraise_frame);
9434       dpyinfo->x_pending_autoraise_frame = NULL;
9435     }
9436 
9437   unblock_input ();
9438 
9439   return count;
9440 }
9441 
9442 
9443 
9444 
9445 /***********************************************************************
9446 			     Text Cursor
9447  ***********************************************************************/
9448 
9449 /* Set clipping for output in glyph row ROW.  W is the window in which
9450    we operate.  GC is the graphics context to set clipping in.
9451 
9452    ROW may be a text row or, e.g., a mode line.  Text rows must be
9453    clipped to the interior of the window dedicated to text display,
9454    mode lines must be clipped to the whole window.  */
9455 
9456 static void
x_clip_to_row(struct window * w,struct glyph_row * row,enum glyph_row_area area,GC gc)9457 x_clip_to_row (struct window *w, struct glyph_row *row,
9458 	       enum glyph_row_area area, GC gc)
9459 {
9460   struct frame *f = XFRAME (WINDOW_FRAME (w));
9461   XRectangle clip_rect;
9462   int window_x, window_y, window_width;
9463 
9464   window_box (w, area, &window_x, &window_y, &window_width, 0);
9465 
9466   clip_rect.x = window_x;
9467   clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y));
9468   clip_rect.y = max (clip_rect.y, window_y);
9469   clip_rect.width = window_width;
9470   clip_rect.height = row->visible_height;
9471 
9472   x_set_clip_rectangles (f, gc, &clip_rect, 1);
9473 }
9474 
9475 
9476 /* Draw a hollow box cursor on window W in glyph row ROW.  */
9477 
9478 static void
x_draw_hollow_cursor(struct window * w,struct glyph_row * row)9479 x_draw_hollow_cursor (struct window *w, struct glyph_row *row)
9480 {
9481   struct frame *f = XFRAME (WINDOW_FRAME (w));
9482   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
9483   Display *dpy = FRAME_X_DISPLAY (f);
9484   int x, y, wd, h;
9485   XGCValues xgcv;
9486   struct glyph *cursor_glyph;
9487   GC gc;
9488 
9489   /* Get the glyph the cursor is on.  If we can't tell because
9490      the current matrix is invalid or such, give up.  */
9491   cursor_glyph = get_phys_cursor_glyph (w);
9492   if (cursor_glyph == NULL)
9493     return;
9494 
9495   /* Compute frame-relative coordinates for phys cursor.  */
9496   get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h);
9497   wd = w->phys_cursor_width - 1;
9498 
9499   /* The foreground of cursor_gc is typically the same as the normal
9500      background color, which can cause the cursor box to be invisible.  */
9501   xgcv.foreground = f->output_data.x->cursor_pixel;
9502   if (dpyinfo->scratch_cursor_gc)
9503     XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
9504   else
9505     dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_DRAWABLE (f),
9506 					    GCForeground, &xgcv);
9507   gc = dpyinfo->scratch_cursor_gc;
9508 
9509   /* When on R2L character, show cursor at the right edge of the
9510      glyph, unless the cursor box is as wide as the glyph or wider
9511      (the latter happens when x-stretch-cursor is non-nil).  */
9512   if ((cursor_glyph->resolved_level & 1) != 0
9513       && cursor_glyph->pixel_width > wd)
9514     {
9515       x += cursor_glyph->pixel_width - wd;
9516       if (wd > 0)
9517 	wd -= 1;
9518     }
9519   /* Set clipping, draw the rectangle, and reset clipping again.  */
9520   x_clip_to_row (w, row, TEXT_AREA, gc);
9521   x_draw_rectangle (f, gc, x, y, wd, h - 1);
9522   x_reset_clip_rectangles (f, gc);
9523 }
9524 
9525 
9526 /* Draw a bar cursor on window W in glyph row ROW.
9527 
9528    Implementation note: One would like to draw a bar cursor with an
9529    angle equal to the one given by the font property XA_ITALIC_ANGLE.
9530    Unfortunately, I didn't find a font yet that has this property set.
9531    --gerd.  */
9532 
9533 static void
x_draw_bar_cursor(struct window * w,struct glyph_row * row,int width,enum text_cursor_kinds kind)9534 x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text_cursor_kinds kind)
9535 {
9536   struct frame *f = XFRAME (w->frame);
9537   struct glyph *cursor_glyph;
9538 
9539   /* If cursor is out of bounds, don't draw garbage.  This can happen
9540      in mini-buffer windows when switching between echo area glyphs
9541      and mini-buffer.  */
9542   cursor_glyph = get_phys_cursor_glyph (w);
9543   if (cursor_glyph == NULL)
9544     return;
9545 
9546   /* Experimental avoidance of cursor on xwidget.  */
9547   if (cursor_glyph->type == XWIDGET_GLYPH)
9548     return;
9549 
9550   /* If on an image, draw like a normal cursor.  That's usually better
9551      visible than drawing a bar, esp. if the image is large so that
9552      the bar might not be in the window.  */
9553   if (cursor_glyph->type == IMAGE_GLYPH)
9554     {
9555       struct glyph_row *r;
9556       r = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
9557       draw_phys_cursor_glyph (w, r, DRAW_CURSOR);
9558     }
9559   else
9560     {
9561       Display *dpy = FRAME_X_DISPLAY (f);
9562       Drawable drawable = FRAME_X_DRAWABLE (f);
9563       GC gc = FRAME_DISPLAY_INFO (f)->scratch_cursor_gc;
9564       unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures;
9565       struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
9566       XGCValues xgcv;
9567 
9568       /* If the glyph's background equals the color we normally draw
9569 	 the bars cursor in, the bar cursor in its normal color is
9570 	 invisible.  Use the glyph's foreground color instead in this
9571 	 case, on the assumption that the glyph's colors are chosen so
9572 	 that the glyph is legible.  */
9573       if (face->background == f->output_data.x->cursor_pixel)
9574 	xgcv.background = xgcv.foreground = face->foreground;
9575       else
9576 	xgcv.background = xgcv.foreground = f->output_data.x->cursor_pixel;
9577       xgcv.graphics_exposures = False;
9578 
9579       if (gc)
9580 	XChangeGC (dpy, gc, mask, &xgcv);
9581       else
9582 	{
9583           gc = XCreateGC (dpy, drawable, mask, &xgcv);
9584 	  FRAME_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
9585 	}
9586 
9587       x_clip_to_row (w, row, TEXT_AREA, gc);
9588 
9589       if (kind == BAR_CURSOR)
9590 	{
9591 	  int x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9592 
9593 	  if (width < 0)
9594 	    width = FRAME_CURSOR_WIDTH (f);
9595 	  width = min (cursor_glyph->pixel_width, width);
9596 
9597 	  w->phys_cursor_width = width;
9598 
9599 	  /* If the character under cursor is R2L, draw the bar cursor
9600 	     on the right of its glyph, rather than on the left.  */
9601 	  if ((cursor_glyph->resolved_level & 1) != 0)
9602 	    x += cursor_glyph->pixel_width - width;
9603 
9604 	  x_fill_rectangle (f, gc, x,
9605 			  WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
9606 			  width, row->height);
9607 	}
9608       else /* HBAR_CURSOR */
9609 	{
9610 	  int dummy_x, dummy_y, dummy_h;
9611 	  int x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9612 
9613 	  if (width < 0)
9614 	    width = row->height;
9615 
9616 	  width = min (row->height, width);
9617 
9618 	  get_phys_cursor_geometry (w, row, cursor_glyph, &dummy_x,
9619 				    &dummy_y, &dummy_h);
9620 
9621 	  if ((cursor_glyph->resolved_level & 1) != 0
9622 	      && cursor_glyph->pixel_width > w->phys_cursor_width - 1)
9623 	    x += cursor_glyph->pixel_width - w->phys_cursor_width + 1;
9624 	  x_fill_rectangle (f, gc, x,
9625 			    WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
9626                                                      row->height - width),
9627                             w->phys_cursor_width - 1, width);
9628 	}
9629 
9630       x_reset_clip_rectangles (f, gc);
9631     }
9632 }
9633 
9634 
9635 /* RIF: Define cursor CURSOR on frame F.  */
9636 
9637 static void
x_define_frame_cursor(struct frame * f,Emacs_Cursor cursor)9638 x_define_frame_cursor (struct frame *f, Emacs_Cursor cursor)
9639 {
9640   if (!f->pointer_invisible
9641       && f->output_data.x->current_cursor != cursor)
9642     XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
9643   f->output_data.x->current_cursor = cursor;
9644 }
9645 
9646 
9647 /* RIF: Clear area on frame F.  */
9648 
9649 static void
x_clear_frame_area(struct frame * f,int x,int y,int width,int height)9650 x_clear_frame_area (struct frame *f, int x, int y, int width, int height)
9651 {
9652   x_clear_area (f, x, y, width, height);
9653 }
9654 
9655 
9656 /* RIF: Draw cursor on window W.  */
9657 
9658 static void
x_draw_window_cursor(struct window * w,struct glyph_row * glyph_row,int x,int y,enum text_cursor_kinds cursor_type,int cursor_width,bool on_p,bool active_p)9659 x_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x,
9660 		      int y, enum text_cursor_kinds cursor_type,
9661 		      int cursor_width, bool on_p, bool active_p)
9662 {
9663   struct frame *f = XFRAME (WINDOW_FRAME (w));
9664 
9665   if (on_p)
9666     {
9667       w->phys_cursor_type = cursor_type;
9668       w->phys_cursor_on_p = true;
9669 
9670       if (glyph_row->exact_window_width_line_p
9671 	  && (glyph_row->reversed_p
9672 	      ? (w->phys_cursor.hpos < 0)
9673 	      : (w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])))
9674 	{
9675 	  glyph_row->cursor_in_fringe_p = true;
9676 	  draw_fringe_bitmap (w, glyph_row, glyph_row->reversed_p);
9677 	}
9678       else
9679 	{
9680 	  switch (cursor_type)
9681 	    {
9682 	    case HOLLOW_BOX_CURSOR:
9683 	      x_draw_hollow_cursor (w, glyph_row);
9684 	      break;
9685 
9686 	    case FILLED_BOX_CURSOR:
9687 	      draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
9688 	      break;
9689 
9690 	    case BAR_CURSOR:
9691 	      x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
9692 	      break;
9693 
9694 	    case HBAR_CURSOR:
9695 	      x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
9696 	      break;
9697 
9698 	    case NO_CURSOR:
9699 	      w->phys_cursor_width = 0;
9700 	      break;
9701 
9702 	    default:
9703 	      emacs_abort ();
9704 	    }
9705 	}
9706 
9707 #ifdef HAVE_X_I18N
9708       if (w == XWINDOW (f->selected_window))
9709 	if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
9710 	  xic_set_preeditarea (w, x, y);
9711 #endif
9712     }
9713 
9714   XFlush (FRAME_X_DISPLAY (f));
9715 }
9716 
9717 
9718 /* Icons.  */
9719 
9720 /* Make the x-window of frame F use the gnu icon bitmap.  */
9721 
9722 static bool
x_bitmap_icon(struct frame * f,Lisp_Object file)9723 x_bitmap_icon (struct frame *f, Lisp_Object file)
9724 {
9725   ptrdiff_t bitmap_id;
9726 
9727   if (FRAME_X_WINDOW (f) == 0)
9728     return true;
9729 
9730   /* Free up our existing icon bitmap and mask if any.  */
9731   if (f->output_data.x->icon_bitmap > 0)
9732     image_destroy_bitmap (f, f->output_data.x->icon_bitmap);
9733   f->output_data.x->icon_bitmap = 0;
9734 
9735   if (STRINGP (file))
9736     {
9737 #ifdef USE_GTK
9738       /* Use gtk_window_set_icon_from_file () if available,
9739 	 It's not restricted to bitmaps */
9740       if (xg_set_icon (f, file))
9741 	return false;
9742 #endif /* USE_GTK */
9743       bitmap_id = image_create_bitmap_from_file (f, file);
9744       x_create_bitmap_mask (f, bitmap_id);
9745     }
9746   else
9747     {
9748       /* Create the GNU bitmap and mask if necessary.  */
9749       if (FRAME_DISPLAY_INFO (f)->icon_bitmap_id < 0)
9750 	{
9751 	  ptrdiff_t rc = -1;
9752 
9753 #ifdef USE_GTK
9754 
9755           if (xg_set_icon (f, xg_default_icon_file)
9756               || xg_set_icon_from_xpm_data (f, gnu_xpm_bits))
9757             {
9758               FRAME_DISPLAY_INFO (f)->icon_bitmap_id = -2;
9759               return false;
9760             }
9761 
9762 #elif defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
9763 
9764 	  rc = x_create_bitmap_from_xpm_data (f, gnu_xpm_bits);
9765 	  if (rc != -1)
9766 	    FRAME_DISPLAY_INFO (f)->icon_bitmap_id = rc;
9767 
9768 #endif
9769 
9770 	  /* If all else fails, use the (black and white) xbm image. */
9771 	  if (rc == -1)
9772 	    {
9773               rc = image_create_bitmap_from_data (f,
9774                                                   (char *) gnu_xbm_bits,
9775                                                   gnu_xbm_width,
9776                                                   gnu_xbm_height);
9777 	      if (rc == -1)
9778 		return true;
9779 
9780 	      FRAME_DISPLAY_INFO (f)->icon_bitmap_id = rc;
9781 	      x_create_bitmap_mask (f, FRAME_DISPLAY_INFO (f)->icon_bitmap_id);
9782 	    }
9783 	}
9784 
9785       /* The first time we create the GNU bitmap and mask,
9786 	 this increments the ref-count one extra time.
9787 	 As a result, the GNU bitmap and mask are never freed.
9788 	 That way, we don't have to worry about allocating it again.  */
9789       image_reference_bitmap (f, FRAME_DISPLAY_INFO (f)->icon_bitmap_id);
9790 
9791       bitmap_id = FRAME_DISPLAY_INFO (f)->icon_bitmap_id;
9792     }
9793 
9794   x_wm_set_icon_pixmap (f, bitmap_id);
9795   f->output_data.x->icon_bitmap = bitmap_id;
9796 
9797   return false;
9798 }
9799 
9800 
9801 /* Make the x-window of frame F use a rectangle with text.
9802    Use ICON_NAME as the text.  */
9803 
9804 bool
x_text_icon(struct frame * f,const char * icon_name)9805 x_text_icon (struct frame *f, const char *icon_name)
9806 {
9807   if (FRAME_X_WINDOW (f) == 0)
9808     return true;
9809 
9810   {
9811     XTextProperty text;
9812     text.value = (unsigned char *) icon_name;
9813     text.encoding = XA_STRING;
9814     text.format = 8;
9815     text.nitems = strlen (icon_name);
9816     XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text);
9817   }
9818 
9819   if (f->output_data.x->icon_bitmap > 0)
9820     image_destroy_bitmap (f, f->output_data.x->icon_bitmap);
9821   f->output_data.x->icon_bitmap = 0;
9822   x_wm_set_icon_pixmap (f, 0);
9823 
9824   return false;
9825 }
9826 
9827 #define X_ERROR_MESSAGE_SIZE 200
9828 
9829 /* If non-nil, this should be a string.
9830    It means catch X errors  and store the error message in this string.
9831 
9832    The reason we use a stack is that x_catch_error/x_uncatch_error can
9833    be called from a signal handler.
9834 */
9835 
9836 struct x_error_message_stack {
9837   char string[X_ERROR_MESSAGE_SIZE];
9838   Display *dpy;
9839   x_special_error_handler handler;
9840   void *handler_data;
9841   struct x_error_message_stack *prev;
9842 };
9843 static struct x_error_message_stack *x_error_message;
9844 
9845 /* An X error handler which stores the error message in
9846    *x_error_message.  This is called from x_error_handler if
9847    x_catch_errors is in effect.  */
9848 
9849 static void
x_error_catcher(Display * display,XErrorEvent * event)9850 x_error_catcher (Display *display, XErrorEvent *event)
9851 {
9852   XGetErrorText (display, event->error_code,
9853 		 x_error_message->string,
9854 		 X_ERROR_MESSAGE_SIZE);
9855   if (x_error_message->handler)
9856     x_error_message->handler (display, event, x_error_message->string,
9857 			      x_error_message->handler_data);
9858 }
9859 
9860 /* Begin trapping X errors for display DPY.  Actually we trap X errors
9861    for all displays, but DPY should be the display you are actually
9862    operating on.
9863 
9864    After calling this function, X protocol errors no longer cause
9865    Emacs to exit; instead, they are recorded in the string
9866    stored in *x_error_message.
9867 
9868    Calling x_check_errors signals an Emacs error if an X error has
9869    occurred since the last call to x_catch_errors or x_check_errors.
9870 
9871    Calling x_uncatch_errors resumes the normal error handling.
9872    Calling x_uncatch_errors_after_check is similar, but skips an XSync
9873    to the server, and should be used only immediately after
9874    x_had_errors_p or x_check_errors.  */
9875 
9876 void
x_catch_errors_with_handler(Display * dpy,x_special_error_handler handler,void * handler_data)9877 x_catch_errors_with_handler (Display *dpy, x_special_error_handler handler,
9878 			     void *handler_data)
9879 {
9880   struct x_error_message_stack *data = xmalloc (sizeof *data);
9881 
9882   /* Make sure any errors from previous requests have been dealt with.  */
9883   XSync (dpy, False);
9884 
9885   data->dpy = dpy;
9886   data->string[0] = 0;
9887   data->handler = handler;
9888   data->handler_data = handler_data;
9889   data->prev = x_error_message;
9890   x_error_message = data;
9891 }
9892 
9893 void
x_catch_errors(Display * dpy)9894 x_catch_errors (Display *dpy)
9895 {
9896   x_catch_errors_with_handler (dpy, NULL, NULL);
9897 }
9898 
9899 /* Undo the last x_catch_errors call.
9900    DPY should be the display that was passed to x_catch_errors.
9901 
9902    This version should be used only if the immediately preceding
9903    X-protocol-related thing was x_check_errors or x_had_error_p, both
9904    of which issue XSync calls, so we don't need to re-sync here.  */
9905 
9906 void
x_uncatch_errors_after_check(void)9907 x_uncatch_errors_after_check (void)
9908 {
9909   struct x_error_message_stack *tmp;
9910 
9911   block_input ();
9912   tmp = x_error_message;
9913   x_error_message = x_error_message->prev;
9914   xfree (tmp);
9915   unblock_input ();
9916 }
9917 
9918 /* Undo the last x_catch_errors call.
9919    DPY should be the display that was passed to x_catch_errors.  */
9920 
9921 void
x_uncatch_errors(void)9922 x_uncatch_errors (void)
9923 {
9924   struct x_error_message_stack *tmp;
9925 
9926   block_input ();
9927 
9928   /* The display may have been closed before this function is called.
9929      Check if it is still open before calling XSync.  */
9930   if (x_display_info_for_display (x_error_message->dpy) != 0)
9931     XSync (x_error_message->dpy, False);
9932 
9933   tmp = x_error_message;
9934   x_error_message = x_error_message->prev;
9935   xfree (tmp);
9936   unblock_input ();
9937 }
9938 
9939 /* If any X protocol errors have arrived since the last call to
9940    x_catch_errors or x_check_errors, signal an Emacs error using
9941    sprintf (a buffer, FORMAT, the x error message text) as the text.  */
9942 
9943 void
x_check_errors(Display * dpy,const char * format)9944 x_check_errors (Display *dpy, const char *format)
9945 {
9946   /* Make sure to catch any errors incurred so far.  */
9947   XSync (dpy, False);
9948 
9949   if (x_error_message->string[0])
9950     {
9951       char string[X_ERROR_MESSAGE_SIZE];
9952       memcpy (string, x_error_message->string, X_ERROR_MESSAGE_SIZE);
9953       x_uncatch_errors ();
9954       error (format, string);
9955     }
9956 }
9957 
9958 /* Nonzero if we had any X protocol errors
9959    since we did x_catch_errors on DPY.  */
9960 
9961 bool
x_had_errors_p(Display * dpy)9962 x_had_errors_p (Display *dpy)
9963 {
9964   /* Make sure to catch any errors incurred so far.  */
9965   XSync (dpy, False);
9966 
9967   return x_error_message->string[0] != 0;
9968 }
9969 
9970 /* Forget about any errors we have had, since we did x_catch_errors on DPY.  */
9971 
9972 void
x_clear_errors(Display * dpy)9973 x_clear_errors (Display *dpy)
9974 {
9975   x_error_message->string[0] = 0;
9976 }
9977 
9978 #if false
9979       /* See comment in unwind_to_catch why calling this is a bad
9980        * idea.  --lorentey   */
9981 /* Close off all unclosed x_catch_errors calls.  */
9982 
9983 void
x_fully_uncatch_errors(void)9984 x_fully_uncatch_errors (void)
9985 {
9986   while (x_error_message)
9987     x_uncatch_errors ();
9988 }
9989 #endif
9990 
9991 #if false
9992 static unsigned int x_wire_count;
x_trace_wire(void)9993 x_trace_wire (void)
9994 {
9995   fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
9996 }
9997 #endif
9998 
9999 
10000 /************************************************************************
10001 			  Handling X errors
10002  ************************************************************************/
10003 
10004 /* Error message passed to x_connection_closed.  */
10005 
10006 static char *error_msg;
10007 
10008 /* Handle the loss of connection to display DPY.  ERROR_MESSAGE is
10009    the text of an error message that lead to the connection loss.  */
10010 
10011 static AVOID
x_connection_closed(Display * dpy,const char * error_message,bool ioerror)10012 x_connection_closed (Display *dpy, const char *error_message, bool ioerror)
10013 {
10014   struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
10015   Lisp_Object frame, tail;
10016   ptrdiff_t idx = SPECPDL_INDEX ();
10017 
10018   error_msg = alloca (strlen (error_message) + 1);
10019   strcpy (error_msg, error_message);
10020 
10021   /* Inhibit redisplay while frames are being deleted. */
10022   specbind (Qinhibit_redisplay, Qt);
10023 
10024   if (dpyinfo)
10025     {
10026       /* Protect display from being closed when we delete the last
10027          frame on it. */
10028       dpyinfo->reference_count++;
10029       dpyinfo->terminal->reference_count++;
10030     }
10031   if (ioerror) dpyinfo->display = 0;
10032 
10033   /* First delete frames whose mini-buffers are on frames
10034      that are on the dead display.  */
10035   FOR_EACH_FRAME (tail, frame)
10036     {
10037       Lisp_Object minibuf_frame;
10038       minibuf_frame
10039 	= WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
10040       if (FRAME_X_P (XFRAME (frame))
10041 	  && FRAME_X_P (XFRAME (minibuf_frame))
10042 	  && ! EQ (frame, minibuf_frame)
10043 	  && FRAME_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
10044 	delete_frame (frame, Qnoelisp);
10045     }
10046 
10047   /* Now delete all remaining frames on the dead display.
10048      We are now sure none of these is used as the mini-buffer
10049      for another frame that we need to delete.  */
10050   FOR_EACH_FRAME (tail, frame)
10051     if (FRAME_X_P (XFRAME (frame))
10052 	&& FRAME_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
10053       {
10054 	/* Set this to t so that delete_frame won't get confused
10055 	   trying to find a replacement.  */
10056 	kset_default_minibuffer_frame (FRAME_KBOARD (XFRAME (frame)), Qt);
10057 	delete_frame (frame, Qnoelisp);
10058       }
10059 
10060   /* If DPYINFO is null, this means we didn't open the display in the
10061      first place, so don't try to close it.  */
10062   if (dpyinfo)
10063     {
10064       /* We can not call XtCloseDisplay here because it calls XSync.
10065          XSync inside the error handler apparently hangs Emacs.  On
10066          current Xt versions, this isn't needed either.  */
10067 #ifdef USE_GTK
10068       /* A long-standing GTK bug prevents proper disconnect handling
10069 	 <https://gitlab.gnome.org/GNOME/gtk/issues/221>.  Once,
10070 	 the resulting Glib error message loop filled a user's disk.
10071 	 To avoid this, kill Emacs unconditionally on disconnect.  */
10072       shut_down_emacs (0, Qnil);
10073       fprintf (stderr, "%s\n\
10074 When compiled with GTK, Emacs cannot recover from X disconnects.\n\
10075 This is a GTK bug: https://gitlab.gnome.org/GNOME/gtk/issues/221\n\
10076 For details, see etc/PROBLEMS.\n",
10077 	       error_msg);
10078       emacs_abort ();
10079 #endif /* USE_GTK */
10080 
10081       /* Indicate that this display is dead.  */
10082       dpyinfo->display = 0;
10083 
10084       dpyinfo->reference_count--;
10085       dpyinfo->terminal->reference_count--;
10086       if (dpyinfo->reference_count != 0)
10087         /* We have just closed all frames on this display. */
10088         emacs_abort ();
10089 
10090       {
10091 	Lisp_Object tmp;
10092 	XSETTERMINAL (tmp, dpyinfo->terminal);
10093 	Fdelete_terminal (tmp, Qnoelisp);
10094       }
10095     }
10096 
10097   if (terminal_list == 0)
10098     {
10099       fprintf (stderr, "%s\n", error_msg);
10100       Fkill_emacs (make_fixnum (70));
10101     }
10102 
10103   totally_unblock_input ();
10104 
10105   unbind_to (idx, Qnil);
10106   clear_waiting_for_input ();
10107 
10108   /* Here, we absolutely have to use a non-local exit (e.g. signal, throw,
10109      longjmp), because returning from this function would get us back into
10110      Xlib's code which will directly call `exit'.  */
10111   error ("%s", error_msg);
10112 }
10113 
10114 static void x_error_quitter (Display *, XErrorEvent *);
10115 
10116 /* This is the first-level handler for X protocol errors.
10117    It calls x_error_quitter or x_error_catcher.  */
10118 
10119 static int
x_error_handler(Display * display,XErrorEvent * event)10120 x_error_handler (Display *display, XErrorEvent *event)
10121 {
10122 #if defined USE_GTK && defined HAVE_GTK3
10123   if ((event->error_code == BadMatch || event->error_code == BadWindow)
10124       && event->request_code == X_SetInputFocus)
10125     {
10126       return 0;
10127     }
10128 #endif
10129 
10130   if (x_error_message)
10131     x_error_catcher (display, event);
10132   else
10133     x_error_quitter (display, event);
10134   return 0;
10135 }
10136 
10137 /* This is the usual handler for X protocol errors.
10138    It kills all frames on the display that we got the error for.
10139    If that was the only one, it prints an error message and kills Emacs.  */
10140 
10141 /* .gdbinit puts a breakpoint here, so make sure it is not inlined.  */
10142 
10143 static void NO_INLINE
x_error_quitter(Display * display,XErrorEvent * event)10144 x_error_quitter (Display *display, XErrorEvent *event)
10145 {
10146   char buf[256], buf1[356];
10147 
10148   /* Ignore BadName errors.  They can happen because of fonts
10149      or colors that are not defined.  */
10150 
10151   if (event->error_code == BadName)
10152     return;
10153 
10154   /* Note that there is no real way portable across R3/R4 to get the
10155      original error handler.  */
10156 
10157   XGetErrorText (display, event->error_code, buf, sizeof (buf));
10158   sprintf (buf1, "X protocol error: %s on protocol request %d",
10159 	   buf, event->request_code);
10160   x_connection_closed (display, buf1, false);
10161 }
10162 
10163 
10164 /* This is the handler for X IO errors, always.
10165    It kills all frames on the display that we lost touch with.
10166    If that was the only one, it prints an error message and kills Emacs.  */
10167 
10168 static _Noreturn ATTRIBUTE_COLD int
x_io_error_quitter(Display * display)10169 x_io_error_quitter (Display *display)
10170 {
10171   char buf[256];
10172 
10173   snprintf (buf, sizeof buf, "Connection lost to X server '%s'",
10174 	    DisplayString (display));
10175   x_connection_closed (display, buf, true);
10176 }
10177 
10178 /* Changing the font of the frame.  */
10179 
10180 /* Give frame F the font FONT-OBJECT as its default font.  The return
10181    value is FONT-OBJECT.  FONTSET is an ID of the fontset for the
10182    frame.  If it is negative, generate a new fontset from
10183    FONT-OBJECT.  */
10184 
10185 static Lisp_Object
x_new_font(struct frame * f,Lisp_Object font_object,int fontset)10186 x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
10187 {
10188   struct font *font = XFONT_OBJECT (font_object);
10189   int unit, font_ascent, font_descent;
10190 #ifndef USE_X_TOOLKIT
10191   int old_menu_bar_height = FRAME_MENU_BAR_HEIGHT (f);
10192   int old_tab_bar_height = FRAME_TAB_BAR_HEIGHT (f);
10193   Lisp_Object fullscreen;
10194 #endif
10195 
10196   if (fontset < 0)
10197     fontset = fontset_from_font (font_object);
10198   FRAME_FONTSET (f) = fontset;
10199   if (FRAME_FONT (f) == font)
10200     /* This font is already set in frame F.  There's nothing more to
10201        do.  */
10202     return font_object;
10203 
10204   FRAME_FONT (f) = font;
10205   FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
10206   FRAME_COLUMN_WIDTH (f) = font->average_width;
10207   get_font_ascent_descent (font, &font_ascent, &font_descent);
10208   FRAME_LINE_HEIGHT (f) = font_ascent + font_descent;
10209 
10210 #ifndef USE_X_TOOLKIT
10211   FRAME_MENU_BAR_HEIGHT (f) = FRAME_MENU_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
10212   FRAME_TAB_BAR_HEIGHT (f) = FRAME_TAB_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
10213 #endif
10214 
10215   /* Compute character columns occupied by scrollbar.
10216 
10217      Don't do things differently for non-toolkit scrollbars
10218      (Bug#17163).  */
10219   unit = FRAME_COLUMN_WIDTH (f);
10220   if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
10221     FRAME_CONFIG_SCROLL_BAR_COLS (f)
10222       = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + unit - 1) / unit;
10223   else
10224     FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit;
10225 
10226   if (FRAME_X_WINDOW (f) != 0)
10227     {
10228       /* Don't change the size of a tip frame; there's no point in
10229 	 doing it because it's done in Fx_show_tip, and it leads to
10230 	 problems because the tip frame has no widget.  */
10231       if (!FRAME_TOOLTIP_P (f))
10232 	{
10233 	  adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
10234 			     FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3,
10235 			     false, Qfont);
10236 #ifndef USE_X_TOOLKIT
10237 	  if ((FRAME_MENU_BAR_HEIGHT (f) != old_menu_bar_height
10238 	       || FRAME_TAB_BAR_HEIGHT (f) != old_tab_bar_height)
10239 	      && !f->after_make_frame
10240 	      && (EQ (frame_inhibit_implied_resize, Qt)
10241 		  || (CONSP (frame_inhibit_implied_resize)
10242 		      && NILP (Fmemq (Qfont, frame_inhibit_implied_resize))))
10243 	      && (NILP (fullscreen = get_frame_param (f, Qfullscreen))
10244 		  || EQ (fullscreen, Qfullwidth)))
10245 	    /* If the menu/tab bar height changes, try to keep text height
10246 	       constant.  */
10247 	    adjust_frame_size
10248 	      (f, -1, FRAME_TEXT_HEIGHT (f) + FRAME_MENU_BAR_HEIGHT (f)
10249 	       + FRAME_TAB_BAR_HEIGHT (f)
10250 	       - old_menu_bar_height - old_tab_bar_height, 1, false, Qfont);
10251 #endif /* USE_X_TOOLKIT  */
10252 	}
10253     }
10254 
10255 #ifdef HAVE_X_I18N
10256   if (FRAME_XIC (f)
10257       && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
10258     {
10259       block_input ();
10260       xic_set_xfontset (f, SSDATA (fontset_ascii (fontset)));
10261       unblock_input ();
10262     }
10263 #endif
10264 
10265   return font_object;
10266 }
10267 
10268 
10269 /***********************************************************************
10270 			   X Input Methods
10271  ***********************************************************************/
10272 
10273 #ifdef HAVE_X_I18N
10274 
10275 #ifdef HAVE_X11R6
10276 
10277 /* XIM destroy callback function, which is called whenever the
10278    connection to input method XIM dies.  CLIENT_DATA contains a
10279    pointer to the x_display_info structure corresponding to XIM.  */
10280 
10281 static void
xim_destroy_callback(XIM xim,XPointer client_data,XPointer call_data)10282 xim_destroy_callback (XIM xim, XPointer client_data, XPointer call_data)
10283 {
10284   struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
10285   Lisp_Object frame, tail;
10286 
10287   block_input ();
10288 
10289   /* No need to call XDestroyIC.. */
10290   FOR_EACH_FRAME (tail, frame)
10291     {
10292       struct frame *f = XFRAME (frame);
10293       if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) == dpyinfo)
10294 	{
10295 	  FRAME_XIC (f) = NULL;
10296           xic_free_xfontset (f);
10297 	}
10298     }
10299 
10300   /* No need to call XCloseIM.  */
10301   dpyinfo->xim = NULL;
10302   XFree (dpyinfo->xim_styles);
10303   unblock_input ();
10304 }
10305 
10306 #endif /* HAVE_X11R6 */
10307 
10308 /* Open the connection to the XIM server on display DPYINFO.
10309    RESOURCE_NAME is the resource name Emacs uses.  */
10310 
10311 static void
xim_open_dpy(struct x_display_info * dpyinfo,char * resource_name)10312 xim_open_dpy (struct x_display_info *dpyinfo, char *resource_name)
10313 {
10314   XIM xim;
10315 
10316 #ifdef HAVE_XIM
10317   if (use_xim)
10318     {
10319       if (dpyinfo->xim)
10320 	XCloseIM (dpyinfo->xim);
10321       xim = XOpenIM (dpyinfo->display, dpyinfo->rdb, resource_name,
10322 		     emacs_class);
10323       dpyinfo->xim = xim;
10324 
10325       if (xim)
10326 	{
10327 #ifdef HAVE_X11R6
10328 	  XIMCallback destroy;
10329 #endif
10330 
10331 	  /* Get supported styles and XIM values.  */
10332 	  XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
10333 
10334 #ifdef HAVE_X11R6
10335 	  destroy.callback = xim_destroy_callback;
10336 	  destroy.client_data = (XPointer)dpyinfo;
10337 	  XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
10338 #endif
10339 	}
10340     }
10341 
10342   else
10343 #endif /* HAVE_XIM */
10344     dpyinfo->xim = NULL;
10345 }
10346 
10347 
10348 #ifdef HAVE_X11R6_XIM
10349 
10350 /* XIM instantiate callback function, which is called whenever an XIM
10351    server is available.  DISPLAY is the display of the XIM.
10352    CLIENT_DATA contains a pointer to an xim_inst_t structure created
10353    when the callback was registered.  */
10354 
10355 static void
xim_instantiate_callback(Display * display,XPointer client_data,XPointer call_data)10356 xim_instantiate_callback (Display *display, XPointer client_data, XPointer call_data)
10357 {
10358   struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
10359   struct x_display_info *dpyinfo = xim_inst->dpyinfo;
10360 
10361   /* We don't support multiple XIM connections. */
10362   if (dpyinfo->xim)
10363     return;
10364 
10365   xim_open_dpy (dpyinfo, xim_inst->resource_name);
10366 
10367   /* Create XIC for the existing frames on the same display, as long
10368      as they have no XIC.  */
10369   if (dpyinfo->xim && dpyinfo->reference_count > 0)
10370     {
10371       Lisp_Object tail, frame;
10372 
10373       block_input ();
10374       FOR_EACH_FRAME (tail, frame)
10375 	{
10376 	  struct frame *f = XFRAME (frame);
10377 
10378 	  if (FRAME_X_P (f)
10379               && FRAME_DISPLAY_INFO (f) == xim_inst->dpyinfo)
10380 	    if (FRAME_XIC (f) == NULL)
10381 	      {
10382 		create_frame_xic (f);
10383 		if (FRAME_XIC_STYLE (f) & XIMStatusArea)
10384 		  xic_set_statusarea (f);
10385 		if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
10386 		  {
10387 		    struct window *w = XWINDOW (f->selected_window);
10388 		    xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
10389 		  }
10390 	      }
10391 	}
10392 
10393       unblock_input ();
10394     }
10395 }
10396 
10397 #endif /* HAVE_X11R6_XIM */
10398 
10399 
10400 /* Open a connection to the XIM server on display DPYINFO.
10401    RESOURCE_NAME is the resource name for Emacs.  On X11R5, open the
10402    connection only at the first time.  On X11R6, open the connection
10403    in the XIM instantiate callback function.  */
10404 
10405 static void
xim_initialize(struct x_display_info * dpyinfo,char * resource_name)10406 xim_initialize (struct x_display_info *dpyinfo, char *resource_name)
10407 {
10408   dpyinfo->xim = NULL;
10409 #ifdef HAVE_XIM
10410   if (use_xim)
10411     {
10412 #ifdef HAVE_X11R6_XIM
10413       struct xim_inst_t *xim_inst = xmalloc (sizeof *xim_inst);
10414       Bool ret;
10415 
10416       dpyinfo->xim_callback_data = xim_inst;
10417       xim_inst->dpyinfo = dpyinfo;
10418       xim_inst->resource_name = xstrdup (resource_name);
10419       ret = XRegisterIMInstantiateCallback
10420 	(dpyinfo->display, dpyinfo->rdb, xim_inst->resource_name,
10421 	 emacs_class, xim_instantiate_callback,
10422 	 /* This is XPointer in XFree86 but (XPointer *)
10423 	    on Tru64, at least, hence the configure test.  */
10424 	 (XRegisterIMInstantiateCallback_arg6) xim_inst);
10425       eassert (ret == True);
10426 #else /* not HAVE_X11R6_XIM */
10427       xim_open_dpy (dpyinfo, resource_name);
10428 #endif /* not HAVE_X11R6_XIM */
10429     }
10430 #endif /* HAVE_XIM */
10431 }
10432 
10433 
10434 /* Close the connection to the XIM server on display DPYINFO. */
10435 
10436 static void
xim_close_dpy(struct x_display_info * dpyinfo)10437 xim_close_dpy (struct x_display_info *dpyinfo)
10438 {
10439 #ifdef HAVE_XIM
10440   if (use_xim)
10441     {
10442 #ifdef HAVE_X11R6_XIM
10443       struct xim_inst_t *xim_inst = dpyinfo->xim_callback_data;
10444 
10445       if (dpyinfo->display)
10446 	{
10447 	  Bool ret = XUnregisterIMInstantiateCallback
10448 	    (dpyinfo->display, dpyinfo->rdb, xim_inst->resource_name,
10449 	     emacs_class, xim_instantiate_callback,
10450 	     (XRegisterIMInstantiateCallback_arg6) xim_inst);
10451 	  eassert (ret == True);
10452 	}
10453       xfree (xim_inst->resource_name);
10454       xfree (xim_inst);
10455 #endif /* HAVE_X11R6_XIM */
10456       if (dpyinfo->display)
10457 	XCloseIM (dpyinfo->xim);
10458       dpyinfo->xim = NULL;
10459       XFree (dpyinfo->xim_styles);
10460     }
10461 #endif /* HAVE_XIM */
10462 }
10463 
10464 #endif /* not HAVE_X11R6_XIM */
10465 
10466 
10467 
10468 /* Calculate the absolute position in frame F
10469    from its current recorded position values and gravity.  */
10470 
10471 static void
x_calc_absolute_position(struct frame * f)10472 x_calc_absolute_position (struct frame *f)
10473 {
10474   int flags = f->size_hint_flags;
10475   struct frame *p = FRAME_PARENT_FRAME (f);
10476 
10477   /* We have nothing to do if the current position
10478      is already for the top-left corner.  */
10479   if (! ((flags & XNegative) || (flags & YNegative)))
10480     return;
10481 
10482   /* Treat negative positions as relative to the leftmost bottommost
10483      position that fits on the screen.  */
10484   if ((flags & XNegative) && (f->left_pos <= 0))
10485     {
10486       int width = FRAME_PIXEL_WIDTH (f);
10487 
10488       /* A frame that has been visible at least once should have outer
10489 	 edges.  */
10490       if (f->output_data.x->has_been_visible && !p)
10491 	{
10492 	  Lisp_Object frame;
10493 	  Lisp_Object edges = Qnil;
10494 
10495 	  XSETFRAME (frame, f);
10496 	  edges = Fx_frame_edges (frame, Qouter_edges);
10497 	  if (!NILP (edges))
10498 	    width = (XFIXNUM (Fnth (make_fixnum (2), edges))
10499 		     - XFIXNUM (Fnth (make_fixnum (0), edges)));
10500 	}
10501 
10502       if (p)
10503 	f->left_pos = (FRAME_PIXEL_WIDTH (p) - width - 2 * f->border_width
10504 		       + f->left_pos);
10505       else
10506 	f->left_pos = (x_display_pixel_width (FRAME_DISPLAY_INFO (f))
10507 		       - width + f->left_pos);
10508 
10509     }
10510 
10511   if ((flags & YNegative) && (f->top_pos <= 0))
10512     {
10513       int height = FRAME_PIXEL_HEIGHT (f);
10514 
10515 #if defined USE_X_TOOLKIT && defined USE_MOTIF
10516       /* Something is fishy here.  When using Motif, starting Emacs with
10517 	 `-g -0-0', the frame appears too low by a few pixels.
10518 
10519 	 This seems to be so because initially, while Emacs is starting,
10520 	 the column widget's height and the frame's pixel height are
10521 	 different.  The column widget's height is the right one.  In
10522 	 later invocations, when Emacs is up, the frame's pixel height
10523 	 is right, though.
10524 
10525 	 It's not obvious where the initial small difference comes from.
10526 	 2000-12-01, gerd.  */
10527 
10528       XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
10529 #endif
10530 
10531       if (f->output_data.x->has_been_visible && !p)
10532 	{
10533 	  Lisp_Object frame;
10534 	  Lisp_Object edges = Qnil;
10535 
10536 	  XSETFRAME (frame, f);
10537 	  if (NILP (edges))
10538 	    edges = Fx_frame_edges (frame, Qouter_edges);
10539 	  if (!NILP (edges))
10540 	    height = (XFIXNUM (Fnth (make_fixnum (3), edges))
10541 		      - XFIXNUM (Fnth (make_fixnum (1), edges)));
10542 	}
10543 
10544       if (p)
10545 	f->top_pos = (FRAME_PIXEL_HEIGHT (p) - height - 2 * f->border_width
10546 		       + f->top_pos);
10547       else
10548 	f->top_pos = (x_display_pixel_height (FRAME_DISPLAY_INFO (f))
10549 		      - height + f->top_pos);
10550   }
10551 
10552   /* The left_pos and top_pos
10553      are now relative to the top and left screen edges,
10554      so the flags should correspond.  */
10555   f->size_hint_flags &= ~ (XNegative | YNegative);
10556 }
10557 
10558 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
10559    to really change the position, and 0 when calling from
10560    x_make_frame_visible (in that case, XOFF and YOFF are the current
10561    position values).  It is -1 when calling from gui_set_frame_parameters,
10562    which means, do adjust for borders but don't change the gravity.  */
10563 
10564 static void
x_set_offset(struct frame * f,register int xoff,register int yoff,int change_gravity)10565 x_set_offset (struct frame *f, register int xoff, register int yoff, int change_gravity)
10566 {
10567   int modified_top, modified_left;
10568 #ifdef USE_GTK
10569   int scale = xg_get_scale (f);
10570 #endif
10571 
10572   if (change_gravity > 0)
10573     {
10574       f->top_pos = yoff;
10575       f->left_pos = xoff;
10576       f->size_hint_flags &= ~ (XNegative | YNegative);
10577       if (xoff < 0)
10578 	f->size_hint_flags |= XNegative;
10579       if (yoff < 0)
10580 	f->size_hint_flags |= YNegative;
10581       f->win_gravity = NorthWestGravity;
10582     }
10583 
10584   x_calc_absolute_position (f);
10585 
10586   block_input ();
10587   x_wm_set_size_hint (f, 0, false);
10588 
10589 #ifdef USE_GTK
10590   if (x_gtk_use_window_move)
10591     {
10592       /* When a position change was requested and the outer GTK widget
10593 	 has been realized already, leave it to gtk_window_move to
10594 	 DTRT and return.  Used for Bug#25851 and Bug#25943.  Convert
10595 	 from X pixels to GTK scaled pixels.  */
10596       if (change_gravity != 0 && FRAME_GTK_OUTER_WIDGET (f))
10597 	gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
10598 			 f->left_pos / scale, f->top_pos / scale);
10599       unblock_input ();
10600       return;
10601     }
10602 #endif /* USE_GTK */
10603 
10604   modified_left = f->left_pos;
10605   modified_top = f->top_pos;
10606 
10607   if (change_gravity != 0 && FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A)
10608     {
10609       /* Some WMs (twm, wmaker at least) has an offset that is smaller
10610          than the WM decorations.  So we use the calculated offset instead
10611          of the WM decoration sizes here (x/y_pixels_outer_diff).  */
10612       modified_left += FRAME_X_OUTPUT (f)->move_offset_left;
10613       modified_top += FRAME_X_OUTPUT (f)->move_offset_top;
10614     }
10615 
10616 #ifdef USE_GTK
10617   /* Make sure we adjust for possible scaling.  */
10618   gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
10619 		   modified_left / scale, modified_top / scale);
10620 #else
10621   XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
10622 	       modified_left, modified_top);
10623 #endif
10624 
10625   /* 'x_sync_with_move' is too costly for dragging child frames.  */
10626   if (!FRAME_PARENT_FRAME (f))
10627     {
10628       x_sync_with_move (f, f->left_pos, f->top_pos,
10629 			FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN);
10630 
10631       /* change_gravity is non-zero when this function is called from Lisp to
10632 	 programmatically move a frame.  In that case, we call
10633 	 x_check_expected_move to discover if we have a "Type A" or "Type B"
10634 	 window manager, and, for a "Type A" window manager, adjust the position
10635 	 of the frame.
10636 
10637 	 We call x_check_expected_move if a programmatic move occurred, and
10638 	 either the window manager type (A/B) is unknown or it is Type A but we
10639 	 need to compute the top/left offset adjustment for this frame.  */
10640 
10641       if (change_gravity != 0
10642 	  && (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
10643 	      || (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A
10644 		  && (FRAME_X_OUTPUT (f)->move_offset_left == 0
10645 		      && FRAME_X_OUTPUT (f)->move_offset_top == 0))))
10646 	x_check_expected_move (f, modified_left, modified_top);
10647     }
10648 
10649   unblock_input ();
10650 }
10651 
10652 /* Return true if _NET_SUPPORTING_WM_CHECK window exists and _NET_SUPPORTED
10653    on the root window for frame F contains ATOMNAME.
10654    This is how a WM check shall be done according to the Window Manager
10655    Specification/Extended Window Manager Hints at
10656    https://freedesktop.org/wiki/Specifications/wm-spec/.  */
10657 
10658 bool
x_wm_supports(struct frame * f,Atom want_atom)10659 x_wm_supports (struct frame *f, Atom want_atom)
10660 {
10661   Atom actual_type;
10662   unsigned long actual_size, bytes_remaining;
10663   int i, rc, actual_format;
10664   bool ret;
10665   Window wmcheck_window;
10666   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
10667   Window target_window = dpyinfo->root_window;
10668   int max_len = 65536;
10669   Display *dpy = FRAME_X_DISPLAY (f);
10670   unsigned char *tmp_data = NULL;
10671   Atom target_type = XA_WINDOW;
10672 
10673   block_input ();
10674 
10675   x_catch_errors (dpy);
10676   rc = XGetWindowProperty (dpy, target_window,
10677                            dpyinfo->Xatom_net_supporting_wm_check,
10678                            0, max_len, False, target_type,
10679                            &actual_type, &actual_format, &actual_size,
10680                            &bytes_remaining, &tmp_data);
10681 
10682   if (rc != Success || actual_type != XA_WINDOW || x_had_errors_p (dpy))
10683     {
10684       if (tmp_data) XFree (tmp_data);
10685       x_uncatch_errors ();
10686       unblock_input ();
10687       return false;
10688     }
10689 
10690   wmcheck_window = *(Window *) tmp_data;
10691   XFree (tmp_data);
10692 
10693   /* Check if window exists. */
10694   XSelectInput (dpy, wmcheck_window, StructureNotifyMask);
10695   if (x_had_errors_p (dpy))
10696     {
10697       x_uncatch_errors_after_check ();
10698       unblock_input ();
10699       return false;
10700     }
10701 
10702   if (dpyinfo->net_supported_window != wmcheck_window)
10703     {
10704       /* Window changed, reload atoms */
10705       if (dpyinfo->net_supported_atoms != NULL)
10706         XFree (dpyinfo->net_supported_atoms);
10707       dpyinfo->net_supported_atoms = NULL;
10708       dpyinfo->nr_net_supported_atoms = 0;
10709       dpyinfo->net_supported_window = 0;
10710 
10711       target_type = XA_ATOM;
10712       tmp_data = NULL;
10713       rc = XGetWindowProperty (dpy, target_window,
10714                                dpyinfo->Xatom_net_supported,
10715                                0, max_len, False, target_type,
10716                                &actual_type, &actual_format, &actual_size,
10717                                &bytes_remaining, &tmp_data);
10718 
10719       if (rc != Success || actual_type != XA_ATOM || x_had_errors_p (dpy))
10720         {
10721           if (tmp_data) XFree (tmp_data);
10722           x_uncatch_errors ();
10723           unblock_input ();
10724           return false;
10725         }
10726 
10727       dpyinfo->net_supported_atoms = (Atom *)tmp_data;
10728       dpyinfo->nr_net_supported_atoms = actual_size;
10729       dpyinfo->net_supported_window = wmcheck_window;
10730     }
10731 
10732   ret = false;
10733 
10734   for (i = 0; !ret && i < dpyinfo->nr_net_supported_atoms; ++i)
10735     ret = dpyinfo->net_supported_atoms[i] == want_atom;
10736 
10737   x_uncatch_errors ();
10738   unblock_input ();
10739 
10740   return ret;
10741 }
10742 
10743 static void
set_wm_state(Lisp_Object frame,bool add,Atom atom,Atom value)10744 set_wm_state (Lisp_Object frame, bool add, Atom atom, Atom value)
10745 {
10746   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (XFRAME (frame));
10747 
10748   x_send_client_event (frame, make_fixnum (0), frame,
10749                        dpyinfo->Xatom_net_wm_state,
10750                        make_fixnum (32),
10751                        /* 1 = add, 0 = remove */
10752                        Fcons
10753                        (make_fixnum (add),
10754                         Fcons
10755                         (INT_TO_INTEGER (atom),
10756                          (value != 0
10757 			  ? list1 (INT_TO_INTEGER (value))
10758 			  : Qnil))));
10759 }
10760 
10761 void
x_set_sticky(struct frame * f,Lisp_Object new_value,Lisp_Object old_value)10762 x_set_sticky (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
10763 {
10764   Lisp_Object frame;
10765   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
10766 
10767   XSETFRAME (frame, f);
10768 
10769   set_wm_state (frame, !NILP (new_value),
10770                 dpyinfo->Xatom_net_wm_state_sticky, None);
10771 }
10772 
10773 /**
10774  * x_set_skip_taskbar:
10775  *
10776  * Set frame F's `skip-taskbar' parameter.  If non-nil, this should
10777  * remove F's icon from the taskbar associated with the display of F's
10778  * window-system window and inhibit switching to F's window via
10779  * <Alt>-<TAB>.  If nil, lift these restrictions.
10780  *
10781  * Some window managers may not honor this parameter.
10782  */
10783 void
x_set_skip_taskbar(struct frame * f,Lisp_Object new_value,Lisp_Object old_value)10784 x_set_skip_taskbar (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
10785 {
10786   if (!EQ (new_value, old_value))
10787     {
10788 #ifdef USE_GTK
10789       xg_set_skip_taskbar (f, new_value);
10790 #else
10791       Lisp_Object frame;
10792       struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
10793 
10794       XSETFRAME (frame, f);
10795       set_wm_state (frame, !NILP (new_value),
10796 		    dpyinfo->Xatom_net_wm_state_skip_taskbar, None);
10797 #endif /* USE_GTK */
10798       FRAME_SKIP_TASKBAR (f) = !NILP (new_value);
10799     }
10800 }
10801 
10802 /**
10803  * x_set_z_group:
10804  *
10805  * Set frame F's `z-group' parameter.  If `above', F's window-system
10806  * window is displayed above all windows that do not have the `above'
10807  * property set.  If nil, F's window is shown below all windows that
10808  * have the `above' property set and above all windows that have the
10809  * `below' property set.  If `below', F's window is displayed below all
10810  * windows that do not have the `below' property set.
10811  *
10812  * Some window managers may not honor this parameter.
10813  *
10814  * Internally, this function also handles a value 'above-suspended'.
10815  * That value is used to temporarily remove F from the 'above' group
10816  * to make sure that it does not obscure a menu currently popped up.
10817  */
10818 void
x_set_z_group(struct frame * f,Lisp_Object new_value,Lisp_Object old_value)10819 x_set_z_group (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
10820 {
10821   /* We don't care about old_value.  The window manager might have
10822      reset the value without telling us.  */
10823   Lisp_Object frame;
10824   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
10825 
10826   XSETFRAME (frame, f);
10827 
10828   if (NILP (new_value))
10829     {
10830       set_wm_state (frame, false,
10831 		    dpyinfo->Xatom_net_wm_state_above, None);
10832       set_wm_state (frame, false,
10833 		    dpyinfo->Xatom_net_wm_state_below, None);
10834       FRAME_Z_GROUP (f) = z_group_none;
10835     }
10836   else if (EQ (new_value, Qabove))
10837     {
10838       set_wm_state (frame, true,
10839 		    dpyinfo->Xatom_net_wm_state_above, None);
10840       set_wm_state (frame, false,
10841 		    dpyinfo->Xatom_net_wm_state_below, None);
10842       FRAME_Z_GROUP (f) = z_group_above;
10843     }
10844   else if (EQ (new_value, Qbelow))
10845     {
10846       set_wm_state (frame, false,
10847 		    dpyinfo->Xatom_net_wm_state_above, None);
10848       set_wm_state (frame, true,
10849 		    dpyinfo->Xatom_net_wm_state_below, None);
10850       FRAME_Z_GROUP (f) = z_group_below;
10851     }
10852   else if (EQ (new_value, Qabove_suspended))
10853     {
10854       set_wm_state (frame, false,
10855 		    dpyinfo->Xatom_net_wm_state_above, None);
10856       FRAME_Z_GROUP (f) = z_group_above_suspended;
10857     }
10858   else
10859     error ("Invalid z-group specification");
10860 }
10861 
10862 
10863 /* Return the current _NET_WM_STATE.
10864    SIZE_STATE is set to one of the FULLSCREEN_* values.
10865    Set *STICKY to the sticky state.
10866 
10867    Return true iff we are not hidden.  */
10868 
10869 static bool
x_get_current_wm_state(struct frame * f,Window window,int * size_state,bool * sticky)10870 x_get_current_wm_state (struct frame *f,
10871                         Window window,
10872                         int *size_state,
10873                         bool *sticky)
10874 {
10875   unsigned long actual_size;
10876   int i;
10877   bool is_hidden = false;
10878   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
10879   long max_len = 65536;
10880   Atom target_type = XA_ATOM;
10881   /* If XCB is available, we can avoid three XSync calls.  */
10882 #ifdef USE_XCB
10883   xcb_get_property_cookie_t prop_cookie;
10884   xcb_get_property_reply_t *prop;
10885   xcb_atom_t *reply_data UNINIT;
10886 #else
10887   Display *dpy = FRAME_X_DISPLAY (f);
10888   unsigned long bytes_remaining;
10889   int rc, actual_format;
10890   Atom actual_type;
10891   unsigned char *tmp_data = NULL;
10892   Atom *reply_data UNINIT;
10893 #endif
10894 
10895   *sticky = false;
10896   *size_state = FULLSCREEN_NONE;
10897 
10898   block_input ();
10899 
10900 #ifdef USE_XCB
10901   prop_cookie = xcb_get_property (dpyinfo->xcb_connection, 0, window,
10902                                   dpyinfo->Xatom_net_wm_state,
10903                                   target_type, 0, max_len);
10904   prop = xcb_get_property_reply (dpyinfo->xcb_connection, prop_cookie, NULL);
10905   if (prop && prop->type == target_type)
10906     {
10907       int actual_bytes = xcb_get_property_value_length (prop);
10908       eassume (0 <= actual_bytes);
10909       actual_size = actual_bytes / sizeof *reply_data;
10910       reply_data = xcb_get_property_value (prop);
10911     }
10912   else
10913     {
10914       actual_size = 0;
10915       is_hidden = FRAME_ICONIFIED_P (f);
10916     }
10917 #else
10918   x_catch_errors (dpy);
10919   rc = XGetWindowProperty (dpy, window, dpyinfo->Xatom_net_wm_state,
10920                            0, max_len, False, target_type,
10921                            &actual_type, &actual_format, &actual_size,
10922                            &bytes_remaining, &tmp_data);
10923 
10924   if (rc == Success && actual_type == target_type && ! x_had_errors_p (dpy))
10925     reply_data = (Atom *) tmp_data;
10926   else
10927     {
10928       actual_size = 0;
10929       is_hidden = FRAME_ICONIFIED_P (f);
10930     }
10931 
10932   x_uncatch_errors ();
10933 #endif
10934 
10935   for (i = 0; i < actual_size; ++i)
10936     {
10937       Atom a = reply_data[i];
10938       if (a == dpyinfo->Xatom_net_wm_state_hidden)
10939 	is_hidden = true;
10940       else if (a == dpyinfo->Xatom_net_wm_state_maximized_horz)
10941         {
10942           if (*size_state == FULLSCREEN_HEIGHT)
10943             *size_state = FULLSCREEN_MAXIMIZED;
10944           else
10945             *size_state = FULLSCREEN_WIDTH;
10946         }
10947       else if (a == dpyinfo->Xatom_net_wm_state_maximized_vert)
10948         {
10949           if (*size_state == FULLSCREEN_WIDTH)
10950             *size_state = FULLSCREEN_MAXIMIZED;
10951           else
10952             *size_state = FULLSCREEN_HEIGHT;
10953         }
10954       else if (a == dpyinfo->Xatom_net_wm_state_fullscreen)
10955         *size_state = FULLSCREEN_BOTH;
10956       else if (a == dpyinfo->Xatom_net_wm_state_sticky)
10957         *sticky = true;
10958     }
10959 
10960 #ifdef USE_XCB
10961   free (prop);
10962 #else
10963   if (tmp_data) XFree (tmp_data);
10964 #endif
10965 
10966   unblock_input ();
10967   return ! is_hidden;
10968 }
10969 
10970 /* Do fullscreen as specified in extended window manager hints */
10971 
10972 static bool
do_ewmh_fullscreen(struct frame * f)10973 do_ewmh_fullscreen (struct frame *f)
10974 {
10975   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
10976   bool have_net_atom = x_wm_supports (f, dpyinfo->Xatom_net_wm_state);
10977   int cur;
10978   bool dummy;
10979 
10980   x_get_current_wm_state (f, FRAME_OUTER_WINDOW (f), &cur, &dummy);
10981 
10982   /* Some window managers don't say they support _NET_WM_STATE, but they do say
10983      they support _NET_WM_STATE_FULLSCREEN.  Try that also.  */
10984   if (!have_net_atom)
10985     have_net_atom = x_wm_supports (f, dpyinfo->Xatom_net_wm_state_fullscreen);
10986 
10987   if (have_net_atom && cur != f->want_fullscreen)
10988     {
10989       Lisp_Object frame;
10990 
10991       XSETFRAME (frame, f);
10992 
10993       /* Keep number of calls to set_wm_state as low as possible.
10994          Some window managers, or possible Gtk+, hangs when too many
10995          are sent at once.  */
10996       switch (f->want_fullscreen)
10997         {
10998         case FULLSCREEN_BOTH:
10999           if (cur != FULLSCREEN_BOTH)
11000             set_wm_state (frame, true, dpyinfo->Xatom_net_wm_state_fullscreen,
11001                           None);
11002           break;
11003         case FULLSCREEN_WIDTH:
11004 	  if (x_frame_normalize_before_maximize && cur == FULLSCREEN_MAXIMIZED)
11005 	    {
11006 	      set_wm_state (frame, false,
11007 			    dpyinfo->Xatom_net_wm_state_maximized_horz,
11008 			    dpyinfo->Xatom_net_wm_state_maximized_vert);
11009 	      set_wm_state (frame, true,
11010 			    dpyinfo->Xatom_net_wm_state_maximized_horz, None);
11011 	    }
11012 	  else
11013 	    {
11014 	      if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_HEIGHT
11015 		  || cur == FULLSCREEN_MAXIMIZED)
11016 		set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
11017 			      dpyinfo->Xatom_net_wm_state_maximized_vert);
11018 	      if (cur != FULLSCREEN_MAXIMIZED || x_frame_normalize_before_maximize)
11019 		set_wm_state (frame, true,
11020 			      dpyinfo->Xatom_net_wm_state_maximized_horz, None);
11021 	    }
11022           break;
11023         case FULLSCREEN_HEIGHT:
11024 	  if (x_frame_normalize_before_maximize && cur == FULLSCREEN_MAXIMIZED)
11025 	    {
11026 	      set_wm_state (frame, false,
11027 			    dpyinfo->Xatom_net_wm_state_maximized_horz,
11028 			    dpyinfo->Xatom_net_wm_state_maximized_vert);
11029 	      set_wm_state (frame, true,
11030 			    dpyinfo->Xatom_net_wm_state_maximized_vert, None);
11031 	    }
11032 	  else
11033 	    {
11034 	      if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_WIDTH
11035 		  || cur == FULLSCREEN_MAXIMIZED)
11036 		set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
11037 			      dpyinfo->Xatom_net_wm_state_maximized_horz);
11038 	      if (cur != FULLSCREEN_MAXIMIZED || x_frame_normalize_before_maximize)
11039 		set_wm_state (frame, true,
11040 			      dpyinfo->Xatom_net_wm_state_maximized_vert, None);
11041 	    }
11042           break;
11043         case FULLSCREEN_MAXIMIZED:
11044 	  if (x_frame_normalize_before_maximize && cur == FULLSCREEN_BOTH)
11045 	    {
11046 	      set_wm_state (frame, false,
11047 			    dpyinfo->Xatom_net_wm_state_fullscreen, None);
11048 	      set_wm_state (frame, true,
11049 			    dpyinfo->Xatom_net_wm_state_maximized_horz,
11050 			    dpyinfo->Xatom_net_wm_state_maximized_vert);
11051 	    }
11052 	  else if (x_frame_normalize_before_maximize && cur == FULLSCREEN_WIDTH)
11053 	    {
11054 	      set_wm_state (frame, false,
11055 			    dpyinfo->Xatom_net_wm_state_maximized_horz, None);
11056 	      set_wm_state (frame, true,
11057 			    dpyinfo->Xatom_net_wm_state_maximized_horz,
11058 			    dpyinfo->Xatom_net_wm_state_maximized_vert);
11059 	    }
11060 	  else if (x_frame_normalize_before_maximize && cur == FULLSCREEN_HEIGHT)
11061 	    {
11062 	      set_wm_state (frame, false,
11063 			    dpyinfo->Xatom_net_wm_state_maximized_vert, None);
11064 	      set_wm_state (frame, true,
11065 			    dpyinfo->Xatom_net_wm_state_maximized_horz,
11066 			    dpyinfo->Xatom_net_wm_state_maximized_vert);
11067 	    }
11068 	  else
11069 	    {
11070 	      if (cur == FULLSCREEN_BOTH)
11071 		set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
11072 			      None);
11073 	      else if (cur == FULLSCREEN_HEIGHT)
11074 		set_wm_state (frame, true,
11075 			      dpyinfo->Xatom_net_wm_state_maximized_horz, None);
11076 	      else if (cur == FULLSCREEN_WIDTH)
11077 		set_wm_state (frame, true, None,
11078 			      dpyinfo->Xatom_net_wm_state_maximized_vert);
11079 	      else
11080 		set_wm_state (frame, true,
11081 			      dpyinfo->Xatom_net_wm_state_maximized_horz,
11082 			      dpyinfo->Xatom_net_wm_state_maximized_vert);
11083 	    }
11084           break;
11085         case FULLSCREEN_NONE:
11086           if (cur == FULLSCREEN_BOTH)
11087             set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
11088 			  None);
11089           else
11090             set_wm_state (frame, false,
11091 			  dpyinfo->Xatom_net_wm_state_maximized_horz,
11092                           dpyinfo->Xatom_net_wm_state_maximized_vert);
11093         }
11094 
11095       f->want_fullscreen = FULLSCREEN_NONE;
11096 
11097     }
11098 
11099   return have_net_atom;
11100 }
11101 
11102 static void
XTfullscreen_hook(struct frame * f)11103 XTfullscreen_hook (struct frame *f)
11104 {
11105   if (FRAME_VISIBLE_P (f))
11106     {
11107       block_input ();
11108       x_check_fullscreen (f);
11109       x_sync (f);
11110       unblock_input ();
11111     }
11112 }
11113 
11114 
11115 static bool
x_handle_net_wm_state(struct frame * f,const XPropertyEvent * event)11116 x_handle_net_wm_state (struct frame *f, const XPropertyEvent *event)
11117 {
11118   int value = FULLSCREEN_NONE;
11119   Lisp_Object lval;
11120   bool sticky = false;
11121   bool not_hidden = x_get_current_wm_state (f, event->window, &value, &sticky);
11122 
11123   lval = Qnil;
11124   switch (value)
11125     {
11126     case FULLSCREEN_WIDTH:
11127       lval = Qfullwidth;
11128       break;
11129     case FULLSCREEN_HEIGHT:
11130       lval = Qfullheight;
11131       break;
11132     case FULLSCREEN_BOTH:
11133       lval = Qfullboth;
11134       break;
11135     case FULLSCREEN_MAXIMIZED:
11136       lval = Qmaximized;
11137       break;
11138     }
11139 
11140   frame_size_history_add
11141     (f, Qx_handle_net_wm_state, 0, 0,
11142      list2 (get_frame_param (f, Qfullscreen), lval));
11143 
11144   store_frame_param (f, Qfullscreen, lval);
11145   store_frame_param (f, Qsticky, sticky ? Qt : Qnil);
11146 
11147   return not_hidden;
11148 }
11149 
11150 /* Check if we need to resize the frame due to a fullscreen request.
11151    If so needed, resize the frame. */
11152 static void
x_check_fullscreen(struct frame * f)11153 x_check_fullscreen (struct frame *f)
11154 {
11155   Lisp_Object lval = Qnil;
11156 
11157   if (do_ewmh_fullscreen (f))
11158     return;
11159 
11160   if (f->output_data.x->parent_desc != FRAME_DISPLAY_INFO (f)->root_window)
11161     return; /* Only fullscreen without WM or with EWM hints (above). */
11162 
11163   /* Setting fullscreen to nil doesn't do anything.  We could save the
11164      last non-fullscreen size and restore it, but it seems like a
11165      lot of work for this unusual case (no window manager running).  */
11166 
11167   if (f->want_fullscreen != FULLSCREEN_NONE)
11168     {
11169       int width = FRAME_PIXEL_WIDTH (f), height = FRAME_PIXEL_HEIGHT (f);
11170       struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
11171 
11172       switch (f->want_fullscreen)
11173         {
11174           /* No difference between these two when there is no WM */
11175         case FULLSCREEN_MAXIMIZED:
11176           lval = Qmaximized;
11177           width = x_display_pixel_width (dpyinfo);
11178           height = x_display_pixel_height (dpyinfo);
11179           break;
11180         case FULLSCREEN_BOTH:
11181           lval = Qfullboth;
11182           width = x_display_pixel_width (dpyinfo);
11183           height = x_display_pixel_height (dpyinfo);
11184           break;
11185         case FULLSCREEN_WIDTH:
11186           lval = Qfullwidth;
11187           width = x_display_pixel_width (dpyinfo);
11188 	  height = height + FRAME_MENUBAR_HEIGHT (f);
11189 	  break;
11190         case FULLSCREEN_HEIGHT:
11191           lval = Qfullheight;
11192           height = x_display_pixel_height (dpyinfo);
11193 	  break;
11194 	default:
11195 	  emacs_abort ();
11196         }
11197 
11198       frame_size_history_add
11199 	(f, Qx_check_fullscreen, width, height, Qnil);
11200 
11201       x_wm_set_size_hint (f, 0, false);
11202 
11203       XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11204 		     width, height);
11205 
11206       if (FRAME_VISIBLE_P (f))
11207 	x_wait_for_event (f, ConfigureNotify);
11208       else
11209 	{
11210 	  change_frame_size (f, width, height - FRAME_MENUBAR_HEIGHT (f),
11211 			     false, true, false, true);
11212 	  x_sync (f);
11213 	}
11214     }
11215 
11216   /* `x_net_wm_state' might have reset the fullscreen frame parameter,
11217      restore it. */
11218   store_frame_param (f, Qfullscreen, lval);
11219 }
11220 
11221 /* This function is called by x_set_offset to determine whether the window
11222    manager interfered with the positioning of the frame.  Type A window
11223    managers position the surrounding window manager decorations a small
11224    amount above and left of the user-supplied position.  Type B window
11225    managers position the surrounding window manager decorations at the
11226    user-specified position.  If we detect a Type A window manager, we
11227    compensate by moving the window right and down by the proper amount.  */
11228 
11229 static void
x_check_expected_move(struct frame * f,int expected_left,int expected_top)11230 x_check_expected_move (struct frame *f, int expected_left, int expected_top)
11231 {
11232   int current_left = 0, current_top = 0;
11233 
11234   /* x_real_positions returns the left and top offsets of the outermost
11235      window manager window around the frame.  */
11236 
11237   x_real_positions (f, &current_left, &current_top);
11238 
11239   if (current_left != expected_left || current_top != expected_top)
11240     {
11241       /* It's a "Type A" window manager. */
11242 
11243       int adjusted_left;
11244       int adjusted_top;
11245 
11246         FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_A;
11247       FRAME_X_OUTPUT (f)->move_offset_left = expected_left - current_left;
11248       FRAME_X_OUTPUT (f)->move_offset_top = expected_top - current_top;
11249 
11250       /* Now fix the mispositioned frame's location. */
11251 
11252       adjusted_left = expected_left + FRAME_X_OUTPUT (f)->move_offset_left;
11253       adjusted_top = expected_top + FRAME_X_OUTPUT (f)->move_offset_top;
11254 
11255       XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11256                    adjusted_left, adjusted_top);
11257 
11258       x_sync_with_move (f, expected_left, expected_top, false);
11259     }
11260   else
11261     /* It's a "Type B" window manager.  We don't have to adjust the
11262        frame's position. */
11263 
11264       FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_B;
11265 }
11266 
11267 
11268 /* Wait for XGetGeometry to return up-to-date position information for a
11269    recently-moved frame.  Call this immediately after calling XMoveWindow.
11270    If FUZZY is non-zero, then LEFT and TOP are just estimates of where the
11271    frame has been moved to, so we use a fuzzy position comparison instead
11272    of an exact comparison.  */
11273 
11274 static void
x_sync_with_move(struct frame * f,int left,int top,bool fuzzy)11275 x_sync_with_move (struct frame *f, int left, int top, bool fuzzy)
11276 {
11277   int count = 0;
11278 
11279   while (count++ < 50)
11280     {
11281       int current_left = 0, current_top = 0;
11282 
11283       /* In theory, this call to XSync only needs to happen once, but in
11284          practice, it doesn't seem to work, hence the need for the surrounding
11285          loop.  */
11286 
11287       XSync (FRAME_X_DISPLAY (f), False);
11288       x_real_positions (f, &current_left, &current_top);
11289 
11290       if (fuzzy)
11291         {
11292           /* The left fuzz-factor is 10 pixels.  The top fuzz-factor is 40
11293              pixels.  */
11294 
11295           if (eabs (current_left - left) <= 10
11296 	      && eabs (current_top - top) <= 40)
11297             return;
11298 	}
11299       else if (current_left == left && current_top == top)
11300         return;
11301     }
11302 
11303   /* As a last resort, just wait 0.5 seconds and hope that XGetGeometry
11304      will then return up-to-date position info. */
11305 
11306   wait_reading_process_output (0, 500000000, 0, false, Qnil, NULL, 0);
11307 }
11308 
11309 
11310 /* Wait for an event on frame F matching EVENTTYPE.  */
11311 void
x_wait_for_event(struct frame * f,int eventtype)11312 x_wait_for_event (struct frame *f, int eventtype)
11313 {
11314   if (!FLOATP (Vx_wait_for_event_timeout))
11315     return;
11316 
11317   int level = interrupt_input_blocked;
11318   fd_set fds;
11319   struct timespec tmo, tmo_at, time_now;
11320   int fd = ConnectionNumber (FRAME_X_DISPLAY (f));
11321 
11322   f->wait_event_type = eventtype;
11323 
11324   /* Default timeout is 0.1 second.  Hopefully not noticeable.  */
11325   double timeout = XFLOAT_DATA (Vx_wait_for_event_timeout);
11326   time_t timeout_seconds = (time_t) timeout;
11327   tmo = make_timespec
11328     (timeout_seconds, (long int) ((timeout - timeout_seconds)
11329                                   * 1000 * 1000 * 1000));
11330   tmo_at = timespec_add (current_timespec (), tmo);
11331 
11332   while (f->wait_event_type)
11333     {
11334       pending_signals = true;
11335       totally_unblock_input ();
11336       /* XTread_socket is called after unblock.  */
11337       block_input ();
11338       interrupt_input_blocked = level;
11339 
11340       FD_ZERO (&fds);
11341       FD_SET (fd, &fds);
11342 
11343       time_now = current_timespec ();
11344       if (timespec_cmp (tmo_at, time_now) < 0)
11345 	break;
11346 
11347       tmo = timespec_sub (tmo_at, time_now);
11348       if (pselect (fd + 1, &fds, NULL, NULL, &tmo, NULL) == 0)
11349         break; /* Timeout */
11350     }
11351 
11352   f->wait_event_type = 0;
11353 }
11354 
11355 
11356 /* Change the size of frame F's X window to WIDTH/HEIGHT in the case F
11357    doesn't have a widget.  If CHANGE_GRAVITY, change to
11358    top-left-corner window gravity for this size change and subsequent
11359    size changes.  Otherwise leave the window gravity unchanged.  */
11360 
11361 static void
x_set_window_size_1(struct frame * f,bool change_gravity,int width,int height)11362 x_set_window_size_1 (struct frame *f, bool change_gravity,
11363 		     int width, int height)
11364 {
11365   int pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width);
11366   int pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height);
11367   int old_width = FRAME_PIXEL_WIDTH (f);
11368   int old_height = FRAME_PIXEL_HEIGHT (f);
11369   Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
11370 
11371   if (change_gravity)
11372     f->win_gravity = NorthWestGravity;
11373   x_wm_set_size_hint (f, 0, false);
11374 
11375   /* When the frame is fullheight and we only want to change the width
11376      or it is fullwidth and we only want to change the height we should
11377      be able to preserve the fullscreen property.  However, due to the
11378      fact that we have to send a resize request anyway, the window
11379      manager will abolish it.  At least the respective size should
11380      remain unchanged but giving the frame back its normal size will
11381      be broken ... */
11382   if (EQ (fullscreen, Qfullwidth) && width == FRAME_TEXT_WIDTH (f))
11383     {
11384       frame_size_history_add
11385 	(f, Qx_set_window_size_1, width, height,
11386 	 list2i (old_height, pixelheight + FRAME_MENUBAR_HEIGHT (f)));
11387 
11388       XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11389 		     old_width, pixelheight + FRAME_MENUBAR_HEIGHT (f));
11390     }
11391   else if (EQ (fullscreen, Qfullheight) && height == FRAME_TEXT_HEIGHT (f))
11392     {
11393       frame_size_history_add
11394 	(f, Qx_set_window_size_2, width, height,
11395 	 list2i (old_width, pixelwidth));
11396 
11397       XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11398 		     pixelwidth, old_height);
11399     }
11400 
11401   else
11402     {
11403       frame_size_history_add
11404 	(f, Qx_set_window_size_3, width, height,
11405 	 list3i (pixelwidth + FRAME_TOOLBAR_WIDTH (f),
11406 		 (pixelheight + FRAME_TOOLBAR_HEIGHT (f)
11407 		  + FRAME_MENUBAR_HEIGHT (f)),
11408 		 FRAME_MENUBAR_HEIGHT (f)));
11409 
11410       XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11411 		     pixelwidth, pixelheight + FRAME_MENUBAR_HEIGHT (f));
11412       fullscreen = Qnil;
11413     }
11414 
11415 
11416 
11417   /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
11418      receive in the ConfigureNotify event; if we get what we asked
11419      for, then the event won't cause the screen to become garbaged, so
11420      we have to make sure to do it here.  */
11421   SET_FRAME_GARBAGED (f);
11422 
11423   /* Now, strictly speaking, we can't be sure that this is accurate,
11424      but the window manager will get around to dealing with the size
11425      change request eventually, and we'll hear how it went when the
11426      ConfigureNotify event gets here.
11427 
11428      We could just not bother storing any of this information here,
11429      and let the ConfigureNotify event set everything up, but that
11430      might be kind of confusing to the Lisp code, since size changes
11431      wouldn't be reported in the frame parameters until some random
11432      point in the future when the ConfigureNotify event arrives.
11433 
11434      Pass true for DELAY since we can't run Lisp code inside of
11435      a BLOCK_INPUT.  */
11436 
11437   /* But the ConfigureNotify may in fact never arrive, and then this is
11438      not right if the frame is visible.  Instead wait (with timeout)
11439      for the ConfigureNotify.  */
11440   if (FRAME_VISIBLE_P (f))
11441     {
11442       x_wait_for_event (f, ConfigureNotify);
11443 
11444       if (!NILP (fullscreen))
11445 	/* Try to restore fullscreen state.  */
11446 	{
11447 	  store_frame_param (f, Qfullscreen, fullscreen);
11448 	  gui_set_fullscreen (f, fullscreen, fullscreen);
11449 	}
11450     }
11451   else
11452     {
11453       change_frame_size (f, width, height, false, true, false, true);
11454       x_sync (f);
11455     }
11456 }
11457 
11458 
11459 /* Call this to change the size of frame F's x-window.
11460    If CHANGE_GRAVITY, change to top-left-corner window gravity
11461    for this size change and subsequent size changes.
11462    Otherwise we leave the window gravity unchanged.  */
11463 
11464 void
x_set_window_size(struct frame * f,bool change_gravity,int width,int height,bool pixelwise)11465 x_set_window_size (struct frame *f, bool change_gravity,
11466 		   int width, int height, bool pixelwise)
11467 {
11468   block_input ();
11469 
11470   /* The following breaks our calculations.  If it's really needed,
11471      think of something else.  */
11472 #if false
11473   if (!FRAME_TOOLTIP_P (f))
11474     {
11475       int text_width, text_height;
11476 
11477       /* When the frame is maximized/fullscreen or running under for
11478          example Xmonad, x_set_window_size_1 will be a no-op.
11479          In that case, the right thing to do is extend rows/width to
11480          the current frame size.  We do that first if x_set_window_size_1
11481          turns out to not be a no-op (there is no way to know).
11482          The size will be adjusted again if the frame gets a
11483          ConfigureNotify event as a result of x_set_window_size.  */
11484       int pixelh = FRAME_PIXEL_HEIGHT (f);
11485 #ifdef USE_X_TOOLKIT
11486       /* The menu bar is not part of text lines.  The tool bar
11487          is however.  */
11488       pixelh -= FRAME_MENUBAR_HEIGHT (f);
11489 #endif
11490       text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, FRAME_PIXEL_WIDTH (f));
11491       text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelh);
11492 
11493       change_frame_size (f, text_width, text_height, false, true, false, true);
11494     }
11495 #endif
11496 
11497   /* Pixelize width and height, if necessary.  */
11498   if (! pixelwise)
11499     {
11500       width = width * FRAME_COLUMN_WIDTH (f);
11501       height = height * FRAME_LINE_HEIGHT (f);
11502     }
11503 
11504 #ifdef USE_GTK
11505   if (FRAME_GTK_WIDGET (f))
11506     xg_frame_set_char_size (f, width, height);
11507   else
11508     x_set_window_size_1 (f, change_gravity, width, height);
11509 #else /* not USE_GTK */
11510   x_set_window_size_1 (f, change_gravity, width, height);
11511   x_clear_under_internal_border (f);
11512 #endif /* not USE_GTK */
11513 
11514   /* If cursor was outside the new size, mark it as off.  */
11515   mark_window_cursors_off (XWINDOW (f->root_window));
11516 
11517   /* Clear out any recollection of where the mouse highlighting was,
11518      since it might be in a place that's outside the new frame size.
11519      Actually checking whether it is outside is a pain in the neck,
11520      so don't try--just let the highlighting be done afresh with new size.  */
11521   cancel_mouse_face (f);
11522 
11523   unblock_input ();
11524 
11525   do_pending_window_change (false);
11526 }
11527 
11528 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F.  */
11529 
11530 void
frame_set_mouse_pixel_position(struct frame * f,int pix_x,int pix_y)11531 frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
11532 {
11533   block_input ();
11534 
11535   XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
11536 		0, 0, 0, 0, pix_x, pix_y);
11537   unblock_input ();
11538 }
11539 
11540 /* Raise frame F.  */
11541 
11542 static void
x_raise_frame(struct frame * f)11543 x_raise_frame (struct frame *f)
11544 {
11545   block_input ();
11546   if (FRAME_VISIBLE_P (f))
11547     XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
11548   XFlush (FRAME_X_DISPLAY (f));
11549   unblock_input ();
11550 }
11551 
11552 /* Lower frame F.  */
11553 
11554 static void
x_lower_frame(struct frame * f)11555 x_lower_frame (struct frame *f)
11556 {
11557   if (FRAME_VISIBLE_P (f))
11558     {
11559       block_input ();
11560       XLowerWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
11561       XFlush (FRAME_X_DISPLAY (f));
11562       unblock_input ();
11563     }
11564 }
11565 
11566 static void
XTframe_raise_lower(struct frame * f,bool raise_flag)11567 XTframe_raise_lower (struct frame *f, bool raise_flag)
11568 {
11569   if (raise_flag)
11570     x_raise_frame (f);
11571   else
11572     x_lower_frame (f);
11573 }
11574 
11575 /* Request focus with XEmbed */
11576 
11577 static void
xembed_request_focus(struct frame * f)11578 xembed_request_focus (struct frame *f)
11579 {
11580   /* See XEmbed Protocol Specification at
11581      https://freedesktop.org/wiki/Specifications/xembed-spec/  */
11582   if (FRAME_VISIBLE_P (f))
11583     xembed_send_message (f, CurrentTime,
11584 			 XEMBED_REQUEST_FOCUS, 0, 0, 0);
11585 }
11586 
11587 /* Activate frame with Extended Window Manager Hints */
11588 
11589 static void
x_ewmh_activate_frame(struct frame * f)11590 x_ewmh_activate_frame (struct frame *f)
11591 {
11592   /* See Window Manager Specification/Extended Window Manager Hints at
11593      https://freedesktop.org/wiki/Specifications/wm-spec/  */
11594 
11595   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
11596 
11597   if (FRAME_VISIBLE_P (f) && x_wm_supports (f, dpyinfo->Xatom_net_active_window))
11598     {
11599       Lisp_Object frame;
11600       XSETFRAME (frame, f);
11601       x_send_client_event (frame, make_fixnum (0), frame,
11602 			   dpyinfo->Xatom_net_active_window,
11603 			   make_fixnum (32),
11604 			   list2 (make_fixnum (1),
11605 				  INT_TO_INTEGER (dpyinfo->last_user_time)));
11606     }
11607 }
11608 
11609 static Lisp_Object
x_get_focus_frame(struct frame * f)11610 x_get_focus_frame (struct frame *f)
11611 {
11612   Lisp_Object lisp_focus;
11613 
11614   struct frame *focus =  FRAME_DISPLAY_INFO (f)->x_focus_frame;
11615 
11616   if (!focus)
11617     return Qnil;
11618 
11619   XSETFRAME (lisp_focus, focus);
11620   return lisp_focus;
11621 }
11622 
11623 /* In certain situations, when the window manager follows a
11624    click-to-focus policy, there seems to be no way around calling
11625    XSetInputFocus to give another frame the input focus .
11626 
11627    In an ideal world, XSetInputFocus should generally be avoided so
11628    that applications don't interfere with the window manager's focus
11629    policy.  But I think it's okay to use when it's clearly done
11630    following a user-command.  */
11631 
11632 static void
x_focus_frame(struct frame * f,bool noactivate)11633 x_focus_frame (struct frame *f, bool noactivate)
11634 {
11635   Display *dpy = FRAME_X_DISPLAY (f);
11636 
11637   block_input ();
11638   x_catch_errors (dpy);
11639 
11640   if (FRAME_X_EMBEDDED_P (f))
11641     {
11642       /* For Xembedded frames, normally the embedder forwards key
11643 	 events.  See XEmbed Protocol Specification at
11644 	 https://freedesktop.org/wiki/Specifications/xembed-spec/  */
11645       xembed_request_focus (f);
11646     }
11647   else
11648     {
11649       XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11650 		      RevertToParent, CurrentTime);
11651       if (!noactivate)
11652 	x_ewmh_activate_frame (f);
11653     }
11654 
11655   x_uncatch_errors ();
11656   unblock_input ();
11657 }
11658 
11659 
11660 /* XEmbed implementation.  */
11661 
11662 #if defined USE_X_TOOLKIT || ! defined USE_GTK
11663 
11664 /* XEmbed implementation.  */
11665 
11666 #define XEMBED_VERSION 0
11667 
11668 static void
xembed_set_info(struct frame * f,enum xembed_info flags)11669 xembed_set_info (struct frame *f, enum xembed_info flags)
11670 {
11671   unsigned long data[2];
11672   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
11673 
11674   data[0] = XEMBED_VERSION;
11675   data[1] = flags;
11676 
11677   XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11678                    dpyinfo->Xatom_XEMBED_INFO, dpyinfo->Xatom_XEMBED_INFO,
11679 		   32, PropModeReplace, (unsigned char *) data, 2);
11680 }
11681 #endif /* defined USE_X_TOOLKIT || ! defined USE_GTK */
11682 
11683 static void
xembed_send_message(struct frame * f,Time t,enum xembed_message msg,long int detail,long int data1,long int data2)11684 xembed_send_message (struct frame *f, Time t, enum xembed_message msg,
11685 		     long int detail, long int data1, long int data2)
11686 {
11687   XEvent event;
11688 
11689   event.xclient.type = ClientMessage;
11690   event.xclient.window = FRAME_X_OUTPUT (f)->parent_desc;
11691   event.xclient.message_type = FRAME_DISPLAY_INFO (f)->Xatom_XEMBED;
11692   event.xclient.format = 32;
11693   event.xclient.data.l[0] = t;
11694   event.xclient.data.l[1] = msg;
11695   event.xclient.data.l[2] = detail;
11696   event.xclient.data.l[3] = data1;
11697   event.xclient.data.l[4] = data2;
11698 
11699   XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_OUTPUT (f)->parent_desc,
11700 	      False, NoEventMask, &event);
11701   XSync (FRAME_X_DISPLAY (f), False);
11702 }
11703 
11704 /* Change of visibility.  */
11705 
11706 /* This tries to wait until the frame is really visible, depending on
11707    the value of Vx_wait_for_event_timeout.
11708    However, if the window manager asks the user where to position
11709    the frame, this will return before the user finishes doing that.
11710    The frame will not actually be visible at that time,
11711    but it will become visible later when the window manager
11712    finishes with it.  */
11713 
11714 void
x_make_frame_visible(struct frame * f)11715 x_make_frame_visible (struct frame *f)
11716 {
11717   if (FRAME_PARENT_FRAME (f))
11718     {
11719       if (!FRAME_VISIBLE_P (f))
11720 	{
11721 	  block_input ();
11722 #ifdef USE_GTK
11723 	  gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
11724 	  XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11725 		       f->left_pos, f->top_pos);
11726 #else
11727 	  XMapRaised (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
11728 #endif
11729 	  unblock_input ();
11730 
11731 	  SET_FRAME_VISIBLE (f, true);
11732 	  SET_FRAME_ICONIFIED (f, false);
11733 	}
11734       return;
11735     }
11736 
11737   block_input ();
11738 
11739   gui_set_bitmap_icon (f);
11740 
11741   if (! FRAME_VISIBLE_P (f))
11742     {
11743       /* We test asked_for_visible here to make sure we don't
11744          call x_set_offset a second time
11745          if we get to x_make_frame_visible a second time
11746 	 before the window gets really visible.  */
11747       if (! FRAME_ICONIFIED_P (f)
11748 	  && ! FRAME_X_EMBEDDED_P (f)
11749 	  && ! f->output_data.x->asked_for_visible)
11750 	x_set_offset (f, f->left_pos, f->top_pos, 0);
11751 
11752       f->output_data.x->asked_for_visible = true;
11753 
11754       if (! EQ (Vx_no_window_manager, Qt))
11755 	x_wm_set_window_state (f, NormalState);
11756 #ifdef USE_X_TOOLKIT
11757       if (FRAME_X_EMBEDDED_P (f))
11758 	xembed_set_info (f, XEMBED_MAPPED);
11759       else
11760 	{
11761 	  /* This was XtPopup, but that did nothing for an iconified frame.  */
11762 	  XtMapWidget (f->output_data.x->widget);
11763 	}
11764 #else /* not USE_X_TOOLKIT */
11765 #ifdef USE_GTK
11766       gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
11767       gtk_window_deiconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
11768 #else
11769       if (FRAME_X_EMBEDDED_P (f))
11770 	xembed_set_info (f, XEMBED_MAPPED);
11771       else
11772 	XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11773 #endif /* not USE_GTK */
11774 #endif /* not USE_X_TOOLKIT */
11775     }
11776 
11777   XFlush (FRAME_X_DISPLAY (f));
11778 
11779   /* Synchronize to ensure Emacs knows the frame is visible
11780      before we do anything else.  We do this loop with input not blocked
11781      so that incoming events are handled.  */
11782   {
11783     Lisp_Object frame;
11784     /* This must be before UNBLOCK_INPUT
11785        since events that arrive in response to the actions above
11786        will set it when they are handled.  */
11787     bool previously_visible = f->output_data.x->has_been_visible;
11788 
11789     XSETFRAME (frame, f);
11790 
11791     int original_left = f->left_pos;
11792     int original_top = f->top_pos;
11793 
11794     /* This must come after we set COUNT.  */
11795     unblock_input ();
11796 
11797     /* We unblock here so that arriving X events are processed.  */
11798 
11799     /* Now move the window back to where it was "supposed to be".
11800        But don't do it if the gravity is negative.
11801        When the gravity is negative, this uses a position
11802        that is 3 pixels too low.  Perhaps that's really the border width.
11803 
11804        Don't do this if the window has never been visible before,
11805        because the window manager may choose the position
11806        and we don't want to override it.  */
11807 
11808     if (!FRAME_VISIBLE_P (f)
11809 	&& !FRAME_ICONIFIED_P (f)
11810 	&& !FRAME_X_EMBEDDED_P (f)
11811 	&& !FRAME_PARENT_FRAME (f)
11812 	&& f->win_gravity == NorthWestGravity
11813 	&& previously_visible)
11814       {
11815 	Drawable rootw;
11816 	int x, y;
11817 	unsigned int width, height, border, depth;
11818 
11819 	block_input ();
11820 
11821 	/* On some window managers (such as FVWM) moving an existing
11822 	   window, even to the same place, causes the window manager
11823 	   to introduce an offset.  This can cause the window to move
11824 	   to an unexpected location.  Check the geometry (a little
11825 	   slow here) and then verify that the window is in the right
11826 	   place.  If the window is not in the right place, move it
11827 	   there, and take the potential window manager hit.  */
11828 	XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11829 		      &rootw, &x, &y, &width, &height, &border, &depth);
11830 
11831 	if (original_left != x || original_top != y)
11832 	  XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11833 		       original_left, original_top);
11834 
11835 	unblock_input ();
11836       }
11837 
11838     /* Try to wait for a MapNotify event (that is what tells us when a
11839        frame becomes visible).  */
11840 
11841 #ifdef CYGWIN
11842     /* On Cygwin, which uses input polling, we need to force input to
11843        be read.  See
11844        https://lists.gnu.org/r/emacs-devel/2013-12/msg00351.html
11845        and https://debbugs.gnu.org/cgi/bugreport.cgi?bug=24091#131.
11846        Fake an alarm signal to let the handler know that there's
11847        something to be read.
11848 
11849        It could be confusing if a real alarm arrives while processing
11850        the fake one.  Turn it off and let the handler reset it.  */
11851     int old_poll_suppress_count = poll_suppress_count;
11852     poll_suppress_count = 1;
11853     poll_for_input_1 ();
11854     poll_suppress_count = old_poll_suppress_count;
11855 #endif
11856     if (! FRAME_VISIBLE_P (f))
11857       x_wait_for_event (f, MapNotify);
11858   }
11859 }
11860 
11861 /* Change from mapped state to withdrawn state.  */
11862 
11863 /* Make the frame visible (mapped and not iconified).  */
11864 
11865 void
x_make_frame_invisible(struct frame * f)11866 x_make_frame_invisible (struct frame *f)
11867 {
11868   Window window;
11869 
11870   /* Use the frame's outermost window, not the one we normally draw on.  */
11871   window = FRAME_OUTER_WINDOW (f);
11872 
11873   /* Don't keep the highlight on an invisible frame.  */
11874   if (FRAME_DISPLAY_INFO (f)->highlight_frame == f)
11875     FRAME_DISPLAY_INFO (f)->highlight_frame = 0;
11876 
11877   block_input ();
11878 
11879   /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
11880      that the current position of the window is user-specified, rather than
11881      program-specified, so that when the window is mapped again, it will be
11882      placed at the same location, without forcing the user to position it
11883      by hand again (they have already done that once for this window.)  */
11884   x_wm_set_size_hint (f, 0, true);
11885 
11886 #ifdef USE_GTK
11887   if (FRAME_GTK_OUTER_WIDGET (f))
11888     gtk_widget_hide (FRAME_GTK_OUTER_WIDGET (f));
11889   else
11890 #else
11891   if (FRAME_X_EMBEDDED_P (f))
11892     xembed_set_info (f, 0);
11893   else
11894 #endif
11895 
11896     if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
11897 			   DefaultScreen (FRAME_X_DISPLAY (f))))
11898       {
11899 	unblock_input ();
11900 	error ("Can't notify window manager of window withdrawal");
11901       }
11902 
11903   x_sync (f);
11904 
11905   /* We can't distinguish this from iconification
11906      just by the event that we get from the server.
11907      So we can't win using the usual strategy of letting
11908      FRAME_SAMPLE_VISIBILITY set this.  So do it by hand,
11909      and synchronize with the server to make sure we agree.  */
11910   SET_FRAME_VISIBLE (f, 0);
11911   SET_FRAME_ICONIFIED (f, false);
11912 
11913   unblock_input ();
11914 }
11915 
11916 static void
x_make_frame_visible_invisible(struct frame * f,bool visible)11917 x_make_frame_visible_invisible (struct frame *f, bool visible)
11918 {
11919   if (visible)
11920     x_make_frame_visible (f);
11921   else
11922     x_make_frame_invisible (f);
11923 }
11924 
11925 /* Change window state from mapped to iconified.  */
11926 
11927 void
x_iconify_frame(struct frame * f)11928 x_iconify_frame (struct frame *f)
11929 {
11930 #ifdef USE_X_TOOLKIT
11931   int result;
11932 #endif
11933 
11934   /* Don't keep the highlight on an invisible frame.  */
11935   if (FRAME_DISPLAY_INFO (f)->highlight_frame == f)
11936     FRAME_DISPLAY_INFO (f)->highlight_frame = 0;
11937 
11938   if (FRAME_ICONIFIED_P (f))
11939     return;
11940 
11941   block_input ();
11942 
11943   gui_set_bitmap_icon (f);
11944 
11945 #if defined (USE_GTK)
11946   if (FRAME_GTK_OUTER_WIDGET (f))
11947     {
11948       if (! FRAME_VISIBLE_P (f))
11949         gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
11950 
11951       gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
11952       SET_FRAME_VISIBLE (f, 0);
11953       SET_FRAME_ICONIFIED (f, true);
11954       unblock_input ();
11955       return;
11956     }
11957 #endif
11958 
11959 #ifdef USE_X_TOOLKIT
11960 
11961   if (! FRAME_VISIBLE_P (f))
11962     {
11963       if (! EQ (Vx_no_window_manager, Qt))
11964 	x_wm_set_window_state (f, IconicState);
11965       /* This was XtPopup, but that did nothing for an iconified frame.  */
11966       XtMapWidget (f->output_data.x->widget);
11967       /* The server won't give us any event to indicate
11968 	 that an invisible frame was changed to an icon,
11969 	 so we have to record it here.  */
11970       SET_FRAME_VISIBLE (f, 0);
11971       SET_FRAME_ICONIFIED (f, true);
11972       unblock_input ();
11973       return;
11974     }
11975 
11976   result = XIconifyWindow (FRAME_X_DISPLAY (f),
11977 			   XtWindow (f->output_data.x->widget),
11978 			   DefaultScreen (FRAME_X_DISPLAY (f)));
11979   unblock_input ();
11980 
11981   if (!result)
11982     error ("Can't notify window manager of iconification");
11983 
11984   SET_FRAME_ICONIFIED (f, true);
11985   SET_FRAME_VISIBLE (f, 0);
11986 
11987   block_input ();
11988   XFlush (FRAME_X_DISPLAY (f));
11989   unblock_input ();
11990 #else /* not USE_X_TOOLKIT */
11991 
11992   /* Make sure the X server knows where the window should be positioned,
11993      in case the user deiconifies with the window manager.  */
11994   if (! FRAME_VISIBLE_P (f)
11995       && ! FRAME_ICONIFIED_P (f)
11996       && ! FRAME_X_EMBEDDED_P (f))
11997     x_set_offset (f, f->left_pos, f->top_pos, 0);
11998 
11999   /* Since we don't know which revision of X we're running, we'll use both
12000      the X11R3 and X11R4 techniques.  I don't know if this is a good idea.  */
12001 
12002   /* X11R4: send a ClientMessage to the window manager using the
12003      WM_CHANGE_STATE type.  */
12004   {
12005     XEvent msg;
12006 
12007     msg.xclient.window = FRAME_X_WINDOW (f);
12008     msg.xclient.type = ClientMessage;
12009     msg.xclient.message_type = FRAME_DISPLAY_INFO (f)->Xatom_wm_change_state;
12010     msg.xclient.format = 32;
12011     msg.xclient.data.l[0] = IconicState;
12012 
12013     if (! XSendEvent (FRAME_X_DISPLAY (f),
12014 		      DefaultRootWindow (FRAME_X_DISPLAY (f)),
12015 		      False,
12016 		      SubstructureRedirectMask | SubstructureNotifyMask,
12017 		      &msg))
12018       {
12019 	unblock_input ();
12020 	error ("Can't notify window manager of iconification");
12021       }
12022   }
12023 
12024   /* X11R3: set the initial_state field of the window manager hints to
12025      IconicState.  */
12026   x_wm_set_window_state (f, IconicState);
12027 
12028   if (!FRAME_VISIBLE_P (f))
12029     {
12030       /* If the frame was withdrawn, before, we must map it.  */
12031       XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12032     }
12033 
12034   SET_FRAME_ICONIFIED (f, true);
12035   SET_FRAME_VISIBLE (f, 0);
12036 
12037   XFlush (FRAME_X_DISPLAY (f));
12038   unblock_input ();
12039 #endif /* not USE_X_TOOLKIT */
12040 }
12041 
12042 
12043 /* Free X resources of frame F.  */
12044 
12045 void
x_free_frame_resources(struct frame * f)12046 x_free_frame_resources (struct frame *f)
12047 {
12048   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
12049   Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
12050 #ifdef USE_X_TOOLKIT
12051   Lisp_Object bar;
12052   struct scroll_bar *b;
12053 #endif
12054 
12055   block_input ();
12056 
12057   /* If a display connection is dead, don't try sending more
12058      commands to the X server.  */
12059   if (dpyinfo->display)
12060     {
12061       /* Always exit with visible pointer to avoid weird issue
12062 	 with Xfixes (Bug#17609).  */
12063       if (f->pointer_invisible)
12064 	FRAME_DISPLAY_INFO (f)->toggle_visible_pointer (f, 0);
12065 
12066       /* We must free faces before destroying windows because some
12067 	 font-driver (e.g. xft) access a window while finishing a
12068 	 face.  */
12069       free_frame_faces (f);
12070       tear_down_x_back_buffer (f);
12071 
12072       if (f->output_data.x->icon_desc)
12073 	XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
12074 
12075 #ifdef USE_X_TOOLKIT
12076       /* Explicitly destroy the scroll bars of the frame.  Without
12077 	 this, we get "BadDrawable" errors from the toolkit later on,
12078 	 presumably from expose events generated for the disappearing
12079 	 toolkit scroll bars.  */
12080       for (bar = FRAME_SCROLL_BARS (f); !NILP (bar); bar = b->next)
12081 	{
12082 	  b = XSCROLL_BAR (bar);
12083 	  x_scroll_bar_remove (b);
12084 	}
12085 #endif
12086 
12087 #ifdef HAVE_X_I18N
12088       if (FRAME_XIC (f))
12089 	free_frame_xic (f);
12090 #endif
12091 
12092 #ifdef USE_CAIRO
12093       x_cr_destroy_frame_context (f);
12094 #endif
12095 #ifdef USE_X_TOOLKIT
12096       if (f->output_data.x->widget)
12097 	{
12098 	  XtDestroyWidget (f->output_data.x->widget);
12099 	  f->output_data.x->widget = NULL;
12100 	}
12101       /* Tooltips don't have widgets, only a simple X window, even if
12102 	 we are using a toolkit.  */
12103       else if (FRAME_X_WINDOW (f))
12104         XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12105 
12106       free_frame_menubar (f);
12107 
12108       if (f->shell_position)
12109 	xfree (f->shell_position);
12110 #else  /* !USE_X_TOOLKIT */
12111 
12112 #ifdef USE_GTK
12113       xg_free_frame_widgets (f);
12114 #endif /* USE_GTK */
12115 
12116       tear_down_x_back_buffer (f);
12117       if (FRAME_X_WINDOW (f))
12118           XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12119 #endif /* !USE_X_TOOLKIT */
12120 
12121       unload_color (f, FRAME_FOREGROUND_PIXEL (f));
12122       unload_color (f, FRAME_BACKGROUND_PIXEL (f));
12123       unload_color (f, f->output_data.x->cursor_pixel);
12124       unload_color (f, f->output_data.x->cursor_foreground_pixel);
12125       unload_color (f, f->output_data.x->border_pixel);
12126       unload_color (f, f->output_data.x->mouse_pixel);
12127 
12128       if (f->output_data.x->scroll_bar_background_pixel != -1)
12129 	unload_color (f, f->output_data.x->scroll_bar_background_pixel);
12130       if (f->output_data.x->scroll_bar_foreground_pixel != -1)
12131 	unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
12132 #if defined (USE_LUCID) && defined (USE_TOOLKIT_SCROLL_BARS)
12133       /* Scrollbar shadow colors.  */
12134       if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
12135 	unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
12136       if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
12137 	unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
12138 #endif /* USE_LUCID && USE_TOOLKIT_SCROLL_BARS */
12139       if (f->output_data.x->white_relief.pixel != -1)
12140 	unload_color (f, f->output_data.x->white_relief.pixel);
12141       if (f->output_data.x->black_relief.pixel != -1)
12142 	unload_color (f, f->output_data.x->black_relief.pixel);
12143 
12144       x_free_gcs (f);
12145 
12146       /* Free extra GCs allocated by x_setup_relief_colors.  */
12147       if (f->output_data.x->white_relief.gc)
12148 	{
12149 	  XFreeGC (dpyinfo->display, f->output_data.x->white_relief.gc);
12150 	  f->output_data.x->white_relief.gc = 0;
12151 	}
12152       if (f->output_data.x->black_relief.gc)
12153 	{
12154 	  XFreeGC (dpyinfo->display, f->output_data.x->black_relief.gc);
12155 	  f->output_data.x->black_relief.gc = 0;
12156 	}
12157 
12158       /* Free cursors.  */
12159       if (f->output_data.x->text_cursor != 0)
12160 	XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->text_cursor);
12161       if (f->output_data.x->nontext_cursor != 0)
12162 	XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->nontext_cursor);
12163       if (f->output_data.x->modeline_cursor != 0)
12164 	XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->modeline_cursor);
12165       if (f->output_data.x->hand_cursor != 0)
12166 	XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->hand_cursor);
12167       if (f->output_data.x->hourglass_cursor != 0)
12168 	XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->hourglass_cursor);
12169       if (f->output_data.x->horizontal_drag_cursor != 0)
12170 	XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->horizontal_drag_cursor);
12171       if (f->output_data.x->vertical_drag_cursor != 0)
12172 	XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->vertical_drag_cursor);
12173       if (f->output_data.x->left_edge_cursor != 0)
12174 	XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->left_edge_cursor);
12175       if (f->output_data.x->top_left_corner_cursor != 0)
12176 	XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->top_left_corner_cursor);
12177       if (f->output_data.x->top_edge_cursor != 0)
12178 	XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->top_edge_cursor);
12179       if (f->output_data.x->top_right_corner_cursor != 0)
12180 	XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->top_right_corner_cursor);
12181       if (f->output_data.x->right_edge_cursor != 0)
12182 	XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->right_edge_cursor);
12183       if (f->output_data.x->bottom_right_corner_cursor != 0)
12184 	XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->bottom_right_corner_cursor);
12185       if (f->output_data.x->bottom_edge_cursor != 0)
12186 	XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->bottom_edge_cursor);
12187       if (f->output_data.x->bottom_left_corner_cursor != 0)
12188 	XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->bottom_left_corner_cursor);
12189 
12190       XFlush (FRAME_X_DISPLAY (f));
12191     }
12192 
12193   xfree (f->output_data.x->saved_menu_event);
12194   xfree (f->output_data.x);
12195   f->output_data.x = NULL;
12196 
12197   if (f == dpyinfo->x_focus_frame)
12198     dpyinfo->x_focus_frame = 0;
12199   if (f == dpyinfo->x_focus_event_frame)
12200     dpyinfo->x_focus_event_frame = 0;
12201   if (f == dpyinfo->highlight_frame)
12202     dpyinfo->highlight_frame = 0;
12203   if (f == hlinfo->mouse_face_mouse_frame)
12204     reset_mouse_highlight (hlinfo);
12205 
12206   unblock_input ();
12207 }
12208 
12209 
12210 /* Destroy the X window of frame F.  */
12211 
12212 static void
x_destroy_window(struct frame * f)12213 x_destroy_window (struct frame *f)
12214 {
12215   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
12216 
12217   /* If a display connection is dead, don't try sending more
12218      commands to the X server.  */
12219   if (dpyinfo->display != 0)
12220     x_free_frame_resources (f);
12221 
12222   dpyinfo->reference_count--;
12223 }
12224 
12225 
12226 /* Setting window manager hints.  */
12227 
12228 /* Set the normal size hints for the window manager, for frame F.
12229    FLAGS is the flags word to use--or 0 meaning preserve the flags
12230    that the window now has.
12231    If USER_POSITION, set the USPosition
12232    flag (this is useful when FLAGS is 0).
12233    The GTK version is in gtkutils.c.  */
12234 
12235 #ifndef USE_GTK
12236 void
x_wm_set_size_hint(struct frame * f,long flags,bool user_position)12237 x_wm_set_size_hint (struct frame *f, long flags, bool user_position)
12238 {
12239   XSizeHints size_hints;
12240   Window window = FRAME_OUTER_WINDOW (f);
12241 
12242   if (!window)
12243     return;
12244 
12245 #ifdef USE_X_TOOLKIT
12246   if (f->output_data.x->widget)
12247     {
12248       widget_update_wm_size_hints (f->output_data.x->widget);
12249       return;
12250     }
12251 #endif
12252 
12253   /* Setting PMaxSize caused various problems.  */
12254   size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
12255 
12256   size_hints.x = f->left_pos;
12257   size_hints.y = f->top_pos;
12258 
12259   size_hints.width = FRAME_PIXEL_WIDTH (f);
12260   size_hints.height = FRAME_PIXEL_HEIGHT (f);
12261 
12262   size_hints.width_inc = frame_resize_pixelwise ? 1 : FRAME_COLUMN_WIDTH (f);
12263   size_hints.height_inc = frame_resize_pixelwise ? 1 : FRAME_LINE_HEIGHT (f);
12264 
12265   size_hints.max_width = x_display_pixel_width (FRAME_DISPLAY_INFO (f))
12266     - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
12267   size_hints.max_height = x_display_pixel_height (FRAME_DISPLAY_INFO (f))
12268     - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
12269 
12270   /* Calculate the base and minimum sizes.  */
12271   {
12272     int base_width, base_height;
12273 
12274     base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
12275     base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
12276 
12277     /* The window manager uses the base width hints to calculate the
12278        current number of rows and columns in the frame while
12279        resizing; min_width and min_height aren't useful for this
12280        purpose, since they might not give the dimensions for a
12281        zero-row, zero-column frame.  */
12282 
12283     size_hints.flags |= PBaseSize;
12284     size_hints.base_width = base_width;
12285     size_hints.base_height = base_height + FRAME_MENUBAR_HEIGHT (f);
12286     size_hints.min_width  = base_width;
12287     size_hints.min_height = base_height;
12288   }
12289 
12290   /* If we don't need the old flags, we don't need the old hint at all.  */
12291   if (flags)
12292     {
12293       size_hints.flags |= flags;
12294       goto no_read;
12295     }
12296 
12297   {
12298     XSizeHints hints;		/* Sometimes I hate X Windows... */
12299     long supplied_return;
12300     int value;
12301 
12302     value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
12303 			       &supplied_return);
12304 
12305     if (flags)
12306       size_hints.flags |= flags;
12307     else
12308       {
12309 	if (value == 0)
12310 	  hints.flags = 0;
12311 	if (hints.flags & PSize)
12312 	  size_hints.flags |= PSize;
12313 	if (hints.flags & PPosition)
12314 	  size_hints.flags |= PPosition;
12315 	if (hints.flags & USPosition)
12316 	  size_hints.flags |= USPosition;
12317 	if (hints.flags & USSize)
12318 	  size_hints.flags |= USSize;
12319       }
12320   }
12321 
12322  no_read:
12323 
12324 #ifdef PWinGravity
12325   size_hints.win_gravity = f->win_gravity;
12326   size_hints.flags |= PWinGravity;
12327 
12328   if (user_position)
12329     {
12330       size_hints.flags &= ~ PPosition;
12331       size_hints.flags |= USPosition;
12332     }
12333 #endif /* PWinGravity */
12334 
12335   XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
12336 }
12337 #endif /* not USE_GTK */
12338 
12339 /* Used for IconicState or NormalState */
12340 
12341 static void
x_wm_set_window_state(struct frame * f,int state)12342 x_wm_set_window_state (struct frame *f, int state)
12343 {
12344 #ifdef USE_X_TOOLKIT
12345   Arg al[1];
12346 
12347   XtSetArg (al[0], XtNinitialState, state);
12348   XtSetValues (f->output_data.x->widget, al, 1);
12349 #else /* not USE_X_TOOLKIT */
12350   Window window = FRAME_X_WINDOW (f);
12351 
12352   f->output_data.x->wm_hints.flags |= StateHint;
12353   f->output_data.x->wm_hints.initial_state = state;
12354 
12355   XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
12356 #endif /* not USE_X_TOOLKIT */
12357 }
12358 
12359 static void
x_wm_set_icon_pixmap(struct frame * f,ptrdiff_t pixmap_id)12360 x_wm_set_icon_pixmap (struct frame *f, ptrdiff_t pixmap_id)
12361 {
12362   Pixmap icon_pixmap, icon_mask;
12363 
12364 #if !defined USE_X_TOOLKIT && !defined USE_GTK
12365   Window window = FRAME_OUTER_WINDOW (f);
12366 #endif
12367 
12368   if (pixmap_id > 0)
12369     {
12370       icon_pixmap = image_bitmap_pixmap (f, pixmap_id);
12371       f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
12372       icon_mask = x_bitmap_mask (f, pixmap_id);
12373       f->output_data.x->wm_hints.icon_mask = icon_mask;
12374     }
12375   else
12376     {
12377       /* It seems there is no way to turn off use of an icon
12378 	 pixmap.  */
12379       return;
12380     }
12381 
12382 
12383 #ifdef USE_GTK
12384   {
12385     xg_set_frame_icon (f, icon_pixmap, icon_mask);
12386     return;
12387   }
12388 
12389 #elif defined (USE_X_TOOLKIT) /* same as in x_wm_set_window_state.  */
12390 
12391   {
12392     Arg al[1];
12393     XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
12394     XtSetValues (f->output_data.x->widget, al, 1);
12395     XtSetArg (al[0], XtNiconMask, icon_mask);
12396     XtSetValues (f->output_data.x->widget, al, 1);
12397   }
12398 
12399 #else /* not USE_X_TOOLKIT && not USE_GTK */
12400 
12401   f->output_data.x->wm_hints.flags |= (IconPixmapHint | IconMaskHint);
12402   XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
12403 
12404 #endif /* not USE_X_TOOLKIT && not USE_GTK */
12405 }
12406 
12407 void
x_wm_set_icon_position(struct frame * f,int icon_x,int icon_y)12408 x_wm_set_icon_position (struct frame *f, int icon_x, int icon_y)
12409 {
12410   Window window = FRAME_OUTER_WINDOW (f);
12411 
12412   f->output_data.x->wm_hints.flags |= IconPositionHint;
12413   f->output_data.x->wm_hints.icon_x = icon_x;
12414   f->output_data.x->wm_hints.icon_y = icon_y;
12415 
12416   XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
12417 }
12418 
12419 
12420 /***********************************************************************
12421 				Fonts
12422  ***********************************************************************/
12423 
12424 #ifdef GLYPH_DEBUG
12425 
12426 /* Check that FONT is valid on frame F.  It is if it can be found in F's
12427    font table.  */
12428 
12429 static void
x_check_font(struct frame * f,struct font * font)12430 x_check_font (struct frame *f, struct font *font)
12431 {
12432   eassert (font != NULL && ! NILP (font->props[FONT_TYPE_INDEX]));
12433   if (font->driver->check)
12434     eassert (font->driver->check (f, font) == 0);
12435 }
12436 
12437 #endif /* GLYPH_DEBUG */
12438 
12439 
12440 /***********************************************************************
12441                              Image Hooks
12442  ***********************************************************************/
12443 
12444 static void
x_free_pixmap(struct frame * f,Emacs_Pixmap pixmap)12445 x_free_pixmap (struct frame *f, Emacs_Pixmap pixmap)
12446 {
12447 #ifdef USE_CAIRO
12448   if (pixmap)
12449     {
12450       xfree (pixmap->data);
12451       xfree (pixmap);
12452     }
12453 #else
12454   XFreePixmap (FRAME_X_DISPLAY (f), pixmap);
12455 #endif
12456 }
12457 
12458 
12459 /***********************************************************************
12460 			    Initialization
12461  ***********************************************************************/
12462 
12463 #ifdef USE_X_TOOLKIT
12464 static XrmOptionDescRec emacs_options[] = {
12465   {(char *) "-geometry", (char *) ".geometry", XrmoptionSepArg, NULL},
12466   {(char *) "-iconic", (char *) ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
12467 
12468   {(char *) "-internal-border-width",
12469    (char *) "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
12470   {(char *) "-ib", (char *) "*EmacsScreen.internalBorderWidth",
12471    XrmoptionSepArg, NULL},
12472   {(char *) "-T", (char *) "*EmacsShell.title", XrmoptionSepArg, NULL},
12473   {(char *) "-wn", (char *) "*EmacsShell.title", XrmoptionSepArg, NULL},
12474   {(char *) "-title", (char *) "*EmacsShell.title", XrmoptionSepArg, NULL},
12475   {(char *) "-iconname", (char *) "*EmacsShell.iconName",
12476    XrmoptionSepArg, NULL},
12477   {(char *) "-in", (char *) "*EmacsShell.iconName", XrmoptionSepArg, NULL},
12478   {(char *) "-mc", (char *) "*pointerColor", XrmoptionSepArg, NULL},
12479   {(char *) "-cr", (char *) "*cursorColor", XrmoptionSepArg, NULL}
12480 };
12481 
12482 /* Whether atimer for Xt timeouts is activated or not.  */
12483 
12484 static bool x_timeout_atimer_activated_flag;
12485 
12486 #endif /* USE_X_TOOLKIT */
12487 
12488 static int x_initialized;
12489 
12490 /* Test whether two display-name strings agree up to the dot that separates
12491    the screen number from the server number.  */
12492 static bool
same_x_server(const char * name1,const char * name2)12493 same_x_server (const char *name1, const char *name2)
12494 {
12495   bool seen_colon = false;
12496   Lisp_Object sysname = Fsystem_name ();
12497   if (! STRINGP (sysname))
12498     sysname = empty_unibyte_string;
12499   const char *system_name = SSDATA (sysname);
12500   ptrdiff_t system_name_length = SBYTES (sysname);
12501   ptrdiff_t length_until_period = 0;
12502 
12503   while (system_name[length_until_period] != 0
12504 	 && system_name[length_until_period] != '.')
12505     length_until_period++;
12506 
12507   /* Treat `unix' like an empty host name.  */
12508   if (! strncmp (name1, "unix:", 5))
12509     name1 += 4;
12510   if (! strncmp (name2, "unix:", 5))
12511     name2 += 4;
12512   /* Treat this host's name like an empty host name.  */
12513   if (! strncmp (name1, system_name, system_name_length)
12514       && name1[system_name_length] == ':')
12515     name1 += system_name_length;
12516   if (! strncmp (name2, system_name, system_name_length)
12517       && name2[system_name_length] == ':')
12518     name2 += system_name_length;
12519   /* Treat this host's domainless name like an empty host name.  */
12520   if (! strncmp (name1, system_name, length_until_period)
12521       && name1[length_until_period] == ':')
12522     name1 += length_until_period;
12523   if (! strncmp (name2, system_name, length_until_period)
12524       && name2[length_until_period] == ':')
12525     name2 += length_until_period;
12526 
12527   for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
12528     {
12529       if (*name1 == ':')
12530 	seen_colon = true;
12531       if (seen_colon && *name1 == '.')
12532 	return true;
12533     }
12534   return (seen_colon
12535 	  && (*name1 == '.' || *name1 == '\0')
12536 	  && (*name2 == '.' || *name2 == '\0'));
12537 }
12538 
12539 /* Count number of set bits in mask and number of bits to shift to
12540    get to the first bit.  With MASK 0x7e0, *BITS is set to 6, and *OFFSET
12541    to 5.  */
12542 static void
get_bits_and_offset(unsigned long mask,int * bits,int * offset)12543 get_bits_and_offset (unsigned long mask, int *bits, int *offset)
12544 {
12545   int nr = 0;
12546   int off = 0;
12547 
12548   while (!(mask & 1))
12549     {
12550       off++;
12551       mask >>= 1;
12552     }
12553 
12554   while (mask & 1)
12555     {
12556       nr++;
12557       mask >>= 1;
12558     }
12559 
12560   *offset = off;
12561   *bits = nr;
12562 }
12563 
12564 /* Return true iff display DISPLAY is available for use.
12565    But don't permanently open it, just test its availability.  */
12566 
12567 bool
x_display_ok(const char * display)12568 x_display_ok (const char *display)
12569 {
12570   /* XOpenDisplay fails if it gets a signal.  Block SIGIO which may arrive.  */
12571   unrequest_sigio ();
12572   Display *dpy = XOpenDisplay (display);
12573   request_sigio ();
12574   if (!dpy)
12575     return false;
12576   XCloseDisplay (dpy);
12577   return true;
12578 }
12579 
12580 #ifdef USE_GTK
12581 static void
my_log_handler(const gchar * log_domain,GLogLevelFlags log_level,const gchar * msg,gpointer user_data)12582 my_log_handler (const gchar *log_domain, GLogLevelFlags log_level,
12583 		const gchar *msg, gpointer user_data)
12584 {
12585   if (!strstr (msg, "g_set_prgname"))
12586       fprintf (stderr, "%s-WARNING **: %s\n", log_domain, msg);
12587 }
12588 #endif
12589 
12590 /* Create invisible cursor on X display referred by DPYINFO.  */
12591 
12592 static Cursor
make_invisible_cursor(struct x_display_info * dpyinfo)12593 make_invisible_cursor (struct x_display_info *dpyinfo)
12594 {
12595   Display *dpy = dpyinfo->display;
12596   static char const no_data[] = { 0 };
12597   Pixmap pix;
12598   XColor col;
12599   Cursor c = 0;
12600 
12601   x_catch_errors (dpy);
12602   pix = XCreateBitmapFromData (dpy, dpyinfo->root_window, no_data, 1, 1);
12603   if (! x_had_errors_p (dpy) && pix != None)
12604     {
12605       Cursor pixc;
12606       col.pixel = 0;
12607       col.red = col.green = col.blue = 0;
12608       col.flags = DoRed | DoGreen | DoBlue;
12609       pixc = XCreatePixmapCursor (dpy, pix, pix, &col, &col, 0, 0);
12610       if (! x_had_errors_p (dpy) && pixc != None)
12611         c = pixc;
12612       XFreePixmap (dpy, pix);
12613     }
12614 
12615   x_uncatch_errors ();
12616 
12617   return c;
12618 }
12619 
12620 /* True if DPY supports Xfixes extension >= 4.  */
12621 
12622 static bool
x_probe_xfixes_extension(Display * dpy)12623 x_probe_xfixes_extension (Display *dpy)
12624 {
12625 #ifdef HAVE_XFIXES
12626   int major, minor;
12627   return XFixesQueryVersion (dpy, &major, &minor) && major >= 4;
12628 #else
12629   return false;
12630 #endif /* HAVE_XFIXES */
12631 }
12632 
12633 /* Toggle mouse pointer visibility on frame F by using Xfixes functions.  */
12634 
12635 static void
xfixes_toggle_visible_pointer(struct frame * f,bool invisible)12636 xfixes_toggle_visible_pointer (struct frame *f, bool invisible)
12637 {
12638 #ifdef HAVE_XFIXES
12639   if (invisible)
12640     XFixesHideCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12641   else
12642     XFixesShowCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12643   f->pointer_invisible = invisible;
12644 #else
12645   emacs_abort ();
12646 #endif /* HAVE_XFIXES */
12647 }
12648 
12649 /* Toggle mouse pointer visibility on frame F by using invisible cursor.  */
12650 
12651 static void
x_toggle_visible_pointer(struct frame * f,bool invisible)12652 x_toggle_visible_pointer (struct frame *f, bool invisible)
12653 {
12654   eassert (FRAME_DISPLAY_INFO (f)->invisible_cursor != 0);
12655   if (invisible)
12656     XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12657 		   FRAME_DISPLAY_INFO (f)->invisible_cursor);
12658   else
12659     XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12660 		   f->output_data.x->current_cursor);
12661   f->pointer_invisible = invisible;
12662 }
12663 
12664 /* Setup pointer blanking, prefer Xfixes if available.  */
12665 
12666 static void
x_setup_pointer_blanking(struct x_display_info * dpyinfo)12667 x_setup_pointer_blanking (struct x_display_info *dpyinfo)
12668 {
12669   /* FIXME: the brave tester should set EMACS_XFIXES because we're suspecting
12670      X server bug, see https://debbugs.gnu.org/cgi/bugreport.cgi?bug=17609.  */
12671   if (egetenv ("EMACS_XFIXES") && x_probe_xfixes_extension (dpyinfo->display))
12672     dpyinfo->toggle_visible_pointer = xfixes_toggle_visible_pointer;
12673   else
12674     {
12675       dpyinfo->toggle_visible_pointer = x_toggle_visible_pointer;
12676       dpyinfo->invisible_cursor = make_invisible_cursor (dpyinfo);
12677     }
12678 }
12679 
12680 /* Current X display connection identifier.  Incremented for each next
12681    connection established.  */
12682 static unsigned x_display_id;
12683 
12684 /* Open a connection to X display DISPLAY_NAME, and return
12685    the structure that describes the open display.
12686    If we cannot contact the display, return null.  */
12687 
12688 struct x_display_info *
x_term_init(Lisp_Object display_name,char * xrm_option,char * resource_name)12689 x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
12690 {
12691   Display *dpy;
12692   struct terminal *terminal;
12693   struct x_display_info *dpyinfo;
12694   XrmDatabase xrdb;
12695 #ifdef USE_XCB
12696   xcb_connection_t *xcb_conn;
12697 #endif
12698 
12699   block_input ();
12700 
12701   if (!x_initialized)
12702     {
12703       x_initialize ();
12704       ++x_initialized;
12705     }
12706 
12707   if (! x_display_ok (SSDATA (display_name)))
12708     error ("Display %s can't be opened", SSDATA (display_name));
12709 
12710 #ifdef USE_GTK
12711   {
12712 #define NUM_ARGV 10
12713     int argc;
12714     char *argv[NUM_ARGV];
12715     char **argv2 = argv;
12716     guint id;
12717 
12718     if (x_initialized++ > 1)
12719       {
12720         xg_display_open (SSDATA (display_name), &dpy);
12721       }
12722     else
12723       {
12724         static char display_opt[] = "--display";
12725         static char name_opt[] = "--name";
12726 
12727         for (argc = 0; argc < NUM_ARGV; ++argc)
12728           argv[argc] = 0;
12729 
12730         argc = 0;
12731         argv[argc++] = initial_argv[0];
12732 
12733         if (! NILP (display_name))
12734           {
12735             argv[argc++] = display_opt;
12736             argv[argc++] = SSDATA (display_name);
12737           }
12738 
12739         argv[argc++] = name_opt;
12740         argv[argc++] = resource_name;
12741 
12742         XSetLocaleModifiers ("");
12743 
12744         /* Work around GLib bug that outputs a faulty warning. See
12745            https://bugzilla.gnome.org/show_bug.cgi?id=563627.  */
12746         id = g_log_set_handler ("GLib", G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL
12747                                   | G_LOG_FLAG_RECURSION, my_log_handler, NULL);
12748 
12749         /* NULL window -> events for all windows go to our function.
12750            Call before gtk_init so Gtk+ event filters comes after our.  */
12751         gdk_window_add_filter (NULL, event_handler_gdk, NULL);
12752 
12753         /* gtk_init does set_locale.  Fix locale before and after.  */
12754         fixup_locale ();
12755         unrequest_sigio (); /* See comment in x_display_ok.  */
12756         gtk_init (&argc, &argv2);
12757         request_sigio ();
12758 
12759         g_log_remove_handler ("GLib", id);
12760 
12761         xg_initialize ();
12762 
12763 	/* Do this after the call to xg_initialize, because when
12764 	   Fontconfig is used, xg_initialize calls its initialization
12765 	   function which in some versions of Fontconfig calls setlocale.  */
12766 	fixup_locale ();
12767 
12768         dpy = DEFAULT_GDK_DISPLAY ();
12769 
12770 #ifndef HAVE_GTK3
12771         /* Load our own gtkrc if it exists.  */
12772         {
12773           const char *file = "~/.emacs.d/gtkrc";
12774           Lisp_Object s, abs_file;
12775 
12776           s = build_string (file);
12777           abs_file = Fexpand_file_name (s, Qnil);
12778 
12779           if (! NILP (abs_file) && !NILP (Ffile_readable_p (abs_file)))
12780             gtk_rc_parse (SSDATA (abs_file));
12781         }
12782 #endif
12783 
12784         XSetErrorHandler (x_error_handler);
12785         XSetIOErrorHandler (x_io_error_quitter);
12786       }
12787   }
12788 #else /* not USE_GTK */
12789 #ifdef USE_X_TOOLKIT
12790   /* weiner@footloose.sps.mot.com reports that this causes
12791      errors with X11R5:
12792 	   X protocol error: BadAtom (invalid Atom parameter)
12793 	   on protocol request 18skiloaf.
12794      So let's not use it until R6.  */
12795 #ifdef HAVE_X11XTR6
12796   XtSetLanguageProc (NULL, NULL, NULL);
12797 #endif
12798 
12799   {
12800     int argc = 0;
12801     char *argv[3];
12802 
12803     argv[0] = (char *) "";
12804     argc = 1;
12805     if (xrm_option)
12806       {
12807 	argv[argc++] = (char *) "-xrm";
12808 	argv[argc++] = xrm_option;
12809       }
12810     turn_on_atimers (false);
12811     unrequest_sigio ();  /* See comment in x_display_ok.  */
12812     dpy = XtOpenDisplay (Xt_app_con, SSDATA (display_name),
12813 			 resource_name, EMACS_CLASS,
12814 			 emacs_options, XtNumber (emacs_options),
12815 			 &argc, argv);
12816     request_sigio ();
12817     turn_on_atimers (true);
12818 
12819 #ifdef HAVE_X11XTR6
12820     /* I think this is to compensate for XtSetLanguageProc.  */
12821     fixup_locale ();
12822 #endif
12823   }
12824 
12825 #else /* not USE_X_TOOLKIT */
12826   XSetLocaleModifiers ("");
12827   unrequest_sigio ();  /* See comment in x_display_ok.  */
12828   dpy = XOpenDisplay (SSDATA (display_name));
12829   request_sigio ();
12830 #endif /* not USE_X_TOOLKIT */
12831 #endif /* not USE_GTK*/
12832 
12833   /* Detect failure.  */
12834   if (dpy == 0)
12835     {
12836       unblock_input ();
12837       return 0;
12838     }
12839 
12840 #ifdef USE_XCB
12841   xcb_conn = XGetXCBConnection (dpy);
12842   if (xcb_conn == 0)
12843     {
12844 #ifdef USE_GTK
12845       xg_display_close (dpy);
12846 #else
12847 #ifdef USE_X_TOOLKIT
12848       XtCloseDisplay (dpy);
12849 #else
12850       XCloseDisplay (dpy);
12851 #endif
12852 #endif /* ! USE_GTK */
12853 
12854       unblock_input ();
12855       return 0;
12856     }
12857 #endif
12858 
12859   /* We have definitely succeeded.  Record the new connection.  */
12860 
12861   dpyinfo = xzalloc (sizeof *dpyinfo);
12862   terminal = x_create_terminal (dpyinfo);
12863 
12864   {
12865     struct x_display_info *share;
12866 
12867     for (share = x_display_list; share; share = share->next)
12868       if (same_x_server (SSDATA (XCAR (share->name_list_element)),
12869 			 SSDATA (display_name)))
12870 	break;
12871     if (share)
12872       terminal->kboard = share->terminal->kboard;
12873     else
12874       {
12875 	terminal->kboard = allocate_kboard (Qx);
12876 
12877 	if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->u.s.function, Qunbound))
12878 	  {
12879 	    char *vendor = ServerVendor (dpy);
12880 
12881 	    /* Temporarily hide the partially initialized terminal.  */
12882 	    terminal_list = terminal->next_terminal;
12883 	    unblock_input ();
12884 	    kset_system_key_alist
12885 	      (terminal->kboard,
12886 	       call1 (Qvendor_specific_keysyms,
12887 		      vendor ? build_string (vendor) : empty_unibyte_string));
12888 	    block_input ();
12889 	    terminal->next_terminal = terminal_list;
12890  	    terminal_list = terminal;
12891 	  }
12892 
12893 	/* Don't let the initial kboard remain current longer than necessary.
12894 	   That would cause problems if a file loaded on startup tries to
12895 	   prompt in the mini-buffer.  */
12896 	if (current_kboard == initial_kboard)
12897 	  current_kboard = terminal->kboard;
12898       }
12899     terminal->kboard->reference_count++;
12900   }
12901 
12902   /* Put this display on the chain.  */
12903   dpyinfo->next = x_display_list;
12904   x_display_list = dpyinfo;
12905 
12906   dpyinfo->name_list_element = Fcons (display_name, Qnil);
12907   dpyinfo->display = dpy;
12908   dpyinfo->connection = ConnectionNumber (dpyinfo->display);
12909 #ifdef USE_XCB
12910   dpyinfo->xcb_connection = xcb_conn;
12911 #endif
12912 
12913   /* https://lists.gnu.org/r/emacs-devel/2015-11/msg00194.html  */
12914   dpyinfo->smallest_font_height = 1;
12915   dpyinfo->smallest_char_width = 1;
12916 
12917   /* Set the name of the terminal. */
12918   terminal->name = xlispstrdup (display_name);
12919 
12920 #if false
12921   XSetAfterFunction (x_current_display, x_trace_wire);
12922 #endif
12923 
12924   Lisp_Object system_name = Fsystem_name ();
12925 
12926   ptrdiff_t nbytes = SBYTES (Vinvocation_name) + 1;
12927   if (STRINGP (system_name)
12928       && INT_ADD_WRAPV (nbytes, SBYTES (system_name) + 1, &nbytes))
12929     memory_full (SIZE_MAX);
12930   dpyinfo->x_id = ++x_display_id;
12931   dpyinfo->x_id_name = xmalloc (nbytes);
12932   char *nametail = lispstpcpy (dpyinfo->x_id_name, Vinvocation_name);
12933   if (STRINGP (system_name))
12934     {
12935       *nametail++ = '@';
12936       lispstpcpy (nametail, system_name);
12937     }
12938 
12939   /* Figure out which modifier bits mean what.  */
12940   x_find_modifier_meanings (dpyinfo);
12941 
12942   /* Get the scroll bar cursor.  */
12943 #ifdef USE_GTK
12944   /* We must create a GTK cursor, it is required for GTK widgets.  */
12945   dpyinfo->xg_cursor = xg_create_default_cursor (dpyinfo->display);
12946 #endif /* USE_GTK */
12947 
12948   dpyinfo->vertical_scroll_bar_cursor
12949     = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
12950 
12951   dpyinfo->horizontal_scroll_bar_cursor
12952     = XCreateFontCursor (dpyinfo->display, XC_sb_h_double_arrow);
12953 
12954   xrdb = x_load_resources (dpyinfo->display, xrm_option,
12955 			   resource_name, EMACS_CLASS);
12956 #ifdef HAVE_XRMSETDATABASE
12957   XrmSetDatabase (dpyinfo->display, xrdb);
12958 #else
12959   dpyinfo->display->db = xrdb;
12960 #endif
12961   /* Put the rdb where we can find it in a way that works on
12962      all versions.  */
12963   dpyinfo->rdb = xrdb;
12964 
12965   dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
12966 				     DefaultScreen (dpyinfo->display));
12967   select_visual (dpyinfo);
12968   dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
12969   dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
12970   dpyinfo->icon_bitmap_id = -1;
12971   dpyinfo->wm_type = X_WMTYPE_UNKNOWN;
12972 
12973   reset_mouse_highlight (&dpyinfo->mouse_highlight);
12974 
12975   /* See if we can construct pixel values from RGB values.  */
12976   if (dpyinfo->visual->class == TrueColor)
12977     {
12978       get_bits_and_offset (dpyinfo->visual->red_mask,
12979                            &dpyinfo->red_bits, &dpyinfo->red_offset);
12980       get_bits_and_offset (dpyinfo->visual->blue_mask,
12981                            &dpyinfo->blue_bits, &dpyinfo->blue_offset);
12982       get_bits_and_offset (dpyinfo->visual->green_mask,
12983                            &dpyinfo->green_bits, &dpyinfo->green_offset);
12984     }
12985 
12986   /* See if a private colormap is requested.  */
12987   if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
12988     {
12989       if (dpyinfo->visual->class == PseudoColor)
12990 	{
12991 	  AUTO_STRING (privateColormap, "privateColormap");
12992 	  AUTO_STRING (PrivateColormap, "PrivateColormap");
12993 	  Lisp_Object value
12994 	    = gui_display_get_resource (dpyinfo, privateColormap,
12995                                         PrivateColormap, Qnil, Qnil);
12996 	  if (STRINGP (value)
12997 	      && (!strcmp (SSDATA (value), "true")
12998 		  || !strcmp (SSDATA (value), "on")))
12999 	    dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
13000 	}
13001     }
13002   else
13003     dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
13004                                      dpyinfo->visual, AllocNone);
13005 
13006 #ifdef HAVE_XDBE
13007   dpyinfo->supports_xdbe = false;
13008   int xdbe_major;
13009   int xdbe_minor;
13010   if (XdbeQueryExtension (dpyinfo->display, &xdbe_major, &xdbe_minor))
13011     dpyinfo->supports_xdbe = true;
13012 #endif
13013 
13014 #if defined USE_CAIRO || defined HAVE_XFT
13015   {
13016     /* If we are using Xft, the following precautions should be made:
13017 
13018        1. Make sure that the Xrender extension is added before the Xft one.
13019        Otherwise, the close-display hook set by Xft is called after the one
13020        for Xrender, and the former tries to re-add the latter.  This results
13021        in inconsistency of internal states and leads to X protocol error when
13022        one reconnects to the same X server (Bug#1696).
13023 
13024        2. Check dpi value in X resources.  It is better we use it as well,
13025        since Xft will use it, as will all Gnome applications.  If our real DPI
13026        is smaller or larger than the one Xft uses, our font will look smaller
13027        or larger than other for other applications, even if it is the same
13028        font name (monospace-10 for example).  */
13029 
13030     int event_base, error_base;
13031     char *v;
13032     double d;
13033 
13034     XRenderQueryExtension (dpyinfo->display, &event_base, &error_base);
13035 
13036     v = XGetDefault (dpyinfo->display, "Xft", "dpi");
13037     if (v != NULL && sscanf (v, "%lf", &d) == 1)
13038       dpyinfo->resy = dpyinfo->resx = d;
13039   }
13040 #endif
13041 
13042   if (dpyinfo->resy < 1)
13043     {
13044       int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
13045       double pixels = DisplayHeight (dpyinfo->display, screen_number);
13046       double mm = DisplayHeightMM (dpyinfo->display, screen_number);
13047       /* Mac OS X 10.3's Xserver sometimes reports 0.0mm.  */
13048       dpyinfo->resy = (mm < 1) ? 100 : pixels * 25.4 / mm;
13049       pixels = DisplayWidth (dpyinfo->display, screen_number);
13050       mm = DisplayWidthMM (dpyinfo->display, screen_number);
13051       /* Mac OS X 10.3's Xserver sometimes reports 0.0mm.  */
13052       dpyinfo->resx = (mm < 1) ? 100 : pixels * 25.4 / mm;
13053     }
13054 
13055   {
13056     static const struct
13057     {
13058       const char *name;
13059       int offset;
13060     } atom_refs[] = {
13061 #define ATOM_REFS_INIT(string, member) \
13062       { string, offsetof (struct x_display_info, member) },
13063       ATOM_REFS_INIT ("WM_PROTOCOLS", Xatom_wm_protocols)
13064       ATOM_REFS_INIT ("WM_TAKE_FOCUS", Xatom_wm_take_focus)
13065       ATOM_REFS_INIT ("WM_SAVE_YOURSELF", Xatom_wm_save_yourself)
13066       ATOM_REFS_INIT ("WM_DELETE_WINDOW", Xatom_wm_delete_window)
13067       ATOM_REFS_INIT ("WM_CHANGE_STATE", Xatom_wm_change_state)
13068       ATOM_REFS_INIT ("WM_CONFIGURE_DENIED", Xatom_wm_configure_denied)
13069       ATOM_REFS_INIT ("WM_MOVED", Xatom_wm_window_moved)
13070       ATOM_REFS_INIT ("WM_CLIENT_LEADER", Xatom_wm_client_leader)
13071       ATOM_REFS_INIT ("Editres", Xatom_editres)
13072       ATOM_REFS_INIT ("CLIPBOARD", Xatom_CLIPBOARD)
13073       ATOM_REFS_INIT ("TIMESTAMP", Xatom_TIMESTAMP)
13074       ATOM_REFS_INIT ("TEXT", Xatom_TEXT)
13075       ATOM_REFS_INIT ("COMPOUND_TEXT", Xatom_COMPOUND_TEXT)
13076       ATOM_REFS_INIT ("UTF8_STRING", Xatom_UTF8_STRING)
13077       ATOM_REFS_INIT ("DELETE", Xatom_DELETE)
13078       ATOM_REFS_INIT ("MULTIPLE", Xatom_MULTIPLE)
13079       ATOM_REFS_INIT ("INCR", Xatom_INCR)
13080       ATOM_REFS_INIT ("_EMACS_TMP_",  Xatom_EMACS_TMP)
13081       ATOM_REFS_INIT ("TARGETS", Xatom_TARGETS)
13082       ATOM_REFS_INIT ("NULL", Xatom_NULL)
13083       ATOM_REFS_INIT ("ATOM", Xatom_ATOM)
13084       ATOM_REFS_INIT ("ATOM_PAIR", Xatom_ATOM_PAIR)
13085       ATOM_REFS_INIT ("CLIPBOARD_MANAGER", Xatom_CLIPBOARD_MANAGER)
13086       ATOM_REFS_INIT ("_XEMBED_INFO", Xatom_XEMBED_INFO)
13087       /* For properties of font.  */
13088       ATOM_REFS_INIT ("PIXEL_SIZE", Xatom_PIXEL_SIZE)
13089       ATOM_REFS_INIT ("AVERAGE_WIDTH", Xatom_AVERAGE_WIDTH)
13090       ATOM_REFS_INIT ("_MULE_BASELINE_OFFSET", Xatom_MULE_BASELINE_OFFSET)
13091       ATOM_REFS_INIT ("_MULE_RELATIVE_COMPOSE", Xatom_MULE_RELATIVE_COMPOSE)
13092       ATOM_REFS_INIT ("_MULE_DEFAULT_ASCENT", Xatom_MULE_DEFAULT_ASCENT)
13093       /* Ghostscript support.  */
13094       ATOM_REFS_INIT ("DONE", Xatom_DONE)
13095       ATOM_REFS_INIT ("PAGE", Xatom_PAGE)
13096       ATOM_REFS_INIT ("SCROLLBAR", Xatom_Scrollbar)
13097       ATOM_REFS_INIT ("HORIZONTAL_SCROLLBAR", Xatom_Horizontal_Scrollbar)
13098       ATOM_REFS_INIT ("_XEMBED", Xatom_XEMBED)
13099       /* EWMH */
13100       ATOM_REFS_INIT ("_NET_WM_STATE", Xatom_net_wm_state)
13101       ATOM_REFS_INIT ("_NET_WM_STATE_FULLSCREEN", Xatom_net_wm_state_fullscreen)
13102       ATOM_REFS_INIT ("_NET_WM_STATE_MAXIMIZED_HORZ",
13103 		      Xatom_net_wm_state_maximized_horz)
13104       ATOM_REFS_INIT ("_NET_WM_STATE_MAXIMIZED_VERT",
13105 		      Xatom_net_wm_state_maximized_vert)
13106       ATOM_REFS_INIT ("_NET_WM_STATE_STICKY", Xatom_net_wm_state_sticky)
13107       ATOM_REFS_INIT ("_NET_WM_STATE_HIDDEN", Xatom_net_wm_state_hidden)
13108       ATOM_REFS_INIT ("_NET_WM_WINDOW_TYPE", Xatom_net_window_type)
13109       ATOM_REFS_INIT ("_NET_WM_WINDOW_TYPE_TOOLTIP",
13110 		      Xatom_net_window_type_tooltip)
13111       ATOM_REFS_INIT ("_NET_WM_ICON_NAME", Xatom_net_wm_icon_name)
13112       ATOM_REFS_INIT ("_NET_WM_NAME", Xatom_net_wm_name)
13113       ATOM_REFS_INIT ("_NET_SUPPORTED",  Xatom_net_supported)
13114       ATOM_REFS_INIT ("_NET_SUPPORTING_WM_CHECK", Xatom_net_supporting_wm_check)
13115       ATOM_REFS_INIT ("_NET_WM_WINDOW_OPACITY", Xatom_net_wm_window_opacity)
13116       ATOM_REFS_INIT ("_NET_ACTIVE_WINDOW", Xatom_net_active_window)
13117       ATOM_REFS_INIT ("_NET_FRAME_EXTENTS", Xatom_net_frame_extents)
13118       ATOM_REFS_INIT ("_NET_CURRENT_DESKTOP", Xatom_net_current_desktop)
13119       ATOM_REFS_INIT ("_NET_WORKAREA", Xatom_net_workarea)
13120       /* Session management */
13121       ATOM_REFS_INIT ("SM_CLIENT_ID", Xatom_SM_CLIENT_ID)
13122       ATOM_REFS_INIT ("_XSETTINGS_SETTINGS", Xatom_xsettings_prop)
13123       ATOM_REFS_INIT ("MANAGER", Xatom_xsettings_mgr)
13124       ATOM_REFS_INIT ("_NET_WM_STATE_SKIP_TASKBAR", Xatom_net_wm_state_skip_taskbar)
13125       ATOM_REFS_INIT ("_NET_WM_STATE_ABOVE", Xatom_net_wm_state_above)
13126       ATOM_REFS_INIT ("_NET_WM_STATE_BELOW", Xatom_net_wm_state_below)
13127     };
13128 
13129     int i;
13130     enum { atom_count = ARRAYELTS (atom_refs) };
13131     /* 1 for _XSETTINGS_SN.  */
13132     enum { total_atom_count = 1 + atom_count };
13133     Atom atoms_return[total_atom_count];
13134     char *atom_names[total_atom_count];
13135     static char const xsettings_fmt[] = "_XSETTINGS_S%d";
13136     char xsettings_atom_name[sizeof xsettings_fmt - 2
13137 			     + INT_STRLEN_BOUND (int)];
13138 
13139     for (i = 0; i < atom_count; i++)
13140       atom_names[i] = (char *) atom_refs[i].name;
13141 
13142     /* Build _XSETTINGS_SN atom name.  */
13143     sprintf (xsettings_atom_name, xsettings_fmt,
13144 	     XScreenNumberOfScreen (dpyinfo->screen));
13145     atom_names[i] = xsettings_atom_name;
13146 
13147     XInternAtoms (dpyinfo->display, atom_names, total_atom_count,
13148                   False, atoms_return);
13149 
13150     for (i = 0; i < atom_count; i++)
13151       *(Atom *) ((char *) dpyinfo + atom_refs[i].offset) = atoms_return[i];
13152 
13153     /* Manually copy last atom.  */
13154     dpyinfo->Xatom_xsettings_sel = atoms_return[i];
13155   }
13156 
13157   dpyinfo->x_dnd_atoms_size = 8;
13158   dpyinfo->x_dnd_atoms = xmalloc (sizeof *dpyinfo->x_dnd_atoms
13159                                   * dpyinfo->x_dnd_atoms_size);
13160   dpyinfo->gray
13161     = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13162 				   gray_bits, gray_width, gray_height,
13163 				   1, 0, 1);
13164 
13165   x_setup_pointer_blanking (dpyinfo);
13166 
13167 #ifdef HAVE_X_I18N
13168   xim_initialize (dpyinfo, resource_name);
13169 #endif
13170 
13171   xsettings_initialize (dpyinfo);
13172 
13173   /* This is only needed for distinguishing keyboard and process input.  */
13174   if (dpyinfo->connection != 0)
13175     add_keyboard_wait_descriptor (dpyinfo->connection);
13176 
13177 #ifdef F_SETOWN
13178   fcntl (dpyinfo->connection, F_SETOWN, getpid ());
13179 #endif /* ! defined (F_SETOWN) */
13180 
13181   if (interrupt_input)
13182     init_sigio (dpyinfo->connection);
13183 
13184 #ifdef USE_LUCID
13185   {
13186     XrmValue d, fr, to;
13187     Font font;
13188 
13189     dpy = dpyinfo->display;
13190     d.addr = (XPointer)&dpy;
13191     d.size = sizeof (Display *);
13192     fr.addr = (char *) XtDefaultFont;
13193     fr.size = sizeof (XtDefaultFont);
13194     to.size = sizeof (Font *);
13195     to.addr = (XPointer)&font;
13196     x_catch_errors (dpy);
13197     if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
13198       emacs_abort ();
13199     if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
13200       XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
13201     /* Do not free XFontStruct returned by the above call to XQueryFont.
13202        This leads to X protocol errors at XtCloseDisplay (Bug#18403).  */
13203     x_uncatch_errors ();
13204   }
13205 #endif
13206 
13207   /* See if we should run in synchronous mode.  This is useful
13208      for debugging X code.  */
13209   {
13210     AUTO_STRING (synchronous, "synchronous");
13211     AUTO_STRING (Synchronous, "Synchronous");
13212     Lisp_Object value = gui_display_get_resource (dpyinfo, synchronous,
13213                                                   Synchronous, Qnil, Qnil);
13214     if (STRINGP (value)
13215 	&& (!strcmp (SSDATA (value), "true")
13216 	    || !strcmp (SSDATA (value), "on")))
13217       XSynchronize (dpyinfo->display, True);
13218   }
13219 
13220   {
13221     AUTO_STRING (useXIM, "useXIM");
13222     AUTO_STRING (UseXIM, "UseXIM");
13223     Lisp_Object value = gui_display_get_resource (dpyinfo, useXIM, UseXIM,
13224                                                   Qnil, Qnil);
13225 #ifdef USE_XIM
13226     if (STRINGP (value)
13227 	&& (!strcmp (SSDATA (value), "false")
13228 	    || !strcmp (SSDATA (value), "off")))
13229       use_xim = false;
13230 #else
13231     if (STRINGP (value)
13232 	&& (!strcmp (SSDATA (value), "true")
13233 	    || !strcmp (SSDATA (value), "on")))
13234       use_xim = true;
13235 #endif
13236   }
13237 
13238 #ifdef HAVE_X_SM
13239   /* Only do this for the very first display in the Emacs session.
13240      Ignore X session management when Emacs was first started on a
13241      tty or started as a daemon.  */
13242   if (terminal->id == 1 && ! IS_DAEMON)
13243     x_session_initialize (dpyinfo);
13244 #endif
13245 
13246 #ifdef USE_CAIRO
13247   x_extension_initialize (dpyinfo);
13248 #endif
13249 
13250   unblock_input ();
13251 
13252   return dpyinfo;
13253 }
13254 
13255 /* Get rid of display DPYINFO, deleting all frames on it,
13256    and without sending any more commands to the X server.  */
13257 
13258 static void
x_delete_display(struct x_display_info * dpyinfo)13259 x_delete_display (struct x_display_info *dpyinfo)
13260 {
13261   struct terminal *t;
13262   struct color_name_cache_entry *color_entry, *next_color_entry;
13263 
13264   /* Close all frames and delete the generic struct terminal for this
13265      X display.  */
13266   for (t = terminal_list; t; t = t->next_terminal)
13267     if (t->type == output_x_window && t->display_info.x == dpyinfo)
13268       {
13269 #ifdef HAVE_X_SM
13270         /* Close X session management when we close its display.  */
13271         if (t->id == 1 && x_session_have_connection ())
13272           x_session_close ();
13273 #endif
13274         delete_terminal (t);
13275         break;
13276       }
13277 
13278   if (next_noop_dpyinfo == dpyinfo)
13279     next_noop_dpyinfo = dpyinfo->next;
13280 
13281   if (x_display_list == dpyinfo)
13282     x_display_list = dpyinfo->next;
13283   else
13284     {
13285       struct x_display_info *tail;
13286 
13287       for (tail = x_display_list; tail; tail = tail->next)
13288 	if (tail->next == dpyinfo)
13289 	  tail->next = tail->next->next;
13290     }
13291 
13292   for (color_entry = dpyinfo->color_names;
13293        color_entry;
13294        color_entry = next_color_entry)
13295     {
13296       next_color_entry = color_entry->next;
13297       xfree (color_entry->name);
13298       xfree (color_entry);
13299     }
13300 
13301   xfree (dpyinfo->x_id_name);
13302   xfree (dpyinfo->x_dnd_atoms);
13303   xfree (dpyinfo->color_cells);
13304   xfree (dpyinfo);
13305 }
13306 
13307 #ifdef USE_X_TOOLKIT
13308 
13309 /* Atimer callback function for TIMER.  Called every 0.1s to process
13310    Xt timeouts, if needed.  We must avoid calling XtAppPending as
13311    much as possible because that function does an implicit XFlush
13312    that slows us down.  */
13313 
13314 static void
x_process_timeouts(struct atimer * timer)13315 x_process_timeouts (struct atimer *timer)
13316 {
13317   block_input ();
13318   x_timeout_atimer_activated_flag = false;
13319   if (toolkit_scroll_bar_interaction || popup_activated ())
13320     {
13321       while (XtAppPending (Xt_app_con) & XtIMTimer)
13322 	XtAppProcessEvent (Xt_app_con, XtIMTimer);
13323       /* Reactivate the atimer for next time.  */
13324       x_activate_timeout_atimer ();
13325     }
13326   unblock_input ();
13327 }
13328 
13329 /* Install an asynchronous timer that processes Xt timeout events
13330    every 0.1s as long as either `toolkit_scroll_bar_interaction' or
13331    `popup_activated_flag' (in xmenu.c) is set.  Make sure to call this
13332    function whenever these variables are set.  This is necessary
13333    because some widget sets use timeouts internally, for example the
13334    LessTif menu bar, or the Xaw3d scroll bar.  When Xt timeouts aren't
13335    processed, these widgets don't behave normally.  */
13336 
13337 void
x_activate_timeout_atimer(void)13338 x_activate_timeout_atimer (void)
13339 {
13340   block_input ();
13341   if (!x_timeout_atimer_activated_flag)
13342     {
13343       struct timespec interval = make_timespec (0, 100 * 1000 * 1000);
13344       start_atimer (ATIMER_RELATIVE, interval, x_process_timeouts, 0);
13345       x_timeout_atimer_activated_flag = true;
13346     }
13347   unblock_input ();
13348 }
13349 
13350 #endif /* USE_X_TOOLKIT */
13351 
13352 
13353 /* Set up use of X before we make the first connection.  */
13354 
13355 extern frame_parm_handler x_frame_parm_handlers[];
13356 
13357 static struct redisplay_interface x_redisplay_interface =
13358   {
13359     x_frame_parm_handlers,
13360     gui_produce_glyphs,
13361     gui_write_glyphs,
13362     gui_insert_glyphs,
13363     gui_clear_end_of_line,
13364     x_scroll_run,
13365     x_after_update_window_line,
13366     NULL, /* update_window_begin */
13367     NULL, /* update_window_end   */
13368     x_flip_and_flush,
13369     gui_clear_window_mouse_face,
13370     gui_get_glyph_overhangs,
13371     gui_fix_overlapping_area,
13372     x_draw_fringe_bitmap,
13373 #ifdef USE_CAIRO
13374     x_cr_define_fringe_bitmap,
13375     x_cr_destroy_fringe_bitmap,
13376 #else
13377     0, /* define_fringe_bitmap */
13378     0, /* destroy_fringe_bitmap */
13379 #endif
13380     x_compute_glyph_string_overhangs,
13381     x_draw_glyph_string,
13382     x_define_frame_cursor,
13383     x_clear_frame_area,
13384     x_clear_under_internal_border,
13385     x_draw_window_cursor,
13386     x_draw_vertical_window_border,
13387     x_draw_window_divider,
13388     x_shift_glyphs_for_insert, /* Never called; see comment in function.  */
13389     x_show_hourglass,
13390     x_hide_hourglass,
13391     x_default_font_parameter
13392   };
13393 
13394 
13395 /* This function is called when the last frame on a display is deleted. */
13396 void
x_delete_terminal(struct terminal * terminal)13397 x_delete_terminal (struct terminal *terminal)
13398 {
13399   struct x_display_info *dpyinfo = terminal->display_info.x;
13400 
13401   /* Protect against recursive calls.  delete_frame in
13402      delete_terminal calls us back when it deletes our last frame.  */
13403   if (!terminal->name)
13404     return;
13405 
13406   block_input ();
13407 #ifdef HAVE_X_I18N
13408   /* We must close our connection to the XIM server before closing the
13409      X display.  */
13410   if (dpyinfo->xim)
13411     xim_close_dpy (dpyinfo);
13412 #endif
13413 
13414   /* Normally, the display is available...  */
13415   if (dpyinfo->display)
13416     {
13417       image_destroy_all_bitmaps (dpyinfo);
13418       XSetCloseDownMode (dpyinfo->display, DestroyAll);
13419 
13420       /* Whether or not XCloseDisplay destroys the associated resource
13421 	 database depends on the version of libX11.  To avoid both
13422 	 crash and memory leak, we dissociate the database from the
13423 	 display and then destroy dpyinfo->rdb ourselves.
13424 
13425 	 Unfortunately, the above strategy does not work in some
13426 	 situations due to a bug in newer versions of libX11: because
13427 	 XrmSetDatabase doesn't clear the flag XlibDisplayDfltRMDB if
13428 	 dpy->db is NULL, XCloseDisplay destroys the associated
13429 	 database whereas it has not been created by XGetDefault
13430 	 (Bug#21974 in freedesktop.org Bugzilla).  As a workaround, we
13431 	 don't destroy the database here in order to avoid the crash
13432 	 in the above situations for now, though that may cause memory
13433 	 leaks in other situations.  */
13434 #if false
13435 #ifdef HAVE_XRMSETDATABASE
13436       XrmSetDatabase (dpyinfo->display, NULL);
13437 #else
13438       dpyinfo->display->db = NULL;
13439 #endif
13440       /* We used to call XrmDestroyDatabase from x_delete_display, but
13441 	 some older versions of libX11 crash if we call it after
13442 	 closing all the displays.  */
13443       XrmDestroyDatabase (dpyinfo->rdb);
13444 #endif
13445 
13446 #ifdef USE_GTK
13447       xg_display_close (dpyinfo->display);
13448 #else
13449 #ifdef USE_X_TOOLKIT
13450       XtCloseDisplay (dpyinfo->display);
13451 #else
13452       XCloseDisplay (dpyinfo->display);
13453 #endif
13454 #endif /* ! USE_GTK */
13455       /* Do not close the connection here because it's already closed
13456 	 by X(t)CloseDisplay (Bug#18403).  */
13457       dpyinfo->display = NULL;
13458     }
13459 
13460   /* ...but if called from x_connection_closed, the display may already
13461      be closed and dpyinfo->display was set to 0 to indicate that.  Since
13462      X server is most likely gone, explicit close is the only reliable
13463      way to continue and avoid Bug#19147.  */
13464   else if (dpyinfo->connection >= 0)
13465     emacs_close (dpyinfo->connection);
13466 
13467   /* No more input on this descriptor.  */
13468   delete_keyboard_wait_descriptor (dpyinfo->connection);
13469   /* Mark as dead. */
13470   dpyinfo->connection = -1;
13471 
13472   x_delete_display (dpyinfo);
13473   unblock_input ();
13474 }
13475 
13476 /* Create a struct terminal, initialize it with the X11 specific
13477    functions and make DISPLAY->TERMINAL point to it.  */
13478 
13479 static struct terminal *
x_create_terminal(struct x_display_info * dpyinfo)13480 x_create_terminal (struct x_display_info *dpyinfo)
13481 {
13482   struct terminal *terminal;
13483 
13484   terminal = create_terminal (output_x_window, &x_redisplay_interface);
13485 
13486   terminal->display_info.x = dpyinfo;
13487   dpyinfo->terminal = terminal;
13488 
13489   /* kboard is initialized in x_term_init. */
13490 
13491   terminal->clear_frame_hook = x_clear_frame;
13492   terminal->ins_del_lines_hook = x_ins_del_lines;
13493   terminal->delete_glyphs_hook = x_delete_glyphs;
13494   terminal->ring_bell_hook = XTring_bell;
13495   terminal->toggle_invisible_pointer_hook = XTtoggle_invisible_pointer;
13496   terminal->update_begin_hook = x_update_begin;
13497   terminal->update_end_hook = x_update_end;
13498   terminal->read_socket_hook = XTread_socket;
13499   terminal->frame_up_to_date_hook = XTframe_up_to_date;
13500   terminal->buffer_flipping_unblocked_hook = XTbuffer_flipping_unblocked_hook;
13501   terminal->defined_color_hook = x_defined_color;
13502   terminal->query_frame_background_color = x_query_frame_background_color;
13503   terminal->query_colors = x_query_colors;
13504   terminal->mouse_position_hook = XTmouse_position;
13505   terminal->get_focus_frame = x_get_focus_frame;
13506   terminal->focus_frame_hook = x_focus_frame;
13507   terminal->frame_rehighlight_hook = XTframe_rehighlight;
13508   terminal->frame_raise_lower_hook = XTframe_raise_lower;
13509   terminal->frame_visible_invisible_hook = x_make_frame_visible_invisible;
13510   terminal->fullscreen_hook = XTfullscreen_hook;
13511   terminal->iconify_frame_hook = x_iconify_frame;
13512   terminal->set_window_size_hook = x_set_window_size;
13513   terminal->set_frame_offset_hook = x_set_offset;
13514   terminal->set_frame_alpha_hook = x_set_frame_alpha;
13515   terminal->set_new_font_hook = x_new_font;
13516   terminal->set_bitmap_icon_hook = x_bitmap_icon;
13517   terminal->implicit_set_name_hook = x_implicitly_set_name;
13518   terminal->menu_show_hook = x_menu_show;
13519 #ifdef HAVE_EXT_MENU_BAR
13520   terminal->activate_menubar_hook = x_activate_menubar;
13521 #endif
13522 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
13523   terminal->popup_dialog_hook = xw_popup_dialog;
13524 #endif
13525   terminal->change_tab_bar_height_hook = x_change_tab_bar_height;
13526 #ifndef HAVE_EXT_TOOL_BAR
13527   terminal->change_tool_bar_height_hook = x_change_tool_bar_height;
13528 #endif
13529   terminal->set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
13530   terminal->set_horizontal_scroll_bar_hook = XTset_horizontal_scroll_bar;
13531   terminal->set_scroll_bar_default_width_hook = x_set_scroll_bar_default_width;
13532   terminal->set_scroll_bar_default_height_hook = x_set_scroll_bar_default_height;
13533   terminal->condemn_scroll_bars_hook = XTcondemn_scroll_bars;
13534   terminal->redeem_scroll_bar_hook = XTredeem_scroll_bar;
13535   terminal->judge_scroll_bars_hook = XTjudge_scroll_bars;
13536   terminal->get_string_resource_hook = x_get_string_resource;
13537   terminal->free_pixmap = x_free_pixmap;
13538   terminal->delete_frame_hook = x_destroy_window;
13539   terminal->delete_terminal_hook = x_delete_terminal;
13540   /* Other hooks are NULL by default.  */
13541 
13542   return terminal;
13543 }
13544 
13545 static void
x_initialize(void)13546 x_initialize (void)
13547 {
13548   baud_rate = 19200;
13549 
13550   x_noop_count = 0;
13551   any_help_event_p = false;
13552   ignore_next_mouse_click_timeout = 0;
13553 
13554 #ifdef USE_GTK
13555   current_count = -1;
13556 #endif
13557 
13558   /* Try to use interrupt input; if we can't, then start polling.  */
13559   Fset_input_interrupt_mode (Qt);
13560 
13561 #if THREADS_ENABLED
13562   /* This must be called before any other Xlib routines.  */
13563   if (XInitThreads () == 0)
13564     fputs ("Warning: An error occurred initializing X11 thread support!\n",
13565 	   stderr);
13566 #endif
13567 
13568 #ifdef USE_X_TOOLKIT
13569   XtToolkitInitialize ();
13570 
13571   Xt_app_con = XtCreateApplicationContext ();
13572 
13573   /* Register a converter from strings to pixels, which uses
13574      Emacs' color allocation infrastructure.  */
13575   XtAppSetTypeConverter (Xt_app_con,
13576 			 XtRString, XtRPixel, cvt_string_to_pixel,
13577 			 cvt_string_to_pixel_args,
13578 			 XtNumber (cvt_string_to_pixel_args),
13579 			 XtCacheByDisplay, cvt_pixel_dtor);
13580 
13581   XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
13582 #endif
13583 
13584 #ifdef USE_TOOLKIT_SCROLL_BARS
13585 #ifndef USE_GTK
13586   xaw3d_arrow_scroll = False;
13587   xaw3d_pick_top = True;
13588 #endif
13589 #endif
13590 
13591 #ifdef USE_CAIRO
13592   gui_init_fringe (&x_redisplay_interface);
13593 #endif
13594 
13595   /* Note that there is no real way portable across R3/R4 to get the
13596      original error handler.  */
13597   XSetErrorHandler (x_error_handler);
13598   XSetIOErrorHandler (x_io_error_quitter);
13599 }
13600 
13601 #ifdef USE_GTK
13602 void
init_xterm(void)13603 init_xterm (void)
13604 {
13605   /* Emacs can handle only core input events, so make sure
13606      Gtk doesn't use Xinput or Xinput2 extensions.  */
13607   xputenv ("GDK_CORE_DEVICE_EVENTS=1");
13608 }
13609 #endif
13610 
13611 void
syms_of_xterm(void)13612 syms_of_xterm (void)
13613 {
13614   x_error_message = NULL;
13615   PDUMPER_IGNORE (x_error_message);
13616 
13617   DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms");
13618   DEFSYM (Qlatin_1, "latin-1");
13619 
13620 #ifdef USE_GTK
13621   xg_default_icon_file = build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg");
13622   staticpro (&xg_default_icon_file);
13623 
13624   DEFSYM (Qx_gtk_map_stock, "x-gtk-map-stock");
13625 #endif
13626 
13627   DEFVAR_BOOL ("x-use-underline-position-properties",
13628 	       x_use_underline_position_properties,
13629      doc: /* Non-nil means make use of UNDERLINE_POSITION font properties.
13630 A value of nil means ignore them.  If you encounter fonts with bogus
13631 UNDERLINE_POSITION font properties, set this to nil.  You can also use
13632 `underline-minimum-offset' to override the font's UNDERLINE_POSITION for
13633 small font display sizes.  */);
13634   x_use_underline_position_properties = true;
13635   DEFSYM (Qx_use_underline_position_properties,
13636 	  "x-use-underline-position-properties");
13637 
13638   DEFVAR_BOOL ("x-underline-at-descent-line",
13639 	       x_underline_at_descent_line,
13640      doc: /* Non-nil means to draw the underline at the same place as the descent line.
13641 (If `line-spacing' is in effect, that moves the underline lower by
13642 that many pixels.)
13643 A value of nil means to draw the underline according to the value of the
13644 variable `x-use-underline-position-properties', which is usually at the
13645 baseline level.  The default value is nil.  */);
13646   x_underline_at_descent_line = false;
13647   DEFSYM (Qx_underline_at_descent_line, "x-underline-at-descent-line");
13648 
13649   DEFVAR_BOOL ("x-mouse-click-focus-ignore-position",
13650 	       x_mouse_click_focus_ignore_position,
13651     doc: /* Non-nil means that a mouse click to focus a frame does not move point.
13652 This variable is used only when the window manager requires that you
13653 click on a frame to select it (give it focus).  In that case, a value
13654 of nil, means that the selected window and cursor position changes to
13655 reflect the mouse click position, while a non-nil value means that the
13656 selected window or cursor position is preserved.  */);
13657   x_mouse_click_focus_ignore_position = false;
13658 
13659   DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
13660     doc: /* Which toolkit scroll bars Emacs uses, if any.
13661 A value of nil means Emacs doesn't use toolkit scroll bars.
13662 With the X Window system, the value is a symbol describing the
13663 X toolkit.  Possible values are: gtk, motif, xaw, or xaw3d.
13664 With MS Windows or Nextstep, the value is t.  */);
13665 #ifdef USE_TOOLKIT_SCROLL_BARS
13666 #ifdef USE_MOTIF
13667   Vx_toolkit_scroll_bars = intern_c_string ("motif");
13668 #elif defined HAVE_XAW3D
13669   Vx_toolkit_scroll_bars = intern_c_string ("xaw3d");
13670 #elif USE_GTK
13671   Vx_toolkit_scroll_bars = intern_c_string ("gtk");
13672 #else
13673   Vx_toolkit_scroll_bars = intern_c_string ("xaw");
13674 #endif
13675 #else
13676   Vx_toolkit_scroll_bars = Qnil;
13677 #endif
13678 
13679   DEFSYM (Qmodifier_value, "modifier-value");
13680   DEFSYM (Qctrl, "ctrl");
13681   Fput (Qctrl, Qmodifier_value, make_fixnum (ctrl_modifier));
13682   DEFSYM (Qalt, "alt");
13683   Fput (Qalt, Qmodifier_value, make_fixnum (alt_modifier));
13684   DEFSYM (Qhyper, "hyper");
13685   Fput (Qhyper, Qmodifier_value, make_fixnum (hyper_modifier));
13686   DEFSYM (Qmeta, "meta");
13687   Fput (Qmeta, Qmodifier_value, make_fixnum (meta_modifier));
13688   DEFSYM (Qsuper, "super");
13689   Fput (Qsuper, Qmodifier_value, make_fixnum (super_modifier));
13690 
13691   DEFVAR_LISP ("x-ctrl-keysym", Vx_ctrl_keysym,
13692     doc: /* Which keys Emacs uses for the ctrl modifier.
13693 This should be one of the symbols `ctrl', `alt', `hyper', `meta',
13694 `super'.  For example, `ctrl' means use the Ctrl_L and Ctrl_R keysyms.
13695 The default is nil, which is the same as `ctrl'.  */);
13696   Vx_ctrl_keysym = Qnil;
13697 
13698   DEFVAR_LISP ("x-alt-keysym", Vx_alt_keysym,
13699     doc: /* Which keys Emacs uses for the alt modifier.
13700 This should be one of the symbols `ctrl', `alt', `hyper', `meta',
13701 `super'.  For example, `alt' means use the Alt_L and Alt_R keysyms.
13702 The default is nil, which is the same as `alt'.  */);
13703   Vx_alt_keysym = Qnil;
13704 
13705   DEFVAR_LISP ("x-hyper-keysym", Vx_hyper_keysym,
13706     doc: /* Which keys Emacs uses for the hyper modifier.
13707 This should be one of the symbols `ctrl', `alt', `hyper', `meta',
13708 `super'.  For example, `hyper' means use the Hyper_L and Hyper_R
13709 keysyms.  The default is nil, which is the same as `hyper'.  */);
13710   Vx_hyper_keysym = Qnil;
13711 
13712   DEFVAR_LISP ("x-meta-keysym", Vx_meta_keysym,
13713     doc: /* Which keys Emacs uses for the meta modifier.
13714 This should be one of the symbols `ctrl', `alt', `hyper', `meta',
13715 `super'.  For example, `meta' means use the Meta_L and Meta_R keysyms.
13716 The default is nil, which is the same as `meta'.  */);
13717   Vx_meta_keysym = Qnil;
13718 
13719   DEFVAR_LISP ("x-super-keysym", Vx_super_keysym,
13720     doc: /* Which keys Emacs uses for the super modifier.
13721 This should be one of the symbols `ctrl', `alt', `hyper', `meta',
13722 `super'.  For example, `super' means use the Super_L and Super_R
13723 keysyms.  The default is nil, which is the same as `super'.  */);
13724   Vx_super_keysym = Qnil;
13725 
13726   DEFVAR_LISP ("x-wait-for-event-timeout", Vx_wait_for_event_timeout,
13727     doc: /* How long to wait for X events.
13728 
13729 Emacs will wait up to this many seconds to receive X events after
13730 making changes which affect the state of the graphical interface.
13731 Under some window managers this can take an indefinite amount of time,
13732 so it is important to limit the wait.
13733 
13734 If set to a non-float value, there will be no wait at all.  */);
13735   Vx_wait_for_event_timeout = make_float (0.1);
13736 
13737   DEFVAR_LISP ("x-keysym-table", Vx_keysym_table,
13738     doc: /* Hash table of character codes indexed by X keysym codes.  */);
13739   Vx_keysym_table = make_hash_table (hashtest_eql, 900,
13740 				     DEFAULT_REHASH_SIZE,
13741 				     DEFAULT_REHASH_THRESHOLD,
13742 				     Qnil, false);
13743 
13744   DEFVAR_BOOL ("x-frame-normalize-before-maximize",
13745 	       x_frame_normalize_before_maximize,
13746     doc: /* Non-nil means normalize frame before maximizing.
13747 If this variable is t, Emacs first asks the window manager to give the
13748 frame its normal size, and only then the final state, whenever changing
13749 from a full-height, full-width or full-both state to the maximized one
13750 or when changing from the maximized to the full-height or full-width
13751 state.
13752 
13753 Set this variable only if your window manager cannot handle the
13754 transition between the various maximization states.  */);
13755   x_frame_normalize_before_maximize = false;
13756 
13757   DEFVAR_BOOL ("x-gtk-use-window-move", x_gtk_use_window_move,
13758     doc: /* Non-nil means rely on gtk_window_move to set frame positions.
13759 If this variable is t (the default), the GTK build uses the function
13760 gtk_window_move to set or store frame positions and disables some time
13761 consuming frame position adjustments.  In newer versions of GTK, Emacs
13762 always uses gtk_window_move and ignores the value of this variable.  */);
13763   x_gtk_use_window_move = true;
13764 }
13765