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