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