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