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 *) ×tamp, 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