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