Unbreak macOS build
[emacs.git] / src / xfns.c
blob97aa923da05619e3ab1c4f9c6b67d110de3453f8
1 /* Functions for the X window system.
3 Copyright (C) 1989, 1992-2017 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 HAVE_XDBE
57 #include <X11/extensions/Xdbe.h>
58 #endif
60 #ifdef USE_X_TOOLKIT
61 #include <X11/Shell.h>
63 #ifndef USE_MOTIF
64 #ifdef HAVE_XAW3D
65 #include <X11/Xaw3d/Paned.h>
66 #include <X11/Xaw3d/Label.h>
67 #else /* !HAVE_XAW3D */
68 #include <X11/Xaw/Paned.h>
69 #include <X11/Xaw/Label.h>
70 #endif /* HAVE_XAW3D */
71 #endif /* USE_MOTIF */
73 #ifdef USG
74 #undef USG /* ####KLUDGE for Solaris 2.2 and up */
75 #include <X11/Xos.h>
76 #define USG
77 #ifdef USG /* Pacify gcc -Wunused-macros. */
78 #endif
79 #else
80 #include <X11/Xos.h>
81 #endif
83 #include "widget.h"
85 #include "../lwlib/lwlib.h"
87 #ifdef USE_MOTIF
88 #include <Xm/Xm.h>
89 #include <Xm/DialogS.h>
90 #include <Xm/FileSB.h>
91 #include <Xm/List.h>
92 #include <Xm/TextF.h>
93 #endif
95 #ifdef USE_LUCID
96 #include "../lwlib/xlwmenu.h"
97 #endif
99 /* Unique id counter for widgets created by the Lucid Widget Library. */
101 extern LWLIB_ID widget_id_tick;
103 #ifdef USE_MOTIF
105 #endif /* USE_MOTIF */
107 #endif /* USE_X_TOOLKIT */
109 #ifdef USE_GTK
111 #endif /* USE_GTK */
113 #define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
115 static ptrdiff_t image_cache_refcount;
116 #ifdef GLYPH_DEBUG
117 static int dpyinfo_refcount;
118 #endif
120 static struct x_display_info *x_display_info_for_name (Lisp_Object);
121 static void set_up_x_back_buffer (struct frame *f);
123 /* Let the user specify an X display with a Lisp object.
124 OBJECT may be nil, a frame or a terminal object.
125 nil stands for the selected frame--or, if that is not an X frame,
126 the first X display on the list. */
128 struct x_display_info *
129 check_x_display_info (Lisp_Object object)
131 struct x_display_info *dpyinfo = NULL;
133 if (NILP (object))
135 struct frame *sf = XFRAME (selected_frame);
137 if (FRAME_X_P (sf) && FRAME_LIVE_P (sf))
138 dpyinfo = FRAME_DISPLAY_INFO (sf);
139 else if (x_display_list != 0)
140 dpyinfo = x_display_list;
141 else
142 error ("X windows are not in use or not initialized");
144 else if (TERMINALP (object))
146 struct terminal *t = decode_live_terminal (object);
148 if (t->type != output_x_window)
149 error ("Terminal %d is not an X display", t->id);
151 dpyinfo = t->display_info.x;
153 else if (STRINGP (object))
154 dpyinfo = x_display_info_for_name (object);
155 else
157 struct frame *f = decode_window_system_frame (object);
158 dpyinfo = FRAME_DISPLAY_INFO (f);
161 return dpyinfo;
164 /* Return the screen positions and offsets of frame F.
165 Store the offsets between FRAME_OUTER_WINDOW and the containing
166 window manager window into LEFT_OFFSET_X, RIGHT_OFFSET_X,
167 TOP_OFFSET_Y and BOTTOM_OFFSET_Y.
168 Store the offsets between FRAME_X_WINDOW and the containing
169 window manager window into X_PIXELS_DIFF and Y_PIXELS_DIFF.
170 Store the screen positions of frame F into XPTR and YPTR.
171 These are the positions of the containing window manager window,
172 not Emacs's own window. */
173 void
174 x_real_pos_and_offsets (struct frame *f,
175 int *left_offset_x,
176 int *right_offset_x,
177 int *top_offset_y,
178 int *bottom_offset_y,
179 int *x_pixels_diff,
180 int *y_pixels_diff,
181 int *xptr,
182 int *yptr,
183 int *outer_border)
185 int win_x = 0, win_y = 0, outer_x = 0, outer_y = 0;
186 int real_x = 0, real_y = 0;
187 bool had_errors = false;
188 Window win = f->output_data.x->parent_desc;
189 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
190 long max_len = 400;
191 Atom target_type = XA_CARDINAL;
192 unsigned int ow = 0, oh = 0;
193 unsigned int fw = 0, fh = 0;
194 unsigned int bw = 0;
195 /* We resort to XCB if possible because there are several X calls
196 here which require responses from the server but do not have data
197 dependencies between them. Using XCB lets us pipeline requests,
198 whereas with Xlib we must wait for each answer before sending the
199 next request.
201 For a non-local display, the round-trip time could be a few tens
202 of milliseconds, depending on the network distance. It doesn't
203 take a lot of those to add up to a noticeable hesitation in
204 responding to user actions. */
205 #ifdef USE_XCB
206 xcb_connection_t *xcb_conn = dpyinfo->xcb_connection;
207 xcb_get_property_cookie_t prop_cookie;
208 xcb_get_geometry_cookie_t outer_geom_cookie;
209 bool sent_requests = false;
210 #else
211 Atom actual_type;
212 unsigned long actual_size, bytes_remaining;
213 int rc, actual_format;
214 Display *dpy = FRAME_X_DISPLAY (f);
215 unsigned char *tmp_data = NULL;
216 #endif
218 if (x_pixels_diff) *x_pixels_diff = 0;
219 if (y_pixels_diff) *y_pixels_diff = 0;
220 if (left_offset_x) *left_offset_x = 0;
221 if (top_offset_y) *top_offset_y = 0;
222 if (right_offset_x) *right_offset_x = 0;
223 if (bottom_offset_y) *bottom_offset_y = 0;
224 if (xptr) *xptr = 0;
225 if (yptr) *yptr = 0;
226 if (outer_border) *outer_border = 0;
228 if (win == dpyinfo->root_window)
229 win = FRAME_OUTER_WINDOW (f);
231 block_input ();
233 #ifndef USE_XCB
234 /* If we're using XCB, all errors are checked for on each call. */
235 x_catch_errors (dpy);
236 #endif
238 /* This loop traverses up the containment tree until we hit the root
239 window. Window managers may intersect many windows between our window
240 and the root window. The window we find just before the root window
241 should be the outer WM window. */
242 for (;;)
244 Window wm_window, rootw;
246 #ifdef USE_XCB
247 xcb_query_tree_cookie_t query_tree_cookie;
248 xcb_query_tree_reply_t *query_tree;
250 query_tree_cookie = xcb_query_tree (xcb_conn, win);
251 query_tree = xcb_query_tree_reply (xcb_conn, query_tree_cookie, NULL);
252 if (query_tree == NULL)
253 had_errors = true;
254 else
256 wm_window = query_tree->parent;
257 rootw = query_tree->root;
258 free (query_tree);
260 #else
261 Window *tmp_children;
262 unsigned int tmp_nchildren;
263 int success;
265 success = XQueryTree (dpy, win, &rootw,
266 &wm_window, &tmp_children, &tmp_nchildren);
268 had_errors = x_had_errors_p (dpy);
270 /* Don't free tmp_children if XQueryTree failed. */
271 if (! success)
272 break;
274 XFree (tmp_children);
275 #endif
277 if (had_errors || wm_window == rootw)
278 break;
280 win = wm_window;
283 if (! had_errors)
285 #ifdef USE_XCB
286 xcb_get_geometry_cookie_t geom_cookie;
287 xcb_translate_coordinates_cookie_t trans_cookie;
288 xcb_translate_coordinates_cookie_t outer_trans_cookie;
290 xcb_translate_coordinates_reply_t *trans;
291 xcb_get_geometry_reply_t *geom;
292 #else
293 Window child, rootw;
294 unsigned int ign;
295 #endif
297 #ifdef USE_XCB
298 /* Fire off the requests that don't have data dependencies.
300 Once we've done this, we must collect the results for each
301 one before returning, even if other errors are detected,
302 making the other responses moot. */
303 geom_cookie = xcb_get_geometry (xcb_conn, win);
305 trans_cookie =
306 xcb_translate_coordinates (xcb_conn,
307 /* From-window, to-window. */
308 FRAME_DISPLAY_INFO (f)->root_window,
309 FRAME_X_WINDOW (f),
311 /* From-position. */
312 0, 0);
313 if (FRAME_X_WINDOW (f) != FRAME_OUTER_WINDOW (f))
314 outer_trans_cookie =
315 xcb_translate_coordinates (xcb_conn,
316 /* From-window, to-window. */
317 FRAME_DISPLAY_INFO (f)->root_window,
318 FRAME_OUTER_WINDOW (f),
320 /* From-position. */
321 0, 0);
322 if (right_offset_x || bottom_offset_y)
323 outer_geom_cookie = xcb_get_geometry (xcb_conn,
324 FRAME_OUTER_WINDOW (f));
326 if (dpyinfo->root_window == f->output_data.x->parent_desc)
327 /* Try _NET_FRAME_EXTENTS if our parent is the root window. */
328 prop_cookie = xcb_get_property (xcb_conn, 0, win,
329 dpyinfo->Xatom_net_frame_extents,
330 target_type, 0, max_len);
332 sent_requests = true;
333 #endif
335 /* Get the real coordinates for the WM window upper left corner */
336 #ifdef USE_XCB
337 geom = xcb_get_geometry_reply (xcb_conn, geom_cookie, NULL);
338 if (geom)
340 real_x = geom->x;
341 real_y = geom->y;
342 ow = geom->width;
343 oh = geom->height;
344 bw = geom->border_width;
345 free (geom);
347 else
348 had_errors = true;
349 #else
350 XGetGeometry (dpy, win,
351 &rootw, &real_x, &real_y, &ow, &oh, &bw, &ign);
352 #endif
354 /* Translate real coordinates to coordinates relative to our
355 window. For our window, the upper left corner is 0, 0.
356 Since the upper left corner of the WM window is outside
357 our window, win_x and win_y will be negative:
359 ------------------ ---> x
360 | title |
361 | ----------------- v y
362 | | our window
364 Since we don't care about the child window corresponding to
365 the actual coordinates, we can send zero to get the offsets
366 and compute the resulting coordinates below. This reduces
367 the data dependencies between calls and lets us pipeline the
368 requests better in the XCB case. */
369 #ifdef USE_XCB
370 trans = xcb_translate_coordinates_reply (xcb_conn, trans_cookie, NULL);
371 if (trans)
373 win_x = trans->dst_x;
374 win_y = trans->dst_y;
375 free (trans);
377 else
378 had_errors = true;
379 #else
380 XTranslateCoordinates (dpy,
382 /* From-window, to-window. */
383 FRAME_DISPLAY_INFO (f)->root_window,
384 FRAME_X_WINDOW (f),
386 /* From-position, to-position. */
387 0, 0, &win_x, &win_y,
389 /* Child of win. */
390 &child);
391 #endif
393 win_x += real_x;
394 win_y += real_y;
396 if (FRAME_X_WINDOW (f) == FRAME_OUTER_WINDOW (f))
398 outer_x = win_x;
399 outer_y = win_y;
401 else
403 #ifdef USE_XCB
404 xcb_translate_coordinates_reply_t *outer_trans;
406 outer_trans = xcb_translate_coordinates_reply (xcb_conn,
407 outer_trans_cookie,
408 NULL);
409 if (outer_trans)
411 outer_x = outer_trans->dst_x;
412 outer_y = outer_trans->dst_y;
413 free (outer_trans);
415 else
416 had_errors = true;
417 #else
418 XTranslateCoordinates (dpy,
420 /* From-window, to-window. */
421 FRAME_DISPLAY_INFO (f)->root_window,
422 FRAME_OUTER_WINDOW (f),
424 /* From-position, to-position. */
425 0, 0, &outer_x, &outer_y,
427 /* Child of win. */
428 &child);
429 #endif
431 outer_x += real_x;
432 outer_y += real_y;
435 #ifndef USE_XCB
436 had_errors = x_had_errors_p (dpy);
437 #endif
440 if (dpyinfo->root_window == f->output_data.x->parent_desc)
442 /* Try _NET_FRAME_EXTENTS if our parent is the root window. */
443 #ifdef USE_XCB
444 /* Make sure we didn't get an X error early and skip sending the
445 request. */
446 if (sent_requests)
448 xcb_get_property_reply_t *prop;
450 prop = xcb_get_property_reply (xcb_conn, prop_cookie, NULL);
451 if (prop)
453 if (prop->type == target_type
454 && prop->format == 32
455 && (xcb_get_property_value_length (prop)
456 == 4 * sizeof (int32_t)))
458 int32_t *fe = xcb_get_property_value (prop);
460 outer_x = -fe[0];
461 outer_y = -fe[2];
462 real_x -= fe[0];
463 real_y -= fe[2];
465 free (prop);
467 /* Xlib version doesn't set had_errors here. Intentional or bug? */
469 #else
470 rc = XGetWindowProperty (dpy, win, dpyinfo->Xatom_net_frame_extents,
471 0, max_len, False, target_type,
472 &actual_type, &actual_format, &actual_size,
473 &bytes_remaining, &tmp_data);
475 if (rc == Success && actual_type == target_type && !x_had_errors_p (dpy)
476 && actual_size == 4 && actual_format == 32)
478 long *fe = (long *)tmp_data;
480 outer_x = -fe[0];
481 outer_y = -fe[2];
482 real_x -= fe[0];
483 real_y -= fe[2];
486 if (tmp_data) XFree (tmp_data);
487 #endif
490 if (right_offset_x || bottom_offset_y)
492 #ifdef USE_XCB
493 /* Make sure we didn't get an X error early and skip sending the
494 request. */
495 if (sent_requests)
497 xcb_get_geometry_reply_t *outer_geom;
499 outer_geom = xcb_get_geometry_reply (xcb_conn, outer_geom_cookie,
500 NULL);
501 if (outer_geom)
503 fw = outer_geom->width;
504 fh = outer_geom->height;
505 free (outer_geom);
507 else
508 had_errors = true;
510 #else
511 int xy_ign;
512 unsigned int ign;
513 Window rootw;
515 XGetGeometry (dpy, FRAME_OUTER_WINDOW (f),
516 &rootw, &xy_ign, &xy_ign, &fw, &fh, &ign, &ign);
517 #endif
520 #ifndef USE_XCB
521 x_uncatch_errors ();
522 #endif
524 unblock_input ();
526 if (had_errors) return;
528 if (x_pixels_diff) *x_pixels_diff = -win_x;
529 if (y_pixels_diff) *y_pixels_diff = -win_y;
531 if (left_offset_x) *left_offset_x = -outer_x;
532 if (top_offset_y) *top_offset_y = -outer_y;
534 if (xptr) *xptr = real_x;
535 if (yptr) *yptr = real_y;
537 if (outer_border) *outer_border = bw;
539 if (right_offset_x) *right_offset_x = ow - fw + outer_x;
540 if (bottom_offset_y) *bottom_offset_y = oh - fh + outer_y;
543 /* Store the screen positions of frame F into XPTR and YPTR.
544 These are the positions of the containing window manager window,
545 not Emacs's own window. */
547 void
548 x_real_positions (struct frame *f, int *xptr, int *yptr)
550 x_real_pos_and_offsets (f, NULL, NULL, NULL, NULL, NULL, NULL, xptr, yptr,
551 NULL);
555 /* Get the mouse position in frame relative coordinates. */
557 void
558 x_relative_mouse_position (struct frame *f, int *x, int *y)
560 Window root, dummy_window;
561 int dummy;
563 eassert (FRAME_X_P (f));
565 block_input ();
567 XQueryPointer (FRAME_X_DISPLAY (f),
568 DefaultRootWindow (FRAME_X_DISPLAY (f)),
570 /* The root window which contains the pointer. */
571 &root,
573 /* Window pointer is on, not used */
574 &dummy_window,
576 /* The position on that root window. */
577 x, y,
579 /* x/y in dummy_window coordinates, not used. */
580 &dummy, &dummy,
582 /* Modifier keys and pointer buttons, about which
583 we don't care. */
584 (unsigned int *) &dummy);
586 XTranslateCoordinates (FRAME_X_DISPLAY (f),
588 /* From-window, to-window. */
589 FRAME_DISPLAY_INFO (f)->root_window,
590 FRAME_X_WINDOW (f),
592 /* From-position, to-position. */
593 *x, *y, x, y,
595 /* Child of win. */
596 &dummy_window);
598 unblock_input ();
601 /* Gamma-correct COLOR on frame F. */
603 void
604 gamma_correct (struct frame *f, XColor *color)
606 if (f->gamma)
608 color->red = pow (color->red / 65535.0, f->gamma) * 65535.0 + 0.5;
609 color->green = pow (color->green / 65535.0, f->gamma) * 65535.0 + 0.5;
610 color->blue = pow (color->blue / 65535.0, f->gamma) * 65535.0 + 0.5;
615 /* Decide if color named COLOR_NAME is valid for use on frame F. If
616 so, return the RGB values in COLOR. If ALLOC_P,
617 allocate the color. Value is false if COLOR_NAME is invalid, or
618 no color could be allocated. */
620 bool
621 x_defined_color (struct frame *f, const char *color_name,
622 XColor *color, bool alloc_p)
624 bool success_p = false;
625 Colormap cmap = FRAME_X_COLORMAP (f);
627 block_input ();
628 #ifdef USE_GTK
629 success_p = xg_check_special_colors (f, color_name, color);
630 #endif
631 if (!success_p)
632 success_p = x_parse_color (f, color_name, color) != 0;
633 if (success_p && alloc_p)
634 success_p = x_alloc_nearest_color (f, cmap, color);
635 unblock_input ();
637 return success_p;
641 /* Return the pixel color value for color COLOR_NAME on frame F. If F
642 is a monochrome frame, return MONO_COLOR regardless of what ARG says.
643 Signal an error if color can't be allocated. */
645 static int
646 x_decode_color (struct frame *f, Lisp_Object color_name, int mono_color)
648 XColor cdef;
650 CHECK_STRING (color_name);
652 #if false /* Don't do this. It's wrong when we're not using the default
653 colormap, it makes freeing difficult, and it's probably not
654 an important optimization. */
655 if (strcmp (SDATA (color_name), "black") == 0)
656 return BLACK_PIX_DEFAULT (f);
657 else if (strcmp (SDATA (color_name), "white") == 0)
658 return WHITE_PIX_DEFAULT (f);
659 #endif
661 /* Return MONO_COLOR for monochrome frames. */
662 if (FRAME_DISPLAY_INFO (f)->n_planes == 1)
663 return mono_color;
665 /* x_defined_color is responsible for coping with failures
666 by looking for a near-miss. */
667 if (x_defined_color (f, SSDATA (color_name), &cdef, true))
668 return cdef.pixel;
670 signal_error ("Undefined color", color_name);
675 /* Change the `wait-for-wm' frame parameter of frame F. OLD_VALUE is
676 the previous value of that parameter, NEW_VALUE is the new value.
677 See also the comment of wait_for_wm in struct x_output. */
679 static void
680 x_set_wait_for_wm (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
682 f->output_data.x->wait_for_wm = !NILP (new_value);
685 static void
686 x_set_tool_bar_position (struct frame *f,
687 Lisp_Object new_value,
688 Lisp_Object old_value)
690 Lisp_Object choice = list4 (Qleft, Qright, Qtop, Qbottom);
692 if (!NILP (Fmemq (new_value, choice)))
694 #ifdef USE_GTK
695 if (!EQ (new_value, old_value))
697 xg_change_toolbar_position (f, new_value);
698 fset_tool_bar_position (f, new_value);
700 #else
701 if (!EQ (new_value, Qtop))
702 error ("The only supported tool bar position is top");
703 #endif
705 else
706 wrong_choice (choice, new_value);
709 static void
710 x_set_inhibit_double_buffering (struct frame *f,
711 Lisp_Object new_value,
712 Lisp_Object old_value)
714 block_input ();
715 if (FRAME_X_WINDOW (f) && !EQ (new_value, old_value))
717 bool want_double_buffering = NILP (new_value);
718 bool was_double_buffered = FRAME_X_DOUBLE_BUFFERED_P (f);
719 /* font_drop_xrender_surfaces in xftfont does something only if
720 we're double-buffered, so call font_drop_xrender_surfaces before
721 and after any potential change. One of the calls will end up
722 being a no-op. */
723 if (want_double_buffering != was_double_buffered)
724 font_drop_xrender_surfaces (f);
725 if (FRAME_X_DOUBLE_BUFFERED_P (f) && !want_double_buffering)
726 tear_down_x_back_buffer (f);
727 else if (!FRAME_X_DOUBLE_BUFFERED_P (f) && want_double_buffering)
728 set_up_x_back_buffer (f);
729 if (FRAME_X_DOUBLE_BUFFERED_P (f) != was_double_buffered)
731 SET_FRAME_GARBAGED (f);
732 font_drop_xrender_surfaces (f);
735 unblock_input ();
738 #ifdef USE_GTK
740 /* Set icon from FILE for frame F. By using GTK functions the icon
741 may be any format that GdkPixbuf knows about, i.e. not just bitmaps. */
743 bool
744 xg_set_icon (struct frame *f, Lisp_Object file)
746 bool result = false;
747 Lisp_Object found;
749 found = x_find_image_file (file);
751 if (! NILP (found))
753 GdkPixbuf *pixbuf;
754 GError *err = NULL;
755 char *filename = SSDATA (ENCODE_FILE (found));
756 block_input ();
758 pixbuf = gdk_pixbuf_new_from_file (filename, &err);
760 if (pixbuf)
762 gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
763 pixbuf);
764 g_object_unref (pixbuf);
766 result = true;
768 else
769 g_error_free (err);
771 unblock_input ();
774 return result;
777 bool
778 xg_set_icon_from_xpm_data (struct frame *f, const char **data)
780 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data (data);
782 if (!pixbuf)
783 return false;
785 gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), pixbuf);
786 g_object_unref (pixbuf);
787 return true;
789 #endif /* USE_GTK */
792 /* Functions called only from `x_set_frame_param'
793 to set individual parameters.
795 If FRAME_X_WINDOW (f) is 0,
796 the frame is being created and its X-window does not exist yet.
797 In that case, just record the parameter's new value
798 in the standard place; do not attempt to change the window. */
800 static void
801 x_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
803 struct x_output *x = f->output_data.x;
804 unsigned long fg, old_fg;
806 fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
807 old_fg = FRAME_FOREGROUND_PIXEL (f);
808 FRAME_FOREGROUND_PIXEL (f) = fg;
810 if (FRAME_X_WINDOW (f) != 0)
812 Display *dpy = FRAME_X_DISPLAY (f);
814 block_input ();
815 XSetForeground (dpy, x->normal_gc, fg);
816 XSetBackground (dpy, x->reverse_gc, fg);
818 if (x->cursor_pixel == old_fg)
820 unload_color (f, x->cursor_pixel);
821 x->cursor_pixel = x_copy_color (f, fg);
822 XSetBackground (dpy, x->cursor_gc, x->cursor_pixel);
825 unblock_input ();
827 update_face_from_frame_parameter (f, Qforeground_color, arg);
829 if (FRAME_VISIBLE_P (f))
830 redraw_frame (f);
833 unload_color (f, old_fg);
836 static void
837 x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
839 struct x_output *x = f->output_data.x;
840 unsigned long bg;
842 bg = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
843 unload_color (f, FRAME_BACKGROUND_PIXEL (f));
844 FRAME_BACKGROUND_PIXEL (f) = bg;
846 if (FRAME_X_WINDOW (f) != 0)
848 Display *dpy = FRAME_X_DISPLAY (f);
850 block_input ();
851 XSetBackground (dpy, x->normal_gc, bg);
852 XSetForeground (dpy, x->reverse_gc, bg);
853 XSetWindowBackground (dpy, FRAME_X_WINDOW (f), bg);
854 XSetForeground (dpy, x->cursor_gc, bg);
856 #ifdef USE_GTK
857 xg_set_background_color (f, bg);
858 #endif
860 #ifndef USE_TOOLKIT_SCROLL_BARS /* Turns out to be annoying with
861 toolkit scroll bars. */
863 Lisp_Object bar;
864 for (bar = FRAME_SCROLL_BARS (f);
865 !NILP (bar);
866 bar = XSCROLL_BAR (bar)->next)
868 Window window = XSCROLL_BAR (bar)->x_window;
869 XSetWindowBackground (dpy, window, bg);
872 #endif /* USE_TOOLKIT_SCROLL_BARS */
874 unblock_input ();
875 update_face_from_frame_parameter (f, Qbackground_color, arg);
877 if (FRAME_VISIBLE_P (f))
878 redraw_frame (f);
882 /* This array must stay in sync with the mouse_cursor_types array below! */
883 enum mouse_cursor {
884 mouse_cursor_text,
885 mouse_cursor_nontext,
886 mouse_cursor_hourglass,
887 mouse_cursor_mode,
888 mouse_cursor_hand,
889 mouse_cursor_horizontal_drag,
890 mouse_cursor_vertical_drag,
891 mouse_cursor_max
894 struct mouse_cursor_types {
895 /* Printable name for error messages (optional). */
896 const char *name;
898 /* Lisp variable controlling the cursor shape. */
899 /* FIXME: A couple of these variables are defined in the C code but
900 are not actually accessible from Lisp. They should probably be
901 made accessible or removed. */
902 Lisp_Object *shape_var_ptr;
904 /* The default shape. */
905 int default_shape;
908 /* This array must stay in sync with enum mouse_cursor above! */
909 static const struct mouse_cursor_types mouse_cursor_types[] = {
910 { "text", &Vx_pointer_shape, XC_xterm },
911 { "nontext", &Vx_nontext_pointer_shape, XC_left_ptr },
912 { "hourglass", &Vx_hourglass_pointer_shape, XC_watch },
913 { "modeline", &Vx_mode_pointer_shape, XC_xterm },
914 { NULL, &Vx_sensitive_text_pointer_shape, XC_hand2 },
915 { NULL, &Vx_window_horizontal_drag_shape, XC_sb_h_double_arrow },
916 { NULL, &Vx_window_vertical_drag_shape, XC_sb_v_double_arrow },
919 struct mouse_cursor_data {
920 /* Last index for which XCreateFontCursor has been called, and thus
921 the last index for which x_request_serial[] is valid. */
922 int last_cursor_create_request;
924 /* Last index for which an X error event was received in response to
925 attempting to create the cursor. */
926 int error_cursor;
928 /* Cursor numbers chosen. */
929 unsigned int cursor_num[mouse_cursor_max];
931 /* Allocated Cursor values, or zero for failed attempts. */
932 Cursor cursor[mouse_cursor_max];
934 /* X serial numbers for the first request sent by XCreateFontCursor.
935 Note that there may be more than one request sent. */
936 unsigned long x_request_serial[mouse_cursor_max];
938 /* If an error has been received, a pointer to where the current
939 error-message text is stored. */
940 char *error_string;
943 static void
944 x_set_mouse_color_handler (Display *dpy, XErrorEvent *event,
945 char *error_string, void *data)
947 struct mouse_cursor_data *cursor_data = data;
948 int i;
950 cursor_data->error_cursor = -1;
951 cursor_data->error_string = error_string;
952 for (i = 0; i < cursor_data->last_cursor_create_request; i++)
954 if (event->serial >= cursor_data->x_request_serial[i])
955 cursor_data->error_cursor = i;
957 if (cursor_data->error_cursor >= 0)
958 /* If we failed to allocate it, don't try to free it. */
959 cursor_data->cursor[cursor_data->error_cursor] = 0;
962 static void
963 x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
965 struct x_output *x = f->output_data.x;
966 Display *dpy = FRAME_X_DISPLAY (f);
967 struct mouse_cursor_data cursor_data = { -1, -1 };
968 unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
969 unsigned long mask_color = FRAME_BACKGROUND_PIXEL (f);
970 int i;
972 /* Don't let pointers be invisible. */
973 if (mask_color == pixel)
975 x_free_colors (f, &pixel, 1);
976 pixel = x_copy_color (f, FRAME_FOREGROUND_PIXEL (f));
979 unload_color (f, x->mouse_pixel);
980 x->mouse_pixel = pixel;
982 for (i = 0; i < mouse_cursor_max; i++)
984 Lisp_Object shape_var = *mouse_cursor_types[i].shape_var_ptr;
985 if (!NILP (shape_var))
987 CHECK_TYPE_RANGED_INTEGER (unsigned, shape_var);
988 cursor_data.cursor_num[i] = XINT (shape_var);
990 else
991 cursor_data.cursor_num[i] = mouse_cursor_types[i].default_shape;
994 block_input ();
996 /* It's not okay to crash if the user selects a screwy cursor. */
997 x_catch_errors_with_handler (dpy, x_set_mouse_color_handler, &cursor_data);
999 for (i = 0; i < mouse_cursor_max; i++)
1001 cursor_data.x_request_serial[i] = XNextRequest (dpy);
1002 cursor_data.last_cursor_create_request = i;
1003 cursor_data.cursor[i] = XCreateFontCursor (dpy,
1004 cursor_data.cursor_num[i]);
1007 /* Now sync up and process all received errors from cursor
1008 creation. */
1009 if (x_had_errors_p (dpy))
1011 const char *bad_cursor_name = NULL;
1012 /* Bounded by X_ERROR_MESSAGE_SIZE in xterm.c. */
1013 size_t message_length = strlen (cursor_data.error_string);
1014 char *xmessage = alloca (1 + message_length);
1015 memcpy (xmessage, cursor_data.error_string, message_length);
1017 x_uncatch_errors ();
1019 /* Free any successfully created cursors. */
1020 for (i = 0; i < mouse_cursor_max; i++)
1021 if (cursor_data.cursor[i] != 0)
1022 XFreeCursor (dpy, cursor_data.cursor[i]);
1024 /* This should only be able to fail if the server's serial
1025 number tracking is broken. */
1026 if (cursor_data.error_cursor >= 0)
1027 bad_cursor_name = mouse_cursor_types[cursor_data.error_cursor].name;
1028 if (bad_cursor_name)
1029 error ("bad %s pointer cursor: %s", bad_cursor_name, xmessage);
1030 else
1031 error ("can't set cursor shape: %s", xmessage);
1034 x_uncatch_errors_after_check ();
1037 XColor colors[2]; /* 0=foreground, 1=background */
1039 colors[0].pixel = x->mouse_pixel;
1040 colors[1].pixel = mask_color;
1041 x_query_colors (f, colors, 2);
1043 for (i = 0; i < mouse_cursor_max; i++)
1044 XRecolorCursor (dpy, cursor_data.cursor[i], &colors[0], &colors[1]);
1047 if (FRAME_X_WINDOW (f) != 0)
1049 f->output_data.x->current_cursor = cursor_data.cursor[mouse_cursor_text];
1050 XDefineCursor (dpy, FRAME_X_WINDOW (f),
1051 f->output_data.x->current_cursor);
1054 #define INSTALL_CURSOR(FIELD, SHORT_INDEX) \
1055 eassert (x->FIELD != cursor_data.cursor[mouse_cursor_ ## SHORT_INDEX]); \
1056 if (x->FIELD != 0) \
1057 XFreeCursor (dpy, x->FIELD); \
1058 x->FIELD = cursor_data.cursor[mouse_cursor_ ## SHORT_INDEX];
1060 INSTALL_CURSOR (text_cursor, text);
1061 INSTALL_CURSOR (nontext_cursor, nontext);
1062 INSTALL_CURSOR (hourglass_cursor, hourglass);
1063 INSTALL_CURSOR (modeline_cursor, mode);
1064 INSTALL_CURSOR (hand_cursor, hand);
1065 INSTALL_CURSOR (horizontal_drag_cursor, horizontal_drag);
1066 INSTALL_CURSOR (vertical_drag_cursor, vertical_drag);
1068 #undef INSTALL_CURSOR
1070 XFlush (dpy);
1071 unblock_input ();
1073 update_face_from_frame_parameter (f, Qmouse_color, arg);
1076 static void
1077 x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1079 unsigned long fore_pixel, pixel;
1080 bool fore_pixel_allocated_p = false, pixel_allocated_p = false;
1081 struct x_output *x = f->output_data.x;
1083 if (!NILP (Vx_cursor_fore_pixel))
1085 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
1086 WHITE_PIX_DEFAULT (f));
1087 fore_pixel_allocated_p = true;
1089 else
1090 fore_pixel = FRAME_BACKGROUND_PIXEL (f);
1092 pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1093 pixel_allocated_p = true;
1095 /* Make sure that the cursor color differs from the background color. */
1096 if (pixel == FRAME_BACKGROUND_PIXEL (f))
1098 if (pixel_allocated_p)
1100 x_free_colors (f, &pixel, 1);
1101 pixel_allocated_p = false;
1104 pixel = x->mouse_pixel;
1105 if (pixel == fore_pixel)
1107 if (fore_pixel_allocated_p)
1109 x_free_colors (f, &fore_pixel, 1);
1110 fore_pixel_allocated_p = false;
1112 fore_pixel = FRAME_BACKGROUND_PIXEL (f);
1116 unload_color (f, x->cursor_foreground_pixel);
1117 if (!fore_pixel_allocated_p)
1118 fore_pixel = x_copy_color (f, fore_pixel);
1119 x->cursor_foreground_pixel = fore_pixel;
1121 unload_color (f, x->cursor_pixel);
1122 if (!pixel_allocated_p)
1123 pixel = x_copy_color (f, pixel);
1124 x->cursor_pixel = pixel;
1126 if (FRAME_X_WINDOW (f) != 0)
1128 block_input ();
1129 XSetBackground (FRAME_X_DISPLAY (f), x->cursor_gc, x->cursor_pixel);
1130 XSetForeground (FRAME_X_DISPLAY (f), x->cursor_gc, fore_pixel);
1131 unblock_input ();
1133 if (FRAME_VISIBLE_P (f))
1135 x_update_cursor (f, false);
1136 x_update_cursor (f, true);
1140 update_face_from_frame_parameter (f, Qcursor_color, arg);
1143 /* Set the border-color of frame F to pixel value PIX.
1144 Note that this does not fully take effect if done before
1145 F has an x-window. */
1147 static void
1148 x_set_border_pixel (struct frame *f, int pix)
1150 unload_color (f, f->output_data.x->border_pixel);
1151 f->output_data.x->border_pixel = pix;
1153 if (FRAME_X_WINDOW (f) != 0 && f->border_width > 0)
1155 block_input ();
1156 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), pix);
1157 unblock_input ();
1159 if (FRAME_VISIBLE_P (f))
1160 redraw_frame (f);
1164 /* Set the border-color of frame F to value described by ARG.
1165 ARG can be a string naming a color.
1166 The border-color is used for the border that is drawn by the X server.
1167 Note that this does not fully take effect if done before
1168 F has an x-window; it must be redone when the window is created.
1170 Note: this is done in two routines because of the way X10 works.
1172 Note: under X11, this is normally the province of the window manager,
1173 and so emacs's border colors may be overridden. */
1175 static void
1176 x_set_border_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1178 int pix;
1180 CHECK_STRING (arg);
1181 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1182 x_set_border_pixel (f, pix);
1183 update_face_from_frame_parameter (f, Qborder_color, arg);
1187 static void
1188 x_set_cursor_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1190 set_frame_cursor_types (f, arg);
1193 static void
1194 x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1196 bool result;
1198 if (STRINGP (arg))
1200 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1201 return;
1203 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1204 return;
1206 block_input ();
1207 if (NILP (arg))
1208 result = x_text_icon (f,
1209 SSDATA ((!NILP (f->icon_name)
1210 ? f->icon_name
1211 : f->name)));
1212 else
1213 result = x_bitmap_icon (f, arg);
1215 if (result)
1217 unblock_input ();
1218 error ("No icon window available");
1221 XFlush (FRAME_X_DISPLAY (f));
1222 unblock_input ();
1225 static void
1226 x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1228 bool result;
1230 if (STRINGP (arg))
1232 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1233 return;
1235 else if (!NILP (arg) || NILP (oldval))
1236 return;
1238 fset_icon_name (f, arg);
1240 if (f->output_data.x->icon_bitmap != 0)
1241 return;
1243 block_input ();
1245 result = x_text_icon (f,
1246 SSDATA ((!NILP (f->icon_name)
1247 ? f->icon_name
1248 : !NILP (f->title)
1249 ? f->title
1250 : f->name)));
1252 if (result)
1254 unblock_input ();
1255 error ("No icon window available");
1258 XFlush (FRAME_X_DISPLAY (f));
1259 unblock_input ();
1263 static void
1264 x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
1266 int nlines;
1267 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
1268 int olines = FRAME_MENU_BAR_LINES (f);
1269 #endif
1271 /* Right now, menu bars don't work properly in minibuf-only frames;
1272 most of the commands try to apply themselves to the minibuffer
1273 frame itself, and get an error because you can't switch buffers
1274 in or split the minibuffer window. */
1275 if (FRAME_MINIBUF_ONLY_P (f))
1276 return;
1278 if (TYPE_RANGED_INTEGERP (int, value))
1279 nlines = XINT (value);
1280 else
1281 nlines = 0;
1283 /* Make sure we redisplay all windows in this frame. */
1284 fset_redisplay (f);
1286 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
1287 FRAME_MENU_BAR_LINES (f) = 0;
1288 FRAME_MENU_BAR_HEIGHT (f) = 0;
1289 if (nlines)
1291 FRAME_EXTERNAL_MENU_BAR (f) = 1;
1292 if (FRAME_X_P (f) && f->output_data.x->menubar_widget == 0)
1293 /* Make sure next redisplay shows the menu bar. */
1294 XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = true;
1296 else
1298 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
1299 free_frame_menubar (f);
1300 FRAME_EXTERNAL_MENU_BAR (f) = 0;
1301 if (FRAME_X_P (f))
1302 f->output_data.x->menubar_widget = 0;
1304 #else /* not USE_X_TOOLKIT && not USE_GTK */
1305 FRAME_MENU_BAR_LINES (f) = nlines;
1306 FRAME_MENU_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f);
1307 adjust_frame_size (f, -1, -1, 2, true, Qx_set_menu_bar_lines);
1308 if (FRAME_X_WINDOW (f))
1309 x_clear_under_internal_border (f);
1311 /* If the menu bar height gets changed, the internal border below
1312 the top margin has to be cleared. Also, if the menu bar gets
1313 larger, the area for the added lines has to be cleared except for
1314 the first menu bar line that is to be drawn later. */
1315 if (nlines != olines)
1317 int height = FRAME_INTERNAL_BORDER_WIDTH (f);
1318 int width = FRAME_PIXEL_WIDTH (f);
1319 int y;
1321 /* height can be zero here. */
1322 if (FRAME_X_WINDOW (f) && height > 0 && width > 0)
1324 y = FRAME_TOP_MARGIN_HEIGHT (f);
1326 block_input ();
1327 x_clear_area (f, 0, y, width, height);
1328 unblock_input ();
1331 if (nlines > 1 && nlines > olines)
1333 y = (olines == 0 ? 1 : olines) * FRAME_LINE_HEIGHT (f);
1334 height = nlines * FRAME_LINE_HEIGHT (f) - y;
1336 block_input ();
1337 x_clear_area (f, 0, y, width, height);
1338 unblock_input ();
1341 if (nlines == 0 && WINDOWP (f->menu_bar_window))
1342 clear_glyph_matrix (XWINDOW (f->menu_bar_window)->current_matrix);
1344 #endif /* not USE_X_TOOLKIT && not USE_GTK */
1345 adjust_frame_glyphs (f);
1349 /* Set the number of lines used for the tool bar of frame F to VALUE.
1350 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
1351 is the old number of tool bar lines. This function changes the
1352 height of all windows on frame F to match the new tool bar height.
1353 The frame's height doesn't change. */
1355 static void
1356 x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
1358 int nlines;
1360 /* Treat tool bars like menu bars. */
1361 if (FRAME_MINIBUF_ONLY_P (f))
1362 return;
1364 /* Use VALUE only if an int >= 0. */
1365 if (RANGED_INTEGERP (0, value, INT_MAX))
1366 nlines = XFASTINT (value);
1367 else
1368 nlines = 0;
1370 x_change_tool_bar_height (f, nlines * FRAME_LINE_HEIGHT (f));
1374 /* Set the pixel height of the tool bar of frame F to HEIGHT. */
1375 void
1376 x_change_tool_bar_height (struct frame *f, int height)
1378 #ifdef USE_GTK
1379 FRAME_TOOL_BAR_LINES (f) = 0;
1380 FRAME_TOOL_BAR_HEIGHT (f) = 0;
1381 if (height)
1383 FRAME_EXTERNAL_TOOL_BAR (f) = true;
1384 if (FRAME_X_P (f) && f->output_data.x->toolbar_widget == 0)
1385 /* Make sure next redisplay shows the tool bar. */
1386 XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = true;
1387 update_frame_tool_bar (f);
1389 else
1391 if (FRAME_EXTERNAL_TOOL_BAR (f))
1392 free_frame_tool_bar (f);
1393 FRAME_EXTERNAL_TOOL_BAR (f) = false;
1395 #else /* !USE_GTK */
1396 int unit = FRAME_LINE_HEIGHT (f);
1397 int old_height = FRAME_TOOL_BAR_HEIGHT (f);
1398 int lines = (height + unit - 1) / unit;
1399 Lisp_Object fullscreen;
1401 /* Make sure we redisplay all windows in this frame. */
1402 fset_redisplay (f);
1404 /* Recalculate tool bar and frame text sizes. */
1405 FRAME_TOOL_BAR_HEIGHT (f) = height;
1406 FRAME_TOOL_BAR_LINES (f) = lines;
1407 /* Store the `tool-bar-lines' and `height' frame parameters. */
1408 store_frame_param (f, Qtool_bar_lines, make_number (lines));
1409 store_frame_param (f, Qheight, make_number (FRAME_LINES (f)));
1411 /* We also have to make sure that the internal border at the top of
1412 the frame, below the menu bar or tool bar, is redrawn when the
1413 tool bar disappears. This is so because the internal border is
1414 below the tool bar if one is displayed, but is below the menu bar
1415 if there isn't a tool bar. The tool bar draws into the area
1416 below the menu bar. */
1417 if (FRAME_X_WINDOW (f) && FRAME_TOOL_BAR_HEIGHT (f) == 0)
1419 clear_frame (f);
1420 clear_current_matrices (f);
1423 if ((height < old_height) && WINDOWP (f->tool_bar_window))
1424 clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
1426 /* Recalculate toolbar height. */
1427 f->n_tool_bar_rows = 0;
1428 if (old_height == 0
1429 && (!f->after_make_frame
1430 || NILP (frame_inhibit_implied_resize)
1431 || (CONSP (frame_inhibit_implied_resize)
1432 && NILP (Fmemq (Qtool_bar_lines, frame_inhibit_implied_resize)))))
1433 f->tool_bar_redisplayed = f->tool_bar_resized = false;
1435 adjust_frame_size (f, -1, -1,
1436 ((!f->tool_bar_resized
1437 && (NILP (fullscreen =
1438 get_frame_param (f, Qfullscreen))
1439 || EQ (fullscreen, Qfullwidth))) ? 1
1440 : (old_height == 0 || height == 0) ? 2
1441 : 4),
1442 false, Qtool_bar_lines);
1444 f->tool_bar_resized = f->tool_bar_redisplayed;
1446 /* adjust_frame_size might not have done anything, garbage frame
1447 here. */
1448 adjust_frame_glyphs (f);
1449 SET_FRAME_GARBAGED (f);
1450 if (FRAME_X_WINDOW (f))
1451 x_clear_under_internal_border (f);
1453 #endif /* USE_GTK */
1457 static void
1458 x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1460 int border;
1462 CHECK_TYPE_RANGED_INTEGER (int, arg);
1463 border = max (XINT (arg), 0);
1465 if (border != FRAME_INTERNAL_BORDER_WIDTH (f))
1467 f->internal_border_width = border;
1469 #ifdef USE_X_TOOLKIT
1470 if (FRAME_X_OUTPUT (f)->edit_widget)
1471 widget_store_internal_border (FRAME_X_OUTPUT (f)->edit_widget);
1472 #endif
1474 if (FRAME_X_WINDOW (f) != 0)
1476 adjust_frame_size (f, -1, -1, 3, false, Qinternal_border_width);
1478 #ifdef USE_GTK
1479 xg_clear_under_internal_border (f);
1480 #else
1481 x_clear_under_internal_border (f);
1482 #endif
1489 /* Set the foreground color for scroll bars on frame F to VALUE.
1490 VALUE should be a string, a color name. If it isn't a string or
1491 isn't a valid color name, do nothing. OLDVAL is the old value of
1492 the frame parameter. */
1494 static void
1495 x_set_scroll_bar_foreground (struct frame *f, Lisp_Object value, Lisp_Object oldval)
1497 unsigned long pixel;
1499 if (STRINGP (value))
1500 pixel = x_decode_color (f, value, BLACK_PIX_DEFAULT (f));
1501 else
1502 pixel = -1;
1504 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
1505 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
1507 f->output_data.x->scroll_bar_foreground_pixel = pixel;
1508 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
1510 /* Remove all scroll bars because they have wrong colors. */
1511 if (FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
1512 (*FRAME_TERMINAL (f)->condemn_scroll_bars_hook) (f);
1513 if (FRAME_TERMINAL (f)->judge_scroll_bars_hook)
1514 (*FRAME_TERMINAL (f)->judge_scroll_bars_hook) (f);
1516 update_face_from_frame_parameter (f, Qscroll_bar_foreground, value);
1517 redraw_frame (f);
1522 /* Set the background color for scroll bars on frame F to VALUE VALUE
1523 should be a string, a color name. If it isn't a string or isn't a
1524 valid color name, do nothing. OLDVAL is the old value of the frame
1525 parameter. */
1527 static void
1528 x_set_scroll_bar_background (struct frame *f, Lisp_Object value, Lisp_Object oldval)
1530 unsigned long pixel;
1532 if (STRINGP (value))
1533 pixel = x_decode_color (f, value, WHITE_PIX_DEFAULT (f));
1534 else
1535 pixel = -1;
1537 if (f->output_data.x->scroll_bar_background_pixel != -1)
1538 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
1540 #if defined (USE_LUCID) && defined (USE_TOOLKIT_SCROLL_BARS)
1541 /* Scrollbar shadow colors. */
1542 if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
1544 unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
1545 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
1547 if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
1549 unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
1550 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
1552 #endif /* USE_LUCID && USE_TOOLKIT_SCROLL_BARS */
1554 f->output_data.x->scroll_bar_background_pixel = pixel;
1555 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
1557 /* Remove all scroll bars because they have wrong colors. */
1558 if (FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
1559 (*FRAME_TERMINAL (f)->condemn_scroll_bars_hook) (f);
1560 if (FRAME_TERMINAL (f)->judge_scroll_bars_hook)
1561 (*FRAME_TERMINAL (f)->judge_scroll_bars_hook) (f);
1563 update_face_from_frame_parameter (f, Qscroll_bar_background, value);
1564 redraw_frame (f);
1569 /* Encode Lisp string STRING as a text in a format appropriate for
1570 XICCC (X Inter Client Communication Conventions).
1572 If STRING contains only ASCII characters, do no conversion and
1573 return the string data of STRING. Otherwise, encode the text by
1574 CODING_SYSTEM, and return a newly allocated memory area which
1575 should be freed by `xfree' by a caller.
1577 Store the byte length of resulting text in *TEXT_BYTES.
1579 If the text contains only ASCII and Latin-1, store true in *STRING_P,
1580 which means that the `encoding' of the result can be `STRING'.
1581 Otherwise store false in *STRINGP, which means that the `encoding' of
1582 the result should be `COMPOUND_TEXT'. */
1584 static unsigned char *
1585 x_encode_text (Lisp_Object string, Lisp_Object coding_system,
1586 ptrdiff_t *text_bytes, bool *stringp, bool *freep)
1588 int result = string_xstring_p (string);
1589 struct coding_system coding;
1591 if (result == 0)
1593 /* No multibyte character in OBJ. We need not encode it. */
1594 *text_bytes = SBYTES (string);
1595 *stringp = true;
1596 *freep = false;
1597 return SDATA (string);
1600 setup_coding_system (coding_system, &coding);
1601 coding.mode |= (CODING_MODE_SAFE_ENCODING | CODING_MODE_LAST_BLOCK);
1602 /* We suppress producing escape sequences for composition. */
1603 coding.common_flags &= ~CODING_ANNOTATION_MASK;
1604 coding.destination = xnmalloc (SCHARS (string), 2);
1605 coding.dst_bytes = SCHARS (string) * 2;
1606 encode_coding_object (&coding, string, 0, 0,
1607 SCHARS (string), SBYTES (string), Qnil);
1608 *text_bytes = coding.produced;
1609 *stringp = (result == 1 || !EQ (coding_system, Qcompound_text));
1610 *freep = true;
1611 return coding.destination;
1615 /* Set the WM name to NAME for frame F. Also set the icon name.
1616 If the frame already has an icon name, use that, otherwise set the
1617 icon name to NAME. */
1619 static void
1620 x_set_name_internal (struct frame *f, Lisp_Object name)
1622 if (FRAME_X_WINDOW (f))
1624 block_input ();
1626 XTextProperty text, icon;
1627 ptrdiff_t bytes;
1628 bool stringp;
1629 bool do_free_icon_value = false, do_free_text_value = false;
1630 Lisp_Object coding_system;
1631 Lisp_Object encoded_name;
1632 Lisp_Object encoded_icon_name;
1634 /* As ENCODE_UTF_8 may cause GC and relocation of string data,
1635 we use it before x_encode_text that may return string data. */
1636 encoded_name = ENCODE_UTF_8 (name);
1638 coding_system = Qcompound_text;
1639 /* Note: Encoding strategy
1641 We encode NAME by compound-text and use "COMPOUND-TEXT" in
1642 text.encoding. But, there are non-internationalized window
1643 managers which don't support that encoding. So, if NAME
1644 contains only ASCII and 8859-1 characters, encode it by
1645 iso-latin-1, and use "STRING" in text.encoding hoping that
1646 such window managers at least analyze this format correctly,
1647 i.e. treat 8-bit bytes as 8859-1 characters.
1649 We may also be able to use "UTF8_STRING" in text.encoding
1650 in the future which can encode all Unicode characters.
1651 But, for the moment, there's no way to know that the
1652 current window manager supports it or not.
1654 Either way, we also set the _NET_WM_NAME and _NET_WM_ICON_NAME
1655 properties. Per the EWMH specification, those two properties
1656 are always UTF8_STRING. This matches what gtk_window_set_title()
1657 does in the USE_GTK case. */
1658 text.value = x_encode_text (name, coding_system, &bytes,
1659 &stringp, &do_free_text_value);
1660 text.encoding = (stringp ? XA_STRING
1661 : FRAME_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
1662 text.format = 8;
1663 text.nitems = bytes;
1665 if (!STRINGP (f->icon_name))
1667 icon = text;
1668 encoded_icon_name = encoded_name;
1670 else
1672 /* See the above comment "Note: Encoding strategy". */
1673 icon.value = x_encode_text (f->icon_name, coding_system, &bytes,
1674 &stringp, &do_free_icon_value);
1675 icon.encoding = (stringp ? XA_STRING
1676 : FRAME_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
1677 icon.format = 8;
1678 icon.nitems = bytes;
1680 encoded_icon_name = ENCODE_UTF_8 (f->icon_name);
1683 #ifdef USE_GTK
1684 gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
1685 SSDATA (encoded_name));
1686 #else /* not USE_GTK */
1687 XSetWMName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text);
1688 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
1689 FRAME_DISPLAY_INFO (f)->Xatom_net_wm_name,
1690 FRAME_DISPLAY_INFO (f)->Xatom_UTF8_STRING,
1691 8, PropModeReplace,
1692 SDATA (encoded_name),
1693 SBYTES (encoded_name));
1694 #endif /* not USE_GTK */
1696 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &icon);
1697 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
1698 FRAME_DISPLAY_INFO (f)->Xatom_net_wm_icon_name,
1699 FRAME_DISPLAY_INFO (f)->Xatom_UTF8_STRING,
1700 8, PropModeReplace,
1701 SDATA (encoded_icon_name),
1702 SBYTES (encoded_icon_name));
1704 if (do_free_icon_value)
1705 xfree (icon.value);
1706 if (do_free_text_value)
1707 xfree (text.value);
1709 unblock_input ();
1713 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
1714 x_id_name.
1716 If EXPLICIT is true, that indicates that lisp code is setting the
1717 name; if NAME is a string, set F's name to NAME and set
1718 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
1720 If EXPLICIT is false, that indicates that Emacs redisplay code is
1721 suggesting a new name, which lisp code should override; if
1722 F->explicit_name is set, ignore the new name; otherwise, set it. */
1724 static void
1725 x_set_name (struct frame *f, Lisp_Object name, bool explicit)
1727 /* Make sure that requests from lisp code override requests from
1728 Emacs redisplay code. */
1729 if (explicit)
1731 /* If we're switching from explicit to implicit, we had better
1732 update the mode lines and thereby update the title. */
1733 if (f->explicit_name && NILP (name))
1734 update_mode_lines = 37;
1736 f->explicit_name = ! NILP (name);
1738 else if (f->explicit_name)
1739 return;
1741 /* If NAME is nil, set the name to the x_id_name. */
1742 if (NILP (name))
1744 /* Check for no change needed in this very common case
1745 before we do any consing. */
1746 if (!strcmp (FRAME_DISPLAY_INFO (f)->x_id_name,
1747 SSDATA (f->name)))
1748 return;
1749 name = build_string (FRAME_DISPLAY_INFO (f)->x_id_name);
1751 else
1752 CHECK_STRING (name);
1754 /* Don't change the name if it's already NAME. */
1755 if (! NILP (Fstring_equal (name, f->name)))
1756 return;
1758 fset_name (f, name);
1760 /* For setting the frame title, the title parameter should override
1761 the name parameter. */
1762 if (! NILP (f->title))
1763 name = f->title;
1765 x_set_name_internal (f, name);
1768 /* This function should be called when the user's lisp code has
1769 specified a name for the frame; the name will override any set by the
1770 redisplay code. */
1771 static void
1772 x_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1774 x_set_name (f, arg, true);
1777 /* This function should be called by Emacs redisplay code to set the
1778 name; names set this way will never override names set by the user's
1779 lisp code. */
1780 void
1781 x_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1783 x_set_name (f, arg, false);
1786 /* Change the title of frame F to NAME.
1787 If NAME is nil, use the frame name as the title. */
1789 static void
1790 x_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name)
1792 /* Don't change the title if it's already NAME. */
1793 if (EQ (name, f->title))
1794 return;
1796 update_mode_lines = 38;
1798 fset_title (f, name);
1800 if (NILP (name))
1801 name = f->name;
1802 else
1803 CHECK_STRING (name);
1805 x_set_name_internal (f, name);
1808 void
1809 x_set_scroll_bar_default_width (struct frame *f)
1811 int unit = FRAME_COLUMN_WIDTH (f);
1812 #ifdef USE_TOOLKIT_SCROLL_BARS
1813 #ifdef USE_GTK
1814 int minw = xg_get_default_scrollbar_width ();
1815 #else
1816 int minw = 16;
1817 #endif
1818 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
1819 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (minw + unit - 1) / unit;
1820 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = minw;
1821 #else
1822 /* The width of a non-toolkit scrollbar is 14 pixels. */
1823 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit;
1824 FRAME_CONFIG_SCROLL_BAR_WIDTH (f)
1825 = FRAME_CONFIG_SCROLL_BAR_COLS (f) * unit;
1826 #endif
1829 void
1830 x_set_scroll_bar_default_height (struct frame *f)
1832 int height = FRAME_LINE_HEIGHT (f);
1833 #ifdef USE_TOOLKIT_SCROLL_BARS
1834 #ifdef USE_GTK
1835 int min_height = xg_get_default_scrollbar_height ();
1836 #else
1837 int min_height = 16;
1838 #endif
1839 /* A minimum height of 14 doesn't look good for toolkit scroll bars. */
1840 FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = min_height;
1841 FRAME_CONFIG_SCROLL_BAR_LINES (f) = (min_height + height - 1) / height;
1842 #else
1843 /* The height of a non-toolkit scrollbar is 14 pixels. */
1844 FRAME_CONFIG_SCROLL_BAR_LINES (f) = (14 + height - 1) / height;
1846 /* Use all of that space (aside from required margins) for the
1847 scroll bar. */
1848 FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = 14;
1849 #endif
1853 /* Record in frame F the specified or default value according to ALIST
1854 of the parameter named PROP (a Lisp symbol). If no value is
1855 specified for PROP, look for an X default for XPROP on the frame
1856 named NAME. If that is not found either, use the value DEFLT. */
1858 static Lisp_Object
1859 x_default_scroll_bar_color_parameter (struct frame *f,
1860 Lisp_Object alist, Lisp_Object prop,
1861 const char *xprop, const char *xclass,
1862 bool foreground_p)
1864 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
1865 Lisp_Object tem;
1867 tem = x_get_arg (dpyinfo, alist, prop, xprop, xclass, RES_TYPE_STRING);
1868 if (EQ (tem, Qunbound))
1870 #ifdef USE_TOOLKIT_SCROLL_BARS
1872 /* See if an X resource for the scroll bar color has been
1873 specified. */
1874 AUTO_STRING (foreground, "foreground");
1875 AUTO_STRING (background, "foreground");
1876 AUTO_STRING (verticalScrollBar, "verticalScrollBar");
1877 tem = (display_x_get_resource
1878 (dpyinfo, foreground_p ? foreground : background,
1879 empty_unibyte_string,
1880 verticalScrollBar,
1881 empty_unibyte_string));
1882 if (!STRINGP (tem))
1884 /* If nothing has been specified, scroll bars will use a
1885 toolkit-dependent default. Because these defaults are
1886 difficult to get at without actually creating a scroll
1887 bar, use nil to indicate that no color has been
1888 specified. */
1889 tem = Qnil;
1892 #else /* not USE_TOOLKIT_SCROLL_BARS */
1894 tem = Qnil;
1896 #endif /* not USE_TOOLKIT_SCROLL_BARS */
1899 AUTO_FRAME_ARG (arg, prop, tem);
1900 x_set_frame_parameters (f, arg);
1901 return tem;
1907 #ifdef USE_X_TOOLKIT
1909 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
1910 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
1911 already be present because of the toolkit (Motif adds some of them,
1912 for example, but Xt doesn't). */
1914 static void
1915 hack_wm_protocols (struct frame *f, Widget widget)
1917 Display *dpy = XtDisplay (widget);
1918 Window w = XtWindow (widget);
1919 bool need_delete = true;
1920 bool need_focus = true;
1921 bool need_save = true;
1923 block_input ();
1925 Atom type;
1926 unsigned char *catoms;
1927 int format = 0;
1928 unsigned long nitems = 0;
1929 unsigned long bytes_after;
1931 if ((XGetWindowProperty (dpy, w,
1932 FRAME_DISPLAY_INFO (f)->Xatom_wm_protocols,
1933 0, 100, False, XA_ATOM,
1934 &type, &format, &nitems, &bytes_after,
1935 &catoms)
1936 == Success)
1937 && format == 32 && type == XA_ATOM)
1939 Atom *atoms = (Atom *) catoms;
1940 while (nitems > 0)
1942 nitems--;
1943 if (atoms[nitems]
1944 == FRAME_DISPLAY_INFO (f)->Xatom_wm_delete_window)
1945 need_delete = false;
1946 else if (atoms[nitems]
1947 == FRAME_DISPLAY_INFO (f)->Xatom_wm_take_focus)
1948 need_focus = false;
1949 else if (atoms[nitems]
1950 == FRAME_DISPLAY_INFO (f)->Xatom_wm_save_yourself)
1951 need_save = false;
1954 if (catoms)
1955 XFree (catoms);
1958 Atom props[10];
1959 int count = 0;
1960 if (need_delete)
1961 props[count++] = FRAME_DISPLAY_INFO (f)->Xatom_wm_delete_window;
1962 if (need_focus)
1963 props[count++] = FRAME_DISPLAY_INFO (f)->Xatom_wm_take_focus;
1964 if (need_save)
1965 props[count++] = FRAME_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
1966 if (count)
1967 XChangeProperty (dpy, w, FRAME_DISPLAY_INFO (f)->Xatom_wm_protocols,
1968 XA_ATOM, 32, PropModeAppend,
1969 (unsigned char *) props, count);
1971 unblock_input ();
1973 #endif
1977 /* Support routines for XIC (X Input Context). */
1979 #ifdef HAVE_X_I18N
1981 static XFontSet xic_create_xfontset (struct frame *);
1982 static XIMStyle best_xim_style (XIMStyles *);
1985 /* Supported XIM styles, ordered by preference. */
1987 static const XIMStyle supported_xim_styles[] =
1989 XIMPreeditPosition | XIMStatusArea,
1990 XIMPreeditPosition | XIMStatusNothing,
1991 XIMPreeditPosition | XIMStatusNone,
1992 XIMPreeditNothing | XIMStatusArea,
1993 XIMPreeditNothing | XIMStatusNothing,
1994 XIMPreeditNothing | XIMStatusNone,
1995 XIMPreeditNone | XIMStatusArea,
1996 XIMPreeditNone | XIMStatusNothing,
1997 XIMPreeditNone | XIMStatusNone,
2002 #if defined HAVE_X_WINDOWS && defined USE_X_TOOLKIT
2003 /* Create an X fontset on frame F with base font name BASE_FONTNAME. */
2005 static const char xic_default_fontset[] = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
2007 /* Create an Xt fontset spec from the name of a base font.
2008 If `motif' is True use the Motif syntax. */
2009 char *
2010 xic_create_fontsetname (const char *base_fontname, bool motif)
2012 const char *sep = motif ? ";" : ",";
2013 char *fontsetname;
2014 char *z;
2016 /* Make a fontset name from the base font name. */
2017 if (xic_default_fontset == base_fontname)
2019 /* There is no base font name, use the default. */
2020 fontsetname = xmalloc (strlen (base_fontname) + 2);
2021 z = stpcpy (fontsetname, base_fontname);
2023 else
2025 /* Make a fontset name from the base font name.
2026 The font set will be made of the following elements:
2027 - the base font.
2028 - the base font where the charset spec is replaced by -*-*.
2029 - the same but with the family also replaced with -*-*-. */
2030 const char *p = base_fontname;
2031 ptrdiff_t i;
2033 for (i = 0; *p; p++)
2034 if (*p == '-') i++;
2035 if (i != 14)
2037 /* As the font name doesn't conform to XLFD, we can't
2038 modify it to generalize it to allcs and allfamilies.
2039 Use the specified font plus the default. */
2040 fontsetname = xmalloc (strlen (base_fontname)
2041 + strlen (xic_default_fontset) + 3);
2042 z = stpcpy (fontsetname, base_fontname);
2043 z = stpcpy (z, sep);
2044 z = stpcpy (z, xic_default_fontset);
2046 else
2048 ptrdiff_t len;
2049 const char *p1 = NULL, *p2 = NULL, *p3 = NULL;
2050 char *font_allcs = NULL;
2051 char *font_allfamilies = NULL;
2052 char *font_all = NULL;
2053 const char *allcs = "*-*-*-*-*-*-*";
2054 const char *allfamilies = "-*-*-";
2055 const char *all = "*-*-*-*-";
2056 char *base;
2058 for (i = 0, p = base_fontname; i < 8; p++)
2060 if (*p == '-')
2062 i++;
2063 if (i == 3)
2064 p1 = p + 1;
2065 else if (i == 7)
2066 p2 = p + 1;
2067 else if (i == 6)
2068 p3 = p + 1;
2071 /* If base_fontname specifies ADSTYLE, make it a
2072 wildcard. */
2073 if (*p3 != '*')
2075 ptrdiff_t diff = (p2 - p3) - 2;
2077 base = alloca (strlen (base_fontname) + 1);
2078 memcpy (base, base_fontname, p3 - base_fontname);
2079 base[p3 - base_fontname] = '*';
2080 base[(p3 - base_fontname) + 1] = '-';
2081 strcpy (base + (p3 - base_fontname) + 2, p2);
2082 p = base + (p - base_fontname) - diff;
2083 p1 = base + (p1 - base_fontname);
2084 p2 = base + (p2 - base_fontname) - diff;
2085 base_fontname = base;
2088 /* Build the font spec that matches all charsets. */
2089 len = p - base_fontname + strlen (allcs) + 1;
2090 font_allcs = alloca (len);
2091 memcpy (font_allcs, base_fontname, p - base_fontname);
2092 strcpy (font_allcs + (p - base_fontname), allcs);
2094 /* Build the font spec that matches all families and
2095 add-styles. */
2096 len = p - p1 + strlen (allcs) + strlen (allfamilies) + 1;
2097 font_allfamilies = alloca (len);
2098 strcpy (font_allfamilies, allfamilies);
2099 memcpy (font_allfamilies + strlen (allfamilies), p1, p - p1);
2100 strcpy (font_allfamilies + strlen (allfamilies) + (p - p1), allcs);
2102 /* Build the font spec that matches all. */
2103 len = p - p2 + strlen (allcs) + strlen (all) + strlen (allfamilies) + 1;
2104 font_all = alloca (len);
2105 z = stpcpy (font_all, allfamilies);
2106 z = stpcpy (z, all);
2107 memcpy (z, p2, p - p2);
2108 strcpy (z + (p - p2), allcs);
2110 /* Build the actual font set name. */
2111 len = strlen (base_fontname) + strlen (font_allcs)
2112 + strlen (font_allfamilies) + strlen (font_all) + 5;
2113 fontsetname = xmalloc (len);
2114 z = stpcpy (fontsetname, base_fontname);
2115 z = stpcpy (z, sep);
2116 z = stpcpy (z, font_allcs);
2117 z = stpcpy (z, sep);
2118 z = stpcpy (z, font_allfamilies);
2119 z = stpcpy (z, sep);
2120 z = stpcpy (z, font_all);
2123 if (motif)
2124 strcpy (z, ":");
2125 return fontsetname;
2127 #endif /* HAVE_X_WINDOWS && USE_X_TOOLKIT */
2129 #ifdef DEBUG_XIC_FONTSET
2130 static void
2131 print_fontset_result (XFontSet xfs, char *name, char **missing_list,
2132 int missing_count)
2134 if (xfs)
2135 fprintf (stderr, "XIC Fontset created: %s\n", name);
2136 else
2138 fprintf (stderr, "XIC Fontset failed: %s\n", name);
2139 while (missing_count-- > 0)
2141 fprintf (stderr, " missing: %s\n", *missing_list);
2142 missing_list++;
2147 #endif
2149 static XFontSet
2150 xic_create_xfontset (struct frame *f)
2152 XFontSet xfs = NULL;
2153 struct font *font = FRAME_FONT (f);
2154 int pixel_size = font->pixel_size;
2155 Lisp_Object rest, frame;
2157 /* See if there is another frame already using same fontset. */
2158 FOR_EACH_FRAME (rest, frame)
2160 struct frame *cf = XFRAME (frame);
2162 if (cf != f && FRAME_LIVE_P (f) && FRAME_X_P (cf)
2163 && FRAME_DISPLAY_INFO (cf) == FRAME_DISPLAY_INFO (f)
2164 && FRAME_FONT (f)
2165 && FRAME_FONT (f)->pixel_size == pixel_size)
2167 xfs = FRAME_XIC_FONTSET (cf);
2168 break;
2172 if (! xfs)
2174 char buf[256];
2175 char **missing_list;
2176 int missing_count;
2177 char *def_string;
2178 const char *xlfd_format = "-*-*-medium-r-normal--%d-*-*-*-*-*";
2180 sprintf (buf, xlfd_format, pixel_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)
2191 /* List of pixel sizes most likely available. Find one that
2192 is closest to pixel_size. */
2193 int sizes[] = {0, 8, 10, 11, 12, 14, 17, 18, 20, 24, 26, 34, 0};
2194 int *smaller, *larger;
2196 for (smaller = sizes; smaller[1]; smaller++)
2197 if (smaller[1] >= pixel_size)
2198 break;
2199 larger = smaller + 1;
2200 if (*larger == pixel_size)
2201 larger++;
2202 while (*smaller || *larger)
2204 int this_size;
2206 if (! *larger)
2207 this_size = *smaller--;
2208 else if (! *smaller)
2209 this_size = *larger++;
2210 else if (pixel_size - *smaller < *larger - pixel_size)
2211 this_size = *smaller--;
2212 else
2213 this_size = *larger++;
2214 sprintf (buf, xlfd_format, this_size);
2215 missing_list = NULL;
2216 xfs = XCreateFontSet (FRAME_X_DISPLAY (f), buf,
2217 &missing_list, &missing_count, &def_string);
2218 #ifdef DEBUG_XIC_FONTSET
2219 print_fontset_result (xfs, buf, missing_list, missing_count);
2220 #endif
2221 if (missing_list)
2222 XFreeStringList (missing_list);
2223 if (xfs)
2224 break;
2227 if (! xfs)
2229 const char *last_resort = "-*-*-*-r-normal--*-*-*-*-*-*";
2231 missing_list = NULL;
2232 xfs = XCreateFontSet (FRAME_X_DISPLAY (f), last_resort,
2233 &missing_list, &missing_count, &def_string);
2234 #ifdef DEBUG_XIC_FONTSET
2235 print_fontset_result (xfs, last_resort, missing_list, missing_count);
2236 #endif
2237 if (missing_list)
2238 XFreeStringList (missing_list);
2243 return xfs;
2246 /* Free the X fontset of frame F if it is the last frame using it. */
2248 void
2249 xic_free_xfontset (struct frame *f)
2251 Lisp_Object rest, frame;
2252 bool shared_p = false;
2254 if (!FRAME_XIC_FONTSET (f))
2255 return;
2257 /* See if there is another frame sharing the same fontset. */
2258 FOR_EACH_FRAME (rest, frame)
2260 struct frame *cf = XFRAME (frame);
2261 if (cf != f && FRAME_LIVE_P (f) && FRAME_X_P (cf)
2262 && FRAME_DISPLAY_INFO (cf) == FRAME_DISPLAY_INFO (f)
2263 && FRAME_XIC_FONTSET (cf) == FRAME_XIC_FONTSET (f))
2265 shared_p = true;
2266 break;
2270 if (!shared_p)
2271 /* The fontset is not used anymore. It is safe to free it. */
2272 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
2274 FRAME_XIC_FONTSET (f) = NULL;
2278 /* Value is the best input style, given user preferences USER (already
2279 checked to be supported by Emacs), and styles supported by the
2280 input method XIM. */
2282 static XIMStyle
2283 best_xim_style (XIMStyles *xim)
2285 int i, j;
2286 int nr_supported = ARRAYELTS (supported_xim_styles);
2288 for (i = 0; i < nr_supported; ++i)
2289 for (j = 0; j < xim->count_styles; ++j)
2290 if (supported_xim_styles[i] == xim->supported_styles[j])
2291 return supported_xim_styles[i];
2293 /* Return the default style. */
2294 return XIMPreeditNothing | XIMStatusNothing;
2297 /* Create XIC for frame F. */
2299 void
2300 create_frame_xic (struct frame *f)
2302 XIM xim;
2303 XIC xic = NULL;
2304 XFontSet xfs = NULL;
2305 XVaNestedList status_attr = NULL;
2306 XVaNestedList preedit_attr = NULL;
2307 XRectangle s_area;
2308 XPoint spot;
2309 XIMStyle xic_style;
2311 if (FRAME_XIC (f))
2312 goto out;
2314 xim = FRAME_X_XIM (f);
2315 if (!xim)
2316 goto out;
2318 /* Determine XIC style. */
2319 xic_style = best_xim_style (FRAME_X_XIM_STYLES (f));
2321 /* Create X fontset. */
2322 if (xic_style & (XIMPreeditPosition | XIMStatusArea))
2324 xfs = xic_create_xfontset (f);
2325 if (!xfs)
2326 goto out;
2328 FRAME_XIC_FONTSET (f) = xfs;
2331 if (xic_style & XIMPreeditPosition)
2333 spot.x = 0; spot.y = 1;
2334 preedit_attr = XVaCreateNestedList (0,
2335 XNFontSet, xfs,
2336 XNForeground,
2337 FRAME_FOREGROUND_PIXEL (f),
2338 XNBackground,
2339 FRAME_BACKGROUND_PIXEL (f),
2340 (xic_style & XIMPreeditPosition
2341 ? XNSpotLocation
2342 : NULL),
2343 &spot,
2344 NULL);
2346 if (!preedit_attr)
2347 goto out;
2350 if (xic_style & XIMStatusArea)
2352 s_area.x = 0; s_area.y = 0; s_area.width = 1; s_area.height = 1;
2353 status_attr = XVaCreateNestedList (0,
2354 XNArea,
2355 &s_area,
2356 XNFontSet,
2357 xfs,
2358 XNForeground,
2359 FRAME_FOREGROUND_PIXEL (f),
2360 XNBackground,
2361 FRAME_BACKGROUND_PIXEL (f),
2362 NULL);
2364 if (!status_attr)
2365 goto out;
2368 if (preedit_attr && status_attr)
2369 xic = XCreateIC (xim,
2370 XNInputStyle, xic_style,
2371 XNClientWindow, FRAME_X_WINDOW (f),
2372 XNFocusWindow, FRAME_X_WINDOW (f),
2373 XNStatusAttributes, status_attr,
2374 XNPreeditAttributes, preedit_attr,
2375 NULL);
2376 else if (preedit_attr)
2377 xic = XCreateIC (xim,
2378 XNInputStyle, xic_style,
2379 XNClientWindow, FRAME_X_WINDOW (f),
2380 XNFocusWindow, FRAME_X_WINDOW (f),
2381 XNPreeditAttributes, preedit_attr,
2382 NULL);
2383 else if (status_attr)
2384 xic = XCreateIC (xim,
2385 XNInputStyle, xic_style,
2386 XNClientWindow, FRAME_X_WINDOW (f),
2387 XNFocusWindow, FRAME_X_WINDOW (f),
2388 XNStatusAttributes, status_attr,
2389 NULL);
2390 else
2391 xic = XCreateIC (xim,
2392 XNInputStyle, xic_style,
2393 XNClientWindow, FRAME_X_WINDOW (f),
2394 XNFocusWindow, FRAME_X_WINDOW (f),
2395 NULL);
2397 if (!xic)
2398 goto out;
2400 FRAME_XIC (f) = xic;
2401 FRAME_XIC_STYLE (f) = xic_style;
2402 xfs = NULL; /* Don't free below. */
2404 out:
2406 if (xfs)
2407 free_frame_xic (f);
2409 if (preedit_attr)
2410 XFree (preedit_attr);
2412 if (status_attr)
2413 XFree (status_attr);
2417 /* Destroy XIC and free XIC fontset of frame F, if any. */
2419 void
2420 free_frame_xic (struct frame *f)
2422 if (FRAME_XIC (f) == NULL)
2423 return;
2425 XDestroyIC (FRAME_XIC (f));
2426 xic_free_xfontset (f);
2428 FRAME_XIC (f) = NULL;
2432 /* Place preedit area for XIC of window W's frame to specified
2433 pixel position X/Y. X and Y are relative to window W. */
2435 void
2436 xic_set_preeditarea (struct window *w, int x, int y)
2438 struct frame *f = XFRAME (w->frame);
2439 XVaNestedList attr;
2440 XPoint spot;
2442 spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x) + WINDOW_LEFT_FRINGE_WIDTH (w);
2443 spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f));
2444 attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL);
2445 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
2446 XFree (attr);
2450 /* Place status area for XIC in bottom right corner of frame F.. */
2452 void
2453 xic_set_statusarea (struct frame *f)
2455 XIC xic = FRAME_XIC (f);
2456 XVaNestedList attr;
2457 XRectangle area;
2458 XRectangle *needed;
2460 /* Negotiate geometry of status area. If input method has existing
2461 status area, use its current size. */
2462 area.x = area.y = area.width = area.height = 0;
2463 attr = XVaCreateNestedList (0, XNAreaNeeded, &area, NULL);
2464 XSetICValues (xic, XNStatusAttributes, attr, NULL);
2465 XFree (attr);
2467 attr = XVaCreateNestedList (0, XNAreaNeeded, &needed, NULL);
2468 XGetICValues (xic, XNStatusAttributes, attr, NULL);
2469 XFree (attr);
2471 if (needed->width == 0) /* Use XNArea instead of XNAreaNeeded */
2473 attr = XVaCreateNestedList (0, XNArea, &needed, NULL);
2474 XGetICValues (xic, XNStatusAttributes, attr, NULL);
2475 XFree (attr);
2478 area.width = needed->width;
2479 area.height = needed->height;
2480 area.x = FRAME_PIXEL_WIDTH (f) - area.width - FRAME_INTERNAL_BORDER_WIDTH (f);
2481 area.y = (FRAME_PIXEL_HEIGHT (f) - area.height
2482 - FRAME_MENUBAR_HEIGHT (f)
2483 - FRAME_TOOLBAR_TOP_HEIGHT (f)
2484 - FRAME_INTERNAL_BORDER_WIDTH (f));
2485 XFree (needed);
2487 attr = XVaCreateNestedList (0, XNArea, &area, NULL);
2488 XSetICValues (xic, XNStatusAttributes, attr, NULL);
2489 XFree (attr);
2493 /* Set X fontset for XIC of frame F, using base font name
2494 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
2496 void
2497 xic_set_xfontset (struct frame *f, const char *base_fontname)
2499 XVaNestedList attr;
2500 XFontSet xfs;
2502 xic_free_xfontset (f);
2504 xfs = xic_create_xfontset (f);
2506 attr = XVaCreateNestedList (0, XNFontSet, xfs, NULL);
2507 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
2508 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
2509 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
2510 XSetICValues (FRAME_XIC (f), XNStatusAttributes, attr, NULL);
2511 XFree (attr);
2513 FRAME_XIC_FONTSET (f) = xfs;
2516 #endif /* HAVE_X_I18N */
2521 void
2522 x_mark_frame_dirty (struct frame *f)
2524 if (FRAME_X_DOUBLE_BUFFERED_P (f) && !FRAME_X_NEED_BUFFER_FLIP (f))
2525 FRAME_X_NEED_BUFFER_FLIP (f) = true;
2528 static void
2529 set_up_x_back_buffer (struct frame *f)
2531 #ifdef HAVE_XDBE
2532 block_input ();
2533 if (FRAME_X_WINDOW (f) && !FRAME_X_DOUBLE_BUFFERED_P (f))
2535 FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
2536 if (FRAME_DISPLAY_INFO (f)->supports_xdbe)
2538 /* If allocating a back buffer fails, either because the
2539 server ran out of memory or we don't have the right kind
2540 of visual, just use single-buffered rendering. */
2541 x_catch_errors (FRAME_X_DISPLAY (f));
2542 FRAME_X_RAW_DRAWABLE (f) = XdbeAllocateBackBufferName (
2543 FRAME_X_DISPLAY (f),
2544 FRAME_X_WINDOW (f),
2545 XdbeCopied);
2546 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
2547 FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
2548 x_uncatch_errors_after_check ();
2551 unblock_input ();
2552 #endif
2555 void
2556 tear_down_x_back_buffer (struct frame *f)
2558 #ifdef HAVE_XDBE
2559 block_input ();
2560 if (FRAME_X_WINDOW (f) && FRAME_X_DOUBLE_BUFFERED_P (f))
2562 if (FRAME_X_DOUBLE_BUFFERED_P (f))
2564 XdbeDeallocateBackBufferName (FRAME_X_DISPLAY (f),
2565 FRAME_X_DRAWABLE (f));
2566 FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
2569 unblock_input ();
2570 #endif
2573 /* Set up double buffering if the frame parameters don't prohibit
2574 it. */
2575 void
2576 initial_set_up_x_back_buffer (struct frame *f)
2578 block_input ();
2579 eassert (FRAME_X_WINDOW (f));
2580 FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
2581 if (NILP (CDR (Fassq (Qinhibit_double_buffering, f->param_alist))))
2582 set_up_x_back_buffer (f);
2583 unblock_input ();
2586 #ifdef USE_X_TOOLKIT
2588 /* Create and set up the X widget for frame F. */
2590 static void
2591 x_window (struct frame *f, long window_prompting)
2593 XClassHint class_hints;
2594 XSetWindowAttributes attributes;
2595 unsigned long attribute_mask;
2596 Widget shell_widget;
2597 Widget pane_widget;
2598 Widget frame_widget;
2599 Arg al[25];
2600 int ac;
2602 block_input ();
2604 /* Use the resource name as the top-level widget name
2605 for looking up resources. Make a non-Lisp copy
2606 for the window manager, so GC relocation won't bother it.
2608 Elsewhere we specify the window name for the window manager. */
2609 f->namebuf = xlispstrdup (Vx_resource_name);
2611 ac = 0;
2612 XtSetArg (al[ac], XtNallowShellResize, 1); ac++;
2613 XtSetArg (al[ac], XtNinput, 1); ac++;
2614 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
2615 XtSetArg (al[ac], XtNborderWidth, f->border_width); ac++;
2616 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
2617 XtSetArg (al[ac], XtNdepth, FRAME_DISPLAY_INFO (f)->n_planes); ac++;
2618 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
2619 shell_widget = XtAppCreateShell (f->namebuf, EMACS_CLASS,
2620 applicationShellWidgetClass,
2621 FRAME_X_DISPLAY (f), al, ac);
2623 f->output_data.x->widget = shell_widget;
2624 /* maybe_set_screen_title_format (shell_widget); */
2626 pane_widget = lw_create_widget ("main", "pane", widget_id_tick++,
2627 NULL, shell_widget, False,
2628 NULL, NULL, NULL, NULL);
2630 ac = 0;
2631 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
2632 XtSetArg (al[ac], XtNdepth, FRAME_DISPLAY_INFO (f)->n_planes); ac++;
2633 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
2634 XtSetArg (al[ac], XtNborderWidth, 0); ac++;
2635 XtSetValues (pane_widget, al, ac);
2636 f->output_data.x->column_widget = pane_widget;
2638 /* mappedWhenManaged to false tells to the paned window to not map/unmap
2639 the emacs screen when changing menubar. This reduces flickering. */
2641 ac = 0;
2642 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
2643 XtSetArg (al[ac], XtNshowGrip, 0); ac++;
2644 XtSetArg (al[ac], XtNallowResize, 1); ac++;
2645 XtSetArg (al[ac], XtNresizeToPreferred, 1); ac++;
2646 XtSetArg (al[ac], XtNemacsFrame, f); ac++;
2647 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
2648 XtSetArg (al[ac], XtNdepth, FRAME_DISPLAY_INFO (f)->n_planes); ac++;
2649 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
2650 XtSetArg (al[ac], XtNborderWidth, 0); ac++;
2651 frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass, pane_widget,
2652 al, ac);
2654 f->output_data.x->edit_widget = frame_widget;
2656 XtManageChild (frame_widget);
2658 /* Do some needed geometry management. */
2660 Arg gal[3];
2661 int gac = 0;
2662 int extra_borders = 0;
2663 int menubar_size
2664 = (f->output_data.x->menubar_widget
2665 ? (f->output_data.x->menubar_widget->core.height
2666 + f->output_data.x->menubar_widget->core.border_width)
2667 : 0);
2669 #if false /* Experimentally, we now get the right results
2670 for -geometry -0-0 without this. 24 Aug 96, rms. */
2671 if (FRAME_EXTERNAL_MENU_BAR (f))
2673 Dimension ibw = 0;
2674 XtVaGetValues (pane_widget, XtNinternalBorderWidth, &ibw, NULL);
2675 menubar_size += ibw;
2677 #endif
2679 FRAME_MENUBAR_HEIGHT (f) = menubar_size;
2681 #ifndef USE_LUCID
2682 /* Motif seems to need this amount added to the sizes
2683 specified for the shell widget. The Athena/Lucid widgets don't.
2684 Both conclusions reached experimentally. -- rms. */
2685 XtVaGetValues (f->output_data.x->edit_widget, XtNinternalBorderWidth,
2686 &extra_borders, NULL);
2687 extra_borders *= 2;
2688 #endif
2690 f->shell_position = xmalloc (sizeof "=x++" + 4 * INT_STRLEN_BOUND (int));
2692 /* Convert our geometry parameters into a geometry string
2693 and specify it.
2694 Note that we do not specify here whether the position
2695 is a user-specified or program-specified one.
2696 We pass that information later, in x_wm_set_size_hints. */
2698 int left = f->left_pos;
2699 bool xneg = (window_prompting & XNegative) != 0;
2700 int top = f->top_pos;
2701 bool yneg = (window_prompting & YNegative) != 0;
2702 if (xneg)
2703 left = -left;
2704 if (yneg)
2705 top = -top;
2707 if (window_prompting & USPosition)
2708 sprintf (f->shell_position, "=%dx%d%c%d%c%d",
2709 FRAME_PIXEL_WIDTH (f) + extra_borders,
2710 FRAME_PIXEL_HEIGHT (f) + menubar_size + extra_borders,
2711 (xneg ? '-' : '+'), left,
2712 (yneg ? '-' : '+'), top);
2713 else
2715 sprintf (f->shell_position, "=%dx%d",
2716 FRAME_PIXEL_WIDTH (f) + extra_borders,
2717 FRAME_PIXEL_HEIGHT (f) + menubar_size + extra_borders);
2719 /* Setting x and y when the position is not specified in
2720 the geometry string will set program position in the WM hints.
2721 If Emacs had just one program position, we could set it in
2722 fallback resources, but since each make-frame call can specify
2723 different program positions, this is easier. */
2724 XtSetArg (gal[gac], XtNx, left); gac++;
2725 XtSetArg (gal[gac], XtNy, top); gac++;
2729 XtSetArg (gal[gac], XtNgeometry, f->shell_position); gac++;
2730 XtSetValues (shell_widget, gal, gac);
2733 XtManageChild (pane_widget);
2734 XtRealizeWidget (shell_widget);
2736 if (FRAME_X_EMBEDDED_P (f))
2737 XReparentWindow (FRAME_X_DISPLAY (f), XtWindow (shell_widget),
2738 f->output_data.x->parent_desc, 0, 0);
2740 FRAME_X_WINDOW (f) = XtWindow (frame_widget);
2741 initial_set_up_x_back_buffer (f);
2742 validate_x_resource_name ();
2744 class_hints.res_name = SSDATA (Vx_resource_name);
2745 class_hints.res_class = SSDATA (Vx_resource_class);
2746 XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints);
2748 #ifdef HAVE_X_I18N
2749 FRAME_XIC (f) = NULL;
2750 if (use_xim)
2751 create_frame_xic (f);
2752 #endif
2754 f->output_data.x->wm_hints.input = True;
2755 f->output_data.x->wm_hints.flags |= InputHint;
2756 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2757 &f->output_data.x->wm_hints);
2759 hack_wm_protocols (f, shell_widget);
2761 #ifdef X_TOOLKIT_EDITRES
2762 XtAddEventHandler (shell_widget, 0, True, _XEditResCheckMessages, 0);
2763 #endif
2765 /* Do a stupid property change to force the server to generate a
2766 PropertyNotify event so that the event_stream server timestamp will
2767 be initialized to something relevant to the time we created the window.
2769 XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
2770 FRAME_DISPLAY_INFO (f)->Xatom_wm_protocols,
2771 XA_ATOM, 32, PropModeAppend, NULL, 0);
2773 /* Make all the standard events reach the Emacs frame. */
2774 attributes.event_mask = STANDARD_EVENT_SET;
2776 #ifdef HAVE_X_I18N
2777 if (FRAME_XIC (f))
2779 /* XIM server might require some X events. */
2780 unsigned long fevent = NoEventMask;
2781 XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
2782 attributes.event_mask |= fevent;
2784 #endif /* HAVE_X_I18N */
2786 attribute_mask = CWEventMask;
2787 XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
2788 attribute_mask, &attributes);
2790 XtMapWidget (frame_widget);
2792 /* x_set_name normally ignores requests to set the name if the
2793 requested name is the same as the current name. This is the one
2794 place where that assumption isn't correct; f->name is set, but
2795 the X server hasn't been told. */
2797 Lisp_Object name;
2798 bool explicit = f->explicit_name;
2800 f->explicit_name = false;
2801 name = f->name;
2802 fset_name (f, Qnil);
2803 x_set_name (f, name, explicit);
2806 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2807 f->output_data.x->current_cursor
2808 = f->output_data.x->text_cursor);
2810 unblock_input ();
2812 /* This is a no-op, except under Motif. Make sure main areas are
2813 set to something reasonable, in case we get an error later. */
2814 lw_set_main_areas (pane_widget, 0, frame_widget);
2817 #else /* not USE_X_TOOLKIT */
2818 #ifdef USE_GTK
2819 static void
2820 x_window (struct frame *f)
2822 if (! xg_create_frame_widgets (f))
2823 error ("Unable to create window");
2825 #ifdef HAVE_X_I18N
2826 FRAME_XIC (f) = NULL;
2827 if (use_xim)
2829 block_input ();
2830 create_frame_xic (f);
2831 if (FRAME_XIC (f))
2833 /* XIM server might require some X events. */
2834 unsigned long fevent = NoEventMask;
2835 XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
2837 if (fevent != NoEventMask)
2839 XSetWindowAttributes attributes;
2840 XWindowAttributes wattr;
2841 unsigned long attribute_mask;
2843 XGetWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2844 &wattr);
2845 attributes.event_mask = wattr.your_event_mask | fevent;
2846 attribute_mask = CWEventMask;
2847 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2848 attribute_mask, &attributes);
2851 unblock_input ();
2853 #endif
2856 #else /*! USE_GTK */
2857 /* Create and set up the X window for frame F. */
2859 static void
2860 x_window (struct frame *f)
2862 XClassHint class_hints;
2863 XSetWindowAttributes attributes;
2864 unsigned long attribute_mask;
2866 attributes.background_pixel = FRAME_BACKGROUND_PIXEL (f);
2867 attributes.border_pixel = f->output_data.x->border_pixel;
2868 attributes.bit_gravity = StaticGravity;
2869 attributes.backing_store = NotUseful;
2870 attributes.save_under = True;
2871 attributes.event_mask = STANDARD_EVENT_SET;
2872 attributes.colormap = FRAME_X_COLORMAP (f);
2873 attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask
2874 | CWColormap);
2876 block_input ();
2877 FRAME_X_WINDOW (f)
2878 = XCreateWindow (FRAME_X_DISPLAY (f),
2879 f->output_data.x->parent_desc,
2880 f->left_pos,
2881 f->top_pos,
2882 FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f),
2883 f->border_width,
2884 CopyFromParent, /* depth */
2885 InputOutput, /* class */
2886 FRAME_X_VISUAL (f),
2887 attribute_mask, &attributes);
2888 initial_set_up_x_back_buffer (f);
2890 #ifdef HAVE_X_I18N
2891 if (use_xim)
2893 create_frame_xic (f);
2894 if (FRAME_XIC (f))
2896 /* XIM server might require some X events. */
2897 unsigned long fevent = NoEventMask;
2898 XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
2899 attributes.event_mask |= fevent;
2900 attribute_mask = CWEventMask;
2901 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2902 attribute_mask, &attributes);
2905 #endif /* HAVE_X_I18N */
2907 validate_x_resource_name ();
2909 class_hints.res_name = SSDATA (Vx_resource_name);
2910 class_hints.res_class = SSDATA (Vx_resource_class);
2911 XSetClassHint (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &class_hints);
2913 /* This indicates that we use the "Passive Input" input model.
2914 Unless we do this, we don't get the Focus{In,Out} events that we
2915 need to draw the cursor correctly. Accursed bureaucrats.
2916 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
2918 f->output_data.x->wm_hints.input = True;
2919 f->output_data.x->wm_hints.flags |= InputHint;
2920 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2921 &f->output_data.x->wm_hints);
2922 f->output_data.x->wm_hints.icon_pixmap = None;
2924 /* Request "save yourself" and "delete window" commands from wm. */
2926 Atom protocols[2];
2927 protocols[0] = FRAME_DISPLAY_INFO (f)->Xatom_wm_delete_window;
2928 protocols[1] = FRAME_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
2929 XSetWMProtocols (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), protocols, 2);
2932 /* x_set_name normally ignores requests to set the name if the
2933 requested name is the same as the current name. This is the one
2934 place where that assumption isn't correct; f->name is set, but
2935 the X server hasn't been told. */
2937 Lisp_Object name;
2938 bool explicit = f->explicit_name;
2940 f->explicit_name = false;
2941 name = f->name;
2942 fset_name (f, Qnil);
2943 x_set_name (f, name, explicit);
2946 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2947 f->output_data.x->current_cursor
2948 = f->output_data.x->text_cursor);
2950 unblock_input ();
2952 if (FRAME_X_WINDOW (f) == 0)
2953 error ("Unable to create window");
2956 #endif /* not USE_GTK */
2957 #endif /* not USE_X_TOOLKIT */
2959 /* Verify that the icon position args for this window are valid. */
2961 static void
2962 x_icon_verify (struct frame *f, Lisp_Object parms)
2964 Lisp_Object icon_x, icon_y;
2966 /* Set the position of the icon. Note that twm groups all
2967 icons in an icon window. */
2968 icon_x = x_frame_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
2969 icon_y = x_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
2970 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
2972 CHECK_NUMBER (icon_x);
2973 CHECK_NUMBER (icon_y);
2975 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
2976 error ("Both left and top icon corners of icon must be specified");
2979 /* Handle the icon stuff for this window. Perhaps later we might
2980 want an x_set_icon_position which can be called interactively as
2981 well. */
2983 static void
2984 x_icon (struct frame *f, Lisp_Object parms)
2986 /* Set the position of the icon. Note that twm groups all
2987 icons in an icon window. */
2988 Lisp_Object icon_x
2989 = x_frame_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
2990 Lisp_Object icon_y
2991 = x_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
2992 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
2994 CHECK_TYPE_RANGED_INTEGER (int, icon_x);
2995 CHECK_TYPE_RANGED_INTEGER (int, icon_y);
2997 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
2998 error ("Both left and top icon corners of icon must be specified");
3000 block_input ();
3002 if (! EQ (icon_x, Qunbound))
3003 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
3005 #if false /* x_get_arg removes the visibility parameter as a side effect,
3006 but x_create_frame still needs it. */
3007 /* Start up iconic or window? */
3008 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
3009 x_wm_set_window_state
3010 (f, (EQ (x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL),
3011 Qicon)
3012 ? IconicState
3013 : NormalState));
3014 #endif
3016 x_text_icon (f, SSDATA ((!NILP (f->icon_name)
3017 ? f->icon_name
3018 : f->name)));
3020 unblock_input ();
3023 /* Make the GCs needed for this window, setting the
3024 background, border and mouse colors; also create the
3025 mouse cursor and the gray border tile. */
3027 static void
3028 x_make_gc (struct frame *f)
3030 XGCValues gc_values;
3032 block_input ();
3034 /* Create the GCs of this frame.
3035 Note that many default values are used. */
3037 gc_values.foreground = FRAME_FOREGROUND_PIXEL (f);
3038 gc_values.background = FRAME_BACKGROUND_PIXEL (f);
3039 gc_values.line_width = 0; /* Means 1 using fast algorithm. */
3040 f->output_data.x->normal_gc
3041 = XCreateGC (FRAME_X_DISPLAY (f),
3042 FRAME_X_DRAWABLE (f),
3043 GCLineWidth | GCForeground | GCBackground,
3044 &gc_values);
3046 /* Reverse video style. */
3047 gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
3048 gc_values.background = FRAME_FOREGROUND_PIXEL (f);
3049 f->output_data.x->reverse_gc
3050 = XCreateGC (FRAME_X_DISPLAY (f),
3051 FRAME_X_DRAWABLE (f),
3052 GCForeground | GCBackground | GCLineWidth,
3053 &gc_values);
3055 /* Cursor has cursor-color background, background-color foreground. */
3056 gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
3057 gc_values.background = f->output_data.x->cursor_pixel;
3058 gc_values.fill_style = FillOpaqueStippled;
3059 f->output_data.x->cursor_gc
3060 = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
3061 (GCForeground | GCBackground
3062 | GCFillStyle | GCLineWidth),
3063 &gc_values);
3065 /* Create the gray border tile used when the pointer is not in
3066 the frame. Since this depends on the frame's pixel values,
3067 this must be done on a per-frame basis. */
3068 f->output_data.x->border_tile
3069 = (XCreatePixmapFromBitmapData
3070 (FRAME_X_DISPLAY (f), FRAME_DISPLAY_INFO (f)->root_window,
3071 gray_bits, gray_width, gray_height,
3072 FRAME_FOREGROUND_PIXEL (f),
3073 FRAME_BACKGROUND_PIXEL (f),
3074 DefaultDepth (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f))));
3076 unblock_input ();
3080 /* Free what was allocated in x_make_gc. */
3082 void
3083 x_free_gcs (struct frame *f)
3085 Display *dpy = FRAME_X_DISPLAY (f);
3087 block_input ();
3089 if (f->output_data.x->normal_gc)
3091 XFreeGC (dpy, f->output_data.x->normal_gc);
3092 f->output_data.x->normal_gc = 0;
3095 if (f->output_data.x->reverse_gc)
3097 XFreeGC (dpy, f->output_data.x->reverse_gc);
3098 f->output_data.x->reverse_gc = 0;
3101 if (f->output_data.x->cursor_gc)
3103 XFreeGC (dpy, f->output_data.x->cursor_gc);
3104 f->output_data.x->cursor_gc = 0;
3107 if (f->output_data.x->border_tile)
3109 XFreePixmap (dpy, f->output_data.x->border_tile);
3110 f->output_data.x->border_tile = 0;
3113 unblock_input ();
3117 /* Handler for signals raised during x_create_frame and
3118 x_create_tip_frame. FRAME is the frame which is partially
3119 constructed. */
3121 static Lisp_Object
3122 unwind_create_frame (Lisp_Object frame)
3124 struct frame *f = XFRAME (frame);
3126 /* If frame is already dead, nothing to do. This can happen if the
3127 display is disconnected after the frame has become official, but
3128 before x_create_frame removes the unwind protect. */
3129 if (!FRAME_LIVE_P (f))
3130 return Qnil;
3132 /* If frame is ``official'', nothing to do. */
3133 if (NILP (Fmemq (frame, Vframe_list)))
3135 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
3136 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
3137 #endif
3139 /* If the frame's image cache refcount is still the same as our
3140 private shadow variable, it means we are unwinding a frame
3141 for which we didn't yet call init_frame_faces, where the
3142 refcount is incremented. Therefore, we increment it here, so
3143 that free_frame_faces, called in x_free_frame_resources
3144 below, will not mistakenly decrement the counter that was not
3145 incremented yet to account for this new frame. */
3146 if (FRAME_IMAGE_CACHE (f) != NULL
3147 && FRAME_IMAGE_CACHE (f)->refcount == image_cache_refcount)
3148 FRAME_IMAGE_CACHE (f)->refcount++;
3150 x_free_frame_resources (f);
3151 free_glyphs (f);
3153 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
3154 /* Check that reference counts are indeed correct. */
3155 eassert (dpyinfo->reference_count == dpyinfo_refcount);
3156 eassert (dpyinfo->terminal->image_cache->refcount == image_cache_refcount);
3157 #endif
3158 return Qt;
3161 return Qnil;
3164 static void
3165 do_unwind_create_frame (Lisp_Object frame)
3167 unwind_create_frame (frame);
3170 static void
3171 x_default_font_parameter (struct frame *f, Lisp_Object parms)
3173 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
3174 Lisp_Object font_param = x_get_arg (dpyinfo, parms, Qfont, NULL, NULL,
3175 RES_TYPE_STRING);
3176 Lisp_Object font = Qnil;
3177 if (EQ (font_param, Qunbound))
3178 font_param = Qnil;
3180 if (NILP (font_param))
3182 /* System font should take precedence over X resources. We suggest this
3183 regardless of font-use-system-font because .emacs may not have been
3184 read yet. */
3185 const char *system_font = xsettings_get_system_font ();
3186 if (system_font)
3187 font = font_open_by_name (f, build_unibyte_string (system_font));
3190 if (NILP (font))
3191 font = !NILP (font_param) ? font_param
3192 : x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
3194 if (! FONTP (font) && ! STRINGP (font))
3196 const char *names[]
3198 #ifdef HAVE_XFT
3199 /* This will find the normal Xft font. */
3200 "monospace-10",
3201 #endif
3202 "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1",
3203 "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1",
3204 "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1",
3205 /* This was formerly the first thing tried, but it finds
3206 too many fonts and takes too long. */
3207 "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1",
3208 /* If those didn't work, look for something which will
3209 at least work. */
3210 "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1",
3211 "fixed",
3212 NULL };
3213 int i;
3215 for (i = 0; names[i]; i++)
3217 font = font_open_by_name (f, build_unibyte_string (names[i]));
3218 if (! NILP (font))
3219 break;
3221 if (NILP (font))
3222 error ("No suitable font was found");
3224 else if (!NILP (font_param))
3226 /* Remember the explicit font parameter, so we can re-apply it after
3227 we've applied the `default' face settings. */
3228 AUTO_FRAME_ARG (arg, Qfont_parameter, font_param);
3229 x_set_frame_parameters (f, arg);
3232 /* This call will make X resources override any system font setting. */
3233 x_default_parameter (f, parms, Qfont, font, "font", "Font", RES_TYPE_STRING);
3237 DEFUN ("x-wm-set-size-hint", Fx_wm_set_size_hint, Sx_wm_set_size_hint,
3238 0, 1, 0,
3239 doc: /* Send the size hints for frame FRAME to the window manager.
3240 If FRAME is omitted or nil, use the selected frame.
3241 Signal error if FRAME is not an X frame. */)
3242 (Lisp_Object frame)
3244 struct frame *f = decode_window_system_frame (frame);
3246 block_input ();
3247 x_wm_set_size_hint (f, 0, false);
3248 unblock_input ();
3249 return Qnil;
3252 static void
3253 set_machine_and_pid_properties (struct frame *f)
3255 /* This will set WM_CLIENT_MACHINE and WM_LOCALE_NAME. */
3256 XSetWMProperties (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), NULL, NULL,
3257 NULL, 0, NULL, NULL, NULL);
3258 pid_t pid = getpid ();
3259 if (pid <= 0xffffffffu)
3261 unsigned long xpid = pid;
3262 XChangeProperty (FRAME_X_DISPLAY (f),
3263 FRAME_OUTER_WINDOW (f),
3264 XInternAtom (FRAME_X_DISPLAY (f),
3265 "_NET_WM_PID",
3266 False),
3267 XA_CARDINAL, 32, PropModeReplace,
3268 (unsigned char *) &xpid, 1);
3272 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
3273 1, 1, 0,
3274 doc: /* Make a new X window, which is called a "frame" in Emacs terms.
3275 Return an Emacs frame object. PARMS is an alist of frame parameters.
3276 If the parameters specify that the frame should not have a minibuffer,
3277 and do not specify a specific minibuffer window to use, then
3278 `default-minibuffer-frame' must be a frame whose minibuffer can be
3279 shared by the new frame.
3281 This function is an internal primitive--use `make-frame' instead. */)
3282 (Lisp_Object parms)
3284 struct frame *f;
3285 Lisp_Object frame, tem;
3286 Lisp_Object name;
3287 bool minibuffer_only = false;
3288 long window_prompting = 0;
3289 ptrdiff_t count = SPECPDL_INDEX ();
3290 Lisp_Object display;
3291 struct x_display_info *dpyinfo = NULL;
3292 Lisp_Object parent;
3293 struct kboard *kb;
3294 int x_width = 0, x_height = 0;
3296 parms = Fcopy_alist (parms);
3298 /* Use this general default value to start with
3299 until we know if this frame has a specified name. */
3300 Vx_resource_name = Vinvocation_name;
3302 display = x_get_arg (dpyinfo, parms, Qterminal, 0, 0, RES_TYPE_NUMBER);
3303 if (EQ (display, Qunbound))
3304 display = x_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING);
3305 if (EQ (display, Qunbound))
3306 display = Qnil;
3307 dpyinfo = check_x_display_info (display);
3308 kb = dpyinfo->terminal->kboard;
3310 if (!dpyinfo->terminal->name)
3311 error ("Terminal is not live, can't create new frames on it");
3313 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
3314 if (!STRINGP (name)
3315 && ! EQ (name, Qunbound)
3316 && ! NILP (name))
3317 error ("Invalid frame name--not a string or nil");
3319 if (STRINGP (name))
3320 Vx_resource_name = name;
3322 /* See if parent window is specified. */
3323 parent = x_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
3324 if (EQ (parent, Qunbound))
3325 parent = Qnil;
3326 if (! NILP (parent))
3327 CHECK_NUMBER (parent);
3329 frame = Qnil;
3330 tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
3331 RES_TYPE_SYMBOL);
3332 if (EQ (tem, Qnone) || NILP (tem))
3333 f = make_frame_without_minibuffer (Qnil, kb, display);
3334 else if (EQ (tem, Qonly))
3336 f = make_minibuffer_frame ();
3337 minibuffer_only = true;
3339 else if (WINDOWP (tem))
3340 f = make_frame_without_minibuffer (tem, kb, display);
3341 else
3342 f = make_frame (true);
3344 XSETFRAME (frame, f);
3346 f->terminal = dpyinfo->terminal;
3348 f->output_method = output_x_window;
3349 f->output_data.x = xzalloc (sizeof *f->output_data.x);
3350 f->output_data.x->icon_bitmap = -1;
3351 FRAME_FONTSET (f) = -1;
3352 f->output_data.x->scroll_bar_foreground_pixel = -1;
3353 f->output_data.x->scroll_bar_background_pixel = -1;
3354 #if defined (USE_LUCID) && defined (USE_TOOLKIT_SCROLL_BARS)
3355 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
3356 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
3357 #endif /* USE_LUCID && USE_TOOLKIT_SCROLL_BARS */
3358 f->output_data.x->white_relief.pixel = -1;
3359 f->output_data.x->black_relief.pixel = -1;
3361 fset_icon_name (f,
3362 x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
3363 RES_TYPE_STRING));
3364 if (! STRINGP (f->icon_name))
3365 fset_icon_name (f, Qnil);
3367 FRAME_DISPLAY_INFO (f) = dpyinfo;
3369 /* With FRAME_DISPLAY_INFO set up, this unwind-protect is safe. */
3370 record_unwind_protect (do_unwind_create_frame, frame);
3372 /* These colors will be set anyway later, but it's important
3373 to get the color reference counts right, so initialize them! */
3375 Lisp_Object black;
3377 /* Function x_decode_color can signal an error. Make
3378 sure to initialize color slots so that we won't try
3379 to free colors we haven't allocated. */
3380 FRAME_FOREGROUND_PIXEL (f) = -1;
3381 FRAME_BACKGROUND_PIXEL (f) = -1;
3382 f->output_data.x->cursor_pixel = -1;
3383 f->output_data.x->cursor_foreground_pixel = -1;
3384 f->output_data.x->border_pixel = -1;
3385 f->output_data.x->mouse_pixel = -1;
3387 black = build_string ("black");
3388 FRAME_FOREGROUND_PIXEL (f)
3389 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3390 FRAME_BACKGROUND_PIXEL (f)
3391 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3392 f->output_data.x->cursor_pixel
3393 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3394 f->output_data.x->cursor_foreground_pixel
3395 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3396 f->output_data.x->border_pixel
3397 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3398 f->output_data.x->mouse_pixel
3399 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3402 /* Specify the parent under which to make this X window. */
3403 if (!NILP (parent))
3405 f->output_data.x->parent_desc = (Window) XFASTINT (parent);
3406 f->output_data.x->explicit_parent = true;
3408 else
3410 f->output_data.x->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
3411 f->output_data.x->explicit_parent = false;
3414 /* Set the name; the functions to which we pass f expect the name to
3415 be set. */
3416 if (EQ (name, Qunbound) || NILP (name))
3418 fset_name (f, build_string (dpyinfo->x_id_name));
3419 f->explicit_name = false;
3421 else
3423 fset_name (f, name);
3424 f->explicit_name = true;
3425 /* Use the frame's title when getting resources for this frame. */
3426 specbind (Qx_resource_name, name);
3429 #ifdef USE_CAIRO
3430 register_font_driver (&ftcrfont_driver, f);
3431 #else
3432 #ifdef HAVE_FREETYPE
3433 #ifdef HAVE_XFT
3434 register_font_driver (&xftfont_driver, f);
3435 #else /* not HAVE_XFT */
3436 register_font_driver (&ftxfont_driver, f);
3437 #endif /* not HAVE_XFT */
3438 #endif /* HAVE_FREETYPE */
3439 register_font_driver (&xfont_driver, f);
3440 #endif /* not USE_CAIRO */
3442 image_cache_refcount =
3443 FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
3444 #ifdef GLYPH_DEBUG
3445 dpyinfo_refcount = dpyinfo->reference_count;
3446 #endif /* GLYPH_DEBUG */
3448 x_default_parameter (f, parms, Qfont_backend, Qnil,
3449 "fontBackend", "FontBackend", RES_TYPE_STRING);
3451 /* Extract the window parameters from the supplied values
3452 that are needed to determine window geometry. */
3453 x_default_font_parameter (f, parms);
3454 if (!FRAME_FONT (f))
3456 delete_frame (frame, Qnoelisp);
3457 error ("Invalid frame font");
3460 /* Frame contents get displaced if an embedded X window has a border. */
3461 if (! FRAME_X_EMBEDDED_P (f))
3462 x_default_parameter (f, parms, Qborder_width, make_number (0),
3463 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
3465 /* This defaults to 1 in order to match xterm. We recognize either
3466 internalBorderWidth or internalBorder (which is what xterm calls
3467 it). */
3468 if (NILP (Fassq (Qinternal_border_width, parms)))
3470 Lisp_Object value;
3472 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
3473 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
3474 if (! EQ (value, Qunbound))
3475 parms = Fcons (Fcons (Qinternal_border_width, value),
3476 parms);
3478 x_default_parameter (f, parms, Qinternal_border_width,
3479 #ifdef USE_GTK /* We used to impose 0 in xg_create_frame_widgets. */
3480 make_number (0),
3481 #else
3482 make_number (1),
3483 #endif
3484 "internalBorderWidth", "internalBorderWidth",
3485 RES_TYPE_NUMBER);
3486 x_default_parameter (f, parms, Qright_divider_width, make_number (0),
3487 NULL, NULL, RES_TYPE_NUMBER);
3488 x_default_parameter (f, parms, Qbottom_divider_width, make_number (0),
3489 NULL, NULL, RES_TYPE_NUMBER);
3490 x_default_parameter (f, parms, Qvertical_scroll_bars,
3491 #if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
3492 Qright,
3493 #else
3494 Qleft,
3495 #endif
3496 "verticalScrollBars", "ScrollBars",
3497 RES_TYPE_SYMBOL);
3498 x_default_parameter (f, parms, Qhorizontal_scroll_bars, Qnil,
3499 "horizontalScrollBars", "ScrollBars",
3500 RES_TYPE_SYMBOL);
3501 /* Also do the stuff which must be set before the window exists. */
3502 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
3503 "foreground", "Foreground", RES_TYPE_STRING);
3504 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
3505 "background", "Background", RES_TYPE_STRING);
3506 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
3507 "pointerColor", "Foreground", RES_TYPE_STRING);
3508 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
3509 "borderColor", "BorderColor", RES_TYPE_STRING);
3510 x_default_parameter (f, parms, Qscreen_gamma, Qnil,
3511 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
3512 x_default_parameter (f, parms, Qline_spacing, Qnil,
3513 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
3514 x_default_parameter (f, parms, Qleft_fringe, Qnil,
3515 "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
3516 x_default_parameter (f, parms, Qright_fringe, Qnil,
3517 "rightFringe", "RightFringe", RES_TYPE_NUMBER);
3519 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
3520 "scrollBarForeground",
3521 "ScrollBarForeground", true);
3522 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_background,
3523 "scrollBarBackground",
3524 "ScrollBarBackground", false);
3526 /* Init faces before x_default_parameter is called for the
3527 scroll-bar-width parameter because otherwise we end up in
3528 init_iterator with a null face cache, which should not happen. */
3529 init_frame_faces (f);
3531 /* The following call of change_frame_size is needed since otherwise
3532 x_set_tool_bar_lines will already work with the character sizes
3533 installed by init_frame_faces while the frame's pixel size is
3534 still calculated from a character size of 1 and we subsequently
3535 hit the (height >= 0) assertion in window_box_height.
3537 The non-pixelwise code apparently worked around this because it
3538 had one frame line vs one toolbar line which left us with a zero
3539 root window height which was obviously wrong as well ... */
3540 adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
3541 FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, true,
3542 Qx_create_frame_1);
3544 /* Set the menu-bar-lines and tool-bar-lines parameters. We don't
3545 look up the X resources controlling the menu-bar and tool-bar
3546 here; they are processed specially at startup, and reflected in
3547 the values of the mode variables. */
3549 x_default_parameter (f, parms, Qmenu_bar_lines,
3550 NILP (Vmenu_bar_mode)
3551 ? make_number (0) : make_number (1),
3552 NULL, NULL, RES_TYPE_NUMBER);
3553 x_default_parameter (f, parms, Qtool_bar_lines,
3554 NILP (Vtool_bar_mode)
3555 ? make_number (0) : make_number (1),
3556 NULL, NULL, RES_TYPE_NUMBER);
3558 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
3559 "bufferPredicate", "BufferPredicate",
3560 RES_TYPE_SYMBOL);
3561 x_default_parameter (f, parms, Qtitle, Qnil,
3562 "title", "Title", RES_TYPE_STRING);
3563 x_default_parameter (f, parms, Qwait_for_wm, Qt,
3564 "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN);
3565 x_default_parameter (f, parms, Qtool_bar_position,
3566 FRAME_TOOL_BAR_POSITION (f), 0, 0, RES_TYPE_SYMBOL);
3567 x_default_parameter (f, parms, Qinhibit_double_buffering, Qnil,
3568 "inhibitDoubleBuffering", "InhibitDoubleBuffering",
3569 RES_TYPE_BOOLEAN);
3571 /* Compute the size of the X window. */
3572 window_prompting = x_figure_window_size (f, parms, true, &x_width, &x_height);
3574 tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
3575 f->no_split = minibuffer_only || EQ (tem, Qt);
3577 x_icon_verify (f, parms);
3579 /* Create the X widget or window. */
3580 #ifdef USE_X_TOOLKIT
3581 x_window (f, window_prompting);
3582 #else
3583 x_window (f);
3584 #endif
3586 x_icon (f, parms);
3587 x_make_gc (f);
3589 /* Now consider the frame official. */
3590 f->terminal->reference_count++;
3591 FRAME_DISPLAY_INFO (f)->reference_count++;
3592 Vframe_list = Fcons (frame, Vframe_list);
3594 /* We need to do this after creating the X window, so that the
3595 icon-creation functions can say whose icon they're describing. */
3596 x_default_parameter (f, parms, Qicon_type, Qt,
3597 "bitmapIcon", "BitmapIcon", RES_TYPE_BOOLEAN);
3599 x_default_parameter (f, parms, Qauto_raise, Qnil,
3600 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
3601 x_default_parameter (f, parms, Qauto_lower, Qnil,
3602 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
3603 x_default_parameter (f, parms, Qcursor_type, Qbox,
3604 "cursorType", "CursorType", RES_TYPE_SYMBOL);
3605 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
3606 "scrollBarWidth", "ScrollBarWidth",
3607 RES_TYPE_NUMBER);
3608 x_default_parameter (f, parms, Qscroll_bar_height, Qnil,
3609 "scrollBarHeight", "ScrollBarHeight",
3610 RES_TYPE_NUMBER);
3611 x_default_parameter (f, parms, Qalpha, Qnil,
3612 "alpha", "Alpha", RES_TYPE_NUMBER);
3614 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
3615 /* Create the menu bar. */
3616 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
3618 /* If this signals an error, we haven't set size hints for the
3619 frame and we didn't make it visible. */
3620 initialize_frame_menubar (f);
3622 #ifndef USE_GTK
3623 /* This is a no-op, except under Motif where it arranges the
3624 main window for the widgets on it. */
3625 lw_set_main_areas (f->output_data.x->column_widget,
3626 f->output_data.x->menubar_widget,
3627 f->output_data.x->edit_widget);
3628 #endif /* not USE_GTK */
3630 #endif /* USE_X_TOOLKIT || USE_GTK */
3632 /* Consider frame official, now. */
3633 f->can_x_set_window_size = true;
3635 if (x_width > 0)
3636 SET_FRAME_WIDTH (f, x_width);
3637 if (x_height > 0)
3638 SET_FRAME_HEIGHT (f, x_height);
3640 /* Tell the server what size and position, etc, we want, and how
3641 badly we want them. This should be done after we have the menu
3642 bar so that its size can be taken into account. */
3643 block_input ();
3644 x_wm_set_size_hint (f, window_prompting, false);
3645 unblock_input ();
3647 adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
3648 0, true, Qx_create_frame_2);
3650 /* Process fullscreen parameter here in the hope that normalizing a
3651 fullheight/fullwidth frame will produce the size set by the last
3652 adjust_frame_size call. */
3653 x_default_parameter (f, parms, Qfullscreen, Qnil,
3654 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
3656 /* Make the window appear on the frame and enable display, unless
3657 the caller says not to. However, with explicit parent, Emacs
3658 cannot control visibility, so don't try. */
3659 if (! f->output_data.x->explicit_parent)
3661 Lisp_Object visibility;
3663 visibility = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
3664 RES_TYPE_SYMBOL);
3665 if (EQ (visibility, Qunbound))
3666 visibility = Qt;
3668 if (EQ (visibility, Qicon))
3669 x_iconify_frame (f);
3670 else if (! NILP (visibility))
3671 x_make_frame_visible (f);
3672 else
3674 /* Must have been Qnil. */
3678 block_input ();
3680 /* Set machine name and pid for the purpose of window managers. */
3681 set_machine_and_pid_properties (f);
3683 /* Set the WM leader property. GTK does this itself, so this is not
3684 needed when using GTK. */
3685 if (dpyinfo->client_leader_window != 0)
3687 XChangeProperty (FRAME_X_DISPLAY (f),
3688 FRAME_OUTER_WINDOW (f),
3689 dpyinfo->Xatom_wm_client_leader,
3690 XA_WINDOW, 32, PropModeReplace,
3691 (unsigned char *) &dpyinfo->client_leader_window, 1);
3694 unblock_input ();
3696 /* Initialize `default-minibuffer-frame' in case this is the first
3697 frame on this terminal. */
3698 if (FRAME_HAS_MINIBUF_P (f)
3699 && (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame))
3700 || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame)))))
3701 kset_default_minibuffer_frame (kb, frame);
3703 /* All remaining specified parameters, which have not been "used"
3704 by x_get_arg and friends, now go in the misc. alist of the frame. */
3705 for (tem = parms; CONSP (tem); tem = XCDR (tem))
3706 if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
3707 fset_param_alist (f, Fcons (XCAR (tem), f->param_alist));
3709 /* Make sure windows on this frame appear in calls to next-window
3710 and similar functions. */
3711 Vwindow_list = Qnil;
3713 return unbind_to (count, frame);
3717 /* FRAME is used only to get a handle on the X display. We don't pass the
3718 display info directly because we're called from frame.c, which doesn't
3719 know about that structure. */
3721 Lisp_Object
3722 x_get_focus_frame (struct frame *frame)
3724 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame);
3725 Lisp_Object xfocus;
3726 if (! dpyinfo->x_focus_frame)
3727 return Qnil;
3729 XSETFRAME (xfocus, dpyinfo->x_focus_frame);
3730 return xfocus;
3734 /* In certain situations, when the window manager follows a
3735 click-to-focus policy, there seems to be no way around calling
3736 XSetInputFocus to give another frame the input focus .
3738 In an ideal world, XSetInputFocus should generally be avoided so
3739 that applications don't interfere with the window manager's focus
3740 policy. But I think it's okay to use when it's clearly done
3741 following a user-command. */
3743 void
3744 x_focus_frame (struct frame *f)
3746 Display *dpy = FRAME_X_DISPLAY (f);
3748 block_input ();
3749 x_catch_errors (dpy);
3751 if (FRAME_X_EMBEDDED_P (f))
3753 /* For Xembedded frames, normally the embedder forwards key
3754 events. See XEmbed Protocol Specification at
3755 http://freedesktop.org/wiki/Specifications/xembed-spec */
3756 xembed_request_focus (f);
3758 else
3760 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3761 RevertToParent, CurrentTime);
3762 x_ewmh_activate_frame (f);
3765 x_uncatch_errors ();
3766 unblock_input ();
3770 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
3771 doc: /* Internal function called by `color-defined-p', which see.
3772 \(Note that the Nextstep version of this function ignores FRAME.) */)
3773 (Lisp_Object color, Lisp_Object frame)
3775 XColor foo;
3776 struct frame *f = decode_window_system_frame (frame);
3778 CHECK_STRING (color);
3780 if (x_defined_color (f, SSDATA (color), &foo, false))
3781 return Qt;
3782 else
3783 return Qnil;
3786 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
3787 doc: /* Internal function called by `color-values', which see. */)
3788 (Lisp_Object color, Lisp_Object frame)
3790 XColor foo;
3791 struct frame *f = decode_window_system_frame (frame);
3793 CHECK_STRING (color);
3795 if (x_defined_color (f, SSDATA (color), &foo, false))
3796 return list3i (foo.red, foo.green, foo.blue);
3797 else
3798 return Qnil;
3801 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
3802 doc: /* Internal function called by `display-color-p', which see. */)
3803 (Lisp_Object terminal)
3805 struct x_display_info *dpyinfo = check_x_display_info (terminal);
3807 if (dpyinfo->n_planes <= 2)
3808 return Qnil;
3810 switch (dpyinfo->visual->class)
3812 case StaticColor:
3813 case PseudoColor:
3814 case TrueColor:
3815 case DirectColor:
3816 return Qt;
3818 default:
3819 return Qnil;
3823 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
3824 0, 1, 0,
3825 doc: /* Return t if the X display supports shades of gray.
3826 Note that color displays do support shades of gray.
3827 The optional argument TERMINAL specifies which display to ask about.
3828 TERMINAL should be a terminal object, a frame or a display name (a string).
3829 If omitted or nil, that stands for the selected frame's display. */)
3830 (Lisp_Object terminal)
3832 struct x_display_info *dpyinfo = check_x_display_info (terminal);
3834 if (dpyinfo->n_planes <= 1)
3835 return Qnil;
3837 switch (dpyinfo->visual->class)
3839 case StaticColor:
3840 case PseudoColor:
3841 case TrueColor:
3842 case DirectColor:
3843 case StaticGray:
3844 case GrayScale:
3845 return Qt;
3847 default:
3848 return Qnil;
3852 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
3853 0, 1, 0,
3854 doc: /* Return the width in pixels of the X display TERMINAL.
3855 The optional argument TERMINAL specifies which display to ask about.
3856 TERMINAL should be a terminal object, a frame or a display name (a string).
3857 If omitted or nil, that stands for the selected frame's display.
3859 On \"multi-monitor\" setups this refers to the pixel width for all
3860 physical monitors associated with TERMINAL. To get information for
3861 each physical monitor, use `display-monitor-attributes-list'. */)
3862 (Lisp_Object terminal)
3864 struct x_display_info *dpyinfo = check_x_display_info (terminal);
3866 return make_number (x_display_pixel_width (dpyinfo));
3869 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
3870 Sx_display_pixel_height, 0, 1, 0,
3871 doc: /* Return the height in pixels of the X display TERMINAL.
3872 The optional argument TERMINAL specifies which display to ask about.
3873 TERMINAL should be a terminal object, a frame or a display name (a string).
3874 If omitted or nil, that stands for the selected frame's display.
3876 On \"multi-monitor\" setups this refers to the pixel height for all
3877 physical monitors associated with TERMINAL. To get information for
3878 each physical monitor, use `display-monitor-attributes-list'. */)
3879 (Lisp_Object terminal)
3881 struct x_display_info *dpyinfo = check_x_display_info (terminal);
3883 return make_number (x_display_pixel_height (dpyinfo));
3886 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
3887 0, 1, 0,
3888 doc: /* Return the number of bitplanes of the X display TERMINAL.
3889 The optional argument TERMINAL specifies which display to ask about.
3890 TERMINAL should be a terminal object, a frame or a display name (a string).
3891 If omitted or nil, that stands for the selected frame's display. */)
3892 (Lisp_Object terminal)
3894 struct x_display_info *dpyinfo = check_x_display_info (terminal);
3896 return make_number (dpyinfo->n_planes);
3899 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
3900 0, 1, 0,
3901 doc: /* Return the number of color cells of the X display TERMINAL.
3902 The optional argument TERMINAL specifies which display to ask about.
3903 TERMINAL should be a terminal object, a frame or a display name (a string).
3904 If omitted or nil, that stands for the selected frame's display. */)
3905 (Lisp_Object terminal)
3907 struct x_display_info *dpyinfo = check_x_display_info (terminal);
3909 int nr_planes = DisplayPlanes (dpyinfo->display,
3910 XScreenNumberOfScreen (dpyinfo->screen));
3912 /* Truncate nr_planes to 24 to avoid integer overflow.
3913 Some displays says 32, but only 24 bits are actually significant.
3914 There are only very few and rare video cards that have more than
3915 24 significant bits. Also 24 bits is more than 16 million colors,
3916 it "should be enough for everyone". */
3917 if (nr_planes > 24) nr_planes = 24;
3919 return make_number (1 << nr_planes);
3922 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
3923 Sx_server_max_request_size,
3924 0, 1, 0,
3925 doc: /* Return the maximum request size of the X server of display TERMINAL.
3926 The optional argument TERMINAL specifies which display to ask about.
3927 TERMINAL should be a terminal object, a frame or a display name (a string).
3928 If omitted or nil, that stands for the selected frame's display. */)
3929 (Lisp_Object terminal)
3931 struct x_display_info *dpyinfo = check_x_display_info (terminal);
3933 return make_number (MAXREQUEST (dpyinfo->display));
3936 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
3937 doc: /* Return the "vendor ID" string of the GUI software on TERMINAL.
3939 \(Labeling every distributor as a "vendor" embodies the false assumption
3940 that operating systems cannot be developed and distributed noncommercially.)
3941 The optional argument TERMINAL specifies which display to ask about.
3943 For GNU and Unix systems, this queries the X server software; for
3944 MS-Windows, this queries the OS.
3946 TERMINAL should be a terminal object, a frame or a display name (a string).
3947 If omitted or nil, that stands for the selected frame's display. */)
3948 (Lisp_Object terminal)
3950 struct x_display_info *dpyinfo = check_x_display_info (terminal);
3951 const char *vendor = ServerVendor (dpyinfo->display);
3953 if (! vendor) vendor = "";
3954 return build_string (vendor);
3957 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
3958 doc: /* Return the version numbers of the GUI software on TERMINAL.
3959 The value is a list of three integers specifying the version of the GUI
3960 software in use.
3962 For GNU and Unix system, the first 2 numbers are the version of the X
3963 Protocol used on TERMINAL and the 3rd number is the distributor-specific
3964 release number. For MS-Windows, the 3 numbers report the version and
3965 the build number of the OS.
3967 See also the function `x-server-vendor'.
3969 The optional argument TERMINAL specifies which display to ask about.
3970 TERMINAL should be a terminal object, a frame or a display name (a string).
3971 If omitted or nil, that stands for the selected frame's display. */)
3972 (Lisp_Object terminal)
3974 struct x_display_info *dpyinfo = check_x_display_info (terminal);
3975 Display *dpy = dpyinfo->display;
3977 return list3i (ProtocolVersion (dpy), ProtocolRevision (dpy),
3978 VendorRelease (dpy));
3981 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
3982 doc: /* Return the number of screens on the X server of display TERMINAL.
3983 The optional argument TERMINAL specifies which display to ask about.
3984 TERMINAL should be a terminal object, a frame or a display name (a string).
3985 If omitted or nil, that stands for the selected frame's display. */)
3986 (Lisp_Object terminal)
3988 struct x_display_info *dpyinfo = check_x_display_info (terminal);
3990 return make_number (ScreenCount (dpyinfo->display));
3993 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
3994 doc: /* Return the height in millimeters of the X display TERMINAL.
3995 The optional argument TERMINAL specifies which display to ask about.
3996 TERMINAL should be a terminal object, a frame or a display name (a string).
3997 If omitted or nil, that stands for the selected frame's display.
3999 On \"multi-monitor\" setups this refers to the height in millimeters for
4000 all physical monitors associated with TERMINAL. To get information
4001 for each physical monitor, use `display-monitor-attributes-list'. */)
4002 (Lisp_Object terminal)
4004 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4006 return make_number (HeightMMOfScreen (dpyinfo->screen));
4009 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
4010 doc: /* Return the width in millimeters of the X display TERMINAL.
4011 The optional argument TERMINAL specifies which display to ask about.
4012 TERMINAL should be a terminal object, a frame or a display name (a string).
4013 If omitted or nil, that stands for the selected frame's display.
4015 On \"multi-monitor\" setups this refers to the width in millimeters for
4016 all physical monitors associated with TERMINAL. To get information
4017 for each physical monitor, use `display-monitor-attributes-list'. */)
4018 (Lisp_Object terminal)
4020 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4022 return make_number (WidthMMOfScreen (dpyinfo->screen));
4025 DEFUN ("x-display-backing-store", Fx_display_backing_store,
4026 Sx_display_backing_store, 0, 1, 0,
4027 doc: /* Return an indication of whether X display TERMINAL does backing store.
4028 The value may be `always', `when-mapped', or `not-useful'.
4029 The optional argument TERMINAL specifies which display to ask about.
4030 TERMINAL should be a terminal object, a frame or a display name (a string).
4031 If omitted or nil, that stands for the selected frame's display. */)
4032 (Lisp_Object terminal)
4034 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4035 Lisp_Object result;
4037 switch (DoesBackingStore (dpyinfo->screen))
4039 case Always:
4040 result = intern ("always");
4041 break;
4043 case WhenMapped:
4044 result = intern ("when-mapped");
4045 break;
4047 case NotUseful:
4048 result = intern ("not-useful");
4049 break;
4051 default:
4052 error ("Strange value for BackingStore parameter of screen");
4055 return result;
4058 DEFUN ("x-display-visual-class", Fx_display_visual_class,
4059 Sx_display_visual_class, 0, 1, 0,
4060 doc: /* Return the visual class of the X display TERMINAL.
4061 The value is one of the symbols `static-gray', `gray-scale',
4062 `static-color', `pseudo-color', `true-color', or `direct-color'.
4064 The optional argument TERMINAL specifies which display to ask about.
4065 TERMINAL should a terminal object, a frame or a display name (a string).
4066 If omitted or nil, that stands for the selected frame's display. */)
4067 (Lisp_Object terminal)
4069 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4070 Lisp_Object result;
4072 switch (dpyinfo->visual->class)
4074 case StaticGray:
4075 result = intern ("static-gray");
4076 break;
4077 case GrayScale:
4078 result = intern ("gray-scale");
4079 break;
4080 case StaticColor:
4081 result = intern ("static-color");
4082 break;
4083 case PseudoColor:
4084 result = intern ("pseudo-color");
4085 break;
4086 case TrueColor:
4087 result = intern ("true-color");
4088 break;
4089 case DirectColor:
4090 result = intern ("direct-color");
4091 break;
4092 default:
4093 error ("Display has an unknown visual class");
4096 return result;
4099 DEFUN ("x-display-save-under", Fx_display_save_under,
4100 Sx_display_save_under, 0, 1, 0,
4101 doc: /* Return t if the X display TERMINAL supports the save-under feature.
4102 The optional argument TERMINAL specifies which display to ask about.
4103 TERMINAL should be a terminal object, a frame or a display name (a string).
4104 If omitted or nil, that stands for the selected frame's display. */)
4105 (Lisp_Object terminal)
4107 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4109 if (DoesSaveUnders (dpyinfo->screen) == True)
4110 return Qt;
4111 else
4112 return Qnil;
4115 /* Store the geometry of the workarea on display DPYINFO into *RECT.
4116 Return false if and only if the workarea information cannot be
4117 obtained via the _NET_WORKAREA root window property. */
4119 #if ! GTK_CHECK_VERSION (3, 4, 0)
4120 static bool
4121 x_get_net_workarea (struct x_display_info *dpyinfo, XRectangle *rect)
4123 Display *dpy = dpyinfo->display;
4124 long offset, max_len;
4125 Atom target_type, actual_type;
4126 unsigned long actual_size, bytes_remaining;
4127 int rc, actual_format;
4128 unsigned char *tmp_data = NULL;
4129 bool result = false;
4131 x_catch_errors (dpy);
4132 offset = 0;
4133 max_len = 1;
4134 target_type = XA_CARDINAL;
4135 rc = XGetWindowProperty (dpy, dpyinfo->root_window,
4136 dpyinfo->Xatom_net_current_desktop,
4137 offset, max_len, False, target_type,
4138 &actual_type, &actual_format, &actual_size,
4139 &bytes_remaining, &tmp_data);
4140 if (rc == Success && actual_type == target_type && !x_had_errors_p (dpy)
4141 && actual_format == 32 && actual_size == max_len)
4143 long current_desktop = ((long *) tmp_data)[0];
4145 XFree (tmp_data);
4146 tmp_data = NULL;
4148 offset = 4 * current_desktop;
4149 max_len = 4;
4150 rc = XGetWindowProperty (dpy, dpyinfo->root_window,
4151 dpyinfo->Xatom_net_workarea,
4152 offset, max_len, False, target_type,
4153 &actual_type, &actual_format, &actual_size,
4154 &bytes_remaining, &tmp_data);
4155 if (rc == Success && actual_type == target_type && !x_had_errors_p (dpy)
4156 && actual_format == 32 && actual_size == max_len)
4158 long *values = (long *) tmp_data;
4160 rect->x = values[0];
4161 rect->y = values[1];
4162 rect->width = values[2];
4163 rect->height = values[3];
4165 XFree (tmp_data);
4166 tmp_data = NULL;
4168 result = true;
4171 if (tmp_data)
4172 XFree (tmp_data);
4173 x_uncatch_errors ();
4175 return result;
4177 #endif
4179 #ifndef USE_GTK
4181 /* Return monitor number where F is "most" or closest to. */
4182 static int
4183 x_get_monitor_for_frame (struct frame *f,
4184 struct MonitorInfo *monitors,
4185 int n_monitors)
4187 XRectangle frect;
4188 int area = 0, dist = -1;
4189 int best_area = -1, best_dist = -1;
4190 int i;
4192 if (n_monitors == 1) return 0;
4193 frect.x = f->left_pos;
4194 frect.y = f->top_pos;
4195 frect.width = FRAME_PIXEL_WIDTH (f);
4196 frect.height = FRAME_PIXEL_HEIGHT (f);
4198 for (i = 0; i < n_monitors; ++i)
4200 struct MonitorInfo *mi = &monitors[i];
4201 XRectangle res;
4202 int a = 0;
4204 if (mi->geom.width == 0) continue;
4206 if (x_intersect_rectangles (&mi->geom, &frect, &res))
4208 a = res.width * res.height;
4209 if (a > area)
4211 area = a;
4212 best_area = i;
4216 if (a == 0 && area == 0)
4218 int dx, dy, d;
4219 if (frect.x + frect.width < mi->geom.x)
4220 dx = mi->geom.x - frect.x + frect.width;
4221 else if (frect.x > mi->geom.x + mi->geom.width)
4222 dx = frect.x - mi->geom.x + mi->geom.width;
4223 else
4224 dx = 0;
4225 if (frect.y + frect.height < mi->geom.y)
4226 dy = mi->geom.y - frect.y + frect.height;
4227 else if (frect.y > mi->geom.y + mi->geom.height)
4228 dy = frect.y - mi->geom.y + mi->geom.height;
4229 else
4230 dy = 0;
4232 d = dx*dx + dy*dy;
4233 if (dist == -1 || dist > d)
4235 dist = d;
4236 best_dist = i;
4241 return best_area != -1 ? best_area : (best_dist != -1 ? best_dist : 0);
4244 static Lisp_Object
4245 x_make_monitor_attribute_list (struct MonitorInfo *monitors,
4246 int n_monitors,
4247 int primary_monitor,
4248 struct x_display_info *dpyinfo,
4249 const char *source)
4251 Lisp_Object monitor_frames = Fmake_vector (make_number (n_monitors), Qnil);
4252 Lisp_Object frame, rest;
4254 FOR_EACH_FRAME (rest, frame)
4256 struct frame *f = XFRAME (frame);
4258 if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) == dpyinfo
4259 && !EQ (frame, tip_frame))
4261 int i = x_get_monitor_for_frame (f, monitors, n_monitors);
4262 ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i)));
4266 return make_monitor_attribute_list (monitors, n_monitors, primary_monitor,
4267 monitor_frames, source);
4270 static Lisp_Object
4271 x_get_monitor_attributes_fallback (struct x_display_info *dpyinfo)
4273 struct MonitorInfo monitor;
4274 XRectangle workarea_r;
4276 /* Fallback: treat (possibly) multiple physical monitors as if they
4277 formed a single monitor as a whole. This should provide a
4278 consistent result at least on single monitor environments. */
4279 monitor.geom.x = monitor.geom.y = 0;
4280 monitor.geom.width = x_display_pixel_width (dpyinfo);
4281 monitor.geom.height = x_display_pixel_height (dpyinfo);
4282 monitor.mm_width = WidthMMOfScreen (dpyinfo->screen);
4283 monitor.mm_height = HeightMMOfScreen (dpyinfo->screen);
4284 monitor.name = xstrdup ("combined screen");
4286 if (x_get_net_workarea (dpyinfo, &workarea_r))
4287 monitor.work = workarea_r;
4288 else
4289 monitor.work = monitor.geom;
4290 return x_make_monitor_attribute_list (&monitor, 1, 0, dpyinfo, "fallback");
4294 #ifdef HAVE_XINERAMA
4295 static Lisp_Object
4296 x_get_monitor_attributes_xinerama (struct x_display_info *dpyinfo)
4298 int n_monitors, i;
4299 Lisp_Object attributes_list = Qnil;
4300 Display *dpy = dpyinfo->display;
4301 XineramaScreenInfo *info = XineramaQueryScreens (dpy, &n_monitors);
4302 struct MonitorInfo *monitors;
4303 double mm_width_per_pixel, mm_height_per_pixel;
4305 if (! info || n_monitors == 0)
4307 if (info)
4308 XFree (info);
4309 return attributes_list;
4312 mm_width_per_pixel = ((double) WidthMMOfScreen (dpyinfo->screen)
4313 / x_display_pixel_width (dpyinfo));
4314 mm_height_per_pixel = ((double) HeightMMOfScreen (dpyinfo->screen)
4315 / x_display_pixel_height (dpyinfo));
4316 monitors = xzalloc (n_monitors * sizeof *monitors);
4317 for (i = 0; i < n_monitors; ++i)
4319 struct MonitorInfo *mi = &monitors[i];
4320 XRectangle workarea_r;
4322 mi->geom.x = info[i].x_org;
4323 mi->geom.y = info[i].y_org;
4324 mi->geom.width = info[i].width;
4325 mi->geom.height = info[i].height;
4326 mi->mm_width = mi->geom.width * mm_width_per_pixel + 0.5;
4327 mi->mm_height = mi->geom.height * mm_height_per_pixel + 0.5;
4328 mi->name = 0;
4330 /* Xinerama usually have primary monitor first, just use that. */
4331 if (i == 0 && 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 XFree (info);
4342 attributes_list = x_make_monitor_attribute_list (monitors,
4343 n_monitors,
4345 dpyinfo,
4346 "Xinerama");
4347 free_monitors (monitors, n_monitors);
4348 return attributes_list;
4350 #endif /* HAVE_XINERAMA */
4353 #ifdef HAVE_XRANDR
4354 static Lisp_Object
4355 x_get_monitor_attributes_xrandr (struct x_display_info *dpyinfo)
4357 Lisp_Object attributes_list = Qnil;
4358 XRRScreenResources *resources;
4359 Display *dpy = dpyinfo->display;
4360 int i, n_monitors, primary = -1;
4361 RROutput pxid = None;
4362 struct MonitorInfo *monitors;
4364 #define RANDR13_LIBRARY \
4365 (RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 3))
4367 #if RANDR13_LIBRARY
4368 /* Check if the display supports 1.3 too. */
4369 bool randr13_avail = (dpyinfo->xrandr_major_version > 1
4370 || (dpyinfo->xrandr_major_version == 1
4371 && dpyinfo->xrandr_minor_version >= 3));
4373 if (randr13_avail)
4374 resources = XRRGetScreenResourcesCurrent (dpy, dpyinfo->root_window);
4375 else
4376 resources = XRRGetScreenResources (dpy, dpyinfo->root_window);
4377 #else
4378 resources = XRRGetScreenResources (dpy, dpyinfo->root_window);
4379 #endif
4380 if (! resources || resources->noutput == 0)
4382 if (resources)
4383 XRRFreeScreenResources (resources);
4384 return Qnil;
4386 n_monitors = resources->noutput;
4387 monitors = xzalloc (n_monitors * sizeof *monitors);
4389 #if RANDR13_LIBRARY
4390 if (randr13_avail)
4391 pxid = XRRGetOutputPrimary (dpy, dpyinfo->root_window);
4392 #endif
4394 for (i = 0; i < n_monitors; ++i)
4396 XRROutputInfo *info = XRRGetOutputInfo (dpy, resources,
4397 resources->outputs[i]);
4398 if (!info)
4399 continue;
4401 if (strcmp (info->name, "default") == 0)
4403 /* Non XRandr 1.2 driver, does not give useful data. */
4404 XRRFreeOutputInfo (info);
4405 XRRFreeScreenResources (resources);
4406 free_monitors (monitors, n_monitors);
4407 return Qnil;
4410 if (info->connection != RR_Disconnected && info->crtc != None)
4412 XRRCrtcInfo *crtc = XRRGetCrtcInfo (dpy, resources, info->crtc);
4413 struct MonitorInfo *mi = &monitors[i];
4414 XRectangle workarea_r;
4416 if (! crtc)
4418 XRRFreeOutputInfo (info);
4419 continue;
4422 mi->geom.x = crtc->x;
4423 mi->geom.y = crtc->y;
4424 mi->geom.width = crtc->width;
4425 mi->geom.height = crtc->height;
4426 mi->mm_width = info->mm_width;
4427 mi->mm_height = info->mm_height;
4428 mi->name = xstrdup (info->name);
4430 if (pxid != None && pxid == resources->outputs[i])
4431 primary = i;
4432 else if (primary == -1 && strcmp (info->name, "LVDS") == 0)
4433 primary = i;
4435 if (i == primary && x_get_net_workarea (dpyinfo, &workarea_r))
4437 mi->work= workarea_r;
4438 if (! x_intersect_rectangles (&mi->geom, &mi->work, &mi->work))
4439 mi->work = mi->geom;
4441 else
4442 mi->work = mi->geom;
4444 XRRFreeCrtcInfo (crtc);
4446 XRRFreeOutputInfo (info);
4448 XRRFreeScreenResources (resources);
4450 attributes_list = x_make_monitor_attribute_list (monitors,
4451 n_monitors,
4452 primary,
4453 dpyinfo,
4454 "XRandr");
4455 free_monitors (monitors, n_monitors);
4456 return attributes_list;
4458 #endif /* HAVE_XRANDR */
4460 static Lisp_Object
4461 x_get_monitor_attributes (struct x_display_info *dpyinfo)
4463 Lisp_Object attributes_list = Qnil;
4464 Display *dpy = dpyinfo->display;
4466 (void) dpy; /* Suppress unused variable warning. */
4468 #ifdef HAVE_XRANDR
4469 int xrr_event_base, xrr_error_base;
4470 bool xrr_ok = false;
4471 xrr_ok = XRRQueryExtension (dpy, &xrr_event_base, &xrr_error_base);
4472 if (xrr_ok)
4474 XRRQueryVersion (dpy, &dpyinfo->xrandr_major_version,
4475 &dpyinfo->xrandr_minor_version);
4476 xrr_ok = ((dpyinfo->xrandr_major_version == 1
4477 && dpyinfo->xrandr_minor_version >= 2)
4478 || dpyinfo->xrandr_major_version > 1);
4481 if (xrr_ok)
4482 attributes_list = x_get_monitor_attributes_xrandr (dpyinfo);
4483 #endif /* HAVE_XRANDR */
4485 #ifdef HAVE_XINERAMA
4486 if (NILP (attributes_list))
4488 int xin_event_base, xin_error_base;
4489 bool xin_ok = false;
4490 xin_ok = XineramaQueryExtension (dpy, &xin_event_base, &xin_error_base);
4491 if (xin_ok && XineramaIsActive (dpy))
4492 attributes_list = x_get_monitor_attributes_xinerama (dpyinfo);
4494 #endif /* HAVE_XINERAMA */
4496 if (NILP (attributes_list))
4497 attributes_list = x_get_monitor_attributes_fallback (dpyinfo);
4499 return attributes_list;
4502 #endif /* !USE_GTK */
4504 DEFUN ("x-display-monitor-attributes-list", Fx_display_monitor_attributes_list,
4505 Sx_display_monitor_attributes_list,
4506 0, 1, 0,
4507 doc: /* Return a list of physical monitor attributes on the X display TERMINAL.
4509 The optional argument TERMINAL specifies which display to ask about.
4510 TERMINAL should be a terminal object, a frame or a display name (a string).
4511 If omitted or nil, that stands for the selected frame's display.
4513 In addition to the standard attribute keys listed in
4514 `display-monitor-attributes-list', the following keys are contained in
4515 the attributes:
4517 source -- String describing the source from which multi-monitor
4518 information is obtained, one of \"Gdk\", \"XRandr\",
4519 \"Xinerama\", or \"fallback\"
4521 Internal use only, use `display-monitor-attributes-list' instead. */)
4522 (Lisp_Object terminal)
4524 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4525 Lisp_Object attributes_list = Qnil;
4527 #ifdef USE_GTK
4528 double mm_width_per_pixel, mm_height_per_pixel;
4529 GdkDisplay *gdpy;
4530 GdkScreen *gscreen;
4531 gint primary_monitor = 0, n_monitors, i;
4532 Lisp_Object monitor_frames, rest, frame;
4533 static const char *source = "Gdk";
4534 struct MonitorInfo *monitors;
4536 block_input ();
4537 mm_width_per_pixel = ((double) WidthMMOfScreen (dpyinfo->screen)
4538 / x_display_pixel_width (dpyinfo));
4539 mm_height_per_pixel = ((double) HeightMMOfScreen (dpyinfo->screen)
4540 / x_display_pixel_height (dpyinfo));
4541 gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display);
4542 gscreen = gdk_display_get_default_screen (gdpy);
4543 #if GTK_CHECK_VERSION (2, 20, 0)
4544 primary_monitor = gdk_screen_get_primary_monitor (gscreen);
4545 #endif
4546 n_monitors = gdk_screen_get_n_monitors (gscreen);
4547 monitor_frames = Fmake_vector (make_number (n_monitors), Qnil);
4548 monitors = xzalloc (n_monitors * sizeof *monitors);
4550 FOR_EACH_FRAME (rest, frame)
4552 struct frame *f = XFRAME (frame);
4554 if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) == dpyinfo
4555 && !EQ (frame, tip_frame))
4557 GdkWindow *gwin = gtk_widget_get_window (FRAME_GTK_WIDGET (f));
4559 i = gdk_screen_get_monitor_at_window (gscreen, gwin);
4560 ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i)));
4564 for (i = 0; i < n_monitors; ++i)
4566 gint width_mm = -1, height_mm = -1;
4567 GdkRectangle rec, work;
4568 struct MonitorInfo *mi = &monitors[i];
4570 gdk_screen_get_monitor_geometry (gscreen, i, &rec);
4572 #if GTK_CHECK_VERSION (2, 14, 0)
4573 width_mm = gdk_screen_get_monitor_width_mm (gscreen, i);
4574 height_mm = gdk_screen_get_monitor_height_mm (gscreen, i);
4575 #endif
4576 if (width_mm < 0)
4577 width_mm = rec.width * mm_width_per_pixel + 0.5;
4578 if (height_mm < 0)
4579 height_mm = rec.height * mm_height_per_pixel + 0.5;
4581 #if GTK_CHECK_VERSION (3, 4, 0)
4582 gdk_screen_get_monitor_workarea (gscreen, i, &work);
4583 #else
4584 /* Emulate the behavior of GTK+ 3.4. */
4586 XRectangle workarea_r;
4588 if (i == primary_monitor && x_get_net_workarea (dpyinfo, &workarea_r))
4590 work.x = workarea_r.x;
4591 work.y = workarea_r.y;
4592 work.width = workarea_r.width;
4593 work.height = workarea_r.height;
4594 if (! gdk_rectangle_intersect (&rec, &work, &work))
4595 work = rec;
4597 else
4598 work = rec;
4600 #endif
4603 mi->geom.x = rec.x;
4604 mi->geom.y = rec.y;
4605 mi->geom.width = rec.width;
4606 mi->geom.height = rec.height;
4607 mi->work.x = work.x;
4608 mi->work.y = work.y;
4609 mi->work.width = work.width;
4610 mi->work.height = work.height;
4611 mi->mm_width = width_mm;
4612 mi->mm_height = height_mm;
4614 #if GTK_CHECK_VERSION (2, 14, 0)
4615 mi->name = gdk_screen_get_monitor_plug_name (gscreen, i);
4616 #endif
4619 attributes_list = make_monitor_attribute_list (monitors,
4620 n_monitors,
4621 primary_monitor,
4622 monitor_frames,
4623 source);
4624 unblock_input ();
4625 #else /* not USE_GTK */
4627 block_input ();
4628 attributes_list = x_get_monitor_attributes (dpyinfo);
4629 unblock_input ();
4631 #endif /* not USE_GTK */
4633 return attributes_list;
4636 /* Return geometric attributes of FRAME. According to the value of
4637 ATTRIBUTES return the outer edges of FRAME (Qouter_edges), the native
4638 edges of FRAME (Qnative_edges), or the inner edges of frame
4639 (Qinner_edges). Any other value means to return the geometry as
4640 returned by Fx_frame_geometry. */
4641 static Lisp_Object
4642 frame_geometry (Lisp_Object frame, Lisp_Object attribute)
4644 struct frame *f = decode_live_frame (frame);
4645 /** XWindowAttributes atts; **/
4646 Window rootw;
4647 unsigned int ign, native_width, native_height;
4648 int xy_ign, xptr, yptr;
4649 int left_off, right_off, top_off, bottom_off;
4650 int outer_left, outer_top, outer_right, outer_bottom;
4651 int native_left, native_top, native_right, native_bottom;
4652 int inner_left, inner_top, inner_right, inner_bottom;
4653 int internal_border_width;
4654 bool menu_bar_external = false, tool_bar_external = false;
4655 int menu_bar_height = 0, menu_bar_width = 0;
4656 int tool_bar_height = 0, tool_bar_width = 0;
4658 if (FRAME_INITIAL_P (f) || !FRAME_X_P (f))
4659 return Qnil;
4661 block_input ();
4662 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
4663 &rootw, &xy_ign, &xy_ign, &native_width, &native_height,
4664 &ign, &ign);
4665 /** XGetWindowAttributes (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &atts); **/
4666 x_real_pos_and_offsets (f, &left_off, &right_off, &top_off, &bottom_off,
4667 NULL, NULL, &xptr, &yptr, NULL);
4668 unblock_input ();
4670 /** native_width = atts.width; **/
4671 /** native_height = atts.height; **/
4673 outer_left = xptr;
4674 outer_top = yptr;
4675 outer_right = outer_left + left_off + native_width + right_off;
4676 outer_bottom = outer_top + top_off + native_height + bottom_off;
4678 native_left = outer_left + left_off;
4679 native_top = outer_top + top_off;
4680 native_right = native_left + native_width;
4681 native_bottom = native_top + native_height;
4683 internal_border_width = FRAME_INTERNAL_BORDER_WIDTH (f);
4684 inner_left = native_left + internal_border_width;
4685 inner_top = native_top + internal_border_width;
4686 inner_right = native_right - internal_border_width;
4687 inner_bottom = native_bottom - internal_border_width;
4689 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
4690 menu_bar_external = true;
4691 menu_bar_height = FRAME_MENUBAR_HEIGHT (f);
4692 native_top += menu_bar_height;
4693 inner_top += menu_bar_height;
4694 #else
4695 menu_bar_height = FRAME_MENU_BAR_HEIGHT (f);
4696 inner_top += menu_bar_height;
4697 #endif
4698 menu_bar_width = menu_bar_height ? native_width : 0;
4700 #if defined (USE_GTK)
4701 tool_bar_external = true;
4702 if (EQ (FRAME_TOOL_BAR_POSITION (f), Qleft))
4704 tool_bar_width = FRAME_TOOLBAR_WIDTH (f);
4705 native_left += tool_bar_width;
4706 inner_left += tool_bar_width;
4707 tool_bar_height
4708 = tool_bar_width ? native_height - menu_bar_height : 0;
4710 else if (EQ (FRAME_TOOL_BAR_POSITION (f), Qtop))
4712 tool_bar_height = FRAME_TOOLBAR_HEIGHT (f);
4713 native_top += tool_bar_height;
4714 inner_top += tool_bar_height;
4715 tool_bar_width = tool_bar_height ? native_width : 0;
4717 else if (EQ (FRAME_TOOL_BAR_POSITION (f), Qright))
4719 tool_bar_width = FRAME_TOOLBAR_WIDTH (f);
4720 native_right -= tool_bar_width;
4721 inner_right -= tool_bar_width;
4722 tool_bar_height
4723 = tool_bar_width ? native_height - menu_bar_height : 0;
4725 else
4727 tool_bar_height = FRAME_TOOLBAR_HEIGHT (f);
4728 native_bottom -= tool_bar_height;
4729 inner_bottom -= tool_bar_height;
4730 tool_bar_width = tool_bar_height ? native_width : 0;
4732 #else
4733 tool_bar_height = FRAME_TOOL_BAR_HEIGHT (f);
4734 tool_bar_width = (tool_bar_height
4735 ? native_width - 2 * internal_border_width
4736 : 0);
4737 inner_top += tool_bar_height;
4738 #endif
4740 /* Construct list. */
4741 if (EQ (attribute, Qouter_edges))
4742 return list4 (make_number (outer_left), make_number (outer_top),
4743 make_number (outer_right), make_number (outer_bottom));
4744 else if (EQ (attribute, Qnative_edges))
4745 return list4 (make_number (native_left), make_number (native_top),
4746 make_number (native_right), make_number (native_bottom));
4747 else if (EQ (attribute, Qinner_edges))
4748 return list4 (make_number (inner_left), make_number (inner_top),
4749 make_number (inner_right), make_number (inner_bottom));
4750 else
4751 return
4752 listn (CONSTYPE_HEAP, 10,
4753 Fcons (Qouter_position,
4754 Fcons (make_number (outer_left),
4755 make_number (outer_top))),
4756 Fcons (Qouter_size,
4757 Fcons (make_number (outer_right - outer_left),
4758 make_number (outer_bottom - outer_top))),
4759 /* Approximate. */
4760 Fcons (Qexternal_border_size,
4761 Fcons (make_number (right_off),
4762 make_number (bottom_off))),
4763 /* Approximate. */
4764 Fcons (Qtitle_bar_size,
4765 Fcons (make_number (0),
4766 make_number (top_off - bottom_off))),
4767 Fcons (Qmenu_bar_external, menu_bar_external ? Qt : Qnil),
4768 Fcons (Qmenu_bar_size,
4769 Fcons (make_number (menu_bar_width),
4770 make_number (menu_bar_height))),
4771 Fcons (Qtool_bar_external, tool_bar_external ? Qt : Qnil),
4772 Fcons (Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f)),
4773 Fcons (Qtool_bar_size,
4774 Fcons (make_number (tool_bar_width),
4775 make_number (tool_bar_height))),
4776 Fcons (Qinternal_border_width,
4777 make_number (internal_border_width)));
4780 DEFUN ("x-frame-geometry", Fx_frame_geometry, Sx_frame_geometry, 0, 1, 0,
4781 doc: /* Return geometric attributes of FRAME.
4782 FRAME must be a live frame and defaults to the selected one. The return
4783 value is an association list of the attributes listed below. All height
4784 and width values are in pixels.
4786 `outer-position' is a cons of the outer left and top edges of FRAME
4787 relative to the origin - the position (0, 0) - of FRAME's display.
4789 `outer-size' is a cons of the outer width and height of FRAME. The
4790 outer size includes the title bar and the external borders as well as
4791 any menu and/or tool bar of frame.
4793 `external-border-size' is a cons of the horizontal and vertical width of
4794 FRAME's external borders as supplied by the window manager.
4796 `title-bar-size' is a cons of the width and height of the title bar of
4797 FRAME as supplied by the window manager. If both of them are zero,
4798 FRAME has no title bar. If only the width is zero, Emacs was not
4799 able to retrieve the width information.
4801 `menu-bar-external', if non-nil, means the menu bar is external (never
4802 included in the inner edges of FRAME).
4804 `menu-bar-size' is a cons of the width and height of the menu bar of
4805 FRAME.
4807 `tool-bar-external', if non-nil, means the tool bar is external (never
4808 included in the inner edges of FRAME).
4810 `tool-bar-position' tells on which side the tool bar on FRAME is and can
4811 be one of `left', `top', `right' or `bottom'. If this is nil, FRAME
4812 has no tool bar.
4814 `tool-bar-size' is a cons of the width and height of the tool bar of
4815 FRAME.
4817 `internal-border-width' is the width of the internal border of
4818 FRAME. */)
4819 (Lisp_Object frame)
4821 return frame_geometry (frame, Qnil);
4824 DEFUN ("x-frame-edges", Fx_frame_edges, Sx_frame_edges, 0, 2, 0,
4825 doc: /* Return edge coordinates of FRAME.
4826 FRAME must be a live frame and defaults to the selected one. The return
4827 value is a list of the form (LEFT, TOP, RIGHT, BOTTOM). All values are
4828 in pixels relative to the origin - the position (0, 0) - of FRAME's
4829 display.
4831 If optional argument TYPE is the symbol `outer-edges', return the outer
4832 edges of FRAME. The outer edges comprise the decorations of the window
4833 manager (like the title bar or external borders) as well as any external
4834 menu or tool bar of FRAME. If optional argument TYPE is the symbol
4835 `native-edges' or nil, return the native edges of FRAME. The native
4836 edges exclude the decorations of the window manager and any external
4837 menu or tool bar of FRAME. If TYPE is the symbol `inner-edges', return
4838 the inner edges of FRAME. These edges exclude title bar, any borders,
4839 menu bar or tool bar of FRAME. */)
4840 (Lisp_Object frame, Lisp_Object type)
4842 return frame_geometry (frame, ((EQ (type, Qouter_edges)
4843 || EQ (type, Qinner_edges))
4844 ? type
4845 : Qnative_edges));
4848 DEFUN ("x-mouse-absolute-pixel-position", Fx_mouse_absolute_pixel_position,
4849 Sx_mouse_absolute_pixel_position, 0, 0, 0,
4850 doc: /* Return absolute position of mouse cursor in pixels.
4851 The position is returned as a cons cell (X . Y) of the coordinates of
4852 the mouse cursor position in pixels relative to a position (0, 0) of the
4853 selected frame's display. */)
4854 (void)
4856 struct frame *f = SELECTED_FRAME ();
4857 Window root, dummy_window;
4858 int x, y, dummy;
4860 if (FRAME_INITIAL_P (f) || !FRAME_X_P (f))
4861 return Qnil;
4863 block_input ();
4864 XQueryPointer (FRAME_X_DISPLAY (f),
4865 DefaultRootWindow (FRAME_X_DISPLAY (f)),
4866 &root, &dummy_window, &x, &y, &dummy, &dummy,
4867 (unsigned int *) &dummy);
4868 unblock_input ();
4870 return Fcons (make_number (x), make_number (y));
4873 DEFUN ("x-set-mouse-absolute-pixel-position", Fx_set_mouse_absolute_pixel_position,
4874 Sx_set_mouse_absolute_pixel_position, 2, 2, 0,
4875 doc: /* Move mouse pointer to absolute pixel position (X, Y).
4876 The coordinates X and Y are interpreted in pixels relative to a position
4877 \(0, 0) of the selected frame's display. */)
4878 (Lisp_Object x, Lisp_Object y)
4880 struct frame *f = SELECTED_FRAME ();
4882 if (FRAME_INITIAL_P (f) || !FRAME_X_P (f))
4883 return Qnil;
4885 CHECK_TYPE_RANGED_INTEGER (int, x);
4886 CHECK_TYPE_RANGED_INTEGER (int, y);
4888 block_input ();
4889 XWarpPointer (FRAME_X_DISPLAY (f), None, DefaultRootWindow (FRAME_X_DISPLAY (f)),
4890 0, 0, 0, 0, XINT (x), XINT (y));
4891 unblock_input ();
4893 return Qnil;
4896 /************************************************************************
4897 X Displays
4898 ************************************************************************/
4901 /* Mapping visual names to visuals. */
4903 static struct visual_class
4905 const char *name;
4906 int class;
4908 visual_classes[] =
4910 {"StaticGray", StaticGray},
4911 {"GrayScale", GrayScale},
4912 {"StaticColor", StaticColor},
4913 {"PseudoColor", PseudoColor},
4914 {"TrueColor", TrueColor},
4915 {"DirectColor", DirectColor},
4916 {NULL, 0}
4920 #ifndef HAVE_XSCREENNUMBEROFSCREEN
4922 /* Value is the screen number of screen SCR. This is a substitute for
4923 the X function with the same name when that doesn't exist. */
4926 XScreenNumberOfScreen (scr)
4927 register Screen *scr;
4929 Display *dpy = scr->display;
4930 int i;
4932 for (i = 0; i < dpy->nscreens; ++i)
4933 if (scr == dpy->screens + i)
4934 break;
4936 return i;
4939 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
4942 /* Select the visual that should be used on display DPYINFO. Set
4943 members of DPYINFO appropriately. Called from x_term_init. */
4945 void
4946 select_visual (struct x_display_info *dpyinfo)
4948 Display *dpy = dpyinfo->display;
4949 Screen *screen = dpyinfo->screen;
4951 /* See if a visual is specified. */
4952 AUTO_STRING (visualClass, "visualClass");
4953 AUTO_STRING (VisualClass, "VisualClass");
4954 Lisp_Object value = display_x_get_resource (dpyinfo, visualClass,
4955 VisualClass, Qnil, Qnil);
4957 if (STRINGP (value))
4959 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
4960 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
4961 depth, a decimal number. NAME is compared with case ignored. */
4962 char *s = alloca (SBYTES (value) + 1);
4963 char *dash;
4964 int i, class = -1;
4965 XVisualInfo vinfo;
4967 lispstpcpy (s, value);
4968 dash = strchr (s, '-');
4969 if (dash)
4971 dpyinfo->n_planes = atoi (dash + 1);
4972 *dash = '\0';
4974 else
4975 /* We won't find a matching visual with depth 0, so that
4976 an error will be printed below. */
4977 dpyinfo->n_planes = 0;
4979 /* Determine the visual class. */
4980 for (i = 0; visual_classes[i].name; ++i)
4981 if (xstrcasecmp (s, visual_classes[i].name) == 0)
4983 class = visual_classes[i].class;
4984 break;
4987 /* Look up a matching visual for the specified class. */
4988 if (class == -1
4989 || !XMatchVisualInfo (dpy, XScreenNumberOfScreen (screen),
4990 dpyinfo->n_planes, class, &vinfo))
4991 fatal ("Invalid visual specification '%s'",
4992 SSDATA (ENCODE_SYSTEM (value)));
4994 dpyinfo->visual = vinfo.visual;
4996 else
4998 int n_visuals;
4999 XVisualInfo *vinfo, vinfo_template;
5001 dpyinfo->visual = DefaultVisualOfScreen (screen);
5003 vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
5004 vinfo_template.screen = XScreenNumberOfScreen (screen);
5005 vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
5006 &vinfo_template, &n_visuals);
5007 if (n_visuals <= 0)
5008 fatal ("Can't get proper X visual info");
5010 dpyinfo->n_planes = vinfo->depth;
5011 XFree (vinfo);
5016 /* Return the X display structure for the display named NAME.
5017 Open a new connection if necessary. */
5019 static struct x_display_info *
5020 x_display_info_for_name (Lisp_Object name)
5022 struct x_display_info *dpyinfo;
5024 CHECK_STRING (name);
5026 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
5027 if (!NILP (Fstring_equal (XCAR (dpyinfo->name_list_element), name)))
5028 return dpyinfo;
5030 /* Use this general default value to start with. */
5031 Vx_resource_name = Vinvocation_name;
5033 validate_x_resource_name ();
5035 dpyinfo = x_term_init (name, 0, SSDATA (Vx_resource_name));
5037 if (dpyinfo == 0)
5038 error ("Cannot connect to X server %s", SDATA (name));
5040 XSETFASTINT (Vwindow_system_version, 11);
5042 return dpyinfo;
5046 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
5047 1, 3, 0,
5048 doc: /* Open a connection to a display server.
5049 DISPLAY is the name of the display to connect to.
5050 Optional second arg XRM-STRING is a string of resources in xrdb format.
5051 If the optional third arg MUST-SUCCEED is non-nil,
5052 terminate Emacs if we can't open the connection.
5053 \(In the Nextstep version, the last two arguments are currently ignored.) */)
5054 (Lisp_Object display, Lisp_Object xrm_string, Lisp_Object must_succeed)
5056 char *xrm_option;
5057 struct x_display_info *dpyinfo;
5059 CHECK_STRING (display);
5060 if (! NILP (xrm_string))
5061 CHECK_STRING (xrm_string);
5063 xrm_option = NILP (xrm_string) ? 0 : SSDATA (xrm_string);
5065 validate_x_resource_name ();
5067 /* This is what opens the connection and sets x_current_display.
5068 This also initializes many symbols, such as those used for input. */
5069 dpyinfo = x_term_init (display, xrm_option,
5070 SSDATA (Vx_resource_name));
5072 if (dpyinfo == 0)
5074 if (!NILP (must_succeed))
5075 fatal ("Cannot connect to X server %s.\n\
5076 Check the DISPLAY environment variable or use `-d'.\n\
5077 Also use the `xauth' program to verify that you have the proper\n\
5078 authorization information needed to connect the X server.\n\
5079 An insecure way to solve the problem may be to use `xhost'.\n",
5080 SDATA (display));
5081 else
5082 error ("Cannot connect to X server %s", SDATA (display));
5085 XSETFASTINT (Vwindow_system_version, 11);
5086 return Qnil;
5089 DEFUN ("x-close-connection", Fx_close_connection,
5090 Sx_close_connection, 1, 1, 0,
5091 doc: /* Close the connection to TERMINAL's X server.
5092 For TERMINAL, specify a terminal object, a frame or a display name (a
5093 string). If TERMINAL is nil, that stands for the selected frame's
5094 terminal. */)
5095 (Lisp_Object terminal)
5097 struct x_display_info *dpyinfo = check_x_display_info (terminal);
5099 if (dpyinfo->reference_count > 0)
5100 error ("Display still has frames on it");
5102 x_delete_terminal (dpyinfo->terminal);
5104 return Qnil;
5107 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
5108 doc: /* Return the list of display names that Emacs has connections to. */)
5109 (void)
5111 Lisp_Object result = Qnil;
5112 struct x_display_info *xdi;
5114 for (xdi = x_display_list; xdi; xdi = xdi->next)
5115 result = Fcons (XCAR (xdi->name_list_element), result);
5117 return result;
5120 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
5121 doc: /* If ON is non-nil, report X errors as soon as the erring request is made.
5122 This function only has an effect on X Windows. With MS Windows, it is
5123 defined but does nothing.
5125 If ON is nil, allow buffering of requests.
5126 Turning on synchronization prohibits the Xlib routines from buffering
5127 requests and seriously degrades performance, but makes debugging much
5128 easier.
5129 The optional second argument TERMINAL specifies which display to act on.
5130 TERMINAL should be a terminal object, a frame or a display name (a string).
5131 If TERMINAL is omitted or nil, that stands for the selected frame's display. */)
5132 (Lisp_Object on, Lisp_Object terminal)
5134 struct x_display_info *dpyinfo = check_x_display_info (terminal);
5136 XSynchronize (dpyinfo->display, !EQ (on, Qnil));
5138 return Qnil;
5141 /* Wait for responses to all X commands issued so far for frame F. */
5143 void
5144 x_sync (struct frame *f)
5146 block_input ();
5147 XSync (FRAME_X_DISPLAY (f), False);
5148 unblock_input ();
5152 /***********************************************************************
5153 Window properties
5154 ***********************************************************************/
5156 DEFUN ("x-change-window-property", Fx_change_window_property,
5157 Sx_change_window_property, 2, 6, 0,
5158 doc: /* Change window property PROP to VALUE on the X window of FRAME.
5159 PROP must be a string. VALUE may be a string or a list of conses,
5160 numbers and/or strings. If an element in the list is a string, it is
5161 converted to an atom and the value of the atom is used. If an element
5162 is a cons, it is converted to a 32 bit number where the car is the 16
5163 top bits and the cdr is the lower 16 bits.
5165 FRAME nil or omitted means use the selected frame.
5166 If TYPE is given and non-nil, it is the name of the type of VALUE.
5167 If TYPE is not given or nil, the type is STRING.
5168 FORMAT gives the size in bits of each element if VALUE is a list.
5169 It must be one of 8, 16 or 32.
5170 If VALUE is a string or FORMAT is nil or not given, FORMAT defaults to 8.
5171 If OUTER-P is non-nil, the property is changed for the outer X window of
5172 FRAME. Default is to change on the edit X window. */)
5173 (Lisp_Object prop, Lisp_Object value, Lisp_Object frame,
5174 Lisp_Object type, Lisp_Object format, Lisp_Object outer_p)
5176 struct frame *f = decode_window_system_frame (frame);
5177 Atom prop_atom;
5178 Atom target_type = XA_STRING;
5179 int element_format = 8;
5180 unsigned char *data;
5181 int nelements;
5182 Window w;
5184 CHECK_STRING (prop);
5186 if (! NILP (format))
5188 CHECK_NUMBER (format);
5190 if (XINT (format) != 8 && XINT (format) != 16
5191 && XINT (format) != 32)
5192 error ("FORMAT must be one of 8, 16 or 32");
5193 element_format = XINT (format);
5196 if (CONSP (value))
5198 ptrdiff_t elsize;
5200 nelements = x_check_property_data (value);
5201 if (nelements == -1)
5202 error ("Bad data in VALUE, must be number, string or cons");
5204 /* The man page for XChangeProperty:
5205 "If the specified format is 32, the property data must be a
5206 long array."
5207 This applies even if long is more than 32 bits. The X library
5208 converts to 32 bits before sending to the X server. */
5209 elsize = element_format == 32 ? sizeof (long) : element_format >> 3;
5210 data = xnmalloc (nelements, elsize);
5212 x_fill_property_data (FRAME_X_DISPLAY (f), value, data, element_format);
5214 else
5216 ptrdiff_t elsize;
5218 CHECK_STRING (value);
5219 data = SDATA (value);
5220 if (INT_MAX < SBYTES (value))
5221 error ("VALUE too long");
5223 /* See comment above about longs and format=32 */
5224 elsize = element_format == 32 ? sizeof (long) : element_format >> 3;
5225 if (SBYTES (value) % elsize != 0)
5226 error ("VALUE must contain an integral number of octets for FORMAT");
5227 nelements = SBYTES (value) / elsize;
5230 block_input ();
5231 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False);
5232 if (! NILP (type))
5234 CHECK_STRING (type);
5235 target_type = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (type), False);
5238 if (! NILP (outer_p)) w = FRAME_OUTER_WINDOW (f);
5239 else w = FRAME_X_WINDOW (f);
5241 XChangeProperty (FRAME_X_DISPLAY (f), w,
5242 prop_atom, target_type, element_format, PropModeReplace,
5243 data, nelements);
5245 if (CONSP (value)) xfree (data);
5247 /* Make sure the property is set when we return. */
5248 XFlush (FRAME_X_DISPLAY (f));
5249 unblock_input ();
5251 return value;
5255 DEFUN ("x-delete-window-property", Fx_delete_window_property,
5256 Sx_delete_window_property, 1, 2, 0,
5257 doc: /* Remove window property PROP from X window of FRAME.
5258 FRAME nil or omitted means use the selected frame. Value is PROP. */)
5259 (Lisp_Object prop, Lisp_Object frame)
5261 struct frame *f = decode_window_system_frame (frame);
5262 Atom prop_atom;
5264 CHECK_STRING (prop);
5265 block_input ();
5266 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False);
5267 XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), prop_atom);
5269 /* Make sure the property is removed when we return. */
5270 XFlush (FRAME_X_DISPLAY (f));
5271 unblock_input ();
5273 return prop;
5277 static Lisp_Object
5278 x_window_property_intern (struct frame *f,
5279 Window target_window,
5280 Atom prop_atom,
5281 Atom target_type,
5282 Lisp_Object delete_p,
5283 Lisp_Object vector_ret_p,
5284 bool *found)
5286 unsigned char *tmp_data = NULL;
5287 Lisp_Object prop_value = Qnil;
5288 Atom actual_type;
5289 int actual_format;
5290 unsigned long actual_size, bytes_remaining;
5291 int rc;
5293 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
5294 prop_atom, 0, 0, False, target_type,
5295 &actual_type, &actual_format, &actual_size,
5296 &bytes_remaining, &tmp_data);
5298 *found = actual_format != 0;
5300 if (rc == Success && *found)
5302 XFree (tmp_data);
5303 tmp_data = NULL;
5305 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
5306 prop_atom, 0, bytes_remaining,
5307 ! NILP (delete_p), target_type,
5308 &actual_type, &actual_format,
5309 &actual_size, &bytes_remaining,
5310 &tmp_data);
5311 if (rc == Success && tmp_data)
5313 /* The man page for XGetWindowProperty says:
5314 "If the returned format is 32, the returned data is represented
5315 as a long array and should be cast to that type to obtain the
5316 elements."
5317 This applies even if long is more than 32 bits, the X library
5318 converts from 32 bit elements received from the X server to long
5319 and passes the long array to us. Thus, for that case memcpy can not
5320 be used. We convert to a 32 bit type here, because so much code
5321 assume on that.
5323 The bytes and offsets passed to XGetWindowProperty refers to the
5324 property and those are indeed in 32 bit quantities if format is
5325 32. */
5327 if (LONG_WIDTH > 32 && actual_format == 32)
5329 unsigned long i;
5330 int *idata = (int *) tmp_data;
5331 long *ldata = (long *) tmp_data;
5333 for (i = 0; i < actual_size; ++i)
5334 idata[i] = (int) ldata[i];
5337 if (NILP (vector_ret_p))
5338 prop_value = make_string ((char *) tmp_data,
5339 (actual_format >> 3) * actual_size);
5340 else
5341 prop_value = x_property_data_to_lisp (f,
5342 tmp_data,
5343 actual_type,
5344 actual_format,
5345 actual_size);
5348 if (tmp_data) XFree (tmp_data);
5351 return prop_value;
5354 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
5355 1, 6, 0,
5356 doc: /* Value is the value of window property PROP on FRAME.
5357 If FRAME is nil or omitted, use the selected frame.
5359 On X Windows, the following optional arguments are also accepted:
5360 If TYPE is nil or omitted, get the property as a string.
5361 Otherwise TYPE is the name of the atom that denotes the type expected.
5362 If SOURCE is non-nil, get the property on that window instead of from
5363 FRAME. The number 0 denotes the root window.
5364 If DELETE-P is non-nil, delete the property after retrieving it.
5365 If VECTOR-RET-P is non-nil, don't return a string but a vector of values.
5367 On MS Windows, this function accepts but ignores those optional arguments.
5369 Value is nil if FRAME hasn't a property with name PROP or if PROP has
5370 no value of TYPE (always string in the MS Windows case). */)
5371 (Lisp_Object prop, Lisp_Object frame, Lisp_Object type,
5372 Lisp_Object source, Lisp_Object delete_p, Lisp_Object vector_ret_p)
5374 struct frame *f = decode_window_system_frame (frame);
5375 Atom prop_atom;
5376 Lisp_Object prop_value = Qnil;
5377 Atom target_type = XA_STRING;
5378 Window target_window = FRAME_X_WINDOW (f);
5379 bool found;
5381 CHECK_STRING (prop);
5383 if (! NILP (source))
5385 CONS_TO_INTEGER (source, Window, target_window);
5386 if (! target_window)
5387 target_window = FRAME_DISPLAY_INFO (f)->root_window;
5390 block_input ();
5391 if (STRINGP (type))
5393 if (strcmp ("AnyPropertyType", SSDATA (type)) == 0)
5394 target_type = AnyPropertyType;
5395 else
5396 target_type = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (type), False);
5399 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False);
5400 prop_value = x_window_property_intern (f,
5401 target_window,
5402 prop_atom,
5403 target_type,
5404 delete_p,
5405 vector_ret_p,
5406 &found);
5407 if (NILP (prop_value)
5408 && ! found
5409 && NILP (source)
5410 && target_window != FRAME_OUTER_WINDOW (f))
5412 prop_value = x_window_property_intern (f,
5413 FRAME_OUTER_WINDOW (f),
5414 prop_atom,
5415 target_type,
5416 delete_p,
5417 vector_ret_p,
5418 &found);
5422 unblock_input ();
5423 return prop_value;
5426 DEFUN ("x-window-property-attributes", Fx_window_property_attributes, Sx_window_property_attributes,
5427 1, 3, 0,
5428 doc: /* Retrieve metadata about window property PROP on FRAME.
5429 If FRAME is nil or omitted, use the selected frame.
5430 If SOURCE is non-nil, get the property on that window instead of from
5431 FRAME. The number 0 denotes the root window.
5433 Return value is nil if FRAME hasn't a property with name PROP.
5434 Otherwise, the return value is a vector with the following fields:
5436 0. The property type, as an integer. The symbolic name of
5437 the type can be obtained with `x-get-atom-name'.
5438 1. The format of each element; one of 8, 16, or 32.
5439 2. The length of the property, in number of elements. */)
5440 (Lisp_Object prop, Lisp_Object frame, Lisp_Object source)
5442 struct frame *f = decode_window_system_frame (frame);
5443 Window target_window = FRAME_X_WINDOW (f);
5444 Atom prop_atom;
5445 Lisp_Object prop_attr = Qnil;
5446 Atom actual_type;
5447 int actual_format;
5448 unsigned long actual_size, bytes_remaining;
5449 unsigned char *tmp_data = NULL;
5450 int rc;
5452 CHECK_STRING (prop);
5454 if (! NILP (source))
5456 CONS_TO_INTEGER (source, Window, target_window);
5457 if (! target_window)
5458 target_window = FRAME_DISPLAY_INFO (f)->root_window;
5461 block_input ();
5463 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False);
5464 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
5465 prop_atom, 0, 0, False, AnyPropertyType,
5466 &actual_type, &actual_format, &actual_size,
5467 &bytes_remaining, &tmp_data);
5468 if (rc == Success /* no invalid params */
5469 && actual_format == 0 /* but prop not found */
5470 && NILP (source)
5471 && target_window != FRAME_OUTER_WINDOW (f))
5473 /* analogous behavior to x-window-property: if property isn't found
5474 on the frame's inner window and no alternate window id was
5475 provided, try the frame's outer window. */
5476 target_window = FRAME_OUTER_WINDOW (f);
5477 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
5478 prop_atom, 0, 0, False, AnyPropertyType,
5479 &actual_type, &actual_format, &actual_size,
5480 &bytes_remaining, &tmp_data);
5483 if (rc == Success && actual_format != 0)
5485 XFree (tmp_data);
5487 prop_attr = make_uninit_vector (3);
5488 ASET (prop_attr, 0, make_number (actual_type));
5489 ASET (prop_attr, 1, make_number (actual_format));
5490 ASET (prop_attr, 2, make_number (bytes_remaining / (actual_format >> 3)));
5493 unblock_input ();
5494 return prop_attr;
5497 /***********************************************************************
5498 Tool tips
5499 ***********************************************************************/
5501 static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
5502 Lisp_Object, int, int, int *, int *);
5504 /* The frame of a currently visible tooltip. */
5506 Lisp_Object tip_frame;
5508 /* If non-nil, a timer started that hides the last tooltip when it
5509 fires. */
5511 static Lisp_Object tip_timer;
5512 Window tip_window;
5514 /* If non-nil, a vector of 3 elements containing the last args
5515 with which x-show-tip was called. See there. */
5517 static Lisp_Object last_show_tip_args;
5520 static void
5521 unwind_create_tip_frame (Lisp_Object frame)
5523 Lisp_Object deleted;
5525 deleted = unwind_create_frame (frame);
5526 if (EQ (deleted, Qt))
5528 tip_window = None;
5529 tip_frame = Qnil;
5534 /* Create a frame for a tooltip on the display described by DPYINFO.
5535 PARMS is a list of frame parameters. TEXT is the string to
5536 display in the tip frame. Value is the frame.
5538 Note that functions called here, esp. x_default_parameter can
5539 signal errors, for instance when a specified color name is
5540 undefined. We have to make sure that we're in a consistent state
5541 when this happens. */
5543 static Lisp_Object
5544 x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms)
5546 struct frame *f;
5547 Lisp_Object frame;
5548 Lisp_Object name;
5549 int width, height;
5550 ptrdiff_t count = SPECPDL_INDEX ();
5551 bool face_change_before = face_change;
5552 int x_width = 0, x_height = 0;
5554 if (!dpyinfo->terminal->name)
5555 error ("Terminal is not live, can't create new frames on it");
5557 parms = Fcopy_alist (parms);
5559 /* Get the name of the frame to use for resource lookup. */
5560 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
5561 if (!STRINGP (name)
5562 && !EQ (name, Qunbound)
5563 && !NILP (name))
5564 error ("Invalid frame name--not a string or nil");
5566 frame = Qnil;
5567 f = make_frame (false);
5568 f->wants_modeline = false;
5569 XSETFRAME (frame, f);
5570 record_unwind_protect (unwind_create_tip_frame, frame);
5572 f->terminal = dpyinfo->terminal;
5574 /* By setting the output method, we're essentially saying that
5575 the frame is live, as per FRAME_LIVE_P. If we get a signal
5576 from this point on, x_destroy_window might screw up reference
5577 counts etc. */
5578 f->output_method = output_x_window;
5579 f->output_data.x = xzalloc (sizeof *f->output_data.x);
5580 f->output_data.x->icon_bitmap = -1;
5581 FRAME_FONTSET (f) = -1;
5582 f->output_data.x->scroll_bar_foreground_pixel = -1;
5583 f->output_data.x->scroll_bar_background_pixel = -1;
5584 #if defined (USE_LUCID) && defined (USE_TOOLKIT_SCROLL_BARS)
5585 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
5586 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
5587 #endif /* USE_LUCID && USE_TOOLKIT_SCROLL_BARS */
5588 f->output_data.x->white_relief.pixel = -1;
5589 f->output_data.x->black_relief.pixel = -1;
5591 fset_icon_name (f, Qnil);
5592 FRAME_DISPLAY_INFO (f) = dpyinfo;
5593 f->output_data.x->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
5594 f->output_data.x->explicit_parent = false;
5596 /* These colors will be set anyway later, but it's important
5597 to get the color reference counts right, so initialize them! */
5599 Lisp_Object black;
5601 /* Function x_decode_color can signal an error. Make
5602 sure to initialize color slots so that we won't try
5603 to free colors we haven't allocated. */
5604 FRAME_FOREGROUND_PIXEL (f) = -1;
5605 FRAME_BACKGROUND_PIXEL (f) = -1;
5606 f->output_data.x->cursor_pixel = -1;
5607 f->output_data.x->cursor_foreground_pixel = -1;
5608 f->output_data.x->border_pixel = -1;
5609 f->output_data.x->mouse_pixel = -1;
5611 black = build_string ("black");
5612 FRAME_FOREGROUND_PIXEL (f)
5613 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
5614 FRAME_BACKGROUND_PIXEL (f)
5615 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
5616 f->output_data.x->cursor_pixel
5617 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
5618 f->output_data.x->cursor_foreground_pixel
5619 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
5620 f->output_data.x->border_pixel
5621 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
5622 f->output_data.x->mouse_pixel
5623 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
5626 /* Set the name; the functions to which we pass f expect the name to
5627 be set. */
5628 if (EQ (name, Qunbound) || NILP (name))
5630 fset_name (f, build_string (dpyinfo->x_id_name));
5631 f->explicit_name = false;
5633 else
5635 fset_name (f, name);
5636 f->explicit_name = true;
5637 /* use the frame's title when getting resources for this frame. */
5638 specbind (Qx_resource_name, name);
5641 #ifdef USE_CAIRO
5642 register_font_driver (&ftcrfont_driver, f);
5643 #else
5644 register_font_driver (&xfont_driver, f);
5645 #ifdef HAVE_FREETYPE
5646 #ifdef HAVE_XFT
5647 register_font_driver (&xftfont_driver, f);
5648 #else /* not HAVE_XFT */
5649 register_font_driver (&ftxfont_driver, f);
5650 #endif /* not HAVE_XFT */
5651 #endif /* HAVE_FREETYPE */
5652 #endif /* not USE_CAIRO */
5654 image_cache_refcount =
5655 FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
5656 #ifdef GLYPH_DEBUG
5657 dpyinfo_refcount = dpyinfo->reference_count;
5658 #endif /* GLYPH_DEBUG */
5660 x_default_parameter (f, parms, Qfont_backend, Qnil,
5661 "fontBackend", "FontBackend", RES_TYPE_STRING);
5663 /* Extract the window parameters from the supplied values that are
5664 needed to determine window geometry. */
5665 x_default_font_parameter (f, parms);
5667 x_default_parameter (f, parms, Qborder_width, make_number (0),
5668 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
5670 /* This defaults to 2 in order to match xterm. We recognize either
5671 internalBorderWidth or internalBorder (which is what xterm calls
5672 it). */
5673 if (NILP (Fassq (Qinternal_border_width, parms)))
5675 Lisp_Object value;
5677 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
5678 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
5679 if (! EQ (value, Qunbound))
5680 parms = Fcons (Fcons (Qinternal_border_width, value),
5681 parms);
5684 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
5685 "internalBorderWidth", "internalBorderWidth",
5686 RES_TYPE_NUMBER);
5687 x_default_parameter (f, parms, Qright_divider_width, make_number (0),
5688 NULL, NULL, RES_TYPE_NUMBER);
5689 x_default_parameter (f, parms, Qbottom_divider_width, make_number (0),
5690 NULL, NULL, RES_TYPE_NUMBER);
5692 /* Also do the stuff which must be set before the window exists. */
5693 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
5694 "foreground", "Foreground", RES_TYPE_STRING);
5695 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
5696 "background", "Background", RES_TYPE_STRING);
5697 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
5698 "pointerColor", "Foreground", RES_TYPE_STRING);
5699 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
5700 "cursorColor", "Foreground", RES_TYPE_STRING);
5701 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
5702 "borderColor", "BorderColor", RES_TYPE_STRING);
5704 /* Init faces before x_default_parameter is called for the
5705 scroll-bar-width parameter because otherwise we end up in
5706 init_iterator with a null face cache, which should not happen. */
5707 init_frame_faces (f);
5709 f->output_data.x->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
5711 x_figure_window_size (f, parms, false, &x_width, &x_height);
5714 XSetWindowAttributes attrs;
5715 unsigned long mask;
5716 Atom type = FRAME_DISPLAY_INFO (f)->Xatom_net_window_type_tooltip;
5718 block_input ();
5719 mask = CWBackPixel | CWOverrideRedirect | CWEventMask | CWCursor;
5720 if (DoesSaveUnders (dpyinfo->screen))
5721 mask |= CWSaveUnder;
5723 /* Window managers look at the override-redirect flag to determine
5724 whether or net to give windows a decoration (Xlib spec, chapter
5725 3.2.8). */
5726 attrs.override_redirect = True;
5727 attrs.save_under = True;
5728 attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
5729 attrs.cursor =
5730 f->output_data.x->current_cursor
5731 = f->output_data.x->text_cursor;
5732 /* Arrange for getting MapNotify and UnmapNotify events. */
5733 attrs.event_mask = StructureNotifyMask;
5734 tip_window
5735 = FRAME_X_WINDOW (f)
5736 = XCreateWindow (FRAME_X_DISPLAY (f),
5737 FRAME_DISPLAY_INFO (f)->root_window,
5738 /* x, y, width, height */
5739 0, 0, 1, 1,
5740 /* Border. */
5741 f->border_width,
5742 CopyFromParent, InputOutput, CopyFromParent,
5743 mask, &attrs);
5744 initial_set_up_x_back_buffer (f);
5745 XChangeProperty (FRAME_X_DISPLAY (f), tip_window,
5746 FRAME_DISPLAY_INFO (f)->Xatom_net_window_type,
5747 XA_ATOM, 32, PropModeReplace,
5748 (unsigned char *)&type, 1);
5749 unblock_input ();
5752 x_make_gc (f);
5754 x_default_parameter (f, parms, Qauto_raise, Qnil,
5755 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
5756 x_default_parameter (f, parms, Qauto_lower, Qnil,
5757 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
5758 x_default_parameter (f, parms, Qcursor_type, Qbox,
5759 "cursorType", "CursorType", RES_TYPE_SYMBOL);
5760 x_default_parameter (f, parms, Qalpha, Qnil,
5761 "alpha", "Alpha", RES_TYPE_NUMBER);
5763 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
5764 Change will not be effected unless different from the current
5765 FRAME_LINES (f). */
5766 width = FRAME_COLS (f);
5767 height = FRAME_LINES (f);
5768 SET_FRAME_COLS (f, 0);
5769 SET_FRAME_LINES (f, 0);
5770 change_frame_size (f, width, height, true, false, false, false);
5772 /* Add `tooltip' frame parameter's default value. */
5773 if (NILP (Fframe_parameter (frame, Qtooltip)))
5775 AUTO_FRAME_ARG (arg, Qtooltip, Qt);
5776 Fmodify_frame_parameters (frame, arg);
5779 /* FIXME - can this be done in a similar way to normal frames?
5780 http://lists.gnu.org/archive/html/emacs-devel/2007-10/msg00641.html */
5782 /* Set the `display-type' frame parameter before setting up faces. */
5784 Lisp_Object disptype;
5786 if (FRAME_DISPLAY_INFO (f)->n_planes == 1)
5787 disptype = Qmono;
5788 else if (FRAME_DISPLAY_INFO (f)->visual->class == GrayScale
5789 || FRAME_DISPLAY_INFO (f)->visual->class == StaticGray)
5790 disptype = intern ("grayscale");
5791 else
5792 disptype = intern ("color");
5794 if (NILP (Fframe_parameter (frame, Qdisplay_type)))
5796 AUTO_FRAME_ARG (arg, Qdisplay_type, disptype);
5797 Fmodify_frame_parameters (frame, arg);
5801 /* Set up faces after all frame parameters are known. This call
5802 also merges in face attributes specified for new frames.
5804 Frame parameters may be changed if .Xdefaults contains
5805 specifications for the default font. For example, if there is an
5806 `Emacs.default.attributeBackground: pink', the `background-color'
5807 attribute of the frame get's set, which let's the internal border
5808 of the tooltip frame appear in pink. Prevent this. */
5810 Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
5812 call2 (Qface_set_after_frame_default, frame, Qnil);
5814 if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
5816 AUTO_FRAME_ARG (arg, Qbackground_color, bg);
5817 Fmodify_frame_parameters (frame, arg);
5821 f->no_split = true;
5823 /* Now that the frame will be official, it counts as a reference to
5824 its display and terminal. */
5825 FRAME_DISPLAY_INFO (f)->reference_count++;
5826 f->terminal->reference_count++;
5828 /* It is now ok to make the frame official even if we get an error
5829 below. And the frame needs to be on Vframe_list or making it
5830 visible won't work. */
5831 Vframe_list = Fcons (frame, Vframe_list);
5832 f->can_x_set_window_size = true;
5834 /* Setting attributes of faces of the tooltip frame from resources
5835 and similar will set face_change, which leads to the clearing of
5836 all current matrices. Since this isn't necessary here, avoid it
5837 by resetting face_change to the value it had before we created
5838 the tip frame. */
5839 face_change = face_change_before;
5841 /* Discard the unwind_protect. */
5842 return unbind_to (count, frame);
5846 /* Compute where to display tip frame F. PARMS is the list of frame
5847 parameters for F. DX and DY are specified offsets from the current
5848 location of the mouse. WIDTH and HEIGHT are the width and height
5849 of the tooltip. Return coordinates relative to the root window of
5850 the display in *ROOT_X, and *ROOT_Y. */
5852 static void
5853 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)
5855 Lisp_Object left, top, right, bottom;
5856 int win_x, win_y;
5857 Window root, child;
5858 unsigned pmask;
5859 int min_x, min_y, max_x, max_y = -1;
5861 /* User-specified position? */
5862 left = Fcdr (Fassq (Qleft, parms));
5863 top = Fcdr (Fassq (Qtop, parms));
5864 right = Fcdr (Fassq (Qright, parms));
5865 bottom = Fcdr (Fassq (Qbottom, parms));
5867 /* Move the tooltip window where the mouse pointer is. Resize and
5868 show it. */
5869 if ((!INTEGERP (left) && !INTEGERP (right))
5870 || (!INTEGERP (top) && !INTEGERP (bottom)))
5872 Lisp_Object frame, attributes, monitor, geometry;
5874 block_input ();
5875 XQueryPointer (FRAME_X_DISPLAY (f), FRAME_DISPLAY_INFO (f)->root_window,
5876 &root, &child, root_x, root_y, &win_x, &win_y, &pmask);
5877 unblock_input ();
5879 XSETFRAME(frame, f);
5880 attributes = Fx_display_monitor_attributes_list (frame);
5882 /* Try to determine the monitor where the mouse pointer is and
5883 its geometry. See bug#22549. */
5884 while (CONSP (attributes))
5886 monitor = XCAR (attributes);
5887 geometry = Fassq (Qgeometry, monitor);
5888 if (CONSP (geometry))
5890 min_x = XINT (Fnth (make_number (1), geometry));
5891 min_y = XINT (Fnth (make_number (2), geometry));
5892 max_x = min_x + XINT (Fnth (make_number (3), geometry));
5893 max_y = min_y + XINT (Fnth (make_number (4), geometry));
5894 if (min_x <= *root_x && *root_x < max_x
5895 && min_y <= *root_y && *root_y < max_y)
5897 break;
5899 max_y = -1;
5902 attributes = XCDR (attributes);
5906 /* It was not possible to determine the monitor's geometry, so we
5907 assign some sane defaults here: */
5908 if ( max_y < 0 )
5910 min_x = 0;
5911 min_y = 0;
5912 max_x = x_display_pixel_width (FRAME_DISPLAY_INFO (f));
5913 max_y = x_display_pixel_height (FRAME_DISPLAY_INFO (f));
5916 if (INTEGERP (top))
5917 *root_y = XINT (top);
5918 else if (INTEGERP (bottom))
5919 *root_y = XINT (bottom) - height;
5920 else if (*root_y + XINT (dy) <= min_y)
5921 *root_y = min_y; /* Can happen for negative dy */
5922 else if (*root_y + XINT (dy) + height <= max_y)
5923 /* It fits below the pointer */
5924 *root_y += XINT (dy);
5925 else if (height + XINT (dy) + min_y <= *root_y)
5926 /* It fits above the pointer. */
5927 *root_y -= height + XINT (dy);
5928 else
5929 /* Put it on the top. */
5930 *root_y = min_y;
5932 if (INTEGERP (left))
5933 *root_x = XINT (left);
5934 else if (INTEGERP (right))
5935 *root_x = XINT (right) - width;
5936 else if (*root_x + XINT (dx) <= min_x)
5937 *root_x = 0; /* Can happen for negative dx */
5938 else if (*root_x + XINT (dx) + width <= max_x)
5939 /* It fits to the right of the pointer. */
5940 *root_x += XINT (dx);
5941 else if (width + XINT (dx) + min_x <= *root_x)
5942 /* It fits to the left of the pointer. */
5943 *root_x -= width + XINT (dx);
5944 else
5945 /* Put it left justified on the screen -- it ought to fit that way. */
5946 *root_x = min_x;
5950 /* Hide tooltip. Delete its frame if DELETE is true. */
5951 static Lisp_Object
5952 x_hide_tip (bool delete)
5954 if (!NILP (tip_timer))
5956 call1 (Qcancel_timer, tip_timer);
5957 tip_timer = Qnil;
5961 if (NILP (tip_frame)
5962 || (!delete && FRAMEP (tip_frame)
5963 && !FRAME_VISIBLE_P (XFRAME (tip_frame))))
5964 return Qnil;
5965 else
5967 ptrdiff_t count;
5968 Lisp_Object was_open = Qnil;
5970 count = SPECPDL_INDEX ();
5971 specbind (Qinhibit_redisplay, Qt);
5972 specbind (Qinhibit_quit, Qt);
5974 #ifdef USE_GTK
5976 /* When using system tooltip, tip_frame is the Emacs frame on
5977 which the tip is shown. */
5978 struct frame *f = XFRAME (tip_frame);
5980 if (FRAME_LIVE_P (f) && xg_hide_tooltip (f))
5982 tip_frame = Qnil;
5983 was_open = Qt;
5986 #endif
5988 if (FRAMEP (tip_frame))
5990 if (delete)
5992 delete_frame (tip_frame, Qnil);
5993 tip_frame = Qnil;
5995 else
5996 x_make_frame_invisible (XFRAME (tip_frame));
5998 was_open = Qt;
6000 #ifdef USE_LUCID
6001 /* Bloodcurdling hack alert: The Lucid menu bar widget's
6002 redisplay procedure is not called when a tip frame over
6003 menu items is unmapped. Redisplay the menu manually... */
6005 Widget w;
6006 struct frame *f = SELECTED_FRAME ();
6007 if (FRAME_X_P (f) && FRAME_LIVE_P (f))
6009 w = f->output_data.x->menubar_widget;
6011 if (!DoesSaveUnders (FRAME_DISPLAY_INFO (f)->screen)
6012 && w != NULL)
6014 block_input ();
6015 xlwmenu_redisplay (w);
6016 unblock_input ();
6020 #endif /* USE_LUCID */
6022 else
6023 tip_frame = Qnil;
6025 return unbind_to (count, was_open);
6029 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
6030 doc: /* Show STRING in a "tooltip" window on frame FRAME.
6031 A tooltip window is a small X window displaying a string.
6033 This is an internal function; Lisp code should call `tooltip-show'.
6035 FRAME nil or omitted means use the selected frame.
6037 PARMS is an optional list of frame parameters which can be used to
6038 change the tooltip's appearance.
6040 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
6041 means use the default timeout of 5 seconds.
6043 If the list of frame parameters PARMS contains a `left' parameter,
6044 display the tooltip at that x-position. If the list of frame parameters
6045 PARMS contains no `left' but a `right' parameter, display the tooltip
6046 right-adjusted at that x-position. Otherwise display it at the
6047 x-position of the mouse, with offset DX added (default is 5 if DX isn't
6048 specified).
6050 Likewise for the y-position: If a `top' frame parameter is specified, it
6051 determines the position of the upper edge of the tooltip window. If a
6052 `bottom' parameter but no `top' frame parameter is specified, it
6053 determines the position of the lower edge of the tooltip window.
6054 Otherwise display the tooltip window at the y-position of the mouse,
6055 with offset DY added (default is -10).
6057 A tooltip's maximum size is specified by `x-max-tooltip-size'.
6058 Text larger than the specified size is clipped. */)
6059 (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy)
6061 struct frame *f, *tip_f;
6062 struct window *w;
6063 int root_x, root_y;
6064 struct buffer *old_buffer;
6065 struct text_pos pos;
6066 int width, height;
6067 int old_windows_or_buffers_changed = windows_or_buffers_changed;
6068 ptrdiff_t count = SPECPDL_INDEX ();
6069 ptrdiff_t count_1;
6070 Lisp_Object window, size;
6071 AUTO_STRING (tip, " *tip*");
6073 specbind (Qinhibit_redisplay, Qt);
6075 CHECK_STRING (string);
6076 if (SCHARS (string) == 0)
6077 string = make_unibyte_string (" ", 1);
6079 f = decode_window_system_frame (frame);
6080 if (NILP (timeout))
6081 timeout = make_number (5);
6082 else
6083 CHECK_NATNUM (timeout);
6085 if (NILP (dx))
6086 dx = make_number (5);
6087 else
6088 CHECK_NUMBER (dx);
6090 if (NILP (dy))
6091 dy = make_number (-10);
6092 else
6093 CHECK_NUMBER (dy);
6095 #ifdef USE_GTK
6096 if (x_gtk_use_system_tooltips)
6098 bool ok;
6100 /* Hide a previous tip, if any. */
6101 Fx_hide_tip ();
6103 block_input ();
6104 ok = xg_prepare_tooltip (f, string, &width, &height);
6105 if (ok)
6107 compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
6108 xg_show_tooltip (f, root_x, root_y);
6109 /* This is used in Fx_hide_tip. */
6110 XSETFRAME (tip_frame, f);
6112 unblock_input ();
6113 if (ok) goto start_timer;
6115 #endif /* USE_GTK */
6117 if (NILP (last_show_tip_args))
6118 last_show_tip_args = Fmake_vector (make_number (3), Qnil);
6120 if (FRAMEP (tip_frame) && FRAME_LIVE_P (XFRAME (tip_frame)))
6122 Lisp_Object last_string = AREF (last_show_tip_args, 0);
6123 Lisp_Object last_frame = AREF (last_show_tip_args, 1);
6124 Lisp_Object last_parms = AREF (last_show_tip_args, 2);
6126 if (FRAME_VISIBLE_P (XFRAME (tip_frame))
6127 && EQ (frame, last_frame)
6128 && !NILP (Fequal_including_properties (last_string, string))
6129 && !NILP (Fequal (last_parms, parms)))
6131 /* Only DX and DY have changed. */
6132 tip_f = XFRAME (tip_frame);
6133 if (!NILP (tip_timer))
6135 Lisp_Object timer = tip_timer;
6137 tip_timer = Qnil;
6138 call1 (Qcancel_timer, timer);
6141 block_input ();
6142 compute_tip_xy (tip_f, parms, dx, dy, FRAME_PIXEL_WIDTH (tip_f),
6143 FRAME_PIXEL_HEIGHT (tip_f), &root_x, &root_y);
6144 XMoveWindow (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f),
6145 root_x, root_y);
6146 unblock_input ();
6148 goto start_timer;
6150 else if (tooltip_reuse_hidden_frame && EQ (frame, last_frame))
6152 bool delete = false;
6153 Lisp_Object tail, elt, parm, last;
6155 /* Check if every parameter in PARMS has the same value in
6156 last_parms unless it should be ignored by means of
6157 Vtooltip_reuse_hidden_frame_parameters. This may destruct
6158 last_parms which, however, will be recreated below. */
6159 for (tail = parms; CONSP (tail); tail = XCDR (tail))
6161 elt = XCAR (tail);
6162 parm = Fcar (elt);
6163 /* The left, top, right and bottom parameters are handled
6164 by compute_tip_xy so they can be ignored here. */
6165 if (!EQ (parm, Qleft) && !EQ (parm, Qtop)
6166 && !EQ (parm, Qright) && !EQ (parm, Qbottom))
6168 last = Fassq (parm, last_parms);
6169 if (NILP (Fequal (Fcdr (elt), Fcdr (last))))
6171 /* We lost, delete the old tooltip. */
6172 delete = true;
6173 break;
6175 else
6176 last_parms = call2 (Qassq_delete_all, parm, last_parms);
6178 else
6179 last_parms = call2 (Qassq_delete_all, parm, last_parms);
6182 /* Now check if every parameter in what is left of last_parms
6183 with a non-nil value has an association in PARMS unless it
6184 should be ignored by means of
6185 Vtooltip_reuse_hidden_frame_parameters. */
6186 for (tail = last_parms; CONSP (tail); tail = XCDR (tail))
6188 elt = XCAR (tail);
6189 parm = Fcar (elt);
6190 if (!EQ (parm, Qleft) && !EQ (parm, Qtop) && !EQ (parm, Qright)
6191 && !EQ (parm, Qbottom) && !NILP (Fcdr (elt)))
6193 /* We lost, delete the old tooltip. */
6194 delete = true;
6195 break;
6199 x_hide_tip (delete);
6201 else
6202 x_hide_tip (true);
6204 else
6205 x_hide_tip (true);
6207 ASET (last_show_tip_args, 0, string);
6208 ASET (last_show_tip_args, 1, frame);
6209 ASET (last_show_tip_args, 2, parms);
6211 if (!FRAMEP (tip_frame) || !FRAME_LIVE_P (XFRAME (tip_frame)))
6213 /* Add default values to frame parameters. */
6214 if (NILP (Fassq (Qname, parms)))
6215 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
6216 if (NILP (Fassq (Qinternal_border_width, parms)))
6217 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
6218 if (NILP (Fassq (Qborder_width, parms)))
6219 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
6220 if (NILP (Fassq (Qborder_color, parms)))
6221 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
6222 if (NILP (Fassq (Qbackground_color, parms)))
6223 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
6224 parms);
6226 /* Create a frame for the tooltip, and record it in the global
6227 variable tip_frame. */
6228 if (NILP (tip_frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parms)))
6229 /* Creating the tip frame failed. */
6230 return unbind_to (count, Qnil);
6233 tip_f = XFRAME (tip_frame);
6234 window = FRAME_ROOT_WINDOW (tip_f);
6235 set_window_buffer (window, Fget_buffer_create (tip), false, false);
6236 w = XWINDOW (window);
6237 w->pseudo_window_p = true;
6239 /* Set up the frame's root window. Note: The following code does not
6240 try to size the window or its frame correctly. Its only purpose is
6241 to make the subsequent text size calculations work. The right
6242 sizes should get installed when the toolkit gets back to us. */
6243 w->left_col = 0;
6244 w->top_line = 0;
6245 w->pixel_left = 0;
6246 w->pixel_top = 0;
6248 if (CONSP (Vx_max_tooltip_size)
6249 && RANGED_INTEGERP (1, XCAR (Vx_max_tooltip_size), INT_MAX)
6250 && RANGED_INTEGERP (1, XCDR (Vx_max_tooltip_size), INT_MAX))
6252 w->total_cols = XFASTINT (XCAR (Vx_max_tooltip_size));
6253 w->total_lines = XFASTINT (XCDR (Vx_max_tooltip_size));
6255 else
6257 w->total_cols = 80;
6258 w->total_lines = 40;
6261 w->pixel_width = w->total_cols * FRAME_COLUMN_WIDTH (tip_f);
6262 w->pixel_height = w->total_lines * FRAME_LINE_HEIGHT (tip_f);
6263 FRAME_TOTAL_COLS (tip_f) = w->total_cols;
6264 adjust_frame_glyphs (tip_f);
6266 /* Insert STRING into root window's buffer and fit the frame to the
6267 buffer. */
6268 count_1 = SPECPDL_INDEX ();
6269 old_buffer = current_buffer;
6270 set_buffer_internal_1 (XBUFFER (w->contents));
6271 bset_truncate_lines (current_buffer, Qnil);
6272 specbind (Qinhibit_read_only, Qt);
6273 specbind (Qinhibit_modification_hooks, Qt);
6274 specbind (Qinhibit_point_motion_hooks, Qt);
6275 Ferase_buffer ();
6276 Finsert (1, &string);
6277 clear_glyph_matrix (w->desired_matrix);
6278 clear_glyph_matrix (w->current_matrix);
6279 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
6280 try_window (window, pos, TRY_WINDOW_IGNORE_FONTS_CHANGE);
6281 /* Calculate size of tooltip window. */
6282 size = Fwindow_text_pixel_size (window, Qnil, Qnil, Qnil,
6283 make_number (w->pixel_height), Qnil);
6284 /* Add the frame's internal border to calculated size. */
6285 width = XINT (Fcar (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
6286 height = XINT (Fcdr (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
6288 /* Calculate position of tooltip frame. */
6289 compute_tip_xy (tip_f, parms, dx, dy, width, height, &root_x, &root_y);
6291 /* Show tooltip frame. */
6292 block_input ();
6293 XMoveResizeWindow (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f),
6294 root_x, root_y, width, height);
6295 XMapRaised (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f));
6296 unblock_input ();
6298 w->must_be_updated_p = true;
6299 update_single_window (w);
6300 set_buffer_internal_1 (old_buffer);
6301 unbind_to (count_1, Qnil);
6302 windows_or_buffers_changed = old_windows_or_buffers_changed;
6304 start_timer:
6305 /* Let the tip disappear after timeout seconds. */
6306 tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
6307 intern ("x-hide-tip"));
6309 return unbind_to (count, Qnil);
6313 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
6314 doc: /* Hide the current tooltip window, if there is any.
6315 Value is t if tooltip was open, nil otherwise. */)
6316 (void)
6318 return x_hide_tip (!tooltip_reuse_hidden_frame);
6321 DEFUN ("x-double-buffered-p", Fx_double_buffered_p, Sx_double_buffered_p,
6322 0, 1, 0,
6323 doc: /* Return t if FRAME is being double buffered. */)
6324 (Lisp_Object frame)
6326 struct frame *f = decode_live_frame (frame);
6327 return FRAME_X_DOUBLE_BUFFERED_P (f) ? Qt : Qnil;
6331 /***********************************************************************
6332 File selection dialog
6333 ***********************************************************************/
6335 DEFUN ("x-uses-old-gtk-dialog", Fx_uses_old_gtk_dialog,
6336 Sx_uses_old_gtk_dialog,
6337 0, 0, 0,
6338 doc: /* Return t if the old Gtk+ file selection dialog is used. */)
6339 (void)
6341 #ifdef USE_GTK
6342 if (use_dialog_box
6343 && use_file_dialog
6344 && window_system_available (SELECTED_FRAME ())
6345 && xg_uses_old_file_dialog ())
6346 return Qt;
6347 #endif
6348 return Qnil;
6352 #ifdef USE_MOTIF
6353 /* Callback for "OK" and "Cancel" on file selection dialog. */
6355 static void
6356 file_dialog_cb (Widget widget, XtPointer client_data, XtPointer call_data)
6358 int *result = client_data;
6359 XmAnyCallbackStruct *cb = call_data;
6360 *result = cb->reason;
6364 /* Callback for unmapping a file selection dialog. This is used to
6365 capture the case where a dialog is closed via a window manager's
6366 closer button, for example. Using a XmNdestroyCallback didn't work
6367 in this case. */
6369 static void
6370 file_dialog_unmap_cb (Widget widget, XtPointer client_data, XtPointer call_data)
6372 int *result = client_data;
6373 *result = XmCR_CANCEL;
6376 static void
6377 clean_up_file_dialog (void *arg)
6379 Widget dialog = arg;
6381 /* Clean up. */
6382 block_input ();
6383 XtUnmanageChild (dialog);
6384 XtDestroyWidget (dialog);
6385 x_menu_set_in_use (false);
6386 unblock_input ();
6390 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
6391 doc: /* Read file name, prompting with PROMPT in directory DIR.
6392 Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file
6393 selection box, if specified. If MUSTMATCH is non-nil, the returned file
6394 or directory must exist.
6396 This function is only defined on NS, MS Windows, and X Windows with the
6397 Motif or Gtk toolkits. With the Motif toolkit, ONLY-DIR-P is ignored.
6398 Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories.
6399 On Windows 7 and later, the file selection dialog "remembers" the last
6400 directory where the user selected a file, and will open that directory
6401 instead of DIR on subsequent invocations of this function with the same
6402 value of DIR as in previous invocations; this is standard Windows behavior. */)
6403 (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename,
6404 Lisp_Object mustmatch, Lisp_Object only_dir_p)
6406 int result;
6407 struct frame *f = SELECTED_FRAME ();
6408 Lisp_Object file = Qnil;
6409 Lisp_Object decoded_file;
6410 Widget dialog, text, help;
6411 Arg al[10];
6412 int ac = 0;
6413 XmString dir_xmstring, pattern_xmstring;
6414 ptrdiff_t count = SPECPDL_INDEX ();
6416 check_window_system (f);
6418 if (popup_activated ())
6419 error ("Trying to use a menu from within a menu-entry");
6421 CHECK_STRING (prompt);
6422 CHECK_STRING (dir);
6424 /* Prevent redisplay. */
6425 specbind (Qinhibit_redisplay, Qt);
6427 block_input ();
6429 /* Create the dialog with PROMPT as title, using DIR as initial
6430 directory and using "*" as pattern. */
6431 dir = Fexpand_file_name (dir, Qnil);
6432 dir_xmstring = XmStringCreateLocalized (SSDATA (dir));
6433 pattern_xmstring = XmStringCreateLocalized ("*");
6435 XtSetArg (al[ac], XmNtitle, SDATA (prompt)); ++ac;
6436 XtSetArg (al[ac], XmNdirectory, dir_xmstring); ++ac;
6437 XtSetArg (al[ac], XmNpattern, pattern_xmstring); ++ac;
6438 XtSetArg (al[ac], XmNresizePolicy, XmRESIZE_GROW); ++ac;
6439 XtSetArg (al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ++ac;
6440 dialog = XmCreateFileSelectionDialog (f->output_data.x->widget,
6441 "fsb", al, ac);
6442 XmStringFree (dir_xmstring);
6443 XmStringFree (pattern_xmstring);
6445 /* Add callbacks for OK and Cancel. */
6446 XtAddCallback (dialog, XmNokCallback, file_dialog_cb,
6447 (XtPointer) &result);
6448 XtAddCallback (dialog, XmNcancelCallback, file_dialog_cb,
6449 (XtPointer) &result);
6450 XtAddCallback (dialog, XmNunmapCallback, file_dialog_unmap_cb,
6451 (XtPointer) &result);
6453 /* Remove the help button since we can't display help. */
6454 help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON);
6455 XtUnmanageChild (help);
6457 /* Mark OK button as default. */
6458 XtVaSetValues (XmFileSelectionBoxGetChild (dialog, XmDIALOG_OK_BUTTON),
6459 XmNshowAsDefault, True, NULL);
6461 /* If MUSTMATCH is non-nil, disable the file entry field of the
6462 dialog, so that the user must select a file from the files list
6463 box. We can't remove it because we wouldn't have a way to get at
6464 the result file name, then. */
6465 text = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
6466 if (!NILP (mustmatch))
6468 Widget label;
6469 label = XmFileSelectionBoxGetChild (dialog, XmDIALOG_SELECTION_LABEL);
6470 XtSetSensitive (text, False);
6471 XtSetSensitive (label, False);
6474 /* Manage the dialog, so that list boxes get filled. */
6475 XtManageChild (dialog);
6477 if (STRINGP (default_filename))
6479 XmString default_xmstring;
6480 Widget wtext = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
6481 Widget list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
6483 XmTextPosition last_pos = XmTextFieldGetLastPosition (wtext);
6484 XmTextFieldReplace (wtext, 0, last_pos,
6485 (SSDATA (Ffile_name_nondirectory (default_filename))));
6487 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
6488 must include the path for this to work. */
6490 default_xmstring = XmStringCreateLocalized (SSDATA (default_filename));
6492 if (XmListItemExists (list, default_xmstring))
6494 int item_pos = XmListItemPos (list, default_xmstring);
6495 /* Select the item and scroll it into view. */
6496 XmListSelectPos (list, item_pos, True);
6497 XmListSetPos (list, item_pos);
6500 XmStringFree (default_xmstring);
6503 record_unwind_protect_ptr (clean_up_file_dialog, dialog);
6505 /* Process events until the user presses Cancel or OK. */
6506 x_menu_set_in_use (true);
6507 result = 0;
6508 while (result == 0)
6510 XEvent event;
6511 x_menu_wait_for_event (0);
6512 XtAppNextEvent (Xt_app_con, &event);
6513 if (event.type == KeyPress
6514 && FRAME_X_DISPLAY (f) == event.xkey.display)
6516 KeySym keysym = XLookupKeysym (&event.xkey, 0);
6518 /* Pop down on C-g. */
6519 if (keysym == XK_g && (event.xkey.state & ControlMask) != 0)
6520 XtUnmanageChild (dialog);
6523 (void) x_dispatch_event (&event, FRAME_X_DISPLAY (f));
6526 /* Get the result. */
6527 if (result == XmCR_OK)
6529 XmString text_string;
6530 String data;
6532 XtVaGetValues (dialog, XmNtextString, &text_string, NULL);
6533 XmStringGetLtoR (text_string, XmFONTLIST_DEFAULT_TAG, &data);
6534 XmStringFree (text_string);
6535 file = build_string (data);
6536 XtFree (data);
6538 else
6539 file = Qnil;
6541 unblock_input ();
6543 /* Make "Cancel" equivalent to C-g. */
6544 if (NILP (file))
6545 quit ();
6547 decoded_file = DECODE_FILE (file);
6549 return unbind_to (count, decoded_file);
6552 #endif /* USE_MOTIF */
6554 #ifdef USE_GTK
6556 static void
6557 clean_up_dialog (void)
6559 x_menu_set_in_use (false);
6562 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
6563 doc: /* Read file name, prompting with PROMPT in directory DIR.
6564 Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file
6565 selection box, if specified. If MUSTMATCH is non-nil, the returned file
6566 or directory must exist.
6568 This function is only defined on NS, MS Windows, and X Windows with the
6569 Motif or Gtk toolkits. With the Motif toolkit, ONLY-DIR-P is ignored.
6570 Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories.
6571 On Windows 7 and later, the file selection dialog "remembers" the last
6572 directory where the user selected a file, and will open that directory
6573 instead of DIR on subsequent invocations of this function with the same
6574 value of DIR as in previous invocations; this is standard Windows behavior. */)
6575 (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename, Lisp_Object mustmatch, Lisp_Object only_dir_p)
6577 struct frame *f = SELECTED_FRAME ();
6578 char *fn;
6579 Lisp_Object file = Qnil;
6580 Lisp_Object decoded_file;
6581 ptrdiff_t count = SPECPDL_INDEX ();
6582 char *cdef_file;
6584 check_window_system (f);
6586 if (popup_activated ())
6587 error ("Trying to use a menu from within a menu-entry");
6589 CHECK_STRING (prompt);
6590 CHECK_STRING (dir);
6592 /* Prevent redisplay. */
6593 specbind (Qinhibit_redisplay, Qt);
6594 record_unwind_protect_void (clean_up_dialog);
6596 block_input ();
6598 if (STRINGP (default_filename))
6599 cdef_file = SSDATA (default_filename);
6600 else
6601 cdef_file = SSDATA (dir);
6603 fn = xg_get_file_name (f, SSDATA (prompt), cdef_file,
6604 ! NILP (mustmatch),
6605 ! NILP (only_dir_p));
6607 if (fn)
6609 file = build_string (fn);
6610 xfree (fn);
6613 unblock_input ();
6615 /* Make "Cancel" equivalent to C-g. */
6616 if (NILP (file))
6617 quit ();
6619 decoded_file = DECODE_FILE (file);
6621 return unbind_to (count, decoded_file);
6625 #ifdef HAVE_FREETYPE
6627 DEFUN ("x-select-font", Fx_select_font, Sx_select_font, 0, 2, 0,
6628 doc: /* Read a font using a GTK dialog.
6629 Return either a font spec (for GTK versions >= 3.2) or a string
6630 containing a GTK-style font name.
6632 FRAME is the frame on which to pop up the font chooser. If omitted or
6633 nil, it defaults to the selected frame. */)
6634 (Lisp_Object frame, Lisp_Object ignored)
6636 struct frame *f = decode_window_system_frame (frame);
6637 Lisp_Object font;
6638 Lisp_Object font_param;
6639 char *default_name = NULL;
6640 ptrdiff_t count = SPECPDL_INDEX ();
6642 if (popup_activated ())
6643 error ("Trying to use a menu from within a menu-entry");
6645 /* Prevent redisplay. */
6646 specbind (Qinhibit_redisplay, Qt);
6647 record_unwind_protect_void (clean_up_dialog);
6649 block_input ();
6651 XSETFONT (font, FRAME_FONT (f));
6652 font_param = Ffont_get (font, QCname);
6653 if (STRINGP (font_param))
6654 default_name = xlispstrdup (font_param);
6655 else
6657 font_param = Fframe_parameter (frame, Qfont_parameter);
6658 if (STRINGP (font_param))
6659 default_name = xlispstrdup (font_param);
6662 font = xg_get_font (f, default_name);
6663 xfree (default_name);
6665 unblock_input ();
6667 if (NILP (font))
6668 quit ();
6670 return unbind_to (count, font);
6672 #endif /* HAVE_FREETYPE */
6674 #endif /* USE_GTK */
6677 /***********************************************************************
6678 Keyboard
6679 ***********************************************************************/
6681 #ifdef HAVE_XKB
6682 #include <X11/XKBlib.h>
6683 #include <X11/keysym.h>
6684 #endif
6686 DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p,
6687 Sx_backspace_delete_keys_p, 0, 1, 0,
6688 doc: /* Check if both Backspace and Delete keys are on the keyboard of FRAME.
6689 FRAME nil means use the selected frame.
6690 Value is t if we know that both keys are present, and are mapped to the
6691 usual X keysyms. Value is `lambda' if we cannot determine if both keys are
6692 present and mapped to the usual X keysyms. */)
6693 (Lisp_Object frame)
6695 #ifndef HAVE_XKB
6696 return Qlambda;
6697 #else
6698 XkbDescPtr kb;
6699 struct frame *f = decode_window_system_frame (frame);
6700 Display *dpy = FRAME_X_DISPLAY (f);
6701 Lisp_Object have_keys;
6702 int major, minor, op, event, error_code;
6704 block_input ();
6706 /* Check library version in case we're dynamically linked. */
6707 major = XkbMajorVersion;
6708 minor = XkbMinorVersion;
6709 if (!XkbLibraryVersion (&major, &minor))
6711 unblock_input ();
6712 return Qlambda;
6715 /* Check that the server supports XKB. */
6716 major = XkbMajorVersion;
6717 minor = XkbMinorVersion;
6718 if (!XkbQueryExtension (dpy, &op, &event, &error_code, &major, &minor))
6720 unblock_input ();
6721 return Qlambda;
6724 /* In this code we check that the keyboard has physical keys with names
6725 that start with BKSP (Backspace) and DELE (Delete), and that they
6726 generate keysym XK_BackSpace and XK_Delete respectively.
6727 This function is used to test if normal-erase-is-backspace should be
6728 turned on.
6729 An alternative approach would be to just check if XK_BackSpace and
6730 XK_Delete are mapped to any key. But if any of those are mapped to
6731 some non-intuitive key combination (Meta-Shift-Ctrl-whatever) and the
6732 user doesn't know about it, it is better to return false here.
6733 It is more obvious to the user what to do if she/he has two keys
6734 clearly marked with names/symbols and one key does something not
6735 expected (i.e. she/he then tries the other).
6736 The cases where Backspace/Delete is mapped to some other key combination
6737 are rare, and in those cases, normal-erase-is-backspace can be turned on
6738 manually. */
6740 have_keys = Qnil;
6741 kb = XkbGetMap (dpy, XkbAllMapComponentsMask, XkbUseCoreKbd);
6742 if (kb)
6744 int delete_keycode = 0, backspace_keycode = 0, i;
6746 if (XkbGetNames (dpy, XkbAllNamesMask, kb) == Success)
6748 for (i = kb->min_key_code;
6749 (i < kb->max_key_code
6750 && (delete_keycode == 0 || backspace_keycode == 0));
6751 ++i)
6753 /* The XKB symbolic key names can be seen most easily in
6754 the PS file generated by `xkbprint -label name
6755 $DISPLAY'. */
6756 if (memcmp ("DELE", kb->names->keys[i].name, 4) == 0)
6757 delete_keycode = i;
6758 else if (memcmp ("BKSP", kb->names->keys[i].name, 4) == 0)
6759 backspace_keycode = i;
6762 XkbFreeNames (kb, 0, True);
6765 /* As of libX11-1.6.2, XkbGetMap manual says that you should use
6766 XkbFreeClientMap to free the data returned by XkbGetMap. But
6767 this function just frees the data referenced from KB and not
6768 KB itself. To free KB as well, call XkbFreeKeyboard. */
6769 XkbFreeKeyboard (kb, XkbAllMapComponentsMask, True);
6771 if (delete_keycode
6772 && backspace_keycode
6773 && XKeysymToKeycode (dpy, XK_Delete) == delete_keycode
6774 && XKeysymToKeycode (dpy, XK_BackSpace) == backspace_keycode)
6775 have_keys = Qt;
6777 unblock_input ();
6778 return have_keys;
6779 #endif
6784 /***********************************************************************
6785 Printing
6786 ***********************************************************************/
6788 #ifdef USE_CAIRO
6789 DEFUN ("x-export-frames", Fx_export_frames, Sx_export_frames, 0, 2, 0,
6790 doc: /* Return image data of FRAMES in TYPE format.
6791 FRAMES should be nil (the selected frame), a frame, or a list of
6792 frames (each of which corresponds to one page). Each frame should be
6793 visible. Optional arg TYPE should be either `pdf' (default), `png',
6794 `postscript', or `svg'. Supported types are determined by the
6795 compile-time configuration of cairo. */)
6796 (Lisp_Object frames, Lisp_Object type)
6798 Lisp_Object rest, tmp;
6799 cairo_surface_type_t surface_type;
6801 if (!CONSP (frames))
6802 frames = list1 (frames);
6804 tmp = Qnil;
6805 for (rest = frames; CONSP (rest); rest = XCDR (rest))
6807 struct frame *f = decode_window_system_frame (XCAR (rest));
6808 Lisp_Object frame;
6810 XSETFRAME (frame, f);
6811 if (!FRAME_VISIBLE_P (f))
6812 error ("Frames to be exported must be visible.");
6813 tmp = Fcons (frame, tmp);
6815 frames = Fnreverse (tmp);
6817 #ifdef CAIRO_HAS_PDF_SURFACE
6818 if (NILP (type) || EQ (type, Qpdf))
6819 surface_type = CAIRO_SURFACE_TYPE_PDF;
6820 else
6821 #endif
6822 #ifdef CAIRO_HAS_PNG_FUNCTIONS
6823 if (EQ (type, Qpng))
6825 if (!NILP (XCDR (frames)))
6826 error ("PNG export cannot handle multiple frames.");
6827 surface_type = CAIRO_SURFACE_TYPE_IMAGE;
6829 else
6830 #endif
6831 #ifdef CAIRO_HAS_PS_SURFACE
6832 if (EQ (type, Qpostscript))
6833 surface_type = CAIRO_SURFACE_TYPE_PS;
6834 else
6835 #endif
6836 #ifdef CAIRO_HAS_SVG_SURFACE
6837 if (EQ (type, Qsvg))
6839 /* For now, we stick to SVG 1.1. */
6840 if (!NILP (XCDR (frames)))
6841 error ("SVG export cannot handle multiple frames.");
6842 surface_type = CAIRO_SURFACE_TYPE_SVG;
6844 else
6845 #endif
6846 error ("Unsupported export type");
6848 return x_cr_export_frames (frames, surface_type);
6851 #ifdef USE_GTK
6852 DEFUN ("x-page-setup-dialog", Fx_page_setup_dialog, Sx_page_setup_dialog, 0, 0, 0,
6853 doc: /* Pop up a page setup dialog.
6854 The current page setup can be obtained using `x-get-page-setup'. */)
6855 (void)
6857 block_input ();
6858 xg_page_setup_dialog ();
6859 unblock_input ();
6861 return Qnil;
6864 DEFUN ("x-get-page-setup", Fx_get_page_setup, Sx_get_page_setup, 0, 0, 0,
6865 doc: /* Return the value of the current page setup.
6866 The return value is an alist containing the following keys:
6868 orientation: page orientation (symbol `portrait', `landscape',
6869 `reverse-portrait', or `reverse-landscape').
6870 width, height: page width/height in points not including margins.
6871 left-margin, right-margin, top-margin, bottom-margin: print margins,
6872 which is the parts of the page that the printer cannot print
6873 on, in points.
6875 The paper width can be obtained as the sum of width, left-margin, and
6876 right-margin values if the page orientation is `portrait' or
6877 `reverse-portrait'. Otherwise, it is the sum of width, top-margin,
6878 and bottom-margin values. Likewise, the paper height is the sum of
6879 height, top-margin, and bottom-margin values if the page orientation
6880 is `portrait' or `reverse-portrait'. Otherwise, it is the sum of
6881 height, left-margin, and right-margin values. */)
6882 (void)
6884 Lisp_Object result;
6886 block_input ();
6887 result = xg_get_page_setup ();
6888 unblock_input ();
6890 return result;
6893 DEFUN ("x-print-frames-dialog", Fx_print_frames_dialog, Sx_print_frames_dialog, 0, 1, "",
6894 doc: /* Pop up a print dialog to print the current contents of FRAMES.
6895 FRAMES should be nil (the selected frame), a frame, or a list of
6896 frames (each of which corresponds to one page). Each frame should be
6897 visible. */)
6898 (Lisp_Object frames)
6900 Lisp_Object rest, tmp;
6901 int count;
6903 if (!CONSP (frames))
6904 frames = list1 (frames);
6906 tmp = Qnil;
6907 for (rest = frames; CONSP (rest); rest = XCDR (rest))
6909 struct frame *f = decode_window_system_frame (XCAR (rest));
6910 Lisp_Object frame;
6912 XSETFRAME (frame, f);
6913 if (!FRAME_VISIBLE_P (f))
6914 error ("Frames to be printed must be visible.");
6915 tmp = Fcons (frame, tmp);
6917 frames = Fnreverse (tmp);
6919 /* Make sure the current matrices are up-to-date. */
6920 count = SPECPDL_INDEX ();
6921 specbind (Qredisplay_dont_pause, Qt);
6922 redisplay_preserve_echo_area (32);
6923 unbind_to (count, Qnil);
6925 block_input ();
6926 xg_print_frames_dialog (frames);
6927 unblock_input ();
6929 return Qnil;
6931 #endif /* USE_GTK */
6932 #endif /* USE_CAIRO */
6935 /***********************************************************************
6936 Initialization
6937 ***********************************************************************/
6939 /* Keep this list in the same order as frame_parms in frame.c.
6940 Use 0 for unsupported frame parameters. */
6942 frame_parm_handler x_frame_parm_handlers[] =
6944 x_set_autoraise,
6945 x_set_autolower,
6946 x_set_background_color,
6947 x_set_border_color,
6948 x_set_border_width,
6949 x_set_cursor_color,
6950 x_set_cursor_type,
6951 x_set_font,
6952 x_set_foreground_color,
6953 x_set_icon_name,
6954 x_set_icon_type,
6955 x_set_internal_border_width,
6956 x_set_right_divider_width,
6957 x_set_bottom_divider_width,
6958 x_set_menu_bar_lines,
6959 x_set_mouse_color,
6960 x_explicitly_set_name,
6961 x_set_scroll_bar_width,
6962 x_set_scroll_bar_height,
6963 x_set_title,
6964 x_set_unsplittable,
6965 x_set_vertical_scroll_bars,
6966 x_set_horizontal_scroll_bars,
6967 x_set_visibility,
6968 x_set_tool_bar_lines,
6969 x_set_scroll_bar_foreground,
6970 x_set_scroll_bar_background,
6971 x_set_screen_gamma,
6972 x_set_line_spacing,
6973 x_set_left_fringe,
6974 x_set_right_fringe,
6975 x_set_wait_for_wm,
6976 x_set_fullscreen,
6977 x_set_font_backend,
6978 x_set_alpha,
6979 x_set_sticky,
6980 x_set_tool_bar_position,
6981 x_set_inhibit_double_buffering,
6984 void
6985 syms_of_xfns (void)
6987 DEFSYM (Qundefined_color, "undefined-color");
6988 DEFSYM (Qcompound_text, "compound-text");
6989 DEFSYM (Qcancel_timer, "cancel-timer");
6990 DEFSYM (Qfont_parameter, "font-parameter");
6991 DEFSYM (Qmono, "mono");
6992 DEFSYM (Qassq_delete_all, "assq-delete-all");
6994 #ifdef USE_CAIRO
6995 DEFSYM (Qpdf, "pdf");
6997 DEFSYM (Qorientation, "orientation");
6998 DEFSYM (Qtop_margin, "top-margin");
6999 DEFSYM (Qbottom_margin, "bottom-margin");
7000 DEFSYM (Qportrait, "portrait");
7001 DEFSYM (Qlandscape, "landscape");
7002 DEFSYM (Qreverse_portrait, "reverse-portrait");
7003 DEFSYM (Qreverse_landscape, "reverse-landscape");
7004 #endif
7006 Fput (Qundefined_color, Qerror_conditions,
7007 listn (CONSTYPE_PURE, 2, Qundefined_color, Qerror));
7008 Fput (Qundefined_color, Qerror_message,
7009 build_pure_c_string ("Undefined color"));
7011 DEFVAR_LISP ("x-pointer-shape", Vx_pointer_shape,
7012 doc: /* The shape of the pointer when over text.
7013 Changing the value does not affect existing frames
7014 unless you set the mouse color. */);
7015 Vx_pointer_shape = Qnil;
7017 #if false /* This doesn't really do anything. */
7018 DEFVAR_LISP ("x-nontext-pointer-shape", Vx_nontext_pointer_shape,
7019 doc: /* The shape of the pointer when not over text.
7020 This variable takes effect when you create a new frame
7021 or when you set the mouse color. */);
7022 #endif
7023 Vx_nontext_pointer_shape = Qnil;
7025 DEFVAR_LISP ("x-hourglass-pointer-shape", Vx_hourglass_pointer_shape,
7026 doc: /* The shape of the pointer when Emacs is busy.
7027 This variable takes effect when you create a new frame
7028 or when you set the mouse color. */);
7029 Vx_hourglass_pointer_shape = Qnil;
7031 #if false /* This doesn't really do anything. */
7032 DEFVAR_LISP ("x-mode-pointer-shape", Vx_mode_pointer_shape,
7033 doc: /* The shape of the pointer when over the mode line.
7034 This variable takes effect when you create a new frame
7035 or when you set the mouse color. */);
7036 #endif
7037 Vx_mode_pointer_shape = Qnil;
7039 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
7040 Vx_sensitive_text_pointer_shape,
7041 doc: /* The shape of the pointer when over mouse-sensitive text.
7042 This variable takes effect when you create a new frame
7043 or when you set the mouse color. */);
7044 Vx_sensitive_text_pointer_shape = Qnil;
7046 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
7047 Vx_window_horizontal_drag_shape,
7048 doc: /* Pointer shape to use for indicating a window can be dragged horizontally.
7049 This variable takes effect when you create a new frame
7050 or when you set the mouse color. */);
7051 Vx_window_horizontal_drag_shape = Qnil;
7053 DEFVAR_LISP ("x-window-vertical-drag-cursor",
7054 Vx_window_vertical_drag_shape,
7055 doc: /* Pointer shape to use for indicating a window can be dragged vertically.
7056 This variable takes effect when you create a new frame
7057 or when you set the mouse color. */);
7058 Vx_window_vertical_drag_shape = Qnil;
7060 DEFVAR_LISP ("x-cursor-fore-pixel", Vx_cursor_fore_pixel,
7061 doc: /* A string indicating the foreground color of the cursor box. */);
7062 Vx_cursor_fore_pixel = Qnil;
7064 DEFVAR_LISP ("x-max-tooltip-size", Vx_max_tooltip_size,
7065 doc: /* Maximum size for tooltips.
7066 Value is a pair (COLUMNS . ROWS). Text larger than this is clipped. */);
7067 Vx_max_tooltip_size = Fcons (make_number (80), make_number (40));
7069 DEFVAR_LISP ("x-no-window-manager", Vx_no_window_manager,
7070 doc: /* Non-nil if no X window manager is in use.
7071 Emacs doesn't try to figure this out; this is always nil
7072 unless you set it to something else. */);
7073 /* We don't have any way to find this out, so set it to nil
7074 and maybe the user would like to set it to t. */
7075 Vx_no_window_manager = Qnil;
7077 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
7078 Vx_pixel_size_width_font_regexp,
7079 doc: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
7081 Since Emacs gets width of a font matching with this regexp from
7082 PIXEL_SIZE field of the name, font finding mechanism gets faster for
7083 such a font. This is especially effective for such large fonts as
7084 Chinese, Japanese, and Korean. */);
7085 Vx_pixel_size_width_font_regexp = Qnil;
7087 /* This is not ifdef:ed, so other builds than GTK can customize it. */
7088 DEFVAR_BOOL ("x-gtk-use-old-file-dialog", x_gtk_use_old_file_dialog,
7089 doc: /* Non-nil means prompt with the old GTK file selection dialog.
7090 If nil or if the file selection dialog is not available, the new GTK file
7091 chooser is used instead. To turn off all file dialogs set the
7092 variable `use-file-dialog'. */);
7093 x_gtk_use_old_file_dialog = false;
7095 DEFVAR_BOOL ("x-gtk-show-hidden-files", x_gtk_show_hidden_files,
7096 doc: /* If non-nil, the GTK file chooser will by default show hidden files.
7097 Note that this is just the default, there is a toggle button on the file
7098 chooser to show or not show hidden files on a case by case basis. */);
7099 x_gtk_show_hidden_files = false;
7101 DEFVAR_BOOL ("x-gtk-file-dialog-help-text", x_gtk_file_dialog_help_text,
7102 doc: /* If non-nil, the GTK file chooser will show additional help text.
7103 If more space for files in the file chooser dialog is wanted, set this to nil
7104 to turn the additional text off. */);
7105 x_gtk_file_dialog_help_text = true;
7107 DEFVAR_BOOL ("x-gtk-use-system-tooltips", x_gtk_use_system_tooltips,
7108 doc: /* If non-nil with a Gtk+ built Emacs, the Gtk+ tooltip is used.
7109 Otherwise use Emacs own tooltip implementation.
7110 When using Gtk+ tooltips, the tooltip face is not used. */);
7111 x_gtk_use_system_tooltips = true;
7113 /* Tell Emacs about this window system. */
7114 Fprovide (Qx, Qnil);
7116 #ifdef USE_X_TOOLKIT
7117 Fprovide (intern_c_string ("x-toolkit"), Qnil);
7118 #ifdef USE_MOTIF
7119 Fprovide (intern_c_string ("motif"), Qnil);
7121 DEFVAR_LISP ("motif-version-string", Vmotif_version_string,
7122 doc: /* Version info for LessTif/Motif. */);
7123 Vmotif_version_string = build_string (XmVERSION_STRING);
7124 #endif /* USE_MOTIF */
7125 #endif /* USE_X_TOOLKIT */
7127 #ifdef USE_GTK
7128 /* Provide x-toolkit also for GTK. Internally GTK does not use Xt so it
7129 is not an X toolkit in that sense (USE_X_TOOLKIT is not defined).
7130 But for a user it is a toolkit for X, and indeed, configure
7131 accepts --with-x-toolkit=gtk. */
7132 Fprovide (intern_c_string ("x-toolkit"), Qnil);
7133 Fprovide (intern_c_string ("gtk"), Qnil);
7134 Fprovide (intern_c_string ("move-toolbar"), Qnil);
7136 DEFVAR_LISP ("gtk-version-string", Vgtk_version_string,
7137 doc: /* Version info for GTK+. */);
7139 char gtk_version[sizeof ".." + 3 * INT_STRLEN_BOUND (int)];
7140 int len = sprintf (gtk_version, "%d.%d.%d",
7141 GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION);
7142 Vgtk_version_string = make_pure_string (gtk_version, len, len, false);
7144 #endif /* USE_GTK */
7146 #ifdef USE_CAIRO
7147 Fprovide (intern_c_string ("cairo"), Qnil);
7149 DEFVAR_LISP ("cairo-version-string", Vcairo_version_string,
7150 doc: /* Version info for cairo. */);
7152 char cairo_version[sizeof ".." + 3 * INT_STRLEN_BOUND (int)];
7153 int len = sprintf (cairo_version, "%d.%d.%d",
7154 CAIRO_VERSION_MAJOR, CAIRO_VERSION_MINOR,
7155 CAIRO_VERSION_MICRO);
7156 Vcairo_version_string = make_pure_string (cairo_version, len, len, false);
7158 #endif
7160 /* X window properties. */
7161 defsubr (&Sx_change_window_property);
7162 defsubr (&Sx_delete_window_property);
7163 defsubr (&Sx_window_property);
7164 defsubr (&Sx_window_property_attributes);
7166 defsubr (&Sxw_display_color_p);
7167 defsubr (&Sx_display_grayscale_p);
7168 defsubr (&Sxw_color_defined_p);
7169 defsubr (&Sxw_color_values);
7170 defsubr (&Sx_server_max_request_size);
7171 defsubr (&Sx_server_vendor);
7172 defsubr (&Sx_server_version);
7173 defsubr (&Sx_display_pixel_width);
7174 defsubr (&Sx_display_pixel_height);
7175 defsubr (&Sx_display_mm_width);
7176 defsubr (&Sx_display_mm_height);
7177 defsubr (&Sx_display_screens);
7178 defsubr (&Sx_display_planes);
7179 defsubr (&Sx_display_color_cells);
7180 defsubr (&Sx_display_visual_class);
7181 defsubr (&Sx_display_backing_store);
7182 defsubr (&Sx_display_save_under);
7183 defsubr (&Sx_display_monitor_attributes_list);
7184 defsubr (&Sx_frame_geometry);
7185 defsubr (&Sx_frame_edges);
7186 defsubr (&Sx_mouse_absolute_pixel_position);
7187 defsubr (&Sx_set_mouse_absolute_pixel_position);
7188 defsubr (&Sx_wm_set_size_hint);
7189 defsubr (&Sx_create_frame);
7190 defsubr (&Sx_open_connection);
7191 defsubr (&Sx_close_connection);
7192 defsubr (&Sx_display_list);
7193 defsubr (&Sx_synchronize);
7194 defsubr (&Sx_backspace_delete_keys_p);
7196 defsubr (&Sx_show_tip);
7197 defsubr (&Sx_hide_tip);
7198 defsubr (&Sx_double_buffered_p);
7199 tip_timer = Qnil;
7200 staticpro (&tip_timer);
7201 tip_frame = Qnil;
7202 staticpro (&tip_frame);
7204 last_show_tip_args = Qnil;
7205 staticpro (&last_show_tip_args);
7207 defsubr (&Sx_uses_old_gtk_dialog);
7208 #if defined (USE_MOTIF) || defined (USE_GTK)
7209 defsubr (&Sx_file_dialog);
7210 #endif
7212 #if defined (USE_GTK) && defined (HAVE_FREETYPE)
7213 defsubr (&Sx_select_font);
7214 #endif
7216 #ifdef USE_CAIRO
7217 defsubr (&Sx_export_frames);
7218 #ifdef USE_GTK
7219 defsubr (&Sx_page_setup_dialog);
7220 defsubr (&Sx_get_page_setup);
7221 defsubr (&Sx_print_frames_dialog);
7222 #endif
7223 #endif