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