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