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