Add seq-set-equal-p to test for set equality
[emacs.git] / src / xfns.c
blobe463391c74a220e96c7b1f108ed8b04a8d734f2d
1 /* Functions for the X window system.
3 Copyright (C) 1989, 1992-2017 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or (at
10 your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20 #include <config.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <math.h>
24 #include <unistd.h>
26 #include "lisp.h"
27 #include "xterm.h"
28 #include "frame.h"
29 #include "window.h"
30 #include "buffer.h"
31 #include "dispextern.h"
32 #include "keyboard.h"
33 #include "blockinput.h"
34 #include "charset.h"
35 #include "coding.h"
36 #include "termhooks.h"
37 #include "font.h"
39 #include <sys/types.h>
40 #include <sys/stat.h>
42 #include "bitmaps/gray.xbm"
43 #include "xsettings.h"
45 #ifdef HAVE_XRANDR
46 #include <X11/extensions/Xrandr.h>
47 #endif
48 #ifdef HAVE_XINERAMA
49 #include <X11/extensions/Xinerama.h>
50 #endif
52 #ifdef USE_GTK
53 #include "gtkutil.h"
54 #endif
56 #ifdef HAVE_XDBE
57 #include <X11/extensions/Xdbe.h>
58 #endif
60 #ifdef USE_X_TOOLKIT
61 #include <X11/Shell.h>
63 #ifndef USE_MOTIF
64 #ifdef HAVE_XAW3D
65 #include <X11/Xaw3d/Paned.h>
66 #include <X11/Xaw3d/Label.h>
67 #else /* !HAVE_XAW3D */
68 #include <X11/Xaw/Paned.h>
69 #include <X11/Xaw/Label.h>
70 #endif /* HAVE_XAW3D */
71 #endif /* USE_MOTIF */
73 #ifdef USG
74 #undef USG /* ####KLUDGE for Solaris 2.2 and up */
75 #include <X11/Xos.h>
76 #define USG
77 #ifdef USG /* Pacify gcc -Wunused-macros. */
78 #endif
79 #else
80 #include <X11/Xos.h>
81 #endif
83 #include "widget.h"
85 #include "../lwlib/lwlib.h"
87 #ifdef USE_MOTIF
88 #include <Xm/Xm.h>
89 #include <Xm/DialogS.h>
90 #include <Xm/FileSB.h>
91 #include <Xm/List.h>
92 #include <Xm/TextF.h>
93 #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_max
1126 struct mouse_cursor_types {
1127 /* Printable name for error messages (optional). */
1128 const char *name;
1130 /* Lisp variable controlling the cursor shape. */
1131 /* FIXME: A couple of these variables are defined in the C code but
1132 are not actually accessible from Lisp. They should probably be
1133 made accessible or removed. */
1134 Lisp_Object *shape_var_ptr;
1136 /* The default shape. */
1137 int default_shape;
1140 /* This array must stay in sync with enum mouse_cursor above! */
1141 static const struct mouse_cursor_types mouse_cursor_types[] = {
1142 { "text", &Vx_pointer_shape, XC_xterm },
1143 { "nontext", &Vx_nontext_pointer_shape, XC_left_ptr },
1144 { "hourglass", &Vx_hourglass_pointer_shape, XC_watch },
1145 { "modeline", &Vx_mode_pointer_shape, XC_xterm },
1146 { NULL, &Vx_sensitive_text_pointer_shape, XC_hand2 },
1147 { NULL, &Vx_window_horizontal_drag_shape, XC_sb_h_double_arrow },
1148 { NULL, &Vx_window_vertical_drag_shape, XC_sb_v_double_arrow },
1151 struct mouse_cursor_data {
1152 /* Last index for which XCreateFontCursor has been called, and thus
1153 the last index for which x_request_serial[] is valid. */
1154 int last_cursor_create_request;
1156 /* Last index for which an X error event was received in response to
1157 attempting to create the cursor. */
1158 int error_cursor;
1160 /* Cursor numbers chosen. */
1161 unsigned int cursor_num[mouse_cursor_max];
1163 /* Allocated Cursor values, or zero for failed attempts. */
1164 Cursor cursor[mouse_cursor_max];
1166 /* X serial numbers for the first request sent by XCreateFontCursor.
1167 Note that there may be more than one request sent. */
1168 unsigned long x_request_serial[mouse_cursor_max];
1170 /* If an error has been received, a pointer to where the current
1171 error-message text is stored. */
1172 char *error_string;
1175 static void
1176 x_set_mouse_color_handler (Display *dpy, XErrorEvent *event,
1177 char *error_string, void *data)
1179 struct mouse_cursor_data *cursor_data = data;
1180 int i;
1182 cursor_data->error_cursor = -1;
1183 cursor_data->error_string = error_string;
1184 for (i = 0; i < cursor_data->last_cursor_create_request; i++)
1186 if (event->serial >= cursor_data->x_request_serial[i])
1187 cursor_data->error_cursor = i;
1189 if (cursor_data->error_cursor >= 0)
1190 /* If we failed to allocate it, don't try to free it. */
1191 cursor_data->cursor[cursor_data->error_cursor] = 0;
1194 static void
1195 x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1197 struct x_output *x = f->output_data.x;
1198 Display *dpy = FRAME_X_DISPLAY (f);
1199 struct mouse_cursor_data cursor_data = { -1, -1 };
1200 unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1201 unsigned long mask_color = FRAME_BACKGROUND_PIXEL (f);
1202 int i;
1204 /* Don't let pointers be invisible. */
1205 if (mask_color == pixel)
1207 x_free_colors (f, &pixel, 1);
1208 pixel = x_copy_color (f, FRAME_FOREGROUND_PIXEL (f));
1211 unload_color (f, x->mouse_pixel);
1212 x->mouse_pixel = pixel;
1214 for (i = 0; i < mouse_cursor_max; i++)
1216 Lisp_Object shape_var = *mouse_cursor_types[i].shape_var_ptr;
1217 if (!NILP (shape_var))
1219 CHECK_TYPE_RANGED_INTEGER (unsigned, shape_var);
1220 cursor_data.cursor_num[i] = XINT (shape_var);
1222 else
1223 cursor_data.cursor_num[i] = mouse_cursor_types[i].default_shape;
1226 block_input ();
1228 /* It's not okay to crash if the user selects a screwy cursor. */
1229 x_catch_errors_with_handler (dpy, x_set_mouse_color_handler, &cursor_data);
1231 for (i = 0; i < mouse_cursor_max; i++)
1233 cursor_data.x_request_serial[i] = XNextRequest (dpy);
1234 cursor_data.last_cursor_create_request = i;
1235 cursor_data.cursor[i] = XCreateFontCursor (dpy,
1236 cursor_data.cursor_num[i]);
1239 /* Now sync up and process all received errors from cursor
1240 creation. */
1241 if (x_had_errors_p (dpy))
1243 const char *bad_cursor_name = NULL;
1244 /* Bounded by X_ERROR_MESSAGE_SIZE in xterm.c. */
1245 size_t message_length = strlen (cursor_data.error_string);
1246 char *xmessage = alloca (1 + message_length);
1247 memcpy (xmessage, cursor_data.error_string, message_length);
1249 x_uncatch_errors ();
1251 /* Free any successfully created cursors. */
1252 for (i = 0; i < mouse_cursor_max; i++)
1253 if (cursor_data.cursor[i] != 0)
1254 XFreeCursor (dpy, cursor_data.cursor[i]);
1256 /* This should only be able to fail if the server's serial
1257 number tracking is broken. */
1258 if (cursor_data.error_cursor >= 0)
1259 bad_cursor_name = mouse_cursor_types[cursor_data.error_cursor].name;
1260 if (bad_cursor_name)
1261 error ("bad %s pointer cursor: %s", bad_cursor_name, xmessage);
1262 else
1263 error ("can't set cursor shape: %s", xmessage);
1266 x_uncatch_errors_after_check ();
1269 XColor colors[2]; /* 0=foreground, 1=background */
1271 colors[0].pixel = x->mouse_pixel;
1272 colors[1].pixel = mask_color;
1273 x_query_colors (f, colors, 2);
1275 for (i = 0; i < mouse_cursor_max; i++)
1276 XRecolorCursor (dpy, cursor_data.cursor[i], &colors[0], &colors[1]);
1279 if (FRAME_X_WINDOW (f) != 0)
1281 f->output_data.x->current_cursor = cursor_data.cursor[mouse_cursor_text];
1282 XDefineCursor (dpy, FRAME_X_WINDOW (f),
1283 f->output_data.x->current_cursor);
1286 #define INSTALL_CURSOR(FIELD, SHORT_INDEX) \
1287 eassert (x->FIELD != cursor_data.cursor[mouse_cursor_ ## SHORT_INDEX]); \
1288 if (x->FIELD != 0) \
1289 XFreeCursor (dpy, x->FIELD); \
1290 x->FIELD = cursor_data.cursor[mouse_cursor_ ## SHORT_INDEX];
1292 INSTALL_CURSOR (text_cursor, text);
1293 INSTALL_CURSOR (nontext_cursor, nontext);
1294 INSTALL_CURSOR (hourglass_cursor, hourglass);
1295 INSTALL_CURSOR (modeline_cursor, mode);
1296 INSTALL_CURSOR (hand_cursor, hand);
1297 INSTALL_CURSOR (horizontal_drag_cursor, horizontal_drag);
1298 INSTALL_CURSOR (vertical_drag_cursor, vertical_drag);
1300 #undef INSTALL_CURSOR
1302 XFlush (dpy);
1303 unblock_input ();
1305 update_face_from_frame_parameter (f, Qmouse_color, arg);
1308 static void
1309 x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1311 unsigned long fore_pixel, pixel;
1312 bool fore_pixel_allocated_p = false, pixel_allocated_p = false;
1313 struct x_output *x = f->output_data.x;
1315 if (!NILP (Vx_cursor_fore_pixel))
1317 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
1318 WHITE_PIX_DEFAULT (f));
1319 fore_pixel_allocated_p = true;
1321 else
1322 fore_pixel = FRAME_BACKGROUND_PIXEL (f);
1324 pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1325 pixel_allocated_p = true;
1327 /* Make sure that the cursor color differs from the background color. */
1328 if (pixel == FRAME_BACKGROUND_PIXEL (f))
1330 if (pixel_allocated_p)
1332 x_free_colors (f, &pixel, 1);
1333 pixel_allocated_p = false;
1336 pixel = x->mouse_pixel;
1337 if (pixel == fore_pixel)
1339 if (fore_pixel_allocated_p)
1341 x_free_colors (f, &fore_pixel, 1);
1342 fore_pixel_allocated_p = false;
1344 fore_pixel = FRAME_BACKGROUND_PIXEL (f);
1348 unload_color (f, x->cursor_foreground_pixel);
1349 if (!fore_pixel_allocated_p)
1350 fore_pixel = x_copy_color (f, fore_pixel);
1351 x->cursor_foreground_pixel = fore_pixel;
1353 unload_color (f, x->cursor_pixel);
1354 if (!pixel_allocated_p)
1355 pixel = x_copy_color (f, pixel);
1356 x->cursor_pixel = pixel;
1358 if (FRAME_X_WINDOW (f) != 0)
1360 block_input ();
1361 XSetBackground (FRAME_X_DISPLAY (f), x->cursor_gc, x->cursor_pixel);
1362 XSetForeground (FRAME_X_DISPLAY (f), x->cursor_gc, fore_pixel);
1363 unblock_input ();
1365 if (FRAME_VISIBLE_P (f))
1367 x_update_cursor (f, false);
1368 x_update_cursor (f, true);
1372 update_face_from_frame_parameter (f, Qcursor_color, arg);
1375 /* Set the border-color of frame F to pixel value PIX.
1376 Note that this does not fully take effect if done before
1377 F has an x-window. */
1379 static void
1380 x_set_border_pixel (struct frame *f, int pix)
1382 unload_color (f, f->output_data.x->border_pixel);
1383 f->output_data.x->border_pixel = pix;
1385 if (FRAME_X_WINDOW (f) != 0 && f->border_width > 0)
1387 block_input ();
1388 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), pix);
1389 unblock_input ();
1391 if (FRAME_VISIBLE_P (f))
1392 redraw_frame (f);
1396 /* Set the border-color of frame F to value described by ARG.
1397 ARG can be a string naming a color.
1398 The border-color is used for the border that is drawn by the X server.
1399 Note that this does not fully take effect if done before
1400 F has an x-window; it must be redone when the window is created.
1402 Note: this is done in two routines because of the way X10 works.
1404 Note: under X11, this is normally the province of the window manager,
1405 and so emacs's border colors may be overridden. */
1407 static void
1408 x_set_border_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1410 int pix;
1412 CHECK_STRING (arg);
1413 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1414 x_set_border_pixel (f, pix);
1415 update_face_from_frame_parameter (f, Qborder_color, arg);
1419 static void
1420 x_set_cursor_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1422 set_frame_cursor_types (f, arg);
1425 static void
1426 x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1428 bool result;
1430 if (STRINGP (arg))
1432 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1433 return;
1435 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1436 return;
1438 block_input ();
1439 if (NILP (arg))
1440 result = x_text_icon (f,
1441 SSDATA ((!NILP (f->icon_name)
1442 ? f->icon_name
1443 : f->name)));
1444 else
1445 result = x_bitmap_icon (f, arg);
1447 if (result)
1449 unblock_input ();
1450 error ("No icon window available");
1453 XFlush (FRAME_X_DISPLAY (f));
1454 unblock_input ();
1457 static void
1458 x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1460 bool result;
1462 if (STRINGP (arg))
1464 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1465 return;
1467 else if (!NILP (arg) || NILP (oldval))
1468 return;
1470 fset_icon_name (f, arg);
1472 if (f->output_data.x->icon_bitmap != 0)
1473 return;
1475 block_input ();
1477 result = x_text_icon (f,
1478 SSDATA ((!NILP (f->icon_name)
1479 ? f->icon_name
1480 : !NILP (f->title)
1481 ? f->title
1482 : f->name)));
1484 if (result)
1486 unblock_input ();
1487 error ("No icon window available");
1490 XFlush (FRAME_X_DISPLAY (f));
1491 unblock_input ();
1495 static void
1496 x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
1498 int nlines;
1499 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
1500 int olines = FRAME_MENU_BAR_LINES (f);
1501 #endif
1503 /* Right now, menu bars don't work properly in minibuf-only frames;
1504 most of the commands try to apply themselves to the minibuffer
1505 frame itself, and get an error because you can't switch buffers
1506 in or split the minibuffer window. */
1507 if (FRAME_MINIBUF_ONLY_P (f) || FRAME_PARENT_FRAME (f))
1508 return;
1510 if (TYPE_RANGED_INTEGERP (int, value))
1511 nlines = XINT (value);
1512 else
1513 nlines = 0;
1515 /* Make sure we redisplay all windows in this frame. */
1516 fset_redisplay (f);
1518 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
1519 FRAME_MENU_BAR_LINES (f) = 0;
1520 FRAME_MENU_BAR_HEIGHT (f) = 0;
1521 if (nlines)
1523 FRAME_EXTERNAL_MENU_BAR (f) = 1;
1524 if (FRAME_X_P (f) && f->output_data.x->menubar_widget == 0)
1525 /* Make sure next redisplay shows the menu bar. */
1526 XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = true;
1528 else
1530 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
1531 free_frame_menubar (f);
1532 FRAME_EXTERNAL_MENU_BAR (f) = 0;
1533 if (FRAME_X_P (f))
1534 f->output_data.x->menubar_widget = 0;
1536 #else /* not USE_X_TOOLKIT && not USE_GTK */
1537 FRAME_MENU_BAR_LINES (f) = nlines;
1538 FRAME_MENU_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f);
1539 adjust_frame_size (f, -1, -1, 2, true, Qx_set_menu_bar_lines);
1540 if (FRAME_X_WINDOW (f))
1541 x_clear_under_internal_border (f);
1543 /* If the menu bar height gets changed, the internal border below
1544 the top margin has to be cleared. Also, if the menu bar gets
1545 larger, the area for the added lines has to be cleared except for
1546 the first menu bar line that is to be drawn later. */
1547 if (nlines != olines)
1549 int height = FRAME_INTERNAL_BORDER_WIDTH (f);
1550 int width = FRAME_PIXEL_WIDTH (f);
1551 int y;
1553 /* height can be zero here. */
1554 if (FRAME_X_WINDOW (f) && height > 0 && width > 0)
1556 y = FRAME_TOP_MARGIN_HEIGHT (f);
1558 block_input ();
1559 x_clear_area (f, 0, y, width, height);
1560 unblock_input ();
1563 if (nlines > 1 && nlines > olines)
1565 y = (olines == 0 ? 1 : olines) * FRAME_LINE_HEIGHT (f);
1566 height = nlines * FRAME_LINE_HEIGHT (f) - y;
1568 block_input ();
1569 x_clear_area (f, 0, y, width, height);
1570 unblock_input ();
1573 if (nlines == 0 && WINDOWP (f->menu_bar_window))
1574 clear_glyph_matrix (XWINDOW (f->menu_bar_window)->current_matrix);
1576 #endif /* not USE_X_TOOLKIT && not USE_GTK */
1577 adjust_frame_glyphs (f);
1581 /* Set the number of lines used for the tool bar of frame F to VALUE.
1582 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
1583 is the old number of tool bar lines. This function changes the
1584 height of all windows on frame F to match the new tool bar height.
1585 The frame's height doesn't change. */
1587 static void
1588 x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
1590 int nlines;
1592 /* Treat tool bars like menu bars. */
1593 if (FRAME_MINIBUF_ONLY_P (f))
1594 return;
1596 /* Use VALUE only if an int >= 0. */
1597 if (RANGED_INTEGERP (0, value, INT_MAX))
1598 nlines = XFASTINT (value);
1599 else
1600 nlines = 0;
1602 x_change_tool_bar_height (f, nlines * FRAME_LINE_HEIGHT (f));
1606 /* Set the pixel height of the tool bar of frame F to HEIGHT. */
1607 void
1608 x_change_tool_bar_height (struct frame *f, int height)
1610 #ifdef USE_GTK
1611 FRAME_TOOL_BAR_LINES (f) = 0;
1612 FRAME_TOOL_BAR_HEIGHT (f) = 0;
1613 if (height)
1615 FRAME_EXTERNAL_TOOL_BAR (f) = true;
1616 if (FRAME_X_P (f) && f->output_data.x->toolbar_widget == 0)
1617 /* Make sure next redisplay shows the tool bar. */
1618 XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = true;
1619 update_frame_tool_bar (f);
1621 else
1623 if (FRAME_EXTERNAL_TOOL_BAR (f))
1624 free_frame_tool_bar (f);
1625 FRAME_EXTERNAL_TOOL_BAR (f) = false;
1627 #else /* !USE_GTK */
1628 int unit = FRAME_LINE_HEIGHT (f);
1629 int old_height = FRAME_TOOL_BAR_HEIGHT (f);
1630 int lines = (height + unit - 1) / unit;
1631 Lisp_Object fullscreen;
1633 /* Make sure we redisplay all windows in this frame. */
1634 fset_redisplay (f);
1636 /* Recalculate tool bar and frame text sizes. */
1637 FRAME_TOOL_BAR_HEIGHT (f) = height;
1638 FRAME_TOOL_BAR_LINES (f) = lines;
1639 /* Store the `tool-bar-lines' and `height' frame parameters. */
1640 store_frame_param (f, Qtool_bar_lines, make_number (lines));
1641 store_frame_param (f, Qheight, make_number (FRAME_LINES (f)));
1643 /* We also have to make sure that the internal border at the top of
1644 the frame, below the menu bar or tool bar, is redrawn when the
1645 tool bar disappears. This is so because the internal border is
1646 below the tool bar if one is displayed, but is below the menu bar
1647 if there isn't a tool bar. The tool bar draws into the area
1648 below the menu bar. */
1649 if (FRAME_X_WINDOW (f) && FRAME_TOOL_BAR_HEIGHT (f) == 0)
1651 clear_frame (f);
1652 clear_current_matrices (f);
1655 if ((height < old_height) && WINDOWP (f->tool_bar_window))
1656 clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
1658 /* Recalculate toolbar height. */
1659 f->n_tool_bar_rows = 0;
1660 if (old_height == 0
1661 && (!f->after_make_frame
1662 || NILP (frame_inhibit_implied_resize)
1663 || (CONSP (frame_inhibit_implied_resize)
1664 && NILP (Fmemq (Qtool_bar_lines, frame_inhibit_implied_resize)))))
1665 f->tool_bar_redisplayed = f->tool_bar_resized = false;
1667 adjust_frame_size (f, -1, -1,
1668 ((!f->tool_bar_resized
1669 && (NILP (fullscreen =
1670 get_frame_param (f, Qfullscreen))
1671 || EQ (fullscreen, Qfullwidth))) ? 1
1672 : (old_height == 0 || height == 0) ? 2
1673 : 4),
1674 false, Qtool_bar_lines);
1676 f->tool_bar_resized = f->tool_bar_redisplayed;
1678 /* adjust_frame_size might not have done anything, garbage frame
1679 here. */
1680 adjust_frame_glyphs (f);
1681 SET_FRAME_GARBAGED (f);
1682 if (FRAME_X_WINDOW (f))
1683 x_clear_under_internal_border (f);
1685 #endif /* USE_GTK */
1689 static void
1690 x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1692 int border;
1694 CHECK_TYPE_RANGED_INTEGER (int, arg);
1695 border = max (XINT (arg), 0);
1697 if (border != FRAME_INTERNAL_BORDER_WIDTH (f))
1699 f->internal_border_width = border;
1701 #ifdef USE_X_TOOLKIT
1702 if (FRAME_X_OUTPUT (f)->edit_widget)
1703 widget_store_internal_border (FRAME_X_OUTPUT (f)->edit_widget);
1704 #endif
1706 if (FRAME_X_WINDOW (f))
1708 adjust_frame_size (f, -1, -1, 3, false, Qinternal_border_width);
1709 x_clear_under_internal_border (f);
1716 /* Set the foreground color for scroll bars on frame F to VALUE.
1717 VALUE should be a string, a color name. If it isn't a string or
1718 isn't a valid color name, do nothing. OLDVAL is the old value of
1719 the frame parameter. */
1721 static void
1722 x_set_scroll_bar_foreground (struct frame *f, Lisp_Object value, Lisp_Object oldval)
1724 unsigned long pixel;
1726 if (STRINGP (value))
1727 pixel = x_decode_color (f, value, BLACK_PIX_DEFAULT (f));
1728 else
1729 pixel = -1;
1731 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
1732 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
1734 f->output_data.x->scroll_bar_foreground_pixel = pixel;
1735 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
1737 /* Remove all scroll bars because they have wrong colors. */
1738 if (FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
1739 (*FRAME_TERMINAL (f)->condemn_scroll_bars_hook) (f);
1740 if (FRAME_TERMINAL (f)->judge_scroll_bars_hook)
1741 (*FRAME_TERMINAL (f)->judge_scroll_bars_hook) (f);
1743 update_face_from_frame_parameter (f, Qscroll_bar_foreground, value);
1744 redraw_frame (f);
1749 /* Set the background color for scroll bars on frame F to VALUE VALUE
1750 should be a string, a color name. If it isn't a string or isn't a
1751 valid color name, do nothing. OLDVAL is the old value of the frame
1752 parameter. */
1754 static void
1755 x_set_scroll_bar_background (struct frame *f, Lisp_Object value, Lisp_Object oldval)
1757 unsigned long pixel;
1759 if (STRINGP (value))
1760 pixel = x_decode_color (f, value, WHITE_PIX_DEFAULT (f));
1761 else
1762 pixel = -1;
1764 if (f->output_data.x->scroll_bar_background_pixel != -1)
1765 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
1767 #if defined (USE_LUCID) && defined (USE_TOOLKIT_SCROLL_BARS)
1768 /* Scrollbar shadow colors. */
1769 if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
1771 unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
1772 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
1774 if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
1776 unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
1777 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
1779 #endif /* USE_LUCID && USE_TOOLKIT_SCROLL_BARS */
1781 f->output_data.x->scroll_bar_background_pixel = pixel;
1782 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
1784 /* Remove all scroll bars because they have wrong colors. */
1785 if (FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
1786 (*FRAME_TERMINAL (f)->condemn_scroll_bars_hook) (f);
1787 if (FRAME_TERMINAL (f)->judge_scroll_bars_hook)
1788 (*FRAME_TERMINAL (f)->judge_scroll_bars_hook) (f);
1790 update_face_from_frame_parameter (f, Qscroll_bar_background, value);
1791 redraw_frame (f);
1796 /* Encode Lisp string STRING as a text in a format appropriate for
1797 XICCC (X Inter Client Communication Conventions).
1799 If STRING contains only ASCII characters, do no conversion and
1800 return the string data of STRING. Otherwise, encode the text by
1801 CODING_SYSTEM, and return a newly allocated memory area which
1802 should be freed by `xfree' by a caller.
1804 Store the byte length of resulting text in *TEXT_BYTES.
1806 If the text contains only ASCII and Latin-1, store true in *STRING_P,
1807 which means that the `encoding' of the result can be `STRING'.
1808 Otherwise store false in *STRINGP, which means that the `encoding' of
1809 the result should be `COMPOUND_TEXT'. */
1811 static unsigned char *
1812 x_encode_text (Lisp_Object string, Lisp_Object coding_system,
1813 ptrdiff_t *text_bytes, bool *stringp, bool *freep)
1815 int result = string_xstring_p (string);
1816 struct coding_system coding;
1818 if (result == 0)
1820 /* No multibyte character in OBJ. We need not encode it. */
1821 *text_bytes = SBYTES (string);
1822 *stringp = true;
1823 *freep = false;
1824 return SDATA (string);
1827 setup_coding_system (coding_system, &coding);
1828 coding.mode |= (CODING_MODE_SAFE_ENCODING | CODING_MODE_LAST_BLOCK);
1829 /* We suppress producing escape sequences for composition. */
1830 coding.common_flags &= ~CODING_ANNOTATION_MASK;
1831 coding.destination = xnmalloc (SCHARS (string), 2);
1832 coding.dst_bytes = SCHARS (string) * 2;
1833 encode_coding_object (&coding, string, 0, 0,
1834 SCHARS (string), SBYTES (string), Qnil);
1835 *text_bytes = coding.produced;
1836 *stringp = (result == 1 || !EQ (coding_system, Qcompound_text));
1837 *freep = true;
1838 return coding.destination;
1842 /* Set the WM name to NAME for frame F. Also set the icon name.
1843 If the frame already has an icon name, use that, otherwise set the
1844 icon name to NAME. */
1846 static void
1847 x_set_name_internal (struct frame *f, Lisp_Object name)
1849 if (FRAME_X_WINDOW (f))
1851 block_input ();
1853 XTextProperty text, icon;
1854 ptrdiff_t bytes;
1855 bool stringp;
1856 bool do_free_icon_value = false, do_free_text_value = false;
1857 Lisp_Object coding_system;
1858 Lisp_Object encoded_name;
1859 Lisp_Object encoded_icon_name;
1861 /* As ENCODE_UTF_8 may cause GC and relocation of string data,
1862 we use it before x_encode_text that may return string data. */
1863 encoded_name = ENCODE_UTF_8 (name);
1865 coding_system = Qcompound_text;
1866 /* Note: Encoding strategy
1868 We encode NAME by compound-text and use "COMPOUND-TEXT" in
1869 text.encoding. But, there are non-internationalized window
1870 managers which don't support that encoding. So, if NAME
1871 contains only ASCII and 8859-1 characters, encode it by
1872 iso-latin-1, and use "STRING" in text.encoding hoping that
1873 such window managers at least analyze this format correctly,
1874 i.e. treat 8-bit bytes as 8859-1 characters.
1876 We may also be able to use "UTF8_STRING" in text.encoding
1877 in the future which can encode all Unicode characters.
1878 But, for the moment, there's no way to know that the
1879 current window manager supports it or not.
1881 Either way, we also set the _NET_WM_NAME and _NET_WM_ICON_NAME
1882 properties. Per the EWMH specification, those two properties
1883 are always UTF8_STRING. This matches what gtk_window_set_title()
1884 does in the USE_GTK case. */
1885 text.value = x_encode_text (name, coding_system, &bytes,
1886 &stringp, &do_free_text_value);
1887 text.encoding = (stringp ? XA_STRING
1888 : FRAME_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
1889 text.format = 8;
1890 text.nitems = bytes;
1892 if (!STRINGP (f->icon_name))
1894 icon = text;
1895 encoded_icon_name = encoded_name;
1897 else
1899 /* See the above comment "Note: Encoding strategy". */
1900 icon.value = x_encode_text (f->icon_name, coding_system, &bytes,
1901 &stringp, &do_free_icon_value);
1902 icon.encoding = (stringp ? XA_STRING
1903 : FRAME_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
1904 icon.format = 8;
1905 icon.nitems = bytes;
1907 encoded_icon_name = ENCODE_UTF_8 (f->icon_name);
1910 #ifdef USE_GTK
1911 gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
1912 SSDATA (encoded_name));
1913 #else /* not USE_GTK */
1914 XSetWMName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text);
1915 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
1916 FRAME_DISPLAY_INFO (f)->Xatom_net_wm_name,
1917 FRAME_DISPLAY_INFO (f)->Xatom_UTF8_STRING,
1918 8, PropModeReplace,
1919 SDATA (encoded_name),
1920 SBYTES (encoded_name));
1921 #endif /* not USE_GTK */
1923 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &icon);
1924 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
1925 FRAME_DISPLAY_INFO (f)->Xatom_net_wm_icon_name,
1926 FRAME_DISPLAY_INFO (f)->Xatom_UTF8_STRING,
1927 8, PropModeReplace,
1928 SDATA (encoded_icon_name),
1929 SBYTES (encoded_icon_name));
1931 if (do_free_icon_value)
1932 xfree (icon.value);
1933 if (do_free_text_value)
1934 xfree (text.value);
1936 unblock_input ();
1940 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
1941 x_id_name.
1943 If EXPLICIT is true, that indicates that lisp code is setting the
1944 name; if NAME is a string, set F's name to NAME and set
1945 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
1947 If EXPLICIT is false, that indicates that Emacs redisplay code is
1948 suggesting a new name, which lisp code should override; if
1949 F->explicit_name is set, ignore the new name; otherwise, set it. */
1951 static void
1952 x_set_name (struct frame *f, Lisp_Object name, bool explicit)
1954 /* Make sure that requests from lisp code override requests from
1955 Emacs redisplay code. */
1956 if (explicit)
1958 /* If we're switching from explicit to implicit, we had better
1959 update the mode lines and thereby update the title. */
1960 if (f->explicit_name && NILP (name))
1961 update_mode_lines = 37;
1963 f->explicit_name = ! NILP (name);
1965 else if (f->explicit_name)
1966 return;
1968 /* If NAME is nil, set the name to the x_id_name. */
1969 if (NILP (name))
1971 /* Check for no change needed in this very common case
1972 before we do any consing. */
1973 if (!strcmp (FRAME_DISPLAY_INFO (f)->x_id_name,
1974 SSDATA (f->name)))
1975 return;
1976 name = build_string (FRAME_DISPLAY_INFO (f)->x_id_name);
1978 else
1979 CHECK_STRING (name);
1981 /* Don't change the name if it's already NAME. */
1982 if (! NILP (Fstring_equal (name, f->name)))
1983 return;
1985 fset_name (f, name);
1987 /* For setting the frame title, the title parameter should override
1988 the name parameter. */
1989 if (! NILP (f->title))
1990 name = f->title;
1992 x_set_name_internal (f, name);
1995 /* This function should be called when the user's lisp code has
1996 specified a name for the frame; the name will override any set by the
1997 redisplay code. */
1998 static void
1999 x_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
2001 x_set_name (f, arg, true);
2004 /* This function should be called by Emacs redisplay code to set the
2005 name; names set this way will never override names set by the user's
2006 lisp code. */
2007 void
2008 x_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
2010 x_set_name (f, arg, false);
2013 /* Change the title of frame F to NAME.
2014 If NAME is nil, use the frame name as the title. */
2016 static void
2017 x_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name)
2019 /* Don't change the title if it's already NAME. */
2020 if (EQ (name, f->title))
2021 return;
2023 update_mode_lines = 38;
2025 fset_title (f, name);
2027 if (NILP (name))
2028 name = f->name;
2029 else
2030 CHECK_STRING (name);
2032 x_set_name_internal (f, name);
2035 void
2036 x_set_scroll_bar_default_width (struct frame *f)
2038 int unit = FRAME_COLUMN_WIDTH (f);
2039 #ifdef USE_TOOLKIT_SCROLL_BARS
2040 #ifdef USE_GTK
2041 int minw = xg_get_default_scrollbar_width ();
2042 #else
2043 int minw = 16;
2044 #endif
2045 /* A minimum width of 14 doesn't look good for toolkit scroll bars. */
2046 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (minw + unit - 1) / unit;
2047 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = minw;
2048 #else
2049 /* The width of a non-toolkit scrollbar is 14 pixels. */
2050 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit;
2051 FRAME_CONFIG_SCROLL_BAR_WIDTH (f)
2052 = FRAME_CONFIG_SCROLL_BAR_COLS (f) * unit;
2053 #endif
2056 void
2057 x_set_scroll_bar_default_height (struct frame *f)
2059 int height = FRAME_LINE_HEIGHT (f);
2060 #ifdef USE_TOOLKIT_SCROLL_BARS
2061 #ifdef USE_GTK
2062 int min_height = xg_get_default_scrollbar_height ();
2063 #else
2064 int min_height = 16;
2065 #endif
2066 /* A minimum height of 14 doesn't look good for toolkit scroll bars. */
2067 FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = min_height;
2068 FRAME_CONFIG_SCROLL_BAR_LINES (f) = (min_height + height - 1) / height;
2069 #else
2070 /* The height of a non-toolkit scrollbar is 14 pixels. */
2071 FRAME_CONFIG_SCROLL_BAR_LINES (f) = (14 + height - 1) / height;
2073 /* Use all of that space (aside from required margins) for the
2074 scroll bar. */
2075 FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = 14;
2076 #endif
2080 /* Record in frame F the specified or default value according to ALIST
2081 of the parameter named PROP (a Lisp symbol). If no value is
2082 specified for PROP, look for an X default for XPROP on the frame
2083 named NAME. If that is not found either, use the value DEFLT. */
2085 static Lisp_Object
2086 x_default_scroll_bar_color_parameter (struct frame *f,
2087 Lisp_Object alist, Lisp_Object prop,
2088 const char *xprop, const char *xclass,
2089 bool foreground_p)
2091 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
2092 Lisp_Object tem;
2094 tem = x_get_arg (dpyinfo, alist, prop, xprop, xclass, RES_TYPE_STRING);
2095 if (EQ (tem, Qunbound))
2097 #ifdef USE_TOOLKIT_SCROLL_BARS
2099 /* See if an X resource for the scroll bar color has been
2100 specified. */
2101 AUTO_STRING (foreground, "foreground");
2102 AUTO_STRING (background, "foreground");
2103 AUTO_STRING (verticalScrollBar, "verticalScrollBar");
2104 tem = (display_x_get_resource
2105 (dpyinfo, foreground_p ? foreground : background,
2106 empty_unibyte_string,
2107 verticalScrollBar,
2108 empty_unibyte_string));
2109 if (!STRINGP (tem))
2111 /* If nothing has been specified, scroll bars will use a
2112 toolkit-dependent default. Because these defaults are
2113 difficult to get at without actually creating a scroll
2114 bar, use nil to indicate that no color has been
2115 specified. */
2116 tem = Qnil;
2119 #else /* not USE_TOOLKIT_SCROLL_BARS */
2121 tem = Qnil;
2123 #endif /* not USE_TOOLKIT_SCROLL_BARS */
2126 AUTO_FRAME_ARG (arg, prop, tem);
2127 x_set_frame_parameters (f, arg);
2128 return tem;
2134 #ifdef USE_X_TOOLKIT
2136 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS,
2137 WM_DELETE_WINDOW, and WM_SAVE_YOURSELF, then add them. (They may
2138 already be present because of the toolkit (Motif adds some of them,
2139 for example, but Xt doesn't). */
2141 static void
2142 hack_wm_protocols (struct frame *f, Widget widget)
2144 Display *dpy = XtDisplay (widget);
2145 Window w = XtWindow (widget);
2146 bool need_delete = true;
2147 bool need_focus = true;
2148 bool need_save = true;
2150 block_input ();
2152 Atom type;
2153 unsigned char *catoms;
2154 int format = 0;
2155 unsigned long nitems = 0;
2156 unsigned long bytes_after;
2158 if ((XGetWindowProperty (dpy, w,
2159 FRAME_DISPLAY_INFO (f)->Xatom_wm_protocols,
2160 0, 100, False, XA_ATOM,
2161 &type, &format, &nitems, &bytes_after,
2162 &catoms)
2163 == Success)
2164 && format == 32 && type == XA_ATOM)
2166 Atom *atoms = (Atom *) catoms;
2167 while (nitems > 0)
2169 nitems--;
2170 if (atoms[nitems]
2171 == FRAME_DISPLAY_INFO (f)->Xatom_wm_delete_window)
2172 need_delete = false;
2173 else if (atoms[nitems]
2174 == FRAME_DISPLAY_INFO (f)->Xatom_wm_take_focus)
2175 need_focus = false;
2176 else if (atoms[nitems]
2177 == FRAME_DISPLAY_INFO (f)->Xatom_wm_save_yourself)
2178 need_save = false;
2181 if (catoms)
2182 XFree (catoms);
2185 Atom props[10];
2186 int count = 0;
2187 if (need_delete)
2188 props[count++] = FRAME_DISPLAY_INFO (f)->Xatom_wm_delete_window;
2189 if (need_focus)
2190 props[count++] = FRAME_DISPLAY_INFO (f)->Xatom_wm_take_focus;
2191 if (need_save)
2192 props[count++] = FRAME_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
2193 if (count)
2194 XChangeProperty (dpy, w, FRAME_DISPLAY_INFO (f)->Xatom_wm_protocols,
2195 XA_ATOM, 32, PropModeAppend,
2196 (unsigned char *) props, count);
2198 unblock_input ();
2200 #endif
2204 /* Support routines for XIC (X Input Context). */
2206 #ifdef HAVE_X_I18N
2208 static XFontSet xic_create_xfontset (struct frame *);
2209 static XIMStyle best_xim_style (XIMStyles *);
2212 /* Supported XIM styles, ordered by preference. */
2214 static const XIMStyle supported_xim_styles[] =
2216 XIMPreeditPosition | XIMStatusArea,
2217 XIMPreeditPosition | XIMStatusNothing,
2218 XIMPreeditPosition | XIMStatusNone,
2219 XIMPreeditNothing | XIMStatusArea,
2220 XIMPreeditNothing | XIMStatusNothing,
2221 XIMPreeditNothing | XIMStatusNone,
2222 XIMPreeditNone | XIMStatusArea,
2223 XIMPreeditNone | XIMStatusNothing,
2224 XIMPreeditNone | XIMStatusNone,
2229 #if defined HAVE_X_WINDOWS && defined USE_X_TOOLKIT
2230 /* Create an X fontset on frame F with base font name BASE_FONTNAME. */
2232 static const char xic_default_fontset[] = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
2234 /* Create an Xt fontset spec from the name of a base font.
2235 If `motif' is True use the Motif syntax. */
2236 char *
2237 xic_create_fontsetname (const char *base_fontname, bool motif)
2239 const char *sep = motif ? ";" : ",";
2240 char *fontsetname;
2241 char *z;
2243 /* Make a fontset name from the base font name. */
2244 if (xic_default_fontset == base_fontname)
2246 /* There is no base font name, use the default. */
2247 fontsetname = xmalloc (strlen (base_fontname) + 2);
2248 z = stpcpy (fontsetname, base_fontname);
2250 else
2252 /* Make a fontset name from the base font name.
2253 The font set will be made of the following elements:
2254 - the base font.
2255 - the base font where the charset spec is replaced by -*-*.
2256 - the same but with the family also replaced with -*-*-. */
2257 const char *p = base_fontname;
2258 ptrdiff_t i;
2260 for (i = 0; *p; p++)
2261 if (*p == '-') i++;
2262 if (i != 14)
2264 /* As the font name doesn't conform to XLFD, we can't
2265 modify it to generalize it to allcs and allfamilies.
2266 Use the specified font plus the default. */
2267 fontsetname = xmalloc (strlen (base_fontname)
2268 + strlen (xic_default_fontset) + 3);
2269 z = stpcpy (fontsetname, base_fontname);
2270 z = stpcpy (z, sep);
2271 z = stpcpy (z, xic_default_fontset);
2273 else
2275 ptrdiff_t len;
2276 const char *p1 = NULL, *p2 = NULL, *p3 = NULL;
2277 char *font_allcs = NULL;
2278 char *font_allfamilies = NULL;
2279 char *font_all = NULL;
2280 const char *allcs = "*-*-*-*-*-*-*";
2281 const char *allfamilies = "-*-*-";
2282 const char *all = "*-*-*-*-";
2283 char *base;
2285 for (i = 0, p = base_fontname; i < 8; p++)
2287 if (*p == '-')
2289 i++;
2290 if (i == 3)
2291 p1 = p + 1;
2292 else if (i == 7)
2293 p2 = p + 1;
2294 else if (i == 6)
2295 p3 = p + 1;
2298 /* If base_fontname specifies ADSTYLE, make it a
2299 wildcard. */
2300 if (*p3 != '*')
2302 ptrdiff_t diff = (p2 - p3) - 2;
2304 base = alloca (strlen (base_fontname) + 1);
2305 memcpy (base, base_fontname, p3 - base_fontname);
2306 base[p3 - base_fontname] = '*';
2307 base[(p3 - base_fontname) + 1] = '-';
2308 strcpy (base + (p3 - base_fontname) + 2, p2);
2309 p = base + (p - base_fontname) - diff;
2310 p1 = base + (p1 - base_fontname);
2311 p2 = base + (p2 - base_fontname) - diff;
2312 base_fontname = base;
2315 /* Build the font spec that matches all charsets. */
2316 len = p - base_fontname + strlen (allcs) + 1;
2317 font_allcs = alloca (len);
2318 memcpy (font_allcs, base_fontname, p - base_fontname);
2319 strcpy (font_allcs + (p - base_fontname), allcs);
2321 /* Build the font spec that matches all families and
2322 add-styles. */
2323 len = p - p1 + strlen (allcs) + strlen (allfamilies) + 1;
2324 font_allfamilies = alloca (len);
2325 strcpy (font_allfamilies, allfamilies);
2326 memcpy (font_allfamilies + strlen (allfamilies), p1, p - p1);
2327 strcpy (font_allfamilies + strlen (allfamilies) + (p - p1), allcs);
2329 /* Build the font spec that matches all. */
2330 len = p - p2 + strlen (allcs) + strlen (all) + strlen (allfamilies) + 1;
2331 font_all = alloca (len);
2332 z = stpcpy (font_all, allfamilies);
2333 z = stpcpy (z, all);
2334 memcpy (z, p2, p - p2);
2335 strcpy (z + (p - p2), allcs);
2337 /* Build the actual font set name. */
2338 len = strlen (base_fontname) + strlen (font_allcs)
2339 + strlen (font_allfamilies) + strlen (font_all) + 5;
2340 fontsetname = xmalloc (len);
2341 z = stpcpy (fontsetname, base_fontname);
2342 z = stpcpy (z, sep);
2343 z = stpcpy (z, font_allcs);
2344 z = stpcpy (z, sep);
2345 z = stpcpy (z, font_allfamilies);
2346 z = stpcpy (z, sep);
2347 z = stpcpy (z, font_all);
2350 if (motif)
2351 strcpy (z, ":");
2352 return fontsetname;
2354 #endif /* HAVE_X_WINDOWS && USE_X_TOOLKIT */
2356 #ifdef DEBUG_XIC_FONTSET
2357 static void
2358 print_fontset_result (XFontSet xfs, char *name, char **missing_list,
2359 int missing_count)
2361 if (xfs)
2362 fprintf (stderr, "XIC Fontset created: %s\n", name);
2363 else
2365 fprintf (stderr, "XIC Fontset failed: %s\n", name);
2366 while (missing_count-- > 0)
2368 fprintf (stderr, " missing: %s\n", *missing_list);
2369 missing_list++;
2374 #endif
2376 static XFontSet
2377 xic_create_xfontset (struct frame *f)
2379 XFontSet xfs = NULL;
2380 struct font *font = FRAME_FONT (f);
2381 int pixel_size = font->pixel_size;
2382 Lisp_Object rest, frame;
2384 /* See if there is another frame already using same fontset. */
2385 FOR_EACH_FRAME (rest, frame)
2387 struct frame *cf = XFRAME (frame);
2389 if (cf != f && FRAME_LIVE_P (f) && FRAME_X_P (cf)
2390 && FRAME_DISPLAY_INFO (cf) == FRAME_DISPLAY_INFO (f)
2391 && FRAME_FONT (f)
2392 && FRAME_FONT (f)->pixel_size == pixel_size)
2394 xfs = FRAME_XIC_FONTSET (cf);
2395 break;
2399 if (! xfs)
2401 char buf[256];
2402 char **missing_list;
2403 int missing_count;
2404 char *def_string;
2405 const char *xlfd_format = "-*-*-medium-r-normal--%d-*-*-*-*-*";
2407 sprintf (buf, xlfd_format, pixel_size);
2408 missing_list = NULL;
2409 xfs = XCreateFontSet (FRAME_X_DISPLAY (f), buf,
2410 &missing_list, &missing_count, &def_string);
2411 #ifdef DEBUG_XIC_FONTSET
2412 print_fontset_result (xfs, buf, missing_list, missing_count);
2413 #endif
2414 if (missing_list)
2415 XFreeStringList (missing_list);
2416 if (! xfs)
2418 /* List of pixel sizes most likely available. Find one that
2419 is closest to pixel_size. */
2420 int sizes[] = {0, 8, 10, 11, 12, 14, 17, 18, 20, 24, 26, 34, 0};
2421 int *smaller, *larger;
2423 for (smaller = sizes; smaller[1]; smaller++)
2424 if (smaller[1] >= pixel_size)
2425 break;
2426 larger = smaller + 1;
2427 if (*larger == pixel_size)
2428 larger++;
2429 while (*smaller || *larger)
2431 int this_size;
2433 if (! *larger)
2434 this_size = *smaller--;
2435 else if (! *smaller)
2436 this_size = *larger++;
2437 else if (pixel_size - *smaller < *larger - pixel_size)
2438 this_size = *smaller--;
2439 else
2440 this_size = *larger++;
2441 sprintf (buf, xlfd_format, this_size);
2442 missing_list = NULL;
2443 xfs = XCreateFontSet (FRAME_X_DISPLAY (f), buf,
2444 &missing_list, &missing_count, &def_string);
2445 #ifdef DEBUG_XIC_FONTSET
2446 print_fontset_result (xfs, buf, missing_list, missing_count);
2447 #endif
2448 if (missing_list)
2449 XFreeStringList (missing_list);
2450 if (xfs)
2451 break;
2454 if (! xfs)
2456 const char *last_resort = "-*-*-*-r-normal--*-*-*-*-*-*";
2458 missing_list = NULL;
2459 xfs = XCreateFontSet (FRAME_X_DISPLAY (f), last_resort,
2460 &missing_list, &missing_count, &def_string);
2461 #ifdef DEBUG_XIC_FONTSET
2462 print_fontset_result (xfs, last_resort, missing_list, missing_count);
2463 #endif
2464 if (missing_list)
2465 XFreeStringList (missing_list);
2470 return xfs;
2473 /* Free the X fontset of frame F if it is the last frame using it. */
2475 void
2476 xic_free_xfontset (struct frame *f)
2478 Lisp_Object rest, frame;
2479 bool shared_p = false;
2481 if (!FRAME_XIC_FONTSET (f))
2482 return;
2484 /* See if there is another frame sharing the same fontset. */
2485 FOR_EACH_FRAME (rest, frame)
2487 struct frame *cf = XFRAME (frame);
2488 if (cf != f && FRAME_LIVE_P (f) && FRAME_X_P (cf)
2489 && FRAME_DISPLAY_INFO (cf) == FRAME_DISPLAY_INFO (f)
2490 && FRAME_XIC_FONTSET (cf) == FRAME_XIC_FONTSET (f))
2492 shared_p = true;
2493 break;
2497 if (!shared_p)
2498 /* The fontset is not used anymore. It is safe to free it. */
2499 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
2501 FRAME_XIC_FONTSET (f) = NULL;
2505 /* Value is the best input style, given user preferences USER (already
2506 checked to be supported by Emacs), and styles supported by the
2507 input method XIM. */
2509 static XIMStyle
2510 best_xim_style (XIMStyles *xim)
2512 int i, j;
2513 int nr_supported = ARRAYELTS (supported_xim_styles);
2515 for (i = 0; i < nr_supported; ++i)
2516 for (j = 0; j < xim->count_styles; ++j)
2517 if (supported_xim_styles[i] == xim->supported_styles[j])
2518 return supported_xim_styles[i];
2520 /* Return the default style. */
2521 return XIMPreeditNothing | XIMStatusNothing;
2524 /* Create XIC for frame F. */
2526 void
2527 create_frame_xic (struct frame *f)
2529 XIM xim;
2530 XIC xic = NULL;
2531 XFontSet xfs = NULL;
2532 XVaNestedList status_attr = NULL;
2533 XVaNestedList preedit_attr = NULL;
2534 XRectangle s_area;
2535 XPoint spot;
2536 XIMStyle xic_style;
2538 if (FRAME_XIC (f))
2539 goto out;
2541 xim = FRAME_X_XIM (f);
2542 if (!xim)
2543 goto out;
2545 /* Determine XIC style. */
2546 xic_style = best_xim_style (FRAME_X_XIM_STYLES (f));
2548 /* Create X fontset. */
2549 if (xic_style & (XIMPreeditPosition | XIMStatusArea))
2551 xfs = xic_create_xfontset (f);
2552 if (!xfs)
2553 goto out;
2555 FRAME_XIC_FONTSET (f) = xfs;
2558 if (xic_style & XIMPreeditPosition)
2560 spot.x = 0; spot.y = 1;
2561 preedit_attr = XVaCreateNestedList (0,
2562 XNFontSet, xfs,
2563 XNForeground,
2564 FRAME_FOREGROUND_PIXEL (f),
2565 XNBackground,
2566 FRAME_BACKGROUND_PIXEL (f),
2567 (xic_style & XIMPreeditPosition
2568 ? XNSpotLocation
2569 : NULL),
2570 &spot,
2571 NULL);
2573 if (!preedit_attr)
2574 goto out;
2577 if (xic_style & XIMStatusArea)
2579 s_area.x = 0; s_area.y = 0; s_area.width = 1; s_area.height = 1;
2580 status_attr = XVaCreateNestedList (0,
2581 XNArea,
2582 &s_area,
2583 XNFontSet,
2584 xfs,
2585 XNForeground,
2586 FRAME_FOREGROUND_PIXEL (f),
2587 XNBackground,
2588 FRAME_BACKGROUND_PIXEL (f),
2589 NULL);
2591 if (!status_attr)
2592 goto out;
2595 if (preedit_attr && status_attr)
2596 xic = XCreateIC (xim,
2597 XNInputStyle, xic_style,
2598 XNClientWindow, FRAME_X_WINDOW (f),
2599 XNFocusWindow, FRAME_X_WINDOW (f),
2600 XNStatusAttributes, status_attr,
2601 XNPreeditAttributes, preedit_attr,
2602 NULL);
2603 else if (preedit_attr)
2604 xic = XCreateIC (xim,
2605 XNInputStyle, xic_style,
2606 XNClientWindow, FRAME_X_WINDOW (f),
2607 XNFocusWindow, FRAME_X_WINDOW (f),
2608 XNPreeditAttributes, preedit_attr,
2609 NULL);
2610 else if (status_attr)
2611 xic = XCreateIC (xim,
2612 XNInputStyle, xic_style,
2613 XNClientWindow, FRAME_X_WINDOW (f),
2614 XNFocusWindow, FRAME_X_WINDOW (f),
2615 XNStatusAttributes, status_attr,
2616 NULL);
2617 else
2618 xic = XCreateIC (xim,
2619 XNInputStyle, xic_style,
2620 XNClientWindow, FRAME_X_WINDOW (f),
2621 XNFocusWindow, FRAME_X_WINDOW (f),
2622 NULL);
2624 if (!xic)
2625 goto out;
2627 FRAME_XIC (f) = xic;
2628 FRAME_XIC_STYLE (f) = xic_style;
2629 xfs = NULL; /* Don't free below. */
2631 out:
2633 if (xfs)
2634 free_frame_xic (f);
2636 if (preedit_attr)
2637 XFree (preedit_attr);
2639 if (status_attr)
2640 XFree (status_attr);
2644 /* Destroy XIC and free XIC fontset of frame F, if any. */
2646 void
2647 free_frame_xic (struct frame *f)
2649 if (FRAME_XIC (f) == NULL)
2650 return;
2652 XDestroyIC (FRAME_XIC (f));
2653 xic_free_xfontset (f);
2655 FRAME_XIC (f) = NULL;
2659 /* Place preedit area for XIC of window W's frame to specified
2660 pixel position X/Y. X and Y are relative to window W. */
2662 void
2663 xic_set_preeditarea (struct window *w, int x, int y)
2665 struct frame *f = XFRAME (w->frame);
2666 XVaNestedList attr;
2667 XPoint spot;
2669 spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x) + WINDOW_LEFT_FRINGE_WIDTH (w);
2670 spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f));
2671 attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL);
2672 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
2673 XFree (attr);
2677 /* Place status area for XIC in bottom right corner of frame F.. */
2679 void
2680 xic_set_statusarea (struct frame *f)
2682 XIC xic = FRAME_XIC (f);
2683 XVaNestedList attr;
2684 XRectangle area;
2685 XRectangle *needed;
2687 /* Negotiate geometry of status area. If input method has existing
2688 status area, use its current size. */
2689 area.x = area.y = area.width = area.height = 0;
2690 attr = XVaCreateNestedList (0, XNAreaNeeded, &area, NULL);
2691 XSetICValues (xic, XNStatusAttributes, attr, NULL);
2692 XFree (attr);
2694 attr = XVaCreateNestedList (0, XNAreaNeeded, &needed, NULL);
2695 XGetICValues (xic, XNStatusAttributes, attr, NULL);
2696 XFree (attr);
2698 if (needed->width == 0) /* Use XNArea instead of XNAreaNeeded */
2700 attr = XVaCreateNestedList (0, XNArea, &needed, NULL);
2701 XGetICValues (xic, XNStatusAttributes, attr, NULL);
2702 XFree (attr);
2705 area.width = needed->width;
2706 area.height = needed->height;
2707 area.x = FRAME_PIXEL_WIDTH (f) - area.width - FRAME_INTERNAL_BORDER_WIDTH (f);
2708 area.y = (FRAME_PIXEL_HEIGHT (f) - area.height
2709 - FRAME_MENUBAR_HEIGHT (f)
2710 - FRAME_TOOLBAR_TOP_HEIGHT (f)
2711 - FRAME_INTERNAL_BORDER_WIDTH (f));
2712 XFree (needed);
2714 attr = XVaCreateNestedList (0, XNArea, &area, NULL);
2715 XSetICValues (xic, XNStatusAttributes, attr, NULL);
2716 XFree (attr);
2720 /* Set X fontset for XIC of frame F, using base font name
2721 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
2723 void
2724 xic_set_xfontset (struct frame *f, const char *base_fontname)
2726 XVaNestedList attr;
2727 XFontSet xfs;
2729 xic_free_xfontset (f);
2731 xfs = xic_create_xfontset (f);
2733 attr = XVaCreateNestedList (0, XNFontSet, xfs, NULL);
2734 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
2735 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
2736 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
2737 XSetICValues (FRAME_XIC (f), XNStatusAttributes, attr, NULL);
2738 XFree (attr);
2740 FRAME_XIC_FONTSET (f) = xfs;
2743 #endif /* HAVE_X_I18N */
2748 void
2749 x_mark_frame_dirty (struct frame *f)
2751 if (FRAME_X_DOUBLE_BUFFERED_P (f) && !FRAME_X_NEED_BUFFER_FLIP (f))
2752 FRAME_X_NEED_BUFFER_FLIP (f) = true;
2755 static void
2756 set_up_x_back_buffer (struct frame *f)
2758 #ifdef HAVE_XDBE
2759 block_input ();
2760 if (FRAME_X_WINDOW (f) && !FRAME_X_DOUBLE_BUFFERED_P (f))
2762 FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
2763 if (FRAME_DISPLAY_INFO (f)->supports_xdbe)
2765 /* If allocating a back buffer fails, either because the
2766 server ran out of memory or we don't have the right kind
2767 of visual, just use single-buffered rendering. */
2768 x_catch_errors (FRAME_X_DISPLAY (f));
2769 FRAME_X_RAW_DRAWABLE (f) = XdbeAllocateBackBufferName (
2770 FRAME_X_DISPLAY (f),
2771 FRAME_X_WINDOW (f),
2772 XdbeCopied);
2773 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
2774 FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
2775 x_uncatch_errors_after_check ();
2778 unblock_input ();
2779 #endif
2782 void
2783 tear_down_x_back_buffer (struct frame *f)
2785 #ifdef HAVE_XDBE
2786 block_input ();
2787 if (FRAME_X_WINDOW (f) && FRAME_X_DOUBLE_BUFFERED_P (f))
2789 if (FRAME_X_DOUBLE_BUFFERED_P (f))
2791 XdbeDeallocateBackBufferName (FRAME_X_DISPLAY (f),
2792 FRAME_X_DRAWABLE (f));
2793 FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
2796 unblock_input ();
2797 #endif
2800 /* Set up double buffering if the frame parameters don't prohibit
2801 it. */
2802 void
2803 initial_set_up_x_back_buffer (struct frame *f)
2805 block_input ();
2806 eassert (FRAME_X_WINDOW (f));
2807 FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
2808 if (NILP (CDR (Fassq (Qinhibit_double_buffering, f->param_alist))))
2809 set_up_x_back_buffer (f);
2810 unblock_input ();
2813 #ifdef USE_X_TOOLKIT
2815 /* Create and set up the X widget for frame F. */
2817 static void
2818 x_window (struct frame *f, long window_prompting)
2820 XClassHint class_hints;
2821 XSetWindowAttributes attributes;
2822 unsigned long attribute_mask;
2823 Widget shell_widget;
2824 Widget pane_widget;
2825 Widget frame_widget;
2826 Arg al[25];
2827 int ac;
2829 block_input ();
2831 /* Use the resource name as the top-level widget name
2832 for looking up resources. Make a non-Lisp copy
2833 for the window manager, so GC relocation won't bother it.
2835 Elsewhere we specify the window name for the window manager. */
2836 f->namebuf = xlispstrdup (Vx_resource_name);
2838 ac = 0;
2839 XtSetArg (al[ac], XtNallowShellResize, 1); ac++;
2840 XtSetArg (al[ac], XtNinput, 1); ac++;
2841 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
2842 XtSetArg (al[ac], XtNborderWidth, f->border_width); ac++;
2843 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
2844 XtSetArg (al[ac], XtNdepth, FRAME_DISPLAY_INFO (f)->n_planes); ac++;
2845 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
2846 shell_widget = XtAppCreateShell (f->namebuf, EMACS_CLASS,
2847 applicationShellWidgetClass,
2848 FRAME_X_DISPLAY (f), al, ac);
2850 f->output_data.x->widget = shell_widget;
2851 /* maybe_set_screen_title_format (shell_widget); */
2853 pane_widget = lw_create_widget ("main", "pane", widget_id_tick++,
2854 NULL, shell_widget, False,
2855 NULL, NULL, NULL, NULL);
2857 ac = 0;
2858 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
2859 XtSetArg (al[ac], XtNdepth, FRAME_DISPLAY_INFO (f)->n_planes); ac++;
2860 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
2861 XtSetArg (al[ac], XtNborderWidth, 0); ac++;
2862 XtSetValues (pane_widget, al, ac);
2863 f->output_data.x->column_widget = pane_widget;
2865 /* mappedWhenManaged to false tells to the paned window to not map/unmap
2866 the emacs screen when changing menubar. This reduces flickering. */
2868 ac = 0;
2869 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
2870 XtSetArg (al[ac], (char *) XtNshowGrip, 0); ac++;
2871 XtSetArg (al[ac], (char *) XtNallowResize, 1); ac++;
2872 XtSetArg (al[ac], (char *) XtNresizeToPreferred, 1); ac++;
2873 XtSetArg (al[ac], (char *) XtNemacsFrame, f); ac++;
2874 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
2875 XtSetArg (al[ac], XtNdepth, FRAME_DISPLAY_INFO (f)->n_planes); ac++;
2876 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
2877 XtSetArg (al[ac], XtNborderWidth, 0); ac++;
2878 frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass, pane_widget,
2879 al, ac);
2881 f->output_data.x->edit_widget = frame_widget;
2883 XtManageChild (frame_widget);
2885 /* Do some needed geometry management. */
2887 Arg gal[3];
2888 int gac = 0;
2889 int extra_borders = 0;
2890 int menubar_size
2891 = (f->output_data.x->menubar_widget
2892 ? (f->output_data.x->menubar_widget->core.height
2893 + f->output_data.x->menubar_widget->core.border_width)
2894 : 0);
2896 #if false /* Experimentally, we now get the right results
2897 for -geometry -0-0 without this. 24 Aug 96, rms. */
2898 if (FRAME_EXTERNAL_MENU_BAR (f))
2900 Dimension ibw = 0;
2901 XtVaGetValues (pane_widget, XtNinternalBorderWidth, &ibw, NULL);
2902 menubar_size += ibw;
2904 #endif
2906 FRAME_MENUBAR_HEIGHT (f) = menubar_size;
2908 #ifndef USE_LUCID
2909 /* Motif seems to need this amount added to the sizes
2910 specified for the shell widget. The Athena/Lucid widgets don't.
2911 Both conclusions reached experimentally. -- rms. */
2912 XtVaGetValues (f->output_data.x->edit_widget, XtNinternalBorderWidth,
2913 &extra_borders, NULL);
2914 extra_borders *= 2;
2915 #endif
2917 f->shell_position = xmalloc (sizeof "=x++" + 4 * INT_STRLEN_BOUND (int));
2919 /* Convert our geometry parameters into a geometry string
2920 and specify it.
2921 Note that we do not specify here whether the position
2922 is a user-specified or program-specified one.
2923 We pass that information later, in x_wm_set_size_hint. */
2925 int left = f->left_pos;
2926 bool xneg = (window_prompting & XNegative) != 0;
2927 int top = f->top_pos;
2928 bool yneg = (window_prompting & YNegative) != 0;
2929 if (xneg)
2930 left = -left;
2931 if (yneg)
2932 top = -top;
2934 if (window_prompting & USPosition)
2935 sprintf (f->shell_position, "=%dx%d%c%d%c%d",
2936 FRAME_PIXEL_WIDTH (f) + extra_borders,
2937 FRAME_PIXEL_HEIGHT (f) + menubar_size + extra_borders,
2938 (xneg ? '-' : '+'), left,
2939 (yneg ? '-' : '+'), top);
2940 else
2942 sprintf (f->shell_position, "=%dx%d",
2943 FRAME_PIXEL_WIDTH (f) + extra_borders,
2944 FRAME_PIXEL_HEIGHT (f) + menubar_size + extra_borders);
2946 /* Setting x and y when the position is not specified in
2947 the geometry string will set program position in the WM hints.
2948 If Emacs had just one program position, we could set it in
2949 fallback resources, but since each make-frame call can specify
2950 different program positions, this is easier. */
2951 XtSetArg (gal[gac], XtNx, left); gac++;
2952 XtSetArg (gal[gac], XtNy, top); gac++;
2956 XtSetArg (gal[gac], XtNgeometry, f->shell_position); gac++;
2957 XtSetValues (shell_widget, gal, gac);
2960 XtManageChild (pane_widget);
2961 XtRealizeWidget (shell_widget);
2963 if (FRAME_X_EMBEDDED_P (f))
2964 XReparentWindow (FRAME_X_DISPLAY (f), XtWindow (shell_widget),
2965 f->output_data.x->parent_desc, 0, 0);
2967 FRAME_X_WINDOW (f) = XtWindow (frame_widget);
2968 initial_set_up_x_back_buffer (f);
2969 validate_x_resource_name ();
2971 class_hints.res_name = SSDATA (Vx_resource_name);
2972 class_hints.res_class = SSDATA (Vx_resource_class);
2973 XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints);
2975 #ifdef HAVE_X_I18N
2976 FRAME_XIC (f) = NULL;
2977 if (use_xim)
2978 create_frame_xic (f);
2979 #endif
2981 f->output_data.x->wm_hints.input = True;
2982 f->output_data.x->wm_hints.flags |= InputHint;
2983 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2984 &f->output_data.x->wm_hints);
2986 hack_wm_protocols (f, shell_widget);
2988 #ifdef X_TOOLKIT_EDITRES
2989 XtAddEventHandler (shell_widget, 0, True, _XEditResCheckMessages, 0);
2990 #endif
2992 /* Do a stupid property change to force the server to generate a
2993 PropertyNotify event so that the event_stream server timestamp will
2994 be initialized to something relevant to the time we created the window.
2996 XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
2997 FRAME_DISPLAY_INFO (f)->Xatom_wm_protocols,
2998 XA_ATOM, 32, PropModeAppend, NULL, 0);
3000 /* Make all the standard events reach the Emacs frame. */
3001 attributes.event_mask = STANDARD_EVENT_SET;
3003 #ifdef HAVE_X_I18N
3004 if (FRAME_XIC (f))
3006 /* XIM server might require some X events. */
3007 unsigned long fevent = NoEventMask;
3008 XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
3009 attributes.event_mask |= fevent;
3011 #endif /* HAVE_X_I18N */
3013 attributes.override_redirect = FRAME_OVERRIDE_REDIRECT (f);
3014 attribute_mask = CWEventMask | CWOverrideRedirect;
3015 XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
3016 attribute_mask, &attributes);
3018 XtMapWidget (frame_widget);
3020 /* x_set_name normally ignores requests to set the name if the
3021 requested name is the same as the current name. This is the one
3022 place where that assumption isn't correct; f->name is set, but
3023 the X server hasn't been told. */
3025 Lisp_Object name;
3026 bool explicit = f->explicit_name;
3028 f->explicit_name = false;
3029 name = f->name;
3030 fset_name (f, Qnil);
3031 x_set_name (f, name, explicit);
3034 if (FRAME_UNDECORATED (f))
3036 Display *dpy = FRAME_X_DISPLAY (f);
3037 PropMotifWmHints hints;
3038 Atom prop = XInternAtom (dpy, "_MOTIF_WM_HINTS", False);
3040 memset (&hints, 0, sizeof(hints));
3041 hints.flags = MWM_HINTS_DECORATIONS;
3042 hints.decorations = 0;
3044 /* For some reason the third and fourth arguments in the following
3045 call must be identical: In the corresponding XGetWindowProperty
3046 call in getMotifHints, xfwm has the third and seventh args both
3047 display_info->atoms[MOTIF_WM_HINTS]. Obviously, YMMV. */
3048 XChangeProperty (dpy, FRAME_OUTER_WINDOW (f), prop, prop, 32,
3049 PropModeReplace, (unsigned char *) &hints,
3050 PROP_MOTIF_WM_HINTS_ELEMENTS);
3053 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3054 f->output_data.x->current_cursor
3055 = f->output_data.x->text_cursor);
3057 unblock_input ();
3059 /* This is a no-op, except under Motif. Make sure main areas are
3060 set to something reasonable, in case we get an error later. */
3061 lw_set_main_areas (pane_widget, 0, frame_widget);
3064 #else /* not USE_X_TOOLKIT */
3065 #ifdef USE_GTK
3066 static void
3067 x_window (struct frame *f)
3069 if (! xg_create_frame_widgets (f))
3070 error ("Unable to create window");
3072 #ifdef HAVE_X_I18N
3073 FRAME_XIC (f) = NULL;
3074 if (use_xim)
3076 block_input ();
3077 create_frame_xic (f);
3078 if (FRAME_XIC (f))
3080 /* XIM server might require some X events. */
3081 unsigned long fevent = NoEventMask;
3082 XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
3084 if (fevent != NoEventMask)
3086 XSetWindowAttributes attributes;
3087 XWindowAttributes wattr;
3088 unsigned long attribute_mask;
3090 XGetWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3091 &wattr);
3092 attributes.event_mask = wattr.your_event_mask | fevent;
3093 attribute_mask = CWEventMask;
3094 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3095 attribute_mask, &attributes);
3098 unblock_input ();
3100 #endif
3103 #else /*! USE_GTK */
3104 /* Create and set up the X window for frame F. */
3106 static void
3107 x_window (struct frame *f)
3109 XClassHint class_hints;
3110 XSetWindowAttributes attributes;
3111 unsigned long attribute_mask;
3113 attributes.background_pixel = FRAME_BACKGROUND_PIXEL (f);
3114 attributes.border_pixel = f->output_data.x->border_pixel;
3115 attributes.bit_gravity = StaticGravity;
3116 attributes.backing_store = NotUseful;
3117 attributes.save_under = True;
3118 attributes.event_mask = STANDARD_EVENT_SET;
3119 attributes.colormap = FRAME_X_COLORMAP (f);
3120 attributes.override_redirect = FRAME_OVERRIDE_REDIRECT (f);
3121 attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask
3122 | CWOverrideRedirect | CWColormap);
3124 block_input ();
3125 FRAME_X_WINDOW (f)
3126 = XCreateWindow (FRAME_X_DISPLAY (f),
3127 f->output_data.x->parent_desc,
3128 f->left_pos,
3129 f->top_pos,
3130 FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f),
3131 f->border_width,
3132 CopyFromParent, /* depth */
3133 InputOutput, /* class */
3134 FRAME_X_VISUAL (f),
3135 attribute_mask, &attributes);
3136 initial_set_up_x_back_buffer (f);
3138 #ifdef HAVE_X_I18N
3139 if (use_xim)
3141 create_frame_xic (f);
3142 if (FRAME_XIC (f))
3144 /* XIM server might require some X events. */
3145 unsigned long fevent = NoEventMask;
3146 XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
3147 attributes.event_mask |= fevent;
3148 attribute_mask = CWEventMask;
3149 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3150 attribute_mask, &attributes);
3153 #endif /* HAVE_X_I18N */
3155 validate_x_resource_name ();
3157 class_hints.res_name = SSDATA (Vx_resource_name);
3158 class_hints.res_class = SSDATA (Vx_resource_class);
3159 XSetClassHint (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &class_hints);
3161 /* This indicates that we use the "Passive Input" input model.
3162 Unless we do this, we don't get the Focus{In,Out} events that we
3163 need to draw the cursor correctly. Accursed bureaucrats.
3164 XWhipsAndChains (FRAME_X_DISPLAY (f), IronMaiden, &TheRack); */
3166 f->output_data.x->wm_hints.input = True;
3167 f->output_data.x->wm_hints.flags |= InputHint;
3168 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3169 &f->output_data.x->wm_hints);
3170 f->output_data.x->wm_hints.icon_pixmap = None;
3172 /* Request "save yourself" and "delete window" commands from wm. */
3174 Atom protocols[2];
3175 protocols[0] = FRAME_DISPLAY_INFO (f)->Xatom_wm_delete_window;
3176 protocols[1] = FRAME_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
3177 XSetWMProtocols (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), protocols, 2);
3180 /* x_set_name normally ignores requests to set the name if the
3181 requested name is the same as the current name. This is the one
3182 place where that assumption isn't correct; f->name is set, but
3183 the X server hasn't been told. */
3185 Lisp_Object name;
3186 bool explicit = f->explicit_name;
3188 f->explicit_name = false;
3189 name = f->name;
3190 fset_name (f, Qnil);
3191 x_set_name (f, name, explicit);
3194 if (FRAME_UNDECORATED (f))
3196 Display *dpy = FRAME_X_DISPLAY (f);
3197 PropMotifWmHints hints;
3198 Atom prop = XInternAtom (dpy, "_MOTIF_WM_HINTS", False);
3200 memset (&hints, 0, sizeof(hints));
3201 hints.flags = MWM_HINTS_DECORATIONS;
3202 hints.decorations = 0;
3204 /* For some reason the third and fourth arguments in the following
3205 call must be identical: In the corresponding XGetWindowProperty
3206 call in getMotifHints, xfwm has the third and seventh args both
3207 display_info->atoms[MOTIF_WM_HINTS]. Obviously, YMMV. */
3208 XChangeProperty (dpy, FRAME_OUTER_WINDOW (f), prop, prop, 32,
3209 PropModeReplace, (unsigned char *) &hints,
3210 PROP_MOTIF_WM_HINTS_ELEMENTS);
3214 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3215 f->output_data.x->current_cursor
3216 = f->output_data.x->text_cursor);
3218 unblock_input ();
3220 if (FRAME_X_WINDOW (f) == 0)
3221 error ("Unable to create window");
3224 #endif /* not USE_GTK */
3225 #endif /* not USE_X_TOOLKIT */
3227 /* Verify that the icon position args for this window are valid. */
3229 static void
3230 x_icon_verify (struct frame *f, Lisp_Object parms)
3232 Lisp_Object icon_x, icon_y;
3234 /* Set the position of the icon. Note that twm groups all
3235 icons in an icon window. */
3236 icon_x = x_frame_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
3237 icon_y = x_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
3238 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
3240 CHECK_NUMBER (icon_x);
3241 CHECK_NUMBER (icon_y);
3243 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
3244 error ("Both left and top icon corners of icon must be specified");
3247 /* Handle the icon stuff for this window. Perhaps later we might
3248 want an x_set_icon_position which can be called interactively as
3249 well. */
3251 static void
3252 x_icon (struct frame *f, Lisp_Object parms)
3254 /* Set the position of the icon. Note that twm groups all
3255 icons in an icon window. */
3256 Lisp_Object icon_x
3257 = x_frame_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
3258 Lisp_Object icon_y
3259 = x_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
3260 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
3262 CHECK_TYPE_RANGED_INTEGER (int, icon_x);
3263 CHECK_TYPE_RANGED_INTEGER (int, icon_y);
3265 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
3266 error ("Both left and top icon corners of icon must be specified");
3268 block_input ();
3270 if (! EQ (icon_x, Qunbound))
3271 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
3273 #if false /* x_get_arg removes the visibility parameter as a side effect,
3274 but x_create_frame still needs it. */
3275 /* Start up iconic or window? */
3276 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
3277 x_wm_set_window_state
3278 (f, (EQ (x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL),
3279 Qicon)
3280 ? IconicState
3281 : NormalState));
3282 #endif
3284 x_text_icon (f, SSDATA ((!NILP (f->icon_name)
3285 ? f->icon_name
3286 : f->name)));
3288 unblock_input ();
3291 /* Make the GCs needed for this window, setting the
3292 background, border and mouse colors; also create the
3293 mouse cursor and the gray border tile. */
3295 static void
3296 x_make_gc (struct frame *f)
3298 XGCValues gc_values;
3300 block_input ();
3302 /* Create the GCs of this frame.
3303 Note that many default values are used. */
3305 gc_values.foreground = FRAME_FOREGROUND_PIXEL (f);
3306 gc_values.background = FRAME_BACKGROUND_PIXEL (f);
3307 gc_values.line_width = 0; /* Means 1 using fast algorithm. */
3308 f->output_data.x->normal_gc
3309 = XCreateGC (FRAME_X_DISPLAY (f),
3310 FRAME_X_DRAWABLE (f),
3311 GCLineWidth | GCForeground | GCBackground,
3312 &gc_values);
3314 /* Reverse video style. */
3315 gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
3316 gc_values.background = FRAME_FOREGROUND_PIXEL (f);
3317 f->output_data.x->reverse_gc
3318 = XCreateGC (FRAME_X_DISPLAY (f),
3319 FRAME_X_DRAWABLE (f),
3320 GCForeground | GCBackground | GCLineWidth,
3321 &gc_values);
3323 /* Cursor has cursor-color background, background-color foreground. */
3324 gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
3325 gc_values.background = f->output_data.x->cursor_pixel;
3326 gc_values.fill_style = FillOpaqueStippled;
3327 f->output_data.x->cursor_gc
3328 = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
3329 (GCForeground | GCBackground
3330 | GCFillStyle | GCLineWidth),
3331 &gc_values);
3333 /* Create the gray border tile used when the pointer is not in
3334 the frame. Since this depends on the frame's pixel values,
3335 this must be done on a per-frame basis. */
3336 f->output_data.x->border_tile
3337 = (XCreatePixmapFromBitmapData
3338 (FRAME_X_DISPLAY (f), FRAME_DISPLAY_INFO (f)->root_window,
3339 gray_bits, gray_width, gray_height,
3340 FRAME_FOREGROUND_PIXEL (f),
3341 FRAME_BACKGROUND_PIXEL (f),
3342 DefaultDepth (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f))));
3344 unblock_input ();
3348 /* Free what was allocated in x_make_gc. */
3350 void
3351 x_free_gcs (struct frame *f)
3353 Display *dpy = FRAME_X_DISPLAY (f);
3355 block_input ();
3357 if (f->output_data.x->normal_gc)
3359 XFreeGC (dpy, f->output_data.x->normal_gc);
3360 f->output_data.x->normal_gc = 0;
3363 if (f->output_data.x->reverse_gc)
3365 XFreeGC (dpy, f->output_data.x->reverse_gc);
3366 f->output_data.x->reverse_gc = 0;
3369 if (f->output_data.x->cursor_gc)
3371 XFreeGC (dpy, f->output_data.x->cursor_gc);
3372 f->output_data.x->cursor_gc = 0;
3375 if (f->output_data.x->border_tile)
3377 XFreePixmap (dpy, f->output_data.x->border_tile);
3378 f->output_data.x->border_tile = 0;
3381 unblock_input ();
3385 /* Handler for signals raised during x_create_frame and
3386 x_create_tip_frame. FRAME is the frame which is partially
3387 constructed. */
3389 static Lisp_Object
3390 unwind_create_frame (Lisp_Object frame)
3392 struct frame *f = XFRAME (frame);
3394 /* If frame is already dead, nothing to do. This can happen if the
3395 display is disconnected after the frame has become official, but
3396 before x_create_frame removes the unwind protect. */
3397 if (!FRAME_LIVE_P (f))
3398 return Qnil;
3400 /* If frame is ``official'', nothing to do. */
3401 if (NILP (Fmemq (frame, Vframe_list)))
3403 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
3404 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
3405 #endif
3407 /* If the frame's image cache refcount is still the same as our
3408 private shadow variable, it means we are unwinding a frame
3409 for which we didn't yet call init_frame_faces, where the
3410 refcount is incremented. Therefore, we increment it here, so
3411 that free_frame_faces, called in x_free_frame_resources
3412 below, will not mistakenly decrement the counter that was not
3413 incremented yet to account for this new frame. */
3414 if (FRAME_IMAGE_CACHE (f) != NULL
3415 && FRAME_IMAGE_CACHE (f)->refcount == image_cache_refcount)
3416 FRAME_IMAGE_CACHE (f)->refcount++;
3418 x_free_frame_resources (f);
3419 free_glyphs (f);
3421 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
3422 /* Check that reference counts are indeed correct. */
3423 eassert (dpyinfo->reference_count == dpyinfo_refcount);
3424 eassert (dpyinfo->terminal->image_cache->refcount == image_cache_refcount);
3425 #endif
3426 return Qt;
3429 return Qnil;
3432 static void
3433 do_unwind_create_frame (Lisp_Object frame)
3435 unwind_create_frame (frame);
3438 static void
3439 x_default_font_parameter (struct frame *f, Lisp_Object parms)
3441 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
3442 Lisp_Object font_param = x_get_arg (dpyinfo, parms, Qfont, NULL, NULL,
3443 RES_TYPE_STRING);
3444 Lisp_Object font = Qnil;
3445 if (EQ (font_param, Qunbound))
3446 font_param = Qnil;
3448 if (NILP (font_param))
3450 /* System font should take precedence over X resources. We suggest this
3451 regardless of font-use-system-font because .emacs may not have been
3452 read yet. */
3453 const char *system_font = xsettings_get_system_font ();
3454 if (system_font)
3455 font = font_open_by_name (f, build_unibyte_string (system_font));
3458 if (NILP (font))
3459 font = !NILP (font_param) ? font_param
3460 : x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
3462 if (! FONTP (font) && ! STRINGP (font))
3464 const char *names[]
3466 #ifdef HAVE_XFT
3467 /* This will find the normal Xft font. */
3468 "monospace-10",
3469 #endif
3470 "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1",
3471 "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1",
3472 "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1",
3473 /* This was formerly the first thing tried, but it finds
3474 too many fonts and takes too long. */
3475 "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1",
3476 /* If those didn't work, look for something which will
3477 at least work. */
3478 "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1",
3479 "fixed",
3480 NULL };
3481 int i;
3483 for (i = 0; names[i]; i++)
3485 font = font_open_by_name (f, build_unibyte_string (names[i]));
3486 if (! NILP (font))
3487 break;
3489 if (NILP (font))
3490 error ("No suitable font was found");
3492 else if (!NILP (font_param))
3494 /* Remember the explicit font parameter, so we can re-apply it after
3495 we've applied the `default' face settings. */
3496 AUTO_FRAME_ARG (arg, Qfont_parameter, font_param);
3497 x_set_frame_parameters (f, arg);
3500 /* This call will make X resources override any system font setting. */
3501 x_default_parameter (f, parms, Qfont, font, "font", "Font", RES_TYPE_STRING);
3505 DEFUN ("x-wm-set-size-hint", Fx_wm_set_size_hint, Sx_wm_set_size_hint,
3506 0, 1, 0,
3507 doc: /* Send the size hints for frame FRAME to the window manager.
3508 If FRAME is omitted or nil, use the selected frame.
3509 Signal error if FRAME is not an X frame. */)
3510 (Lisp_Object frame)
3512 struct frame *f = decode_window_system_frame (frame);
3514 block_input ();
3515 x_wm_set_size_hint (f, 0, false);
3516 unblock_input ();
3517 return Qnil;
3520 static void
3521 set_machine_and_pid_properties (struct frame *f)
3523 /* This will set WM_CLIENT_MACHINE and WM_LOCALE_NAME. */
3524 XSetWMProperties (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), NULL, NULL,
3525 NULL, 0, NULL, NULL, NULL);
3526 pid_t pid = getpid ();
3527 if (pid <= 0xffffffffu)
3529 unsigned long xpid = pid;
3530 XChangeProperty (FRAME_X_DISPLAY (f),
3531 FRAME_OUTER_WINDOW (f),
3532 XInternAtom (FRAME_X_DISPLAY (f),
3533 "_NET_WM_PID",
3534 False),
3535 XA_CARDINAL, 32, PropModeReplace,
3536 (unsigned char *) &xpid, 1);
3540 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
3541 1, 1, 0,
3542 doc: /* Make a new X window, which is called a "frame" in Emacs terms.
3543 Return an Emacs frame object. PARMS is an alist of frame parameters.
3544 If the parameters specify that the frame should not have a minibuffer,
3545 and do not specify a specific minibuffer window to use, then
3546 `default-minibuffer-frame' must be a frame whose minibuffer can be
3547 shared by the new frame.
3549 This function is an internal primitive--use `make-frame' instead. */)
3550 (Lisp_Object parms)
3552 struct frame *f;
3553 Lisp_Object frame, tem;
3554 Lisp_Object name;
3555 bool minibuffer_only = false;
3556 bool undecorated = false, override_redirect = false;
3557 long window_prompting = 0;
3558 ptrdiff_t count = SPECPDL_INDEX ();
3559 Lisp_Object display;
3560 struct x_display_info *dpyinfo = NULL;
3561 Lisp_Object parent, parent_frame;
3562 struct kboard *kb;
3563 int x_width = 0, x_height = 0;
3565 parms = Fcopy_alist (parms);
3567 /* Use this general default value to start with
3568 until we know if this frame has a specified name. */
3569 Vx_resource_name = Vinvocation_name;
3571 display = x_get_arg (dpyinfo, parms, Qterminal, 0, 0, RES_TYPE_NUMBER);
3572 if (EQ (display, Qunbound))
3573 display = x_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING);
3574 if (EQ (display, Qunbound))
3575 display = Qnil;
3576 dpyinfo = check_x_display_info (display);
3577 kb = dpyinfo->terminal->kboard;
3579 if (!dpyinfo->terminal->name)
3580 error ("Terminal is not live, can't create new frames on it");
3582 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
3583 if (!STRINGP (name)
3584 && ! EQ (name, Qunbound)
3585 && ! NILP (name))
3586 error ("Invalid frame name--not a string or nil");
3588 if (STRINGP (name))
3589 Vx_resource_name = name;
3591 /* See if parent window is specified. */
3592 parent = x_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
3593 if (EQ (parent, Qunbound))
3594 parent = Qnil;
3595 if (! NILP (parent))
3596 CHECK_NUMBER (parent);
3598 frame = Qnil;
3599 tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
3600 RES_TYPE_SYMBOL);
3601 if (EQ (tem, Qnone) || NILP (tem))
3602 f = make_frame_without_minibuffer (Qnil, kb, display);
3603 else if (EQ (tem, Qonly))
3605 f = make_minibuffer_frame ();
3606 minibuffer_only = true;
3608 else if (WINDOWP (tem))
3609 f = make_frame_without_minibuffer (tem, kb, display);
3610 else
3611 f = make_frame (true);
3613 parent_frame = x_get_arg (dpyinfo, parms, Qparent_frame, NULL, NULL,
3614 RES_TYPE_SYMBOL);
3615 /* Accept parent-frame iff parent-id was not specified. */
3616 if (!NILP (parent)
3617 || EQ (parent_frame, Qunbound)
3618 || NILP (parent_frame)
3619 || !FRAMEP (parent_frame)
3620 || !FRAME_LIVE_P (XFRAME (parent_frame))
3621 || !FRAME_X_P (XFRAME (parent_frame)))
3622 parent_frame = Qnil;
3624 fset_parent_frame (f, parent_frame);
3625 store_frame_param (f, Qparent_frame, parent_frame);
3627 if (!NILP (tem = (x_get_arg (dpyinfo, parms, Qundecorated, NULL, NULL,
3628 RES_TYPE_BOOLEAN)))
3629 && !(EQ (tem, Qunbound)))
3630 undecorated = true;
3632 FRAME_UNDECORATED (f) = undecorated;
3633 store_frame_param (f, Qundecorated, undecorated ? Qt : Qnil);
3635 if (!NILP (tem = (x_get_arg (dpyinfo, parms, Qoverride_redirect, NULL, NULL,
3636 RES_TYPE_BOOLEAN)))
3637 && !(EQ (tem, Qunbound)))
3638 override_redirect = true;
3640 FRAME_OVERRIDE_REDIRECT (f) = override_redirect;
3641 store_frame_param (f, Qoverride_redirect, override_redirect ? Qt : Qnil);
3643 XSETFRAME (frame, f);
3645 f->terminal = dpyinfo->terminal;
3647 f->output_method = output_x_window;
3648 f->output_data.x = xzalloc (sizeof *f->output_data.x);
3649 f->output_data.x->icon_bitmap = -1;
3650 FRAME_FONTSET (f) = -1;
3651 f->output_data.x->scroll_bar_foreground_pixel = -1;
3652 f->output_data.x->scroll_bar_background_pixel = -1;
3653 #if defined (USE_LUCID) && defined (USE_TOOLKIT_SCROLL_BARS)
3654 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
3655 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
3656 #endif /* USE_LUCID && USE_TOOLKIT_SCROLL_BARS */
3657 f->output_data.x->white_relief.pixel = -1;
3658 f->output_data.x->black_relief.pixel = -1;
3660 fset_icon_name (f,
3661 x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
3662 RES_TYPE_STRING));
3663 if (! STRINGP (f->icon_name))
3664 fset_icon_name (f, Qnil);
3666 FRAME_DISPLAY_INFO (f) = dpyinfo;
3668 /* With FRAME_DISPLAY_INFO set up, this unwind-protect is safe. */
3669 record_unwind_protect (do_unwind_create_frame, frame);
3671 /* These colors will be set anyway later, but it's important
3672 to get the color reference counts right, so initialize them! */
3674 Lisp_Object black;
3676 /* Function x_decode_color can signal an error. Make
3677 sure to initialize color slots so that we won't try
3678 to free colors we haven't allocated. */
3679 FRAME_FOREGROUND_PIXEL (f) = -1;
3680 FRAME_BACKGROUND_PIXEL (f) = -1;
3681 f->output_data.x->cursor_pixel = -1;
3682 f->output_data.x->cursor_foreground_pixel = -1;
3683 f->output_data.x->border_pixel = -1;
3684 f->output_data.x->mouse_pixel = -1;
3686 black = build_string ("black");
3687 FRAME_FOREGROUND_PIXEL (f)
3688 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3689 FRAME_BACKGROUND_PIXEL (f)
3690 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3691 f->output_data.x->cursor_pixel
3692 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3693 f->output_data.x->cursor_foreground_pixel
3694 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3695 f->output_data.x->border_pixel
3696 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3697 f->output_data.x->mouse_pixel
3698 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3701 /* Specify the parent under which to make this X window. */
3702 if (!NILP (parent))
3704 f->output_data.x->parent_desc = (Window) XFASTINT (parent);
3705 f->output_data.x->explicit_parent = true;
3707 else
3709 f->output_data.x->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
3710 f->output_data.x->explicit_parent = false;
3713 /* Set the name; the functions to which we pass f expect the name to
3714 be set. */
3715 if (EQ (name, Qunbound) || NILP (name))
3717 fset_name (f, build_string (dpyinfo->x_id_name));
3718 f->explicit_name = false;
3720 else
3722 fset_name (f, name);
3723 f->explicit_name = true;
3724 /* Use the frame's title when getting resources for this frame. */
3725 specbind (Qx_resource_name, name);
3728 #ifdef USE_CAIRO
3729 register_font_driver (&ftcrfont_driver, f);
3730 #else
3731 #ifdef HAVE_FREETYPE
3732 #ifdef HAVE_XFT
3733 register_font_driver (&xftfont_driver, f);
3734 #else /* not HAVE_XFT */
3735 register_font_driver (&ftxfont_driver, f);
3736 #endif /* not HAVE_XFT */
3737 #endif /* HAVE_FREETYPE */
3738 register_font_driver (&xfont_driver, f);
3739 #endif /* not USE_CAIRO */
3741 image_cache_refcount =
3742 FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
3743 #ifdef GLYPH_DEBUG
3744 dpyinfo_refcount = dpyinfo->reference_count;
3745 #endif /* GLYPH_DEBUG */
3747 x_default_parameter (f, parms, Qfont_backend, Qnil,
3748 "fontBackend", "FontBackend", RES_TYPE_STRING);
3750 /* Extract the window parameters from the supplied values
3751 that are needed to determine window geometry. */
3752 x_default_font_parameter (f, parms);
3753 if (!FRAME_FONT (f))
3755 delete_frame (frame, Qnoelisp);
3756 error ("Invalid frame font");
3759 /* Frame contents get displaced if an embedded X window has a border. */
3760 if (! FRAME_X_EMBEDDED_P (f))
3761 x_default_parameter (f, parms, Qborder_width, make_number (0),
3762 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
3764 /* This defaults to 1 in order to match xterm. We recognize either
3765 internalBorderWidth or internalBorder (which is what xterm calls
3766 it). */
3767 if (NILP (Fassq (Qinternal_border_width, parms)))
3769 Lisp_Object value;
3771 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
3772 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
3773 if (! EQ (value, Qunbound))
3774 parms = Fcons (Fcons (Qinternal_border_width, value),
3775 parms);
3777 x_default_parameter (f, parms, Qinternal_border_width,
3778 #ifdef USE_GTK /* We used to impose 0 in xg_create_frame_widgets. */
3779 make_number (0),
3780 #else
3781 make_number (1),
3782 #endif
3783 "internalBorderWidth", "internalBorderWidth",
3784 RES_TYPE_NUMBER);
3785 x_default_parameter (f, parms, Qright_divider_width, make_number (0),
3786 NULL, NULL, RES_TYPE_NUMBER);
3787 x_default_parameter (f, parms, Qbottom_divider_width, make_number (0),
3788 NULL, NULL, RES_TYPE_NUMBER);
3789 x_default_parameter (f, parms, Qvertical_scroll_bars,
3790 #if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
3791 Qright,
3792 #else
3793 Qleft,
3794 #endif
3795 "verticalScrollBars", "ScrollBars",
3796 RES_TYPE_SYMBOL);
3797 x_default_parameter (f, parms, Qhorizontal_scroll_bars, Qnil,
3798 "horizontalScrollBars", "ScrollBars",
3799 RES_TYPE_SYMBOL);
3800 /* Also do the stuff which must be set before the window exists. */
3801 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
3802 "foreground", "Foreground", RES_TYPE_STRING);
3803 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
3804 "background", "Background", RES_TYPE_STRING);
3805 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
3806 "pointerColor", "Foreground", RES_TYPE_STRING);
3807 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
3808 "borderColor", "BorderColor", RES_TYPE_STRING);
3809 x_default_parameter (f, parms, Qscreen_gamma, Qnil,
3810 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
3811 x_default_parameter (f, parms, Qline_spacing, Qnil,
3812 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
3813 x_default_parameter (f, parms, Qleft_fringe, Qnil,
3814 "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
3815 x_default_parameter (f, parms, Qright_fringe, Qnil,
3816 "rightFringe", "RightFringe", RES_TYPE_NUMBER);
3818 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
3819 "scrollBarForeground",
3820 "ScrollBarForeground", true);
3821 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_background,
3822 "scrollBarBackground",
3823 "ScrollBarBackground", false);
3825 /* Init faces before x_default_parameter is called for the
3826 scroll-bar-width parameter because otherwise we end up in
3827 init_iterator with a null face cache, which should not happen. */
3828 init_frame_faces (f);
3830 /* We have to call adjust_frame_size here since otherwise
3831 x_set_tool_bar_lines will already work with the character sizes
3832 installed by init_frame_faces while the frame's pixel size is still
3833 calculated from a character size of 1 and we subsequently hit the
3834 (height >= 0) assertion in window_box_height.
3836 The non-pixelwise code apparently worked around this because it
3837 had one frame line vs one toolbar line which left us with a zero
3838 root window height which was obviously wrong as well ...
3840 Also process `min-width' and `min-height' parameters right here
3841 because `frame-windows-min-size' needs them. */
3842 tem = x_get_arg (dpyinfo, parms, Qmin_width, NULL, NULL, RES_TYPE_NUMBER);
3843 if (NUMBERP (tem))
3844 store_frame_param (f, Qmin_width, tem);
3845 tem = x_get_arg (dpyinfo, parms, Qmin_height, NULL, NULL, RES_TYPE_NUMBER);
3846 if (NUMBERP (tem))
3847 store_frame_param (f, Qmin_height, tem);
3848 adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
3849 FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, true,
3850 Qx_create_frame_1);
3852 /* Set the menu-bar-lines and tool-bar-lines parameters. We don't
3853 look up the X resources controlling the menu-bar and tool-bar
3854 here; they are processed specially at startup, and reflected in
3855 the values of the mode variables. */
3857 x_default_parameter (f, parms, Qmenu_bar_lines,
3858 NILP (Vmenu_bar_mode)
3859 ? make_number (0) : make_number (1),
3860 NULL, NULL, RES_TYPE_NUMBER);
3861 x_default_parameter (f, parms, Qtool_bar_lines,
3862 NILP (Vtool_bar_mode)
3863 ? make_number (0) : make_number (1),
3864 NULL, NULL, RES_TYPE_NUMBER);
3866 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
3867 "bufferPredicate", "BufferPredicate",
3868 RES_TYPE_SYMBOL);
3869 x_default_parameter (f, parms, Qtitle, Qnil,
3870 "title", "Title", RES_TYPE_STRING);
3871 x_default_parameter (f, parms, Qwait_for_wm, Qt,
3872 "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN);
3873 x_default_parameter (f, parms, Qtool_bar_position,
3874 FRAME_TOOL_BAR_POSITION (f), 0, 0, RES_TYPE_SYMBOL);
3875 x_default_parameter (f, parms, Qinhibit_double_buffering, Qnil,
3876 "inhibitDoubleBuffering", "InhibitDoubleBuffering",
3877 RES_TYPE_BOOLEAN);
3879 /* Compute the size of the X window. */
3880 window_prompting = x_figure_window_size (f, parms, true, &x_width, &x_height);
3882 tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
3883 f->no_split = minibuffer_only || EQ (tem, Qt);
3885 x_icon_verify (f, parms);
3887 /* Create the X widget or window. */
3888 #ifdef USE_X_TOOLKIT
3889 x_window (f, window_prompting);
3890 #else
3891 x_window (f);
3892 #endif
3894 x_icon (f, parms);
3895 x_make_gc (f);
3897 /* Now consider the frame official. */
3898 f->terminal->reference_count++;
3899 FRAME_DISPLAY_INFO (f)->reference_count++;
3900 Vframe_list = Fcons (frame, Vframe_list);
3902 /* We need to do this after creating the X window, so that the
3903 icon-creation functions can say whose icon they're describing. */
3904 x_default_parameter (f, parms, Qicon_type, Qt,
3905 "bitmapIcon", "BitmapIcon", RES_TYPE_BOOLEAN);
3907 x_default_parameter (f, parms, Qauto_raise, Qnil,
3908 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
3909 x_default_parameter (f, parms, Qauto_lower, Qnil,
3910 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
3911 x_default_parameter (f, parms, Qcursor_type, Qbox,
3912 "cursorType", "CursorType", RES_TYPE_SYMBOL);
3913 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
3914 "scrollBarWidth", "ScrollBarWidth",
3915 RES_TYPE_NUMBER);
3916 x_default_parameter (f, parms, Qscroll_bar_height, Qnil,
3917 "scrollBarHeight", "ScrollBarHeight",
3918 RES_TYPE_NUMBER);
3919 x_default_parameter (f, parms, Qalpha, Qnil,
3920 "alpha", "Alpha", RES_TYPE_NUMBER);
3922 if (!NILP (parent_frame))
3924 struct frame *p = XFRAME (parent_frame);
3926 block_input ();
3927 XReparentWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
3928 FRAME_X_WINDOW (p), f->left_pos, f->top_pos);
3929 unblock_input ();
3932 x_default_parameter (f, parms, Qno_focus_on_map, Qnil,
3933 NULL, NULL, RES_TYPE_BOOLEAN);
3934 x_default_parameter (f, parms, Qno_accept_focus, Qnil,
3935 NULL, NULL, RES_TYPE_BOOLEAN);
3937 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
3938 /* Create the menu bar. */
3939 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
3941 /* If this signals an error, we haven't set size hints for the
3942 frame and we didn't make it visible. */
3943 initialize_frame_menubar (f);
3945 #ifndef USE_GTK
3946 /* This is a no-op, except under Motif where it arranges the
3947 main window for the widgets on it. */
3948 lw_set_main_areas (f->output_data.x->column_widget,
3949 f->output_data.x->menubar_widget,
3950 f->output_data.x->edit_widget);
3951 #endif /* not USE_GTK */
3953 #endif /* USE_X_TOOLKIT || USE_GTK */
3955 /* Consider frame official, now. */
3956 f->can_x_set_window_size = true;
3958 if (x_width > 0)
3959 SET_FRAME_WIDTH (f, x_width);
3960 if (x_height > 0)
3961 SET_FRAME_HEIGHT (f, x_height);
3963 /* Tell the server what size and position, etc, we want, and how
3964 badly we want them. This should be done after we have the menu
3965 bar so that its size can be taken into account. */
3966 block_input ();
3967 x_wm_set_size_hint (f, window_prompting, false);
3968 unblock_input ();
3970 adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
3971 0, true, Qx_create_frame_2);
3973 /* Process fullscreen parameter here in the hope that normalizing a
3974 fullheight/fullwidth frame will produce the size set by the last
3975 adjust_frame_size call. */
3976 x_default_parameter (f, parms, Qfullscreen, Qnil,
3977 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
3979 /* Make the window appear on the frame and enable display, unless
3980 the caller says not to. However, with explicit parent, Emacs
3981 cannot control visibility, so don't try. */
3982 if (!f->output_data.x->explicit_parent)
3984 Lisp_Object visibility
3985 = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
3987 if (EQ (visibility, Qicon))
3988 x_iconify_frame (f);
3989 else
3991 if (EQ (visibility, Qunbound))
3992 visibility = Qt;
3994 if (!NILP (visibility))
3995 x_make_frame_visible (f);
3998 store_frame_param (f, Qvisibility, visibility);
4001 block_input ();
4003 /* Set machine name and pid for the purpose of window managers. */
4004 set_machine_and_pid_properties (f);
4006 /* Set the WM leader property. GTK does this itself, so this is not
4007 needed when using GTK. */
4008 if (dpyinfo->client_leader_window != 0)
4010 XChangeProperty (FRAME_X_DISPLAY (f),
4011 FRAME_OUTER_WINDOW (f),
4012 dpyinfo->Xatom_wm_client_leader,
4013 XA_WINDOW, 32, PropModeReplace,
4014 (unsigned char *) &dpyinfo->client_leader_window, 1);
4017 unblock_input ();
4019 /* Works iff frame has been already mapped. */
4020 x_default_parameter (f, parms, Qskip_taskbar, Qnil,
4021 NULL, NULL, RES_TYPE_BOOLEAN);
4022 /* The `z-group' parameter works only for visible frames. */
4023 x_default_parameter (f, parms, Qz_group, Qnil,
4024 NULL, NULL, RES_TYPE_SYMBOL);
4026 /* Initialize `default-minibuffer-frame' in case this is the first
4027 frame on this terminal. */
4028 if (FRAME_HAS_MINIBUF_P (f)
4029 && (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame))
4030 || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame)))))
4031 kset_default_minibuffer_frame (kb, frame);
4033 /* All remaining specified parameters, which have not been "used"
4034 by x_get_arg and friends, now go in the misc. alist of the frame. */
4035 for (tem = parms; CONSP (tem); tem = XCDR (tem))
4036 if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
4037 fset_param_alist (f, Fcons (XCAR (tem), f->param_alist));
4039 /* Make sure windows on this frame appear in calls to next-window
4040 and similar functions. */
4041 Vwindow_list = Qnil;
4043 return unbind_to (count, frame);
4047 /* FRAME is used only to get a handle on the X display. We don't pass the
4048 display info directly because we're called from frame.c, which doesn't
4049 know about that structure. */
4051 Lisp_Object
4052 x_get_focus_frame (struct frame *frame)
4054 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame);
4055 Lisp_Object xfocus;
4056 if (! dpyinfo->x_focus_frame)
4057 return Qnil;
4059 XSETFRAME (xfocus, dpyinfo->x_focus_frame);
4060 return xfocus;
4064 /* In certain situations, when the window manager follows a
4065 click-to-focus policy, there seems to be no way around calling
4066 XSetInputFocus to give another frame the input focus .
4068 In an ideal world, XSetInputFocus should generally be avoided so
4069 that applications don't interfere with the window manager's focus
4070 policy. But I think it's okay to use when it's clearly done
4071 following a user-command. */
4073 void
4074 x_focus_frame (struct frame *f, bool noactivate)
4076 Display *dpy = FRAME_X_DISPLAY (f);
4078 block_input ();
4079 x_catch_errors (dpy);
4081 if (FRAME_X_EMBEDDED_P (f))
4083 /* For Xembedded frames, normally the embedder forwards key
4084 events. See XEmbed Protocol Specification at
4085 http://freedesktop.org/wiki/Specifications/xembed-spec */
4086 xembed_request_focus (f);
4088 else
4090 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4091 RevertToParent, CurrentTime);
4092 if (!noactivate)
4093 x_ewmh_activate_frame (f);
4096 x_uncatch_errors ();
4097 unblock_input ();
4101 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
4102 doc: /* Internal function called by `color-defined-p', which see.
4103 \(Note that the Nextstep version of this function ignores FRAME.) */)
4104 (Lisp_Object color, Lisp_Object frame)
4106 XColor foo;
4107 struct frame *f = decode_window_system_frame (frame);
4109 CHECK_STRING (color);
4111 if (x_defined_color (f, SSDATA (color), &foo, false))
4112 return Qt;
4113 else
4114 return Qnil;
4117 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
4118 doc: /* Internal function called by `color-values', which see. */)
4119 (Lisp_Object color, Lisp_Object frame)
4121 XColor foo;
4122 struct frame *f = decode_window_system_frame (frame);
4124 CHECK_STRING (color);
4126 if (x_defined_color (f, SSDATA (color), &foo, false))
4127 return list3i (foo.red, foo.green, foo.blue);
4128 else
4129 return Qnil;
4132 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
4133 doc: /* Internal function called by `display-color-p', which see. */)
4134 (Lisp_Object terminal)
4136 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4138 if (dpyinfo->n_planes <= 2)
4139 return Qnil;
4141 switch (dpyinfo->visual->class)
4143 case StaticColor:
4144 case PseudoColor:
4145 case TrueColor:
4146 case DirectColor:
4147 return Qt;
4149 default:
4150 return Qnil;
4154 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
4155 0, 1, 0,
4156 doc: /* Return t if the X display supports shades of gray.
4157 Note that color displays do support shades of gray.
4158 The optional argument TERMINAL specifies which display to ask about.
4159 TERMINAL should be a terminal object, a frame or a display name (a string).
4160 If omitted or nil, that stands for the selected frame's display. */)
4161 (Lisp_Object terminal)
4163 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4165 if (dpyinfo->n_planes <= 1)
4166 return Qnil;
4168 switch (dpyinfo->visual->class)
4170 case StaticColor:
4171 case PseudoColor:
4172 case TrueColor:
4173 case DirectColor:
4174 case StaticGray:
4175 case GrayScale:
4176 return Qt;
4178 default:
4179 return Qnil;
4183 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
4184 0, 1, 0,
4185 doc: /* Return the width in pixels of the X display TERMINAL.
4186 The optional argument TERMINAL specifies which display to ask about.
4187 TERMINAL should be a terminal object, a frame or a display name (a string).
4188 If omitted or nil, that stands for the selected frame's display.
4190 On \"multi-monitor\" setups this refers to the pixel width for all
4191 physical monitors associated with TERMINAL. To get information for
4192 each physical monitor, use `display-monitor-attributes-list'. */)
4193 (Lisp_Object terminal)
4195 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4197 return make_number (x_display_pixel_width (dpyinfo));
4200 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
4201 Sx_display_pixel_height, 0, 1, 0,
4202 doc: /* Return the height in pixels of the X display TERMINAL.
4203 The optional argument TERMINAL specifies which display to ask about.
4204 TERMINAL should be a terminal object, a frame or a display name (a string).
4205 If omitted or nil, that stands for the selected frame's display.
4207 On \"multi-monitor\" setups this refers to the pixel height for all
4208 physical monitors associated with TERMINAL. To get information for
4209 each physical monitor, use `display-monitor-attributes-list'. */)
4210 (Lisp_Object terminal)
4212 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4214 return make_number (x_display_pixel_height (dpyinfo));
4217 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
4218 0, 1, 0,
4219 doc: /* Return the number of bitplanes of the X display TERMINAL.
4220 The optional argument TERMINAL specifies which display to ask about.
4221 TERMINAL should be a terminal object, a frame or a display name (a string).
4222 If omitted or nil, that stands for the selected frame's display. */)
4223 (Lisp_Object terminal)
4225 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4227 return make_number (dpyinfo->n_planes);
4230 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
4231 0, 1, 0,
4232 doc: /* Return the number of color cells of the X display TERMINAL.
4233 The optional argument TERMINAL specifies which display to ask about.
4234 TERMINAL should be a terminal object, a frame or a display name (a string).
4235 If omitted or nil, that stands for the selected frame's display. */)
4236 (Lisp_Object terminal)
4238 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4240 int nr_planes = DisplayPlanes (dpyinfo->display,
4241 XScreenNumberOfScreen (dpyinfo->screen));
4243 /* Truncate nr_planes to 24 to avoid integer overflow.
4244 Some displays says 32, but only 24 bits are actually significant.
4245 There are only very few and rare video cards that have more than
4246 24 significant bits. Also 24 bits is more than 16 million colors,
4247 it "should be enough for everyone". */
4248 if (nr_planes > 24) nr_planes = 24;
4250 return make_number (1 << nr_planes);
4253 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
4254 Sx_server_max_request_size,
4255 0, 1, 0,
4256 doc: /* Return the maximum request size of the X server of display TERMINAL.
4257 The optional argument TERMINAL specifies which display to ask about.
4258 TERMINAL should be a terminal object, a frame or a display name (a string).
4259 If omitted or nil, that stands for the selected frame's display. */)
4260 (Lisp_Object terminal)
4262 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4264 return make_number (MAXREQUEST (dpyinfo->display));
4267 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
4268 doc: /* Return the "vendor ID" string of the GUI software on TERMINAL.
4270 \(Labeling every distributor as a "vendor" embodies the false assumption
4271 that operating systems cannot be developed and distributed noncommercially.)
4272 The optional argument TERMINAL specifies which display to ask about.
4274 For GNU and Unix systems, this queries the X server software; for
4275 MS-Windows, this queries the OS.
4277 TERMINAL should be a terminal object, a frame or a display name (a string).
4278 If omitted or nil, that stands for the selected frame's display. */)
4279 (Lisp_Object terminal)
4281 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4282 const char *vendor = ServerVendor (dpyinfo->display);
4284 if (! vendor) vendor = "";
4285 return build_string (vendor);
4288 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
4289 doc: /* Return the version numbers of the GUI software on TERMINAL.
4290 The value is a list of three integers specifying the version of the GUI
4291 software in use.
4293 For GNU and Unix system, the first 2 numbers are the version of the X
4294 Protocol used on TERMINAL and the 3rd number is the distributor-specific
4295 release number. For MS-Windows, the 3 numbers report the version and
4296 the build number of the OS.
4298 See also the function `x-server-vendor'.
4300 The optional argument TERMINAL specifies which display to ask about.
4301 TERMINAL should be a terminal object, a frame or a display name (a string).
4302 If omitted or nil, that stands for the selected frame's display. */)
4303 (Lisp_Object terminal)
4305 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4306 Display *dpy = dpyinfo->display;
4308 return list3i (ProtocolVersion (dpy), ProtocolRevision (dpy),
4309 VendorRelease (dpy));
4312 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
4313 doc: /* Return the number of screens on the X server of display TERMINAL.
4314 The optional argument TERMINAL specifies which display to ask about.
4315 TERMINAL should be a terminal object, a frame or a display name (a string).
4316 If omitted or nil, that stands for the selected frame's display. */)
4317 (Lisp_Object terminal)
4319 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4321 return make_number (ScreenCount (dpyinfo->display));
4324 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
4325 doc: /* Return the height in millimeters of the X display TERMINAL.
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.
4330 On \"multi-monitor\" setups this refers to the height in millimeters for
4331 all physical monitors associated with TERMINAL. To get information
4332 for each physical monitor, use `display-monitor-attributes-list'. */)
4333 (Lisp_Object terminal)
4335 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4337 return make_number (HeightMMOfScreen (dpyinfo->screen));
4340 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
4341 doc: /* Return the width in millimeters of the X display TERMINAL.
4342 The optional argument TERMINAL specifies which display to ask about.
4343 TERMINAL should be a terminal object, a frame or a display name (a string).
4344 If omitted or nil, that stands for the selected frame's display.
4346 On \"multi-monitor\" setups this refers to the width in millimeters for
4347 all physical monitors associated with TERMINAL. To get information
4348 for each physical monitor, use `display-monitor-attributes-list'. */)
4349 (Lisp_Object terminal)
4351 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4353 return make_number (WidthMMOfScreen (dpyinfo->screen));
4356 DEFUN ("x-display-backing-store", Fx_display_backing_store,
4357 Sx_display_backing_store, 0, 1, 0,
4358 doc: /* Return an indication of whether X display TERMINAL does backing store.
4359 The value may be `always', `when-mapped', or `not-useful'.
4360 The optional argument TERMINAL specifies which display to ask about.
4361 TERMINAL should be a terminal object, a frame or a display name (a string).
4362 If omitted or nil, that stands for the selected frame's display. */)
4363 (Lisp_Object terminal)
4365 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4366 Lisp_Object result;
4368 switch (DoesBackingStore (dpyinfo->screen))
4370 case Always:
4371 result = intern ("always");
4372 break;
4374 case WhenMapped:
4375 result = intern ("when-mapped");
4376 break;
4378 case NotUseful:
4379 result = intern ("not-useful");
4380 break;
4382 default:
4383 error ("Strange value for BackingStore parameter of screen");
4386 return result;
4389 DEFUN ("x-display-visual-class", Fx_display_visual_class,
4390 Sx_display_visual_class, 0, 1, 0,
4391 doc: /* Return the visual class of the X display TERMINAL.
4392 The value is one of the symbols `static-gray', `gray-scale',
4393 `static-color', `pseudo-color', `true-color', or `direct-color'.
4395 The optional argument TERMINAL specifies which display to ask about.
4396 TERMINAL should a terminal object, a frame or a display name (a string).
4397 If omitted or nil, that stands for the selected frame's display. */)
4398 (Lisp_Object terminal)
4400 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4401 Lisp_Object result;
4403 switch (dpyinfo->visual->class)
4405 case StaticGray:
4406 result = intern ("static-gray");
4407 break;
4408 case GrayScale:
4409 result = intern ("gray-scale");
4410 break;
4411 case StaticColor:
4412 result = intern ("static-color");
4413 break;
4414 case PseudoColor:
4415 result = intern ("pseudo-color");
4416 break;
4417 case TrueColor:
4418 result = intern ("true-color");
4419 break;
4420 case DirectColor:
4421 result = intern ("direct-color");
4422 break;
4423 default:
4424 error ("Display has an unknown visual class");
4427 return result;
4430 DEFUN ("x-display-save-under", Fx_display_save_under,
4431 Sx_display_save_under, 0, 1, 0,
4432 doc: /* Return t if the X display TERMINAL supports the save-under feature.
4433 The optional argument TERMINAL specifies which display to ask about.
4434 TERMINAL should be a terminal object, a frame or a display name (a string).
4435 If omitted or nil, that stands for the selected frame's display. */)
4436 (Lisp_Object terminal)
4438 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4440 if (DoesSaveUnders (dpyinfo->screen) == True)
4441 return Qt;
4442 else
4443 return Qnil;
4446 /* Store the geometry of the workarea on display DPYINFO into *RECT.
4447 Return false if and only if the workarea information cannot be
4448 obtained via the _NET_WORKAREA root window property. */
4450 #if ! GTK_CHECK_VERSION (3, 4, 0)
4451 static bool
4452 x_get_net_workarea (struct x_display_info *dpyinfo, XRectangle *rect)
4454 Display *dpy = dpyinfo->display;
4455 long offset, max_len;
4456 Atom target_type, actual_type;
4457 unsigned long actual_size, bytes_remaining;
4458 int rc, actual_format;
4459 unsigned char *tmp_data = NULL;
4460 bool result = false;
4462 x_catch_errors (dpy);
4463 offset = 0;
4464 max_len = 1;
4465 target_type = XA_CARDINAL;
4466 rc = XGetWindowProperty (dpy, dpyinfo->root_window,
4467 dpyinfo->Xatom_net_current_desktop,
4468 offset, max_len, False, target_type,
4469 &actual_type, &actual_format, &actual_size,
4470 &bytes_remaining, &tmp_data);
4471 if (rc == Success && actual_type == target_type && !x_had_errors_p (dpy)
4472 && actual_format == 32 && actual_size == max_len)
4474 long current_desktop = ((long *) tmp_data)[0];
4476 XFree (tmp_data);
4477 tmp_data = NULL;
4479 offset = 4 * current_desktop;
4480 max_len = 4;
4481 rc = XGetWindowProperty (dpy, dpyinfo->root_window,
4482 dpyinfo->Xatom_net_workarea,
4483 offset, max_len, False, target_type,
4484 &actual_type, &actual_format, &actual_size,
4485 &bytes_remaining, &tmp_data);
4486 if (rc == Success && actual_type == target_type && !x_had_errors_p (dpy)
4487 && actual_format == 32 && actual_size == max_len)
4489 long *values = (long *) tmp_data;
4491 rect->x = values[0];
4492 rect->y = values[1];
4493 rect->width = values[2];
4494 rect->height = values[3];
4496 XFree (tmp_data);
4497 tmp_data = NULL;
4499 result = true;
4502 if (tmp_data)
4503 XFree (tmp_data);
4504 x_uncatch_errors ();
4506 return result;
4508 #endif
4510 #ifndef USE_GTK
4512 /* Return monitor number where F is "most" or closest to. */
4513 static int
4514 x_get_monitor_for_frame (struct frame *f,
4515 struct MonitorInfo *monitors,
4516 int n_monitors)
4518 XRectangle frect;
4519 int area = 0, dist = -1;
4520 int best_area = -1, best_dist = -1;
4521 int i;
4523 if (n_monitors == 1) return 0;
4524 frect.x = f->left_pos;
4525 frect.y = f->top_pos;
4526 frect.width = FRAME_PIXEL_WIDTH (f);
4527 frect.height = FRAME_PIXEL_HEIGHT (f);
4529 for (i = 0; i < n_monitors; ++i)
4531 struct MonitorInfo *mi = &monitors[i];
4532 XRectangle res;
4533 int a = 0;
4535 if (mi->geom.width == 0) continue;
4537 if (x_intersect_rectangles (&mi->geom, &frect, &res))
4539 a = res.width * res.height;
4540 if (a > area)
4542 area = a;
4543 best_area = i;
4547 if (a == 0 && area == 0)
4549 int dx, dy, d;
4550 if (frect.x + frect.width < mi->geom.x)
4551 dx = mi->geom.x - frect.x + frect.width;
4552 else if (frect.x > mi->geom.x + mi->geom.width)
4553 dx = frect.x - mi->geom.x + mi->geom.width;
4554 else
4555 dx = 0;
4556 if (frect.y + frect.height < mi->geom.y)
4557 dy = mi->geom.y - frect.y + frect.height;
4558 else if (frect.y > mi->geom.y + mi->geom.height)
4559 dy = frect.y - mi->geom.y + mi->geom.height;
4560 else
4561 dy = 0;
4563 d = dx*dx + dy*dy;
4564 if (dist == -1 || dist > d)
4566 dist = d;
4567 best_dist = i;
4572 return best_area != -1 ? best_area : (best_dist != -1 ? best_dist : 0);
4575 static Lisp_Object
4576 x_make_monitor_attribute_list (struct MonitorInfo *monitors,
4577 int n_monitors,
4578 int primary_monitor,
4579 struct x_display_info *dpyinfo,
4580 const char *source)
4582 Lisp_Object monitor_frames = Fmake_vector (make_number (n_monitors), Qnil);
4583 Lisp_Object frame, rest;
4585 FOR_EACH_FRAME (rest, frame)
4587 struct frame *f = XFRAME (frame);
4589 if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) == dpyinfo
4590 && !EQ (frame, tip_frame))
4592 int i = x_get_monitor_for_frame (f, monitors, n_monitors);
4593 ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i)));
4597 return make_monitor_attribute_list (monitors, n_monitors, primary_monitor,
4598 monitor_frames, source);
4601 static Lisp_Object
4602 x_get_monitor_attributes_fallback (struct x_display_info *dpyinfo)
4604 struct MonitorInfo monitor;
4605 XRectangle workarea_r;
4607 /* Fallback: treat (possibly) multiple physical monitors as if they
4608 formed a single monitor as a whole. This should provide a
4609 consistent result at least on single monitor environments. */
4610 monitor.geom.x = monitor.geom.y = 0;
4611 monitor.geom.width = x_display_pixel_width (dpyinfo);
4612 monitor.geom.height = x_display_pixel_height (dpyinfo);
4613 monitor.mm_width = WidthMMOfScreen (dpyinfo->screen);
4614 monitor.mm_height = HeightMMOfScreen (dpyinfo->screen);
4615 monitor.name = xstrdup ("combined screen");
4617 if (x_get_net_workarea (dpyinfo, &workarea_r))
4618 monitor.work = workarea_r;
4619 else
4620 monitor.work = monitor.geom;
4621 return x_make_monitor_attribute_list (&monitor, 1, 0, dpyinfo, "fallback");
4625 #ifdef HAVE_XINERAMA
4626 static Lisp_Object
4627 x_get_monitor_attributes_xinerama (struct x_display_info *dpyinfo)
4629 int n_monitors, i;
4630 Lisp_Object attributes_list = Qnil;
4631 Display *dpy = dpyinfo->display;
4632 XineramaScreenInfo *info = XineramaQueryScreens (dpy, &n_monitors);
4633 struct MonitorInfo *monitors;
4634 double mm_width_per_pixel, mm_height_per_pixel;
4636 if (! info || n_monitors == 0)
4638 if (info)
4639 XFree (info);
4640 return attributes_list;
4643 mm_width_per_pixel = ((double) WidthMMOfScreen (dpyinfo->screen)
4644 / x_display_pixel_width (dpyinfo));
4645 mm_height_per_pixel = ((double) HeightMMOfScreen (dpyinfo->screen)
4646 / x_display_pixel_height (dpyinfo));
4647 monitors = xzalloc (n_monitors * sizeof *monitors);
4648 for (i = 0; i < n_monitors; ++i)
4650 struct MonitorInfo *mi = &monitors[i];
4651 XRectangle workarea_r;
4653 mi->geom.x = info[i].x_org;
4654 mi->geom.y = info[i].y_org;
4655 mi->geom.width = info[i].width;
4656 mi->geom.height = info[i].height;
4657 mi->mm_width = mi->geom.width * mm_width_per_pixel + 0.5;
4658 mi->mm_height = mi->geom.height * mm_height_per_pixel + 0.5;
4659 mi->name = 0;
4661 /* Xinerama usually have primary monitor first, just use that. */
4662 if (i == 0 && x_get_net_workarea (dpyinfo, &workarea_r))
4664 mi->work = workarea_r;
4665 if (! x_intersect_rectangles (&mi->geom, &mi->work, &mi->work))
4666 mi->work = mi->geom;
4668 else
4669 mi->work = mi->geom;
4671 XFree (info);
4673 attributes_list = x_make_monitor_attribute_list (monitors,
4674 n_monitors,
4676 dpyinfo,
4677 "Xinerama");
4678 free_monitors (monitors, n_monitors);
4679 return attributes_list;
4681 #endif /* HAVE_XINERAMA */
4684 #ifdef HAVE_XRANDR
4685 static Lisp_Object
4686 x_get_monitor_attributes_xrandr (struct x_display_info *dpyinfo)
4688 Lisp_Object attributes_list = Qnil;
4689 XRRScreenResources *resources;
4690 Display *dpy = dpyinfo->display;
4691 int i, n_monitors, primary = -1;
4692 RROutput pxid = None;
4693 struct MonitorInfo *monitors;
4695 #define RANDR13_LIBRARY \
4696 (RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 3))
4698 #if RANDR13_LIBRARY
4699 /* Check if the display supports 1.3 too. */
4700 bool randr13_avail = (dpyinfo->xrandr_major_version > 1
4701 || (dpyinfo->xrandr_major_version == 1
4702 && dpyinfo->xrandr_minor_version >= 3));
4704 if (randr13_avail)
4705 resources = XRRGetScreenResourcesCurrent (dpy, dpyinfo->root_window);
4706 else
4707 resources = XRRGetScreenResources (dpy, dpyinfo->root_window);
4708 #else
4709 resources = XRRGetScreenResources (dpy, dpyinfo->root_window);
4710 #endif
4711 if (! resources || resources->noutput == 0)
4713 if (resources)
4714 XRRFreeScreenResources (resources);
4715 return Qnil;
4717 n_monitors = resources->noutput;
4718 monitors = xzalloc (n_monitors * sizeof *monitors);
4720 #if RANDR13_LIBRARY
4721 if (randr13_avail)
4722 pxid = XRRGetOutputPrimary (dpy, dpyinfo->root_window);
4723 #endif
4725 for (i = 0; i < n_monitors; ++i)
4727 XRROutputInfo *info = XRRGetOutputInfo (dpy, resources,
4728 resources->outputs[i]);
4729 if (!info)
4730 continue;
4732 if (strcmp (info->name, "default") == 0)
4734 /* Non XRandr 1.2 driver, does not give useful data. */
4735 XRRFreeOutputInfo (info);
4736 XRRFreeScreenResources (resources);
4737 free_monitors (monitors, n_monitors);
4738 return Qnil;
4741 if (info->connection != RR_Disconnected && info->crtc != None)
4743 XRRCrtcInfo *crtc = XRRGetCrtcInfo (dpy, resources, info->crtc);
4744 struct MonitorInfo *mi = &monitors[i];
4745 XRectangle workarea_r;
4747 if (! crtc)
4749 XRRFreeOutputInfo (info);
4750 continue;
4753 mi->geom.x = crtc->x;
4754 mi->geom.y = crtc->y;
4755 mi->geom.width = crtc->width;
4756 mi->geom.height = crtc->height;
4757 mi->mm_width = info->mm_width;
4758 mi->mm_height = info->mm_height;
4759 mi->name = xstrdup (info->name);
4761 if (pxid != None && pxid == resources->outputs[i])
4762 primary = i;
4763 else if (primary == -1 && strcmp (info->name, "LVDS") == 0)
4764 primary = i;
4766 if (i == primary && x_get_net_workarea (dpyinfo, &workarea_r))
4768 mi->work= workarea_r;
4769 if (! x_intersect_rectangles (&mi->geom, &mi->work, &mi->work))
4770 mi->work = mi->geom;
4772 else
4773 mi->work = mi->geom;
4775 XRRFreeCrtcInfo (crtc);
4777 XRRFreeOutputInfo (info);
4779 XRRFreeScreenResources (resources);
4781 attributes_list = x_make_monitor_attribute_list (monitors,
4782 n_monitors,
4783 primary,
4784 dpyinfo,
4785 "XRandr");
4786 free_monitors (monitors, n_monitors);
4787 return attributes_list;
4789 #endif /* HAVE_XRANDR */
4791 static Lisp_Object
4792 x_get_monitor_attributes (struct x_display_info *dpyinfo)
4794 Lisp_Object attributes_list = Qnil;
4795 Display *dpy = dpyinfo->display;
4797 (void) dpy; /* Suppress unused variable warning. */
4799 #ifdef HAVE_XRANDR
4800 int xrr_event_base, xrr_error_base;
4801 bool xrr_ok = false;
4802 xrr_ok = XRRQueryExtension (dpy, &xrr_event_base, &xrr_error_base);
4803 if (xrr_ok)
4805 XRRQueryVersion (dpy, &dpyinfo->xrandr_major_version,
4806 &dpyinfo->xrandr_minor_version);
4807 xrr_ok = ((dpyinfo->xrandr_major_version == 1
4808 && dpyinfo->xrandr_minor_version >= 2)
4809 || dpyinfo->xrandr_major_version > 1);
4812 if (xrr_ok)
4813 attributes_list = x_get_monitor_attributes_xrandr (dpyinfo);
4814 #endif /* HAVE_XRANDR */
4816 #ifdef HAVE_XINERAMA
4817 if (NILP (attributes_list))
4819 int xin_event_base, xin_error_base;
4820 bool xin_ok = false;
4821 xin_ok = XineramaQueryExtension (dpy, &xin_event_base, &xin_error_base);
4822 if (xin_ok && XineramaIsActive (dpy))
4823 attributes_list = x_get_monitor_attributes_xinerama (dpyinfo);
4825 #endif /* HAVE_XINERAMA */
4827 if (NILP (attributes_list))
4828 attributes_list = x_get_monitor_attributes_fallback (dpyinfo);
4830 return attributes_list;
4833 #endif /* !USE_GTK */
4835 DEFUN ("x-display-monitor-attributes-list", Fx_display_monitor_attributes_list,
4836 Sx_display_monitor_attributes_list,
4837 0, 1, 0,
4838 doc: /* Return a list of physical monitor attributes on the X display TERMINAL.
4840 The optional argument TERMINAL specifies which display to ask about.
4841 TERMINAL should be a terminal object, a frame or a display name (a string).
4842 If omitted or nil, that stands for the selected frame's display.
4844 In addition to the standard attribute keys listed in
4845 `display-monitor-attributes-list', the following keys are contained in
4846 the attributes:
4848 source -- String describing the source from which multi-monitor
4849 information is obtained, one of \"Gdk\", \"XRandr\",
4850 \"Xinerama\", or \"fallback\"
4852 Internal use only, use `display-monitor-attributes-list' instead. */)
4853 (Lisp_Object terminal)
4855 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4856 Lisp_Object attributes_list = Qnil;
4858 #ifdef USE_GTK
4859 double mm_width_per_pixel, mm_height_per_pixel;
4860 GdkDisplay *gdpy;
4861 GdkScreen *gscreen;
4862 gint primary_monitor = 0, n_monitors, i;
4863 Lisp_Object monitor_frames, rest, frame;
4864 static const char *source = "Gdk";
4865 struct MonitorInfo *monitors;
4867 block_input ();
4868 mm_width_per_pixel = ((double) WidthMMOfScreen (dpyinfo->screen)
4869 / x_display_pixel_width (dpyinfo));
4870 mm_height_per_pixel = ((double) HeightMMOfScreen (dpyinfo->screen)
4871 / x_display_pixel_height (dpyinfo));
4872 gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display);
4873 gscreen = gdk_display_get_default_screen (gdpy);
4874 #if GTK_CHECK_VERSION (2, 20, 0)
4875 primary_monitor = gdk_screen_get_primary_monitor (gscreen);
4876 #endif
4877 n_monitors = gdk_screen_get_n_monitors (gscreen);
4878 monitor_frames = Fmake_vector (make_number (n_monitors), Qnil);
4879 monitors = xzalloc (n_monitors * sizeof *monitors);
4881 FOR_EACH_FRAME (rest, frame)
4883 struct frame *f = XFRAME (frame);
4885 if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) == dpyinfo
4886 && !EQ (frame, tip_frame))
4888 GdkWindow *gwin = gtk_widget_get_window (FRAME_GTK_WIDGET (f));
4890 i = gdk_screen_get_monitor_at_window (gscreen, gwin);
4891 ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i)));
4895 for (i = 0; i < n_monitors; ++i)
4897 gint width_mm = -1, height_mm = -1;
4898 GdkRectangle rec, work;
4899 struct MonitorInfo *mi = &monitors[i];
4901 gdk_screen_get_monitor_geometry (gscreen, i, &rec);
4903 #if GTK_CHECK_VERSION (2, 14, 0)
4904 width_mm = gdk_screen_get_monitor_width_mm (gscreen, i);
4905 height_mm = gdk_screen_get_monitor_height_mm (gscreen, i);
4906 #endif
4907 if (width_mm < 0)
4908 width_mm = rec.width * mm_width_per_pixel + 0.5;
4909 if (height_mm < 0)
4910 height_mm = rec.height * mm_height_per_pixel + 0.5;
4912 #if GTK_CHECK_VERSION (3, 4, 0)
4913 gdk_screen_get_monitor_workarea (gscreen, i, &work);
4914 #else
4915 /* Emulate the behavior of GTK+ 3.4. */
4917 XRectangle workarea_r;
4919 if (i == primary_monitor && x_get_net_workarea (dpyinfo, &workarea_r))
4921 work.x = workarea_r.x;
4922 work.y = workarea_r.y;
4923 work.width = workarea_r.width;
4924 work.height = workarea_r.height;
4925 if (! gdk_rectangle_intersect (&rec, &work, &work))
4926 work = rec;
4928 else
4929 work = rec;
4931 #endif
4934 mi->geom.x = rec.x;
4935 mi->geom.y = rec.y;
4936 mi->geom.width = rec.width;
4937 mi->geom.height = rec.height;
4938 mi->work.x = work.x;
4939 mi->work.y = work.y;
4940 mi->work.width = work.width;
4941 mi->work.height = work.height;
4942 mi->mm_width = width_mm;
4943 mi->mm_height = height_mm;
4945 #if GTK_CHECK_VERSION (2, 14, 0)
4946 mi->name = gdk_screen_get_monitor_plug_name (gscreen, i);
4947 #endif
4950 attributes_list = make_monitor_attribute_list (monitors,
4951 n_monitors,
4952 primary_monitor,
4953 monitor_frames,
4954 source);
4955 unblock_input ();
4956 #else /* not USE_GTK */
4958 block_input ();
4959 attributes_list = x_get_monitor_attributes (dpyinfo);
4960 unblock_input ();
4962 #endif /* not USE_GTK */
4964 return attributes_list;
4967 /* Return geometric attributes of FRAME. According to the value of
4968 ATTRIBUTES return the outer edges of FRAME (Qouter_edges), the native
4969 edges of FRAME (Qnative_edges), or the inner edges of frame
4970 (Qinner_edges). Any other value means to return the geometry as
4971 returned by Fx_frame_geometry. */
4972 static Lisp_Object
4973 frame_geometry (Lisp_Object frame, Lisp_Object attribute)
4975 struct frame *f = decode_live_frame (frame);
4976 /** XWindowAttributes atts; **/
4977 Window rootw;
4978 unsigned int ign, native_width, native_height, x_border_width = 0;
4979 int x_native = 0, y_native = 0, xptr = 0, yptr = 0;
4980 int left_off = 0, right_off = 0, top_off = 0, bottom_off = 0;
4981 int outer_left, outer_top, outer_right, outer_bottom;
4982 int native_left, native_top, native_right, native_bottom;
4983 int inner_left, inner_top, inner_right, inner_bottom;
4984 int internal_border_width;
4985 bool menu_bar_external = false, tool_bar_external = false;
4986 int menu_bar_height = 0, menu_bar_width = 0;
4987 int tool_bar_height = 0, tool_bar_width = 0;
4989 if (FRAME_INITIAL_P (f) || !FRAME_X_P (f))
4990 return Qnil;
4992 block_input ();
4993 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
4994 &rootw, &x_native, &y_native, &native_width, &native_height,
4995 &x_border_width, &ign);
4996 /** XGetWindowAttributes (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &atts); **/
4997 if (!FRAME_PARENT_FRAME (f))
4998 x_real_pos_and_offsets (f, &left_off, &right_off, &top_off, &bottom_off,
4999 NULL, NULL, &xptr, &yptr, NULL);
5000 unblock_input ();
5002 /** native_width = atts.width; **/
5003 /** native_height = atts.height; **/
5005 if (FRAME_PARENT_FRAME (f))
5007 Lisp_Object parent, edges;
5009 XSETFRAME (parent, FRAME_PARENT_FRAME (f));
5010 edges = Fx_frame_edges (parent, Qnative_edges);
5011 if (!NILP (edges))
5013 x_native += XINT (Fnth (make_number (0), edges));
5014 y_native += XINT (Fnth (make_number (1), edges));
5017 outer_left = x_native;
5018 outer_top = y_native;
5019 outer_right = outer_left + native_width + 2 * x_border_width;
5020 outer_bottom = outer_top + native_height + 2 * x_border_width;
5022 native_left = x_native + x_border_width;
5023 native_top = y_native + x_border_width;
5024 native_right = native_left + native_width;
5025 native_bottom = native_top + native_height;
5027 else
5029 outer_left = xptr;
5030 outer_top = yptr;
5031 outer_right = outer_left + left_off + native_width + right_off;
5032 outer_bottom = outer_top + top_off + native_height + bottom_off;
5034 native_left = outer_left + left_off;
5035 native_top = outer_top + top_off;
5036 native_right = native_left + native_width;
5037 native_bottom = native_top + native_height;
5040 internal_border_width = FRAME_INTERNAL_BORDER_WIDTH (f);
5041 inner_left = native_left + internal_border_width;
5042 inner_top = native_top + internal_border_width;
5043 inner_right = native_right - internal_border_width;
5044 inner_bottom = native_bottom - internal_border_width;
5046 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
5047 menu_bar_external = true;
5048 menu_bar_height = FRAME_MENUBAR_HEIGHT (f);
5049 native_top += menu_bar_height;
5050 inner_top += menu_bar_height;
5051 #else
5052 menu_bar_height = FRAME_MENU_BAR_HEIGHT (f);
5053 inner_top += menu_bar_height;
5054 #endif
5055 menu_bar_width = menu_bar_height ? native_width : 0;
5057 #if defined (USE_GTK)
5058 tool_bar_external = true;
5059 if (EQ (FRAME_TOOL_BAR_POSITION (f), Qleft))
5061 tool_bar_width = FRAME_TOOLBAR_WIDTH (f);
5062 native_left += tool_bar_width;
5063 inner_left += tool_bar_width;
5064 tool_bar_height
5065 = tool_bar_width ? native_height - menu_bar_height : 0;
5067 else if (EQ (FRAME_TOOL_BAR_POSITION (f), Qtop))
5069 tool_bar_height = FRAME_TOOLBAR_HEIGHT (f);
5070 native_top += tool_bar_height;
5071 inner_top += tool_bar_height;
5072 tool_bar_width = tool_bar_height ? native_width : 0;
5074 else if (EQ (FRAME_TOOL_BAR_POSITION (f), Qright))
5076 tool_bar_width = FRAME_TOOLBAR_WIDTH (f);
5077 native_right -= tool_bar_width;
5078 inner_right -= tool_bar_width;
5079 tool_bar_height
5080 = tool_bar_width ? native_height - menu_bar_height : 0;
5082 else
5084 tool_bar_height = FRAME_TOOLBAR_HEIGHT (f);
5085 native_bottom -= tool_bar_height;
5086 inner_bottom -= tool_bar_height;
5087 tool_bar_width = tool_bar_height ? native_width : 0;
5089 #else
5090 tool_bar_height = FRAME_TOOL_BAR_HEIGHT (f);
5091 tool_bar_width = (tool_bar_height
5092 ? native_width - 2 * internal_border_width
5093 : 0);
5094 inner_top += tool_bar_height;
5095 #endif
5097 /* Construct list. */
5098 if (EQ (attribute, Qouter_edges))
5099 return list4 (make_number (outer_left), make_number (outer_top),
5100 make_number (outer_right), make_number (outer_bottom));
5101 else if (EQ (attribute, Qnative_edges))
5102 return list4 (make_number (native_left), make_number (native_top),
5103 make_number (native_right), make_number (native_bottom));
5104 else if (EQ (attribute, Qinner_edges))
5105 return list4 (make_number (inner_left), make_number (inner_top),
5106 make_number (inner_right), make_number (inner_bottom));
5107 else
5108 return
5109 listn (CONSTYPE_HEAP, 11,
5110 Fcons (Qouter_position,
5111 Fcons (make_number (outer_left),
5112 make_number (outer_top))),
5113 Fcons (Qouter_size,
5114 Fcons (make_number (outer_right - outer_left),
5115 make_number (outer_bottom - outer_top))),
5116 /* Approximate. */
5117 Fcons (Qexternal_border_size,
5118 Fcons (make_number (right_off),
5119 make_number (bottom_off))),
5120 Fcons (Qouter_border_width, make_number (x_border_width)),
5121 /* Approximate. */
5122 Fcons (Qtitle_bar_size,
5123 Fcons (make_number (0),
5124 make_number (top_off - bottom_off))),
5125 Fcons (Qmenu_bar_external, menu_bar_external ? Qt : Qnil),
5126 Fcons (Qmenu_bar_size,
5127 Fcons (make_number (menu_bar_width),
5128 make_number (menu_bar_height))),
5129 Fcons (Qtool_bar_external, tool_bar_external ? Qt : Qnil),
5130 Fcons (Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f)),
5131 Fcons (Qtool_bar_size,
5132 Fcons (make_number (tool_bar_width),
5133 make_number (tool_bar_height))),
5134 Fcons (Qinternal_border_width,
5135 make_number (internal_border_width)));
5138 DEFUN ("x-frame-geometry", Fx_frame_geometry, Sx_frame_geometry, 0, 1, 0,
5139 doc: /* Return geometric attributes of FRAME.
5140 FRAME must be a live frame and defaults to the selected one. The return
5141 value is an association list of the attributes listed below. All height
5142 and width values are in pixels.
5144 `outer-position' is a cons of the outer left and top edges of FRAME
5145 relative to the origin - the position (0, 0) - of FRAME's display.
5147 `outer-size' is a cons of the outer width and height of FRAME. The
5148 outer size includes the title bar and the external borders as well as
5149 any menu and/or tool bar of frame. For a child frame the value
5150 includes FRAME's X borders, if any.
5152 `external-border-size' is a cons of the horizontal and vertical width of
5153 FRAME's external borders as supplied by the window manager.
5155 `title-bar-size' is a cons of the width and height of the title bar of
5156 FRAME as supplied by the window manager. If both of them are zero,
5157 FRAME has no title bar. If only the width is zero, Emacs was not
5158 able to retrieve the width information.
5160 `menu-bar-external', if non-nil, means the menu bar is external (never
5161 included in the inner edges of FRAME).
5163 `menu-bar-size' is a cons of the width and height of the menu bar of
5164 FRAME.
5166 `tool-bar-external', if non-nil, means the tool bar is external (never
5167 included in the inner edges of FRAME).
5169 `tool-bar-position' tells on which side the tool bar on FRAME is and can
5170 be one of `left', `top', `right' or `bottom'. If this is nil, FRAME
5171 has no tool bar.
5173 `tool-bar-size' is a cons of the width and height of the tool bar of
5174 FRAME.
5176 `internal-border-width' is the width of the internal border of
5177 FRAME.
5179 `outer-border-width' is the width of the X border of FRAME. The X
5180 border is usually only shown for frames without window manager
5181 decorations like child and tooltip frames. */)
5182 (Lisp_Object frame)
5184 return frame_geometry (frame, Qnil);
5187 DEFUN ("x-frame-edges", Fx_frame_edges, Sx_frame_edges, 0, 2, 0,
5188 doc: /* Return edge coordinates of FRAME.
5189 FRAME must be a live frame and defaults to the selected one. The return
5190 value is a list of the form (LEFT, TOP, RIGHT, BOTTOM). All values are
5191 in pixels relative to the origin - the position (0, 0) - of FRAME's
5192 display.
5194 If optional argument TYPE is the symbol `outer-edges', return the outer
5195 edges of FRAME. The outer edges comprise the decorations of the window
5196 manager (like the title bar or external borders) as well as any external
5197 menu or tool bar of FRAME. If optional argument TYPE is the symbol
5198 `native-edges' or nil, return the native edges of FRAME. The native
5199 edges exclude the decorations of the window manager and any external
5200 menu or tool bar of FRAME. If TYPE is the symbol `inner-edges', return
5201 the inner edges of FRAME. These edges exclude title bar, any borders,
5202 menu bar or tool bar of FRAME. */)
5203 (Lisp_Object frame, Lisp_Object type)
5205 return frame_geometry (frame, ((EQ (type, Qouter_edges)
5206 || EQ (type, Qinner_edges))
5207 ? type
5208 : Qnative_edges));
5212 * x_frame_list_z_order:
5214 * Recursively add list of all frames on the display specified via
5215 * DPYINFO and whose window-system window's parent is specified by
5216 * WINDOW to FRAMES and return FRAMES.
5218 static Lisp_Object
5219 x_frame_list_z_order (Display* dpy, Window window)
5221 Window root, parent, *children;
5222 unsigned int nchildren;
5223 int i;
5224 Lisp_Object frames = Qnil;
5226 block_input ();
5227 if (XQueryTree (dpy, window, &root, &parent, &children, &nchildren))
5229 unblock_input ();
5230 for (i = 0; i < nchildren; i++)
5232 Lisp_Object frame, tail;
5234 FOR_EACH_FRAME (tail, frame)
5235 /* With a reparenting window manager the parent_desc field
5236 usually specifies the topmost windows of our frames.
5237 Otherwise FRAME_OUTER_WINDOW should do. */
5238 if (XFRAME (frame)->output_data.x->parent_desc == children[i]
5239 || FRAME_OUTER_WINDOW (XFRAME (frame)) == children[i])
5240 frames = Fcons (frame, frames);
5243 if (children) XFree ((char *)children);
5245 else
5246 unblock_input ();
5248 return frames;
5252 DEFUN ("x-frame-list-z-order", Fx_frame_list_z_order,
5253 Sx_frame_list_z_order, 0, 1, 0,
5254 doc: /* Return list of Emacs' frames, in Z (stacking) order.
5255 The optional argument TERMINAL specifies which display to ask about.
5256 TERMINAL should be either a frame or a display name (a string). If
5257 omitted or nil, that stands for the selected frame's display. Return
5258 nil if TERMINAL contains no Emacs frame.
5260 As a special case, if TERMINAL is non-nil and specifies a live frame,
5261 return the child frames of that frame in Z (stacking) order.
5263 Frames are listed from topmost (first) to bottommost (last). */)
5264 (Lisp_Object terminal)
5266 struct x_display_info *dpyinfo = check_x_display_info (terminal);
5267 Display *dpy = dpyinfo->display;
5268 Window window;
5270 if (FRAMEP (terminal) && FRAME_LIVE_P (XFRAME (terminal)))
5271 window = FRAME_X_WINDOW (XFRAME (terminal));
5272 else
5273 window = dpyinfo->root_window;
5275 return x_frame_list_z_order (dpy, window);
5279 * x_frame_restack:
5281 * Restack frame F1 below frame F2, above if ABOVE_FLAG is non-nil. In
5282 * practice this is a two-step action: The first step removes F1's
5283 * window-system window from the display. The second step reinserts
5284 * F1's window below (above if ABOVE_FLAG is true) that of F2.
5286 static void
5287 x_frame_restack (struct frame *f1, struct frame *f2, bool above_flag)
5289 #ifdef USE_GTK
5290 block_input ();
5291 xg_frame_restack (f1, f2, above_flag);
5292 unblock_input ();
5293 #else
5294 Display *dpy = FRAME_X_DISPLAY (f1);
5295 Window window1 = FRAME_OUTER_WINDOW (f1);
5296 XWindowChanges wc;
5297 unsigned long mask = (CWSibling | CWStackMode);
5299 wc.sibling = FRAME_OUTER_WINDOW (f2);
5300 wc.stack_mode = above_flag ? Above : Below;
5301 block_input ();
5302 /* Configure the window manager window (a normal XConfigureWindow
5303 won't cut it). This should also work for child frames. */
5304 XReconfigureWMWindow (dpy, window1, FRAME_X_SCREEN_NUMBER (f1), mask, &wc);
5305 unblock_input ();
5306 #endif /* USE_GTK */
5310 DEFUN ("x-frame-restack", Fx_frame_restack, Sx_frame_restack, 2, 3, 0,
5311 doc: /* Restack FRAME1 below FRAME2.
5312 This means that if both frames are visible and the display areas of
5313 these frames overlap, FRAME2 (partially) obscures FRAME1. If optional
5314 third argument ABOVE is non-nil, restack FRAME1 above FRAME2. This
5315 means that if both frames are visible and the display areas of these
5316 frames overlap, FRAME1 (partially) obscures FRAME2.
5318 This may be thought of as an atomic action performed in two steps: The
5319 first step removes FRAME1's window-step window from the display. The
5320 second step reinserts FRAME1's window below (above if ABOVE is true)
5321 that of FRAME2. Hence the position of FRAME2 in its display's Z
5322 \(stacking) order relative to all other frames excluding FRAME1 remains
5323 unaltered.
5325 Some window managers may refuse to restack windows. */)
5326 (Lisp_Object frame1, Lisp_Object frame2, Lisp_Object above)
5328 struct frame *f1 = decode_live_frame (frame1);
5329 struct frame *f2 = decode_live_frame (frame2);
5331 if (FRAME_OUTER_WINDOW (f1) && FRAME_OUTER_WINDOW (f2))
5333 x_frame_restack (f1, f2, !NILP (above));
5334 return Qt;
5336 else
5338 error ("Cannot restack frames");
5339 return Qnil;
5344 DEFUN ("x-mouse-absolute-pixel-position", Fx_mouse_absolute_pixel_position,
5345 Sx_mouse_absolute_pixel_position, 0, 0, 0,
5346 doc: /* Return absolute position of mouse cursor in pixels.
5347 The position is returned as a cons cell (X . Y) of the coordinates of
5348 the mouse cursor position in pixels relative to a position (0, 0) of the
5349 selected frame's display. */)
5350 (void)
5352 struct frame *f = SELECTED_FRAME ();
5353 Window root, dummy_window;
5354 int x, y, dummy;
5356 if (FRAME_INITIAL_P (f) || !FRAME_X_P (f))
5357 return Qnil;
5359 block_input ();
5360 XQueryPointer (FRAME_X_DISPLAY (f),
5361 DefaultRootWindow (FRAME_X_DISPLAY (f)),
5362 &root, &dummy_window, &x, &y, &dummy, &dummy,
5363 (unsigned int *) &dummy);
5364 unblock_input ();
5366 return Fcons (make_number (x), make_number (y));
5369 DEFUN ("x-set-mouse-absolute-pixel-position", Fx_set_mouse_absolute_pixel_position,
5370 Sx_set_mouse_absolute_pixel_position, 2, 2, 0,
5371 doc: /* Move mouse pointer to absolute pixel position (X, Y).
5372 The coordinates X and Y are interpreted in pixels relative to a position
5373 \(0, 0) of the selected frame's display. */)
5374 (Lisp_Object x, Lisp_Object y)
5376 struct frame *f = SELECTED_FRAME ();
5378 if (FRAME_INITIAL_P (f) || !FRAME_X_P (f))
5379 return Qnil;
5381 CHECK_TYPE_RANGED_INTEGER (int, x);
5382 CHECK_TYPE_RANGED_INTEGER (int, y);
5384 block_input ();
5385 XWarpPointer (FRAME_X_DISPLAY (f), None, DefaultRootWindow (FRAME_X_DISPLAY (f)),
5386 0, 0, 0, 0, XINT (x), XINT (y));
5387 unblock_input ();
5389 return Qnil;
5392 /************************************************************************
5393 X Displays
5394 ************************************************************************/
5397 /* Mapping visual names to visuals. */
5399 static struct visual_class
5401 const char *name;
5402 int class;
5404 visual_classes[] =
5406 {"StaticGray", StaticGray},
5407 {"GrayScale", GrayScale},
5408 {"StaticColor", StaticColor},
5409 {"PseudoColor", PseudoColor},
5410 {"TrueColor", TrueColor},
5411 {"DirectColor", DirectColor},
5412 {NULL, 0}
5416 #ifndef HAVE_XSCREENNUMBEROFSCREEN
5418 /* Value is the screen number of screen SCR. This is a substitute for
5419 the X function with the same name when that doesn't exist. */
5422 XScreenNumberOfScreen (scr)
5423 register Screen *scr;
5425 Display *dpy = scr->display;
5426 int i;
5428 for (i = 0; i < dpy->nscreens; ++i)
5429 if (scr == dpy->screens + i)
5430 break;
5432 return i;
5435 #endif /* not HAVE_XSCREENNUMBEROFSCREEN */
5438 /* Select the visual that should be used on display DPYINFO. Set
5439 members of DPYINFO appropriately. Called from x_term_init. */
5441 void
5442 select_visual (struct x_display_info *dpyinfo)
5444 Display *dpy = dpyinfo->display;
5445 Screen *screen = dpyinfo->screen;
5447 /* See if a visual is specified. */
5448 AUTO_STRING (visualClass, "visualClass");
5449 AUTO_STRING (VisualClass, "VisualClass");
5450 Lisp_Object value = display_x_get_resource (dpyinfo, visualClass,
5451 VisualClass, Qnil, Qnil);
5453 if (STRINGP (value))
5455 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
5456 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
5457 depth, a decimal number. NAME is compared with case ignored. */
5458 char *s = alloca (SBYTES (value) + 1);
5459 char *dash;
5460 int i, class = -1;
5461 XVisualInfo vinfo;
5463 lispstpcpy (s, value);
5464 dash = strchr (s, '-');
5465 if (dash)
5467 dpyinfo->n_planes = atoi (dash + 1);
5468 *dash = '\0';
5470 else
5471 /* We won't find a matching visual with depth 0, so that
5472 an error will be printed below. */
5473 dpyinfo->n_planes = 0;
5475 /* Determine the visual class. */
5476 for (i = 0; visual_classes[i].name; ++i)
5477 if (xstrcasecmp (s, visual_classes[i].name) == 0)
5479 class = visual_classes[i].class;
5480 break;
5483 /* Look up a matching visual for the specified class. */
5484 if (class == -1
5485 || !XMatchVisualInfo (dpy, XScreenNumberOfScreen (screen),
5486 dpyinfo->n_planes, class, &vinfo))
5487 fatal ("Invalid visual specification '%s'",
5488 SSDATA (ENCODE_SYSTEM (value)));
5490 dpyinfo->visual = vinfo.visual;
5492 else
5494 int n_visuals;
5495 XVisualInfo *vinfo, vinfo_template;
5497 dpyinfo->visual = DefaultVisualOfScreen (screen);
5499 vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
5500 vinfo_template.screen = XScreenNumberOfScreen (screen);
5501 vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
5502 &vinfo_template, &n_visuals);
5503 if (n_visuals <= 0)
5504 fatal ("Can't get proper X visual info");
5506 dpyinfo->n_planes = vinfo->depth;
5507 XFree (vinfo);
5512 /* Return the X display structure for the display named NAME.
5513 Open a new connection if necessary. */
5515 static struct x_display_info *
5516 x_display_info_for_name (Lisp_Object name)
5518 struct x_display_info *dpyinfo;
5520 CHECK_STRING (name);
5522 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
5523 if (!NILP (Fstring_equal (XCAR (dpyinfo->name_list_element), name)))
5524 return dpyinfo;
5526 /* Use this general default value to start with. */
5527 Vx_resource_name = Vinvocation_name;
5529 validate_x_resource_name ();
5531 dpyinfo = x_term_init (name, 0, SSDATA (Vx_resource_name));
5533 if (dpyinfo == 0)
5534 error ("Cannot connect to X server %s", SDATA (name));
5536 XSETFASTINT (Vwindow_system_version, 11);
5538 return dpyinfo;
5542 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
5543 1, 3, 0,
5544 doc: /* Open a connection to a display server.
5545 DISPLAY is the name of the display to connect to.
5546 Optional second arg XRM-STRING is a string of resources in xrdb format.
5547 If the optional third arg MUST-SUCCEED is non-nil,
5548 terminate Emacs if we can't open the connection.
5549 \(In the Nextstep version, the last two arguments are currently ignored.) */)
5550 (Lisp_Object display, Lisp_Object xrm_string, Lisp_Object must_succeed)
5552 char *xrm_option;
5553 struct x_display_info *dpyinfo;
5555 CHECK_STRING (display);
5556 if (! NILP (xrm_string))
5557 CHECK_STRING (xrm_string);
5559 xrm_option = NILP (xrm_string) ? 0 : SSDATA (xrm_string);
5561 validate_x_resource_name ();
5563 /* This is what opens the connection and sets x_current_display.
5564 This also initializes many symbols, such as those used for input. */
5565 dpyinfo = x_term_init (display, xrm_option,
5566 SSDATA (Vx_resource_name));
5568 if (dpyinfo == 0)
5570 if (!NILP (must_succeed))
5571 fatal ("Cannot connect to X server %s.\n\
5572 Check the DISPLAY environment variable or use `-d'.\n\
5573 Also use the `xauth' program to verify that you have the proper\n\
5574 authorization information needed to connect the X server.\n\
5575 An insecure way to solve the problem may be to use `xhost'.\n",
5576 SDATA (display));
5577 else
5578 error ("Cannot connect to X server %s", SDATA (display));
5581 XSETFASTINT (Vwindow_system_version, 11);
5582 return Qnil;
5585 DEFUN ("x-close-connection", Fx_close_connection,
5586 Sx_close_connection, 1, 1, 0,
5587 doc: /* Close the connection to TERMINAL's X server.
5588 For TERMINAL, specify a terminal object, a frame or a display name (a
5589 string). If TERMINAL is nil, that stands for the selected frame's
5590 terminal. */)
5591 (Lisp_Object terminal)
5593 struct x_display_info *dpyinfo = check_x_display_info (terminal);
5595 if (dpyinfo->reference_count > 0)
5596 error ("Display still has frames on it");
5598 x_delete_terminal (dpyinfo->terminal);
5600 return Qnil;
5603 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
5604 doc: /* Return the list of display names that Emacs has connections to. */)
5605 (void)
5607 Lisp_Object result = Qnil;
5608 struct x_display_info *xdi;
5610 for (xdi = x_display_list; xdi; xdi = xdi->next)
5611 result = Fcons (XCAR (xdi->name_list_element), result);
5613 return result;
5616 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
5617 doc: /* If ON is non-nil, report X errors as soon as the erring request is made.
5618 This function only has an effect on X Windows. With MS Windows, it is
5619 defined but does nothing.
5621 If ON is nil, allow buffering of requests.
5622 Turning on synchronization prohibits the Xlib routines from buffering
5623 requests and seriously degrades performance, but makes debugging much
5624 easier.
5625 The optional second argument TERMINAL specifies which display to act on.
5626 TERMINAL should be a terminal object, a frame or a display name (a string).
5627 If TERMINAL is omitted or nil, that stands for the selected frame's display. */)
5628 (Lisp_Object on, Lisp_Object terminal)
5630 struct x_display_info *dpyinfo = check_x_display_info (terminal);
5632 XSynchronize (dpyinfo->display, !EQ (on, Qnil));
5634 return Qnil;
5637 /* Wait for responses to all X commands issued so far for frame F. */
5639 void
5640 x_sync (struct frame *f)
5642 block_input ();
5643 XSync (FRAME_X_DISPLAY (f), False);
5644 unblock_input ();
5648 /***********************************************************************
5649 Window properties
5650 ***********************************************************************/
5652 DEFUN ("x-change-window-property", Fx_change_window_property,
5653 Sx_change_window_property, 2, 6, 0,
5654 doc: /* Change window property PROP to VALUE on the X window of FRAME.
5655 PROP must be a string. VALUE may be a string or a list of conses,
5656 numbers and/or strings. If an element in the list is a string, it is
5657 converted to an atom and the value of the atom is used. If an element
5658 is a cons, it is converted to a 32 bit number where the car is the 16
5659 top bits and the cdr is the lower 16 bits.
5661 FRAME nil or omitted means use the selected frame.
5662 If TYPE is given and non-nil, it is the name of the type of VALUE.
5663 If TYPE is not given or nil, the type is STRING.
5664 FORMAT gives the size in bits of each element if VALUE is a list.
5665 It must be one of 8, 16 or 32.
5666 If VALUE is a string or FORMAT is nil or not given, FORMAT defaults to 8.
5667 If OUTER-P is non-nil, the property is changed for the outer X window of
5668 FRAME. Default is to change on the edit X window. */)
5669 (Lisp_Object prop, Lisp_Object value, Lisp_Object frame,
5670 Lisp_Object type, Lisp_Object format, Lisp_Object outer_p)
5672 struct frame *f = decode_window_system_frame (frame);
5673 Atom prop_atom;
5674 Atom target_type = XA_STRING;
5675 int element_format = 8;
5676 unsigned char *data;
5677 int nelements;
5678 Window w;
5680 CHECK_STRING (prop);
5682 if (! NILP (format))
5684 CHECK_NUMBER (format);
5686 if (XINT (format) != 8 && XINT (format) != 16
5687 && XINT (format) != 32)
5688 error ("FORMAT must be one of 8, 16 or 32");
5689 element_format = XINT (format);
5692 if (CONSP (value))
5694 ptrdiff_t elsize;
5696 nelements = x_check_property_data (value);
5697 if (nelements == -1)
5698 error ("Bad data in VALUE, must be number, string or cons");
5700 /* The man page for XChangeProperty:
5701 "If the specified format is 32, the property data must be a
5702 long array."
5703 This applies even if long is more than 32 bits. The X library
5704 converts to 32 bits before sending to the X server. */
5705 elsize = element_format == 32 ? sizeof (long) : element_format >> 3;
5706 data = xnmalloc (nelements, elsize);
5708 x_fill_property_data (FRAME_X_DISPLAY (f), value, data, element_format);
5710 else
5712 ptrdiff_t elsize;
5714 CHECK_STRING (value);
5715 data = SDATA (value);
5716 if (INT_MAX < SBYTES (value))
5717 error ("VALUE too long");
5719 /* See comment above about longs and format=32 */
5720 elsize = element_format == 32 ? sizeof (long) : element_format >> 3;
5721 if (SBYTES (value) % elsize != 0)
5722 error ("VALUE must contain an integral number of octets for FORMAT");
5723 nelements = SBYTES (value) / elsize;
5726 block_input ();
5727 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False);
5728 if (! NILP (type))
5730 CHECK_STRING (type);
5731 target_type = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (type), False);
5734 if (! NILP (outer_p)) w = FRAME_OUTER_WINDOW (f);
5735 else w = FRAME_X_WINDOW (f);
5737 XChangeProperty (FRAME_X_DISPLAY (f), w,
5738 prop_atom, target_type, element_format, PropModeReplace,
5739 data, nelements);
5741 if (CONSP (value)) xfree (data);
5743 /* Make sure the property is set when we return. */
5744 XFlush (FRAME_X_DISPLAY (f));
5745 unblock_input ();
5747 return value;
5751 DEFUN ("x-delete-window-property", Fx_delete_window_property,
5752 Sx_delete_window_property, 1, 2, 0,
5753 doc: /* Remove window property PROP from X window of FRAME.
5754 FRAME nil or omitted means use the selected frame. Value is PROP. */)
5755 (Lisp_Object prop, Lisp_Object frame)
5757 struct frame *f = decode_window_system_frame (frame);
5758 Atom prop_atom;
5760 CHECK_STRING (prop);
5761 block_input ();
5762 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False);
5763 XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), prop_atom);
5765 /* Make sure the property is removed when we return. */
5766 XFlush (FRAME_X_DISPLAY (f));
5767 unblock_input ();
5769 return prop;
5773 static Lisp_Object
5774 x_window_property_intern (struct frame *f,
5775 Window target_window,
5776 Atom prop_atom,
5777 Atom target_type,
5778 Lisp_Object delete_p,
5779 Lisp_Object vector_ret_p,
5780 bool *found)
5782 unsigned char *tmp_data = NULL;
5783 Lisp_Object prop_value = Qnil;
5784 Atom actual_type;
5785 int actual_format;
5786 unsigned long actual_size, bytes_remaining;
5787 int rc;
5789 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
5790 prop_atom, 0, 0, False, target_type,
5791 &actual_type, &actual_format, &actual_size,
5792 &bytes_remaining, &tmp_data);
5794 *found = actual_format != 0;
5796 if (rc == Success && *found)
5798 XFree (tmp_data);
5799 tmp_data = NULL;
5801 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
5802 prop_atom, 0, bytes_remaining,
5803 ! NILP (delete_p), target_type,
5804 &actual_type, &actual_format,
5805 &actual_size, &bytes_remaining,
5806 &tmp_data);
5807 if (rc == Success && tmp_data)
5809 /* The man page for XGetWindowProperty says:
5810 "If the returned format is 32, the returned data is represented
5811 as a long array and should be cast to that type to obtain the
5812 elements."
5813 This applies even if long is more than 32 bits, the X library
5814 converts from 32 bit elements received from the X server to long
5815 and passes the long array to us. Thus, for that case memcpy can not
5816 be used. We convert to a 32 bit type here, because so much code
5817 assume on that.
5819 The bytes and offsets passed to XGetWindowProperty refers to the
5820 property and those are indeed in 32 bit quantities if format is
5821 32. */
5823 if (LONG_WIDTH > 32 && actual_format == 32)
5825 unsigned long i;
5826 int *idata = (int *) tmp_data;
5827 long *ldata = (long *) tmp_data;
5829 for (i = 0; i < actual_size; ++i)
5830 idata[i] = (int) ldata[i];
5833 if (NILP (vector_ret_p))
5834 prop_value = make_string ((char *) tmp_data,
5835 (actual_format >> 3) * actual_size);
5836 else
5837 prop_value = x_property_data_to_lisp (f,
5838 tmp_data,
5839 actual_type,
5840 actual_format,
5841 actual_size);
5844 if (tmp_data) XFree (tmp_data);
5847 return prop_value;
5850 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
5851 1, 6, 0,
5852 doc: /* Value is the value of window property PROP on FRAME.
5853 If FRAME is nil or omitted, use the selected frame.
5855 On X Windows, the following optional arguments are also accepted:
5856 If TYPE is nil or omitted, get the property as a string.
5857 Otherwise TYPE is the name of the atom that denotes the type expected.
5858 If SOURCE is non-nil, get the property on that window instead of from
5859 FRAME. The number 0 denotes the root window.
5860 If DELETE-P is non-nil, delete the property after retrieving it.
5861 If VECTOR-RET-P is non-nil, don't return a string but a vector of values.
5863 On MS Windows, this function accepts but ignores those optional arguments.
5865 Value is nil if FRAME hasn't a property with name PROP or if PROP has
5866 no value of TYPE (always string in the MS Windows case). */)
5867 (Lisp_Object prop, Lisp_Object frame, Lisp_Object type,
5868 Lisp_Object source, Lisp_Object delete_p, Lisp_Object vector_ret_p)
5870 struct frame *f = decode_window_system_frame (frame);
5871 Atom prop_atom;
5872 Lisp_Object prop_value = Qnil;
5873 Atom target_type = XA_STRING;
5874 Window target_window = FRAME_X_WINDOW (f);
5875 bool found;
5877 CHECK_STRING (prop);
5879 if (! NILP (source))
5881 CONS_TO_INTEGER (source, Window, target_window);
5882 if (! target_window)
5883 target_window = FRAME_DISPLAY_INFO (f)->root_window;
5886 block_input ();
5887 if (STRINGP (type))
5889 if (strcmp ("AnyPropertyType", SSDATA (type)) == 0)
5890 target_type = AnyPropertyType;
5891 else
5892 target_type = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (type), False);
5895 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False);
5896 prop_value = x_window_property_intern (f,
5897 target_window,
5898 prop_atom,
5899 target_type,
5900 delete_p,
5901 vector_ret_p,
5902 &found);
5903 if (NILP (prop_value)
5904 && ! found
5905 && NILP (source)
5906 && target_window != FRAME_OUTER_WINDOW (f))
5908 prop_value = x_window_property_intern (f,
5909 FRAME_OUTER_WINDOW (f),
5910 prop_atom,
5911 target_type,
5912 delete_p,
5913 vector_ret_p,
5914 &found);
5918 unblock_input ();
5919 return prop_value;
5922 DEFUN ("x-window-property-attributes", Fx_window_property_attributes, Sx_window_property_attributes,
5923 1, 3, 0,
5924 doc: /* Retrieve metadata about window property PROP on FRAME.
5925 If FRAME is nil or omitted, use the selected frame.
5926 If SOURCE is non-nil, get the property on that window instead of from
5927 FRAME. The number 0 denotes the root window.
5929 Return value is nil if FRAME hasn't a property with name PROP.
5930 Otherwise, the return value is a vector with the following fields:
5932 0. The property type, as an integer. The symbolic name of
5933 the type can be obtained with `x-get-atom-name'.
5934 1. The format of each element; one of 8, 16, or 32.
5935 2. The length of the property, in number of elements. */)
5936 (Lisp_Object prop, Lisp_Object frame, Lisp_Object source)
5938 struct frame *f = decode_window_system_frame (frame);
5939 Window target_window = FRAME_X_WINDOW (f);
5940 Atom prop_atom;
5941 Lisp_Object prop_attr = Qnil;
5942 Atom actual_type;
5943 int actual_format;
5944 unsigned long actual_size, bytes_remaining;
5945 unsigned char *tmp_data = NULL;
5946 int rc;
5948 CHECK_STRING (prop);
5950 if (! NILP (source))
5952 CONS_TO_INTEGER (source, Window, target_window);
5953 if (! target_window)
5954 target_window = FRAME_DISPLAY_INFO (f)->root_window;
5957 block_input ();
5959 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False);
5960 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
5961 prop_atom, 0, 0, False, AnyPropertyType,
5962 &actual_type, &actual_format, &actual_size,
5963 &bytes_remaining, &tmp_data);
5964 if (rc == Success /* no invalid params */
5965 && actual_format == 0 /* but prop not found */
5966 && NILP (source)
5967 && target_window != FRAME_OUTER_WINDOW (f))
5969 /* analogous behavior to x-window-property: if property isn't found
5970 on the frame's inner window and no alternate window id was
5971 provided, try the frame's outer window. */
5972 target_window = FRAME_OUTER_WINDOW (f);
5973 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
5974 prop_atom, 0, 0, False, AnyPropertyType,
5975 &actual_type, &actual_format, &actual_size,
5976 &bytes_remaining, &tmp_data);
5979 if (rc == Success && actual_format != 0)
5981 XFree (tmp_data);
5983 prop_attr = make_uninit_vector (3);
5984 ASET (prop_attr, 0, make_number (actual_type));
5985 ASET (prop_attr, 1, make_number (actual_format));
5986 ASET (prop_attr, 2, make_number (bytes_remaining / (actual_format >> 3)));
5989 unblock_input ();
5990 return prop_attr;
5993 /***********************************************************************
5994 Tool tips
5995 ***********************************************************************/
5997 static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
5998 Lisp_Object, int, int, int *, int *);
6000 /* The frame of a currently visible tooltip. */
6002 Lisp_Object tip_frame;
6004 /* If non-nil, a timer started that hides the last tooltip when it
6005 fires. */
6007 static Lisp_Object tip_timer;
6008 Window tip_window;
6010 /* If non-nil, a vector of 3 elements containing the last args
6011 with which x-show-tip was called. See there. */
6013 static Lisp_Object last_show_tip_args;
6016 static void
6017 unwind_create_tip_frame (Lisp_Object frame)
6019 Lisp_Object deleted;
6021 deleted = unwind_create_frame (frame);
6022 if (EQ (deleted, Qt))
6024 tip_window = None;
6025 tip_frame = Qnil;
6030 /* Create a frame for a tooltip on the display described by DPYINFO.
6031 PARMS is a list of frame parameters. TEXT is the string to
6032 display in the tip frame. Value is the frame.
6034 Note that functions called here, esp. x_default_parameter can
6035 signal errors, for instance when a specified color name is
6036 undefined. We have to make sure that we're in a consistent state
6037 when this happens. */
6039 static Lisp_Object
6040 x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms)
6042 struct frame *f;
6043 Lisp_Object frame;
6044 Lisp_Object name;
6045 int width, height;
6046 ptrdiff_t count = SPECPDL_INDEX ();
6047 bool face_change_before = face_change;
6048 int x_width = 0, x_height = 0;
6050 if (!dpyinfo->terminal->name)
6051 error ("Terminal is not live, can't create new frames on it");
6053 parms = Fcopy_alist (parms);
6055 /* Get the name of the frame to use for resource lookup. */
6056 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
6057 if (!STRINGP (name)
6058 && !EQ (name, Qunbound)
6059 && !NILP (name))
6060 error ("Invalid frame name--not a string or nil");
6062 frame = Qnil;
6063 f = make_frame (false);
6064 f->wants_modeline = false;
6065 XSETFRAME (frame, f);
6066 record_unwind_protect (unwind_create_tip_frame, frame);
6068 f->terminal = dpyinfo->terminal;
6070 /* By setting the output method, we're essentially saying that
6071 the frame is live, as per FRAME_LIVE_P. If we get a signal
6072 from this point on, x_destroy_window might screw up reference
6073 counts etc. */
6074 f->output_method = output_x_window;
6075 f->output_data.x = xzalloc (sizeof *f->output_data.x);
6076 f->output_data.x->icon_bitmap = -1;
6077 FRAME_FONTSET (f) = -1;
6078 f->output_data.x->scroll_bar_foreground_pixel = -1;
6079 f->output_data.x->scroll_bar_background_pixel = -1;
6080 #if defined (USE_LUCID) && defined (USE_TOOLKIT_SCROLL_BARS)
6081 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
6082 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
6083 #endif /* USE_LUCID && USE_TOOLKIT_SCROLL_BARS */
6084 f->output_data.x->white_relief.pixel = -1;
6085 f->output_data.x->black_relief.pixel = -1;
6087 fset_icon_name (f, Qnil);
6088 FRAME_DISPLAY_INFO (f) = dpyinfo;
6089 f->output_data.x->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
6090 f->output_data.x->explicit_parent = false;
6092 /* These colors will be set anyway later, but it's important
6093 to get the color reference counts right, so initialize them! */
6095 Lisp_Object black;
6097 /* Function x_decode_color can signal an error. Make
6098 sure to initialize color slots so that we won't try
6099 to free colors we haven't allocated. */
6100 FRAME_FOREGROUND_PIXEL (f) = -1;
6101 FRAME_BACKGROUND_PIXEL (f) = -1;
6102 f->output_data.x->cursor_pixel = -1;
6103 f->output_data.x->cursor_foreground_pixel = -1;
6104 f->output_data.x->border_pixel = -1;
6105 f->output_data.x->mouse_pixel = -1;
6107 black = build_string ("black");
6108 FRAME_FOREGROUND_PIXEL (f)
6109 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
6110 FRAME_BACKGROUND_PIXEL (f)
6111 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
6112 f->output_data.x->cursor_pixel
6113 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
6114 f->output_data.x->cursor_foreground_pixel
6115 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
6116 f->output_data.x->border_pixel
6117 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
6118 f->output_data.x->mouse_pixel
6119 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
6122 /* Set the name; the functions to which we pass f expect the name to
6123 be set. */
6124 if (EQ (name, Qunbound) || NILP (name))
6126 fset_name (f, build_string (dpyinfo->x_id_name));
6127 f->explicit_name = false;
6129 else
6131 fset_name (f, name);
6132 f->explicit_name = true;
6133 /* use the frame's title when getting resources for this frame. */
6134 specbind (Qx_resource_name, name);
6137 #ifdef USE_CAIRO
6138 register_font_driver (&ftcrfont_driver, f);
6139 #else
6140 register_font_driver (&xfont_driver, f);
6141 #ifdef HAVE_FREETYPE
6142 #ifdef HAVE_XFT
6143 register_font_driver (&xftfont_driver, f);
6144 #else /* not HAVE_XFT */
6145 register_font_driver (&ftxfont_driver, f);
6146 #endif /* not HAVE_XFT */
6147 #endif /* HAVE_FREETYPE */
6148 #endif /* not USE_CAIRO */
6150 image_cache_refcount =
6151 FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
6152 #ifdef GLYPH_DEBUG
6153 dpyinfo_refcount = dpyinfo->reference_count;
6154 #endif /* GLYPH_DEBUG */
6156 x_default_parameter (f, parms, Qfont_backend, Qnil,
6157 "fontBackend", "FontBackend", RES_TYPE_STRING);
6159 /* Extract the window parameters from the supplied values that are
6160 needed to determine window geometry. */
6161 x_default_font_parameter (f, parms);
6163 x_default_parameter (f, parms, Qborder_width, make_number (0),
6164 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
6166 /* This defaults to 2 in order to match xterm. We recognize either
6167 internalBorderWidth or internalBorder (which is what xterm calls
6168 it). */
6169 if (NILP (Fassq (Qinternal_border_width, parms)))
6171 Lisp_Object value;
6173 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
6174 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
6175 if (! EQ (value, Qunbound))
6176 parms = Fcons (Fcons (Qinternal_border_width, value),
6177 parms);
6180 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
6181 "internalBorderWidth", "internalBorderWidth",
6182 RES_TYPE_NUMBER);
6183 x_default_parameter (f, parms, Qright_divider_width, make_number (0),
6184 NULL, NULL, RES_TYPE_NUMBER);
6185 x_default_parameter (f, parms, Qbottom_divider_width, make_number (0),
6186 NULL, NULL, RES_TYPE_NUMBER);
6188 /* Also do the stuff which must be set before the window exists. */
6189 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
6190 "foreground", "Foreground", RES_TYPE_STRING);
6191 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
6192 "background", "Background", RES_TYPE_STRING);
6193 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
6194 "pointerColor", "Foreground", RES_TYPE_STRING);
6195 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
6196 "cursorColor", "Foreground", RES_TYPE_STRING);
6197 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
6198 "borderColor", "BorderColor", RES_TYPE_STRING);
6200 /* Init faces before x_default_parameter is called for the
6201 scroll-bar-width parameter because otherwise we end up in
6202 init_iterator with a null face cache, which should not happen. */
6203 init_frame_faces (f);
6205 f->output_data.x->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
6207 x_figure_window_size (f, parms, false, &x_width, &x_height);
6210 XSetWindowAttributes attrs;
6211 unsigned long mask;
6212 Atom type = FRAME_DISPLAY_INFO (f)->Xatom_net_window_type_tooltip;
6214 block_input ();
6215 mask = CWBackPixel | CWOverrideRedirect | CWEventMask | CWCursor;
6216 if (DoesSaveUnders (dpyinfo->screen))
6217 mask |= CWSaveUnder;
6219 /* Window managers look at the override-redirect flag to determine
6220 whether or net to give windows a decoration (Xlib spec, chapter
6221 3.2.8). */
6222 attrs.override_redirect = True;
6223 attrs.save_under = True;
6224 attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
6225 attrs.cursor =
6226 f->output_data.x->current_cursor
6227 = f->output_data.x->text_cursor;
6228 /* Arrange for getting MapNotify and UnmapNotify events. */
6229 attrs.event_mask = StructureNotifyMask;
6230 tip_window
6231 = FRAME_X_WINDOW (f)
6232 = XCreateWindow (FRAME_X_DISPLAY (f),
6233 FRAME_DISPLAY_INFO (f)->root_window,
6234 /* x, y, width, height */
6235 0, 0, 1, 1,
6236 /* Border. */
6237 f->border_width,
6238 CopyFromParent, InputOutput, CopyFromParent,
6239 mask, &attrs);
6240 initial_set_up_x_back_buffer (f);
6241 XChangeProperty (FRAME_X_DISPLAY (f), tip_window,
6242 FRAME_DISPLAY_INFO (f)->Xatom_net_window_type,
6243 XA_ATOM, 32, PropModeReplace,
6244 (unsigned char *)&type, 1);
6245 unblock_input ();
6248 x_make_gc (f);
6250 x_default_parameter (f, parms, Qauto_raise, Qnil,
6251 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
6252 x_default_parameter (f, parms, Qauto_lower, Qnil,
6253 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
6254 x_default_parameter (f, parms, Qcursor_type, Qbox,
6255 "cursorType", "CursorType", RES_TYPE_SYMBOL);
6256 x_default_parameter (f, parms, Qalpha, Qnil,
6257 "alpha", "Alpha", RES_TYPE_NUMBER);
6259 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
6260 Change will not be effected unless different from the current
6261 FRAME_LINES (f). */
6262 width = FRAME_COLS (f);
6263 height = FRAME_LINES (f);
6264 SET_FRAME_COLS (f, 0);
6265 SET_FRAME_LINES (f, 0);
6266 change_frame_size (f, width, height, true, false, false, false);
6268 /* Add `tooltip' frame parameter's default value. */
6269 if (NILP (Fframe_parameter (frame, Qtooltip)))
6271 AUTO_FRAME_ARG (arg, Qtooltip, Qt);
6272 Fmodify_frame_parameters (frame, arg);
6275 /* FIXME - can this be done in a similar way to normal frames?
6276 http://lists.gnu.org/archive/html/emacs-devel/2007-10/msg00641.html */
6278 /* Set the `display-type' frame parameter before setting up faces. */
6280 Lisp_Object disptype;
6282 if (FRAME_DISPLAY_INFO (f)->n_planes == 1)
6283 disptype = Qmono;
6284 else if (FRAME_DISPLAY_INFO (f)->visual->class == GrayScale
6285 || FRAME_DISPLAY_INFO (f)->visual->class == StaticGray)
6286 disptype = intern ("grayscale");
6287 else
6288 disptype = intern ("color");
6290 if (NILP (Fframe_parameter (frame, Qdisplay_type)))
6292 AUTO_FRAME_ARG (arg, Qdisplay_type, disptype);
6293 Fmodify_frame_parameters (frame, arg);
6297 /* Set up faces after all frame parameters are known. This call
6298 also merges in face attributes specified for new frames.
6300 Frame parameters may be changed if .Xdefaults contains
6301 specifications for the default font. For example, if there is an
6302 `Emacs.default.attributeBackground: pink', the `background-color'
6303 attribute of the frame get's set, which let's the internal border
6304 of the tooltip frame appear in pink. Prevent this. */
6306 Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
6308 call2 (Qface_set_after_frame_default, frame, Qnil);
6310 if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
6312 AUTO_FRAME_ARG (arg, Qbackground_color, bg);
6313 Fmodify_frame_parameters (frame, arg);
6317 f->no_split = true;
6319 /* Now that the frame will be official, it counts as a reference to
6320 its display and terminal. */
6321 FRAME_DISPLAY_INFO (f)->reference_count++;
6322 f->terminal->reference_count++;
6324 /* It is now ok to make the frame official even if we get an error
6325 below. And the frame needs to be on Vframe_list or making it
6326 visible won't work. */
6327 Vframe_list = Fcons (frame, Vframe_list);
6328 f->can_x_set_window_size = true;
6330 /* Setting attributes of faces of the tooltip frame from resources
6331 and similar will set face_change, which leads to the clearing of
6332 all current matrices. Since this isn't necessary here, avoid it
6333 by resetting face_change to the value it had before we created
6334 the tip frame. */
6335 face_change = face_change_before;
6337 /* Discard the unwind_protect. */
6338 return unbind_to (count, frame);
6342 /* Compute where to display tip frame F. PARMS is the list of frame
6343 parameters for F. DX and DY are specified offsets from the current
6344 location of the mouse. WIDTH and HEIGHT are the width and height
6345 of the tooltip. Return coordinates relative to the root window of
6346 the display in *ROOT_X, and *ROOT_Y. */
6348 static void
6349 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)
6351 Lisp_Object left, top, right, bottom;
6352 int win_x, win_y;
6353 Window root, child;
6354 unsigned pmask;
6355 int min_x, min_y, max_x, max_y = -1;
6357 /* User-specified position? */
6358 left = Fcdr (Fassq (Qleft, parms));
6359 top = Fcdr (Fassq (Qtop, parms));
6360 right = Fcdr (Fassq (Qright, parms));
6361 bottom = Fcdr (Fassq (Qbottom, parms));
6363 /* Move the tooltip window where the mouse pointer is. Resize and
6364 show it. */
6365 if ((!INTEGERP (left) && !INTEGERP (right))
6366 || (!INTEGERP (top) && !INTEGERP (bottom)))
6368 Lisp_Object frame, attributes, monitor, geometry;
6370 block_input ();
6371 XQueryPointer (FRAME_X_DISPLAY (f), FRAME_DISPLAY_INFO (f)->root_window,
6372 &root, &child, root_x, root_y, &win_x, &win_y, &pmask);
6373 unblock_input ();
6375 XSETFRAME(frame, f);
6376 attributes = Fx_display_monitor_attributes_list (frame);
6378 /* Try to determine the monitor where the mouse pointer is and
6379 its geometry. See bug#22549. */
6380 while (CONSP (attributes))
6382 monitor = XCAR (attributes);
6383 geometry = Fassq (Qgeometry, monitor);
6384 if (CONSP (geometry))
6386 min_x = XINT (Fnth (make_number (1), geometry));
6387 min_y = XINT (Fnth (make_number (2), geometry));
6388 max_x = min_x + XINT (Fnth (make_number (3), geometry));
6389 max_y = min_y + XINT (Fnth (make_number (4), geometry));
6390 if (min_x <= *root_x && *root_x < max_x
6391 && min_y <= *root_y && *root_y < max_y)
6393 break;
6395 max_y = -1;
6398 attributes = XCDR (attributes);
6402 /* It was not possible to determine the monitor's geometry, so we
6403 assign some sane defaults here: */
6404 if ( max_y < 0 )
6406 min_x = 0;
6407 min_y = 0;
6408 max_x = x_display_pixel_width (FRAME_DISPLAY_INFO (f));
6409 max_y = x_display_pixel_height (FRAME_DISPLAY_INFO (f));
6412 if (INTEGERP (top))
6413 *root_y = XINT (top);
6414 else if (INTEGERP (bottom))
6415 *root_y = XINT (bottom) - height;
6416 else if (*root_y + XINT (dy) <= min_y)
6417 *root_y = min_y; /* Can happen for negative dy */
6418 else if (*root_y + XINT (dy) + height <= max_y)
6419 /* It fits below the pointer */
6420 *root_y += XINT (dy);
6421 else if (height + XINT (dy) + min_y <= *root_y)
6422 /* It fits above the pointer. */
6423 *root_y -= height + XINT (dy);
6424 else
6425 /* Put it on the top. */
6426 *root_y = min_y;
6428 if (INTEGERP (left))
6429 *root_x = XINT (left);
6430 else if (INTEGERP (right))
6431 *root_x = XINT (right) - width;
6432 else if (*root_x + XINT (dx) <= min_x)
6433 *root_x = 0; /* Can happen for negative dx */
6434 else if (*root_x + XINT (dx) + width <= max_x)
6435 /* It fits to the right of the pointer. */
6436 *root_x += XINT (dx);
6437 else if (width + XINT (dx) + min_x <= *root_x)
6438 /* It fits to the left of the pointer. */
6439 *root_x -= width + XINT (dx);
6440 else
6441 /* Put it left justified on the screen -- it ought to fit that way. */
6442 *root_x = min_x;
6446 /* Hide tooltip. Delete its frame if DELETE is true. */
6447 static Lisp_Object
6448 x_hide_tip (bool delete)
6450 if (!NILP (tip_timer))
6452 call1 (Qcancel_timer, tip_timer);
6453 tip_timer = Qnil;
6457 if (NILP (tip_frame)
6458 || (!delete && FRAMEP (tip_frame)
6459 && !FRAME_VISIBLE_P (XFRAME (tip_frame))))
6460 return Qnil;
6461 else
6463 ptrdiff_t count;
6464 Lisp_Object was_open = Qnil;
6466 count = SPECPDL_INDEX ();
6467 specbind (Qinhibit_redisplay, Qt);
6468 specbind (Qinhibit_quit, Qt);
6470 #ifdef USE_GTK
6472 /* When using system tooltip, tip_frame is the Emacs frame on
6473 which the tip is shown. */
6474 struct frame *f = XFRAME (tip_frame);
6476 if (FRAME_LIVE_P (f) && xg_hide_tooltip (f))
6478 tip_frame = Qnil;
6479 was_open = Qt;
6482 #endif
6484 if (FRAMEP (tip_frame))
6486 if (delete)
6488 delete_frame (tip_frame, Qnil);
6489 tip_frame = Qnil;
6491 else
6492 x_make_frame_invisible (XFRAME (tip_frame));
6494 was_open = Qt;
6496 #ifdef USE_LUCID
6497 /* Bloodcurdling hack alert: The Lucid menu bar widget's
6498 redisplay procedure is not called when a tip frame over
6499 menu items is unmapped. Redisplay the menu manually... */
6501 Widget w;
6502 struct frame *f = SELECTED_FRAME ();
6503 if (FRAME_X_P (f) && FRAME_LIVE_P (f))
6505 w = f->output_data.x->menubar_widget;
6507 if (!DoesSaveUnders (FRAME_DISPLAY_INFO (f)->screen)
6508 && w != NULL)
6510 block_input ();
6511 xlwmenu_redisplay (w);
6512 unblock_input ();
6516 #endif /* USE_LUCID */
6518 else
6519 tip_frame = Qnil;
6521 return unbind_to (count, was_open);
6525 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
6526 doc: /* Show STRING in a "tooltip" window on frame FRAME.
6527 A tooltip window is a small X window displaying a string.
6529 This is an internal function; Lisp code should call `tooltip-show'.
6531 FRAME nil or omitted means use the selected frame.
6533 PARMS is an optional list of frame parameters which can be used to
6534 change the tooltip's appearance.
6536 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
6537 means use the default timeout of 5 seconds.
6539 If the list of frame parameters PARMS contains a `left' parameter,
6540 display the tooltip at that x-position. If the list of frame parameters
6541 PARMS contains no `left' but a `right' parameter, display the tooltip
6542 right-adjusted at that x-position. Otherwise display it at the
6543 x-position of the mouse, with offset DX added (default is 5 if DX isn't
6544 specified).
6546 Likewise for the y-position: If a `top' frame parameter is specified, it
6547 determines the position of the upper edge of the tooltip window. If a
6548 `bottom' parameter but no `top' frame parameter is specified, it
6549 determines the position of the lower edge of the tooltip window.
6550 Otherwise display the tooltip window at the y-position of the mouse,
6551 with offset DY added (default is -10).
6553 A tooltip's maximum size is specified by `x-max-tooltip-size'.
6554 Text larger than the specified size is clipped. */)
6555 (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy)
6557 struct frame *f, *tip_f;
6558 struct window *w;
6559 int root_x, root_y;
6560 struct buffer *old_buffer;
6561 struct text_pos pos;
6562 int width, height;
6563 int old_windows_or_buffers_changed = windows_or_buffers_changed;
6564 ptrdiff_t count = SPECPDL_INDEX ();
6565 ptrdiff_t count_1;
6566 Lisp_Object window, size;
6567 AUTO_STRING (tip, " *tip*");
6569 specbind (Qinhibit_redisplay, Qt);
6571 CHECK_STRING (string);
6572 if (SCHARS (string) == 0)
6573 string = make_unibyte_string (" ", 1);
6575 f = decode_window_system_frame (frame);
6576 if (NILP (timeout))
6577 timeout = make_number (5);
6578 else
6579 CHECK_NATNUM (timeout);
6581 if (NILP (dx))
6582 dx = make_number (5);
6583 else
6584 CHECK_NUMBER (dx);
6586 if (NILP (dy))
6587 dy = make_number (-10);
6588 else
6589 CHECK_NUMBER (dy);
6591 #ifdef USE_GTK
6592 if (x_gtk_use_system_tooltips)
6594 bool ok;
6596 /* Hide a previous tip, if any. */
6597 Fx_hide_tip ();
6599 block_input ();
6600 ok = xg_prepare_tooltip (f, string, &width, &height);
6601 if (ok)
6603 compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
6604 xg_show_tooltip (f, root_x, root_y);
6605 /* This is used in Fx_hide_tip. */
6606 XSETFRAME (tip_frame, f);
6608 unblock_input ();
6609 if (ok) goto start_timer;
6611 #endif /* USE_GTK */
6613 if (NILP (last_show_tip_args))
6614 last_show_tip_args = Fmake_vector (make_number (3), Qnil);
6616 if (FRAMEP (tip_frame) && FRAME_LIVE_P (XFRAME (tip_frame)))
6618 Lisp_Object last_string = AREF (last_show_tip_args, 0);
6619 Lisp_Object last_frame = AREF (last_show_tip_args, 1);
6620 Lisp_Object last_parms = AREF (last_show_tip_args, 2);
6622 if (FRAME_VISIBLE_P (XFRAME (tip_frame))
6623 && EQ (frame, last_frame)
6624 && !NILP (Fequal_including_properties (last_string, string))
6625 && !NILP (Fequal (last_parms, parms)))
6627 /* Only DX and DY have changed. */
6628 tip_f = XFRAME (tip_frame);
6629 if (!NILP (tip_timer))
6631 Lisp_Object timer = tip_timer;
6633 tip_timer = Qnil;
6634 call1 (Qcancel_timer, timer);
6637 block_input ();
6638 compute_tip_xy (tip_f, parms, dx, dy, FRAME_PIXEL_WIDTH (tip_f),
6639 FRAME_PIXEL_HEIGHT (tip_f), &root_x, &root_y);
6640 XMoveWindow (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f),
6641 root_x, root_y);
6642 unblock_input ();
6644 goto start_timer;
6646 else if (tooltip_reuse_hidden_frame && EQ (frame, last_frame))
6648 bool delete = false;
6649 Lisp_Object tail, elt, parm, last;
6651 /* Check if every parameter in PARMS has the same value in
6652 last_parms unless it should be ignored by means of
6653 Vtooltip_reuse_hidden_frame_parameters. This may destruct
6654 last_parms which, however, will be recreated below. */
6655 for (tail = parms; CONSP (tail); tail = XCDR (tail))
6657 elt = XCAR (tail);
6658 parm = Fcar (elt);
6659 /* The left, top, right and bottom parameters are handled
6660 by compute_tip_xy so they can be ignored here. */
6661 if (!EQ (parm, Qleft) && !EQ (parm, Qtop)
6662 && !EQ (parm, Qright) && !EQ (parm, Qbottom))
6664 last = Fassq (parm, last_parms);
6665 if (NILP (Fequal (Fcdr (elt), Fcdr (last))))
6667 /* We lost, delete the old tooltip. */
6668 delete = true;
6669 break;
6671 else
6672 last_parms = call2 (Qassq_delete_all, parm, last_parms);
6674 else
6675 last_parms = call2 (Qassq_delete_all, parm, last_parms);
6678 /* Now check if every parameter in what is left of last_parms
6679 with a non-nil value has an association in PARMS unless it
6680 should be ignored by means of
6681 Vtooltip_reuse_hidden_frame_parameters. */
6682 for (tail = last_parms; CONSP (tail); tail = XCDR (tail))
6684 elt = XCAR (tail);
6685 parm = Fcar (elt);
6686 if (!EQ (parm, Qleft) && !EQ (parm, Qtop) && !EQ (parm, Qright)
6687 && !EQ (parm, Qbottom) && !NILP (Fcdr (elt)))
6689 /* We lost, delete the old tooltip. */
6690 delete = true;
6691 break;
6695 x_hide_tip (delete);
6697 else
6698 x_hide_tip (true);
6700 else
6701 x_hide_tip (true);
6703 ASET (last_show_tip_args, 0, string);
6704 ASET (last_show_tip_args, 1, frame);
6705 ASET (last_show_tip_args, 2, parms);
6707 if (!FRAMEP (tip_frame) || !FRAME_LIVE_P (XFRAME (tip_frame)))
6709 /* Add default values to frame parameters. */
6710 if (NILP (Fassq (Qname, parms)))
6711 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
6712 if (NILP (Fassq (Qinternal_border_width, parms)))
6713 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
6714 if (NILP (Fassq (Qborder_width, parms)))
6715 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
6716 if (NILP (Fassq (Qborder_color, parms)))
6717 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
6718 if (NILP (Fassq (Qbackground_color, parms)))
6719 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
6720 parms);
6722 /* Create a frame for the tooltip, and record it in the global
6723 variable tip_frame. */
6724 if (NILP (tip_frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parms)))
6725 /* Creating the tip frame failed. */
6726 return unbind_to (count, Qnil);
6729 tip_f = XFRAME (tip_frame);
6730 window = FRAME_ROOT_WINDOW (tip_f);
6731 set_window_buffer (window, Fget_buffer_create (tip), false, false);
6732 w = XWINDOW (window);
6733 w->pseudo_window_p = true;
6735 /* Set up the frame's root window. Note: The following code does not
6736 try to size the window or its frame correctly. Its only purpose is
6737 to make the subsequent text size calculations work. The right
6738 sizes should get installed when the toolkit gets back to us. */
6739 w->left_col = 0;
6740 w->top_line = 0;
6741 w->pixel_left = 0;
6742 w->pixel_top = 0;
6744 if (CONSP (Vx_max_tooltip_size)
6745 && RANGED_INTEGERP (1, XCAR (Vx_max_tooltip_size), INT_MAX)
6746 && RANGED_INTEGERP (1, XCDR (Vx_max_tooltip_size), INT_MAX))
6748 w->total_cols = XFASTINT (XCAR (Vx_max_tooltip_size));
6749 w->total_lines = XFASTINT (XCDR (Vx_max_tooltip_size));
6751 else
6753 w->total_cols = 80;
6754 w->total_lines = 40;
6757 w->pixel_width = w->total_cols * FRAME_COLUMN_WIDTH (tip_f);
6758 w->pixel_height = w->total_lines * FRAME_LINE_HEIGHT (tip_f);
6759 FRAME_TOTAL_COLS (tip_f) = w->total_cols;
6760 adjust_frame_glyphs (tip_f);
6762 /* Insert STRING into root window's buffer and fit the frame to the
6763 buffer. */
6764 count_1 = SPECPDL_INDEX ();
6765 old_buffer = current_buffer;
6766 set_buffer_internal_1 (XBUFFER (w->contents));
6767 bset_truncate_lines (current_buffer, Qnil);
6768 specbind (Qinhibit_read_only, Qt);
6769 specbind (Qinhibit_modification_hooks, Qt);
6770 specbind (Qinhibit_point_motion_hooks, Qt);
6771 Ferase_buffer ();
6772 Finsert (1, &string);
6773 clear_glyph_matrix (w->desired_matrix);
6774 clear_glyph_matrix (w->current_matrix);
6775 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
6776 try_window (window, pos, TRY_WINDOW_IGNORE_FONTS_CHANGE);
6777 /* Calculate size of tooltip window. */
6778 size = Fwindow_text_pixel_size (window, Qnil, Qnil, Qnil,
6779 make_number (w->pixel_height), Qnil);
6780 /* Add the frame's internal border to calculated size. */
6781 width = XINT (Fcar (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
6782 height = XINT (Fcdr (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
6784 /* Calculate position of tooltip frame. */
6785 compute_tip_xy (tip_f, parms, dx, dy, width, height, &root_x, &root_y);
6787 /* Show tooltip frame. */
6788 block_input ();
6789 XMoveResizeWindow (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f),
6790 root_x, root_y, width, height);
6791 XMapRaised (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f));
6792 unblock_input ();
6794 w->must_be_updated_p = true;
6795 update_single_window (w);
6796 set_buffer_internal_1 (old_buffer);
6797 unbind_to (count_1, Qnil);
6798 windows_or_buffers_changed = old_windows_or_buffers_changed;
6800 start_timer:
6801 /* Let the tip disappear after timeout seconds. */
6802 tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
6803 intern ("x-hide-tip"));
6805 return unbind_to (count, Qnil);
6809 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
6810 doc: /* Hide the current tooltip window, if there is any.
6811 Value is t if tooltip was open, nil otherwise. */)
6812 (void)
6814 return x_hide_tip (!tooltip_reuse_hidden_frame);
6817 DEFUN ("x-double-buffered-p", Fx_double_buffered_p, Sx_double_buffered_p,
6818 0, 1, 0,
6819 doc: /* Return t if FRAME is being double buffered. */)
6820 (Lisp_Object frame)
6822 struct frame *f = decode_live_frame (frame);
6823 return FRAME_X_DOUBLE_BUFFERED_P (f) ? Qt : Qnil;
6827 /***********************************************************************
6828 File selection dialog
6829 ***********************************************************************/
6831 DEFUN ("x-uses-old-gtk-dialog", Fx_uses_old_gtk_dialog,
6832 Sx_uses_old_gtk_dialog,
6833 0, 0, 0,
6834 doc: /* Return t if the old Gtk+ file selection dialog is used. */)
6835 (void)
6837 #ifdef USE_GTK
6838 if (use_dialog_box
6839 && use_file_dialog
6840 && window_system_available (SELECTED_FRAME ())
6841 && xg_uses_old_file_dialog ())
6842 return Qt;
6843 #endif
6844 return Qnil;
6848 #ifdef USE_MOTIF
6849 /* Callback for "OK" and "Cancel" on file selection dialog. */
6851 static void
6852 file_dialog_cb (Widget widget, XtPointer client_data, XtPointer call_data)
6854 int *result = client_data;
6855 XmAnyCallbackStruct *cb = call_data;
6856 *result = cb->reason;
6860 /* Callback for unmapping a file selection dialog. This is used to
6861 capture the case where a dialog is closed via a window manager's
6862 closer button, for example. Using a XmNdestroyCallback didn't work
6863 in this case. */
6865 static void
6866 file_dialog_unmap_cb (Widget widget, XtPointer client_data, XtPointer call_data)
6868 int *result = client_data;
6869 *result = XmCR_CANCEL;
6872 static void
6873 clean_up_file_dialog (void *arg)
6875 Widget dialog = arg;
6877 /* Clean up. */
6878 block_input ();
6879 XtUnmanageChild (dialog);
6880 XtDestroyWidget (dialog);
6881 x_menu_set_in_use (false);
6882 unblock_input ();
6886 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
6887 doc: /* Read file name, prompting with PROMPT in directory DIR.
6888 Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file
6889 selection box, if specified. If MUSTMATCH is non-nil, the returned file
6890 or directory must exist.
6892 This function is only defined on NS, MS Windows, and X Windows with the
6893 Motif or Gtk toolkits. With the Motif toolkit, ONLY-DIR-P is ignored.
6894 Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories.
6895 On Windows 7 and later, the file selection dialog "remembers" the last
6896 directory where the user selected a file, and will open that directory
6897 instead of DIR on subsequent invocations of this function with the same
6898 value of DIR as in previous invocations; this is standard Windows behavior. */)
6899 (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename,
6900 Lisp_Object mustmatch, Lisp_Object only_dir_p)
6902 int result;
6903 struct frame *f = SELECTED_FRAME ();
6904 Lisp_Object file = Qnil;
6905 Lisp_Object decoded_file;
6906 Widget dialog, text, help;
6907 Arg al[10];
6908 int ac = 0;
6909 XmString dir_xmstring, pattern_xmstring;
6910 ptrdiff_t count = SPECPDL_INDEX ();
6912 check_window_system (f);
6914 if (popup_activated ())
6915 error ("Trying to use a menu from within a menu-entry");
6917 CHECK_STRING (prompt);
6918 CHECK_STRING (dir);
6920 /* Prevent redisplay. */
6921 specbind (Qinhibit_redisplay, Qt);
6923 block_input ();
6925 /* Create the dialog with PROMPT as title, using DIR as initial
6926 directory and using "*" as pattern. */
6927 dir = Fexpand_file_name (dir, Qnil);
6928 dir_xmstring = XmStringCreateLocalized (SSDATA (dir));
6929 pattern_xmstring = XmStringCreateLocalized ("*");
6931 XtSetArg (al[ac], XmNtitle, SDATA (prompt)); ++ac;
6932 XtSetArg (al[ac], XmNdirectory, dir_xmstring); ++ac;
6933 XtSetArg (al[ac], XmNpattern, pattern_xmstring); ++ac;
6934 XtSetArg (al[ac], XmNresizePolicy, XmRESIZE_GROW); ++ac;
6935 XtSetArg (al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ++ac;
6936 dialog = XmCreateFileSelectionDialog (f->output_data.x->widget,
6937 "fsb", al, ac);
6938 XmStringFree (dir_xmstring);
6939 XmStringFree (pattern_xmstring);
6941 /* Add callbacks for OK and Cancel. */
6942 XtAddCallback (dialog, XmNokCallback, file_dialog_cb,
6943 (XtPointer) &result);
6944 XtAddCallback (dialog, XmNcancelCallback, file_dialog_cb,
6945 (XtPointer) &result);
6946 XtAddCallback (dialog, XmNunmapCallback, file_dialog_unmap_cb,
6947 (XtPointer) &result);
6949 /* Remove the help button since we can't display help. */
6950 help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON);
6951 XtUnmanageChild (help);
6953 /* Mark OK button as default. */
6954 XtVaSetValues (XmFileSelectionBoxGetChild (dialog, XmDIALOG_OK_BUTTON),
6955 XmNshowAsDefault, True, NULL);
6957 /* If MUSTMATCH is non-nil, disable the file entry field of the
6958 dialog, so that the user must select a file from the files list
6959 box. We can't remove it because we wouldn't have a way to get at
6960 the result file name, then. */
6961 text = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
6962 if (!NILP (mustmatch))
6964 Widget label;
6965 label = XmFileSelectionBoxGetChild (dialog, XmDIALOG_SELECTION_LABEL);
6966 XtSetSensitive (text, False);
6967 XtSetSensitive (label, False);
6970 /* Manage the dialog, so that list boxes get filled. */
6971 XtManageChild (dialog);
6973 if (STRINGP (default_filename))
6975 XmString default_xmstring;
6976 Widget wtext = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
6977 Widget list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
6979 XmTextPosition last_pos = XmTextFieldGetLastPosition (wtext);
6980 XmTextFieldReplace (wtext, 0, last_pos,
6981 (SSDATA (Ffile_name_nondirectory (default_filename))));
6983 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
6984 must include the path for this to work. */
6986 default_xmstring = XmStringCreateLocalized (SSDATA (default_filename));
6988 if (XmListItemExists (list, default_xmstring))
6990 int item_pos = XmListItemPos (list, default_xmstring);
6991 /* Select the item and scroll it into view. */
6992 XmListSelectPos (list, item_pos, True);
6993 XmListSetPos (list, item_pos);
6996 XmStringFree (default_xmstring);
6999 record_unwind_protect_ptr (clean_up_file_dialog, dialog);
7001 /* Process events until the user presses Cancel or OK. */
7002 x_menu_set_in_use (true);
7003 result = 0;
7004 while (result == 0)
7006 XEvent event;
7007 x_menu_wait_for_event (0);
7008 XtAppNextEvent (Xt_app_con, &event);
7009 if (event.type == KeyPress
7010 && FRAME_X_DISPLAY (f) == event.xkey.display)
7012 KeySym keysym = XLookupKeysym (&event.xkey, 0);
7014 /* Pop down on C-g. */
7015 if (keysym == XK_g && (event.xkey.state & ControlMask) != 0)
7016 XtUnmanageChild (dialog);
7019 (void) x_dispatch_event (&event, FRAME_X_DISPLAY (f));
7022 /* Get the result. */
7023 if (result == XmCR_OK)
7025 XmString text_string;
7026 String data;
7028 XtVaGetValues (dialog, XmNtextString, &text_string, NULL);
7029 XmStringGetLtoR (text_string, XmFONTLIST_DEFAULT_TAG, &data);
7030 XmStringFree (text_string);
7031 file = build_string (data);
7032 XtFree (data);
7034 else
7035 file = Qnil;
7037 unblock_input ();
7039 /* Make "Cancel" equivalent to C-g. */
7040 if (NILP (file))
7041 quit ();
7043 decoded_file = DECODE_FILE (file);
7045 return unbind_to (count, decoded_file);
7048 #endif /* USE_MOTIF */
7050 #ifdef USE_GTK
7052 static void
7053 clean_up_dialog (void)
7055 x_menu_set_in_use (false);
7058 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
7059 doc: /* Read file name, prompting with PROMPT in directory DIR.
7060 Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file
7061 selection box, if specified. If MUSTMATCH is non-nil, the returned file
7062 or directory must exist.
7064 This function is only defined on NS, MS Windows, and X Windows with the
7065 Motif or Gtk toolkits. With the Motif toolkit, ONLY-DIR-P is ignored.
7066 Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories.
7067 On Windows 7 and later, the file selection dialog "remembers" the last
7068 directory where the user selected a file, and will open that directory
7069 instead of DIR on subsequent invocations of this function with the same
7070 value of DIR as in previous invocations; this is standard Windows behavior. */)
7071 (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename, Lisp_Object mustmatch, Lisp_Object only_dir_p)
7073 struct frame *f = SELECTED_FRAME ();
7074 char *fn;
7075 Lisp_Object file = Qnil;
7076 Lisp_Object decoded_file;
7077 ptrdiff_t count = SPECPDL_INDEX ();
7078 char *cdef_file;
7080 check_window_system (f);
7082 if (popup_activated ())
7083 error ("Trying to use a menu from within a menu-entry");
7084 else
7085 x_menu_set_in_use (true);
7087 CHECK_STRING (prompt);
7088 CHECK_STRING (dir);
7090 /* Prevent redisplay. */
7091 specbind (Qinhibit_redisplay, Qt);
7092 record_unwind_protect_void (clean_up_dialog);
7094 block_input ();
7096 if (STRINGP (default_filename))
7097 cdef_file = SSDATA (default_filename);
7098 else
7099 cdef_file = SSDATA (dir);
7101 fn = xg_get_file_name (f, SSDATA (prompt), cdef_file,
7102 ! NILP (mustmatch),
7103 ! NILP (only_dir_p));
7105 if (fn)
7107 file = build_string (fn);
7108 xfree (fn);
7111 unblock_input ();
7113 /* Make "Cancel" equivalent to C-g. */
7114 if (NILP (file))
7115 quit ();
7117 decoded_file = DECODE_FILE (file);
7119 return unbind_to (count, decoded_file);
7123 #ifdef HAVE_FREETYPE
7125 DEFUN ("x-select-font", Fx_select_font, Sx_select_font, 0, 2, 0,
7126 doc: /* Read a font using a GTK dialog.
7127 Return either a font spec (for GTK versions >= 3.2) or a string
7128 containing a GTK-style font name.
7130 FRAME is the frame on which to pop up the font chooser. If omitted or
7131 nil, it defaults to the selected frame. */)
7132 (Lisp_Object frame, Lisp_Object ignored)
7134 struct frame *f = decode_window_system_frame (frame);
7135 Lisp_Object font;
7136 Lisp_Object font_param;
7137 char *default_name = NULL;
7138 ptrdiff_t count = SPECPDL_INDEX ();
7140 if (popup_activated ())
7141 error ("Trying to use a menu from within a menu-entry");
7142 else
7143 x_menu_set_in_use (true);
7145 /* Prevent redisplay. */
7146 specbind (Qinhibit_redisplay, Qt);
7147 record_unwind_protect_void (clean_up_dialog);
7149 block_input ();
7151 XSETFONT (font, FRAME_FONT (f));
7152 font_param = Ffont_get (font, QCname);
7153 if (STRINGP (font_param))
7154 default_name = xlispstrdup (font_param);
7155 else
7157 font_param = Fframe_parameter (frame, Qfont_parameter);
7158 if (STRINGP (font_param))
7159 default_name = xlispstrdup (font_param);
7162 font = xg_get_font (f, default_name);
7163 xfree (default_name);
7165 unblock_input ();
7167 if (NILP (font))
7168 quit ();
7170 return unbind_to (count, font);
7172 #endif /* HAVE_FREETYPE */
7174 #endif /* USE_GTK */
7177 /***********************************************************************
7178 Keyboard
7179 ***********************************************************************/
7181 #ifdef HAVE_XKB
7182 #include <X11/XKBlib.h>
7183 #include <X11/keysym.h>
7184 #endif
7186 DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p,
7187 Sx_backspace_delete_keys_p, 0, 1, 0,
7188 doc: /* Check if both Backspace and Delete keys are on the keyboard of FRAME.
7189 FRAME nil means use the selected frame.
7190 Value is t if we know that both keys are present, and are mapped to the
7191 usual X keysyms. Value is `lambda' if we cannot determine if both keys are
7192 present and mapped to the usual X keysyms. */)
7193 (Lisp_Object frame)
7195 #ifndef HAVE_XKB
7196 return Qlambda;
7197 #else
7198 XkbDescPtr kb;
7199 struct frame *f = decode_window_system_frame (frame);
7200 Display *dpy = FRAME_X_DISPLAY (f);
7201 Lisp_Object have_keys;
7202 int major, minor, op, event, error_code;
7204 block_input ();
7206 /* Check library version in case we're dynamically linked. */
7207 major = XkbMajorVersion;
7208 minor = XkbMinorVersion;
7209 if (!XkbLibraryVersion (&major, &minor))
7211 unblock_input ();
7212 return Qlambda;
7215 /* Check that the server supports XKB. */
7216 major = XkbMajorVersion;
7217 minor = XkbMinorVersion;
7218 if (!XkbQueryExtension (dpy, &op, &event, &error_code, &major, &minor))
7220 unblock_input ();
7221 return Qlambda;
7224 /* In this code we check that the keyboard has physical keys with names
7225 that start with BKSP (Backspace) and DELE (Delete), and that they
7226 generate keysym XK_BackSpace and XK_Delete respectively.
7227 This function is used to test if normal-erase-is-backspace should be
7228 turned on.
7229 An alternative approach would be to just check if XK_BackSpace and
7230 XK_Delete are mapped to any key. But if any of those are mapped to
7231 some non-intuitive key combination (Meta-Shift-Ctrl-whatever) and the
7232 user doesn't know about it, it is better to return false here.
7233 It is more obvious to the user what to do if she/he has two keys
7234 clearly marked with names/symbols and one key does something not
7235 expected (i.e. she/he then tries the other).
7236 The cases where Backspace/Delete is mapped to some other key combination
7237 are rare, and in those cases, normal-erase-is-backspace can be turned on
7238 manually. */
7240 have_keys = Qnil;
7241 kb = XkbGetMap (dpy, XkbAllMapComponentsMask, XkbUseCoreKbd);
7242 if (kb)
7244 int delete_keycode = 0, backspace_keycode = 0, i;
7246 if (XkbGetNames (dpy, XkbAllNamesMask, kb) == Success)
7248 for (i = kb->min_key_code;
7249 (i < kb->max_key_code
7250 && (delete_keycode == 0 || backspace_keycode == 0));
7251 ++i)
7253 /* The XKB symbolic key names can be seen most easily in
7254 the PS file generated by `xkbprint -label name
7255 $DISPLAY'. */
7256 if (memcmp ("DELE", kb->names->keys[i].name, 4) == 0)
7257 delete_keycode = i;
7258 else if (memcmp ("BKSP", kb->names->keys[i].name, 4) == 0)
7259 backspace_keycode = i;
7262 XkbFreeNames (kb, 0, True);
7265 /* As of libX11-1.6.2, XkbGetMap manual says that you should use
7266 XkbFreeClientMap to free the data returned by XkbGetMap. But
7267 this function just frees the data referenced from KB and not
7268 KB itself. To free KB as well, call XkbFreeKeyboard. */
7269 XkbFreeKeyboard (kb, XkbAllMapComponentsMask, True);
7271 if (delete_keycode
7272 && backspace_keycode
7273 && XKeysymToKeycode (dpy, XK_Delete) == delete_keycode
7274 && XKeysymToKeycode (dpy, XK_BackSpace) == backspace_keycode)
7275 have_keys = Qt;
7277 unblock_input ();
7278 return have_keys;
7279 #endif
7284 /***********************************************************************
7285 Printing
7286 ***********************************************************************/
7288 #ifdef USE_CAIRO
7289 DEFUN ("x-export-frames", Fx_export_frames, Sx_export_frames, 0, 2, 0,
7290 doc: /* Return image data of FRAMES in TYPE format.
7291 FRAMES should be nil (the selected frame), a frame, or a list of
7292 frames (each of which corresponds to one page). Each frame should be
7293 visible. Optional arg TYPE should be either `pdf' (default), `png',
7294 `postscript', or `svg'. Supported types are determined by the
7295 compile-time configuration of cairo. */)
7296 (Lisp_Object frames, Lisp_Object type)
7298 Lisp_Object rest, tmp;
7299 cairo_surface_type_t surface_type;
7301 if (!CONSP (frames))
7302 frames = list1 (frames);
7304 tmp = Qnil;
7305 for (rest = frames; CONSP (rest); rest = XCDR (rest))
7307 struct frame *f = decode_window_system_frame (XCAR (rest));
7308 Lisp_Object frame;
7310 XSETFRAME (frame, f);
7311 if (!FRAME_VISIBLE_P (f))
7312 error ("Frames to be exported must be visible.");
7313 tmp = Fcons (frame, tmp);
7315 frames = Fnreverse (tmp);
7317 #ifdef CAIRO_HAS_PDF_SURFACE
7318 if (NILP (type) || EQ (type, Qpdf))
7319 surface_type = CAIRO_SURFACE_TYPE_PDF;
7320 else
7321 #endif
7322 #ifdef CAIRO_HAS_PNG_FUNCTIONS
7323 if (EQ (type, Qpng))
7325 if (!NILP (XCDR (frames)))
7326 error ("PNG export cannot handle multiple frames.");
7327 surface_type = CAIRO_SURFACE_TYPE_IMAGE;
7329 else
7330 #endif
7331 #ifdef CAIRO_HAS_PS_SURFACE
7332 if (EQ (type, Qpostscript))
7333 surface_type = CAIRO_SURFACE_TYPE_PS;
7334 else
7335 #endif
7336 #ifdef CAIRO_HAS_SVG_SURFACE
7337 if (EQ (type, Qsvg))
7339 /* For now, we stick to SVG 1.1. */
7340 if (!NILP (XCDR (frames)))
7341 error ("SVG export cannot handle multiple frames.");
7342 surface_type = CAIRO_SURFACE_TYPE_SVG;
7344 else
7345 #endif
7346 error ("Unsupported export type");
7348 return x_cr_export_frames (frames, surface_type);
7351 #ifdef USE_GTK
7352 DEFUN ("x-page-setup-dialog", Fx_page_setup_dialog, Sx_page_setup_dialog, 0, 0, 0,
7353 doc: /* Pop up a page setup dialog.
7354 The current page setup can be obtained using `x-get-page-setup'. */)
7355 (void)
7357 block_input ();
7358 xg_page_setup_dialog ();
7359 unblock_input ();
7361 return Qnil;
7364 DEFUN ("x-get-page-setup", Fx_get_page_setup, Sx_get_page_setup, 0, 0, 0,
7365 doc: /* Return the value of the current page setup.
7366 The return value is an alist containing the following keys:
7368 orientation: page orientation (symbol `portrait', `landscape',
7369 `reverse-portrait', or `reverse-landscape').
7370 width, height: page width/height in points not including margins.
7371 left-margin, right-margin, top-margin, bottom-margin: print margins,
7372 which is the parts of the page that the printer cannot print
7373 on, in points.
7375 The paper width can be obtained as the sum of width, left-margin, and
7376 right-margin values if the page orientation is `portrait' or
7377 `reverse-portrait'. Otherwise, it is the sum of width, top-margin,
7378 and bottom-margin values. Likewise, the paper height is the sum of
7379 height, top-margin, and bottom-margin values if the page orientation
7380 is `portrait' or `reverse-portrait'. Otherwise, it is the sum of
7381 height, left-margin, and right-margin values. */)
7382 (void)
7384 Lisp_Object result;
7386 block_input ();
7387 result = xg_get_page_setup ();
7388 unblock_input ();
7390 return result;
7393 DEFUN ("x-print-frames-dialog", Fx_print_frames_dialog, Sx_print_frames_dialog, 0, 1, "",
7394 doc: /* Pop up a print dialog to print the current contents of FRAMES.
7395 FRAMES should be nil (the selected frame), a frame, or a list of
7396 frames (each of which corresponds to one page). Each frame should be
7397 visible. */)
7398 (Lisp_Object frames)
7400 Lisp_Object rest, tmp;
7401 int count;
7403 if (!CONSP (frames))
7404 frames = list1 (frames);
7406 tmp = Qnil;
7407 for (rest = frames; CONSP (rest); rest = XCDR (rest))
7409 struct frame *f = decode_window_system_frame (XCAR (rest));
7410 Lisp_Object frame;
7412 XSETFRAME (frame, f);
7413 if (!FRAME_VISIBLE_P (f))
7414 error ("Frames to be printed must be visible.");
7415 tmp = Fcons (frame, tmp);
7417 frames = Fnreverse (tmp);
7419 /* Make sure the current matrices are up-to-date. */
7420 count = SPECPDL_INDEX ();
7421 specbind (Qredisplay_dont_pause, Qt);
7422 redisplay_preserve_echo_area (32);
7423 unbind_to (count, Qnil);
7425 block_input ();
7426 xg_print_frames_dialog (frames);
7427 unblock_input ();
7429 return Qnil;
7431 #endif /* USE_GTK */
7432 #endif /* USE_CAIRO */
7435 /***********************************************************************
7436 Initialization
7437 ***********************************************************************/
7439 /* Keep this list in the same order as frame_parms in frame.c.
7440 Use 0 for unsupported frame parameters. */
7442 frame_parm_handler x_frame_parm_handlers[] =
7444 x_set_autoraise,
7445 x_set_autolower,
7446 x_set_background_color,
7447 x_set_border_color,
7448 x_set_border_width,
7449 x_set_cursor_color,
7450 x_set_cursor_type,
7451 x_set_font,
7452 x_set_foreground_color,
7453 x_set_icon_name,
7454 x_set_icon_type,
7455 x_set_internal_border_width,
7456 x_set_right_divider_width,
7457 x_set_bottom_divider_width,
7458 x_set_menu_bar_lines,
7459 x_set_mouse_color,
7460 x_explicitly_set_name,
7461 x_set_scroll_bar_width,
7462 x_set_scroll_bar_height,
7463 x_set_title,
7464 x_set_unsplittable,
7465 x_set_vertical_scroll_bars,
7466 x_set_horizontal_scroll_bars,
7467 x_set_visibility,
7468 x_set_tool_bar_lines,
7469 x_set_scroll_bar_foreground,
7470 x_set_scroll_bar_background,
7471 x_set_screen_gamma,
7472 x_set_line_spacing,
7473 x_set_left_fringe,
7474 x_set_right_fringe,
7475 x_set_wait_for_wm,
7476 x_set_fullscreen,
7477 x_set_font_backend,
7478 x_set_alpha,
7479 x_set_sticky,
7480 x_set_tool_bar_position,
7481 x_set_inhibit_double_buffering,
7482 x_set_undecorated,
7483 x_set_parent_frame,
7484 x_set_skip_taskbar,
7485 x_set_no_focus_on_map,
7486 x_set_no_accept_focus,
7487 x_set_z_group,
7488 x_set_override_redirect,
7491 void
7492 syms_of_xfns (void)
7494 DEFSYM (Qundefined_color, "undefined-color");
7495 DEFSYM (Qcompound_text, "compound-text");
7496 DEFSYM (Qcancel_timer, "cancel-timer");
7497 DEFSYM (Qfont_parameter, "font-parameter");
7498 DEFSYM (Qmono, "mono");
7499 DEFSYM (Qassq_delete_all, "assq-delete-all");
7501 #ifdef USE_CAIRO
7502 DEFSYM (Qpdf, "pdf");
7504 DEFSYM (Qorientation, "orientation");
7505 DEFSYM (Qtop_margin, "top-margin");
7506 DEFSYM (Qbottom_margin, "bottom-margin");
7507 DEFSYM (Qportrait, "portrait");
7508 DEFSYM (Qlandscape, "landscape");
7509 DEFSYM (Qreverse_portrait, "reverse-portrait");
7510 DEFSYM (Qreverse_landscape, "reverse-landscape");
7511 #endif
7513 Fput (Qundefined_color, Qerror_conditions,
7514 listn (CONSTYPE_PURE, 2, Qundefined_color, Qerror));
7515 Fput (Qundefined_color, Qerror_message,
7516 build_pure_c_string ("Undefined color"));
7518 DEFVAR_LISP ("x-pointer-shape", Vx_pointer_shape,
7519 doc: /* The shape of the pointer when over text.
7520 Changing the value does not affect existing frames
7521 unless you set the mouse color. */);
7522 Vx_pointer_shape = Qnil;
7524 #if false /* This doesn't really do anything. */
7525 DEFVAR_LISP ("x-nontext-pointer-shape", Vx_nontext_pointer_shape,
7526 doc: /* The shape of the pointer when not over text.
7527 This variable takes effect when you create a new frame
7528 or when you set the mouse color. */);
7529 #endif
7530 Vx_nontext_pointer_shape = Qnil;
7532 DEFVAR_LISP ("x-hourglass-pointer-shape", Vx_hourglass_pointer_shape,
7533 doc: /* The shape of the pointer when Emacs is busy.
7534 This variable takes effect when you create a new frame
7535 or when you set the mouse color. */);
7536 Vx_hourglass_pointer_shape = Qnil;
7538 #if false /* This doesn't really do anything. */
7539 DEFVAR_LISP ("x-mode-pointer-shape", Vx_mode_pointer_shape,
7540 doc: /* The shape of the pointer when over the mode line.
7541 This variable takes effect when you create a new frame
7542 or when you set the mouse color. */);
7543 #endif
7544 Vx_mode_pointer_shape = Qnil;
7546 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
7547 Vx_sensitive_text_pointer_shape,
7548 doc: /* The shape of the pointer when over mouse-sensitive text.
7549 This variable takes effect when you create a new frame
7550 or when you set the mouse color. */);
7551 Vx_sensitive_text_pointer_shape = Qnil;
7553 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
7554 Vx_window_horizontal_drag_shape,
7555 doc: /* Pointer shape to use for indicating a window can be dragged horizontally.
7556 This variable takes effect when you create a new frame
7557 or when you set the mouse color. */);
7558 Vx_window_horizontal_drag_shape = Qnil;
7560 DEFVAR_LISP ("x-window-vertical-drag-cursor",
7561 Vx_window_vertical_drag_shape,
7562 doc: /* Pointer shape to use for indicating a window can be dragged vertically.
7563 This variable takes effect when you create a new frame
7564 or when you set the mouse color. */);
7565 Vx_window_vertical_drag_shape = Qnil;
7567 DEFVAR_LISP ("x-cursor-fore-pixel", Vx_cursor_fore_pixel,
7568 doc: /* A string indicating the foreground color of the cursor box. */);
7569 Vx_cursor_fore_pixel = Qnil;
7571 DEFVAR_LISP ("x-max-tooltip-size", Vx_max_tooltip_size,
7572 doc: /* Maximum size for tooltips.
7573 Value is a pair (COLUMNS . ROWS). Text larger than this is clipped. */);
7574 Vx_max_tooltip_size = Fcons (make_number (80), make_number (40));
7576 DEFVAR_LISP ("x-no-window-manager", Vx_no_window_manager,
7577 doc: /* Non-nil if no X window manager is in use.
7578 Emacs doesn't try to figure this out; this is always nil
7579 unless you set it to something else. */);
7580 /* We don't have any way to find this out, so set it to nil
7581 and maybe the user would like to set it to t. */
7582 Vx_no_window_manager = Qnil;
7584 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
7585 Vx_pixel_size_width_font_regexp,
7586 doc: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
7588 Since Emacs gets width of a font matching with this regexp from
7589 PIXEL_SIZE field of the name, font finding mechanism gets faster for
7590 such a font. This is especially effective for such large fonts as
7591 Chinese, Japanese, and Korean. */);
7592 Vx_pixel_size_width_font_regexp = Qnil;
7594 /* This is not ifdef:ed, so other builds than GTK can customize it. */
7595 DEFVAR_BOOL ("x-gtk-use-old-file-dialog", x_gtk_use_old_file_dialog,
7596 doc: /* Non-nil means prompt with the old GTK file selection dialog.
7597 If nil or if the file selection dialog is not available, the new GTK file
7598 chooser is used instead. To turn off all file dialogs set the
7599 variable `use-file-dialog'. */);
7600 x_gtk_use_old_file_dialog = false;
7602 DEFVAR_BOOL ("x-gtk-show-hidden-files", x_gtk_show_hidden_files,
7603 doc: /* If non-nil, the GTK file chooser will by default show hidden files.
7604 Note that this is just the default, there is a toggle button on the file
7605 chooser to show or not show hidden files on a case by case basis. */);
7606 x_gtk_show_hidden_files = false;
7608 DEFVAR_BOOL ("x-gtk-file-dialog-help-text", x_gtk_file_dialog_help_text,
7609 doc: /* If non-nil, the GTK file chooser will show additional help text.
7610 If more space for files in the file chooser dialog is wanted, set this to nil
7611 to turn the additional text off. */);
7612 x_gtk_file_dialog_help_text = true;
7614 DEFVAR_BOOL ("x-gtk-use-system-tooltips", x_gtk_use_system_tooltips,
7615 doc: /* If non-nil with a Gtk+ built Emacs, the Gtk+ tooltip is used.
7616 Otherwise use Emacs own tooltip implementation.
7617 When using Gtk+ tooltips, the tooltip face is not used. */);
7618 x_gtk_use_system_tooltips = true;
7620 /* Tell Emacs about this window system. */
7621 Fprovide (Qx, Qnil);
7623 #ifdef USE_X_TOOLKIT
7624 Fprovide (intern_c_string ("x-toolkit"), Qnil);
7625 #ifdef USE_MOTIF
7626 Fprovide (intern_c_string ("motif"), Qnil);
7628 DEFVAR_LISP ("motif-version-string", Vmotif_version_string,
7629 doc: /* Version info for LessTif/Motif. */);
7630 Vmotif_version_string = build_string (XmVERSION_STRING);
7631 #endif /* USE_MOTIF */
7632 #endif /* USE_X_TOOLKIT */
7634 #ifdef USE_GTK
7635 /* Provide x-toolkit also for GTK. Internally GTK does not use Xt so it
7636 is not an X toolkit in that sense (USE_X_TOOLKIT is not defined).
7637 But for a user it is a toolkit for X, and indeed, configure
7638 accepts --with-x-toolkit=gtk. */
7639 Fprovide (intern_c_string ("x-toolkit"), Qnil);
7640 Fprovide (intern_c_string ("gtk"), Qnil);
7641 Fprovide (intern_c_string ("move-toolbar"), Qnil);
7643 DEFVAR_LISP ("gtk-version-string", Vgtk_version_string,
7644 doc: /* Version info for GTK+. */);
7646 char gtk_version[sizeof ".." + 3 * INT_STRLEN_BOUND (int)];
7647 int len = sprintf (gtk_version, "%d.%d.%d",
7648 GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION);
7649 Vgtk_version_string = make_pure_string (gtk_version, len, len, false);
7651 #endif /* USE_GTK */
7653 #ifdef USE_CAIRO
7654 Fprovide (intern_c_string ("cairo"), Qnil);
7656 DEFVAR_LISP ("cairo-version-string", Vcairo_version_string,
7657 doc: /* Version info for cairo. */);
7659 char cairo_version[sizeof ".." + 3 * INT_STRLEN_BOUND (int)];
7660 int len = sprintf (cairo_version, "%d.%d.%d",
7661 CAIRO_VERSION_MAJOR, CAIRO_VERSION_MINOR,
7662 CAIRO_VERSION_MICRO);
7663 Vcairo_version_string = make_pure_string (cairo_version, len, len, false);
7665 #endif
7667 /* X window properties. */
7668 defsubr (&Sx_change_window_property);
7669 defsubr (&Sx_delete_window_property);
7670 defsubr (&Sx_window_property);
7671 defsubr (&Sx_window_property_attributes);
7673 defsubr (&Sxw_display_color_p);
7674 defsubr (&Sx_display_grayscale_p);
7675 defsubr (&Sxw_color_defined_p);
7676 defsubr (&Sxw_color_values);
7677 defsubr (&Sx_server_max_request_size);
7678 defsubr (&Sx_server_vendor);
7679 defsubr (&Sx_server_version);
7680 defsubr (&Sx_display_pixel_width);
7681 defsubr (&Sx_display_pixel_height);
7682 defsubr (&Sx_display_mm_width);
7683 defsubr (&Sx_display_mm_height);
7684 defsubr (&Sx_display_screens);
7685 defsubr (&Sx_display_planes);
7686 defsubr (&Sx_display_color_cells);
7687 defsubr (&Sx_display_visual_class);
7688 defsubr (&Sx_display_backing_store);
7689 defsubr (&Sx_display_save_under);
7690 defsubr (&Sx_display_monitor_attributes_list);
7691 defsubr (&Sx_frame_geometry);
7692 defsubr (&Sx_frame_edges);
7693 defsubr (&Sx_frame_list_z_order);
7694 defsubr (&Sx_frame_restack);
7695 defsubr (&Sx_mouse_absolute_pixel_position);
7696 defsubr (&Sx_set_mouse_absolute_pixel_position);
7697 defsubr (&Sx_wm_set_size_hint);
7698 defsubr (&Sx_create_frame);
7699 defsubr (&Sx_open_connection);
7700 defsubr (&Sx_close_connection);
7701 defsubr (&Sx_display_list);
7702 defsubr (&Sx_synchronize);
7703 defsubr (&Sx_backspace_delete_keys_p);
7705 defsubr (&Sx_show_tip);
7706 defsubr (&Sx_hide_tip);
7707 defsubr (&Sx_double_buffered_p);
7708 tip_timer = Qnil;
7709 staticpro (&tip_timer);
7710 tip_frame = Qnil;
7711 staticpro (&tip_frame);
7713 last_show_tip_args = Qnil;
7714 staticpro (&last_show_tip_args);
7716 defsubr (&Sx_uses_old_gtk_dialog);
7717 #if defined (USE_MOTIF) || defined (USE_GTK)
7718 defsubr (&Sx_file_dialog);
7719 #endif
7721 #if defined (USE_GTK) && defined (HAVE_FREETYPE)
7722 defsubr (&Sx_select_font);
7723 #endif
7725 #ifdef USE_CAIRO
7726 defsubr (&Sx_export_frames);
7727 #ifdef USE_GTK
7728 defsubr (&Sx_page_setup_dialog);
7729 defsubr (&Sx_get_page_setup);
7730 defsubr (&Sx_print_frames_dialog);
7731 #endif
7732 #endif