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