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