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