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