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