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