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