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