1 /* Functions for the X Window System.
2 
3 Copyright (C) 1989, 1992-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 #include <config.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <math.h>
24 #include <unistd.h>
25 
26 #include "lisp.h"
27 #include "xterm.h"
28 #include "frame.h"
29 #include "window.h"
30 #include "buffer.h"
31 #include "dispextern.h"
32 #include "keyboard.h"
33 #include "blockinput.h"
34 #include "charset.h"
35 #include "coding.h"
36 #include "termhooks.h"
37 #include "font.h"
38 
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 
42 #include "bitmaps/gray.xbm"
43 #include "xsettings.h"
44 
45 #ifdef HAVE_XRANDR
46 #include <X11/extensions/Xrandr.h>
47 #endif
48 #ifdef HAVE_XINERAMA
49 #include <X11/extensions/Xinerama.h>
50 #endif
51 
52 #ifdef USE_GTK
53 #include "gtkutil.h"
54 #endif
55 
56 #ifdef HAVE_XDBE
57 #include <X11/extensions/Xdbe.h>
58 #endif
59 
60 #ifdef USE_X_TOOLKIT
61 #include <X11/Shell.h>
62 
63 #ifndef USE_MOTIF
64 #ifdef HAVE_XAW3D
65 #include <X11/Xaw3d/Paned.h>
66 #include <X11/Xaw3d/Label.h>
67 #else /* !HAVE_XAW3D */
68 #include <X11/Xaw/Paned.h>
69 #include <X11/Xaw/Label.h>
70 #endif /* HAVE_XAW3D */
71 #endif /* USE_MOTIF */
72 
73 #ifdef USG
74 #undef USG	/* ####KLUDGE for Solaris 2.2 and up */
75 #include <X11/Xos.h>
76 #define USG
77 #ifdef USG /* Pacify gcc -Wunused-macros.  */
78 #endif
79 #else
80 #include <X11/Xos.h>
81 #endif
82 
83 #include "widget.h"
84 
85 #include "../lwlib/lwlib.h"
86 
87 #ifdef USE_MOTIF
88 #include <Xm/Xm.h>
89 #include <Xm/DialogS.h>
90 #include <Xm/FileSB.h>
91 #include <Xm/List.h>
92 #include <Xm/TextF.h>
93 #include <Xm/MwmUtil.h>
94 #endif
95 
96 #ifdef USE_LUCID
97 #include "../lwlib/xlwmenu.h"
98 #endif
99 
100 /* Unique id counter for widgets created by the Lucid Widget Library.  */
101 
102 extern LWLIB_ID widget_id_tick;
103 
104 #ifdef USE_MOTIF
105 
106 #endif /* USE_MOTIF */
107 
108 #endif /* USE_X_TOOLKIT */
109 
110 #ifdef USE_GTK
111 
112 #endif /* USE_GTK */
113 
114 #define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
115 
116 static ptrdiff_t image_cache_refcount;
117 #ifdef GLYPH_DEBUG
118 static int dpyinfo_refcount;
119 #endif
120 
121 #ifndef USE_MOTIF
122 #ifndef USE_GTK
123 /** #define MWM_HINTS_FUNCTIONS     (1L << 0) **/
124 #define MWM_HINTS_DECORATIONS   (1L << 1)
125 /** #define MWM_HINTS_INPUT_MODE    (1L << 2) **/
126 /** #define MWM_HINTS_STATUS        (1L << 3) **/
127 
128 #define MWM_DECOR_ALL           (1L << 0)
129 /** #define MWM_DECOR_BORDER        (1L << 1) **/
130 /** #define MWM_DECOR_RESIZEH       (1L << 2) **/
131 /** #define MWM_DECOR_TITLE         (1L << 3) **/
132 /** #define MWM_DECOR_MENU          (1L << 4) **/
133 /** #define MWM_DECOR_MINIMIZE      (1L << 5) **/
134 /** #define MWM_DECOR_MAXIMIZE      (1L << 6) **/
135 
136 /** #define _XA_MOTIF_WM_HINTS "_MOTIF_WM_HINTS" **/
137 
138 typedef struct {
139     unsigned long flags;
140     unsigned long functions;
141     unsigned long decorations;
142     long input_mode;
143     unsigned long status;
144 } PropMotifWmHints;
145 
146 #define PROP_MOTIF_WM_HINTS_ELEMENTS 5
147 #endif /* NOT USE_GTK */
148 #endif /* NOT USE_MOTIF */
149 
150 static struct x_display_info *x_display_info_for_name (Lisp_Object);
151 static void set_up_x_back_buffer (struct frame *f);
152 
153 /* Let the user specify an X display with a Lisp object.
154    OBJECT may be nil, a frame or a terminal object.
155    nil stands for the selected frame--or, if that is not an X frame,
156    the first X display on the list.  */
157 
158 struct x_display_info *
check_x_display_info(Lisp_Object object)159 check_x_display_info (Lisp_Object object)
160 {
161   struct x_display_info *dpyinfo = NULL;
162 
163   if (NILP (object))
164     {
165       struct frame *sf = XFRAME (selected_frame);
166 
167       if (FRAME_X_P (sf) && FRAME_LIVE_P (sf))
168 	dpyinfo = FRAME_DISPLAY_INFO (sf);
169       else if (x_display_list != 0)
170 	dpyinfo = x_display_list;
171       else
172 	error ("X windows are not in use or not initialized");
173     }
174   else if (TERMINALP (object))
175     {
176       struct terminal *t = decode_live_terminal (object);
177 
178       if (t->type != output_x_window)
179         error ("Terminal %d is not an X display", t->id);
180 
181       dpyinfo = t->display_info.x;
182     }
183   else if (STRINGP (object))
184     dpyinfo = x_display_info_for_name (object);
185   else
186     {
187       struct frame *f = decode_window_system_frame (object);
188       dpyinfo = FRAME_DISPLAY_INFO (f);
189     }
190 
191   return dpyinfo;
192 }
193 
194 /* Return the screen positions and offsets of frame F.
195    Store the offsets between FRAME_OUTER_WINDOW and the containing
196    window manager window into LEFT_OFFSET_X, RIGHT_OFFSET_X,
197    TOP_OFFSET_Y and BOTTOM_OFFSET_Y.
198    Store the offsets between FRAME_X_WINDOW and the containing
199    window manager window into X_PIXELS_DIFF and Y_PIXELS_DIFF.
200    Store the screen positions of frame F into XPTR and YPTR.
201    These are the positions of the containing window manager window,
202    not Emacs's own window.  */
203 void
x_real_pos_and_offsets(struct frame * f,int * left_offset_x,int * right_offset_x,int * top_offset_y,int * bottom_offset_y,int * x_pixels_diff,int * y_pixels_diff,int * xptr,int * yptr,int * outer_border)204 x_real_pos_and_offsets (struct frame *f,
205                         int *left_offset_x,
206                         int *right_offset_x,
207                         int *top_offset_y,
208                         int *bottom_offset_y,
209                         int *x_pixels_diff,
210                         int *y_pixels_diff,
211                         int *xptr,
212                         int *yptr,
213                         int *outer_border)
214 {
215   int win_x = 0, win_y = 0, outer_x = 0, outer_y = 0;
216   int real_x = 0, real_y = 0;
217   bool had_errors = false;
218   struct frame *parent_frame = FRAME_PARENT_FRAME (f);
219   Window win = (parent_frame
220 		? FRAME_X_WINDOW (parent_frame)
221 		: f->output_data.x->parent_desc);
222   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
223   long max_len = 400;
224   Atom target_type = XA_CARDINAL;
225   unsigned int ow = 0, oh = 0;
226   unsigned int fw = 0, fh = 0;
227   unsigned int bw = 0;
228   /* We resort to XCB if possible because there are several X calls
229      here which require responses from the server but do not have data
230      dependencies between them.  Using XCB lets us pipeline requests,
231      whereas with Xlib we must wait for each answer before sending the
232      next request.
233 
234      For a non-local display, the round-trip time could be a few tens
235      of milliseconds, depending on the network distance.  It doesn't
236      take a lot of those to add up to a noticeable hesitation in
237      responding to user actions.  */
238 #ifdef USE_XCB
239   xcb_connection_t *xcb_conn = dpyinfo->xcb_connection;
240   xcb_get_property_cookie_t prop_cookie;
241   xcb_get_geometry_cookie_t outer_geom_cookie;
242   bool sent_requests = false;
243 #else
244   Atom actual_type;
245   unsigned long actual_size, bytes_remaining;
246   int rc, actual_format;
247   Display *dpy = FRAME_X_DISPLAY (f);
248   unsigned char *tmp_data = NULL;
249 #endif
250 
251   if (x_pixels_diff) *x_pixels_diff = 0;
252   if (y_pixels_diff) *y_pixels_diff = 0;
253   if (left_offset_x) *left_offset_x = 0;
254   if (top_offset_y) *top_offset_y = 0;
255   if (right_offset_x) *right_offset_x = 0;
256   if (bottom_offset_y) *bottom_offset_y = 0;
257   if (xptr) *xptr = 0;
258   if (yptr) *yptr = 0;
259   if (outer_border) *outer_border = 0;
260 
261   if (win == dpyinfo->root_window)
262     win = FRAME_OUTER_WINDOW (f);
263 
264   block_input ();
265 
266 #ifndef USE_XCB
267   /* If we're using XCB, all errors are checked for on each call.  */
268   x_catch_errors (dpy);
269 #endif
270 
271   /* This loop traverses up the containment tree until we hit the root
272      window.  Window managers may intersect many windows between our window
273      and the root window.  The window we find just before the root window
274      should be the outer WM window. */
275   for (;;)
276     {
277       Window wm_window UNINIT, rootw UNINIT;
278 
279 #ifdef USE_XCB
280       xcb_query_tree_cookie_t query_tree_cookie;
281       xcb_query_tree_reply_t *query_tree;
282 
283       query_tree_cookie = xcb_query_tree (xcb_conn, win);
284       query_tree = xcb_query_tree_reply (xcb_conn, query_tree_cookie, NULL);
285       if (query_tree == NULL)
286 	had_errors = true;
287       else
288 	{
289 	  wm_window = query_tree->parent;
290 	  rootw = query_tree->root;
291 	  free (query_tree);
292 	}
293 #else
294       Window *tmp_children;
295       unsigned int tmp_nchildren;
296       int success;
297 
298       success = XQueryTree (dpy, win, &rootw,
299 			    &wm_window, &tmp_children, &tmp_nchildren);
300 
301       had_errors = x_had_errors_p (dpy);
302 
303       /* Don't free tmp_children if XQueryTree failed.  */
304       if (! success)
305 	break;
306 
307       XFree (tmp_children);
308 #endif
309 
310       if (had_errors || wm_window == rootw)
311         break;
312 
313       win = wm_window;
314     }
315 
316   if (! had_errors)
317     {
318 #ifdef USE_XCB
319       xcb_get_geometry_cookie_t geom_cookie;
320       xcb_translate_coordinates_cookie_t trans_cookie;
321       xcb_translate_coordinates_cookie_t outer_trans_cookie;
322 
323       xcb_translate_coordinates_reply_t *trans;
324       xcb_get_geometry_reply_t *geom;
325 #else
326       Window child, rootw;
327       unsigned int ign;
328 #endif
329 
330 #ifdef USE_XCB
331       /* Fire off the requests that don't have data dependencies.
332 
333          Once we've done this, we must collect the results for each
334          one before returning, even if other errors are detected,
335          making the other responses moot.  */
336       geom_cookie = xcb_get_geometry (xcb_conn, win);
337 
338       trans_cookie =
339         xcb_translate_coordinates (xcb_conn,
340                                    /* From-window, to-window.  */
341                                    FRAME_DISPLAY_INFO (f)->root_window,
342                                    FRAME_X_WINDOW (f),
343 
344                                    /* From-position.  */
345                                    0, 0);
346       if (FRAME_X_WINDOW (f) != FRAME_OUTER_WINDOW (f))
347         outer_trans_cookie =
348           xcb_translate_coordinates (xcb_conn,
349                                      /* From-window, to-window.  */
350                                      FRAME_DISPLAY_INFO (f)->root_window,
351                                      FRAME_OUTER_WINDOW (f),
352 
353                                      /* From-position.  */
354                                      0, 0);
355       if (right_offset_x || bottom_offset_y)
356 	outer_geom_cookie = xcb_get_geometry (xcb_conn,
357 					      FRAME_OUTER_WINDOW (f));
358 
359       if (!parent_frame
360 	  && dpyinfo->root_window == f->output_data.x->parent_desc)
361 	/* Try _NET_FRAME_EXTENTS if our parent is the root window.  */
362 	prop_cookie = xcb_get_property (xcb_conn, 0, win,
363 					dpyinfo->Xatom_net_frame_extents,
364 					target_type, 0, max_len);
365 
366       sent_requests = true;
367 #endif
368 
369       /* Get the real coordinates for the WM window upper left corner */
370 #ifdef USE_XCB
371       geom = xcb_get_geometry_reply (xcb_conn, geom_cookie, NULL);
372       if (geom)
373 	{
374 	  real_x = geom->x;
375 	  real_y = geom->y;
376 	  ow = geom->width;
377 	  oh = geom->height;
378 	  bw = geom->border_width;
379 	  free (geom);
380 	}
381       else
382 	had_errors = true;
383 #else
384       XGetGeometry (dpy, win,
385 		    &rootw, &real_x, &real_y, &ow, &oh, &bw, &ign);
386 #endif
387 
388       /* Translate real coordinates to coordinates relative to our
389          window.  For our window, the upper left corner is 0, 0.
390          Since the upper left corner of the WM window is outside
391          our window, win_x and win_y will be negative:
392 
393          ------------------          ---> x
394          |      title                |
395          | -----------------         v y
396          | |  our window
397 
398          Since we don't care about the child window corresponding to
399          the actual coordinates, we can send zero to get the offsets
400          and compute the resulting coordinates below.  This reduces
401          the data dependencies between calls and lets us pipeline the
402          requests better in the XCB case.  */
403 #ifdef USE_XCB
404       trans = xcb_translate_coordinates_reply (xcb_conn, trans_cookie, NULL);
405       if (trans)
406 	{
407 	  win_x = trans->dst_x;
408 	  win_y = trans->dst_y;
409 	  free (trans);
410 	}
411       else
412 	had_errors = true;
413 #else
414       XTranslateCoordinates (dpy,
415 
416 			     /* From-window, to-window.  */
417 			     FRAME_DISPLAY_INFO (f)->root_window,
418                              FRAME_X_WINDOW (f),
419 
420 			     /* From-position, to-position.  */
421                              0, 0, &win_x, &win_y,
422 
423 			     /* Child of win.  */
424 			     &child);
425 #endif
426 
427       win_x += real_x;
428       win_y += real_y;
429 
430       if (FRAME_X_WINDOW (f) == FRAME_OUTER_WINDOW (f))
431 	{
432           outer_x = win_x;
433           outer_y = win_y;
434 	}
435       else
436         {
437 #ifdef USE_XCB
438           xcb_translate_coordinates_reply_t *outer_trans;
439 
440           outer_trans = xcb_translate_coordinates_reply (xcb_conn,
441                                                          outer_trans_cookie,
442                                                          NULL);
443           if (outer_trans)
444             {
445               outer_x = outer_trans->dst_x;
446               outer_y = outer_trans->dst_y;
447               free (outer_trans);
448             }
449           else
450 	    had_errors = true;
451 #else
452           XTranslateCoordinates (dpy,
453 
454                                  /* From-window, to-window.  */
455                                  FRAME_DISPLAY_INFO (f)->root_window,
456                                  FRAME_OUTER_WINDOW (f),
457 
458                                  /* From-position, to-position.  */
459                                  0, 0, &outer_x, &outer_y,
460 
461                                  /* Child of win.  */
462                                  &child);
463 #endif
464 
465 	  outer_x += real_x;
466 	  outer_y += real_y;
467 	}
468 
469 #ifndef USE_XCB
470       had_errors = x_had_errors_p (dpy);
471 #endif
472     }
473 
474   if (!parent_frame && dpyinfo->root_window == f->output_data.x->parent_desc)
475     {
476       /* Try _NET_FRAME_EXTENTS if our parent is the root window.  */
477 #ifdef USE_XCB
478       /* Make sure we didn't get an X error early and skip sending the
479          request.  */
480       if (sent_requests)
481         {
482           xcb_get_property_reply_t *prop;
483 
484           prop = xcb_get_property_reply (xcb_conn, prop_cookie, NULL);
485           if (prop)
486             {
487               if (prop->type == target_type
488                   && prop->format == 32
489                   && (xcb_get_property_value_length (prop)
490 		      == 4 * sizeof (int32_t)))
491                 {
492                   int32_t *fe = xcb_get_property_value (prop);
493 
494                   outer_x = -fe[0];
495                   outer_y = -fe[2];
496                   real_x -= fe[0];
497                   real_y -= fe[2];
498                 }
499               free (prop);
500             }
501           /* Xlib version doesn't set had_errors here.  Intentional or bug?  */
502         }
503 #else
504       rc = XGetWindowProperty (dpy, win, dpyinfo->Xatom_net_frame_extents,
505                                0, max_len, False, target_type,
506                                &actual_type, &actual_format, &actual_size,
507                                &bytes_remaining, &tmp_data);
508 
509       if (rc == Success && actual_type == target_type && !x_had_errors_p (dpy)
510           && actual_size == 4 && actual_format == 32)
511         {
512           long *fe = (long *)tmp_data;
513 
514           outer_x = -fe[0];
515           outer_y = -fe[2];
516           real_x -= fe[0];
517           real_y -= fe[2];
518         }
519 
520       if (tmp_data) XFree (tmp_data);
521 #endif
522     }
523 
524   if (right_offset_x || bottom_offset_y)
525     {
526 #ifdef USE_XCB
527       /* Make sure we didn't get an X error early and skip sending the
528          request.  */
529       if (sent_requests)
530         {
531           xcb_get_geometry_reply_t *outer_geom;
532 
533           outer_geom = xcb_get_geometry_reply (xcb_conn, outer_geom_cookie,
534                                                NULL);
535           if (outer_geom)
536             {
537               fw = outer_geom->width;
538               fh = outer_geom->height;
539               free (outer_geom);
540             }
541           else
542 	    had_errors = true;
543         }
544 #else
545       int xy_ign;
546       unsigned int ign;
547       Window rootw;
548 
549       XGetGeometry (dpy, FRAME_OUTER_WINDOW (f),
550 		    &rootw, &xy_ign, &xy_ign, &fw, &fh, &ign, &ign);
551 #endif
552     }
553 
554 #ifndef USE_XCB
555   x_uncatch_errors ();
556 #endif
557 
558   unblock_input ();
559 
560   if (had_errors) return;
561 
562   if (x_pixels_diff) *x_pixels_diff = -win_x;
563   if (y_pixels_diff) *y_pixels_diff = -win_y;
564 
565   if (left_offset_x) *left_offset_x = -outer_x;
566   if (top_offset_y) *top_offset_y = -outer_y;
567 
568   if (xptr) *xptr = real_x;
569   if (yptr) *yptr = real_y;
570 
571   if (outer_border) *outer_border = bw;
572 
573   if (right_offset_x) *right_offset_x = ow - fw + outer_x;
574   if (bottom_offset_y) *bottom_offset_y = oh - fh + outer_y;
575 }
576 
577 /* Store the screen positions of frame F into XPTR and YPTR.
578    These are the positions of the containing window manager window,
579    not Emacs's own window.  */
580 
581 void
x_real_positions(struct frame * f,int * xptr,int * yptr)582 x_real_positions (struct frame *f, int *xptr, int *yptr)
583 {
584   x_real_pos_and_offsets (f, NULL, NULL, NULL, NULL, NULL, NULL, xptr, yptr,
585                           NULL);
586 }
587 
588 
589 /* Get the mouse position in frame relative coordinates.  */
590 
591 void
x_relative_mouse_position(struct frame * f,int * x,int * y)592 x_relative_mouse_position (struct frame *f, int *x, int *y)
593 {
594   Window root, dummy_window;
595   int dummy;
596 
597   eassert (FRAME_X_P (f));
598 
599   block_input ();
600 
601   XQueryPointer (FRAME_X_DISPLAY (f),
602                  DefaultRootWindow (FRAME_X_DISPLAY (f)),
603 
604                  /* The root window which contains the pointer.  */
605                  &root,
606 
607                  /* Window pointer is on, not used  */
608                  &dummy_window,
609 
610                  /* The position on that root window.  */
611                  x, y,
612 
613                  /* x/y in dummy_window coordinates, not used.  */
614                  &dummy, &dummy,
615 
616                  /* Modifier keys and pointer buttons, about which
617                     we don't care.  */
618                  (unsigned int *) &dummy);
619 
620   XTranslateCoordinates (FRAME_X_DISPLAY (f),
621 
622                          /* From-window, to-window.  */
623                          FRAME_DISPLAY_INFO (f)->root_window,
624                          FRAME_X_WINDOW (f),
625 
626                          /* From-position, to-position.  */
627                          *x, *y, x, y,
628 
629                          /* Child of win.  */
630                          &dummy_window);
631 
632   unblock_input ();
633 }
634 
635 /* Gamma-correct COLOR on frame F.  */
636 
637 void
gamma_correct(struct frame * f,XColor * color)638 gamma_correct (struct frame *f, XColor *color)
639 {
640   if (f->gamma)
641     {
642       color->red = pow (color->red / 65535.0, f->gamma) * 65535.0 + 0.5;
643       color->green = pow (color->green / 65535.0, f->gamma) * 65535.0 + 0.5;
644       color->blue = pow (color->blue / 65535.0, f->gamma) * 65535.0 + 0.5;
645     }
646 }
647 
648 
649 /* Decide if color named COLOR_NAME is valid for use on frame F.  If
650    so, return the RGB values in COLOR.  If ALLOC_P,
651    allocate the color.  Value is false if COLOR_NAME is invalid, or
652    no color could be allocated.  */
653 
654 bool
x_defined_color(struct frame * f,const char * color_name,Emacs_Color * color,bool alloc_p,bool _makeIndex)655 x_defined_color (struct frame *f, const char *color_name,
656 		 Emacs_Color *color, bool alloc_p, bool _makeIndex)
657 {
658   bool success_p = false;
659   Colormap cmap = FRAME_X_COLORMAP (f);
660 
661   block_input ();
662 #ifdef USE_GTK
663   success_p = xg_check_special_colors (f, color_name, color);
664 #endif
665   if (!success_p)
666     success_p = x_parse_color (f, color_name, color) != 0;
667   if (success_p && alloc_p)
668     success_p = x_alloc_nearest_color (f, cmap, color);
669   unblock_input ();
670 
671   return success_p;
672 }
673 
674 
675 /* Return the pixel color value for color COLOR_NAME on frame F.  If F
676    is a monochrome frame, return MONO_COLOR regardless of what ARG says.
677    Signal an error if color can't be allocated.  */
678 
679 static int
x_decode_color(struct frame * f,Lisp_Object color_name,int mono_color)680 x_decode_color (struct frame *f, Lisp_Object color_name, int mono_color)
681 {
682   XColor cdef;
683 
684   CHECK_STRING (color_name);
685 
686 #if false /* Don't do this.  It's wrong when we're not using the default
687 	     colormap, it makes freeing difficult, and it's probably not
688 	     an important optimization.  */
689   if (strcmp (SDATA (color_name), "black") == 0)
690     return BLACK_PIX_DEFAULT (f);
691   else if (strcmp (SDATA (color_name), "white") == 0)
692     return WHITE_PIX_DEFAULT (f);
693 #endif
694 
695   /* Return MONO_COLOR for monochrome frames.  */
696   if (FRAME_DISPLAY_INFO (f)->n_planes == 1)
697     return mono_color;
698 
699   /* x_defined_color is responsible for coping with failures
700      by looking for a near-miss.  */
701   if (x_defined_color (f, SSDATA (color_name), &cdef, true, false))
702     return cdef.pixel;
703 
704   signal_error ("Undefined color", color_name);
705 }
706 
707 
708 
709 /* Change the `wait-for-wm' frame parameter of frame F.  OLD_VALUE is
710    the previous value of that parameter, NEW_VALUE is the new value.
711    See also the comment of wait_for_wm in struct x_output.  */
712 
713 static void
x_set_wait_for_wm(struct frame * f,Lisp_Object new_value,Lisp_Object old_value)714 x_set_wait_for_wm (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
715 {
716   f->output_data.x->wait_for_wm = !NILP (new_value);
717 }
718 
719 static void
x_set_tool_bar_position(struct frame * f,Lisp_Object new_value,Lisp_Object old_value)720 x_set_tool_bar_position (struct frame *f,
721                          Lisp_Object new_value,
722                          Lisp_Object old_value)
723 {
724   Lisp_Object choice = list4 (Qleft, Qright, Qtop, Qbottom);
725 
726   if (!NILP (Fmemq (new_value, choice)))
727     {
728 #ifdef USE_GTK
729       if (!EQ (new_value, old_value))
730 	{
731 	  xg_change_toolbar_position (f, new_value);
732 	  fset_tool_bar_position (f, new_value);
733 	}
734 #else
735       if (!EQ (new_value, Qtop))
736 	error ("The only supported tool bar position is top");
737 #endif
738     }
739   else
740     wrong_choice (choice, new_value);
741 }
742 
743 static void
x_set_inhibit_double_buffering(struct frame * f,Lisp_Object new_value,Lisp_Object old_value)744 x_set_inhibit_double_buffering (struct frame *f,
745                                 Lisp_Object new_value,
746                                 Lisp_Object old_value)
747 {
748   block_input ();
749   if (FRAME_X_WINDOW (f) && !EQ (new_value, old_value))
750     {
751       bool want_double_buffering = NILP (new_value);
752       bool was_double_buffered = FRAME_X_DOUBLE_BUFFERED_P (f);
753       /* font_drop_xrender_surfaces in xftfont does something only if
754          we're double-buffered, so call font_drop_xrender_surfaces before
755          and after any potential change.  One of the calls will end up
756          being a no-op.  */
757       if (want_double_buffering != was_double_buffered)
758         font_drop_xrender_surfaces (f);
759       if (FRAME_X_DOUBLE_BUFFERED_P (f) && !want_double_buffering)
760         tear_down_x_back_buffer (f);
761       else if (!FRAME_X_DOUBLE_BUFFERED_P (f) && want_double_buffering)
762         set_up_x_back_buffer (f);
763       if (FRAME_X_DOUBLE_BUFFERED_P (f) != was_double_buffered)
764         {
765           SET_FRAME_GARBAGED (f);
766           font_drop_xrender_surfaces (f);
767         }
768     }
769   unblock_input ();
770 }
771 
772 /**
773  * x_set_undecorated:
774  *
775  * Set frame F's `undecorated' parameter.  If non-nil, F's window-system
776  * window is drawn without decorations, title, minimize/maximize boxes
777  * and external borders.  This usually means that the window cannot be
778  * dragged, resized, iconified, maximized or deleted with the mouse.  If
779  * nil, draw the frame with all the elements listed above unless these
780  * have been suspended via window manager settings.
781  *
782  * Some window managers may not honor this parameter.
783  */
784 static void
x_set_undecorated(struct frame * f,Lisp_Object new_value,Lisp_Object old_value)785 x_set_undecorated (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
786 {
787   if (!EQ (new_value, old_value))
788     {
789       FRAME_UNDECORATED (f) = NILP (new_value) ? false : true;
790 #ifdef USE_GTK
791       xg_set_undecorated (f, new_value);
792 #else
793       Display *dpy = FRAME_X_DISPLAY (f);
794       PropMotifWmHints hints;
795       Atom prop = XInternAtom (dpy, "_MOTIF_WM_HINTS", False);
796 
797       memset (&hints, 0, sizeof(hints));
798       hints.flags = MWM_HINTS_DECORATIONS;
799       hints.decorations = NILP (new_value) ? MWM_DECOR_ALL : 0;
800 
801       block_input ();
802       /* For some reason the third and fourth arguments in the following
803 	 call must be identical: In the corresponding XGetWindowProperty
804 	 call in getMotifHints, xfwm has the third and seventh args both
805 	 display_info->atoms[MOTIF_WM_HINTS].  Obviously, YMMV.   */
806       XChangeProperty (dpy, FRAME_OUTER_WINDOW (f), prop, prop, 32,
807 		       PropModeReplace, (unsigned char *) &hints,
808 		       PROP_MOTIF_WM_HINTS_ELEMENTS);
809       unblock_input ();
810 
811 #endif /* USE_GTK */
812     }
813 }
814 
815 /**
816  * x_set_parent_frame:
817  *
818  * Set frame F's `parent-frame' parameter.  If non-nil, make F a child
819  * frame of the frame specified by that parameter.  Technically, this
820  * makes F's window-system window a child window of the parent frame's
821  * window-system window.  If nil, make F's window-system window a
822  * top-level window--a child of its display's root window.
823  *
824  * A child frame is clipped at the native edges of its parent frame.
825  * Its `left' and `top' parameters specify positions relative to the
826  * top-left corner of its parent frame's native rectangle.  Usually,
827  * moving a parent frame moves all its child frames too, keeping their
828  * position relative to the parent unaltered.  When a parent frame is
829  * iconified or made invisible, its child frames are made invisible.
830  * When a parent frame is deleted, its child frames are deleted too.
831  *
832  * A visible child frame always appears on top of its parent frame thus
833  * obscuring parts of it.  When a frame has more than one child frame,
834  * their stacking order is specified just as that of non-child frames
835  * relative to their display.
836  *
837  * Whether a child frame has a menu or tool bar may be window-system or
838  * window manager dependent.  It's advisable to disable both via the
839  * frame parameter settings.
840  *
841  * Some window managers may not honor this parameter.
842  */
843 static void
x_set_parent_frame(struct frame * f,Lisp_Object new_value,Lisp_Object old_value)844 x_set_parent_frame (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
845 {
846   struct frame *p = NULL;
847 
848   if (!NILP (new_value)
849       && (!FRAMEP (new_value)
850 	  || !FRAME_LIVE_P (p = XFRAME (new_value))
851 	  || !FRAME_X_P (p)))
852     {
853       store_frame_param (f, Qparent_frame, old_value);
854       error ("Invalid specification of `parent-frame'");
855     }
856 
857   if (p != FRAME_PARENT_FRAME (f))
858     {
859       block_input ();
860       XReparentWindow
861 	(FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
862 	 p ? FRAME_X_WINDOW (p) : DefaultRootWindow (FRAME_X_DISPLAY (f)),
863 	 f->left_pos, f->top_pos);
864 #ifdef USE_GTK
865       if (EQ (x_gtk_resize_child_frames, Qresize_mode))
866 	gtk_container_set_resize_mode
867 	  (GTK_CONTAINER (FRAME_GTK_OUTER_WIDGET (f)),
868 	   p ? GTK_RESIZE_IMMEDIATE : GTK_RESIZE_QUEUE);
869 #endif
870       unblock_input ();
871 
872       fset_parent_frame (f, new_value);
873     }
874 }
875 
876 /**
877  * x_set_no_focus_on_map:
878  *
879  * Set frame F's `no-focus-on-map' parameter which, if non-nil, means
880  * that F's window-system window does not want to receive input focus
881  * when it is mapped.  (A frame's window is mapped when the frame is
882  * displayed for the first time and when the frame changes its state
883  * from `iconified' or `invisible' to `visible'.)
884  *
885  * Some window managers may not honor this parameter.
886  */
887 static void
x_set_no_focus_on_map(struct frame * f,Lisp_Object new_value,Lisp_Object old_value)888 x_set_no_focus_on_map (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
889 {
890   if (!EQ (new_value, old_value))
891     {
892 #ifdef USE_GTK
893       xg_set_no_focus_on_map (f, new_value);
894 #else /* not USE_GTK */
895       Display *dpy = FRAME_X_DISPLAY (f);
896       Atom prop = XInternAtom (dpy, "_NET_WM_USER_TIME", False);
897       Time timestamp = NILP (new_value) ? CurrentTime : 0;
898 
899       XChangeProperty (dpy, FRAME_OUTER_WINDOW (f), prop,
900 		       XA_CARDINAL, 32, PropModeReplace,
901 		       (unsigned char *) &timestamp, 1);
902 #endif /* USE_GTK */
903       FRAME_NO_FOCUS_ON_MAP (f) = !NILP (new_value);
904     }
905 }
906 
907 /**
908  * x_set_no_accept_focus:
909  *
910  * Set frame F's `no-accept-focus' parameter which, if non-nil, hints
911  * that F's window-system window does not want to receive input focus
912  * via mouse clicks or by moving the mouse into it.
913  *
914  * If non-nil, this may have the unwanted side-effect that a user cannot
915  * scroll a non-selected frame with the mouse.
916  *
917  * Some window managers may not honor this parameter.
918  */
919 static void
x_set_no_accept_focus(struct frame * f,Lisp_Object new_value,Lisp_Object old_value)920 x_set_no_accept_focus (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
921 {
922   if (!EQ (new_value, old_value))
923     {
924 #ifdef USE_GTK
925       xg_set_no_accept_focus (f, new_value);
926 #else /* not USE_GTK */
927 #ifdef USE_X_TOOLKIT
928       Arg al[1];
929 
930       XtSetArg (al[0], XtNinput, NILP (new_value) ? True : False);
931       XtSetValues (f->output_data.x->widget, al, 1);
932 #else /* not USE_X_TOOLKIT */
933       Window window = FRAME_X_WINDOW (f);
934 
935       f->output_data.x->wm_hints.input = NILP (new_value) ? True : False;
936       XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
937 #endif /* USE_X_TOOLKIT */
938 #endif /* USE_GTK */
939       FRAME_NO_ACCEPT_FOCUS (f) = !NILP (new_value);
940     }
941 }
942 
943 /**
944  * x_set_override_redirect:
945  *
946  * Set frame F's `override_redirect' parameter which, if non-nil, hints
947  * that the window manager doesn't want to deal with F.  Usually, such
948  * frames have no decorations and always appear on top of all frames.
949  *
950  * Some window managers may not honor this parameter.
951  */
952 static void
x_set_override_redirect(struct frame * f,Lisp_Object new_value,Lisp_Object old_value)953 x_set_override_redirect (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
954 {
955   if (!EQ (new_value, old_value))
956     {
957       /* Here (xfwm) override_redirect can be changed for invisible
958 	 frames only.  */
959       x_make_frame_invisible (f);
960 
961 #ifdef USE_GTK
962       xg_set_override_redirect (f, new_value);
963 #else /* not USE_GTK */
964       XSetWindowAttributes attributes;
965 
966       attributes.override_redirect = NILP (new_value) ? False : True;
967       XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
968 			       CWOverrideRedirect, &attributes);
969 #endif
970       x_make_frame_visible (f);
971       FRAME_OVERRIDE_REDIRECT (f) = !NILP (new_value);
972     }
973 }
974 
975 
976 #ifdef USE_GTK
977 
978 /* Set icon from FILE for frame F.  By using GTK functions the icon
979    may be any format that GdkPixbuf knows about, i.e. not just bitmaps.  */
980 
981 bool
xg_set_icon(struct frame * f,Lisp_Object file)982 xg_set_icon (struct frame *f, Lisp_Object file)
983 {
984   bool result = false;
985   Lisp_Object found;
986 
987   found = image_find_image_file (file);
988 
989   if (! NILP (found))
990     {
991       GdkPixbuf *pixbuf;
992       GError *err = NULL;
993       char *filename = SSDATA (ENCODE_FILE (found));
994       block_input ();
995 
996       pixbuf = gdk_pixbuf_new_from_file (filename, &err);
997 
998       if (pixbuf)
999 	{
1000 	  gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
1001 			       pixbuf);
1002 	  g_object_unref (pixbuf);
1003 
1004 	  result = true;
1005 	}
1006       else
1007 	g_error_free (err);
1008 
1009       unblock_input ();
1010     }
1011 
1012   return result;
1013 }
1014 
1015 bool
xg_set_icon_from_xpm_data(struct frame * f,const char ** data)1016 xg_set_icon_from_xpm_data (struct frame *f, const char **data)
1017 {
1018   GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data (data);
1019 
1020   if (!pixbuf)
1021     return false;
1022 
1023   gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), pixbuf);
1024   g_object_unref (pixbuf);
1025   return true;
1026 }
1027 #endif /* USE_GTK */
1028 
1029 
1030 /* Functions called only from `gui_set_frame_parameters'
1031    to set individual parameters.
1032 
1033    If FRAME_X_WINDOW (f) is 0,
1034    the frame is being created and its X-window does not exist yet.
1035    In that case, just record the parameter's new value
1036    in the standard place; do not attempt to change the window.  */
1037 
1038 static void
x_set_foreground_color(struct frame * f,Lisp_Object arg,Lisp_Object oldval)1039 x_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1040 {
1041   struct x_output *x = f->output_data.x;
1042   unsigned long fg, old_fg;
1043 
1044   fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1045   old_fg = FRAME_FOREGROUND_PIXEL (f);
1046   FRAME_FOREGROUND_PIXEL (f) = fg;
1047 
1048   if (FRAME_X_WINDOW (f) != 0)
1049     {
1050       Display *dpy = FRAME_X_DISPLAY (f);
1051 
1052       block_input ();
1053       XSetForeground (dpy, x->normal_gc, fg);
1054       XSetBackground (dpy, x->reverse_gc, fg);
1055 
1056       if (x->cursor_pixel == old_fg)
1057 	{
1058 	  unload_color (f, x->cursor_pixel);
1059 	  x->cursor_pixel = x_copy_color (f, fg);
1060 	  XSetBackground (dpy, x->cursor_gc, x->cursor_pixel);
1061 	}
1062 
1063       unblock_input ();
1064 
1065       update_face_from_frame_parameter (f, Qforeground_color, arg);
1066 
1067       if (FRAME_VISIBLE_P (f))
1068         redraw_frame (f);
1069     }
1070 
1071   unload_color (f, old_fg);
1072 }
1073 
1074 static void
x_set_background_color(struct frame * f,Lisp_Object arg,Lisp_Object oldval)1075 x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1076 {
1077   struct x_output *x = f->output_data.x;
1078   unsigned long bg;
1079 
1080   bg = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
1081   unload_color (f, FRAME_BACKGROUND_PIXEL (f));
1082   FRAME_BACKGROUND_PIXEL (f) = bg;
1083 
1084   if (FRAME_X_WINDOW (f) != 0)
1085     {
1086       Display *dpy = FRAME_X_DISPLAY (f);
1087 
1088       block_input ();
1089       XSetBackground (dpy, x->normal_gc, bg);
1090       XSetForeground (dpy, x->reverse_gc, bg);
1091       XSetWindowBackground (dpy, FRAME_X_WINDOW (f), bg);
1092       XSetForeground (dpy, x->cursor_gc, bg);
1093 
1094 #ifdef USE_GTK
1095       xg_set_background_color (f, bg);
1096 #endif
1097 
1098 #ifndef USE_TOOLKIT_SCROLL_BARS /* Turns out to be annoying with
1099 				   toolkit scroll bars.  */
1100       {
1101 	Lisp_Object bar;
1102 	for (bar = FRAME_SCROLL_BARS (f);
1103 	     !NILP (bar);
1104 	     bar = XSCROLL_BAR (bar)->next)
1105 	  {
1106 	    Window window = XSCROLL_BAR (bar)->x_window;
1107 	    XSetWindowBackground (dpy, window, bg);
1108 	  }
1109       }
1110 #endif /* USE_TOOLKIT_SCROLL_BARS */
1111 
1112       unblock_input ();
1113       update_face_from_frame_parameter (f, Qbackground_color, arg);
1114 
1115       if (FRAME_VISIBLE_P (f))
1116         redraw_frame (f);
1117     }
1118 }
1119 
1120 /* This array must stay in sync with the mouse_cursor_types array below!  */
1121 enum mouse_cursor {
1122   mouse_cursor_text,
1123   mouse_cursor_nontext,
1124   mouse_cursor_hourglass,
1125   mouse_cursor_mode,
1126   mouse_cursor_hand,
1127   mouse_cursor_horizontal_drag,
1128   mouse_cursor_vertical_drag,
1129   mouse_cursor_left_edge,
1130   mouse_cursor_top_left_corner,
1131   mouse_cursor_top_edge,
1132   mouse_cursor_top_right_corner,
1133   mouse_cursor_right_edge,
1134   mouse_cursor_bottom_right_corner,
1135   mouse_cursor_bottom_edge,
1136   mouse_cursor_bottom_left_corner,
1137   mouse_cursor_max
1138 };
1139 
1140 struct mouse_cursor_types {
1141   /* Printable name for error messages (optional).  */
1142   const char *name;
1143 
1144   /* Lisp variable controlling the cursor shape.  */
1145   /* FIXME: A couple of these variables are defined in the C code but
1146      are not actually accessible from Lisp.  They should probably be
1147      made accessible or removed.  */
1148   Lisp_Object *shape_var_ptr;
1149 
1150   /* The default shape.  */
1151   int default_shape;
1152 };
1153 
1154 /* This array must stay in sync with enum mouse_cursor above!  */
1155 static const struct mouse_cursor_types mouse_cursor_types[] = {
1156   { "text",      &Vx_pointer_shape,                    XC_xterm               },
1157   { "nontext",   &Vx_nontext_pointer_shape,            XC_left_ptr            },
1158   { "hourglass", &Vx_hourglass_pointer_shape,          XC_watch               },
1159   { "modeline",  &Vx_mode_pointer_shape,               XC_xterm               },
1160   { NULL,        &Vx_sensitive_text_pointer_shape,     XC_hand2               },
1161   { NULL,        &Vx_window_horizontal_drag_shape,     XC_sb_h_double_arrow   },
1162   { NULL,        &Vx_window_vertical_drag_shape,       XC_sb_v_double_arrow   },
1163   { NULL,        &Vx_window_left_edge_shape,           XC_left_side           },
1164   { NULL,        &Vx_window_top_left_corner_shape,     XC_top_left_corner     },
1165   { NULL,        &Vx_window_top_edge_shape,            XC_top_side            },
1166   { NULL,        &Vx_window_top_right_corner_shape,    XC_top_right_corner    },
1167   { NULL,        &Vx_window_right_edge_shape,          XC_right_side          },
1168   { NULL,        &Vx_window_bottom_right_corner_shape, XC_bottom_right_corner },
1169   { NULL,        &Vx_window_bottom_edge_shape,         XC_bottom_side         },
1170   { NULL,        &Vx_window_bottom_left_corner_shape,  XC_bottom_left_corner  },
1171 };
1172 
1173 struct mouse_cursor_data {
1174   /* Last index for which XCreateFontCursor has been called, and thus
1175      the last index for which x_request_serial[] is valid.  */
1176   int last_cursor_create_request;
1177 
1178   /* Last index for which an X error event was received in response to
1179      attempting to create the cursor.  */
1180   int error_cursor;
1181 
1182   /* Cursor numbers chosen.  */
1183   unsigned int cursor_num[mouse_cursor_max];
1184 
1185   /* Allocated Cursor values, or zero for failed attempts.  */
1186   Cursor cursor[mouse_cursor_max];
1187 
1188   /* X serial numbers for the first request sent by XCreateFontCursor.
1189      Note that there may be more than one request sent.  */
1190   unsigned long x_request_serial[mouse_cursor_max];
1191 
1192   /* If an error has been received, a pointer to where the current
1193      error-message text is stored.  */
1194   char *error_string;
1195 };
1196 
1197 static void
x_set_mouse_color_handler(Display * dpy,XErrorEvent * event,char * error_string,void * data)1198 x_set_mouse_color_handler (Display *dpy, XErrorEvent *event,
1199 			   char *error_string, void *data)
1200 {
1201   struct mouse_cursor_data *cursor_data = data;
1202   int i;
1203 
1204   cursor_data->error_cursor = -1;
1205   cursor_data->error_string = error_string;
1206   for (i = 0; i < cursor_data->last_cursor_create_request; i++)
1207     {
1208       if (event->serial >= cursor_data->x_request_serial[i])
1209 	cursor_data->error_cursor = i;
1210     }
1211   if (cursor_data->error_cursor >= 0)
1212     /* If we failed to allocate it, don't try to free it.  */
1213     cursor_data->cursor[cursor_data->error_cursor] = 0;
1214 }
1215 
1216 static void
x_set_mouse_color(struct frame * f,Lisp_Object arg,Lisp_Object oldval)1217 x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1218 {
1219   struct x_output *x = f->output_data.x;
1220   Display *dpy = FRAME_X_DISPLAY (f);
1221   struct mouse_cursor_data cursor_data = { -1, -1 };
1222   unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1223   unsigned long mask_color = FRAME_BACKGROUND_PIXEL (f);
1224   int i;
1225 
1226   /* Don't let pointers be invisible.  */
1227   if (mask_color == pixel)
1228     {
1229       x_free_colors (f, &pixel, 1);
1230       pixel = x_copy_color (f, FRAME_FOREGROUND_PIXEL (f));
1231     }
1232 
1233   unload_color (f, x->mouse_pixel);
1234   x->mouse_pixel = pixel;
1235 
1236   for (i = 0; i < mouse_cursor_max; i++)
1237     {
1238       Lisp_Object shape_var = *mouse_cursor_types[i].shape_var_ptr;
1239       if (!NILP (shape_var))
1240 	{
1241 	  CHECK_TYPE_RANGED_INTEGER (unsigned, shape_var);
1242 	  cursor_data.cursor_num[i] = XFIXNUM (shape_var);
1243 	}
1244       else
1245 	cursor_data.cursor_num[i] = mouse_cursor_types[i].default_shape;
1246     }
1247 
1248   block_input ();
1249 
1250   /* It's not okay to crash if the user selects a screwy cursor.  */
1251   x_catch_errors_with_handler (dpy, x_set_mouse_color_handler, &cursor_data);
1252 
1253   for (i = 0; i < mouse_cursor_max; i++)
1254     {
1255       cursor_data.x_request_serial[i] = XNextRequest (dpy);
1256       cursor_data.last_cursor_create_request = i;
1257       cursor_data.cursor[i] = XCreateFontCursor (dpy,
1258 						 cursor_data.cursor_num[i]);
1259     }
1260 
1261   /* Now sync up and process all received errors from cursor
1262      creation.  */
1263   if (x_had_errors_p (dpy))
1264     {
1265       const char *bad_cursor_name = NULL;
1266       /* Bounded by X_ERROR_MESSAGE_SIZE in xterm.c.  */
1267       size_t message_length = strlen (cursor_data.error_string);
1268       char *xmessage = alloca (1 + message_length);
1269       memcpy (xmessage, cursor_data.error_string, message_length);
1270 
1271       x_uncatch_errors ();
1272 
1273       /* Free any successfully created cursors.  */
1274       for (i = 0; i < mouse_cursor_max; i++)
1275 	if (cursor_data.cursor[i] != 0)
1276 	  XFreeCursor (dpy, cursor_data.cursor[i]);
1277 
1278       /* This should only be able to fail if the server's serial
1279 	 number tracking is broken.  */
1280       if (cursor_data.error_cursor >= 0)
1281 	bad_cursor_name = mouse_cursor_types[cursor_data.error_cursor].name;
1282       if (bad_cursor_name)
1283 	error ("bad %s pointer cursor: %s", bad_cursor_name, xmessage);
1284       else
1285 	error ("can't set cursor shape: %s", xmessage);
1286     }
1287 
1288   x_uncatch_errors_after_check ();
1289 
1290   {
1291     XColor colors[2]; /* 0=foreground, 1=background */
1292 
1293     colors[0].pixel = x->mouse_pixel;
1294     colors[1].pixel = mask_color;
1295     x_query_colors (f, colors, 2);
1296 
1297     for (i = 0; i < mouse_cursor_max; i++)
1298       XRecolorCursor (dpy, cursor_data.cursor[i], &colors[0], &colors[1]);
1299   }
1300 
1301   if (FRAME_X_WINDOW (f) != 0)
1302     {
1303       f->output_data.x->current_cursor = cursor_data.cursor[mouse_cursor_text];
1304       XDefineCursor (dpy, FRAME_X_WINDOW (f),
1305 		     f->output_data.x->current_cursor);
1306     }
1307 
1308 #define INSTALL_CURSOR(FIELD, SHORT_INDEX)				\
1309   eassert (x->FIELD != cursor_data.cursor[mouse_cursor_ ## SHORT_INDEX]); \
1310   if (x->FIELD != 0)							\
1311     XFreeCursor (dpy, x->FIELD);					\
1312   x->FIELD = cursor_data.cursor[mouse_cursor_ ## SHORT_INDEX];
1313 
1314   INSTALL_CURSOR (text_cursor, text);
1315   INSTALL_CURSOR (nontext_cursor, nontext);
1316   INSTALL_CURSOR (hourglass_cursor, hourglass);
1317   INSTALL_CURSOR (modeline_cursor, mode);
1318   INSTALL_CURSOR (hand_cursor, hand);
1319   INSTALL_CURSOR (horizontal_drag_cursor, horizontal_drag);
1320   INSTALL_CURSOR (vertical_drag_cursor, vertical_drag);
1321   INSTALL_CURSOR (left_edge_cursor, left_edge);
1322   INSTALL_CURSOR (top_left_corner_cursor, top_left_corner);
1323   INSTALL_CURSOR (top_edge_cursor, top_edge);
1324   INSTALL_CURSOR (top_right_corner_cursor, top_right_corner);
1325   INSTALL_CURSOR (right_edge_cursor, right_edge);
1326   INSTALL_CURSOR (bottom_right_corner_cursor, bottom_right_corner);
1327   INSTALL_CURSOR (bottom_edge_cursor, bottom_edge);
1328   INSTALL_CURSOR (bottom_left_corner_cursor, bottom_left_corner);
1329 
1330 #undef INSTALL_CURSOR
1331 
1332   XFlush (dpy);
1333   unblock_input ();
1334 
1335   update_face_from_frame_parameter (f, Qmouse_color, arg);
1336 }
1337 
1338 static void
x_set_cursor_color(struct frame * f,Lisp_Object arg,Lisp_Object oldval)1339 x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1340 {
1341   unsigned long fore_pixel, pixel;
1342   bool fore_pixel_allocated_p = false, pixel_allocated_p = false;
1343   struct x_output *x = f->output_data.x;
1344 
1345   if (!NILP (Vx_cursor_fore_pixel))
1346     {
1347       fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
1348 				   WHITE_PIX_DEFAULT (f));
1349       fore_pixel_allocated_p = true;
1350     }
1351   else
1352     fore_pixel = FRAME_BACKGROUND_PIXEL (f);
1353 
1354   pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1355   pixel_allocated_p = true;
1356 
1357   /* Make sure that the cursor color differs from the background color.  */
1358   if (pixel == FRAME_BACKGROUND_PIXEL (f))
1359     {
1360       if (pixel_allocated_p)
1361 	{
1362 	  x_free_colors (f, &pixel, 1);
1363 	  pixel_allocated_p = false;
1364 	}
1365 
1366       pixel = x->mouse_pixel;
1367       if (pixel == fore_pixel)
1368 	{
1369 	  if (fore_pixel_allocated_p)
1370 	    {
1371 	      x_free_colors (f, &fore_pixel, 1);
1372 	      fore_pixel_allocated_p = false;
1373 	    }
1374 	  fore_pixel = FRAME_BACKGROUND_PIXEL (f);
1375 	}
1376     }
1377 
1378   unload_color (f, x->cursor_foreground_pixel);
1379   if (!fore_pixel_allocated_p)
1380     fore_pixel = x_copy_color (f, fore_pixel);
1381   x->cursor_foreground_pixel = fore_pixel;
1382 
1383   unload_color (f, x->cursor_pixel);
1384   if (!pixel_allocated_p)
1385     pixel = x_copy_color (f, pixel);
1386   x->cursor_pixel = pixel;
1387 
1388   if (FRAME_X_WINDOW (f) != 0)
1389     {
1390       block_input ();
1391       XSetBackground (FRAME_X_DISPLAY (f), x->cursor_gc, x->cursor_pixel);
1392       XSetForeground (FRAME_X_DISPLAY (f), x->cursor_gc, fore_pixel);
1393       unblock_input ();
1394 
1395       if (FRAME_VISIBLE_P (f))
1396 	{
1397 	  gui_update_cursor (f, false);
1398 	  gui_update_cursor (f, true);
1399 	}
1400     }
1401 
1402   update_face_from_frame_parameter (f, Qcursor_color, arg);
1403 }
1404 
1405 /* Set the border-color of frame F to pixel value PIX.
1406    Note that this does not fully take effect if done before
1407    F has an x-window.  */
1408 
1409 static void
x_set_border_pixel(struct frame * f,int pix)1410 x_set_border_pixel (struct frame *f, int pix)
1411 {
1412   unload_color (f, f->output_data.x->border_pixel);
1413   f->output_data.x->border_pixel = pix;
1414 
1415   if (FRAME_X_WINDOW (f) != 0 && f->border_width > 0)
1416     {
1417       block_input ();
1418       XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), pix);
1419       unblock_input ();
1420 
1421       if (FRAME_VISIBLE_P (f))
1422         redraw_frame (f);
1423     }
1424 }
1425 
1426 /* Set the border-color of frame F to value described by ARG.
1427    ARG can be a string naming a color.
1428    The border-color is used for the border that is drawn by the X server.
1429    Note that this does not fully take effect if done before
1430    F has an x-window; it must be redone when the window is created.
1431 
1432    Note: this is done in two routines because of the way X10 works.
1433 
1434    Note: under X11, this is normally the province of the window manager,
1435    and so emacs's border colors may be overridden.  */
1436 
1437 static void
x_set_border_color(struct frame * f,Lisp_Object arg,Lisp_Object oldval)1438 x_set_border_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1439 {
1440   int pix;
1441 
1442   CHECK_STRING (arg);
1443   pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1444   x_set_border_pixel (f, pix);
1445   update_face_from_frame_parameter (f, Qborder_color, arg);
1446 }
1447 
1448 
1449 static void
x_set_cursor_type(struct frame * f,Lisp_Object arg,Lisp_Object oldval)1450 x_set_cursor_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1451 {
1452   set_frame_cursor_types (f, arg);
1453 }
1454 
1455 static void
x_set_icon_type(struct frame * f,Lisp_Object arg,Lisp_Object oldval)1456 x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1457 {
1458   bool result;
1459 
1460   if (STRINGP (arg))
1461     {
1462       if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1463 	return;
1464     }
1465   else if (!STRINGP (oldval) && NILP (oldval) == NILP (arg))
1466     return;
1467 
1468   block_input ();
1469   if (NILP (arg))
1470     result = x_text_icon (f,
1471 			  SSDATA ((!NILP (f->icon_name)
1472 				   ? f->icon_name
1473 				   : f->name)));
1474   else
1475     result = FRAME_TERMINAL (f)->set_bitmap_icon_hook (f, arg);
1476 
1477   if (result)
1478     {
1479       unblock_input ();
1480       error ("No icon window available");
1481     }
1482 
1483   XFlush (FRAME_X_DISPLAY (f));
1484   unblock_input ();
1485 }
1486 
1487 static void
x_set_icon_name(struct frame * f,Lisp_Object arg,Lisp_Object oldval)1488 x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1489 {
1490   bool result;
1491 
1492   if (STRINGP (arg))
1493     {
1494       if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1495 	return;
1496     }
1497   else if (!NILP (arg) || NILP (oldval))
1498     return;
1499 
1500   fset_icon_name (f, arg);
1501 
1502   if (f->output_data.x->icon_bitmap != 0)
1503     return;
1504 
1505   block_input ();
1506 
1507   result = x_text_icon (f,
1508 			SSDATA ((!NILP (f->icon_name)
1509 				 ? f->icon_name
1510 				 : !NILP (f->title)
1511 				 ? f->title
1512 				 : f->name)));
1513 
1514   if (result)
1515     {
1516       unblock_input ();
1517       error ("No icon window available");
1518     }
1519 
1520   XFlush (FRAME_X_DISPLAY (f));
1521   unblock_input ();
1522 }
1523 
1524 
1525 static void
x_set_menu_bar_lines(struct frame * f,Lisp_Object value,Lisp_Object oldval)1526 x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
1527 {
1528   int nlines;
1529 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
1530   int olines = FRAME_MENU_BAR_LINES (f);
1531 #endif
1532 
1533   /* Right now, menu bars don't work properly in minibuf-only frames;
1534      most of the commands try to apply themselves to the minibuffer
1535      frame itself, and get an error because you can't switch buffers
1536      in or split the minibuffer window.  */
1537   if (FRAME_MINIBUF_ONLY_P (f) || FRAME_PARENT_FRAME (f))
1538     return;
1539 
1540   if (TYPE_RANGED_FIXNUMP (int, value))
1541     nlines = XFIXNUM (value);
1542   else
1543     nlines = 0;
1544 
1545   /* Make sure we redisplay all windows in this frame.  */
1546   fset_redisplay (f);
1547 
1548 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
1549   FRAME_MENU_BAR_LINES (f) = 0;
1550   FRAME_MENU_BAR_HEIGHT (f) = 0;
1551   if (nlines)
1552     {
1553       FRAME_EXTERNAL_MENU_BAR (f) = 1;
1554       if (FRAME_X_P (f) && f->output_data.x->menubar_widget == 0)
1555 	/* Make sure next redisplay shows the menu bar.  */
1556 	XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = true;
1557     }
1558   else
1559     {
1560       if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
1561 	free_frame_menubar (f);
1562       FRAME_EXTERNAL_MENU_BAR (f) = 0;
1563       if (FRAME_X_P (f))
1564 	f->output_data.x->menubar_widget = 0;
1565     }
1566 #else /* not USE_X_TOOLKIT && not USE_GTK */
1567   FRAME_MENU_BAR_LINES (f) = nlines;
1568   FRAME_MENU_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f);
1569   adjust_frame_size (f, -1, -1, 2, true, Qx_set_menu_bar_lines);
1570   if (FRAME_X_WINDOW (f))
1571     x_clear_under_internal_border (f);
1572 
1573   /* If the menu bar height gets changed, the internal border below
1574      the top margin has to be cleared.  Also, if the menu bar gets
1575      larger, the area for the added lines has to be cleared except for
1576      the first menu bar line that is to be drawn later.  */
1577   if (nlines != olines)
1578     {
1579       int height = FRAME_INTERNAL_BORDER_WIDTH (f);
1580       int width = FRAME_PIXEL_WIDTH (f);
1581       int y;
1582 
1583       /* height can be zero here. */
1584       if (FRAME_X_WINDOW (f) && height > 0 && width > 0)
1585 	{
1586 	  y = FRAME_TOP_MARGIN_HEIGHT (f);
1587 
1588 	  block_input ();
1589 	  x_clear_area (f, 0, y, width, height);
1590 	  unblock_input ();
1591 	}
1592 
1593       if (nlines > 1 && nlines > olines)
1594 	{
1595 	  y = (olines == 0 ? 1 : olines) * FRAME_LINE_HEIGHT (f);
1596 	  height = nlines * FRAME_LINE_HEIGHT (f) - y;
1597 
1598 	  block_input ();
1599 	  x_clear_area (f, 0, y, width, height);
1600 	  unblock_input ();
1601 	}
1602 
1603       if (nlines == 0 && WINDOWP (f->menu_bar_window))
1604 	clear_glyph_matrix (XWINDOW (f->menu_bar_window)->current_matrix);
1605     }
1606 #endif /* not USE_X_TOOLKIT && not USE_GTK */
1607   adjust_frame_glyphs (f);
1608 }
1609 
1610 
1611 /* Set the number of lines used for the tab bar of frame F to VALUE.
1612    VALUE not an integer, or < 0 means set the lines to zero.  OLDVAL
1613    is the old number of tab bar lines.  This function changes the
1614    height of all windows on frame F to match the new tab bar height.
1615    The frame's height doesn't change.  */
1616 
1617 static void
x_set_tab_bar_lines(struct frame * f,Lisp_Object value,Lisp_Object oldval)1618 x_set_tab_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
1619 {
1620   int nlines;
1621 
1622   /* Treat tab bars like menu bars.  */
1623   if (FRAME_MINIBUF_ONLY_P (f))
1624     return;
1625 
1626   /* Use VALUE only if an int >= 0.  */
1627   if (RANGED_FIXNUMP (0, value, INT_MAX))
1628     nlines = XFIXNAT (value);
1629   else
1630     nlines = 0;
1631 
1632   x_change_tab_bar_height (f, nlines * FRAME_LINE_HEIGHT (f));
1633 }
1634 
1635 
1636 /* Set the pixel height of the tab bar of frame F to HEIGHT.  */
1637 void
x_change_tab_bar_height(struct frame * f,int height)1638 x_change_tab_bar_height (struct frame *f, int height)
1639 {
1640   int unit = FRAME_LINE_HEIGHT (f);
1641   int old_height = FRAME_TAB_BAR_HEIGHT (f);
1642   int lines = (height + unit - 1) / unit;
1643   Lisp_Object fullscreen;
1644 
1645   /* Make sure we redisplay all windows in this frame.  */
1646   fset_redisplay (f);
1647 
1648   /* Recalculate tab bar and frame text sizes.  */
1649   FRAME_TAB_BAR_HEIGHT (f) = height;
1650   FRAME_TAB_BAR_LINES (f) = lines;
1651   /* Store the `tab-bar-lines' and `height' frame parameters.  */
1652   store_frame_param (f, Qtab_bar_lines, make_fixnum (lines));
1653   store_frame_param (f, Qheight, make_fixnum (FRAME_LINES (f)));
1654 
1655   /* We also have to make sure that the internal border at the top of
1656      the frame, below the menu bar or tab bar, is redrawn when the
1657      tab bar disappears.  This is so because the internal border is
1658      below the tab bar if one is displayed, but is below the menu bar
1659      if there isn't a tab bar.  The tab bar draws into the area
1660      below the menu bar.  */
1661   if (FRAME_X_WINDOW (f) && FRAME_TAB_BAR_HEIGHT (f) == 0)
1662     {
1663       clear_frame (f);
1664       clear_current_matrices (f);
1665     }
1666 
1667   if ((height < old_height) && WINDOWP (f->tab_bar_window))
1668     clear_glyph_matrix (XWINDOW (f->tab_bar_window)->current_matrix);
1669 
1670   /* Recalculate tabbar height.  */
1671   f->n_tab_bar_rows = 0;
1672   if (old_height == 0
1673       && (!f->after_make_frame
1674 	  || NILP (frame_inhibit_implied_resize)
1675 	  || (CONSP (frame_inhibit_implied_resize)
1676 	      && NILP (Fmemq (Qtab_bar_lines, frame_inhibit_implied_resize)))))
1677     f->tab_bar_redisplayed = f->tab_bar_resized = false;
1678 
1679   adjust_frame_size (f, -1, -1,
1680 		     ((!f->tab_bar_resized
1681 		       && (NILP (fullscreen =
1682 				 get_frame_param (f, Qfullscreen))
1683 			   || EQ (fullscreen, Qfullwidth))) ? 1
1684 		      : (old_height == 0 || height == 0) ? 2
1685 		      : 4),
1686 		     false, Qtab_bar_lines);
1687 
1688   f->tab_bar_resized = f->tab_bar_redisplayed;
1689 
1690   /* adjust_frame_size might not have done anything, garbage frame
1691      here.  */
1692   adjust_frame_glyphs (f);
1693   SET_FRAME_GARBAGED (f);
1694   if (FRAME_X_WINDOW (f))
1695     x_clear_under_internal_border (f);
1696 }
1697 
1698 
1699 /* Set the number of lines used for the tool bar of frame F to VALUE.
1700    VALUE not an integer, or < 0 means set the lines to zero.  OLDVAL
1701    is the old number of tool bar lines.  This function changes the
1702    height of all windows on frame F to match the new tool bar height.
1703    The frame's height doesn't change.  */
1704 
1705 static void
x_set_tool_bar_lines(struct frame * f,Lisp_Object value,Lisp_Object oldval)1706 x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
1707 {
1708   int nlines;
1709 
1710   /* Treat tool bars like menu bars.  */
1711   if (FRAME_MINIBUF_ONLY_P (f))
1712     return;
1713 
1714   /* Use VALUE only if an int >= 0.  */
1715   if (RANGED_FIXNUMP (0, value, INT_MAX))
1716     nlines = XFIXNAT (value);
1717   else
1718     nlines = 0;
1719 
1720   x_change_tool_bar_height (f, nlines * FRAME_LINE_HEIGHT (f));
1721 }
1722 
1723 
1724 /* Set the pixel height of the tool bar of frame F to HEIGHT.  */
1725 void
x_change_tool_bar_height(struct frame * f,int height)1726 x_change_tool_bar_height (struct frame *f, int height)
1727 {
1728 #ifdef USE_GTK
1729   FRAME_TOOL_BAR_LINES (f) = 0;
1730   FRAME_TOOL_BAR_HEIGHT (f) = 0;
1731   if (height)
1732     {
1733       FRAME_EXTERNAL_TOOL_BAR (f) = true;
1734       if (FRAME_X_P (f) && f->output_data.x->toolbar_widget == 0)
1735 	/* Make sure next redisplay shows the tool bar.  */
1736 	XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = true;
1737       update_frame_tool_bar (f);
1738     }
1739   else
1740     {
1741       if (FRAME_EXTERNAL_TOOL_BAR (f))
1742         free_frame_tool_bar (f);
1743       FRAME_EXTERNAL_TOOL_BAR (f) = false;
1744     }
1745 #else /* !USE_GTK */
1746   int unit = FRAME_LINE_HEIGHT (f);
1747   int old_height = FRAME_TOOL_BAR_HEIGHT (f);
1748   int lines = (height + unit - 1) / unit;
1749   Lisp_Object fullscreen;
1750 
1751   /* Make sure we redisplay all windows in this frame.  */
1752   fset_redisplay (f);
1753 
1754   /* Recalculate tool bar and frame text sizes.  */
1755   FRAME_TOOL_BAR_HEIGHT (f) = height;
1756   FRAME_TOOL_BAR_LINES (f) = lines;
1757   /* Store the `tool-bar-lines' and `height' frame parameters.  */
1758   store_frame_param (f, Qtool_bar_lines, make_fixnum (lines));
1759   store_frame_param (f, Qheight, make_fixnum (FRAME_LINES (f)));
1760 
1761   /* We also have to make sure that the internal border at the top of
1762      the frame, below the menu bar or tool bar, is redrawn when the
1763      tool bar disappears.  This is so because the internal border is
1764      below the tool bar if one is displayed, but is below the menu bar
1765      if there isn't a tool bar.  The tool bar draws into the area
1766      below the menu bar.  */
1767   if (FRAME_X_WINDOW (f) && FRAME_TOOL_BAR_HEIGHT (f) == 0)
1768     {
1769       clear_frame (f);
1770       clear_current_matrices (f);
1771     }
1772 
1773   if ((height < old_height) && WINDOWP (f->tool_bar_window))
1774     clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
1775 
1776   /* Recalculate toolbar height.  */
1777   f->n_tool_bar_rows = 0;
1778   if (old_height == 0
1779       && (!f->after_make_frame
1780 	  || NILP (frame_inhibit_implied_resize)
1781 	  || (CONSP (frame_inhibit_implied_resize)
1782 	      && NILP (Fmemq (Qtool_bar_lines, frame_inhibit_implied_resize)))))
1783     f->tool_bar_redisplayed = f->tool_bar_resized = false;
1784 
1785   adjust_frame_size (f, -1, -1,
1786 		     ((!f->tool_bar_resized
1787 		       && (NILP (fullscreen =
1788 				 get_frame_param (f, Qfullscreen))
1789 			   || EQ (fullscreen, Qfullwidth))) ? 1
1790 		      : (old_height == 0 || height == 0) ? 2
1791 		      : 4),
1792 		     false, Qtool_bar_lines);
1793 
1794   f->tool_bar_resized = f->tool_bar_redisplayed;
1795 
1796   /* adjust_frame_size might not have done anything, garbage frame
1797      here.  */
1798   adjust_frame_glyphs (f);
1799   SET_FRAME_GARBAGED (f);
1800   if (FRAME_X_WINDOW (f))
1801     x_clear_under_internal_border (f);
1802 
1803 #endif /* USE_GTK */
1804 }
1805 
1806 
1807 static void
x_set_internal_border_width(struct frame * f,Lisp_Object arg,Lisp_Object oldval)1808 x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1809 {
1810   int border;
1811 
1812   CHECK_TYPE_RANGED_INTEGER (int, arg);
1813   border = max (XFIXNUM (arg), 0);
1814 
1815   if (border != FRAME_INTERNAL_BORDER_WIDTH (f))
1816     {
1817       f->internal_border_width = border;
1818 
1819 #ifdef USE_X_TOOLKIT
1820       if (FRAME_X_OUTPUT (f)->edit_widget)
1821 	widget_store_internal_border (FRAME_X_OUTPUT (f)->edit_widget);
1822 #endif
1823 
1824       if (FRAME_X_WINDOW (f))
1825 	{
1826 	  adjust_frame_size (f, -1, -1, 3, false, Qinternal_border_width);
1827 	  x_clear_under_internal_border (f);
1828 	}
1829     }
1830 
1831 }
1832 
1833 
1834 /* Set the foreground color for scroll bars on frame F to VALUE.
1835    VALUE should be a string, a color name.  If it isn't a string or
1836    isn't a valid color name, do nothing.  OLDVAL is the old value of
1837    the frame parameter.  */
1838 
1839 static void
x_set_scroll_bar_foreground(struct frame * f,Lisp_Object value,Lisp_Object oldval)1840 x_set_scroll_bar_foreground (struct frame *f, Lisp_Object value, Lisp_Object oldval)
1841 {
1842   unsigned long pixel;
1843 
1844   if (STRINGP (value))
1845     pixel = x_decode_color (f, value, BLACK_PIX_DEFAULT (f));
1846   else
1847     pixel = -1;
1848 
1849   if (f->output_data.x->scroll_bar_foreground_pixel != -1)
1850     unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
1851 
1852   f->output_data.x->scroll_bar_foreground_pixel = pixel;
1853   if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
1854     {
1855       /* Remove all scroll bars because they have wrong colors.  */
1856       if (FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
1857 	(*FRAME_TERMINAL (f)->condemn_scroll_bars_hook) (f);
1858       if (FRAME_TERMINAL (f)->judge_scroll_bars_hook)
1859 	(*FRAME_TERMINAL (f)->judge_scroll_bars_hook) (f);
1860 
1861       update_face_from_frame_parameter (f, Qscroll_bar_foreground, value);
1862       redraw_frame (f);
1863     }
1864 }
1865 
1866 
1867 /* Set the background color for scroll bars on frame F to VALUE VALUE
1868    should be a string, a color name.  If it isn't a string or isn't a
1869    valid color name, do nothing.  OLDVAL is the old value of the frame
1870    parameter.  */
1871 
1872 static void
x_set_scroll_bar_background(struct frame * f,Lisp_Object value,Lisp_Object oldval)1873 x_set_scroll_bar_background (struct frame *f, Lisp_Object value, Lisp_Object oldval)
1874 {
1875   unsigned long pixel;
1876 
1877   if (STRINGP (value))
1878     pixel = x_decode_color (f, value, WHITE_PIX_DEFAULT (f));
1879   else
1880     pixel = -1;
1881 
1882   if (f->output_data.x->scroll_bar_background_pixel != -1)
1883     unload_color (f, f->output_data.x->scroll_bar_background_pixel);
1884 
1885 #if defined (USE_LUCID) && defined (USE_TOOLKIT_SCROLL_BARS)
1886   /* Scrollbar shadow colors.  */
1887   if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
1888     {
1889       unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
1890       f->output_data.x->scroll_bar_top_shadow_pixel = -1;
1891     }
1892   if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
1893     {
1894       unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
1895       f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
1896     }
1897 #endif /* USE_LUCID && USE_TOOLKIT_SCROLL_BARS */
1898 
1899   f->output_data.x->scroll_bar_background_pixel = pixel;
1900   if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
1901     {
1902       /* Remove all scroll bars because they have wrong colors.  */
1903       if (FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
1904 	(*FRAME_TERMINAL (f)->condemn_scroll_bars_hook) (f);
1905       if (FRAME_TERMINAL (f)->judge_scroll_bars_hook)
1906 	(*FRAME_TERMINAL (f)->judge_scroll_bars_hook) (f);
1907 
1908       update_face_from_frame_parameter (f, Qscroll_bar_background, value);
1909       redraw_frame (f);
1910     }
1911 }
1912 
1913 
1914 /* Encode Lisp string STRING as a text in a format appropriate for
1915    XICCC (X Inter Client Communication Conventions).
1916 
1917    If STRING contains only ASCII characters, do no conversion and
1918    return the string data of STRING.  Otherwise, encode the text by
1919    CODING_SYSTEM, and return a newly allocated memory area which
1920    should be freed by `xfree' by a caller.
1921 
1922    Store the byte length of resulting text in *TEXT_BYTES.
1923 
1924    If the text contains only ASCII and Latin-1, store true in *STRING_P,
1925    which means that the `encoding' of the result can be `STRING'.
1926    Otherwise store false in *STRINGP, which means that the `encoding' of
1927    the result should be `COMPOUND_TEXT'.  */
1928 
1929 static unsigned char *
x_encode_text(Lisp_Object string,Lisp_Object coding_system,ptrdiff_t * text_bytes,bool * stringp,bool * freep)1930 x_encode_text (Lisp_Object string, Lisp_Object coding_system,
1931 	       ptrdiff_t *text_bytes, bool *stringp, bool *freep)
1932 {
1933   int result = string_xstring_p (string);
1934   struct coding_system coding;
1935 
1936   if (result == 0)
1937     {
1938       /* No multibyte character in OBJ.  We need not encode it.  */
1939       *text_bytes = SBYTES (string);
1940       *stringp = true;
1941       *freep = false;
1942       return SDATA (string);
1943     }
1944 
1945   setup_coding_system (coding_system, &coding);
1946   coding.mode |= (CODING_MODE_SAFE_ENCODING | CODING_MODE_LAST_BLOCK);
1947   /* We suppress producing escape sequences for composition.  */
1948   coding.common_flags &= ~CODING_ANNOTATION_MASK;
1949   coding.destination = xnmalloc (SCHARS (string), 2);
1950   coding.dst_bytes = SCHARS (string) * 2;
1951   encode_coding_object (&coding, string, 0, 0,
1952 			SCHARS (string), SBYTES (string), Qnil);
1953   *text_bytes = coding.produced;
1954   *stringp = (result == 1 || !EQ (coding_system, Qcompound_text));
1955   *freep = true;
1956   return coding.destination;
1957 }
1958 
1959 
1960 /* Set the WM name to NAME for frame F. Also set the icon name.
1961    If the frame already has an icon name, use that, otherwise set the
1962    icon name to NAME.  */
1963 
1964 static void
x_set_name_internal(struct frame * f,Lisp_Object name)1965 x_set_name_internal (struct frame *f, Lisp_Object name)
1966 {
1967   if (FRAME_X_WINDOW (f))
1968     {
1969       block_input ();
1970       {
1971 	XTextProperty text, icon;
1972 	ptrdiff_t bytes;
1973 	bool stringp;
1974 	bool do_free_icon_value = false, do_free_text_value = false;
1975 	Lisp_Object coding_system;
1976 	Lisp_Object encoded_name;
1977 	Lisp_Object encoded_icon_name;
1978 
1979 	/* As ENCODE_UTF_8 may cause GC and relocation of string data,
1980 	   we use it before x_encode_text that may return string data.  */
1981 	encoded_name = ENCODE_UTF_8 (name);
1982 
1983 	coding_system = Qcompound_text;
1984 	/* Note: Encoding strategy
1985 
1986 	   We encode NAME by compound-text and use "COMPOUND-TEXT" in
1987 	   text.encoding.  But, there are non-internationalized window
1988 	   managers which don't support that encoding.  So, if NAME
1989 	   contains only ASCII and 8859-1 characters, encode it by
1990 	   iso-latin-1, and use "STRING" in text.encoding hoping that
1991 	   such window managers at least analyze this format correctly,
1992 	   i.e. treat 8-bit bytes as 8859-1 characters.
1993 
1994 	   We may also be able to use "UTF8_STRING" in text.encoding
1995 	   in the future which can encode all Unicode characters.
1996 	   But, for the moment, there's no way to know that the
1997 	   current window manager supports it or not.
1998 
1999 	   Either way, we also set the _NET_WM_NAME and _NET_WM_ICON_NAME
2000 	   properties.  Per the EWMH specification, those two properties
2001 	   are always UTF8_STRING.  This matches what gtk_window_set_title()
2002 	   does in the USE_GTK case. */
2003 	text.value = x_encode_text (name, coding_system, &bytes,
2004 				    &stringp, &do_free_text_value);
2005 	text.encoding = (stringp ? XA_STRING
2006 			 : FRAME_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2007 	text.format = 8;
2008 	text.nitems = bytes;
2009 
2010 	if (!STRINGP (f->icon_name))
2011 	  {
2012 	    icon = text;
2013 	    encoded_icon_name = encoded_name;
2014 	  }
2015 	else
2016 	  {
2017 	    /* See the above comment "Note: Encoding strategy".  */
2018 	    icon.value = x_encode_text (f->icon_name, coding_system, &bytes,
2019 					&stringp, &do_free_icon_value);
2020 	    icon.encoding = (stringp ? XA_STRING
2021 			     : FRAME_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2022 	    icon.format = 8;
2023 	    icon.nitems = bytes;
2024 
2025 	    encoded_icon_name = ENCODE_UTF_8 (f->icon_name);
2026 	  }
2027 
2028 #ifdef USE_GTK
2029         gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
2030                               SSDATA (encoded_name));
2031 #else /* not USE_GTK */
2032 	XSetWMName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text);
2033 	XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
2034 			 FRAME_DISPLAY_INFO (f)->Xatom_net_wm_name,
2035 			 FRAME_DISPLAY_INFO (f)->Xatom_UTF8_STRING,
2036 			 8, PropModeReplace,
2037 			 SDATA (encoded_name),
2038 			 SBYTES (encoded_name));
2039 #endif /* not USE_GTK */
2040 
2041 	XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &icon);
2042 	XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
2043 			 FRAME_DISPLAY_INFO (f)->Xatom_net_wm_icon_name,
2044 			 FRAME_DISPLAY_INFO (f)->Xatom_UTF8_STRING,
2045 			 8, PropModeReplace,
2046 			 SDATA (encoded_icon_name),
2047 			 SBYTES (encoded_icon_name));
2048 
2049 	if (do_free_icon_value)
2050 	  xfree (icon.value);
2051 	if (do_free_text_value)
2052 	  xfree (text.value);
2053       }
2054       unblock_input ();
2055     }
2056 }
2057 
2058 /* Change the name of frame F to NAME.  If NAME is nil, set F's name to
2059        x_id_name.
2060 
2061    If EXPLICIT is true, that indicates that lisp code is setting the
2062        name; if NAME is a string, set F's name to NAME and set
2063        F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2064 
2065    If EXPLICIT is false, that indicates that Emacs redisplay code is
2066        suggesting a new name, which lisp code should override; if
2067        F->explicit_name is set, ignore the new name; otherwise, set it.  */
2068 
2069 static void
x_set_name(struct frame * f,Lisp_Object name,bool explicit)2070 x_set_name (struct frame *f, Lisp_Object name, bool explicit)
2071 {
2072   /* Make sure that requests from lisp code override requests from
2073      Emacs redisplay code.  */
2074   if (explicit)
2075     {
2076       /* If we're switching from explicit to implicit, we had better
2077 	 update the mode lines and thereby update the title.  */
2078       if (f->explicit_name && NILP (name))
2079 	update_mode_lines = 37;
2080 
2081       f->explicit_name = ! NILP (name);
2082     }
2083   else if (f->explicit_name)
2084     return;
2085 
2086   /* If NAME is nil, set the name to the x_id_name.  */
2087   if (NILP (name))
2088     {
2089       /* Check for no change needed in this very common case
2090 	 before we do any consing.  */
2091       if (!strcmp (FRAME_DISPLAY_INFO (f)->x_id_name,
2092 		   SSDATA (f->name)))
2093 	return;
2094       name = build_string (FRAME_DISPLAY_INFO (f)->x_id_name);
2095     }
2096   else
2097     CHECK_STRING (name);
2098 
2099   /* Don't change the name if it's already NAME.  */
2100   if (! NILP (Fstring_equal (name, f->name)))
2101     return;
2102 
2103   fset_name (f, name);
2104 
2105   /* For setting the frame title, the title parameter should override
2106      the name parameter.  */
2107   if (! NILP (f->title))
2108     name = f->title;
2109 
2110   x_set_name_internal (f, name);
2111 }
2112 
2113 /* This function should be called when the user's lisp code has
2114    specified a name for the frame; the name will override any set by the
2115    redisplay code.  */
2116 static void
x_explicitly_set_name(struct frame * f,Lisp_Object arg,Lisp_Object oldval)2117 x_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
2118 {
2119   x_set_name (f, arg, true);
2120 }
2121 
2122 /* This function should be called by Emacs redisplay code to set the
2123    name; names set this way will never override names set by the user's
2124    lisp code.  */
2125 void
x_implicitly_set_name(struct frame * f,Lisp_Object arg,Lisp_Object oldval)2126 x_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
2127 {
2128   x_set_name (f, arg, false);
2129 }
2130 
2131 /* Change the title of frame F to NAME.
2132    If NAME is nil, use the frame name as the title.  */
2133 
2134 static void
x_set_title(struct frame * f,Lisp_Object name,Lisp_Object old_name)2135 x_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name)
2136 {
2137   /* Don't change the title if it's already NAME.  */
2138   if (EQ (name, f->title))
2139     return;
2140 
2141   update_mode_lines = 38;
2142 
2143   fset_title (f, name);
2144 
2145   if (NILP (name))
2146     name = f->name;
2147   else
2148     CHECK_STRING (name);
2149 
2150   x_set_name_internal (f, name);
2151 }
2152 
2153 void
x_set_scroll_bar_default_width(struct frame * f)2154 x_set_scroll_bar_default_width (struct frame *f)
2155 {
2156   int unit = FRAME_COLUMN_WIDTH (f);
2157 #ifdef USE_TOOLKIT_SCROLL_BARS
2158 #ifdef USE_GTK
2159   int minw = xg_get_default_scrollbar_width (f);
2160 #else
2161   int minw = 16;
2162 #endif
2163   /* A minimum width of 14 doesn't look good for toolkit scroll bars.  */
2164   FRAME_CONFIG_SCROLL_BAR_COLS (f) = (minw + unit - 1) / unit;
2165   FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = minw;
2166 #else
2167   /* The width of a non-toolkit scrollbar is 14 pixels.  */
2168   FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit;
2169   FRAME_CONFIG_SCROLL_BAR_WIDTH (f)
2170     = FRAME_CONFIG_SCROLL_BAR_COLS (f) * unit;
2171 #endif
2172 }
2173 
2174 void
x_set_scroll_bar_default_height(struct frame * f)2175 x_set_scroll_bar_default_height (struct frame *f)
2176 {
2177   int height = FRAME_LINE_HEIGHT (f);
2178 #ifdef USE_TOOLKIT_SCROLL_BARS
2179 #ifdef USE_GTK
2180   int min_height = xg_get_default_scrollbar_height (f);
2181 #else
2182   int min_height = 16;
2183 #endif
2184   /* A minimum height of 14 doesn't look good for toolkit scroll bars.  */
2185   FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = min_height;
2186   FRAME_CONFIG_SCROLL_BAR_LINES (f) = (min_height + height - 1) / height;
2187 #else
2188   /* The height of a non-toolkit scrollbar is 14 pixels.  */
2189   FRAME_CONFIG_SCROLL_BAR_LINES (f) = (14 + height - 1) / height;
2190 
2191   /* Use all of that space (aside from required margins) for the
2192      scroll bar.  */
2193   FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = 14;
2194 #endif
2195 }
2196 
2197 
2198 /* Record in frame F the specified or default value according to ALIST
2199    of the parameter named PROP (a Lisp symbol).  If no value is
2200    specified for PROP, look for an X default for XPROP on the frame
2201    named NAME.  If that is not found either, use the value DEFLT.  */
2202 
2203 static Lisp_Object
x_default_scroll_bar_color_parameter(struct frame * f,Lisp_Object alist,Lisp_Object prop,const char * xprop,const char * xclass,bool foreground_p)2204 x_default_scroll_bar_color_parameter (struct frame *f,
2205 				      Lisp_Object alist, Lisp_Object prop,
2206 				      const char *xprop, const char *xclass,
2207 				      bool foreground_p)
2208 {
2209   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
2210   Lisp_Object tem;
2211 
2212   tem = gui_display_get_arg (dpyinfo, alist, prop, xprop, xclass,
2213                              RES_TYPE_STRING);
2214   if (EQ (tem, Qunbound))
2215     {
2216 #ifdef USE_TOOLKIT_SCROLL_BARS
2217 
2218       /* See if an X resource for the scroll bar color has been
2219 	 specified.  */
2220       AUTO_STRING (foreground, "foreground");
2221       AUTO_STRING (background, "foreground");
2222       AUTO_STRING (verticalScrollBar, "verticalScrollBar");
2223       tem = (gui_display_get_resource
2224 	     (dpyinfo, foreground_p ? foreground : background,
2225 	      empty_unibyte_string,
2226 	      verticalScrollBar,
2227 	      empty_unibyte_string));
2228       if (!STRINGP (tem))
2229 	{
2230 	  /* If nothing has been specified, scroll bars will use a
2231 	     toolkit-dependent default.  Because these defaults are
2232 	     difficult to get at without actually creating a scroll
2233 	     bar, use nil to indicate that no color has been
2234 	     specified.  */
2235 	  tem = Qnil;
2236 	}
2237 
2238 #else /* not USE_TOOLKIT_SCROLL_BARS */
2239 
2240       tem = Qnil;
2241 
2242 #endif /* not USE_TOOLKIT_SCROLL_BARS */
2243     }
2244 
2245   AUTO_FRAME_ARG (arg, prop, tem);
2246   gui_set_frame_parameters (f, arg);
2247   return tem;
2248 }
2249 
2250 
2251 
2252 
2253 #ifdef USE_X_TOOLKIT
2254 
2255 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
2256    WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them.  (They may
2257    already be present because of the toolkit (Motif adds some of them,
2258    for example, but Xt doesn't).  */
2259 
2260 static void
hack_wm_protocols(struct frame * f,Widget widget)2261 hack_wm_protocols (struct frame *f, Widget widget)
2262 {
2263   Display *dpy = XtDisplay (widget);
2264   Window w = XtWindow (widget);
2265   bool need_delete = true;
2266   bool need_focus = true;
2267   bool need_save = true;
2268 
2269   block_input ();
2270   {
2271     Atom type;
2272     unsigned char *catoms;
2273     int format = 0;
2274     unsigned long nitems = 0;
2275     unsigned long bytes_after;
2276 
2277     if ((XGetWindowProperty (dpy, w,
2278 			     FRAME_DISPLAY_INFO (f)->Xatom_wm_protocols,
2279 			     0, 100, False, XA_ATOM,
2280 			     &type, &format, &nitems, &bytes_after,
2281 			     &catoms)
2282 	 == Success)
2283 	&& format == 32 && type == XA_ATOM)
2284       {
2285 	Atom *atoms = (Atom *) catoms;
2286 	while (nitems > 0)
2287 	  {
2288 	    nitems--;
2289 	    if (atoms[nitems]
2290 		== FRAME_DISPLAY_INFO (f)->Xatom_wm_delete_window)
2291 	      need_delete = false;
2292 	    else if (atoms[nitems]
2293 		     == FRAME_DISPLAY_INFO (f)->Xatom_wm_take_focus)
2294 	      need_focus = false;
2295 	    else if (atoms[nitems]
2296 		     == FRAME_DISPLAY_INFO (f)->Xatom_wm_save_yourself)
2297 	      need_save = false;
2298 	  }
2299       }
2300     if (catoms)
2301       XFree (catoms);
2302   }
2303   {
2304     Atom props[10];
2305     int count = 0;
2306     if (need_delete)
2307       props[count++] = FRAME_DISPLAY_INFO (f)->Xatom_wm_delete_window;
2308     if (need_focus)
2309       props[count++] = FRAME_DISPLAY_INFO (f)->Xatom_wm_take_focus;
2310     if (need_save)
2311       props[count++] = FRAME_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
2312     if (count)
2313       XChangeProperty (dpy, w, FRAME_DISPLAY_INFO (f)->Xatom_wm_protocols,
2314 		       XA_ATOM, 32, PropModeAppend,
2315 		       (unsigned char *) props, count);
2316   }
2317   unblock_input ();
2318 }
2319 #endif
2320 
2321 
2322 
2323 /* Support routines for XIC (X Input Context).  */
2324 
2325 #ifdef HAVE_X_I18N
2326 
2327 static XFontSet xic_create_xfontset (struct frame *);
2328 static XIMStyle best_xim_style (XIMStyles *);
2329 
2330 
2331 /* Supported XIM styles, ordered by preference.  */
2332 
2333 static const XIMStyle supported_xim_styles[] =
2334 {
2335   XIMPreeditPosition | XIMStatusArea,
2336   XIMPreeditPosition | XIMStatusNothing,
2337   XIMPreeditPosition | XIMStatusNone,
2338   XIMPreeditNothing | XIMStatusArea,
2339   XIMPreeditNothing | XIMStatusNothing,
2340   XIMPreeditNothing | XIMStatusNone,
2341   XIMPreeditNone | XIMStatusArea,
2342   XIMPreeditNone | XIMStatusNothing,
2343   XIMPreeditNone | XIMStatusNone,
2344   0,
2345 };
2346 
2347 
2348 #if defined HAVE_X_WINDOWS && defined USE_X_TOOLKIT
2349 /* Create an X fontset on frame F with base font name BASE_FONTNAME.  */
2350 
2351 static const char xic_default_fontset[] = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
2352 
2353 /* Create an Xt fontset spec from the name of a base font.
2354    If `motif' is True use the Motif syntax.  */
2355 char *
xic_create_fontsetname(const char * base_fontname,bool motif)2356 xic_create_fontsetname (const char *base_fontname, bool motif)
2357 {
2358   const char *sep = motif ? ";" : ",";
2359   char *fontsetname;
2360   char *z;
2361 
2362   /* Make a fontset name from the base font name.  */
2363   if (xic_default_fontset == base_fontname)
2364     {
2365       /* There is no base font name, use the default.  */
2366       fontsetname = xmalloc (strlen (base_fontname) + 2);
2367       z = stpcpy (fontsetname, base_fontname);
2368     }
2369   else
2370     {
2371       /* Make a fontset name from the base font name.
2372 	 The font set will be made of the following elements:
2373 	 - the base font.
2374 	 - the base font where the charset spec is replaced by -*-*.
2375 	 - the same but with the family also replaced with -*-*-.  */
2376       const char *p = base_fontname;
2377       ptrdiff_t i;
2378 
2379       for (i = 0; *p; p++)
2380 	if (*p == '-') i++;
2381       if (i != 14)
2382 	{
2383 	  /* As the font name doesn't conform to XLFD, we can't
2384 	     modify it to generalize it to allcs and allfamilies.
2385 	     Use the specified font plus the default.  */
2386 	  fontsetname = xmalloc (strlen (base_fontname)
2387 				 + strlen (xic_default_fontset) + 3);
2388 	  z = stpcpy (fontsetname, base_fontname);
2389 	  z = stpcpy (z, sep);
2390 	  z = stpcpy (z, xic_default_fontset);
2391 	}
2392       else
2393 	{
2394 	  ptrdiff_t len;
2395 	  const char *p1 = NULL, *p2 = NULL, *p3 = NULL;
2396 	  char *font_allcs = NULL;
2397 	  char *font_allfamilies = NULL;
2398 	  char *font_all = NULL;
2399 	  const char *allcs = "*-*-*-*-*-*-*";
2400 	  const char *allfamilies = "-*-*-";
2401 	  const char *all = "*-*-*-*-";
2402 	  char *base;
2403 
2404 	  for (i = 0, p = base_fontname; i < 8; p++)
2405 	    {
2406 	      if (*p == '-')
2407 		{
2408 		  i++;
2409 		  if (i == 3)
2410 		    p1 = p + 1;
2411 		  else if (i == 7)
2412 		    p2 = p + 1;
2413 		  else if (i == 6)
2414 		    p3 = p + 1;
2415 		}
2416 	    }
2417 	  /* If base_fontname specifies ADSTYLE, make it a
2418 	     wildcard.  */
2419 	  if (*p3 != '*')
2420 	    {
2421 	      ptrdiff_t diff = (p2 - p3) - 2;
2422 
2423 	      base = alloca (strlen (base_fontname) + 1);
2424 	      memcpy (base, base_fontname, p3 - base_fontname);
2425 	      base[p3 - base_fontname] = '*';
2426 	      base[(p3 - base_fontname) + 1] = '-';
2427 	      strcpy (base + (p3 - base_fontname) + 2, p2);
2428 	      p = base + (p - base_fontname) - diff;
2429 	      p1 = base + (p1 - base_fontname);
2430 	      p2 = base + (p2 - base_fontname) - diff;
2431 	      base_fontname = base;
2432 	    }
2433 
2434 	  /* Build the font spec that matches all charsets.  */
2435 	  len = p - base_fontname + strlen (allcs) + 1;
2436 	  font_allcs = alloca (len);
2437 	  memcpy (font_allcs, base_fontname, p - base_fontname);
2438 	  strcpy (font_allcs + (p - base_fontname), allcs);
2439 
2440 	  /* Build the font spec that matches all families and
2441 	     add-styles.  */
2442 	  len = p - p1 + strlen (allcs) + strlen (allfamilies) + 1;
2443 	  font_allfamilies = alloca (len);
2444 	  strcpy (font_allfamilies, allfamilies);
2445 	  memcpy (font_allfamilies + strlen (allfamilies), p1, p - p1);
2446 	  strcpy (font_allfamilies + strlen (allfamilies) + (p - p1), allcs);
2447 
2448 	  /* Build the font spec that matches all.  */
2449 	  len = p - p2 + strlen (allcs) + strlen (all) + strlen (allfamilies) + 1;
2450 	  font_all = alloca (len);
2451 	  z = stpcpy (font_all, allfamilies);
2452 	  z = stpcpy (z, all);
2453 	  memcpy (z, p2, p - p2);
2454 	  strcpy (z + (p - p2), allcs);
2455 
2456 	  /* Build the actual font set name.  */
2457 	  len = strlen (base_fontname) + strlen (font_allcs)
2458 	    + strlen (font_allfamilies) + strlen (font_all) + 5;
2459 	  fontsetname = xmalloc (len);
2460 	  z = stpcpy (fontsetname, base_fontname);
2461 	  z = stpcpy (z, sep);
2462 	  z = stpcpy (z, font_allcs);
2463 	  z = stpcpy (z, sep);
2464 	  z = stpcpy (z, font_allfamilies);
2465 	  z = stpcpy (z, sep);
2466 	  z = stpcpy (z, font_all);
2467 	}
2468     }
2469   if (motif)
2470     strcpy (z, ":");
2471   return fontsetname;
2472 }
2473 #endif /* HAVE_X_WINDOWS && USE_X_TOOLKIT */
2474 
2475 #ifdef DEBUG_XIC_FONTSET
2476 static void
print_fontset_result(XFontSet xfs,char * name,char ** missing_list,int missing_count)2477 print_fontset_result (XFontSet xfs, char *name, char **missing_list,
2478 		      int missing_count)
2479 {
2480   if (xfs)
2481     fprintf (stderr, "XIC Fontset created: %s\n", name);
2482   else
2483     {
2484       fprintf (stderr, "XIC Fontset failed: %s\n", name);
2485       while (missing_count-- > 0)
2486 	{
2487 	  fprintf (stderr, "  missing: %s\n", *missing_list);
2488 	  missing_list++;
2489 	}
2490     }
2491 
2492 }
2493 #endif
2494 
2495 static XFontSet
xic_create_xfontset(struct frame * f)2496 xic_create_xfontset (struct frame *f)
2497 {
2498   XFontSet xfs = NULL;
2499   struct font *font = FRAME_FONT (f);
2500   int pixel_size = font->pixel_size;
2501   Lisp_Object rest, frame;
2502 
2503   /* See if there is another frame already using same fontset.  */
2504   FOR_EACH_FRAME (rest, frame)
2505     {
2506       struct frame *cf = XFRAME (frame);
2507 
2508       if (cf != f && FRAME_LIVE_P (f) && FRAME_X_P (cf)
2509           && FRAME_DISPLAY_INFO (cf) == FRAME_DISPLAY_INFO (f)
2510 	  && FRAME_FONT (f)
2511 	  && FRAME_FONT (f)->pixel_size == pixel_size)
2512         {
2513           xfs = FRAME_XIC_FONTSET (cf);
2514           break;
2515         }
2516     }
2517 
2518   if (! xfs)
2519     {
2520       char buf[256];
2521       char **missing_list;
2522       int missing_count;
2523       char *def_string;
2524       const char *xlfd_format = "-*-*-medium-r-normal--%d-*-*-*-*-*";
2525 
2526       sprintf (buf, xlfd_format, pixel_size);
2527       missing_list = NULL;
2528       xfs = XCreateFontSet (FRAME_X_DISPLAY (f), buf,
2529 			    &missing_list, &missing_count, &def_string);
2530 #ifdef DEBUG_XIC_FONTSET
2531       print_fontset_result (xfs, buf, missing_list, missing_count);
2532 #endif
2533       if (missing_list)
2534 	XFreeStringList (missing_list);
2535       if (! xfs)
2536 	{
2537 	  /* List of pixel sizes most likely available.  Find one that
2538 	     is closest to pixel_size.  */
2539 	  int sizes[] = {0, 8, 10, 11, 12, 14, 17, 18, 20, 24, 26, 34, 0};
2540 	  int *smaller, *larger;
2541 
2542 	  for (smaller = sizes; smaller[1]; smaller++)
2543 	    if (smaller[1] >= pixel_size)
2544 	      break;
2545 	  larger = smaller + 1;
2546 	  if (*larger == pixel_size)
2547 	    larger++;
2548 	  while (*smaller || *larger)
2549 	    {
2550 	      int this_size;
2551 
2552 	      if (! *larger)
2553 		this_size = *smaller--;
2554 	      else if (! *smaller)
2555 		this_size = *larger++;
2556 	      else if (pixel_size - *smaller < *larger - pixel_size)
2557 		this_size = *smaller--;
2558 	      else
2559 		this_size = *larger++;
2560 	      sprintf (buf, xlfd_format, this_size);
2561 	      missing_list = NULL;
2562 	      xfs = XCreateFontSet (FRAME_X_DISPLAY (f), buf,
2563 				    &missing_list, &missing_count, &def_string);
2564 #ifdef DEBUG_XIC_FONTSET
2565 	      print_fontset_result (xfs, buf, missing_list, missing_count);
2566 #endif
2567 	      if (missing_list)
2568 		XFreeStringList (missing_list);
2569 	      if (xfs)
2570 		break;
2571 	    }
2572 	}
2573       if (! xfs)
2574 	{
2575 	  const char *last_resort = "-*-*-*-r-normal--*-*-*-*-*-*";
2576 
2577 	  missing_list = NULL;
2578 	  xfs = XCreateFontSet (FRAME_X_DISPLAY (f), last_resort,
2579 				&missing_list, &missing_count, &def_string);
2580 #ifdef DEBUG_XIC_FONTSET
2581 	  print_fontset_result (xfs, last_resort, missing_list, missing_count);
2582 #endif
2583 	  if (missing_list)
2584 	    XFreeStringList (missing_list);
2585 	}
2586 
2587     }
2588 
2589   return xfs;
2590 }
2591 
2592 /* Free the X fontset of frame F if it is the last frame using it.  */
2593 
2594 void
xic_free_xfontset(struct frame * f)2595 xic_free_xfontset (struct frame *f)
2596 {
2597   Lisp_Object rest, frame;
2598   bool shared_p = false;
2599 
2600   if (!FRAME_XIC_FONTSET (f))
2601     return;
2602 
2603   /* See if there is another frame sharing the same fontset.  */
2604   FOR_EACH_FRAME (rest, frame)
2605     {
2606       struct frame *cf = XFRAME (frame);
2607       if (cf != f && FRAME_LIVE_P (f) && FRAME_X_P (cf)
2608           && FRAME_DISPLAY_INFO (cf) == FRAME_DISPLAY_INFO (f)
2609           && FRAME_XIC_FONTSET (cf) == FRAME_XIC_FONTSET (f))
2610         {
2611           shared_p = true;
2612           break;
2613         }
2614     }
2615 
2616   if (!shared_p)
2617     /* The fontset is not used anymore.  It is safe to free it.  */
2618     XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
2619 
2620   FRAME_XIC_FONTSET (f) = NULL;
2621 }
2622 
2623 
2624 /* Value is the best input style, given user preferences USER (already
2625    checked to be supported by Emacs), and styles supported by the
2626    input method XIM.  */
2627 
2628 static XIMStyle
best_xim_style(XIMStyles * xim)2629 best_xim_style (XIMStyles *xim)
2630 {
2631   int i, j;
2632   int nr_supported = ARRAYELTS (supported_xim_styles);
2633 
2634   for (i = 0; i < nr_supported; ++i)
2635     for (j = 0; j < xim->count_styles; ++j)
2636       if (supported_xim_styles[i] == xim->supported_styles[j])
2637 	return supported_xim_styles[i];
2638 
2639   /* Return the default style.  */
2640   return XIMPreeditNothing | XIMStatusNothing;
2641 }
2642 
2643 /* Create XIC for frame F. */
2644 
2645 void
create_frame_xic(struct frame * f)2646 create_frame_xic (struct frame *f)
2647 {
2648   XIM xim;
2649   XIC xic = NULL;
2650   XFontSet xfs = NULL;
2651   XVaNestedList status_attr = NULL;
2652   XVaNestedList preedit_attr = NULL;
2653   XRectangle s_area;
2654   XPoint spot;
2655   XIMStyle xic_style;
2656 
2657   if (FRAME_XIC (f))
2658     goto out;
2659 
2660   xim = FRAME_X_XIM (f);
2661   if (!xim || ! FRAME_X_XIM_STYLES(f))
2662     goto out;
2663 
2664   /* Determine XIC style.  */
2665   xic_style = best_xim_style (FRAME_X_XIM_STYLES (f));
2666 
2667   /* Create X fontset. */
2668   if (xic_style & (XIMPreeditPosition | XIMStatusArea))
2669     {
2670       xfs = xic_create_xfontset (f);
2671       if (!xfs)
2672         goto out;
2673 
2674       FRAME_XIC_FONTSET (f) = xfs;
2675     }
2676 
2677   if (xic_style & XIMPreeditPosition)
2678     {
2679       spot.x = 0; spot.y = 1;
2680       preedit_attr = XVaCreateNestedList (0,
2681 					  XNFontSet, xfs,
2682 					  XNForeground,
2683 					  FRAME_FOREGROUND_PIXEL (f),
2684 					  XNBackground,
2685 					  FRAME_BACKGROUND_PIXEL (f),
2686 					  (xic_style & XIMPreeditPosition
2687 					   ? XNSpotLocation
2688 					   : NULL),
2689 					  &spot,
2690 					  NULL);
2691 
2692       if (!preedit_attr)
2693         goto out;
2694     }
2695 
2696   if (xic_style & XIMStatusArea)
2697     {
2698       s_area.x = 0; s_area.y = 0; s_area.width = 1; s_area.height = 1;
2699       status_attr = XVaCreateNestedList (0,
2700                                          XNArea,
2701                                          &s_area,
2702                                          XNFontSet,
2703                                          xfs,
2704                                          XNForeground,
2705                                          FRAME_FOREGROUND_PIXEL (f),
2706                                          XNBackground,
2707                                          FRAME_BACKGROUND_PIXEL (f),
2708                                          NULL);
2709 
2710       if (!status_attr)
2711         goto out;
2712     }
2713 
2714   if (preedit_attr && status_attr)
2715     xic = XCreateIC (xim,
2716                      XNInputStyle, xic_style,
2717                      XNClientWindow, FRAME_X_WINDOW (f),
2718                      XNFocusWindow, FRAME_X_WINDOW (f),
2719                      XNStatusAttributes, status_attr,
2720                      XNPreeditAttributes, preedit_attr,
2721                      NULL);
2722   else if (preedit_attr)
2723     xic = XCreateIC (xim,
2724                      XNInputStyle, xic_style,
2725                      XNClientWindow, FRAME_X_WINDOW (f),
2726                      XNFocusWindow, FRAME_X_WINDOW (f),
2727                      XNPreeditAttributes, preedit_attr,
2728                      NULL);
2729   else if (status_attr)
2730     xic = XCreateIC (xim,
2731                      XNInputStyle, xic_style,
2732                      XNClientWindow, FRAME_X_WINDOW (f),
2733                      XNFocusWindow, FRAME_X_WINDOW (f),
2734                      XNStatusAttributes, status_attr,
2735                      NULL);
2736   else
2737     xic = XCreateIC (xim,
2738                      XNInputStyle, xic_style,
2739                      XNClientWindow, FRAME_X_WINDOW (f),
2740                      XNFocusWindow, FRAME_X_WINDOW (f),
2741                      NULL);
2742 
2743   if (!xic)
2744     goto out;
2745 
2746   FRAME_XIC (f) = xic;
2747   FRAME_XIC_STYLE (f) = xic_style;
2748   xfs = NULL; /* Don't free below.  */
2749 
2750  out:
2751 
2752   if (xfs)
2753     free_frame_xic (f);
2754 
2755   if (preedit_attr)
2756     XFree (preedit_attr);
2757 
2758   if (status_attr)
2759     XFree (status_attr);
2760 }
2761 
2762 
2763 /* Destroy XIC and free XIC fontset of frame F, if any. */
2764 
2765 void
free_frame_xic(struct frame * f)2766 free_frame_xic (struct frame *f)
2767 {
2768   if (FRAME_XIC (f) == NULL)
2769     return;
2770 
2771   XDestroyIC (FRAME_XIC (f));
2772   xic_free_xfontset (f);
2773 
2774   FRAME_XIC (f) = NULL;
2775 }
2776 
2777 
2778 /* Place preedit area for XIC of window W's frame to specified
2779    pixel position X/Y.  X and Y are relative to window W.  */
2780 
2781 void
xic_set_preeditarea(struct window * w,int x,int y)2782 xic_set_preeditarea (struct window *w, int x, int y)
2783 {
2784   struct frame *f = XFRAME (w->frame);
2785   XVaNestedList attr;
2786   XPoint spot;
2787 
2788   spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x) + WINDOW_LEFT_FRINGE_WIDTH (w);
2789   spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f));
2790   attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL);
2791   XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
2792   XFree (attr);
2793 }
2794 
2795 
2796 /* Place status area for XIC in bottom right corner of frame F.. */
2797 
2798 void
xic_set_statusarea(struct frame * f)2799 xic_set_statusarea (struct frame *f)
2800 {
2801   XIC xic = FRAME_XIC (f);
2802   XVaNestedList attr;
2803   XRectangle area;
2804   XRectangle *needed;
2805 
2806   /* Negotiate geometry of status area.  If input method has existing
2807      status area, use its current size.  */
2808   area.x = area.y = area.width = area.height = 0;
2809   attr = XVaCreateNestedList (0, XNAreaNeeded, &area, NULL);
2810   XSetICValues (xic, XNStatusAttributes, attr, NULL);
2811   XFree (attr);
2812 
2813   attr = XVaCreateNestedList (0, XNAreaNeeded, &needed, NULL);
2814   XGetICValues (xic, XNStatusAttributes, attr, NULL);
2815   XFree (attr);
2816 
2817   if (needed->width == 0) /* Use XNArea instead of XNAreaNeeded */
2818     {
2819       attr = XVaCreateNestedList (0, XNArea, &needed, NULL);
2820       XGetICValues (xic, XNStatusAttributes, attr, NULL);
2821       XFree (attr);
2822     }
2823 
2824   area.width  = needed->width;
2825   area.height = needed->height;
2826   area.x = FRAME_PIXEL_WIDTH (f) - area.width - FRAME_INTERNAL_BORDER_WIDTH (f);
2827   area.y = (FRAME_PIXEL_HEIGHT (f) - area.height
2828 	    - FRAME_MENUBAR_HEIGHT (f)
2829 	    - FRAME_TOOLBAR_TOP_HEIGHT (f)
2830             - FRAME_INTERNAL_BORDER_WIDTH (f));
2831   XFree (needed);
2832 
2833   attr = XVaCreateNestedList (0, XNArea, &area, NULL);
2834   XSetICValues (xic, XNStatusAttributes, attr, NULL);
2835   XFree (attr);
2836 }
2837 
2838 
2839 /* Set X fontset for XIC of frame F, using base font name
2840    BASE_FONTNAME.  Called when a new Emacs fontset is chosen.  */
2841 
2842 void
xic_set_xfontset(struct frame * f,const char * base_fontname)2843 xic_set_xfontset (struct frame *f, const char *base_fontname)
2844 {
2845   XVaNestedList attr;
2846   XFontSet xfs;
2847 
2848   xic_free_xfontset (f);
2849 
2850   xfs = xic_create_xfontset (f);
2851 
2852   attr = XVaCreateNestedList (0, XNFontSet, xfs, NULL);
2853   if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
2854     XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
2855   if (FRAME_XIC_STYLE (f) & XIMStatusArea)
2856     XSetICValues (FRAME_XIC (f), XNStatusAttributes, attr, NULL);
2857   XFree (attr);
2858 
2859   FRAME_XIC_FONTSET (f) = xfs;
2860 }
2861 
2862 #endif /* HAVE_X_I18N */
2863 
2864 
2865 
2866 
2867 void
x_mark_frame_dirty(struct frame * f)2868 x_mark_frame_dirty (struct frame *f)
2869 {
2870   if (FRAME_X_DOUBLE_BUFFERED_P (f) && !FRAME_X_NEED_BUFFER_FLIP (f))
2871     FRAME_X_NEED_BUFFER_FLIP (f) = true;
2872 }
2873 
2874 static void
set_up_x_back_buffer(struct frame * f)2875 set_up_x_back_buffer (struct frame *f)
2876 {
2877 #ifdef HAVE_XDBE
2878   block_input ();
2879   if (FRAME_X_WINDOW (f) && !FRAME_X_DOUBLE_BUFFERED_P (f))
2880     {
2881 #ifdef USE_CAIRO
2882       x_cr_destroy_frame_context (f);
2883 #endif
2884       FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
2885       if (FRAME_DISPLAY_INFO (f)->supports_xdbe)
2886         {
2887           /* If allocating a back buffer fails, either because the
2888              server ran out of memory or we don't have the right kind
2889              of visual, just use single-buffered rendering.  */
2890           x_catch_errors (FRAME_X_DISPLAY (f));
2891           FRAME_X_RAW_DRAWABLE (f) = XdbeAllocateBackBufferName (
2892             FRAME_X_DISPLAY (f),
2893             FRAME_X_WINDOW (f),
2894             XdbeCopied);
2895           if (x_had_errors_p (FRAME_X_DISPLAY (f)))
2896             FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
2897           x_uncatch_errors_after_check ();
2898         }
2899     }
2900   unblock_input ();
2901 #endif
2902 }
2903 
2904 void
tear_down_x_back_buffer(struct frame * f)2905 tear_down_x_back_buffer (struct frame *f)
2906 {
2907 #ifdef HAVE_XDBE
2908   block_input ();
2909   if (FRAME_X_WINDOW (f) && FRAME_X_DOUBLE_BUFFERED_P (f))
2910     {
2911       if (FRAME_X_DOUBLE_BUFFERED_P (f))
2912         {
2913 #ifdef USE_CAIRO
2914 	  x_cr_destroy_frame_context (f);
2915 #endif
2916           XdbeDeallocateBackBufferName (FRAME_X_DISPLAY (f),
2917                                         FRAME_X_DRAWABLE (f));
2918           FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
2919         }
2920     }
2921   unblock_input ();
2922 #endif
2923 }
2924 
2925 /* Set up double buffering if the frame parameters don't prohibit
2926    it.  */
2927 void
initial_set_up_x_back_buffer(struct frame * f)2928 initial_set_up_x_back_buffer (struct frame *f)
2929 {
2930   block_input ();
2931   eassert (FRAME_X_WINDOW (f));
2932   FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
2933   if (NILP (CDR (Fassq (Qinhibit_double_buffering, f->param_alist))))
2934     set_up_x_back_buffer (f);
2935   unblock_input ();
2936 }
2937 
2938 #ifdef USE_X_TOOLKIT
2939 
2940 /* Create and set up the X widget for frame F.  */
2941 
2942 static void
x_window(struct frame * f,long window_prompting)2943 x_window (struct frame *f, long window_prompting)
2944 {
2945   XClassHint class_hints;
2946   XSetWindowAttributes attributes;
2947   unsigned long attribute_mask;
2948   Widget shell_widget;
2949   Widget pane_widget;
2950   Widget frame_widget;
2951   Arg al[25];
2952   int ac;
2953 
2954   block_input ();
2955 
2956   /* Use the resource name as the top-level widget name
2957      for looking up resources.  Make a non-Lisp copy
2958      for the window manager, so GC relocation won't bother it.
2959 
2960      Elsewhere we specify the window name for the window manager.  */
2961   f->namebuf = xlispstrdup (Vx_resource_name);
2962 
2963   ac = 0;
2964   XtSetArg (al[ac], XtNallowShellResize, 1); ac++;
2965   XtSetArg (al[ac], XtNinput, 1); ac++;
2966   XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
2967   XtSetArg (al[ac], XtNborderWidth, f->border_width); ac++;
2968   XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
2969   XtSetArg (al[ac], XtNdepth, FRAME_DISPLAY_INFO (f)->n_planes); ac++;
2970   XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
2971   shell_widget = XtAppCreateShell (f->namebuf, EMACS_CLASS,
2972 				   applicationShellWidgetClass,
2973 				   FRAME_X_DISPLAY (f), al, ac);
2974 
2975   f->output_data.x->widget = shell_widget;
2976   /* maybe_set_screen_title_format (shell_widget); */
2977 
2978   pane_widget = lw_create_widget ("main", "pane", widget_id_tick++,
2979 				  NULL, shell_widget, False,
2980 				  NULL, NULL, NULL, NULL);
2981 
2982   ac = 0;
2983   XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
2984   XtSetArg (al[ac], XtNdepth, FRAME_DISPLAY_INFO (f)->n_planes); ac++;
2985   XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
2986   XtSetArg (al[ac], XtNborderWidth, 0); ac++;
2987   XtSetValues (pane_widget, al, ac);
2988   f->output_data.x->column_widget = pane_widget;
2989 
2990   /* mappedWhenManaged to false tells to the paned window to not map/unmap
2991      the emacs screen when changing menubar.  This reduces flickering.  */
2992 
2993   ac = 0;
2994   XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
2995   XtSetArg (al[ac], (char *) XtNshowGrip, 0); ac++;
2996   XtSetArg (al[ac], (char *) XtNallowResize, 1); ac++;
2997   XtSetArg (al[ac], (char *) XtNresizeToPreferred, 1); ac++;
2998   XtSetArg (al[ac], (char *) XtNemacsFrame, f); ac++;
2999   XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
3000   XtSetArg (al[ac], XtNdepth, FRAME_DISPLAY_INFO (f)->n_planes); ac++;
3001   XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
3002   XtSetArg (al[ac], XtNborderWidth, 0); ac++;
3003   frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass (), pane_widget,
3004 				 al, ac);
3005 
3006   f->output_data.x->edit_widget = frame_widget;
3007 
3008   XtManageChild (frame_widget);
3009 
3010   /* Do some needed geometry management.  */
3011   {
3012     Arg gal[3];
3013     int gac = 0;
3014     int extra_borders = 0;
3015     int menubar_size
3016       = (f->output_data.x->menubar_widget
3017 	 ? (f->output_data.x->menubar_widget->core.height
3018 	    + f->output_data.x->menubar_widget->core.border_width)
3019 	 : 0);
3020 
3021 #if false /* Experimentally, we now get the right results
3022 	     for -geometry -0-0 without this.  24 Aug 96, rms.  */
3023     if (FRAME_EXTERNAL_MENU_BAR (f))
3024       {
3025         Dimension ibw = 0;
3026         XtVaGetValues (pane_widget, XtNinternalBorderWidth, &ibw, NULL);
3027         menubar_size += ibw;
3028       }
3029 #endif
3030 
3031     FRAME_MENUBAR_HEIGHT (f) = menubar_size;
3032 
3033 #ifndef USE_LUCID
3034     /* Motif seems to need this amount added to the sizes
3035        specified for the shell widget.  The Athena/Lucid widgets don't.
3036        Both conclusions reached experimentally.  -- rms.  */
3037     XtVaGetValues (f->output_data.x->edit_widget, XtNinternalBorderWidth,
3038 		   &extra_borders, NULL);
3039     extra_borders *= 2;
3040 #endif
3041 
3042     f->shell_position = xmalloc (sizeof "=x++" + 4 * INT_STRLEN_BOUND (int));
3043 
3044     /* Convert our geometry parameters into a geometry string
3045        and specify it.
3046        Note that we do not specify here whether the position
3047        is a user-specified or program-specified one.
3048        We pass that information later, in x_wm_set_size_hint.  */
3049     {
3050       int left = f->left_pos;
3051       bool xneg = (window_prompting & XNegative) != 0;
3052       int top = f->top_pos;
3053       bool yneg = (window_prompting & YNegative) != 0;
3054       if (xneg)
3055 	left = -left;
3056       if (yneg)
3057 	top = -top;
3058 
3059       if (window_prompting & USPosition)
3060 	sprintf (f->shell_position, "=%dx%d%c%d%c%d",
3061 		 FRAME_PIXEL_WIDTH (f) + extra_borders,
3062 		 FRAME_PIXEL_HEIGHT (f) + menubar_size + extra_borders,
3063 		 (xneg ? '-' : '+'), left,
3064 		 (yneg ? '-' : '+'), top);
3065       else
3066         {
3067           sprintf (f->shell_position, "=%dx%d",
3068                    FRAME_PIXEL_WIDTH (f) + extra_borders,
3069                    FRAME_PIXEL_HEIGHT (f) + menubar_size + extra_borders);
3070 
3071           /* Setting x and y when the position is not specified in
3072              the geometry string will set program position in the WM hints.
3073              If Emacs had just one program position, we could set it in
3074              fallback resources, but since each make-frame call can specify
3075              different program positions, this is easier.  */
3076           XtSetArg (gal[gac], XtNx, left); gac++;
3077           XtSetArg (gal[gac], XtNy, top); gac++;
3078         }
3079     }
3080 
3081     XtSetArg (gal[gac], XtNgeometry, f->shell_position); gac++;
3082     XtSetValues (shell_widget, gal, gac);
3083   }
3084 
3085   XtManageChild (pane_widget);
3086   XtRealizeWidget (shell_widget);
3087 
3088   if (FRAME_X_EMBEDDED_P (f))
3089     XReparentWindow (FRAME_X_DISPLAY (f), XtWindow (shell_widget),
3090 		     f->output_data.x->parent_desc, 0, 0);
3091 
3092   FRAME_X_WINDOW (f) = XtWindow (frame_widget);
3093   initial_set_up_x_back_buffer (f);
3094   validate_x_resource_name ();
3095 
3096   class_hints.res_name = SSDATA (Vx_resource_name);
3097   class_hints.res_class = SSDATA (Vx_resource_class);
3098   XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints);
3099 
3100 #ifdef HAVE_X_I18N
3101   FRAME_XIC (f) = NULL;
3102   if (use_xim)
3103     create_frame_xic (f);
3104 #endif
3105 
3106   f->output_data.x->wm_hints.input = True;
3107   f->output_data.x->wm_hints.flags |= InputHint;
3108   XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3109 	       &f->output_data.x->wm_hints);
3110 
3111   hack_wm_protocols (f, shell_widget);
3112 
3113 #ifdef X_TOOLKIT_EDITRES
3114   XtAddEventHandler (shell_widget, 0, True, _XEditResCheckMessages, 0);
3115 #endif
3116 
3117   /* Do a stupid property change to force the server to generate a
3118      PropertyNotify event so that the event_stream server timestamp will
3119      be initialized to something relevant to the time we created the window.
3120      */
3121   XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
3122 		   FRAME_DISPLAY_INFO (f)->Xatom_wm_protocols,
3123 		   XA_ATOM, 32, PropModeAppend, NULL, 0);
3124 
3125   /* Make all the standard events reach the Emacs frame.  */
3126   attributes.event_mask = STANDARD_EVENT_SET;
3127 
3128 #ifdef HAVE_X_I18N
3129   if (FRAME_XIC (f))
3130     {
3131       /* XIM server might require some X events. */
3132       unsigned long fevent = NoEventMask;
3133       XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
3134       attributes.event_mask |= fevent;
3135     }
3136 #endif /* HAVE_X_I18N */
3137 
3138   attributes.override_redirect = FRAME_OVERRIDE_REDIRECT (f);
3139   attribute_mask = CWEventMask | CWOverrideRedirect;
3140   XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
3141 			   attribute_mask, &attributes);
3142 
3143   XtMapWidget (frame_widget);
3144 
3145   /* x_set_name normally ignores requests to set the name if the
3146      requested name is the same as the current name.  This is the one
3147      place where that assumption isn't correct; f->name is set, but
3148      the X server hasn't been told.  */
3149   {
3150     Lisp_Object name;
3151     bool explicit = f->explicit_name;
3152 
3153     f->explicit_name = false;
3154     name = f->name;
3155     fset_name (f, Qnil);
3156     x_set_name (f, name, explicit);
3157   }
3158 
3159   if (FRAME_UNDECORATED (f))
3160     {
3161       Display *dpy = FRAME_X_DISPLAY (f);
3162       PropMotifWmHints hints;
3163       Atom prop = XInternAtom (dpy, "_MOTIF_WM_HINTS", False);
3164 
3165       memset (&hints, 0, sizeof(hints));
3166       hints.flags = MWM_HINTS_DECORATIONS;
3167       hints.decorations = 0;
3168 
3169       /* For some reason the third and fourth arguments in the following
3170 	 call must be identical: In the corresponding XGetWindowProperty
3171 	 call in getMotifHints, xfwm has the third and seventh args both
3172 	 display_info->atoms[MOTIF_WM_HINTS].  Obviously, YMMV.   */
3173       XChangeProperty (dpy, FRAME_OUTER_WINDOW (f), prop, prop, 32,
3174 		       PropModeReplace, (unsigned char *) &hints,
3175 		       PROP_MOTIF_WM_HINTS_ELEMENTS);
3176     }
3177 
3178   XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3179 		 f->output_data.x->current_cursor
3180                  = f->output_data.x->text_cursor);
3181 
3182   unblock_input ();
3183 
3184   /* This is a no-op, except under Motif.  Make sure main areas are
3185      set to something reasonable, in case we get an error later.  */
3186   lw_set_main_areas (pane_widget, 0, frame_widget);
3187 }
3188 
3189 #else /* not USE_X_TOOLKIT */
3190 #ifdef USE_GTK
3191 static void
x_window(struct frame * f)3192 x_window (struct frame *f)
3193 {
3194   if (! xg_create_frame_widgets (f))
3195     error ("Unable to create window");
3196 
3197 #ifdef HAVE_X_I18N
3198   FRAME_XIC (f) = NULL;
3199   if (use_xim)
3200   {
3201     block_input ();
3202     create_frame_xic (f);
3203     if (FRAME_XIC (f))
3204       {
3205 	/* XIM server might require some X events. */
3206 	unsigned long fevent = NoEventMask;
3207 	XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
3208 
3209 	if (fevent != NoEventMask)
3210 	  {
3211 	    XSetWindowAttributes attributes;
3212 	    XWindowAttributes wattr;
3213 	    unsigned long attribute_mask;
3214 
3215 	    XGetWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3216 				  &wattr);
3217 	    attributes.event_mask = wattr.your_event_mask | fevent;
3218 	    attribute_mask = CWEventMask;
3219 	    XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3220 				     attribute_mask, &attributes);
3221 	  }
3222       }
3223     unblock_input ();
3224   }
3225 #endif
3226 }
3227 
3228 #else /*! USE_GTK */
3229 /* Create and set up the X window for frame F.  */
3230 
3231 static void
x_window(struct frame * f)3232 x_window (struct frame *f)
3233 {
3234   XClassHint class_hints;
3235   XSetWindowAttributes attributes;
3236   unsigned long attribute_mask;
3237 
3238   attributes.background_pixel = FRAME_BACKGROUND_PIXEL (f);
3239   attributes.border_pixel = f->output_data.x->border_pixel;
3240   attributes.bit_gravity = StaticGravity;
3241   attributes.backing_store = NotUseful;
3242   attributes.save_under = True;
3243   attributes.event_mask = STANDARD_EVENT_SET;
3244   attributes.colormap = FRAME_X_COLORMAP (f);
3245   attributes.override_redirect = FRAME_OVERRIDE_REDIRECT (f);
3246   attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask
3247 		    | CWOverrideRedirect | CWColormap);
3248 
3249   block_input ();
3250   FRAME_X_WINDOW (f)
3251     = XCreateWindow (FRAME_X_DISPLAY (f),
3252 		     f->output_data.x->parent_desc,
3253 		     f->left_pos,
3254 		     f->top_pos,
3255 		     FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f),
3256 		     f->border_width,
3257 		     CopyFromParent, /* depth */
3258 		     InputOutput, /* class */
3259 		     FRAME_X_VISUAL (f),
3260                      attribute_mask, &attributes);
3261   initial_set_up_x_back_buffer (f);
3262 
3263 #ifdef HAVE_X_I18N
3264   if (use_xim)
3265     {
3266       create_frame_xic (f);
3267       if (FRAME_XIC (f))
3268 	{
3269 	  /* XIM server might require some X events. */
3270 	  unsigned long fevent = NoEventMask;
3271 	  XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
3272 	  attributes.event_mask |= fevent;
3273 	  attribute_mask = CWEventMask;
3274 	  XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3275 				   attribute_mask, &attributes);
3276 	}
3277     }
3278 #endif /* HAVE_X_I18N */
3279 
3280   validate_x_resource_name ();
3281 
3282   class_hints.res_name = SSDATA (Vx_resource_name);
3283   class_hints.res_class = SSDATA (Vx_resource_class);
3284   XSetClassHint (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &class_hints);
3285 
3286   /* This indicates that we use the "Passive Input" input model.
3287      Unless we do this, we don't get the Focus{In,Out} events that we
3288      need to draw the cursor correctly.  Accursed bureaucrats.
3289    XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack);  */
3290 
3291   f->output_data.x->wm_hints.input = True;
3292   f->output_data.x->wm_hints.flags |= InputHint;
3293   XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3294 	       &f->output_data.x->wm_hints);
3295   f->output_data.x->wm_hints.icon_pixmap = None;
3296 
3297   /* Request "save yourself" and "delete window" commands from wm.  */
3298   {
3299     Atom protocols[2];
3300     protocols[0] = FRAME_DISPLAY_INFO (f)->Xatom_wm_delete_window;
3301     protocols[1] = FRAME_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
3302     XSetWMProtocols (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), protocols, 2);
3303   }
3304 
3305   /* x_set_name normally ignores requests to set the name if the
3306      requested name is the same as the current name.  This is the one
3307      place where that assumption isn't correct; f->name is set, but
3308      the X server hasn't been told.  */
3309   {
3310     Lisp_Object name;
3311     bool explicit = f->explicit_name;
3312 
3313     f->explicit_name = false;
3314     name = f->name;
3315     fset_name (f, Qnil);
3316     x_set_name (f, name, explicit);
3317   }
3318 
3319   if (FRAME_UNDECORATED (f))
3320     {
3321       Display *dpy = FRAME_X_DISPLAY (f);
3322       PropMotifWmHints hints;
3323       Atom prop = XInternAtom (dpy, "_MOTIF_WM_HINTS", False);
3324 
3325       memset (&hints, 0, sizeof(hints));
3326       hints.flags = MWM_HINTS_DECORATIONS;
3327       hints.decorations = 0;
3328 
3329       /* For some reason the third and fourth arguments in the following
3330 	 call must be identical: In the corresponding XGetWindowProperty
3331 	 call in getMotifHints, xfwm has the third and seventh args both
3332 	 display_info->atoms[MOTIF_WM_HINTS].  Obviously, YMMV.   */
3333       XChangeProperty (dpy, FRAME_OUTER_WINDOW (f), prop, prop, 32,
3334 		       PropModeReplace, (unsigned char *) &hints,
3335 		       PROP_MOTIF_WM_HINTS_ELEMENTS);
3336     }
3337 
3338 
3339   XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3340 		 f->output_data.x->current_cursor
3341                  = f->output_data.x->text_cursor);
3342 
3343   unblock_input ();
3344 
3345   if (FRAME_X_WINDOW (f) == 0)
3346     error ("Unable to create window");
3347 }
3348 
3349 #endif /* not USE_GTK */
3350 #endif /* not USE_X_TOOLKIT */
3351 
3352 /* Verify that the icon position args for this window are valid.  */
3353 
3354 static void
x_icon_verify(struct frame * f,Lisp_Object parms)3355 x_icon_verify (struct frame *f, Lisp_Object parms)
3356 {
3357   Lisp_Object icon_x, icon_y;
3358 
3359   /* Set the position of the icon.  Note that twm groups all
3360      icons in an icon window.  */
3361   icon_x = gui_frame_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
3362   icon_y = gui_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
3363   if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
3364     {
3365       CHECK_FIXNUM (icon_x);
3366       CHECK_FIXNUM (icon_y);
3367     }
3368   else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
3369     error ("Both left and top icon corners of icon must be specified");
3370 }
3371 
3372 /* Handle the icon stuff for this window.  Perhaps later we might
3373    want an x_set_icon_position which can be called interactively as
3374    well.  */
3375 
3376 static void
x_icon(struct frame * f,Lisp_Object parms)3377 x_icon (struct frame *f, Lisp_Object parms)
3378 {
3379   /* Set the position of the icon.  Note that twm groups all
3380      icons in an icon window.  */
3381   Lisp_Object icon_x
3382     = gui_frame_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
3383   Lisp_Object icon_y
3384     = gui_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
3385   if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
3386     {
3387       CHECK_TYPE_RANGED_INTEGER (int, icon_x);
3388       CHECK_TYPE_RANGED_INTEGER (int, icon_y);
3389     }
3390   else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
3391     error ("Both left and top icon corners of icon must be specified");
3392 
3393   block_input ();
3394 
3395   if (! EQ (icon_x, Qunbound))
3396     x_wm_set_icon_position (f, XFIXNUM (icon_x), XFIXNUM (icon_y));
3397 
3398 #if false /* gui_display_get_arg removes the visibility parameter as a
3399 	     side effect, but x_create_frame still needs it.  */
3400   /* Start up iconic or window? */
3401   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
3402   x_wm_set_window_state
3403     (f, (EQ (gui_display_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
3404                                   RES_TYPE_SYMBOL),
3405 	     Qicon)
3406 	 ? IconicState
3407 	 : NormalState));
3408 #endif
3409 
3410   x_text_icon (f, SSDATA ((!NILP (f->icon_name)
3411 			   ? f->icon_name
3412 			   : f->name)));
3413 
3414   unblock_input ();
3415 }
3416 
3417 /* Make the GCs needed for this window, setting the
3418    background, border and mouse colors; also create the
3419    mouse cursor and the gray border tile.  */
3420 
3421 static void
x_make_gc(struct frame * f)3422 x_make_gc (struct frame *f)
3423 {
3424   XGCValues gc_values;
3425 
3426   block_input ();
3427 
3428   /* Create the GCs of this frame.
3429      Note that many default values are used.  */
3430 
3431   gc_values.foreground = FRAME_FOREGROUND_PIXEL (f);
3432   gc_values.background = FRAME_BACKGROUND_PIXEL (f);
3433   gc_values.line_width = 0;	/* Means 1 using fast algorithm.  */
3434   f->output_data.x->normal_gc
3435     = XCreateGC (FRAME_X_DISPLAY (f),
3436                  FRAME_X_DRAWABLE (f),
3437 		 GCLineWidth | GCForeground | GCBackground,
3438 		 &gc_values);
3439 
3440   /* Reverse video style.  */
3441   gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
3442   gc_values.background = FRAME_FOREGROUND_PIXEL (f);
3443   f->output_data.x->reverse_gc
3444     = XCreateGC (FRAME_X_DISPLAY (f),
3445                  FRAME_X_DRAWABLE (f),
3446 		 GCForeground | GCBackground | GCLineWidth,
3447 		 &gc_values);
3448 
3449   /* Cursor has cursor-color background, background-color foreground.  */
3450   gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
3451   gc_values.background = f->output_data.x->cursor_pixel;
3452   gc_values.fill_style = FillOpaqueStippled;
3453   f->output_data.x->cursor_gc
3454     = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
3455 		 (GCForeground | GCBackground
3456 		  | GCFillStyle | GCLineWidth),
3457 		 &gc_values);
3458 
3459   /* Create the gray border tile used when the pointer is not in
3460      the frame.  Since this depends on the frame's pixel values,
3461      this must be done on a per-frame basis.  */
3462   f->output_data.x->border_tile
3463     = (XCreatePixmapFromBitmapData
3464        (FRAME_X_DISPLAY (f), FRAME_DISPLAY_INFO (f)->root_window,
3465 	gray_bits, gray_width, gray_height,
3466 	FRAME_FOREGROUND_PIXEL (f),
3467 	FRAME_BACKGROUND_PIXEL (f),
3468 	DefaultDepth (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f))));
3469 
3470   unblock_input ();
3471 }
3472 
3473 
3474 /* Free what was allocated in x_make_gc.  */
3475 
3476 void
x_free_gcs(struct frame * f)3477 x_free_gcs (struct frame *f)
3478 {
3479   Display *dpy = FRAME_X_DISPLAY (f);
3480 
3481   block_input ();
3482 
3483   if (f->output_data.x->normal_gc)
3484     {
3485       XFreeGC (dpy, f->output_data.x->normal_gc);
3486       f->output_data.x->normal_gc = 0;
3487     }
3488 
3489   if (f->output_data.x->reverse_gc)
3490     {
3491       XFreeGC (dpy, f->output_data.x->reverse_gc);
3492       f->output_data.x->reverse_gc = 0;
3493     }
3494 
3495   if (f->output_data.x->cursor_gc)
3496     {
3497       XFreeGC (dpy, f->output_data.x->cursor_gc);
3498       f->output_data.x->cursor_gc = 0;
3499     }
3500 
3501   if (f->output_data.x->border_tile)
3502     {
3503       XFreePixmap (dpy, f->output_data.x->border_tile);
3504       f->output_data.x->border_tile = 0;
3505     }
3506 
3507   unblock_input ();
3508 }
3509 
3510 
3511 /* Handler for signals raised during x_create_frame and
3512    Fx_create_tip_frame.  FRAME is the frame which is partially
3513    constructed.  */
3514 
3515 static Lisp_Object
unwind_create_frame(Lisp_Object frame)3516 unwind_create_frame (Lisp_Object frame)
3517 {
3518   struct frame *f = XFRAME (frame);
3519 
3520   /* If frame is already dead, nothing to do.  This can happen if the
3521      display is disconnected after the frame has become official, but
3522      before Fx_create_frame removes the unwind protect.  */
3523   if (!FRAME_LIVE_P (f))
3524     return Qnil;
3525 
3526   /* If frame is ``official'', nothing to do.  */
3527   if (NILP (Fmemq (frame, Vframe_list)))
3528     {
3529 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
3530       struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
3531 #endif
3532 
3533       /* If the frame's image cache refcount is still the same as our
3534 	 private shadow variable, it means we are unwinding a frame
3535 	 for which we didn't yet call init_frame_faces, where the
3536 	 refcount is incremented.  Therefore, we increment it here, so
3537 	 that free_frame_faces, called in x_free_frame_resources
3538 	 below, will not mistakenly decrement the counter that was not
3539 	 incremented yet to account for this new frame.  */
3540       if (FRAME_IMAGE_CACHE (f) != NULL
3541 	  && FRAME_IMAGE_CACHE (f)->refcount == image_cache_refcount)
3542 	FRAME_IMAGE_CACHE (f)->refcount++;
3543 
3544       x_free_frame_resources (f);
3545       free_glyphs (f);
3546 
3547 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
3548       /* Check that reference counts are indeed correct.  */
3549       eassert (dpyinfo->reference_count == dpyinfo_refcount);
3550       eassert (dpyinfo->terminal->image_cache->refcount == image_cache_refcount);
3551 #endif
3552       return Qt;
3553     }
3554 
3555   return Qnil;
3556 }
3557 
3558 static void
do_unwind_create_frame(Lisp_Object frame)3559 do_unwind_create_frame (Lisp_Object frame)
3560 {
3561   unwind_create_frame (frame);
3562 }
3563 
3564 void
x_default_font_parameter(struct frame * f,Lisp_Object parms)3565 x_default_font_parameter (struct frame *f, Lisp_Object parms)
3566 {
3567   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
3568   Lisp_Object font_param = gui_display_get_arg (dpyinfo, parms, Qfont, NULL, NULL,
3569                                                 RES_TYPE_STRING);
3570   Lisp_Object font = Qnil;
3571   if (EQ (font_param, Qunbound))
3572     font_param = Qnil;
3573 
3574   if (NILP (font_param))
3575     {
3576       /* System font should take precedence over X resources.  We suggest this
3577          regardless of font-use-system-font because .emacs may not have been
3578          read yet.  */
3579       const char *system_font = xsettings_get_system_font ();
3580       if (system_font)
3581 	font = font_open_by_name (f, build_unibyte_string (system_font));
3582     }
3583 
3584   if (NILP (font))
3585       font = !NILP (font_param) ? font_param
3586       : gui_display_get_arg (dpyinfo, parms, Qfont, "font", "Font",
3587                              RES_TYPE_STRING);
3588 
3589   if (! FONTP (font) && ! STRINGP (font))
3590     {
3591       const char *names[]
3592 	= {
3593 #if defined USE_CAIRO || defined HAVE_XFT
3594 	    /* This will find the normal Xft font.  */
3595  	    "monospace-10",
3596 #endif
3597 	    "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1",
3598 	    "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1",
3599 	    "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1",
3600 	    /* This was formerly the first thing tried, but it finds
3601 	       too many fonts and takes too long.  */
3602 	    "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1",
3603 	    /* If those didn't work, look for something which will
3604 	       at least work.  */
3605 	    "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1",
3606 	    "fixed",
3607 	    NULL };
3608       int i;
3609 
3610       for (i = 0; names[i]; i++)
3611 	{
3612 	  font = font_open_by_name (f, build_unibyte_string (names[i]));
3613 	  if (! NILP (font))
3614 	    break;
3615 	}
3616       if (NILP (font))
3617 	error ("No suitable font was found");
3618     }
3619   else if (!NILP (font_param))
3620     {
3621       /* Remember the explicit font parameter, so we can re-apply it after
3622 	 we've applied the `default' face settings.  */
3623       AUTO_FRAME_ARG (arg, Qfont_parameter, font_param);
3624       gui_set_frame_parameters (f, arg);
3625     }
3626 
3627   /* This call will make X resources override any system font setting.  */
3628   gui_default_parameter (f, parms, Qfont, font, "font", "Font", RES_TYPE_STRING);
3629 }
3630 
3631 
3632 DEFUN ("x-wm-set-size-hint", Fx_wm_set_size_hint, Sx_wm_set_size_hint,
3633        0, 1, 0,
3634        doc: /* Send the size hints for frame FRAME to the window manager.
3635 If FRAME is omitted or nil, use the selected frame.
3636 Signal error if FRAME is not an X frame.  */)
3637   (Lisp_Object frame)
3638 {
3639   struct frame *f = decode_window_system_frame (frame);
3640 
3641   block_input ();
3642   x_wm_set_size_hint (f, 0, false);
3643   unblock_input ();
3644   return Qnil;
3645 }
3646 
3647 static void
set_machine_and_pid_properties(struct frame * f)3648 set_machine_and_pid_properties (struct frame *f)
3649 {
3650   /* This will set WM_CLIENT_MACHINE and WM_LOCALE_NAME.  */
3651   XSetWMProperties (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), NULL, NULL,
3652                     NULL, 0, NULL, NULL, NULL);
3653   pid_t pid = getpid ();
3654   if (pid <= 0xffffffffu)
3655     {
3656       unsigned long xpid = pid;
3657       XChangeProperty (FRAME_X_DISPLAY (f),
3658 		       FRAME_OUTER_WINDOW (f),
3659 		       XInternAtom (FRAME_X_DISPLAY (f),
3660 				    "_NET_WM_PID",
3661 				    False),
3662 		       XA_CARDINAL, 32, PropModeReplace,
3663 		       (unsigned char *) &xpid, 1);
3664     }
3665 }
3666 
3667 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
3668        1, 1, 0,
3669        doc: /* Make a new X window, which is called a "frame" in Emacs terms.
3670 Return an Emacs frame object.  PARMS is an alist of frame parameters.
3671 If the parameters specify that the frame should not have a minibuffer,
3672 and do not specify a specific minibuffer window to use, then
3673 `default-minibuffer-frame' must be a frame whose minibuffer can be
3674 shared by the new frame.
3675 
3676 This function is an internal primitive--use `make-frame' instead.  */)
3677   (Lisp_Object parms)
3678 {
3679   struct frame *f;
3680   Lisp_Object frame, tem;
3681   Lisp_Object name;
3682   bool minibuffer_only = false;
3683   bool undecorated = false, override_redirect = false;
3684   long window_prompting = 0;
3685   ptrdiff_t count = SPECPDL_INDEX ();
3686   Lisp_Object display;
3687   struct x_display_info *dpyinfo = NULL;
3688   Lisp_Object parent, parent_frame;
3689   struct kboard *kb;
3690   int x_width = 0, x_height = 0;
3691 
3692   parms = Fcopy_alist (parms);
3693 
3694   /* Use this general default value to start with
3695      until we know if this frame has a specified name.  */
3696   Vx_resource_name = Vinvocation_name;
3697 
3698   display = gui_display_get_arg (dpyinfo, parms, Qterminal, 0, 0,
3699                                  RES_TYPE_NUMBER);
3700   if (EQ (display, Qunbound))
3701     display = gui_display_get_arg (dpyinfo, parms, Qdisplay, 0, 0,
3702                                    RES_TYPE_STRING);
3703   if (EQ (display, Qunbound))
3704     display = Qnil;
3705   dpyinfo = check_x_display_info (display);
3706   kb = dpyinfo->terminal->kboard;
3707 
3708   if (!dpyinfo->terminal->name)
3709     error ("Terminal is not live, can't create new frames on it");
3710 
3711   name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name",
3712                               RES_TYPE_STRING);
3713   if (!STRINGP (name)
3714       && ! EQ (name, Qunbound)
3715       && ! NILP (name))
3716     error ("Invalid frame name--not a string or nil");
3717 
3718   if (STRINGP (name))
3719     Vx_resource_name = name;
3720 
3721   /* See if parent window is specified.  */
3722   parent = gui_display_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL,
3723                                 RES_TYPE_NUMBER);
3724   if (EQ (parent, Qunbound))
3725     parent = Qnil;
3726   if (! NILP (parent))
3727     CHECK_FIXNUM (parent);
3728 
3729   frame = Qnil;
3730   tem = gui_display_get_arg (dpyinfo,
3731                              parms, Qminibuffer, "minibuffer", "Minibuffer",
3732                              RES_TYPE_SYMBOL);
3733   if (EQ (tem, Qnone) || NILP (tem))
3734     f = make_frame_without_minibuffer (Qnil, kb, display);
3735   else if (EQ (tem, Qonly))
3736     {
3737       f = make_minibuffer_frame ();
3738       minibuffer_only = true;
3739     }
3740   else if (WINDOWP (tem))
3741     f = make_frame_without_minibuffer (tem, kb, display);
3742   else
3743     f = make_frame (true);
3744 
3745   parent_frame = gui_display_get_arg (dpyinfo,
3746                                       parms,
3747                                       Qparent_frame,
3748                                       NULL,
3749                                       NULL,
3750                                       RES_TYPE_SYMBOL);
3751   /* Accept parent-frame iff parent-id was not specified.  */
3752   if (!NILP (parent)
3753       || EQ (parent_frame, Qunbound)
3754       || NILP (parent_frame)
3755       || !FRAMEP (parent_frame)
3756       || !FRAME_LIVE_P (XFRAME (parent_frame))
3757       || !FRAME_X_P (XFRAME (parent_frame)))
3758     parent_frame = Qnil;
3759 
3760   fset_parent_frame (f, parent_frame);
3761   store_frame_param (f, Qparent_frame, parent_frame);
3762 
3763   if (!NILP (tem = (gui_display_get_arg (dpyinfo,
3764                                          parms,
3765                                          Qundecorated,
3766                                          NULL,
3767                                          NULL,
3768                                          RES_TYPE_BOOLEAN)))
3769       && !(EQ (tem, Qunbound)))
3770     undecorated = true;
3771 
3772   FRAME_UNDECORATED (f) = undecorated;
3773   store_frame_param (f, Qundecorated, undecorated ? Qt : Qnil);
3774 
3775   if (!NILP (tem = (gui_display_get_arg (dpyinfo,
3776                                          parms,
3777                                          Qoverride_redirect,
3778                                          NULL,
3779                                          NULL,
3780                                          RES_TYPE_BOOLEAN)))
3781       && !(EQ (tem, Qunbound)))
3782     override_redirect = true;
3783 
3784   FRAME_OVERRIDE_REDIRECT (f) = override_redirect;
3785   store_frame_param (f, Qoverride_redirect, override_redirect ? Qt : Qnil);
3786 
3787   XSETFRAME (frame, f);
3788 
3789   f->terminal = dpyinfo->terminal;
3790 
3791   f->output_method = output_x_window;
3792   f->output_data.x = xzalloc (sizeof *f->output_data.x);
3793   f->output_data.x->icon_bitmap = -1;
3794   FRAME_FONTSET (f) = -1;
3795   f->output_data.x->scroll_bar_foreground_pixel = -1;
3796   f->output_data.x->scroll_bar_background_pixel = -1;
3797 #if defined (USE_LUCID) && defined (USE_TOOLKIT_SCROLL_BARS)
3798   f->output_data.x->scroll_bar_top_shadow_pixel = -1;
3799   f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
3800 #endif /* USE_LUCID && USE_TOOLKIT_SCROLL_BARS */
3801   f->output_data.x->white_relief.pixel = -1;
3802   f->output_data.x->black_relief.pixel = -1;
3803 
3804   fset_icon_name (f, gui_display_get_arg (dpyinfo,
3805                                           parms,
3806                                           Qicon_name,
3807                                           "iconName",
3808                                           "Title",
3809                                           RES_TYPE_STRING));
3810   if (! STRINGP (f->icon_name))
3811     fset_icon_name (f, Qnil);
3812 
3813   FRAME_DISPLAY_INFO (f) = dpyinfo;
3814 
3815   /* With FRAME_DISPLAY_INFO set up, this unwind-protect is safe.  */
3816   record_unwind_protect (do_unwind_create_frame, frame);
3817 
3818   /* These colors will be set anyway later, but it's important
3819      to get the color reference counts right, so initialize them!  */
3820   {
3821     Lisp_Object black;
3822 
3823     /* Function x_decode_color can signal an error.  Make
3824        sure to initialize color slots so that we won't try
3825        to free colors we haven't allocated.  */
3826     FRAME_FOREGROUND_PIXEL (f) = -1;
3827     FRAME_BACKGROUND_PIXEL (f) = -1;
3828     f->output_data.x->cursor_pixel = -1;
3829     f->output_data.x->cursor_foreground_pixel = -1;
3830     f->output_data.x->border_pixel = -1;
3831     f->output_data.x->mouse_pixel = -1;
3832 
3833     black = build_string ("black");
3834     FRAME_FOREGROUND_PIXEL (f)
3835       = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3836     FRAME_BACKGROUND_PIXEL (f)
3837       = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3838     f->output_data.x->cursor_pixel
3839       = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3840     f->output_data.x->cursor_foreground_pixel
3841       = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3842     f->output_data.x->border_pixel
3843       = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3844     f->output_data.x->mouse_pixel
3845       = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3846   }
3847 
3848   /* Specify the parent under which to make this X window.  */
3849   if (!NILP (parent))
3850     {
3851       f->output_data.x->parent_desc = (Window) XFIXNAT (parent);
3852       f->output_data.x->explicit_parent = true;
3853     }
3854   else
3855     {
3856       f->output_data.x->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
3857       f->output_data.x->explicit_parent = false;
3858     }
3859 
3860   /* Set the name; the functions to which we pass f expect the name to
3861      be set.  */
3862   if (EQ (name, Qunbound) || NILP (name))
3863     {
3864       fset_name (f, build_string (dpyinfo->x_id_name));
3865       f->explicit_name = false;
3866     }
3867   else
3868     {
3869       fset_name (f, name);
3870       f->explicit_name = true;
3871       /* Use the frame's title when getting resources for this frame.  */
3872       specbind (Qx_resource_name, name);
3873     }
3874 
3875 #ifdef USE_CAIRO
3876   register_font_driver (&ftcrfont_driver, f);
3877 #ifdef HAVE_HARFBUZZ
3878   register_font_driver (&ftcrhbfont_driver, f);
3879 #endif	/* HAVE_HARFBUZZ */
3880 #else
3881 #ifdef HAVE_FREETYPE
3882 #ifdef HAVE_XFT
3883   register_font_driver (&xftfont_driver, f);
3884 #ifdef HAVE_HARFBUZZ
3885   register_font_driver (&xfthbfont_driver, f);
3886 #endif
3887 #else	/* not HAVE_XFT */
3888   register_font_driver (&ftxfont_driver, f);
3889 #endif	/* not HAVE_XFT */
3890 #endif	/* HAVE_FREETYPE */
3891 #endif	/* not USE_CAIRO */
3892   register_font_driver (&xfont_driver, f);
3893 
3894   image_cache_refcount =
3895     FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
3896 #ifdef GLYPH_DEBUG
3897   dpyinfo_refcount = dpyinfo->reference_count;
3898 #endif /* GLYPH_DEBUG */
3899 
3900   gui_default_parameter (f, parms, Qfont_backend, Qnil,
3901                          "fontBackend", "FontBackend", RES_TYPE_STRING);
3902 
3903   /* Extract the window parameters from the supplied values
3904      that are needed to determine window geometry.  */
3905   x_default_font_parameter (f, parms);
3906   if (!FRAME_FONT (f))
3907     {
3908       delete_frame (frame, Qnoelisp);
3909       error ("Invalid frame font");
3910     }
3911 
3912   /* Frame contents get displaced if an embedded X window has a border.  */
3913   if (! FRAME_X_EMBEDDED_P (f))
3914     gui_default_parameter (f, parms, Qborder_width, make_fixnum (0),
3915                            "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
3916 
3917   /* This defaults to 1 in order to match xterm.  We recognize either
3918      internalBorderWidth or internalBorder (which is what xterm calls
3919      it).  */
3920   if (NILP (Fassq (Qinternal_border_width, parms)))
3921     {
3922       Lisp_Object value;
3923 
3924       value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width,
3925                                    "internalBorder", "internalBorder",
3926                                    RES_TYPE_NUMBER);
3927       if (! EQ (value, Qunbound))
3928 	parms = Fcons (Fcons (Qinternal_border_width, value),
3929 		       parms);
3930     }
3931   gui_default_parameter (f, parms, Qinternal_border_width,
3932 #ifdef USE_GTK /* We used to impose 0 in xg_create_frame_widgets.  */
3933                          make_fixnum (0),
3934 #else
3935                          make_fixnum (1),
3936 #endif
3937                          "internalBorderWidth", "internalBorderWidth",
3938                          RES_TYPE_NUMBER);
3939   gui_default_parameter (f, parms, Qright_divider_width, make_fixnum (0),
3940                          NULL, NULL, RES_TYPE_NUMBER);
3941   gui_default_parameter (f, parms, Qbottom_divider_width, make_fixnum (0),
3942                          NULL, NULL, RES_TYPE_NUMBER);
3943   gui_default_parameter (f, parms, Qvertical_scroll_bars,
3944 #if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
3945                          Qright,
3946 #else
3947                          Qleft,
3948 #endif
3949                          "verticalScrollBars", "ScrollBars",
3950                          RES_TYPE_SYMBOL);
3951   gui_default_parameter (f, parms, Qhorizontal_scroll_bars, Qnil,
3952                          "horizontalScrollBars", "ScrollBars",
3953                          RES_TYPE_SYMBOL);
3954   /* Also do the stuff which must be set before the window exists.  */
3955   gui_default_parameter (f, parms, Qforeground_color, build_string ("black"),
3956                          "foreground", "Foreground", RES_TYPE_STRING);
3957   gui_default_parameter (f, parms, Qbackground_color, build_string ("white"),
3958                          "background", "Background", RES_TYPE_STRING);
3959   gui_default_parameter (f, parms, Qmouse_color, build_string ("black"),
3960                          "pointerColor", "Foreground", RES_TYPE_STRING);
3961   gui_default_parameter (f, parms, Qborder_color, build_string ("black"),
3962                          "borderColor", "BorderColor", RES_TYPE_STRING);
3963   gui_default_parameter (f, parms, Qscreen_gamma, Qnil,
3964                          "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
3965   gui_default_parameter (f, parms, Qline_spacing, Qnil,
3966                          "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
3967   gui_default_parameter (f, parms, Qleft_fringe, Qnil,
3968                          "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
3969   gui_default_parameter (f, parms, Qright_fringe, Qnil,
3970                          "rightFringe", "RightFringe", RES_TYPE_NUMBER);
3971   gui_default_parameter (f, parms, Qno_special_glyphs, Qnil,
3972                          NULL, NULL, RES_TYPE_BOOLEAN);
3973 
3974   x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
3975 					"scrollBarForeground",
3976 					"ScrollBarForeground", true);
3977   x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_background,
3978 					"scrollBarBackground",
3979 					"ScrollBarBackground", false);
3980 
3981   /* Init faces before gui_default_parameter is called for the
3982      scroll-bar-width parameter because otherwise we end up in
3983      init_iterator with a null face cache, which should not happen.  */
3984   init_frame_faces (f);
3985 
3986   /* We have to call adjust_frame_size here since otherwise
3987      x_set_tool_bar_lines will already work with the character sizes
3988      installed by init_frame_faces while the frame's pixel size is still
3989      calculated from a character size of 1 and we subsequently hit the
3990      (height >= 0) assertion in window_box_height.
3991 
3992      The non-pixelwise code apparently worked around this because it
3993      had one frame line vs one toolbar line which left us with a zero
3994      root window height which was obviously wrong as well ...
3995 
3996      Also process `min-width' and `min-height' parameters right here
3997      because `frame-windows-min-size' needs them.  */
3998   tem = gui_display_get_arg (dpyinfo, parms, Qmin_width, NULL, NULL,
3999                              RES_TYPE_NUMBER);
4000   if (FIXNUMP (tem))
4001     store_frame_param (f, Qmin_width, tem);
4002   tem = gui_display_get_arg (dpyinfo, parms, Qmin_height, NULL, NULL,
4003                              RES_TYPE_NUMBER);
4004   if (FIXNUMP (tem))
4005     store_frame_param (f, Qmin_height, tem);
4006   adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
4007 		     FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, true,
4008 		     Qx_create_frame_1);
4009 
4010   /* Set the menu-bar-lines and tool-bar-lines parameters.  We don't
4011      look up the X resources controlling the menu-bar and tool-bar
4012      here; they are processed specially at startup, and reflected in
4013      the values of the mode variables.  */
4014 
4015   gui_default_parameter (f, parms, Qmenu_bar_lines,
4016                          NILP (Vmenu_bar_mode)
4017                          ? make_fixnum (0) : make_fixnum (1),
4018                          NULL, NULL, RES_TYPE_NUMBER);
4019   gui_default_parameter (f, parms, Qtab_bar_lines,
4020                          NILP (Vtab_bar_mode)
4021                          ? make_fixnum (0) : make_fixnum (1),
4022                          NULL, NULL, RES_TYPE_NUMBER);
4023   gui_default_parameter (f, parms, Qtool_bar_lines,
4024                          NILP (Vtool_bar_mode)
4025                          ? make_fixnum (0) : make_fixnum (1),
4026                          NULL, NULL, RES_TYPE_NUMBER);
4027 
4028   gui_default_parameter (f, parms, Qbuffer_predicate, Qnil,
4029                          "bufferPredicate", "BufferPredicate",
4030                          RES_TYPE_SYMBOL);
4031   gui_default_parameter (f, parms, Qtitle, Qnil,
4032                          "title", "Title", RES_TYPE_STRING);
4033   gui_default_parameter (f, parms, Qwait_for_wm, Qt,
4034                          "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN);
4035   gui_default_parameter (f, parms, Qtool_bar_position,
4036                          FRAME_TOOL_BAR_POSITION (f), 0, 0, RES_TYPE_SYMBOL);
4037   gui_default_parameter (f, parms, Qinhibit_double_buffering, Qnil,
4038                          "inhibitDoubleBuffering", "InhibitDoubleBuffering",
4039                          RES_TYPE_BOOLEAN);
4040 
4041   /* Compute the size of the X window.  */
4042   window_prompting = gui_figure_window_size (f, parms, true, true,
4043                                              &x_width, &x_height);
4044 
4045   tem = gui_display_get_arg (dpyinfo, parms, Qunsplittable, 0, 0,
4046                              RES_TYPE_BOOLEAN);
4047   f->no_split = minibuffer_only || EQ (tem, Qt);
4048 
4049   x_icon_verify (f, parms);
4050 
4051   /* Create the X widget or window.  */
4052 #ifdef USE_X_TOOLKIT
4053   x_window (f, window_prompting);
4054 #else
4055   x_window (f);
4056 #endif
4057 
4058   x_icon (f, parms);
4059   x_make_gc (f);
4060 
4061   /* Now consider the frame official.  */
4062   f->terminal->reference_count++;
4063   FRAME_DISPLAY_INFO (f)->reference_count++;
4064   Vframe_list = Fcons (frame, Vframe_list);
4065 
4066   /* We need to do this after creating the X window, so that the
4067      icon-creation functions can say whose icon they're describing.  */
4068   gui_default_parameter (f, parms, Qicon_type, Qt,
4069                          "bitmapIcon", "BitmapIcon", RES_TYPE_BOOLEAN);
4070 
4071   gui_default_parameter (f, parms, Qauto_raise, Qnil,
4072                          "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4073   gui_default_parameter (f, parms, Qauto_lower, Qnil,
4074                          "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4075   gui_default_parameter (f, parms, Qcursor_type, Qbox,
4076                          "cursorType", "CursorType", RES_TYPE_SYMBOL);
4077   gui_default_parameter (f, parms, Qscroll_bar_width, Qnil,
4078                          "scrollBarWidth", "ScrollBarWidth",
4079                          RES_TYPE_NUMBER);
4080   gui_default_parameter (f, parms, Qscroll_bar_height, Qnil,
4081                          "scrollBarHeight", "ScrollBarHeight",
4082                          RES_TYPE_NUMBER);
4083   gui_default_parameter (f, parms, Qalpha, Qnil,
4084                          "alpha", "Alpha", RES_TYPE_NUMBER);
4085 
4086   if (!NILP (parent_frame))
4087     {
4088       struct frame *p = XFRAME (parent_frame);
4089 
4090       block_input ();
4091       XReparentWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
4092 		       FRAME_X_WINDOW (p), f->left_pos, f->top_pos);
4093 #ifdef USE_GTK
4094       if (EQ (x_gtk_resize_child_frames, Qresize_mode))
4095 	gtk_container_set_resize_mode
4096 	  (GTK_CONTAINER (FRAME_GTK_OUTER_WIDGET (f)), GTK_RESIZE_IMMEDIATE);
4097 #endif
4098       unblock_input ();
4099     }
4100 
4101   gui_default_parameter (f, parms, Qno_focus_on_map, Qnil,
4102                          NULL, NULL, RES_TYPE_BOOLEAN);
4103   gui_default_parameter (f, parms, Qno_accept_focus, Qnil,
4104                          NULL, NULL, RES_TYPE_BOOLEAN);
4105 
4106 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
4107   /* Create the menu bar.  */
4108   if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
4109     {
4110       /* If this signals an error, we haven't set size hints for the
4111 	 frame and we didn't make it visible.  */
4112       initialize_frame_menubar (f);
4113 
4114 #ifndef USE_GTK
4115       /* This is a no-op, except under Motif where it arranges the
4116 	 main window for the widgets on it.  */
4117       lw_set_main_areas (f->output_data.x->column_widget,
4118 			 f->output_data.x->menubar_widget,
4119 			 f->output_data.x->edit_widget);
4120 #endif /* not USE_GTK */
4121     }
4122 #endif /* USE_X_TOOLKIT || USE_GTK */
4123 
4124   /* Consider frame official, now.  */
4125   f->can_set_window_size = true;
4126 
4127   if (x_width > 0)
4128     SET_FRAME_WIDTH (f, x_width);
4129   if (x_height > 0)
4130     SET_FRAME_HEIGHT (f, x_height);
4131 
4132   /* Tell the server what size and position, etc, we want, and how
4133      badly we want them.  This should be done after we have the menu
4134      bar so that its size can be taken into account.  */
4135   block_input ();
4136   x_wm_set_size_hint (f, window_prompting, false);
4137   unblock_input ();
4138 
4139   adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
4140 		     0, true, Qx_create_frame_2);
4141 
4142   /* Process fullscreen parameter here in the hope that normalizing a
4143      fullheight/fullwidth frame will produce the size set by the last
4144      adjust_frame_size call.  */
4145   gui_default_parameter (f, parms, Qfullscreen, Qnil,
4146                          "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
4147 
4148   /* Make the window appear on the frame and enable display, unless
4149      the caller says not to.  However, with explicit parent, Emacs
4150      cannot control visibility, so don't try.  */
4151   if (!f->output_data.x->explicit_parent)
4152     {
4153       Lisp_Object visibility
4154 	= gui_display_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
4155                                RES_TYPE_SYMBOL);
4156 
4157       if (EQ (visibility, Qicon))
4158 	x_iconify_frame (f);
4159       else
4160 	{
4161 	  if (EQ (visibility, Qunbound))
4162 	    visibility = Qt;
4163 
4164 	  if (!NILP (visibility))
4165 	    x_make_frame_visible (f);
4166 	}
4167 
4168       store_frame_param (f, Qvisibility, visibility);
4169     }
4170 
4171   block_input ();
4172 
4173   /* Set machine name and pid for the purpose of window managers.  */
4174   set_machine_and_pid_properties (f);
4175 
4176   /* Set the WM leader property.  GTK does this itself, so this is not
4177      needed when using GTK.  */
4178   if (dpyinfo->client_leader_window != 0)
4179     {
4180       XChangeProperty (FRAME_X_DISPLAY (f),
4181 		       FRAME_OUTER_WINDOW (f),
4182 		       dpyinfo->Xatom_wm_client_leader,
4183 		       XA_WINDOW, 32, PropModeReplace,
4184 		       (unsigned char *) &dpyinfo->client_leader_window, 1);
4185     }
4186 
4187   unblock_input ();
4188 
4189   /* Works iff frame has been already mapped.  */
4190   gui_default_parameter (f, parms, Qskip_taskbar, Qnil,
4191                          NULL, NULL, RES_TYPE_BOOLEAN);
4192   /* The `z-group' parameter works only for visible frames.  */
4193   gui_default_parameter (f, parms, Qz_group, Qnil,
4194                          NULL, NULL, RES_TYPE_SYMBOL);
4195 
4196   /* Initialize `default-minibuffer-frame' in case this is the first
4197      frame on this terminal.  */
4198   if (FRAME_HAS_MINIBUF_P (f)
4199       && (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame))
4200           || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame)))))
4201     kset_default_minibuffer_frame (kb, frame);
4202 
4203   /* All remaining specified parameters, which have not been "used" by
4204      gui_display_get_arg and friends, now go in the misc. alist of the
4205      frame.  */
4206   for (tem = parms; CONSP (tem); tem = XCDR (tem))
4207     if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
4208       fset_param_alist (f, Fcons (XCAR (tem), f->param_alist));
4209 
4210   /* Make sure windows on this frame appear in calls to next-window
4211      and similar functions.  */
4212   Vwindow_list = Qnil;
4213 
4214  return unbind_to (count, frame);
4215 }
4216 
4217 
4218 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
4219        doc: /* Internal function called by `color-defined-p'.
4220 \(Note that the Nextstep version of this function ignores FRAME.)  */)
4221   (Lisp_Object color, Lisp_Object frame)
4222 {
4223   XColor foo;
4224   struct frame *f = decode_window_system_frame (frame);
4225 
4226   CHECK_STRING (color);
4227 
4228   if (x_defined_color (f, SSDATA (color), &foo, false, false))
4229     return Qt;
4230   else
4231     return Qnil;
4232 }
4233 
4234 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
4235        doc: /* Internal function called by `color-values'.
4236 \(Note that the Nextstep version of this function ignores FRAME.)  */)
4237   (Lisp_Object color, Lisp_Object frame)
4238 {
4239   XColor foo;
4240   struct frame *f = decode_window_system_frame (frame);
4241 
4242   CHECK_STRING (color);
4243 
4244   if (x_defined_color (f, SSDATA (color), &foo, false, false))
4245     return list3i (foo.red, foo.green, foo.blue);
4246   else
4247     return Qnil;
4248 }
4249 
4250 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
4251        doc: /* Internal function called by `display-color-p'.  */)
4252   (Lisp_Object terminal)
4253 {
4254   struct x_display_info *dpyinfo = check_x_display_info (terminal);
4255 
4256   if (dpyinfo->n_planes <= 2)
4257     return Qnil;
4258 
4259   switch (dpyinfo->visual->class)
4260     {
4261     case StaticColor:
4262     case PseudoColor:
4263     case TrueColor:
4264     case DirectColor:
4265       return Qt;
4266 
4267     default:
4268       return Qnil;
4269     }
4270 }
4271 
4272 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
4273        0, 1, 0,
4274        doc: /* Return t if the X display supports shades of gray.
4275 Note that color displays do support shades of gray.
4276 The optional argument TERMINAL specifies which display to ask about.
4277 TERMINAL should be a terminal object, a frame or a display name (a string).
4278 If omitted or nil, that stands for the selected frame's display.  */)
4279   (Lisp_Object terminal)
4280 {
4281   struct x_display_info *dpyinfo = check_x_display_info (terminal);
4282 
4283   if (dpyinfo->n_planes <= 1)
4284     return Qnil;
4285 
4286   switch (dpyinfo->visual->class)
4287     {
4288     case StaticColor:
4289     case PseudoColor:
4290     case TrueColor:
4291     case DirectColor:
4292     case StaticGray:
4293     case GrayScale:
4294       return Qt;
4295 
4296     default:
4297       return Qnil;
4298     }
4299 }
4300 
4301 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
4302        0, 1, 0,
4303        doc: /* Return the width in pixels of the X display TERMINAL.
4304 The optional argument TERMINAL specifies which display to ask about.
4305 TERMINAL should be a terminal object, a frame or a display name (a string).
4306 If omitted or nil, that stands for the selected frame's display.
4307 \(On MS Windows, this function does not accept terminal objects.)
4308 
4309 On \"multi-monitor\" setups this refers to the pixel width for all
4310 physical monitors associated with TERMINAL.  To get information for
4311 each physical monitor, use `display-monitor-attributes-list'.  */)
4312   (Lisp_Object terminal)
4313 {
4314   struct x_display_info *dpyinfo = check_x_display_info (terminal);
4315 
4316   return make_fixnum (x_display_pixel_width (dpyinfo));
4317 }
4318 
4319 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
4320        Sx_display_pixel_height, 0, 1, 0,
4321        doc: /* Return the height in pixels of the X display TERMINAL.
4322 The optional argument TERMINAL specifies which display to ask about.
4323 TERMINAL should be a terminal object, a frame or a display name (a string).
4324 If omitted or nil, that stands for the selected frame's display.
4325 \(On MS Windows, this function does not accept terminal objects.)
4326 
4327 On \"multi-monitor\" setups this refers to the pixel height for all
4328 physical monitors associated with TERMINAL.  To get information for
4329 each physical monitor, use `display-monitor-attributes-list'.  */)
4330   (Lisp_Object terminal)
4331 {
4332   struct x_display_info *dpyinfo = check_x_display_info (terminal);
4333 
4334   return make_fixnum (x_display_pixel_height (dpyinfo));
4335 }
4336 
4337 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
4338        0, 1, 0,
4339        doc: /* Return the number of bitplanes of the X display TERMINAL.
4340 The optional argument TERMINAL specifies which display to ask about.
4341 TERMINAL should be a terminal object, a frame or a display name (a string).
4342 If omitted or nil, that stands for the selected frame's display.
4343 \(On MS Windows, this function does not accept terminal objects.)  */)
4344   (Lisp_Object terminal)
4345 {
4346   struct x_display_info *dpyinfo = check_x_display_info (terminal);
4347 
4348   return make_fixnum (dpyinfo->n_planes);
4349 }
4350 
4351 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
4352        0, 1, 0,
4353        doc: /* Return the number of color cells of the X display TERMINAL.
4354 The optional argument TERMINAL specifies which display to ask about.
4355 TERMINAL should be a terminal object, a frame or a display name (a string).
4356 If omitted or nil, that stands for the selected frame's display.
4357 \(On MS Windows, this function does not accept terminal objects.)  */)
4358   (Lisp_Object terminal)
4359 {
4360   struct x_display_info *dpyinfo = check_x_display_info (terminal);
4361 
4362   int nr_planes = DisplayPlanes (dpyinfo->display,
4363                                  XScreenNumberOfScreen (dpyinfo->screen));
4364 
4365   /* Truncate nr_planes to 24 to avoid integer overflow.
4366      Some displays says 32, but only 24 bits are actually significant.
4367      There are only very few and rare video cards that have more than
4368      24 significant bits.  Also 24 bits is more than 16 million colors,
4369      it "should be enough for everyone".  */
4370   if (nr_planes > 24) nr_planes = 24;
4371 
4372   return make_fixnum (1 << nr_planes);
4373 }
4374 
4375 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
4376        Sx_server_max_request_size,
4377        0, 1, 0,
4378        doc: /* Return the maximum request size of the X server of display TERMINAL.
4379 The optional argument TERMINAL specifies which display to ask about.
4380 TERMINAL should be a terminal object, a frame or a display name (a string).
4381 If omitted or nil, that stands for the selected frame's display.
4382 
4383 On MS Windows, this function just returns 1.
4384 On Nextstep, this function just returns nil.  */)
4385   (Lisp_Object terminal)
4386 {
4387   struct x_display_info *dpyinfo = check_x_display_info (terminal);
4388 
4389   return make_fixnum (MAXREQUEST (dpyinfo->display));
4390 }
4391 
4392 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
4393        doc: /* Return the "vendor ID" string of the GUI software on TERMINAL.
4394 
4395 \(Labeling every distributor as a "vendor" embodies the false assumption
4396 that operating systems cannot be developed and distributed noncommercially.)
4397 The optional argument TERMINAL specifies which display to ask about.
4398 
4399 For GNU and Unix systems, this queries the X server software.
4400 For MS Windows and Nextstep the result is hard-coded.
4401 
4402 TERMINAL should be a terminal object, a frame or a display name (a string).
4403 If omitted or nil, that stands for the selected frame's display.  */)
4404   (Lisp_Object terminal)
4405 {
4406   struct x_display_info *dpyinfo = check_x_display_info (terminal);
4407   const char *vendor = ServerVendor (dpyinfo->display);
4408 
4409   if (! vendor) vendor = "";
4410   return build_string (vendor);
4411 }
4412 
4413 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
4414        doc: /* Return the version numbers of the GUI software on TERMINAL.
4415 The value is a list of three integers specifying the version of the GUI
4416 software in use.
4417 
4418 For GNU and Unix system, the first 2 numbers are the version of the X
4419 Protocol used on TERMINAL and the 3rd number is the distributor-specific
4420 release number.  For MS Windows, the 3 numbers report the OS major and
4421 minor version and build number.  For Nextstep, the first 2 numbers are
4422 hard-coded and the 3rd represents the OS version.
4423 
4424 See also the function `x-server-vendor'.
4425 
4426 The optional argument TERMINAL specifies which display to ask about.
4427 TERMINAL should be a terminal object, a frame or a display name (a string).
4428 If omitted or nil, that stands for the selected frame's display.  */)
4429   (Lisp_Object terminal)
4430 {
4431   struct x_display_info *dpyinfo = check_x_display_info (terminal);
4432   Display *dpy = dpyinfo->display;
4433 
4434   return list3i (ProtocolVersion (dpy), ProtocolRevision (dpy),
4435 		 VendorRelease (dpy));
4436 }
4437 
4438 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
4439        doc: /* Return the number of screens on the X server of display TERMINAL.
4440 The optional argument TERMINAL specifies which display to ask about.
4441 TERMINAL should be a terminal object, a frame or a display name (a string).
4442 If omitted or nil, that stands for the selected frame's display.
4443 
4444 On MS Windows, this function just returns 1.
4445 On Nextstep, "screen" is in X terminology, not that of Nextstep.
4446 For the number of physical monitors, use `(length
4447 \(display-monitor-attributes-list TERMINAL))' instead.  */)
4448   (Lisp_Object terminal)
4449 {
4450   struct x_display_info *dpyinfo = check_x_display_info (terminal);
4451 
4452   return make_fixnum (ScreenCount (dpyinfo->display));
4453 }
4454 
4455 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
4456        doc: /* Return the height in millimeters of the X display TERMINAL.
4457 The optional argument TERMINAL specifies which display to ask about.
4458 TERMINAL should be a terminal object, a frame or a display name (a string).
4459 If omitted or nil, that stands for the selected frame's display.
4460 \(On MS Windows, this function does not accept terminal objects.)
4461 
4462 On \"multi-monitor\" setups this refers to the height in millimeters for
4463 all physical monitors associated with TERMINAL.  To get information
4464 for each physical monitor, use `display-monitor-attributes-list'.  */)
4465   (Lisp_Object terminal)
4466 {
4467   struct x_display_info *dpyinfo = check_x_display_info (terminal);
4468 
4469   return make_fixnum (HeightMMOfScreen (dpyinfo->screen));
4470 }
4471 
4472 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
4473        doc: /* Return the width in millimeters of the X display TERMINAL.
4474 The optional argument TERMINAL specifies which display to ask about.
4475 TERMINAL should be a terminal object, a frame or a display name (a string).
4476 If omitted or nil, that stands for the selected frame's display.
4477 \(On MS Windows, this function does not accept terminal objects.)
4478 
4479 On \"multi-monitor\" setups this refers to the width in millimeters for
4480 all physical monitors associated with TERMINAL.  To get information
4481 for each physical monitor, use `display-monitor-attributes-list'.  */)
4482   (Lisp_Object terminal)
4483 {
4484   struct x_display_info *dpyinfo = check_x_display_info (terminal);
4485 
4486   return make_fixnum (WidthMMOfScreen (dpyinfo->screen));
4487 }
4488 
4489 DEFUN ("x-display-backing-store", Fx_display_backing_store,
4490        Sx_display_backing_store, 0, 1, 0,
4491        doc: /* Return an indication of whether X display TERMINAL does backing store.
4492 The optional argument TERMINAL specifies which display to ask about.
4493 TERMINAL should be a terminal object, a frame or a display name (a string).
4494 If omitted or nil, that stands for the selected frame's display.
4495 
4496 The value may be `always', `when-mapped', or `not-useful'.
4497 On Nextstep, the value may be `buffered', `retained', or `non-retained'.
4498 On MS Windows, this returns nothing useful.  */)
4499   (Lisp_Object terminal)
4500 {
4501   struct x_display_info *dpyinfo = check_x_display_info (terminal);
4502   Lisp_Object result;
4503 
4504   switch (DoesBackingStore (dpyinfo->screen))
4505     {
4506     case Always:
4507       result = intern ("always");
4508       break;
4509 
4510     case WhenMapped:
4511       result = intern ("when-mapped");
4512       break;
4513 
4514     case NotUseful:
4515       result = intern ("not-useful");
4516       break;
4517 
4518     default:
4519       error ("Strange value for BackingStore parameter of screen");
4520     }
4521 
4522   return result;
4523 }
4524 
4525 DEFUN ("x-display-visual-class", Fx_display_visual_class,
4526        Sx_display_visual_class, 0, 1, 0,
4527        doc: /* Return the visual class of the X display TERMINAL.
4528 The value is one of the symbols `static-gray', `gray-scale',
4529 `static-color', `pseudo-color', `true-color', or `direct-color'.
4530 \(On MS Windows, the second and last result above are not possible.)
4531 
4532 The optional argument TERMINAL specifies which display to ask about.
4533 TERMINAL should a terminal object, a frame or a display name (a string).
4534 If omitted or nil, that stands for the selected frame's display.
4535 \(On MS Windows, this function does not accept terminal objects.)  */)
4536   (Lisp_Object terminal)
4537 {
4538   struct x_display_info *dpyinfo = check_x_display_info (terminal);
4539   Lisp_Object result;
4540 
4541   switch (dpyinfo->visual->class)
4542     {
4543     case StaticGray:
4544       result = intern ("static-gray");
4545       break;
4546     case GrayScale:
4547       result = intern ("gray-scale");
4548       break;
4549     case StaticColor:
4550       result = intern ("static-color");
4551       break;
4552     case PseudoColor:
4553       result = intern ("pseudo-color");
4554       break;
4555     case TrueColor:
4556       result = intern ("true-color");
4557       break;
4558     case DirectColor:
4559       result = intern ("direct-color");
4560       break;
4561     default:
4562       error ("Display has an unknown visual class");
4563     }
4564 
4565   return result;
4566 }
4567 
4568 DEFUN ("x-display-save-under", Fx_display_save_under,
4569        Sx_display_save_under, 0, 1, 0,
4570        doc: /* Return t if the X display TERMINAL supports the save-under feature.
4571 The optional argument TERMINAL specifies which display to ask about.
4572 TERMINAL should be a terminal object, a frame or a display name (a string).
4573 If omitted or nil, that stands for the selected frame's display.
4574 
4575 On MS Windows, this just returns nil.  */)
4576   (Lisp_Object terminal)
4577 {
4578   struct x_display_info *dpyinfo = check_x_display_info (terminal);
4579 
4580   if (DoesSaveUnders (dpyinfo->screen) == True)
4581     return Qt;
4582   else
4583     return Qnil;
4584 }
4585 
4586 #if !defined USE_GTK || !defined HAVE_GTK3
4587 
4588 /* Store the geometry of the workarea on display DPYINFO into *RECT.
4589    Return false if and only if the workarea information cannot be
4590    obtained via the _NET_WORKAREA root window property.  */
4591 
4592 static bool
x_get_net_workarea(struct x_display_info * dpyinfo,XRectangle * rect)4593 x_get_net_workarea (struct x_display_info *dpyinfo, XRectangle *rect)
4594 {
4595   Display *dpy = dpyinfo->display;
4596   long offset, max_len;
4597   Atom target_type, actual_type;
4598   unsigned long actual_size, bytes_remaining;
4599   int rc, actual_format;
4600   unsigned char *tmp_data = NULL;
4601   bool result = false;
4602 
4603   x_catch_errors (dpy);
4604   offset = 0;
4605   max_len = 1;
4606   target_type = XA_CARDINAL;
4607   rc = XGetWindowProperty (dpy, dpyinfo->root_window,
4608 			   dpyinfo->Xatom_net_current_desktop,
4609 			   offset, max_len, False, target_type,
4610 			   &actual_type, &actual_format, &actual_size,
4611 			   &bytes_remaining, &tmp_data);
4612   if (rc == Success && actual_type == target_type && !x_had_errors_p (dpy)
4613       && actual_format == 32 && actual_size == max_len)
4614     {
4615       long current_desktop = ((long *) tmp_data)[0];
4616 
4617       XFree (tmp_data);
4618       tmp_data = NULL;
4619 
4620       offset = 4 * current_desktop;
4621       max_len = 4;
4622       rc = XGetWindowProperty (dpy, dpyinfo->root_window,
4623 			       dpyinfo->Xatom_net_workarea,
4624 			       offset, max_len, False, target_type,
4625 			       &actual_type, &actual_format, &actual_size,
4626 			       &bytes_remaining, &tmp_data);
4627       if (rc == Success && actual_type == target_type && !x_had_errors_p (dpy)
4628 	  && actual_format == 32 && actual_size == max_len)
4629 	{
4630 	  long *values = (long *) tmp_data;
4631 
4632 	  rect->x = values[0];
4633 	  rect->y = values[1];
4634 	  rect->width = values[2];
4635 	  rect->height = values[3];
4636 
4637 	  XFree (tmp_data);
4638 	  tmp_data = NULL;
4639 
4640 	  result = true;
4641 	}
4642     }
4643   if (tmp_data)
4644     XFree (tmp_data);
4645   x_uncatch_errors ();
4646 
4647   return result;
4648 }
4649 
4650 /* Return monitor number where F is "most" or closest to.  */
4651 static int
x_get_monitor_for_frame(struct frame * f,struct MonitorInfo * monitors,int n_monitors)4652 x_get_monitor_for_frame (struct frame *f,
4653                          struct MonitorInfo *monitors,
4654                          int n_monitors)
4655 {
4656   XRectangle frect;
4657   int area = 0, dist = -1;
4658   int best_area = -1, best_dist = -1;
4659   int i;
4660 
4661   if (n_monitors == 1) return 0;
4662   frect.x = f->left_pos;
4663   frect.y = f->top_pos;
4664   frect.width = FRAME_PIXEL_WIDTH (f);
4665   frect.height = FRAME_PIXEL_HEIGHT (f);
4666 
4667   for (i = 0; i < n_monitors; ++i)
4668     {
4669       struct MonitorInfo *mi = &monitors[i];
4670       XRectangle res;
4671       int a = 0;
4672 
4673       if (mi->geom.width == 0) continue;
4674 
4675       if (gui_intersect_rectangles (&mi->geom, &frect, &res))
4676         {
4677           a = res.width * res.height;
4678           if (a > area)
4679 	    {
4680 	      area = a;
4681 	      best_area = i;
4682 	    }
4683         }
4684 
4685       if (a == 0 && area == 0)
4686         {
4687           int dx, dy, d;
4688           if (frect.x + frect.width < mi->geom.x)
4689             dx = mi->geom.x - frect.x + frect.width;
4690           else if (frect.x > mi->geom.x + mi->geom.width)
4691             dx = frect.x - mi->geom.x + mi->geom.width;
4692           else
4693             dx = 0;
4694           if (frect.y + frect.height < mi->geom.y)
4695             dy = mi->geom.y - frect.y + frect.height;
4696           else if (frect.y > mi->geom.y + mi->geom.height)
4697             dy = frect.y - mi->geom.y + mi->geom.height;
4698           else
4699             dy = 0;
4700 
4701           d = dx*dx + dy*dy;
4702           if (dist == -1 || dist > d)
4703             {
4704               dist = d;
4705               best_dist = i;
4706             }
4707         }
4708     }
4709 
4710   return best_area != -1 ? best_area : (best_dist != -1 ? best_dist : 0);
4711 }
4712 
4713 static Lisp_Object
x_make_monitor_attribute_list(struct MonitorInfo * monitors,int n_monitors,int primary_monitor,struct x_display_info * dpyinfo,const char * source)4714 x_make_monitor_attribute_list (struct MonitorInfo *monitors,
4715                                int n_monitors,
4716                                int primary_monitor,
4717                                struct x_display_info *dpyinfo,
4718                                const char *source)
4719 {
4720   Lisp_Object monitor_frames = make_nil_vector (n_monitors);
4721   Lisp_Object frame, rest;
4722 
4723   FOR_EACH_FRAME (rest, frame)
4724     {
4725       struct frame *f = XFRAME (frame);
4726 
4727       if (FRAME_X_P (f)
4728 	  && FRAME_DISPLAY_INFO (f) == dpyinfo
4729 	  && !FRAME_TOOLTIP_P (f))
4730 	{
4731 	  int i = x_get_monitor_for_frame (f, monitors, n_monitors);
4732 	  ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i)));
4733 	}
4734     }
4735 
4736   return make_monitor_attribute_list (monitors, n_monitors, primary_monitor,
4737                                       monitor_frames, source);
4738 }
4739 
4740 static Lisp_Object
x_get_monitor_attributes_fallback(struct x_display_info * dpyinfo)4741 x_get_monitor_attributes_fallback (struct x_display_info *dpyinfo)
4742 {
4743   struct MonitorInfo monitor;
4744   XRectangle workarea_r;
4745 
4746   /* Fallback: treat (possibly) multiple physical monitors as if they
4747      formed a single monitor as a whole.  This should provide a
4748      consistent result at least on single monitor environments.  */
4749   monitor.geom.x = monitor.geom.y = 0;
4750   monitor.geom.width = x_display_pixel_width (dpyinfo);
4751   monitor.geom.height = x_display_pixel_height (dpyinfo);
4752   monitor.mm_width = WidthMMOfScreen (dpyinfo->screen);
4753   monitor.mm_height = HeightMMOfScreen (dpyinfo->screen);
4754   monitor.name = xstrdup ("combined screen");
4755 
4756   if (x_get_net_workarea (dpyinfo, &workarea_r))
4757     monitor.work = workarea_r;
4758   else
4759     monitor.work = monitor.geom;
4760   return x_make_monitor_attribute_list (&monitor, 1, 0, dpyinfo, "fallback");
4761 }
4762 
4763 
4764 #ifdef HAVE_XINERAMA
4765 static Lisp_Object
x_get_monitor_attributes_xinerama(struct x_display_info * dpyinfo)4766 x_get_monitor_attributes_xinerama (struct x_display_info *dpyinfo)
4767 {
4768   int n_monitors, i;
4769   Lisp_Object attributes_list = Qnil;
4770   Display *dpy = dpyinfo->display;
4771   XineramaScreenInfo *info = XineramaQueryScreens (dpy, &n_monitors);
4772   struct MonitorInfo *monitors;
4773   double mm_width_per_pixel, mm_height_per_pixel;
4774 
4775   if (! info || n_monitors == 0)
4776     {
4777       if (info)
4778 	XFree (info);
4779       return attributes_list;
4780     }
4781 
4782   mm_width_per_pixel = ((double) WidthMMOfScreen (dpyinfo->screen)
4783 			/ x_display_pixel_width (dpyinfo));
4784   mm_height_per_pixel = ((double) HeightMMOfScreen (dpyinfo->screen)
4785 			 / x_display_pixel_height (dpyinfo));
4786   monitors = xzalloc (n_monitors * sizeof *monitors);
4787   for (i = 0; i < n_monitors; ++i)
4788     {
4789       struct MonitorInfo *mi = &monitors[i];
4790       XRectangle workarea_r;
4791 
4792       mi->geom.x = info[i].x_org;
4793       mi->geom.y = info[i].y_org;
4794       mi->geom.width = info[i].width;
4795       mi->geom.height = info[i].height;
4796       mi->mm_width = mi->geom.width * mm_width_per_pixel + 0.5;
4797       mi->mm_height = mi->geom.height * mm_height_per_pixel + 0.5;
4798       mi->name = 0;
4799 
4800       /* Xinerama usually have primary monitor first, just use that.  */
4801       if (i == 0 && x_get_net_workarea (dpyinfo, &workarea_r))
4802 	{
4803 	  mi->work = workarea_r;
4804 	  if (! gui_intersect_rectangles (&mi->geom, &mi->work, &mi->work))
4805 	    mi->work = mi->geom;
4806 	}
4807       else
4808 	mi->work = mi->geom;
4809     }
4810   XFree (info);
4811 
4812   attributes_list = x_make_monitor_attribute_list (monitors,
4813                                                    n_monitors,
4814                                                    0,
4815                                                    dpyinfo,
4816                                                    "Xinerama");
4817   free_monitors (monitors, n_monitors);
4818   return attributes_list;
4819 }
4820 #endif /* HAVE_XINERAMA */
4821 
4822 
4823 #ifdef HAVE_XRANDR
4824 static Lisp_Object
x_get_monitor_attributes_xrandr(struct x_display_info * dpyinfo)4825 x_get_monitor_attributes_xrandr (struct x_display_info *dpyinfo)
4826 {
4827   Lisp_Object attributes_list = Qnil;
4828   XRRScreenResources *resources;
4829   Display *dpy = dpyinfo->display;
4830   int i, n_monitors, primary = -1;
4831   RROutput pxid = None;
4832   struct MonitorInfo *monitors;
4833 
4834 #define RANDR13_LIBRARY \
4835   (RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 3))
4836 
4837 #if RANDR13_LIBRARY
4838   /* Check if the display supports 1.3 too.  */
4839   bool randr13_avail = (dpyinfo->xrandr_major_version > 1
4840 			|| (dpyinfo->xrandr_major_version == 1
4841 			    && dpyinfo->xrandr_minor_version >= 3));
4842 
4843   if (randr13_avail)
4844     resources = XRRGetScreenResourcesCurrent (dpy, dpyinfo->root_window);
4845   else
4846     resources = XRRGetScreenResources (dpy, dpyinfo->root_window);
4847 #else
4848   resources = XRRGetScreenResources (dpy, dpyinfo->root_window);
4849 #endif
4850   if (! resources || resources->noutput == 0)
4851     {
4852       if (resources)
4853 	XRRFreeScreenResources (resources);
4854       return Qnil;
4855     }
4856   n_monitors = resources->noutput;
4857   monitors = xzalloc (n_monitors * sizeof *monitors);
4858 
4859 #if RANDR13_LIBRARY
4860   if (randr13_avail)
4861     pxid = XRRGetOutputPrimary (dpy, dpyinfo->root_window);
4862 #endif
4863 
4864   for (i = 0; i < n_monitors; ++i)
4865     {
4866       XRROutputInfo *info = XRRGetOutputInfo (dpy, resources,
4867                                               resources->outputs[i]);
4868       if (!info)
4869 	continue;
4870 
4871       if (strcmp (info->name, "default") == 0)
4872         {
4873           /* Non XRandr 1.2 driver, does not give useful data.  */
4874 	  XRRFreeOutputInfo (info);
4875 	  XRRFreeScreenResources (resources);
4876           free_monitors (monitors, n_monitors);
4877           return Qnil;
4878         }
4879 
4880       if (info->connection != RR_Disconnected && info->crtc != None)
4881         {
4882           XRRCrtcInfo *crtc = XRRGetCrtcInfo (dpy, resources, info->crtc);
4883           struct MonitorInfo *mi = &monitors[i];
4884           XRectangle workarea_r;
4885 
4886           if (! crtc)
4887 	    {
4888 	      XRRFreeOutputInfo (info);
4889 	      continue;
4890 	    }
4891 
4892           mi->geom.x = crtc->x;
4893           mi->geom.y = crtc->y;
4894           mi->geom.width = crtc->width;
4895           mi->geom.height = crtc->height;
4896           mi->mm_width = info->mm_width;
4897           mi->mm_height = info->mm_height;
4898           mi->name = xstrdup (info->name);
4899 
4900           if (pxid != None && pxid == resources->outputs[i])
4901             primary = i;
4902           else if (primary == -1 && strcmp (info->name, "LVDS") == 0)
4903             primary = i;
4904 
4905           if (i == primary && x_get_net_workarea (dpyinfo, &workarea_r))
4906             {
4907               mi->work= workarea_r;
4908               if (! gui_intersect_rectangles (&mi->geom, &mi->work, &mi->work))
4909                 mi->work = mi->geom;
4910             }
4911           else
4912             mi->work = mi->geom;
4913 
4914           XRRFreeCrtcInfo (crtc);
4915         }
4916       XRRFreeOutputInfo (info);
4917     }
4918   XRRFreeScreenResources (resources);
4919 
4920   attributes_list = x_make_monitor_attribute_list (monitors,
4921                                                    n_monitors,
4922                                                    primary,
4923                                                    dpyinfo,
4924                                                    "XRandr");
4925   free_monitors (monitors, n_monitors);
4926   return attributes_list;
4927 }
4928 #endif /* HAVE_XRANDR */
4929 
4930 static Lisp_Object
x_get_monitor_attributes(struct x_display_info * dpyinfo)4931 x_get_monitor_attributes (struct x_display_info *dpyinfo)
4932 {
4933   Lisp_Object attributes_list = Qnil;
4934   Display *dpy = dpyinfo->display;
4935 
4936   (void) dpy; /* Suppress unused variable warning.  */
4937 
4938 #ifdef HAVE_XRANDR
4939   int xrr_event_base, xrr_error_base;
4940   bool xrr_ok = false;
4941   xrr_ok = XRRQueryExtension (dpy, &xrr_event_base, &xrr_error_base);
4942   if (xrr_ok)
4943     {
4944       XRRQueryVersion (dpy, &dpyinfo->xrandr_major_version,
4945 		       &dpyinfo->xrandr_minor_version);
4946       xrr_ok = ((dpyinfo->xrandr_major_version == 1
4947 		 && dpyinfo->xrandr_minor_version >= 2)
4948 		|| dpyinfo->xrandr_major_version > 1);
4949     }
4950 
4951   if (xrr_ok)
4952     attributes_list = x_get_monitor_attributes_xrandr (dpyinfo);
4953 #endif /* HAVE_XRANDR */
4954 
4955 #ifdef HAVE_XINERAMA
4956   if (NILP (attributes_list))
4957     {
4958       int xin_event_base, xin_error_base;
4959       bool xin_ok = false;
4960       xin_ok = XineramaQueryExtension (dpy, &xin_event_base, &xin_error_base);
4961       if (xin_ok && XineramaIsActive (dpy))
4962         attributes_list = x_get_monitor_attributes_xinerama (dpyinfo);
4963     }
4964 #endif /* HAVE_XINERAMA */
4965 
4966   if (NILP (attributes_list))
4967     attributes_list = x_get_monitor_attributes_fallback (dpyinfo);
4968 
4969   return attributes_list;
4970 }
4971 
4972 #endif /* !USE_GTK */
4973 
4974 DEFUN ("x-display-monitor-attributes-list", Fx_display_monitor_attributes_list,
4975        Sx_display_monitor_attributes_list,
4976        0, 1, 0,
4977        doc: /* Return a list of physical monitor attributes on the X display TERMINAL.
4978 
4979 The optional argument TERMINAL specifies which display to ask about.
4980 TERMINAL should be a terminal object, a frame or a display name (a string).
4981 If omitted or nil, that stands for the selected frame's display.
4982 
4983 In addition to the standard attribute keys listed in
4984 `display-monitor-attributes-list', the following keys are contained in
4985 the attributes:
4986 
4987  source -- String describing the source from which multi-monitor
4988 	   information is obtained, one of \"Gdk\", \"XRandr\",
4989 	   \"Xinerama\", or \"fallback\"
4990 
4991 Internal use only, use `display-monitor-attributes-list' instead.  */)
4992   (Lisp_Object terminal)
4993 {
4994   struct x_display_info *dpyinfo = check_x_display_info (terminal);
4995   Lisp_Object attributes_list = Qnil;
4996 
4997 #ifdef USE_GTK
4998   GdkDisplay *gdpy;
4999 #if ! GTK_CHECK_VERSION (3, 22, 0)
5000   double mm_width_per_pixel, mm_height_per_pixel;
5001   GdkScreen *gscreen;
5002 #endif
5003   gint primary_monitor = 0, n_monitors, i;
5004   Lisp_Object monitor_frames, rest, frame;
5005   static const char *source = "Gdk";
5006   struct MonitorInfo *monitors;
5007 
5008   block_input ();
5009   gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display);
5010 #if GTK_CHECK_VERSION (3, 22, 0)
5011   n_monitors = gdk_display_get_n_monitors (gdpy);
5012 #else
5013   gscreen = gdk_display_get_default_screen (gdpy);
5014   n_monitors = gdk_screen_get_n_monitors (gscreen);
5015   primary_monitor = gdk_screen_get_primary_monitor (gscreen);
5016   /* Fallback if gdk_screen_get_monitor_{width,height}_mm fail */
5017   mm_width_per_pixel = ((double) WidthMMOfScreen (dpyinfo->screen)
5018 			/ x_display_pixel_width (dpyinfo));
5019   mm_height_per_pixel = ((double) HeightMMOfScreen (dpyinfo->screen)
5020 			 / x_display_pixel_height (dpyinfo));
5021 #endif
5022   monitor_frames = make_nil_vector (n_monitors);
5023   monitors = xzalloc (n_monitors * sizeof *monitors);
5024 
FOR_EACH_FRAME(rest,frame)5025   FOR_EACH_FRAME (rest, frame)
5026     {
5027       struct frame *f = XFRAME (frame);
5028 
5029       if (FRAME_X_P (f)
5030 	  && FRAME_DISPLAY_INFO (f) == dpyinfo
5031 	  && !FRAME_TOOLTIP_P (f))
5032 	{
5033 	  GdkWindow *gwin = gtk_widget_get_window (FRAME_GTK_WIDGET (f));
5034 
5035 #if GTK_CHECK_VERSION (3, 22, 0)
5036           for (i = 0; i < n_monitors; i++)
5037             if (gdk_display_get_monitor_at_window (gdpy, gwin)
5038                 == gdk_display_get_monitor (gdpy, i))
5039               break;
5040 #else
5041 	  i = gdk_screen_get_monitor_at_window (gscreen, gwin);
5042 #endif
5043 	  ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i)));
5044 	}
5045     }
5046 
5047   for (i = 0; i < n_monitors; ++i)
5048     {
5049       gint width_mm, height_mm;
5050       GdkRectangle rec, work;
5051       struct MonitorInfo *mi = &monitors[i];
5052       int scale = 1;
5053 
5054 #if GTK_CHECK_VERSION (3, 22, 0)
5055       GdkMonitor *monitor = gdk_display_get_monitor (gdpy, i);
5056       if (gdk_monitor_is_primary (monitor))
5057         primary_monitor = i;
5058       gdk_monitor_get_geometry (monitor, &rec);
5059 #else
5060       gdk_screen_get_monitor_geometry (gscreen, i, &rec);
5061 #endif
5062 
5063 #if GTK_CHECK_VERSION (3, 22, 0)
5064       width_mm = gdk_monitor_get_width_mm (monitor);
5065       height_mm = gdk_monitor_get_height_mm (monitor);
5066 #else
5067       width_mm = gdk_screen_get_monitor_width_mm (gscreen, i);
5068       height_mm = gdk_screen_get_monitor_height_mm (gscreen, i);
5069       if (width_mm < 0)
5070 	width_mm = rec.width * mm_width_per_pixel + 0.5;
5071       if (height_mm < 0)
5072 	height_mm = rec.height * mm_height_per_pixel + 0.5;
5073 #endif
5074 #if GTK_CHECK_VERSION (3, 22, 0)
5075       gdk_monitor_get_workarea (monitor, &work);
5076 #elif defined HAVE_GTK3
5077       gdk_screen_get_monitor_workarea (gscreen, i, &work);
5078 #else
5079       /* Emulate the behavior of GTK+ 3.4.  */
5080       {
5081 	XRectangle workarea_r;
5082 
5083 	if (i == primary_monitor && x_get_net_workarea (dpyinfo, &workarea_r))
5084 	  {
5085 	    work.x = workarea_r.x;
5086 	    work.y = workarea_r.y;
5087 	    work.width = workarea_r.width;
5088 	    work.height = workarea_r.height;
5089 	    if (! gdk_rectangle_intersect (&rec, &work, &work))
5090               work = rec;
5091           }
5092         else
5093           work = rec;
5094       }
5095 #endif
5096 
5097       /* GTK returns scaled sizes for the workareas.  */
5098 #if GTK_CHECK_VERSION (3, 22, 0)
5099       scale = gdk_monitor_get_scale_factor (monitor);
5100 #elif defined HAVE_GTK3
5101       scale = gdk_screen_get_monitor_scale_factor (gscreen, i);
5102 #endif
5103       rec.x *= scale;
5104       rec.y *= scale;
5105       rec.width *= scale;
5106       rec.height *= scale;
5107       work.x *= scale;
5108       work.y *= scale;
5109       work.width *= scale;
5110       work.height *= scale;
5111 
5112       mi->geom.x = rec.x;
5113       mi->geom.y = rec.y;
5114       mi->geom.width = rec.width;
5115       mi->geom.height = rec.height;
5116       mi->work.x = work.x;
5117       mi->work.y = work.y;
5118       mi->work.width = work.width;
5119       mi->work.height = work.height;
5120       mi->mm_width = width_mm;
5121       mi->mm_height = height_mm;
5122 
5123 #if GTK_CHECK_VERSION (3, 22, 0)
5124       dupstring (&mi->name, (gdk_monitor_get_model (monitor)));
5125 #else
5126       mi->name = gdk_screen_get_monitor_plug_name (gscreen, i);
5127 #endif
5128     }
5129 
5130   attributes_list = make_monitor_attribute_list (monitors,
5131                                                  n_monitors,
5132                                                  primary_monitor,
5133                                                  monitor_frames,
5134                                                  source);
5135   free_monitors (monitors, n_monitors);
5136   unblock_input ();
5137 #else  /* not USE_GTK */
5138 
5139   block_input ();
5140   attributes_list = x_get_monitor_attributes (dpyinfo);
5141   unblock_input ();
5142 
5143 #endif	/* not USE_GTK */
5144 
5145   return attributes_list;
5146 }
5147 
5148 /* Return geometric attributes of FRAME.  According to the value of
5149    ATTRIBUTES return the outer edges of FRAME (Qouter_edges), the native
5150    edges of FRAME (Qnative_edges), or the inner edges of frame
5151    (Qinner_edges).  Any other value means to return the geometry as
5152    returned by Fx_frame_geometry.  */
5153 static Lisp_Object
frame_geometry(Lisp_Object frame,Lisp_Object attribute)5154 frame_geometry (Lisp_Object frame, Lisp_Object attribute)
5155 {
5156   struct frame *f = decode_live_frame (frame);
5157   /**   XWindowAttributes atts; **/
5158   Window rootw;
5159   unsigned int ign, native_width, native_height, x_border_width = 0;
5160   int x_native = 0, y_native = 0, xptr = 0, yptr = 0;
5161   int left_off = 0, right_off = 0, top_off = 0, bottom_off = 0;
5162   int outer_left, outer_top, outer_right, outer_bottom;
5163   int native_left, native_top, native_right, native_bottom;
5164   int inner_left, inner_top, inner_right, inner_bottom;
5165   int internal_border_width;
5166   bool menu_bar_external = false, tool_bar_external = false;
5167   int menu_bar_height = 0, menu_bar_width = 0;
5168   int tab_bar_height = 0, tab_bar_width = 0;
5169   int tool_bar_height = 0, tool_bar_width = 0;
5170 
5171   if (FRAME_INITIAL_P (f) || !FRAME_X_P (f) || !FRAME_OUTER_WINDOW (f))
5172     return Qnil;
5173 
5174   block_input ();
5175   XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
5176 		&rootw, &x_native, &y_native, &native_width, &native_height,
5177 		&x_border_width, &ign);
5178   /**   XGetWindowAttributes (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &atts); **/
5179   if (!FRAME_PARENT_FRAME (f))
5180     x_real_pos_and_offsets (f, &left_off, &right_off, &top_off, &bottom_off,
5181 			    NULL, NULL, &xptr, &yptr, NULL);
5182   unblock_input ();
5183 
5184   /**   native_width = atts.width; **/
5185   /**   native_height = atts.height; **/
5186 
5187   if (FRAME_PARENT_FRAME (f))
5188     {
5189       Lisp_Object parent, edges;
5190 
5191       XSETFRAME (parent, FRAME_PARENT_FRAME (f));
5192       edges = Fx_frame_edges (parent, Qnative_edges);
5193       if (!NILP (edges))
5194 	{
5195 	  x_native += XFIXNUM (Fnth (make_fixnum (0), edges));
5196 	  y_native += XFIXNUM (Fnth (make_fixnum (1), edges));
5197 	}
5198 
5199       outer_left = x_native;
5200       outer_top = y_native;
5201       outer_right = outer_left + native_width + 2 * x_border_width;
5202       outer_bottom = outer_top + native_height + 2 * x_border_width;
5203 
5204       native_left = x_native + x_border_width;
5205       native_top = y_native + x_border_width;
5206       native_right = native_left + native_width;
5207       native_bottom = native_top + native_height;
5208     }
5209   else
5210     {
5211       outer_left = xptr;
5212       outer_top = yptr;
5213       outer_right = outer_left + left_off + native_width + right_off;
5214       outer_bottom = outer_top + top_off + native_height + bottom_off;
5215 
5216       native_left = outer_left + left_off;
5217       native_top = outer_top + top_off;
5218       native_right = native_left + native_width;
5219       native_bottom = native_top + native_height;
5220     }
5221 
5222   internal_border_width = FRAME_INTERNAL_BORDER_WIDTH (f);
5223   inner_left = native_left + internal_border_width;
5224   inner_top = native_top + internal_border_width;
5225   inner_right = native_right - internal_border_width;
5226   inner_bottom = native_bottom - internal_border_width;
5227 
5228 #ifdef HAVE_EXT_MENU_BAR
5229   menu_bar_external = true;
5230   menu_bar_height = FRAME_MENUBAR_HEIGHT (f);
5231   native_top += menu_bar_height;
5232   inner_top += menu_bar_height;
5233 #else
5234   menu_bar_height = FRAME_MENU_BAR_HEIGHT (f);
5235   inner_top += menu_bar_height;
5236 #endif
5237   menu_bar_width = menu_bar_height ? native_width : 0;
5238 
5239   tab_bar_height = FRAME_TAB_BAR_HEIGHT (f);
5240   tab_bar_width = (tab_bar_height
5241 		    ? native_width - 2 * internal_border_width
5242 		    : 0);
5243   inner_top += tab_bar_height;
5244 
5245 #ifdef HAVE_EXT_TOOL_BAR
5246   tool_bar_external = true;
5247   if (EQ (FRAME_TOOL_BAR_POSITION (f), Qleft))
5248     {
5249       tool_bar_width = FRAME_TOOLBAR_WIDTH (f);
5250       native_left += tool_bar_width;
5251       inner_left += tool_bar_width;
5252       tool_bar_height
5253 	= tool_bar_width ? native_height - menu_bar_height : 0;
5254     }
5255   else if (EQ (FRAME_TOOL_BAR_POSITION (f), Qtop))
5256     {
5257       tool_bar_height = FRAME_TOOLBAR_HEIGHT (f);
5258       native_top += tool_bar_height;
5259       inner_top += tool_bar_height;
5260       tool_bar_width = tool_bar_height ? native_width : 0;
5261     }
5262   else if (EQ (FRAME_TOOL_BAR_POSITION (f), Qright))
5263     {
5264       tool_bar_width = FRAME_TOOLBAR_WIDTH (f);
5265       native_right -= tool_bar_width;
5266       inner_right -= tool_bar_width;
5267       tool_bar_height
5268 	= tool_bar_width ? native_height - menu_bar_height : 0;
5269     }
5270   else
5271     {
5272       tool_bar_height = FRAME_TOOLBAR_HEIGHT (f);
5273       native_bottom -= tool_bar_height;
5274       inner_bottom -= tool_bar_height;
5275       tool_bar_width = tool_bar_height ? native_width : 0;
5276     }
5277 #else
5278   tool_bar_height = FRAME_TOOL_BAR_HEIGHT (f);
5279   tool_bar_width = (tool_bar_height
5280 		    ? native_width - 2 * internal_border_width
5281 		    : 0);
5282   inner_top += tool_bar_height;
5283 #endif
5284 
5285   /* Construct list.  */
5286   if (EQ (attribute, Qouter_edges))
5287     return list4i (outer_left, outer_top, outer_right, outer_bottom);
5288   else if (EQ (attribute, Qnative_edges))
5289     return list4i (native_left, native_top, native_right, native_bottom);
5290   else if (EQ (attribute, Qinner_edges))
5291     return list4i (inner_left, inner_top, inner_right, inner_bottom);
5292   else
5293     return
5294        list (Fcons (Qouter_position,
5295 		    Fcons (make_fixnum (outer_left),
5296 			   make_fixnum (outer_top))),
5297 	     Fcons (Qouter_size,
5298 		    Fcons (make_fixnum (outer_right - outer_left),
5299 			   make_fixnum (outer_bottom - outer_top))),
5300 	     /* Approximate.  */
5301 	     Fcons (Qexternal_border_size,
5302 		    Fcons (make_fixnum (right_off),
5303 			   make_fixnum (bottom_off))),
5304 	     Fcons (Qouter_border_width, make_fixnum (x_border_width)),
5305 	     /* Approximate.  */
5306 	     Fcons (Qtitle_bar_size,
5307 		    Fcons (make_fixnum (0),
5308 			   make_fixnum (top_off - bottom_off))),
5309 	     Fcons (Qmenu_bar_external, menu_bar_external ? Qt : Qnil),
5310 	     Fcons (Qmenu_bar_size,
5311 		    Fcons (make_fixnum (menu_bar_width),
5312 			   make_fixnum (menu_bar_height))),
5313 	     Fcons (Qtab_bar_size,
5314 		    Fcons (make_fixnum (tab_bar_width),
5315 			   make_fixnum (tab_bar_height))),
5316 	     Fcons (Qtool_bar_external, tool_bar_external ? Qt : Qnil),
5317 	     Fcons (Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f)),
5318 	     Fcons (Qtool_bar_size,
5319 		    Fcons (make_fixnum (tool_bar_width),
5320 			   make_fixnum (tool_bar_height))),
5321 	     Fcons (Qinternal_border_width,
5322 		    make_fixnum (internal_border_width)));
5323 }
5324 
5325 DEFUN ("x-frame-geometry", Fx_frame_geometry, Sx_frame_geometry, 0, 1, 0,
5326        doc: /* Return geometric attributes of FRAME.
5327 FRAME must be a live frame and defaults to the selected one.  The return
5328 value is an association list of the attributes listed below.  All height
5329 and width values are in pixels.
5330 
5331 `outer-position' is a cons of the outer left and top edges of FRAME
5332   relative to the origin - the position (0, 0) - of FRAME's display.
5333 
5334 `outer-size' is a cons of the outer width and height of FRAME.  The
5335   outer size includes the title bar and the external borders as well as
5336   any menu and/or tool bar of frame.  For a child frame the value
5337   includes FRAME's X borders, if any.
5338 
5339 `external-border-size' is a cons of the horizontal and vertical width of
5340   FRAME's external borders as supplied by the window manager.
5341 
5342 `title-bar-size' is a cons of the width and height of the title bar of
5343   FRAME as supplied by the window manager.  If both of them are zero,
5344   FRAME has no title bar.  If only the width is zero, Emacs was not
5345   able to retrieve the width information.
5346 
5347 `menu-bar-external', if non-nil, means the menu bar is external (never
5348   included in the inner edges of FRAME).
5349 
5350 `menu-bar-size' is a cons of the width and height of the menu bar of
5351   FRAME.
5352 
5353 `tool-bar-external', if non-nil, means the tool bar is external (never
5354   included in the inner edges of FRAME).
5355 
5356 `tool-bar-position' tells on which side the tool bar on FRAME is and can
5357   be one of `left', `top', `right' or `bottom'.  If this is nil, FRAME
5358   has no tool bar.
5359 
5360 `tool-bar-size' is a cons of the width and height of the tool bar of
5361   FRAME.
5362 
5363 `internal-border-width' is the width of the internal border of
5364   FRAME.
5365 
5366 `outer-border-width' is the width of the X border of FRAME.  The X
5367   border is usually shown only for frames without window manager
5368   decorations, such as child and tooltip frames.  */)
5369   (Lisp_Object frame)
5370 {
5371   return frame_geometry (frame, Qnil);
5372 }
5373 
5374 DEFUN ("x-frame-edges", Fx_frame_edges, Sx_frame_edges, 0, 2, 0,
5375        doc: /* Return edge coordinates of FRAME.
5376 FRAME must be a live frame and defaults to the selected one.  The return
5377 value is a list of the form (LEFT, TOP, RIGHT, BOTTOM).  All values are
5378 in pixels relative to the origin - the position (0, 0) - of FRAME's
5379 display.
5380 
5381 If optional argument TYPE is the symbol `outer-edges', return the outer
5382 edges of FRAME.  The outer edges comprise the decorations of the window
5383 manager (like the title bar or external borders) as well as any external
5384 menu or tool bar of FRAME.  If optional argument TYPE is the symbol
5385 `native-edges' or nil, return the native edges of FRAME.  The native
5386 edges exclude the decorations of the window manager and any external
5387 menu or tool bar of FRAME.  If TYPE is the symbol `inner-edges', return
5388 the inner edges of FRAME.  These edges exclude title bar, any borders,
5389 menu bar or tool bar of FRAME.  */)
5390   (Lisp_Object frame, Lisp_Object type)
5391 {
5392   return frame_geometry (frame, ((EQ (type, Qouter_edges)
5393 				  || EQ (type, Qinner_edges))
5394 				 ? type
5395 				 : Qnative_edges));
5396 }
5397 
5398 /**
5399  * x_frame_list_z_order:
5400  *
5401  * Recursively add list of all frames on the display specified via
5402  * DPYINFO and whose window-system window's parent is specified by
5403  * WINDOW to FRAMES and return FRAMES.
5404  */
5405 static Lisp_Object
x_frame_list_z_order(Display * dpy,Window window)5406 x_frame_list_z_order (Display* dpy, Window window)
5407 {
5408   Window root, parent, *children;
5409   unsigned int nchildren;
5410   int i;
5411   Lisp_Object frames = Qnil;
5412 
5413   block_input ();
5414   if (XQueryTree (dpy, window, &root, &parent, &children, &nchildren))
5415     {
5416       unblock_input ();
5417       for (i = 0; i < nchildren; i++)
5418 	{
5419 	  Lisp_Object frame, tail;
5420 
5421 	  FOR_EACH_FRAME (tail, frame)
5422             {
5423               struct frame *cf = XFRAME (frame);
5424               /* With a reparenting window manager the parent_desc
5425                  field usually specifies the topmost windows of our
5426                  frames.  Otherwise FRAME_OUTER_WINDOW should do.  */
5427               if (FRAME_X_P (cf)
5428                   && (cf->output_data.x->parent_desc == children[i]
5429                       || FRAME_OUTER_WINDOW (cf) == children[i]))
5430                 frames = Fcons (frame, frames);
5431             }
5432 	}
5433 
5434       if (children) XFree ((char *)children);
5435     }
5436   else
5437     unblock_input ();
5438 
5439   return frames;
5440 }
5441 
5442 
5443 DEFUN ("x-frame-list-z-order", Fx_frame_list_z_order,
5444        Sx_frame_list_z_order, 0, 1, 0,
5445        doc: /* Return list of Emacs' frames, in Z (stacking) order.
5446 The optional argument TERMINAL specifies which display to ask about.
5447 TERMINAL should be either a frame or a display name (a string).  If
5448 omitted or nil, that stands for the selected frame's display.  Return
5449 nil if TERMINAL contains no Emacs frame.
5450 
5451 As a special case, if TERMINAL is non-nil and specifies a live frame,
5452 return the child frames of that frame in Z (stacking) order.
5453 
5454 Frames are listed from topmost (first) to bottommost (last).  */)
5455   (Lisp_Object terminal)
5456 {
5457   struct x_display_info *dpyinfo = check_x_display_info (terminal);
5458   Display *dpy = dpyinfo->display;
5459   Window window;
5460 
5461   if (FRAMEP (terminal) && FRAME_LIVE_P (XFRAME (terminal)))
5462     window = FRAME_X_WINDOW (XFRAME (terminal));
5463   else
5464     window = dpyinfo->root_window;
5465 
5466   return x_frame_list_z_order (dpy, window);
5467 }
5468 
5469 /**
5470  * x_frame_restack:
5471  *
5472  * Restack frame F1 below frame F2, above if ABOVE_FLAG is non-nil.  In
5473  * practice this is a two-step action: The first step removes F1's
5474  * window-system window from the display.  The second step reinserts
5475  * F1's window below (above if ABOVE_FLAG is true) that of F2.
5476  */
5477 static void
x_frame_restack(struct frame * f1,struct frame * f2,bool above_flag)5478 x_frame_restack (struct frame *f1, struct frame *f2, bool above_flag)
5479 {
5480 #ifdef USE_GTK
5481   block_input ();
5482   xg_frame_restack (f1, f2, above_flag);
5483   unblock_input ();
5484 #else
5485   Display *dpy = FRAME_X_DISPLAY (f1);
5486   Window window1 = FRAME_OUTER_WINDOW (f1);
5487   XWindowChanges wc;
5488   unsigned long mask = (CWSibling | CWStackMode);
5489 
5490   wc.sibling = FRAME_OUTER_WINDOW (f2);
5491   wc.stack_mode = above_flag ? Above : Below;
5492   block_input ();
5493   /* Configure the window manager window (a normal XConfigureWindow
5494      won't cut it).  This should also work for child frames.  */
5495   XReconfigureWMWindow (dpy, window1, FRAME_X_SCREEN_NUMBER (f1), mask, &wc);
5496   unblock_input ();
5497 #endif /* USE_GTK */
5498 }
5499 
5500 
5501 DEFUN ("x-frame-restack", Fx_frame_restack, Sx_frame_restack, 2, 3, 0,
5502        doc: /* Restack FRAME1 below FRAME2.
5503 This means that if both frames are visible and the display areas of
5504 these frames overlap, FRAME2 (partially) obscures FRAME1.  If optional
5505 third argument ABOVE is non-nil, restack FRAME1 above FRAME2.  This
5506 means that if both frames are visible and the display areas of these
5507 frames overlap, FRAME1 (partially) obscures FRAME2.
5508 
5509 This may be thought of as an atomic action performed in two steps: The
5510 first step removes FRAME1's window-step window from the display.  The
5511 second step reinserts FRAME1's window below (above if ABOVE is true)
5512 that of FRAME2.  Hence the position of FRAME2 in its display's Z
5513 \(stacking) order relative to all other frames excluding FRAME1 remains
5514 unaltered.
5515 
5516 Some window managers may refuse to restack windows.  */)
5517      (Lisp_Object frame1, Lisp_Object frame2, Lisp_Object above)
5518 {
5519   struct frame *f1 = decode_live_frame (frame1);
5520   struct frame *f2 = decode_live_frame (frame2);
5521 
5522   if (! (FRAME_OUTER_WINDOW (f1) && FRAME_OUTER_WINDOW (f2)))
5523     error ("Cannot restack frames");
5524   x_frame_restack (f1, f2, !NILP (above));
5525   return Qt;
5526 }
5527 
5528 
5529 DEFUN ("x-mouse-absolute-pixel-position", Fx_mouse_absolute_pixel_position,
5530        Sx_mouse_absolute_pixel_position, 0, 0, 0,
5531        doc: /* Return absolute position of mouse cursor in pixels.
5532 The position is returned as a cons cell (X . Y) of the coordinates of
5533 the mouse cursor position in pixels relative to a position (0, 0) of the
5534 selected frame's display.  */)
5535   (void)
5536 {
5537   struct frame *f = SELECTED_FRAME ();
5538   Window root, dummy_window;
5539   int x, y, dummy;
5540 
5541   if (FRAME_INITIAL_P (f) || !FRAME_X_P (f))
5542     return Qnil;
5543 
5544   block_input ();
5545   XQueryPointer (FRAME_X_DISPLAY (f),
5546                  DefaultRootWindow (FRAME_X_DISPLAY (f)),
5547                  &root, &dummy_window, &x, &y, &dummy, &dummy,
5548                  (unsigned int *) &dummy);
5549   unblock_input ();
5550 
5551   return Fcons (make_fixnum (x), make_fixnum (y));
5552 }
5553 
5554 DEFUN ("x-set-mouse-absolute-pixel-position", Fx_set_mouse_absolute_pixel_position,
5555        Sx_set_mouse_absolute_pixel_position, 2, 2, 0,
5556        doc: /* Move mouse pointer to absolute pixel position (X, Y).
5557 The coordinates X and Y are interpreted in pixels relative to a position
5558 \(0, 0) of the selected frame's display.  */)
5559   (Lisp_Object x, Lisp_Object y)
5560   {
5561   struct frame *f = SELECTED_FRAME ();
5562 
5563   if (FRAME_INITIAL_P (f) || !FRAME_X_P (f))
5564     return Qnil;
5565 
5566   CHECK_TYPE_RANGED_INTEGER (int, x);
5567   CHECK_TYPE_RANGED_INTEGER (int, y);
5568 
5569   block_input ();
5570   XWarpPointer (FRAME_X_DISPLAY (f), None, DefaultRootWindow (FRAME_X_DISPLAY (f)),
5571 		0, 0, 0, 0, XFIXNUM (x), XFIXNUM (y));
5572   unblock_input ();
5573 
5574   return Qnil;
5575 }
5576 
5577 /************************************************************************
5578 			      X Displays
5579  ************************************************************************/
5580 
5581 
5582 /* Mapping visual names to visuals.  */
5583 
5584 static struct visual_class
5585 {
5586   const char *name;
5587   int class;
5588 }
5589 visual_classes[] =
5590 {
5591   {"StaticGray",	StaticGray},
5592   {"GrayScale",		GrayScale},
5593   {"StaticColor",	StaticColor},
5594   {"PseudoColor",	PseudoColor},
5595   {"TrueColor",		TrueColor},
5596   {"DirectColor",	DirectColor},
5597   {NULL, 0}
5598 };
5599 
5600 
5601 #ifndef HAVE_XSCREENNUMBEROFSCREEN
5602 
5603 /* Value is the screen number of screen SCR.  This is a substitute for
5604    the X function with the same name when that doesn't exist.  */
5605 
5606 int
XScreenNumberOfScreen(scr)5607 XScreenNumberOfScreen (scr)
5608     register Screen *scr;
5609 {
5610   Display *dpy = scr->display;
5611   int i;
5612 
5613   for (i = 0; i < dpy->nscreens; ++i)
5614     if (scr == dpy->screens + i)
5615       break;
5616 
5617   return i;
5618 }
5619 
5620 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
5621 
5622 
5623 /* Select the visual that should be used on display DPYINFO.  Set
5624    members of DPYINFO appropriately.  Called from x_term_init.  */
5625 
5626 void
select_visual(struct x_display_info * dpyinfo)5627 select_visual (struct x_display_info *dpyinfo)
5628 {
5629   Display *dpy = dpyinfo->display;
5630   Screen *screen = dpyinfo->screen;
5631 
5632   /* See if a visual is specified.  */
5633   AUTO_STRING (visualClass, "visualClass");
5634   AUTO_STRING (VisualClass, "VisualClass");
5635   Lisp_Object value = gui_display_get_resource (dpyinfo, visualClass,
5636                                                 VisualClass, Qnil, Qnil);
5637 
5638   if (STRINGP (value))
5639     {
5640       /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
5641 	 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
5642 	 depth, a decimal number.  NAME is compared with case ignored.  */
5643       char *s = alloca (SBYTES (value) + 1);
5644       char *dash;
5645       int i, class = -1;
5646       XVisualInfo vinfo;
5647 
5648       lispstpcpy (s, value);
5649       dash = strchr (s, '-');
5650       if (dash)
5651 	{
5652 	  dpyinfo->n_planes = atoi (dash + 1);
5653 	  *dash = '\0';
5654 	}
5655       else
5656 	/* We won't find a matching visual with depth 0, so that
5657 	   an error will be printed below.  */
5658 	dpyinfo->n_planes = 0;
5659 
5660       /* Determine the visual class.  */
5661       for (i = 0; visual_classes[i].name; ++i)
5662 	if (xstrcasecmp (s, visual_classes[i].name) == 0)
5663 	  {
5664 	    class = visual_classes[i].class;
5665 	    break;
5666 	  }
5667 
5668       /* Look up a matching visual for the specified class.  */
5669       if (class == -1
5670 	  || !XMatchVisualInfo (dpy, XScreenNumberOfScreen (screen),
5671 				dpyinfo->n_planes, class, &vinfo))
5672 	fatal ("Invalid visual specification '%s'",
5673 	       SSDATA (ENCODE_SYSTEM (value)));
5674 
5675       dpyinfo->visual = vinfo.visual;
5676     }
5677   else
5678     {
5679       int n_visuals;
5680       XVisualInfo *vinfo, vinfo_template;
5681 
5682       dpyinfo->visual = DefaultVisualOfScreen (screen);
5683 
5684       vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
5685       vinfo_template.screen = XScreenNumberOfScreen (screen);
5686       vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
5687 			      &vinfo_template, &n_visuals);
5688       if (n_visuals <= 0)
5689 	fatal ("Can't get proper X visual info");
5690 
5691       dpyinfo->n_planes = vinfo->depth;
5692       XFree (vinfo);
5693     }
5694 }
5695 
5696 
5697 /* Return the X display structure for the display named NAME.
5698    Open a new connection if necessary.  */
5699 
5700 static struct x_display_info *
x_display_info_for_name(Lisp_Object name)5701 x_display_info_for_name (Lisp_Object name)
5702 {
5703   struct x_display_info *dpyinfo;
5704 
5705   CHECK_STRING (name);
5706 
5707   for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
5708     if (!NILP (Fstring_equal (XCAR (dpyinfo->name_list_element), name)))
5709       return dpyinfo;
5710 
5711   /* Use this general default value to start with.  */
5712   Vx_resource_name = Vinvocation_name;
5713 
5714   validate_x_resource_name ();
5715 
5716   dpyinfo = x_term_init (name, 0, SSDATA (Vx_resource_name));
5717 
5718   if (dpyinfo == 0)
5719     error ("Cannot connect to X server %s", SDATA (name));
5720 
5721   XSETFASTINT (Vwindow_system_version, 11);
5722 
5723   return dpyinfo;
5724 }
5725 
5726 
5727 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
5728        1, 3, 0,
5729        doc: /* Open a connection to a display server.
5730 DISPLAY is the name of the display to connect to.
5731 Optional second arg XRM-STRING is a string of resources in xrdb format.
5732 If the optional third arg MUST-SUCCEED is non-nil,
5733 terminate Emacs if we can't open the connection.
5734 \(In the Nextstep version, the last two arguments are currently ignored.)  */)
5735   (Lisp_Object display, Lisp_Object xrm_string, Lisp_Object must_succeed)
5736 {
5737   char *xrm_option;
5738   struct x_display_info *dpyinfo;
5739 
5740   CHECK_STRING (display);
5741   if (! NILP (xrm_string))
5742     CHECK_STRING (xrm_string);
5743 
5744   xrm_option = NILP (xrm_string) ? 0 : SSDATA (xrm_string);
5745 
5746   validate_x_resource_name ();
5747 
5748   /* This is what opens the connection and sets x_current_display.
5749      This also initializes many symbols, such as those used for input.  */
5750   dpyinfo = x_term_init (display, xrm_option,
5751 			 SSDATA (Vx_resource_name));
5752 
5753   if (dpyinfo == 0)
5754     {
5755       if (!NILP (must_succeed))
5756 	fatal ("Cannot connect to X server %s.\n\
5757 Check the DISPLAY environment variable or use `-d'.\n\
5758 Also use the `xauth' program to verify that you have the proper\n\
5759 authorization information needed to connect the X server.\n\
5760 An insecure way to solve the problem may be to use `xhost'.\n",
5761 	       SDATA (display));
5762       else
5763 	error ("Cannot connect to X server %s", SDATA (display));
5764     }
5765 
5766   XSETFASTINT (Vwindow_system_version, 11);
5767   return Qnil;
5768 }
5769 
5770 DEFUN ("x-close-connection", Fx_close_connection,
5771        Sx_close_connection, 1, 1, 0,
5772        doc: /* Close the connection to TERMINAL's X server.
5773 For TERMINAL, specify a terminal object, a frame or a display name (a
5774 string).  If TERMINAL is nil, that stands for the selected frame's terminal.
5775 \(On MS Windows, this function does not accept terminal objects.)  */)
5776   (Lisp_Object terminal)
5777 {
5778   struct x_display_info *dpyinfo = check_x_display_info (terminal);
5779 
5780   if (dpyinfo->reference_count > 0)
5781     error ("Display still has frames on it");
5782 
5783   x_delete_terminal (dpyinfo->terminal);
5784 
5785   return Qnil;
5786 }
5787 
5788 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
5789        doc: /* Return the list of display names that Emacs has connections to.  */)
5790   (void)
5791 {
5792   Lisp_Object result = Qnil;
5793   struct x_display_info *xdi;
5794 
5795   for (xdi = x_display_list; xdi; xdi = xdi->next)
5796     result = Fcons (XCAR (xdi->name_list_element), result);
5797 
5798   return result;
5799 }
5800 
5801 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
5802        doc: /* If ON is non-nil, report X errors as soon as the erring request is made.
5803 This function has an effect only on X Windows.  With MS Windows, it is
5804 defined but does nothing.
5805 
5806 If ON is nil, allow buffering of requests.
5807 Turning on synchronization prohibits the Xlib routines from buffering
5808 requests and seriously degrades performance, but makes debugging much
5809 easier.
5810 The optional second argument TERMINAL specifies which display to act on.
5811 TERMINAL should be a terminal object, a frame or a display name (a string).
5812 If TERMINAL is omitted or nil, that stands for the selected frame's display.  */)
5813   (Lisp_Object on, Lisp_Object terminal)
5814 {
5815   struct x_display_info *dpyinfo = check_x_display_info (terminal);
5816 
5817   XSynchronize (dpyinfo->display, !NILP (on));
5818 
5819   return Qnil;
5820 }
5821 
5822 /* Wait for responses to all X commands issued so far for frame F.  */
5823 
5824 void
x_sync(struct frame * f)5825 x_sync (struct frame *f)
5826 {
5827   block_input ();
5828   XSync (FRAME_X_DISPLAY (f), False);
5829   unblock_input ();
5830 }
5831 
5832 
5833 /***********************************************************************
5834                            Window properties
5835  ***********************************************************************/
5836 
5837 DEFUN ("x-change-window-property", Fx_change_window_property,
5838        Sx_change_window_property, 2, 7, 0,
5839        doc: /* Change window property PROP to VALUE on the X window of FRAME.
5840 PROP must be a string.  VALUE may be a string or a list of conses,
5841 numbers and/or strings.  If an element in the list is a string, it is
5842 converted to an atom and the value of the atom is used.  If an element
5843 is a cons, it is converted to a 32 bit number where the car is the 16
5844 top bits and the cdr is the lower 16 bits.
5845 
5846 FRAME nil or omitted means use the selected frame.
5847 If TYPE is given and non-nil, it is the name of the type of VALUE.
5848  If TYPE is not given or nil, the type is STRING.
5849 FORMAT gives the size in bits of each element if VALUE is a list.
5850  It must be one of 8, 16 or 32.
5851  If VALUE is a string or FORMAT is nil or not given, FORMAT defaults to 8.
5852 If OUTER-P is non-nil, the property is changed for the outer X window of
5853  FRAME.  Default is to change on the edit X window.
5854 If WINDOW-ID is non-nil, change the property of that window instead
5855  of FRAME's X window; the number 0 denotes the root window.  This argument
5856  is separate from FRAME because window IDs are not unique across X
5857  displays or screens on the same display, so FRAME provides context
5858  for the window ID. */)
5859   (Lisp_Object prop, Lisp_Object value, Lisp_Object frame,
5860    Lisp_Object type, Lisp_Object format, Lisp_Object outer_p,
5861    Lisp_Object window_id)
5862 {
5863   struct frame *f = decode_window_system_frame (frame);
5864   Atom prop_atom;
5865   Atom target_type = XA_STRING;
5866   int element_format = 8;
5867   unsigned char *data;
5868   int nelements;
5869   Window target_window;
5870 
5871   CHECK_STRING (prop);
5872 
5873   if (! NILP (format))
5874     {
5875       CHECK_FIXNUM (format);
5876 
5877       if (XFIXNUM (format) != 8 && XFIXNUM (format) != 16
5878           && XFIXNUM (format) != 32)
5879         error ("FORMAT must be one of 8, 16 or 32");
5880       element_format = XFIXNUM (format);
5881     }
5882 
5883   if (CONSP (value))
5884     {
5885       ptrdiff_t elsize;
5886 
5887       nelements = x_check_property_data (value);
5888       if (nelements == -1)
5889         error ("Bad data in VALUE, must be number, string or cons");
5890 
5891       /* The man page for XChangeProperty:
5892 	     "If the specified format is 32, the property data must be a
5893 	      long array."
5894 	 This applies even if long is more than 32 bits.  The X library
5895 	 converts to 32 bits before sending to the X server.  */
5896       elsize = element_format == 32 ? sizeof (long) : element_format >> 3;
5897       data = xnmalloc (nelements, elsize);
5898 
5899       x_fill_property_data (FRAME_X_DISPLAY (f), value, data, element_format);
5900     }
5901   else
5902     {
5903       ptrdiff_t elsize;
5904 
5905       CHECK_STRING (value);
5906       data = SDATA (value);
5907       if (INT_MAX < SBYTES (value))
5908 	error ("VALUE too long");
5909 
5910       /* See comment above about longs and format=32 */
5911       elsize = element_format == 32 ? sizeof (long) : element_format >> 3;
5912       if (SBYTES (value) % elsize != 0)
5913         error ("VALUE must contain an integral number of octets for FORMAT");
5914       nelements = SBYTES (value) / elsize;
5915     }
5916 
5917   if (! NILP (window_id))
5918     {
5919       CONS_TO_INTEGER (window_id, Window, target_window);
5920       if (! target_window)
5921         target_window = FRAME_DISPLAY_INFO (f)->root_window;
5922     }
5923   else
5924     {
5925       if (! NILP (outer_p))
5926         target_window = FRAME_OUTER_WINDOW (f);
5927       else
5928         target_window = FRAME_X_WINDOW (f);
5929     }
5930 
5931   block_input ();
5932   prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False);
5933   if (! NILP (type))
5934     {
5935       CHECK_STRING (type);
5936       target_type = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (type), False);
5937     }
5938 
5939   XChangeProperty (FRAME_X_DISPLAY (f), target_window,
5940 		   prop_atom, target_type, element_format, PropModeReplace,
5941 		   data, nelements);
5942 
5943   if (CONSP (value)) xfree (data);
5944 
5945   /* Make sure the property is set when we return.  */
5946   XFlush (FRAME_X_DISPLAY (f));
5947   unblock_input ();
5948 
5949   return value;
5950 }
5951 
5952 
5953 DEFUN ("x-delete-window-property", Fx_delete_window_property,
5954        Sx_delete_window_property, 1, 3, 0,
5955        doc: /* Remove window property PROP from X window of FRAME.
5956 FRAME nil or omitted means use the selected frame.
5957 If WINDOW-ID is non-nil, remove property from that window instead
5958  of FRAME's X window; the number 0 denotes the root window.  This
5959  argument is separate from FRAME because window IDs are not unique
5960  across X displays or screens on the same display, so FRAME provides
5961  context for the window ID.
5962 
5963 Value is PROP.  */)
5964   (Lisp_Object prop, Lisp_Object frame, Lisp_Object window_id)
5965 {
5966   struct frame *f = decode_window_system_frame (frame);
5967   Window target_window = FRAME_X_WINDOW (f);
5968   Atom prop_atom;
5969 
5970   CHECK_STRING (prop);
5971 
5972   if (! NILP (window_id))
5973     {
5974       CONS_TO_INTEGER (window_id, Window, target_window);
5975       if (! target_window)
5976         target_window = FRAME_DISPLAY_INFO (f)->root_window;
5977     }
5978 
5979   block_input ();
5980   prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False);
5981   XDeleteProperty (FRAME_X_DISPLAY (f), target_window, prop_atom);
5982 
5983   /* Make sure the property is removed when we return.  */
5984   XFlush (FRAME_X_DISPLAY (f));
5985   unblock_input ();
5986 
5987   return prop;
5988 }
5989 
5990 
5991 static Lisp_Object
x_window_property_intern(struct frame * f,Window target_window,Atom prop_atom,Atom target_type,Lisp_Object delete_p,Lisp_Object vector_ret_p,bool * found)5992 x_window_property_intern (struct frame *f,
5993                           Window target_window,
5994                           Atom prop_atom,
5995                           Atom target_type,
5996                           Lisp_Object delete_p,
5997                           Lisp_Object vector_ret_p,
5998                           bool *found)
5999 {
6000   unsigned char *tmp_data = NULL;
6001   Lisp_Object prop_value = Qnil;
6002   Atom actual_type;
6003   int actual_format;
6004   unsigned long actual_size, bytes_remaining;
6005   int rc;
6006 
6007   rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
6008 			   prop_atom, 0, 0, False, target_type,
6009 			   &actual_type, &actual_format, &actual_size,
6010 			   &bytes_remaining, &tmp_data);
6011 
6012   *found = actual_format != 0;
6013 
6014   if (rc == Success && *found)
6015     {
6016       XFree (tmp_data);
6017       tmp_data = NULL;
6018 
6019       rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
6020                                prop_atom, 0, bytes_remaining,
6021                                ! NILP (delete_p), target_type,
6022                                &actual_type, &actual_format,
6023                                &actual_size, &bytes_remaining,
6024                                &tmp_data);
6025       if (rc == Success && tmp_data)
6026         {
6027           /* The man page for XGetWindowProperty says:
6028              "If the returned format is 32, the returned data is represented
6029              as a long array and should be cast to that type to obtain the
6030              elements."
6031              This applies even if long is more than 32 bits, the X library
6032              converts from 32 bit elements received from the X server to long
6033              and passes the long array to us.  Thus, for that case memcpy can not
6034              be used.  We convert to a 32 bit type here, because so much code
6035              assume on that.
6036 
6037              The bytes and offsets passed to XGetWindowProperty refers to the
6038              property and those are indeed in 32 bit quantities if format is
6039              32.  */
6040 
6041           if (LONG_WIDTH > 32 && actual_format == 32)
6042             {
6043               unsigned long i;
6044               int  *idata = (int *) tmp_data;
6045               long *ldata = (long *) tmp_data;
6046 
6047               for (i = 0; i < actual_size; ++i)
6048                 idata[i] = (int) ldata[i];
6049             }
6050 
6051           if (NILP (vector_ret_p))
6052             prop_value = make_string ((char *) tmp_data,
6053                                       (actual_format >> 3) * actual_size);
6054           else
6055             prop_value = x_property_data_to_lisp (f,
6056                                                   tmp_data,
6057                                                   actual_type,
6058                                                   actual_format,
6059                                                   actual_size);
6060         }
6061 
6062       if (tmp_data) XFree (tmp_data);
6063     }
6064 
6065   return prop_value;
6066 }
6067 
6068 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
6069        1, 6, 0,
6070        doc: /* Value is the value of window property PROP on FRAME.
6071 If FRAME is nil or omitted, use the selected frame.
6072 
6073 On X Windows, the following optional arguments are also accepted:
6074 If TYPE is nil or omitted, get the property as a string.
6075  Otherwise TYPE is the name of the atom that denotes the expected type.
6076 If WINDOW-ID is non-nil, get the property of that window instead of
6077  FRAME's X window; the number 0 denotes the root window.  This argument
6078  is separate from FRAME because window IDs are not unique across X
6079  displays or screens on the same display, so FRAME provides context
6080  for the window ID.
6081 If DELETE-P is non-nil, delete the property after retrieving it.
6082 If VECTOR-RET-P is non-nil, return a vector of values instead of a string.
6083 
6084 Return value is nil if FRAME doesn't have a property with name PROP or
6085 if PROP has no value of TYPE (always a string in the MS Windows case). */)
6086   (Lisp_Object prop, Lisp_Object frame, Lisp_Object type,
6087    Lisp_Object window_id, Lisp_Object delete_p, Lisp_Object vector_ret_p)
6088 {
6089   struct frame *f = decode_window_system_frame (frame);
6090   Atom prop_atom;
6091   Lisp_Object prop_value = Qnil;
6092   Atom target_type = XA_STRING;
6093   Window target_window = FRAME_X_WINDOW (f);
6094   bool found;
6095 
6096   CHECK_STRING (prop);
6097 
6098   if (! NILP (window_id))
6099     {
6100       CONS_TO_INTEGER (window_id, Window, target_window);
6101       if (! target_window)
6102         target_window = FRAME_DISPLAY_INFO (f)->root_window;
6103     }
6104 
6105   block_input ();
6106   if (STRINGP (type))
6107     {
6108       if (strcmp ("AnyPropertyType", SSDATA (type)) == 0)
6109         target_type = AnyPropertyType;
6110       else
6111         target_type = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (type), False);
6112     }
6113 
6114   prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False);
6115   prop_value = x_window_property_intern (f,
6116                                          target_window,
6117                                          prop_atom,
6118                                          target_type,
6119                                          delete_p,
6120                                          vector_ret_p,
6121                                          &found);
6122   if (NILP (prop_value)
6123       && ! found
6124       && NILP (window_id)
6125       && target_window != FRAME_OUTER_WINDOW (f))
6126     {
6127       prop_value = x_window_property_intern (f,
6128                                              FRAME_OUTER_WINDOW (f),
6129                                              prop_atom,
6130                                              target_type,
6131                                              delete_p,
6132                                              vector_ret_p,
6133                                              &found);
6134     }
6135 
6136 
6137   unblock_input ();
6138   return prop_value;
6139 }
6140 
6141 DEFUN ("x-window-property-attributes", Fx_window_property_attributes, Sx_window_property_attributes,
6142        1, 3, 0,
6143        doc: /* Retrieve metadata about window property PROP on FRAME.
6144 If FRAME is nil or omitted, use the selected frame.
6145 If WINDOW-ID is non-nil, get the property of that window instead of
6146  FRAME's X window; the number 0 denotes the root window.  This
6147  argument is separate from FRAME because window IDs are not unique
6148  across X displays or screens on the same display, so FRAME provides
6149  context for the window ID.
6150 
6151 Return value is nil if FRAME doesn't have a property named PROP.
6152 Otherwise, the return value is a vector with the following fields:
6153 
6154 0. The property type, as an integer.  The symbolic name of
6155  the type can be obtained with `x-get-atom-name'.
6156 1. The format of each element; one of 8, 16, or 32.
6157 2. The length of the property, in number of elements. */)
6158   (Lisp_Object prop, Lisp_Object frame, Lisp_Object window_id)
6159 {
6160   struct frame *f = decode_window_system_frame (frame);
6161   Window target_window = FRAME_X_WINDOW (f);
6162   Atom prop_atom;
6163   Lisp_Object prop_attr = Qnil;
6164   Atom actual_type;
6165   int actual_format;
6166   unsigned long actual_size, bytes_remaining;
6167   unsigned char *tmp_data = NULL;
6168   int rc;
6169 
6170   CHECK_STRING (prop);
6171 
6172   if (! NILP (window_id))
6173     {
6174       CONS_TO_INTEGER (window_id, Window, target_window);
6175       if (! target_window)
6176 	target_window = FRAME_DISPLAY_INFO (f)->root_window;
6177     }
6178 
6179   block_input ();
6180 
6181   prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False);
6182   rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
6183 			   prop_atom, 0, 0, False, AnyPropertyType,
6184 			   &actual_type, &actual_format, &actual_size,
6185 			   &bytes_remaining, &tmp_data);
6186   if (rc == Success          /* no invalid params */
6187       && actual_format == 0  /* but prop not found */
6188       && NILP (window_id)
6189       && target_window != FRAME_OUTER_WINDOW (f))
6190     {
6191       /* analogous behavior to x-window-property: if property isn't found
6192          on the frame's inner window and no alternate window id was
6193          provided, try the frame's outer window. */
6194       target_window = FRAME_OUTER_WINDOW (f);
6195       rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
6196                                prop_atom, 0, 0, False, AnyPropertyType,
6197                                &actual_type, &actual_format, &actual_size,
6198                                &bytes_remaining, &tmp_data);
6199     }
6200 
6201   if (rc == Success && actual_format != 0)
6202     {
6203       XFree (tmp_data);
6204 
6205       prop_attr = make_uninit_vector (3);
6206       ASET (prop_attr, 0, make_fixnum (actual_type));
6207       ASET (prop_attr, 1, make_fixnum (actual_format));
6208       ASET (prop_attr, 2, make_fixnum (bytes_remaining / (actual_format >> 3)));
6209     }
6210 
6211   unblock_input ();
6212   return prop_attr;
6213 }
6214 
6215 /***********************************************************************
6216 				Tool tips
6217  ***********************************************************************/
6218 
6219 static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
6220 			    Lisp_Object, int, int, int *, int *);
6221 
6222 /* The frame of the currently visible tooltip.  */
6223 static Lisp_Object tip_frame;
6224 
6225 /* The window-system window corresponding to the frame of the
6226    currently visible tooltip.  */
6227 Window tip_window;
6228 
6229 /* A timer that hides or deletes the currently visible tooltip when it
6230    fires.  */
6231 static Lisp_Object tip_timer;
6232 
6233 /* STRING argument of last `x-show-tip' call.  */
6234 static Lisp_Object tip_last_string;
6235 
6236 /* Normalized FRAME argument of last `x-show-tip' call.  */
6237 static Lisp_Object tip_last_frame;
6238 
6239 /* PARMS argument of last `x-show-tip' call.  */
6240 static Lisp_Object tip_last_parms;
6241 
6242 
6243 static void
unwind_create_tip_frame(Lisp_Object frame)6244 unwind_create_tip_frame (Lisp_Object frame)
6245 {
6246   Lisp_Object deleted;
6247 
6248   deleted = unwind_create_frame (frame);
6249   if (EQ (deleted, Qt))
6250     {
6251       tip_window = None;
6252       tip_frame = Qnil;
6253     }
6254 }
6255 
6256 
6257 /* Create a frame for a tooltip on the display described by DPYINFO.
6258    PARMS is a list of frame parameters.  TEXT is the string to
6259    display in the tip frame.  Value is the frame.
6260 
6261    Note that functions called here, esp. gui_default_parameter can
6262    signal errors, for instance when a specified color name is
6263    undefined.  We have to make sure that we're in a consistent state
6264    when this happens.  */
6265 
6266 static Lisp_Object
x_create_tip_frame(struct x_display_info * dpyinfo,Lisp_Object parms)6267 x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms)
6268 {
6269   struct frame *f;
6270   Lisp_Object frame;
6271   Lisp_Object name;
6272   int width, height;
6273   ptrdiff_t count = SPECPDL_INDEX ();
6274   bool face_change_before = face_change;
6275   int x_width = 0, x_height = 0;
6276 
6277   if (!dpyinfo->terminal->name)
6278     error ("Terminal is not live, can't create new frames on it");
6279 
6280   parms = Fcopy_alist (parms);
6281 
6282   /* Get the name of the frame to use for resource lookup.  */
6283   name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name",
6284                               RES_TYPE_STRING);
6285   if (!STRINGP (name)
6286       && !EQ (name, Qunbound)
6287       && !NILP (name))
6288     error ("Invalid frame name--not a string or nil");
6289 
6290   frame = Qnil;
6291   f = make_frame (false);
6292   f->wants_modeline = false;
6293   XSETFRAME (frame, f);
6294   record_unwind_protect (unwind_create_tip_frame, frame);
6295 
6296   f->terminal = dpyinfo->terminal;
6297 
6298   /* By setting the output method, we're essentially saying that
6299      the frame is live, as per FRAME_LIVE_P.  If we get a signal
6300      from this point on, x_destroy_window might screw up reference
6301      counts etc.  */
6302   f->output_method = output_x_window;
6303   f->output_data.x = xzalloc (sizeof *f->output_data.x);
6304   f->output_data.x->icon_bitmap = -1;
6305   FRAME_FONTSET (f) = -1;
6306   f->output_data.x->scroll_bar_foreground_pixel = -1;
6307   f->output_data.x->scroll_bar_background_pixel = -1;
6308 #if defined (USE_LUCID) && defined (USE_TOOLKIT_SCROLL_BARS)
6309   f->output_data.x->scroll_bar_top_shadow_pixel = -1;
6310   f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
6311 #endif /* USE_LUCID && USE_TOOLKIT_SCROLL_BARS */
6312   f->output_data.x->white_relief.pixel = -1;
6313   f->output_data.x->black_relief.pixel = -1;
6314 
6315   f->tooltip = true;
6316   fset_icon_name (f, Qnil);
6317   FRAME_DISPLAY_INFO (f) = dpyinfo;
6318   f->output_data.x->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
6319   f->output_data.x->explicit_parent = false;
6320 
6321   /* These colors will be set anyway later, but it's important
6322      to get the color reference counts right, so initialize them!  */
6323   {
6324     Lisp_Object black;
6325 
6326     /* Function x_decode_color can signal an error.  Make
6327        sure to initialize color slots so that we won't try
6328        to free colors we haven't allocated.  */
6329     FRAME_FOREGROUND_PIXEL (f) = -1;
6330     FRAME_BACKGROUND_PIXEL (f) = -1;
6331     f->output_data.x->cursor_pixel = -1;
6332     f->output_data.x->cursor_foreground_pixel = -1;
6333     f->output_data.x->border_pixel = -1;
6334     f->output_data.x->mouse_pixel = -1;
6335 
6336     black = build_string ("black");
6337     FRAME_FOREGROUND_PIXEL (f)
6338       = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
6339     FRAME_BACKGROUND_PIXEL (f)
6340       = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
6341     f->output_data.x->cursor_pixel
6342       = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
6343     f->output_data.x->cursor_foreground_pixel
6344       = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
6345     f->output_data.x->border_pixel
6346       = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
6347     f->output_data.x->mouse_pixel
6348       = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
6349   }
6350 
6351   /* Set the name; the functions to which we pass f expect the name to
6352      be set.  */
6353   if (EQ (name, Qunbound) || NILP (name))
6354     {
6355       fset_name (f, build_string (dpyinfo->x_id_name));
6356       f->explicit_name = false;
6357     }
6358   else
6359     {
6360       fset_name (f, name);
6361       f->explicit_name = true;
6362       /* use the frame's title when getting resources for this frame.  */
6363       specbind (Qx_resource_name, name);
6364     }
6365 
6366 #ifdef USE_CAIRO
6367   register_font_driver (&ftcrfont_driver, f);
6368 #ifdef HAVE_HARFBUZZ
6369   register_font_driver (&ftcrhbfont_driver, f);
6370 #endif	/* HAVE_HARFBUZZ */
6371 #else
6372 #ifdef HAVE_FREETYPE
6373 #ifdef HAVE_XFT
6374   register_font_driver (&xftfont_driver, f);
6375 #ifdef HAVE_HARFBUZZ
6376   register_font_driver (&xfthbfont_driver, f);
6377 #endif
6378 #else	/* not HAVE_XFT */
6379   register_font_driver (&ftxfont_driver, f);
6380 #endif	/* not HAVE_XFT */
6381 #endif	/* HAVE_FREETYPE */
6382 #endif	/* not USE_CAIRO */
6383   register_font_driver (&xfont_driver, f);
6384 
6385   image_cache_refcount =
6386     FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
6387 #ifdef GLYPH_DEBUG
6388   dpyinfo_refcount = dpyinfo->reference_count;
6389 #endif /* GLYPH_DEBUG */
6390 
6391   gui_default_parameter (f, parms, Qfont_backend, Qnil,
6392                          "fontBackend", "FontBackend", RES_TYPE_STRING);
6393 
6394   /* Extract the window parameters from the supplied values that are
6395      needed to determine window geometry.  */
6396   x_default_font_parameter (f, parms);
6397 
6398   gui_default_parameter (f, parms, Qborder_width, make_fixnum (0),
6399                          "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
6400 
6401   /* This defaults to 2 in order to match xterm.  We recognize either
6402      internalBorderWidth or internalBorder (which is what xterm calls
6403      it).  */
6404   if (NILP (Fassq (Qinternal_border_width, parms)))
6405     {
6406       Lisp_Object value;
6407 
6408       value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width,
6409                                    "internalBorder", "internalBorder",
6410                                    RES_TYPE_NUMBER);
6411       if (! EQ (value, Qunbound))
6412 	parms = Fcons (Fcons (Qinternal_border_width, value),
6413 		       parms);
6414     }
6415 
6416   gui_default_parameter (f, parms, Qinternal_border_width, make_fixnum (1),
6417                          "internalBorderWidth", "internalBorderWidth",
6418                          RES_TYPE_NUMBER);
6419   gui_default_parameter (f, parms, Qright_divider_width, make_fixnum (0),
6420                          NULL, NULL, RES_TYPE_NUMBER);
6421   gui_default_parameter (f, parms, Qbottom_divider_width, make_fixnum (0),
6422                          NULL, NULL, RES_TYPE_NUMBER);
6423 
6424   /* Also do the stuff which must be set before the window exists.  */
6425   gui_default_parameter (f, parms, Qforeground_color, build_string ("black"),
6426                          "foreground", "Foreground", RES_TYPE_STRING);
6427   gui_default_parameter (f, parms, Qbackground_color, build_string ("white"),
6428                          "background", "Background", RES_TYPE_STRING);
6429   gui_default_parameter (f, parms, Qmouse_color, build_string ("black"),
6430                          "pointerColor", "Foreground", RES_TYPE_STRING);
6431   gui_default_parameter (f, parms, Qcursor_color, build_string ("black"),
6432                          "cursorColor", "Foreground", RES_TYPE_STRING);
6433   gui_default_parameter (f, parms, Qborder_color, build_string ("black"),
6434                          "borderColor", "BorderColor", RES_TYPE_STRING);
6435   gui_default_parameter (f, parms, Qno_special_glyphs, Qnil,
6436                          NULL, NULL, RES_TYPE_BOOLEAN);
6437 
6438   /* Init faces before gui_default_parameter is called for the
6439      scroll-bar-width parameter because otherwise we end up in
6440      init_iterator with a null face cache, which should not happen.  */
6441   init_frame_faces (f);
6442 
6443   f->output_data.x->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
6444 
6445   gui_default_parameter (f, parms, Qinhibit_double_buffering, Qnil,
6446                          "inhibitDoubleBuffering", "InhibitDoubleBuffering",
6447                          RES_TYPE_BOOLEAN);
6448 
6449   gui_figure_window_size (f, parms, false, false, &x_width, &x_height);
6450 
6451   {
6452     XSetWindowAttributes attrs;
6453     unsigned long mask;
6454     Atom type = FRAME_DISPLAY_INFO (f)->Xatom_net_window_type_tooltip;
6455 
6456     block_input ();
6457     mask = CWBackPixel | CWOverrideRedirect | CWEventMask | CWCursor;
6458     if (DoesSaveUnders (dpyinfo->screen))
6459       mask |= CWSaveUnder;
6460 
6461     /* Window managers look at the override-redirect flag to determine
6462        whether or net to give windows a decoration (Xlib spec, chapter
6463        3.2.8).  */
6464     attrs.override_redirect = True;
6465     attrs.save_under = True;
6466     attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
6467     attrs.cursor =
6468       f->output_data.x->current_cursor
6469       = f->output_data.x->text_cursor;
6470     /* Arrange for getting MapNotify and UnmapNotify events.  */
6471     attrs.event_mask = StructureNotifyMask;
6472     tip_window
6473       = FRAME_X_WINDOW (f)
6474       = XCreateWindow (FRAME_X_DISPLAY (f),
6475 		       FRAME_DISPLAY_INFO (f)->root_window,
6476 		       /* x, y, width, height */
6477 		       0, 0, 1, 1,
6478 		       /* Border.  */
6479 		       f->border_width,
6480 		       CopyFromParent, InputOutput, CopyFromParent,
6481                        mask, &attrs);
6482     initial_set_up_x_back_buffer (f);
6483     XChangeProperty (FRAME_X_DISPLAY (f), tip_window,
6484                      FRAME_DISPLAY_INFO (f)->Xatom_net_window_type,
6485                      XA_ATOM, 32, PropModeReplace,
6486                      (unsigned char *)&type, 1);
6487     unblock_input ();
6488   }
6489 
6490   x_make_gc (f);
6491 
6492   gui_default_parameter (f, parms, Qauto_raise, Qnil,
6493                          "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
6494   gui_default_parameter (f, parms, Qauto_lower, Qnil,
6495                          "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
6496   gui_default_parameter (f, parms, Qcursor_type, Qbox,
6497                          "cursorType", "CursorType", RES_TYPE_SYMBOL);
6498   gui_default_parameter (f, parms, Qalpha, Qnil,
6499                          "alpha", "Alpha", RES_TYPE_NUMBER);
6500 
6501   /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
6502      Change will not be effected unless different from the current
6503      FRAME_LINES (f).  */
6504   width = FRAME_COLS (f);
6505   height = FRAME_LINES (f);
6506   SET_FRAME_COLS (f, 0);
6507   SET_FRAME_LINES (f, 0);
6508   change_frame_size (f, width, height, true, false, false, false);
6509 
6510   /* Add `tooltip' frame parameter's default value. */
6511   if (NILP (Fframe_parameter (frame, Qtooltip)))
6512     {
6513       AUTO_FRAME_ARG (arg, Qtooltip, Qt);
6514       Fmodify_frame_parameters (frame, arg);
6515     }
6516 
6517   /* FIXME - can this be done in a similar way to normal frames?
6518      https://lists.gnu.org/r/emacs-devel/2007-10/msg00641.html */
6519 
6520   /* Set the `display-type' frame parameter before setting up faces. */
6521   {
6522     Lisp_Object disptype;
6523 
6524     if (FRAME_DISPLAY_INFO (f)->n_planes == 1)
6525       disptype = Qmono;
6526     else if (FRAME_DISPLAY_INFO (f)->visual->class == GrayScale
6527              || FRAME_DISPLAY_INFO (f)->visual->class == StaticGray)
6528       disptype = intern ("grayscale");
6529     else
6530       disptype = intern ("color");
6531 
6532     if (NILP (Fframe_parameter (frame, Qdisplay_type)))
6533       {
6534 	AUTO_FRAME_ARG (arg, Qdisplay_type, disptype);
6535 	Fmodify_frame_parameters (frame, arg);
6536       }
6537   }
6538 
6539   /* Set up faces after all frame parameters are known.  This call
6540      also merges in face attributes specified for new frames.
6541 
6542      Frame parameters may be changed if .Xdefaults contains
6543      specifications for the default font.  For example, if there is an
6544      `Emacs.default.attributeBackground: pink', the `background-color'
6545      attribute of the frame get's set, which let's the internal border
6546      of the tooltip frame appear in pink.  Prevent this.  */
6547   {
6548     Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
6549 
6550     call2 (Qface_set_after_frame_default, frame, Qnil);
6551 
6552     if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
6553       {
6554 	AUTO_FRAME_ARG (arg, Qbackground_color, bg);
6555 	Fmodify_frame_parameters (frame, arg);
6556       }
6557   }
6558 
6559   f->no_split = true;
6560 
6561   /* Now that the frame will be official, it counts as a reference to
6562      its display and terminal.  */
6563   FRAME_DISPLAY_INFO (f)->reference_count++;
6564   f->terminal->reference_count++;
6565 
6566   /* It is now ok to make the frame official even if we get an error
6567      below.  And the frame needs to be on Vframe_list or making it
6568      visible won't work.  */
6569   Vframe_list = Fcons (frame, Vframe_list);
6570   f->can_set_window_size = true;
6571 
6572   /* Setting attributes of faces of the tooltip frame from resources
6573      and similar will set face_change, which leads to the clearing of
6574      all current matrices.  Since this isn't necessary here, avoid it
6575      by resetting face_change to the value it had before we created
6576      the tip frame.  */
6577   face_change = face_change_before;
6578 
6579   /* Discard the unwind_protect.  */
6580   return unbind_to (count, frame);
6581 }
6582 
6583 
6584 /* Compute where to display tip frame F.  PARMS is the list of frame
6585    parameters for F.  DX and DY are specified offsets from the current
6586    location of the mouse.  WIDTH and HEIGHT are the width and height
6587    of the tooltip.  Return coordinates relative to the root window of
6588    the display in *ROOT_X, and *ROOT_Y.  */
6589 
6590 static void
compute_tip_xy(struct frame * f,Lisp_Object parms,Lisp_Object dx,Lisp_Object dy,int width,int height,int * root_x,int * root_y)6591 compute_tip_xy (struct frame *f,
6592 		Lisp_Object parms, Lisp_Object dx, Lisp_Object dy,
6593 		int width, int height, int *root_x, int *root_y)
6594 {
6595   Lisp_Object left, top, right, bottom;
6596   int win_x, win_y;
6597   Window root, child;
6598   unsigned pmask;
6599   int min_x, min_y, max_x, max_y = -1;
6600 
6601   /* User-specified position?  */
6602   left = Fcdr (Fassq (Qleft, parms));
6603   top  = Fcdr (Fassq (Qtop, parms));
6604   right = Fcdr (Fassq (Qright, parms));
6605   bottom = Fcdr (Fassq (Qbottom, parms));
6606 
6607   /* Move the tooltip window where the mouse pointer is.  Resize and
6608      show it.  */
6609   if ((!FIXNUMP (left) && !FIXNUMP (right))
6610       || (!FIXNUMP (top) && !FIXNUMP (bottom)))
6611     {
6612       Lisp_Object frame, attributes, monitor, geometry;
6613 
6614       block_input ();
6615       XQueryPointer (FRAME_X_DISPLAY (f), FRAME_DISPLAY_INFO (f)->root_window,
6616 		     &root, &child, root_x, root_y, &win_x, &win_y, &pmask);
6617       unblock_input ();
6618 
6619       XSETFRAME(frame, f);
6620       attributes = Fx_display_monitor_attributes_list (frame);
6621 
6622       /* Try to determine the monitor where the mouse pointer is and
6623          its geometry.  See bug#22549.  */
6624       while (CONSP (attributes))
6625 	{
6626           monitor = XCAR (attributes);
6627           geometry = Fassq (Qgeometry, monitor);
6628           if (CONSP (geometry))
6629             {
6630               min_x = XFIXNUM (Fnth (make_fixnum (1), geometry));
6631               min_y = XFIXNUM (Fnth (make_fixnum (2), geometry));
6632               max_x = min_x + XFIXNUM (Fnth (make_fixnum (3), geometry));
6633               max_y = min_y + XFIXNUM (Fnth (make_fixnum (4), geometry));
6634               if (min_x <= *root_x && *root_x < max_x
6635                   && min_y <= *root_y && *root_y < max_y)
6636                 {
6637                   break;
6638                 }
6639               max_y = -1;
6640             }
6641 
6642           attributes = XCDR (attributes);
6643 	}
6644     }
6645 
6646   /* It was not possible to determine the monitor's geometry, so we
6647      assign some sane defaults here: */
6648   if ( max_y < 0 )
6649     {
6650       min_x = 0;
6651       min_y = 0;
6652       max_x = x_display_pixel_width (FRAME_DISPLAY_INFO (f));
6653       max_y = x_display_pixel_height (FRAME_DISPLAY_INFO (f));
6654     }
6655 
6656   if (FIXNUMP (top))
6657     *root_y = XFIXNUM (top);
6658   else if (FIXNUMP (bottom))
6659     *root_y = XFIXNUM (bottom) - height;
6660   else if (*root_y + XFIXNUM (dy) <= min_y)
6661     *root_y = min_y; /* Can happen for negative dy */
6662   else if (*root_y + XFIXNUM (dy) + height <= max_y)
6663     /* It fits below the pointer */
6664     *root_y += XFIXNUM (dy);
6665   else if (height + XFIXNUM (dy) + min_y <= *root_y)
6666     /* It fits above the pointer.  */
6667     *root_y -= height + XFIXNUM (dy);
6668   else
6669     /* Put it on the top.  */
6670     *root_y = min_y;
6671 
6672   if (FIXNUMP (left))
6673     *root_x = XFIXNUM (left);
6674   else if (FIXNUMP (right))
6675     *root_x = XFIXNUM (right) - width;
6676   else if (*root_x + XFIXNUM (dx) <= min_x)
6677     *root_x = 0; /* Can happen for negative dx */
6678   else if (*root_x + XFIXNUM (dx) + width <= max_x)
6679     /* It fits to the right of the pointer.  */
6680     *root_x += XFIXNUM (dx);
6681   else if (width + XFIXNUM (dx) + min_x <= *root_x)
6682     /* It fits to the left of the pointer.  */
6683     *root_x -= width + XFIXNUM (dx);
6684   else
6685     /* Put it left justified on the screen -- it ought to fit that way.  */
6686     *root_x = min_x;
6687 }
6688 
6689 
6690 /**
6691  * x_hide_tip:
6692  *
6693  * Hide currently visible tooltip and cancel its timer.
6694  *
6695  * If GTK+ system tooltips are used, this will try to hide the tooltip
6696  * referenced by the x_output structure of tooltip_last_frame.  For
6697  * Emacs tooltips this will try to make tooltip_frame invisible (if
6698  * DELETE is false) or delete tooltip_frame (if DELETE is true).
6699  *
6700  * Return Qt if the tooltip was either deleted or made invisible, Qnil
6701  * otherwise.
6702  */
6703 static Lisp_Object
x_hide_tip(bool delete)6704 x_hide_tip (bool delete)
6705 {
6706   if (!NILP (tip_timer))
6707     {
6708       call1 (Qcancel_timer, tip_timer);
6709       tip_timer = Qnil;
6710     }
6711 
6712 #ifdef USE_GTK
6713   /* Any GTK+ system tooltip can be found via the x_output structure of
6714      tip_last_frame, provided that frame is still live.  Any Emacs
6715      tooltip is found via the tip_frame variable.  Note that the current
6716      value of x_gtk_use_system_tooltips might not be the same as used
6717      for the tooltip we have to hide, see Bug#30399.  */
6718   if ((NILP (tip_last_frame) && NILP (tip_frame))
6719       || (!x_gtk_use_system_tooltips
6720 	  && !delete
6721 	  && FRAMEP (tip_frame)
6722 	  && FRAME_LIVE_P (XFRAME (tip_frame))
6723 	  && !FRAME_VISIBLE_P (XFRAME (tip_frame))))
6724     /* Either there's no tooltip to hide or it's an already invisible
6725        Emacs tooltip and we don't want to change its type.  Return
6726        quickly.  */
6727     return Qnil;
6728   else
6729     {
6730       ptrdiff_t count;
6731       Lisp_Object was_open = Qnil;
6732 
6733       count = SPECPDL_INDEX ();
6734       specbind (Qinhibit_redisplay, Qt);
6735       specbind (Qinhibit_quit, Qt);
6736 
6737       /* Try to hide the GTK+ system tip first.  */
6738       if (FRAMEP (tip_last_frame))
6739 	{
6740 	  struct frame *f = XFRAME (tip_last_frame);
6741 
6742 	  if (FRAME_LIVE_P (f))
6743 	    {
6744 	      if (xg_hide_tooltip (f))
6745 		was_open = Qt;
6746 	    }
6747 	}
6748 
6749       /* When using GTK+ system tooltips (compare Bug#41200) reset
6750 	 tip_last_frame.  It will be reassigned when showing the next
6751 	 GTK+ system tooltip.  */
6752       if (x_gtk_use_system_tooltips)
6753 	tip_last_frame = Qnil;
6754 
6755       /* Now look whether there's an Emacs tip around.  */
6756       if (FRAMEP (tip_frame))
6757 	{
6758 	  struct frame *f = XFRAME (tip_frame);
6759 
6760 	  if (FRAME_LIVE_P (f))
6761 	    {
6762 	      if (delete || x_gtk_use_system_tooltips)
6763 		{
6764 		  /* Delete the Emacs tooltip frame when DELETE is true
6765 		     or we change the tooltip type from an Emacs one to
6766 		     a GTK+ system one.  */
6767 		  delete_frame (tip_frame, Qnil);
6768 		  tip_frame = Qnil;
6769 		}
6770 	      else
6771 		x_make_frame_invisible (f);
6772 
6773 	      was_open = Qt;
6774 	    }
6775 	  else
6776 	    tip_frame = Qnil;
6777 	}
6778       else
6779 	tip_frame = Qnil;
6780 
6781       return unbind_to (count, was_open);
6782     }
6783 #else /* not USE_GTK */
6784   if (NILP (tip_frame)
6785       || (!delete
6786 	  && FRAMEP (tip_frame)
6787 	  && FRAME_LIVE_P (XFRAME (tip_frame))
6788 	  && !FRAME_VISIBLE_P (XFRAME (tip_frame))))
6789     return Qnil;
6790   else
6791     {
6792       ptrdiff_t count;
6793       Lisp_Object was_open = Qnil;
6794 
6795       count = SPECPDL_INDEX ();
6796       specbind (Qinhibit_redisplay, Qt);
6797       specbind (Qinhibit_quit, Qt);
6798 
6799       if (FRAMEP (tip_frame))
6800 	{
6801 	  struct frame *f = XFRAME (tip_frame);
6802 
6803 	  if (FRAME_LIVE_P (f))
6804 	    {
6805 	      if (delete)
6806 		{
6807 		  delete_frame (tip_frame, Qnil);
6808 		  tip_frame = Qnil;
6809 		}
6810 	      else
6811 		x_make_frame_invisible (XFRAME (tip_frame));
6812 
6813 #ifdef USE_LUCID
6814 	      /* Bloodcurdling hack alert: The Lucid menu bar widget's
6815 		 redisplay procedure is not called when a tip frame over
6816 		 menu items is unmapped.  Redisplay the menu manually...  */
6817 	      {
6818 		Widget w;
6819 		struct frame *f = SELECTED_FRAME ();
6820 
6821 		if (FRAME_X_P (f) && FRAME_LIVE_P (f))
6822 		  {
6823 		    w = f->output_data.x->menubar_widget;
6824 
6825 		    if (!DoesSaveUnders (FRAME_DISPLAY_INFO (f)->screen)
6826 			&& w != NULL)
6827 		      {
6828 			block_input ();
6829 			xlwmenu_redisplay (w);
6830 			unblock_input ();
6831 		      }
6832 		  }
6833 	      }
6834 #endif /* USE_LUCID */
6835 
6836 	      was_open = Qt;
6837 	    }
6838 	  else
6839 	    tip_frame = Qnil;
6840 	}
6841       else
6842 	tip_frame = Qnil;
6843 
6844       return unbind_to (count, was_open);
6845     }
6846 #endif /* USE_GTK */
6847 }
6848 
6849 
6850 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
6851        doc: /* Show STRING in a "tooltip" window on frame FRAME.
6852 A tooltip window is a small X window displaying a string.
6853 
6854 This is an internal function; Lisp code should call `tooltip-show'.
6855 
6856 FRAME nil or omitted means use the selected frame.
6857 
6858 PARMS is an optional list of frame parameters which can be used to
6859 change the tooltip's appearance.
6860 
6861 Automatically hide the tooltip after TIMEOUT seconds.  TIMEOUT nil
6862 means use the default timeout of 5 seconds.
6863 
6864 If the list of frame parameters PARMS contains a `left' parameter,
6865 display the tooltip at that x-position.  If the list of frame parameters
6866 PARMS contains no `left' but a `right' parameter, display the tooltip
6867 right-adjusted at that x-position. Otherwise display it at the
6868 x-position of the mouse, with offset DX added (default is 5 if DX isn't
6869 specified).
6870 
6871 Likewise for the y-position: If a `top' frame parameter is specified, it
6872 determines the position of the upper edge of the tooltip window.  If a
6873 `bottom' parameter but no `top' frame parameter is specified, it
6874 determines the position of the lower edge of the tooltip window.
6875 Otherwise display the tooltip window at the y-position of the mouse,
6876 with offset DY added (default is -10).
6877 
6878 A tooltip's maximum size is specified by `x-max-tooltip-size'.
6879 Text larger than the specified size is clipped.  */)
6880   (Lisp_Object string, Lisp_Object frame, Lisp_Object parms,
6881    Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy)
6882 {
6883   struct frame *f, *tip_f;
6884   struct window *w;
6885   int root_x, root_y;
6886   struct buffer *old_buffer;
6887   struct text_pos pos;
6888   int width, height;
6889   int old_windows_or_buffers_changed = windows_or_buffers_changed;
6890   ptrdiff_t count = SPECPDL_INDEX ();
6891   ptrdiff_t count_1;
6892   Lisp_Object window, size, tip_buf;
6893   AUTO_STRING (tip, " *tip*");
6894 
6895   specbind (Qinhibit_redisplay, Qt);
6896 
6897   CHECK_STRING (string);
6898   if (SCHARS (string) == 0)
6899     string = make_unibyte_string (" ", 1);
6900 
6901   if (NILP (frame))
6902     frame = selected_frame;
6903   f = decode_window_system_frame (frame);
6904 
6905   if (NILP (timeout))
6906     timeout = make_fixnum (5);
6907   else
6908     CHECK_FIXNAT (timeout);
6909 
6910   if (NILP (dx))
6911     dx = make_fixnum (5);
6912   else
6913     CHECK_FIXNUM (dx);
6914 
6915   if (NILP (dy))
6916     dy = make_fixnum (-10);
6917   else
6918     CHECK_FIXNUM (dy);
6919 
6920 #ifdef USE_GTK
6921   if (x_gtk_use_system_tooltips)
6922     {
6923       bool ok;
6924 
6925       /* Hide a previous tip, if any.  */
6926       Fx_hide_tip ();
6927 
6928       block_input ();
6929       ok = xg_prepare_tooltip (f, string, &width, &height);
6930       if (ok)
6931         {
6932 	  compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
6933           xg_show_tooltip (f, root_x, root_y);
6934 	  tip_last_frame = frame;
6935         }
6936 
6937       unblock_input ();
6938       if (ok) goto start_timer;
6939     }
6940 #endif /* USE_GTK */
6941 
6942   if (FRAMEP (tip_frame) && FRAME_LIVE_P (XFRAME (tip_frame)))
6943     {
6944       if (FRAME_VISIBLE_P (XFRAME (tip_frame))
6945 	  && EQ (frame, tip_last_frame)
6946 	  && !NILP (Fequal_including_properties (tip_last_string, string))
6947 	  && !NILP (Fequal (tip_last_parms, parms)))
6948 	{
6949 	  /* Only DX and DY have changed.  */
6950 	  tip_f = XFRAME (tip_frame);
6951 	  if (!NILP (tip_timer))
6952 	    {
6953 	      call1 (Qcancel_timer, tip_timer);
6954 	      tip_timer = Qnil;
6955 	    }
6956 
6957 	  block_input ();
6958 	  compute_tip_xy (tip_f, parms, dx, dy, FRAME_PIXEL_WIDTH (tip_f),
6959 			  FRAME_PIXEL_HEIGHT (tip_f), &root_x, &root_y);
6960 	  XMoveWindow (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f),
6961 		       root_x, root_y);
6962 	  unblock_input ();
6963 
6964 	  goto start_timer;
6965 	}
6966       else if (tooltip_reuse_hidden_frame && EQ (frame, tip_last_frame))
6967 	{
6968 	  bool delete = false;
6969 	  Lisp_Object tail, elt, parm, last;
6970 
6971 	  /* Check if every parameter in PARMS has the same value in
6972 	     tip_last_parms.  This may destruct tip_last_parms which,
6973 	     however, will be recreated below.  */
6974 	  for (tail = parms; CONSP (tail); tail = XCDR (tail))
6975 	    {
6976 	      elt = XCAR (tail);
6977 	      parm = Fcar (elt);
6978 	      /* The left, top, right and bottom parameters are handled
6979 		 by compute_tip_xy so they can be ignored here.  */
6980 	      if (!EQ (parm, Qleft) && !EQ (parm, Qtop)
6981 		  && !EQ (parm, Qright) && !EQ (parm, Qbottom))
6982 		{
6983 		  last = Fassq (parm, tip_last_parms);
6984 		  if (NILP (Fequal (Fcdr (elt), Fcdr (last))))
6985 		    {
6986 		      /* We lost, delete the old tooltip.  */
6987 		      delete = true;
6988 		      break;
6989 		    }
6990 		  else
6991 		    tip_last_parms =
6992 		      call2 (Qassq_delete_all, parm, tip_last_parms);
6993 		}
6994 	      else
6995 		tip_last_parms =
6996 		  call2 (Qassq_delete_all, parm, tip_last_parms);
6997 	    }
6998 
6999 	  /* Now check if every parameter in what is left of
7000 	     tip_last_parms with a non-nil value has an association in
7001 	     PARMS.  */
7002 	  for (tail = tip_last_parms; CONSP (tail); tail = XCDR (tail))
7003 	    {
7004 	      elt = XCAR (tail);
7005 	      parm = Fcar (elt);
7006 	      if (!EQ (parm, Qleft) && !EQ (parm, Qtop) && !EQ (parm, Qright)
7007 		  && !EQ (parm, Qbottom) && !NILP (Fcdr (elt)))
7008 		{
7009 		  /* We lost, delete the old tooltip.  */
7010 		  delete = true;
7011 		  break;
7012 		}
7013 	    }
7014 
7015 	  x_hide_tip (delete);
7016 	}
7017       else
7018 	x_hide_tip (true);
7019     }
7020   else
7021     x_hide_tip (true);
7022 
7023   tip_last_frame = frame;
7024   tip_last_string = string;
7025   tip_last_parms = parms;
7026 
7027   if (!FRAMEP (tip_frame) || !FRAME_LIVE_P (XFRAME (tip_frame)))
7028     {
7029       /* Add default values to frame parameters.  */
7030       if (NILP (Fassq (Qname, parms)))
7031 	parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
7032       if (NILP (Fassq (Qinternal_border_width, parms)))
7033 	parms = Fcons (Fcons (Qinternal_border_width, make_fixnum (3)), parms);
7034       if (NILP (Fassq (Qborder_width, parms)))
7035 	parms = Fcons (Fcons (Qborder_width, make_fixnum (1)), parms);
7036       if (NILP (Fassq (Qborder_color, parms)))
7037 	parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
7038       if (NILP (Fassq (Qbackground_color, parms)))
7039 	parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
7040 		       parms);
7041 
7042       /* Create a frame for the tooltip, and record it in the global
7043 	 variable tip_frame.  */
7044       if (NILP (tip_frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parms)))
7045 	/* Creating the tip frame failed.  */
7046 	return unbind_to (count, Qnil);
7047     }
7048 
7049   tip_f = XFRAME (tip_frame);
7050   window = FRAME_ROOT_WINDOW (tip_f);
7051   tip_buf = Fget_buffer_create (tip);
7052   /* We will mark the tip window a "pseudo-window" below, and such
7053      windows cannot have display margins.  */
7054   bset_left_margin_cols (XBUFFER (tip_buf), make_fixnum (0));
7055   bset_right_margin_cols (XBUFFER (tip_buf), make_fixnum (0));
7056   set_window_buffer (window, tip_buf, false, false);
7057   w = XWINDOW (window);
7058   w->pseudo_window_p = true;
7059 
7060   /* Set up the frame's root window.  Note: The following code does not
7061      try to size the window or its frame correctly.  Its only purpose is
7062      to make the subsequent text size calculations work.  The right
7063      sizes should get installed when the toolkit gets back to us.  */
7064   w->left_col = 0;
7065   w->top_line = 0;
7066   w->pixel_left = 0;
7067   w->pixel_top = 0;
7068 
7069   if (CONSP (Vx_max_tooltip_size)
7070       && RANGED_FIXNUMP (1, XCAR (Vx_max_tooltip_size), INT_MAX)
7071       && RANGED_FIXNUMP (1, XCDR (Vx_max_tooltip_size), INT_MAX))
7072     {
7073       w->total_cols = XFIXNAT (XCAR (Vx_max_tooltip_size));
7074       w->total_lines = XFIXNAT (XCDR (Vx_max_tooltip_size));
7075     }
7076   else
7077     {
7078       w->total_cols = 80;
7079       w->total_lines = 40;
7080     }
7081 
7082   w->pixel_width = w->total_cols * FRAME_COLUMN_WIDTH (tip_f);
7083   w->pixel_height = w->total_lines * FRAME_LINE_HEIGHT (tip_f);
7084   FRAME_TOTAL_COLS (tip_f) = w->total_cols;
7085   adjust_frame_glyphs (tip_f);
7086 
7087   /* Insert STRING into root window's buffer and fit the frame to the
7088      buffer.  */
7089   count_1 = SPECPDL_INDEX ();
7090   old_buffer = current_buffer;
7091   set_buffer_internal_1 (XBUFFER (w->contents));
7092   bset_truncate_lines (current_buffer, Qnil);
7093   specbind (Qinhibit_read_only, Qt);
7094   specbind (Qinhibit_modification_hooks, Qt);
7095   specbind (Qinhibit_point_motion_hooks, Qt);
7096   Ferase_buffer ();
7097   Finsert (1, &string);
7098   clear_glyph_matrix (w->desired_matrix);
7099   clear_glyph_matrix (w->current_matrix);
7100   SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
7101   try_window (window, pos, TRY_WINDOW_IGNORE_FONTS_CHANGE);
7102   /* Calculate size of tooltip window.  */
7103   size = Fwindow_text_pixel_size (window, Qnil, Qnil, Qnil,
7104 				  make_fixnum (w->pixel_height), Qnil);
7105   /* Add the frame's internal border to calculated size.  */
7106   width = XFIXNUM (Fcar (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
7107   height = XFIXNUM (Fcdr (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
7108 
7109   /* Calculate position of tooltip frame.  */
7110   compute_tip_xy (tip_f, parms, dx, dy, width, height, &root_x, &root_y);
7111 
7112   /* Show tooltip frame.  */
7113   block_input ();
7114   XMoveResizeWindow (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f),
7115 		     root_x, root_y, width, height);
7116   XMapRaised (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f));
7117   unblock_input ();
7118 
7119 #ifdef USE_CAIRO
7120   x_cr_update_surface_desired_size (tip_f, width, height);
7121 #endif	/* USE_CAIRO */
7122 
7123   w->must_be_updated_p = true;
7124   update_single_window (w);
7125   flush_frame (tip_f);
7126   set_buffer_internal_1 (old_buffer);
7127   unbind_to (count_1, Qnil);
7128   windows_or_buffers_changed = old_windows_or_buffers_changed;
7129 
7130  start_timer:
7131   /* Let the tip disappear after timeout seconds.  */
7132   tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
7133 		     intern ("x-hide-tip"));
7134 
7135   return unbind_to (count, Qnil);
7136 }
7137 
7138 
7139 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
7140        doc: /* Hide the current tooltip window, if there is any.
7141 Value is t if tooltip was open, nil otherwise.  */)
7142   (void)
7143 {
7144   return x_hide_tip (!tooltip_reuse_hidden_frame);
7145 }
7146 
7147 DEFUN ("x-double-buffered-p", Fx_double_buffered_p, Sx_double_buffered_p,
7148        0, 1, 0,
7149        doc: /* Return t if FRAME is being double buffered.  */)
7150      (Lisp_Object frame)
7151 {
7152   struct frame *f = decode_live_frame (frame);
7153   return FRAME_X_DOUBLE_BUFFERED_P (f) ? Qt : Qnil;
7154 }
7155 
7156 
7157 /***********************************************************************
7158 			File selection dialog
7159  ***********************************************************************/
7160 
7161 DEFUN ("x-uses-old-gtk-dialog", Fx_uses_old_gtk_dialog,
7162        Sx_uses_old_gtk_dialog,
7163        0, 0, 0,
7164        doc: /* Return t if the old Gtk+ file selection dialog is used.  */)
7165   (void)
7166 {
7167 #ifdef USE_GTK
7168   if (use_dialog_box
7169       && use_file_dialog
7170       && window_system_available (SELECTED_FRAME ())
7171       && xg_uses_old_file_dialog ())
7172     return Qt;
7173 #endif
7174   return Qnil;
7175 }
7176 
7177 
7178 #ifdef USE_MOTIF
7179 /* Callback for "OK" and "Cancel" on file selection dialog.  */
7180 
7181 static void
file_dialog_cb(Widget widget,XtPointer client_data,XtPointer call_data)7182 file_dialog_cb (Widget widget, XtPointer client_data, XtPointer call_data)
7183 {
7184   int *result = client_data;
7185   XmAnyCallbackStruct *cb = call_data;
7186   *result = cb->reason;
7187 }
7188 
7189 
7190 /* Callback for unmapping a file selection dialog.  This is used to
7191    capture the case where a dialog is closed via a window manager's
7192    closer button, for example. Using a XmNdestroyCallback didn't work
7193    in this case.  */
7194 
7195 static void
file_dialog_unmap_cb(Widget widget,XtPointer client_data,XtPointer call_data)7196 file_dialog_unmap_cb (Widget widget, XtPointer client_data, XtPointer call_data)
7197 {
7198   int *result = client_data;
7199   *result = XmCR_CANCEL;
7200 }
7201 
7202 static void
clean_up_file_dialog(void * arg)7203 clean_up_file_dialog (void *arg)
7204 {
7205   Widget dialog = arg;
7206 
7207   /* Clean up.  */
7208   block_input ();
7209   XtUnmanageChild (dialog);
7210   XtDestroyWidget (dialog);
7211   x_menu_set_in_use (false);
7212   unblock_input ();
7213 }
7214 
7215 
7216 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
7217        doc: /* SKIP: real doc in USE_GTK definition in xfns.c.  */)
7218   (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename,
7219    Lisp_Object mustmatch, Lisp_Object only_dir_p)
7220 {
7221   int result;
7222   struct frame *f = SELECTED_FRAME ();
7223   Lisp_Object file = Qnil;
7224   Lisp_Object decoded_file;
7225   Widget dialog, text, help;
7226   Arg al[10];
7227   int ac = 0;
7228   XmString dir_xmstring, pattern_xmstring;
7229   ptrdiff_t count = SPECPDL_INDEX ();
7230 
7231   check_window_system (f);
7232 
7233   if (popup_activated ())
7234     error ("Trying to use a menu from within a menu-entry");
7235 
7236   CHECK_STRING (prompt);
7237   CHECK_STRING (dir);
7238 
7239   /* Prevent redisplay.  */
7240   specbind (Qinhibit_redisplay, Qt);
7241 
7242   block_input ();
7243 
7244   /* Create the dialog with PROMPT as title, using DIR as initial
7245      directory and using "*" as pattern.  */
7246   dir = Fexpand_file_name (dir, Qnil);
7247   dir_xmstring = XmStringCreateLocalized (SSDATA (dir));
7248   pattern_xmstring = XmStringCreateLocalized ("*");
7249 
7250   XtSetArg (al[ac], XmNtitle, SDATA (prompt)); ++ac;
7251   XtSetArg (al[ac], XmNdirectory, dir_xmstring); ++ac;
7252   XtSetArg (al[ac], XmNpattern, pattern_xmstring); ++ac;
7253   XtSetArg (al[ac], XmNresizePolicy, XmRESIZE_GROW); ++ac;
7254   XtSetArg (al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ++ac;
7255   dialog = XmCreateFileSelectionDialog (f->output_data.x->widget,
7256 					"fsb", al, ac);
7257   XmStringFree (dir_xmstring);
7258   XmStringFree (pattern_xmstring);
7259 
7260   /* Add callbacks for OK and Cancel.  */
7261   XtAddCallback (dialog, XmNokCallback, file_dialog_cb,
7262 		 (XtPointer) &result);
7263   XtAddCallback (dialog, XmNcancelCallback, file_dialog_cb,
7264 		 (XtPointer) &result);
7265   XtAddCallback (dialog, XmNunmapCallback, file_dialog_unmap_cb,
7266 		 (XtPointer) &result);
7267 
7268   /* Remove the help button since we can't display help.  */
7269   help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON);
7270   XtUnmanageChild (help);
7271 
7272   /* Mark OK button as default.  */
7273   XtVaSetValues (XmFileSelectionBoxGetChild (dialog, XmDIALOG_OK_BUTTON),
7274 		 XmNshowAsDefault, True, NULL);
7275 
7276   /* If MUSTMATCH is non-nil, disable the file entry field of the
7277      dialog, so that the user must select a file from the files list
7278      box.  We can't remove it because we wouldn't have a way to get at
7279      the result file name, then.  */
7280   text = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
7281   if (!NILP (mustmatch))
7282     {
7283       Widget label;
7284       label = XmFileSelectionBoxGetChild (dialog, XmDIALOG_SELECTION_LABEL);
7285       XtSetSensitive (text, False);
7286       XtSetSensitive (label, False);
7287     }
7288 
7289   /* Manage the dialog, so that list boxes get filled.  */
7290   XtManageChild (dialog);
7291 
7292   if (STRINGP (default_filename))
7293     {
7294       XmString default_xmstring;
7295       Widget wtext = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
7296       Widget list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
7297 
7298       XmTextPosition last_pos = XmTextFieldGetLastPosition (wtext);
7299       XmTextFieldReplace (wtext, 0, last_pos,
7300                           (SSDATA (Ffile_name_nondirectory (default_filename))));
7301 
7302       /* Select DEFAULT_FILENAME in the files list box.  DEFAULT_FILENAME
7303          must include the path for this to work.  */
7304 
7305       default_xmstring = XmStringCreateLocalized (SSDATA (default_filename));
7306 
7307       if (XmListItemExists (list, default_xmstring))
7308         {
7309           int item_pos = XmListItemPos (list, default_xmstring);
7310           /* Select the item and scroll it into view.  */
7311           XmListSelectPos (list, item_pos, True);
7312           XmListSetPos (list, item_pos);
7313         }
7314 
7315       XmStringFree (default_xmstring);
7316     }
7317 
7318   record_unwind_protect_ptr (clean_up_file_dialog, dialog);
7319 
7320   /* Process events until the user presses Cancel or OK.  */
7321   x_menu_set_in_use (true);
7322   result = 0;
7323   while (result == 0)
7324     {
7325       XEvent event;
7326       x_menu_wait_for_event (0);
7327       XtAppNextEvent (Xt_app_con, &event);
7328       if (event.type == KeyPress
7329           && FRAME_X_DISPLAY (f) == event.xkey.display)
7330         {
7331           KeySym keysym = XLookupKeysym (&event.xkey, 0);
7332 
7333           /* Pop down on C-g.  */
7334           if (keysym == XK_g && (event.xkey.state & ControlMask) != 0)
7335             XtUnmanageChild (dialog);
7336         }
7337 
7338       (void) x_dispatch_event (&event, FRAME_X_DISPLAY (f));
7339     }
7340 
7341   /* Get the result.  */
7342   if (result == XmCR_OK)
7343     {
7344       XmString text_string;
7345       String data;
7346 
7347       XtVaGetValues (dialog, XmNtextString, &text_string, NULL);
7348       XmStringGetLtoR (text_string, XmFONTLIST_DEFAULT_TAG, &data);
7349       XmStringFree (text_string);
7350       file = build_string (data);
7351       XtFree (data);
7352     }
7353   else
7354     file = Qnil;
7355 
7356   unblock_input ();
7357 
7358   /* Make "Cancel" equivalent to C-g.  */
7359   if (NILP (file))
7360     quit ();
7361 
7362   decoded_file = DECODE_FILE (file);
7363 
7364   return unbind_to (count, decoded_file);
7365 }
7366 
7367 #endif /* USE_MOTIF */
7368 
7369 #ifdef USE_GTK
7370 
7371 static void
clean_up_dialog(void)7372 clean_up_dialog (void)
7373 {
7374   x_menu_set_in_use (false);
7375 }
7376 
7377 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
7378        doc: /* Read file name, prompting with PROMPT in directory DIR.
7379 Use a file selection dialog.  Select DEFAULT-FILENAME in the dialog's file
7380 selection box, if specified.  If MUSTMATCH is non-nil, the returned file
7381 or directory must exist.
7382 
7383 This function is defined only on NS, MS Windows, and X Windows with the
7384 Motif or Gtk toolkits.  With the Motif toolkit, ONLY-DIR-P is ignored.
7385 Otherwise, if ONLY-DIR-P is non-nil, the user can select only directories.
7386 On MS Windows 7 and later, the file selection dialog "remembers" the last
7387 directory where the user selected a file, and will open that directory
7388 instead of DIR on subsequent invocations of this function with the same
7389 value of DIR as in previous invocations; this is standard MS Windows behavior.  */)
7390   (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename, Lisp_Object mustmatch, Lisp_Object only_dir_p)
7391 {
7392   struct frame *f = SELECTED_FRAME ();
7393   char *fn;
7394   Lisp_Object file = Qnil;
7395   Lisp_Object decoded_file;
7396   ptrdiff_t count = SPECPDL_INDEX ();
7397   char *cdef_file;
7398 
7399   check_window_system (f);
7400 
7401   if (popup_activated ())
7402     error ("Trying to use a menu from within a menu-entry");
7403   else
7404     x_menu_set_in_use (true);
7405 
7406   CHECK_STRING (prompt);
7407   CHECK_STRING (dir);
7408 
7409   /* Prevent redisplay.  */
7410   specbind (Qinhibit_redisplay, Qt);
7411   record_unwind_protect_void (clean_up_dialog);
7412 
7413   block_input ();
7414 
7415   if (STRINGP (default_filename))
7416     cdef_file = SSDATA (default_filename);
7417   else
7418     cdef_file = SSDATA (dir);
7419 
7420   fn = xg_get_file_name (f, SSDATA (prompt), cdef_file,
7421                          ! NILP (mustmatch),
7422                          ! NILP (only_dir_p));
7423 
7424   if (fn)
7425     {
7426       file = build_string (fn);
7427       xfree (fn);
7428     }
7429 
7430   unblock_input ();
7431 
7432   /* Make "Cancel" equivalent to C-g.  */
7433   if (NILP (file))
7434     quit ();
7435 
7436   decoded_file = DECODE_FILE (file);
7437 
7438   return unbind_to (count, decoded_file);
7439 }
7440 
7441 
7442 #ifdef HAVE_FREETYPE
7443 
7444 DEFUN ("x-select-font", Fx_select_font, Sx_select_font, 0, 2, 0,
7445        doc: /* Read a font using a GTK dialog.
7446 Return either a font spec (for GTK versions >= 3.2) or a string
7447 containing a GTK-style font name.
7448 
7449 FRAME is the frame on which to pop up the font chooser.  If omitted or
7450 nil, it defaults to the selected frame. */)
7451   (Lisp_Object frame, Lisp_Object ignored)
7452 {
7453   struct frame *f = decode_window_system_frame (frame);
7454   Lisp_Object font;
7455   Lisp_Object font_param;
7456   char *default_name = NULL;
7457   ptrdiff_t count = SPECPDL_INDEX ();
7458 
7459   if (popup_activated ())
7460     error ("Trying to use a menu from within a menu-entry");
7461   else
7462     x_menu_set_in_use (true);
7463 
7464   /* Prevent redisplay.  */
7465   specbind (Qinhibit_redisplay, Qt);
7466   record_unwind_protect_void (clean_up_dialog);
7467 
7468   block_input ();
7469 
7470   XSETFONT (font, FRAME_FONT (f));
7471   font_param = Ffont_get (font, QCname);
7472   if (STRINGP (font_param))
7473     default_name = xlispstrdup (font_param);
7474   else
7475     {
7476       font_param = Fframe_parameter (frame, Qfont_parameter);
7477       if (STRINGP (font_param))
7478         default_name = xlispstrdup (font_param);
7479     }
7480 
7481   font = xg_get_font (f, default_name);
7482   xfree (default_name);
7483 
7484   unblock_input ();
7485 
7486   if (NILP (font))
7487     quit ();
7488 
7489   return unbind_to (count, font);
7490 }
7491 #endif /* HAVE_FREETYPE */
7492 
7493 #endif /* USE_GTK */
7494 
7495 
7496 /***********************************************************************
7497 			       Keyboard
7498  ***********************************************************************/
7499 
7500 #ifdef HAVE_XKB
7501 #include <X11/XKBlib.h>
7502 #include <X11/keysym.h>
7503 #endif
7504 
7505 DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p,
7506        Sx_backspace_delete_keys_p, 0, 1, 0,
7507        doc: /* Check if both Backspace and Delete keys are on the keyboard of FRAME.
7508 FRAME nil means use the selected frame.
7509 Value is t if we know that both keys are present, and are mapped to the
7510 usual X keysyms.  Value is `lambda' if we cannot determine if both keys are
7511 present and mapped to the usual X keysyms.  */)
7512   (Lisp_Object frame)
7513 {
7514 #ifndef HAVE_XKB
7515   return Qlambda;
7516 #else
7517   XkbDescPtr kb;
7518   struct frame *f = decode_window_system_frame (frame);
7519   Display *dpy = FRAME_X_DISPLAY (f);
7520   Lisp_Object have_keys;
7521   int major, minor, op, event, error_code;
7522 
7523   block_input ();
7524 
7525   /* Check library version in case we're dynamically linked.  */
7526   major = XkbMajorVersion;
7527   minor = XkbMinorVersion;
7528   if (!XkbLibraryVersion (&major, &minor))
7529     {
7530       unblock_input ();
7531       return Qlambda;
7532     }
7533 
7534   /* Check that the server supports XKB.  */
7535   major = XkbMajorVersion;
7536   minor = XkbMinorVersion;
7537   if (!XkbQueryExtension (dpy, &op, &event, &error_code, &major, &minor))
7538     {
7539       unblock_input ();
7540       return Qlambda;
7541     }
7542 
7543   /* In this code we check that the keyboard has physical keys with names
7544      that start with BKSP (Backspace) and DELE (Delete), and that they
7545      generate keysym XK_BackSpace and XK_Delete respectively.
7546      This function is used to test if normal-erase-is-backspace should be
7547      turned on.
7548      An alternative approach would be to just check if XK_BackSpace and
7549      XK_Delete are mapped to any key.  But if any of those are mapped to
7550      some non-intuitive key combination (Meta-Shift-Ctrl-whatever) and the
7551      user doesn't know about it, it is better to return false here.
7552      It is more obvious to the user what to do if she/he has two keys
7553      clearly marked with names/symbols and one key does something not
7554      expected (i.e. she/he then tries the other).
7555      The cases where Backspace/Delete is mapped to some other key combination
7556      are rare, and in those cases, normal-erase-is-backspace can be turned on
7557      manually.  */
7558 
7559   have_keys = Qnil;
7560   kb = XkbGetMap (dpy, XkbAllMapComponentsMask, XkbUseCoreKbd);
7561   if (kb)
7562     {
7563       int delete_keycode = 0, backspace_keycode = 0, i;
7564 
7565       if (XkbGetNames (dpy, XkbAllNamesMask, kb) == Success)
7566 	{
7567 	  for (i = kb->min_key_code;
7568 	       (i < kb->max_key_code
7569 		&& (delete_keycode == 0 || backspace_keycode == 0));
7570 	       ++i)
7571 	    {
7572 	      /* The XKB symbolic key names can be seen most easily in
7573 		 the PS file generated by `xkbprint -label name
7574 		 $DISPLAY'.  */
7575 	      if (memcmp ("DELE", kb->names->keys[i].name, 4) == 0)
7576 		delete_keycode = i;
7577 	      else if (memcmp ("BKSP", kb->names->keys[i].name, 4) == 0)
7578 		backspace_keycode = i;
7579 	    }
7580 
7581 	  XkbFreeNames (kb, 0, True);
7582 	}
7583 
7584       /* As of libX11-1.6.2, XkbGetMap manual says that you should use
7585 	 XkbFreeClientMap to free the data returned by XkbGetMap.  But
7586 	 this function just frees the data referenced from KB and not
7587 	 KB itself.  To free KB as well, call XkbFreeKeyboard.  */
7588       XkbFreeKeyboard (kb, XkbAllMapComponentsMask, True);
7589 
7590       if (delete_keycode
7591 	  && backspace_keycode
7592 	  && XKeysymToKeycode (dpy, XK_Delete) == delete_keycode
7593 	  && XKeysymToKeycode (dpy, XK_BackSpace) == backspace_keycode)
7594 	have_keys = Qt;
7595     }
7596   unblock_input ();
7597   return have_keys;
7598 #endif
7599 }
7600 
7601 
7602 
7603 /***********************************************************************
7604 			       Printing
7605  ***********************************************************************/
7606 
7607 #ifdef USE_CAIRO
7608 DEFUN ("x-export-frames", Fx_export_frames, Sx_export_frames, 0, 2, 0,
7609        doc: /* Return image data of FRAMES in TYPE format.
7610 FRAMES should be nil (the selected frame), a frame, or a list of
7611 frames (each of which corresponds to one page).  Each frame should be
7612 visible.  Optional arg TYPE should be either `pdf' (default), `png',
7613 `postscript', or `svg'.  Supported types are determined by the
7614 compile-time configuration of cairo.
7615 
7616 Note: Text drawn with the `x' font backend is shown with hollow boxes
7617 unless TYPE is `png'.  */)
7618      (Lisp_Object frames, Lisp_Object type)
7619 {
7620   Lisp_Object rest, tmp;
7621   cairo_surface_type_t surface_type;
7622 
7623   if (!CONSP (frames))
7624     frames = list1 (frames);
7625 
7626   tmp = Qnil;
7627   for (rest = frames; CONSP (rest); rest = XCDR (rest))
7628     {
7629       struct frame *f = decode_window_system_frame (XCAR (rest));
7630       Lisp_Object frame;
7631 
7632       XSETFRAME (frame, f);
7633       if (!FRAME_VISIBLE_P (f))
7634 	error ("Frames to be exported must be visible.");
7635       tmp = Fcons (frame, tmp);
7636     }
7637   frames = Fnreverse (tmp);
7638 
7639 #ifdef CAIRO_HAS_PDF_SURFACE
7640   if (NILP (type) || EQ (type, Qpdf))
7641     surface_type = CAIRO_SURFACE_TYPE_PDF;
7642   else
7643 #endif
7644 #ifdef CAIRO_HAS_PNG_FUNCTIONS
7645   if (EQ (type, Qpng))
7646     {
7647       if (!NILP (XCDR (frames)))
7648 	error ("PNG export cannot handle multiple frames.");
7649       surface_type = CAIRO_SURFACE_TYPE_IMAGE;
7650     }
7651   else
7652 #endif
7653 #ifdef CAIRO_HAS_PS_SURFACE
7654   if (EQ (type, Qpostscript))
7655     surface_type = CAIRO_SURFACE_TYPE_PS;
7656   else
7657 #endif
7658 #ifdef CAIRO_HAS_SVG_SURFACE
7659   if (EQ (type, Qsvg))
7660     {
7661       /* For now, we stick to SVG 1.1.  */
7662       if (!NILP (XCDR (frames)))
7663 	error ("SVG export cannot handle multiple frames.");
7664       surface_type = CAIRO_SURFACE_TYPE_SVG;
7665     }
7666   else
7667 #endif
7668     error ("Unsupported export type");
7669 
7670   return x_cr_export_frames (frames, surface_type);
7671 }
7672 
7673 #ifdef USE_GTK
7674 DEFUN ("x-page-setup-dialog", Fx_page_setup_dialog, Sx_page_setup_dialog, 0, 0, 0,
7675        doc: /* Pop up a page setup dialog.
7676 The current page setup can be obtained using `x-get-page-setup'.  */)
7677      (void)
7678 {
7679   block_input ();
7680   xg_page_setup_dialog ();
7681   unblock_input ();
7682 
7683   return Qnil;
7684 }
7685 
7686 DEFUN ("x-get-page-setup", Fx_get_page_setup, Sx_get_page_setup, 0, 0, 0,
7687        doc: /* Return the value of the current page setup.
7688 The return value is an alist containing the following keys:
7689 
7690   orientation: page orientation (symbol `portrait', `landscape',
7691 	`reverse-portrait', or `reverse-landscape').
7692   width, height: page width/height in points not including margins.
7693   left-margin, right-margin, top-margin, bottom-margin: print margins,
7694 	which is the parts of the page that the printer cannot print
7695 	on, in points.
7696 
7697 The paper width can be obtained as the sum of width, left-margin, and
7698 right-margin values if the page orientation is `portrait' or
7699 `reverse-portrait'.  Otherwise, it is the sum of width, top-margin,
7700 and bottom-margin values.  Likewise, the paper height is the sum of
7701 height, top-margin, and bottom-margin values if the page orientation
7702 is `portrait' or `reverse-portrait'.  Otherwise, it is the sum of
7703 height, left-margin, and right-margin values.  */)
7704      (void)
7705 {
7706   Lisp_Object result;
7707 
7708   block_input ();
7709   result = xg_get_page_setup ();
7710   unblock_input ();
7711 
7712   return result;
7713 }
7714 
7715 DEFUN ("x-print-frames-dialog", Fx_print_frames_dialog, Sx_print_frames_dialog, 0, 1, "",
7716        doc: /* Pop up a print dialog to print the current contents of FRAMES.
7717 FRAMES should be nil (the selected frame), a frame, or a list of
7718 frames (each of which corresponds to one page).  Each frame should be
7719 visible.
7720 
7721 Note: Text drawn with the `x' font backend is shown with hollow boxes.  */)
7722      (Lisp_Object frames)
7723 {
7724   Lisp_Object rest, tmp;
7725   int count;
7726 
7727   if (!CONSP (frames))
7728     frames = list1 (frames);
7729 
7730   tmp = Qnil;
7731   for (rest = frames; CONSP (rest); rest = XCDR (rest))
7732     {
7733       struct frame *f = decode_window_system_frame (XCAR (rest));
7734       Lisp_Object frame;
7735 
7736       XSETFRAME (frame, f);
7737       if (!FRAME_VISIBLE_P (f))
7738 	error ("Frames to be printed must be visible.");
7739       tmp = Fcons (frame, tmp);
7740     }
7741   frames = Fnreverse (tmp);
7742 
7743   /* Make sure the current matrices are up-to-date.  */
7744   count = SPECPDL_INDEX ();
7745   specbind (Qredisplay_dont_pause, Qt);
7746   redisplay_preserve_echo_area (32);
7747   unbind_to (count, Qnil);
7748 
7749   block_input ();
7750   xg_print_frames_dialog (frames);
7751   unblock_input ();
7752 
7753   return Qnil;
7754 }
7755 #endif	/* USE_GTK */
7756 #endif	/* USE_CAIRO */
7757 
7758 #ifdef USE_GTK
7759 #ifdef HAVE_GTK3
7760 #if GTK_CHECK_VERSION (3, 14, 0)
7761 DEFUN ("x-gtk-debug", Fx_gtk_debug, Sx_gtk_debug, 1, 1, 0,
7762        doc: /* Toggle interactive GTK debugging.   */)
7763   (Lisp_Object enable)
7764 {
7765   gboolean enable_debug = !NILP (enable);
7766 
7767   block_input ();
7768   gtk_window_set_interactive_debugging (enable_debug);
7769   unblock_input ();
7770 
7771   return NILP (enable) ? Qnil : Qt;
7772 }
7773 #endif /* GTK_CHECK_VERSION (3, 14, 0) */
7774 #endif /* HAVE_GTK3 */
7775 #endif	/* USE_GTK */
7776 
7777 /***********************************************************************
7778 			    Initialization
7779  ***********************************************************************/
7780 
7781 /* Keep this list in the same order as frame_parms in frame.c.
7782    Use 0 for unsupported frame parameters.  */
7783 
7784 frame_parm_handler x_frame_parm_handlers[] =
7785 {
7786   gui_set_autoraise,
7787   gui_set_autolower,
7788   x_set_background_color,
7789   x_set_border_color,
7790   gui_set_border_width,
7791   x_set_cursor_color,
7792   x_set_cursor_type,
7793   gui_set_font,
7794   x_set_foreground_color,
7795   x_set_icon_name,
7796   x_set_icon_type,
7797   x_set_internal_border_width,
7798   gui_set_right_divider_width,
7799   gui_set_bottom_divider_width,
7800   x_set_menu_bar_lines,
7801   x_set_mouse_color,
7802   x_explicitly_set_name,
7803   gui_set_scroll_bar_width,
7804   gui_set_scroll_bar_height,
7805   x_set_title,
7806   gui_set_unsplittable,
7807   gui_set_vertical_scroll_bars,
7808   gui_set_horizontal_scroll_bars,
7809   gui_set_visibility,
7810   x_set_tab_bar_lines,
7811   x_set_tool_bar_lines,
7812   x_set_scroll_bar_foreground,
7813   x_set_scroll_bar_background,
7814   gui_set_screen_gamma,
7815   gui_set_line_spacing,
7816   gui_set_left_fringe,
7817   gui_set_right_fringe,
7818   x_set_wait_for_wm,
7819   gui_set_fullscreen,
7820   gui_set_font_backend,
7821   gui_set_alpha,
7822   x_set_sticky,
7823   x_set_tool_bar_position,
7824   x_set_inhibit_double_buffering,
7825   x_set_undecorated,
7826   x_set_parent_frame,
7827   x_set_skip_taskbar,
7828   x_set_no_focus_on_map,
7829   x_set_no_accept_focus,
7830   x_set_z_group,
7831   x_set_override_redirect,
7832   gui_set_no_special_glyphs,
7833 };
7834 
7835 void
syms_of_xfns(void)7836 syms_of_xfns (void)
7837 {
7838   DEFSYM (Qundefined_color, "undefined-color");
7839   DEFSYM (Qcompound_text, "compound-text");
7840   DEFSYM (Qcancel_timer, "cancel-timer");
7841   DEFSYM (Qfont_parameter, "font-parameter");
7842   DEFSYM (Qmono, "mono");
7843   DEFSYM (Qassq_delete_all, "assq-delete-all");
7844   DEFSYM (Qhide, "hide");
7845   DEFSYM (Qresize_mode, "resize-mode");
7846 
7847 #ifdef USE_CAIRO
7848   DEFSYM (Qpdf, "pdf");
7849 
7850   DEFSYM (Qorientation, "orientation");
7851   DEFSYM (Qtop_margin, "top-margin");
7852   DEFSYM (Qbottom_margin, "bottom-margin");
7853   DEFSYM (Qportrait, "portrait");
7854   DEFSYM (Qlandscape, "landscape");
7855   DEFSYM (Qreverse_portrait, "reverse-portrait");
7856   DEFSYM (Qreverse_landscape, "reverse-landscape");
7857 #endif
7858 
7859   Fput (Qundefined_color, Qerror_conditions,
7860 	pure_list (Qundefined_color, Qerror));
7861   Fput (Qundefined_color, Qerror_message,
7862 	build_pure_c_string ("Undefined color"));
7863 
7864   DEFVAR_LISP ("x-pointer-shape", Vx_pointer_shape,
7865     doc: /* The shape of the pointer when over text.
7866 Changing the value does not affect existing frames
7867 unless you set the mouse color.  */);
7868   Vx_pointer_shape = Qnil;
7869 
7870 #if false /* This doesn't really do anything.  */
7871   DEFVAR_LISP ("x-nontext-pointer-shape", Vx_nontext_pointer_shape,
7872     doc: /* The shape of the pointer when not over text.
7873 This variable takes effect when you create a new frame
7874 or when you set the mouse color.  */);
7875 #endif
7876   Vx_nontext_pointer_shape = Qnil;
7877 
7878   DEFVAR_LISP ("x-hourglass-pointer-shape", Vx_hourglass_pointer_shape,
7879     doc: /* The shape of the pointer when Emacs is busy.
7880 This variable takes effect when you create a new frame
7881 or when you set the mouse color.  */);
7882   Vx_hourglass_pointer_shape = Qnil;
7883 
7884 #if false /* This doesn't really do anything.  */
7885   DEFVAR_LISP ("x-mode-pointer-shape", Vx_mode_pointer_shape,
7886     doc: /* The shape of the pointer when over the mode line.
7887 This variable takes effect when you create a new frame
7888 or when you set the mouse color.  */);
7889 #endif
7890   Vx_mode_pointer_shape = Qnil;
7891 
7892   DEFVAR_LISP ("x-sensitive-text-pointer-shape",
7893 	      Vx_sensitive_text_pointer_shape,
7894 	       doc: /* The shape of the pointer when over mouse-sensitive text.
7895 This variable takes effect when you create a new frame
7896 or when you set the mouse color.  */);
7897   Vx_sensitive_text_pointer_shape = Qnil;
7898 
7899   DEFVAR_LISP ("x-window-horizontal-drag-cursor",
7900 	      Vx_window_horizontal_drag_shape,
7901   doc: /* Pointer shape to use for indicating a window can be dragged horizontally.
7902 This variable takes effect when you create a new frame
7903 or when you set the mouse color.  */);
7904   Vx_window_horizontal_drag_shape = Qnil;
7905 
7906   DEFVAR_LISP ("x-window-vertical-drag-cursor",
7907 	      Vx_window_vertical_drag_shape,
7908   doc: /* Pointer shape to use for indicating a window can be dragged vertically.
7909 This variable takes effect when you create a new frame
7910 or when you set the mouse color.  */);
7911   Vx_window_vertical_drag_shape = Qnil;
7912 
7913   DEFVAR_LISP ("x-window-left-edge-cursor",
7914 	       Vx_window_left_edge_shape,
7915   doc: /* Pointer shape indicating a left x-window edge can be dragged.
7916 This variable takes effect when you create a new frame
7917 or when you set the mouse color.  */);
7918   Vx_window_left_edge_shape = Qnil;
7919 
7920   DEFVAR_LISP ("x-window-top-left-corner-cursor",
7921 	       Vx_window_top_left_corner_shape,
7922   doc: /* Pointer shape indicating a top left x-window corner can be dragged.
7923 This variable takes effect when you create a new frame
7924 or when you set the mouse color.  */);
7925   Vx_window_top_left_corner_shape = Qnil;
7926 
7927   DEFVAR_LISP ("x-window-top-edge-cursor",
7928 	       Vx_window_top_edge_shape,
7929   doc: /* Pointer shape indicating a top x-window edge can be dragged.
7930 This variable takes effect when you create a new frame
7931 or when you set the mouse color.  */);
7932   Vx_window_top_edge_shape = Qnil;
7933 
7934   DEFVAR_LISP ("x-window-top-right-corner-cursor",
7935 	       Vx_window_top_right_corner_shape,
7936   doc: /* Pointer shape indicating a top right x-window corner can be dragged.
7937 This variable takes effect when you create a new frame
7938 or when you set the mouse color.  */);
7939   Vx_window_top_right_corner_shape = Qnil;
7940 
7941   DEFVAR_LISP ("x-window-right-edge-cursor",
7942 	       Vx_window_right_edge_shape,
7943   doc: /* Pointer shape indicating a right x-window edge can be dragged.
7944 This variable takes effect when you create a new frame
7945 or when you set the mouse color.  */);
7946   Vx_window_right_edge_shape = Qnil;
7947 
7948   DEFVAR_LISP ("x-window-bottom-right-corner-cursor",
7949 	       Vx_window_bottom_right_corner_shape,
7950   doc: /* Pointer shape indicating a bottom right x-window corner can be dragged.
7951 This variable takes effect when you create a new frame
7952 or when you set the mouse color.  */);
7953   Vx_window_bottom_right_corner_shape = Qnil;
7954 
7955   DEFVAR_LISP ("x-window-bottom-edge-cursor",
7956 	       Vx_window_bottom_edge_shape,
7957   doc: /* Pointer shape indicating a bottom x-window edge can be dragged.
7958 This variable takes effect when you create a new frame
7959 or when you set the mouse color.  */);
7960   Vx_window_bottom_edge_shape = Qnil;
7961 
7962   DEFVAR_LISP ("x-window-bottom-left-corner-cursor",
7963 	       Vx_window_bottom_left_corner_shape,
7964   doc: /* Pointer shape indicating a bottom left x-window corner can be dragged.
7965 This variable takes effect when you create a new frame
7966 or when you set the mouse color.  */);
7967   Vx_window_bottom_left_corner_shape = Qnil;
7968 
7969   DEFVAR_LISP ("x-cursor-fore-pixel", Vx_cursor_fore_pixel,
7970     doc: /* A string indicating the foreground color of the cursor box.  */);
7971   Vx_cursor_fore_pixel = Qnil;
7972 
7973   DEFVAR_LISP ("x-max-tooltip-size", Vx_max_tooltip_size,
7974     doc: /* Maximum size for tooltips.
7975 Value is a pair (COLUMNS . ROWS).  Text larger than this is clipped.  */);
7976   Vx_max_tooltip_size = Fcons (make_fixnum (80), make_fixnum (40));
7977 
7978   DEFVAR_LISP ("x-no-window-manager", Vx_no_window_manager,
7979     doc: /* Non-nil if no X window manager is in use.
7980 Emacs doesn't try to figure this out; this is always nil
7981 unless you set it to something else.  */);
7982   /* We don't have any way to find this out, so set it to nil
7983      and maybe the user would like to set it to t.  */
7984   Vx_no_window_manager = Qnil;
7985 
7986   DEFVAR_LISP ("x-pixel-size-width-font-regexp",
7987 	       Vx_pixel_size_width_font_regexp,
7988     doc: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
7989 
7990 Since Emacs gets the width of a font matching this regexp from the
7991 PIXEL_SIZE field of the name, the font-finding mechanism gets faster for
7992 such a font.  This is especially effective for large fonts such as
7993 Chinese, Japanese, and Korean.  */);
7994   Vx_pixel_size_width_font_regexp = Qnil;
7995 
7996 /* This is not ifdef:ed, so other builds than GTK can customize it.  */
7997   DEFVAR_BOOL ("x-gtk-use-old-file-dialog", x_gtk_use_old_file_dialog,
7998     doc: /* Non-nil means prompt with the old GTK file selection dialog.
7999 If nil or if the file selection dialog is not available, the new GTK file
8000 chooser is used instead.  To turn off all file dialogs set the
8001 variable `use-file-dialog'.  */);
8002   x_gtk_use_old_file_dialog = false;
8003 
8004   DEFVAR_BOOL ("x-gtk-show-hidden-files", x_gtk_show_hidden_files,
8005     doc: /* If non-nil, the GTK file chooser will by default show hidden files.
8006 Note that this is just the default, there is a toggle button on the file
8007 chooser to show or not show hidden files on a case by case basis.  */);
8008   x_gtk_show_hidden_files = false;
8009 
8010   DEFVAR_BOOL ("x-gtk-file-dialog-help-text", x_gtk_file_dialog_help_text,
8011     doc: /* If non-nil, the GTK file chooser will show additional help text.
8012 If more space for files in the file chooser dialog is wanted, set this to nil
8013 to turn the additional text off.  */);
8014   x_gtk_file_dialog_help_text = true;
8015 
8016   DEFVAR_BOOL ("x-gtk-use-system-tooltips", x_gtk_use_system_tooltips,
8017     doc: /* If non-nil with a Gtk+ built Emacs, the Gtk+ tooltip is used.
8018 Otherwise use Emacs own tooltip implementation.
8019 When using Gtk+ tooltips, the tooltip face is not used.  */);
8020   x_gtk_use_system_tooltips = true;
8021 
8022   DEFVAR_LISP ("x-gtk-resize-child-frames", x_gtk_resize_child_frames,
8023     doc: /* If non-nil, resize child frames specially with GTK builds.
8024 If this is nil, resize child frames like any other frames.  This is the
8025 default and usually works with most desktops.  Some desktop environments
8026 (GNOME shell in particular when using the mutter window manager),
8027 however, may refuse to resize a child frame when Emacs is built with
8028 GTK3.  For those environments, the two settings below are provided.
8029 
8030 If this equals the symbol 'hide', Emacs temporarily hides the child
8031 frame during resizing.  This approach seems to work reliably, may
8032 however induce some flicker when the frame is made visible again.
8033 
8034 If this equals the symbol 'resize-mode', Emacs uses GTK's resize mode to
8035 always trigger an immediate resize of the child frame.  This method is
8036 deprecated by GTK and may not work in future versions of that toolkit.
8037 It also may freeze Emacs when used with other desktop environments.  It
8038 avoids, however, the unpleasant flicker induced by the hiding approach.
8039 
8040 This variable is considered a temporary workaround and will be hopefully
8041 eliminated in future versions of Emacs.  */);
8042   x_gtk_resize_child_frames = Qnil;
8043 
8044   /* Tell Emacs about this window system.  */
8045   Fprovide (Qx, Qnil);
8046 
8047 #ifdef USE_X_TOOLKIT
8048   Fprovide (intern_c_string ("x-toolkit"), Qnil);
8049 #ifdef USE_MOTIF
8050   Fprovide (intern_c_string ("motif"), Qnil);
8051 
8052   DEFVAR_LISP ("motif-version-string", Vmotif_version_string,
8053 	       doc: /* Version info for LessTif/Motif.  */);
8054   Vmotif_version_string = build_string (XmVERSION_STRING);
8055 #endif /* USE_MOTIF */
8056 #endif /* USE_X_TOOLKIT */
8057 
8058 #ifdef USE_GTK
8059   /* Provide x-toolkit also for GTK.  Internally GTK does not use Xt so it
8060      is not an X toolkit in that sense (USE_X_TOOLKIT is not defined).
8061      But for a user it is a toolkit for X, and indeed, configure
8062      accepts --with-x-toolkit=gtk.  */
8063   Fprovide (intern_c_string ("x-toolkit"), Qnil);
8064   Fprovide (intern_c_string ("gtk"), Qnil);
8065   Fprovide (intern_c_string ("move-toolbar"), Qnil);
8066 
8067   DEFVAR_LISP ("gtk-version-string", Vgtk_version_string,
8068                doc: /* Version info for GTK+.  */);
8069   {
8070     char gtk_version[sizeof ".." + 3 * INT_STRLEN_BOUND (int)];
8071     int len = sprintf (gtk_version, "%d.%d.%d",
8072 		       GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION);
8073     Vgtk_version_string = make_pure_string (gtk_version, len, len, false);
8074   }
8075 #endif /* USE_GTK */
8076 
8077 #ifdef USE_CAIRO
8078   Fprovide (intern_c_string ("cairo"), Qnil);
8079 
8080   DEFVAR_LISP ("cairo-version-string", Vcairo_version_string,
8081                doc: /* Version info for cairo.  */);
8082   {
8083     char cairo_version[sizeof ".." + 3 * INT_STRLEN_BOUND (int)];
8084     int len = sprintf (cairo_version, "%d.%d.%d",
8085 		       CAIRO_VERSION_MAJOR, CAIRO_VERSION_MINOR,
8086                        CAIRO_VERSION_MICRO);
8087     Vcairo_version_string = make_pure_string (cairo_version, len, len, false);
8088   }
8089 #endif
8090 
8091   /* X window properties.  */
8092   defsubr (&Sx_change_window_property);
8093   defsubr (&Sx_delete_window_property);
8094   defsubr (&Sx_window_property);
8095   defsubr (&Sx_window_property_attributes);
8096 
8097   defsubr (&Sxw_display_color_p);
8098   defsubr (&Sx_display_grayscale_p);
8099   defsubr (&Sxw_color_defined_p);
8100   defsubr (&Sxw_color_values);
8101   defsubr (&Sx_server_max_request_size);
8102   defsubr (&Sx_server_vendor);
8103   defsubr (&Sx_server_version);
8104   defsubr (&Sx_display_pixel_width);
8105   defsubr (&Sx_display_pixel_height);
8106   defsubr (&Sx_display_mm_width);
8107   defsubr (&Sx_display_mm_height);
8108   defsubr (&Sx_display_screens);
8109   defsubr (&Sx_display_planes);
8110   defsubr (&Sx_display_color_cells);
8111   defsubr (&Sx_display_visual_class);
8112   defsubr (&Sx_display_backing_store);
8113   defsubr (&Sx_display_save_under);
8114   defsubr (&Sx_display_monitor_attributes_list);
8115   defsubr (&Sx_frame_geometry);
8116   defsubr (&Sx_frame_edges);
8117   defsubr (&Sx_frame_list_z_order);
8118   defsubr (&Sx_frame_restack);
8119   defsubr (&Sx_mouse_absolute_pixel_position);
8120   defsubr (&Sx_set_mouse_absolute_pixel_position);
8121   defsubr (&Sx_wm_set_size_hint);
8122   defsubr (&Sx_create_frame);
8123   defsubr (&Sx_open_connection);
8124   defsubr (&Sx_close_connection);
8125   defsubr (&Sx_display_list);
8126   defsubr (&Sx_synchronize);
8127   defsubr (&Sx_backspace_delete_keys_p);
8128   defsubr (&Sx_show_tip);
8129   defsubr (&Sx_hide_tip);
8130   defsubr (&Sx_double_buffered_p);
8131   tip_timer = Qnil;
8132   staticpro (&tip_timer);
8133   tip_frame = Qnil;
8134   staticpro (&tip_frame);
8135   tip_last_frame = Qnil;
8136   staticpro (&tip_last_frame);
8137   tip_last_string = Qnil;
8138   staticpro (&tip_last_string);
8139   tip_last_parms = Qnil;
8140   staticpro (&tip_last_parms);
8141 
8142   defsubr (&Sx_uses_old_gtk_dialog);
8143 #if defined (USE_MOTIF) || defined (USE_GTK)
8144   defsubr (&Sx_file_dialog);
8145 #endif
8146 
8147 #if defined (USE_GTK) && defined (HAVE_FREETYPE)
8148   defsubr (&Sx_select_font);
8149 #endif
8150 
8151 #ifdef USE_CAIRO
8152   defsubr (&Sx_export_frames);
8153 #ifdef USE_GTK
8154   defsubr (&Sx_page_setup_dialog);
8155   defsubr (&Sx_get_page_setup);
8156   defsubr (&Sx_print_frames_dialog);
8157 #endif
8158 #endif
8159 #ifdef USE_GTK
8160 #ifdef HAVE_GTK3
8161 #if GTK_CHECK_VERSION (3, 14, 0)
8162   defsubr (&Sx_gtk_debug);
8163 #endif
8164 #endif
8165 #endif
8166 }
8167