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