Document reserved keys
[emacs.git] / src / xfns.c
blob20fe61bffd8a1dd5d3aa8c2b5f8ff403580fbe0c
1 /* Functions for the X window system.
3 Copyright (C) 1989, 1992-2018 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 <https://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 #include <Xm/MwmUtil.h>
94 #endif
96 #ifdef USE_LUCID
97 #include "../lwlib/xlwmenu.h"
98 #endif
100 /* Unique id counter for widgets created by the Lucid Widget Library. */
102 extern LWLIB_ID widget_id_tick;
104 #ifdef USE_MOTIF
106 #endif /* USE_MOTIF */
108 #endif /* USE_X_TOOLKIT */
110 #ifdef USE_GTK
112 #endif /* USE_GTK */
114 #define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
116 static ptrdiff_t image_cache_refcount;
117 #ifdef GLYPH_DEBUG
118 static int dpyinfo_refcount;
119 #endif
121 #ifndef USE_MOTIF
122 #ifndef USE_GTK
123 /** #define MWM_HINTS_FUNCTIONS (1L << 0) **/
124 #define MWM_HINTS_DECORATIONS (1L << 1)
125 /** #define MWM_HINTS_INPUT_MODE (1L << 2) **/
126 /** #define MWM_HINTS_STATUS (1L << 3) **/
128 #define MWM_DECOR_ALL (1L << 0)
129 /** #define MWM_DECOR_BORDER (1L << 1) **/
130 /** #define MWM_DECOR_RESIZEH (1L << 2) **/
131 /** #define MWM_DECOR_TITLE (1L << 3) **/
132 /** #define MWM_DECOR_MENU (1L << 4) **/
133 /** #define MWM_DECOR_MINIMIZE (1L << 5) **/
134 /** #define MWM_DECOR_MAXIMIZE (1L << 6) **/
136 /** #define _XA_MOTIF_WM_HINTS "_MOTIF_WM_HINTS" **/
138 typedef struct {
139 unsigned long flags;
140 unsigned long functions;
141 unsigned long decorations;
142 long input_mode;
143 unsigned long status;
144 } PropMotifWmHints;
146 #define PROP_MOTIF_WM_HINTS_ELEMENTS 5
147 #endif /* NOT USE_GTK */
148 #endif /* NOT USE_MOTIF */
150 static struct x_display_info *x_display_info_for_name (Lisp_Object);
151 static void set_up_x_back_buffer (struct frame *f);
153 /* Let the user specify an X display with a Lisp object.
154 OBJECT may be nil, a frame or a terminal object.
155 nil stands for the selected frame--or, if that is not an X frame,
156 the first X display on the list. */
158 struct x_display_info *
159 check_x_display_info (Lisp_Object object)
161 struct x_display_info *dpyinfo = NULL;
163 if (NILP (object))
165 struct frame *sf = XFRAME (selected_frame);
167 if (FRAME_X_P (sf) && FRAME_LIVE_P (sf))
168 dpyinfo = FRAME_DISPLAY_INFO (sf);
169 else if (x_display_list != 0)
170 dpyinfo = x_display_list;
171 else
172 error ("X windows are not in use or not initialized");
174 else if (TERMINALP (object))
176 struct terminal *t = decode_live_terminal (object);
178 if (t->type != output_x_window)
179 error ("Terminal %d is not an X display", t->id);
181 dpyinfo = t->display_info.x;
183 else if (STRINGP (object))
184 dpyinfo = x_display_info_for_name (object);
185 else
187 struct frame *f = decode_window_system_frame (object);
188 dpyinfo = FRAME_DISPLAY_INFO (f);
191 return dpyinfo;
194 /* Return the screen positions and offsets of frame F.
195 Store the offsets between FRAME_OUTER_WINDOW and the containing
196 window manager window into LEFT_OFFSET_X, RIGHT_OFFSET_X,
197 TOP_OFFSET_Y and BOTTOM_OFFSET_Y.
198 Store the offsets between FRAME_X_WINDOW and the containing
199 window manager window into X_PIXELS_DIFF and Y_PIXELS_DIFF.
200 Store the screen positions of frame F into XPTR and YPTR.
201 These are the positions of the containing window manager window,
202 not Emacs's own window. */
203 void
204 x_real_pos_and_offsets (struct frame *f,
205 int *left_offset_x,
206 int *right_offset_x,
207 int *top_offset_y,
208 int *bottom_offset_y,
209 int *x_pixels_diff,
210 int *y_pixels_diff,
211 int *xptr,
212 int *yptr,
213 int *outer_border)
215 int win_x = 0, win_y = 0, outer_x = 0, outer_y = 0;
216 int real_x = 0, real_y = 0;
217 bool had_errors = false;
218 Window win = (FRAME_PARENT_FRAME (f)
219 ? FRAME_X_WINDOW (FRAME_PARENT_FRAME (f))
220 : f->output_data.x->parent_desc);
221 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
222 long max_len = 400;
223 Atom target_type = XA_CARDINAL;
224 unsigned int ow = 0, oh = 0;
225 unsigned int fw = 0, fh = 0;
226 unsigned int bw = 0;
227 /* We resort to XCB if possible because there are several X calls
228 here which require responses from the server but do not have data
229 dependencies between them. Using XCB lets us pipeline requests,
230 whereas with Xlib we must wait for each answer before sending the
231 next request.
233 For a non-local display, the round-trip time could be a few tens
234 of milliseconds, depending on the network distance. It doesn't
235 take a lot of those to add up to a noticeable hesitation in
236 responding to user actions. */
237 #ifdef USE_XCB
238 xcb_connection_t *xcb_conn = dpyinfo->xcb_connection;
239 xcb_get_property_cookie_t prop_cookie;
240 xcb_get_geometry_cookie_t outer_geom_cookie;
241 bool sent_requests = false;
242 #else
243 Atom actual_type;
244 unsigned long actual_size, bytes_remaining;
245 int rc, actual_format;
246 Display *dpy = FRAME_X_DISPLAY (f);
247 unsigned char *tmp_data = NULL;
248 #endif
250 if (x_pixels_diff) *x_pixels_diff = 0;
251 if (y_pixels_diff) *y_pixels_diff = 0;
252 if (left_offset_x) *left_offset_x = 0;
253 if (top_offset_y) *top_offset_y = 0;
254 if (right_offset_x) *right_offset_x = 0;
255 if (bottom_offset_y) *bottom_offset_y = 0;
256 if (xptr) *xptr = 0;
257 if (yptr) *yptr = 0;
258 if (outer_border) *outer_border = 0;
260 if (win == dpyinfo->root_window)
261 win = FRAME_OUTER_WINDOW (f);
263 block_input ();
265 #ifndef USE_XCB
266 /* If we're using XCB, all errors are checked for on each call. */
267 x_catch_errors (dpy);
268 #endif
270 /* This loop traverses up the containment tree until we hit the root
271 window. Window managers may intersect many windows between our window
272 and the root window. The window we find just before the root window
273 should be the outer WM window. */
274 for (;;)
276 Window wm_window, rootw;
278 #ifdef USE_XCB
279 xcb_query_tree_cookie_t query_tree_cookie;
280 xcb_query_tree_reply_t *query_tree;
282 query_tree_cookie = xcb_query_tree (xcb_conn, win);
283 query_tree = xcb_query_tree_reply (xcb_conn, query_tree_cookie, NULL);
284 if (query_tree == NULL)
285 had_errors = true;
286 else
288 wm_window = query_tree->parent;
289 rootw = query_tree->root;
290 free (query_tree);
292 #else
293 Window *tmp_children;
294 unsigned int tmp_nchildren;
295 int success;
297 success = XQueryTree (dpy, win, &rootw,
298 &wm_window, &tmp_children, &tmp_nchildren);
300 had_errors = x_had_errors_p (dpy);
302 /* Don't free tmp_children if XQueryTree failed. */
303 if (! success)
304 break;
306 XFree (tmp_children);
307 #endif
309 if (had_errors || wm_window == rootw)
310 break;
312 win = wm_window;
315 if (! had_errors)
317 #ifdef USE_XCB
318 xcb_get_geometry_cookie_t geom_cookie;
319 xcb_translate_coordinates_cookie_t trans_cookie;
320 xcb_translate_coordinates_cookie_t outer_trans_cookie;
322 xcb_translate_coordinates_reply_t *trans;
323 xcb_get_geometry_reply_t *geom;
324 #else
325 Window child, rootw;
326 unsigned int ign;
327 #endif
329 #ifdef USE_XCB
330 /* Fire off the requests that don't have data dependencies.
332 Once we've done this, we must collect the results for each
333 one before returning, even if other errors are detected,
334 making the other responses moot. */
335 geom_cookie = xcb_get_geometry (xcb_conn, win);
337 trans_cookie =
338 xcb_translate_coordinates (xcb_conn,
339 /* From-window, to-window. */
340 FRAME_DISPLAY_INFO (f)->root_window,
341 FRAME_X_WINDOW (f),
343 /* From-position. */
344 0, 0);
345 if (FRAME_X_WINDOW (f) != FRAME_OUTER_WINDOW (f))
346 outer_trans_cookie =
347 xcb_translate_coordinates (xcb_conn,
348 /* From-window, to-window. */
349 FRAME_DISPLAY_INFO (f)->root_window,
350 FRAME_OUTER_WINDOW (f),
352 /* From-position. */
353 0, 0);
354 if (right_offset_x || bottom_offset_y)
355 outer_geom_cookie = xcb_get_geometry (xcb_conn,
356 FRAME_OUTER_WINDOW (f));
358 if ((dpyinfo->root_window == f->output_data.x->parent_desc)
359 && !FRAME_PARENT_FRAME (f))
360 /* Try _NET_FRAME_EXTENTS if our parent is the root window. */
361 prop_cookie = xcb_get_property (xcb_conn, 0, win,
362 dpyinfo->Xatom_net_frame_extents,
363 target_type, 0, max_len);
365 sent_requests = true;
366 #endif
368 /* Get the real coordinates for the WM window upper left corner */
369 #ifdef USE_XCB
370 geom = xcb_get_geometry_reply (xcb_conn, geom_cookie, NULL);
371 if (geom)
373 real_x = geom->x;
374 real_y = geom->y;
375 ow = geom->width;
376 oh = geom->height;
377 bw = geom->border_width;
378 free (geom);
380 else
381 had_errors = true;
382 #else
383 XGetGeometry (dpy, win,
384 &rootw, &real_x, &real_y, &ow, &oh, &bw, &ign);
385 #endif
387 /* Translate real coordinates to coordinates relative to our
388 window. For our window, the upper left corner is 0, 0.
389 Since the upper left corner of the WM window is outside
390 our window, win_x and win_y will be negative:
392 ------------------ ---> x
393 | title |
394 | ----------------- v y
395 | | our window
397 Since we don't care about the child window corresponding to
398 the actual coordinates, we can send zero to get the offsets
399 and compute the resulting coordinates below. This reduces
400 the data dependencies between calls and lets us pipeline the
401 requests better in the XCB case. */
402 #ifdef USE_XCB
403 trans = xcb_translate_coordinates_reply (xcb_conn, trans_cookie, NULL);
404 if (trans)
406 win_x = trans->dst_x;
407 win_y = trans->dst_y;
408 free (trans);
410 else
411 had_errors = true;
412 #else
413 XTranslateCoordinates (dpy,
415 /* From-window, to-window. */
416 FRAME_DISPLAY_INFO (f)->root_window,
417 FRAME_X_WINDOW (f),
419 /* From-position, to-position. */
420 0, 0, &win_x, &win_y,
422 /* Child of win. */
423 &child);
424 #endif
426 win_x += real_x;
427 win_y += real_y;
429 if (FRAME_X_WINDOW (f) == FRAME_OUTER_WINDOW (f))
431 outer_x = win_x;
432 outer_y = win_y;
434 else
436 #ifdef USE_XCB
437 xcb_translate_coordinates_reply_t *outer_trans;
439 outer_trans = xcb_translate_coordinates_reply (xcb_conn,
440 outer_trans_cookie,
441 NULL);
442 if (outer_trans)
444 outer_x = outer_trans->dst_x;
445 outer_y = outer_trans->dst_y;
446 free (outer_trans);
448 else
449 had_errors = true;
450 #else
451 XTranslateCoordinates (dpy,
453 /* From-window, to-window. */
454 FRAME_DISPLAY_INFO (f)->root_window,
455 FRAME_OUTER_WINDOW (f),
457 /* From-position, to-position. */
458 0, 0, &outer_x, &outer_y,
460 /* Child of win. */
461 &child);
462 #endif
464 outer_x += real_x;
465 outer_y += real_y;
468 #ifndef USE_XCB
469 had_errors = x_had_errors_p (dpy);
470 #endif
473 if ((dpyinfo->root_window == f->output_data.x->parent_desc)
474 && !FRAME_PARENT_FRAME (f))
476 /* Try _NET_FRAME_EXTENTS if our parent is the root window. */
477 #ifdef USE_XCB
478 /* Make sure we didn't get an X error early and skip sending the
479 request. */
480 if (sent_requests)
482 xcb_get_property_reply_t *prop;
484 prop = xcb_get_property_reply (xcb_conn, prop_cookie, NULL);
485 if (prop)
487 if (prop->type == target_type
488 && prop->format == 32
489 && (xcb_get_property_value_length (prop)
490 == 4 * sizeof (int32_t)))
492 int32_t *fe = xcb_get_property_value (prop);
494 outer_x = -fe[0];
495 outer_y = -fe[2];
496 real_x -= fe[0];
497 real_y -= fe[2];
499 free (prop);
501 /* Xlib version doesn't set had_errors here. Intentional or bug? */
503 #else
504 rc = XGetWindowProperty (dpy, win, dpyinfo->Xatom_net_frame_extents,
505 0, max_len, False, target_type,
506 &actual_type, &actual_format, &actual_size,
507 &bytes_remaining, &tmp_data);
509 if (rc == Success && actual_type == target_type && !x_had_errors_p (dpy)
510 && actual_size == 4 && actual_format == 32)
512 long *fe = (long *)tmp_data;
514 outer_x = -fe[0];
515 outer_y = -fe[2];
516 real_x -= fe[0];
517 real_y -= fe[2];
520 if (tmp_data) XFree (tmp_data);
521 #endif
524 if (right_offset_x || bottom_offset_y)
526 #ifdef USE_XCB
527 /* Make sure we didn't get an X error early and skip sending the
528 request. */
529 if (sent_requests)
531 xcb_get_geometry_reply_t *outer_geom;
533 outer_geom = xcb_get_geometry_reply (xcb_conn, outer_geom_cookie,
534 NULL);
535 if (outer_geom)
537 fw = outer_geom->width;
538 fh = outer_geom->height;
539 free (outer_geom);
541 else
542 had_errors = true;
544 #else
545 int xy_ign;
546 unsigned int ign;
547 Window rootw;
549 XGetGeometry (dpy, FRAME_OUTER_WINDOW (f),
550 &rootw, &xy_ign, &xy_ign, &fw, &fh, &ign, &ign);
551 #endif
554 #ifndef USE_XCB
555 x_uncatch_errors ();
556 #endif
558 unblock_input ();
560 if (had_errors) return;
562 if (x_pixels_diff) *x_pixels_diff = -win_x;
563 if (y_pixels_diff) *y_pixels_diff = -win_y;
565 if (left_offset_x) *left_offset_x = -outer_x;
566 if (top_offset_y) *top_offset_y = -outer_y;
568 if (xptr) *xptr = real_x;
569 if (yptr) *yptr = real_y;
571 if (outer_border) *outer_border = bw;
573 if (right_offset_x) *right_offset_x = ow - fw + outer_x;
574 if (bottom_offset_y) *bottom_offset_y = oh - fh + outer_y;
577 /* Store the screen positions of frame F into XPTR and YPTR.
578 These are the positions of the containing window manager window,
579 not Emacs's own window. */
581 void
582 x_real_positions (struct frame *f, int *xptr, int *yptr)
584 x_real_pos_and_offsets (f, NULL, NULL, NULL, NULL, NULL, NULL, xptr, yptr,
585 NULL);
589 /* Get the mouse position in frame relative coordinates. */
591 void
592 x_relative_mouse_position (struct frame *f, int *x, int *y)
594 Window root, dummy_window;
595 int dummy;
597 eassert (FRAME_X_P (f));
599 block_input ();
601 XQueryPointer (FRAME_X_DISPLAY (f),
602 DefaultRootWindow (FRAME_X_DISPLAY (f)),
604 /* The root window which contains the pointer. */
605 &root,
607 /* Window pointer is on, not used */
608 &dummy_window,
610 /* The position on that root window. */
611 x, y,
613 /* x/y in dummy_window coordinates, not used. */
614 &dummy, &dummy,
616 /* Modifier keys and pointer buttons, about which
617 we don't care. */
618 (unsigned int *) &dummy);
620 XTranslateCoordinates (FRAME_X_DISPLAY (f),
622 /* From-window, to-window. */
623 FRAME_DISPLAY_INFO (f)->root_window,
624 FRAME_X_WINDOW (f),
626 /* From-position, to-position. */
627 *x, *y, x, y,
629 /* Child of win. */
630 &dummy_window);
632 unblock_input ();
635 /* Gamma-correct COLOR on frame F. */
637 void
638 gamma_correct (struct frame *f, XColor *color)
640 if (f->gamma)
642 color->red = pow (color->red / 65535.0, f->gamma) * 65535.0 + 0.5;
643 color->green = pow (color->green / 65535.0, f->gamma) * 65535.0 + 0.5;
644 color->blue = pow (color->blue / 65535.0, f->gamma) * 65535.0 + 0.5;
649 /* Decide if color named COLOR_NAME is valid for use on frame F. If
650 so, return the RGB values in COLOR. If ALLOC_P,
651 allocate the color. Value is false if COLOR_NAME is invalid, or
652 no color could be allocated. */
654 bool
655 x_defined_color (struct frame *f, const char *color_name,
656 XColor *color, bool alloc_p)
658 bool success_p = false;
659 Colormap cmap = FRAME_X_COLORMAP (f);
661 block_input ();
662 #ifdef USE_GTK
663 success_p = xg_check_special_colors (f, color_name, color);
664 #endif
665 if (!success_p)
666 success_p = x_parse_color (f, color_name, color) != 0;
667 if (success_p && alloc_p)
668 success_p = x_alloc_nearest_color (f, cmap, color);
669 unblock_input ();
671 return success_p;
675 /* Return the pixel color value for color COLOR_NAME on frame F. If F
676 is a monochrome frame, return MONO_COLOR regardless of what ARG says.
677 Signal an error if color can't be allocated. */
679 static int
680 x_decode_color (struct frame *f, Lisp_Object color_name, int mono_color)
682 XColor cdef;
684 CHECK_STRING (color_name);
686 #if false /* Don't do this. It's wrong when we're not using the default
687 colormap, it makes freeing difficult, and it's probably not
688 an important optimization. */
689 if (strcmp (SDATA (color_name), "black") == 0)
690 return BLACK_PIX_DEFAULT (f);
691 else if (strcmp (SDATA (color_name), "white") == 0)
692 return WHITE_PIX_DEFAULT (f);
693 #endif
695 /* Return MONO_COLOR for monochrome frames. */
696 if (FRAME_DISPLAY_INFO (f)->n_planes == 1)
697 return mono_color;
699 /* x_defined_color is responsible for coping with failures
700 by looking for a near-miss. */
701 if (x_defined_color (f, SSDATA (color_name), &cdef, true))
702 return cdef.pixel;
704 signal_error ("Undefined color", color_name);
709 /* Change the `wait-for-wm' frame parameter of frame F. OLD_VALUE is
710 the previous value of that parameter, NEW_VALUE is the new value.
711 See also the comment of wait_for_wm in struct x_output. */
713 static void
714 x_set_wait_for_wm (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
716 f->output_data.x->wait_for_wm = !NILP (new_value);
719 static void
720 x_set_tool_bar_position (struct frame *f,
721 Lisp_Object new_value,
722 Lisp_Object old_value)
724 Lisp_Object choice = list4 (Qleft, Qright, Qtop, Qbottom);
726 if (!NILP (Fmemq (new_value, choice)))
728 #ifdef USE_GTK
729 if (!EQ (new_value, old_value))
731 xg_change_toolbar_position (f, new_value);
732 fset_tool_bar_position (f, new_value);
734 #else
735 if (!EQ (new_value, Qtop))
736 error ("The only supported tool bar position is top");
737 #endif
739 else
740 wrong_choice (choice, new_value);
743 static void
744 x_set_inhibit_double_buffering (struct frame *f,
745 Lisp_Object new_value,
746 Lisp_Object old_value)
748 block_input ();
749 if (FRAME_X_WINDOW (f) && !EQ (new_value, old_value))
751 bool want_double_buffering = NILP (new_value);
752 bool was_double_buffered = FRAME_X_DOUBLE_BUFFERED_P (f);
753 /* font_drop_xrender_surfaces in xftfont does something only if
754 we're double-buffered, so call font_drop_xrender_surfaces before
755 and after any potential change. One of the calls will end up
756 being a no-op. */
757 if (want_double_buffering != was_double_buffered)
758 font_drop_xrender_surfaces (f);
759 if (FRAME_X_DOUBLE_BUFFERED_P (f) && !want_double_buffering)
760 tear_down_x_back_buffer (f);
761 else if (!FRAME_X_DOUBLE_BUFFERED_P (f) && want_double_buffering)
762 set_up_x_back_buffer (f);
763 if (FRAME_X_DOUBLE_BUFFERED_P (f) != was_double_buffered)
765 SET_FRAME_GARBAGED (f);
766 font_drop_xrender_surfaces (f);
769 unblock_input ();
773 * x_set_undecorated:
775 * Set frame F's `undecorated' parameter. If non-nil, F's window-system
776 * window is drawn without decorations, title, minimize/maximize boxes
777 * and external borders. This usually means that the window cannot be
778 * dragged, resized, iconified, maximized or deleted with the mouse. If
779 * nil, draw the frame with all the elements listed above unless these
780 * have been suspended via window manager settings.
782 * Some window managers may not honor this parameter.
784 static void
785 x_set_undecorated (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
787 if (!EQ (new_value, old_value))
789 FRAME_UNDECORATED (f) = NILP (new_value) ? false : true;
790 #ifdef USE_GTK
791 xg_set_undecorated (f, new_value);
792 #else
793 Display *dpy = FRAME_X_DISPLAY (f);
794 PropMotifWmHints hints;
795 Atom prop = XInternAtom (dpy, "_MOTIF_WM_HINTS", False);
797 memset (&hints, 0, sizeof(hints));
798 hints.flags = MWM_HINTS_DECORATIONS;
799 hints.decorations = NILP (new_value) ? MWM_DECOR_ALL : 0;
801 block_input ();
802 /* For some reason the third and fourth arguments in the following
803 call must be identical: In the corresponding XGetWindowProperty
804 call in getMotifHints, xfwm has the third and seventh args both
805 display_info->atoms[MOTIF_WM_HINTS]. Obviously, YMMV. */
806 XChangeProperty (dpy, FRAME_OUTER_WINDOW (f), prop, prop, 32,
807 PropModeReplace, (unsigned char *) &hints,
808 PROP_MOTIF_WM_HINTS_ELEMENTS);
809 unblock_input ();
811 #endif /* USE_GTK */
816 * x_set_parent_frame:
818 * Set frame F's `parent-frame' parameter. If non-nil, make F a child
819 * frame of the frame specified by that parameter. Technically, this
820 * makes F's window-system window a child window of the parent frame's
821 * window-system window. If nil, make F's window-system window a
822 * top-level window--a child of its display's root window.
824 * A child frame is clipped at the native edges of its parent frame.
825 * Its `left' and `top' parameters specify positions relative to the
826 * top-left corner of its parent frame's native rectangle. Usually,
827 * moving a parent frame moves all its child frames too, keeping their
828 * position relative to the parent unaltered. When a parent frame is
829 * iconified or made invisible, its child frames are made invisible.
830 * When a parent frame is deleted, its child frames are deleted too.
832 * A visible child frame always appears on top of its parent frame thus
833 * obscuring parts of it. When a frame has more than one child frame,
834 * their stacking order is specified just as that of non-child frames
835 * relative to their display.
837 * Whether a child frame has a menu or tool bar may be window-system or
838 * window manager dependent. It's advisable to disable both via the
839 * frame parameter settings.
841 * Some window managers may not honor this parameter.
843 static void
844 x_set_parent_frame (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
846 struct frame *p = NULL;
848 if (!NILP (new_value)
849 && (!FRAMEP (new_value)
850 || !FRAME_LIVE_P (p = XFRAME (new_value))
851 || !FRAME_X_P (p)))
853 store_frame_param (f, Qparent_frame, old_value);
854 error ("Invalid specification of `parent-frame'");
857 if (p != FRAME_PARENT_FRAME (f))
859 block_input ();
860 XReparentWindow
861 (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
862 p ? FRAME_X_WINDOW (p) : DefaultRootWindow (FRAME_X_DISPLAY (f)),
863 f->left_pos, f->top_pos);
864 unblock_input ();
866 fset_parent_frame (f, new_value);
871 * x_set_no_focus_on_map:
873 * Set frame F's `no-focus-on-map' parameter which, if non-nil, means
874 * that F's window-system window does not want to receive input focus
875 * when it is mapped. (A frame's window is mapped when the frame is
876 * displayed for the first time and when the frame changes its state
877 * from `iconified' or `invisible' to `visible'.)
879 * Some window managers may not honor this parameter.
881 static void
882 x_set_no_focus_on_map (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
884 if (!EQ (new_value, old_value))
886 #ifdef USE_GTK
887 xg_set_no_focus_on_map (f, new_value);
888 #else /* not USE_GTK */
889 Display *dpy = FRAME_X_DISPLAY (f);
890 Atom prop = XInternAtom (dpy, "_NET_WM_USER_TIME", False);
891 Time timestamp = NILP (new_value) ? CurrentTime : 0;
893 XChangeProperty (dpy, FRAME_OUTER_WINDOW (f), prop,
894 XA_CARDINAL, 32, PropModeReplace,
895 (unsigned char *) &timestamp, 1);
896 #endif /* USE_GTK */
897 FRAME_NO_FOCUS_ON_MAP (f) = !NILP (new_value);
902 * x_set_no_accept_focus:
904 * Set frame F's `no-accept-focus' parameter which, if non-nil, hints
905 * that F's window-system window does not want to receive input focus
906 * via mouse clicks or by moving the mouse into it.
908 * If non-nil, this may have the unwanted side-effect that a user cannot
909 * scroll a non-selected frame with the mouse.
911 * Some window managers may not honor this parameter.
913 static void
914 x_set_no_accept_focus (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
916 if (!EQ (new_value, old_value))
918 #ifdef USE_GTK
919 xg_set_no_accept_focus (f, new_value);
920 #else /* not USE_GTK */
921 #ifdef USE_X_TOOLKIT
922 Arg al[1];
924 XtSetArg (al[0], XtNinput, NILP (new_value) ? True : False);
925 XtSetValues (f->output_data.x->widget, al, 1);
926 #else /* not USE_X_TOOLKIT */
927 Window window = FRAME_X_WINDOW (f);
929 f->output_data.x->wm_hints.input = NILP (new_value) ? True : False;
930 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
931 #endif /* USE_X_TOOLKIT */
932 #endif /* USE_GTK */
933 FRAME_NO_ACCEPT_FOCUS (f) = !NILP (new_value);
938 * x_set_override_redirect:
940 * Set frame F's `override_redirect' parameter which, if non-nil, hints
941 * that the window manager doesn't want to deal with F. Usually, such
942 * frames have no decorations and always appear on top of all frames.
944 * Some window managers may not honor this parameter.
946 static void
947 x_set_override_redirect (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
949 if (!EQ (new_value, old_value))
951 /* Here (xfwm) override_redirect can be changed for invisible
952 frames only. */
953 x_make_frame_invisible (f);
955 #ifdef USE_GTK
956 xg_set_override_redirect (f, new_value);
957 #else /* not USE_GTK */
958 XSetWindowAttributes attributes;
960 attributes.override_redirect = NILP (new_value) ? False : True;
961 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
962 CWOverrideRedirect, &attributes);
963 #endif
964 x_make_frame_visible (f);
965 FRAME_OVERRIDE_REDIRECT (f) = !NILP (new_value);
970 #ifdef USE_GTK
972 /* Set icon from FILE for frame F. By using GTK functions the icon
973 may be any format that GdkPixbuf knows about, i.e. not just bitmaps. */
975 bool
976 xg_set_icon (struct frame *f, Lisp_Object file)
978 bool result = false;
979 Lisp_Object found;
981 found = x_find_image_file (file);
983 if (! NILP (found))
985 GdkPixbuf *pixbuf;
986 GError *err = NULL;
987 char *filename = SSDATA (ENCODE_FILE (found));
988 block_input ();
990 pixbuf = gdk_pixbuf_new_from_file (filename, &err);
992 if (pixbuf)
994 gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
995 pixbuf);
996 g_object_unref (pixbuf);
998 result = true;
1000 else
1001 g_error_free (err);
1003 unblock_input ();
1006 return result;
1009 bool
1010 xg_set_icon_from_xpm_data (struct frame *f, const char **data)
1012 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data (data);
1014 if (!pixbuf)
1015 return false;
1017 gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), pixbuf);
1018 g_object_unref (pixbuf);
1019 return true;
1021 #endif /* USE_GTK */
1024 /* Functions called only from `x_set_frame_param'
1025 to set individual parameters.
1027 If FRAME_X_WINDOW (f) is 0,
1028 the frame is being created and its X-window does not exist yet.
1029 In that case, just record the parameter's new value
1030 in the standard place; do not attempt to change the window. */
1032 static void
1033 x_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1035 struct x_output *x = f->output_data.x;
1036 unsigned long fg, old_fg;
1038 fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1039 old_fg = FRAME_FOREGROUND_PIXEL (f);
1040 FRAME_FOREGROUND_PIXEL (f) = fg;
1042 if (FRAME_X_WINDOW (f) != 0)
1044 Display *dpy = FRAME_X_DISPLAY (f);
1046 block_input ();
1047 XSetForeground (dpy, x->normal_gc, fg);
1048 XSetBackground (dpy, x->reverse_gc, fg);
1050 if (x->cursor_pixel == old_fg)
1052 unload_color (f, x->cursor_pixel);
1053 x->cursor_pixel = x_copy_color (f, fg);
1054 XSetBackground (dpy, x->cursor_gc, x->cursor_pixel);
1057 unblock_input ();
1059 update_face_from_frame_parameter (f, Qforeground_color, arg);
1061 if (FRAME_VISIBLE_P (f))
1062 redraw_frame (f);
1065 unload_color (f, old_fg);
1068 static void
1069 x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1071 struct x_output *x = f->output_data.x;
1072 unsigned long bg;
1074 bg = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
1075 unload_color (f, FRAME_BACKGROUND_PIXEL (f));
1076 FRAME_BACKGROUND_PIXEL (f) = bg;
1078 if (FRAME_X_WINDOW (f) != 0)
1080 Display *dpy = FRAME_X_DISPLAY (f);
1082 block_input ();
1083 XSetBackground (dpy, x->normal_gc, bg);
1084 XSetForeground (dpy, x->reverse_gc, bg);
1085 XSetWindowBackground (dpy, FRAME_X_WINDOW (f), bg);
1086 XSetForeground (dpy, x->cursor_gc, bg);
1088 #ifdef USE_GTK
1089 xg_set_background_color (f, bg);
1090 #endif
1092 #ifndef USE_TOOLKIT_SCROLL_BARS /* Turns out to be annoying with
1093 toolkit scroll bars. */
1095 Lisp_Object bar;
1096 for (bar = FRAME_SCROLL_BARS (f);
1097 !NILP (bar);
1098 bar = XSCROLL_BAR (bar)->next)
1100 Window window = XSCROLL_BAR (bar)->x_window;
1101 XSetWindowBackground (dpy, window, bg);
1104 #endif /* USE_TOOLKIT_SCROLL_BARS */
1106 unblock_input ();
1107 update_face_from_frame_parameter (f, Qbackground_color, arg);
1109 if (FRAME_VISIBLE_P (f))
1110 redraw_frame (f);
1114 /* This array must stay in sync with the mouse_cursor_types array below! */
1115 enum mouse_cursor {
1116 mouse_cursor_text,
1117 mouse_cursor_nontext,
1118 mouse_cursor_hourglass,
1119 mouse_cursor_mode,
1120 mouse_cursor_hand,
1121 mouse_cursor_horizontal_drag,
1122 mouse_cursor_vertical_drag,
1123 mouse_cursor_left_edge,
1124 mouse_cursor_top_left_corner,
1125 mouse_cursor_top_edge,
1126 mouse_cursor_top_right_corner,
1127 mouse_cursor_right_edge,
1128 mouse_cursor_bottom_right_corner,
1129 mouse_cursor_bottom_edge,
1130 mouse_cursor_bottom_left_corner,
1131 mouse_cursor_max
1134 struct mouse_cursor_types {
1135 /* Printable name for error messages (optional). */
1136 const char *name;
1138 /* Lisp variable controlling the cursor shape. */
1139 /* FIXME: A couple of these variables are defined in the C code but
1140 are not actually accessible from Lisp. They should probably be
1141 made accessible or removed. */
1142 Lisp_Object *shape_var_ptr;
1144 /* The default shape. */
1145 int default_shape;
1148 /* This array must stay in sync with enum mouse_cursor above! */
1149 static const struct mouse_cursor_types mouse_cursor_types[] = {
1150 { "text", &Vx_pointer_shape, XC_xterm },
1151 { "nontext", &Vx_nontext_pointer_shape, XC_left_ptr },
1152 { "hourglass", &Vx_hourglass_pointer_shape, XC_watch },
1153 { "modeline", &Vx_mode_pointer_shape, XC_xterm },
1154 { NULL, &Vx_sensitive_text_pointer_shape, XC_hand2 },
1155 { NULL, &Vx_window_horizontal_drag_shape, XC_sb_h_double_arrow },
1156 { NULL, &Vx_window_vertical_drag_shape, XC_sb_v_double_arrow },
1157 { NULL, &Vx_window_left_edge_shape, XC_left_side },
1158 { NULL, &Vx_window_top_left_corner_shape, XC_top_left_corner },
1159 { NULL, &Vx_window_top_edge_shape, XC_top_side },
1160 { NULL, &Vx_window_top_right_corner_shape, XC_top_right_corner },
1161 { NULL, &Vx_window_right_edge_shape, XC_right_side },
1162 { NULL, &Vx_window_bottom_right_corner_shape, XC_bottom_right_corner },
1163 { NULL, &Vx_window_bottom_edge_shape, XC_bottom_side },
1164 { NULL, &Vx_window_bottom_left_corner_shape, XC_bottom_left_corner },
1167 struct mouse_cursor_data {
1168 /* Last index for which XCreateFontCursor has been called, and thus
1169 the last index for which x_request_serial[] is valid. */
1170 int last_cursor_create_request;
1172 /* Last index for which an X error event was received in response to
1173 attempting to create the cursor. */
1174 int error_cursor;
1176 /* Cursor numbers chosen. */
1177 unsigned int cursor_num[mouse_cursor_max];
1179 /* Allocated Cursor values, or zero for failed attempts. */
1180 Cursor cursor[mouse_cursor_max];
1182 /* X serial numbers for the first request sent by XCreateFontCursor.
1183 Note that there may be more than one request sent. */
1184 unsigned long x_request_serial[mouse_cursor_max];
1186 /* If an error has been received, a pointer to where the current
1187 error-message text is stored. */
1188 char *error_string;
1191 static void
1192 x_set_mouse_color_handler (Display *dpy, XErrorEvent *event,
1193 char *error_string, void *data)
1195 struct mouse_cursor_data *cursor_data = data;
1196 int i;
1198 cursor_data->error_cursor = -1;
1199 cursor_data->error_string = error_string;
1200 for (i = 0; i < cursor_data->last_cursor_create_request; i++)
1202 if (event->serial >= cursor_data->x_request_serial[i])
1203 cursor_data->error_cursor = i;
1205 if (cursor_data->error_cursor >= 0)
1206 /* If we failed to allocate it, don't try to free it. */
1207 cursor_data->cursor[cursor_data->error_cursor] = 0;
1210 static void
1211 x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1213 struct x_output *x = f->output_data.x;
1214 Display *dpy = FRAME_X_DISPLAY (f);
1215 struct mouse_cursor_data cursor_data = { -1, -1 };
1216 unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1217 unsigned long mask_color = FRAME_BACKGROUND_PIXEL (f);
1218 int i;
1220 /* Don't let pointers be invisible. */
1221 if (mask_color == pixel)
1223 x_free_colors (f, &pixel, 1);
1224 pixel = x_copy_color (f, FRAME_FOREGROUND_PIXEL (f));
1227 unload_color (f, x->mouse_pixel);
1228 x->mouse_pixel = pixel;
1230 for (i = 0; i < mouse_cursor_max; i++)
1232 Lisp_Object shape_var = *mouse_cursor_types[i].shape_var_ptr;
1233 if (!NILP (shape_var))
1235 CHECK_TYPE_RANGED_INTEGER (unsigned, shape_var);
1236 cursor_data.cursor_num[i] = XINT (shape_var);
1238 else
1239 cursor_data.cursor_num[i] = mouse_cursor_types[i].default_shape;
1242 block_input ();
1244 /* It's not okay to crash if the user selects a screwy cursor. */
1245 x_catch_errors_with_handler (dpy, x_set_mouse_color_handler, &cursor_data);
1247 for (i = 0; i < mouse_cursor_max; i++)
1249 cursor_data.x_request_serial[i] = XNextRequest (dpy);
1250 cursor_data.last_cursor_create_request = i;
1251 cursor_data.cursor[i] = XCreateFontCursor (dpy,
1252 cursor_data.cursor_num[i]);
1255 /* Now sync up and process all received errors from cursor
1256 creation. */
1257 if (x_had_errors_p (dpy))
1259 const char *bad_cursor_name = NULL;
1260 /* Bounded by X_ERROR_MESSAGE_SIZE in xterm.c. */
1261 size_t message_length = strlen (cursor_data.error_string);
1262 char *xmessage = alloca (1 + message_length);
1263 memcpy (xmessage, cursor_data.error_string, message_length);
1265 x_uncatch_errors ();
1267 /* Free any successfully created cursors. */
1268 for (i = 0; i < mouse_cursor_max; i++)
1269 if (cursor_data.cursor[i] != 0)
1270 XFreeCursor (dpy, cursor_data.cursor[i]);
1272 /* This should only be able to fail if the server's serial
1273 number tracking is broken. */
1274 if (cursor_data.error_cursor >= 0)
1275 bad_cursor_name = mouse_cursor_types[cursor_data.error_cursor].name;
1276 if (bad_cursor_name)
1277 error ("bad %s pointer cursor: %s", bad_cursor_name, xmessage);
1278 else
1279 error ("can't set cursor shape: %s", xmessage);
1282 x_uncatch_errors_after_check ();
1285 XColor colors[2]; /* 0=foreground, 1=background */
1287 colors[0].pixel = x->mouse_pixel;
1288 colors[1].pixel = mask_color;
1289 x_query_colors (f, colors, 2);
1291 for (i = 0; i < mouse_cursor_max; i++)
1292 XRecolorCursor (dpy, cursor_data.cursor[i], &colors[0], &colors[1]);
1295 if (FRAME_X_WINDOW (f) != 0)
1297 f->output_data.x->current_cursor = cursor_data.cursor[mouse_cursor_text];
1298 XDefineCursor (dpy, FRAME_X_WINDOW (f),
1299 f->output_data.x->current_cursor);
1302 #define INSTALL_CURSOR(FIELD, SHORT_INDEX) \
1303 eassert (x->FIELD != cursor_data.cursor[mouse_cursor_ ## SHORT_INDEX]); \
1304 if (x->FIELD != 0) \
1305 XFreeCursor (dpy, x->FIELD); \
1306 x->FIELD = cursor_data.cursor[mouse_cursor_ ## SHORT_INDEX];
1308 INSTALL_CURSOR (text_cursor, text);
1309 INSTALL_CURSOR (nontext_cursor, nontext);
1310 INSTALL_CURSOR (hourglass_cursor, hourglass);
1311 INSTALL_CURSOR (modeline_cursor, mode);
1312 INSTALL_CURSOR (hand_cursor, hand);
1313 INSTALL_CURSOR (horizontal_drag_cursor, horizontal_drag);
1314 INSTALL_CURSOR (vertical_drag_cursor, vertical_drag);
1315 INSTALL_CURSOR (left_edge_cursor, left_edge);
1316 INSTALL_CURSOR (top_left_corner_cursor, top_left_corner);
1317 INSTALL_CURSOR (top_edge_cursor, top_edge);
1318 INSTALL_CURSOR (top_right_corner_cursor, top_right_corner);
1319 INSTALL_CURSOR (right_edge_cursor, right_edge);
1320 INSTALL_CURSOR (bottom_right_corner_cursor, bottom_right_corner);
1321 INSTALL_CURSOR (bottom_edge_cursor, bottom_edge);
1322 INSTALL_CURSOR (bottom_left_corner_cursor, bottom_left_corner);
1324 #undef INSTALL_CURSOR
1326 XFlush (dpy);
1327 unblock_input ();
1329 update_face_from_frame_parameter (f, Qmouse_color, arg);
1332 static void
1333 x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1335 unsigned long fore_pixel, pixel;
1336 bool fore_pixel_allocated_p = false, pixel_allocated_p = false;
1337 struct x_output *x = f->output_data.x;
1339 if (!NILP (Vx_cursor_fore_pixel))
1341 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
1342 WHITE_PIX_DEFAULT (f));
1343 fore_pixel_allocated_p = true;
1345 else
1346 fore_pixel = FRAME_BACKGROUND_PIXEL (f);
1348 pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1349 pixel_allocated_p = true;
1351 /* Make sure that the cursor color differs from the background color. */
1352 if (pixel == FRAME_BACKGROUND_PIXEL (f))
1354 if (pixel_allocated_p)
1356 x_free_colors (f, &pixel, 1);
1357 pixel_allocated_p = false;
1360 pixel = x->mouse_pixel;
1361 if (pixel == fore_pixel)
1363 if (fore_pixel_allocated_p)
1365 x_free_colors (f, &fore_pixel, 1);
1366 fore_pixel_allocated_p = false;
1368 fore_pixel = FRAME_BACKGROUND_PIXEL (f);
1372 unload_color (f, x->cursor_foreground_pixel);
1373 if (!fore_pixel_allocated_p)
1374 fore_pixel = x_copy_color (f, fore_pixel);
1375 x->cursor_foreground_pixel = fore_pixel;
1377 unload_color (f, x->cursor_pixel);
1378 if (!pixel_allocated_p)
1379 pixel = x_copy_color (f, pixel);
1380 x->cursor_pixel = pixel;
1382 if (FRAME_X_WINDOW (f) != 0)
1384 block_input ();
1385 XSetBackground (FRAME_X_DISPLAY (f), x->cursor_gc, x->cursor_pixel);
1386 XSetForeground (FRAME_X_DISPLAY (f), x->cursor_gc, fore_pixel);
1387 unblock_input ();
1389 if (FRAME_VISIBLE_P (f))
1391 x_update_cursor (f, false);
1392 x_update_cursor (f, true);
1396 update_face_from_frame_parameter (f, Qcursor_color, arg);
1399 /* Set the border-color of frame F to pixel value PIX.
1400 Note that this does not fully take effect if done before
1401 F has an x-window. */
1403 static void
1404 x_set_border_pixel (struct frame *f, int pix)
1406 unload_color (f, f->output_data.x->border_pixel);
1407 f->output_data.x->border_pixel = pix;
1409 if (FRAME_X_WINDOW (f) != 0 && f->border_width > 0)
1411 block_input ();
1412 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), pix);
1413 unblock_input ();
1415 if (FRAME_VISIBLE_P (f))
1416 redraw_frame (f);
1420 /* Set the border-color of frame F to value described by ARG.
1421 ARG can be a string naming a color.
1422 The border-color is used for the border that is drawn by the X server.
1423 Note that this does not fully take effect if done before
1424 F has an x-window; it must be redone when the window is created.
1426 Note: this is done in two routines because of the way X10 works.
1428 Note: under X11, this is normally the province of the window manager,
1429 and so emacs's border colors may be overridden. */
1431 static void
1432 x_set_border_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1434 int pix;
1436 CHECK_STRING (arg);
1437 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1438 x_set_border_pixel (f, pix);
1439 update_face_from_frame_parameter (f, Qborder_color, arg);
1443 static void
1444 x_set_cursor_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1446 set_frame_cursor_types (f, arg);
1449 static void
1450 x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1452 bool result;
1454 if (STRINGP (arg))
1456 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1457 return;
1459 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1460 return;
1462 block_input ();
1463 if (NILP (arg))
1464 result = x_text_icon (f,
1465 SSDATA ((!NILP (f->icon_name)
1466 ? f->icon_name
1467 : f->name)));
1468 else
1469 result = x_bitmap_icon (f, arg);
1471 if (result)
1473 unblock_input ();
1474 error ("No icon window available");
1477 XFlush (FRAME_X_DISPLAY (f));
1478 unblock_input ();
1481 static void
1482 x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1484 bool result;
1486 if (STRINGP (arg))
1488 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1489 return;
1491 else if (!NILP (arg) || NILP (oldval))
1492 return;
1494 fset_icon_name (f, arg);
1496 if (f->output_data.x->icon_bitmap != 0)
1497 return;
1499 block_input ();
1501 result = x_text_icon (f,
1502 SSDATA ((!NILP (f->icon_name)
1503 ? f->icon_name
1504 : !NILP (f->title)
1505 ? f->title
1506 : f->name)));
1508 if (result)
1510 unblock_input ();
1511 error ("No icon window available");
1514 XFlush (FRAME_X_DISPLAY (f));
1515 unblock_input ();
1519 static void
1520 x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
1522 int nlines;
1523 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
1524 int olines = FRAME_MENU_BAR_LINES (f);
1525 #endif
1527 /* Right now, menu bars don't work properly in minibuf-only frames;
1528 most of the commands try to apply themselves to the minibuffer
1529 frame itself, and get an error because you can't switch buffers
1530 in or split the minibuffer window. */
1531 if (FRAME_MINIBUF_ONLY_P (f) || FRAME_PARENT_FRAME (f))
1532 return;
1534 if (TYPE_RANGED_INTEGERP (int, value))
1535 nlines = XINT (value);
1536 else
1537 nlines = 0;
1539 /* Make sure we redisplay all windows in this frame. */
1540 fset_redisplay (f);
1542 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
1543 FRAME_MENU_BAR_LINES (f) = 0;
1544 FRAME_MENU_BAR_HEIGHT (f) = 0;
1545 if (nlines)
1547 FRAME_EXTERNAL_MENU_BAR (f) = 1;
1548 if (FRAME_X_P (f) && f->output_data.x->menubar_widget == 0)
1549 /* Make sure next redisplay shows the menu bar. */
1550 XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = true;
1552 else
1554 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
1555 free_frame_menubar (f);
1556 FRAME_EXTERNAL_MENU_BAR (f) = 0;
1557 if (FRAME_X_P (f))
1558 f->output_data.x->menubar_widget = 0;
1560 #else /* not USE_X_TOOLKIT && not USE_GTK */
1561 FRAME_MENU_BAR_LINES (f) = nlines;
1562 FRAME_MENU_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f);
1563 adjust_frame_size (f, -1, -1, 2, true, Qx_set_menu_bar_lines);
1564 if (FRAME_X_WINDOW (f))
1565 x_clear_under_internal_border (f);
1567 /* If the menu bar height gets changed, the internal border below
1568 the top margin has to be cleared. Also, if the menu bar gets
1569 larger, the area for the added lines has to be cleared except for
1570 the first menu bar line that is to be drawn later. */
1571 if (nlines != olines)
1573 int height = FRAME_INTERNAL_BORDER_WIDTH (f);
1574 int width = FRAME_PIXEL_WIDTH (f);
1575 int y;
1577 /* height can be zero here. */
1578 if (FRAME_X_WINDOW (f) && height > 0 && width > 0)
1580 y = FRAME_TOP_MARGIN_HEIGHT (f);
1582 block_input ();
1583 x_clear_area (f, 0, y, width, height);
1584 unblock_input ();
1587 if (nlines > 1 && nlines > olines)
1589 y = (olines == 0 ? 1 : olines) * FRAME_LINE_HEIGHT (f);
1590 height = nlines * FRAME_LINE_HEIGHT (f) - y;
1592 block_input ();
1593 x_clear_area (f, 0, y, width, height);
1594 unblock_input ();
1597 if (nlines == 0 && WINDOWP (f->menu_bar_window))
1598 clear_glyph_matrix (XWINDOW (f->menu_bar_window)->current_matrix);
1600 #endif /* not USE_X_TOOLKIT && not USE_GTK */
1601 adjust_frame_glyphs (f);
1605 /* Set the number of lines used for the tool bar of frame F to VALUE.
1606 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
1607 is the old number of tool bar lines. This function changes the
1608 height of all windows on frame F to match the new tool bar height.
1609 The frame's height doesn't change. */
1611 static void
1612 x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
1614 int nlines;
1616 /* Treat tool bars like menu bars. */
1617 if (FRAME_MINIBUF_ONLY_P (f))
1618 return;
1620 /* Use VALUE only if an int >= 0. */
1621 if (RANGED_INTEGERP (0, value, INT_MAX))
1622 nlines = XFASTINT (value);
1623 else
1624 nlines = 0;
1626 x_change_tool_bar_height (f, nlines * FRAME_LINE_HEIGHT (f));
1630 /* Set the pixel height of the tool bar of frame F to HEIGHT. */
1631 void
1632 x_change_tool_bar_height (struct frame *f, int height)
1634 #ifdef USE_GTK
1635 FRAME_TOOL_BAR_LINES (f) = 0;
1636 FRAME_TOOL_BAR_HEIGHT (f) = 0;
1637 if (height)
1639 FRAME_EXTERNAL_TOOL_BAR (f) = true;
1640 if (FRAME_X_P (f) && f->output_data.x->toolbar_widget == 0)
1641 /* Make sure next redisplay shows the tool bar. */
1642 XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = true;
1643 update_frame_tool_bar (f);
1645 else
1647 if (FRAME_EXTERNAL_TOOL_BAR (f))
1648 free_frame_tool_bar (f);
1649 FRAME_EXTERNAL_TOOL_BAR (f) = false;
1651 #else /* !USE_GTK */
1652 int unit = FRAME_LINE_HEIGHT (f);
1653 int old_height = FRAME_TOOL_BAR_HEIGHT (f);
1654 int lines = (height + unit - 1) / unit;
1655 Lisp_Object fullscreen;
1657 /* Make sure we redisplay all windows in this frame. */
1658 fset_redisplay (f);
1660 /* Recalculate tool bar and frame text sizes. */
1661 FRAME_TOOL_BAR_HEIGHT (f) = height;
1662 FRAME_TOOL_BAR_LINES (f) = lines;
1663 /* Store the `tool-bar-lines' and `height' frame parameters. */
1664 store_frame_param (f, Qtool_bar_lines, make_number (lines));
1665 store_frame_param (f, Qheight, make_number (FRAME_LINES (f)));
1667 /* We also have to make sure that the internal border at the top of
1668 the frame, below the menu bar or tool bar, is redrawn when the
1669 tool bar disappears. This is so because the internal border is
1670 below the tool bar if one is displayed, but is below the menu bar
1671 if there isn't a tool bar. The tool bar draws into the area
1672 below the menu bar. */
1673 if (FRAME_X_WINDOW (f) && FRAME_TOOL_BAR_HEIGHT (f) == 0)
1675 clear_frame (f);
1676 clear_current_matrices (f);
1679 if ((height < old_height) && WINDOWP (f->tool_bar_window))
1680 clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
1682 /* Recalculate toolbar height. */
1683 f->n_tool_bar_rows = 0;
1684 if (old_height == 0
1685 && (!f->after_make_frame
1686 || NILP (frame_inhibit_implied_resize)
1687 || (CONSP (frame_inhibit_implied_resize)
1688 && NILP (Fmemq (Qtool_bar_lines, frame_inhibit_implied_resize)))))
1689 f->tool_bar_redisplayed = f->tool_bar_resized = false;
1691 adjust_frame_size (f, -1, -1,
1692 ((!f->tool_bar_resized
1693 && (NILP (fullscreen =
1694 get_frame_param (f, Qfullscreen))
1695 || EQ (fullscreen, Qfullwidth))) ? 1
1696 : (old_height == 0 || height == 0) ? 2
1697 : 4),
1698 false, Qtool_bar_lines);
1700 f->tool_bar_resized = f->tool_bar_redisplayed;
1702 /* adjust_frame_size might not have done anything, garbage frame
1703 here. */
1704 adjust_frame_glyphs (f);
1705 SET_FRAME_GARBAGED (f);
1706 if (FRAME_X_WINDOW (f))
1707 x_clear_under_internal_border (f);
1709 #endif /* USE_GTK */
1713 static void
1714 x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1716 int border;
1718 CHECK_TYPE_RANGED_INTEGER (int, arg);
1719 border = max (XINT (arg), 0);
1721 if (border != FRAME_INTERNAL_BORDER_WIDTH (f))
1723 f->internal_border_width = border;
1725 #ifdef USE_X_TOOLKIT
1726 if (FRAME_X_OUTPUT (f)->edit_widget)
1727 widget_store_internal_border (FRAME_X_OUTPUT (f)->edit_widget);
1728 #endif
1730 if (FRAME_X_WINDOW (f))
1732 adjust_frame_size (f, -1, -1, 3, false, Qinternal_border_width);
1733 x_clear_under_internal_border (f);
1740 /* Set the foreground color for scroll bars on frame F to VALUE.
1741 VALUE should be a string, a color name. If it isn't a string or
1742 isn't a valid color name, do nothing. OLDVAL is the old value of
1743 the frame parameter. */
1745 static void
1746 x_set_scroll_bar_foreground (struct frame *f, Lisp_Object value, Lisp_Object oldval)
1748 unsigned long pixel;
1750 if (STRINGP (value))
1751 pixel = x_decode_color (f, value, BLACK_PIX_DEFAULT (f));
1752 else
1753 pixel = -1;
1755 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
1756 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
1758 f->output_data.x->scroll_bar_foreground_pixel = pixel;
1759 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
1761 /* Remove all scroll bars because they have wrong colors. */
1762 if (FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
1763 (*FRAME_TERMINAL (f)->condemn_scroll_bars_hook) (f);
1764 if (FRAME_TERMINAL (f)->judge_scroll_bars_hook)
1765 (*FRAME_TERMINAL (f)->judge_scroll_bars_hook) (f);
1767 update_face_from_frame_parameter (f, Qscroll_bar_foreground, value);
1768 redraw_frame (f);
1773 /* Set the background color for scroll bars on frame F to VALUE VALUE
1774 should be a string, a color name. If it isn't a string or isn't a
1775 valid color name, do nothing. OLDVAL is the old value of the frame
1776 parameter. */
1778 static void
1779 x_set_scroll_bar_background (struct frame *f, Lisp_Object value, Lisp_Object oldval)
1781 unsigned long pixel;
1783 if (STRINGP (value))
1784 pixel = x_decode_color (f, value, WHITE_PIX_DEFAULT (f));
1785 else
1786 pixel = -1;
1788 if (f->output_data.x->scroll_bar_background_pixel != -1)
1789 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
1791 #if defined (USE_LUCID) && defined (USE_TOOLKIT_SCROLL_BARS)
1792 /* Scrollbar shadow colors. */
1793 if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
1795 unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
1796 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
1798 if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
1800 unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
1801 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
1803 #endif /* USE_LUCID && USE_TOOLKIT_SCROLL_BARS */
1805 f->output_data.x->scroll_bar_background_pixel = pixel;
1806 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
1808 /* Remove all scroll bars because they have wrong colors. */
1809 if (FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
1810 (*FRAME_TERMINAL (f)->condemn_scroll_bars_hook) (f);
1811 if (FRAME_TERMINAL (f)->judge_scroll_bars_hook)
1812 (*FRAME_TERMINAL (f)->judge_scroll_bars_hook) (f);
1814 update_face_from_frame_parameter (f, Qscroll_bar_background, value);
1815 redraw_frame (f);
1820 /* Encode Lisp string STRING as a text in a format appropriate for
1821 XICCC (X Inter Client Communication Conventions).
1823 If STRING contains only ASCII characters, do no conversion and
1824 return the string data of STRING. Otherwise, encode the text by
1825 CODING_SYSTEM, and return a newly allocated memory area which
1826 should be freed by `xfree' by a caller.
1828 Store the byte length of resulting text in *TEXT_BYTES.
1830 If the text contains only ASCII and Latin-1, store true in *STRING_P,
1831 which means that the `encoding' of the result can be `STRING'.
1832 Otherwise store false in *STRINGP, which means that the `encoding' of
1833 the result should be `COMPOUND_TEXT'. */
1835 static unsigned char *
1836 x_encode_text (Lisp_Object string, Lisp_Object coding_system,
1837 ptrdiff_t *text_bytes, bool *stringp, bool *freep)
1839 int result = string_xstring_p (string);
1840 struct coding_system coding;
1842 if (result == 0)
1844 /* No multibyte character in OBJ. We need not encode it. */
1845 *text_bytes = SBYTES (string);
1846 *stringp = true;
1847 *freep = false;
1848 return SDATA (string);
1851 setup_coding_system (coding_system, &coding);
1852 coding.mode |= (CODING_MODE_SAFE_ENCODING | CODING_MODE_LAST_BLOCK);
1853 /* We suppress producing escape sequences for composition. */
1854 coding.common_flags &= ~CODING_ANNOTATION_MASK;
1855 coding.destination = xnmalloc (SCHARS (string), 2);
1856 coding.dst_bytes = SCHARS (string) * 2;
1857 encode_coding_object (&coding, string, 0, 0,
1858 SCHARS (string), SBYTES (string), Qnil);
1859 *text_bytes = coding.produced;
1860 *stringp = (result == 1 || !EQ (coding_system, Qcompound_text));
1861 *freep = true;
1862 return coding.destination;
1866 /* Set the WM name to NAME for frame F. Also set the icon name.
1867 If the frame already has an icon name, use that, otherwise set the
1868 icon name to NAME. */
1870 static void
1871 x_set_name_internal (struct frame *f, Lisp_Object name)
1873 if (FRAME_X_WINDOW (f))
1875 block_input ();
1877 XTextProperty text, icon;
1878 ptrdiff_t bytes;
1879 bool stringp;
1880 bool do_free_icon_value = false, do_free_text_value = false;
1881 Lisp_Object coding_system;
1882 Lisp_Object encoded_name;
1883 Lisp_Object encoded_icon_name;
1885 /* As ENCODE_UTF_8 may cause GC and relocation of string data,
1886 we use it before x_encode_text that may return string data. */
1887 encoded_name = ENCODE_UTF_8 (name);
1889 coding_system = Qcompound_text;
1890 /* Note: Encoding strategy
1892 We encode NAME by compound-text and use "COMPOUND-TEXT" in
1893 text.encoding. But, there are non-internationalized window
1894 managers which don't support that encoding. So, if NAME
1895 contains only ASCII and 8859-1 characters, encode it by
1896 iso-latin-1, and use "STRING" in text.encoding hoping that
1897 such window managers at least analyze this format correctly,
1898 i.e. treat 8-bit bytes as 8859-1 characters.
1900 We may also be able to use "UTF8_STRING" in text.encoding
1901 in the future which can encode all Unicode characters.
1902 But, for the moment, there's no way to know that the
1903 current window manager supports it or not.
1905 Either way, we also set the _NET_WM_NAME and _NET_WM_ICON_NAME
1906 properties. Per the EWMH specification, those two properties
1907 are always UTF8_STRING. This matches what gtk_window_set_title()
1908 does in the USE_GTK case. */
1909 text.value = x_encode_text (name, coding_system, &bytes,
1910 &stringp, &do_free_text_value);
1911 text.encoding = (stringp ? XA_STRING
1912 : FRAME_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
1913 text.format = 8;
1914 text.nitems = bytes;
1916 if (!STRINGP (f->icon_name))
1918 icon = text;
1919 encoded_icon_name = encoded_name;
1921 else
1923 /* See the above comment "Note: Encoding strategy". */
1924 icon.value = x_encode_text (f->icon_name, coding_system, &bytes,
1925 &stringp, &do_free_icon_value);
1926 icon.encoding = (stringp ? XA_STRING
1927 : FRAME_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
1928 icon.format = 8;
1929 icon.nitems = bytes;
1931 encoded_icon_name = ENCODE_UTF_8 (f->icon_name);
1934 #ifdef USE_GTK
1935 gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
1936 SSDATA (encoded_name));
1937 #else /* not USE_GTK */
1938 XSetWMName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text);
1939 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
1940 FRAME_DISPLAY_INFO (f)->Xatom_net_wm_name,
1941 FRAME_DISPLAY_INFO (f)->Xatom_UTF8_STRING,
1942 8, PropModeReplace,
1943 SDATA (encoded_name),
1944 SBYTES (encoded_name));
1945 #endif /* not USE_GTK */
1947 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &icon);
1948 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
1949 FRAME_DISPLAY_INFO (f)->Xatom_net_wm_icon_name,
1950 FRAME_DISPLAY_INFO (f)->Xatom_UTF8_STRING,
1951 8, PropModeReplace,
1952 SDATA (encoded_icon_name),
1953 SBYTES (encoded_icon_name));
1955 if (do_free_icon_value)
1956 xfree (icon.value);
1957 if (do_free_text_value)
1958 xfree (text.value);
1960 unblock_input ();
1964 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
1965 x_id_name.
1967 If EXPLICIT is true, that indicates that lisp code is setting the
1968 name; if NAME is a string, set F's name to NAME and set
1969 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
1971 If EXPLICIT is false, that indicates that Emacs redisplay code is
1972 suggesting a new name, which lisp code should override; if
1973 F->explicit_name is set, ignore the new name; otherwise, set it. */
1975 static void
1976 x_set_name (struct frame *f, Lisp_Object name, bool explicit)
1978 /* Make sure that requests from lisp code override requests from
1979 Emacs redisplay code. */
1980 if (explicit)
1982 /* If we're switching from explicit to implicit, we had better
1983 update the mode lines and thereby update the title. */
1984 if (f->explicit_name && NILP (name))
1985 update_mode_lines = 37;
1987 f->explicit_name = ! NILP (name);
1989 else if (f->explicit_name)
1990 return;
1992 /* If NAME is nil, set the name to the x_id_name. */
1993 if (NILP (name))
1995 /* Check for no change needed in this very common case
1996 before we do any consing. */
1997 if (!strcmp (FRAME_DISPLAY_INFO (f)->x_id_name,
1998 SSDATA (f->name)))
1999 return;
2000 name = build_string (FRAME_DISPLAY_INFO (f)->x_id_name);
2002 else
2003 CHECK_STRING (name);
2005 /* Don't change the name if it's already NAME. */
2006 if (! NILP (Fstring_equal (name, f->name)))
2007 return;
2009 fset_name (f, name);
2011 /* For setting the frame title, the title parameter should override
2012 the name parameter. */
2013 if (! NILP (f->title))
2014 name = f->title;
2016 x_set_name_internal (f, name);
2019 /* This function should be called when the user's lisp code has
2020 specified a name for the frame; the name will override any set by the
2021 redisplay code. */
2022 static void
2023 x_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
2025 x_set_name (f, arg, true);
2028 /* This function should be called by Emacs redisplay code to set the
2029 name; names set this way will never override names set by the user's
2030 lisp code. */
2031 void
2032 x_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
2034 x_set_name (f, arg, false);
2037 /* Change the title of frame F to NAME.
2038 If NAME is nil, use the frame name as the title. */
2040 static void
2041 x_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name)
2043 /* Don't change the title if it's already NAME. */
2044 if (EQ (name, f->title))
2045 return;
2047 update_mode_lines = 38;
2049 fset_title (f, name);
2051 if (NILP (name))
2052 name = f->name;
2053 else
2054 CHECK_STRING (name);
2056 x_set_name_internal (f, name);
2059 void
2060 x_set_scroll_bar_default_width (struct frame *f)
2062 int unit = FRAME_COLUMN_WIDTH (f);
2063 #ifdef USE_TOOLKIT_SCROLL_BARS
2064 #ifdef USE_GTK
2065 int minw = xg_get_default_scrollbar_width (f);
2066 #else
2067 int minw = 16;
2068 #endif
2069 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
2070 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (minw + unit - 1) / unit;
2071 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = minw;
2072 #else
2073 /* The width of a non-toolkit scrollbar is 14 pixels. */
2074 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit;
2075 FRAME_CONFIG_SCROLL_BAR_WIDTH (f)
2076 = FRAME_CONFIG_SCROLL_BAR_COLS (f) * unit;
2077 #endif
2080 void
2081 x_set_scroll_bar_default_height (struct frame *f)
2083 int height = FRAME_LINE_HEIGHT (f);
2084 #ifdef USE_TOOLKIT_SCROLL_BARS
2085 #ifdef USE_GTK
2086 int min_height = xg_get_default_scrollbar_height (f);
2087 #else
2088 int min_height = 16;
2089 #endif
2090 /* A minimum height of 14 doesn't look good for toolkit scroll bars. */
2091 FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = min_height;
2092 FRAME_CONFIG_SCROLL_BAR_LINES (f) = (min_height + height - 1) / height;
2093 #else
2094 /* The height of a non-toolkit scrollbar is 14 pixels. */
2095 FRAME_CONFIG_SCROLL_BAR_LINES (f) = (14 + height - 1) / height;
2097 /* Use all of that space (aside from required margins) for the
2098 scroll bar. */
2099 FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = 14;
2100 #endif
2104 /* Record in frame F the specified or default value according to ALIST
2105 of the parameter named PROP (a Lisp symbol). If no value is
2106 specified for PROP, look for an X default for XPROP on the frame
2107 named NAME. If that is not found either, use the value DEFLT. */
2109 static Lisp_Object
2110 x_default_scroll_bar_color_parameter (struct frame *f,
2111 Lisp_Object alist, Lisp_Object prop,
2112 const char *xprop, const char *xclass,
2113 bool foreground_p)
2115 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
2116 Lisp_Object tem;
2118 tem = x_get_arg (dpyinfo, alist, prop, xprop, xclass, RES_TYPE_STRING);
2119 if (EQ (tem, Qunbound))
2121 #ifdef USE_TOOLKIT_SCROLL_BARS
2123 /* See if an X resource for the scroll bar color has been
2124 specified. */
2125 AUTO_STRING (foreground, "foreground");
2126 AUTO_STRING (background, "foreground");
2127 AUTO_STRING (verticalScrollBar, "verticalScrollBar");
2128 tem = (display_x_get_resource
2129 (dpyinfo, foreground_p ? foreground : background,
2130 empty_unibyte_string,
2131 verticalScrollBar,
2132 empty_unibyte_string));
2133 if (!STRINGP (tem))
2135 /* If nothing has been specified, scroll bars will use a
2136 toolkit-dependent default. Because these defaults are
2137 difficult to get at without actually creating a scroll
2138 bar, use nil to indicate that no color has been
2139 specified. */
2140 tem = Qnil;
2143 #else /* not USE_TOOLKIT_SCROLL_BARS */
2145 tem = Qnil;
2147 #endif /* not USE_TOOLKIT_SCROLL_BARS */
2150 AUTO_FRAME_ARG (arg, prop, tem);
2151 x_set_frame_parameters (f, arg);
2152 return tem;
2158 #ifdef USE_X_TOOLKIT
2160 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
2161 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
2162 already be present because of the toolkit (Motif adds some of them,
2163 for example, but Xt doesn't). */
2165 static void
2166 hack_wm_protocols (struct frame *f, Widget widget)
2168 Display *dpy = XtDisplay (widget);
2169 Window w = XtWindow (widget);
2170 bool need_delete = true;
2171 bool need_focus = true;
2172 bool need_save = true;
2174 block_input ();
2176 Atom type;
2177 unsigned char *catoms;
2178 int format = 0;
2179 unsigned long nitems = 0;
2180 unsigned long bytes_after;
2182 if ((XGetWindowProperty (dpy, w,
2183 FRAME_DISPLAY_INFO (f)->Xatom_wm_protocols,
2184 0, 100, False, XA_ATOM,
2185 &type, &format, &nitems, &bytes_after,
2186 &catoms)
2187 == Success)
2188 && format == 32 && type == XA_ATOM)
2190 Atom *atoms = (Atom *) catoms;
2191 while (nitems > 0)
2193 nitems--;
2194 if (atoms[nitems]
2195 == FRAME_DISPLAY_INFO (f)->Xatom_wm_delete_window)
2196 need_delete = false;
2197 else if (atoms[nitems]
2198 == FRAME_DISPLAY_INFO (f)->Xatom_wm_take_focus)
2199 need_focus = false;
2200 else if (atoms[nitems]
2201 == FRAME_DISPLAY_INFO (f)->Xatom_wm_save_yourself)
2202 need_save = false;
2205 if (catoms)
2206 XFree (catoms);
2209 Atom props[10];
2210 int count = 0;
2211 if (need_delete)
2212 props[count++] = FRAME_DISPLAY_INFO (f)->Xatom_wm_delete_window;
2213 if (need_focus)
2214 props[count++] = FRAME_DISPLAY_INFO (f)->Xatom_wm_take_focus;
2215 if (need_save)
2216 props[count++] = FRAME_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
2217 if (count)
2218 XChangeProperty (dpy, w, FRAME_DISPLAY_INFO (f)->Xatom_wm_protocols,
2219 XA_ATOM, 32, PropModeAppend,
2220 (unsigned char *) props, count);
2222 unblock_input ();
2224 #endif
2228 /* Support routines for XIC (X Input Context). */
2230 #ifdef HAVE_X_I18N
2232 static XFontSet xic_create_xfontset (struct frame *);
2233 static XIMStyle best_xim_style (XIMStyles *);
2236 /* Supported XIM styles, ordered by preference. */
2238 static const XIMStyle supported_xim_styles[] =
2240 XIMPreeditPosition | XIMStatusArea,
2241 XIMPreeditPosition | XIMStatusNothing,
2242 XIMPreeditPosition | XIMStatusNone,
2243 XIMPreeditNothing | XIMStatusArea,
2244 XIMPreeditNothing | XIMStatusNothing,
2245 XIMPreeditNothing | XIMStatusNone,
2246 XIMPreeditNone | XIMStatusArea,
2247 XIMPreeditNone | XIMStatusNothing,
2248 XIMPreeditNone | XIMStatusNone,
2253 #if defined HAVE_X_WINDOWS && defined USE_X_TOOLKIT
2254 /* Create an X fontset on frame F with base font name BASE_FONTNAME. */
2256 static const char xic_default_fontset[] = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
2258 /* Create an Xt fontset spec from the name of a base font.
2259 If `motif' is True use the Motif syntax. */
2260 char *
2261 xic_create_fontsetname (const char *base_fontname, bool motif)
2263 const char *sep = motif ? ";" : ",";
2264 char *fontsetname;
2265 char *z;
2267 /* Make a fontset name from the base font name. */
2268 if (xic_default_fontset == base_fontname)
2270 /* There is no base font name, use the default. */
2271 fontsetname = xmalloc (strlen (base_fontname) + 2);
2272 z = stpcpy (fontsetname, base_fontname);
2274 else
2276 /* Make a fontset name from the base font name.
2277 The font set will be made of the following elements:
2278 - the base font.
2279 - the base font where the charset spec is replaced by -*-*.
2280 - the same but with the family also replaced with -*-*-. */
2281 const char *p = base_fontname;
2282 ptrdiff_t i;
2284 for (i = 0; *p; p++)
2285 if (*p == '-') i++;
2286 if (i != 14)
2288 /* As the font name doesn't conform to XLFD, we can't
2289 modify it to generalize it to allcs and allfamilies.
2290 Use the specified font plus the default. */
2291 fontsetname = xmalloc (strlen (base_fontname)
2292 + strlen (xic_default_fontset) + 3);
2293 z = stpcpy (fontsetname, base_fontname);
2294 z = stpcpy (z, sep);
2295 z = stpcpy (z, xic_default_fontset);
2297 else
2299 ptrdiff_t len;
2300 const char *p1 = NULL, *p2 = NULL, *p3 = NULL;
2301 char *font_allcs = NULL;
2302 char *font_allfamilies = NULL;
2303 char *font_all = NULL;
2304 const char *allcs = "*-*-*-*-*-*-*";
2305 const char *allfamilies = "-*-*-";
2306 const char *all = "*-*-*-*-";
2307 char *base;
2309 for (i = 0, p = base_fontname; i < 8; p++)
2311 if (*p == '-')
2313 i++;
2314 if (i == 3)
2315 p1 = p + 1;
2316 else if (i == 7)
2317 p2 = p + 1;
2318 else if (i == 6)
2319 p3 = p + 1;
2322 /* If base_fontname specifies ADSTYLE, make it a
2323 wildcard. */
2324 if (*p3 != '*')
2326 ptrdiff_t diff = (p2 - p3) - 2;
2328 base = alloca (strlen (base_fontname) + 1);
2329 memcpy (base, base_fontname, p3 - base_fontname);
2330 base[p3 - base_fontname] = '*';
2331 base[(p3 - base_fontname) + 1] = '-';
2332 strcpy (base + (p3 - base_fontname) + 2, p2);
2333 p = base + (p - base_fontname) - diff;
2334 p1 = base + (p1 - base_fontname);
2335 p2 = base + (p2 - base_fontname) - diff;
2336 base_fontname = base;
2339 /* Build the font spec that matches all charsets. */
2340 len = p - base_fontname + strlen (allcs) + 1;
2341 font_allcs = alloca (len);
2342 memcpy (font_allcs, base_fontname, p - base_fontname);
2343 strcpy (font_allcs + (p - base_fontname), allcs);
2345 /* Build the font spec that matches all families and
2346 add-styles. */
2347 len = p - p1 + strlen (allcs) + strlen (allfamilies) + 1;
2348 font_allfamilies = alloca (len);
2349 strcpy (font_allfamilies, allfamilies);
2350 memcpy (font_allfamilies + strlen (allfamilies), p1, p - p1);
2351 strcpy (font_allfamilies + strlen (allfamilies) + (p - p1), allcs);
2353 /* Build the font spec that matches all. */
2354 len = p - p2 + strlen (allcs) + strlen (all) + strlen (allfamilies) + 1;
2355 font_all = alloca (len);
2356 z = stpcpy (font_all, allfamilies);
2357 z = stpcpy (z, all);
2358 memcpy (z, p2, p - p2);
2359 strcpy (z + (p - p2), allcs);
2361 /* Build the actual font set name. */
2362 len = strlen (base_fontname) + strlen (font_allcs)
2363 + strlen (font_allfamilies) + strlen (font_all) + 5;
2364 fontsetname = xmalloc (len);
2365 z = stpcpy (fontsetname, base_fontname);
2366 z = stpcpy (z, sep);
2367 z = stpcpy (z, font_allcs);
2368 z = stpcpy (z, sep);
2369 z = stpcpy (z, font_allfamilies);
2370 z = stpcpy (z, sep);
2371 z = stpcpy (z, font_all);
2374 if (motif)
2375 strcpy (z, ":");
2376 return fontsetname;
2378 #endif /* HAVE_X_WINDOWS && USE_X_TOOLKIT */
2380 #ifdef DEBUG_XIC_FONTSET
2381 static void
2382 print_fontset_result (XFontSet xfs, char *name, char **missing_list,
2383 int missing_count)
2385 if (xfs)
2386 fprintf (stderr, "XIC Fontset created: %s\n", name);
2387 else
2389 fprintf (stderr, "XIC Fontset failed: %s\n", name);
2390 while (missing_count-- > 0)
2392 fprintf (stderr, " missing: %s\n", *missing_list);
2393 missing_list++;
2398 #endif
2400 static XFontSet
2401 xic_create_xfontset (struct frame *f)
2403 XFontSet xfs = NULL;
2404 struct font *font = FRAME_FONT (f);
2405 int pixel_size = font->pixel_size;
2406 Lisp_Object rest, frame;
2408 /* See if there is another frame already using same fontset. */
2409 FOR_EACH_FRAME (rest, frame)
2411 struct frame *cf = XFRAME (frame);
2413 if (cf != f && FRAME_LIVE_P (f) && FRAME_X_P (cf)
2414 && FRAME_DISPLAY_INFO (cf) == FRAME_DISPLAY_INFO (f)
2415 && FRAME_FONT (f)
2416 && FRAME_FONT (f)->pixel_size == pixel_size)
2418 xfs = FRAME_XIC_FONTSET (cf);
2419 break;
2423 if (! xfs)
2425 char buf[256];
2426 char **missing_list;
2427 int missing_count;
2428 char *def_string;
2429 const char *xlfd_format = "-*-*-medium-r-normal--%d-*-*-*-*-*";
2431 sprintf (buf, xlfd_format, pixel_size);
2432 missing_list = NULL;
2433 xfs = XCreateFontSet (FRAME_X_DISPLAY (f), buf,
2434 &missing_list, &missing_count, &def_string);
2435 #ifdef DEBUG_XIC_FONTSET
2436 print_fontset_result (xfs, buf, missing_list, missing_count);
2437 #endif
2438 if (missing_list)
2439 XFreeStringList (missing_list);
2440 if (! xfs)
2442 /* List of pixel sizes most likely available. Find one that
2443 is closest to pixel_size. */
2444 int sizes[] = {0, 8, 10, 11, 12, 14, 17, 18, 20, 24, 26, 34, 0};
2445 int *smaller, *larger;
2447 for (smaller = sizes; smaller[1]; smaller++)
2448 if (smaller[1] >= pixel_size)
2449 break;
2450 larger = smaller + 1;
2451 if (*larger == pixel_size)
2452 larger++;
2453 while (*smaller || *larger)
2455 int this_size;
2457 if (! *larger)
2458 this_size = *smaller--;
2459 else if (! *smaller)
2460 this_size = *larger++;
2461 else if (pixel_size - *smaller < *larger - pixel_size)
2462 this_size = *smaller--;
2463 else
2464 this_size = *larger++;
2465 sprintf (buf, xlfd_format, this_size);
2466 missing_list = NULL;
2467 xfs = XCreateFontSet (FRAME_X_DISPLAY (f), buf,
2468 &missing_list, &missing_count, &def_string);
2469 #ifdef DEBUG_XIC_FONTSET
2470 print_fontset_result (xfs, buf, missing_list, missing_count);
2471 #endif
2472 if (missing_list)
2473 XFreeStringList (missing_list);
2474 if (xfs)
2475 break;
2478 if (! xfs)
2480 const char *last_resort = "-*-*-*-r-normal--*-*-*-*-*-*";
2482 missing_list = NULL;
2483 xfs = XCreateFontSet (FRAME_X_DISPLAY (f), last_resort,
2484 &missing_list, &missing_count, &def_string);
2485 #ifdef DEBUG_XIC_FONTSET
2486 print_fontset_result (xfs, last_resort, missing_list, missing_count);
2487 #endif
2488 if (missing_list)
2489 XFreeStringList (missing_list);
2494 return xfs;
2497 /* Free the X fontset of frame F if it is the last frame using it. */
2499 void
2500 xic_free_xfontset (struct frame *f)
2502 Lisp_Object rest, frame;
2503 bool shared_p = false;
2505 if (!FRAME_XIC_FONTSET (f))
2506 return;
2508 /* See if there is another frame sharing the same fontset. */
2509 FOR_EACH_FRAME (rest, frame)
2511 struct frame *cf = XFRAME (frame);
2512 if (cf != f && FRAME_LIVE_P (f) && FRAME_X_P (cf)
2513 && FRAME_DISPLAY_INFO (cf) == FRAME_DISPLAY_INFO (f)
2514 && FRAME_XIC_FONTSET (cf) == FRAME_XIC_FONTSET (f))
2516 shared_p = true;
2517 break;
2521 if (!shared_p)
2522 /* The fontset is not used anymore. It is safe to free it. */
2523 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
2525 FRAME_XIC_FONTSET (f) = NULL;
2529 /* Value is the best input style, given user preferences USER (already
2530 checked to be supported by Emacs), and styles supported by the
2531 input method XIM. */
2533 static XIMStyle
2534 best_xim_style (XIMStyles *xim)
2536 int i, j;
2537 int nr_supported = ARRAYELTS (supported_xim_styles);
2539 for (i = 0; i < nr_supported; ++i)
2540 for (j = 0; j < xim->count_styles; ++j)
2541 if (supported_xim_styles[i] == xim->supported_styles[j])
2542 return supported_xim_styles[i];
2544 /* Return the default style. */
2545 return XIMPreeditNothing | XIMStatusNothing;
2548 /* Create XIC for frame F. */
2550 void
2551 create_frame_xic (struct frame *f)
2553 XIM xim;
2554 XIC xic = NULL;
2555 XFontSet xfs = NULL;
2556 XVaNestedList status_attr = NULL;
2557 XVaNestedList preedit_attr = NULL;
2558 XRectangle s_area;
2559 XPoint spot;
2560 XIMStyle xic_style;
2562 if (FRAME_XIC (f))
2563 goto out;
2565 xim = FRAME_X_XIM (f);
2566 if (!xim)
2567 goto out;
2569 /* Determine XIC style. */
2570 xic_style = best_xim_style (FRAME_X_XIM_STYLES (f));
2572 /* Create X fontset. */
2573 if (xic_style & (XIMPreeditPosition | XIMStatusArea))
2575 xfs = xic_create_xfontset (f);
2576 if (!xfs)
2577 goto out;
2579 FRAME_XIC_FONTSET (f) = xfs;
2582 if (xic_style & XIMPreeditPosition)
2584 spot.x = 0; spot.y = 1;
2585 preedit_attr = XVaCreateNestedList (0,
2586 XNFontSet, xfs,
2587 XNForeground,
2588 FRAME_FOREGROUND_PIXEL (f),
2589 XNBackground,
2590 FRAME_BACKGROUND_PIXEL (f),
2591 (xic_style & XIMPreeditPosition
2592 ? XNSpotLocation
2593 : NULL),
2594 &spot,
2595 NULL);
2597 if (!preedit_attr)
2598 goto out;
2601 if (xic_style & XIMStatusArea)
2603 s_area.x = 0; s_area.y = 0; s_area.width = 1; s_area.height = 1;
2604 status_attr = XVaCreateNestedList (0,
2605 XNArea,
2606 &s_area,
2607 XNFontSet,
2608 xfs,
2609 XNForeground,
2610 FRAME_FOREGROUND_PIXEL (f),
2611 XNBackground,
2612 FRAME_BACKGROUND_PIXEL (f),
2613 NULL);
2615 if (!status_attr)
2616 goto out;
2619 if (preedit_attr && status_attr)
2620 xic = XCreateIC (xim,
2621 XNInputStyle, xic_style,
2622 XNClientWindow, FRAME_X_WINDOW (f),
2623 XNFocusWindow, FRAME_X_WINDOW (f),
2624 XNStatusAttributes, status_attr,
2625 XNPreeditAttributes, preedit_attr,
2626 NULL);
2627 else if (preedit_attr)
2628 xic = XCreateIC (xim,
2629 XNInputStyle, xic_style,
2630 XNClientWindow, FRAME_X_WINDOW (f),
2631 XNFocusWindow, FRAME_X_WINDOW (f),
2632 XNPreeditAttributes, preedit_attr,
2633 NULL);
2634 else if (status_attr)
2635 xic = XCreateIC (xim,
2636 XNInputStyle, xic_style,
2637 XNClientWindow, FRAME_X_WINDOW (f),
2638 XNFocusWindow, FRAME_X_WINDOW (f),
2639 XNStatusAttributes, status_attr,
2640 NULL);
2641 else
2642 xic = XCreateIC (xim,
2643 XNInputStyle, xic_style,
2644 XNClientWindow, FRAME_X_WINDOW (f),
2645 XNFocusWindow, FRAME_X_WINDOW (f),
2646 NULL);
2648 if (!xic)
2649 goto out;
2651 FRAME_XIC (f) = xic;
2652 FRAME_XIC_STYLE (f) = xic_style;
2653 xfs = NULL; /* Don't free below. */
2655 out:
2657 if (xfs)
2658 free_frame_xic (f);
2660 if (preedit_attr)
2661 XFree (preedit_attr);
2663 if (status_attr)
2664 XFree (status_attr);
2668 /* Destroy XIC and free XIC fontset of frame F, if any. */
2670 void
2671 free_frame_xic (struct frame *f)
2673 if (FRAME_XIC (f) == NULL)
2674 return;
2676 XDestroyIC (FRAME_XIC (f));
2677 xic_free_xfontset (f);
2679 FRAME_XIC (f) = NULL;
2683 /* Place preedit area for XIC of window W's frame to specified
2684 pixel position X/Y. X and Y are relative to window W. */
2686 void
2687 xic_set_preeditarea (struct window *w, int x, int y)
2689 struct frame *f = XFRAME (w->frame);
2690 XVaNestedList attr;
2691 XPoint spot;
2693 spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x) + WINDOW_LEFT_FRINGE_WIDTH (w);
2694 spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f));
2695 attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL);
2696 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
2697 XFree (attr);
2701 /* Place status area for XIC in bottom right corner of frame F.. */
2703 void
2704 xic_set_statusarea (struct frame *f)
2706 XIC xic = FRAME_XIC (f);
2707 XVaNestedList attr;
2708 XRectangle area;
2709 XRectangle *needed;
2711 /* Negotiate geometry of status area. If input method has existing
2712 status area, use its current size. */
2713 area.x = area.y = area.width = area.height = 0;
2714 attr = XVaCreateNestedList (0, XNAreaNeeded, &area, NULL);
2715 XSetICValues (xic, XNStatusAttributes, attr, NULL);
2716 XFree (attr);
2718 attr = XVaCreateNestedList (0, XNAreaNeeded, &needed, NULL);
2719 XGetICValues (xic, XNStatusAttributes, attr, NULL);
2720 XFree (attr);
2722 if (needed->width == 0) /* Use XNArea instead of XNAreaNeeded */
2724 attr = XVaCreateNestedList (0, XNArea, &needed, NULL);
2725 XGetICValues (xic, XNStatusAttributes, attr, NULL);
2726 XFree (attr);
2729 area.width = needed->width;
2730 area.height = needed->height;
2731 area.x = FRAME_PIXEL_WIDTH (f) - area.width - FRAME_INTERNAL_BORDER_WIDTH (f);
2732 area.y = (FRAME_PIXEL_HEIGHT (f) - area.height
2733 - FRAME_MENUBAR_HEIGHT (f)
2734 - FRAME_TOOLBAR_TOP_HEIGHT (f)
2735 - FRAME_INTERNAL_BORDER_WIDTH (f));
2736 XFree (needed);
2738 attr = XVaCreateNestedList (0, XNArea, &area, NULL);
2739 XSetICValues (xic, XNStatusAttributes, attr, NULL);
2740 XFree (attr);
2744 /* Set X fontset for XIC of frame F, using base font name
2745 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
2747 void
2748 xic_set_xfontset (struct frame *f, const char *base_fontname)
2750 XVaNestedList attr;
2751 XFontSet xfs;
2753 xic_free_xfontset (f);
2755 xfs = xic_create_xfontset (f);
2757 attr = XVaCreateNestedList (0, XNFontSet, xfs, NULL);
2758 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
2759 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
2760 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
2761 XSetICValues (FRAME_XIC (f), XNStatusAttributes, attr, NULL);
2762 XFree (attr);
2764 FRAME_XIC_FONTSET (f) = xfs;
2767 #endif /* HAVE_X_I18N */
2772 void
2773 x_mark_frame_dirty (struct frame *f)
2775 if (FRAME_X_DOUBLE_BUFFERED_P (f) && !FRAME_X_NEED_BUFFER_FLIP (f))
2776 FRAME_X_NEED_BUFFER_FLIP (f) = true;
2779 static void
2780 set_up_x_back_buffer (struct frame *f)
2782 #ifdef HAVE_XDBE
2783 block_input ();
2784 if (FRAME_X_WINDOW (f) && !FRAME_X_DOUBLE_BUFFERED_P (f))
2786 FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
2787 if (FRAME_DISPLAY_INFO (f)->supports_xdbe)
2789 /* If allocating a back buffer fails, either because the
2790 server ran out of memory or we don't have the right kind
2791 of visual, just use single-buffered rendering. */
2792 x_catch_errors (FRAME_X_DISPLAY (f));
2793 FRAME_X_RAW_DRAWABLE (f) = XdbeAllocateBackBufferName (
2794 FRAME_X_DISPLAY (f),
2795 FRAME_X_WINDOW (f),
2796 XdbeCopied);
2797 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
2798 FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
2799 x_uncatch_errors_after_check ();
2802 unblock_input ();
2803 #endif
2806 void
2807 tear_down_x_back_buffer (struct frame *f)
2809 #ifdef HAVE_XDBE
2810 block_input ();
2811 if (FRAME_X_WINDOW (f) && FRAME_X_DOUBLE_BUFFERED_P (f))
2813 if (FRAME_X_DOUBLE_BUFFERED_P (f))
2815 XdbeDeallocateBackBufferName (FRAME_X_DISPLAY (f),
2816 FRAME_X_DRAWABLE (f));
2817 FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
2820 unblock_input ();
2821 #endif
2824 /* Set up double buffering if the frame parameters don't prohibit
2825 it. */
2826 void
2827 initial_set_up_x_back_buffer (struct frame *f)
2829 block_input ();
2830 eassert (FRAME_X_WINDOW (f));
2831 FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
2832 if (NILP (CDR (Fassq (Qinhibit_double_buffering, f->param_alist))))
2833 set_up_x_back_buffer (f);
2834 unblock_input ();
2837 #ifdef USE_X_TOOLKIT
2839 /* Create and set up the X widget for frame F. */
2841 static void
2842 x_window (struct frame *f, long window_prompting)
2844 XClassHint class_hints;
2845 XSetWindowAttributes attributes;
2846 unsigned long attribute_mask;
2847 Widget shell_widget;
2848 Widget pane_widget;
2849 Widget frame_widget;
2850 Arg al[25];
2851 int ac;
2853 block_input ();
2855 /* Use the resource name as the top-level widget name
2856 for looking up resources. Make a non-Lisp copy
2857 for the window manager, so GC relocation won't bother it.
2859 Elsewhere we specify the window name for the window manager. */
2860 f->namebuf = xlispstrdup (Vx_resource_name);
2862 ac = 0;
2863 XtSetArg (al[ac], XtNallowShellResize, 1); ac++;
2864 XtSetArg (al[ac], XtNinput, 1); ac++;
2865 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
2866 XtSetArg (al[ac], XtNborderWidth, f->border_width); ac++;
2867 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
2868 XtSetArg (al[ac], XtNdepth, FRAME_DISPLAY_INFO (f)->n_planes); ac++;
2869 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
2870 shell_widget = XtAppCreateShell (f->namebuf, EMACS_CLASS,
2871 applicationShellWidgetClass,
2872 FRAME_X_DISPLAY (f), al, ac);
2874 f->output_data.x->widget = shell_widget;
2875 /* maybe_set_screen_title_format (shell_widget); */
2877 pane_widget = lw_create_widget ("main", "pane", widget_id_tick++,
2878 NULL, shell_widget, False,
2879 NULL, NULL, NULL, NULL);
2881 ac = 0;
2882 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
2883 XtSetArg (al[ac], XtNdepth, FRAME_DISPLAY_INFO (f)->n_planes); ac++;
2884 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
2885 XtSetArg (al[ac], XtNborderWidth, 0); ac++;
2886 XtSetValues (pane_widget, al, ac);
2887 f->output_data.x->column_widget = pane_widget;
2889 /* mappedWhenManaged to false tells to the paned window to not map/unmap
2890 the emacs screen when changing menubar. This reduces flickering. */
2892 ac = 0;
2893 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
2894 XtSetArg (al[ac], (char *) XtNshowGrip, 0); ac++;
2895 XtSetArg (al[ac], (char *) XtNallowResize, 1); ac++;
2896 XtSetArg (al[ac], (char *) XtNresizeToPreferred, 1); ac++;
2897 XtSetArg (al[ac], (char *) XtNemacsFrame, f); ac++;
2898 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
2899 XtSetArg (al[ac], XtNdepth, FRAME_DISPLAY_INFO (f)->n_planes); ac++;
2900 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
2901 XtSetArg (al[ac], XtNborderWidth, 0); ac++;
2902 frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass (), pane_widget,
2903 al, ac);
2905 f->output_data.x->edit_widget = frame_widget;
2907 XtManageChild (frame_widget);
2909 /* Do some needed geometry management. */
2911 Arg gal[3];
2912 int gac = 0;
2913 int extra_borders = 0;
2914 int menubar_size
2915 = (f->output_data.x->menubar_widget
2916 ? (f->output_data.x->menubar_widget->core.height
2917 + f->output_data.x->menubar_widget->core.border_width)
2918 : 0);
2920 #if false /* Experimentally, we now get the right results
2921 for -geometry -0-0 without this. 24 Aug 96, rms. */
2922 if (FRAME_EXTERNAL_MENU_BAR (f))
2924 Dimension ibw = 0;
2925 XtVaGetValues (pane_widget, XtNinternalBorderWidth, &ibw, NULL);
2926 menubar_size += ibw;
2928 #endif
2930 FRAME_MENUBAR_HEIGHT (f) = menubar_size;
2932 #ifndef USE_LUCID
2933 /* Motif seems to need this amount added to the sizes
2934 specified for the shell widget. The Athena/Lucid widgets don't.
2935 Both conclusions reached experimentally. -- rms. */
2936 XtVaGetValues (f->output_data.x->edit_widget, XtNinternalBorderWidth,
2937 &extra_borders, NULL);
2938 extra_borders *= 2;
2939 #endif
2941 f->shell_position = xmalloc (sizeof "=x++" + 4 * INT_STRLEN_BOUND (int));
2943 /* Convert our geometry parameters into a geometry string
2944 and specify it.
2945 Note that we do not specify here whether the position
2946 is a user-specified or program-specified one.
2947 We pass that information later, in x_wm_set_size_hint. */
2949 int left = f->left_pos;
2950 bool xneg = (window_prompting & XNegative) != 0;
2951 int top = f->top_pos;
2952 bool yneg = (window_prompting & YNegative) != 0;
2953 if (xneg)
2954 left = -left;
2955 if (yneg)
2956 top = -top;
2958 if (window_prompting & USPosition)
2959 sprintf (f->shell_position, "=%dx%d%c%d%c%d",
2960 FRAME_PIXEL_WIDTH (f) + extra_borders,
2961 FRAME_PIXEL_HEIGHT (f) + menubar_size + extra_borders,
2962 (xneg ? '-' : '+'), left,
2963 (yneg ? '-' : '+'), top);
2964 else
2966 sprintf (f->shell_position, "=%dx%d",
2967 FRAME_PIXEL_WIDTH (f) + extra_borders,
2968 FRAME_PIXEL_HEIGHT (f) + menubar_size + extra_borders);
2970 /* Setting x and y when the position is not specified in
2971 the geometry string will set program position in the WM hints.
2972 If Emacs had just one program position, we could set it in
2973 fallback resources, but since each make-frame call can specify
2974 different program positions, this is easier. */
2975 XtSetArg (gal[gac], XtNx, left); gac++;
2976 XtSetArg (gal[gac], XtNy, top); gac++;
2980 XtSetArg (gal[gac], XtNgeometry, f->shell_position); gac++;
2981 XtSetValues (shell_widget, gal, gac);
2984 XtManageChild (pane_widget);
2985 XtRealizeWidget (shell_widget);
2987 if (FRAME_X_EMBEDDED_P (f))
2988 XReparentWindow (FRAME_X_DISPLAY (f), XtWindow (shell_widget),
2989 f->output_data.x->parent_desc, 0, 0);
2991 FRAME_X_WINDOW (f) = XtWindow (frame_widget);
2992 initial_set_up_x_back_buffer (f);
2993 validate_x_resource_name ();
2995 class_hints.res_name = SSDATA (Vx_resource_name);
2996 class_hints.res_class = SSDATA (Vx_resource_class);
2997 XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints);
2999 #ifdef HAVE_X_I18N
3000 FRAME_XIC (f) = NULL;
3001 if (use_xim)
3002 create_frame_xic (f);
3003 #endif
3005 f->output_data.x->wm_hints.input = True;
3006 f->output_data.x->wm_hints.flags |= InputHint;
3007 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3008 &f->output_data.x->wm_hints);
3010 hack_wm_protocols (f, shell_widget);
3012 #ifdef X_TOOLKIT_EDITRES
3013 XtAddEventHandler (shell_widget, 0, True, _XEditResCheckMessages, 0);
3014 #endif
3016 /* Do a stupid property change to force the server to generate a
3017 PropertyNotify event so that the event_stream server timestamp will
3018 be initialized to something relevant to the time we created the window.
3020 XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
3021 FRAME_DISPLAY_INFO (f)->Xatom_wm_protocols,
3022 XA_ATOM, 32, PropModeAppend, NULL, 0);
3024 /* Make all the standard events reach the Emacs frame. */
3025 attributes.event_mask = STANDARD_EVENT_SET;
3027 #ifdef HAVE_X_I18N
3028 if (FRAME_XIC (f))
3030 /* XIM server might require some X events. */
3031 unsigned long fevent = NoEventMask;
3032 XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
3033 attributes.event_mask |= fevent;
3035 #endif /* HAVE_X_I18N */
3037 attributes.override_redirect = FRAME_OVERRIDE_REDIRECT (f);
3038 attribute_mask = CWEventMask | CWOverrideRedirect;
3039 XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
3040 attribute_mask, &attributes);
3042 XtMapWidget (frame_widget);
3044 /* x_set_name normally ignores requests to set the name if the
3045 requested name is the same as the current name. This is the one
3046 place where that assumption isn't correct; f->name is set, but
3047 the X server hasn't been told. */
3049 Lisp_Object name;
3050 bool explicit = f->explicit_name;
3052 f->explicit_name = false;
3053 name = f->name;
3054 fset_name (f, Qnil);
3055 x_set_name (f, name, explicit);
3058 if (FRAME_UNDECORATED (f))
3060 Display *dpy = FRAME_X_DISPLAY (f);
3061 PropMotifWmHints hints;
3062 Atom prop = XInternAtom (dpy, "_MOTIF_WM_HINTS", False);
3064 memset (&hints, 0, sizeof(hints));
3065 hints.flags = MWM_HINTS_DECORATIONS;
3066 hints.decorations = 0;
3068 /* For some reason the third and fourth arguments in the following
3069 call must be identical: In the corresponding XGetWindowProperty
3070 call in getMotifHints, xfwm has the third and seventh args both
3071 display_info->atoms[MOTIF_WM_HINTS]. Obviously, YMMV. */
3072 XChangeProperty (dpy, FRAME_OUTER_WINDOW (f), prop, prop, 32,
3073 PropModeReplace, (unsigned char *) &hints,
3074 PROP_MOTIF_WM_HINTS_ELEMENTS);
3077 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3078 f->output_data.x->current_cursor
3079 = f->output_data.x->text_cursor);
3081 unblock_input ();
3083 /* This is a no-op, except under Motif. Make sure main areas are
3084 set to something reasonable, in case we get an error later. */
3085 lw_set_main_areas (pane_widget, 0, frame_widget);
3088 #else /* not USE_X_TOOLKIT */
3089 #ifdef USE_GTK
3090 static void
3091 x_window (struct frame *f)
3093 if (! xg_create_frame_widgets (f))
3094 error ("Unable to create window");
3096 #ifdef HAVE_X_I18N
3097 FRAME_XIC (f) = NULL;
3098 if (use_xim)
3100 block_input ();
3101 create_frame_xic (f);
3102 if (FRAME_XIC (f))
3104 /* XIM server might require some X events. */
3105 unsigned long fevent = NoEventMask;
3106 XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
3108 if (fevent != NoEventMask)
3110 XSetWindowAttributes attributes;
3111 XWindowAttributes wattr;
3112 unsigned long attribute_mask;
3114 XGetWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3115 &wattr);
3116 attributes.event_mask = wattr.your_event_mask | fevent;
3117 attribute_mask = CWEventMask;
3118 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3119 attribute_mask, &attributes);
3122 unblock_input ();
3124 #endif
3127 #else /*! USE_GTK */
3128 /* Create and set up the X window for frame F. */
3130 static void
3131 x_window (struct frame *f)
3133 XClassHint class_hints;
3134 XSetWindowAttributes attributes;
3135 unsigned long attribute_mask;
3137 attributes.background_pixel = FRAME_BACKGROUND_PIXEL (f);
3138 attributes.border_pixel = f->output_data.x->border_pixel;
3139 attributes.bit_gravity = StaticGravity;
3140 attributes.backing_store = NotUseful;
3141 attributes.save_under = True;
3142 attributes.event_mask = STANDARD_EVENT_SET;
3143 attributes.colormap = FRAME_X_COLORMAP (f);
3144 attributes.override_redirect = FRAME_OVERRIDE_REDIRECT (f);
3145 attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask
3146 | CWOverrideRedirect | CWColormap);
3148 block_input ();
3149 FRAME_X_WINDOW (f)
3150 = XCreateWindow (FRAME_X_DISPLAY (f),
3151 f->output_data.x->parent_desc,
3152 f->left_pos,
3153 f->top_pos,
3154 FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f),
3155 f->border_width,
3156 CopyFromParent, /* depth */
3157 InputOutput, /* class */
3158 FRAME_X_VISUAL (f),
3159 attribute_mask, &attributes);
3160 initial_set_up_x_back_buffer (f);
3162 #ifdef HAVE_X_I18N
3163 if (use_xim)
3165 create_frame_xic (f);
3166 if (FRAME_XIC (f))
3168 /* XIM server might require some X events. */
3169 unsigned long fevent = NoEventMask;
3170 XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
3171 attributes.event_mask |= fevent;
3172 attribute_mask = CWEventMask;
3173 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3174 attribute_mask, &attributes);
3177 #endif /* HAVE_X_I18N */
3179 validate_x_resource_name ();
3181 class_hints.res_name = SSDATA (Vx_resource_name);
3182 class_hints.res_class = SSDATA (Vx_resource_class);
3183 XSetClassHint (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &class_hints);
3185 /* This indicates that we use the "Passive Input" input model.
3186 Unless we do this, we don't get the Focus{In,Out} events that we
3187 need to draw the cursor correctly. Accursed bureaucrats.
3188 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
3190 f->output_data.x->wm_hints.input = True;
3191 f->output_data.x->wm_hints.flags |= InputHint;
3192 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3193 &f->output_data.x->wm_hints);
3194 f->output_data.x->wm_hints.icon_pixmap = None;
3196 /* Request "save yourself" and "delete window" commands from wm. */
3198 Atom protocols[2];
3199 protocols[0] = FRAME_DISPLAY_INFO (f)->Xatom_wm_delete_window;
3200 protocols[1] = FRAME_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
3201 XSetWMProtocols (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), protocols, 2);
3204 /* x_set_name normally ignores requests to set the name if the
3205 requested name is the same as the current name. This is the one
3206 place where that assumption isn't correct; f->name is set, but
3207 the X server hasn't been told. */
3209 Lisp_Object name;
3210 bool explicit = f->explicit_name;
3212 f->explicit_name = false;
3213 name = f->name;
3214 fset_name (f, Qnil);
3215 x_set_name (f, name, explicit);
3218 if (FRAME_UNDECORATED (f))
3220 Display *dpy = FRAME_X_DISPLAY (f);
3221 PropMotifWmHints hints;
3222 Atom prop = XInternAtom (dpy, "_MOTIF_WM_HINTS", False);
3224 memset (&hints, 0, sizeof(hints));
3225 hints.flags = MWM_HINTS_DECORATIONS;
3226 hints.decorations = 0;
3228 /* For some reason the third and fourth arguments in the following
3229 call must be identical: In the corresponding XGetWindowProperty
3230 call in getMotifHints, xfwm has the third and seventh args both
3231 display_info->atoms[MOTIF_WM_HINTS]. Obviously, YMMV. */
3232 XChangeProperty (dpy, FRAME_OUTER_WINDOW (f), prop, prop, 32,
3233 PropModeReplace, (unsigned char *) &hints,
3234 PROP_MOTIF_WM_HINTS_ELEMENTS);
3238 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3239 f->output_data.x->current_cursor
3240 = f->output_data.x->text_cursor);
3242 unblock_input ();
3244 if (FRAME_X_WINDOW (f) == 0)
3245 error ("Unable to create window");
3248 #endif /* not USE_GTK */
3249 #endif /* not USE_X_TOOLKIT */
3251 /* Verify that the icon position args for this window are valid. */
3253 static void
3254 x_icon_verify (struct frame *f, Lisp_Object parms)
3256 Lisp_Object icon_x, icon_y;
3258 /* Set the position of the icon. Note that twm groups all
3259 icons in an icon window. */
3260 icon_x = x_frame_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
3261 icon_y = x_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
3262 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
3264 CHECK_NUMBER (icon_x);
3265 CHECK_NUMBER (icon_y);
3267 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
3268 error ("Both left and top icon corners of icon must be specified");
3271 /* Handle the icon stuff for this window. Perhaps later we might
3272 want an x_set_icon_position which can be called interactively as
3273 well. */
3275 static void
3276 x_icon (struct frame *f, Lisp_Object parms)
3278 /* Set the position of the icon. Note that twm groups all
3279 icons in an icon window. */
3280 Lisp_Object icon_x
3281 = x_frame_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
3282 Lisp_Object icon_y
3283 = x_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
3284 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
3286 CHECK_TYPE_RANGED_INTEGER (int, icon_x);
3287 CHECK_TYPE_RANGED_INTEGER (int, icon_y);
3289 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
3290 error ("Both left and top icon corners of icon must be specified");
3292 block_input ();
3294 if (! EQ (icon_x, Qunbound))
3295 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
3297 #if false /* x_get_arg removes the visibility parameter as a side effect,
3298 but x_create_frame still needs it. */
3299 /* Start up iconic or window? */
3300 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
3301 x_wm_set_window_state
3302 (f, (EQ (x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL),
3303 Qicon)
3304 ? IconicState
3305 : NormalState));
3306 #endif
3308 x_text_icon (f, SSDATA ((!NILP (f->icon_name)
3309 ? f->icon_name
3310 : f->name)));
3312 unblock_input ();
3315 /* Make the GCs needed for this window, setting the
3316 background, border and mouse colors; also create the
3317 mouse cursor and the gray border tile. */
3319 static void
3320 x_make_gc (struct frame *f)
3322 XGCValues gc_values;
3324 block_input ();
3326 /* Create the GCs of this frame.
3327 Note that many default values are used. */
3329 gc_values.foreground = FRAME_FOREGROUND_PIXEL (f);
3330 gc_values.background = FRAME_BACKGROUND_PIXEL (f);
3331 gc_values.line_width = 0; /* Means 1 using fast algorithm. */
3332 f->output_data.x->normal_gc
3333 = XCreateGC (FRAME_X_DISPLAY (f),
3334 FRAME_X_DRAWABLE (f),
3335 GCLineWidth | GCForeground | GCBackground,
3336 &gc_values);
3338 /* Reverse video style. */
3339 gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
3340 gc_values.background = FRAME_FOREGROUND_PIXEL (f);
3341 f->output_data.x->reverse_gc
3342 = XCreateGC (FRAME_X_DISPLAY (f),
3343 FRAME_X_DRAWABLE (f),
3344 GCForeground | GCBackground | GCLineWidth,
3345 &gc_values);
3347 /* Cursor has cursor-color background, background-color foreground. */
3348 gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
3349 gc_values.background = f->output_data.x->cursor_pixel;
3350 gc_values.fill_style = FillOpaqueStippled;
3351 f->output_data.x->cursor_gc
3352 = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
3353 (GCForeground | GCBackground
3354 | GCFillStyle | GCLineWidth),
3355 &gc_values);
3357 /* Create the gray border tile used when the pointer is not in
3358 the frame. Since this depends on the frame's pixel values,
3359 this must be done on a per-frame basis. */
3360 f->output_data.x->border_tile
3361 = (XCreatePixmapFromBitmapData
3362 (FRAME_X_DISPLAY (f), FRAME_DISPLAY_INFO (f)->root_window,
3363 gray_bits, gray_width, gray_height,
3364 FRAME_FOREGROUND_PIXEL (f),
3365 FRAME_BACKGROUND_PIXEL (f),
3366 DefaultDepth (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f))));
3368 unblock_input ();
3372 /* Free what was allocated in x_make_gc. */
3374 void
3375 x_free_gcs (struct frame *f)
3377 Display *dpy = FRAME_X_DISPLAY (f);
3379 block_input ();
3381 if (f->output_data.x->normal_gc)
3383 XFreeGC (dpy, f->output_data.x->normal_gc);
3384 f->output_data.x->normal_gc = 0;
3387 if (f->output_data.x->reverse_gc)
3389 XFreeGC (dpy, f->output_data.x->reverse_gc);
3390 f->output_data.x->reverse_gc = 0;
3393 if (f->output_data.x->cursor_gc)
3395 XFreeGC (dpy, f->output_data.x->cursor_gc);
3396 f->output_data.x->cursor_gc = 0;
3399 if (f->output_data.x->border_tile)
3401 XFreePixmap (dpy, f->output_data.x->border_tile);
3402 f->output_data.x->border_tile = 0;
3405 unblock_input ();
3409 /* Handler for signals raised during x_create_frame and
3410 x_create_tip_frame. FRAME is the frame which is partially
3411 constructed. */
3413 static Lisp_Object
3414 unwind_create_frame (Lisp_Object frame)
3416 struct frame *f = XFRAME (frame);
3418 /* If frame is already dead, nothing to do. This can happen if the
3419 display is disconnected after the frame has become official, but
3420 before x_create_frame removes the unwind protect. */
3421 if (!FRAME_LIVE_P (f))
3422 return Qnil;
3424 /* If frame is ``official'', nothing to do. */
3425 if (NILP (Fmemq (frame, Vframe_list)))
3427 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
3428 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
3429 #endif
3431 /* If the frame's image cache refcount is still the same as our
3432 private shadow variable, it means we are unwinding a frame
3433 for which we didn't yet call init_frame_faces, where the
3434 refcount is incremented. Therefore, we increment it here, so
3435 that free_frame_faces, called in x_free_frame_resources
3436 below, will not mistakenly decrement the counter that was not
3437 incremented yet to account for this new frame. */
3438 if (FRAME_IMAGE_CACHE (f) != NULL
3439 && FRAME_IMAGE_CACHE (f)->refcount == image_cache_refcount)
3440 FRAME_IMAGE_CACHE (f)->refcount++;
3442 x_free_frame_resources (f);
3443 free_glyphs (f);
3445 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
3446 /* Check that reference counts are indeed correct. */
3447 eassert (dpyinfo->reference_count == dpyinfo_refcount);
3448 eassert (dpyinfo->terminal->image_cache->refcount == image_cache_refcount);
3449 #endif
3450 return Qt;
3453 return Qnil;
3456 static void
3457 do_unwind_create_frame (Lisp_Object frame)
3459 unwind_create_frame (frame);
3462 static void
3463 x_default_font_parameter (struct frame *f, Lisp_Object parms)
3465 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
3466 Lisp_Object font_param = x_get_arg (dpyinfo, parms, Qfont, NULL, NULL,
3467 RES_TYPE_STRING);
3468 Lisp_Object font = Qnil;
3469 if (EQ (font_param, Qunbound))
3470 font_param = Qnil;
3472 if (NILP (font_param))
3474 /* System font should take precedence over X resources. We suggest this
3475 regardless of font-use-system-font because .emacs may not have been
3476 read yet. */
3477 const char *system_font = xsettings_get_system_font ();
3478 if (system_font)
3479 font = font_open_by_name (f, build_unibyte_string (system_font));
3482 if (NILP (font))
3483 font = !NILP (font_param) ? font_param
3484 : x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
3486 if (! FONTP (font) && ! STRINGP (font))
3488 const char *names[]
3490 #ifdef HAVE_XFT
3491 /* This will find the normal Xft font. */
3492 "monospace-10",
3493 #endif
3494 "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1",
3495 "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1",
3496 "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1",
3497 /* This was formerly the first thing tried, but it finds
3498 too many fonts and takes too long. */
3499 "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1",
3500 /* If those didn't work, look for something which will
3501 at least work. */
3502 "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1",
3503 "fixed",
3504 NULL };
3505 int i;
3507 for (i = 0; names[i]; i++)
3509 font = font_open_by_name (f, build_unibyte_string (names[i]));
3510 if (! NILP (font))
3511 break;
3513 if (NILP (font))
3514 error ("No suitable font was found");
3516 else if (!NILP (font_param))
3518 /* Remember the explicit font parameter, so we can re-apply it after
3519 we've applied the `default' face settings. */
3520 AUTO_FRAME_ARG (arg, Qfont_parameter, font_param);
3521 x_set_frame_parameters (f, arg);
3524 /* This call will make X resources override any system font setting. */
3525 x_default_parameter (f, parms, Qfont, font, "font", "Font", RES_TYPE_STRING);
3529 DEFUN ("x-wm-set-size-hint", Fx_wm_set_size_hint, Sx_wm_set_size_hint,
3530 0, 1, 0,
3531 doc: /* Send the size hints for frame FRAME to the window manager.
3532 If FRAME is omitted or nil, use the selected frame.
3533 Signal error if FRAME is not an X frame. */)
3534 (Lisp_Object frame)
3536 struct frame *f = decode_window_system_frame (frame);
3538 block_input ();
3539 x_wm_set_size_hint (f, 0, false);
3540 unblock_input ();
3541 return Qnil;
3544 static void
3545 set_machine_and_pid_properties (struct frame *f)
3547 /* This will set WM_CLIENT_MACHINE and WM_LOCALE_NAME. */
3548 XSetWMProperties (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), NULL, NULL,
3549 NULL, 0, NULL, NULL, NULL);
3550 pid_t pid = getpid ();
3551 if (pid <= 0xffffffffu)
3553 unsigned long xpid = pid;
3554 XChangeProperty (FRAME_X_DISPLAY (f),
3555 FRAME_OUTER_WINDOW (f),
3556 XInternAtom (FRAME_X_DISPLAY (f),
3557 "_NET_WM_PID",
3558 False),
3559 XA_CARDINAL, 32, PropModeReplace,
3560 (unsigned char *) &xpid, 1);
3564 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
3565 1, 1, 0,
3566 doc: /* Make a new X window, which is called a "frame" in Emacs terms.
3567 Return an Emacs frame object. PARMS is an alist of frame parameters.
3568 If the parameters specify that the frame should not have a minibuffer,
3569 and do not specify a specific minibuffer window to use, then
3570 `default-minibuffer-frame' must be a frame whose minibuffer can be
3571 shared by the new frame.
3573 This function is an internal primitive--use `make-frame' instead. */)
3574 (Lisp_Object parms)
3576 struct frame *f;
3577 Lisp_Object frame, tem;
3578 Lisp_Object name;
3579 bool minibuffer_only = false;
3580 bool undecorated = false, override_redirect = false;
3581 long window_prompting = 0;
3582 ptrdiff_t count = SPECPDL_INDEX ();
3583 Lisp_Object display;
3584 struct x_display_info *dpyinfo = NULL;
3585 Lisp_Object parent, parent_frame;
3586 struct kboard *kb;
3587 int x_width = 0, x_height = 0;
3589 parms = Fcopy_alist (parms);
3591 /* Use this general default value to start with
3592 until we know if this frame has a specified name. */
3593 Vx_resource_name = Vinvocation_name;
3595 display = x_get_arg (dpyinfo, parms, Qterminal, 0, 0, RES_TYPE_NUMBER);
3596 if (EQ (display, Qunbound))
3597 display = x_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING);
3598 if (EQ (display, Qunbound))
3599 display = Qnil;
3600 dpyinfo = check_x_display_info (display);
3601 kb = dpyinfo->terminal->kboard;
3603 if (!dpyinfo->terminal->name)
3604 error ("Terminal is not live, can't create new frames on it");
3606 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
3607 if (!STRINGP (name)
3608 && ! EQ (name, Qunbound)
3609 && ! NILP (name))
3610 error ("Invalid frame name--not a string or nil");
3612 if (STRINGP (name))
3613 Vx_resource_name = name;
3615 /* See if parent window is specified. */
3616 parent = x_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
3617 if (EQ (parent, Qunbound))
3618 parent = Qnil;
3619 if (! NILP (parent))
3620 CHECK_NUMBER (parent);
3622 frame = Qnil;
3623 tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
3624 RES_TYPE_SYMBOL);
3625 if (EQ (tem, Qnone) || NILP (tem))
3626 f = make_frame_without_minibuffer (Qnil, kb, display);
3627 else if (EQ (tem, Qonly))
3629 f = make_minibuffer_frame ();
3630 minibuffer_only = true;
3632 else if (WINDOWP (tem))
3633 f = make_frame_without_minibuffer (tem, kb, display);
3634 else
3635 f = make_frame (true);
3637 parent_frame = x_get_arg (dpyinfo, parms, Qparent_frame, NULL, NULL,
3638 RES_TYPE_SYMBOL);
3639 /* Accept parent-frame iff parent-id was not specified. */
3640 if (!NILP (parent)
3641 || EQ (parent_frame, Qunbound)
3642 || NILP (parent_frame)
3643 || !FRAMEP (parent_frame)
3644 || !FRAME_LIVE_P (XFRAME (parent_frame))
3645 || !FRAME_X_P (XFRAME (parent_frame)))
3646 parent_frame = Qnil;
3648 fset_parent_frame (f, parent_frame);
3649 store_frame_param (f, Qparent_frame, parent_frame);
3651 if (!NILP (tem = (x_get_arg (dpyinfo, parms, Qundecorated, NULL, NULL,
3652 RES_TYPE_BOOLEAN)))
3653 && !(EQ (tem, Qunbound)))
3654 undecorated = true;
3656 FRAME_UNDECORATED (f) = undecorated;
3657 store_frame_param (f, Qundecorated, undecorated ? Qt : Qnil);
3659 if (!NILP (tem = (x_get_arg (dpyinfo, parms, Qoverride_redirect, NULL, NULL,
3660 RES_TYPE_BOOLEAN)))
3661 && !(EQ (tem, Qunbound)))
3662 override_redirect = true;
3664 FRAME_OVERRIDE_REDIRECT (f) = override_redirect;
3665 store_frame_param (f, Qoverride_redirect, override_redirect ? Qt : Qnil);
3667 XSETFRAME (frame, f);
3669 f->terminal = dpyinfo->terminal;
3671 f->output_method = output_x_window;
3672 f->output_data.x = xzalloc (sizeof *f->output_data.x);
3673 f->output_data.x->icon_bitmap = -1;
3674 FRAME_FONTSET (f) = -1;
3675 f->output_data.x->scroll_bar_foreground_pixel = -1;
3676 f->output_data.x->scroll_bar_background_pixel = -1;
3677 #if defined (USE_LUCID) && defined (USE_TOOLKIT_SCROLL_BARS)
3678 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
3679 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
3680 #endif /* USE_LUCID && USE_TOOLKIT_SCROLL_BARS */
3681 f->output_data.x->white_relief.pixel = -1;
3682 f->output_data.x->black_relief.pixel = -1;
3684 fset_icon_name (f,
3685 x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
3686 RES_TYPE_STRING));
3687 if (! STRINGP (f->icon_name))
3688 fset_icon_name (f, Qnil);
3690 FRAME_DISPLAY_INFO (f) = dpyinfo;
3692 /* With FRAME_DISPLAY_INFO set up, this unwind-protect is safe. */
3693 record_unwind_protect (do_unwind_create_frame, frame);
3695 /* These colors will be set anyway later, but it's important
3696 to get the color reference counts right, so initialize them! */
3698 Lisp_Object black;
3700 /* Function x_decode_color can signal an error. Make
3701 sure to initialize color slots so that we won't try
3702 to free colors we haven't allocated. */
3703 FRAME_FOREGROUND_PIXEL (f) = -1;
3704 FRAME_BACKGROUND_PIXEL (f) = -1;
3705 f->output_data.x->cursor_pixel = -1;
3706 f->output_data.x->cursor_foreground_pixel = -1;
3707 f->output_data.x->border_pixel = -1;
3708 f->output_data.x->mouse_pixel = -1;
3710 black = build_string ("black");
3711 FRAME_FOREGROUND_PIXEL (f)
3712 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3713 FRAME_BACKGROUND_PIXEL (f)
3714 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3715 f->output_data.x->cursor_pixel
3716 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3717 f->output_data.x->cursor_foreground_pixel
3718 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3719 f->output_data.x->border_pixel
3720 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3721 f->output_data.x->mouse_pixel
3722 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3725 /* Specify the parent under which to make this X window. */
3726 if (!NILP (parent))
3728 f->output_data.x->parent_desc = (Window) XFASTINT (parent);
3729 f->output_data.x->explicit_parent = true;
3731 else
3733 f->output_data.x->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
3734 f->output_data.x->explicit_parent = false;
3737 /* Set the name; the functions to which we pass f expect the name to
3738 be set. */
3739 if (EQ (name, Qunbound) || NILP (name))
3741 fset_name (f, build_string (dpyinfo->x_id_name));
3742 f->explicit_name = false;
3744 else
3746 fset_name (f, name);
3747 f->explicit_name = true;
3748 /* Use the frame's title when getting resources for this frame. */
3749 specbind (Qx_resource_name, name);
3752 #ifdef USE_CAIRO
3753 register_font_driver (&ftcrfont_driver, f);
3754 #else
3755 #ifdef HAVE_FREETYPE
3756 #ifdef HAVE_XFT
3757 register_font_driver (&xftfont_driver, f);
3758 #else /* not HAVE_XFT */
3759 register_font_driver (&ftxfont_driver, f);
3760 #endif /* not HAVE_XFT */
3761 #endif /* HAVE_FREETYPE */
3762 register_font_driver (&xfont_driver, f);
3763 #endif /* not USE_CAIRO */
3765 image_cache_refcount =
3766 FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
3767 #ifdef GLYPH_DEBUG
3768 dpyinfo_refcount = dpyinfo->reference_count;
3769 #endif /* GLYPH_DEBUG */
3771 x_default_parameter (f, parms, Qfont_backend, Qnil,
3772 "fontBackend", "FontBackend", RES_TYPE_STRING);
3774 /* Extract the window parameters from the supplied values
3775 that are needed to determine window geometry. */
3776 x_default_font_parameter (f, parms);
3777 if (!FRAME_FONT (f))
3779 delete_frame (frame, Qnoelisp);
3780 error ("Invalid frame font");
3783 /* Frame contents get displaced if an embedded X window has a border. */
3784 if (! FRAME_X_EMBEDDED_P (f))
3785 x_default_parameter (f, parms, Qborder_width, make_number (0),
3786 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
3788 /* This defaults to 1 in order to match xterm. We recognize either
3789 internalBorderWidth or internalBorder (which is what xterm calls
3790 it). */
3791 if (NILP (Fassq (Qinternal_border_width, parms)))
3793 Lisp_Object value;
3795 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
3796 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
3797 if (! EQ (value, Qunbound))
3798 parms = Fcons (Fcons (Qinternal_border_width, value),
3799 parms);
3801 x_default_parameter (f, parms, Qinternal_border_width,
3802 #ifdef USE_GTK /* We used to impose 0 in xg_create_frame_widgets. */
3803 make_number (0),
3804 #else
3805 make_number (1),
3806 #endif
3807 "internalBorderWidth", "internalBorderWidth",
3808 RES_TYPE_NUMBER);
3809 x_default_parameter (f, parms, Qright_divider_width, make_number (0),
3810 NULL, NULL, RES_TYPE_NUMBER);
3811 x_default_parameter (f, parms, Qbottom_divider_width, make_number (0),
3812 NULL, NULL, RES_TYPE_NUMBER);
3813 x_default_parameter (f, parms, Qvertical_scroll_bars,
3814 #if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
3815 Qright,
3816 #else
3817 Qleft,
3818 #endif
3819 "verticalScrollBars", "ScrollBars",
3820 RES_TYPE_SYMBOL);
3821 x_default_parameter (f, parms, Qhorizontal_scroll_bars, Qnil,
3822 "horizontalScrollBars", "ScrollBars",
3823 RES_TYPE_SYMBOL);
3824 /* Also do the stuff which must be set before the window exists. */
3825 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
3826 "foreground", "Foreground", RES_TYPE_STRING);
3827 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
3828 "background", "Background", RES_TYPE_STRING);
3829 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
3830 "pointerColor", "Foreground", RES_TYPE_STRING);
3831 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
3832 "borderColor", "BorderColor", RES_TYPE_STRING);
3833 x_default_parameter (f, parms, Qscreen_gamma, Qnil,
3834 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
3835 x_default_parameter (f, parms, Qline_spacing, Qnil,
3836 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
3837 x_default_parameter (f, parms, Qleft_fringe, Qnil,
3838 "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
3839 x_default_parameter (f, parms, Qright_fringe, Qnil,
3840 "rightFringe", "RightFringe", RES_TYPE_NUMBER);
3841 x_default_parameter (f, parms, Qno_special_glyphs, Qnil,
3842 NULL, NULL, RES_TYPE_BOOLEAN);
3844 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
3845 "scrollBarForeground",
3846 "ScrollBarForeground", true);
3847 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_background,
3848 "scrollBarBackground",
3849 "ScrollBarBackground", false);
3851 /* Init faces before x_default_parameter is called for the
3852 scroll-bar-width parameter because otherwise we end up in
3853 init_iterator with a null face cache, which should not happen. */
3854 init_frame_faces (f);
3856 /* We have to call adjust_frame_size here since otherwise
3857 x_set_tool_bar_lines will already work with the character sizes
3858 installed by init_frame_faces while the frame's pixel size is still
3859 calculated from a character size of 1 and we subsequently hit the
3860 (height >= 0) assertion in window_box_height.
3862 The non-pixelwise code apparently worked around this because it
3863 had one frame line vs one toolbar line which left us with a zero
3864 root window height which was obviously wrong as well ...
3866 Also process `min-width' and `min-height' parameters right here
3867 because `frame-windows-min-size' needs them. */
3868 tem = x_get_arg (dpyinfo, parms, Qmin_width, NULL, NULL, RES_TYPE_NUMBER);
3869 if (NUMBERP (tem))
3870 store_frame_param (f, Qmin_width, tem);
3871 tem = x_get_arg (dpyinfo, parms, Qmin_height, NULL, NULL, RES_TYPE_NUMBER);
3872 if (NUMBERP (tem))
3873 store_frame_param (f, Qmin_height, tem);
3874 adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
3875 FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, true,
3876 Qx_create_frame_1);
3878 /* Set the menu-bar-lines and tool-bar-lines parameters. We don't
3879 look up the X resources controlling the menu-bar and tool-bar
3880 here; they are processed specially at startup, and reflected in
3881 the values of the mode variables. */
3883 x_default_parameter (f, parms, Qmenu_bar_lines,
3884 NILP (Vmenu_bar_mode)
3885 ? make_number (0) : make_number (1),
3886 NULL, NULL, RES_TYPE_NUMBER);
3887 x_default_parameter (f, parms, Qtool_bar_lines,
3888 NILP (Vtool_bar_mode)
3889 ? make_number (0) : make_number (1),
3890 NULL, NULL, RES_TYPE_NUMBER);
3892 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
3893 "bufferPredicate", "BufferPredicate",
3894 RES_TYPE_SYMBOL);
3895 x_default_parameter (f, parms, Qtitle, Qnil,
3896 "title", "Title", RES_TYPE_STRING);
3897 x_default_parameter (f, parms, Qwait_for_wm, Qt,
3898 "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN);
3899 x_default_parameter (f, parms, Qtool_bar_position,
3900 FRAME_TOOL_BAR_POSITION (f), 0, 0, RES_TYPE_SYMBOL);
3901 x_default_parameter (f, parms, Qinhibit_double_buffering, Qnil,
3902 "inhibitDoubleBuffering", "InhibitDoubleBuffering",
3903 RES_TYPE_BOOLEAN);
3905 /* Compute the size of the X window. */
3906 window_prompting = x_figure_window_size (f, parms, true, &x_width, &x_height);
3908 tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
3909 f->no_split = minibuffer_only || EQ (tem, Qt);
3911 x_icon_verify (f, parms);
3913 /* Create the X widget or window. */
3914 #ifdef USE_X_TOOLKIT
3915 x_window (f, window_prompting);
3916 #else
3917 x_window (f);
3918 #endif
3920 x_icon (f, parms);
3921 x_make_gc (f);
3923 /* Now consider the frame official. */
3924 f->terminal->reference_count++;
3925 FRAME_DISPLAY_INFO (f)->reference_count++;
3926 Vframe_list = Fcons (frame, Vframe_list);
3928 /* We need to do this after creating the X window, so that the
3929 icon-creation functions can say whose icon they're describing. */
3930 x_default_parameter (f, parms, Qicon_type, Qt,
3931 "bitmapIcon", "BitmapIcon", RES_TYPE_BOOLEAN);
3933 x_default_parameter (f, parms, Qauto_raise, Qnil,
3934 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
3935 x_default_parameter (f, parms, Qauto_lower, Qnil,
3936 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
3937 x_default_parameter (f, parms, Qcursor_type, Qbox,
3938 "cursorType", "CursorType", RES_TYPE_SYMBOL);
3939 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
3940 "scrollBarWidth", "ScrollBarWidth",
3941 RES_TYPE_NUMBER);
3942 x_default_parameter (f, parms, Qscroll_bar_height, Qnil,
3943 "scrollBarHeight", "ScrollBarHeight",
3944 RES_TYPE_NUMBER);
3945 x_default_parameter (f, parms, Qalpha, Qnil,
3946 "alpha", "Alpha", RES_TYPE_NUMBER);
3948 if (!NILP (parent_frame))
3950 struct frame *p = XFRAME (parent_frame);
3952 block_input ();
3953 XReparentWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
3954 FRAME_X_WINDOW (p), f->left_pos, f->top_pos);
3955 unblock_input ();
3958 x_default_parameter (f, parms, Qno_focus_on_map, Qnil,
3959 NULL, NULL, RES_TYPE_BOOLEAN);
3960 x_default_parameter (f, parms, Qno_accept_focus, Qnil,
3961 NULL, NULL, RES_TYPE_BOOLEAN);
3963 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
3964 /* Create the menu bar. */
3965 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
3967 /* If this signals an error, we haven't set size hints for the
3968 frame and we didn't make it visible. */
3969 initialize_frame_menubar (f);
3971 #ifndef USE_GTK
3972 /* This is a no-op, except under Motif where it arranges the
3973 main window for the widgets on it. */
3974 lw_set_main_areas (f->output_data.x->column_widget,
3975 f->output_data.x->menubar_widget,
3976 f->output_data.x->edit_widget);
3977 #endif /* not USE_GTK */
3979 #endif /* USE_X_TOOLKIT || USE_GTK */
3981 /* Consider frame official, now. */
3982 f->can_x_set_window_size = true;
3984 if (x_width > 0)
3985 SET_FRAME_WIDTH (f, x_width);
3986 if (x_height > 0)
3987 SET_FRAME_HEIGHT (f, x_height);
3989 /* Tell the server what size and position, etc, we want, and how
3990 badly we want them. This should be done after we have the menu
3991 bar so that its size can be taken into account. */
3992 block_input ();
3993 x_wm_set_size_hint (f, window_prompting, false);
3994 unblock_input ();
3996 adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
3997 0, true, Qx_create_frame_2);
3999 /* Process fullscreen parameter here in the hope that normalizing a
4000 fullheight/fullwidth frame will produce the size set by the last
4001 adjust_frame_size call. */
4002 x_default_parameter (f, parms, Qfullscreen, Qnil,
4003 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
4005 /* Make the window appear on the frame and enable display, unless
4006 the caller says not to. However, with explicit parent, Emacs
4007 cannot control visibility, so don't try. */
4008 if (!f->output_data.x->explicit_parent)
4010 Lisp_Object visibility
4011 = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
4013 if (EQ (visibility, Qicon))
4014 x_iconify_frame (f);
4015 else
4017 if (EQ (visibility, Qunbound))
4018 visibility = Qt;
4020 if (!NILP (visibility))
4021 x_make_frame_visible (f);
4024 store_frame_param (f, Qvisibility, visibility);
4027 block_input ();
4029 /* Set machine name and pid for the purpose of window managers. */
4030 set_machine_and_pid_properties (f);
4032 /* Set the WM leader property. GTK does this itself, so this is not
4033 needed when using GTK. */
4034 if (dpyinfo->client_leader_window != 0)
4036 XChangeProperty (FRAME_X_DISPLAY (f),
4037 FRAME_OUTER_WINDOW (f),
4038 dpyinfo->Xatom_wm_client_leader,
4039 XA_WINDOW, 32, PropModeReplace,
4040 (unsigned char *) &dpyinfo->client_leader_window, 1);
4043 unblock_input ();
4045 /* Works iff frame has been already mapped. */
4046 x_default_parameter (f, parms, Qskip_taskbar, Qnil,
4047 NULL, NULL, RES_TYPE_BOOLEAN);
4048 /* The `z-group' parameter works only for visible frames. */
4049 x_default_parameter (f, parms, Qz_group, Qnil,
4050 NULL, NULL, RES_TYPE_SYMBOL);
4052 /* Initialize `default-minibuffer-frame' in case this is the first
4053 frame on this terminal. */
4054 if (FRAME_HAS_MINIBUF_P (f)
4055 && (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame))
4056 || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame)))))
4057 kset_default_minibuffer_frame (kb, frame);
4059 /* All remaining specified parameters, which have not been "used"
4060 by x_get_arg and friends, now go in the misc. alist of the frame. */
4061 for (tem = parms; CONSP (tem); tem = XCDR (tem))
4062 if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
4063 fset_param_alist (f, Fcons (XCAR (tem), f->param_alist));
4065 /* Make sure windows on this frame appear in calls to next-window
4066 and similar functions. */
4067 Vwindow_list = Qnil;
4069 return unbind_to (count, frame);
4073 /* FRAME is used only to get a handle on the X display. We don't pass the
4074 display info directly because we're called from frame.c, which doesn't
4075 know about that structure. */
4077 Lisp_Object
4078 x_get_focus_frame (struct frame *frame)
4080 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame);
4081 Lisp_Object xfocus;
4082 if (! dpyinfo->x_focus_frame)
4083 return Qnil;
4085 XSETFRAME (xfocus, dpyinfo->x_focus_frame);
4086 return xfocus;
4090 /* In certain situations, when the window manager follows a
4091 click-to-focus policy, there seems to be no way around calling
4092 XSetInputFocus to give another frame the input focus .
4094 In an ideal world, XSetInputFocus should generally be avoided so
4095 that applications don't interfere with the window manager's focus
4096 policy. But I think it's okay to use when it's clearly done
4097 following a user-command. */
4099 void
4100 x_focus_frame (struct frame *f, bool noactivate)
4102 Display *dpy = FRAME_X_DISPLAY (f);
4104 block_input ();
4105 x_catch_errors (dpy);
4107 if (FRAME_X_EMBEDDED_P (f))
4109 /* For Xembedded frames, normally the embedder forwards key
4110 events. See XEmbed Protocol Specification at
4111 http://freedesktop.org/wiki/Specifications/xembed-spec */
4112 xembed_request_focus (f);
4114 else
4116 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4117 RevertToParent, CurrentTime);
4118 if (!noactivate)
4119 x_ewmh_activate_frame (f);
4122 x_uncatch_errors ();
4123 unblock_input ();
4127 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
4128 doc: /* Internal function called by `color-defined-p', which see.
4129 \(Note that the Nextstep version of this function ignores FRAME.) */)
4130 (Lisp_Object color, Lisp_Object frame)
4132 XColor foo;
4133 struct frame *f = decode_window_system_frame (frame);
4135 CHECK_STRING (color);
4137 if (x_defined_color (f, SSDATA (color), &foo, false))
4138 return Qt;
4139 else
4140 return Qnil;
4143 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
4144 doc: /* Internal function called by `color-values', which see. */)
4145 (Lisp_Object color, Lisp_Object frame)
4147 XColor foo;
4148 struct frame *f = decode_window_system_frame (frame);
4150 CHECK_STRING (color);
4152 if (x_defined_color (f, SSDATA (color), &foo, false))
4153 return list3i (foo.red, foo.green, foo.blue);
4154 else
4155 return Qnil;
4158 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
4159 doc: /* Internal function called by `display-color-p', which see. */)
4160 (Lisp_Object terminal)
4162 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4164 if (dpyinfo->n_planes <= 2)
4165 return Qnil;
4167 switch (dpyinfo->visual->class)
4169 case StaticColor:
4170 case PseudoColor:
4171 case TrueColor:
4172 case DirectColor:
4173 return Qt;
4175 default:
4176 return Qnil;
4180 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
4181 0, 1, 0,
4182 doc: /* Return t if the X display supports shades of gray.
4183 Note that color displays do support shades of gray.
4184 The optional argument TERMINAL specifies which display to ask about.
4185 TERMINAL should be a terminal object, a frame or a display name (a string).
4186 If omitted or nil, that stands for the selected frame's display. */)
4187 (Lisp_Object terminal)
4189 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4191 if (dpyinfo->n_planes <= 1)
4192 return Qnil;
4194 switch (dpyinfo->visual->class)
4196 case StaticColor:
4197 case PseudoColor:
4198 case TrueColor:
4199 case DirectColor:
4200 case StaticGray:
4201 case GrayScale:
4202 return Qt;
4204 default:
4205 return Qnil;
4209 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
4210 0, 1, 0,
4211 doc: /* Return the width in pixels of the X display TERMINAL.
4212 The optional argument TERMINAL specifies which display to ask about.
4213 TERMINAL should be a terminal object, a frame or a display name (a string).
4214 If omitted or nil, that stands for the selected frame's display.
4216 On \"multi-monitor\" setups this refers to the pixel width for all
4217 physical monitors associated with TERMINAL. To get information for
4218 each physical monitor, use `display-monitor-attributes-list'. */)
4219 (Lisp_Object terminal)
4221 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4223 return make_number (x_display_pixel_width (dpyinfo));
4226 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
4227 Sx_display_pixel_height, 0, 1, 0,
4228 doc: /* Return the height in pixels of the X display TERMINAL.
4229 The optional argument TERMINAL specifies which display to ask about.
4230 TERMINAL should be a terminal object, a frame or a display name (a string).
4231 If omitted or nil, that stands for the selected frame's display.
4233 On \"multi-monitor\" setups this refers to the pixel height for all
4234 physical monitors associated with TERMINAL. To get information for
4235 each physical monitor, use `display-monitor-attributes-list'. */)
4236 (Lisp_Object terminal)
4238 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4240 return make_number (x_display_pixel_height (dpyinfo));
4243 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
4244 0, 1, 0,
4245 doc: /* Return the number of bitplanes of the X display TERMINAL.
4246 The optional argument TERMINAL specifies which display to ask about.
4247 TERMINAL should be a terminal object, a frame or a display name (a string).
4248 If omitted or nil, that stands for the selected frame's display. */)
4249 (Lisp_Object terminal)
4251 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4253 return make_number (dpyinfo->n_planes);
4256 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
4257 0, 1, 0,
4258 doc: /* Return the number of color cells of the X display TERMINAL.
4259 The optional argument TERMINAL specifies which display to ask about.
4260 TERMINAL should be a terminal object, a frame or a display name (a string).
4261 If omitted or nil, that stands for the selected frame's display. */)
4262 (Lisp_Object terminal)
4264 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4266 int nr_planes = DisplayPlanes (dpyinfo->display,
4267 XScreenNumberOfScreen (dpyinfo->screen));
4269 /* Truncate nr_planes to 24 to avoid integer overflow.
4270 Some displays says 32, but only 24 bits are actually significant.
4271 There are only very few and rare video cards that have more than
4272 24 significant bits. Also 24 bits is more than 16 million colors,
4273 it "should be enough for everyone". */
4274 if (nr_planes > 24) nr_planes = 24;
4276 return make_number (1 << nr_planes);
4279 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
4280 Sx_server_max_request_size,
4281 0, 1, 0,
4282 doc: /* Return the maximum request size of the X server of display TERMINAL.
4283 The optional argument TERMINAL specifies which display to ask about.
4284 TERMINAL should be a terminal object, a frame or a display name (a string).
4285 If omitted or nil, that stands for the selected frame's display. */)
4286 (Lisp_Object terminal)
4288 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4290 return make_number (MAXREQUEST (dpyinfo->display));
4293 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
4294 doc: /* Return the "vendor ID" string of the GUI software on TERMINAL.
4296 \(Labeling every distributor as a "vendor" embodies the false assumption
4297 that operating systems cannot be developed and distributed noncommercially.)
4298 The optional argument TERMINAL specifies which display to ask about.
4300 For GNU and Unix systems, this queries the X server software; for
4301 MS-Windows, this queries the OS.
4303 TERMINAL should be a terminal object, a frame or a display name (a string).
4304 If omitted or nil, that stands for the selected frame's display. */)
4305 (Lisp_Object terminal)
4307 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4308 const char *vendor = ServerVendor (dpyinfo->display);
4310 if (! vendor) vendor = "";
4311 return build_string (vendor);
4314 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
4315 doc: /* Return the version numbers of the GUI software on TERMINAL.
4316 The value is a list of three integers specifying the version of the GUI
4317 software in use.
4319 For GNU and Unix system, the first 2 numbers are the version of the X
4320 Protocol used on TERMINAL and the 3rd number is the distributor-specific
4321 release number. For MS-Windows, the 3 numbers report the version and
4322 the build number of the OS.
4324 See also the function `x-server-vendor'.
4326 The optional argument TERMINAL specifies which display to ask about.
4327 TERMINAL should be a terminal object, a frame or a display name (a string).
4328 If omitted or nil, that stands for the selected frame's display. */)
4329 (Lisp_Object terminal)
4331 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4332 Display *dpy = dpyinfo->display;
4334 return list3i (ProtocolVersion (dpy), ProtocolRevision (dpy),
4335 VendorRelease (dpy));
4338 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
4339 doc: /* Return the number of screens on the X server of display TERMINAL.
4340 The optional argument TERMINAL specifies which display to ask about.
4341 TERMINAL should be a terminal object, a frame or a display name (a string).
4342 If omitted or nil, that stands for the selected frame's display. */)
4343 (Lisp_Object terminal)
4345 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4347 return make_number (ScreenCount (dpyinfo->display));
4350 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
4351 doc: /* Return the height in millimeters of the X display TERMINAL.
4352 The optional argument TERMINAL specifies which display to ask about.
4353 TERMINAL should be a terminal object, a frame or a display name (a string).
4354 If omitted or nil, that stands for the selected frame's display.
4356 On \"multi-monitor\" setups this refers to the height in millimeters for
4357 all physical monitors associated with TERMINAL. To get information
4358 for each physical monitor, use `display-monitor-attributes-list'. */)
4359 (Lisp_Object terminal)
4361 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4363 return make_number (HeightMMOfScreen (dpyinfo->screen));
4366 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
4367 doc: /* Return the width in millimeters of the X display TERMINAL.
4368 The optional argument TERMINAL specifies which display to ask about.
4369 TERMINAL should be a terminal object, a frame or a display name (a string).
4370 If omitted or nil, that stands for the selected frame's display.
4372 On \"multi-monitor\" setups this refers to the width in millimeters for
4373 all physical monitors associated with TERMINAL. To get information
4374 for each physical monitor, use `display-monitor-attributes-list'. */)
4375 (Lisp_Object terminal)
4377 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4379 return make_number (WidthMMOfScreen (dpyinfo->screen));
4382 DEFUN ("x-display-backing-store", Fx_display_backing_store,
4383 Sx_display_backing_store, 0, 1, 0,
4384 doc: /* Return an indication of whether X display TERMINAL does backing store.
4385 The value may be `always', `when-mapped', or `not-useful'.
4386 The optional argument TERMINAL specifies which display to ask about.
4387 TERMINAL should be a terminal object, a frame or a display name (a string).
4388 If omitted or nil, that stands for the selected frame's display. */)
4389 (Lisp_Object terminal)
4391 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4392 Lisp_Object result;
4394 switch (DoesBackingStore (dpyinfo->screen))
4396 case Always:
4397 result = intern ("always");
4398 break;
4400 case WhenMapped:
4401 result = intern ("when-mapped");
4402 break;
4404 case NotUseful:
4405 result = intern ("not-useful");
4406 break;
4408 default:
4409 error ("Strange value for BackingStore parameter of screen");
4412 return result;
4415 DEFUN ("x-display-visual-class", Fx_display_visual_class,
4416 Sx_display_visual_class, 0, 1, 0,
4417 doc: /* Return the visual class of the X display TERMINAL.
4418 The value is one of the symbols `static-gray', `gray-scale',
4419 `static-color', `pseudo-color', `true-color', or `direct-color'.
4421 The optional argument TERMINAL specifies which display to ask about.
4422 TERMINAL should a terminal object, a frame or a display name (a string).
4423 If omitted or nil, that stands for the selected frame's display. */)
4424 (Lisp_Object terminal)
4426 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4427 Lisp_Object result;
4429 switch (dpyinfo->visual->class)
4431 case StaticGray:
4432 result = intern ("static-gray");
4433 break;
4434 case GrayScale:
4435 result = intern ("gray-scale");
4436 break;
4437 case StaticColor:
4438 result = intern ("static-color");
4439 break;
4440 case PseudoColor:
4441 result = intern ("pseudo-color");
4442 break;
4443 case TrueColor:
4444 result = intern ("true-color");
4445 break;
4446 case DirectColor:
4447 result = intern ("direct-color");
4448 break;
4449 default:
4450 error ("Display has an unknown visual class");
4453 return result;
4456 DEFUN ("x-display-save-under", Fx_display_save_under,
4457 Sx_display_save_under, 0, 1, 0,
4458 doc: /* Return t if the X display TERMINAL supports the save-under feature.
4459 The optional argument TERMINAL specifies which display to ask about.
4460 TERMINAL should be a terminal object, a frame or a display name (a string).
4461 If omitted or nil, that stands for the selected frame's display. */)
4462 (Lisp_Object terminal)
4464 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4466 if (DoesSaveUnders (dpyinfo->screen) == True)
4467 return Qt;
4468 else
4469 return Qnil;
4472 /* Store the geometry of the workarea on display DPYINFO into *RECT.
4473 Return false if and only if the workarea information cannot be
4474 obtained via the _NET_WORKAREA root window property. */
4476 #if ! GTK_CHECK_VERSION (3, 4, 0)
4477 static bool
4478 x_get_net_workarea (struct x_display_info *dpyinfo, XRectangle *rect)
4480 Display *dpy = dpyinfo->display;
4481 long offset, max_len;
4482 Atom target_type, actual_type;
4483 unsigned long actual_size, bytes_remaining;
4484 int rc, actual_format;
4485 unsigned char *tmp_data = NULL;
4486 bool result = false;
4488 x_catch_errors (dpy);
4489 offset = 0;
4490 max_len = 1;
4491 target_type = XA_CARDINAL;
4492 rc = XGetWindowProperty (dpy, dpyinfo->root_window,
4493 dpyinfo->Xatom_net_current_desktop,
4494 offset, max_len, False, target_type,
4495 &actual_type, &actual_format, &actual_size,
4496 &bytes_remaining, &tmp_data);
4497 if (rc == Success && actual_type == target_type && !x_had_errors_p (dpy)
4498 && actual_format == 32 && actual_size == max_len)
4500 long current_desktop = ((long *) tmp_data)[0];
4502 XFree (tmp_data);
4503 tmp_data = NULL;
4505 offset = 4 * current_desktop;
4506 max_len = 4;
4507 rc = XGetWindowProperty (dpy, dpyinfo->root_window,
4508 dpyinfo->Xatom_net_workarea,
4509 offset, max_len, False, target_type,
4510 &actual_type, &actual_format, &actual_size,
4511 &bytes_remaining, &tmp_data);
4512 if (rc == Success && actual_type == target_type && !x_had_errors_p (dpy)
4513 && actual_format == 32 && actual_size == max_len)
4515 long *values = (long *) tmp_data;
4517 rect->x = values[0];
4518 rect->y = values[1];
4519 rect->width = values[2];
4520 rect->height = values[3];
4522 XFree (tmp_data);
4523 tmp_data = NULL;
4525 result = true;
4528 if (tmp_data)
4529 XFree (tmp_data);
4530 x_uncatch_errors ();
4532 return result;
4534 #endif
4536 #ifndef USE_GTK
4538 /* Return monitor number where F is "most" or closest to. */
4539 static int
4540 x_get_monitor_for_frame (struct frame *f,
4541 struct MonitorInfo *monitors,
4542 int n_monitors)
4544 XRectangle frect;
4545 int area = 0, dist = -1;
4546 int best_area = -1, best_dist = -1;
4547 int i;
4549 if (n_monitors == 1) return 0;
4550 frect.x = f->left_pos;
4551 frect.y = f->top_pos;
4552 frect.width = FRAME_PIXEL_WIDTH (f);
4553 frect.height = FRAME_PIXEL_HEIGHT (f);
4555 for (i = 0; i < n_monitors; ++i)
4557 struct MonitorInfo *mi = &monitors[i];
4558 XRectangle res;
4559 int a = 0;
4561 if (mi->geom.width == 0) continue;
4563 if (x_intersect_rectangles (&mi->geom, &frect, &res))
4565 a = res.width * res.height;
4566 if (a > area)
4568 area = a;
4569 best_area = i;
4573 if (a == 0 && area == 0)
4575 int dx, dy, d;
4576 if (frect.x + frect.width < mi->geom.x)
4577 dx = mi->geom.x - frect.x + frect.width;
4578 else if (frect.x > mi->geom.x + mi->geom.width)
4579 dx = frect.x - mi->geom.x + mi->geom.width;
4580 else
4581 dx = 0;
4582 if (frect.y + frect.height < mi->geom.y)
4583 dy = mi->geom.y - frect.y + frect.height;
4584 else if (frect.y > mi->geom.y + mi->geom.height)
4585 dy = frect.y - mi->geom.y + mi->geom.height;
4586 else
4587 dy = 0;
4589 d = dx*dx + dy*dy;
4590 if (dist == -1 || dist > d)
4592 dist = d;
4593 best_dist = i;
4598 return best_area != -1 ? best_area : (best_dist != -1 ? best_dist : 0);
4601 static Lisp_Object
4602 x_make_monitor_attribute_list (struct MonitorInfo *monitors,
4603 int n_monitors,
4604 int primary_monitor,
4605 struct x_display_info *dpyinfo,
4606 const char *source)
4608 Lisp_Object monitor_frames = Fmake_vector (make_number (n_monitors), Qnil);
4609 Lisp_Object frame, rest;
4611 FOR_EACH_FRAME (rest, frame)
4613 struct frame *f = XFRAME (frame);
4615 if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) == dpyinfo
4616 && !EQ (frame, tip_frame))
4618 int i = x_get_monitor_for_frame (f, monitors, n_monitors);
4619 ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i)));
4623 return make_monitor_attribute_list (monitors, n_monitors, primary_monitor,
4624 monitor_frames, source);
4627 static Lisp_Object
4628 x_get_monitor_attributes_fallback (struct x_display_info *dpyinfo)
4630 struct MonitorInfo monitor;
4631 XRectangle workarea_r;
4633 /* Fallback: treat (possibly) multiple physical monitors as if they
4634 formed a single monitor as a whole. This should provide a
4635 consistent result at least on single monitor environments. */
4636 monitor.geom.x = monitor.geom.y = 0;
4637 monitor.geom.width = x_display_pixel_width (dpyinfo);
4638 monitor.geom.height = x_display_pixel_height (dpyinfo);
4639 monitor.mm_width = WidthMMOfScreen (dpyinfo->screen);
4640 monitor.mm_height = HeightMMOfScreen (dpyinfo->screen);
4641 monitor.name = xstrdup ("combined screen");
4643 if (x_get_net_workarea (dpyinfo, &workarea_r))
4644 monitor.work = workarea_r;
4645 else
4646 monitor.work = monitor.geom;
4647 return x_make_monitor_attribute_list (&monitor, 1, 0, dpyinfo, "fallback");
4651 #ifdef HAVE_XINERAMA
4652 static Lisp_Object
4653 x_get_monitor_attributes_xinerama (struct x_display_info *dpyinfo)
4655 int n_monitors, i;
4656 Lisp_Object attributes_list = Qnil;
4657 Display *dpy = dpyinfo->display;
4658 XineramaScreenInfo *info = XineramaQueryScreens (dpy, &n_monitors);
4659 struct MonitorInfo *monitors;
4660 double mm_width_per_pixel, mm_height_per_pixel;
4662 if (! info || n_monitors == 0)
4664 if (info)
4665 XFree (info);
4666 return attributes_list;
4669 mm_width_per_pixel = ((double) WidthMMOfScreen (dpyinfo->screen)
4670 / x_display_pixel_width (dpyinfo));
4671 mm_height_per_pixel = ((double) HeightMMOfScreen (dpyinfo->screen)
4672 / x_display_pixel_height (dpyinfo));
4673 monitors = xzalloc (n_monitors * sizeof *monitors);
4674 for (i = 0; i < n_monitors; ++i)
4676 struct MonitorInfo *mi = &monitors[i];
4677 XRectangle workarea_r;
4679 mi->geom.x = info[i].x_org;
4680 mi->geom.y = info[i].y_org;
4681 mi->geom.width = info[i].width;
4682 mi->geom.height = info[i].height;
4683 mi->mm_width = mi->geom.width * mm_width_per_pixel + 0.5;
4684 mi->mm_height = mi->geom.height * mm_height_per_pixel + 0.5;
4685 mi->name = 0;
4687 /* Xinerama usually have primary monitor first, just use that. */
4688 if (i == 0 && x_get_net_workarea (dpyinfo, &workarea_r))
4690 mi->work = workarea_r;
4691 if (! x_intersect_rectangles (&mi->geom, &mi->work, &mi->work))
4692 mi->work = mi->geom;
4694 else
4695 mi->work = mi->geom;
4697 XFree (info);
4699 attributes_list = x_make_monitor_attribute_list (monitors,
4700 n_monitors,
4702 dpyinfo,
4703 "Xinerama");
4704 free_monitors (monitors, n_monitors);
4705 return attributes_list;
4707 #endif /* HAVE_XINERAMA */
4710 #ifdef HAVE_XRANDR
4711 static Lisp_Object
4712 x_get_monitor_attributes_xrandr (struct x_display_info *dpyinfo)
4714 Lisp_Object attributes_list = Qnil;
4715 XRRScreenResources *resources;
4716 Display *dpy = dpyinfo->display;
4717 int i, n_monitors, primary = -1;
4718 RROutput pxid = None;
4719 struct MonitorInfo *monitors;
4721 #define RANDR13_LIBRARY \
4722 (RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 3))
4724 #if RANDR13_LIBRARY
4725 /* Check if the display supports 1.3 too. */
4726 bool randr13_avail = (dpyinfo->xrandr_major_version > 1
4727 || (dpyinfo->xrandr_major_version == 1
4728 && dpyinfo->xrandr_minor_version >= 3));
4730 if (randr13_avail)
4731 resources = XRRGetScreenResourcesCurrent (dpy, dpyinfo->root_window);
4732 else
4733 resources = XRRGetScreenResources (dpy, dpyinfo->root_window);
4734 #else
4735 resources = XRRGetScreenResources (dpy, dpyinfo->root_window);
4736 #endif
4737 if (! resources || resources->noutput == 0)
4739 if (resources)
4740 XRRFreeScreenResources (resources);
4741 return Qnil;
4743 n_monitors = resources->noutput;
4744 monitors = xzalloc (n_monitors * sizeof *monitors);
4746 #if RANDR13_LIBRARY
4747 if (randr13_avail)
4748 pxid = XRRGetOutputPrimary (dpy, dpyinfo->root_window);
4749 #endif
4751 for (i = 0; i < n_monitors; ++i)
4753 XRROutputInfo *info = XRRGetOutputInfo (dpy, resources,
4754 resources->outputs[i]);
4755 if (!info)
4756 continue;
4758 if (strcmp (info->name, "default") == 0)
4760 /* Non XRandr 1.2 driver, does not give useful data. */
4761 XRRFreeOutputInfo (info);
4762 XRRFreeScreenResources (resources);
4763 free_monitors (monitors, n_monitors);
4764 return Qnil;
4767 if (info->connection != RR_Disconnected && info->crtc != None)
4769 XRRCrtcInfo *crtc = XRRGetCrtcInfo (dpy, resources, info->crtc);
4770 struct MonitorInfo *mi = &monitors[i];
4771 XRectangle workarea_r;
4773 if (! crtc)
4775 XRRFreeOutputInfo (info);
4776 continue;
4779 mi->geom.x = crtc->x;
4780 mi->geom.y = crtc->y;
4781 mi->geom.width = crtc->width;
4782 mi->geom.height = crtc->height;
4783 mi->mm_width = info->mm_width;
4784 mi->mm_height = info->mm_height;
4785 mi->name = xstrdup (info->name);
4787 if (pxid != None && pxid == resources->outputs[i])
4788 primary = i;
4789 else if (primary == -1 && strcmp (info->name, "LVDS") == 0)
4790 primary = i;
4792 if (i == primary && x_get_net_workarea (dpyinfo, &workarea_r))
4794 mi->work= workarea_r;
4795 if (! x_intersect_rectangles (&mi->geom, &mi->work, &mi->work))
4796 mi->work = mi->geom;
4798 else
4799 mi->work = mi->geom;
4801 XRRFreeCrtcInfo (crtc);
4803 XRRFreeOutputInfo (info);
4805 XRRFreeScreenResources (resources);
4807 attributes_list = x_make_monitor_attribute_list (monitors,
4808 n_monitors,
4809 primary,
4810 dpyinfo,
4811 "XRandr");
4812 free_monitors (monitors, n_monitors);
4813 return attributes_list;
4815 #endif /* HAVE_XRANDR */
4817 static Lisp_Object
4818 x_get_monitor_attributes (struct x_display_info *dpyinfo)
4820 Lisp_Object attributes_list = Qnil;
4821 Display *dpy = dpyinfo->display;
4823 (void) dpy; /* Suppress unused variable warning. */
4825 #ifdef HAVE_XRANDR
4826 int xrr_event_base, xrr_error_base;
4827 bool xrr_ok = false;
4828 xrr_ok = XRRQueryExtension (dpy, &xrr_event_base, &xrr_error_base);
4829 if (xrr_ok)
4831 XRRQueryVersion (dpy, &dpyinfo->xrandr_major_version,
4832 &dpyinfo->xrandr_minor_version);
4833 xrr_ok = ((dpyinfo->xrandr_major_version == 1
4834 && dpyinfo->xrandr_minor_version >= 2)
4835 || dpyinfo->xrandr_major_version > 1);
4838 if (xrr_ok)
4839 attributes_list = x_get_monitor_attributes_xrandr (dpyinfo);
4840 #endif /* HAVE_XRANDR */
4842 #ifdef HAVE_XINERAMA
4843 if (NILP (attributes_list))
4845 int xin_event_base, xin_error_base;
4846 bool xin_ok = false;
4847 xin_ok = XineramaQueryExtension (dpy, &xin_event_base, &xin_error_base);
4848 if (xin_ok && XineramaIsActive (dpy))
4849 attributes_list = x_get_monitor_attributes_xinerama (dpyinfo);
4851 #endif /* HAVE_XINERAMA */
4853 if (NILP (attributes_list))
4854 attributes_list = x_get_monitor_attributes_fallback (dpyinfo);
4856 return attributes_list;
4859 #endif /* !USE_GTK */
4861 DEFUN ("x-display-monitor-attributes-list", Fx_display_monitor_attributes_list,
4862 Sx_display_monitor_attributes_list,
4863 0, 1, 0,
4864 doc: /* Return a list of physical monitor attributes on the X display TERMINAL.
4866 The optional argument TERMINAL specifies which display to ask about.
4867 TERMINAL should be a terminal object, a frame or a display name (a string).
4868 If omitted or nil, that stands for the selected frame's display.
4870 In addition to the standard attribute keys listed in
4871 `display-monitor-attributes-list', the following keys are contained in
4872 the attributes:
4874 source -- String describing the source from which multi-monitor
4875 information is obtained, one of \"Gdk\", \"XRandr\",
4876 \"Xinerama\", or \"fallback\"
4878 Internal use only, use `display-monitor-attributes-list' instead. */)
4879 (Lisp_Object terminal)
4881 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4882 Lisp_Object attributes_list = Qnil;
4884 #ifdef USE_GTK
4885 double mm_width_per_pixel, mm_height_per_pixel;
4886 GdkDisplay *gdpy;
4887 #if ! GTK_CHECK_VERSION (3, 22, 0)
4888 GdkScreen *gscreen;
4889 #endif
4890 gint primary_monitor = 0, n_monitors, i;
4891 Lisp_Object monitor_frames, rest, frame;
4892 static const char *source = "Gdk";
4893 struct MonitorInfo *monitors;
4895 block_input ();
4896 mm_width_per_pixel = ((double) WidthMMOfScreen (dpyinfo->screen)
4897 / x_display_pixel_width (dpyinfo));
4898 mm_height_per_pixel = ((double) HeightMMOfScreen (dpyinfo->screen)
4899 / x_display_pixel_height (dpyinfo));
4900 gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display);
4901 #if GTK_CHECK_VERSION (3, 22, 0)
4902 n_monitors = gdk_display_get_n_monitors (gdpy);
4903 #else
4904 gscreen = gdk_display_get_default_screen (gdpy);
4905 #if GTK_CHECK_VERSION (2, 20, 0)
4906 primary_monitor = gdk_screen_get_primary_monitor (gscreen);
4907 #endif
4908 n_monitors = gdk_screen_get_n_monitors (gscreen);
4909 #endif
4910 monitor_frames = Fmake_vector (make_number (n_monitors), Qnil);
4911 monitors = xzalloc (n_monitors * sizeof *monitors);
4913 FOR_EACH_FRAME (rest, frame)
4915 struct frame *f = XFRAME (frame);
4917 if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) == dpyinfo
4918 && !(EQ (frame, tip_frame)
4919 #ifdef USE_GTK
4920 && !NILP (Fframe_parameter (tip_frame, Qtooltip))
4921 #endif
4924 GdkWindow *gwin = gtk_widget_get_window (FRAME_GTK_WIDGET (f));
4926 #if GTK_CHECK_VERSION (3, 22, 0)
4927 for (i = 0; i < n_monitors; i++)
4928 if (gdk_display_get_monitor_at_window (gdpy, gwin)
4929 == gdk_display_get_monitor (gdpy, i))
4930 break;
4931 #else
4932 i = gdk_screen_get_monitor_at_window (gscreen, gwin);
4933 #endif
4934 ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i)));
4938 for (i = 0; i < n_monitors; ++i)
4940 gint width_mm = -1, height_mm = -1;
4941 GdkRectangle rec, work;
4942 struct MonitorInfo *mi = &monitors[i];
4943 int scale = 1;
4945 #if GTK_CHECK_VERSION (3, 22, 0)
4946 GdkMonitor *monitor = gdk_display_get_monitor (gdpy, i);
4947 if (gdk_monitor_is_primary (monitor))
4948 primary_monitor = i;
4949 gdk_monitor_get_geometry (monitor, &rec);
4950 #else
4951 gdk_screen_get_monitor_geometry (gscreen, i, &rec);
4952 #endif
4954 #if GTK_CHECK_VERSION (3, 22, 0)
4955 width_mm = gdk_monitor_get_width_mm (monitor);
4956 height_mm = gdk_monitor_get_height_mm (monitor);
4957 #elif GTK_CHECK_VERSION (2, 14, 0)
4958 width_mm = gdk_screen_get_monitor_width_mm (gscreen, i);
4959 height_mm = gdk_screen_get_monitor_height_mm (gscreen, i);
4960 #endif
4961 if (width_mm < 0)
4962 width_mm = rec.width * mm_width_per_pixel + 0.5;
4963 if (height_mm < 0)
4964 height_mm = rec.height * mm_height_per_pixel + 0.5;
4966 #if GTK_CHECK_VERSION (3, 22, 0)
4967 gdk_monitor_get_workarea (monitor, &work);
4968 #elif GTK_CHECK_VERSION (3, 4, 0)
4969 gdk_screen_get_monitor_workarea (gscreen, i, &work);
4970 #else
4971 /* Emulate the behavior of GTK+ 3.4. */
4973 XRectangle workarea_r;
4975 if (i == primary_monitor && x_get_net_workarea (dpyinfo, &workarea_r))
4977 work.x = workarea_r.x;
4978 work.y = workarea_r.y;
4979 work.width = workarea_r.width;
4980 work.height = workarea_r.height;
4981 if (! gdk_rectangle_intersect (&rec, &work, &work))
4982 work = rec;
4984 else
4985 work = rec;
4987 #endif
4989 /* GTK returns scaled sizes for the workareas. */
4990 #if GTK_CHECK_VERSION (3, 22, 0)
4991 scale = gdk_monitor_get_scale_factor (monitor);
4992 #elif GTK_CHECK_VERSION (3, 10, 0)
4993 scale = gdk_screen_get_monitor_scale_factor (gscreen, i);
4994 #endif
4995 rec.width *= scale;
4996 rec.height *= scale;
4997 work.width *= scale;
4998 work.height *= scale;
5000 mi->geom.x = rec.x;
5001 mi->geom.y = rec.y;
5002 mi->geom.width = rec.width;
5003 mi->geom.height = rec.height;
5004 mi->work.x = work.x;
5005 mi->work.y = work.y;
5006 mi->work.width = work.width;
5007 mi->work.height = work.height;
5008 mi->mm_width = width_mm;
5009 mi->mm_height = height_mm;
5011 #if GTK_CHECK_VERSION (3, 22, 0)
5012 mi->name = g_strdup (gdk_monitor_get_model (monitor));
5013 #elif GTK_CHECK_VERSION (2, 14, 0)
5014 mi->name = gdk_screen_get_monitor_plug_name (gscreen, i);
5015 #endif
5018 attributes_list = make_monitor_attribute_list (monitors,
5019 n_monitors,
5020 primary_monitor,
5021 monitor_frames,
5022 source);
5023 unblock_input ();
5024 #else /* not USE_GTK */
5026 block_input ();
5027 attributes_list = x_get_monitor_attributes (dpyinfo);
5028 unblock_input ();
5030 #endif /* not USE_GTK */
5032 return attributes_list;
5035 /* Return geometric attributes of FRAME. According to the value of
5036 ATTRIBUTES return the outer edges of FRAME (Qouter_edges), the native
5037 edges of FRAME (Qnative_edges), or the inner edges of frame
5038 (Qinner_edges). Any other value means to return the geometry as
5039 returned by Fx_frame_geometry. */
5040 static Lisp_Object
5041 frame_geometry (Lisp_Object frame, Lisp_Object attribute)
5043 struct frame *f = decode_live_frame (frame);
5044 /** XWindowAttributes atts; **/
5045 Window rootw;
5046 unsigned int ign, native_width, native_height, x_border_width = 0;
5047 int x_native = 0, y_native = 0, xptr = 0, yptr = 0;
5048 int left_off = 0, right_off = 0, top_off = 0, bottom_off = 0;
5049 int outer_left, outer_top, outer_right, outer_bottom;
5050 int native_left, native_top, native_right, native_bottom;
5051 int inner_left, inner_top, inner_right, inner_bottom;
5052 int internal_border_width;
5053 bool menu_bar_external = false, tool_bar_external = false;
5054 int menu_bar_height = 0, menu_bar_width = 0;
5055 int tool_bar_height = 0, tool_bar_width = 0;
5057 if (FRAME_INITIAL_P (f) || !FRAME_X_P (f))
5058 return Qnil;
5060 block_input ();
5061 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
5062 &rootw, &x_native, &y_native, &native_width, &native_height,
5063 &x_border_width, &ign);
5064 /** XGetWindowAttributes (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &atts); **/
5065 if (!FRAME_PARENT_FRAME (f))
5066 x_real_pos_and_offsets (f, &left_off, &right_off, &top_off, &bottom_off,
5067 NULL, NULL, &xptr, &yptr, NULL);
5068 unblock_input ();
5070 /** native_width = atts.width; **/
5071 /** native_height = atts.height; **/
5073 if (FRAME_PARENT_FRAME (f))
5075 Lisp_Object parent, edges;
5077 XSETFRAME (parent, FRAME_PARENT_FRAME (f));
5078 edges = Fx_frame_edges (parent, Qnative_edges);
5079 if (!NILP (edges))
5081 x_native += XINT (Fnth (make_number (0), edges));
5082 y_native += XINT (Fnth (make_number (1), edges));
5085 outer_left = x_native;
5086 outer_top = y_native;
5087 outer_right = outer_left + native_width + 2 * x_border_width;
5088 outer_bottom = outer_top + native_height + 2 * x_border_width;
5090 native_left = x_native + x_border_width;
5091 native_top = y_native + x_border_width;
5092 native_right = native_left + native_width;
5093 native_bottom = native_top + native_height;
5095 else
5097 outer_left = xptr;
5098 outer_top = yptr;
5099 outer_right = outer_left + left_off + native_width + right_off;
5100 outer_bottom = outer_top + top_off + native_height + bottom_off;
5102 native_left = outer_left + left_off;
5103 native_top = outer_top + top_off;
5104 native_right = native_left + native_width;
5105 native_bottom = native_top + native_height;
5108 internal_border_width = FRAME_INTERNAL_BORDER_WIDTH (f);
5109 inner_left = native_left + internal_border_width;
5110 inner_top = native_top + internal_border_width;
5111 inner_right = native_right - internal_border_width;
5112 inner_bottom = native_bottom - internal_border_width;
5114 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
5115 menu_bar_external = true;
5116 menu_bar_height = FRAME_MENUBAR_HEIGHT (f);
5117 native_top += menu_bar_height;
5118 inner_top += menu_bar_height;
5119 #else
5120 menu_bar_height = FRAME_MENU_BAR_HEIGHT (f);
5121 inner_top += menu_bar_height;
5122 #endif
5123 menu_bar_width = menu_bar_height ? native_width : 0;
5125 #if defined (USE_GTK)
5126 tool_bar_external = true;
5127 if (EQ (FRAME_TOOL_BAR_POSITION (f), Qleft))
5129 tool_bar_width = FRAME_TOOLBAR_WIDTH (f);
5130 native_left += tool_bar_width;
5131 inner_left += tool_bar_width;
5132 tool_bar_height
5133 = tool_bar_width ? native_height - menu_bar_height : 0;
5135 else if (EQ (FRAME_TOOL_BAR_POSITION (f), Qtop))
5137 tool_bar_height = FRAME_TOOLBAR_HEIGHT (f);
5138 native_top += tool_bar_height;
5139 inner_top += tool_bar_height;
5140 tool_bar_width = tool_bar_height ? native_width : 0;
5142 else if (EQ (FRAME_TOOL_BAR_POSITION (f), Qright))
5144 tool_bar_width = FRAME_TOOLBAR_WIDTH (f);
5145 native_right -= tool_bar_width;
5146 inner_right -= tool_bar_width;
5147 tool_bar_height
5148 = tool_bar_width ? native_height - menu_bar_height : 0;
5150 else
5152 tool_bar_height = FRAME_TOOLBAR_HEIGHT (f);
5153 native_bottom -= tool_bar_height;
5154 inner_bottom -= tool_bar_height;
5155 tool_bar_width = tool_bar_height ? native_width : 0;
5157 #else
5158 tool_bar_height = FRAME_TOOL_BAR_HEIGHT (f);
5159 tool_bar_width = (tool_bar_height
5160 ? native_width - 2 * internal_border_width
5161 : 0);
5162 inner_top += tool_bar_height;
5163 #endif
5165 /* Construct list. */
5166 if (EQ (attribute, Qouter_edges))
5167 return list4 (make_number (outer_left), make_number (outer_top),
5168 make_number (outer_right), make_number (outer_bottom));
5169 else if (EQ (attribute, Qnative_edges))
5170 return list4 (make_number (native_left), make_number (native_top),
5171 make_number (native_right), make_number (native_bottom));
5172 else if (EQ (attribute, Qinner_edges))
5173 return list4 (make_number (inner_left), make_number (inner_top),
5174 make_number (inner_right), make_number (inner_bottom));
5175 else
5176 return
5177 listn (CONSTYPE_HEAP, 11,
5178 Fcons (Qouter_position,
5179 Fcons (make_number (outer_left),
5180 make_number (outer_top))),
5181 Fcons (Qouter_size,
5182 Fcons (make_number (outer_right - outer_left),
5183 make_number (outer_bottom - outer_top))),
5184 /* Approximate. */
5185 Fcons (Qexternal_border_size,
5186 Fcons (make_number (right_off),
5187 make_number (bottom_off))),
5188 Fcons (Qouter_border_width, make_number (x_border_width)),
5189 /* Approximate. */
5190 Fcons (Qtitle_bar_size,
5191 Fcons (make_number (0),
5192 make_number (top_off - bottom_off))),
5193 Fcons (Qmenu_bar_external, menu_bar_external ? Qt : Qnil),
5194 Fcons (Qmenu_bar_size,
5195 Fcons (make_number (menu_bar_width),
5196 make_number (menu_bar_height))),
5197 Fcons (Qtool_bar_external, tool_bar_external ? Qt : Qnil),
5198 Fcons (Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f)),
5199 Fcons (Qtool_bar_size,
5200 Fcons (make_number (tool_bar_width),
5201 make_number (tool_bar_height))),
5202 Fcons (Qinternal_border_width,
5203 make_number (internal_border_width)));
5206 DEFUN ("x-frame-geometry", Fx_frame_geometry, Sx_frame_geometry, 0, 1, 0,
5207 doc: /* Return geometric attributes of FRAME.
5208 FRAME must be a live frame and defaults to the selected one. The return
5209 value is an association list of the attributes listed below. All height
5210 and width values are in pixels.
5212 `outer-position' is a cons of the outer left and top edges of FRAME
5213 relative to the origin - the position (0, 0) - of FRAME's display.
5215 `outer-size' is a cons of the outer width and height of FRAME. The
5216 outer size includes the title bar and the external borders as well as
5217 any menu and/or tool bar of frame. For a child frame the value
5218 includes FRAME's X borders, if any.
5220 `external-border-size' is a cons of the horizontal and vertical width of
5221 FRAME's external borders as supplied by the window manager.
5223 `title-bar-size' is a cons of the width and height of the title bar of
5224 FRAME as supplied by the window manager. If both of them are zero,
5225 FRAME has no title bar. If only the width is zero, Emacs was not
5226 able to retrieve the width information.
5228 `menu-bar-external', if non-nil, means the menu bar is external (never
5229 included in the inner edges of FRAME).
5231 `menu-bar-size' is a cons of the width and height of the menu bar of
5232 FRAME.
5234 `tool-bar-external', if non-nil, means the tool bar is external (never
5235 included in the inner edges of FRAME).
5237 `tool-bar-position' tells on which side the tool bar on FRAME is and can
5238 be one of `left', `top', `right' or `bottom'. If this is nil, FRAME
5239 has no tool bar.
5241 `tool-bar-size' is a cons of the width and height of the tool bar of
5242 FRAME.
5244 `internal-border-width' is the width of the internal border of
5245 FRAME.
5247 `outer-border-width' is the width of the X border of FRAME. The X
5248 border is usually only shown for frames without window manager
5249 decorations like child and tooltip frames. */)
5250 (Lisp_Object frame)
5252 return frame_geometry (frame, Qnil);
5255 DEFUN ("x-frame-edges", Fx_frame_edges, Sx_frame_edges, 0, 2, 0,
5256 doc: /* Return edge coordinates of FRAME.
5257 FRAME must be a live frame and defaults to the selected one. The return
5258 value is a list of the form (LEFT, TOP, RIGHT, BOTTOM). All values are
5259 in pixels relative to the origin - the position (0, 0) - of FRAME's
5260 display.
5262 If optional argument TYPE is the symbol `outer-edges', return the outer
5263 edges of FRAME. The outer edges comprise the decorations of the window
5264 manager (like the title bar or external borders) as well as any external
5265 menu or tool bar of FRAME. If optional argument TYPE is the symbol
5266 `native-edges' or nil, return the native edges of FRAME. The native
5267 edges exclude the decorations of the window manager and any external
5268 menu or tool bar of FRAME. If TYPE is the symbol `inner-edges', return
5269 the inner edges of FRAME. These edges exclude title bar, any borders,
5270 menu bar or tool bar of FRAME. */)
5271 (Lisp_Object frame, Lisp_Object type)
5273 return frame_geometry (frame, ((EQ (type, Qouter_edges)
5274 || EQ (type, Qinner_edges))
5275 ? type
5276 : Qnative_edges));
5280 * x_frame_list_z_order:
5282 * Recursively add list of all frames on the display specified via
5283 * DPYINFO and whose window-system window's parent is specified by
5284 * WINDOW to FRAMES and return FRAMES.
5286 static Lisp_Object
5287 x_frame_list_z_order (Display* dpy, Window window)
5289 Window root, parent, *children;
5290 unsigned int nchildren;
5291 int i;
5292 Lisp_Object frames = Qnil;
5294 block_input ();
5295 if (XQueryTree (dpy, window, &root, &parent, &children, &nchildren))
5297 unblock_input ();
5298 for (i = 0; i < nchildren; i++)
5300 Lisp_Object frame, tail;
5302 FOR_EACH_FRAME (tail, frame)
5303 /* With a reparenting window manager the parent_desc field
5304 usually specifies the topmost windows of our frames.
5305 Otherwise FRAME_OUTER_WINDOW should do. */
5306 if (XFRAME (frame)->output_data.x->parent_desc == children[i]
5307 || FRAME_OUTER_WINDOW (XFRAME (frame)) == children[i])
5308 frames = Fcons (frame, frames);
5311 if (children) XFree ((char *)children);
5313 else
5314 unblock_input ();
5316 return frames;
5320 DEFUN ("x-frame-list-z-order", Fx_frame_list_z_order,
5321 Sx_frame_list_z_order, 0, 1, 0,
5322 doc: /* Return list of Emacs' frames, in Z (stacking) order.
5323 The optional argument TERMINAL specifies which display to ask about.
5324 TERMINAL should be either a frame or a display name (a string). If
5325 omitted or nil, that stands for the selected frame's display. Return
5326 nil if TERMINAL contains no Emacs frame.
5328 As a special case, if TERMINAL is non-nil and specifies a live frame,
5329 return the child frames of that frame in Z (stacking) order.
5331 Frames are listed from topmost (first) to bottommost (last). */)
5332 (Lisp_Object terminal)
5334 struct x_display_info *dpyinfo = check_x_display_info (terminal);
5335 Display *dpy = dpyinfo->display;
5336 Window window;
5338 if (FRAMEP (terminal) && FRAME_LIVE_P (XFRAME (terminal)))
5339 window = FRAME_X_WINDOW (XFRAME (terminal));
5340 else
5341 window = dpyinfo->root_window;
5343 return x_frame_list_z_order (dpy, window);
5347 * x_frame_restack:
5349 * Restack frame F1 below frame F2, above if ABOVE_FLAG is non-nil. In
5350 * practice this is a two-step action: The first step removes F1's
5351 * window-system window from the display. The second step reinserts
5352 * F1's window below (above if ABOVE_FLAG is true) that of F2.
5354 static void
5355 x_frame_restack (struct frame *f1, struct frame *f2, bool above_flag)
5357 #if defined (USE_GTK) && GTK_CHECK_VERSION (2, 18, 0)
5358 block_input ();
5359 xg_frame_restack (f1, f2, above_flag);
5360 unblock_input ();
5361 #else
5362 Display *dpy = FRAME_X_DISPLAY (f1);
5363 Window window1 = FRAME_OUTER_WINDOW (f1);
5364 XWindowChanges wc;
5365 unsigned long mask = (CWSibling | CWStackMode);
5367 wc.sibling = FRAME_OUTER_WINDOW (f2);
5368 wc.stack_mode = above_flag ? Above : Below;
5369 block_input ();
5370 /* Configure the window manager window (a normal XConfigureWindow
5371 won't cut it). This should also work for child frames. */
5372 XReconfigureWMWindow (dpy, window1, FRAME_X_SCREEN_NUMBER (f1), mask, &wc);
5373 unblock_input ();
5374 #endif /* USE_GTK */
5378 DEFUN ("x-frame-restack", Fx_frame_restack, Sx_frame_restack, 2, 3, 0,
5379 doc: /* Restack FRAME1 below FRAME2.
5380 This means that if both frames are visible and the display areas of
5381 these frames overlap, FRAME2 (partially) obscures FRAME1. If optional
5382 third argument ABOVE is non-nil, restack FRAME1 above FRAME2. This
5383 means that if both frames are visible and the display areas of these
5384 frames overlap, FRAME1 (partially) obscures FRAME2.
5386 This may be thought of as an atomic action performed in two steps: The
5387 first step removes FRAME1's window-step window from the display. The
5388 second step reinserts FRAME1's window below (above if ABOVE is true)
5389 that of FRAME2. Hence the position of FRAME2 in its display's Z
5390 \(stacking) order relative to all other frames excluding FRAME1 remains
5391 unaltered.
5393 Some window managers may refuse to restack windows. */)
5394 (Lisp_Object frame1, Lisp_Object frame2, Lisp_Object above)
5396 struct frame *f1 = decode_live_frame (frame1);
5397 struct frame *f2 = decode_live_frame (frame2);
5399 if (FRAME_OUTER_WINDOW (f1) && FRAME_OUTER_WINDOW (f2))
5401 x_frame_restack (f1, f2, !NILP (above));
5402 return Qt;
5404 else
5406 error ("Cannot restack frames");
5407 return Qnil;
5412 DEFUN ("x-mouse-absolute-pixel-position", Fx_mouse_absolute_pixel_position,
5413 Sx_mouse_absolute_pixel_position, 0, 0, 0,
5414 doc: /* Return absolute position of mouse cursor in pixels.
5415 The position is returned as a cons cell (X . Y) of the coordinates of
5416 the mouse cursor position in pixels relative to a position (0, 0) of the
5417 selected frame's display. */)
5418 (void)
5420 struct frame *f = SELECTED_FRAME ();
5421 Window root, dummy_window;
5422 int x, y, dummy;
5424 if (FRAME_INITIAL_P (f) || !FRAME_X_P (f))
5425 return Qnil;
5427 block_input ();
5428 XQueryPointer (FRAME_X_DISPLAY (f),
5429 DefaultRootWindow (FRAME_X_DISPLAY (f)),
5430 &root, &dummy_window, &x, &y, &dummy, &dummy,
5431 (unsigned int *) &dummy);
5432 unblock_input ();
5434 return Fcons (make_number (x), make_number (y));
5437 DEFUN ("x-set-mouse-absolute-pixel-position", Fx_set_mouse_absolute_pixel_position,
5438 Sx_set_mouse_absolute_pixel_position, 2, 2, 0,
5439 doc: /* Move mouse pointer to absolute pixel position (X, Y).
5440 The coordinates X and Y are interpreted in pixels relative to a position
5441 \(0, 0) of the selected frame's display. */)
5442 (Lisp_Object x, Lisp_Object y)
5444 struct frame *f = SELECTED_FRAME ();
5446 if (FRAME_INITIAL_P (f) || !FRAME_X_P (f))
5447 return Qnil;
5449 CHECK_TYPE_RANGED_INTEGER (int, x);
5450 CHECK_TYPE_RANGED_INTEGER (int, y);
5452 block_input ();
5453 XWarpPointer (FRAME_X_DISPLAY (f), None, DefaultRootWindow (FRAME_X_DISPLAY (f)),
5454 0, 0, 0, 0, XINT (x), XINT (y));
5455 unblock_input ();
5457 return Qnil;
5460 /************************************************************************
5461 X Displays
5462 ************************************************************************/
5465 /* Mapping visual names to visuals. */
5467 static struct visual_class
5469 const char *name;
5470 int class;
5472 visual_classes[] =
5474 {"StaticGray", StaticGray},
5475 {"GrayScale", GrayScale},
5476 {"StaticColor", StaticColor},
5477 {"PseudoColor", PseudoColor},
5478 {"TrueColor", TrueColor},
5479 {"DirectColor", DirectColor},
5480 {NULL, 0}
5484 #ifndef HAVE_XSCREENNUMBEROFSCREEN
5486 /* Value is the screen number of screen SCR. This is a substitute for
5487 the X function with the same name when that doesn't exist. */
5490 XScreenNumberOfScreen (scr)
5491 register Screen *scr;
5493 Display *dpy = scr->display;
5494 int i;
5496 for (i = 0; i < dpy->nscreens; ++i)
5497 if (scr == dpy->screens + i)
5498 break;
5500 return i;
5503 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
5506 /* Select the visual that should be used on display DPYINFO. Set
5507 members of DPYINFO appropriately. Called from x_term_init. */
5509 void
5510 select_visual (struct x_display_info *dpyinfo)
5512 Display *dpy = dpyinfo->display;
5513 Screen *screen = dpyinfo->screen;
5515 /* See if a visual is specified. */
5516 AUTO_STRING (visualClass, "visualClass");
5517 AUTO_STRING (VisualClass, "VisualClass");
5518 Lisp_Object value = display_x_get_resource (dpyinfo, visualClass,
5519 VisualClass, Qnil, Qnil);
5521 if (STRINGP (value))
5523 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
5524 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
5525 depth, a decimal number. NAME is compared with case ignored. */
5526 char *s = alloca (SBYTES (value) + 1);
5527 char *dash;
5528 int i, class = -1;
5529 XVisualInfo vinfo;
5531 lispstpcpy (s, value);
5532 dash = strchr (s, '-');
5533 if (dash)
5535 dpyinfo->n_planes = atoi (dash + 1);
5536 *dash = '\0';
5538 else
5539 /* We won't find a matching visual with depth 0, so that
5540 an error will be printed below. */
5541 dpyinfo->n_planes = 0;
5543 /* Determine the visual class. */
5544 for (i = 0; visual_classes[i].name; ++i)
5545 if (xstrcasecmp (s, visual_classes[i].name) == 0)
5547 class = visual_classes[i].class;
5548 break;
5551 /* Look up a matching visual for the specified class. */
5552 if (class == -1
5553 || !XMatchVisualInfo (dpy, XScreenNumberOfScreen (screen),
5554 dpyinfo->n_planes, class, &vinfo))
5555 fatal ("Invalid visual specification '%s'",
5556 SSDATA (ENCODE_SYSTEM (value)));
5558 dpyinfo->visual = vinfo.visual;
5560 else
5562 int n_visuals;
5563 XVisualInfo *vinfo, vinfo_template;
5565 dpyinfo->visual = DefaultVisualOfScreen (screen);
5567 vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
5568 vinfo_template.screen = XScreenNumberOfScreen (screen);
5569 vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
5570 &vinfo_template, &n_visuals);
5571 if (n_visuals <= 0)
5572 fatal ("Can't get proper X visual info");
5574 dpyinfo->n_planes = vinfo->depth;
5575 XFree (vinfo);
5580 /* Return the X display structure for the display named NAME.
5581 Open a new connection if necessary. */
5583 static struct x_display_info *
5584 x_display_info_for_name (Lisp_Object name)
5586 struct x_display_info *dpyinfo;
5588 CHECK_STRING (name);
5590 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
5591 if (!NILP (Fstring_equal (XCAR (dpyinfo->name_list_element), name)))
5592 return dpyinfo;
5594 /* Use this general default value to start with. */
5595 Vx_resource_name = Vinvocation_name;
5597 validate_x_resource_name ();
5599 dpyinfo = x_term_init (name, 0, SSDATA (Vx_resource_name));
5601 if (dpyinfo == 0)
5602 error ("Cannot connect to X server %s", SDATA (name));
5604 XSETFASTINT (Vwindow_system_version, 11);
5606 return dpyinfo;
5610 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
5611 1, 3, 0,
5612 doc: /* Open a connection to a display server.
5613 DISPLAY is the name of the display to connect to.
5614 Optional second arg XRM-STRING is a string of resources in xrdb format.
5615 If the optional third arg MUST-SUCCEED is non-nil,
5616 terminate Emacs if we can't open the connection.
5617 \(In the Nextstep version, the last two arguments are currently ignored.) */)
5618 (Lisp_Object display, Lisp_Object xrm_string, Lisp_Object must_succeed)
5620 char *xrm_option;
5621 struct x_display_info *dpyinfo;
5623 CHECK_STRING (display);
5624 if (! NILP (xrm_string))
5625 CHECK_STRING (xrm_string);
5627 xrm_option = NILP (xrm_string) ? 0 : SSDATA (xrm_string);
5629 validate_x_resource_name ();
5631 /* This is what opens the connection and sets x_current_display.
5632 This also initializes many symbols, such as those used for input. */
5633 dpyinfo = x_term_init (display, xrm_option,
5634 SSDATA (Vx_resource_name));
5636 if (dpyinfo == 0)
5638 if (!NILP (must_succeed))
5639 fatal ("Cannot connect to X server %s.\n\
5640 Check the DISPLAY environment variable or use `-d'.\n\
5641 Also use the `xauth' program to verify that you have the proper\n\
5642 authorization information needed to connect the X server.\n\
5643 An insecure way to solve the problem may be to use `xhost'.\n",
5644 SDATA (display));
5645 else
5646 error ("Cannot connect to X server %s", SDATA (display));
5649 XSETFASTINT (Vwindow_system_version, 11);
5650 return Qnil;
5653 DEFUN ("x-close-connection", Fx_close_connection,
5654 Sx_close_connection, 1, 1, 0,
5655 doc: /* Close the connection to TERMINAL's X server.
5656 For TERMINAL, specify a terminal object, a frame or a display name (a
5657 string). If TERMINAL is nil, that stands for the selected frame's
5658 terminal. */)
5659 (Lisp_Object terminal)
5661 struct x_display_info *dpyinfo = check_x_display_info (terminal);
5663 if (dpyinfo->reference_count > 0)
5664 error ("Display still has frames on it");
5666 x_delete_terminal (dpyinfo->terminal);
5668 return Qnil;
5671 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
5672 doc: /* Return the list of display names that Emacs has connections to. */)
5673 (void)
5675 Lisp_Object result = Qnil;
5676 struct x_display_info *xdi;
5678 for (xdi = x_display_list; xdi; xdi = xdi->next)
5679 result = Fcons (XCAR (xdi->name_list_element), result);
5681 return result;
5684 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
5685 doc: /* If ON is non-nil, report X errors as soon as the erring request is made.
5686 This function only has an effect on X Windows. With MS Windows, it is
5687 defined but does nothing.
5689 If ON is nil, allow buffering of requests.
5690 Turning on synchronization prohibits the Xlib routines from buffering
5691 requests and seriously degrades performance, but makes debugging much
5692 easier.
5693 The optional second argument TERMINAL specifies which display to act on.
5694 TERMINAL should be a terminal object, a frame or a display name (a string).
5695 If TERMINAL is omitted or nil, that stands for the selected frame's display. */)
5696 (Lisp_Object on, Lisp_Object terminal)
5698 struct x_display_info *dpyinfo = check_x_display_info (terminal);
5700 XSynchronize (dpyinfo->display, !EQ (on, Qnil));
5702 return Qnil;
5705 /* Wait for responses to all X commands issued so far for frame F. */
5707 void
5708 x_sync (struct frame *f)
5710 block_input ();
5711 XSync (FRAME_X_DISPLAY (f), False);
5712 unblock_input ();
5716 /***********************************************************************
5717 Window properties
5718 ***********************************************************************/
5720 DEFUN ("x-change-window-property", Fx_change_window_property,
5721 Sx_change_window_property, 2, 6, 0,
5722 doc: /* Change window property PROP to VALUE on the X window of FRAME.
5723 PROP must be a string. VALUE may be a string or a list of conses,
5724 numbers and/or strings. If an element in the list is a string, it is
5725 converted to an atom and the value of the atom is used. If an element
5726 is a cons, it is converted to a 32 bit number where the car is the 16
5727 top bits and the cdr is the lower 16 bits.
5729 FRAME nil or omitted means use the selected frame.
5730 If TYPE is given and non-nil, it is the name of the type of VALUE.
5731 If TYPE is not given or nil, the type is STRING.
5732 FORMAT gives the size in bits of each element if VALUE is a list.
5733 It must be one of 8, 16 or 32.
5734 If VALUE is a string or FORMAT is nil or not given, FORMAT defaults to 8.
5735 If OUTER-P is non-nil, the property is changed for the outer X window of
5736 FRAME. Default is to change on the edit X window. */)
5737 (Lisp_Object prop, Lisp_Object value, Lisp_Object frame,
5738 Lisp_Object type, Lisp_Object format, Lisp_Object outer_p)
5740 struct frame *f = decode_window_system_frame (frame);
5741 Atom prop_atom;
5742 Atom target_type = XA_STRING;
5743 int element_format = 8;
5744 unsigned char *data;
5745 int nelements;
5746 Window w;
5748 CHECK_STRING (prop);
5750 if (! NILP (format))
5752 CHECK_NUMBER (format);
5754 if (XINT (format) != 8 && XINT (format) != 16
5755 && XINT (format) != 32)
5756 error ("FORMAT must be one of 8, 16 or 32");
5757 element_format = XINT (format);
5760 if (CONSP (value))
5762 ptrdiff_t elsize;
5764 nelements = x_check_property_data (value);
5765 if (nelements == -1)
5766 error ("Bad data in VALUE, must be number, string or cons");
5768 /* The man page for XChangeProperty:
5769 "If the specified format is 32, the property data must be a
5770 long array."
5771 This applies even if long is more than 32 bits. The X library
5772 converts to 32 bits before sending to the X server. */
5773 elsize = element_format == 32 ? sizeof (long) : element_format >> 3;
5774 data = xnmalloc (nelements, elsize);
5776 x_fill_property_data (FRAME_X_DISPLAY (f), value, data, element_format);
5778 else
5780 ptrdiff_t elsize;
5782 CHECK_STRING (value);
5783 data = SDATA (value);
5784 if (INT_MAX < SBYTES (value))
5785 error ("VALUE too long");
5787 /* See comment above about longs and format=32 */
5788 elsize = element_format == 32 ? sizeof (long) : element_format >> 3;
5789 if (SBYTES (value) % elsize != 0)
5790 error ("VALUE must contain an integral number of octets for FORMAT");
5791 nelements = SBYTES (value) / elsize;
5794 block_input ();
5795 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False);
5796 if (! NILP (type))
5798 CHECK_STRING (type);
5799 target_type = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (type), False);
5802 if (! NILP (outer_p)) w = FRAME_OUTER_WINDOW (f);
5803 else w = FRAME_X_WINDOW (f);
5805 XChangeProperty (FRAME_X_DISPLAY (f), w,
5806 prop_atom, target_type, element_format, PropModeReplace,
5807 data, nelements);
5809 if (CONSP (value)) xfree (data);
5811 /* Make sure the property is set when we return. */
5812 XFlush (FRAME_X_DISPLAY (f));
5813 unblock_input ();
5815 return value;
5819 DEFUN ("x-delete-window-property", Fx_delete_window_property,
5820 Sx_delete_window_property, 1, 2, 0,
5821 doc: /* Remove window property PROP from X window of FRAME.
5822 FRAME nil or omitted means use the selected frame. Value is PROP. */)
5823 (Lisp_Object prop, Lisp_Object frame)
5825 struct frame *f = decode_window_system_frame (frame);
5826 Atom prop_atom;
5828 CHECK_STRING (prop);
5829 block_input ();
5830 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False);
5831 XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), prop_atom);
5833 /* Make sure the property is removed when we return. */
5834 XFlush (FRAME_X_DISPLAY (f));
5835 unblock_input ();
5837 return prop;
5841 static Lisp_Object
5842 x_window_property_intern (struct frame *f,
5843 Window target_window,
5844 Atom prop_atom,
5845 Atom target_type,
5846 Lisp_Object delete_p,
5847 Lisp_Object vector_ret_p,
5848 bool *found)
5850 unsigned char *tmp_data = NULL;
5851 Lisp_Object prop_value = Qnil;
5852 Atom actual_type;
5853 int actual_format;
5854 unsigned long actual_size, bytes_remaining;
5855 int rc;
5857 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
5858 prop_atom, 0, 0, False, target_type,
5859 &actual_type, &actual_format, &actual_size,
5860 &bytes_remaining, &tmp_data);
5862 *found = actual_format != 0;
5864 if (rc == Success && *found)
5866 XFree (tmp_data);
5867 tmp_data = NULL;
5869 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
5870 prop_atom, 0, bytes_remaining,
5871 ! NILP (delete_p), target_type,
5872 &actual_type, &actual_format,
5873 &actual_size, &bytes_remaining,
5874 &tmp_data);
5875 if (rc == Success && tmp_data)
5877 /* The man page for XGetWindowProperty says:
5878 "If the returned format is 32, the returned data is represented
5879 as a long array and should be cast to that type to obtain the
5880 elements."
5881 This applies even if long is more than 32 bits, the X library
5882 converts from 32 bit elements received from the X server to long
5883 and passes the long array to us. Thus, for that case memcpy can not
5884 be used. We convert to a 32 bit type here, because so much code
5885 assume on that.
5887 The bytes and offsets passed to XGetWindowProperty refers to the
5888 property and those are indeed in 32 bit quantities if format is
5889 32. */
5891 if (LONG_WIDTH > 32 && actual_format == 32)
5893 unsigned long i;
5894 int *idata = (int *) tmp_data;
5895 long *ldata = (long *) tmp_data;
5897 for (i = 0; i < actual_size; ++i)
5898 idata[i] = (int) ldata[i];
5901 if (NILP (vector_ret_p))
5902 prop_value = make_string ((char *) tmp_data,
5903 (actual_format >> 3) * actual_size);
5904 else
5905 prop_value = x_property_data_to_lisp (f,
5906 tmp_data,
5907 actual_type,
5908 actual_format,
5909 actual_size);
5912 if (tmp_data) XFree (tmp_data);
5915 return prop_value;
5918 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
5919 1, 6, 0,
5920 doc: /* Value is the value of window property PROP on FRAME.
5921 If FRAME is nil or omitted, use the selected frame.
5923 On X Windows, the following optional arguments are also accepted:
5924 If TYPE is nil or omitted, get the property as a string.
5925 Otherwise TYPE is the name of the atom that denotes the type expected.
5926 If SOURCE is non-nil, get the property on that window instead of from
5927 FRAME. The number 0 denotes the root window.
5928 If DELETE-P is non-nil, delete the property after retrieving it.
5929 If VECTOR-RET-P is non-nil, don't return a string but a vector of values.
5931 On MS Windows, this function accepts but ignores those optional arguments.
5933 Value is nil if FRAME hasn't a property with name PROP or if PROP has
5934 no value of TYPE (always string in the MS Windows case). */)
5935 (Lisp_Object prop, Lisp_Object frame, Lisp_Object type,
5936 Lisp_Object source, Lisp_Object delete_p, Lisp_Object vector_ret_p)
5938 struct frame *f = decode_window_system_frame (frame);
5939 Atom prop_atom;
5940 Lisp_Object prop_value = Qnil;
5941 Atom target_type = XA_STRING;
5942 Window target_window = FRAME_X_WINDOW (f);
5943 bool found;
5945 CHECK_STRING (prop);
5947 if (! NILP (source))
5949 CONS_TO_INTEGER (source, Window, target_window);
5950 if (! target_window)
5951 target_window = FRAME_DISPLAY_INFO (f)->root_window;
5954 block_input ();
5955 if (STRINGP (type))
5957 if (strcmp ("AnyPropertyType", SSDATA (type)) == 0)
5958 target_type = AnyPropertyType;
5959 else
5960 target_type = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (type), False);
5963 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False);
5964 prop_value = x_window_property_intern (f,
5965 target_window,
5966 prop_atom,
5967 target_type,
5968 delete_p,
5969 vector_ret_p,
5970 &found);
5971 if (NILP (prop_value)
5972 && ! found
5973 && NILP (source)
5974 && target_window != FRAME_OUTER_WINDOW (f))
5976 prop_value = x_window_property_intern (f,
5977 FRAME_OUTER_WINDOW (f),
5978 prop_atom,
5979 target_type,
5980 delete_p,
5981 vector_ret_p,
5982 &found);
5986 unblock_input ();
5987 return prop_value;
5990 DEFUN ("x-window-property-attributes", Fx_window_property_attributes, Sx_window_property_attributes,
5991 1, 3, 0,
5992 doc: /* Retrieve metadata about window property PROP on FRAME.
5993 If FRAME is nil or omitted, use the selected frame.
5994 If SOURCE is non-nil, get the property on that window instead of from
5995 FRAME. The number 0 denotes the root window.
5997 Return value is nil if FRAME hasn't a property with name PROP.
5998 Otherwise, the return value is a vector with the following fields:
6000 0. The property type, as an integer. The symbolic name of
6001 the type can be obtained with `x-get-atom-name'.
6002 1. The format of each element; one of 8, 16, or 32.
6003 2. The length of the property, in number of elements. */)
6004 (Lisp_Object prop, Lisp_Object frame, Lisp_Object source)
6006 struct frame *f = decode_window_system_frame (frame);
6007 Window target_window = FRAME_X_WINDOW (f);
6008 Atom prop_atom;
6009 Lisp_Object prop_attr = Qnil;
6010 Atom actual_type;
6011 int actual_format;
6012 unsigned long actual_size, bytes_remaining;
6013 unsigned char *tmp_data = NULL;
6014 int rc;
6016 CHECK_STRING (prop);
6018 if (! NILP (source))
6020 CONS_TO_INTEGER (source, Window, target_window);
6021 if (! target_window)
6022 target_window = FRAME_DISPLAY_INFO (f)->root_window;
6025 block_input ();
6027 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False);
6028 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
6029 prop_atom, 0, 0, False, AnyPropertyType,
6030 &actual_type, &actual_format, &actual_size,
6031 &bytes_remaining, &tmp_data);
6032 if (rc == Success /* no invalid params */
6033 && actual_format == 0 /* but prop not found */
6034 && NILP (source)
6035 && target_window != FRAME_OUTER_WINDOW (f))
6037 /* analogous behavior to x-window-property: if property isn't found
6038 on the frame's inner window and no alternate window id was
6039 provided, try the frame's outer window. */
6040 target_window = FRAME_OUTER_WINDOW (f);
6041 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
6042 prop_atom, 0, 0, False, AnyPropertyType,
6043 &actual_type, &actual_format, &actual_size,
6044 &bytes_remaining, &tmp_data);
6047 if (rc == Success && actual_format != 0)
6049 XFree (tmp_data);
6051 prop_attr = make_uninit_vector (3);
6052 ASET (prop_attr, 0, make_number (actual_type));
6053 ASET (prop_attr, 1, make_number (actual_format));
6054 ASET (prop_attr, 2, make_number (bytes_remaining / (actual_format >> 3)));
6057 unblock_input ();
6058 return prop_attr;
6061 /***********************************************************************
6062 Tool tips
6063 ***********************************************************************/
6065 static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
6066 Lisp_Object, int, int, int *, int *);
6068 /* The frame of a currently visible tooltip. */
6070 Lisp_Object tip_frame;
6072 /* If non-nil, a timer started that hides the last tooltip when it
6073 fires. */
6075 static Lisp_Object tip_timer;
6076 Window tip_window;
6078 /* If non-nil, a vector of 3 elements containing the last args
6079 with which x-show-tip was called. See there. */
6081 static Lisp_Object last_show_tip_args;
6084 static void
6085 unwind_create_tip_frame (Lisp_Object frame)
6087 Lisp_Object deleted;
6089 deleted = unwind_create_frame (frame);
6090 if (EQ (deleted, Qt))
6092 tip_window = None;
6093 tip_frame = Qnil;
6098 /* Create a frame for a tooltip on the display described by DPYINFO.
6099 PARMS is a list of frame parameters. TEXT is the string to
6100 display in the tip frame. Value is the frame.
6102 Note that functions called here, esp. x_default_parameter can
6103 signal errors, for instance when a specified color name is
6104 undefined. We have to make sure that we're in a consistent state
6105 when this happens. */
6107 static Lisp_Object
6108 x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms)
6110 struct frame *f;
6111 Lisp_Object frame;
6112 Lisp_Object name;
6113 int width, height;
6114 ptrdiff_t count = SPECPDL_INDEX ();
6115 bool face_change_before = face_change;
6116 int x_width = 0, x_height = 0;
6118 if (!dpyinfo->terminal->name)
6119 error ("Terminal is not live, can't create new frames on it");
6121 parms = Fcopy_alist (parms);
6123 /* Get the name of the frame to use for resource lookup. */
6124 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
6125 if (!STRINGP (name)
6126 && !EQ (name, Qunbound)
6127 && !NILP (name))
6128 error ("Invalid frame name--not a string or nil");
6130 frame = Qnil;
6131 f = make_frame (false);
6132 f->wants_modeline = false;
6133 XSETFRAME (frame, f);
6134 record_unwind_protect (unwind_create_tip_frame, frame);
6136 f->terminal = dpyinfo->terminal;
6138 /* By setting the output method, we're essentially saying that
6139 the frame is live, as per FRAME_LIVE_P. If we get a signal
6140 from this point on, x_destroy_window might screw up reference
6141 counts etc. */
6142 f->output_method = output_x_window;
6143 f->output_data.x = xzalloc (sizeof *f->output_data.x);
6144 f->output_data.x->icon_bitmap = -1;
6145 FRAME_FONTSET (f) = -1;
6146 f->output_data.x->scroll_bar_foreground_pixel = -1;
6147 f->output_data.x->scroll_bar_background_pixel = -1;
6148 #if defined (USE_LUCID) && defined (USE_TOOLKIT_SCROLL_BARS)
6149 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
6150 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
6151 #endif /* USE_LUCID && USE_TOOLKIT_SCROLL_BARS */
6152 f->output_data.x->white_relief.pixel = -1;
6153 f->output_data.x->black_relief.pixel = -1;
6155 fset_icon_name (f, Qnil);
6156 FRAME_DISPLAY_INFO (f) = dpyinfo;
6157 f->output_data.x->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
6158 f->output_data.x->explicit_parent = false;
6160 /* These colors will be set anyway later, but it's important
6161 to get the color reference counts right, so initialize them! */
6163 Lisp_Object black;
6165 /* Function x_decode_color can signal an error. Make
6166 sure to initialize color slots so that we won't try
6167 to free colors we haven't allocated. */
6168 FRAME_FOREGROUND_PIXEL (f) = -1;
6169 FRAME_BACKGROUND_PIXEL (f) = -1;
6170 f->output_data.x->cursor_pixel = -1;
6171 f->output_data.x->cursor_foreground_pixel = -1;
6172 f->output_data.x->border_pixel = -1;
6173 f->output_data.x->mouse_pixel = -1;
6175 black = build_string ("black");
6176 FRAME_FOREGROUND_PIXEL (f)
6177 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
6178 FRAME_BACKGROUND_PIXEL (f)
6179 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
6180 f->output_data.x->cursor_pixel
6181 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
6182 f->output_data.x->cursor_foreground_pixel
6183 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
6184 f->output_data.x->border_pixel
6185 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
6186 f->output_data.x->mouse_pixel
6187 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
6190 /* Set the name; the functions to which we pass f expect the name to
6191 be set. */
6192 if (EQ (name, Qunbound) || NILP (name))
6194 fset_name (f, build_string (dpyinfo->x_id_name));
6195 f->explicit_name = false;
6197 else
6199 fset_name (f, name);
6200 f->explicit_name = true;
6201 /* use the frame's title when getting resources for this frame. */
6202 specbind (Qx_resource_name, name);
6205 #ifdef USE_CAIRO
6206 register_font_driver (&ftcrfont_driver, f);
6207 #else
6208 register_font_driver (&xfont_driver, f);
6209 #ifdef HAVE_FREETYPE
6210 #ifdef HAVE_XFT
6211 register_font_driver (&xftfont_driver, f);
6212 #else /* not HAVE_XFT */
6213 register_font_driver (&ftxfont_driver, f);
6214 #endif /* not HAVE_XFT */
6215 #endif /* HAVE_FREETYPE */
6216 #endif /* not USE_CAIRO */
6218 image_cache_refcount =
6219 FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
6220 #ifdef GLYPH_DEBUG
6221 dpyinfo_refcount = dpyinfo->reference_count;
6222 #endif /* GLYPH_DEBUG */
6224 x_default_parameter (f, parms, Qfont_backend, Qnil,
6225 "fontBackend", "FontBackend", RES_TYPE_STRING);
6227 /* Extract the window parameters from the supplied values that are
6228 needed to determine window geometry. */
6229 x_default_font_parameter (f, parms);
6231 x_default_parameter (f, parms, Qborder_width, make_number (0),
6232 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
6234 /* This defaults to 2 in order to match xterm. We recognize either
6235 internalBorderWidth or internalBorder (which is what xterm calls
6236 it). */
6237 if (NILP (Fassq (Qinternal_border_width, parms)))
6239 Lisp_Object value;
6241 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
6242 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
6243 if (! EQ (value, Qunbound))
6244 parms = Fcons (Fcons (Qinternal_border_width, value),
6245 parms);
6248 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
6249 "internalBorderWidth", "internalBorderWidth",
6250 RES_TYPE_NUMBER);
6251 x_default_parameter (f, parms, Qright_divider_width, make_number (0),
6252 NULL, NULL, RES_TYPE_NUMBER);
6253 x_default_parameter (f, parms, Qbottom_divider_width, make_number (0),
6254 NULL, NULL, RES_TYPE_NUMBER);
6256 /* Also do the stuff which must be set before the window exists. */
6257 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
6258 "foreground", "Foreground", RES_TYPE_STRING);
6259 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
6260 "background", "Background", RES_TYPE_STRING);
6261 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
6262 "pointerColor", "Foreground", RES_TYPE_STRING);
6263 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
6264 "cursorColor", "Foreground", RES_TYPE_STRING);
6265 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
6266 "borderColor", "BorderColor", RES_TYPE_STRING);
6267 x_default_parameter (f, parms, Qno_special_glyphs, Qnil,
6268 NULL, NULL, RES_TYPE_BOOLEAN);
6270 /* Init faces before x_default_parameter is called for the
6271 scroll-bar-width parameter because otherwise we end up in
6272 init_iterator with a null face cache, which should not happen. */
6273 init_frame_faces (f);
6275 f->output_data.x->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
6277 x_figure_window_size (f, parms, false, &x_width, &x_height);
6280 XSetWindowAttributes attrs;
6281 unsigned long mask;
6282 Atom type = FRAME_DISPLAY_INFO (f)->Xatom_net_window_type_tooltip;
6284 block_input ();
6285 mask = CWBackPixel | CWOverrideRedirect | CWEventMask | CWCursor;
6286 if (DoesSaveUnders (dpyinfo->screen))
6287 mask |= CWSaveUnder;
6289 /* Window managers look at the override-redirect flag to determine
6290 whether or net to give windows a decoration (Xlib spec, chapter
6291 3.2.8). */
6292 attrs.override_redirect = True;
6293 attrs.save_under = True;
6294 attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
6295 attrs.cursor =
6296 f->output_data.x->current_cursor
6297 = f->output_data.x->text_cursor;
6298 /* Arrange for getting MapNotify and UnmapNotify events. */
6299 attrs.event_mask = StructureNotifyMask;
6300 tip_window
6301 = FRAME_X_WINDOW (f)
6302 = XCreateWindow (FRAME_X_DISPLAY (f),
6303 FRAME_DISPLAY_INFO (f)->root_window,
6304 /* x, y, width, height */
6305 0, 0, 1, 1,
6306 /* Border. */
6307 f->border_width,
6308 CopyFromParent, InputOutput, CopyFromParent,
6309 mask, &attrs);
6310 initial_set_up_x_back_buffer (f);
6311 XChangeProperty (FRAME_X_DISPLAY (f), tip_window,
6312 FRAME_DISPLAY_INFO (f)->Xatom_net_window_type,
6313 XA_ATOM, 32, PropModeReplace,
6314 (unsigned char *)&type, 1);
6315 unblock_input ();
6318 x_make_gc (f);
6320 x_default_parameter (f, parms, Qauto_raise, Qnil,
6321 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
6322 x_default_parameter (f, parms, Qauto_lower, Qnil,
6323 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
6324 x_default_parameter (f, parms, Qcursor_type, Qbox,
6325 "cursorType", "CursorType", RES_TYPE_SYMBOL);
6326 x_default_parameter (f, parms, Qalpha, Qnil,
6327 "alpha", "Alpha", RES_TYPE_NUMBER);
6329 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
6330 Change will not be effected unless different from the current
6331 FRAME_LINES (f). */
6332 width = FRAME_COLS (f);
6333 height = FRAME_LINES (f);
6334 SET_FRAME_COLS (f, 0);
6335 SET_FRAME_LINES (f, 0);
6336 change_frame_size (f, width, height, true, false, false, false);
6338 /* Add `tooltip' frame parameter's default value. */
6339 if (NILP (Fframe_parameter (frame, Qtooltip)))
6341 AUTO_FRAME_ARG (arg, Qtooltip, Qt);
6342 Fmodify_frame_parameters (frame, arg);
6345 /* FIXME - can this be done in a similar way to normal frames?
6346 https://lists.gnu.org/r/emacs-devel/2007-10/msg00641.html */
6348 /* Set the `display-type' frame parameter before setting up faces. */
6350 Lisp_Object disptype;
6352 if (FRAME_DISPLAY_INFO (f)->n_planes == 1)
6353 disptype = Qmono;
6354 else if (FRAME_DISPLAY_INFO (f)->visual->class == GrayScale
6355 || FRAME_DISPLAY_INFO (f)->visual->class == StaticGray)
6356 disptype = intern ("grayscale");
6357 else
6358 disptype = intern ("color");
6360 if (NILP (Fframe_parameter (frame, Qdisplay_type)))
6362 AUTO_FRAME_ARG (arg, Qdisplay_type, disptype);
6363 Fmodify_frame_parameters (frame, arg);
6367 /* Set up faces after all frame parameters are known. This call
6368 also merges in face attributes specified for new frames.
6370 Frame parameters may be changed if .Xdefaults contains
6371 specifications for the default font. For example, if there is an
6372 `Emacs.default.attributeBackground: pink', the `background-color'
6373 attribute of the frame get's set, which let's the internal border
6374 of the tooltip frame appear in pink. Prevent this. */
6376 Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
6378 call2 (Qface_set_after_frame_default, frame, Qnil);
6380 if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
6382 AUTO_FRAME_ARG (arg, Qbackground_color, bg);
6383 Fmodify_frame_parameters (frame, arg);
6387 f->no_split = true;
6389 /* Now that the frame will be official, it counts as a reference to
6390 its display and terminal. */
6391 FRAME_DISPLAY_INFO (f)->reference_count++;
6392 f->terminal->reference_count++;
6394 /* It is now ok to make the frame official even if we get an error
6395 below. And the frame needs to be on Vframe_list or making it
6396 visible won't work. */
6397 Vframe_list = Fcons (frame, Vframe_list);
6398 f->can_x_set_window_size = true;
6400 /* Setting attributes of faces of the tooltip frame from resources
6401 and similar will set face_change, which leads to the clearing of
6402 all current matrices. Since this isn't necessary here, avoid it
6403 by resetting face_change to the value it had before we created
6404 the tip frame. */
6405 face_change = face_change_before;
6407 /* Discard the unwind_protect. */
6408 return unbind_to (count, frame);
6412 /* Compute where to display tip frame F. PARMS is the list of frame
6413 parameters for F. DX and DY are specified offsets from the current
6414 location of the mouse. WIDTH and HEIGHT are the width and height
6415 of the tooltip. Return coordinates relative to the root window of
6416 the display in *ROOT_X, and *ROOT_Y. */
6418 static void
6419 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)
6421 Lisp_Object left, top, right, bottom;
6422 int win_x, win_y;
6423 Window root, child;
6424 unsigned pmask;
6425 int min_x, min_y, max_x, max_y = -1;
6427 /* User-specified position? */
6428 left = Fcdr (Fassq (Qleft, parms));
6429 top = Fcdr (Fassq (Qtop, parms));
6430 right = Fcdr (Fassq (Qright, parms));
6431 bottom = Fcdr (Fassq (Qbottom, parms));
6433 /* Move the tooltip window where the mouse pointer is. Resize and
6434 show it. */
6435 if ((!INTEGERP (left) && !INTEGERP (right))
6436 || (!INTEGERP (top) && !INTEGERP (bottom)))
6438 Lisp_Object frame, attributes, monitor, geometry;
6440 block_input ();
6441 XQueryPointer (FRAME_X_DISPLAY (f), FRAME_DISPLAY_INFO (f)->root_window,
6442 &root, &child, root_x, root_y, &win_x, &win_y, &pmask);
6443 unblock_input ();
6445 XSETFRAME(frame, f);
6446 attributes = Fx_display_monitor_attributes_list (frame);
6448 /* Try to determine the monitor where the mouse pointer is and
6449 its geometry. See bug#22549. */
6450 while (CONSP (attributes))
6452 monitor = XCAR (attributes);
6453 geometry = Fassq (Qgeometry, monitor);
6454 if (CONSP (geometry))
6456 min_x = XINT (Fnth (make_number (1), geometry));
6457 min_y = XINT (Fnth (make_number (2), geometry));
6458 max_x = min_x + XINT (Fnth (make_number (3), geometry));
6459 max_y = min_y + XINT (Fnth (make_number (4), geometry));
6460 if (min_x <= *root_x && *root_x < max_x
6461 && min_y <= *root_y && *root_y < max_y)
6463 break;
6465 max_y = -1;
6468 attributes = XCDR (attributes);
6472 /* It was not possible to determine the monitor's geometry, so we
6473 assign some sane defaults here: */
6474 if ( max_y < 0 )
6476 min_x = 0;
6477 min_y = 0;
6478 max_x = x_display_pixel_width (FRAME_DISPLAY_INFO (f));
6479 max_y = x_display_pixel_height (FRAME_DISPLAY_INFO (f));
6482 if (INTEGERP (top))
6483 *root_y = XINT (top);
6484 else if (INTEGERP (bottom))
6485 *root_y = XINT (bottom) - height;
6486 else if (*root_y + XINT (dy) <= min_y)
6487 *root_y = min_y; /* Can happen for negative dy */
6488 else if (*root_y + XINT (dy) + height <= max_y)
6489 /* It fits below the pointer */
6490 *root_y += XINT (dy);
6491 else if (height + XINT (dy) + min_y <= *root_y)
6492 /* It fits above the pointer. */
6493 *root_y -= height + XINT (dy);
6494 else
6495 /* Put it on the top. */
6496 *root_y = min_y;
6498 if (INTEGERP (left))
6499 *root_x = XINT (left);
6500 else if (INTEGERP (right))
6501 *root_x = XINT (right) - width;
6502 else if (*root_x + XINT (dx) <= min_x)
6503 *root_x = 0; /* Can happen for negative dx */
6504 else if (*root_x + XINT (dx) + width <= max_x)
6505 /* It fits to the right of the pointer. */
6506 *root_x += XINT (dx);
6507 else if (width + XINT (dx) + min_x <= *root_x)
6508 /* It fits to the left of the pointer. */
6509 *root_x -= width + XINT (dx);
6510 else
6511 /* Put it left justified on the screen -- it ought to fit that way. */
6512 *root_x = min_x;
6516 /* Hide tooltip. Delete its frame if DELETE is true. */
6517 static Lisp_Object
6518 x_hide_tip (bool delete)
6520 if (!NILP (tip_timer))
6522 call1 (Qcancel_timer, tip_timer);
6523 tip_timer = Qnil;
6527 if (NILP (tip_frame)
6528 || (!delete && FRAMEP (tip_frame)
6529 && !FRAME_VISIBLE_P (XFRAME (tip_frame))))
6530 return Qnil;
6531 else
6533 ptrdiff_t count;
6534 Lisp_Object was_open = Qnil;
6536 count = SPECPDL_INDEX ();
6537 specbind (Qinhibit_redisplay, Qt);
6538 specbind (Qinhibit_quit, Qt);
6540 #ifdef USE_GTK
6542 /* When using system tooltip, tip_frame is the Emacs frame on
6543 which the tip is shown. */
6544 struct frame *f = XFRAME (tip_frame);
6546 if (FRAME_LIVE_P (f) && xg_hide_tooltip (f))
6548 tip_frame = Qnil;
6549 was_open = Qt;
6552 #endif
6554 if (FRAMEP (tip_frame))
6556 if (delete)
6558 delete_frame (tip_frame, Qnil);
6559 tip_frame = Qnil;
6561 else
6562 x_make_frame_invisible (XFRAME (tip_frame));
6564 was_open = Qt;
6566 #ifdef USE_LUCID
6567 /* Bloodcurdling hack alert: The Lucid menu bar widget's
6568 redisplay procedure is not called when a tip frame over
6569 menu items is unmapped. Redisplay the menu manually... */
6571 Widget w;
6572 struct frame *f = SELECTED_FRAME ();
6573 if (FRAME_X_P (f) && FRAME_LIVE_P (f))
6575 w = f->output_data.x->menubar_widget;
6577 if (!DoesSaveUnders (FRAME_DISPLAY_INFO (f)->screen)
6578 && w != NULL)
6580 block_input ();
6581 xlwmenu_redisplay (w);
6582 unblock_input ();
6586 #endif /* USE_LUCID */
6588 else
6589 tip_frame = Qnil;
6591 return unbind_to (count, was_open);
6595 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
6596 doc: /* Show STRING in a "tooltip" window on frame FRAME.
6597 A tooltip window is a small X window displaying a string.
6599 This is an internal function; Lisp code should call `tooltip-show'.
6601 FRAME nil or omitted means use the selected frame.
6603 PARMS is an optional list of frame parameters which can be used to
6604 change the tooltip's appearance.
6606 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
6607 means use the default timeout of 5 seconds.
6609 If the list of frame parameters PARMS contains a `left' parameter,
6610 display the tooltip at that x-position. If the list of frame parameters
6611 PARMS contains no `left' but a `right' parameter, display the tooltip
6612 right-adjusted at that x-position. Otherwise display it at the
6613 x-position of the mouse, with offset DX added (default is 5 if DX isn't
6614 specified).
6616 Likewise for the y-position: If a `top' frame parameter is specified, it
6617 determines the position of the upper edge of the tooltip window. If a
6618 `bottom' parameter but no `top' frame parameter is specified, it
6619 determines the position of the lower edge of the tooltip window.
6620 Otherwise display the tooltip window at the y-position of the mouse,
6621 with offset DY added (default is -10).
6623 A tooltip's maximum size is specified by `x-max-tooltip-size'.
6624 Text larger than the specified size is clipped. */)
6625 (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy)
6627 struct frame *f, *tip_f;
6628 struct window *w;
6629 int root_x, root_y;
6630 struct buffer *old_buffer;
6631 struct text_pos pos;
6632 int width, height;
6633 int old_windows_or_buffers_changed = windows_or_buffers_changed;
6634 ptrdiff_t count = SPECPDL_INDEX ();
6635 ptrdiff_t count_1;
6636 Lisp_Object window, size;
6637 Lisp_Object tip_buf;
6638 AUTO_STRING (tip, " *tip*");
6640 specbind (Qinhibit_redisplay, Qt);
6642 CHECK_STRING (string);
6643 if (SCHARS (string) == 0)
6644 string = make_unibyte_string (" ", 1);
6646 f = decode_window_system_frame (frame);
6647 if (NILP (timeout))
6648 timeout = make_number (5);
6649 else
6650 CHECK_NATNUM (timeout);
6652 if (NILP (dx))
6653 dx = make_number (5);
6654 else
6655 CHECK_NUMBER (dx);
6657 if (NILP (dy))
6658 dy = make_number (-10);
6659 else
6660 CHECK_NUMBER (dy);
6662 #ifdef USE_GTK
6663 if (x_gtk_use_system_tooltips)
6665 bool ok;
6667 /* Hide a previous tip, if any. */
6668 Fx_hide_tip ();
6670 block_input ();
6671 ok = xg_prepare_tooltip (f, string, &width, &height);
6672 if (ok)
6674 compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
6675 xg_show_tooltip (f, root_x, root_y);
6676 /* This is used in Fx_hide_tip. */
6677 XSETFRAME (tip_frame, f);
6679 unblock_input ();
6680 if (ok) goto start_timer;
6682 #endif /* USE_GTK */
6684 if (NILP (last_show_tip_args))
6685 last_show_tip_args = Fmake_vector (make_number (3), Qnil);
6687 if (FRAMEP (tip_frame) && FRAME_LIVE_P (XFRAME (tip_frame)))
6689 Lisp_Object last_string = AREF (last_show_tip_args, 0);
6690 Lisp_Object last_frame = AREF (last_show_tip_args, 1);
6691 Lisp_Object last_parms = AREF (last_show_tip_args, 2);
6693 if (FRAME_VISIBLE_P (XFRAME (tip_frame))
6694 && EQ (frame, last_frame)
6695 && !NILP (Fequal_including_properties (last_string, string))
6696 && !NILP (Fequal (last_parms, parms)))
6698 /* Only DX and DY have changed. */
6699 tip_f = XFRAME (tip_frame);
6700 if (!NILP (tip_timer))
6702 Lisp_Object timer = tip_timer;
6704 tip_timer = Qnil;
6705 call1 (Qcancel_timer, timer);
6708 block_input ();
6709 compute_tip_xy (tip_f, parms, dx, dy, FRAME_PIXEL_WIDTH (tip_f),
6710 FRAME_PIXEL_HEIGHT (tip_f), &root_x, &root_y);
6711 XMoveWindow (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f),
6712 root_x, root_y);
6713 unblock_input ();
6715 goto start_timer;
6717 else if (tooltip_reuse_hidden_frame && EQ (frame, last_frame))
6719 bool delete = false;
6720 Lisp_Object tail, elt, parm, last;
6722 /* Check if every parameter in PARMS has the same value in
6723 last_parms unless it should be ignored by means of
6724 Vtooltip_reuse_hidden_frame_parameters. This may destruct
6725 last_parms which, however, will be recreated below. */
6726 for (tail = parms; CONSP (tail); tail = XCDR (tail))
6728 elt = XCAR (tail);
6729 parm = Fcar (elt);
6730 /* The left, top, right and bottom parameters are handled
6731 by compute_tip_xy so they can be ignored here. */
6732 if (!EQ (parm, Qleft) && !EQ (parm, Qtop)
6733 && !EQ (parm, Qright) && !EQ (parm, Qbottom))
6735 last = Fassq (parm, last_parms);
6736 if (NILP (Fequal (Fcdr (elt), Fcdr (last))))
6738 /* We lost, delete the old tooltip. */
6739 delete = true;
6740 break;
6742 else
6743 last_parms = call2 (Qassq_delete_all, parm, last_parms);
6745 else
6746 last_parms = call2 (Qassq_delete_all, parm, last_parms);
6749 /* Now check if every parameter in what is left of last_parms
6750 with a non-nil value has an association in PARMS unless it
6751 should be ignored by means of
6752 Vtooltip_reuse_hidden_frame_parameters. */
6753 for (tail = last_parms; CONSP (tail); tail = XCDR (tail))
6755 elt = XCAR (tail);
6756 parm = Fcar (elt);
6757 if (!EQ (parm, Qleft) && !EQ (parm, Qtop) && !EQ (parm, Qright)
6758 && !EQ (parm, Qbottom) && !NILP (Fcdr (elt)))
6760 /* We lost, delete the old tooltip. */
6761 delete = true;
6762 break;
6766 x_hide_tip (delete);
6768 else
6769 x_hide_tip (true);
6771 else
6772 x_hide_tip (true);
6774 ASET (last_show_tip_args, 0, string);
6775 ASET (last_show_tip_args, 1, frame);
6776 ASET (last_show_tip_args, 2, parms);
6778 if (!FRAMEP (tip_frame) || !FRAME_LIVE_P (XFRAME (tip_frame)))
6780 /* Add default values to frame parameters. */
6781 if (NILP (Fassq (Qname, parms)))
6782 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
6783 if (NILP (Fassq (Qinternal_border_width, parms)))
6784 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
6785 if (NILP (Fassq (Qborder_width, parms)))
6786 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
6787 if (NILP (Fassq (Qborder_color, parms)))
6788 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
6789 if (NILP (Fassq (Qbackground_color, parms)))
6790 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
6791 parms);
6793 /* Create a frame for the tooltip, and record it in the global
6794 variable tip_frame. */
6795 if (NILP (tip_frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parms)))
6796 /* Creating the tip frame failed. */
6797 return unbind_to (count, Qnil);
6800 tip_f = XFRAME (tip_frame);
6801 window = FRAME_ROOT_WINDOW (tip_f);
6802 tip_buf = Fget_buffer_create (tip);
6803 /* We will mark the tip window a "pseudo-window" below, and such
6804 windows cannot have display margins. */
6805 bset_left_margin_cols (XBUFFER (tip_buf), make_number (0));
6806 bset_right_margin_cols (XBUFFER (tip_buf), make_number (0));
6807 set_window_buffer (window, tip_buf, false, false);
6808 w = XWINDOW (window);
6809 w->pseudo_window_p = true;
6811 /* Set up the frame's root window. Note: The following code does not
6812 try to size the window or its frame correctly. Its only purpose is
6813 to make the subsequent text size calculations work. The right
6814 sizes should get installed when the toolkit gets back to us. */
6815 w->left_col = 0;
6816 w->top_line = 0;
6817 w->pixel_left = 0;
6818 w->pixel_top = 0;
6820 if (CONSP (Vx_max_tooltip_size)
6821 && RANGED_INTEGERP (1, XCAR (Vx_max_tooltip_size), INT_MAX)
6822 && RANGED_INTEGERP (1, XCDR (Vx_max_tooltip_size), INT_MAX))
6824 w->total_cols = XFASTINT (XCAR (Vx_max_tooltip_size));
6825 w->total_lines = XFASTINT (XCDR (Vx_max_tooltip_size));
6827 else
6829 w->total_cols = 80;
6830 w->total_lines = 40;
6833 w->pixel_width = w->total_cols * FRAME_COLUMN_WIDTH (tip_f);
6834 w->pixel_height = w->total_lines * FRAME_LINE_HEIGHT (tip_f);
6835 FRAME_TOTAL_COLS (tip_f) = w->total_cols;
6836 adjust_frame_glyphs (tip_f);
6838 /* Insert STRING into root window's buffer and fit the frame to the
6839 buffer. */
6840 count_1 = SPECPDL_INDEX ();
6841 old_buffer = current_buffer;
6842 set_buffer_internal_1 (XBUFFER (w->contents));
6843 bset_truncate_lines (current_buffer, Qnil);
6844 specbind (Qinhibit_read_only, Qt);
6845 specbind (Qinhibit_modification_hooks, Qt);
6846 specbind (Qinhibit_point_motion_hooks, Qt);
6847 Ferase_buffer ();
6848 Finsert (1, &string);
6849 clear_glyph_matrix (w->desired_matrix);
6850 clear_glyph_matrix (w->current_matrix);
6851 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
6852 try_window (window, pos, TRY_WINDOW_IGNORE_FONTS_CHANGE);
6853 /* Calculate size of tooltip window. */
6854 size = Fwindow_text_pixel_size (window, Qnil, Qnil, Qnil,
6855 make_number (w->pixel_height), Qnil);
6856 /* Add the frame's internal border to calculated size. */
6857 width = XINT (Fcar (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
6858 height = XINT (Fcdr (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
6860 /* Calculate position of tooltip frame. */
6861 compute_tip_xy (tip_f, parms, dx, dy, width, height, &root_x, &root_y);
6863 /* Show tooltip frame. */
6864 block_input ();
6865 XMoveResizeWindow (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f),
6866 root_x, root_y, width, height);
6867 XMapRaised (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f));
6868 unblock_input ();
6870 w->must_be_updated_p = true;
6871 update_single_window (w);
6872 set_buffer_internal_1 (old_buffer);
6873 unbind_to (count_1, Qnil);
6874 windows_or_buffers_changed = old_windows_or_buffers_changed;
6876 start_timer:
6877 /* Let the tip disappear after timeout seconds. */
6878 tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
6879 intern ("x-hide-tip"));
6881 return unbind_to (count, Qnil);
6885 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
6886 doc: /* Hide the current tooltip window, if there is any.
6887 Value is t if tooltip was open, nil otherwise. */)
6888 (void)
6890 return x_hide_tip (!tooltip_reuse_hidden_frame);
6893 DEFUN ("x-double-buffered-p", Fx_double_buffered_p, Sx_double_buffered_p,
6894 0, 1, 0,
6895 doc: /* Return t if FRAME is being double buffered. */)
6896 (Lisp_Object frame)
6898 struct frame *f = decode_live_frame (frame);
6899 return FRAME_X_DOUBLE_BUFFERED_P (f) ? Qt : Qnil;
6903 /***********************************************************************
6904 File selection dialog
6905 ***********************************************************************/
6907 DEFUN ("x-uses-old-gtk-dialog", Fx_uses_old_gtk_dialog,
6908 Sx_uses_old_gtk_dialog,
6909 0, 0, 0,
6910 doc: /* Return t if the old Gtk+ file selection dialog is used. */)
6911 (void)
6913 #ifdef USE_GTK
6914 if (use_dialog_box
6915 && use_file_dialog
6916 && window_system_available (SELECTED_FRAME ())
6917 && xg_uses_old_file_dialog ())
6918 return Qt;
6919 #endif
6920 return Qnil;
6924 #ifdef USE_MOTIF
6925 /* Callback for "OK" and "Cancel" on file selection dialog. */
6927 static void
6928 file_dialog_cb (Widget widget, XtPointer client_data, XtPointer call_data)
6930 int *result = client_data;
6931 XmAnyCallbackStruct *cb = call_data;
6932 *result = cb->reason;
6936 /* Callback for unmapping a file selection dialog. This is used to
6937 capture the case where a dialog is closed via a window manager's
6938 closer button, for example. Using a XmNdestroyCallback didn't work
6939 in this case. */
6941 static void
6942 file_dialog_unmap_cb (Widget widget, XtPointer client_data, XtPointer call_data)
6944 int *result = client_data;
6945 *result = XmCR_CANCEL;
6948 static void
6949 clean_up_file_dialog (void *arg)
6951 Widget dialog = arg;
6953 /* Clean up. */
6954 block_input ();
6955 XtUnmanageChild (dialog);
6956 XtDestroyWidget (dialog);
6957 x_menu_set_in_use (false);
6958 unblock_input ();
6962 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
6963 doc: /* Read file name, prompting with PROMPT in directory DIR.
6964 Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file
6965 selection box, if specified. If MUSTMATCH is non-nil, the returned file
6966 or directory must exist.
6968 This function is only defined on NS, MS Windows, and X Windows with the
6969 Motif or Gtk toolkits. With the Motif toolkit, ONLY-DIR-P is ignored.
6970 Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories.
6971 On Windows 7 and later, the file selection dialog "remembers" the last
6972 directory where the user selected a file, and will open that directory
6973 instead of DIR on subsequent invocations of this function with the same
6974 value of DIR as in previous invocations; this is standard Windows behavior. */)
6975 (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename,
6976 Lisp_Object mustmatch, Lisp_Object only_dir_p)
6978 int result;
6979 struct frame *f = SELECTED_FRAME ();
6980 Lisp_Object file = Qnil;
6981 Lisp_Object decoded_file;
6982 Widget dialog, text, help;
6983 Arg al[10];
6984 int ac = 0;
6985 XmString dir_xmstring, pattern_xmstring;
6986 ptrdiff_t count = SPECPDL_INDEX ();
6988 check_window_system (f);
6990 if (popup_activated ())
6991 error ("Trying to use a menu from within a menu-entry");
6993 CHECK_STRING (prompt);
6994 CHECK_STRING (dir);
6996 /* Prevent redisplay. */
6997 specbind (Qinhibit_redisplay, Qt);
6999 block_input ();
7001 /* Create the dialog with PROMPT as title, using DIR as initial
7002 directory and using "*" as pattern. */
7003 dir = Fexpand_file_name (dir, Qnil);
7004 dir_xmstring = XmStringCreateLocalized (SSDATA (dir));
7005 pattern_xmstring = XmStringCreateLocalized ("*");
7007 XtSetArg (al[ac], XmNtitle, SDATA (prompt)); ++ac;
7008 XtSetArg (al[ac], XmNdirectory, dir_xmstring); ++ac;
7009 XtSetArg (al[ac], XmNpattern, pattern_xmstring); ++ac;
7010 XtSetArg (al[ac], XmNresizePolicy, XmRESIZE_GROW); ++ac;
7011 XtSetArg (al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ++ac;
7012 dialog = XmCreateFileSelectionDialog (f->output_data.x->widget,
7013 "fsb", al, ac);
7014 XmStringFree (dir_xmstring);
7015 XmStringFree (pattern_xmstring);
7017 /* Add callbacks for OK and Cancel. */
7018 XtAddCallback (dialog, XmNokCallback, file_dialog_cb,
7019 (XtPointer) &result);
7020 XtAddCallback (dialog, XmNcancelCallback, file_dialog_cb,
7021 (XtPointer) &result);
7022 XtAddCallback (dialog, XmNunmapCallback, file_dialog_unmap_cb,
7023 (XtPointer) &result);
7025 /* Remove the help button since we can't display help. */
7026 help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON);
7027 XtUnmanageChild (help);
7029 /* Mark OK button as default. */
7030 XtVaSetValues (XmFileSelectionBoxGetChild (dialog, XmDIALOG_OK_BUTTON),
7031 XmNshowAsDefault, True, NULL);
7033 /* If MUSTMATCH is non-nil, disable the file entry field of the
7034 dialog, so that the user must select a file from the files list
7035 box. We can't remove it because we wouldn't have a way to get at
7036 the result file name, then. */
7037 text = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
7038 if (!NILP (mustmatch))
7040 Widget label;
7041 label = XmFileSelectionBoxGetChild (dialog, XmDIALOG_SELECTION_LABEL);
7042 XtSetSensitive (text, False);
7043 XtSetSensitive (label, False);
7046 /* Manage the dialog, so that list boxes get filled. */
7047 XtManageChild (dialog);
7049 if (STRINGP (default_filename))
7051 XmString default_xmstring;
7052 Widget wtext = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
7053 Widget list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
7055 XmTextPosition last_pos = XmTextFieldGetLastPosition (wtext);
7056 XmTextFieldReplace (wtext, 0, last_pos,
7057 (SSDATA (Ffile_name_nondirectory (default_filename))));
7059 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
7060 must include the path for this to work. */
7062 default_xmstring = XmStringCreateLocalized (SSDATA (default_filename));
7064 if (XmListItemExists (list, default_xmstring))
7066 int item_pos = XmListItemPos (list, default_xmstring);
7067 /* Select the item and scroll it into view. */
7068 XmListSelectPos (list, item_pos, True);
7069 XmListSetPos (list, item_pos);
7072 XmStringFree (default_xmstring);
7075 record_unwind_protect_ptr (clean_up_file_dialog, dialog);
7077 /* Process events until the user presses Cancel or OK. */
7078 x_menu_set_in_use (true);
7079 result = 0;
7080 while (result == 0)
7082 XEvent event;
7083 x_menu_wait_for_event (0);
7084 XtAppNextEvent (Xt_app_con, &event);
7085 if (event.type == KeyPress
7086 && FRAME_X_DISPLAY (f) == event.xkey.display)
7088 KeySym keysym = XLookupKeysym (&event.xkey, 0);
7090 /* Pop down on C-g. */
7091 if (keysym == XK_g && (event.xkey.state & ControlMask) != 0)
7092 XtUnmanageChild (dialog);
7095 (void) x_dispatch_event (&event, FRAME_X_DISPLAY (f));
7098 /* Get the result. */
7099 if (result == XmCR_OK)
7101 XmString text_string;
7102 String data;
7104 XtVaGetValues (dialog, XmNtextString, &text_string, NULL);
7105 XmStringGetLtoR (text_string, XmFONTLIST_DEFAULT_TAG, &data);
7106 XmStringFree (text_string);
7107 file = build_string (data);
7108 XtFree (data);
7110 else
7111 file = Qnil;
7113 unblock_input ();
7115 /* Make "Cancel" equivalent to C-g. */
7116 if (NILP (file))
7117 quit ();
7119 decoded_file = DECODE_FILE (file);
7121 return unbind_to (count, decoded_file);
7124 #endif /* USE_MOTIF */
7126 #ifdef USE_GTK
7128 static void
7129 clean_up_dialog (void)
7131 x_menu_set_in_use (false);
7134 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
7135 doc: /* Read file name, prompting with PROMPT in directory DIR.
7136 Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file
7137 selection box, if specified. If MUSTMATCH is non-nil, the returned file
7138 or directory must exist.
7140 This function is only defined on NS, MS Windows, and X Windows with the
7141 Motif or Gtk toolkits. With the Motif toolkit, ONLY-DIR-P is ignored.
7142 Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories.
7143 On Windows 7 and later, the file selection dialog "remembers" the last
7144 directory where the user selected a file, and will open that directory
7145 instead of DIR on subsequent invocations of this function with the same
7146 value of DIR as in previous invocations; this is standard Windows behavior. */)
7147 (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename, Lisp_Object mustmatch, Lisp_Object only_dir_p)
7149 struct frame *f = SELECTED_FRAME ();
7150 char *fn;
7151 Lisp_Object file = Qnil;
7152 Lisp_Object decoded_file;
7153 ptrdiff_t count = SPECPDL_INDEX ();
7154 char *cdef_file;
7156 check_window_system (f);
7158 if (popup_activated ())
7159 error ("Trying to use a menu from within a menu-entry");
7160 else
7161 x_menu_set_in_use (true);
7163 CHECK_STRING (prompt);
7164 CHECK_STRING (dir);
7166 /* Prevent redisplay. */
7167 specbind (Qinhibit_redisplay, Qt);
7168 record_unwind_protect_void (clean_up_dialog);
7170 block_input ();
7172 if (STRINGP (default_filename))
7173 cdef_file = SSDATA (default_filename);
7174 else
7175 cdef_file = SSDATA (dir);
7177 fn = xg_get_file_name (f, SSDATA (prompt), cdef_file,
7178 ! NILP (mustmatch),
7179 ! NILP (only_dir_p));
7181 if (fn)
7183 file = build_string (fn);
7184 xfree (fn);
7187 unblock_input ();
7189 /* Make "Cancel" equivalent to C-g. */
7190 if (NILP (file))
7191 quit ();
7193 decoded_file = DECODE_FILE (file);
7195 return unbind_to (count, decoded_file);
7199 #ifdef HAVE_FREETYPE
7201 DEFUN ("x-select-font", Fx_select_font, Sx_select_font, 0, 2, 0,
7202 doc: /* Read a font using a GTK dialog.
7203 Return either a font spec (for GTK versions >= 3.2) or a string
7204 containing a GTK-style font name.
7206 FRAME is the frame on which to pop up the font chooser. If omitted or
7207 nil, it defaults to the selected frame. */)
7208 (Lisp_Object frame, Lisp_Object ignored)
7210 struct frame *f = decode_window_system_frame (frame);
7211 Lisp_Object font;
7212 Lisp_Object font_param;
7213 char *default_name = NULL;
7214 ptrdiff_t count = SPECPDL_INDEX ();
7216 if (popup_activated ())
7217 error ("Trying to use a menu from within a menu-entry");
7218 else
7219 x_menu_set_in_use (true);
7221 /* Prevent redisplay. */
7222 specbind (Qinhibit_redisplay, Qt);
7223 record_unwind_protect_void (clean_up_dialog);
7225 block_input ();
7227 XSETFONT (font, FRAME_FONT (f));
7228 font_param = Ffont_get (font, QCname);
7229 if (STRINGP (font_param))
7230 default_name = xlispstrdup (font_param);
7231 else
7233 font_param = Fframe_parameter (frame, Qfont_parameter);
7234 if (STRINGP (font_param))
7235 default_name = xlispstrdup (font_param);
7238 font = xg_get_font (f, default_name);
7239 xfree (default_name);
7241 unblock_input ();
7243 if (NILP (font))
7244 quit ();
7246 return unbind_to (count, font);
7248 #endif /* HAVE_FREETYPE */
7250 #endif /* USE_GTK */
7253 /***********************************************************************
7254 Keyboard
7255 ***********************************************************************/
7257 #ifdef HAVE_XKB
7258 #include <X11/XKBlib.h>
7259 #include <X11/keysym.h>
7260 #endif
7262 DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p,
7263 Sx_backspace_delete_keys_p, 0, 1, 0,
7264 doc: /* Check if both Backspace and Delete keys are on the keyboard of FRAME.
7265 FRAME nil means use the selected frame.
7266 Value is t if we know that both keys are present, and are mapped to the
7267 usual X keysyms. Value is `lambda' if we cannot determine if both keys are
7268 present and mapped to the usual X keysyms. */)
7269 (Lisp_Object frame)
7271 #ifndef HAVE_XKB
7272 return Qlambda;
7273 #else
7274 XkbDescPtr kb;
7275 struct frame *f = decode_window_system_frame (frame);
7276 Display *dpy = FRAME_X_DISPLAY (f);
7277 Lisp_Object have_keys;
7278 int major, minor, op, event, error_code;
7280 block_input ();
7282 /* Check library version in case we're dynamically linked. */
7283 major = XkbMajorVersion;
7284 minor = XkbMinorVersion;
7285 if (!XkbLibraryVersion (&major, &minor))
7287 unblock_input ();
7288 return Qlambda;
7291 /* Check that the server supports XKB. */
7292 major = XkbMajorVersion;
7293 minor = XkbMinorVersion;
7294 if (!XkbQueryExtension (dpy, &op, &event, &error_code, &major, &minor))
7296 unblock_input ();
7297 return Qlambda;
7300 /* In this code we check that the keyboard has physical keys with names
7301 that start with BKSP (Backspace) and DELE (Delete), and that they
7302 generate keysym XK_BackSpace and XK_Delete respectively.
7303 This function is used to test if normal-erase-is-backspace should be
7304 turned on.
7305 An alternative approach would be to just check if XK_BackSpace and
7306 XK_Delete are mapped to any key. But if any of those are mapped to
7307 some non-intuitive key combination (Meta-Shift-Ctrl-whatever) and the
7308 user doesn't know about it, it is better to return false here.
7309 It is more obvious to the user what to do if she/he has two keys
7310 clearly marked with names/symbols and one key does something not
7311 expected (i.e. she/he then tries the other).
7312 The cases where Backspace/Delete is mapped to some other key combination
7313 are rare, and in those cases, normal-erase-is-backspace can be turned on
7314 manually. */
7316 have_keys = Qnil;
7317 kb = XkbGetMap (dpy, XkbAllMapComponentsMask, XkbUseCoreKbd);
7318 if (kb)
7320 int delete_keycode = 0, backspace_keycode = 0, i;
7322 if (XkbGetNames (dpy, XkbAllNamesMask, kb) == Success)
7324 for (i = kb->min_key_code;
7325 (i < kb->max_key_code
7326 && (delete_keycode == 0 || backspace_keycode == 0));
7327 ++i)
7329 /* The XKB symbolic key names can be seen most easily in
7330 the PS file generated by `xkbprint -label name
7331 $DISPLAY'. */
7332 if (memcmp ("DELE", kb->names->keys[i].name, 4) == 0)
7333 delete_keycode = i;
7334 else if (memcmp ("BKSP", kb->names->keys[i].name, 4) == 0)
7335 backspace_keycode = i;
7338 XkbFreeNames (kb, 0, True);
7341 /* As of libX11-1.6.2, XkbGetMap manual says that you should use
7342 XkbFreeClientMap to free the data returned by XkbGetMap. But
7343 this function just frees the data referenced from KB and not
7344 KB itself. To free KB as well, call XkbFreeKeyboard. */
7345 XkbFreeKeyboard (kb, XkbAllMapComponentsMask, True);
7347 if (delete_keycode
7348 && backspace_keycode
7349 && XKeysymToKeycode (dpy, XK_Delete) == delete_keycode
7350 && XKeysymToKeycode (dpy, XK_BackSpace) == backspace_keycode)
7351 have_keys = Qt;
7353 unblock_input ();
7354 return have_keys;
7355 #endif
7360 /***********************************************************************
7361 Printing
7362 ***********************************************************************/
7364 #ifdef USE_CAIRO
7365 DEFUN ("x-export-frames", Fx_export_frames, Sx_export_frames, 0, 2, 0,
7366 doc: /* Return image data of FRAMES in TYPE format.
7367 FRAMES should be nil (the selected frame), a frame, or a list of
7368 frames (each of which corresponds to one page). Each frame should be
7369 visible. Optional arg TYPE should be either `pdf' (default), `png',
7370 `postscript', or `svg'. Supported types are determined by the
7371 compile-time configuration of cairo. */)
7372 (Lisp_Object frames, Lisp_Object type)
7374 Lisp_Object rest, tmp;
7375 cairo_surface_type_t surface_type;
7377 if (!CONSP (frames))
7378 frames = list1 (frames);
7380 tmp = Qnil;
7381 for (rest = frames; CONSP (rest); rest = XCDR (rest))
7383 struct frame *f = decode_window_system_frame (XCAR (rest));
7384 Lisp_Object frame;
7386 XSETFRAME (frame, f);
7387 if (!FRAME_VISIBLE_P (f))
7388 error ("Frames to be exported must be visible.");
7389 tmp = Fcons (frame, tmp);
7391 frames = Fnreverse (tmp);
7393 #ifdef CAIRO_HAS_PDF_SURFACE
7394 if (NILP (type) || EQ (type, Qpdf))
7395 surface_type = CAIRO_SURFACE_TYPE_PDF;
7396 else
7397 #endif
7398 #ifdef CAIRO_HAS_PNG_FUNCTIONS
7399 if (EQ (type, Qpng))
7401 if (!NILP (XCDR (frames)))
7402 error ("PNG export cannot handle multiple frames.");
7403 surface_type = CAIRO_SURFACE_TYPE_IMAGE;
7405 else
7406 #endif
7407 #ifdef CAIRO_HAS_PS_SURFACE
7408 if (EQ (type, Qpostscript))
7409 surface_type = CAIRO_SURFACE_TYPE_PS;
7410 else
7411 #endif
7412 #ifdef CAIRO_HAS_SVG_SURFACE
7413 if (EQ (type, Qsvg))
7415 /* For now, we stick to SVG 1.1. */
7416 if (!NILP (XCDR (frames)))
7417 error ("SVG export cannot handle multiple frames.");
7418 surface_type = CAIRO_SURFACE_TYPE_SVG;
7420 else
7421 #endif
7422 error ("Unsupported export type");
7424 return x_cr_export_frames (frames, surface_type);
7427 #ifdef USE_GTK
7428 DEFUN ("x-page-setup-dialog", Fx_page_setup_dialog, Sx_page_setup_dialog, 0, 0, 0,
7429 doc: /* Pop up a page setup dialog.
7430 The current page setup can be obtained using `x-get-page-setup'. */)
7431 (void)
7433 block_input ();
7434 xg_page_setup_dialog ();
7435 unblock_input ();
7437 return Qnil;
7440 DEFUN ("x-get-page-setup", Fx_get_page_setup, Sx_get_page_setup, 0, 0, 0,
7441 doc: /* Return the value of the current page setup.
7442 The return value is an alist containing the following keys:
7444 orientation: page orientation (symbol `portrait', `landscape',
7445 `reverse-portrait', or `reverse-landscape').
7446 width, height: page width/height in points not including margins.
7447 left-margin, right-margin, top-margin, bottom-margin: print margins,
7448 which is the parts of the page that the printer cannot print
7449 on, in points.
7451 The paper width can be obtained as the sum of width, left-margin, and
7452 right-margin values if the page orientation is `portrait' or
7453 `reverse-portrait'. Otherwise, it is the sum of width, top-margin,
7454 and bottom-margin values. Likewise, the paper height is the sum of
7455 height, top-margin, and bottom-margin values if the page orientation
7456 is `portrait' or `reverse-portrait'. Otherwise, it is the sum of
7457 height, left-margin, and right-margin values. */)
7458 (void)
7460 Lisp_Object result;
7462 block_input ();
7463 result = xg_get_page_setup ();
7464 unblock_input ();
7466 return result;
7469 DEFUN ("x-print-frames-dialog", Fx_print_frames_dialog, Sx_print_frames_dialog, 0, 1, "",
7470 doc: /* Pop up a print dialog to print the current contents of FRAMES.
7471 FRAMES should be nil (the selected frame), a frame, or a list of
7472 frames (each of which corresponds to one page). Each frame should be
7473 visible. */)
7474 (Lisp_Object frames)
7476 Lisp_Object rest, tmp;
7477 int count;
7479 if (!CONSP (frames))
7480 frames = list1 (frames);
7482 tmp = Qnil;
7483 for (rest = frames; CONSP (rest); rest = XCDR (rest))
7485 struct frame *f = decode_window_system_frame (XCAR (rest));
7486 Lisp_Object frame;
7488 XSETFRAME (frame, f);
7489 if (!FRAME_VISIBLE_P (f))
7490 error ("Frames to be printed must be visible.");
7491 tmp = Fcons (frame, tmp);
7493 frames = Fnreverse (tmp);
7495 /* Make sure the current matrices are up-to-date. */
7496 count = SPECPDL_INDEX ();
7497 specbind (Qredisplay_dont_pause, Qt);
7498 redisplay_preserve_echo_area (32);
7499 unbind_to (count, Qnil);
7501 block_input ();
7502 xg_print_frames_dialog (frames);
7503 unblock_input ();
7505 return Qnil;
7507 #endif /* USE_GTK */
7508 #endif /* USE_CAIRO */
7511 /***********************************************************************
7512 Initialization
7513 ***********************************************************************/
7515 /* Keep this list in the same order as frame_parms in frame.c.
7516 Use 0 for unsupported frame parameters. */
7518 frame_parm_handler x_frame_parm_handlers[] =
7520 x_set_autoraise,
7521 x_set_autolower,
7522 x_set_background_color,
7523 x_set_border_color,
7524 x_set_border_width,
7525 x_set_cursor_color,
7526 x_set_cursor_type,
7527 x_set_font,
7528 x_set_foreground_color,
7529 x_set_icon_name,
7530 x_set_icon_type,
7531 x_set_internal_border_width,
7532 x_set_right_divider_width,
7533 x_set_bottom_divider_width,
7534 x_set_menu_bar_lines,
7535 x_set_mouse_color,
7536 x_explicitly_set_name,
7537 x_set_scroll_bar_width,
7538 x_set_scroll_bar_height,
7539 x_set_title,
7540 x_set_unsplittable,
7541 x_set_vertical_scroll_bars,
7542 x_set_horizontal_scroll_bars,
7543 x_set_visibility,
7544 x_set_tool_bar_lines,
7545 x_set_scroll_bar_foreground,
7546 x_set_scroll_bar_background,
7547 x_set_screen_gamma,
7548 x_set_line_spacing,
7549 x_set_left_fringe,
7550 x_set_right_fringe,
7551 x_set_wait_for_wm,
7552 x_set_fullscreen,
7553 x_set_font_backend,
7554 x_set_alpha,
7555 x_set_sticky,
7556 x_set_tool_bar_position,
7557 x_set_inhibit_double_buffering,
7558 x_set_undecorated,
7559 x_set_parent_frame,
7560 x_set_skip_taskbar,
7561 x_set_no_focus_on_map,
7562 x_set_no_accept_focus,
7563 x_set_z_group,
7564 x_set_override_redirect,
7565 x_set_no_special_glyphs,
7568 void
7569 syms_of_xfns (void)
7571 DEFSYM (Qundefined_color, "undefined-color");
7572 DEFSYM (Qcompound_text, "compound-text");
7573 DEFSYM (Qcancel_timer, "cancel-timer");
7574 DEFSYM (Qfont_parameter, "font-parameter");
7575 DEFSYM (Qmono, "mono");
7576 DEFSYM (Qassq_delete_all, "assq-delete-all");
7578 #ifdef USE_CAIRO
7579 DEFSYM (Qpdf, "pdf");
7581 DEFSYM (Qorientation, "orientation");
7582 DEFSYM (Qtop_margin, "top-margin");
7583 DEFSYM (Qbottom_margin, "bottom-margin");
7584 DEFSYM (Qportrait, "portrait");
7585 DEFSYM (Qlandscape, "landscape");
7586 DEFSYM (Qreverse_portrait, "reverse-portrait");
7587 DEFSYM (Qreverse_landscape, "reverse-landscape");
7588 #endif
7590 Fput (Qundefined_color, Qerror_conditions,
7591 listn (CONSTYPE_PURE, 2, Qundefined_color, Qerror));
7592 Fput (Qundefined_color, Qerror_message,
7593 build_pure_c_string ("Undefined color"));
7595 DEFVAR_LISP ("x-pointer-shape", Vx_pointer_shape,
7596 doc: /* The shape of the pointer when over text.
7597 Changing the value does not affect existing frames
7598 unless you set the mouse color. */);
7599 Vx_pointer_shape = Qnil;
7601 #if false /* This doesn't really do anything. */
7602 DEFVAR_LISP ("x-nontext-pointer-shape", Vx_nontext_pointer_shape,
7603 doc: /* The shape of the pointer when not over text.
7604 This variable takes effect when you create a new frame
7605 or when you set the mouse color. */);
7606 #endif
7607 Vx_nontext_pointer_shape = Qnil;
7609 DEFVAR_LISP ("x-hourglass-pointer-shape", Vx_hourglass_pointer_shape,
7610 doc: /* The shape of the pointer when Emacs is busy.
7611 This variable takes effect when you create a new frame
7612 or when you set the mouse color. */);
7613 Vx_hourglass_pointer_shape = Qnil;
7615 #if false /* This doesn't really do anything. */
7616 DEFVAR_LISP ("x-mode-pointer-shape", Vx_mode_pointer_shape,
7617 doc: /* The shape of the pointer when over the mode line.
7618 This variable takes effect when you create a new frame
7619 or when you set the mouse color. */);
7620 #endif
7621 Vx_mode_pointer_shape = Qnil;
7623 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
7624 Vx_sensitive_text_pointer_shape,
7625 doc: /* The shape of the pointer when over mouse-sensitive text.
7626 This variable takes effect when you create a new frame
7627 or when you set the mouse color. */);
7628 Vx_sensitive_text_pointer_shape = Qnil;
7630 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
7631 Vx_window_horizontal_drag_shape,
7632 doc: /* Pointer shape to use for indicating a window can be dragged horizontally.
7633 This variable takes effect when you create a new frame
7634 or when you set the mouse color. */);
7635 Vx_window_horizontal_drag_shape = Qnil;
7637 DEFVAR_LISP ("x-window-vertical-drag-cursor",
7638 Vx_window_vertical_drag_shape,
7639 doc: /* Pointer shape to use for indicating a window can be dragged vertically.
7640 This variable takes effect when you create a new frame
7641 or when you set the mouse color. */);
7642 Vx_window_vertical_drag_shape = Qnil;
7644 DEFVAR_LISP ("x-window-left-edge-cursor",
7645 Vx_window_left_edge_shape,
7646 doc: /* Pointer shape indicating a left x-window edge can be dragged.
7647 This variable takes effect when you create a new frame
7648 or when you set the mouse color. */);
7649 Vx_window_left_edge_shape = Qnil;
7651 DEFVAR_LISP ("x-window-top-left-corner-cursor",
7652 Vx_window_top_left_corner_shape,
7653 doc: /* Pointer shape indicating a top left x-window corner can be dragged.
7654 This variable takes effect when you create a new frame
7655 or when you set the mouse color. */);
7656 Vx_window_top_left_corner_shape = Qnil;
7658 DEFVAR_LISP ("x-window-top-edge-cursor",
7659 Vx_window_top_edge_shape,
7660 doc: /* Pointer shape indicating a top x-window edge can be dragged.
7661 This variable takes effect when you create a new frame
7662 or when you set the mouse color. */);
7663 Vx_window_top_edge_shape = Qnil;
7665 DEFVAR_LISP ("x-window-top-right-corner-cursor",
7666 Vx_window_top_right_corner_shape,
7667 doc: /* Pointer shape indicating a top right x-window corner can be dragged.
7668 This variable takes effect when you create a new frame
7669 or when you set the mouse color. */);
7670 Vx_window_top_right_corner_shape = Qnil;
7672 DEFVAR_LISP ("x-window-right-edge-cursor",
7673 Vx_window_right_edge_shape,
7674 doc: /* Pointer shape indicating a right x-window edge can be dragged.
7675 This variable takes effect when you create a new frame
7676 or when you set the mouse color. */);
7677 Vx_window_right_edge_shape = Qnil;
7679 DEFVAR_LISP ("x-window-bottom-right-corner-cursor",
7680 Vx_window_bottom_right_corner_shape,
7681 doc: /* Pointer shape indicating a bottom right x-window corner can be dragged.
7682 This variable takes effect when you create a new frame
7683 or when you set the mouse color. */);
7684 Vx_window_bottom_right_corner_shape = Qnil;
7686 DEFVAR_LISP ("x-window-bottom-edge-cursor",
7687 Vx_window_bottom_edge_shape,
7688 doc: /* Pointer shape indicating a bottom x-window edge can be dragged.
7689 This variable takes effect when you create a new frame
7690 or when you set the mouse color. */);
7691 Vx_window_bottom_edge_shape = Qnil;
7693 DEFVAR_LISP ("x-window-bottom-left-corner-cursor",
7694 Vx_window_bottom_left_corner_shape,
7695 doc: /* Pointer shape indicating a bottom left x-window corner can be dragged.
7696 This variable takes effect when you create a new frame
7697 or when you set the mouse color. */);
7698 Vx_window_bottom_left_corner_shape = Qnil;
7700 DEFVAR_LISP ("x-cursor-fore-pixel", Vx_cursor_fore_pixel,
7701 doc: /* A string indicating the foreground color of the cursor box. */);
7702 Vx_cursor_fore_pixel = Qnil;
7704 DEFVAR_LISP ("x-max-tooltip-size", Vx_max_tooltip_size,
7705 doc: /* Maximum size for tooltips.
7706 Value is a pair (COLUMNS . ROWS). Text larger than this is clipped. */);
7707 Vx_max_tooltip_size = Fcons (make_number (80), make_number (40));
7709 DEFVAR_LISP ("x-no-window-manager", Vx_no_window_manager,
7710 doc: /* Non-nil if no X window manager is in use.
7711 Emacs doesn't try to figure this out; this is always nil
7712 unless you set it to something else. */);
7713 /* We don't have any way to find this out, so set it to nil
7714 and maybe the user would like to set it to t. */
7715 Vx_no_window_manager = Qnil;
7717 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
7718 Vx_pixel_size_width_font_regexp,
7719 doc: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
7721 Since Emacs gets width of a font matching with this regexp from
7722 PIXEL_SIZE field of the name, font finding mechanism gets faster for
7723 such a font. This is especially effective for such large fonts as
7724 Chinese, Japanese, and Korean. */);
7725 Vx_pixel_size_width_font_regexp = Qnil;
7727 /* This is not ifdef:ed, so other builds than GTK can customize it. */
7728 DEFVAR_BOOL ("x-gtk-use-old-file-dialog", x_gtk_use_old_file_dialog,
7729 doc: /* Non-nil means prompt with the old GTK file selection dialog.
7730 If nil or if the file selection dialog is not available, the new GTK file
7731 chooser is used instead. To turn off all file dialogs set the
7732 variable `use-file-dialog'. */);
7733 x_gtk_use_old_file_dialog = false;
7735 DEFVAR_BOOL ("x-gtk-show-hidden-files", x_gtk_show_hidden_files,
7736 doc: /* If non-nil, the GTK file chooser will by default show hidden files.
7737 Note that this is just the default, there is a toggle button on the file
7738 chooser to show or not show hidden files on a case by case basis. */);
7739 x_gtk_show_hidden_files = false;
7741 DEFVAR_BOOL ("x-gtk-file-dialog-help-text", x_gtk_file_dialog_help_text,
7742 doc: /* If non-nil, the GTK file chooser will show additional help text.
7743 If more space for files in the file chooser dialog is wanted, set this to nil
7744 to turn the additional text off. */);
7745 x_gtk_file_dialog_help_text = true;
7747 DEFVAR_BOOL ("x-gtk-use-system-tooltips", x_gtk_use_system_tooltips,
7748 doc: /* If non-nil with a Gtk+ built Emacs, the Gtk+ tooltip is used.
7749 Otherwise use Emacs own tooltip implementation.
7750 When using Gtk+ tooltips, the tooltip face is not used. */);
7751 x_gtk_use_system_tooltips = true;
7753 /* Tell Emacs about this window system. */
7754 Fprovide (Qx, Qnil);
7756 #ifdef USE_X_TOOLKIT
7757 Fprovide (intern_c_string ("x-toolkit"), Qnil);
7758 #ifdef USE_MOTIF
7759 Fprovide (intern_c_string ("motif"), Qnil);
7761 DEFVAR_LISP ("motif-version-string", Vmotif_version_string,
7762 doc: /* Version info for LessTif/Motif. */);
7763 Vmotif_version_string = build_string (XmVERSION_STRING);
7764 #endif /* USE_MOTIF */
7765 #endif /* USE_X_TOOLKIT */
7767 #ifdef USE_GTK
7768 /* Provide x-toolkit also for GTK. Internally GTK does not use Xt so it
7769 is not an X toolkit in that sense (USE_X_TOOLKIT is not defined).
7770 But for a user it is a toolkit for X, and indeed, configure
7771 accepts --with-x-toolkit=gtk. */
7772 Fprovide (intern_c_string ("x-toolkit"), Qnil);
7773 Fprovide (intern_c_string ("gtk"), Qnil);
7774 Fprovide (intern_c_string ("move-toolbar"), Qnil);
7776 DEFVAR_LISP ("gtk-version-string", Vgtk_version_string,
7777 doc: /* Version info for GTK+. */);
7779 char gtk_version[sizeof ".." + 3 * INT_STRLEN_BOUND (int)];
7780 int len = sprintf (gtk_version, "%d.%d.%d",
7781 GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION);
7782 Vgtk_version_string = make_pure_string (gtk_version, len, len, false);
7784 #endif /* USE_GTK */
7786 #ifdef USE_CAIRO
7787 Fprovide (intern_c_string ("cairo"), Qnil);
7789 DEFVAR_LISP ("cairo-version-string", Vcairo_version_string,
7790 doc: /* Version info for cairo. */);
7792 char cairo_version[sizeof ".." + 3 * INT_STRLEN_BOUND (int)];
7793 int len = sprintf (cairo_version, "%d.%d.%d",
7794 CAIRO_VERSION_MAJOR, CAIRO_VERSION_MINOR,
7795 CAIRO_VERSION_MICRO);
7796 Vcairo_version_string = make_pure_string (cairo_version, len, len, false);
7798 #endif
7800 /* X window properties. */
7801 defsubr (&Sx_change_window_property);
7802 defsubr (&Sx_delete_window_property);
7803 defsubr (&Sx_window_property);
7804 defsubr (&Sx_window_property_attributes);
7806 defsubr (&Sxw_display_color_p);
7807 defsubr (&Sx_display_grayscale_p);
7808 defsubr (&Sxw_color_defined_p);
7809 defsubr (&Sxw_color_values);
7810 defsubr (&Sx_server_max_request_size);
7811 defsubr (&Sx_server_vendor);
7812 defsubr (&Sx_server_version);
7813 defsubr (&Sx_display_pixel_width);
7814 defsubr (&Sx_display_pixel_height);
7815 defsubr (&Sx_display_mm_width);
7816 defsubr (&Sx_display_mm_height);
7817 defsubr (&Sx_display_screens);
7818 defsubr (&Sx_display_planes);
7819 defsubr (&Sx_display_color_cells);
7820 defsubr (&Sx_display_visual_class);
7821 defsubr (&Sx_display_backing_store);
7822 defsubr (&Sx_display_save_under);
7823 defsubr (&Sx_display_monitor_attributes_list);
7824 defsubr (&Sx_frame_geometry);
7825 defsubr (&Sx_frame_edges);
7826 defsubr (&Sx_frame_list_z_order);
7827 defsubr (&Sx_frame_restack);
7828 defsubr (&Sx_mouse_absolute_pixel_position);
7829 defsubr (&Sx_set_mouse_absolute_pixel_position);
7830 defsubr (&Sx_wm_set_size_hint);
7831 defsubr (&Sx_create_frame);
7832 defsubr (&Sx_open_connection);
7833 defsubr (&Sx_close_connection);
7834 defsubr (&Sx_display_list);
7835 defsubr (&Sx_synchronize);
7836 defsubr (&Sx_backspace_delete_keys_p);
7838 defsubr (&Sx_show_tip);
7839 defsubr (&Sx_hide_tip);
7840 defsubr (&Sx_double_buffered_p);
7841 tip_timer = Qnil;
7842 staticpro (&tip_timer);
7843 tip_frame = Qnil;
7844 staticpro (&tip_frame);
7846 last_show_tip_args = Qnil;
7847 staticpro (&last_show_tip_args);
7849 defsubr (&Sx_uses_old_gtk_dialog);
7850 #if defined (USE_MOTIF) || defined (USE_GTK)
7851 defsubr (&Sx_file_dialog);
7852 #endif
7854 #if defined (USE_GTK) && defined (HAVE_FREETYPE)
7855 defsubr (&Sx_select_font);
7856 #endif
7858 #ifdef USE_CAIRO
7859 defsubr (&Sx_export_frames);
7860 #ifdef USE_GTK
7861 defsubr (&Sx_page_setup_dialog);
7862 defsubr (&Sx_get_page_setup);
7863 defsubr (&Sx_print_frames_dialog);
7864 #endif
7865 #endif