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