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