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