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