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