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