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