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