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