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