Separate read and write access to Lisp_Object slots of struct window.
[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
98c6f1e3 463 XFree (tmp_children);
e7161ad9 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))
edd74c35 668 FSET (f, tool_bar_position, new_value);
bfeabdc3
JD
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,
edd74c35
DA
1126 SSDATA ((!NILP (FGET (f, icon_name))
1127 ? FGET (f, icon_name)
1128 : FGET (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
edd74c35 1155 FSET (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,
edd74c35
DA
1163 SSDATA ((!NILP (FGET (f, icon_name))
1164 ? FGET (f, icon_name)
1165 : !NILP (FGET (f, title))
1166 ? FGET (f, title)
1167 : FGET (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
edd74c35
DA
1256 if (nlines == 0 && WINDOWP (FGET (f, menu_bar_window)))
1257 clear_glyph_matrix (XWINDOW (FGET (f, menu_bar_window))->current_matrix);
1df47e38
YM
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 1354
edd74c35
DA
1355 if (WINDOWP (FGET (f, tool_bar_window)))
1356 clear_glyph_matrix (XWINDOW (FGET (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
edd74c35 1551 if (!STRINGP (FGET (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". */
edd74c35 1559 icon.value = x_encode_text (FGET (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 1567
edd74c35 1568 encoded_icon_name = ENCODE_UTF_8 (FGET (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,
edd74c35 1635 SSDATA (FGET (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. */
edd74c35 1643 if (! NILP (Fstring_equal (name, FGET (f, name))))
b10daec7
JD
1644 return;
1645
edd74c35 1646 FSET (f, name, name);
b10daec7
JD
1647
1648 /* For setting the frame title, the title parameter should override
1649 the name parameter. */
edd74c35
DA
1650 if (! NILP (FGET (f, title)))
1651 name = FGET (f, title);
b10daec7
JD
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 1680 /* Don't change the title if it's already NAME. */
edd74c35 1681 if (EQ (name, FGET (f, title)))
7c0d3ed8 1682 return;
01f1ba30 1683
7c0d3ed8 1684 update_mode_lines = 1;
60fb3ee1 1685
edd74c35 1686 FSET (f, title, name);
f9942c9e 1687
7c0d3ed8 1688 if (NILP (name))
edd74c35 1689 name = FGET (f, name);
7c0d3ed8
KS
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 2262{
077288cf 2263 struct frame *f = XFRAME (WGET (w, frame));
5a7df7d7
GM
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;
edd74c35
DA
2574 name = FGET (f, name);
2575 FSET (f, name, Qnil);
8fc2766b
RS
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;
edd74c35
DA
2717 name = FGET (f, name);
2718 FSET (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
edd74c35
DA
2794 x_text_icon (f, SSDATA ((!NILP (FGET (f, icon_name))
2795 ? FGET (f, icon_name)
2796 : FGET (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 2958 if (system_font)
d7ea76b4 2959 font = font_open_by_name (f, build_unibyte_string (system_font));
637fa988 2960 }
0d1d0d26 2961
e9b7ab96
JD
2962 if (NILP (font))
2963 font = !NILP (font_param) ? font_param
2964 : x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
2965
2966 if (! FONTP (font) && ! STRINGP (font))
02ed2ea8 2967 {
675e2c69 2968 const char *names[]
be9d013a
CY
2969 = {
2970#ifdef HAVE_XFT
d7afccca 2971 /* This will find the normal Xft font. */
c024ac08 2972 "monospace-10",
be9d013a
CY
2973#endif
2974 "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1",
2975 "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1",
02ed2ea8
KH
2976 "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1",
2977 /* This was formerly the first thing tried, but it finds
2978 too many fonts and takes too long. */
2979 "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1",
2980 /* If those didn't work, look for something which will
2981 at least work. */
2982 "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1",
25c25256 2983 "fixed",
02ed2ea8
KH
2984 NULL };
2985 int i;
2986
2987 for (i = 0; names[i]; i++)
2988 {
d7ea76b4 2989 font = font_open_by_name (f, build_unibyte_string (names[i]));
02ed2ea8
KH
2990 if (! NILP (font))
2991 break;
2992 }
2993 if (NILP (font))
25c25256 2994 error ("No suitable font was found");
02ed2ea8 2995 }
770e2e6e 2996 else if (!NILP (font_param))
27129af9
SM
2997 {
2998 /* Remember the explicit font parameter, so we can re-apply it after
2999 we've applied the `default' face settings. */
770e2e6e
SM
3000 x_set_frame_parameters (f, Fcons (Fcons (Qfont_param, font_param), Qnil));
3001 }
637fa988 3002
5fc8e5bc
J
3003 /* This call will make X resources override any system font setting. */
3004 x_default_parameter (f, parms, Qfont, font, "font", "Font", RES_TYPE_STRING);
02ed2ea8 3005}
b51238f5 3006
eaf1eea9 3007
1c44e124
CY
3008DEFUN ("x-wm-set-size-hint", Fx_wm_set_size_hint, Sx_wm_set_size_hint,
3009 0, 1, 0,
3010 doc: /* Send the size hints for frame FRAME to the window manager.
3011If FRAME is nil, use the selected frame. */)
5842a27b 3012 (Lisp_Object frame)
1c44e124
CY
3013{
3014 struct frame *f;
3015 if (NILP (frame))
3016 frame = selected_frame;
3017 f = XFRAME (frame);
3018 BLOCK_INPUT;
3b18571d
CY
3019 if (FRAME_X_P (f))
3020 x_wm_set_size_hint (f, 0, 0);
1c44e124 3021 UNBLOCK_INPUT;
653a3150 3022 return Qnil;
1c44e124
CY
3023}
3024
3e6bec3b
JD
3025static void
3026set_machine_and_pid_properties (struct frame *f)
3027{
ac61e7e1 3028 long pid = (long) getpid ();
3e6bec3b 3029
66b16767
J
3030 /* This will set WM_CLIENT_MACHINE and WM_LOCALE_NAME. */
3031 XSetWMProperties (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), NULL, NULL,
3032 NULL, 0, NULL, NULL, NULL);
3e6bec3b
JD
3033 XChangeProperty (FRAME_X_DISPLAY (f),
3034 FRAME_OUTER_WINDOW (f),
3035 XInternAtom (FRAME_X_DISPLAY (f),
3036 "_NET_WM_PID",
3037 False),
3038 XA_CARDINAL, 32, PropModeReplace,
3039 (unsigned char *) &pid, 1);
3040}
3041
f676886a 3042DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
01f1ba30 3043 1, 1, 0,
7ee72033 3044 doc: /* Make a new X window, which is called a "frame" in Emacs terms.
d29a9848 3045Return an Emacs frame object.
e0079d39 3046PARMS is an alist of frame parameters.
c061c855
GM
3047If the parameters specify that the frame should not have a minibuffer,
3048and do not specify a specific minibuffer window to use,
3049then `default-minibuffer-frame' must be a frame whose minibuffer can
3050be shared by the new frame.
3051
7ee72033 3052This function is an internal primitive--use `make-frame' instead. */)
5842a27b 3053 (Lisp_Object parms)
01f1ba30 3054{
f676886a 3055 struct frame *f;
2365c027 3056 Lisp_Object frame, tem;
01f1ba30
JB
3057 Lisp_Object name;
3058 int minibuffer_only = 0;
3059 long window_prompting = 0;
45d45af5 3060 int width, height;
d311d28c 3061 ptrdiff_t count = SPECPDL_INDEX ();
ecaca587 3062 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
b9dc4443 3063 Lisp_Object display;
333b20bb 3064 struct x_display_info *dpyinfo = NULL;
a59e4f3d 3065 Lisp_Object parent;
e557f19d 3066 struct kboard *kb;
01f1ba30 3067
5fa98fcf
RS
3068 parms = Fcopy_alist (parms);
3069
b7975ee4
KH
3070 /* Use this general default value to start with
3071 until we know if this frame has a specified name. */
3072 Vx_resource_name = Vinvocation_name;
3073
6ed8eeff 3074 display = x_get_arg (dpyinfo, parms, Qterminal, 0, 0, RES_TYPE_NUMBER);
1705c933 3075 if (EQ (display, Qunbound))
b6660415 3076 display = x_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING);
b9dc4443
RS
3077 if (EQ (display, Qunbound))
3078 display = Qnil;
3079 dpyinfo = check_x_display_info (display);
6ed8eeff 3080 kb = dpyinfo->terminal->kboard;
b9dc4443 3081
89acb56d
SM
3082 if (!dpyinfo->terminal->name)
3083 error ("Terminal is not live, can't create new frames on it");
ab797f65 3084
333b20bb 3085 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
6a5e54e2 3086 if (!STRINGP (name)
cf177271
JB
3087 && ! EQ (name, Qunbound)
3088 && ! NILP (name))
08a90d6a 3089 error ("Invalid frame name--not a string or nil");
01f1ba30 3090
b7975ee4
KH
3091 if (STRINGP (name))
3092 Vx_resource_name = name;
3093
a59e4f3d 3094 /* See if parent window is specified. */
333b20bb 3095 parent = x_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
a59e4f3d
RS
3096 if (EQ (parent, Qunbound))
3097 parent = Qnil;
3098 if (! NILP (parent))
b7826503 3099 CHECK_NUMBER (parent);
a59e4f3d 3100
ecaca587
RS
3101 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
3102 /* No need to protect DISPLAY because that's not used after passing
3103 it to make_frame_without_minibuffer. */
3104 frame = Qnil;
3105 GCPRO4 (parms, parent, name, frame);
333b20bb
GM
3106 tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
3107 RES_TYPE_SYMBOL);
f9942c9e 3108 if (EQ (tem, Qnone) || NILP (tem))
2526c290 3109 f = make_frame_without_minibuffer (Qnil, kb, display);
f9942c9e 3110 else if (EQ (tem, Qonly))
01f1ba30 3111 {
f676886a 3112 f = make_minibuffer_frame ();
01f1ba30
JB
3113 minibuffer_only = 1;
3114 }
6a5e54e2 3115 else if (WINDOWP (tem))
2526c290 3116 f = make_frame_without_minibuffer (tem, kb, display);
f9942c9e
JB
3117 else
3118 f = make_frame (1);
01f1ba30 3119
ecaca587
RS
3120 XSETFRAME (frame, f);
3121
a3c87d4e
JB
3122 /* Note that X Windows does support scroll bars. */
3123 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
179956b9 3124
6ed8eeff 3125 f->terminal = dpyinfo->terminal;
428a555e 3126
08a90d6a 3127 f->output_method = output_x_window;
38182d90 3128 f->output_data.x = xzalloc (sizeof *f->output_data.x);
7556890b 3129 f->output_data.x->icon_bitmap = -1;
be786000 3130 FRAME_FONTSET (f) = -1;
333b20bb
GM
3131 f->output_data.x->scroll_bar_foreground_pixel = -1;
3132 f->output_data.x->scroll_bar_background_pixel = -1;
f15340b7
MB
3133#ifdef USE_TOOLKIT_SCROLL_BARS
3134 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
3135 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
3136#endif /* USE_TOOLKIT_SCROLL_BARS */
08a90d6a 3137
edd74c35
DA
3138 FSET (f, icon_name,
3139 x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
3140 RES_TYPE_STRING));
3141 if (! STRINGP (FGET (f, icon_name)))
3142 FSET (f, icon_name, Qnil);
80534dd6 3143
08a90d6a 3144 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
e3d56613
RS
3145
3146 /* With FRAME_X_DISPLAY_INFO set up, this unwind-protect is safe. */
3147 record_unwind_protect (unwind_create_frame, frame);
08a90d6a 3148
9b2956e2
GM
3149 /* These colors will be set anyway later, but it's important
3150 to get the color reference counts right, so initialize them! */
3151 {
3152 Lisp_Object black;
dbf31225 3153 struct gcpro gcpro1;
cefecbcf
GM
3154
3155 /* Function x_decode_color can signal an error. Make
3156 sure to initialize color slots so that we won't try
3157 to free colors we haven't allocated. */
ce593f6e
KL
3158 FRAME_FOREGROUND_PIXEL (f) = -1;
3159 FRAME_BACKGROUND_PIXEL (f) = -1;
cefecbcf
GM
3160 f->output_data.x->cursor_pixel = -1;
3161 f->output_data.x->cursor_foreground_pixel = -1;
3162 f->output_data.x->border_pixel = -1;
3163 f->output_data.x->mouse_pixel = -1;
177c0ea7 3164
9b2956e2 3165 black = build_string ("black");
dbf31225 3166 GCPRO1 (black);
ce593f6e 3167 FRAME_FOREGROUND_PIXEL (f)
9b2956e2 3168 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
ce593f6e 3169 FRAME_BACKGROUND_PIXEL (f)
9b2956e2
GM
3170 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3171 f->output_data.x->cursor_pixel
3172 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3173 f->output_data.x->cursor_foreground_pixel
3174 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3175 f->output_data.x->border_pixel
3176 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
3177 f->output_data.x->mouse_pixel
3178 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
dbf31225 3179 UNGCPRO;
9b2956e2
GM
3180 }
3181
a59e4f3d
RS
3182 /* Specify the parent under which to make this X window. */
3183
3184 if (!NILP (parent))
3185 {
8c239ac3 3186 f->output_data.x->parent_desc = (Window) XFASTINT (parent);
7556890b 3187 f->output_data.x->explicit_parent = 1;
a59e4f3d
RS
3188 }
3189 else
3190 {
7556890b
RS
3191 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
3192 f->output_data.x->explicit_parent = 0;
a59e4f3d
RS
3193 }
3194
cf177271
JB
3195 /* Set the name; the functions to which we pass f expect the name to
3196 be set. */
3197 if (EQ (name, Qunbound) || NILP (name))
3198 {
edd74c35 3199 FSET (f, name, build_string (dpyinfo->x_id_name));
cf177271
JB
3200 f->explicit_name = 0;
3201 }
3202 else
3203 {
edd74c35 3204 FSET (f, name, name);
cf177271 3205 f->explicit_name = 1;
9ef48a9d
RS
3206 /* use the frame's title when getting resources for this frame. */
3207 specbind (Qx_resource_name, name);
cf177271 3208 }
01f1ba30 3209
02ed2ea8
KH
3210 f->resx = dpyinfo->resx;
3211 f->resy = dpyinfo->resy;
3212
02ed2ea8
KH
3213#ifdef HAVE_FREETYPE
3214#ifdef HAVE_XFT
b51238f5 3215 register_font_driver (&xftfont_driver, f);
02ed2ea8 3216#else /* not HAVE_XFT */
b51238f5 3217 register_font_driver (&ftxfont_driver, f);
02ed2ea8
KH
3218#endif /* not HAVE_XFT */
3219#endif /* HAVE_FREETYPE */
6332668d 3220 register_font_driver (&xfont_driver, f);
297cc20a 3221
b51238f5
KH
3222 x_default_parameter (f, parms, Qfont_backend, Qnil,
3223 "fontBackend", "FontBackend", RES_TYPE_STRING);
02ed2ea8 3224
01f1ba30
JB
3225 /* Extract the window parameters from the supplied values
3226 that are needed to determine window geometry. */
b51238f5 3227 x_default_font_parameter (f, parms);
62d168d8
CY
3228 if (!FRAME_FONT (f))
3229 {
3230 delete_frame (frame, Qnoelisp);
3231 error ("Invalid frame font");
3232 }
9ef48a9d 3233
2532f20c
JD
3234 /* Frame contents get displaced if an embedded X window has a border. */
3235 if (! FRAME_X_EMBEDDED_P (f))
4bef8d26 3236 x_default_parameter (f, parms, Qborder_width, make_number (0),
2532f20c 3237 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
177c0ea7 3238
4e397688 3239 /* This defaults to 1 in order to match xterm. We recognize either
ddf768c3
JB
3240 internalBorderWidth or internalBorder (which is what xterm calls
3241 it). */
3242 if (NILP (Fassq (Qinternal_border_width, parms)))
3243 {
3244 Lisp_Object value;
3245
abb4b7ec 3246 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
333b20bb 3247 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
ddf768c3
JB
3248 if (! EQ (value, Qunbound))
3249 parms = Fcons (Fcons (Qinternal_border_width, value),
3250 parms);
3251 }
a099c27a
SM
3252 x_default_parameter (f, parms, Qinternal_border_width,
3253#ifdef USE_GTK /* We used to impose 0 in xg_create_frame_widgets. */
3254 make_number (0),
3255#else
3256 make_number (1),
3257#endif
333b20bb
GM
3258 "internalBorderWidth", "internalBorderWidth",
3259 RES_TYPE_NUMBER);
303500aa 3260 x_default_parameter (f, parms, Qvertical_scroll_bars,
5e617bc2 3261#if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
303500aa
CY
3262 Qright,
3263#else
3264 Qleft,
3265#endif
333b20bb
GM
3266 "verticalScrollBars", "ScrollBars",
3267 RES_TYPE_SYMBOL);
01f1ba30 3268
b9dc4443 3269 /* Also do the stuff which must be set before the window exists. */
cf177271 3270 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
333b20bb 3271 "foreground", "Foreground", RES_TYPE_STRING);
cf177271 3272 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
0b60fc91 3273 "background", "Background", RES_TYPE_STRING);
cf177271 3274 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
333b20bb 3275 "pointerColor", "Foreground", RES_TYPE_STRING);
cf177271 3276 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
333b20bb 3277 "borderColor", "BorderColor", RES_TYPE_STRING);
d62c8769
GM
3278 x_default_parameter (f, parms, Qscreen_gamma, Qnil,
3279 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
563b67aa
GM
3280 x_default_parameter (f, parms, Qline_spacing, Qnil,
3281 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
b3ba0aa8
KS
3282 x_default_parameter (f, parms, Qleft_fringe, Qnil,
3283 "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
3284 x_default_parameter (f, parms, Qright_fringe, Qnil,
3285 "rightFringe", "RightFringe", RES_TYPE_NUMBER);
333b20bb
GM
3286
3287 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
3288 "scrollBarForeground",
3289 "ScrollBarForeground", 1);
3290 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_background,
3291 "scrollBarBackground",
3292 "ScrollBarBackground", 0);
3293
e509cfa6 3294#ifdef GLYPH_DEBUG
c9e7db78
JD
3295 image_cache_refcount =
3296 FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
3297 dpyinfo_refcount = dpyinfo->reference_count;
3298#endif /* GLYPH_DEBUG */
3299
333b20bb
GM
3300 /* Init faces before x_default_parameter is called for scroll-bar
3301 parameters because that function calls x_set_scroll_bar_width,
3302 which calls change_frame_size, which calls Fset_window_buffer,
3303 which runs hooks, which call Fvertical_motion. At the end, we
3304 end up in init_iterator with a null face cache, which should not
3305 happen. */
3306 init_frame_faces (f);
177c0ea7 3307
f01d3321
CY
3308 /* Set the menu-bar-lines and tool-bar-lines parameters. We don't
3309 look up the X resources controlling the menu-bar and tool-bar
3310 here; they are processed specially at startup, and reflected in
3311 the values of the mode variables.
3312
3313 Avoid calling window-configuration-change-hook; otherwise we
3314 could get an infloop in next_frame since the frame is not yet in
3315 Vframe_list. */
3316 {
a89654f8 3317 ptrdiff_t count2 = SPECPDL_INDEX ();
d1f55f16
CY
3318 record_unwind_protect (unwind_create_frame_1, inhibit_lisp_code);
3319 inhibit_lisp_code = Qt;
f01d3321
CY
3320
3321 x_default_parameter (f, parms, Qmenu_bar_lines,
3322 NILP (Vmenu_bar_mode)
3323 ? make_number (0) : make_number (1),
3324 NULL, NULL, RES_TYPE_NUMBER);
3325 x_default_parameter (f, parms, Qtool_bar_lines,
3326 NILP (Vtool_bar_mode)
3327 ? make_number (0) : make_number (1),
3328 NULL, NULL, RES_TYPE_NUMBER);
3329
3330 unbind_to (count2, Qnil);
3331 }
6431f2e6 3332
79873d50 3333 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
333b20bb
GM
3334 "bufferPredicate", "BufferPredicate",
3335 RES_TYPE_SYMBOL);
c2304e02 3336 x_default_parameter (f, parms, Qtitle, Qnil,
333b20bb 3337 "title", "Title", RES_TYPE_STRING);
ea0a1f53
GM
3338 x_default_parameter (f, parms, Qwait_for_wm, Qt,
3339 "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN);
49d41073
EZ
3340 x_default_parameter (f, parms, Qfullscreen, Qnil,
3341 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
2b4e6277 3342 x_default_parameter (f, parms, Qtool_bar_position,
edd74c35 3343 FGET (f, tool_bar_position), 0, 0, RES_TYPE_SYMBOL);
90eb1019 3344
35f59f6b 3345 /* Compute the size of the X window. */
7c0d3ed8 3346 window_prompting = x_figure_window_size (f, parms, 1);
38d22040 3347
495fa05e
GM
3348 tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
3349 f->no_split = minibuffer_only || EQ (tem, Qt);
3350
289978b5
LT
3351 x_icon_verify (f, parms);
3352
6a1bcd01 3353 /* Create the X widget or window. */
a7f7d550
FP
3354#ifdef USE_X_TOOLKIT
3355 x_window (f, window_prompting, minibuffer_only);
3356#else
f676886a 3357 x_window (f);
a7f7d550 3358#endif
177c0ea7 3359
f676886a
JB
3360 x_icon (f, parms);
3361 x_make_gc (f);
01f1ba30 3362
495fa05e 3363 /* Now consider the frame official. */
c9e7db78 3364 f->terminal->reference_count++;
495fa05e
GM
3365 FRAME_X_DISPLAY_INFO (f)->reference_count++;
3366 Vframe_list = Fcons (frame, Vframe_list);
3367
f9942c9e
JB
3368 /* We need to do this after creating the X window, so that the
3369 icon-creation functions can say whose icon they're describing. */
84f25880 3370 x_default_parameter (f, parms, Qicon_type, Qt,
33ed493b 3371 "bitmapIcon", "BitmapIcon", RES_TYPE_BOOLEAN);
f9942c9e 3372
cf177271 3373 x_default_parameter (f, parms, Qauto_raise, Qnil,
333b20bb 3374 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
cf177271 3375 x_default_parameter (f, parms, Qauto_lower, Qnil,
333b20bb 3376 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
dbc4e1c1 3377 x_default_parameter (f, parms, Qcursor_type, Qbox,
333b20bb 3378 "cursorType", "CursorType", RES_TYPE_SYMBOL);
28d7281d
GM
3379 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
3380 "scrollBarWidth", "ScrollBarWidth",
3381 RES_TYPE_NUMBER);
271a71c7
GM
3382 x_default_parameter (f, parms, Qalpha, Qnil,
3383 "alpha", "Alpha", RES_TYPE_NUMBER);
f9942c9e 3384
be786000 3385 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
01f1ba30 3386 Change will not be effected unless different from the current
be786000
KS
3387 FRAME_LINES (f). */
3388 width = FRAME_COLS (f);
3389 height = FRAME_LINES (f);
177c0ea7 3390
be786000
KS
3391 SET_FRAME_COLS (f, 0);
3392 FRAME_LINES (f) = 0;
8938a4fb 3393 change_frame_size (f, height, width, 1, 0, 0);
d043f1a4 3394
488dd4c4 3395#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
495fa05e
GM
3396 /* Create the menu bar. */
3397 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
3398 {
3399 /* If this signals an error, we haven't set size hints for the
3400 frame and we didn't make it visible. */
3401 initialize_frame_menubar (f);
3402
488dd4c4 3403#ifndef USE_GTK
495fa05e
GM
3404 /* This is a no-op, except under Motif where it arranges the
3405 main window for the widgets on it. */
3406 lw_set_main_areas (f->output_data.x->column_widget,
3407 f->output_data.x->menubar_widget,
3408 f->output_data.x->edit_widget);
488dd4c4 3409#endif /* not USE_GTK */
495fa05e 3410 }
488dd4c4 3411#endif /* USE_X_TOOLKIT || USE_GTK */
495fa05e
GM
3412
3413 /* Tell the server what size and position, etc, we want, and how
3414 badly we want them. This should be done after we have the menu
3415 bar so that its size can be taken into account. */
01f1ba30 3416 BLOCK_INPUT;
7989f084 3417 x_wm_set_size_hint (f, window_prompting, 0);
01f1ba30
JB
3418 UNBLOCK_INPUT;
3419
495fa05e
GM
3420 /* Make the window appear on the frame and enable display, unless
3421 the caller says not to. However, with explicit parent, Emacs
3422 cannot control visibility, so don't try. */
7556890b 3423 if (! f->output_data.x->explicit_parent)
a59e4f3d
RS
3424 {
3425 Lisp_Object visibility;
49795535 3426
333b20bb
GM
3427 visibility = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
3428 RES_TYPE_SYMBOL);
a59e4f3d
RS
3429 if (EQ (visibility, Qunbound))
3430 visibility = Qt;
49795535 3431
a59e4f3d
RS
3432 if (EQ (visibility, Qicon))
3433 x_iconify_frame (f);
3434 else if (! NILP (visibility))
3435 x_make_frame_visible (f);
3436 else
6b437900
PE
3437 {
3438 /* Must have been Qnil. */
3439 }
a59e4f3d 3440 }
01f1ba30 3441
3e6bec3b 3442 BLOCK_INPUT;
717c30e0 3443
3e6bec3b 3444 /* Set machine name and pid for the purpose of window managers. */
5e617bc2 3445 set_machine_and_pid_properties (f);
3e6bec3b 3446
6b61353c
KH
3447 /* Set the WM leader property. GTK does this itself, so this is not
3448 needed when using GTK. */
3449 if (dpyinfo->client_leader_window != 0)
3450 {
6b61353c
KH
3451 XChangeProperty (FRAME_X_DISPLAY (f),
3452 FRAME_OUTER_WINDOW (f),
3453 dpyinfo->Xatom_wm_client_leader,
3454 XA_WINDOW, 32, PropModeReplace,
47c53789 3455 (unsigned char *) &dpyinfo->client_leader_window, 1);
6b61353c
KH
3456 }
3457
3e6bec3b
JD
3458 UNBLOCK_INPUT;
3459
225c13a5 3460 /* Initialize `default-minibuffer-frame' in case this is the first
6ed8eeff 3461 frame on this terminal. */
225c13a5 3462 if (FRAME_HAS_MINIBUF_P (f)
1344aad4
TT
3463 && (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame))
3464 || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame)))))
3465 KVAR (kb, Vdefault_minibuffer_frame) = frame;
225c13a5 3466
5fa98fcf
RS
3467 /* All remaining specified parameters, which have not been "used"
3468 by x_get_arg and friends, now go in the misc. alist of the frame. */
9beb8baa 3469 for (tem = parms; CONSP (tem); tem = XCDR (tem))
5fa98fcf 3470 if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
edd74c35 3471 FSET (f, param_alist, Fcons (XCAR (tem), FGET (f, param_alist)));
5fa98fcf 3472
495fa05e 3473 UNGCPRO;
9e57df62
GM
3474
3475 /* Make sure windows on this frame appear in calls to next-window
3476 and similar functions. */
3477 Vwindow_list = Qnil;
177c0ea7 3478
9ef48a9d 3479 return unbind_to (count, frame);
01f1ba30
JB
3480}
3481
eaf1eea9 3482
0d17d282
KH
3483/* FRAME is used only to get a handle on the X display. We don't pass the
3484 display info directly because we're called from frame.c, which doesn't
3485 know about that structure. */
e4f79258 3486
87498171 3487Lisp_Object
971de7fb 3488x_get_focus_frame (struct frame *frame)
87498171 3489{
0d17d282 3490 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (frame);
87498171 3491 Lisp_Object xfocus;
0d17d282 3492 if (! dpyinfo->x_focus_frame)
87498171
KH
3493 return Qnil;
3494
0d17d282 3495 XSETFRAME (xfocus, dpyinfo->x_focus_frame);
87498171
KH
3496 return xfocus;
3497}
f0614854 3498
3decc1e7
GM
3499
3500/* In certain situations, when the window manager follows a
3501 click-to-focus policy, there seems to be no way around calling
3502 XSetInputFocus to give another frame the input focus .
3503
3504 In an ideal world, XSetInputFocus should generally be avoided so
3505 that applications don't interfere with the window manager's focus
3506 policy. But I think it's okay to use when it's clearly done
3507 following a user-command. */
3508
a7ca3326 3509DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
7ee72033
MB
3510 doc: /* Set the input focus to FRAME.
3511FRAME nil means use the selected frame. */)
5842a27b 3512 (Lisp_Object frame)
3decc1e7
GM
3513{
3514 struct frame *f = check_x_frame (frame);
3515 Display *dpy = FRAME_X_DISPLAY (f);
3decc1e7
GM
3516
3517 BLOCK_INPUT;
9ba8e10d 3518 x_catch_errors (dpy);
75bf0d33
DB
3519
3520 if (FRAME_X_EMBEDDED_P (f))
3521 {
3522 /* For Xembedded frames, normally the embedder forwards key
3523 events. See XEmbed Protocol Specification at
3524 http://freedesktop.org/wiki/Specifications/xembed-spec */
3525 xembed_request_focus (f);
3526 }
3527 else
3528 {
3529 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3530 RevertToParent, CurrentTime);
3531 x_ewmh_activate_frame (f);
3532 }
3533
4545fa20 3534 x_uncatch_errors ();
3decc1e7 3535 UNBLOCK_INPUT;
177c0ea7 3536
3decc1e7
GM
3537 return Qnil;
3538}
3539
f0614854 3540\f
2d764c78 3541DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
4f4f2973
GM
3542 doc: /* Internal function called by `color-defined-p', which see
3543.\(Note that the Nextstep version of this function ignores FRAME.) */)
5842a27b 3544 (Lisp_Object color, Lisp_Object frame)
e12d55b2 3545{
b9dc4443
RS
3546 XColor foo;
3547 FRAME_PTR f = check_x_frame (frame);
e12d55b2 3548
b7826503 3549 CHECK_STRING (color);
b9dc4443 3550
42a5b22f 3551 if (x_defined_color (f, SSDATA (color), &foo, 0))
e12d55b2
RS
3552 return Qt;
3553 else
3554 return Qnil;
3555}
3556
2d764c78 3557DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
7ee72033 3558 doc: /* Internal function called by `color-values', which see. */)
5842a27b 3559 (Lisp_Object color, Lisp_Object frame)
01f1ba30 3560{
b9dc4443
RS
3561 XColor foo;
3562 FRAME_PTR f = check_x_frame (frame);
3563
b7826503 3564 CHECK_STRING (color);
01f1ba30 3565
42a5b22f 3566 if (x_defined_color (f, SSDATA (color), &foo, 0))
a508663b
KS
3567 return list3 (make_number (foo.red),
3568 make_number (foo.green),
3569 make_number (foo.blue));
01f1ba30
JB
3570 else
3571 return Qnil;
3572}
3573
a7ca3326 3574DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
7ee72033 3575 doc: /* Internal function called by `display-color-p', which see. */)
5842a27b 3576 (Lisp_Object terminal)
01f1ba30 3577{
6ed8eeff 3578 struct x_display_info *dpyinfo = check_x_display_info (terminal);
11ae94fe 3579
b9dc4443 3580 if (dpyinfo->n_planes <= 2)
01f1ba30
JB
3581 return Qnil;
3582
b9dc4443 3583 switch (dpyinfo->visual->class)
01f1ba30
JB
3584 {
3585 case StaticColor:
3586 case PseudoColor:
3587 case TrueColor:
3588 case DirectColor:
3589 return Qt;
3590
3591 default:
3592 return Qnil;
3593 }
3594}
3595
a7ca3326 3596DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
c061c855 3597 0, 1, 0,
7ee72033 3598 doc: /* Return t if the X display supports shades of gray.
c061c855 3599Note that color displays do support shades of gray.
6ed8eeff 3600The optional argument TERMINAL specifies which display to ask about.
708e05dc 3601TERMINAL should be a terminal object, a frame or a display name (a string).
7ee72033 3602If omitted or nil, that stands for the selected frame's display. */)
5842a27b 3603 (Lisp_Object terminal)
d0c9d219 3604{
6ed8eeff 3605 struct x_display_info *dpyinfo = check_x_display_info (terminal);
d0c9d219 3606
ae6b58f9 3607 if (dpyinfo->n_planes <= 1)
b9dc4443
RS
3608 return Qnil;
3609
ae6b58f9
RS
3610 switch (dpyinfo->visual->class)
3611 {
3612 case StaticColor:
3613 case PseudoColor:
3614 case TrueColor:
3615 case DirectColor:
3616 case StaticGray:
3617 case GrayScale:
3618 return Qt;
3619
3620 default:
3621 return Qnil;
3622 }
d0c9d219
RS
3623}
3624
41beb8fc 3625DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
c061c855 3626 0, 1, 0,
d29a9848 3627 doc: /* Return the width in pixels of the X display TERMINAL.
6ed8eeff 3628The optional argument TERMINAL specifies which display to ask about.
708e05dc 3629TERMINAL should be a terminal object, a frame or a display name (a string).
7ee72033 3630If omitted or nil, that stands for the selected frame's display. */)
5842a27b 3631 (Lisp_Object terminal)
41beb8fc 3632{
6ed8eeff 3633 struct x_display_info *dpyinfo = check_x_display_info (terminal);
b9dc4443 3634
abe9d29c 3635 return make_number (x_display_pixel_width (dpyinfo));
41beb8fc
RS
3636}
3637
3638DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
c061c855 3639 Sx_display_pixel_height, 0, 1, 0,
d29a9848 3640 doc: /* Return the height in pixels of the X display TERMINAL.
6ed8eeff 3641The optional argument TERMINAL specifies which display to ask about.
708e05dc 3642TERMINAL should be a terminal object, a frame or a display name (a string).
7ee72033 3643If omitted or nil, that stands for the selected frame's display. */)
5842a27b 3644 (Lisp_Object terminal)
41beb8fc 3645{
6ed8eeff 3646 struct x_display_info *dpyinfo = check_x_display_info (terminal);
b9dc4443 3647
abe9d29c 3648 return make_number (x_display_pixel_height (dpyinfo));
41beb8fc
RS
3649}
3650
3651DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
c061c855 3652 0, 1, 0,
d29a9848 3653 doc: /* Return the number of bitplanes of the X display TERMINAL.
6ed8eeff 3654The optional argument TERMINAL specifies which display to ask about.
708e05dc 3655TERMINAL should be a terminal object, a frame or a display name (a string).
7ee72033 3656If omitted or nil, that stands for the selected frame's display. */)
5842a27b 3657 (Lisp_Object terminal)
41beb8fc 3658{
6ed8eeff 3659 struct x_display_info *dpyinfo = check_x_display_info (terminal);
b9dc4443
RS
3660
3661 return make_number (dpyinfo->n_planes);
41beb8fc
RS
3662}
3663
3664DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
c061c855 3665 0, 1, 0,
d29a9848 3666 doc: /* Return the number of color cells of the X display TERMINAL.
6ed8eeff 3667The optional argument TERMINAL specifies which display to ask about.
708e05dc 3668TERMINAL should be a terminal object, a frame or a display name (a string).
7ee72033 3669If omitted or nil, that stands for the selected frame's display. */)
5842a27b 3670 (Lisp_Object terminal)
41beb8fc 3671{
6ed8eeff 3672 struct x_display_info *dpyinfo = check_x_display_info (terminal);
b9dc4443 3673
6b61353c
KH
3674 int nr_planes = DisplayPlanes (dpyinfo->display,
3675 XScreenNumberOfScreen (dpyinfo->screen));
3676
3677 /* Truncate nr_planes to 24 to avoid integer overflow.
3678 Some displays says 32, but only 24 bits are actually significant.
3679 There are only very few and rare video cards that have more than
3680 24 significant bits. Also 24 bits is more than 16 million colors,
3681 it "should be enough for everyone". */
3682 if (nr_planes > 24) nr_planes = 24;
3683
3684 return make_number (1 << nr_planes);
41beb8fc
RS
3685}
3686
9d317b2c
RS
3687DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
3688 Sx_server_max_request_size,
c061c855 3689 0, 1, 0,
d29a9848 3690 doc: /* Return the maximum request size of the X server of display TERMINAL.
6ed8eeff 3691The optional argument TERMINAL specifies which display to ask about.
708e05dc 3692TERMINAL should be a terminal object, a frame or a display name (a string).
7ee72033 3693If omitted or nil, that stands for the selected frame's display. */)
5842a27b 3694 (Lisp_Object terminal)
9d317b2c 3695{
6ed8eeff 3696 struct x_display_info *dpyinfo = check_x_display_info (terminal);
b9dc4443
RS
3697
3698 return make_number (MAXREQUEST (dpyinfo->display));
9d317b2c
RS
3699}
3700
41beb8fc 3701DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
d29a9848 3702 doc: /* Return the "vendor ID" string of the X server of display TERMINAL.
09e80d9f 3703\(Labeling every distributor as a "vendor" embodies the false assumption
95d62d8a 3704that operating systems cannot be developed and distributed noncommercially.)
6ed8eeff 3705The optional argument TERMINAL specifies which display to ask about.
708e05dc 3706TERMINAL should be a terminal object, a frame or a display name (a string).
7ee72033 3707If omitted or nil, that stands for the selected frame's display. */)
5842a27b 3708 (Lisp_Object terminal)
41beb8fc 3709{
6ed8eeff 3710 struct x_display_info *dpyinfo = check_x_display_info (terminal);
675e2c69 3711 const char *vendor = ServerVendor (dpyinfo->display);
b9dc4443 3712
41beb8fc
RS
3713 if (! vendor) vendor = "";
3714 return build_string (vendor);
3715}
3716
3717DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
d29a9848 3718 doc: /* Return the version numbers of the X server of display TERMINAL.
c061c855 3719The value is a list of three integers: the major and minor
95d62d8a 3720version numbers of the X Protocol in use, and the distributor-specific release
c061c855
GM
3721number. See also the function `x-server-vendor'.
3722
6ed8eeff 3723The optional argument TERMINAL specifies which display to ask about.
708e05dc 3724TERMINAL should be a terminal object, a frame or a display name (a string).
7ee72033 3725If omitted or nil, that stands for the selected frame's display. */)
5842a27b 3726 (Lisp_Object terminal)
41beb8fc 3727{
6ed8eeff 3728 struct x_display_info *dpyinfo = check_x_display_info (terminal);
b9dc4443 3729 Display *dpy = dpyinfo->display;
11ae94fe 3730
41beb8fc
RS
3731 return Fcons (make_number (ProtocolVersion (dpy)),
3732 Fcons (make_number (ProtocolRevision (dpy)),
3733 Fcons (make_number (VendorRelease (dpy)), Qnil)));
3734}
3735
3736DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
6ed8eeff
KL
3737 doc: /* Return the number of screens on the X server of display TERMINAL.
3738The optional argument TERMINAL specifies which display to ask about.
708e05dc 3739TERMINAL should be a terminal object, a frame or a display name (a string).
7ee72033 3740If omitted or nil, that stands for the selected frame's display. */)
5842a27b 3741 (Lisp_Object terminal)
41beb8fc 3742{
6ed8eeff 3743 struct x_display_info *dpyinfo = check_x_display_info (terminal);
b9dc4443
RS
3744
3745 return make_number (ScreenCount (dpyinfo->display));
41beb8fc
RS
3746}
3747
3748DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
6ed8eeff
KL
3749 doc: /* Return the height in millimeters of the X display TERMINAL.
3750The optional argument TERMINAL specifies which display to ask about.
708e05dc 3751TERMINAL should be a terminal object, a frame or a display name (a string).
7ee72033 3752If omitted or nil, that stands for the selected frame's display. */)
5842a27b 3753 (Lisp_Object terminal)
41beb8fc 3754{
6ed8eeff 3755 struct x_display_info *dpyinfo = check_x_display_info (terminal);
b9dc4443
RS
3756
3757 return make_number (HeightMMOfScreen (dpyinfo->screen));
41beb8fc
RS
3758}
3759
3760DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
6ed8eeff
KL
3761 doc: /* Return the width in millimeters of the X display TERMINAL.
3762The optional argument TERMINAL specifies which display to ask about.
708e05dc 3763TERMINAL should be a terminal object, a frame or a display name (a string).
7ee72033 3764If omitted or nil, that stands for the selected frame's display. */)
5842a27b 3765 (Lisp_Object terminal)
41beb8fc 3766{
6ed8eeff 3767 struct x_display_info *dpyinfo = check_x_display_info (terminal);
b9dc4443
RS
3768
3769 return make_number (WidthMMOfScreen (dpyinfo->screen));
41beb8fc
RS
3770}
3771
3772DEFUN ("x-display-backing-store", Fx_display_backing_store,
c061c855 3773 Sx_display_backing_store, 0, 1, 0,
d29a9848 3774 doc: /* Return an indication of whether X display TERMINAL does backing store.
c061c855 3775The value may be `always', `when-mapped', or `not-useful'.
6ed8eeff 3776The optional argument TERMINAL specifies which display to ask about.
708e05dc 3777TERMINAL should be a terminal object, a frame or a display name (a string).
7ee72033 3778If omitted or nil, that stands for the selected frame's display. */)
5842a27b 3779 (Lisp_Object terminal)
41beb8fc 3780{
6ed8eeff 3781 struct x_display_info *dpyinfo = check_x_display_info (terminal);
8ec8a5ec 3782 Lisp_Object result;
11ae94fe 3783
b9dc4443 3784 switch (DoesBackingStore (dpyinfo->screen))
41beb8fc
RS
3785 {
3786 case Always:
8ec8a5ec
GM
3787 result = intern ("always");
3788 break;
41beb8fc
RS
3789
3790 case WhenMapped:
8ec8a5ec
GM
3791 result = intern ("when-mapped");
3792 break;
41beb8fc
RS
3793
3794 case NotUseful:
8ec8a5ec
GM
3795 result = intern ("not-useful");
3796 break;
41beb8fc
RS
3797
3798 default:
3799 error ("Strange value for BackingStore parameter of screen");
8ec8a5ec 3800 result = Qnil;
41beb8fc 3801 }
8ec8a5ec
GM
3802
3803 return result;
41beb8fc
RS
3804}
3805
3806DEFUN ("x-display-visual-class", Fx_display_visual_class,
c061c855 3807 Sx_display_visual_class, 0, 1, 0,
6ed8eeff 3808 doc: /* Return the visual class of the X display TERMINAL.
c061c855
GM
3809The value is one of the symbols `static-gray', `gray-scale',
3810`static-color', `pseudo-color', `true-color', or `direct-color'.
3811
6ed8eeff 3812The optional argument TERMINAL specifies which display to ask about.
708e05dc 3813TERMINAL should a terminal object, a frame or a display name (a string).
7ee72033 3814If omitted or nil, that stands for the selected frame's display. */)
5842a27b 3815 (Lisp_Object terminal)
41beb8fc 3816{
6ed8eeff 3817 struct x_display_info *dpyinfo = check_x_display_info (terminal);
8ec8a5ec 3818 Lisp_Object result;
11ae94fe 3819
b9dc4443 3820 switch (dpyinfo->visual->class)
41beb8fc 3821 {
8ec8a5ec
GM
3822 case StaticGray:
3823 result = intern ("static-gray");
3824 break;
3825 case GrayScale:
3826 result = intern ("gray-scale");
3827 break;
3828 case StaticColor:
3829 result = intern ("static-color");
3830 break;
3831 case PseudoColor:
3832 result = intern ("pseudo-color");
3833 break;
3834 case TrueColor:
3835 result = intern ("true-color");
3836 break;
3837 case DirectColor:
3838 result = intern ("direct-color");
3839 break;
41beb8fc
RS
3840 default:
3841 error ("Display has an unknown visual class");
8ec8a5ec 3842 result = Qnil;
41beb8fc 3843 }
177c0ea7 3844
8ec8a5ec 3845 return result;
41beb8fc
RS
3846}
3847
3848DEFUN ("x-display-save-under", Fx_display_save_under,
c061c855 3849 Sx_display_save_under, 0, 1, 0,
d29a9848 3850 doc: /* Return t if the X display TERMINAL supports the save-under feature.
6ed8eeff 3851The optional argument TERMINAL specifies which display to ask about.
708e05dc 3852TERMINAL should be a terminal object, a frame or a display name (a string).
7ee72033 3853If omitted or nil, that stands for the selected frame's display. */)
5842a27b 3854 (Lisp_Object terminal)
41beb8fc 3855{
6ed8eeff 3856 struct x_display_info *dpyinfo = check_x_display_info (terminal);
11ae94fe 3857
b9dc4443 3858 if (DoesSaveUnders (dpyinfo->screen) == True)
41beb8fc
RS
3859 return Qt;
3860 else
3861 return Qnil;
3862}
3863\f
b9dc4443 3864int
971de7fb 3865x_pixel_width (register struct frame *f)
01f1ba30 3866{
be786000 3867 return FRAME_PIXEL_WIDTH (f);
01f1ba30
JB
3868}
3869
b9dc4443 3870int
971de7fb 3871x_pixel_height (register struct frame *f)
01f1ba30 3872{
be786000 3873 return FRAME_PIXEL_HEIGHT (f);
55caf99c
RS
3874}
3875
b9dc4443 3876int
971de7fb 3877x_char_width (register struct frame *f)
55caf99c 3878{
be786000 3879 return FRAME_COLUMN_WIDTH (f);
55caf99c
RS
3880}
3881
b9dc4443 3882int
971de7fb 3883x_char_height (register struct frame *f)
55caf99c 3884{
be786000 3885 return FRAME_LINE_HEIGHT (f);
01f1ba30 3886}
b9dc4443 3887
a6ad00c0
GM
3888
3889\f
3890/************************************************************************
3891 X Displays
3892 ************************************************************************/
3893
01f1ba30 3894\f
a6ad00c0
GM
3895/* Mapping visual names to visuals. */
3896
3897static struct visual_class
3898{
675e2c69 3899 const char *name;
a6ad00c0
GM
3900 int class;
3901}
3902visual_classes[] =
3903{
3904 {"StaticGray", StaticGray},
3905 {"GrayScale", GrayScale},
3906 {"StaticColor", StaticColor},
3907 {"PseudoColor", PseudoColor},
3908 {"TrueColor", TrueColor},
3909 {"DirectColor", DirectColor},
9908a324 3910 {NULL, 0}
a6ad00c0
GM
3911};
3912
3913
404daac1 3914#ifndef HAVE_XSCREENNUMBEROFSCREEN
a6ad00c0
GM
3915
3916/* Value is the screen number of screen SCR. This is a substitute for
3917 the X function with the same name when that doesn't exist. */
3918
404daac1
RS
3919int
3920XScreenNumberOfScreen (scr)
3921 register Screen *scr;
3922{
a6ad00c0
GM
3923 Display *dpy = scr->display;
3924 int i;
3df34fdb 3925
a6ad00c0 3926 for (i = 0; i < dpy->nscreens; ++i)
fbd5ceb2 3927 if (scr == dpy->screens + i)
a6ad00c0 3928 break;
404daac1 3929
a6ad00c0 3930 return i;
404daac1 3931}
a6ad00c0 3932
404daac1
RS
3933#endif /* not HAVE_XSCREENNUMBEROFSCREEN */
3934
01f1ba30 3935
a6ad00c0
GM
3936/* Select the visual that should be used on display DPYINFO. Set
3937 members of DPYINFO appropriately. Called from x_term_init. */
fe24a618 3938
a6ad00c0 3939void
971de7fb 3940select_visual (struct x_display_info *dpyinfo)
a6ad00c0
GM
3941{
3942 Display *dpy = dpyinfo->display;
3943 Screen *screen = dpyinfo->screen;
3944 Lisp_Object value;
fe24a618 3945
a6ad00c0
GM
3946 /* See if a visual is specified. */
3947 value = display_x_get_resource (dpyinfo,
3948 build_string ("visualClass"),
3949 build_string ("VisualClass"),
3950 Qnil, Qnil);
3951 if (STRINGP (value))
3952 {
3953 /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
3954 of `PseudoColor', `TrueColor' etc. and DEPTH is the color
3955 depth, a decimal number. NAME is compared with case ignored. */
38182d90 3956 char *s = alloca (SBYTES (value) + 1);
a6ad00c0
GM
3957 char *dash;
3958 int i, class = -1;
3959 XVisualInfo vinfo;
3960
42a5b22f 3961 strcpy (s, SSDATA (value));
8966b757 3962 dash = strchr (s, '-');
a6ad00c0
GM
3963 if (dash)
3964 {
3965 dpyinfo->n_planes = atoi (dash + 1);
3966 *dash = '\0';
3967 }
3968 else
3969 /* We won't find a matching visual with depth 0, so that
3970 an error will be printed below. */
3971 dpyinfo->n_planes = 0;
f0614854 3972
a6ad00c0
GM
3973 /* Determine the visual class. */
3974 for (i = 0; visual_classes[i].name; ++i)
05131107 3975 if (xstrcasecmp (s, visual_classes[i].name) == 0)
a6ad00c0
GM
3976 {
3977 class = visual_classes[i].class;
3978 break;
3979 }
01f1ba30 3980
a6ad00c0
GM
3981 /* Look up a matching visual for the specified class. */
3982 if (class == -1
3983 || !XMatchVisualInfo (dpy, XScreenNumberOfScreen (screen),
3984 dpyinfo->n_planes, class, &vinfo))
d5db4077 3985 fatal ("Invalid visual specification `%s'", SDATA (value));
177c0ea7 3986
a6ad00c0
GM
3987 dpyinfo->visual = vinfo.visual;
3988 }
01f1ba30
JB
3989 else
3990 {
a6ad00c0
GM
3991 int n_visuals;
3992 XVisualInfo *vinfo, vinfo_template;
177c0ea7 3993
a6ad00c0
GM
3994 dpyinfo->visual = DefaultVisualOfScreen (screen);
3995
a6ad00c0 3996 vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
a6ad00c0
GM
3997 vinfo_template.screen = XScreenNumberOfScreen (screen);
3998 vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
3999 &vinfo_template, &n_visuals);
83725342 4000 if (n_visuals <= 0)
a6ad00c0
GM
4001 fatal ("Can't get proper X visual info");
4002
94ac875b 4003 dpyinfo->n_planes = vinfo->depth;
98c6f1e3 4004 XFree (vinfo);
a6ad00c0 4005 }
01f1ba30 4006}
01f1ba30 4007
a6ad00c0 4008
b9dc4443
RS
4009/* Return the X display structure for the display named NAME.
4010 Open a new connection if necessary. */
4011
e4cebfca 4012static struct x_display_info *
971de7fb 4013x_display_info_for_name (Lisp_Object name)
b9dc4443 4014{
08a90d6a 4015 Lisp_Object names;
b9dc4443
RS
4016 struct x_display_info *dpyinfo;
4017
b7826503 4018 CHECK_STRING (name);
b9dc4443 4019
2246281f
KL
4020#if 0
4021 if (! EQ (Vinitial_window_system, intern ("x")))
4022 error ("Not using X Windows"); /* That doesn't stop us anymore. */
4023#endif
806048df 4024
08a90d6a
RS
4025 for (dpyinfo = x_display_list, names = x_display_name_list;
4026 dpyinfo;
8e713be6 4027 dpyinfo = dpyinfo->next, names = XCDR (names))
b9dc4443
RS
4028 {
4029 Lisp_Object tem;
8e713be6 4030 tem = Fstring_equal (XCAR (XCAR (names)), name);
08a90d6a 4031 if (!NILP (tem))
b9dc4443
RS
4032 return dpyinfo;
4033 }
4034
b7975ee4
KH
4035 /* Use this general default value to start with. */
4036 Vx_resource_name = Vinvocation_name;
4037
b9dc4443
RS
4038 validate_x_resource_name ();
4039
9b207e8e 4040 dpyinfo = x_term_init (name, (char *)0,
51b59d79 4041 SSDATA (Vx_resource_name));
b9dc4443 4042
08a90d6a 4043 if (dpyinfo == 0)
d5db4077 4044 error ("Cannot connect to X server %s", SDATA (name));
08a90d6a 4045
b9dc4443
RS
4046 x_in_use = 1;
4047 XSETFASTINT (Vwindow_system_version, 11);
4048
4049 return dpyinfo;
4050}
4051
a6ad00c0 4052
01f1ba30 4053DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
c061c855 4054 1, 3, 0,
4f4f2973 4055 doc: /* Open a connection to a display server.
c061c855
GM
4056DISPLAY is the name of the display to connect to.
4057Optional second arg XRM-STRING is a string of resources in xrdb format.
4058If the optional third arg MUST-SUCCEED is non-nil,
4f4f2973
GM
4059terminate Emacs if we can't open the connection.
4060\(In the Nextstep version, the last two arguments are currently ignored.) */)
5842a27b 4061 (Lisp_Object display, Lisp_Object xrm_string, Lisp_Object must_succeed)
01f1ba30 4062{
5f742c1b 4063 char *xrm_option;
b9dc4443 4064 struct x_display_info *dpyinfo;
01f1ba30 4065
b7826503 4066 CHECK_STRING (display);
d387c960 4067 if (! NILP (xrm_string))
b7826503 4068 CHECK_STRING (xrm_string);
01f1ba30 4069
2246281f
KL
4070#if 0
4071 if (! EQ (Vinitial_window_system, intern ("x")))
4072 error ("Not using X Windows"); /* That doesn't stop us anymore. */
4073#endif
806048df 4074
d387c960 4075 if (! NILP (xrm_string))
5f742c1b 4076 xrm_option = SSDATA (xrm_string);
01f1ba30 4077 else
5f742c1b 4078 xrm_option = (char *) 0;
d387c960
JB
4079
4080 validate_x_resource_name ();
4081
e1b1bee8 4082 /* This is what opens the connection and sets x_current_display.
b9dc4443
RS
4083 This also initializes many symbols, such as those used for input. */
4084 dpyinfo = x_term_init (display, xrm_option,
51b59d79 4085 SSDATA (Vx_resource_name));
f1c16f36 4086
08a90d6a
RS
4087 if (dpyinfo == 0)
4088 {
4089 if (!NILP (must_succeed))
10ffbc14
GM
4090 fatal ("Cannot connect to X server %s.\n\
4091Check the DISPLAY environment variable or use `-d'.\n\
842a9389
JB
4092Also use the `xauth' program to verify that you have the proper\n\
4093authorization information needed to connect the X server.\n\
bf770132 4094An insecure way to solve the problem may be to use `xhost'.\n",
d5db4077 4095 SDATA (display));
08a90d6a 4096 else
d5db4077 4097 error ("Cannot connect to X server %s", SDATA (display));
08a90d6a
RS
4098 }
4099
b9dc4443 4100 x_in_use = 1;
01f1ba30 4101
b9dc4443 4102 XSETFASTINT (Vwindow_system_version, 11);
01f1ba30
JB
4103 return Qnil;
4104}
4105
08a90d6a
RS
4106DEFUN ("x-close-connection", Fx_close_connection,
4107 Sx_close_connection, 1, 1, 0,
00d385b0 4108 doc: /* Close the connection to TERMINAL's X server.
708e05dc 4109For TERMINAL, specify a terminal object, a frame or a display name (a
00d385b0
KL
4110string). If TERMINAL is nil, that stands for the selected frame's
4111terminal. */)
5842a27b 4112 (Lisp_Object terminal)
01f1ba30 4113{
00d385b0 4114 struct x_display_info *dpyinfo = check_x_display_info (terminal);
3457bc6e 4115
08a90d6a
RS
4116 if (dpyinfo->reference_count > 0)
4117 error ("Display still has frames on it");
01f1ba30 4118
6ed8eeff 4119 x_delete_terminal (dpyinfo->terminal);
3457bc6e 4120
01f1ba30
JB
4121 return Qnil;
4122}
4123
08a90d6a 4124DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
7ee72033 4125 doc: /* Return the list of display names that Emacs has connections to. */)
5842a27b 4126 (void)
08a90d6a
RS
4127{
4128 Lisp_Object tail, result;
4129
4130 result = Qnil;
9beb8baa 4131 for (tail = x_display_name_list; CONSP (tail); tail = XCDR (tail))
8e713be6 4132 result = Fcons (XCAR (XCAR (tail)), result);
08a90d6a
RS
4133
4134 return result;
4135}
4136
4137DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
7ee72033 4138 doc: /* If ON is non-nil, report X errors as soon as the erring request is made.
7c051dd8
GM
4139This function only has an effect on X Windows. With MS Windows, it is
4140defined but does nothing.
4141
c061c855
GM
4142If ON is nil, allow buffering of requests.
4143Turning on synchronization prohibits the Xlib routines from buffering
4144requests and seriously degrades performance, but makes debugging much
4145easier.
00d385b0 4146The optional second argument TERMINAL specifies which display to act on.
708e05dc 4147TERMINAL should be a terminal object, a frame or a display name (a string).
00d385b0 4148If TERMINAL is omitted or nil, that stands for the selected frame's display. */)
5842a27b 4149 (Lisp_Object on, Lisp_Object terminal)
01f1ba30 4150{
00d385b0 4151 struct x_display_info *dpyinfo = check_x_display_info (terminal);
11ae94fe 4152
b9dc4443 4153 XSynchronize (dpyinfo->display, !EQ (on, Qnil));
01f1ba30
JB
4154
4155 return Qnil;
4156}
4157
b9dc4443 4158/* Wait for responses to all X commands issued so far for frame F. */
6b7b1820
RS
4159
4160void
971de7fb 4161x_sync (FRAME_PTR f)
6b7b1820 4162{
4e87f4d2 4163 BLOCK_INPUT;
b9dc4443 4164 XSync (FRAME_X_DISPLAY (f), False);
4e87f4d2 4165 UNBLOCK_INPUT;
6b7b1820 4166}
333b20bb 4167
01f1ba30 4168\f
333b20bb 4169/***********************************************************************
6b61353c 4170 Window properties
333b20bb 4171 ***********************************************************************/
f1c16f36 4172
6b61353c
KH
4173DEFUN ("x-change-window-property", Fx_change_window_property,
4174 Sx_change_window_property, 2, 6, 0,
4175 doc: /* Change window property PROP to VALUE on the X window of FRAME.
7c051dd8
GM
4176PROP must be a string. VALUE may be a string or a list of conses,
4177numbers and/or strings. If an element in the list is a string, it is
4178converted to an atom and the value of the atom is used. If an element
4179is a cons, it is converted to a 32 bit number where the car is the 16
4180top bits and the cdr is the lower 16 bits.
4181
6b61353c
KH
4182FRAME nil or omitted means use the selected frame.
4183If TYPE is given and non-nil, it is the name of the type of VALUE.
4184If TYPE is not given or nil, the type is STRING.
4185FORMAT gives the size in bits of each element if VALUE is a list.
4186It must be one of 8, 16 or 32.
4187If VALUE is a string or FORMAT is nil or not given, FORMAT defaults to 8.
fca8d6b6 4188If OUTER-P is non-nil, the property is changed for the outer X window of
7c051dd8 4189FRAME. Default is to change on the edit X window. */)
fca8d6b6
AS
4190 (Lisp_Object prop, Lisp_Object value, Lisp_Object frame,
4191 Lisp_Object type, Lisp_Object format, Lisp_Object outer_p)
6b61353c
KH
4192{
4193 struct frame *f = check_x_frame (frame);
4194 Atom prop_atom;
4195 Atom target_type = XA_STRING;
4196 int element_format = 8;
4197 unsigned char *data;
4198 int nelements;
4199 Window w;
333b20bb 4200
6b61353c 4201 CHECK_STRING (prop);
333b20bb 4202
6b61353c
KH
4203 if (! NILP (format))
4204 {
4205 CHECK_NUMBER (format);
333b20bb 4206
d311d28c
PE
4207 if (XINT (format) != 8 && XINT (format) != 16
4208 && XINT (format) != 32)
6b61353c 4209 error ("FORMAT must be one of 8, 16 or 32");
d311d28c 4210 element_format = XINT (format);
6b61353c 4211 }
333b20bb 4212
6b61353c
KH
4213 if (CONSP (value))
4214 {
c678c835
PE
4215 ptrdiff_t elsize;
4216
6b61353c
KH
4217 nelements = x_check_property_data (value);
4218 if (nelements == -1)
4219 error ("Bad data in VALUE, must be number, string or cons");
333b20bb 4220
c678c835
PE
4221 /* The man page for XChangeProperty:
4222 "If the specified format is 32, the property data must be a
4223 long array."
4224 This applies even if long is more than 32 bits. The X library
4225 converts to 32 bits before sending to the X server. */
4226 elsize = element_format == 32 ? sizeof (long) : element_format >> 3;
0065d054 4227 data = xnmalloc (nelements, elsize);
333b20bb 4228
6b61353c
KH
4229 x_fill_property_data (FRAME_X_DISPLAY (f), value, data, element_format);
4230 }
4231 else
4232 {
4233 CHECK_STRING (value);
4234 data = SDATA (value);
c678c835
PE
4235 if (INT_MAX < SBYTES (value))
4236 error ("VALUE too long");
4237 nelements = SBYTES (value);
6b61353c 4238 }
333b20bb 4239
6b61353c 4240 BLOCK_INPUT;
42a5b22f 4241 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False);
6b61353c
KH
4242 if (! NILP (type))
4243 {
4244 CHECK_STRING (type);
42a5b22f 4245 target_type = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (type), False);
6b61353c 4246 }
333b20bb 4247
6b61353c
KH
4248 if (! NILP (outer_p)) w = FRAME_OUTER_WINDOW (f);
4249 else w = FRAME_X_WINDOW (f);
5b3f8550 4250
6b61353c
KH
4251 XChangeProperty (FRAME_X_DISPLAY (f), w,
4252 prop_atom, target_type, element_format, PropModeReplace,
4253 data, nelements);
333b20bb 4254
6b61353c 4255 if (CONSP (value)) xfree (data);
333b20bb 4256
6b61353c
KH
4257 /* Make sure the property is set when we return. */
4258 XFlush (FRAME_X_DISPLAY (f));
4259 UNBLOCK_INPUT;
333b20bb 4260
6b61353c 4261 return value;
333b20bb
GM
4262}
4263
4264
6b61353c
KH
4265DEFUN ("x-delete-window-property", Fx_delete_window_property,
4266 Sx_delete_window_property, 1, 2, 0,
4267 doc: /* Remove window property PROP from X window of FRAME.
4268FRAME nil or omitted means use the selected frame. Value is PROP. */)
5842a27b 4269 (Lisp_Object prop, Lisp_Object frame)
333b20bb 4270{
6b61353c
KH
4271 struct frame *f = check_x_frame (frame);
4272 Atom prop_atom;
333b20bb 4273
6b61353c
KH
4274 CHECK_STRING (prop);
4275 BLOCK_INPUT;
42a5b22f 4276 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False);
6b61353c 4277 XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), prop_atom);
333b20bb 4278
6b61353c
KH
4279 /* Make sure the property is removed when we return. */
4280 XFlush (FRAME_X_DISPLAY (f));
4281 UNBLOCK_INPUT;
333b20bb 4282
6b61353c
KH
4283 return prop;
4284}
333b20bb 4285
333b20bb 4286
6b61353c
KH
4287DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
4288 1, 6, 0,
4289 doc: /* Value is the value of window property PROP on FRAME.
4290If FRAME is nil or omitted, use the selected frame.
7c051dd8 4291
7c051dd8
GM
4292On X Windows, the following optional arguments are also accepted:
4293If TYPE is nil or omitted, get the property as a string.
4294Otherwise TYPE is the name of the atom that denotes the type expected.
6b61353c
KH
4295If SOURCE is non-nil, get the property on that window instead of from
4296FRAME. The number 0 denotes the root window.
ddadbc0e
AS
4297If DELETE-P is non-nil, delete the property after retrieving it.
4298If VECTOR-RET-P is non-nil, don't return a string but a vector of values.
4299
4300On MS Windows, this function accepts but ignores those optional arguments.
6b61353c
KH
4301
4302Value is nil if FRAME hasn't a property with name PROP or if PROP has
7c051dd8 4303no value of TYPE (always string in the MS Windows case). */)
ddadbc0e
AS
4304 (Lisp_Object prop, Lisp_Object frame, Lisp_Object type,
4305 Lisp_Object source, Lisp_Object delete_p, Lisp_Object vector_ret_p)
333b20bb 4306{
6b61353c
KH
4307 struct frame *f = check_x_frame (frame);
4308 Atom prop_atom;
4309 int rc;
4310 Lisp_Object prop_value = Qnil;
a3db4b26 4311 unsigned char *tmp_data = NULL;
6b61353c
KH
4312 Atom actual_type;
4313 Atom target_type = XA_STRING;
4314 int actual_format;
4315 unsigned long actual_size, bytes_remaining;
4316 Window target_window = FRAME_X_WINDOW (f);
4317 struct gcpro gcpro1;
177c0ea7 4318
6b61353c
KH
4319 GCPRO1 (prop_value);
4320 CHECK_STRING (prop);
1783ffa2 4321
6b61353c
KH
4322 if (! NILP (source))
4323 {
be44ca6c
PE
4324 CONS_TO_INTEGER (source, Window, target_window);
4325 if (! target_window)
4326 target_window = FRAME_X_DISPLAY_INFO (f)->root_window;
333b20bb
GM
4327 }
4328
6b61353c
KH
4329 BLOCK_INPUT;
4330 if (STRINGP (type))
4331 {
42a5b22f 4332 if (strcmp ("AnyPropertyType", SSDATA (type)) == 0)
6b61353c
KH
4333 target_type = AnyPropertyType;
4334 else
42a5b22f 4335 target_type = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (type), False);
6b61353c 4336 }
333b20bb 4337
42a5b22f 4338 prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False);
6b61353c
KH
4339 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
4340 prop_atom, 0, 0, False, target_type,
4341 &actual_type, &actual_format, &actual_size,
a3db4b26 4342 &bytes_remaining, &tmp_data);
6b61353c
KH
4343 if (rc == Success)
4344 {
4345 int size = bytes_remaining;
333b20bb 4346
6b61353c
KH
4347 XFree (tmp_data);
4348 tmp_data = NULL;
333b20bb 4349
6b61353c 4350 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
333b20bb 4351 prop_atom, 0, bytes_remaining,
6b61353c 4352 ! NILP (delete_p), target_type,
177c0ea7
JB
4353 &actual_type, &actual_format,
4354 &actual_size, &bytes_remaining,
a3db4b26 4355 &tmp_data);
4c8c7926 4356 if (rc == Success && tmp_data)
6b61353c 4357 {
fede04ef
JD
4358 /* The man page for XGetWindowProperty says:
4359 "If the returned format is 32, the returned data is represented
4360 as a long array and should be cast to that type to obtain the
4361 elements."
4362 This applies even if long is more than 32 bits, the X library
4363 converts from 32 bit elements received from the X server to long
72af86bd 4364 and passes the long array to us. Thus, for that case memcpy can not
fede04ef
JD
4365 be used. We convert to a 32 bit type here, because so much code
4366 assume on that.
4367
4368 The bytes and offsets passed to XGetWindowProperty refers to the
4369 property and those are indeed in 32 bit quantities if format is
4370 32. */
4371
2172544b 4372 if (32 < BITS_PER_LONG && actual_format == 32)
fede04ef
JD
4373 {
4374 unsigned long i;
4375 int *idata = (int *) tmp_data;
4376 long *ldata = (long *) tmp_data;
4377
4378 for (i = 0; i < actual_size; ++i)
a3db4b26 4379 idata[i] = (int) ldata[i];
fede04ef
JD
4380 }
4381
6b61353c 4382 if (NILP (vector_ret_p))
5f742c1b 4383 prop_value = make_string ((char *) tmp_data, size);
6b61353c
KH
4384 else
4385 prop_value = x_property_data_to_lisp (f,
a3db4b26 4386 tmp_data,
6b61353c
KH
4387 actual_type,
4388 actual_format,
4389 actual_size);
4390 }
333b20bb 4391
6b61353c 4392 if (tmp_data) XFree (tmp_data);
333b20bb
GM
4393 }
4394
4395 UNBLOCK_INPUT;
6b61353c 4396 UNGCPRO;
333b20bb
GM
4397 return prop_value;
4398}
4399
4400
4401\f
4402/***********************************************************************
4403 Busy cursor
4404 ***********************************************************************/
4405
0af913d7
GM
4406/* Timer function of hourglass_atimer. TIMER is equal to
4407 hourglass_atimer.
4ae9a85e 4408
0af913d7
GM
4409 Display an hourglass pointer on all frames by mapping the frames'
4410 hourglass_window. Set the hourglass_p flag in the frames'
4411 output_data.x structure to indicate that an hourglass cursor is
4412 shown on the frames. */
4ae9a85e 4413
1885ab29 4414void
971de7fb 4415show_hourglass (struct atimer *timer)
4ae9a85e
GM
4416{
4417 /* The timer implementation will cancel this timer automatically
0af913d7 4418 after this function has run. Set hourglass_atimer to null
4ae9a85e 4419 so that we know the timer doesn't have to be canceled. */
0af913d7 4420 hourglass_atimer = NULL;
4ae9a85e 4421
0af913d7 4422 if (!hourglass_shown_p)
333b20bb
GM
4423 {
4424 Lisp_Object rest, frame;
177c0ea7 4425
4ae9a85e 4426 BLOCK_INPUT;
177c0ea7 4427
333b20bb 4428 FOR_EACH_FRAME (rest, frame)
5f7a1890
GM
4429 {
4430 struct frame *f = XFRAME (frame);
177c0ea7 4431
5f7a1890
GM
4432 if (FRAME_LIVE_P (f) && FRAME_X_P (f) && FRAME_X_DISPLAY (f))
4433 {
4434 Display *dpy = FRAME_X_DISPLAY (f);
177c0ea7 4435
5f7a1890
GM
4436#ifdef USE_X_TOOLKIT
4437 if (f->output_data.x->widget)
4438#else
4439 if (FRAME_OUTER_WINDOW (f))
4440#endif
4441 {
0af913d7 4442 f->output_data.x->hourglass_p = 1;
177c0ea7 4443
0af913d7 4444 if (!f->output_data.x->hourglass_window)
5f7a1890
GM
4445 {
4446 unsigned long mask = CWCursor;
4447 XSetWindowAttributes attrs;
49b8b5dc
JD
4448#ifdef USE_GTK
4449 Window parent = FRAME_X_WINDOW (f);
4450#else
4451 Window parent = FRAME_OUTER_WINDOW (f);
4452#endif
0af913d7 4453 attrs.cursor = f->output_data.x->hourglass_cursor;
177c0ea7 4454
0af913d7 4455 f->output_data.x->hourglass_window
49b8b5dc 4456 = XCreateWindow (dpy, parent,
5f7a1890
GM
4457 0, 0, 32000, 32000, 0, 0,
4458 InputOnly,
4459 CopyFromParent,
4460 mask, &attrs);
4461 }
177c0ea7 4462
0af913d7 4463 XMapRaised (dpy, f->output_data.x->hourglass_window);
5f7a1890
GM
4464 XFlush (dpy);
4465 }
4466 }
4467 }
333b20bb 4468
0af913d7 4469 hourglass_shown_p = 1;
4ae9a85e
GM
4470 UNBLOCK_INPUT;
4471 }
333b20bb
GM
4472}
4473
4474
0af913d7
GM
4475/* Hide the hourglass pointer on all frames, if it is currently
4476 shown. */
333b20bb 4477
1885ab29 4478void
971de7fb 4479hide_hourglass (void)
4ae9a85e 4480{
0af913d7 4481 if (hourglass_shown_p)
333b20bb 4482 {
4ae9a85e
GM
4483 Lisp_Object rest, frame;
4484
4485 BLOCK_INPUT;
4486 FOR_EACH_FRAME (rest, frame)
333b20bb 4487 {
4ae9a85e 4488 struct frame *f = XFRAME (frame);
177c0ea7 4489
4ae9a85e
GM
4490 if (FRAME_X_P (f)
4491 /* Watch out for newly created frames. */
0af913d7 4492 && f->output_data.x->hourglass_window)
4ae9a85e 4493 {
0af913d7
GM
4494 XUnmapWindow (FRAME_X_DISPLAY (f),
4495 f->output_data.x->hourglass_window);
4496 /* Sync here because XTread_socket looks at the
4497 hourglass_p flag that is reset to zero below. */
4ae9a85e 4498 XSync (FRAME_X_DISPLAY (f), False);
0af913d7 4499 f->output_data.x->hourglass_p = 0;
4ae9a85e 4500 }
333b20bb 4501 }
333b20bb 4502
0af913d7 4503 hourglass_shown_p = 0;
4ae9a85e
GM
4504 UNBLOCK_INPUT;
4505 }
333b20bb
GM
4506}
4507
4508
4509\f
4510/***********************************************************************
4511 Tool tips
4512 ***********************************************************************/
4513
f57e2426
J
4514static Lisp_Object x_create_tip_frame (struct x_display_info *,
4515 Lisp_Object, Lisp_Object);
4516static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
4517 Lisp_Object, int, int, int *, int *);
177c0ea7 4518
44b5a125 4519/* The frame of a currently visible tooltip. */
333b20bb 4520
44b5a125 4521Lisp_Object tip_frame;
333b20bb
GM
4522
4523/* If non-nil, a timer started that hides the last tooltip when it
4524 fires. */
4525
e4cebfca 4526static Lisp_Object tip_timer;
333b20bb
GM
4527Window tip_window;
4528
06d62053
GM
4529/* If non-nil, a vector of 3 elements containing the last args
4530 with which x-show-tip was called. See there. */
4531
e4cebfca 4532static Lisp_Object last_show_tip_args;
06d62053 4533
eaf1eea9
GM
4534
4535static Lisp_Object
971de7fb 4536unwind_create_tip_frame (Lisp_Object frame)
eaf1eea9 4537{
c844a81a
GM
4538 Lisp_Object deleted;
4539
4540 deleted = unwind_create_frame (frame);
4541 if (EQ (deleted, Qt))
4542 {
4543 tip_window = None;
4544 tip_frame = Qnil;
4545 }
177c0ea7 4546
c844a81a 4547 return deleted;
eaf1eea9
GM
4548}
4549
4550
333b20bb 4551/* Create a frame for a tooltip on the display described by DPYINFO.
275841bf
GM
4552 PARMS is a list of frame parameters. TEXT is the string to
4553 display in the tip frame. Value is the frame.
eaf1eea9
GM
4554
4555 Note that functions called here, esp. x_default_parameter can
4556 signal errors, for instance when a specified color name is
4557 undefined. We have to make sure that we're in a consistent state
4558 when this happens. */
333b20bb
GM
4559
4560static Lisp_Object
aa1859f5
J
4561x_create_tip_frame (struct x_display_info *dpyinfo,
4562 Lisp_Object parms,
4563 Lisp_Object text)
333b20bb
GM
4564{
4565 struct frame *f;
06b0c8a0 4566 Lisp_Object frame;
333b20bb 4567 Lisp_Object name;
333b20bb 4568 int width, height;
d311d28c 4569 ptrdiff_t count = SPECPDL_INDEX ();
b6d7acec 4570 struct gcpro gcpro1, gcpro2, gcpro3;
06d62053 4571 int face_change_count_before = face_change_count;
275841bf
GM
4572 Lisp_Object buffer;
4573 struct buffer *old_buffer;
333b20bb
GM
4574
4575 check_x ();
4576
89acb56d
SM
4577 if (!dpyinfo->terminal->name)
4578 error ("Terminal is not live, can't create new frames on it");
333b20bb 4579
47f3c6b4 4580 parms = Fcopy_alist (parms);
333b20bb
GM
4581
4582 /* Get the name of the frame to use for resource lookup. */
4583 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
4584 if (!STRINGP (name)
4585 && !EQ (name, Qunbound)
4586 && !NILP (name))
4587 error ("Invalid frame name--not a string or nil");
333b20bb
GM
4588
4589 frame = Qnil;
4590 GCPRO3 (parms, name, frame);
44b5a125 4591 f = make_frame (1);
333b20bb 4592 XSETFRAME (frame, f);
275841bf
GM
4593
4594 buffer = Fget_buffer_create (build_string (" *tip*"));
be786000 4595 Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer, Qnil);
275841bf
GM
4596 old_buffer = current_buffer;
4597 set_buffer_internal_1 (XBUFFER (buffer));
4b4deea2 4598 BVAR (current_buffer, truncate_lines) = Qnil;
5c2a995d
KH
4599 specbind (Qinhibit_read_only, Qt);
4600 specbind (Qinhibit_modification_hooks, Qt);
275841bf
GM
4601 Ferase_buffer ();
4602 Finsert (1, &text);
4603 set_buffer_internal_1 (old_buffer);
177c0ea7 4604
333b20bb 4605 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
8a1a7743 4606 record_unwind_protect (unwind_create_tip_frame, frame);
333b20bb 4607
6ed8eeff 4608 f->terminal = dpyinfo->terminal;
daf01701 4609
eaf1eea9
GM
4610 /* By setting the output method, we're essentially saying that
4611 the frame is live, as per FRAME_LIVE_P. If we get a signal
4612 from this point on, x_destroy_window might screw up reference
4613 counts etc. */
333b20bb 4614 f->output_method = output_x_window;
38182d90 4615 f->output_data.x = xzalloc (sizeof *f->output_data.x);
333b20bb 4616 f->output_data.x->icon_bitmap = -1;
be786000 4617 FRAME_FONTSET (f) = -1;
61d461a8
GM
4618 f->output_data.x->scroll_bar_foreground_pixel = -1;
4619 f->output_data.x->scroll_bar_background_pixel = -1;
f15340b7
MB
4620#ifdef USE_TOOLKIT_SCROLL_BARS
4621 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
4622 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
4623#endif /* USE_TOOLKIT_SCROLL_BARS */
edd74c35 4624 FSET (f, icon_name, Qnil);
333b20bb 4625 FRAME_X_DISPLAY_INFO (f) = dpyinfo;
333b20bb
GM
4626 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
4627 f->output_data.x->explicit_parent = 0;
4628
61d461a8
GM
4629 /* These colors will be set anyway later, but it's important
4630 to get the color reference counts right, so initialize them! */
4631 {
4632 Lisp_Object black;
dbf31225 4633 struct gcpro gcpro1;
177c0ea7 4634
9d3d44ba
KL
4635 /* Function x_decode_color can signal an error. Make
4636 sure to initialize color slots so that we won't try
4637 to free colors we haven't allocated. */
ce593f6e
KL
4638 FRAME_FOREGROUND_PIXEL (f) = -1;
4639 FRAME_BACKGROUND_PIXEL (f) = -1;
9d3d44ba
KL
4640 f->output_data.x->cursor_pixel = -1;
4641 f->output_data.x->cursor_foreground_pixel = -1;
4642 f->output_data.x->border_pixel = -1;
4643 f->output_data.x->mouse_pixel = -1;
4644
61d461a8 4645 black = build_string ("black");
dbf31225 4646 GCPRO1 (black);
ce593f6e 4647 FRAME_FOREGROUND_PIXEL (f)
61d461a8 4648 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
ce593f6e 4649 FRAME_BACKGROUND_PIXEL (f)
61d461a8
GM
4650 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4651 f->output_data.x->cursor_pixel
4652 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4653 f->output_data.x->cursor_foreground_pixel
4654 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4655 f->output_data.x->border_pixel
4656 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
4657 f->output_data.x->mouse_pixel
4658 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
dbf31225 4659 UNGCPRO;
61d461a8
GM
4660 }
4661
333b20bb
GM
4662 /* Set the name; the functions to which we pass f expect the name to
4663 be set. */
4664 if (EQ (name, Qunbound) || NILP (name))
4665 {
edd74c35 4666 FSET (f, name, build_string (dpyinfo->x_id_name));
333b20bb
GM
4667 f->explicit_name = 0;
4668 }
4669 else
4670 {
edd74c35 4671 FSET (f, name, name);
333b20bb
GM
4672 f->explicit_name = 1;
4673 /* use the frame's title when getting resources for this frame. */
4674 specbind (Qx_resource_name, name);
4675 }
4676
02ed2ea8
KH
4677 f->resx = dpyinfo->resx;
4678 f->resy = dpyinfo->resy;
4679
bf970f2b 4680 register_font_driver (&xfont_driver, f);
02ed2ea8
KH
4681#ifdef HAVE_FREETYPE
4682#ifdef HAVE_XFT
b51238f5 4683 register_font_driver (&xftfont_driver, f);
02ed2ea8 4684#else /* not HAVE_XFT */
b51238f5 4685 register_font_driver (&ftxfont_driver, f);
02ed2ea8
KH
4686#endif /* not HAVE_XFT */
4687#endif /* HAVE_FREETYPE */
d43f6b74 4688
b51238f5
KH
4689 x_default_parameter (f, parms, Qfont_backend, Qnil,
4690 "fontBackend", "FontBackend", RES_TYPE_STRING);
02ed2ea8 4691
eaf1eea9
GM
4692 /* Extract the window parameters from the supplied values that are
4693 needed to determine window geometry. */
b51238f5 4694 x_default_font_parameter (f, parms);
333b20bb 4695
4bef8d26 4696 x_default_parameter (f, parms, Qborder_width, make_number (0),
333b20bb 4697 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
177c0ea7 4698
333b20bb
GM
4699 /* This defaults to 2 in order to match xterm. We recognize either
4700 internalBorderWidth or internalBorder (which is what xterm calls
4701 it). */
4702 if (NILP (Fassq (Qinternal_border_width, parms)))
4703 {
4704 Lisp_Object value;
4705
4706 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
4707 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
4708 if (! EQ (value, Qunbound))
4709 parms = Fcons (Fcons (Qinternal_border_width, value),
4710 parms);
4711 }
4712
4713 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
4714 "internalBorderWidth", "internalBorderWidth",
4715 RES_TYPE_NUMBER);
4716
4717 /* Also do the stuff which must be set before the window exists. */
4718 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
4719 "foreground", "Foreground", RES_TYPE_STRING);
4720 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
4721 "background", "Background", RES_TYPE_STRING);
4722 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
4723 "pointerColor", "Foreground", RES_TYPE_STRING);
4724 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
4725 "cursorColor", "Foreground", RES_TYPE_STRING);
4726 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
4727 "borderColor", "BorderColor", RES_TYPE_STRING);
4728
e509cfa6 4729#ifdef GLYPH_DEBUG
c9e7db78
JD
4730 image_cache_refcount =
4731 FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
4732 dpyinfo_refcount = dpyinfo->reference_count;
4733#endif /* GLYPH_DEBUG */
4734
333b20bb
GM
4735 /* Init faces before x_default_parameter is called for scroll-bar
4736 parameters because that function calls x_set_scroll_bar_width,
4737 which calls change_frame_size, which calls Fset_window_buffer,
4738 which runs hooks, which call Fvertical_motion. At the end, we
4739 end up in init_iterator with a null face cache, which should not
4740 happen. */
4741 init_frame_faces (f);
177c0ea7 4742
333b20bb 4743 f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
333b20bb 4744
0ce7538d 4745 x_figure_window_size (f, parms, 0);
333b20bb 4746
333b20bb
GM
4747 {
4748 XSetWindowAttributes attrs;
4749 unsigned long mask;
36acb2a7 4750 Atom type = FRAME_X_DISPLAY_INFO (f)->Xatom_net_window_type_tooltip;
177c0ea7 4751
333b20bb 4752 BLOCK_INPUT;
c51d2b5e
GM
4753 mask = CWBackPixel | CWOverrideRedirect | CWEventMask;
4754 if (DoesSaveUnders (dpyinfo->screen))
4755 mask |= CWSaveUnder;
177c0ea7 4756
9b2956e2
GM
4757 /* Window managers look at the override-redirect flag to determine
4758 whether or net to give windows a decoration (Xlib spec, chapter
333b20bb
GM
4759 3.2.8). */
4760 attrs.override_redirect = True;
4761 attrs.save_under = True;
4762 attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
4763 /* Arrange for getting MapNotify and UnmapNotify events. */
4764 attrs.event_mask = StructureNotifyMask;
4765 tip_window
4766 = FRAME_X_WINDOW (f)
4767 = XCreateWindow (FRAME_X_DISPLAY (f),
4768 FRAME_X_DISPLAY_INFO (f)->root_window,
4769 /* x, y, width, height */
4770 0, 0, 1, 1,
4771 /* Border. */
a979dde1 4772 f->border_width,
333b20bb
GM
4773 CopyFromParent, InputOutput, CopyFromParent,
4774 mask, &attrs);
36acb2a7
JD
4775 XChangeProperty (FRAME_X_DISPLAY (f), tip_window,
4776 FRAME_X_DISPLAY_INFO (f)->Xatom_net_window_type,
4777 XA_ATOM, 32, PropModeReplace,
4778 (unsigned char *)&type, 1);
333b20bb
GM
4779 UNBLOCK_INPUT;
4780 }
4781
4782 x_make_gc (f);
4783
333b20bb
GM
4784 x_default_parameter (f, parms, Qauto_raise, Qnil,
4785 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4786 x_default_parameter (f, parms, Qauto_lower, Qnil,
4787 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4788 x_default_parameter (f, parms, Qcursor_type, Qbox,
4789 "cursorType", "CursorType", RES_TYPE_SYMBOL);
4790
be786000 4791 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
333b20bb 4792 Change will not be effected unless different from the current
be786000
KS
4793 FRAME_LINES (f). */
4794 width = FRAME_COLS (f);
4795 height = FRAME_LINES (f);
4796 SET_FRAME_COLS (f, 0);
4797 FRAME_LINES (f) = 0;
8938a4fb 4798 change_frame_size (f, height, width, 1, 0, 0);
177c0ea7 4799
cd1d850f 4800 /* Add `tooltip' frame parameter's default value. */
54ee7410
CY
4801 if (NILP (Fframe_parameter (frame, Qtooltip)))
4802 Fmodify_frame_parameters (frame, Fcons (Fcons (Qtooltip, Qt), Qnil));
177c0ea7 4803
cedb4d8b
GM
4804 /* FIXME - can this be done in a similar way to normal frames?
4805 http://lists.gnu.org/archive/html/emacs-devel/2007-10/msg00641.html */
4806
35fdaa62
GM
4807 /* Set the `display-type' frame parameter before setting up faces. */
4808 {
4809 Lisp_Object disptype;
4810
4811 if (FRAME_X_DISPLAY_INFO (f)->n_planes == 1)
4812 disptype = intern ("mono");
219ccf1b
RS
4813 else if (FRAME_X_DISPLAY_INFO (f)->visual->class == GrayScale
4814 || FRAME_X_DISPLAY_INFO (f)->visual->class == StaticGray)
35fdaa62
GM
4815 disptype = intern ("grayscale");
4816 else
4817 disptype = intern ("color");
4818
4819 if (NILP (Fframe_parameter (frame, Qdisplay_type)))
4820 Fmodify_frame_parameters (frame, Fcons (Fcons (Qdisplay_type, disptype),
4821 Qnil));
4822 }
4823
035d5114 4824 /* Set up faces after all frame parameters are known. This call
6801a572
GM
4825 also merges in face attributes specified for new frames.
4826
4827 Frame parameters may be changed if .Xdefaults contains
4828 specifications for the default font. For example, if there is an
4829 `Emacs.default.attributeBackground: pink', the `background-color'
4830 attribute of the frame get's set, which let's the internal border
4831 of the tooltip frame appear in pink. Prevent this. */
4832 {
4833 Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
4834
4835 /* Set tip_frame here, so that */
4836 tip_frame = frame;
45cebfd9 4837 call2 (Qface_set_after_frame_default, frame, Qnil);
177c0ea7 4838
6801a572
GM
4839 if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
4840 Fmodify_frame_parameters (frame, Fcons (Fcons (Qbackground_color, bg),
4841 Qnil));
4842 }
177c0ea7 4843
333b20bb
GM
4844 f->no_split = 1;
4845
4846 UNGCPRO;
4847
c9e7db78
JD
4848 /* Now that the frame will be official, it counts as a reference to
4849 its display and terminal. */
4850 FRAME_X_DISPLAY_INFO (f)->reference_count++;
4851 f->terminal->reference_count++;
4852
333b20bb
GM
4853 /* It is now ok to make the frame official even if we get an error
4854 below. And the frame needs to be on Vframe_list or making it
4855 visible won't work. */
4856 Vframe_list = Fcons (frame, Vframe_list);
4857
333b20bb 4858
06d62053
GM
4859 /* Setting attributes of faces of the tooltip frame from resources
4860 and similar will increment face_change_count, which leads to the
4861 clearing of all current matrices. Since this isn't necessary
4862 here, avoid it by resetting face_change_count to the value it
4863 had before we created the tip frame. */
4864 face_change_count = face_change_count_before;
4865
eaf1eea9 4866 /* Discard the unwind_protect. */
333b20bb
GM
4867 return unbind_to (count, frame);
4868}
4869
4870
06d62053
GM
4871/* Compute where to display tip frame F. PARMS is the list of frame
4872 parameters for F. DX and DY are specified offsets from the current
ab452f99
GM
4873 location of the mouse. WIDTH and HEIGHT are the width and height
4874 of the tooltip. Return coordinates relative to the root window of
4875 the display in *ROOT_X, and *ROOT_Y. */
06d62053
GM
4876
4877static void
971de7fb 4878compute_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
4879{
4880 Lisp_Object left, top;
4881 int win_x, win_y;
4882 Window root, child;
4883 unsigned pmask;
177c0ea7 4884
06d62053
GM
4885 /* User-specified position? */
4886 left = Fcdr (Fassq (Qleft, parms));
4887 top = Fcdr (Fassq (Qtop, parms));
177c0ea7 4888
06d62053
GM
4889 /* Move the tooltip window where the mouse pointer is. Resize and
4890 show it. */
570d22b0 4891 if (!INTEGERP (left) || !INTEGERP (top))
ab452f99
GM
4892 {
4893 BLOCK_INPUT;
4894 XQueryPointer (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
4895 &root, &child, root_x, root_y, &win_x, &win_y, &pmask);
4896 UNBLOCK_INPUT;
4897 }
06d62053 4898
06d62053
GM
4899 if (INTEGERP (top))
4900 *root_y = XINT (top);
bf63eb69
JD
4901 else if (*root_y + XINT (dy) <= 0)
4902 *root_y = 0; /* Can happen for negative dy */
abe9d29c
CY
4903 else if (*root_y + XINT (dy) + height
4904 <= x_display_pixel_height (FRAME_X_DISPLAY_INFO (f)))
7e8410d1 4905 /* It fits below the pointer */
abe9d29c 4906 *root_y += XINT (dy);
7e8410d1
JD
4907 else if (height + XINT (dy) <= *root_y)
4908 /* It fits above the pointer. */
4909 *root_y -= height + XINT (dy);
4910 else
4911 /* Put it on the top. */
4912 *root_y = 0;
ab452f99
GM
4913
4914 if (INTEGERP (left))
4915 *root_x = XINT (left);
bf63eb69
JD
4916 else if (*root_x + XINT (dx) <= 0)
4917 *root_x = 0; /* Can happen for negative dx */
abe9d29c
CY
4918 else if (*root_x + XINT (dx) + width
4919 <= x_display_pixel_width (FRAME_X_DISPLAY_INFO (f)))
d682d3df
RS
4920 /* It fits to the right of the pointer. */
4921 *root_x += XINT (dx);
4922 else if (width + XINT (dx) <= *root_x)
4923 /* It fits to the left of the pointer. */
ab452f99
GM
4924 *root_x -= width + XINT (dx);
4925 else
d682d3df
RS
4926 /* Put it left-justified on the screen--it ought to fit that way. */
4927 *root_x = 0;
06d62053
GM
4928}
4929
4930
0634ce98 4931DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
7ee72033 4932 doc: /* Show STRING in a "tooltip" window on frame FRAME.
c061c855
GM
4933A tooltip window is a small X window displaying a string.
4934
87c891c7
EZ
4935This is an internal function; Lisp code should call `tooltip-show'.
4936
c061c855
GM
4937FRAME nil or omitted means use the selected frame.
4938
4939PARMS is an optional list of frame parameters which can be used to
4940change the tooltip's appearance.
4941
4942Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
4943means use the default timeout of 5 seconds.
4944
c869cc37 4945If the list of frame parameters PARMS contains a `left' parameters,
c061c855
GM
4946the tooltip is displayed at that x-position. Otherwise it is
4947displayed at the mouse position, with offset DX added (default is 5 if
4948DX isn't specified). Likewise for the y-position; if a `top' frame
4949parameter is specified, it determines the y-position of the tooltip
4950window, otherwise it is displayed at the mouse position, with offset
4951DY added (default is -10).
4952
4953A tooltip's maximum size is specified by `x-max-tooltip-size'.
7ee72033 4954Text larger than the specified size is clipped. */)
5842a27b 4955 (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy)
333b20bb
GM
4956{
4957 struct frame *f;
4958 struct window *w;
06d62053 4959 int root_x, root_y;
333b20bb
GM
4960 struct buffer *old_buffer;
4961 struct text_pos pos;
a971c0a7 4962 int i, width, height, seen_reversed_p;
393f2d14 4963 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
333b20bb 4964 int old_windows_or_buffers_changed = windows_or_buffers_changed;
d311d28c 4965 ptrdiff_t count = SPECPDL_INDEX ();
177c0ea7 4966
333b20bb
GM
4967 specbind (Qinhibit_redisplay, Qt);
4968
393f2d14 4969 GCPRO4 (string, parms, frame, timeout);
333b20bb 4970
b7826503 4971 CHECK_STRING (string);
2d7117fe
JD
4972 if (SCHARS (string) == 0)
4973 string = make_unibyte_string (" ", 1);
4974
333b20bb
GM
4975 f = check_x_frame (frame);
4976 if (NILP (timeout))
4977 timeout = make_number (5);
4978 else
b7826503 4979 CHECK_NATNUM (timeout);
177c0ea7 4980
0634ce98
GM
4981 if (NILP (dx))
4982 dx = make_number (5);
4983 else
b7826503 4984 CHECK_NUMBER (dx);
177c0ea7 4985
0634ce98 4986 if (NILP (dy))
12c67a7f 4987 dy = make_number (-10);
0634ce98 4988 else
b7826503 4989 CHECK_NUMBER (dy);
333b20bb 4990
aa1859f5
J
4991#ifdef USE_GTK
4992 if (x_gtk_use_system_tooltips)
4993 {
717c30e0 4994 int ok;
aa1859f5
J
4995
4996 /* Hide a previous tip, if any. */
4997 Fx_hide_tip ();
4998
4999 BLOCK_INPUT;
5000 if ((ok = xg_prepare_tooltip (f, string, &width, &height)) != 0)
5001 {
5002 compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
5003 xg_show_tooltip (f, root_x, root_y);
5004 /* This is used in Fx_hide_tip. */
5005 XSETFRAME (tip_frame, f);
5006 }
5007 UNBLOCK_INPUT;
5008 if (ok) goto start_timer;
5009 }
5010#endif /* USE_GTK */
5011
06d62053
GM
5012 if (NILP (last_show_tip_args))
5013 last_show_tip_args = Fmake_vector (make_number (3), Qnil);
5014
5015 if (!NILP (tip_frame))
5016 {
5017 Lisp_Object last_string = AREF (last_show_tip_args, 0);
5018 Lisp_Object last_frame = AREF (last_show_tip_args, 1);
5019 Lisp_Object last_parms = AREF (last_show_tip_args, 2);
5020
5021 if (EQ (frame, last_frame)
5022 && !NILP (Fequal (last_string, string))
5023 && !NILP (Fequal (last_parms, parms)))
5024 {
58d2d479 5025 struct frame *tip_f = XFRAME (tip_frame);
177c0ea7 5026
06d62053
GM
5027 /* Only DX and DY have changed. */
5028 if (!NILP (tip_timer))
ae782866
GM
5029 {
5030 Lisp_Object timer = tip_timer;
5031 tip_timer = Qnil;
5032 call1 (Qcancel_timer, timer);
5033 }
06d62053
GM
5034
5035 BLOCK_INPUT;
58d2d479
PE
5036 compute_tip_xy (tip_f, parms, dx, dy, FRAME_PIXEL_WIDTH (tip_f),
5037 FRAME_PIXEL_HEIGHT (tip_f), &root_x, &root_y);
5038 XMoveWindow (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f),
ab452f99 5039 root_x, root_y);
06d62053
GM
5040 UNBLOCK_INPUT;
5041 goto start_timer;
5042 }
5043 }
5044
333b20bb
GM
5045 /* Hide a previous tip, if any. */
5046 Fx_hide_tip ();
5047
06d62053
GM
5048 ASET (last_show_tip_args, 0, string);
5049 ASET (last_show_tip_args, 1, frame);
5050 ASET (last_show_tip_args, 2, parms);
5051
333b20bb
GM
5052 /* Add default values to frame parameters. */
5053 if (NILP (Fassq (Qname, parms)))
5054 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
5055 if (NILP (Fassq (Qinternal_border_width, parms)))
5056 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
5057 if (NILP (Fassq (Qborder_width, parms)))
5058 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
5059 if (NILP (Fassq (Qborder_color, parms)))
5060 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
5061 if (NILP (Fassq (Qbackground_color, parms)))
5062 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
5063 parms);
5064
5065 /* Create a frame for the tooltip, and record it in the global
5066 variable tip_frame. */
275841bf 5067 frame = x_create_tip_frame (FRAME_X_DISPLAY_INFO (f), parms, string);
44b5a125 5068 f = XFRAME (frame);
333b20bb 5069
d63931a2 5070 /* Set up the frame's root window. */
333b20bb 5071 w = XWINDOW (FRAME_ROOT_WINDOW (f));
077288cf
DA
5072 WSET (w, left_col, make_number (0));
5073 WSET (w, top_line, make_number (0));
177c0ea7 5074
d63931a2 5075 if (CONSP (Vx_max_tooltip_size)
d311d28c
PE
5076 && RANGED_INTEGERP (1, XCAR (Vx_max_tooltip_size), INT_MAX)
5077 && RANGED_INTEGERP (1, XCDR (Vx_max_tooltip_size), INT_MAX))
d63931a2 5078 {
077288cf
DA
5079 WSET (w, total_cols, XCAR (Vx_max_tooltip_size));
5080 WSET (w, total_lines, XCDR (Vx_max_tooltip_size));
d63931a2
GM
5081 }
5082 else
5083 {
077288cf
DA
5084 WSET (w, total_cols, make_number (80));
5085 WSET (w, total_lines, make_number (40));
d63931a2 5086 }
177c0ea7 5087
077288cf 5088 FRAME_TOTAL_COLS (f) = XINT (WGET (w, total_cols));
333b20bb
GM
5089 adjust_glyphs (f);
5090 w->pseudo_window_p = 1;
5091
5092 /* Display the tooltip text in a temporary buffer. */
333b20bb 5093 old_buffer = current_buffer;
077288cf 5094 set_buffer_internal_1 (XBUFFER (WGET (XWINDOW (FRAME_ROOT_WINDOW (f)), buffer)));
4b4deea2 5095 BVAR (current_buffer, truncate_lines) = Qnil;
5634ff85
YM
5096 clear_glyph_matrix (w->desired_matrix);
5097 clear_glyph_matrix (w->current_matrix);
5098 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
6eff5c3d 5099 try_window (FRAME_ROOT_WINDOW (f), pos, TRY_WINDOW_IGNORE_FONTS_CHANGE);
333b20bb
GM
5100
5101 /* Compute width and height of the tooltip. */
a971c0a7 5102 width = height = seen_reversed_p = 0;
333b20bb
GM
5103 for (i = 0; i < w->desired_matrix->nrows; ++i)
5104 {
5105 struct glyph_row *row = &w->desired_matrix->rows[i];
5106 struct glyph *last;
5107 int row_width;
5108
5109 /* Stop at the first empty row at the end. */
5110 if (!row->enabled_p || !row->displays_text_p)
5111 break;
5112
d7bf0342
GM
5113 /* Let the row go over the full width of the frame. */
5114 row->full_width_p = 1;
333b20bb 5115
5b253e9c 5116 row_width = row->pixel_width;
333b20bb
GM
5117 if (row->used[TEXT_AREA])
5118 {
a971c0a7
EZ
5119 /* There's a glyph at the end of rows that is used to place
5120 the cursor there. Don't include the width of this glyph. */
5121 if (!row->reversed_p)
5122 {
5123 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
5124 if (INTEGERP (last->object))
5125 row_width -= last->pixel_width;
5126 }
5127 else
5128 {
5129 /* There could be a stretch glyph at the beginning of R2L
5130 rows that is produced by extend_face_to_end_of_line.
5131 Don't count that glyph. */
5132 struct glyph *g = row->glyphs[TEXT_AREA];
5133
5134 if (g->type == STRETCH_GLYPH && INTEGERP (g->object))
5135 {
5136 row_width -= g->pixel_width;
5137 seen_reversed_p = 1;
5138 }
5139 }
333b20bb 5140 }
177c0ea7 5141
333b20bb
GM
5142 height += row->height;
5143 width = max (width, row_width);
5144 }
5145
a971c0a7
EZ
5146 /* If we've seen partial-length R2L rows, we need to re-adjust the
5147 tool-tip frame width and redisplay it again, to avoid over-wide
5148 tips due to the stretch glyph that extends R2L lines to full
5149 width of the frame. */
5150 if (seen_reversed_p)
5151 {
5152 /* w->total_cols and FRAME_TOTAL_COLS want the width in columns,
5153 not in pixels. */
5154 width /= WINDOW_FRAME_COLUMN_WIDTH (w);
077288cf 5155 WSET (w, total_cols, make_number (width));
a971c0a7
EZ
5156 FRAME_TOTAL_COLS (f) = width;
5157 adjust_glyphs (f);
5158 clear_glyph_matrix (w->desired_matrix);
5159 clear_glyph_matrix (w->current_matrix);
5160 try_window (FRAME_ROOT_WINDOW (f), pos, 0);
5161 width = height = 0;
5162 /* Recompute width and height of the tooltip. */
5163 for (i = 0; i < w->desired_matrix->nrows; ++i)
5164 {
5165 struct glyph_row *row = &w->desired_matrix->rows[i];
5166 struct glyph *last;
5167 int row_width;
5168
5169 if (!row->enabled_p || !row->displays_text_p)
5170 break;
5171 row->full_width_p = 1;
5172 row_width = row->pixel_width;
5173 if (row->used[TEXT_AREA] && !row->reversed_p)
5174 {
5175 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
5176 if (INTEGERP (last->object))
5177 row_width -= last->pixel_width;
5178 }
5179
5180 height += row->height;
5181 width = max (width, row_width);
5182 }
5183 }
5184
333b20bb
GM
5185 /* Add the frame's internal border to the width and height the X
5186 window should have. */
5187 height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
5188 width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
5189
5190 /* Move the tooltip window where the mouse pointer is. Resize and
5191 show it. */
ab452f99 5192 compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
0634ce98 5193
0634ce98 5194 BLOCK_INPUT;
333b20bb 5195 XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
ab452f99 5196 root_x, root_y, width, height);
333b20bb
GM
5197 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5198 UNBLOCK_INPUT;
177c0ea7 5199
333b20bb
GM
5200 /* Draw into the window. */
5201 w->must_be_updated_p = 1;
5202 update_single_window (w, 1);
5203
5204 /* Restore original current buffer. */
5205 set_buffer_internal_1 (old_buffer);
5206 windows_or_buffers_changed = old_windows_or_buffers_changed;
5207
06d62053 5208 start_timer:
333b20bb
GM
5209 /* Let the tip disappear after timeout seconds. */
5210 tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
5211 intern ("x-hide-tip"));
a744a2ec
DL
5212
5213 UNGCPRO;
333b20bb
GM
5214 return unbind_to (count, Qnil);
5215}
5216
5217
a7ca3326 5218DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
7ee72033
MB
5219 doc: /* Hide the current tooltip window, if there is any.
5220Value is t if tooltip was open, nil otherwise. */)
5842a27b 5221 (void)
333b20bb 5222{
d311d28c 5223 ptrdiff_t count;
c0006262
GM
5224 Lisp_Object deleted, frame, timer;
5225 struct gcpro gcpro1, gcpro2;
44b5a125
GM
5226
5227 /* Return quickly if nothing to do. */
c0006262 5228 if (NILP (tip_timer) && NILP (tip_frame))
44b5a125 5229 return Qnil;
177c0ea7 5230
c0006262
GM
5231 frame = tip_frame;
5232 timer = tip_timer;
5233 GCPRO2 (frame, timer);
5234 tip_frame = tip_timer = deleted = Qnil;
177c0ea7 5235
331379bf 5236 count = SPECPDL_INDEX ();
333b20bb 5237 specbind (Qinhibit_redisplay, Qt);
44b5a125 5238 specbind (Qinhibit_quit, Qt);
177c0ea7 5239
c0006262 5240 if (!NILP (timer))
ae782866 5241 call1 (Qcancel_timer, timer);
333b20bb 5242
aa1859f5 5243#ifdef USE_GTK
1fe72bf8
PE
5244 {
5245 /* When using system tooltip, tip_frame is the Emacs frame on which
5246 the tip is shown. */
5247 struct frame *f = XFRAME (frame);
5248 if (FRAME_LIVE_P (f) && xg_hide_tooltip (f))
5249 frame = Qnil;
5250 }
aa1859f5
J
5251#endif
5252
c0006262 5253 if (FRAMEP (frame))
333b20bb 5254 {
56f2de10 5255 delete_frame (frame, Qnil);
44b5a125 5256 deleted = Qt;
f6c44811
GM
5257
5258#ifdef USE_LUCID
5259 /* Bloodcurdling hack alert: The Lucid menu bar widget's
5260 redisplay procedure is not called when a tip frame over menu
5261 items is unmapped. Redisplay the menu manually... */
5262 {
aa1859f5 5263 Widget w;
1fe72bf8 5264 struct frame *f = SELECTED_FRAME ();
aa1859f5 5265 w = f->output_data.x->menubar_widget;
9180dc8c 5266
f6c44811 5267 if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f)->screen)
dbc64aa7 5268 && w != NULL)
f6c44811
GM
5269 {
5270 BLOCK_INPUT;
5271 xlwmenu_redisplay (w);
5272 UNBLOCK_INPUT;
5273 }
5274 }
5275#endif /* USE_LUCID */
333b20bb
GM
5276 }
5277
c0006262 5278 UNGCPRO;
44b5a125 5279 return unbind_to (count, deleted);
333b20bb
GM
5280}
5281
5282
5283\f
5284/***********************************************************************
5285 File selection dialog
5286 ***********************************************************************/
5287
90f2e16b
JD
5288DEFUN ("x-uses-old-gtk-dialog", Fx_uses_old_gtk_dialog,
5289 Sx_uses_old_gtk_dialog,
5290 0, 0, 0,
5291 doc: /* Return t if the old Gtk+ file selection dialog is used. */)
5842a27b 5292 (void)
90f2e16b
JD
5293{
5294#ifdef USE_GTK
90f2e16b
JD
5295 if (use_dialog_box
5296 && use_file_dialog
5297 && have_menus_p ()
5298 && xg_uses_old_file_dialog ())
5299 return Qt;
5300#endif
5301 return Qnil;
5302}
5303
333b20bb 5304
90f2e16b 5305#ifdef USE_MOTIF
333b20bb
GM
5306/* Callback for "OK" and "Cancel" on file selection dialog. */
5307
5308static void
dee186b6 5309file_dialog_cb (Widget widget, XtPointer client_data, XtPointer call_data)
333b20bb
GM
5310{
5311 int *result = (int *) client_data;
5312 XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data;
5313 *result = cb->reason;
5314}
5315
5316
a779d213
GM
5317/* Callback for unmapping a file selection dialog. This is used to
5318 capture the case where a dialog is closed via a window manager's
5319 closer button, for example. Using a XmNdestroyCallback didn't work
5320 in this case. */
5321
5322static void
dee186b6 5323file_dialog_unmap_cb (Widget widget, XtPointer client_data, XtPointer call_data)
a779d213
GM
5324{
5325 int *result = (int *) client_data;
5326 *result = XmCR_CANCEL;
5327}
5328
24ca7c5a 5329static Lisp_Object
dee186b6 5330clean_up_file_dialog (Lisp_Object arg)
24ca7c5a
JD
5331{
5332 struct Lisp_Save_Value *p = XSAVE_VALUE (arg);
5333 Widget dialog = (Widget) p->pointer;
5334
5335 /* Clean up. */
5336 BLOCK_INPUT;
5337 XtUnmanageChild (dialog);
5338 XtDestroyWidget (dialog);
5339 x_menu_set_in_use (0);
5340 UNBLOCK_INPUT;
5341
5342 return Qnil;
5343}
5344
a779d213 5345
f9d64bb3 5346DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
7ee72033 5347 doc: /* Read file name, prompting with PROMPT in directory DIR.
f9d64bb3
JD
5348Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file
5349selection box, if specified. If MUSTMATCH is non-nil, the returned file
7c051dd8
GM
5350or directory must exist.
5351
5352This function is only defined on MS Windows, and X Windows with the
5353Motif or Gtk toolkits. With the Motif toolkit, ONLY-DIR-P is ignored.
5354Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */)
5842a27b 5355 (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename, Lisp_Object mustmatch, Lisp_Object only_dir_p)
333b20bb
GM
5356{
5357 int result;
0fe92f72 5358 struct frame *f = SELECTED_FRAME ();
333b20bb 5359 Lisp_Object file = Qnil;
a8f4bdc6 5360 Lisp_Object decoded_file;
f9d64bb3 5361 Widget dialog, text, help;
333b20bb
GM
5362 Arg al[10];
5363 int ac = 0;
333b20bb 5364 XmString dir_xmstring, pattern_xmstring;
d311d28c 5365 ptrdiff_t count = SPECPDL_INDEX ();
f9d64bb3 5366 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
333b20bb 5367
6eeee4d6
YM
5368 check_x ();
5369
f9d64bb3 5370 GCPRO6 (prompt, dir, default_filename, mustmatch, only_dir_p, file);
24ca7c5a 5371
5ae53dcf 5372 if (popup_activated ())
24ca7c5a
JD
5373 error ("Trying to use a menu from within a menu-entry");
5374
b7826503
PJ
5375 CHECK_STRING (prompt);
5376 CHECK_STRING (dir);
333b20bb
GM
5377
5378 /* Prevent redisplay. */
5379 specbind (Qinhibit_redisplay, Qt);
5380
5381 BLOCK_INPUT;
5382
5383 /* Create the dialog with PROMPT as title, using DIR as initial
5384 directory and using "*" as pattern. */
5385 dir = Fexpand_file_name (dir, Qnil);
c09bfb2f 5386 dir_xmstring = XmStringCreateLocalized (SSDATA (dir));
333b20bb 5387 pattern_xmstring = XmStringCreateLocalized ("*");
177c0ea7 5388
d5db4077 5389 XtSetArg (al[ac], XmNtitle, SDATA (prompt)); ++ac;
333b20bb
GM
5390 XtSetArg (al[ac], XmNdirectory, dir_xmstring); ++ac;
5391 XtSetArg (al[ac], XmNpattern, pattern_xmstring); ++ac;
5392 XtSetArg (al[ac], XmNresizePolicy, XmRESIZE_GROW); ++ac;
5393 XtSetArg (al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ++ac;
5394 dialog = XmCreateFileSelectionDialog (f->output_data.x->widget,
5395 "fsb", al, ac);
5396 XmStringFree (dir_xmstring);
5397 XmStringFree (pattern_xmstring);
5398
5399 /* Add callbacks for OK and Cancel. */
5400 XtAddCallback (dialog, XmNokCallback, file_dialog_cb,
5401 (XtPointer) &result);
5402 XtAddCallback (dialog, XmNcancelCallback, file_dialog_cb,
5403 (XtPointer) &result);
a779d213
GM
5404 XtAddCallback (dialog, XmNunmapCallback, file_dialog_unmap_cb,
5405 (XtPointer) &result);
333b20bb 5406
f9d64bb3 5407 /* Remove the help button since we can't display help. */
333b20bb 5408 help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON);
f9d64bb3 5409 XtUnmanageChild (help);
333b20bb 5410
177c0ea7 5411 /* Mark OK button as default. */
333b20bb
GM
5412 XtVaSetValues (XmFileSelectionBoxGetChild (dialog, XmDIALOG_OK_BUTTON),
5413 XmNshowAsDefault, True, NULL);
5414
5415 /* If MUSTMATCH is non-nil, disable the file entry field of the
5416 dialog, so that the user must select a file from the files list
5417 box. We can't remove it because we wouldn't have a way to get at
5418 the result file name, then. */
5419 text = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
5420 if (!NILP (mustmatch))
5421 {
5422 Widget label;
5423 label = XmFileSelectionBoxGetChild (dialog, XmDIALOG_SELECTION_LABEL);
5424 XtSetSensitive (text, False);
5425 XtSetSensitive (label, False);
5426 }
5427
5428 /* Manage the dialog, so that list boxes get filled. */
5429 XtManageChild (dialog);
5430
333b20bb
GM
5431 if (STRINGP (default_filename))
5432 {
5433 XmString default_xmstring;
f9d64bb3
JD
5434 Widget wtext = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
5435 Widget list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
333b20bb 5436
f9d64bb3
JD
5437 XmTextPosition last_pos = XmTextFieldGetLastPosition (wtext);
5438 XmTextFieldReplace (wtext, 0, last_pos,
c09bfb2f 5439 (SSDATA (Ffile_name_nondirectory (default_filename))));
333b20bb 5440
f9d64bb3
JD
5441 /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
5442 must include the path for this to work. */
5443
c09bfb2f 5444 default_xmstring = XmStringCreateLocalized (SSDATA (default_filename));
333b20bb 5445
f9d64bb3
JD
5446 if (XmListItemExists (list, default_xmstring))
5447 {
5448 int item_pos = XmListItemPos (list, default_xmstring);
5449 /* Select the item and scroll it into view. */
5450 XmListSelectPos (list, item_pos, True);
5451 XmListSetPos (list, item_pos);
5452 }
5453
5454 XmStringFree (default_xmstring);
333b20bb
GM
5455 }
5456
24ca7c5a
JD
5457 record_unwind_protect (clean_up_file_dialog, make_save_value (dialog, 0));
5458
bf338245 5459 /* Process events until the user presses Cancel or OK. */
5ae53dcf 5460 x_menu_set_in_use (1);
03100098 5461 result = 0;
a779d213 5462 while (result == 0)
563b384d 5463 {
bf338245 5464 XEvent event;
24ca7c5a 5465 x_menu_wait_for_event (0);
bf338245 5466 XtAppNextEvent (Xt_app_con, &event);
9f6fcdc5
JD
5467 if (event.type == KeyPress
5468 && FRAME_X_DISPLAY (f) == event.xkey.display)
5469 {
5470 KeySym keysym = XLookupKeysym (&event.xkey, 0);
5471
5472 /* Pop down on C-g. */
5473 if (keysym == XK_g && (event.xkey.state & ControlMask) != 0)
5474 XtUnmanageChild (dialog);
5475 }
5b3f8550 5476
24ca7c5a 5477 (void) x_dispatch_event (&event, FRAME_X_DISPLAY (f));
563b384d 5478 }
03100098 5479
333b20bb
GM
5480 /* Get the result. */
5481 if (result == XmCR_OK)
5482 {
91a3e27b 5483 XmString text_string;
333b20bb 5484 String data;
177c0ea7 5485
91a3e27b
PE
5486 XtVaGetValues (dialog, XmNtextString, &text_string, NULL);
5487 XmStringGetLtoR (text_string, XmFONTLIST_DEFAULT_TAG, &data);
5488 XmStringFree (text_string);
333b20bb
GM
5489 file = build_string (data);
5490 XtFree (data);
5491 }
5492 else
5493 file = Qnil;
5494
333b20bb
GM
5495 UNBLOCK_INPUT;
5496 UNGCPRO;
5497
5498 /* Make "Cancel" equivalent to C-g. */
5499 if (NILP (file))
5500 Fsignal (Qquit, Qnil);
177c0ea7 5501
a8f4bdc6
JD
5502 decoded_file = DECODE_FILE (file);
5503
5504 return unbind_to (count, decoded_file);
333b20bb
GM
5505}
5506
5507#endif /* USE_MOTIF */
5508
488dd4c4
JD
5509#ifdef USE_GTK
5510
24ca7c5a 5511static Lisp_Object
971de7fb 5512clean_up_dialog (Lisp_Object arg)
24ca7c5a
JD
5513{
5514 x_menu_set_in_use (0);
5515
5516 return Qnil;
5517}
5518
f9d64bb3
JD
5519DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
5520 doc: /* Read file name, prompting with PROMPT in directory DIR.
5521Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file
5522selection box, if specified. If MUSTMATCH is non-nil, the returned file
7c051dd8
GM
5523or directory must exist.
5524
5525This function is only defined on MS Windows, and X Windows with the
5526Motif or Gtk toolkits. With the Motif toolkit, ONLY-DIR-P is ignored.
5527Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */)
5842a27b 5528 (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename, Lisp_Object mustmatch, Lisp_Object only_dir_p)
488dd4c4
JD
5529{
5530 FRAME_PTR f = SELECTED_FRAME ();
5531 char *fn;
5532 Lisp_Object file = Qnil;
a8f4bdc6 5533 Lisp_Object decoded_file;
d311d28c 5534 ptrdiff_t count = SPECPDL_INDEX ();
f9d64bb3 5535 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
488dd4c4 5536 char *cdef_file;
177c0ea7 5537
6eeee4d6
YM
5538 check_x ();
5539
f9d64bb3 5540 GCPRO6 (prompt, dir, default_filename, mustmatch, only_dir_p, file);
24ca7c5a 5541
5ae53dcf 5542 if (popup_activated ())
24ca7c5a
JD
5543 error ("Trying to use a menu from within a menu-entry");
5544
488dd4c4
JD
5545 CHECK_STRING (prompt);
5546 CHECK_STRING (dir);
5547
5548 /* Prevent redisplay. */
5549 specbind (Qinhibit_redisplay, Qt);
24ca7c5a 5550 record_unwind_protect (clean_up_dialog, Qnil);
488dd4c4
JD
5551
5552 BLOCK_INPUT;
5553
5554 if (STRINGP (default_filename))
c0951e53 5555 cdef_file = SSDATA (default_filename);
488dd4c4 5556 else
c0951e53 5557 cdef_file = SSDATA (dir);
488dd4c4 5558
c0951e53 5559 fn = xg_get_file_name (f, SSDATA (prompt), cdef_file,
f9d64bb3
JD
5560 ! NILP (mustmatch),
5561 ! NILP (only_dir_p));
177c0ea7 5562
488dd4c4
JD
5563 if (fn)
5564 {
5565 file = build_string (fn);
5566 xfree (fn);
5567 }
5568
5569 UNBLOCK_INPUT;
5570 UNGCPRO;
5571
5572 /* Make "Cancel" equivalent to C-g. */
5573 if (NILP (file))
5574 Fsignal (Qquit, Qnil);
177c0ea7 5575
a8f4bdc6
JD
5576 decoded_file = DECODE_FILE (file);
5577
5578 return unbind_to (count, decoded_file);
488dd4c4
JD
5579}
5580
9bf80974
CY
5581
5582#ifdef HAVE_FREETYPE
5583
f82605c6
CY
5584DEFUN ("x-select-font", Fx_select_font, Sx_select_font, 0, 2, 0,
5585 doc: /* Read a font name using a GTK font selection dialog.
5586Return a GTK-style font string corresponding to the selection.
5587
5588If FRAME is omitted or nil, it defaults to the selected frame. */)
5842a27b 5589 (Lisp_Object frame, Lisp_Object ignored)
9bf80974 5590{
f82605c6 5591 FRAME_PTR f = check_x_frame (frame);
53c7540d 5592 char *name;
637fa988 5593 Lisp_Object font;
e0ab5fcf
JD
5594 Lisp_Object font_param;
5595 char *default_name = NULL;
637fa988 5596 struct gcpro gcpro1, gcpro2;
d311d28c 5597 ptrdiff_t count = SPECPDL_INDEX ();
9bf80974
CY
5598
5599 check_x ();
5600
5601 if (popup_activated ())
5602 error ("Trying to use a menu from within a menu-entry");
5603
5604 /* Prevent redisplay. */
5605 specbind (Qinhibit_redisplay, Qt);
5606 record_unwind_protect (clean_up_dialog, Qnil);
5607
5608 BLOCK_INPUT;
5609
5e617bc2 5610 GCPRO2 (font_param, font);
e0ab5fcf 5611
637fa988 5612 XSETFONT (font, FRAME_FONT (f));
581e51e8 5613 font_param = Ffont_get (font, intern (":name"));
637fa988 5614 if (STRINGP (font_param))
c0951e53 5615 default_name = xstrdup (SSDATA (font_param));
f5f6c0e0 5616 else
53c7540d 5617 {
637fa988
JD
5618 font_param = Fframe_parameter (frame, Qfont_param);
5619 if (STRINGP (font_param))
c0951e53 5620 default_name = xstrdup (SSDATA (font_param));
53c7540d 5621 }
e0ab5fcf 5622
637fa988 5623 if (default_name == NULL && x_last_font_name != NULL)
581e51e8
JD
5624 default_name = xstrdup (x_last_font_name);
5625
5626 /* Convert fontconfig names to Gtk names, i.e. remove - before number */
f5f6c0e0 5627 if (default_name)
581e51e8
JD
5628 {
5629 char *p = strrchr (default_name, '-');
5630 if (p)
5631 {
5632 char *ep = p+1;
5633 while (isdigit (*ep))
5634 ++ep;
5635 if (*ep == '\0') *p = ' ';
5636 }
5637 }
637fa988 5638
e0ab5fcf 5639 name = xg_get_font_name (f, default_name);
581e51e8 5640 xfree (default_name);
9bf80974 5641
53c7540d 5642 if (name)
9bf80974 5643 {
53c7540d 5644 font = build_string (name);
e0ab5fcf
JD
5645 g_free (x_last_font_name);
5646 x_last_font_name = name;
9bf80974
CY
5647 }
5648
5649 UNBLOCK_INPUT;
5650
5651 if (NILP (font))
5652 Fsignal (Qquit, Qnil);
5653
5654 return unbind_to (count, font);
5655}
5656#endif /* HAVE_FREETYPE */
5657
488dd4c4 5658#endif /* USE_GTK */
333b20bb
GM
5659
5660\f
82bab41c
GM
5661/***********************************************************************
5662 Keyboard
5663 ***********************************************************************/
5664
5665#ifdef HAVE_XKBGETKEYBOARD
5666#include <X11/XKBlib.h>
5667#include <X11/keysym.h>
5668#endif
5669
5670DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p,
5671 Sx_backspace_delete_keys_p, 0, 1, 0,
7ee72033 5672 doc: /* Check if both Backspace and Delete keys are on the keyboard of FRAME.
c061c855
GM
5673FRAME nil means use the selected frame.
5674Value is t if we know that both keys are present, and are mapped to the
20d1c5c5
DN
5675usual X keysyms. Value is `lambda' if we cannot determine if both keys are
5676present and mapped to the usual X keysyms. */)
5842a27b 5677 (Lisp_Object frame)
82bab41c
GM
5678{
5679#ifdef HAVE_XKBGETKEYBOARD
5680 XkbDescPtr kb;
5681 struct frame *f = check_x_frame (frame);
5682 Display *dpy = FRAME_X_DISPLAY (f);
5683 Lisp_Object have_keys;
58d2d479 5684 int major, minor, op, event, error_code;
82bab41c
GM
5685
5686 BLOCK_INPUT;
46f6a258
GM
5687
5688 /* Check library version in case we're dynamically linked. */
5689 major = XkbMajorVersion;
5690 minor = XkbMinorVersion;
5691 if (!XkbLibraryVersion (&major, &minor))
c1efd260
GM
5692 {
5693 UNBLOCK_INPUT;
20d1c5c5 5694 return Qlambda;
c1efd260 5695 }
46f6a258
GM
5696
5697 /* Check that the server supports XKB. */
5698 major = XkbMajorVersion;
5699 minor = XkbMinorVersion;
58d2d479 5700 if (!XkbQueryExtension (dpy, &op, &event, &error_code, &major, &minor))
c1efd260
GM
5701 {
5702 UNBLOCK_INPUT;
20d1c5c5 5703 return Qlambda;
c1efd260 5704 }
177c0ea7 5705
3a441526
JD
5706 /* In this code we check that the keyboard has physical keys with names
5707 that start with BKSP (Backspace) and DELE (Delete), and that they
5708 generate keysym XK_BackSpace and XK_Delete respectively.
5709 This function is used to test if normal-erase-is-backspace should be
5710 turned on.
5711 An alternative approach would be to just check if XK_BackSpace and
5712 XK_Delete are mapped to any key. But if any of those are mapped to
5713 some non-intuitive key combination (Meta-Shift-Ctrl-whatever) and the
5714 user doesn't know about it, it is better to return false here.
5715 It is more obvious to the user what to do if she/he has two keys
5716 clearly marked with names/symbols and one key does something not
5717 expected (i.e. she/he then tries the other).
5718 The cases where Backspace/Delete is mapped to some other key combination
5719 are rare, and in those cases, normal-erase-is-backspace can be turned on
5720 manually. */
5721
46f6a258 5722 have_keys = Qnil;
c1efd260 5723 kb = XkbGetMap (dpy, XkbAllMapComponentsMask, XkbUseCoreKbd);
82bab41c
GM
5724 if (kb)
5725 {
5726 int delete_keycode = 0, backspace_keycode = 0, i;
c1efd260
GM
5727
5728 if (XkbGetNames (dpy, XkbAllNamesMask, kb) == Success)
82bab41c 5729 {
c1efd260
GM
5730 for (i = kb->min_key_code;
5731 (i < kb->max_key_code
5732 && (delete_keycode == 0 || backspace_keycode == 0));
5733 ++i)
5734 {
d63931a2
GM
5735 /* The XKB symbolic key names can be seen most easily in
5736 the PS file generated by `xkbprint -label name
5737 $DISPLAY'. */
72af86bd 5738 if (memcmp ("DELE", kb->names->keys[i].name, 4) == 0)
c1efd260 5739 delete_keycode = i;
72af86bd 5740 else if (memcmp ("BKSP", kb->names->keys[i].name, 4) == 0)
c1efd260
GM
5741 backspace_keycode = i;
5742 }
5743
5744 XkbFreeNames (kb, 0, True);
82bab41c
GM
5745 }
5746
c1efd260 5747 XkbFreeClientMap (kb, 0, True);
177c0ea7 5748
82bab41c
GM
5749 if (delete_keycode
5750 && backspace_keycode
5751 && XKeysymToKeycode (dpy, XK_Delete) == delete_keycode
5752 && XKeysymToKeycode (dpy, XK_BackSpace) == backspace_keycode)
5753 have_keys = Qt;
5754 }
5755 UNBLOCK_INPUT;
5756 return have_keys;
5757#else /* not HAVE_XKBGETKEYBOARD */
20d1c5c5 5758 return Qlambda;
82bab41c
GM
5759#endif /* not HAVE_XKBGETKEYBOARD */
5760}
5761
5762
5763\f
333b20bb
GM
5764/***********************************************************************
5765 Initialization
5766 ***********************************************************************/
5767
4dacadcc 5768/* Keep this list in the same order as frame_parms in frame.c.
7c0d3ed8
KS
5769 Use 0 for unsupported frame parameters. */
5770
5771frame_parm_handler x_frame_parm_handlers[] =
5772{
5773 x_set_autoraise,
5774 x_set_autolower,
5775 x_set_background_color,
5776 x_set_border_color,
5777 x_set_border_width,
5778 x_set_cursor_color,
5779 x_set_cursor_type,
5780 x_set_font,
5781 x_set_foreground_color,
5782 x_set_icon_name,
5783 x_set_icon_type,
5784 x_set_internal_border_width,
5785 x_set_menu_bar_lines,
5786 x_set_mouse_color,
5787 x_explicitly_set_name,
5788 x_set_scroll_bar_width,
5789 x_set_title,
5790 x_set_unsplittable,
5791 x_set_vertical_scroll_bars,
5792 x_set_visibility,
5793 x_set_tool_bar_lines,
5794 x_set_scroll_bar_foreground,
5795 x_set_scroll_bar_background,
5796 x_set_screen_gamma,
5797 x_set_line_spacing,
5798 x_set_fringe_width,
5799 x_set_fringe_width,
5800 x_set_wait_for_wm,
5801 x_set_fullscreen,
271a71c7 5802 x_set_font_backend,
cad9ef74
JD
5803 x_set_alpha,
5804 x_set_sticky,
bfeabdc3 5805 x_set_tool_bar_position,
7c0d3ed8
KS
5806};
5807
333b20bb 5808void
971de7fb 5809syms_of_xfns (void)
333b20bb
GM
5810{
5811 /* This is zero if not using X windows. */
5812 x_in_use = 0;
5813
5814 /* The section below is built by the lisp expression at the top of the file,
5815 just above where these variables are declared. */
5816 /*&&& init symbols here &&&*/
cd3520a4
JB
5817 DEFSYM (Qnone, "none");
5818 DEFSYM (Qsuppress_icon, "suppress-icon");
5819 DEFSYM (Qundefined_color, "undefined-color");
5820 DEFSYM (Qcompound_text, "compound-text");
5821 DEFSYM (Qcancel_timer, "cancel-timer");
5822 DEFSYM (Qfont_param, "font-parameter");
f9942c9e
JB
5823 /* This is the end of symbol initialization. */
5824
01f1ba30 5825 Fput (Qundefined_color, Qerror_conditions,
3438fe21 5826 listn (CONSTYPE_PURE, 2, Qundefined_color, Qerror));
01f1ba30 5827 Fput (Qundefined_color, Qerror_message,
2a0213a6 5828 build_pure_c_string ("Undefined color"));
01f1ba30 5829
29208e82 5830 DEFVAR_LISP ("x-pointer-shape", Vx_pointer_shape,
7ee72033 5831 doc: /* The shape of the pointer when over text.
c061c855
GM
5832Changing the value does not affect existing frames
5833unless you set the mouse color. */);
01f1ba30
JB
5834 Vx_pointer_shape = Qnil;
5835
ca0ecbf5 5836#if 0 /* This doesn't really do anything. */
29208e82 5837 DEFVAR_LISP ("x-nontext-pointer-shape", Vx_nontext_pointer_shape,
7ee72033 5838 doc: /* The shape of the pointer when not over text.
c061c855
GM
5839This variable takes effect when you create a new frame
5840or when you set the mouse color. */);
af01ef26 5841#endif
01f1ba30
JB
5842 Vx_nontext_pointer_shape = Qnil;
5843
29208e82 5844 DEFVAR_LISP ("x-hourglass-pointer-shape", Vx_hourglass_pointer_shape,
7ee72033 5845 doc: /* The shape of the pointer when Emacs is busy.
c061c855
GM
5846This variable takes effect when you create a new frame
5847or when you set the mouse color. */);
0af913d7 5848 Vx_hourglass_pointer_shape = Qnil;
333b20bb 5849
ca0ecbf5 5850#if 0 /* This doesn't really do anything. */
29208e82 5851 DEFVAR_LISP ("x-mode-pointer-shape", Vx_mode_pointer_shape,
7ee72033 5852 doc: /* The shape of the pointer when over the mode line.
c061c855
GM
5853This variable takes effect when you create a new frame
5854or when you set the mouse color. */);
af01ef26 5855#endif
01f1ba30
JB
5856 Vx_mode_pointer_shape = Qnil;
5857
d3b06468 5858 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
29208e82 5859 Vx_sensitive_text_pointer_shape,
7ee72033 5860 doc: /* The shape of the pointer when over mouse-sensitive text.
c061c855
GM
5861This variable takes effect when you create a new frame
5862or when you set the mouse color. */);
ca0ecbf5 5863 Vx_sensitive_text_pointer_shape = Qnil;
95f80c78 5864
8fb4ec9c 5865 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
29208e82 5866 Vx_window_horizontal_drag_shape,
7ee72033 5867 doc: /* Pointer shape to use for indicating a window can be dragged horizontally.
c061c855
GM
5868This variable takes effect when you create a new frame
5869or when you set the mouse color. */);
8fb4ec9c
GM
5870 Vx_window_horizontal_drag_shape = Qnil;
5871
29208e82 5872 DEFVAR_LISP ("x-cursor-fore-pixel", Vx_cursor_fore_pixel,
7ee72033 5873 doc: /* A string indicating the foreground color of the cursor box. */);
01f1ba30
JB
5874 Vx_cursor_fore_pixel = Qnil;
5875
29208e82 5876 DEFVAR_LISP ("x-max-tooltip-size", Vx_max_tooltip_size,
f5f6c0e0
JB
5877 doc: /* Maximum size for tooltips.
5878Value is a pair (COLUMNS . ROWS). Text larger than this is clipped. */);
d63931a2 5879 Vx_max_tooltip_size = Fcons (make_number (80), make_number (40));
177c0ea7 5880
29208e82 5881 DEFVAR_LISP ("x-no-window-manager", Vx_no_window_manager,
7ee72033 5882 doc: /* Non-nil if no X window manager is in use.
c061c855
GM
5883Emacs doesn't try to figure this out; this is always nil
5884unless you set it to something else. */);
2d38195d
RS
5885 /* We don't have any way to find this out, so set it to nil
5886 and maybe the user would like to set it to t. */
5887 Vx_no_window_manager = Qnil;
1d3dac41 5888
942ea06d 5889 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
29208e82 5890 Vx_pixel_size_width_font_regexp,
7ee72033 5891 doc: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
c061c855
GM
5892
5893Since Emacs gets width of a font matching with this regexp from
5894PIXEL_SIZE field of the name, font finding mechanism gets faster for
5895such a font. This is especially effective for such large fonts as
5896Chinese, Japanese, and Korean. */);
942ea06d
KH
5897 Vx_pixel_size_width_font_regexp = Qnil;
5898
255e4140 5899/* This is not ifdef:ed, so other builds than GTK can customize it. */
29208e82 5900 DEFVAR_BOOL ("x-gtk-use-old-file-dialog", x_gtk_use_old_file_dialog,
fb7ada5f 5901 doc: /* Non-nil means prompt with the old GTK file selection dialog.
255e4140
JD
5902If nil or if the file selection dialog is not available, the new GTK file
5903chooser is used instead. To turn off all file dialogs set the
5904variable `use-file-dialog'. */);
fe2b14b7 5905 x_gtk_use_old_file_dialog = 0;
255e4140 5906
29208e82 5907 DEFVAR_BOOL ("x-gtk-show-hidden-files", x_gtk_show_hidden_files,
fb7ada5f 5908 doc: /* If non-nil, the GTK file chooser will by default show hidden files.
a8a35720
JD
5909Note that this is just the default, there is a toggle button on the file
5910chooser to show or not show hidden files on a case by case basis. */);
5911 x_gtk_show_hidden_files = 0;
5912
29208e82 5913 DEFVAR_BOOL ("x-gtk-file-dialog-help-text", x_gtk_file_dialog_help_text,
fb7ada5f 5914 doc: /* If non-nil, the GTK file chooser will show additional help text.
641c0105
JD
5915If more space for files in the file chooser dialog is wanted, set this to nil
5916to turn the additional text off. */);
159f8da7 5917 x_gtk_file_dialog_help_text = 1;
641c0105 5918
29208e82 5919 DEFVAR_BOOL ("x-gtk-whole-detached-tool-bar", x_gtk_whole_detached_tool_bar,
fb7ada5f 5920 doc: /* If non-nil, a detached tool bar is shown in full.
e0f467cb
JD
5921The default is to just show an arrow and pressing on that arrow shows
5922the tool bar buttons. */);
5923 x_gtk_whole_detached_tool_bar = 0;
5924
29208e82 5925 DEFVAR_BOOL ("x-gtk-use-system-tooltips", x_gtk_use_system_tooltips,
fb7ada5f 5926 doc: /* If non-nil with a Gtk+ built Emacs, the Gtk+ tooltip is used.
aa1859f5
J
5927Otherwise use Emacs own tooltip implementation.
5928When using Gtk+ tooltips, the tooltip face is not used. */);
5929 x_gtk_use_system_tooltips = 1;
5930
d67b4f80 5931 Fprovide (intern_c_string ("x"), Qnil);
49be9d28 5932
1d3dac41 5933#ifdef USE_X_TOOLKIT
d67b4f80 5934 Fprovide (intern_c_string ("x-toolkit"), Qnil);
5b827abb 5935#ifdef USE_MOTIF
d67b4f80 5936 Fprovide (intern_c_string ("motif"), Qnil);
fc2cdd9a 5937
29208e82 5938 DEFVAR_LISP ("motif-version-string", Vmotif_version_string,
7ee72033 5939 doc: /* Version info for LessTif/Motif. */);
fc2cdd9a
GM
5940 Vmotif_version_string = build_string (XmVERSION_STRING);
5941#endif /* USE_MOTIF */
5942#endif /* USE_X_TOOLKIT */
01f1ba30 5943
6b61353c 5944#ifdef USE_GTK
1ec2a572
JD
5945 /* Provide x-toolkit also for GTK. Internally GTK does not use Xt so it
5946 is not an X toolkit in that sense (USE_X_TOOLKIT is not defined).
5947 But for a user it is a toolkit for X, and indeed, configure
5948 accepts --with-x-toolkit=gtk. */
d67b4f80
DN
5949 Fprovide (intern_c_string ("x-toolkit"), Qnil);
5950 Fprovide (intern_c_string ("gtk"), Qnil);
bfeabdc3 5951 Fprovide (intern_c_string ("move-toolbar"), Qnil);
6b61353c 5952
29208e82 5953 DEFVAR_LISP ("gtk-version-string", Vgtk_version_string,
6b61353c
KH
5954 doc: /* Version info for GTK+. */);
5955 {
99027bdd
PE
5956 char gtk_version[sizeof ".." + 3 * INT_STRLEN_BOUND (int)];
5957 int len = sprintf (gtk_version, "%d.%d.%d",
5958 GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION);
5959 Vgtk_version_string = make_pure_string (gtk_version, len, len, 0);
6b61353c
KH
5960 }
5961#endif /* USE_GTK */
5962
333b20bb
GM
5963 /* X window properties. */
5964 defsubr (&Sx_change_window_property);
5965 defsubr (&Sx_delete_window_property);
5966 defsubr (&Sx_window_property);
5967
2d764c78 5968 defsubr (&Sxw_display_color_p);
d0c9d219 5969 defsubr (&Sx_display_grayscale_p);
2d764c78
EZ
5970 defsubr (&Sxw_color_defined_p);
5971 defsubr (&Sxw_color_values);
9d317b2c 5972 defsubr (&Sx_server_max_request_size);
41beb8fc
RS
5973 defsubr (&Sx_server_vendor);
5974 defsubr (&Sx_server_version);
5975 defsubr (&Sx_display_pixel_width);
5976 defsubr (&Sx_display_pixel_height);
5977 defsubr (&Sx_display_mm_width);
5978 defsubr (&Sx_display_mm_height);
5979 defsubr (&Sx_display_screens);
5980 defsubr (&Sx_display_planes);
5981 defsubr (&Sx_display_color_cells);
5982 defsubr (&Sx_display_visual_class);
5983 defsubr (&Sx_display_backing_store);
5984 defsubr (&Sx_display_save_under);
1c44e124 5985 defsubr (&Sx_wm_set_size_hint);
f676886a 5986 defsubr (&Sx_create_frame);
01f1ba30 5987 defsubr (&Sx_open_connection);
08a90d6a
RS
5988 defsubr (&Sx_close_connection);
5989 defsubr (&Sx_display_list);
01f1ba30 5990 defsubr (&Sx_synchronize);
3decc1e7 5991 defsubr (&Sx_focus_frame);
82bab41c 5992 defsubr (&Sx_backspace_delete_keys_p);
177c0ea7 5993
942ea06d 5994 /* Setting callback functions for fontset handler. */
942ea06d 5995 check_window_system_func = check_x;
333b20bb 5996
333b20bb
GM
5997 defsubr (&Sx_show_tip);
5998 defsubr (&Sx_hide_tip);
333b20bb 5999 tip_timer = Qnil;
44b5a125
GM
6000 staticpro (&tip_timer);
6001 tip_frame = Qnil;
6002 staticpro (&tip_frame);
333b20bb 6003
06d62053
GM
6004 last_show_tip_args = Qnil;
6005 staticpro (&last_show_tip_args);
6006
90f2e16b 6007 defsubr (&Sx_uses_old_gtk_dialog);
29fabd8c 6008#if defined (USE_MOTIF) || defined (USE_GTK)
333b20bb
GM
6009 defsubr (&Sx_file_dialog);
6010#endif
9bf80974 6011
946598bf 6012#if defined (USE_GTK) && defined (HAVE_FREETYPE)
f82605c6 6013 defsubr (&Sx_select_font);
e0ab5fcf 6014 x_last_font_name = NULL;
9bf80974 6015#endif
333b20bb
GM
6016}
6017
01f1ba30 6018#endif /* HAVE_X_WINDOWS */