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