This source file includes following definitions.
- check_x_display_info
- x_real_pos_and_offsets
- x_real_positions
- x_relative_mouse_position
- gamma_correct
- x_defined_color
- x_decode_color
- x_set_wait_for_wm
- x_set_alpha_background
- x_set_tool_bar_position
- x_set_inhibit_double_buffering
- x_set_undecorated
- x_set_parent_frame
- x_set_no_focus_on_map
- x_set_no_accept_focus
- x_set_override_redirect
- xg_set_icon
- xg_set_icon_from_xpm_data
- x_set_foreground_color
- x_set_background_color
- x_set_mouse_color_handler
- x_set_mouse_color
- x_set_cursor_color
- x_set_border_pixel
- x_set_border_color
- x_set_cursor_type
- x_set_icon_type
- x_set_icon_name
- x_set_menu_bar_lines
- x_set_tab_bar_lines
- x_change_tab_bar_height
- x_set_tool_bar_lines
- x_change_tool_bar_height
- x_set_child_frame_border_width
- x_set_internal_border_width
- x_set_scroll_bar_foreground
- x_set_scroll_bar_background
- x_encode_text
- x_set_name_internal
- x_set_name
- x_explicitly_set_name
- x_implicitly_set_name
- x_set_title
- x_set_scroll_bar_default_width
- x_set_scroll_bar_default_height
- x_set_alpha
- x_set_use_frame_synchronization
- x_default_scroll_bar_color_parameter
- hack_wm_protocols
- append_wm_protocols
- xic_create_fontsetname
- print_fontset_result
- xic_create_xfontset
- xic_free_xfontset
- best_xim_style
- create_frame_xic
- free_frame_xic
- xic_set_preeditarea
- xic_set_statusarea
- x_xic_to_frame
- xic_preedit_start_callback
- xic_preedit_caret_callback
- xic_preedit_done_callback
- x_xim_text_to_utf8_unix_1
- x_encode_xim_text_1
- x_xim_text_to_utf8_unix_2
- x_xim_text_to_utf8_unix
- x_encode_xim_text
- xic_preedit_draw_callback
- xic_set_xfontset
- xic_string_conversion_callback
- x_mark_frame_dirty
- set_up_x_back_buffer
- tear_down_x_back_buffer
- initial_set_up_x_back_buffer
- setup_xi_event_mask
- x_window
- x_window
- x_window
- x_icon_verify
- x_icon
- x_make_gc
- x_free_gcs
- unwind_create_frame
- do_unwind_create_frame
- x_default_font_parameter
- DEFUN
- set_machine_and_pid_properties
- DEFUN
- DEFUN
- DEFUN
- DEFUN
- DEFUN
- DEFUN
- DEFUN
- DEFUN
- DEFUN
- DEFUN
- DEFUN
- DEFUN
- DEFUN
- DEFUN
- DEFUN
- DEFUN
- DEFUN
- x_get_net_workarea
- x_get_monitor_for_frame
- x_make_monitor_attribute_list
- x_get_monitor_attributes_fallback
- x_get_monitor_attributes_xinerama
- x_get_monitor_attributes_xrandr
- x_get_monitor_attributes
- xlw_monitor_dimensions_at_pos_1
- xlw_monitor_dimensions_at_pos
- DEFUN
- frame_geometry
- DEFUN
- x_frame_list_z_order
- DEFUN
- x_frame_restack
- DEFUN
- XScreenNumberOfScreen
- select_visual
- x_display_info_for_name
- DEFUN
- DEFUN
- x_window_property_intern
- unwind_create_tip_frame
- x_create_tip_frame
- compute_tip_xy
- x_hide_tip
- DEFUN
- DEFUN
- DEFUN
- file_dialog_cb
- file_dialog_unmap_cb
- clean_up_file_dialog
- clean_up_dialog
- DEFUN
- DEFUN
- DEFUN
- DEFUN
- DEFUN
- DEFUN
- DEFUN
- XkbRefreshKeyboardMapping
- XkbFreeNames
- XDisplayCells
- XDestroySubwindows
- syms_of_xfns
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <config.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <math.h>
24 #include <unistd.h>
25
26 #include "lisp.h"
27 #include "character.h"
28 #include "xterm.h"
29 #include "frame.h"
30 #include "window.h"
31 #include "buffer.h"
32 #include "dispextern.h"
33 #include "keyboard.h"
34 #include "blockinput.h"
35 #include "charset.h"
36 #include "coding.h"
37 #include "termhooks.h"
38 #include "font.h"
39
40 #ifdef HAVE_X_I18N
41 #include "textconv.h"
42 #endif
43
44 #include <sys/types.h>
45 #include <sys/stat.h>
46
47 #ifdef USE_XCB
48 #include <xcb/xcb.h>
49 #include <xcb/xproto.h>
50 #endif
51
52 #include "bitmaps/gray.xbm"
53 #include "xsettings.h"
54
55 #ifdef HAVE_XRANDR
56 #include <X11/extensions/Xrandr.h>
57 #endif
58 #ifdef HAVE_XINERAMA
59 #include <X11/extensions/Xinerama.h>
60 #endif
61
62 #ifdef USE_GTK
63 #include "gtkutil.h"
64 #endif
65
66 #ifdef HAVE_XDBE
67 #include <X11/extensions/Xdbe.h>
68 #endif
69
70 #ifdef HAVE_XINPUT2
71 #include <X11/extensions/XInput2.h>
72 #endif
73
74 #ifdef USE_X_TOOLKIT
75 #include <X11/Shell.h>
76
77 #ifndef USE_MOTIF
78 #ifdef HAVE_XAW3D
79 #include <X11/Xaw3d/Paned.h>
80 #include <X11/Xaw3d/Label.h>
81 #else
82 #include <X11/Xaw/Paned.h>
83 #include <X11/Xaw/Label.h>
84 #endif
85 #endif
86
87 #ifdef USG
88 #undef USG
89 #include <X11/Xos.h>
90 #define USG
91 #ifdef USG
92 #endif
93 #else
94 #include <X11/Xos.h>
95 #endif
96
97 #include "widget.h"
98
99 #include "../lwlib/lwlib.h"
100
101 #ifdef USE_MOTIF
102 #include <Xm/Xm.h>
103 #include <Xm/DialogS.h>
104 #include <Xm/FileSB.h>
105 #include <Xm/List.h>
106 #include <Xm/TextF.h>
107 #include <Xm/MwmUtil.h>
108 #endif
109
110 #ifdef USE_LUCID
111 #include "../lwlib/xlwmenu.h"
112 #endif
113
114
115
116 extern LWLIB_ID widget_id_tick;
117
118 #ifdef USE_MOTIF
119
120 #endif
121
122 #endif
123
124 #ifdef USE_GTK
125
126 #endif
127
128 #define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
129
130 static ptrdiff_t image_cache_refcount;
131 #ifdef GLYPH_DEBUG
132 static int dpyinfo_refcount;
133 #endif
134
135 #ifndef USE_MOTIF
136 #ifndef USE_GTK
137
138 #define MWM_HINTS_DECORATIONS (1L << 1)
139
140
141
142 #define MWM_DECOR_ALL (1L << 0)
143
144
145
146
147
148
149
150
151
152 typedef struct {
153 unsigned long flags;
154 unsigned long functions;
155 unsigned long decorations;
156 long input_mode;
157 unsigned long status;
158 } PropMotifWmHints;
159
160 #define PROP_MOTIF_WM_HINTS_ELEMENTS 5
161 #endif
162 #endif
163
164 static struct x_display_info *x_display_info_for_name (Lisp_Object);
165 static void set_up_x_back_buffer (struct frame *f);
166
167
168
169
170
171
172 struct x_display_info *
173 check_x_display_info (Lisp_Object object)
174 {
175 struct x_display_info *dpyinfo = NULL;
176
177 if (NILP (object))
178 {
179 struct frame *sf = XFRAME (selected_frame);
180
181 if (FRAME_X_P (sf) && FRAME_LIVE_P (sf))
182 dpyinfo = FRAME_DISPLAY_INFO (sf);
183 else if (x_display_list != 0)
184 dpyinfo = x_display_list;
185 else
186 error ("X windows are not in use or not initialized");
187 }
188 else if (TERMINALP (object))
189 {
190 struct terminal *t = decode_live_terminal (object);
191
192 if (t->type != output_x_window)
193 error ("Terminal %d is not an X display", t->id);
194
195 dpyinfo = t->display_info.x;
196 }
197 else if (STRINGP (object))
198 dpyinfo = x_display_info_for_name (object);
199 else
200 {
201 struct frame *f = decode_window_system_frame (object);
202 dpyinfo = FRAME_DISPLAY_INFO (f);
203 }
204
205 return dpyinfo;
206 }
207
208
209
210
211
212
213
214
215
216
217 void
218 x_real_pos_and_offsets (struct frame *f,
219 int *left_offset_x,
220 int *right_offset_x,
221 int *top_offset_y,
222 int *bottom_offset_y,
223 int *x_pixels_diff,
224 int *y_pixels_diff,
225 int *xptr,
226 int *yptr,
227 int *outer_border)
228 {
229 int win_x = 0, win_y = 0, outer_x = 0, outer_y = 0;
230 int real_x = 0, real_y = 0;
231 bool had_errors = false;
232 struct frame *parent_frame = FRAME_PARENT_FRAME (f);
233 Window win = (parent_frame
234 ? FRAME_X_WINDOW (parent_frame)
235 : f->output_data.x->parent_desc);
236 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
237 long max_len = 400;
238 Atom target_type = XA_CARDINAL;
239 unsigned int ow = 0, oh = 0;
240 unsigned int fw = 0, fh = 0;
241 unsigned int bw = 0;
242
243
244
245
246
247
248
249
250
251
252 #ifdef USE_XCB
253 xcb_connection_t *xcb_conn = dpyinfo->xcb_connection;
254 xcb_get_property_cookie_t prop_cookie;
255 xcb_get_geometry_cookie_t outer_geom_cookie;
256 bool sent_requests = false;
257 #else
258 Atom actual_type;
259 unsigned long actual_size, bytes_remaining;
260 int rc, actual_format;
261 Display *dpy = FRAME_X_DISPLAY (f);
262 unsigned char *tmp_data = NULL;
263 #endif
264
265 if (x_pixels_diff) *x_pixels_diff = 0;
266 if (y_pixels_diff) *y_pixels_diff = 0;
267 if (left_offset_x) *left_offset_x = 0;
268 if (top_offset_y) *top_offset_y = 0;
269 if (right_offset_x) *right_offset_x = 0;
270 if (bottom_offset_y) *bottom_offset_y = 0;
271 if (xptr) *xptr = 0;
272 if (yptr) *yptr = 0;
273 if (outer_border) *outer_border = 0;
274
275 if (win == dpyinfo->root_window)
276 win = FRAME_OUTER_WINDOW (f);
277
278 block_input ();
279
280 #ifndef USE_XCB
281
282 x_catch_errors (dpy);
283 #endif
284
285
286
287
288
289 for (;;)
290 {
291 Window wm_window UNINIT, rootw UNINIT;
292
293 #ifdef USE_XCB
294 xcb_query_tree_cookie_t query_tree_cookie;
295 xcb_query_tree_reply_t *query_tree;
296
297 query_tree_cookie = xcb_query_tree (xcb_conn, win);
298 query_tree = xcb_query_tree_reply (xcb_conn, query_tree_cookie, NULL);
299 if (query_tree == NULL)
300 had_errors = true;
301 else
302 {
303 wm_window = query_tree->parent;
304 rootw = query_tree->root;
305 free (query_tree);
306 }
307 #else
308 Window *tmp_children;
309 unsigned int tmp_nchildren;
310 int success;
311
312 success = XQueryTree (dpy, win, &rootw,
313 &wm_window, &tmp_children, &tmp_nchildren);
314
315 had_errors = x_had_errors_p (dpy);
316
317
318 if (! success)
319 break;
320
321 XFree (tmp_children);
322 #endif
323
324 if (had_errors || wm_window == rootw)
325 break;
326
327 win = wm_window;
328 }
329
330 if (! had_errors)
331 {
332 #ifdef USE_XCB
333 xcb_get_geometry_cookie_t geom_cookie;
334 xcb_translate_coordinates_cookie_t trans_cookie;
335 xcb_translate_coordinates_cookie_t outer_trans_cookie;
336
337 xcb_translate_coordinates_reply_t *trans;
338 xcb_get_geometry_reply_t *geom;
339 #else
340 Window child, rootw;
341 unsigned int ign;
342 #endif
343
344 #ifdef USE_XCB
345
346
347
348
349
350 geom_cookie = xcb_get_geometry (xcb_conn, win);
351
352 trans_cookie =
353 xcb_translate_coordinates (xcb_conn,
354
355 FRAME_DISPLAY_INFO (f)->root_window,
356 FRAME_X_WINDOW (f),
357
358
359 0, 0);
360 if (FRAME_X_WINDOW (f) != FRAME_OUTER_WINDOW (f))
361 outer_trans_cookie =
362 xcb_translate_coordinates (xcb_conn,
363
364 FRAME_DISPLAY_INFO (f)->root_window,
365 FRAME_OUTER_WINDOW (f),
366
367
368 0, 0);
369 if (right_offset_x || bottom_offset_y)
370 outer_geom_cookie = xcb_get_geometry (xcb_conn,
371 FRAME_OUTER_WINDOW (f));
372
373 if (!parent_frame
374 && dpyinfo->root_window == f->output_data.x->parent_desc)
375
376 prop_cookie = xcb_get_property (xcb_conn, 0, win,
377 dpyinfo->Xatom_net_frame_extents,
378 target_type, 0, max_len);
379
380 sent_requests = true;
381 #endif
382
383
384 #ifdef USE_XCB
385 geom = xcb_get_geometry_reply (xcb_conn, geom_cookie, NULL);
386 if (geom)
387 {
388 real_x = geom->x;
389 real_y = geom->y;
390 ow = geom->width;
391 oh = geom->height;
392 bw = geom->border_width;
393 free (geom);
394 }
395 else
396 had_errors = true;
397 #else
398 XGetGeometry (dpy, win,
399 &rootw, &real_x, &real_y, &ow, &oh, &bw, &ign);
400 #endif
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417 #ifdef USE_XCB
418 trans = xcb_translate_coordinates_reply (xcb_conn, trans_cookie, NULL);
419 if (trans)
420 {
421 win_x = trans->dst_x;
422 win_y = trans->dst_y;
423 free (trans);
424 }
425 else
426 had_errors = true;
427 #else
428 XTranslateCoordinates (dpy,
429
430
431 FRAME_DISPLAY_INFO (f)->root_window,
432 FRAME_X_WINDOW (f),
433
434
435 0, 0, &win_x, &win_y,
436
437
438 &child);
439 #endif
440
441 win_x += real_x;
442 win_y += real_y;
443
444 if (FRAME_X_WINDOW (f) == FRAME_OUTER_WINDOW (f))
445 {
446 outer_x = win_x;
447 outer_y = win_y;
448 }
449 else
450 {
451 #ifdef USE_XCB
452 xcb_translate_coordinates_reply_t *outer_trans;
453
454 outer_trans = xcb_translate_coordinates_reply (xcb_conn,
455 outer_trans_cookie,
456 NULL);
457 if (outer_trans)
458 {
459 outer_x = outer_trans->dst_x;
460 outer_y = outer_trans->dst_y;
461 free (outer_trans);
462 }
463 else
464 had_errors = true;
465 #else
466 XTranslateCoordinates (dpy,
467
468
469 FRAME_DISPLAY_INFO (f)->root_window,
470 FRAME_OUTER_WINDOW (f),
471
472
473 0, 0, &outer_x, &outer_y,
474
475
476 &child);
477 #endif
478
479 outer_x += real_x;
480 outer_y += real_y;
481 }
482
483 #ifndef USE_XCB
484 had_errors = x_had_errors_p (dpy);
485 #endif
486 }
487
488 if (!parent_frame && dpyinfo->root_window == f->output_data.x->parent_desc)
489 {
490
491 #ifdef USE_XCB
492
493
494 if (sent_requests)
495 {
496 xcb_get_property_reply_t *prop;
497
498 prop = xcb_get_property_reply (xcb_conn, prop_cookie, NULL);
499 if (prop)
500 {
501 if (prop->type == target_type
502 && prop->format == 32
503 && (xcb_get_property_value_length (prop)
504 == 4 * sizeof (int32_t)))
505 {
506 int32_t *fe = xcb_get_property_value (prop);
507
508 outer_x = -fe[0];
509 outer_y = -fe[2];
510 real_x -= fe[0];
511 real_y -= fe[2];
512 }
513 free (prop);
514 }
515
516 }
517 #else
518 rc = XGetWindowProperty (dpy, win, dpyinfo->Xatom_net_frame_extents,
519 0, max_len, False, target_type,
520 &actual_type, &actual_format, &actual_size,
521 &bytes_remaining, &tmp_data);
522
523 if (rc == Success && actual_type == target_type && !x_had_errors_p (dpy)
524 && actual_size == 4 && actual_format == 32)
525 {
526 long *fe = (long *)tmp_data;
527
528 outer_x = -fe[0];
529 outer_y = -fe[2];
530 real_x -= fe[0];
531 real_y -= fe[2];
532 }
533
534 if (tmp_data) XFree (tmp_data);
535 #endif
536 }
537
538 if (right_offset_x || bottom_offset_y)
539 {
540 #ifdef USE_XCB
541
542
543 if (sent_requests)
544 {
545 xcb_get_geometry_reply_t *outer_geom;
546
547 outer_geom = xcb_get_geometry_reply (xcb_conn, outer_geom_cookie,
548 NULL);
549 if (outer_geom)
550 {
551 fw = outer_geom->width;
552 fh = outer_geom->height;
553 free (outer_geom);
554 }
555 else
556 had_errors = true;
557 }
558 #else
559 int xy_ign;
560 unsigned int ign;
561 Window rootw;
562
563 XGetGeometry (dpy, FRAME_OUTER_WINDOW (f),
564 &rootw, &xy_ign, &xy_ign, &fw, &fh, &ign, &ign);
565 #endif
566 }
567
568 #ifndef USE_XCB
569 x_uncatch_errors ();
570 #endif
571
572 unblock_input ();
573
574 if (had_errors) return;
575
576 if (x_pixels_diff) *x_pixels_diff = -win_x;
577 if (y_pixels_diff) *y_pixels_diff = -win_y;
578
579 if (left_offset_x) *left_offset_x = -outer_x;
580 if (top_offset_y) *top_offset_y = -outer_y;
581
582 if (xptr) *xptr = real_x;
583 if (yptr) *yptr = real_y;
584
585 if (outer_border) *outer_border = bw;
586
587 if (right_offset_x) *right_offset_x = ow - fw + outer_x;
588 if (bottom_offset_y) *bottom_offset_y = oh - fh + outer_y;
589 }
590
591
592
593
594
595 void
596 x_real_positions (struct frame *f, int *xptr, int *yptr)
597 {
598 x_real_pos_and_offsets (f, NULL, NULL, NULL, NULL, NULL, NULL, xptr, yptr,
599 NULL);
600 }
601
602
603
604
605 void
606 x_relative_mouse_position (struct frame *f, int *x, int *y)
607 {
608 Window root, dummy_window;
609 int dummy;
610
611 eassert (FRAME_X_P (f));
612
613 block_input ();
614
615 x_query_pointer (FRAME_X_DISPLAY (f),
616 FRAME_DISPLAY_INFO (f)->root_window,
617
618
619 &root,
620
621
622 &dummy_window,
623
624
625 x, y,
626
627
628 &dummy, &dummy,
629
630
631
632 (unsigned int *) &dummy);
633
634 XTranslateCoordinates (FRAME_X_DISPLAY (f),
635
636
637 FRAME_DISPLAY_INFO (f)->root_window,
638 FRAME_X_WINDOW (f),
639
640
641 *x, *y, x, y,
642
643
644 &dummy_window);
645
646 unblock_input ();
647 }
648
649
650
651 void
652 gamma_correct (struct frame *f, XColor *color)
653 {
654 if (f->gamma)
655 {
656 color->red = pow (color->red / 65535.0, f->gamma) * 65535.0 + 0.5;
657 color->green = pow (color->green / 65535.0, f->gamma) * 65535.0 + 0.5;
658 color->blue = pow (color->blue / 65535.0, f->gamma) * 65535.0 + 0.5;
659 }
660 }
661
662
663
664
665
666
667
668 bool
669 x_defined_color (struct frame *f, const char *color_name,
670 Emacs_Color *color, bool alloc_p, bool _makeIndex)
671 {
672 bool success_p = false;
673 Colormap cmap = FRAME_X_COLORMAP (f);
674
675 block_input ();
676 #ifdef USE_GTK
677 success_p = xg_check_special_colors (f, color_name, color);
678 #endif
679 if (!success_p)
680 success_p = x_parse_color (f, color_name, color) != 0;
681 if (success_p && alloc_p)
682 success_p = x_alloc_nearest_color (f, cmap, color);
683 unblock_input ();
684
685 return success_p;
686 }
687
688
689
690
691
692
693 static unsigned long
694 x_decode_color (struct frame *f, Lisp_Object color_name, int mono_color)
695 {
696 XColor cdef;
697
698 CHECK_STRING (color_name);
699
700 #if false
701
702
703 if (strcmp (SDATA (color_name), "black") == 0)
704 return BLACK_PIX_DEFAULT (f);
705 else if (strcmp (SDATA (color_name), "white") == 0)
706 return WHITE_PIX_DEFAULT (f);
707 #endif
708
709
710 if (FRAME_DISPLAY_INFO (f)->n_planes == 1)
711 return mono_color;
712
713
714
715 if (x_defined_color (f, SSDATA (color_name), &cdef, true, false))
716 return cdef.pixel;
717
718 signal_error ("Undefined color", color_name);
719 }
720
721
722
723
724
725
726
727 static void
728 x_set_wait_for_wm (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
729 {
730 f->output_data.x->wait_for_wm = !NILP (new_value);
731 }
732
733 static void
734 x_set_alpha_background (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
735 {
736 unsigned long opaque_region[] = {0, 0, FRAME_PIXEL_WIDTH (f),
737 FRAME_PIXEL_HEIGHT (f)};
738 #ifdef HAVE_GTK3
739 GObjectClass *object_class;
740 GtkWidgetClass *class;
741 #endif
742
743 gui_set_alpha_background (f, arg, oldval);
744
745 #ifdef HAVE_XRENDER
746
747
748
749 if (f->alpha_background < 1.0
750 && !FRAME_DISPLAY_INFO (f)->alpha_bits
751 && !FRAME_CHECK_XR_VERSION (f, 0, 2))
752 f->alpha_background = 1.0;
753 #else
754 f->alpha_background = 1.0;
755 #endif
756
757 #ifdef USE_GTK
758
759
760
761 if (!FRAME_TOOLTIP_P (f))
762 gtk_widget_set_app_paintable (FRAME_GTK_OUTER_WIDGET (f),
763 f->alpha_background != 1.0);
764 #endif
765
766 if (!FRAME_DISPLAY_INFO (f)->alpha_bits)
767 return;
768
769 if (f->alpha_background != 1.0)
770 {
771 XChangeProperty (FRAME_X_DISPLAY (f),
772 FRAME_X_WINDOW (f),
773 FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region,
774 XA_CARDINAL, 32, PropModeReplace,
775 NULL, 0);
776 }
777 #ifndef HAVE_GTK3
778 else
779 XChangeProperty (FRAME_X_DISPLAY (f),
780 FRAME_X_WINDOW (f),
781 FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region,
782 XA_CARDINAL, 32, PropModeReplace,
783 (unsigned char *) &opaque_region, 4);
784 #else
785 else
786 {
787 if (FRAME_TOOLTIP_P (f))
788 XChangeProperty (FRAME_X_DISPLAY (f),
789 FRAME_X_WINDOW (f),
790 FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region,
791 XA_CARDINAL, 32, PropModeReplace,
792 (unsigned char *) &opaque_region, 4);
793 else
794 {
795 object_class = G_OBJECT_GET_CLASS (FRAME_GTK_OUTER_WIDGET (f));
796 class = GTK_WIDGET_CLASS (object_class);
797
798 if (class->style_updated)
799 class->style_updated (FRAME_GTK_OUTER_WIDGET (f));
800 }
801 }
802 #endif
803 }
804
805 static void
806 x_set_tool_bar_position (struct frame *f,
807 Lisp_Object new_value,
808 Lisp_Object old_value)
809 {
810 #ifdef USE_GTK
811 Lisp_Object choice;
812
813 choice = list4 (Qleft, Qright, Qtop, Qbottom);
814
815 if (!NILP (Fmemq (new_value, choice)))
816 {
817 if (!EQ (new_value, old_value))
818 {
819 xg_change_toolbar_position (f, new_value);
820 fset_tool_bar_position (f, new_value);
821 }
822 #else
823 if (!EQ (new_value, Qtop) && !EQ (new_value, Qbottom))
824 error ("Tool bar position must be either `top' or `bottom'");
825
826 if (EQ (new_value, old_value))
827 return;
828
829
830 fset_tool_bar_position (f, new_value);
831
832
833
834
835
836
837 adjust_frame_size (f, -1, -1, 3, false, Qtool_bar_position);
838 adjust_frame_glyphs (f);
839 SET_FRAME_GARBAGED (f);
840
841 if (FRAME_X_WINDOW (f))
842 x_clear_under_internal_border (f);
843 #endif
844 #ifdef USE_GTK
845 }
846 else
847 wrong_choice (choice, new_value);
848 #endif
849 }
850
851 #ifdef HAVE_XDBE
852 static void
853 x_set_inhibit_double_buffering (struct frame *f,
854 Lisp_Object new_value,
855 Lisp_Object old_value)
856 {
857 bool want_double_buffering, was_double_buffered;
858
859 if (FRAME_X_WINDOW (f) && !EQ (new_value, old_value))
860 {
861 want_double_buffering = NILP (new_value);
862 was_double_buffered = FRAME_X_DOUBLE_BUFFERED_P (f);
863
864 block_input ();
865 if (want_double_buffering != was_double_buffered)
866
867
868 font_drop_xrender_surfaces (f);
869 if (FRAME_X_DOUBLE_BUFFERED_P (f) && !want_double_buffering)
870 tear_down_x_back_buffer (f);
871 else if (!FRAME_X_DOUBLE_BUFFERED_P (f) && want_double_buffering)
872 set_up_x_back_buffer (f);
873 if (FRAME_X_DOUBLE_BUFFERED_P (f) != was_double_buffered)
874 {
875 SET_FRAME_GARBAGED (f);
876 font_drop_xrender_surfaces (f);
877 }
878 unblock_input ();
879 }
880 }
881 #endif
882
883
884
885
886
887
888
889
890
891
892
893
894
895 static void
896 x_set_undecorated (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
897 {
898 if (!EQ (new_value, old_value))
899 {
900 FRAME_UNDECORATED (f) = NILP (new_value) ? false : true;
901 #ifdef USE_GTK
902 xg_set_undecorated (f, new_value);
903 #else
904 Display *dpy = FRAME_X_DISPLAY (f);
905 PropMotifWmHints hints;
906 Atom prop = FRAME_DISPLAY_INFO (f)->Xatom_MOTIF_WM_HINTS;
907
908 memset (&hints, 0, sizeof(hints));
909 hints.flags = MWM_HINTS_DECORATIONS;
910 hints.decorations = NILP (new_value) ? MWM_DECOR_ALL : 0;
911
912 block_input ();
913
914
915
916
917 XChangeProperty (dpy, FRAME_OUTER_WINDOW (f), prop, prop, 32,
918 PropModeReplace, (unsigned char *) &hints,
919 PROP_MOTIF_WM_HINTS_ELEMENTS);
920 unblock_input ();
921
922 #endif
923 }
924 }
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954 static void
955 x_set_parent_frame (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
956 {
957 struct frame *p = NULL;
958 #ifdef HAVE_GTK3
959 GdkWindow *window;
960 #endif
961
962 if (!NILP (new_value)
963 && (!FRAMEP (new_value)
964 || !FRAME_LIVE_P (p = XFRAME (new_value))
965 || !FRAME_X_P (p)))
966 {
967 store_frame_param (f, Qparent_frame, old_value);
968 error ("Invalid specification of `parent-frame'");
969 }
970
971 if (p != FRAME_PARENT_FRAME (f))
972 {
973 block_input ();
974 XReparentWindow
975 (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
976 p ? FRAME_X_WINDOW (p) : FRAME_DISPLAY_INFO (f)->root_window,
977 f->left_pos, f->top_pos);
978 #ifdef USE_GTK
979 if (EQ (x_gtk_resize_child_frames, Qresize_mode))
980 gtk_container_set_resize_mode
981 (GTK_CONTAINER (FRAME_GTK_OUTER_WIDGET (f)),
982 p ? GTK_RESIZE_IMMEDIATE : GTK_RESIZE_QUEUE);
983 #endif
984
985 #ifdef HAVE_GTK3
986 if (p)
987 {
988 window = gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (f));
989 gdk_x11_window_set_frame_sync_enabled (window, FALSE);
990 }
991 #endif
992
993 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
994
995
996
997
998
999 FRAME_X_OUTPUT (f)->use_vsync_p = false;
1000 FRAME_X_WAITING_FOR_DRAW (f) = false;
1001 #endif
1002 unblock_input ();
1003
1004 fset_parent_frame (f, new_value);
1005 }
1006 }
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019 static void
1020 x_set_no_focus_on_map (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
1021 {
1022 if (!EQ (new_value, old_value))
1023 {
1024 #ifdef USE_GTK
1025 xg_set_no_focus_on_map (f, new_value);
1026 #else
1027 Display *dpy = FRAME_X_DISPLAY (f);
1028 Atom prop = FRAME_DISPLAY_INFO (f)->Xatom_net_wm_user_time;
1029 Time timestamp = NILP (new_value) ? CurrentTime : 0;
1030
1031 XChangeProperty (dpy, FRAME_OUTER_WINDOW (f), prop,
1032 XA_CARDINAL, 32, PropModeReplace,
1033 (unsigned char *) ×tamp, 1);
1034 #endif
1035 FRAME_NO_FOCUS_ON_MAP (f) = !NILP (new_value);
1036 }
1037 }
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051 static void
1052 x_set_no_accept_focus (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
1053 {
1054 if (!EQ (new_value, old_value))
1055 {
1056 #ifdef USE_GTK
1057 xg_set_no_accept_focus (f, new_value);
1058 #else
1059 #ifdef USE_X_TOOLKIT
1060 Arg al[1];
1061
1062 XtSetArg (al[0], XtNinput, NILP (new_value) ? True : False);
1063 XtSetValues (f->output_data.x->widget, al, 1);
1064 #else
1065 Window window = FRAME_X_WINDOW (f);
1066
1067 f->output_data.x->wm_hints.input = NILP (new_value) ? True : False;
1068 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
1069 #endif
1070 #endif
1071 FRAME_NO_ACCEPT_FOCUS (f) = !NILP (new_value);
1072 }
1073 }
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084 static void
1085 x_set_override_redirect (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
1086 {
1087 if (!EQ (new_value, old_value))
1088 {
1089
1090
1091 x_make_frame_invisible (f);
1092
1093 #ifdef USE_GTK
1094 xg_set_override_redirect (f, new_value);
1095 #else
1096 XSetWindowAttributes attributes;
1097
1098 attributes.override_redirect = NILP (new_value) ? False : True;
1099 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
1100 CWOverrideRedirect, &attributes);
1101 #endif
1102 x_make_frame_visible (f);
1103 FRAME_OVERRIDE_REDIRECT (f) = !NILP (new_value);
1104 }
1105 }
1106
1107
1108 #ifdef USE_GTK
1109
1110
1111
1112
1113 bool
1114 xg_set_icon (struct frame *f, Lisp_Object file)
1115 {
1116 bool result = false;
1117 Lisp_Object found;
1118
1119 found = image_find_image_file (file);
1120
1121 if (! NILP (found))
1122 {
1123 GdkPixbuf *pixbuf;
1124 GError *err = NULL;
1125 char *filename = SSDATA (ENCODE_FILE (found));
1126 block_input ();
1127
1128 pixbuf = gdk_pixbuf_new_from_file (filename, &err);
1129
1130 if (pixbuf)
1131 {
1132 gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
1133 pixbuf);
1134 g_object_unref (pixbuf);
1135
1136 result = true;
1137 }
1138 else
1139 g_error_free (err);
1140
1141 unblock_input ();
1142 }
1143
1144 return result;
1145 }
1146
1147 bool
1148 xg_set_icon_from_xpm_data (struct frame *f, const char **data)
1149 {
1150 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data (data);
1151
1152 if (!pixbuf)
1153 return false;
1154
1155 gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), pixbuf);
1156 g_object_unref (pixbuf);
1157 return true;
1158 }
1159 #endif
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170 static void
1171 x_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1172 {
1173 struct x_output *x = f->output_data.x;
1174 unsigned long fg, old_fg;
1175
1176 fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1177 old_fg = FRAME_FOREGROUND_PIXEL (f);
1178 FRAME_FOREGROUND_PIXEL (f) = fg;
1179
1180 if (FRAME_X_WINDOW (f) != 0)
1181 {
1182 Display *dpy = FRAME_X_DISPLAY (f);
1183
1184 block_input ();
1185 XSetForeground (dpy, x->normal_gc, fg);
1186 XSetBackground (dpy, x->reverse_gc, fg);
1187
1188 if (x->cursor_pixel == old_fg)
1189 {
1190 unload_color (f, x->cursor_pixel);
1191 x->cursor_pixel = x_copy_color (f, fg);
1192 XSetBackground (dpy, x->cursor_gc, x->cursor_pixel);
1193 }
1194
1195 unblock_input ();
1196
1197 update_face_from_frame_parameter (f, Qforeground_color, arg);
1198
1199 if (FRAME_VISIBLE_P (f))
1200 redraw_frame (f);
1201 }
1202
1203 unload_color (f, old_fg);
1204 }
1205
1206 static void
1207 x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1208 {
1209 struct x_output *x = f->output_data.x;
1210 unsigned long bg;
1211
1212 bg = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
1213 unload_color (f, FRAME_BACKGROUND_PIXEL (f));
1214 FRAME_BACKGROUND_PIXEL (f) = bg;
1215
1216 if (FRAME_X_WINDOW (f) != 0)
1217 {
1218 Display *dpy = FRAME_X_DISPLAY (f);
1219
1220 block_input ();
1221 XSetBackground (dpy, x->normal_gc, bg);
1222 XSetForeground (dpy, x->reverse_gc, bg);
1223 XSetWindowBackground (dpy, FRAME_X_WINDOW (f), bg);
1224 XSetForeground (dpy, x->cursor_gc, bg);
1225
1226 #ifdef USE_GTK
1227 xg_set_background_color (f, bg);
1228 #endif
1229
1230 unblock_input ();
1231 update_face_from_frame_parameter (f, Qbackground_color, arg);
1232
1233 if (FRAME_VISIBLE_P (f))
1234 redraw_frame (f);
1235 }
1236 }
1237
1238
1239 enum mouse_cursor {
1240 mouse_cursor_text,
1241 mouse_cursor_nontext,
1242 mouse_cursor_hourglass,
1243 mouse_cursor_mode,
1244 mouse_cursor_hand,
1245 mouse_cursor_horizontal_drag,
1246 mouse_cursor_vertical_drag,
1247 mouse_cursor_left_edge,
1248 mouse_cursor_top_left_corner,
1249 mouse_cursor_top_edge,
1250 mouse_cursor_top_right_corner,
1251 mouse_cursor_right_edge,
1252 mouse_cursor_bottom_right_corner,
1253 mouse_cursor_bottom_edge,
1254 mouse_cursor_bottom_left_corner,
1255 mouse_cursor_max
1256 };
1257
1258 struct mouse_cursor_types {
1259
1260 const char *name;
1261
1262
1263
1264
1265
1266 Lisp_Object *shape_var_ptr;
1267
1268
1269 int default_shape;
1270 };
1271
1272
1273 static const struct mouse_cursor_types mouse_cursor_types[] =
1274 {
1275 { "text", &Vx_pointer_shape, XC_xterm },
1276 { "nontext", &Vx_nontext_pointer_shape, XC_left_ptr },
1277 { "hourglass", &Vx_hourglass_pointer_shape, XC_watch },
1278 { "modeline", &Vx_mode_pointer_shape, XC_xterm },
1279 { NULL, &Vx_sensitive_text_pointer_shape, XC_hand2 },
1280 { NULL, &Vx_window_horizontal_drag_shape, XC_sb_h_double_arrow },
1281 { NULL, &Vx_window_vertical_drag_shape, XC_sb_v_double_arrow },
1282 { NULL, &Vx_window_left_edge_shape, XC_left_side },
1283 { NULL, &Vx_window_top_left_corner_shape, XC_top_left_corner },
1284 { NULL, &Vx_window_top_edge_shape, XC_top_side },
1285 { NULL, &Vx_window_top_right_corner_shape, XC_top_right_corner },
1286 { NULL, &Vx_window_right_edge_shape, XC_right_side },
1287 { NULL, &Vx_window_bottom_right_corner_shape, XC_bottom_right_corner },
1288 { NULL, &Vx_window_bottom_edge_shape, XC_bottom_side },
1289 { NULL, &Vx_window_bottom_left_corner_shape, XC_bottom_left_corner },
1290 };
1291
1292 struct mouse_cursor_data
1293 {
1294
1295
1296 int last_cursor_create_request;
1297
1298
1299
1300 int error_cursor;
1301
1302
1303 unsigned int cursor_num[mouse_cursor_max];
1304
1305
1306 Cursor cursor[mouse_cursor_max];
1307
1308
1309
1310 unsigned long x_request_serial[mouse_cursor_max];
1311
1312
1313
1314 char *error_string;
1315 };
1316
1317 static void
1318 x_set_mouse_color_handler (Display *dpy, XErrorEvent *event,
1319 char *error_string, void *data)
1320 {
1321 struct mouse_cursor_data *cursor_data = data;
1322 int i;
1323
1324 cursor_data->error_cursor = -1;
1325 cursor_data->error_string = error_string;
1326 for (i = 0; i < cursor_data->last_cursor_create_request; i++)
1327 {
1328 if (event->serial >= cursor_data->x_request_serial[i])
1329 cursor_data->error_cursor = i;
1330 }
1331 if (cursor_data->error_cursor >= 0)
1332
1333 cursor_data->cursor[cursor_data->error_cursor] = 0;
1334 }
1335
1336 static void
1337 x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1338 {
1339 struct x_output *x = f->output_data.x;
1340 Display *dpy = FRAME_X_DISPLAY (f);
1341 struct mouse_cursor_data cursor_data = { -1, -1 };
1342 unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1343 unsigned long mask_color = FRAME_BACKGROUND_PIXEL (f);
1344 int i;
1345
1346
1347 if (mask_color == pixel)
1348 {
1349 x_free_colors (f, &pixel, 1);
1350 pixel = x_copy_color (f, FRAME_FOREGROUND_PIXEL (f));
1351 }
1352
1353 unload_color (f, x->mouse_pixel);
1354 x->mouse_pixel = pixel;
1355
1356 for (i = 0; i < mouse_cursor_max; i++)
1357 {
1358 Lisp_Object shape_var = *mouse_cursor_types[i].shape_var_ptr;
1359 cursor_data.cursor_num[i]
1360 = (!NILP (shape_var)
1361 ? check_uinteger_max (shape_var, UINT_MAX)
1362 : mouse_cursor_types[i].default_shape);
1363 }
1364
1365 block_input ();
1366
1367
1368 x_catch_errors_with_handler (dpy, x_set_mouse_color_handler, &cursor_data);
1369
1370 for (i = 0; i < mouse_cursor_max; i++)
1371 {
1372 cursor_data.x_request_serial[i] = XNextRequest (dpy);
1373 cursor_data.last_cursor_create_request = i;
1374
1375 cursor_data.cursor[i]
1376 = x_create_font_cursor (FRAME_DISPLAY_INFO (f),
1377 cursor_data.cursor_num[i]);
1378 }
1379
1380
1381
1382 if (x_had_errors_p (dpy))
1383 {
1384 const char *bad_cursor_name = NULL;
1385
1386 size_t message_length = strlen (cursor_data.error_string);
1387 char *xmessage = alloca (1 + message_length);
1388 memcpy (xmessage, cursor_data.error_string, message_length);
1389
1390 x_uncatch_errors_after_check ();
1391
1392
1393
1394
1395
1396 x_ignore_errors_for_next_request (FRAME_DISPLAY_INFO (f), 0);
1397
1398
1399 for (i = 0; i < mouse_cursor_max; i++)
1400 if (cursor_data.cursor[i] != 0)
1401 XFreeCursor (dpy, cursor_data.cursor[i]);
1402
1403 x_stop_ignoring_errors (FRAME_DISPLAY_INFO (f));
1404
1405
1406
1407 if (cursor_data.error_cursor >= 0)
1408 bad_cursor_name = mouse_cursor_types[cursor_data.error_cursor].name;
1409 if (bad_cursor_name)
1410 error ("bad %s pointer cursor: %s", bad_cursor_name, xmessage);
1411 else
1412 error ("can't set cursor shape: %s", xmessage);
1413 }
1414
1415 x_uncatch_errors_after_check ();
1416
1417 {
1418 XColor colors[2];
1419
1420 colors[0].pixel = x->mouse_pixel;
1421 colors[1].pixel = mask_color;
1422 x_query_colors (f, colors, 2);
1423
1424 for (i = 0; i < mouse_cursor_max; i++)
1425 XRecolorCursor (dpy, cursor_data.cursor[i], &colors[0], &colors[1]);
1426 }
1427
1428 if (FRAME_X_WINDOW (f) != 0)
1429 {
1430 f->output_data.x->current_cursor = cursor_data.cursor[mouse_cursor_text];
1431 XDefineCursor (dpy, FRAME_X_WINDOW (f),
1432 f->output_data.x->current_cursor);
1433 }
1434
1435 #define INSTALL_CURSOR(FIELD, SHORT_INDEX) \
1436 eassert (x->FIELD != cursor_data.cursor[mouse_cursor_ ## SHORT_INDEX]); \
1437 if (x->FIELD != 0) \
1438 XFreeCursor (dpy, x->FIELD); \
1439 x->FIELD = cursor_data.cursor[mouse_cursor_ ## SHORT_INDEX];
1440
1441 INSTALL_CURSOR (text_cursor, text);
1442 INSTALL_CURSOR (nontext_cursor, nontext);
1443 INSTALL_CURSOR (hourglass_cursor, hourglass);
1444 INSTALL_CURSOR (modeline_cursor, mode);
1445 INSTALL_CURSOR (hand_cursor, hand);
1446 INSTALL_CURSOR (horizontal_drag_cursor, horizontal_drag);
1447 INSTALL_CURSOR (vertical_drag_cursor, vertical_drag);
1448 INSTALL_CURSOR (left_edge_cursor, left_edge);
1449 INSTALL_CURSOR (top_left_corner_cursor, top_left_corner);
1450 INSTALL_CURSOR (top_edge_cursor, top_edge);
1451 INSTALL_CURSOR (top_right_corner_cursor, top_right_corner);
1452 INSTALL_CURSOR (right_edge_cursor, right_edge);
1453 INSTALL_CURSOR (bottom_right_corner_cursor, bottom_right_corner);
1454 INSTALL_CURSOR (bottom_edge_cursor, bottom_edge);
1455 INSTALL_CURSOR (bottom_left_corner_cursor, bottom_left_corner);
1456
1457 #undef INSTALL_CURSOR
1458
1459 XFlush (dpy);
1460 unblock_input ();
1461
1462 update_face_from_frame_parameter (f, Qmouse_color, arg);
1463 }
1464
1465 static void
1466 x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1467 {
1468 unsigned long fore_pixel, pixel;
1469 bool fore_pixel_allocated_p = false, pixel_allocated_p = false;
1470 struct x_output *x = f->output_data.x;
1471
1472 if (!NILP (Vx_cursor_fore_pixel))
1473 {
1474 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
1475 WHITE_PIX_DEFAULT (f));
1476 fore_pixel_allocated_p = true;
1477 }
1478 else
1479 fore_pixel = FRAME_BACKGROUND_PIXEL (f);
1480
1481 pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1482 pixel_allocated_p = true;
1483
1484
1485 if (pixel == FRAME_BACKGROUND_PIXEL (f))
1486 {
1487 if (pixel_allocated_p)
1488 {
1489 x_free_colors (f, &pixel, 1);
1490 pixel_allocated_p = false;
1491 }
1492
1493 pixel = x->mouse_pixel;
1494 if (pixel == fore_pixel)
1495 {
1496 if (fore_pixel_allocated_p)
1497 {
1498 x_free_colors (f, &fore_pixel, 1);
1499 fore_pixel_allocated_p = false;
1500 }
1501 fore_pixel = FRAME_BACKGROUND_PIXEL (f);
1502 }
1503 }
1504
1505 unload_color (f, x->cursor_foreground_pixel);
1506 if (!fore_pixel_allocated_p)
1507 fore_pixel = x_copy_color (f, fore_pixel);
1508 x->cursor_foreground_pixel = fore_pixel;
1509
1510 unload_color (f, x->cursor_pixel);
1511 if (!pixel_allocated_p)
1512 pixel = x_copy_color (f, pixel);
1513 x->cursor_pixel = pixel;
1514
1515 if (FRAME_X_WINDOW (f) != 0)
1516 {
1517 block_input ();
1518 XSetBackground (FRAME_X_DISPLAY (f), x->cursor_gc, x->cursor_pixel);
1519 XSetForeground (FRAME_X_DISPLAY (f), x->cursor_gc, fore_pixel);
1520 unblock_input ();
1521
1522 if (FRAME_VISIBLE_P (f))
1523 {
1524 gui_update_cursor (f, false);
1525 gui_update_cursor (f, true);
1526 }
1527 }
1528
1529 update_face_from_frame_parameter (f, Qcursor_color, arg);
1530 }
1531
1532
1533
1534
1535
1536 static void
1537 x_set_border_pixel (struct frame *f, unsigned long pix)
1538 {
1539 unload_color (f, f->output_data.x->border_pixel);
1540 f->output_data.x->border_pixel = pix;
1541
1542 #ifdef USE_X_TOOLKIT
1543 if (f->output_data.x->widget && f->border_width > 0)
1544 {
1545 block_input ();
1546 XtVaSetValues (f->output_data.x->widget, XtNborderColor,
1547 (Pixel) pix, NULL);
1548 unblock_input ();
1549
1550 if (FRAME_VISIBLE_P (f))
1551 redraw_frame (f);
1552
1553 return;
1554 }
1555 #endif
1556
1557 if (FRAME_X_WINDOW (f) != 0 && f->border_width > 0)
1558 {
1559 block_input ();
1560 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), pix);
1561 unblock_input ();
1562
1563 if (FRAME_VISIBLE_P (f))
1564 redraw_frame (f);
1565 }
1566 }
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579 static void
1580 x_set_border_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1581 {
1582 unsigned long pix;
1583
1584 CHECK_STRING (arg);
1585 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1586 x_set_border_pixel (f, pix);
1587 update_face_from_frame_parameter (f, Qborder_color, arg);
1588 }
1589
1590
1591 static void
1592 x_set_cursor_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1593 {
1594 set_frame_cursor_types (f, arg);
1595 }
1596
1597 static void
1598 x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1599 {
1600 bool result;
1601
1602 if (STRINGP (arg))
1603 {
1604 if (STRINGP (oldval) && BASE_EQ (Fstring_equal (oldval, arg), Qt))
1605 return;
1606 }
1607 else if (!STRINGP (oldval) && NILP (oldval) == NILP (arg))
1608 return;
1609
1610 block_input ();
1611 if (NILP (arg))
1612 result = x_text_icon (f,
1613 SSDATA ((!NILP (f->icon_name)
1614 ? f->icon_name
1615 : f->name)));
1616 else
1617 result = FRAME_TERMINAL (f)->set_bitmap_icon_hook (f, arg);
1618
1619 if (result)
1620 {
1621 unblock_input ();
1622 error ("No icon window available");
1623 }
1624
1625 XFlush (FRAME_X_DISPLAY (f));
1626 unblock_input ();
1627 }
1628
1629 static void
1630 x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1631 {
1632 bool result;
1633
1634 if (STRINGP (arg))
1635 {
1636 if (STRINGP (oldval) && BASE_EQ (Fstring_equal (oldval, arg), Qt))
1637 return;
1638 }
1639 else if (!NILP (arg) || NILP (oldval))
1640 return;
1641
1642 fset_icon_name (f, arg);
1643
1644 if (f->output_data.x->icon_bitmap != 0)
1645 return;
1646
1647 block_input ();
1648
1649 result = x_text_icon (f,
1650 SSDATA ((!NILP (f->icon_name)
1651 ? f->icon_name
1652 : !NILP (f->title)
1653 ? f->title
1654 : f->name)));
1655
1656 if (result)
1657 {
1658 unblock_input ();
1659 error ("No icon window available");
1660 }
1661
1662 XFlush (FRAME_X_DISPLAY (f));
1663 unblock_input ();
1664 }
1665
1666
1667 static void
1668 x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
1669 {
1670 int nlines;
1671 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
1672 int olines = FRAME_MENU_BAR_LINES (f);
1673 #endif
1674
1675
1676
1677
1678
1679 if (FRAME_MINIBUF_ONLY_P (f) || FRAME_PARENT_FRAME (f))
1680 return;
1681
1682 if (TYPE_RANGED_FIXNUMP (int, value))
1683 nlines = XFIXNUM (value);
1684 else
1685 nlines = 0;
1686
1687
1688 fset_redisplay (f);
1689
1690 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
1691 FRAME_MENU_BAR_LINES (f) = 0;
1692 FRAME_MENU_BAR_HEIGHT (f) = 0;
1693 if (nlines)
1694 {
1695 FRAME_EXTERNAL_MENU_BAR (f) = 1;
1696 if (FRAME_X_P (f) && f->output_data.x->menubar_widget == 0)
1697
1698 XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = true;
1699 }
1700 else
1701 {
1702 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
1703 free_frame_menubar (f);
1704 FRAME_EXTERNAL_MENU_BAR (f) = 0;
1705 if (FRAME_X_P (f))
1706 f->output_data.x->menubar_widget = 0;
1707 }
1708 #else
1709 FRAME_MENU_BAR_LINES (f) = nlines;
1710 FRAME_MENU_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f);
1711 if (FRAME_X_WINDOW (f))
1712 x_clear_under_internal_border (f);
1713
1714
1715
1716
1717
1718 if (nlines != olines)
1719 {
1720 int height = FRAME_INTERNAL_BORDER_WIDTH (f);
1721 int width = FRAME_PIXEL_WIDTH (f);
1722 int y;
1723
1724 adjust_frame_size (f, -1, -1, 3, true, Qmenu_bar_lines);
1725
1726
1727 if (FRAME_X_WINDOW (f) && height > 0 && width > 0)
1728 {
1729 y = FRAME_TOP_MARGIN_HEIGHT (f);
1730
1731 block_input ();
1732 x_clear_area (f, 0, y, width, height);
1733 unblock_input ();
1734 }
1735
1736 if (nlines > 1 && nlines > olines)
1737 {
1738 y = (olines == 0 ? 1 : olines) * FRAME_LINE_HEIGHT (f);
1739 height = nlines * FRAME_LINE_HEIGHT (f) - y;
1740
1741 block_input ();
1742 x_clear_area (f, 0, y, width, height);
1743 unblock_input ();
1744 }
1745
1746 if (nlines == 0 && WINDOWP (f->menu_bar_window))
1747 clear_glyph_matrix (XWINDOW (f->menu_bar_window)->current_matrix);
1748 }
1749 #endif
1750 adjust_frame_glyphs (f);
1751 }
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761 static void
1762 x_set_tab_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
1763 {
1764 int olines = FRAME_TAB_BAR_LINES (f);
1765 int nlines;
1766
1767
1768 if (FRAME_MINIBUF_ONLY_P (f))
1769 return;
1770
1771
1772 if (RANGED_FIXNUMP (0, value, INT_MAX))
1773 nlines = XFIXNAT (value);
1774 else
1775 nlines = 0;
1776
1777 if (nlines != olines && (olines == 0 || nlines == 0))
1778 x_change_tab_bar_height (f, nlines * FRAME_LINE_HEIGHT (f));
1779 }
1780
1781
1782
1783 void
1784 x_change_tab_bar_height (struct frame *f, int height)
1785 {
1786 int unit = FRAME_LINE_HEIGHT (f);
1787 int old_height = FRAME_TAB_BAR_HEIGHT (f);
1788
1789
1790
1791
1792
1793
1794 int lines = height / unit;
1795 if (lines == 0 && height != 0)
1796 lines = 1;
1797
1798
1799 fset_redisplay (f);
1800
1801
1802 FRAME_TAB_BAR_HEIGHT (f) = height;
1803 FRAME_TAB_BAR_LINES (f) = lines;
1804 store_frame_param (f, Qtab_bar_lines, make_fixnum (lines));
1805
1806 if (FRAME_X_WINDOW (f) && FRAME_TAB_BAR_HEIGHT (f) == 0)
1807 {
1808 clear_frame (f);
1809 clear_current_matrices (f);
1810 }
1811
1812 if ((height < old_height) && WINDOWP (f->tab_bar_window))
1813 clear_glyph_matrix (XWINDOW (f->tab_bar_window)->current_matrix);
1814
1815 if (!f->tab_bar_resized)
1816 {
1817 Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
1818
1819
1820
1821 if (NILP (fullscreen) || EQ (fullscreen, Qfullwidth))
1822 adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
1823 1, false, Qtab_bar_lines);
1824 else
1825 adjust_frame_size (f, -1, -1, 4, false, Qtab_bar_lines);
1826
1827 f->tab_bar_resized = f->tab_bar_redisplayed;
1828 }
1829 else
1830
1831 adjust_frame_size (f, -1, -1, 3, false, Qtab_bar_lines);
1832
1833
1834
1835 adjust_frame_glyphs (f);
1836 SET_FRAME_GARBAGED (f);
1837 if (FRAME_X_WINDOW (f))
1838 x_clear_under_internal_border (f);
1839 }
1840
1841
1842
1843
1844
1845
1846
1847
1848 static void
1849 x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
1850 {
1851 int nlines;
1852
1853
1854 if (FRAME_MINIBUF_ONLY_P (f))
1855 return;
1856
1857
1858 if (RANGED_FIXNUMP (0, value, INT_MAX))
1859 nlines = XFIXNAT (value);
1860 else
1861 nlines = 0;
1862
1863 x_change_tool_bar_height (f, nlines * FRAME_LINE_HEIGHT (f));
1864 }
1865
1866
1867
1868 void
1869 x_change_tool_bar_height (struct frame *f, int height)
1870 {
1871 #ifdef USE_GTK
1872 FRAME_TOOL_BAR_LINES (f) = 0;
1873 FRAME_TOOL_BAR_HEIGHT (f) = 0;
1874 if (height)
1875 {
1876 FRAME_EXTERNAL_TOOL_BAR (f) = true;
1877 if (FRAME_X_P (f) && f->output_data.x->toolbar_widget == 0)
1878
1879 XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = true;
1880 update_frame_tool_bar (f);
1881 }
1882 else
1883 {
1884 if (FRAME_EXTERNAL_TOOL_BAR (f))
1885 free_frame_tool_bar (f);
1886 FRAME_EXTERNAL_TOOL_BAR (f) = false;
1887 }
1888 #else
1889 int unit = FRAME_LINE_HEIGHT (f);
1890 int old_height = FRAME_TOOL_BAR_HEIGHT (f);
1891 int lines = (height + unit - 1) / unit;
1892 Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
1893
1894
1895 fset_redisplay (f);
1896
1897 FRAME_TOOL_BAR_HEIGHT (f) = height;
1898 FRAME_TOOL_BAR_LINES (f) = lines;
1899 store_frame_param (f, Qtool_bar_lines, make_fixnum (lines));
1900
1901 if (FRAME_X_WINDOW (f) && FRAME_TOOL_BAR_HEIGHT (f) == 0)
1902 {
1903 clear_frame (f);
1904 clear_current_matrices (f);
1905 }
1906
1907 if ((height < old_height) && WINDOWP (f->tool_bar_window))
1908 clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
1909
1910 if (!f->tool_bar_resized)
1911 {
1912
1913
1914 if (NILP (fullscreen) || EQ (fullscreen, Qfullwidth))
1915 adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
1916 1, false, Qtool_bar_lines);
1917 else
1918 adjust_frame_size (f, -1, -1, 4, false, Qtool_bar_lines);
1919
1920 f->tool_bar_resized = f->tool_bar_redisplayed;
1921 }
1922 else
1923
1924 adjust_frame_size (f, -1, -1, 3, false, Qtool_bar_lines);
1925
1926
1927
1928 adjust_frame_glyphs (f);
1929 SET_FRAME_GARBAGED (f);
1930 if (FRAME_X_WINDOW (f))
1931 x_clear_under_internal_border (f);
1932
1933 #endif
1934 }
1935
1936 static void
1937 x_set_child_frame_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1938 {
1939 int border;
1940
1941 if (NILP (arg))
1942 border = -1;
1943 else if (RANGED_FIXNUMP (0, arg, INT_MAX))
1944 border = XFIXNAT (arg);
1945 else
1946 signal_error ("Invalid child frame border width", arg);
1947
1948 if (border != FRAME_CHILD_FRAME_BORDER_WIDTH (f))
1949 {
1950 f->child_frame_border_width = border;
1951
1952 #ifdef USE_X_TOOLKIT
1953 if (FRAME_X_OUTPUT (f)->edit_widget)
1954 widget_store_internal_border (FRAME_X_OUTPUT (f)->edit_widget);
1955 #endif
1956
1957 if (FRAME_X_WINDOW (f))
1958 {
1959 adjust_frame_size (f, -1, -1, 3, false, Qchild_frame_border_width);
1960 x_clear_under_internal_border (f);
1961 }
1962 }
1963
1964 }
1965
1966 static void
1967 x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1968 {
1969 int border = check_int_nonnegative (arg);
1970
1971 if (border != FRAME_INTERNAL_BORDER_WIDTH (f))
1972 {
1973 f->internal_border_width = border;
1974
1975 #ifdef USE_X_TOOLKIT
1976 if (FRAME_X_OUTPUT (f)->edit_widget)
1977 widget_store_internal_border (FRAME_X_OUTPUT (f)->edit_widget);
1978 #endif
1979
1980 if (FRAME_X_WINDOW (f))
1981 {
1982 adjust_frame_size (f, -1, -1, 3, false, Qinternal_border_width);
1983 x_clear_under_internal_border (f);
1984 }
1985 }
1986
1987 }
1988
1989
1990
1991
1992
1993
1994
1995 static void
1996 x_set_scroll_bar_foreground (struct frame *f, Lisp_Object value, Lisp_Object oldval)
1997 {
1998 unsigned long pixel;
1999 #ifdef HAVE_GTK3
2000 XColor color;
2001 char css[64];
2002 #endif
2003
2004 if (STRINGP (value))
2005 pixel = x_decode_color (f, value, BLACK_PIX_DEFAULT (f));
2006 else
2007 pixel = -1;
2008
2009 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
2010 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
2011
2012 f->output_data.x->scroll_bar_foreground_pixel = pixel;
2013 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
2014 {
2015
2016 if (FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
2017 (*FRAME_TERMINAL (f)->condemn_scroll_bars_hook) (f);
2018 if (FRAME_TERMINAL (f)->judge_scroll_bars_hook)
2019 (*FRAME_TERMINAL (f)->judge_scroll_bars_hook) (f);
2020
2021 update_face_from_frame_parameter (f, Qscroll_bar_foreground, value);
2022 redraw_frame (f);
2023 }
2024
2025 #ifdef HAVE_GTK3
2026 if (!FRAME_TOOLTIP_P (f))
2027 {
2028 if (pixel != -1)
2029 {
2030 color.pixel = pixel;
2031
2032 XQueryColor (FRAME_X_DISPLAY (f),
2033 FRAME_X_COLORMAP (f),
2034 &color);
2035
2036 sprintf (css, "scrollbar slider { background-color: #%02x%02x%02x; }",
2037 color.red >> 8, color.green >> 8, color.blue >> 8);
2038 gtk_css_provider_load_from_data (FRAME_X_OUTPUT (f)->scrollbar_foreground_css_provider,
2039 css, -1, NULL);
2040 }
2041 else
2042 gtk_css_provider_load_from_data (FRAME_X_OUTPUT (f)->scrollbar_foreground_css_provider,
2043 "", -1, NULL);
2044 }
2045 #endif
2046 }
2047
2048
2049
2050
2051
2052
2053
2054 static void
2055 x_set_scroll_bar_background (struct frame *f, Lisp_Object value, Lisp_Object oldval)
2056 {
2057 unsigned long pixel;
2058 #ifdef HAVE_GTK3
2059 XColor color;
2060 char css[64];
2061 #endif
2062
2063 if (STRINGP (value))
2064 pixel = x_decode_color (f, value, WHITE_PIX_DEFAULT (f));
2065 else
2066 pixel = -1;
2067
2068 if (f->output_data.x->scroll_bar_background_pixel != -1)
2069 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
2070
2071 #if defined (USE_LUCID) && defined (USE_TOOLKIT_SCROLL_BARS)
2072
2073 if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
2074 {
2075 unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
2076 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
2077 }
2078 if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
2079 {
2080 unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
2081 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
2082 }
2083 #endif
2084
2085 f->output_data.x->scroll_bar_background_pixel = pixel;
2086 if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
2087 {
2088
2089 if (FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
2090 (*FRAME_TERMINAL (f)->condemn_scroll_bars_hook) (f);
2091 if (FRAME_TERMINAL (f)->judge_scroll_bars_hook)
2092 (*FRAME_TERMINAL (f)->judge_scroll_bars_hook) (f);
2093
2094 update_face_from_frame_parameter (f, Qscroll_bar_background, value);
2095 redraw_frame (f);
2096 }
2097
2098 #ifdef HAVE_GTK3
2099 if (!FRAME_TOOLTIP_P (f))
2100 {
2101 if (pixel != -1)
2102 {
2103 color.pixel = pixel;
2104
2105 XQueryColor (FRAME_X_DISPLAY (f),
2106 FRAME_X_COLORMAP (f),
2107 &color);
2108
2109 sprintf (css, "scrollbar trough { background-color: #%02x%02x%02x; }",
2110 color.red >> 8, color.green >> 8, color.blue >> 8);
2111 gtk_css_provider_load_from_data (FRAME_X_OUTPUT (f)->scrollbar_background_css_provider,
2112 css, -1, NULL);
2113 }
2114 else
2115 gtk_css_provider_load_from_data (FRAME_X_OUTPUT (f)->scrollbar_background_css_provider,
2116 "", -1, NULL);
2117 }
2118 #endif
2119 }
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137 static unsigned char *
2138 x_encode_text (Lisp_Object string, Lisp_Object coding_system,
2139 ptrdiff_t *text_bytes, bool *stringp, bool *freep)
2140 {
2141 int result = string_xstring_p (string);
2142 struct coding_system coding;
2143
2144 if (result == 0)
2145 {
2146
2147 *text_bytes = SBYTES (string);
2148 *stringp = true;
2149 *freep = false;
2150 return SDATA (string);
2151 }
2152
2153 setup_coding_system (coding_system, &coding);
2154 coding.mode |= (CODING_MODE_SAFE_ENCODING | CODING_MODE_LAST_BLOCK);
2155
2156 coding.common_flags &= ~CODING_ANNOTATION_MASK;
2157 coding.destination = xnmalloc (SCHARS (string), 2);
2158 coding.dst_bytes = SCHARS (string) * 2;
2159 encode_coding_object (&coding, string, 0, 0,
2160 SCHARS (string), SBYTES (string), Qnil);
2161 *text_bytes = coding.produced;
2162 *stringp = (result == 1 || !EQ (coding_system, Qcompound_text));
2163 *freep = true;
2164 return coding.destination;
2165 }
2166
2167
2168
2169
2170
2171
2172 static void
2173 x_set_name_internal (struct frame *f, Lisp_Object name)
2174 {
2175 if (FRAME_X_WINDOW (f))
2176 {
2177 block_input ();
2178 {
2179 XTextProperty text, icon;
2180 ptrdiff_t bytes;
2181 bool stringp;
2182 bool do_free_icon_value = false, do_free_text_value = false;
2183 Lisp_Object coding_system;
2184 Lisp_Object encoded_name;
2185 Lisp_Object encoded_icon_name;
2186
2187
2188
2189 encoded_name = ENCODE_UTF_8 (name);
2190
2191 coding_system = Qcompound_text;
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211 text.value = x_encode_text (name, coding_system, &bytes,
2212 &stringp, &do_free_text_value);
2213 text.encoding = (stringp ? XA_STRING
2214 : FRAME_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2215 text.format = 8;
2216 text.nitems = bytes;
2217
2218 if (!STRINGP (f->icon_name))
2219 {
2220 icon = text;
2221 encoded_icon_name = encoded_name;
2222 }
2223 else
2224 {
2225
2226 icon.value = x_encode_text (f->icon_name, coding_system, &bytes,
2227 &stringp, &do_free_icon_value);
2228 icon.encoding = (stringp ? XA_STRING
2229 : FRAME_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
2230 icon.format = 8;
2231 icon.nitems = bytes;
2232
2233 encoded_icon_name = ENCODE_UTF_8 (f->icon_name);
2234 }
2235
2236 #ifdef USE_GTK
2237 gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
2238 SSDATA (encoded_name));
2239 #else
2240 XSetWMName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text);
2241 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
2242 FRAME_DISPLAY_INFO (f)->Xatom_net_wm_name,
2243 FRAME_DISPLAY_INFO (f)->Xatom_UTF8_STRING,
2244 8, PropModeReplace,
2245 SDATA (encoded_name),
2246 SBYTES (encoded_name));
2247 #endif
2248
2249 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &icon);
2250 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
2251 FRAME_DISPLAY_INFO (f)->Xatom_net_wm_icon_name,
2252 FRAME_DISPLAY_INFO (f)->Xatom_UTF8_STRING,
2253 8, PropModeReplace,
2254 SDATA (encoded_icon_name),
2255 SBYTES (encoded_icon_name));
2256
2257 if (do_free_icon_value)
2258 xfree (icon.value);
2259 if (do_free_text_value)
2260 xfree (text.value);
2261 }
2262 unblock_input ();
2263 }
2264 }
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277 static void
2278 x_set_name (struct frame *f, Lisp_Object name, bool explicit)
2279 {
2280
2281
2282 if (explicit)
2283 {
2284
2285
2286 if (f->explicit_name && NILP (name))
2287 update_mode_lines = 37;
2288
2289 f->explicit_name = ! NILP (name);
2290 }
2291 else if (f->explicit_name)
2292 return;
2293
2294
2295 if (NILP (name))
2296 {
2297
2298
2299 if (!strcmp (FRAME_DISPLAY_INFO (f)->x_id_name,
2300 SSDATA (f->name)))
2301 return;
2302 name = build_string (FRAME_DISPLAY_INFO (f)->x_id_name);
2303 }
2304 else
2305 CHECK_STRING (name);
2306
2307
2308 if (! NILP (Fstring_equal (name, f->name)))
2309 return;
2310
2311 fset_name (f, name);
2312
2313
2314
2315 if (! NILP (f->title))
2316 name = f->title;
2317
2318 x_set_name_internal (f, name);
2319 }
2320
2321
2322
2323
2324 static void
2325 x_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
2326 {
2327 x_set_name (f, arg, true);
2328 }
2329
2330
2331
2332
2333 void
2334 x_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
2335 {
2336 x_set_name (f, arg, false);
2337 }
2338
2339
2340
2341
2342 static void
2343 x_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name)
2344 {
2345
2346 if (EQ (name, f->title))
2347 return;
2348
2349 update_mode_lines = 38;
2350
2351 fset_title (f, name);
2352
2353 if (NILP (name))
2354 name = f->name;
2355 else
2356 CHECK_STRING (name);
2357
2358 x_set_name_internal (f, name);
2359 }
2360
2361 void
2362 x_set_scroll_bar_default_width (struct frame *f)
2363 {
2364 int unit = FRAME_COLUMN_WIDTH (f);
2365 #ifdef USE_TOOLKIT_SCROLL_BARS
2366 #ifdef USE_GTK
2367 int minw = xg_get_default_scrollbar_width (f);
2368 #else
2369 int minw = 16;
2370 #endif
2371
2372 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (minw + unit - 1) / unit;
2373 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = minw;
2374 #else
2375
2376 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit;
2377 FRAME_CONFIG_SCROLL_BAR_WIDTH (f)
2378 = FRAME_CONFIG_SCROLL_BAR_COLS (f) * unit;
2379 #endif
2380 }
2381
2382 void
2383 x_set_scroll_bar_default_height (struct frame *f)
2384 {
2385 int height = FRAME_LINE_HEIGHT (f);
2386 #ifdef USE_TOOLKIT_SCROLL_BARS
2387 #ifdef USE_GTK
2388 int min_height = xg_get_default_scrollbar_height (f);
2389 #else
2390 int min_height = 16;
2391 #endif
2392
2393 FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = min_height;
2394 FRAME_CONFIG_SCROLL_BAR_LINES (f) = (min_height + height - 1) / height;
2395 #else
2396
2397 FRAME_CONFIG_SCROLL_BAR_LINES (f) = (14 + height - 1) / height;
2398
2399
2400
2401 FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = 14;
2402 #endif
2403 }
2404
2405 static void
2406 x_set_alpha (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
2407 {
2408 double alpha = 1.0;
2409 double newval[2];
2410 int i;
2411 Lisp_Object item;
2412 bool alpha_identical_p;
2413
2414 alpha_identical_p = true;
2415
2416 for (i = 0; i < 2; i++)
2417 {
2418 newval[i] = 1.0;
2419 if (CONSP (arg))
2420 {
2421 item = CAR (arg);
2422 arg = CDR (arg);
2423
2424 alpha_identical_p = false;
2425 }
2426 else
2427 item = arg;
2428
2429 if (NILP (item))
2430 alpha = - 1.0;
2431 else if (FLOATP (item))
2432 {
2433 alpha = XFLOAT_DATA (item);
2434 if (! (0 <= alpha && alpha <= 1.0))
2435 args_out_of_range (make_float (0.0), make_float (1.0));
2436 }
2437 else if (FIXNUMP (item))
2438 {
2439 EMACS_INT ialpha = XFIXNUM (item);
2440 if (! (0 <= ialpha && ialpha <= 100))
2441 args_out_of_range (make_fixnum (0), make_fixnum (100));
2442 alpha = ialpha / 100.0;
2443 }
2444 else
2445 wrong_type_argument (Qnumberp, item);
2446 newval[i] = alpha;
2447 }
2448
2449 for (i = 0; i < 2; i++)
2450 f->alpha[i] = newval[i];
2451
2452 FRAME_X_OUTPUT (f)->alpha_identical_p = alpha_identical_p;
2453
2454 if (FRAME_TERMINAL (f)->set_frame_alpha_hook)
2455 {
2456 block_input ();
2457 FRAME_TERMINAL (f)->set_frame_alpha_hook (f);
2458 unblock_input ();
2459 }
2460 }
2461
2462 static void
2463 x_set_use_frame_synchronization (struct frame *f, Lisp_Object arg,
2464 Lisp_Object oldval)
2465 {
2466 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
2467 struct x_display_info *dpyinfo;
2468 unsigned long bypass_compositor;
2469
2470 dpyinfo = FRAME_DISPLAY_INFO (f);
2471
2472 if (!NILP (arg) && FRAME_X_EXTENDED_COUNTER (f))
2473 {
2474 FRAME_X_OUTPUT (f)->use_vsync_p
2475 = x_wm_supports (f, dpyinfo->Xatom_net_wm_frame_drawn);
2476
2477
2478
2479
2480 bypass_compositor = 2;
2481 XChangeProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
2482 dpyinfo->Xatom_net_wm_bypass_compositor,
2483 XA_CARDINAL, 32, PropModeReplace,
2484 (unsigned char *) &bypass_compositor, 1);
2485 }
2486 else
2487 {
2488 FRAME_X_OUTPUT (f)->use_vsync_p = false;
2489
2490
2491
2492 XDeleteProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
2493 dpyinfo->Xatom_net_wm_bypass_compositor);
2494 }
2495
2496 store_frame_param (f, Quse_frame_synchronization,
2497 FRAME_X_OUTPUT (f)->use_vsync_p ? Qt : Qnil);
2498 #else
2499 store_frame_param (f, Quse_frame_synchronization, Qnil);
2500 #endif
2501 }
2502
2503
2504
2505
2506
2507
2508
2509 static Lisp_Object
2510 x_default_scroll_bar_color_parameter (struct frame *f,
2511 Lisp_Object alist, Lisp_Object prop,
2512 const char *xprop, const char *xclass,
2513 bool foreground_p)
2514 {
2515 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
2516 Lisp_Object tem;
2517
2518 tem = gui_display_get_arg (dpyinfo, alist, prop, xprop, xclass,
2519 RES_TYPE_STRING);
2520 if (BASE_EQ (tem, Qunbound))
2521 {
2522 #ifdef USE_TOOLKIT_SCROLL_BARS
2523
2524
2525
2526 AUTO_STRING (foreground, "foreground");
2527 AUTO_STRING (background, "foreground");
2528 AUTO_STRING (verticalScrollBar, "verticalScrollBar");
2529 tem = (gui_display_get_resource
2530 (dpyinfo, foreground_p ? foreground : background,
2531 empty_unibyte_string,
2532 verticalScrollBar,
2533 empty_unibyte_string));
2534 if (!STRINGP (tem))
2535 {
2536
2537
2538
2539
2540
2541 tem = Qnil;
2542 }
2543
2544 #else
2545
2546 tem = Qnil;
2547
2548 #endif
2549 }
2550
2551 AUTO_FRAME_ARG (arg, prop, tem);
2552 gui_set_frame_parameters (f, arg);
2553 return tem;
2554 }
2555
2556
2557
2558
2559 #ifdef USE_X_TOOLKIT
2560
2561
2562
2563
2564
2565
2566 static void
2567 hack_wm_protocols (struct frame *f, Widget widget)
2568 {
2569 Display *dpy = XtDisplay (widget);
2570 Window w = XtWindow (widget);
2571 bool need_delete = true;
2572 bool need_focus = true;
2573 bool need_save = true;
2574
2575 block_input ();
2576 {
2577 Atom type;
2578 unsigned char *catoms;
2579 int format = 0;
2580 unsigned long nitems = 0;
2581 unsigned long bytes_after;
2582
2583 if ((XGetWindowProperty (dpy, w,
2584 FRAME_DISPLAY_INFO (f)->Xatom_wm_protocols,
2585 0, 100, False, XA_ATOM,
2586 &type, &format, &nitems, &bytes_after,
2587 &catoms)
2588 == Success)
2589 && format == 32 && type == XA_ATOM)
2590 {
2591 Atom *atoms = (Atom *) catoms;
2592 while (nitems > 0)
2593 {
2594 nitems--;
2595 if (atoms[nitems]
2596 == FRAME_DISPLAY_INFO (f)->Xatom_wm_delete_window)
2597 need_delete = false;
2598 else if (atoms[nitems]
2599 == FRAME_DISPLAY_INFO (f)->Xatom_wm_take_focus)
2600 need_focus = false;
2601 else if (atoms[nitems]
2602 == FRAME_DISPLAY_INFO (f)->Xatom_wm_save_yourself)
2603 need_save = false;
2604 }
2605 }
2606 if (catoms)
2607 XFree (catoms);
2608 }
2609 {
2610 Atom props[10];
2611 int count = 0;
2612 if (need_delete)
2613 props[count++] = FRAME_DISPLAY_INFO (f)->Xatom_wm_delete_window;
2614 if (need_focus)
2615 props[count++] = FRAME_DISPLAY_INFO (f)->Xatom_wm_take_focus;
2616 if (need_save)
2617 props[count++] = FRAME_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
2618 if (count)
2619 XChangeProperty (dpy, w, FRAME_DISPLAY_INFO (f)->Xatom_wm_protocols,
2620 XA_ATOM, 32, PropModeAppend,
2621 (unsigned char *) props, count);
2622 }
2623 unblock_input ();
2624 }
2625 #endif
2626
2627 static void
2628 append_wm_protocols (struct x_display_info *dpyinfo,
2629 struct frame *f)
2630 {
2631 unsigned char *existing = NULL;
2632 int format = 0;
2633 unsigned long nitems = 0;
2634 Atom type;
2635 Atom *existing_protocols;
2636 Atom protos[10];
2637 int num_protos = 0;
2638 bool found_wm_ping = false;
2639 #if !defined HAVE_GTK3 && defined HAVE_XSYNC
2640 bool found_wm_sync_request = false;
2641 #endif
2642 unsigned long bytes_after;
2643
2644 block_input ();
2645 if ((XGetWindowProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
2646 dpyinfo->Xatom_wm_protocols,
2647 0, 100, False, XA_ATOM, &type, &format, &nitems,
2648 &bytes_after, &existing) == Success)
2649 && format == 32 && type == XA_ATOM)
2650 {
2651 existing_protocols = (Atom *) existing;
2652
2653 while (nitems)
2654 {
2655 nitems--;
2656
2657 if (existing_protocols[nitems]
2658 == dpyinfo->Xatom_net_wm_ping)
2659 found_wm_ping = true;
2660 #if !defined HAVE_GTK3 && defined HAVE_XSYNC
2661 else if (existing_protocols[nitems]
2662 == dpyinfo->Xatom_net_wm_sync_request)
2663 found_wm_sync_request = true;
2664 #endif
2665 }
2666 }
2667
2668 if (existing)
2669 XFree (existing);
2670
2671 if (!dpyinfo->untrusted)
2672 {
2673
2674
2675
2676 if (!found_wm_ping)
2677 protos[num_protos++] = dpyinfo->Xatom_net_wm_ping;
2678 #if !defined HAVE_GTK3 && defined HAVE_XSYNC
2679 if (!found_wm_sync_request && dpyinfo->xsync_supported_p)
2680 protos[num_protos++] = dpyinfo->Xatom_net_wm_sync_request;
2681 #endif
2682 }
2683
2684 if (num_protos)
2685 XChangeProperty (dpyinfo->display,
2686 FRAME_OUTER_WINDOW (f),
2687 dpyinfo->Xatom_wm_protocols,
2688 XA_ATOM, 32, PropModeAppend,
2689 (unsigned char *) protos,
2690 num_protos);
2691 unblock_input ();
2692 }
2693
2694
2695
2696
2697
2698 #ifdef HAVE_X_I18N
2699
2700 static void xic_preedit_draw_callback (XIC, XPointer,
2701 XIMPreeditDrawCallbackStruct *);
2702 static void xic_preedit_caret_callback (XIC, XPointer,
2703 XIMPreeditCaretCallbackStruct *);
2704 static void xic_preedit_done_callback (XIC, XPointer, XPointer);
2705 static int xic_preedit_start_callback (XIC, XPointer, XPointer);
2706 static void xic_string_conversion_callback (XIC, XPointer,
2707 XIMStringConversionCallbackStruct *);
2708
2709 #ifndef HAVE_XICCALLBACK_CALLBACK
2710 #define XICCallback XIMCallback
2711 #define XICProc XIMProc
2712 #endif
2713
2714 static XIMCallback Xxic_preedit_draw_callback =
2715 {
2716 NULL,
2717 (XIMProc) xic_preedit_draw_callback,
2718 };
2719
2720 static XIMCallback Xxic_preedit_caret_callback =
2721 {
2722 NULL,
2723 (XIMProc) xic_preedit_caret_callback,
2724 };
2725
2726 static XIMCallback Xxic_preedit_done_callback =
2727 {
2728 NULL,
2729 (XIMProc) xic_preedit_done_callback,
2730 };
2731
2732 static XICCallback Xxic_preedit_start_callback =
2733 {
2734 NULL,
2735 (XICProc) xic_preedit_start_callback,
2736 };
2737
2738 static XIMCallback Xxic_string_conversion_callback =
2739 {
2740
2741 NULL,
2742 (XIMProc) xic_string_conversion_callback,
2743 };
2744
2745 #if defined HAVE_X_WINDOWS && defined USE_X_TOOLKIT
2746
2747
2748 static const char xic_default_fontset[] = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
2749
2750
2751
2752 char *
2753 xic_create_fontsetname (const char *base_fontname, bool motif)
2754 {
2755 const char *sep = motif ? ";" : ",";
2756 char *fontsetname;
2757 char *z;
2758
2759
2760 if (xic_default_fontset == base_fontname)
2761 {
2762
2763 fontsetname = xmalloc (strlen (base_fontname) + 2);
2764 z = stpcpy (fontsetname, base_fontname);
2765 }
2766 else
2767 {
2768
2769
2770
2771
2772
2773 const char *p = base_fontname;
2774 ptrdiff_t i;
2775
2776 for (i = 0; *p; p++)
2777 if (*p == '-') i++;
2778 if (i != 14)
2779 {
2780
2781
2782
2783 fontsetname = xmalloc (strlen (base_fontname)
2784 + strlen (xic_default_fontset) + 3);
2785 z = stpcpy (fontsetname, base_fontname);
2786 z = stpcpy (z, sep);
2787 z = stpcpy (z, xic_default_fontset);
2788 }
2789 else
2790 {
2791 ptrdiff_t len;
2792 const char *p1 = NULL, *p2 = NULL, *p3 = NULL;
2793 char *font_allcs = NULL;
2794 char *font_allfamilies = NULL;
2795 char *font_all = NULL;
2796 const char *allcs = "*-*-*-*-*-*-*";
2797 const char *allfamilies = "-*-*-";
2798 const char *all = "*-*-*-*-";
2799 char *base;
2800
2801 for (i = 0, p = base_fontname; i < 8; p++)
2802 {
2803 if (*p == '-')
2804 {
2805 i++;
2806 if (i == 3)
2807 p1 = p + 1;
2808 else if (i == 7)
2809 p2 = p + 1;
2810 else if (i == 6)
2811 p3 = p + 1;
2812 }
2813 }
2814
2815
2816 if (*p3 != '*')
2817 {
2818 ptrdiff_t diff = (p2 - p3) - 2;
2819
2820 base = alloca (strlen (base_fontname) + 1);
2821 memcpy (base, base_fontname, p3 - base_fontname);
2822 base[p3 - base_fontname] = '*';
2823 base[(p3 - base_fontname) + 1] = '-';
2824 strcpy (base + (p3 - base_fontname) + 2, p2);
2825 p = base + (p - base_fontname) - diff;
2826 p1 = base + (p1 - base_fontname);
2827 p2 = base + (p2 - base_fontname) - diff;
2828 base_fontname = base;
2829 }
2830
2831
2832 len = p - base_fontname + strlen (allcs) + 1;
2833 font_allcs = alloca (len);
2834 memcpy (font_allcs, base_fontname, p - base_fontname);
2835 strcpy (font_allcs + (p - base_fontname), allcs);
2836
2837
2838
2839 len = p - p1 + strlen (allcs) + strlen (allfamilies) + 1;
2840 font_allfamilies = alloca (len);
2841 strcpy (font_allfamilies, allfamilies);
2842 memcpy (font_allfamilies + strlen (allfamilies), p1, p - p1);
2843 strcpy (font_allfamilies + strlen (allfamilies) + (p - p1), allcs);
2844
2845
2846 len = p - p2 + strlen (allcs) + strlen (all) + strlen (allfamilies) + 1;
2847 font_all = alloca (len);
2848 z = stpcpy (font_all, allfamilies);
2849 z = stpcpy (z, all);
2850 memcpy (z, p2, p - p2);
2851 strcpy (z + (p - p2), allcs);
2852
2853
2854 len = strlen (base_fontname) + strlen (font_allcs)
2855 + strlen (font_allfamilies) + strlen (font_all) + 5;
2856 fontsetname = xmalloc (len);
2857 z = stpcpy (fontsetname, base_fontname);
2858 z = stpcpy (z, sep);
2859 z = stpcpy (z, font_allcs);
2860 z = stpcpy (z, sep);
2861 z = stpcpy (z, font_allfamilies);
2862 z = stpcpy (z, sep);
2863 z = stpcpy (z, font_all);
2864 }
2865 }
2866 if (motif)
2867 strcpy (z, ":");
2868 return fontsetname;
2869 }
2870 #endif
2871
2872 #ifdef DEBUG_XIC_FONTSET
2873 static void
2874 print_fontset_result (XFontSet xfs, char *name, char **missing_list,
2875 int missing_count)
2876 {
2877 if (xfs)
2878 fprintf (stderr, "XIC Fontset created: %s\n", name);
2879 else
2880 {
2881 fprintf (stderr, "XIC Fontset failed: %s\n", name);
2882 while (missing_count-- > 0)
2883 {
2884 fprintf (stderr, " missing: %s\n", *missing_list);
2885 missing_list++;
2886 }
2887 }
2888
2889 }
2890 #endif
2891
2892 static XFontSet
2893 xic_create_xfontset (struct frame *f)
2894 {
2895 XFontSet xfs = NULL;
2896 struct font *font = FRAME_FONT (f);
2897 int pixel_size = font->pixel_size;
2898 Lisp_Object rest, frame;
2899
2900
2901 FOR_EACH_FRAME (rest, frame)
2902 {
2903 struct frame *cf = XFRAME (frame);
2904
2905 if (cf != f && FRAME_LIVE_P (f) && FRAME_X_P (cf)
2906 && FRAME_DISPLAY_INFO (cf) == FRAME_DISPLAY_INFO (f)
2907 && FRAME_FONT (f)
2908 && FRAME_FONT (f)->pixel_size == pixel_size)
2909 {
2910 xfs = FRAME_XIC_FONTSET (cf);
2911 break;
2912 }
2913 }
2914
2915 if (! xfs)
2916 {
2917 char buf[256];
2918 char **missing_list;
2919 int missing_count;
2920 char *def_string;
2921 const char *xlfd_format = "-*-*-medium-r-normal--%d-*-*-*-*-*";
2922
2923 sprintf (buf, xlfd_format, pixel_size);
2924 missing_list = NULL;
2925 xfs = XCreateFontSet (FRAME_X_DISPLAY (f), buf,
2926 &missing_list, &missing_count, &def_string);
2927 #ifdef DEBUG_XIC_FONTSET
2928 print_fontset_result (xfs, buf, missing_list, missing_count);
2929 #endif
2930 if (missing_list)
2931 XFreeStringList (missing_list);
2932 if (! xfs)
2933 {
2934
2935
2936 int sizes[] = {0, 8, 10, 11, 12, 14, 17, 18, 20, 24, 26, 34, 0};
2937 int *smaller, *larger;
2938
2939 for (smaller = sizes; smaller[1]; smaller++)
2940 if (smaller[1] >= pixel_size)
2941 break;
2942 larger = smaller + 1;
2943 if (*larger == pixel_size)
2944 larger++;
2945 while (*smaller || *larger)
2946 {
2947 int this_size;
2948
2949 if (! *larger)
2950 this_size = *smaller--;
2951 else if (! *smaller)
2952 this_size = *larger++;
2953 else if (pixel_size - *smaller < *larger - pixel_size)
2954 this_size = *smaller--;
2955 else
2956 this_size = *larger++;
2957 sprintf (buf, xlfd_format, this_size);
2958 missing_list = NULL;
2959 xfs = XCreateFontSet (FRAME_X_DISPLAY (f), buf,
2960 &missing_list, &missing_count, &def_string);
2961 #ifdef DEBUG_XIC_FONTSET
2962 print_fontset_result (xfs, buf, missing_list, missing_count);
2963 #endif
2964 if (missing_list)
2965 XFreeStringList (missing_list);
2966 if (xfs)
2967 break;
2968 }
2969 }
2970 if (! xfs)
2971 {
2972 const char *last_resort = "-*-*-*-r-normal--*-*-*-*-*-*";
2973
2974 missing_list = NULL;
2975 xfs = XCreateFontSet (FRAME_X_DISPLAY (f), last_resort,
2976 &missing_list, &missing_count, &def_string);
2977 #ifdef DEBUG_XIC_FONTSET
2978 print_fontset_result (xfs, last_resort, missing_list, missing_count);
2979 #endif
2980 if (missing_list)
2981 XFreeStringList (missing_list);
2982 }
2983
2984 }
2985
2986 return xfs;
2987 }
2988
2989
2990
2991 void
2992 xic_free_xfontset (struct frame *f)
2993 {
2994 Lisp_Object rest, frame;
2995 bool shared_p = false;
2996
2997 if (!FRAME_XIC_FONTSET (f))
2998 return;
2999
3000
3001 FOR_EACH_FRAME (rest, frame)
3002 {
3003 struct frame *cf = XFRAME (frame);
3004 if (cf != f && FRAME_LIVE_P (f) && FRAME_X_P (cf)
3005 && FRAME_DISPLAY_INFO (cf) == FRAME_DISPLAY_INFO (f)
3006 && FRAME_XIC_FONTSET (cf) == FRAME_XIC_FONTSET (f))
3007 {
3008 shared_p = true;
3009 break;
3010 }
3011 }
3012
3013 if (!shared_p)
3014
3015 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
3016
3017 FRAME_XIC_FONTSET (f) = NULL;
3018 }
3019
3020
3021
3022 static const XIMStyle supported_xim_styles[] =
3023 {
3024 STYLE_NONE,
3025 STYLE_CALLBACK,
3026 STYLE_OVERTHESPOT,
3027 STYLE_OFFTHESPOT,
3028 STYLE_ROOT
3029 };
3030
3031
3032
3033
3034
3035 static XIMStyle
3036 best_xim_style (struct x_display_info *dpyinfo,
3037 XIMStyles *xim)
3038 {
3039 int i, j;
3040 int nr_supported = ARRAYELTS (supported_xim_styles);
3041
3042 if (dpyinfo->preferred_xim_style)
3043 return dpyinfo->preferred_xim_style;
3044
3045 for (i = 0; i < nr_supported; ++i)
3046 for (j = 0; j < xim->count_styles; ++j)
3047 if (supported_xim_styles[i] == xim->supported_styles[j])
3048 return supported_xim_styles[i];
3049
3050
3051 return XIMPreeditNothing | XIMStatusNothing;
3052 }
3053
3054
3055
3056 void
3057 create_frame_xic (struct frame *f)
3058 {
3059 XIM xim;
3060 XIC xic = NULL;
3061 XFontSet xfs = NULL;
3062 XVaNestedList status_attr = NULL;
3063 XVaNestedList preedit_attr = NULL;
3064 XRectangle s_area;
3065 XPoint spot;
3066 XIMStyle xic_style;
3067
3068 if (FRAME_XIC (f))
3069 goto out;
3070
3071 xim = FRAME_X_XIM (f);
3072 if (!xim || ! FRAME_X_XIM_STYLES(f))
3073 goto out;
3074
3075
3076 xic_style = best_xim_style (FRAME_DISPLAY_INFO (f),
3077 FRAME_X_XIM_STYLES (f));
3078
3079
3080 if (xic_style & (XIMPreeditPosition | XIMStatusArea))
3081 {
3082 xfs = xic_create_xfontset (f);
3083 if (!xfs)
3084 goto out;
3085
3086 FRAME_XIC_FONTSET (f) = xfs;
3087 }
3088
3089 if (xic_style & XIMPreeditPosition)
3090 {
3091 spot.x = 0; spot.y = 1;
3092 preedit_attr = XVaCreateNestedList (0,
3093 XNFontSet, xfs,
3094 XNForeground,
3095 FRAME_FOREGROUND_PIXEL (f),
3096 XNBackground,
3097 FRAME_BACKGROUND_PIXEL (f),
3098 (xic_style & XIMPreeditPosition
3099 ? XNSpotLocation
3100 : NULL),
3101 &spot,
3102 NULL);
3103
3104 if (!preedit_attr)
3105 goto out;
3106 }
3107
3108 if (xic_style & XIMStatusArea)
3109 {
3110 s_area.x = 0; s_area.y = 0; s_area.width = 1; s_area.height = 1;
3111 status_attr = XVaCreateNestedList (0,
3112 XNArea,
3113 &s_area,
3114 XNFontSet,
3115 xfs,
3116 XNForeground,
3117 FRAME_FOREGROUND_PIXEL (f),
3118 XNBackground,
3119 FRAME_BACKGROUND_PIXEL (f),
3120 NULL);
3121
3122 if (!status_attr)
3123 goto out;
3124 }
3125
3126 if (xic_style & XIMPreeditCallbacks)
3127 {
3128 spot.x = 0;
3129 spot.y = 0;
3130 preedit_attr = XVaCreateNestedList (0,
3131 XNSpotLocation, &spot,
3132 XNPreeditStartCallback, &Xxic_preedit_start_callback,
3133 XNPreeditDoneCallback, &Xxic_preedit_done_callback,
3134 XNPreeditDrawCallback, &Xxic_preedit_draw_callback,
3135 XNPreeditCaretCallback, &Xxic_preedit_caret_callback,
3136 NULL);
3137
3138 if (!preedit_attr)
3139 goto out;
3140 }
3141
3142 if (preedit_attr && status_attr)
3143 xic = XCreateIC (xim,
3144 XNInputStyle, xic_style,
3145 XNClientWindow, FRAME_X_WINDOW (f),
3146 XNFocusWindow, FRAME_X_WINDOW (f),
3147 XNStatusAttributes, status_attr,
3148 XNPreeditAttributes, preedit_attr,
3149 XNStringConversionCallback,
3150 &Xxic_string_conversion_callback,
3151 NULL);
3152 else if (preedit_attr)
3153 xic = XCreateIC (xim,
3154 XNInputStyle, xic_style,
3155 XNClientWindow, FRAME_X_WINDOW (f),
3156 XNFocusWindow, FRAME_X_WINDOW (f),
3157 XNPreeditAttributes, preedit_attr,
3158 XNStringConversionCallback,
3159 &Xxic_string_conversion_callback,
3160 NULL);
3161 else if (status_attr)
3162 xic = XCreateIC (xim,
3163 XNInputStyle, xic_style,
3164 XNClientWindow, FRAME_X_WINDOW (f),
3165 XNFocusWindow, FRAME_X_WINDOW (f),
3166 XNStatusAttributes, status_attr,
3167 XNStringConversionCallback,
3168 &Xxic_string_conversion_callback,
3169 NULL);
3170 else
3171 xic = XCreateIC (xim,
3172 XNInputStyle, xic_style,
3173 XNClientWindow, FRAME_X_WINDOW (f),
3174 XNFocusWindow, FRAME_X_WINDOW (f),
3175 XNStringConversionCallback,
3176 &Xxic_string_conversion_callback,
3177 NULL);
3178
3179 if (!xic)
3180 goto out;
3181
3182 FRAME_XIC (f) = xic;
3183 FRAME_XIC_STYLE (f) = xic_style;
3184 xfs = NULL;
3185
3186 out:
3187
3188 if (xfs)
3189 free_frame_xic (f);
3190
3191 if (preedit_attr)
3192 XFree (preedit_attr);
3193
3194 if (status_attr)
3195 XFree (status_attr);
3196 }
3197
3198
3199
3200
3201 void
3202 free_frame_xic (struct frame *f)
3203 {
3204 if (FRAME_XIC (f) == NULL)
3205 return;
3206
3207 XDestroyIC (FRAME_XIC (f));
3208 xic_free_xfontset (f);
3209
3210 FRAME_XIC (f) = NULL;
3211 }
3212
3213
3214
3215
3216
3217 void
3218 xic_set_preeditarea (struct window *w, int x, int y)
3219 {
3220 struct frame *f = WINDOW_XFRAME (w);
3221 XVaNestedList attr;
3222 XPoint spot;
3223
3224 if (FRAME_XIC (f))
3225 {
3226 spot.x = (WINDOW_TO_FRAME_PIXEL_X (w, x)
3227 + WINDOW_LEFT_FRINGE_WIDTH (w)
3228 + WINDOW_LEFT_MARGIN_WIDTH (w));
3229 spot.y = (WINDOW_TO_FRAME_PIXEL_Y (w, y)
3230 + w->phys_cursor_height);
3231
3232 if (FRAME_XIC_STYLE (f) & XIMPreeditCallbacks)
3233 attr = XVaCreateNestedList (0, XNSpotLocation, &spot,
3234 XNPreeditStartCallback, &Xxic_preedit_start_callback,
3235 XNPreeditDoneCallback, &Xxic_preedit_done_callback,
3236 XNPreeditDrawCallback, &Xxic_preedit_draw_callback,
3237 XNPreeditCaretCallback, &Xxic_preedit_caret_callback,
3238 NULL);
3239 else
3240 attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL);
3241 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
3242 XFree (attr);
3243 }
3244 #ifdef USE_GTK
3245 if (f->tooltip)
3246 return;
3247
3248 GdkRectangle rect;
3249 int scale = xg_get_scale (f);
3250
3251 rect.x = (WINDOW_TO_FRAME_PIXEL_X (w, x)
3252 + WINDOW_LEFT_FRINGE_WIDTH (w)
3253 + WINDOW_LEFT_MARGIN_WIDTH (w)) / scale;
3254 rect.y = (WINDOW_TO_FRAME_PIXEL_Y (w, y)
3255 + FRAME_TOOLBAR_HEIGHT (f)
3256 + FRAME_MENUBAR_HEIGHT (f)) / scale;
3257 rect.width = w->phys_cursor_width / scale;
3258 rect.height = w->phys_cursor_height / scale;
3259
3260 gtk_im_context_set_cursor_location (FRAME_X_OUTPUT (f)->im_context,
3261 &rect);
3262 #endif
3263 }
3264
3265
3266
3267
3268 void
3269 xic_set_statusarea (struct frame *f)
3270 {
3271 XIC xic = FRAME_XIC (f);
3272 XVaNestedList attr;
3273 XRectangle area;
3274 XRectangle *needed;
3275
3276
3277
3278 area.x = area.y = area.width = area.height = 0;
3279 attr = XVaCreateNestedList (0, XNAreaNeeded, &area, NULL);
3280 XSetICValues (xic, XNStatusAttributes, attr, NULL);
3281 XFree (attr);
3282
3283 attr = XVaCreateNestedList (0, XNAreaNeeded, &needed, NULL);
3284 XGetICValues (xic, XNStatusAttributes, attr, NULL);
3285 XFree (attr);
3286
3287 if (needed->width == 0)
3288 {
3289 attr = XVaCreateNestedList (0, XNArea, &needed, NULL);
3290 XGetICValues (xic, XNStatusAttributes, attr, NULL);
3291 XFree (attr);
3292 }
3293
3294 area.width = needed->width;
3295 area.height = needed->height;
3296 area.x = FRAME_PIXEL_WIDTH (f) - area.width - FRAME_INTERNAL_BORDER_WIDTH (f);
3297 area.y = (FRAME_PIXEL_HEIGHT (f) - area.height
3298 - FRAME_MENUBAR_HEIGHT (f)
3299 - FRAME_TOOLBAR_TOP_HEIGHT (f)
3300 - FRAME_INTERNAL_BORDER_WIDTH (f));
3301 XFree (needed);
3302
3303 attr = XVaCreateNestedList (0, XNArea, &area, NULL);
3304 XSetICValues (xic, XNStatusAttributes, attr, NULL);
3305 XFree (attr);
3306 }
3307
3308 static struct frame *
3309 x_xic_to_frame (XIC xic)
3310 {
3311 Lisp_Object tail, tem;
3312 struct frame *f;
3313
3314 FOR_EACH_FRAME (tail, tem)
3315 {
3316 f = XFRAME (tem);
3317
3318 if (FRAME_X_P (f) && FRAME_XIC (f) == xic)
3319 return f;
3320 }
3321
3322 return NULL;
3323 }
3324
3325 static int
3326 xic_preedit_start_callback (XIC xic, XPointer client_data,
3327 XPointer call_data)
3328 {
3329 struct frame *f = x_xic_to_frame (xic);
3330 struct x_output *output;
3331
3332 if (f)
3333 {
3334 output = FRAME_X_OUTPUT (f);
3335
3336 output->preedit_size = 0;
3337 output->preedit_active = true;
3338 output->preedit_caret = 0;
3339
3340 if (output->preedit_chars)
3341 xfree (output->preedit_chars);
3342
3343 output->preedit_chars = NULL;
3344 }
3345
3346 return -1;
3347 }
3348
3349 static void
3350 xic_preedit_caret_callback (XIC xic, XPointer client_data,
3351 XIMPreeditCaretCallbackStruct *call_data)
3352 {
3353 struct frame *f = x_xic_to_frame (xic);
3354 struct x_output *output;
3355 struct input_event ie;
3356 EVENT_INIT (ie);
3357
3358 if (f)
3359 {
3360 output = FRAME_X_OUTPUT (f);
3361
3362 if (!output->preedit_active)
3363 return;
3364
3365 switch (call_data->direction)
3366 {
3367 case XIMAbsolutePosition:
3368 output->preedit_caret = call_data->position;
3369 break;
3370 case XIMForwardChar:
3371 case XIMForwardWord:
3372 call_data->position = output->preedit_caret++;
3373 break;
3374 case XIMBackwardChar:
3375 case XIMBackwardWord:
3376 call_data->position = max (0, output->preedit_caret--);
3377 break;
3378 default:
3379 call_data->position = output->preedit_caret;
3380 }
3381
3382 if (output->preedit_chars)
3383 {
3384 ie.kind = PREEDIT_TEXT_EVENT;
3385 XSETFRAME (ie.frame_or_window, f);
3386 ie.arg = make_string_from_utf8 (output->preedit_chars,
3387 output->preedit_size);
3388
3389 if (SCHARS (ie.arg))
3390 Fput_text_property (make_fixnum (min (SCHARS (ie.arg) - 1,
3391 max (0, output->preedit_caret))),
3392 make_fixnum (max (SCHARS (ie.arg),
3393 max (0, output->preedit_caret) + 1)),
3394 Qcursor, Qt, ie.arg);
3395
3396 XSETINT (ie.x, 0);
3397 XSETINT (ie.y, 0);
3398
3399 kbd_buffer_store_event (&ie);
3400 }
3401 }
3402 }
3403
3404
3405 static void
3406 xic_preedit_done_callback (XIC xic, XPointer client_data,
3407 XPointer call_data)
3408 {
3409 struct frame *f = x_xic_to_frame (xic);
3410 struct x_output *output;
3411 struct input_event ie;
3412 EVENT_INIT (ie);
3413
3414 if (f)
3415 {
3416 ie.kind = PREEDIT_TEXT_EVENT;
3417 ie.arg = Qnil;
3418 XSETFRAME (ie.frame_or_window, f);
3419 XSETINT (ie.x, 0);
3420 XSETINT (ie.y, 0);
3421 kbd_buffer_store_event (&ie);
3422
3423 output = FRAME_X_OUTPUT (f);
3424
3425 if (output->preedit_chars)
3426 xfree (output->preedit_chars);
3427
3428 output->preedit_size = 0;
3429 output->preedit_active = false;
3430 output->preedit_chars = NULL;
3431 output->preedit_caret = 0;
3432 }
3433 }
3434
3435 struct x_xim_text_conversion_data
3436 {
3437 struct coding_system *coding;
3438 char *source;
3439 struct x_display_info *dpyinfo;
3440 size_t size;
3441 };
3442
3443 static Lisp_Object
3444 x_xim_text_to_utf8_unix_1 (ptrdiff_t nargs, Lisp_Object *args)
3445 {
3446 struct x_xim_text_conversion_data *data;
3447 ptrdiff_t nbytes;
3448 Lisp_Object coding_system;
3449
3450 data = xmint_pointer (args[0]);
3451
3452 if (SYMBOLP (Vx_input_coding_system))
3453 coding_system = Vx_input_coding_system;
3454 else if (!NILP (data->dpyinfo->xim_coding))
3455 coding_system = data->dpyinfo->xim_coding;
3456 else
3457 coding_system = Vlocale_coding_system;
3458
3459 nbytes = strlen (data->source);
3460
3461 data->coding->destination = NULL;
3462
3463 setup_coding_system (coding_system, data->coding);
3464 data->coding->mode |= (CODING_MODE_LAST_BLOCK
3465 | CODING_MODE_SAFE_ENCODING);
3466 data->coding->source = (const unsigned char *) data->source;
3467 data->coding->dst_bytes = 2048;
3468 data->coding->destination = xmalloc (2048);
3469 decode_coding_object (data->coding, Qnil, 0, 0,
3470 nbytes, nbytes, Qnil);
3471
3472 return Qnil;
3473 }
3474
3475 static Lisp_Object
3476 x_encode_xim_text_1 (ptrdiff_t nargs, Lisp_Object *args)
3477 {
3478 struct x_xim_text_conversion_data *data;
3479 ptrdiff_t nbytes;
3480 Lisp_Object coding_system;
3481
3482 data = xmint_pointer (args[0]);
3483
3484 if (SYMBOLP (Vx_input_coding_system))
3485 coding_system = Vx_input_coding_system;
3486 else if (!NILP (data->dpyinfo->xim_coding))
3487 coding_system = data->dpyinfo->xim_coding;
3488 else
3489 coding_system = Vlocale_coding_system;
3490
3491 nbytes = data->size;
3492
3493 data->coding->destination = NULL;
3494
3495 setup_coding_system (coding_system, data->coding);
3496 data->coding->mode |= (CODING_MODE_LAST_BLOCK
3497 | CODING_MODE_SAFE_ENCODING);
3498 data->coding->source = (const unsigned char *) data->source;
3499 data->coding->dst_bytes = 2048;
3500 data->coding->destination = xmalloc (2048);
3501 encode_coding_object (data->coding, Qnil, 0, 0,
3502 nbytes, nbytes, Qnil);
3503
3504 return Qnil;
3505 }
3506
3507 static Lisp_Object
3508 x_xim_text_to_utf8_unix_2 (Lisp_Object val, ptrdiff_t nargs,
3509 Lisp_Object *args)
3510 {
3511 struct x_xim_text_conversion_data *data;
3512
3513 data = xmint_pointer (args[0]);
3514
3515 if (data->coding->destination)
3516 xfree (data->coding->destination);
3517
3518 data->coding->destination = NULL;
3519
3520 return Qnil;
3521 }
3522
3523
3524 static char *
3525 x_xim_text_to_utf8_unix (struct x_display_info *dpyinfo,
3526 XIMText *text, ptrdiff_t *length)
3527 {
3528 unsigned char *wchar_buf;
3529 ptrdiff_t wchar_actual_length, i;
3530 struct coding_system coding;
3531 struct x_xim_text_conversion_data data;
3532 bool was_waiting_for_input_p;
3533 Lisp_Object arg;
3534
3535 if (text->encoding_is_wchar)
3536 {
3537 wchar_buf = xmalloc ((text->length + 1) * MAX_MULTIBYTE_LENGTH);
3538 wchar_actual_length = 0;
3539
3540 for (i = 0; i < text->length; ++i)
3541 wchar_actual_length += CHAR_STRING (text->string.wide_char[i],
3542 wchar_buf + wchar_actual_length);
3543 *length = wchar_actual_length;
3544
3545 return (char *) wchar_buf;
3546 }
3547
3548 data.coding = &coding;
3549 data.source = text->string.multi_byte;
3550 data.dpyinfo = dpyinfo;
3551
3552 was_waiting_for_input_p = waiting_for_input;
3553
3554 waiting_for_input = false;
3555 arg = make_mint_ptr (&data);
3556 internal_condition_case_n (x_xim_text_to_utf8_unix_1, 1, &arg,
3557 Qt, x_xim_text_to_utf8_unix_2);
3558 waiting_for_input = was_waiting_for_input_p;
3559
3560 *length = coding.produced;
3561 return (char *) coding.destination;
3562 }
3563
3564
3565
3566
3567
3568
3569
3570
3571 static char *
3572 x_encode_xim_text (struct x_display_info *dpyinfo, char *text,
3573 size_t size, ptrdiff_t *length,
3574 ptrdiff_t *chars)
3575 {
3576 struct coding_system coding;
3577 struct x_xim_text_conversion_data data;
3578 Lisp_Object arg;
3579 bool was_waiting_for_input_p;
3580
3581 data.coding = &coding;
3582 data.source = text;
3583 data.dpyinfo = dpyinfo;
3584 data.size = size;
3585
3586 was_waiting_for_input_p = waiting_for_input;
3587
3588 waiting_for_input = false;
3589
3590 arg = make_mint_ptr (&data);
3591 internal_condition_case_n (x_encode_xim_text_1, 1, &arg,
3592 Qt, x_xim_text_to_utf8_unix_2);
3593 waiting_for_input = was_waiting_for_input_p;
3594
3595 if (length)
3596 *length = coding.produced;
3597
3598 if (chars)
3599 *chars = coding.produced_char;
3600
3601 return (char *) coding.destination;
3602 }
3603
3604 static void
3605 xic_preedit_draw_callback (XIC xic, XPointer client_data,
3606 XIMPreeditDrawCallbackStruct *call_data)
3607 {
3608 struct frame *f;
3609 struct x_output *output;
3610 ptrdiff_t text_length;
3611 ptrdiff_t charpos;
3612 ptrdiff_t original_size;
3613 char *text;
3614 char *chg_start, *chg_end;
3615 struct input_event ie;
3616
3617 f = x_xic_to_frame (xic);
3618 EVENT_INIT (ie);
3619
3620 if (f)
3621 {
3622 text_length = 0;
3623 output = FRAME_X_OUTPUT (f);
3624
3625 if (!output->preedit_active)
3626 return;
3627
3628 if (call_data->text)
3629 {
3630 text = x_xim_text_to_utf8_unix (FRAME_DISPLAY_INFO (f),
3631 call_data->text, &text_length);
3632
3633 if (!text)
3634
3635 goto im_abort;
3636 }
3637 else
3638 text = NULL;
3639
3640 original_size = output->preedit_size;
3641
3642
3643
3644 if (!call_data->chg_length)
3645 {
3646 if (!text)
3647 goto im_abort;
3648
3649 if (output->preedit_chars)
3650 output->preedit_chars = xrealloc (output->preedit_chars,
3651 output->preedit_size += text_length);
3652 else
3653 output->preedit_chars = xmalloc (output->preedit_size += text_length);
3654 }
3655
3656 chg_start = output->preedit_chars;
3657
3658
3659
3660 if (!output->preedit_chars && call_data->chg_first)
3661 goto im_abort;
3662
3663
3664
3665 if (call_data->chg_first)
3666 {
3667 charpos = 0;
3668
3669 while (charpos < call_data->chg_first)
3670 {
3671 chg_start += BYTES_BY_CHAR_HEAD (*chg_start);
3672
3673 if ((chg_start - output->preedit_chars) > output->preedit_size)
3674
3675
3676 goto im_abort;
3677 ++charpos;
3678 }
3679 }
3680
3681 if (!call_data->chg_length)
3682 {
3683 if (!text)
3684 goto im_abort;
3685
3686 memmove (chg_start + text_length, chg_start,
3687 original_size - (chg_start - output->preedit_chars));
3688 memcpy (chg_start, text, text_length);
3689 }
3690 else
3691 {
3692 if (call_data->chg_length < 1)
3693 goto im_abort;
3694
3695 charpos = 0;
3696 chg_end = chg_start;
3697
3698 while (charpos < call_data->chg_length)
3699 {
3700 chg_end += BYTES_BY_CHAR_HEAD (*chg_end);
3701
3702 if ((chg_end - output->preedit_chars) > output->preedit_size)
3703
3704
3705 goto im_abort;
3706 ++charpos;
3707 }
3708
3709 memmove (chg_start, chg_end, ((output->preedit_chars
3710 + output->preedit_size) - chg_end));
3711 output->preedit_size -= (chg_end - chg_start);
3712
3713 if (text)
3714 {
3715 original_size = output->preedit_size;
3716 output->preedit_chars = xrealloc (output->preedit_chars,
3717 output->preedit_size += text_length);
3718
3719
3720
3721 chg_start = output->preedit_chars;
3722 charpos = 0;
3723
3724 while (charpos < call_data->chg_first)
3725 {
3726 chg_start += BYTES_BY_CHAR_HEAD (*chg_start);
3727
3728 if ((chg_start - output->preedit_chars) > output->preedit_size)
3729
3730
3731 goto im_abort;
3732 ++charpos;
3733 }
3734
3735 memmove (chg_start + text_length, chg_start,
3736 original_size - (chg_start - output->preedit_chars));
3737 memcpy (chg_start, text, text_length);
3738 }
3739 }
3740
3741 if (text)
3742 xfree (text);
3743
3744 output->preedit_caret = call_data->caret;
3745
3746
3747
3748
3749 ie.kind = PREEDIT_TEXT_EVENT;
3750 XSETFRAME (ie.frame_or_window, f);
3751 ie.arg = make_string_from_utf8 (output->preedit_chars,
3752 output->preedit_size);
3753
3754 if (SCHARS (ie.arg))
3755 Fput_text_property (make_fixnum (min (SCHARS (ie.arg) - 1,
3756 max (0, output->preedit_caret))),
3757 make_fixnum (min (SCHARS (ie.arg),
3758 max (0, output->preedit_caret) + 1)),
3759 Qcursor, Qt, ie.arg);
3760
3761 XSETINT (ie.x, 0);
3762 XSETINT (ie.y, 0);
3763
3764 kbd_buffer_store_event (&ie);
3765 }
3766
3767 return;
3768
3769 im_abort:
3770 if (text)
3771 xfree (text);
3772 if (output->preedit_chars)
3773 xfree (output->preedit_chars);
3774 output->preedit_chars = NULL;
3775 output->preedit_size = 0;
3776 output->preedit_active = false;
3777 output->preedit_caret = 0;
3778 }
3779
3780 void
3781 xic_set_xfontset (struct frame *f, const char *base_fontname)
3782 {
3783 XVaNestedList attr;
3784 XFontSet xfs;
3785
3786 xic_free_xfontset (f);
3787
3788 xfs = xic_create_xfontset (f);
3789
3790 attr = XVaCreateNestedList (0, XNFontSet, xfs, NULL);
3791 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
3792 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
3793 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
3794 XSetICValues (FRAME_XIC (f), XNStatusAttributes, attr, NULL);
3795 XFree (attr);
3796
3797 FRAME_XIC_FONTSET (f) = xfs;
3798 }
3799
3800
3801
3802
3803
3804 static void
3805 xic_string_conversion_callback (XIC ic, XPointer client_data,
3806 XIMStringConversionCallbackStruct *call_data)
3807 {
3808 struct textconv_callback_struct request;
3809 ptrdiff_t length;
3810 struct frame *f;
3811 int rc;
3812
3813
3814 f = x_xic_to_frame (ic);
3815
3816 if (!f)
3817 goto failure;
3818
3819
3820 call_data->text->feedback = NULL;
3821 call_data->text->encoding_is_wchar = False;
3822
3823
3824
3825 request.position = call_data->position;
3826
3827 switch (call_data->direction)
3828 {
3829 case XIMForwardChar:
3830 request.direction = TEXTCONV_FORWARD_CHAR;
3831 break;
3832
3833 case XIMBackwardChar:
3834 request.direction = TEXTCONV_BACKWARD_CHAR;
3835 break;
3836
3837 case XIMForwardWord:
3838 request.direction = TEXTCONV_FORWARD_WORD;
3839 break;
3840
3841 case XIMBackwardWord:
3842 request.direction = TEXTCONV_BACKWARD_WORD;
3843 break;
3844
3845 case XIMCaretUp:
3846 request.direction = TEXTCONV_CARET_UP;
3847 break;
3848
3849 case XIMCaretDown:
3850 request.direction = TEXTCONV_CARET_DOWN;
3851 break;
3852
3853 case XIMNextLine:
3854 request.direction = TEXTCONV_NEXT_LINE;
3855 break;
3856
3857 case XIMPreviousLine:
3858 request.direction = TEXTCONV_PREVIOUS_LINE;
3859 break;
3860
3861 case XIMLineStart:
3862 request.direction = TEXTCONV_LINE_START;
3863 break;
3864
3865 case XIMLineEnd:
3866 request.direction = TEXTCONV_LINE_END;
3867 break;
3868
3869 case XIMAbsolutePosition:
3870 request.direction = TEXTCONV_ABSOLUTE_POSITION;
3871 break;
3872
3873 default:
3874 goto failure;
3875 }
3876
3877
3878 request.factor = call_data->factor;
3879
3880 if (call_data->operation == XIMStringConversionSubstitution)
3881 request.operation = TEXTCONV_SUBSTITUTION;
3882 else
3883 request.operation = TEXTCONV_RETRIEVAL;
3884
3885
3886 rc = textconv_query (f, &request, 0);
3887
3888 if (rc)
3889 {
3890 xfree (request.text.text);
3891 goto failure;
3892 }
3893
3894
3895
3896 request.text.text = NULL;
3897 call_data->text->string.mbs
3898 = x_encode_xim_text (FRAME_DISPLAY_INFO (f),
3899 request.text.text,
3900 request.text.bytes, NULL,
3901 &length);
3902 call_data->text->length = length;
3903
3904
3905
3906 xfree (request.text.text);
3907
3908
3909 if (!call_data->text->string.mbs)
3910 goto failure;
3911
3912 return;
3913
3914 failure:
3915
3916
3917
3918 call_data->text->length = 0;
3919 call_data->text->string.mbs = malloc (0);
3920 }
3921
3922 #endif
3923
3924
3925
3926
3927 void
3928 x_mark_frame_dirty (struct frame *f)
3929 {
3930 #ifdef HAVE_XDBE
3931 if (FRAME_X_DOUBLE_BUFFERED_P (f)
3932 && !FRAME_X_NEED_BUFFER_FLIP (f))
3933 FRAME_X_NEED_BUFFER_FLIP (f) = true;
3934 #endif
3935 }
3936
3937 static void
3938 set_up_x_back_buffer (struct frame *f)
3939 {
3940 #ifdef HAVE_XRENDER
3941 block_input ();
3942 if (FRAME_X_PICTURE (f) != None)
3943 {
3944 XRenderFreePicture (FRAME_X_DISPLAY (f),
3945 FRAME_X_PICTURE (f));
3946 FRAME_X_PICTURE (f) = None;
3947 }
3948 unblock_input ();
3949 #endif
3950
3951 #ifdef HAVE_XDBE
3952 block_input ();
3953 if (FRAME_X_WINDOW (f) && !FRAME_X_DOUBLE_BUFFERED_P (f))
3954 {
3955 #ifdef USE_CAIRO
3956 x_cr_destroy_frame_context (f);
3957 #endif
3958 FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
3959 if (FRAME_DISPLAY_INFO (f)->supports_xdbe)
3960 {
3961
3962
3963
3964 x_catch_errors (FRAME_X_DISPLAY (f));
3965 FRAME_X_RAW_DRAWABLE (f)
3966 = XdbeAllocateBackBufferName (FRAME_X_DISPLAY (f),
3967 FRAME_X_WINDOW (f),
3968 XdbeCopied);
3969 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
3970 FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
3971 x_uncatch_errors_after_check ();
3972 }
3973 }
3974 unblock_input ();
3975 #endif
3976 }
3977
3978 void
3979 tear_down_x_back_buffer (struct frame *f)
3980 {
3981 #ifdef HAVE_XRENDER
3982 block_input ();
3983 if (FRAME_X_PICTURE (f) != None)
3984 {
3985 XRenderFreePicture (FRAME_X_DISPLAY (f),
3986 FRAME_X_PICTURE (f));
3987 FRAME_X_PICTURE (f) = None;
3988 }
3989 unblock_input ();
3990 #endif
3991
3992 #ifdef HAVE_XDBE
3993 block_input ();
3994 if (FRAME_X_WINDOW (f) && FRAME_X_DOUBLE_BUFFERED_P (f))
3995 {
3996 if (FRAME_X_DOUBLE_BUFFERED_P (f))
3997 {
3998 #ifdef USE_CAIRO
3999 x_cr_destroy_frame_context (f);
4000 #endif
4001 XdbeDeallocateBackBufferName (FRAME_X_DISPLAY (f),
4002 FRAME_X_DRAWABLE (f));
4003 FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
4004 }
4005 }
4006 unblock_input ();
4007 #endif
4008 }
4009
4010
4011
4012 void
4013 initial_set_up_x_back_buffer (struct frame *f)
4014 {
4015 eassert (FRAME_X_WINDOW (f));
4016 FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
4017
4018 if (NILP (CDR (Fassq (Qinhibit_double_buffering,
4019 f->param_alist))))
4020 set_up_x_back_buffer (f);
4021 }
4022
4023 #if defined HAVE_XINPUT2
4024 static void
4025 setup_xi_event_mask (struct frame *f)
4026 {
4027 XIEventMask mask;
4028 ptrdiff_t l = XIMaskLen (XI_LASTEVENT);
4029 unsigned char *m;
4030 #ifndef HAVE_XINPUT2_1
4031
4032
4033 XIEventMask *selected;
4034
4035 selected = xzalloc (sizeof *selected + l);
4036 selected->mask = ((unsigned char *) selected) + sizeof *selected;
4037 selected->mask_len = l;
4038 selected->deviceid = XIAllMasterDevices;
4039 #endif
4040
4041 mask.mask = m = alloca (l);
4042 memset (m, 0, l);
4043 mask.mask_len = l;
4044
4045 block_input ();
4046 #ifndef HAVE_GTK3
4047 mask.deviceid = XIAllMasterDevices;
4048
4049 XISetMask (m, XI_ButtonPress);
4050 XISetMask (m, XI_ButtonRelease);
4051 XISetMask (m, XI_Motion);
4052 XISetMask (m, XI_Enter);
4053 XISetMask (m, XI_Leave);
4054 #ifndef USE_GTK
4055 XISetMask (m, XI_FocusIn);
4056 XISetMask (m, XI_FocusOut);
4057 XISetMask (m, XI_KeyPress);
4058 XISetMask (m, XI_KeyRelease);
4059 #endif
4060 #if defined HAVE_XINPUT2_4
4061 if (FRAME_DISPLAY_INFO (f)->xi2_version >= 4)
4062 {
4063
4064
4065
4066
4067 XISetMask (m, XI_GesturePinchBegin);
4068 XISetMask (m, XI_GesturePinchUpdate);
4069 XISetMask (m, XI_GesturePinchEnd);
4070 }
4071 #endif
4072 XISelectEvents (FRAME_X_DISPLAY (f),
4073 FRAME_X_WINDOW (f),
4074 &mask, 1);
4075
4076
4077
4078 #ifndef HAVE_XINPUT2_1
4079 memcpy (selected->mask, m, l);
4080 #endif
4081
4082 memset (m, 0, l);
4083 #endif
4084
4085 #ifdef USE_X_TOOLKIT
4086 XISetMask (m, XI_KeyPress);
4087 XISetMask (m, XI_KeyRelease);
4088 XISetMask (m, XI_FocusIn);
4089 XISetMask (m, XI_FocusOut);
4090
4091 XISelectEvents (FRAME_X_DISPLAY (f),
4092 FRAME_OUTER_WINDOW (f),
4093 &mask, 1);
4094 memset (m, 0, l);
4095 #endif
4096
4097 #ifdef HAVE_XINPUT2_2
4098 if (FRAME_DISPLAY_INFO (f)->xi2_version >= 2)
4099 {
4100
4101
4102
4103
4104
4105 mask.deviceid = XIAllDevices;
4106
4107 XISetMask (m, XI_TouchBegin);
4108 XISetMask (m, XI_TouchUpdate);
4109 XISetMask (m, XI_TouchEnd);
4110 XISetMask (m, XI_TouchOwnership);
4111
4112 #if defined HAVE_XINPUT2_4 && defined USE_GTK3
4113 if (FRAME_DISPLAY_INFO (f)->xi2_version >= 4)
4114 {
4115
4116
4117
4118
4119
4120 XISetMask (m, XI_GesturePinchBegin);
4121 XISetMask (m, XI_GesturePinchUpdate);
4122 XISetMask (m, XI_GesturePinchEnd);
4123 }
4124 #endif
4125
4126 XISelectEvents (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4127 &mask, 1);
4128 }
4129 #endif
4130
4131 #ifndef HAVE_XINPUT2_1
4132 FRAME_X_OUTPUT (f)->xi_masks = selected;
4133 FRAME_X_OUTPUT (f)->num_xi_masks = 1;
4134 #endif
4135
4136 unblock_input ();
4137 }
4138 #endif
4139
4140 #ifdef USE_X_TOOLKIT
4141
4142
4143
4144 static void
4145 x_window (struct frame *f, long window_prompting)
4146 {
4147 XClassHint class_hints;
4148 XSetWindowAttributes attributes;
4149 unsigned long attribute_mask;
4150 Widget shell_widget;
4151 Widget pane_widget;
4152 Widget frame_widget;
4153 Arg al[25];
4154 int ac;
4155
4156 block_input ();
4157
4158
4159
4160
4161
4162
4163 f->namebuf = xlispstrdup (Vx_resource_name);
4164
4165 ac = 0;
4166 XtSetArg (al[ac], XtNallowShellResize, 1); ac++;
4167 XtSetArg (al[ac], XtNinput, 1); ac++;
4168 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
4169 XtSetArg (al[ac], XtNborderWidth, f->border_width); ac++;
4170 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
4171 XtSetArg (al[ac], XtNdepth, FRAME_DISPLAY_INFO (f)->n_planes); ac++;
4172 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
4173 shell_widget = XtAppCreateShell (f->namebuf, EMACS_CLASS,
4174 applicationShellWidgetClass,
4175 FRAME_X_DISPLAY (f), al, ac);
4176
4177 f->output_data.x->widget = shell_widget;
4178
4179
4180 pane_widget = lw_create_widget ("main", "pane", widget_id_tick++,
4181 NULL, shell_widget, False,
4182 NULL, NULL, NULL, NULL);
4183
4184 ac = 0;
4185 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
4186 XtSetArg (al[ac], XtNdepth, FRAME_DISPLAY_INFO (f)->n_planes); ac++;
4187 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
4188 XtSetArg (al[ac], XtNborderWidth, 0); ac++;
4189 XtSetValues (pane_widget, al, ac);
4190 f->output_data.x->column_widget = pane_widget;
4191
4192
4193
4194
4195 ac = 0;
4196 XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
4197 XtSetArg (al[ac], (char *) XtNshowGrip, 0); ac++;
4198 XtSetArg (al[ac], (char *) XtNallowResize, 1); ac++;
4199 XtSetArg (al[ac], (char *) XtNresizeToPreferred, 1); ac++;
4200 XtSetArg (al[ac], (char *) XtNemacsFrame, f); ac++;
4201 XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
4202 XtSetArg (al[ac], XtNdepth, FRAME_DISPLAY_INFO (f)->n_planes); ac++;
4203 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
4204 XtSetArg (al[ac], XtNborderWidth, 0); ac++;
4205 frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass (), pane_widget,
4206 al, ac);
4207
4208 f->output_data.x->edit_widget = frame_widget;
4209
4210 XtManageChild (frame_widget);
4211
4212
4213 {
4214 Arg gal[3];
4215 int gac = 0;
4216 int extra_borders = 0;
4217 int menubar_size
4218 = (f->output_data.x->menubar_widget
4219 ? (f->output_data.x->menubar_widget->core.height
4220 + f->output_data.x->menubar_widget->core.border_width)
4221 : 0);
4222
4223 #if false
4224
4225 if (FRAME_EXTERNAL_MENU_BAR (f))
4226 {
4227 Dimension ibw = 0;
4228 XtVaGetValues (pane_widget, XtNinternalBorderWidth, &ibw, NULL);
4229 menubar_size += ibw;
4230 }
4231 #endif
4232
4233 FRAME_MENUBAR_HEIGHT (f) = menubar_size;
4234
4235 #ifndef USE_LUCID
4236
4237
4238
4239 XtVaGetValues (f->output_data.x->edit_widget, XtNinternalBorderWidth,
4240 &extra_borders, NULL);
4241 extra_borders *= 2;
4242 #endif
4243
4244 f->shell_position = xmalloc (sizeof "=x++" + 4 * INT_STRLEN_BOUND (int));
4245
4246
4247
4248
4249
4250
4251 {
4252 int left = f->left_pos;
4253 bool xneg = (window_prompting & XNegative) != 0;
4254 int top = f->top_pos;
4255 bool yneg = (window_prompting & YNegative) != 0;
4256 if (xneg)
4257 left = -left;
4258 if (yneg)
4259 top = -top;
4260
4261 if (window_prompting & USPosition)
4262 sprintf (f->shell_position, "=%dx%d%c%d%c%d",
4263 FRAME_PIXEL_WIDTH (f) + extra_borders,
4264 FRAME_PIXEL_HEIGHT (f) + menubar_size + extra_borders,
4265 (xneg ? '-' : '+'), left,
4266 (yneg ? '-' : '+'), top);
4267 else
4268 {
4269 sprintf (f->shell_position, "=%dx%d",
4270 FRAME_PIXEL_WIDTH (f) + extra_borders,
4271 FRAME_PIXEL_HEIGHT (f) + menubar_size + extra_borders);
4272
4273
4274
4275
4276
4277
4278 XtSetArg (gal[gac], XtNx, left); gac++;
4279 XtSetArg (gal[gac], XtNy, top); gac++;
4280 }
4281 }
4282
4283 XtSetArg (gal[gac], XtNgeometry, f->shell_position); gac++;
4284 XtSetValues (shell_widget, gal, gac);
4285 }
4286
4287 XtManageChild (pane_widget);
4288 XtRealizeWidget (shell_widget);
4289
4290 FRAME_X_WINDOW (f) = XtWindow (frame_widget);
4291 initial_set_up_x_back_buffer (f);
4292 validate_x_resource_name ();
4293
4294 class_hints.res_name = SSDATA (Vx_resource_name);
4295 class_hints.res_class = SSDATA (Vx_resource_class);
4296 XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints);
4297
4298 #ifdef HAVE_X_I18N
4299 FRAME_XIC (f) = NULL;
4300 if (FRAME_DISPLAY_INFO (f)->use_xim)
4301 create_frame_xic (f);
4302 #endif
4303
4304 f->output_data.x->wm_hints.input = True;
4305 f->output_data.x->wm_hints.flags |= InputHint;
4306 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4307 &f->output_data.x->wm_hints);
4308
4309 hack_wm_protocols (f, shell_widget);
4310 append_wm_protocols (FRAME_DISPLAY_INFO (f), f);
4311
4312 #ifdef X_TOOLKIT_EDITRES
4313 XtAddEventHandler (shell_widget, 0, True, _XEditResCheckMessages, 0);
4314 #endif
4315
4316
4317
4318
4319
4320 XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
4321 FRAME_DISPLAY_INFO (f)->Xatom_wm_protocols,
4322 XA_ATOM, 32, PropModeAppend, NULL, 0);
4323
4324
4325 attributes.event_mask = STANDARD_EVENT_SET;
4326
4327 #ifdef HAVE_X_I18N
4328 if (FRAME_XIC (f))
4329 {
4330
4331 unsigned long fevent = NoEventMask;
4332 XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
4333 attributes.event_mask |= fevent;
4334 }
4335 #endif
4336
4337 attributes.override_redirect = FRAME_OVERRIDE_REDIRECT (f);
4338 attribute_mask = CWEventMask | CWOverrideRedirect;
4339 XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
4340 attribute_mask, &attributes);
4341
4342 XtMapWidget (frame_widget);
4343
4344
4345
4346
4347
4348 {
4349 Lisp_Object name;
4350 bool explicit = f->explicit_name;
4351
4352 f->explicit_name = false;
4353 name = f->name;
4354 fset_name (f, Qnil);
4355 x_set_name (f, name, explicit);
4356 }
4357
4358 if (FRAME_UNDECORATED (f))
4359 {
4360 Display *dpy = FRAME_X_DISPLAY (f);
4361 PropMotifWmHints hints;
4362 Atom prop = FRAME_DISPLAY_INFO (f)->Xatom_MOTIF_WM_HINTS;
4363
4364 memset (&hints, 0, sizeof(hints));
4365 hints.flags = MWM_HINTS_DECORATIONS;
4366 hints.decorations = 0;
4367
4368
4369
4370
4371
4372 XChangeProperty (dpy, FRAME_OUTER_WINDOW (f), prop, prop, 32,
4373 PropModeReplace, (unsigned char *) &hints,
4374 PROP_MOTIF_WM_HINTS_ELEMENTS);
4375 }
4376
4377 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4378 f->output_data.x->current_cursor
4379 = f->output_data.x->text_cursor);
4380
4381 unblock_input ();
4382
4383
4384
4385 lw_set_main_areas (pane_widget, 0, frame_widget);
4386
4387 #ifdef HAVE_XINPUT2
4388 if (FRAME_DISPLAY_INFO (f)->supports_xi2)
4389 setup_xi_event_mask (f);
4390 #endif
4391 }
4392
4393 #else
4394 #ifdef USE_GTK
4395 static void
4396 x_window (struct frame *f)
4397 {
4398 if (! xg_create_frame_widgets (f))
4399 error ("Unable to create window");
4400
4401 #ifdef HAVE_X_I18N
4402 FRAME_XIC (f) = NULL;
4403 if (FRAME_DISPLAY_INFO (f)->use_xim)
4404 {
4405 block_input ();
4406 create_frame_xic (f);
4407 if (FRAME_XIC (f))
4408 {
4409
4410 unsigned long fevent = NoEventMask;
4411 XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
4412
4413 if (fevent != NoEventMask)
4414 {
4415 XSetWindowAttributes attributes;
4416 XWindowAttributes wattr;
4417 unsigned long attribute_mask;
4418
4419 XGetWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4420 &wattr);
4421 attributes.event_mask = wattr.your_event_mask | fevent;
4422 attribute_mask = CWEventMask;
4423 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4424 attribute_mask, &attributes);
4425 }
4426 }
4427 unblock_input ();
4428 }
4429 #endif
4430
4431 append_wm_protocols (FRAME_DISPLAY_INFO (f), f);
4432
4433 #ifdef HAVE_XINPUT2
4434 if (FRAME_DISPLAY_INFO (f)->supports_xi2)
4435 setup_xi_event_mask (f);
4436 #endif
4437 }
4438
4439 #else
4440
4441
4442 static void
4443 x_window (struct frame *f)
4444 {
4445 XClassHint class_hints;
4446 XSetWindowAttributes attributes;
4447 unsigned long attribute_mask;
4448
4449 attributes.background_pixel = FRAME_BACKGROUND_PIXEL (f);
4450 attributes.border_pixel = f->output_data.x->border_pixel;
4451 attributes.bit_gravity = StaticGravity;
4452 attributes.backing_store = NotUseful;
4453 attributes.save_under = True;
4454 attributes.event_mask = STANDARD_EVENT_SET;
4455 attributes.colormap = FRAME_X_COLORMAP (f);
4456 attributes.override_redirect = FRAME_OVERRIDE_REDIRECT (f);
4457 attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask
4458 | CWOverrideRedirect | CWColormap);
4459
4460 block_input ();
4461 FRAME_X_WINDOW (f)
4462 = XCreateWindow (FRAME_X_DISPLAY (f),
4463 FRAME_DISPLAY_INFO (f)->root_window,
4464 f->left_pos,
4465 f->top_pos,
4466 FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f),
4467 f->border_width,
4468 FRAME_DISPLAY_INFO (f)->n_planes,
4469 InputOutput,
4470 FRAME_X_VISUAL (f),
4471 attribute_mask, &attributes);
4472 initial_set_up_x_back_buffer (f);
4473
4474 #ifdef HAVE_X_I18N
4475 if (FRAME_DISPLAY_INFO (f)->use_xim)
4476 {
4477 create_frame_xic (f);
4478 if (FRAME_XIC (f))
4479 {
4480
4481 unsigned long fevent = NoEventMask;
4482
4483 if (fevent)
4484 {
4485 XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
4486 attributes.event_mask |= fevent;
4487 attribute_mask = CWEventMask;
4488 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4489 attribute_mask, &attributes);
4490 }
4491 }
4492 }
4493 #endif
4494
4495 #ifdef HAVE_XINPUT2
4496 if (FRAME_DISPLAY_INFO (f)->supports_xi2)
4497 setup_xi_event_mask (f);
4498 #endif
4499
4500 validate_x_resource_name ();
4501
4502 class_hints.res_name = SSDATA (Vx_resource_name);
4503 class_hints.res_class = SSDATA (Vx_resource_class);
4504 XSetClassHint (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &class_hints);
4505
4506
4507
4508
4509
4510
4511 f->output_data.x->wm_hints.input = True;
4512 f->output_data.x->wm_hints.flags |= InputHint;
4513 XSetWMHints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4514 &f->output_data.x->wm_hints);
4515 f->output_data.x->wm_hints.icon_pixmap = None;
4516
4517
4518 {
4519 Atom protocols[2];
4520 protocols[0] = FRAME_DISPLAY_INFO (f)->Xatom_wm_delete_window;
4521 protocols[1] = FRAME_DISPLAY_INFO (f)->Xatom_wm_save_yourself;
4522 XSetWMProtocols (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), protocols, 2);
4523 }
4524
4525 append_wm_protocols (FRAME_DISPLAY_INFO (f), f);
4526
4527
4528
4529
4530
4531 {
4532 Lisp_Object name;
4533 bool explicit = f->explicit_name;
4534
4535 f->explicit_name = false;
4536 name = f->name;
4537 fset_name (f, Qnil);
4538 x_set_name (f, name, explicit);
4539 }
4540
4541 if (FRAME_UNDECORATED (f))
4542 {
4543 Display *dpy = FRAME_X_DISPLAY (f);
4544 PropMotifWmHints hints;
4545 Atom prop = FRAME_DISPLAY_INFO (f)->Xatom_MOTIF_WM_HINTS;
4546
4547 memset (&hints, 0, sizeof(hints));
4548 hints.flags = MWM_HINTS_DECORATIONS;
4549 hints.decorations = 0;
4550
4551
4552
4553
4554
4555 XChangeProperty (dpy, FRAME_OUTER_WINDOW (f), prop, prop, 32,
4556 PropModeReplace, (unsigned char *) &hints,
4557 PROP_MOTIF_WM_HINTS_ELEMENTS);
4558 }
4559
4560
4561 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4562 f->output_data.x->current_cursor
4563 = f->output_data.x->text_cursor);
4564
4565 unblock_input ();
4566
4567 if (FRAME_X_WINDOW (f) == 0)
4568 error ("Unable to create window");
4569 }
4570
4571 #endif
4572 #endif
4573
4574
4575
4576 static void
4577 x_icon_verify (struct frame *f, Lisp_Object parms)
4578 {
4579 Lisp_Object icon_x, icon_y;
4580
4581
4582
4583 icon_x = gui_frame_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
4584 icon_y = gui_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
4585 if (!BASE_EQ (icon_x, Qunbound) && !BASE_EQ (icon_y, Qunbound))
4586 {
4587 CHECK_FIXNUM (icon_x);
4588 CHECK_FIXNUM (icon_y);
4589 }
4590 else if (!BASE_EQ (icon_x, Qunbound) || !BASE_EQ (icon_y, Qunbound))
4591 error ("Both left and top icon corners of icon must be specified");
4592 }
4593
4594
4595
4596
4597
4598 static void
4599 x_icon (struct frame *f, Lisp_Object parms)
4600 {
4601
4602
4603 Lisp_Object icon_x
4604 = gui_frame_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
4605 Lisp_Object icon_y
4606 = gui_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
4607 int icon_xval, icon_yval;
4608
4609 bool xgiven = !BASE_EQ (icon_x, Qunbound);
4610 bool ygiven = !BASE_EQ (icon_y, Qunbound);
4611 if (xgiven != ygiven)
4612 error ("Both left and top icon corners of icon must be specified");
4613 if (xgiven)
4614 {
4615 icon_xval = check_integer_range (icon_x, INT_MIN, INT_MAX);
4616 icon_yval = check_integer_range (icon_y, INT_MIN, INT_MAX);
4617 }
4618
4619 block_input ();
4620
4621 if (xgiven)
4622 x_wm_set_icon_position (f, icon_xval, icon_yval);
4623
4624 #if false
4625
4626
4627 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
4628 x_wm_set_window_state
4629 (f, (EQ (gui_display_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
4630 RES_TYPE_SYMBOL),
4631 Qicon)
4632 ? IconicState
4633 : NormalState));
4634 #endif
4635
4636 x_text_icon (f, SSDATA ((!NILP (f->icon_name)
4637 ? f->icon_name
4638 : f->name)));
4639
4640 unblock_input ();
4641 }
4642
4643
4644
4645
4646
4647 static void
4648 x_make_gc (struct frame *f)
4649 {
4650 XGCValues gc_values;
4651
4652 block_input ();
4653
4654
4655
4656
4657 gc_values.foreground = FRAME_FOREGROUND_PIXEL (f);
4658 gc_values.background = FRAME_BACKGROUND_PIXEL (f);
4659 gc_values.line_width = 1;
4660 f->output_data.x->normal_gc
4661 = XCreateGC (FRAME_X_DISPLAY (f),
4662 FRAME_X_DRAWABLE (f),
4663 GCLineWidth | GCForeground | GCBackground,
4664 &gc_values);
4665
4666
4667 gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
4668 gc_values.background = FRAME_FOREGROUND_PIXEL (f);
4669 f->output_data.x->reverse_gc
4670 = XCreateGC (FRAME_X_DISPLAY (f),
4671 FRAME_X_DRAWABLE (f),
4672 GCForeground | GCBackground | GCLineWidth,
4673 &gc_values);
4674
4675
4676 gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
4677 gc_values.background = f->output_data.x->cursor_pixel;
4678 f->output_data.x->cursor_gc
4679 = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
4680 (GCForeground | GCBackground | GCLineWidth),
4681 &gc_values);
4682
4683
4684
4685
4686 f->output_data.x->border_tile
4687 = (XCreatePixmapFromBitmapData
4688 (FRAME_X_DISPLAY (f), FRAME_DISPLAY_INFO (f)->root_window,
4689 gray_bits, gray_width, gray_height,
4690 FRAME_FOREGROUND_PIXEL (f),
4691 FRAME_BACKGROUND_PIXEL (f),
4692 DefaultDepth (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f))));
4693
4694 unblock_input ();
4695 }
4696
4697
4698
4699
4700 void
4701 x_free_gcs (struct frame *f)
4702 {
4703 Display *dpy = FRAME_X_DISPLAY (f);
4704
4705 block_input ();
4706
4707 if (f->output_data.x->normal_gc)
4708 {
4709 XFreeGC (dpy, f->output_data.x->normal_gc);
4710 f->output_data.x->normal_gc = 0;
4711 }
4712
4713 if (f->output_data.x->reverse_gc)
4714 {
4715 XFreeGC (dpy, f->output_data.x->reverse_gc);
4716 f->output_data.x->reverse_gc = 0;
4717 }
4718
4719 if (f->output_data.x->cursor_gc)
4720 {
4721 XFreeGC (dpy, f->output_data.x->cursor_gc);
4722 f->output_data.x->cursor_gc = 0;
4723 }
4724
4725 if (f->output_data.x->border_tile)
4726 {
4727 XFreePixmap (dpy, f->output_data.x->border_tile);
4728 f->output_data.x->border_tile = 0;
4729 }
4730
4731 unblock_input ();
4732 }
4733
4734
4735
4736
4737
4738
4739 static Lisp_Object
4740 unwind_create_frame (Lisp_Object frame)
4741 {
4742 struct frame *f = XFRAME (frame);
4743
4744
4745
4746
4747 if (!FRAME_LIVE_P (f))
4748 return Qnil;
4749
4750
4751 if (NILP (Fmemq (frame, Vframe_list)))
4752 {
4753 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
4754 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
4755 #endif
4756
4757
4758
4759
4760
4761
4762
4763
4764 if (FRAME_IMAGE_CACHE (f) != NULL
4765 && FRAME_IMAGE_CACHE (f)->refcount == image_cache_refcount)
4766 FRAME_IMAGE_CACHE (f)->refcount++;
4767
4768 x_free_frame_resources (f);
4769 free_glyphs (f);
4770
4771 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
4772
4773 eassert (dpyinfo->reference_count == dpyinfo_refcount);
4774 eassert (dpyinfo->terminal->image_cache->refcount == image_cache_refcount);
4775 #endif
4776 return Qt;
4777 }
4778
4779 return Qnil;
4780 }
4781
4782 static void
4783 do_unwind_create_frame (Lisp_Object frame)
4784 {
4785 unwind_create_frame (frame);
4786 }
4787
4788 void
4789 x_default_font_parameter (struct frame *f, Lisp_Object parms)
4790 {
4791 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
4792 Lisp_Object font_param = gui_display_get_arg (dpyinfo, parms, Qfont, NULL, NULL,
4793 RES_TYPE_STRING);
4794 Lisp_Object font = Qnil;
4795 if (BASE_EQ (font_param, Qunbound))
4796 font_param = Qnil;
4797
4798 if (NILP (font_param))
4799 {
4800
4801
4802
4803 const char *system_font = xsettings_get_system_font ();
4804 if (system_font)
4805 font = font_open_by_name (f, build_unibyte_string (system_font));
4806 }
4807
4808 if (NILP (font))
4809 font = (!NILP (font_param)
4810 ? font_param
4811 : gui_display_get_arg (dpyinfo, parms,
4812 Qfont, "font", "Font",
4813 RES_TYPE_STRING));
4814
4815 if (! FONTP (font) && ! STRINGP (font))
4816 {
4817 const char *names[]
4818 = {
4819 #if defined USE_CAIRO || defined HAVE_XFT
4820
4821 "monospace-10",
4822 #endif
4823 "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1",
4824 "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1",
4825 "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1",
4826
4827
4828 "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1",
4829
4830
4831 "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1",
4832 "fixed",
4833 NULL };
4834 int i;
4835
4836 for (i = 0; names[i]; i++)
4837 {
4838 font = font_open_by_name (f, build_unibyte_string (names[i]));
4839 if (! NILP (font))
4840 break;
4841 }
4842 if (NILP (font))
4843 error ("No suitable font was found");
4844 }
4845
4846
4847 gui_default_parameter (f, parms, Qfont, font, "font", "Font", RES_TYPE_STRING);
4848 }
4849
4850
4851 DEFUN ("x-wm-set-size-hint", Fx_wm_set_size_hint, Sx_wm_set_size_hint,
4852 0, 1, 0,
4853 doc:
4854
4855 )
4856 (Lisp_Object frame)
4857 {
4858 struct frame *f = decode_window_system_frame (frame);
4859
4860 block_input ();
4861 x_wm_set_size_hint (f, 0, false);
4862 unblock_input ();
4863 return Qnil;
4864 }
4865
4866 static void
4867 set_machine_and_pid_properties (struct frame *f)
4868 {
4869
4870 XSetWMProperties (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), NULL, NULL,
4871 NULL, 0, NULL, NULL, NULL);
4872 pid_t pid = getpid ();
4873 if (pid <= 0xffffffffu)
4874 {
4875 unsigned long xpid = pid;
4876 XChangeProperty (FRAME_X_DISPLAY (f),
4877 FRAME_OUTER_WINDOW (f),
4878 FRAME_DISPLAY_INFO (f)->Xatom_net_wm_pid,
4879 XA_CARDINAL, 32, PropModeReplace,
4880 (unsigned char *) &xpid, 1);
4881 }
4882 }
4883
4884 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
4885 1, 1, 0,
4886 doc:
4887
4888
4889
4890
4891
4892
4893 )
4894 (Lisp_Object parms)
4895 {
4896 struct frame *f;
4897 Lisp_Object frame, tem;
4898 Lisp_Object name;
4899 bool minibuffer_only = false;
4900 bool undecorated = false, override_redirect = false;
4901 long window_prompting = 0;
4902 specpdl_ref count = SPECPDL_INDEX ();
4903 Lisp_Object display;
4904 struct x_display_info *dpyinfo = NULL;
4905 Lisp_Object parent, parent_frame;
4906 struct kboard *kb;
4907 #ifdef HAVE_GTK3
4908 GdkWindow *gwin;
4909 #endif
4910
4911 parms = Fcopy_alist (parms);
4912
4913
4914
4915 Vx_resource_name = Vinvocation_name;
4916
4917 display = gui_display_get_arg (dpyinfo, parms, Qterminal, 0, 0,
4918 RES_TYPE_NUMBER);
4919 if (BASE_EQ (display, Qunbound))
4920 display = gui_display_get_arg (dpyinfo, parms, Qdisplay, 0, 0,
4921 RES_TYPE_STRING);
4922 if (BASE_EQ (display, Qunbound))
4923 display = Qnil;
4924 dpyinfo = check_x_display_info (display);
4925 kb = dpyinfo->terminal->kboard;
4926
4927 if (!dpyinfo->terminal->name)
4928 error ("Terminal is not live, can't create new frames on it");
4929
4930 name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name",
4931 RES_TYPE_STRING);
4932 if (!STRINGP (name)
4933 && ! BASE_EQ (name, Qunbound)
4934 && ! NILP (name))
4935 error ("Invalid frame name--not a string or nil");
4936
4937 if (STRINGP (name))
4938 Vx_resource_name = name;
4939
4940
4941 parent = gui_display_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL,
4942 RES_TYPE_NUMBER);
4943 if (BASE_EQ (parent, Qunbound))
4944 parent = Qnil;
4945 if (! NILP (parent))
4946 CHECK_FIXNUM (parent);
4947
4948 frame = Qnil;
4949 tem = gui_display_get_arg (dpyinfo,
4950 parms, Qminibuffer, "minibuffer", "Minibuffer",
4951 RES_TYPE_SYMBOL);
4952 if (EQ (tem, Qnone) || NILP (tem))
4953 f = make_frame_without_minibuffer (Qnil, kb, display);
4954 else if (EQ (tem, Qonly))
4955 {
4956 f = make_minibuffer_frame ();
4957 minibuffer_only = true;
4958 }
4959 else if (WINDOWP (tem))
4960 f = make_frame_without_minibuffer (tem, kb, display);
4961 else
4962 f = make_frame (true);
4963
4964 parent_frame = gui_display_get_arg (dpyinfo,
4965 parms,
4966 Qparent_frame,
4967 NULL,
4968 NULL,
4969 RES_TYPE_SYMBOL);
4970
4971 if (!NILP (parent)
4972 || BASE_EQ (parent_frame, Qunbound)
4973 || NILP (parent_frame)
4974 || !FRAMEP (parent_frame)
4975 || !FRAME_LIVE_P (XFRAME (parent_frame))
4976 || !FRAME_X_P (XFRAME (parent_frame)))
4977 parent_frame = Qnil;
4978
4979 fset_parent_frame (f, parent_frame);
4980 store_frame_param (f, Qparent_frame, parent_frame);
4981
4982 if (!NILP (tem = (gui_display_get_arg (dpyinfo,
4983 parms,
4984 Qundecorated,
4985 NULL,
4986 NULL,
4987 RES_TYPE_BOOLEAN)))
4988 && !(BASE_EQ (tem, Qunbound)))
4989 undecorated = true;
4990
4991 FRAME_UNDECORATED (f) = undecorated;
4992 store_frame_param (f, Qundecorated, undecorated ? Qt : Qnil);
4993
4994 if (!NILP (tem = (gui_display_get_arg (dpyinfo,
4995 parms,
4996 Qoverride_redirect,
4997 NULL,
4998 NULL,
4999 RES_TYPE_BOOLEAN)))
5000 && !(BASE_EQ (tem, Qunbound)))
5001 override_redirect = true;
5002
5003 FRAME_OVERRIDE_REDIRECT (f) = override_redirect;
5004 store_frame_param (f, Qoverride_redirect, override_redirect ? Qt : Qnil);
5005
5006 XSETFRAME (frame, f);
5007
5008 f->terminal = dpyinfo->terminal;
5009
5010 f->output_method = output_x_window;
5011 f->output_data.x = xzalloc (sizeof *f->output_data.x);
5012 f->output_data.x->icon_bitmap = -1;
5013 FRAME_FONTSET (f) = -1;
5014 f->output_data.x->scroll_bar_foreground_pixel = -1;
5015 f->output_data.x->scroll_bar_background_pixel = -1;
5016 #if defined (USE_LUCID) && defined (USE_TOOLKIT_SCROLL_BARS)
5017 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
5018 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
5019 #endif
5020 f->output_data.x->white_relief.pixel = -1;
5021 f->output_data.x->black_relief.pixel = -1;
5022 f->output_data.x->visibility_state = VisibilityFullyObscured;
5023
5024 fset_icon_name (f, gui_display_get_arg (dpyinfo,
5025 parms,
5026 Qicon_name,
5027 "iconName",
5028 "Title",
5029 RES_TYPE_STRING));
5030 if (! STRINGP (f->icon_name))
5031 fset_icon_name (f, Qnil);
5032
5033 FRAME_DISPLAY_INFO (f) = dpyinfo;
5034
5035
5036 record_unwind_protect (do_unwind_create_frame, frame);
5037
5038
5039
5040 {
5041 Lisp_Object black;
5042
5043
5044
5045
5046 FRAME_FOREGROUND_PIXEL (f) = -1;
5047 FRAME_BACKGROUND_PIXEL (f) = -1;
5048 f->output_data.x->cursor_pixel = -1;
5049 f->output_data.x->cursor_foreground_pixel = -1;
5050 f->output_data.x->border_pixel = -1;
5051 f->output_data.x->mouse_pixel = -1;
5052
5053 black = build_string ("black");
5054 FRAME_FOREGROUND_PIXEL (f)
5055 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
5056 FRAME_BACKGROUND_PIXEL (f)
5057 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
5058 f->output_data.x->cursor_pixel
5059 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
5060 f->output_data.x->cursor_foreground_pixel
5061 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
5062 f->output_data.x->border_pixel
5063 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
5064 f->output_data.x->mouse_pixel
5065 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
5066 }
5067
5068
5069 if (!NILP (parent))
5070 {
5071 f->output_data.x->parent_desc = (Window) XFIXNAT (parent);
5072 f->output_data.x->explicit_parent = true;
5073 }
5074 else
5075 {
5076 f->output_data.x->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
5077 f->output_data.x->explicit_parent = false;
5078 }
5079
5080
5081
5082 if (BASE_EQ (name, Qunbound) || NILP (name))
5083 {
5084 fset_name (f, build_string (dpyinfo->x_id_name));
5085 f->explicit_name = false;
5086 }
5087 else
5088 {
5089 fset_name (f, name);
5090 f->explicit_name = true;
5091
5092 specbind (Qx_resource_name, name);
5093 }
5094
5095 #ifdef USE_CAIRO
5096 register_font_driver (&ftcrfont_driver, f);
5097 #ifdef HAVE_HARFBUZZ
5098 register_font_driver (&ftcrhbfont_driver, f);
5099 #endif
5100 #else
5101 #ifdef HAVE_FREETYPE
5102 #ifdef HAVE_XFT
5103 register_font_driver (&xftfont_driver, f);
5104 #ifdef HAVE_HARFBUZZ
5105 register_font_driver (&xfthbfont_driver, f);
5106 #endif
5107 #endif
5108 #endif
5109 #endif
5110 register_font_driver (&xfont_driver, f);
5111
5112 image_cache_refcount =
5113 FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
5114 #ifdef GLYPH_DEBUG
5115 dpyinfo_refcount = dpyinfo->reference_count;
5116 #endif
5117
5118 gui_default_parameter (f, parms, Qfont_backend, Qnil,
5119 "fontBackend", "FontBackend", RES_TYPE_STRING);
5120
5121
5122
5123 x_default_font_parameter (f, parms);
5124 if (!FRAME_FONT (f))
5125 {
5126 delete_frame (frame, Qnoelisp);
5127 error ("Invalid frame font");
5128 }
5129
5130
5131 if (! FRAME_X_EMBEDDED_P (f))
5132 gui_default_parameter (f, parms, Qborder_width, make_fixnum (0),
5133 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
5134
5135
5136
5137
5138 if (NILP (Fassq (Qinternal_border_width, parms)))
5139 {
5140 Lisp_Object value;
5141
5142 value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width,
5143 "internalBorder", "internalBorder",
5144 RES_TYPE_NUMBER);
5145 if (! BASE_EQ (value, Qunbound))
5146 parms = Fcons (Fcons (Qinternal_border_width, value),
5147 parms);
5148 }
5149
5150 gui_default_parameter (f, parms, Qinternal_border_width,
5151 #ifdef USE_GTK
5152 make_fixnum (0),
5153 #else
5154 make_fixnum (1),
5155 #endif
5156 "internalBorderWidth", "internalBorderWidth",
5157 RES_TYPE_NUMBER);
5158
5159
5160 if (NILP (Fassq (Qchild_frame_border_width, parms)))
5161 {
5162 Lisp_Object value;
5163
5164 value = gui_display_get_arg (dpyinfo, parms, Qchild_frame_border_width,
5165 "childFrameBorder", "childFrameBorder",
5166 RES_TYPE_NUMBER);
5167 if (! BASE_EQ (value, Qunbound))
5168 parms = Fcons (Fcons (Qchild_frame_border_width, value),
5169 parms);
5170 }
5171
5172 gui_default_parameter (f, parms, Qchild_frame_border_width, Qnil,
5173 "childFrameBorderWidth", "childFrameBorderWidth",
5174 RES_TYPE_NUMBER);
5175 gui_default_parameter (f, parms, Qright_divider_width, make_fixnum (0),
5176 NULL, NULL, RES_TYPE_NUMBER);
5177 gui_default_parameter (f, parms, Qbottom_divider_width, make_fixnum (0),
5178 NULL, NULL, RES_TYPE_NUMBER);
5179 gui_default_parameter (f, parms, Qvertical_scroll_bars,
5180 #if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
5181 Qright,
5182 #else
5183 Qleft,
5184 #endif
5185 "verticalScrollBars", "ScrollBars",
5186 RES_TYPE_SYMBOL);
5187 gui_default_parameter (f, parms, Qhorizontal_scroll_bars, Qnil,
5188 "horizontalScrollBars", "ScrollBars",
5189 RES_TYPE_SYMBOL);
5190
5191 gui_default_parameter (f, parms, Qforeground_color, build_string ("black"),
5192 "foreground", "Foreground", RES_TYPE_STRING);
5193 gui_default_parameter (f, parms, Qbackground_color, build_string ("white"),
5194 "background", "Background", RES_TYPE_STRING);
5195 gui_default_parameter (f, parms, Qmouse_color, build_string ("black"),
5196 "pointerColor", "Foreground", RES_TYPE_STRING);
5197 gui_default_parameter (f, parms, Qborder_color, build_string ("black"),
5198 "borderColor", "BorderColor", RES_TYPE_STRING);
5199 gui_default_parameter (f, parms, Qscreen_gamma, Qnil,
5200 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
5201 gui_default_parameter (f, parms, Qline_spacing, Qnil,
5202 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
5203 gui_default_parameter (f, parms, Qleft_fringe, Qnil,
5204 "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
5205 gui_default_parameter (f, parms, Qright_fringe, Qnil,
5206 "rightFringe", "RightFringe", RES_TYPE_NUMBER);
5207 gui_default_parameter (f, parms, Qno_special_glyphs, Qnil,
5208 NULL, NULL, RES_TYPE_BOOLEAN);
5209
5210 #ifdef HAVE_GTK3
5211 FRAME_OUTPUT_DATA (f)->scrollbar_background_css_provider
5212 = gtk_css_provider_new ();
5213 FRAME_OUTPUT_DATA (f)->scrollbar_foreground_css_provider
5214 = gtk_css_provider_new ();
5215 #endif
5216
5217 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
5218 "scrollBarForeground",
5219 "ScrollBarForeground", true);
5220 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_background,
5221 "scrollBarBackground",
5222 "ScrollBarBackground", false);
5223
5224
5225
5226
5227 init_frame_faces (f);
5228
5229 tem = gui_display_get_arg (dpyinfo, parms, Qmin_width, NULL, NULL,
5230 RES_TYPE_NUMBER);
5231 if (FIXNUMP (tem))
5232 store_frame_param (f, Qmin_width, tem);
5233 tem = gui_display_get_arg (dpyinfo, parms, Qmin_height, NULL, NULL,
5234 RES_TYPE_NUMBER);
5235 if (FIXNUMP (tem))
5236 store_frame_param (f, Qmin_height, tem);
5237
5238 adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
5239 FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, true,
5240 Qx_create_frame_1);
5241
5242
5243
5244
5245
5246
5247 gui_default_parameter (f, parms, Qmenu_bar_lines,
5248 NILP (Vmenu_bar_mode)
5249 ? make_fixnum (0) : make_fixnum (1),
5250 NULL, NULL, RES_TYPE_NUMBER);
5251 gui_default_parameter (f, parms, Qtab_bar_lines,
5252 NILP (Vtab_bar_mode)
5253 ? make_fixnum (0) : make_fixnum (1),
5254 NULL, NULL, RES_TYPE_NUMBER);
5255 gui_default_parameter (f, parms, Qtool_bar_lines,
5256 NILP (Vtool_bar_mode)
5257 ? make_fixnum (0) : make_fixnum (1),
5258 NULL, NULL, RES_TYPE_NUMBER);
5259
5260 gui_default_parameter (f, parms, Qbuffer_predicate, Qnil,
5261 "bufferPredicate", "BufferPredicate",
5262 RES_TYPE_SYMBOL);
5263 gui_default_parameter (f, parms, Qtitle, Qnil,
5264 "title", "Title", RES_TYPE_STRING);
5265 gui_default_parameter (f, parms, Qwait_for_wm, Qt,
5266 "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN);
5267 gui_default_parameter (f, parms, Qtool_bar_position,
5268 FRAME_TOOL_BAR_POSITION (f), 0, 0, RES_TYPE_SYMBOL);
5269 gui_default_parameter (f, parms, Qinhibit_double_buffering, Qnil,
5270 "inhibitDoubleBuffering", "InhibitDoubleBuffering",
5271 RES_TYPE_BOOLEAN);
5272
5273
5274 window_prompting = gui_figure_window_size (f, parms, true, true);
5275
5276 tem = gui_display_get_arg (dpyinfo, parms, Qunsplittable, 0, 0,
5277 RES_TYPE_BOOLEAN);
5278 f->no_split = minibuffer_only || EQ (tem, Qt);
5279
5280 x_icon_verify (f, parms);
5281
5282
5283 #ifdef USE_X_TOOLKIT
5284 x_window (f, window_prompting);
5285 #else
5286 x_window (f);
5287 #endif
5288
5289 #ifndef USE_GTK
5290 if (FRAME_X_EMBEDDED_P (f)
5291 && !x_embed_frame (dpyinfo, f))
5292 error ("The frame could not be embedded; does the embedder exist?");
5293 #endif
5294
5295 x_icon (f, parms);
5296 x_make_gc (f);
5297
5298
5299
5300
5301 #if defined HAVE_XINPUT2 && defined HAVE_XINPUT2_1
5302 if (dpyinfo->supports_xi2)
5303 FRAME_X_OUTPUT (f)->xi_masks
5304 = XIGetSelectedEvents (dpyinfo->display, FRAME_X_WINDOW (f),
5305 &FRAME_X_OUTPUT (f)->num_xi_masks);
5306 #endif
5307
5308
5309 f->terminal->reference_count++;
5310 FRAME_DISPLAY_INFO (f)->reference_count++;
5311 Vframe_list = Fcons (frame, Vframe_list);
5312
5313
5314
5315 gui_default_parameter (f, parms, Qicon_type, Qt,
5316 "bitmapIcon", "BitmapIcon", RES_TYPE_BOOLEAN);
5317
5318 gui_default_parameter (f, parms, Qauto_raise, Qnil,
5319 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
5320 gui_default_parameter (f, parms, Qauto_lower, Qnil,
5321 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
5322 gui_default_parameter (f, parms, Qcursor_type, Qbox,
5323 "cursorType", "CursorType", RES_TYPE_SYMBOL);
5324 gui_default_parameter (f, parms, Qscroll_bar_width, Qnil,
5325 "scrollBarWidth", "ScrollBarWidth",
5326 RES_TYPE_NUMBER);
5327 gui_default_parameter (f, parms, Qscroll_bar_height, Qnil,
5328 "scrollBarHeight", "ScrollBarHeight",
5329 RES_TYPE_NUMBER);
5330 gui_default_parameter (f, parms, Qalpha, Qnil,
5331 "alpha", "Alpha", RES_TYPE_NUMBER);
5332 gui_default_parameter (f, parms, Qalpha_background, Qnil,
5333 "alphaBackground", "AlphaBackground", RES_TYPE_NUMBER);
5334
5335 if (!NILP (parent_frame))
5336 {
5337 struct frame *p = XFRAME (parent_frame);
5338
5339 block_input ();
5340 XReparentWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
5341 FRAME_X_WINDOW (p), f->left_pos, f->top_pos);
5342 #ifdef USE_GTK
5343 if (EQ (x_gtk_resize_child_frames, Qresize_mode))
5344 gtk_container_set_resize_mode
5345 (GTK_CONTAINER (FRAME_GTK_OUTER_WIDGET (f)), GTK_RESIZE_IMMEDIATE);
5346 #endif
5347 #ifdef HAVE_GTK3
5348 gwin = gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (f));
5349 gdk_x11_window_set_frame_sync_enabled (gwin, FALSE);
5350 #endif
5351 unblock_input ();
5352 }
5353
5354 gui_default_parameter (f, parms, Qno_focus_on_map, Qnil,
5355 NULL, NULL, RES_TYPE_BOOLEAN);
5356 gui_default_parameter (f, parms, Qno_accept_focus, Qnil,
5357 NULL, NULL, RES_TYPE_BOOLEAN);
5358
5359 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
5360
5361 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
5362 {
5363
5364
5365 initialize_frame_menubar (f);
5366
5367 #ifndef USE_GTK
5368
5369
5370 lw_set_main_areas (f->output_data.x->column_widget,
5371 f->output_data.x->menubar_widget,
5372 f->output_data.x->edit_widget);
5373 #endif
5374 }
5375 #endif
5376
5377
5378 f->can_set_window_size = true;
5379
5380
5381
5382
5383 block_input ();
5384 x_wm_set_size_hint (f, window_prompting, false);
5385 unblock_input ();
5386
5387 adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
5388 0, true, Qx_create_frame_2);
5389
5390
5391
5392
5393 gui_default_parameter (f, parms, Qfullscreen, Qnil,
5394 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
5395
5396 #ifdef USE_CAIRO
5397
5398
5399
5400
5401
5402
5403 x_cr_update_surface_desired_size (f, FRAME_PIXEL_WIDTH (f),
5404 FRAME_PIXEL_HEIGHT (f));
5405 #endif
5406
5407
5408
5409
5410 if (!f->output_data.x->explicit_parent)
5411 {
5412
5413
5414 Lisp_Object visibility
5415 = gui_display_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
5416 RES_TYPE_SYMBOL);
5417 Lisp_Object height
5418 = gui_display_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
5419 Lisp_Object width
5420 = gui_display_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
5421
5422 if (EQ (visibility, Qicon))
5423 {
5424 f->was_invisible = true;
5425 x_iconify_frame (f);
5426 }
5427 else
5428 {
5429 if (BASE_EQ (visibility, Qunbound))
5430 visibility = Qt;
5431
5432 if (!NILP (visibility))
5433 x_make_frame_visible (f);
5434 else
5435 f->was_invisible = true;
5436 }
5437
5438
5439
5440
5441 f->was_invisible
5442 = (f->was_invisible
5443 && (!BASE_EQ (height, Qunbound) || !BASE_EQ (width, Qunbound)));
5444
5445 store_frame_param (f, Qvisibility, visibility);
5446 }
5447
5448 block_input ();
5449
5450
5451 set_machine_and_pid_properties (f);
5452
5453
5454
5455 if (dpyinfo->client_leader_window != 0)
5456 {
5457 XChangeProperty (FRAME_X_DISPLAY (f),
5458 FRAME_OUTER_WINDOW (f),
5459 dpyinfo->Xatom_wm_client_leader,
5460 XA_WINDOW, 32, PropModeReplace,
5461 (unsigned char *) &dpyinfo->client_leader_window, 1);
5462 }
5463
5464 #ifdef HAVE_XSYNC
5465 if (dpyinfo->xsync_supported_p
5466
5467 && NILP (parent_frame)
5468 && !f->output_data.x->explicit_parent)
5469 {
5470 #ifndef HAVE_GTK3
5471 XSyncValue initial_value;
5472 XSyncCounter counters[2];
5473
5474 AUTO_STRING (synchronizeResize, "synchronizeResize");
5475 AUTO_STRING (SynchronizeResize, "SynchronizeResize");
5476
5477 Lisp_Object value = gui_display_get_resource (dpyinfo,
5478 synchronizeResize,
5479 SynchronizeResize,
5480 Qnil, Qnil);
5481
5482 XSyncIntToValue (&initial_value, 0);
5483 counters[0]
5484 = FRAME_X_BASIC_COUNTER (f)
5485 = XSyncCreateCounter (FRAME_X_DISPLAY (f),
5486 initial_value);
5487
5488 if (STRINGP (value) && !strcmp (SSDATA (value), "extended"))
5489 counters[1]
5490 = FRAME_X_EXTENDED_COUNTER (f)
5491 = XSyncCreateCounter (FRAME_X_DISPLAY (f),
5492 initial_value);
5493
5494 FRAME_X_OUTPUT (f)->current_extended_counter_value
5495 = initial_value;
5496
5497 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
5498 dpyinfo->Xatom_net_wm_sync_request_counter,
5499 XA_CARDINAL, 32, PropModeReplace,
5500 (unsigned char *) &counters,
5501 ((STRINGP (value)
5502 && !strcmp (SSDATA (value), "extended")) ? 2 : 1));
5503
5504 #if defined HAVE_XSYNCTRIGGERFENCE && !defined USE_GTK \
5505 && defined HAVE_CLOCK_GETTIME
5506 x_sync_init_fences (f);
5507 #endif
5508 #endif
5509 }
5510 #endif
5511
5512 unblock_input ();
5513
5514
5515 gui_default_parameter (f, parms, Quse_frame_synchronization, Qt,
5516 NULL, NULL, RES_TYPE_BOOLEAN);
5517
5518
5519 gui_default_parameter (f, parms, Qskip_taskbar, Qnil,
5520 NULL, NULL, RES_TYPE_BOOLEAN);
5521
5522 gui_default_parameter (f, parms, Qz_group, Qnil,
5523 NULL, NULL, RES_TYPE_SYMBOL);
5524
5525
5526
5527 if (FRAME_HAS_MINIBUF_P (f)
5528 && (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame))
5529 || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame)))))
5530 kset_default_minibuffer_frame (kb, frame);
5531
5532
5533
5534
5535 for (tem = parms; CONSP (tem); tem = XCDR (tem))
5536 if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
5537 fset_param_alist (f, Fcons (XCAR (tem), f->param_alist));
5538
5539
5540
5541 Vwindow_list = Qnil;
5542
5543 return unbind_to (count, frame);
5544 }
5545
5546
5547 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
5548 doc:
5549 )
5550 (Lisp_Object color, Lisp_Object frame)
5551 {
5552 XColor foo;
5553 struct frame *f = decode_window_system_frame (frame);
5554
5555 CHECK_STRING (color);
5556
5557 if (x_defined_color (f, SSDATA (color), &foo, false, false))
5558 return Qt;
5559 else
5560 return Qnil;
5561 }
5562
5563 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
5564 doc:
5565 )
5566 (Lisp_Object color, Lisp_Object frame)
5567 {
5568 XColor foo;
5569 struct frame *f = decode_window_system_frame (frame);
5570
5571 CHECK_STRING (color);
5572
5573 if (x_defined_color (f, SSDATA (color), &foo, false, false))
5574 return list3i (foo.red, foo.green, foo.blue);
5575 else
5576 return Qnil;
5577 }
5578
5579 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
5580 doc: )
5581 (Lisp_Object terminal)
5582 {
5583 struct x_display_info *dpyinfo = check_x_display_info (terminal);
5584
5585 if (dpyinfo->n_planes <= 2)
5586 return Qnil;
5587
5588 switch (dpyinfo->visual_info.class)
5589 {
5590 case StaticColor:
5591 case PseudoColor:
5592 case TrueColor:
5593 case DirectColor:
5594 return Qt;
5595
5596 default:
5597 return Qnil;
5598 }
5599 }
5600
5601 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
5602 0, 1, 0,
5603 doc:
5604
5605
5606
5607 )
5608 (Lisp_Object terminal)
5609 {
5610 struct x_display_info *dpyinfo = check_x_display_info (terminal);
5611
5612 if (dpyinfo->n_planes <= 1)
5613 return Qnil;
5614
5615 switch (dpyinfo->visual_info.class)
5616 {
5617 case StaticColor:
5618 case PseudoColor:
5619 case TrueColor:
5620 case DirectColor:
5621 case StaticGray:
5622 case GrayScale:
5623 return Qt;
5624
5625 default:
5626 return Qnil;
5627 }
5628 }
5629
5630 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
5631 0, 1, 0,
5632 doc:
5633
5634
5635
5636
5637
5638
5639
5640 )
5641 (Lisp_Object terminal)
5642 {
5643 struct x_display_info *dpyinfo = check_x_display_info (terminal);
5644
5645 return make_fixnum (x_display_pixel_width (dpyinfo));
5646 }
5647
5648 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
5649 Sx_display_pixel_height, 0, 1, 0,
5650 doc:
5651
5652
5653
5654
5655
5656
5657
5658 )
5659 (Lisp_Object terminal)
5660 {
5661 struct x_display_info *dpyinfo = check_x_display_info (terminal);
5662
5663 return make_fixnum (x_display_pixel_height (dpyinfo));
5664 }
5665
5666 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
5667 0, 1, 0,
5668 doc:
5669
5670
5671
5672 )
5673 (Lisp_Object terminal)
5674 {
5675 struct x_display_info *dpyinfo = check_x_display_info (terminal);
5676
5677 return make_fixnum (dpyinfo->n_planes);
5678 }
5679
5680 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
5681 0, 1, 0,
5682 doc:
5683
5684
5685
5686 )
5687 (Lisp_Object terminal)
5688 {
5689 struct x_display_info *dpyinfo = check_x_display_info (terminal);
5690
5691 if (dpyinfo->visual_info.class != TrueColor
5692 && dpyinfo->visual_info.class != DirectColor)
5693 return make_fixnum (dpyinfo->visual_info.colormap_size);
5694
5695 int nr_planes = dpyinfo->n_planes;
5696
5697
5698
5699
5700
5701
5702 if (nr_planes > 24) nr_planes = 24;
5703
5704 return make_fixnum (1 << nr_planes);
5705 }
5706
5707 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
5708 Sx_server_max_request_size,
5709 0, 1, 0,
5710 doc:
5711
5712
5713
5714
5715
5716 )
5717 (Lisp_Object terminal)
5718 {
5719 struct x_display_info *dpyinfo = check_x_display_info (terminal);
5720
5721 return make_fixnum (MAXREQUEST (dpyinfo->display));
5722 }
5723
5724 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
5725 doc:
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737 )
5738 (Lisp_Object terminal)
5739 {
5740 struct x_display_info *dpyinfo = check_x_display_info (terminal);
5741 const char *vendor = ServerVendor (dpyinfo->display);
5742
5743 if (! vendor) vendor = "";
5744 return build_string (vendor);
5745 }
5746
5747 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
5748 doc:
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764 )
5765 (Lisp_Object terminal)
5766 {
5767 struct x_display_info *dpyinfo = check_x_display_info (terminal);
5768 Display *dpy = dpyinfo->display;
5769
5770 return list3i (ProtocolVersion (dpy), ProtocolRevision (dpy),
5771 VendorRelease (dpy));
5772 }
5773
5774 DEFUN ("x-server-input-extension-version", Fx_server_input_extension_version,
5775 Sx_server_input_extension_version, 0, 1, 0,
5776 doc:
5777
5778
5779
5780
5781 )
5782 (Lisp_Object terminal)
5783 {
5784 #ifdef HAVE_XINPUT2
5785 struct x_display_info *dpyinfo = check_x_display_info (terminal);
5786
5787 return (dpyinfo->supports_xi2
5788 ? list2i (2, dpyinfo->xi2_version)
5789 : Qnil);
5790 #else
5791 return Qnil;
5792 #endif
5793 }
5794
5795 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
5796 doc:
5797
5798
5799
5800
5801
5802
5803
5804 )
5805 (Lisp_Object terminal)
5806 {
5807 struct x_display_info *dpyinfo = check_x_display_info (terminal);
5808
5809 return make_fixnum (ScreenCount (dpyinfo->display));
5810 }
5811
5812 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
5813 doc:
5814
5815
5816
5817
5818
5819
5820
5821 )
5822 (Lisp_Object terminal)
5823 {
5824 struct x_display_info *dpyinfo = check_x_display_info (terminal);
5825
5826 if (dpyinfo->screen_mm_height)
5827 return make_fixnum (dpyinfo->screen_mm_height);
5828
5829 return make_fixnum (HeightMMOfScreen (dpyinfo->screen));
5830 }
5831
5832 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
5833 doc:
5834
5835
5836
5837
5838
5839
5840
5841 )
5842 (Lisp_Object terminal)
5843 {
5844 struct x_display_info *dpyinfo = check_x_display_info (terminal);
5845
5846 if (dpyinfo->screen_mm_width)
5847 return make_fixnum (dpyinfo->screen_mm_width);
5848
5849 return make_fixnum (WidthMMOfScreen (dpyinfo->screen));
5850 }
5851
5852 DEFUN ("x-display-backing-store", Fx_display_backing_store,
5853 Sx_display_backing_store, 0, 1, 0,
5854 doc:
5855
5856
5857
5858
5859
5860
5861 )
5862 (Lisp_Object terminal)
5863 {
5864 struct x_display_info *dpyinfo = check_x_display_info (terminal);
5865 Lisp_Object result;
5866
5867 switch (DoesBackingStore (dpyinfo->screen))
5868 {
5869 case Always:
5870 result = Qalways;
5871 break;
5872
5873 case WhenMapped:
5874 result = Qwhen_mapped;
5875 break;
5876
5877 case NotUseful:
5878 result = Qnot_useful;
5879 break;
5880
5881 default:
5882 error ("Strange value for BackingStore parameter of screen");
5883 }
5884
5885 return result;
5886 }
5887
5888 DEFUN ("x-display-visual-class", Fx_display_visual_class,
5889 Sx_display_visual_class, 0, 1, 0,
5890 doc:
5891
5892
5893
5894
5895
5896
5897
5898 )
5899 (Lisp_Object terminal)
5900 {
5901 struct x_display_info *dpyinfo = check_x_display_info (terminal);
5902 Lisp_Object result;
5903
5904 switch (dpyinfo->visual_info.class)
5905 {
5906 case StaticGray:
5907 result = Qstatic_gray;
5908 break;
5909 case GrayScale:
5910 result = Qgray_scale;
5911 break;
5912 case StaticColor:
5913 result = Qstatic_color;
5914 break;
5915 case PseudoColor:
5916 result = Qpseudo_color;
5917 break;
5918 case TrueColor:
5919 result = Qtrue_color;
5920 break;
5921 case DirectColor:
5922 result = Qdirect_color;
5923 break;
5924 default:
5925 error ("Display has an unknown visual class");
5926 }
5927
5928 return result;
5929 }
5930
5931 DEFUN ("x-display-save-under", Fx_display_save_under,
5932 Sx_display_save_under, 0, 1, 0,
5933 doc:
5934
5935
5936
5937
5938 )
5939 (Lisp_Object terminal)
5940 {
5941 struct x_display_info *dpyinfo = check_x_display_info (terminal);
5942
5943 if (DoesSaveUnders (dpyinfo->screen) == True)
5944 return Qt;
5945 else
5946 return Qnil;
5947 }
5948
5949 #if !(defined USE_GTK && defined HAVE_GTK3)
5950
5951
5952
5953
5954
5955 static bool
5956 x_get_net_workarea (struct x_display_info *dpyinfo, XRectangle *rect)
5957 {
5958 #ifndef USE_XCB
5959 Display *dpy = dpyinfo->display;
5960 long offset, max_len;
5961 Atom target_type, actual_type;
5962 unsigned long actual_size, bytes_remaining;
5963 int rc, actual_format;
5964 unsigned char *tmp_data = NULL;
5965 bool result = false;
5966
5967 x_catch_errors (dpy);
5968 offset = 0;
5969 max_len = 1;
5970 target_type = XA_CARDINAL;
5971 rc = XGetWindowProperty (dpy, dpyinfo->root_window,
5972 dpyinfo->Xatom_net_current_desktop,
5973 offset, max_len, False, target_type,
5974 &actual_type, &actual_format, &actual_size,
5975 &bytes_remaining, &tmp_data);
5976 if (rc == Success && actual_type == target_type && !x_had_errors_p (dpy)
5977 && actual_format == 32 && actual_size == max_len)
5978 {
5979 long current_desktop = ((long *) tmp_data)[0];
5980
5981 XFree (tmp_data);
5982 tmp_data = NULL;
5983
5984 offset = 4 * current_desktop;
5985 max_len = 4;
5986 rc = XGetWindowProperty (dpy, dpyinfo->root_window,
5987 dpyinfo->Xatom_net_workarea,
5988 offset, max_len, False, target_type,
5989 &actual_type, &actual_format, &actual_size,
5990 &bytes_remaining, &tmp_data);
5991 if (rc == Success && actual_type == target_type && !x_had_errors_p (dpy)
5992 && actual_format == 32 && actual_size == max_len)
5993 {
5994 long *values = (long *) tmp_data;
5995
5996 rect->x = values[0];
5997 rect->y = values[1];
5998 rect->width = values[2];
5999 rect->height = values[3];
6000
6001 XFree (tmp_data);
6002 tmp_data = NULL;
6003
6004 result = true;
6005 }
6006 }
6007 if (tmp_data)
6008 XFree (tmp_data);
6009 x_uncatch_errors ();
6010
6011 return result;
6012 #else
6013 xcb_get_property_cookie_t current_desktop_cookie;
6014 xcb_get_property_cookie_t workarea_cookie;
6015 xcb_get_property_reply_t *reply;
6016 xcb_generic_error_t *error;
6017 bool rc;
6018 uint32_t current_workspace, *values;
6019
6020 current_desktop_cookie
6021 = xcb_get_property (dpyinfo->xcb_connection, 0,
6022 (xcb_window_t) dpyinfo->root_window,
6023 (xcb_atom_t) dpyinfo->Xatom_net_current_desktop,
6024 XA_CARDINAL, 0, 1);
6025
6026 workarea_cookie
6027 = xcb_get_property (dpyinfo->xcb_connection, 0,
6028 (xcb_window_t) dpyinfo->root_window,
6029 (xcb_atom_t) dpyinfo->Xatom_net_workarea,
6030 XA_CARDINAL, 0, UINT32_MAX);
6031
6032 reply = xcb_get_property_reply (dpyinfo->xcb_connection,
6033 current_desktop_cookie, &error);
6034 rc = true;
6035
6036 if (!reply)
6037 free (error), rc = false;
6038 else
6039 {
6040 if (xcb_get_property_value_length (reply) != 4
6041 || reply->type != XA_CARDINAL || reply->format != 32)
6042 rc = false;
6043 else
6044 current_workspace = *(uint32_t *) xcb_get_property_value (reply);
6045
6046 free (reply);
6047 }
6048
6049 reply = xcb_get_property_reply (dpyinfo->xcb_connection,
6050 workarea_cookie, &error);
6051
6052 if (!reply)
6053 free (error), rc = false;
6054 else
6055 {
6056 if (rc && reply->type == XA_CARDINAL && reply->format == 32
6057 && (xcb_get_property_value_length (reply) / sizeof (uint32_t)
6058 >= current_workspace + 4))
6059 {
6060 values = xcb_get_property_value (reply);
6061
6062 rect->x = values[current_workspace];
6063 rect->y = values[current_workspace + 1];
6064 rect->width = values[current_workspace + 2];
6065 rect->height = values[current_workspace + 3];
6066 }
6067 else
6068 rc = false;
6069
6070 free (reply);
6071 }
6072
6073 return rc;
6074 #endif
6075 }
6076 #endif
6077
6078 #ifndef USE_GTK
6079
6080
6081 static int
6082 x_get_monitor_for_frame (struct frame *f,
6083 struct MonitorInfo *monitors,
6084 int n_monitors)
6085 {
6086 XRectangle frect;
6087 int area = 0, dist = -1;
6088 int best_area = -1, best_dist = -1;
6089 int i;
6090
6091 if (n_monitors == 1) return 0;
6092 frect.x = f->left_pos;
6093 frect.y = f->top_pos;
6094 frect.width = FRAME_PIXEL_WIDTH (f);
6095 frect.height = FRAME_PIXEL_HEIGHT (f);
6096
6097 for (i = 0; i < n_monitors; ++i)
6098 {
6099 struct MonitorInfo *mi = &monitors[i];
6100 XRectangle res;
6101 int a = 0;
6102
6103 if (mi->geom.width == 0) continue;
6104
6105 if (gui_intersect_rectangles (&mi->geom, &frect, &res))
6106 {
6107 a = res.width * res.height;
6108 if (a > area)
6109 {
6110 area = a;
6111 best_area = i;
6112 }
6113 }
6114
6115 if (a == 0 && area == 0)
6116 {
6117 int dx, dy, d;
6118 if (frect.x + frect.width < mi->geom.x)
6119 dx = mi->geom.x - frect.x + frect.width;
6120 else if (frect.x > mi->geom.x + mi->geom.width)
6121 dx = frect.x - mi->geom.x + mi->geom.width;
6122 else
6123 dx = 0;
6124 if (frect.y + frect.height < mi->geom.y)
6125 dy = mi->geom.y - frect.y + frect.height;
6126 else if (frect.y > mi->geom.y + mi->geom.height)
6127 dy = frect.y - mi->geom.y + mi->geom.height;
6128 else
6129 dy = 0;
6130
6131 d = dx*dx + dy*dy;
6132 if (dist == -1 || dist > d)
6133 {
6134 dist = d;
6135 best_dist = i;
6136 }
6137 }
6138 }
6139
6140 return best_area != -1 ? best_area : (best_dist != -1 ? best_dist : 0);
6141 }
6142
6143 static Lisp_Object
6144 x_make_monitor_attribute_list (struct MonitorInfo *monitors,
6145 int n_monitors,
6146 int primary_monitor,
6147 struct x_display_info *dpyinfo,
6148 const char *source)
6149 {
6150 Lisp_Object monitor_frames = make_nil_vector (n_monitors);
6151 Lisp_Object frame, rest;
6152
6153 FOR_EACH_FRAME (rest, frame)
6154 {
6155 struct frame *f = XFRAME (frame);
6156
6157 if (FRAME_X_P (f)
6158 && FRAME_DISPLAY_INFO (f) == dpyinfo
6159 && !FRAME_TOOLTIP_P (f))
6160 {
6161 int i = x_get_monitor_for_frame (f, monitors, n_monitors);
6162 ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i)));
6163 }
6164 }
6165
6166 return make_monitor_attribute_list (monitors, n_monitors, primary_monitor,
6167 monitor_frames, source);
6168 }
6169
6170 static Lisp_Object
6171 x_get_monitor_attributes_fallback (struct x_display_info *dpyinfo)
6172 {
6173 struct MonitorInfo monitor;
6174 XRectangle workarea_r;
6175
6176
6177
6178
6179 monitor.geom.x = monitor.geom.y = 0;
6180 monitor.geom.width = x_display_pixel_width (dpyinfo);
6181 monitor.geom.height = x_display_pixel_height (dpyinfo);
6182 monitor.mm_width = WidthMMOfScreen (dpyinfo->screen);
6183 monitor.mm_height = HeightMMOfScreen (dpyinfo->screen);
6184 monitor.name = xstrdup ("combined screen");
6185
6186 if (x_get_net_workarea (dpyinfo, &workarea_r))
6187 monitor.work = workarea_r;
6188 else
6189 monitor.work = monitor.geom;
6190 return x_make_monitor_attribute_list (&monitor, 1, 0, dpyinfo, "fallback");
6191 }
6192
6193
6194 #ifdef HAVE_XINERAMA
6195 static Lisp_Object
6196 x_get_monitor_attributes_xinerama (struct x_display_info *dpyinfo)
6197 {
6198 int n_monitors, i;
6199 Lisp_Object attributes_list = Qnil;
6200 Display *dpy = dpyinfo->display;
6201 XineramaScreenInfo *info = XineramaQueryScreens (dpy, &n_monitors);
6202 struct MonitorInfo *monitors;
6203 double mm_width_per_pixel, mm_height_per_pixel;
6204
6205 if (! info || n_monitors == 0)
6206 {
6207 if (info)
6208 XFree (info);
6209 return attributes_list;
6210 }
6211
6212 mm_width_per_pixel = ((double) WidthMMOfScreen (dpyinfo->screen)
6213 / x_display_pixel_width (dpyinfo));
6214 mm_height_per_pixel = ((double) HeightMMOfScreen (dpyinfo->screen)
6215 / x_display_pixel_height (dpyinfo));
6216 monitors = xzalloc (n_monitors * sizeof *monitors);
6217 for (i = 0; i < n_monitors; ++i)
6218 {
6219 struct MonitorInfo *mi = &monitors[i];
6220 XRectangle workarea_r;
6221
6222 mi->geom.x = info[i].x_org;
6223 mi->geom.y = info[i].y_org;
6224 mi->geom.width = info[i].width;
6225 mi->geom.height = info[i].height;
6226 mi->mm_width = mi->geom.width * mm_width_per_pixel + 0.5;
6227 mi->mm_height = mi->geom.height * mm_height_per_pixel + 0.5;
6228 mi->name = 0;
6229
6230
6231 if (i == 0 && x_get_net_workarea (dpyinfo, &workarea_r))
6232 {
6233 mi->work = workarea_r;
6234 if (! gui_intersect_rectangles (&mi->geom, &mi->work, &mi->work))
6235 mi->work = mi->geom;
6236 }
6237 else
6238 mi->work = mi->geom;
6239 }
6240 XFree (info);
6241
6242 attributes_list = x_make_monitor_attribute_list (monitors,
6243 n_monitors,
6244 0,
6245 dpyinfo,
6246 "Xinerama");
6247 free_monitors (monitors, n_monitors);
6248 return attributes_list;
6249 }
6250 #endif
6251
6252
6253 #ifdef HAVE_XRANDR
6254 static Lisp_Object
6255 x_get_monitor_attributes_xrandr (struct x_display_info *dpyinfo)
6256 {
6257 Lisp_Object attributes_list = Qnil;
6258 XRRScreenResources *resources;
6259 Display *dpy = dpyinfo->display;
6260 int i, n_monitors, primary = -1;
6261 RROutput pxid = None;
6262 struct MonitorInfo *monitors;
6263 bool randr15_p = false;
6264
6265 #if RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 5)
6266 XRRMonitorInfo *rr_monitors;
6267 #ifdef USE_XCB
6268 xcb_get_atom_name_cookie_t *atom_name_cookies;
6269 xcb_get_atom_name_reply_t *reply;
6270 xcb_generic_error_t *error;
6271 int length;
6272 #endif
6273
6274
6275
6276
6277 if (dpyinfo->xrandr_major_version > 1
6278 || (dpyinfo->xrandr_major_version == 1
6279 && dpyinfo->xrandr_minor_version >= 5))
6280 {
6281 XRectangle workarea;
6282 char *name;
6283
6284 rr_monitors = XRRGetMonitors (dpyinfo->display,
6285 dpyinfo->root_window,
6286 True, &n_monitors);
6287 if (!rr_monitors)
6288 goto fallback;
6289
6290 monitors = xzalloc (n_monitors * sizeof *monitors);
6291 #ifdef USE_XCB
6292 atom_name_cookies = alloca (n_monitors * sizeof *atom_name_cookies);
6293 #endif
6294
6295 for (int i = 0; i < n_monitors; ++i)
6296 {
6297 monitors[i].geom.x = rr_monitors[i].x;
6298 monitors[i].geom.y = rr_monitors[i].y;
6299 monitors[i].geom.width = rr_monitors[i].width;
6300 monitors[i].geom.height = rr_monitors[i].height;
6301 monitors[i].mm_width = rr_monitors[i].mwidth;
6302 monitors[i].mm_height = rr_monitors[i].mheight;
6303
6304 #ifndef USE_XCB
6305 name = XGetAtomName (dpyinfo->display, rr_monitors[i].name);
6306 if (name)
6307 {
6308 monitors[i].name = xstrdup (name);
6309 XFree (name);
6310 }
6311 else
6312 monitors[i].name = xstrdup ("Unknown Monitor");
6313 #else
6314 atom_name_cookies[i]
6315 = xcb_get_atom_name (dpyinfo->xcb_connection,
6316 (xcb_atom_t) rr_monitors[i].name);
6317 #endif
6318
6319 if (rr_monitors[i].primary)
6320 primary = i;
6321
6322 if (rr_monitors[i].primary
6323 && x_get_net_workarea (dpyinfo, &workarea))
6324 {
6325 monitors[i].work = workarea;
6326 if (!gui_intersect_rectangles (&monitors[i].geom,
6327 &monitors[i].work,
6328 &monitors[i].work))
6329 monitors[i].work = monitors[i].geom;
6330 }
6331 else
6332 monitors[i].work = monitors[i].geom;
6333 }
6334
6335 #ifdef USE_XCB
6336 for (int i = 0; i < n_monitors; ++i)
6337 {
6338 reply = xcb_get_atom_name_reply (dpyinfo->xcb_connection,
6339 atom_name_cookies[i], &error);
6340
6341 if (!reply)
6342 {
6343 monitors[i].name = xstrdup ("Unknown monitor");
6344 free (error);
6345 }
6346 else
6347 {
6348 length = xcb_get_atom_name_name_length (reply);
6349 name = xmalloc (length + 1);
6350 memcpy (name, xcb_get_atom_name_name (reply), length);
6351 name[length] = '\0';
6352 monitors[i].name = name;
6353 free (reply);
6354 }
6355 }
6356 #endif
6357
6358 XRRFreeMonitors (rr_monitors);
6359 randr15_p = true;
6360 goto out;
6361 }
6362
6363 fallback:;
6364 #endif
6365
6366 #define RANDR13_LIBRARY \
6367 (RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 3))
6368
6369 #if RANDR13_LIBRARY
6370
6371 bool randr13_avail = (dpyinfo->xrandr_major_version > 1
6372 || (dpyinfo->xrandr_major_version == 1
6373 && dpyinfo->xrandr_minor_version >= 3));
6374
6375 if (randr13_avail)
6376 resources = XRRGetScreenResourcesCurrent (dpy, dpyinfo->root_window);
6377 else
6378 resources = XRRGetScreenResources (dpy, dpyinfo->root_window);
6379 #else
6380 resources = XRRGetScreenResources (dpy, dpyinfo->root_window);
6381 #endif
6382 if (! resources || resources->noutput == 0)
6383 {
6384 if (resources)
6385 XRRFreeScreenResources (resources);
6386 return Qnil;
6387 }
6388 n_monitors = resources->noutput;
6389 monitors = xzalloc (n_monitors * sizeof *monitors);
6390
6391 #if RANDR13_LIBRARY
6392 if (randr13_avail)
6393 pxid = XRRGetOutputPrimary (dpy, dpyinfo->root_window);
6394 #endif
6395
6396 #undef RANDR13_LIBRARY
6397
6398 for (i = 0; i < n_monitors; ++i)
6399 {
6400 XRROutputInfo *info = XRRGetOutputInfo (dpy, resources,
6401 resources->outputs[i]);
6402 if (!info)
6403 continue;
6404
6405 if (strcmp (info->name, "default") == 0)
6406 {
6407
6408 XRRFreeOutputInfo (info);
6409 XRRFreeScreenResources (resources);
6410 free_monitors (monitors, n_monitors);
6411 return Qnil;
6412 }
6413
6414 if (info->connection != RR_Disconnected && info->crtc != None)
6415 {
6416 XRRCrtcInfo *crtc = XRRGetCrtcInfo (dpy, resources, info->crtc);
6417 struct MonitorInfo *mi = &monitors[i];
6418 XRectangle workarea_r;
6419
6420 if (! crtc)
6421 {
6422 XRRFreeOutputInfo (info);
6423 continue;
6424 }
6425
6426 mi->geom.x = crtc->x;
6427 mi->geom.y = crtc->y;
6428 mi->geom.width = crtc->width;
6429 mi->geom.height = crtc->height;
6430 mi->mm_width = info->mm_width;
6431 mi->mm_height = info->mm_height;
6432 mi->name = xstrdup (info->name);
6433
6434 if (pxid != None && pxid == resources->outputs[i])
6435 primary = i;
6436 else if (primary == -1 && strcmp (info->name, "LVDS") == 0)
6437 primary = i;
6438
6439 if (i == primary && x_get_net_workarea (dpyinfo, &workarea_r))
6440 {
6441 mi->work= workarea_r;
6442 if (! gui_intersect_rectangles (&mi->geom, &mi->work, &mi->work))
6443 mi->work = mi->geom;
6444 }
6445 else
6446 mi->work = mi->geom;
6447
6448 XRRFreeCrtcInfo (crtc);
6449 }
6450 XRRFreeOutputInfo (info);
6451 }
6452 XRRFreeScreenResources (resources);
6453 #if RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 5)
6454 out:
6455 #endif
6456 attributes_list = x_make_monitor_attribute_list (monitors,
6457 n_monitors,
6458 primary,
6459 dpyinfo,
6460 (randr15_p
6461 ? "XRandR 1.5"
6462 : "XRandr"));
6463 free_monitors (monitors, n_monitors);
6464 return attributes_list;
6465 }
6466 #endif
6467
6468 static Lisp_Object
6469 x_get_monitor_attributes (struct x_display_info *dpyinfo)
6470 {
6471 Lisp_Object attributes_list = Qnil;
6472 Display *dpy = dpyinfo->display;
6473
6474 (void) dpy;
6475
6476 #ifdef HAVE_XRANDR
6477 bool xrr_ok = ((dpyinfo->xrandr_major_version == 1
6478 && dpyinfo->xrandr_minor_version >= 2)
6479 || dpyinfo->xrandr_major_version > 1);
6480
6481 if (xrr_ok)
6482 attributes_list = x_get_monitor_attributes_xrandr (dpyinfo);
6483 #endif
6484
6485 #ifdef HAVE_XINERAMA
6486 if (NILP (attributes_list))
6487 {
6488 if (dpyinfo->xinerama_supported_p && XineramaIsActive (dpy))
6489 attributes_list = x_get_monitor_attributes_xinerama (dpyinfo);
6490 }
6491 #endif
6492
6493 if (NILP (attributes_list))
6494 attributes_list = x_get_monitor_attributes_fallback (dpyinfo);
6495
6496 return attributes_list;
6497 }
6498
6499 #endif
6500
6501 #ifdef USE_LUCID
6502
6503
6504 static void
6505 xlw_monitor_dimensions_at_pos_1 (struct x_display_info *dpyinfo,
6506 Screen *screen, int src_x, int src_y,
6507 int *x, int *y, int *width, int *height)
6508 {
6509 Lisp_Object attrs, tem, val;
6510
6511 attrs = x_get_monitor_attributes (dpyinfo);
6512
6513 for (tem = attrs; CONSP (tem); tem = XCDR (tem))
6514 {
6515 int sx, sy, swidth, sheight;
6516 val = assq_no_quit (Qworkarea, XCAR (tem));
6517 if (!NILP (val))
6518 {
6519 sx = XFIXNUM (XCAR (XCDR (val)));
6520 sy = XFIXNUM (XCAR (XCDR (XCDR (val))));
6521 swidth = XFIXNUM (XCAR (XCDR (XCDR (XCDR (val)))));
6522 sheight = XFIXNUM (XCAR (XCDR (XCDR (XCDR (XCDR (val))))));
6523
6524 if (sx <= src_x && src_x < (sx + swidth)
6525 && sy <= src_y && src_y < (sy + swidth))
6526 {
6527 *x = sx;
6528 *y = sy;
6529 *width = swidth;
6530 *height = sheight;
6531 return;
6532 }
6533 }
6534 }
6535
6536 *x = 0;
6537 *y = 0;
6538 *width = WidthOfScreen (screen);
6539 *height = HeightOfScreen (screen);
6540 }
6541
6542 void
6543 xlw_monitor_dimensions_at_pos (Display *dpy, Screen *screen, int src_x,
6544 int src_y, int *x, int *y, int *width, int *height)
6545 {
6546 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
6547
6548 if (!dpyinfo)
6549 emacs_abort ();
6550
6551 block_input ();
6552 xlw_monitor_dimensions_at_pos_1 (dpyinfo, screen, src_x, src_y,
6553 x, y, width, height);
6554
6555 unblock_input ();
6556 }
6557 #endif
6558
6559
6560 DEFUN ("x-display-monitor-attributes-list", Fx_display_monitor_attributes_list,
6561 Sx_display_monitor_attributes_list,
6562 0, 1, 0,
6563 doc:
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577 )
6578 (Lisp_Object terminal)
6579 {
6580 struct x_display_info *dpyinfo = check_x_display_info (terminal);
6581 Lisp_Object attributes_list = Qnil;
6582
6583 #ifdef USE_GTK
6584 GdkDisplay *gdpy;
6585 #if ! GTK_CHECK_VERSION (3, 22, 0)
6586 double mm_width_per_pixel, mm_height_per_pixel;
6587 GdkScreen *gscreen;
6588 #endif
6589 gint primary_monitor = 0, n_monitors, i;
6590 Lisp_Object monitor_frames, rest, frame;
6591 static const char *source = "Gdk";
6592 struct MonitorInfo *monitors;
6593
6594 block_input ();
6595 gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display);
6596 #if GTK_CHECK_VERSION (3, 22, 0)
6597 n_monitors = gdk_display_get_n_monitors (gdpy);
6598 #else
6599 gscreen = gdk_display_get_default_screen (gdpy);
6600 n_monitors = gdk_screen_get_n_monitors (gscreen);
6601 primary_monitor = gdk_screen_get_primary_monitor (gscreen);
6602
6603 mm_width_per_pixel = ((double) WidthMMOfScreen (dpyinfo->screen)
6604 / x_display_pixel_width (dpyinfo));
6605 mm_height_per_pixel = ((double) HeightMMOfScreen (dpyinfo->screen)
6606 / x_display_pixel_height (dpyinfo));
6607 #endif
6608 monitor_frames = make_nil_vector (n_monitors);
6609 monitors = xzalloc (n_monitors * sizeof *monitors);
6610
6611 FOR_EACH_FRAME (rest, frame)
6612 {
6613 struct frame *f = XFRAME (frame);
6614
6615 if (FRAME_X_P (f)
6616 && FRAME_DISPLAY_INFO (f) == dpyinfo
6617 && !FRAME_TOOLTIP_P (f))
6618 {
6619 GdkWindow *gwin = gtk_widget_get_window (FRAME_GTK_WIDGET (f));
6620
6621 #if GTK_CHECK_VERSION (3, 22, 0)
6622 for (i = 0; i < n_monitors; i++)
6623 if (gdk_display_get_monitor_at_window (gdpy, gwin)
6624 == gdk_display_get_monitor (gdpy, i))
6625 break;
6626 #else
6627 i = gdk_screen_get_monitor_at_window (gscreen, gwin);
6628 #endif
6629 ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i)));
6630 }
6631 }
6632
6633 for (i = 0; i < n_monitors; ++i)
6634 {
6635 gint width_mm, height_mm;
6636 GdkRectangle rec, work;
6637 struct MonitorInfo *mi = &monitors[i];
6638 int scale = 1;
6639
6640 #if GTK_CHECK_VERSION (3, 22, 0)
6641 GdkMonitor *monitor = gdk_display_get_monitor (gdpy, i);
6642 if (gdk_monitor_is_primary (monitor))
6643 primary_monitor = i;
6644 gdk_monitor_get_geometry (monitor, &rec);
6645 #else
6646 gdk_screen_get_monitor_geometry (gscreen, i, &rec);
6647 #endif
6648
6649 #if GTK_CHECK_VERSION (3, 22, 0)
6650 width_mm = gdk_monitor_get_width_mm (monitor);
6651 height_mm = gdk_monitor_get_height_mm (monitor);
6652 #else
6653 width_mm = gdk_screen_get_monitor_width_mm (gscreen, i);
6654 height_mm = gdk_screen_get_monitor_height_mm (gscreen, i);
6655 if (width_mm < 0)
6656 width_mm = rec.width * mm_width_per_pixel + 0.5;
6657 if (height_mm < 0)
6658 height_mm = rec.height * mm_height_per_pixel + 0.5;
6659 #endif
6660 #if GTK_CHECK_VERSION (3, 22, 0)
6661 gdk_monitor_get_workarea (monitor, &work);
6662 #elif defined HAVE_GTK3
6663 gdk_screen_get_monitor_workarea (gscreen, i, &work);
6664 #else
6665
6666 {
6667 XRectangle workarea_r;
6668
6669 if (i == primary_monitor && x_get_net_workarea (dpyinfo, &workarea_r))
6670 {
6671 work.x = workarea_r.x;
6672 work.y = workarea_r.y;
6673 work.width = workarea_r.width;
6674 work.height = workarea_r.height;
6675 if (! gdk_rectangle_intersect (&rec, &work, &work))
6676 work = rec;
6677 }
6678 else
6679 work = rec;
6680 }
6681 #endif
6682
6683
6684 #if GTK_CHECK_VERSION (3, 22, 0)
6685 scale = gdk_monitor_get_scale_factor (monitor);
6686 #elif defined HAVE_GTK3
6687 scale = gdk_screen_get_monitor_scale_factor (gscreen, i);
6688 #endif
6689 rec.x *= scale;
6690 rec.y *= scale;
6691 rec.width *= scale;
6692 rec.height *= scale;
6693 work.x *= scale;
6694 work.y *= scale;
6695 work.width *= scale;
6696 work.height *= scale;
6697
6698 mi->geom.x = rec.x;
6699 mi->geom.y = rec.y;
6700 mi->geom.width = rec.width;
6701 mi->geom.height = rec.height;
6702 mi->work.x = work.x;
6703 mi->work.y = work.y;
6704 mi->work.width = work.width;
6705 mi->work.height = work.height;
6706 mi->mm_width = width_mm;
6707 mi->mm_height = height_mm;
6708
6709 #if GTK_CHECK_VERSION (3, 22, 0)
6710 dupstring (&mi->name, (gdk_monitor_get_model (monitor)));
6711 #else
6712 mi->name = gdk_screen_get_monitor_plug_name (gscreen, i);
6713 #endif
6714 }
6715
6716 attributes_list = make_monitor_attribute_list (monitors,
6717 n_monitors,
6718 primary_monitor,
6719 monitor_frames,
6720 source);
6721 free_monitors (monitors, n_monitors);
6722 unblock_input ();
6723 #else
6724
6725 block_input ();
6726 attributes_list = x_get_monitor_attributes (dpyinfo);
6727 unblock_input ();
6728
6729 #endif
6730
6731 return attributes_list;
6732 }
6733
6734
6735
6736
6737
6738
6739
6740 static Lisp_Object
6741 frame_geometry (Lisp_Object frame, Lisp_Object attribute)
6742 {
6743 struct frame *f = decode_live_frame (frame);
6744
6745 Window rootw;
6746 unsigned int ign, native_width, native_height, x_border_width = 0;
6747 int x_native = 0, y_native = 0, xptr = 0, yptr = 0;
6748 int left_off = 0, right_off = 0, top_off = 0, bottom_off = 0;
6749 int outer_left, outer_top, outer_right, outer_bottom;
6750 int native_left, native_top, native_right, native_bottom;
6751 int inner_left, inner_top, inner_right, inner_bottom;
6752 int internal_border_width;
6753 bool menu_bar_external = false, tool_bar_external = false;
6754 int menu_bar_height = 0, menu_bar_width = 0;
6755 int tab_bar_height = 0, tab_bar_width = 0;
6756 int tool_bar_height = 0, tool_bar_width = 0;
6757
6758 if (FRAME_INITIAL_P (f) || !FRAME_X_P (f) || !FRAME_OUTER_WINDOW (f))
6759 return Qnil;
6760
6761 block_input ();
6762 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
6763 &rootw, &x_native, &y_native, &native_width, &native_height,
6764 &x_border_width, &ign);
6765
6766 if (!FRAME_PARENT_FRAME (f))
6767 x_real_pos_and_offsets (f, &left_off, &right_off, &top_off, &bottom_off,
6768 NULL, NULL, &xptr, &yptr, NULL);
6769 unblock_input ();
6770
6771
6772
6773
6774 if (FRAME_PARENT_FRAME (f))
6775 {
6776 Lisp_Object parent, edges;
6777
6778 XSETFRAME (parent, FRAME_PARENT_FRAME (f));
6779 edges = Fx_frame_edges (parent, Qnative_edges);
6780 if (!NILP (edges))
6781 {
6782 x_native += XFIXNUM (Fnth (make_fixnum (0), edges));
6783 y_native += XFIXNUM (Fnth (make_fixnum (1), edges));
6784 }
6785
6786 outer_left = x_native;
6787 outer_top = y_native;
6788 outer_right = outer_left + native_width + 2 * x_border_width;
6789 outer_bottom = outer_top + native_height + 2 * x_border_width;
6790
6791 native_left = x_native + x_border_width;
6792 native_top = y_native + x_border_width;
6793 native_right = native_left + native_width;
6794 native_bottom = native_top + native_height;
6795 }
6796 else
6797 {
6798 outer_left = xptr;
6799 outer_top = yptr;
6800 outer_right = outer_left + left_off + native_width + right_off;
6801 outer_bottom = outer_top + top_off + native_height + bottom_off;
6802
6803 native_left = outer_left + left_off;
6804 native_top = outer_top + top_off;
6805 native_right = native_left + native_width;
6806 native_bottom = native_top + native_height;
6807 }
6808
6809 internal_border_width = FRAME_INTERNAL_BORDER_WIDTH (f);
6810 inner_left = native_left + internal_border_width;
6811 inner_top = native_top + internal_border_width;
6812 inner_right = native_right - internal_border_width;
6813 inner_bottom = native_bottom - internal_border_width;
6814
6815 #ifdef HAVE_EXT_MENU_BAR
6816 menu_bar_external = true;
6817 menu_bar_height = FRAME_MENUBAR_HEIGHT (f);
6818 native_top += menu_bar_height;
6819 inner_top += menu_bar_height;
6820 #else
6821 menu_bar_height = FRAME_MENU_BAR_HEIGHT (f);
6822 inner_top += menu_bar_height;
6823 #endif
6824 menu_bar_width = menu_bar_height ? native_width : 0;
6825
6826 tab_bar_height = FRAME_TAB_BAR_HEIGHT (f);
6827 tab_bar_width = (tab_bar_height
6828 ? native_width - 2 * internal_border_width
6829 : 0);
6830 inner_top += tab_bar_height;
6831
6832 #ifdef HAVE_EXT_TOOL_BAR
6833 tool_bar_external = true;
6834 if (EQ (FRAME_TOOL_BAR_POSITION (f), Qleft))
6835 {
6836 tool_bar_width = FRAME_TOOLBAR_WIDTH (f);
6837 native_left += tool_bar_width;
6838 inner_left += tool_bar_width;
6839 tool_bar_height
6840 = tool_bar_width ? native_height - menu_bar_height : 0;
6841 }
6842 else if (EQ (FRAME_TOOL_BAR_POSITION (f), Qtop))
6843 {
6844 tool_bar_height = FRAME_TOOLBAR_HEIGHT (f);
6845 native_top += tool_bar_height;
6846 inner_top += tool_bar_height;
6847 tool_bar_width = tool_bar_height ? native_width : 0;
6848 }
6849 else if (EQ (FRAME_TOOL_BAR_POSITION (f), Qright))
6850 {
6851 tool_bar_width = FRAME_TOOLBAR_WIDTH (f);
6852 native_right -= tool_bar_width;
6853 inner_right -= tool_bar_width;
6854 tool_bar_height
6855 = tool_bar_width ? native_height - menu_bar_height : 0;
6856 }
6857 else
6858 {
6859 tool_bar_height = FRAME_TOOLBAR_HEIGHT (f);
6860 native_bottom -= tool_bar_height;
6861 inner_bottom -= tool_bar_height;
6862 tool_bar_width = tool_bar_height ? native_width : 0;
6863 }
6864 #else
6865 tool_bar_height = FRAME_TOOL_BAR_HEIGHT (f);
6866 tool_bar_width = (tool_bar_height
6867 ? native_width - 2 * internal_border_width
6868 : 0);
6869
6870
6871
6872
6873 if (EQ (FRAME_TOOL_BAR_POSITION (f), Qtop))
6874 inner_top += tool_bar_height;
6875 else
6876 inner_bottom -= tool_bar_height;
6877 #endif
6878
6879
6880 if (EQ (attribute, Qouter_edges))
6881 return list4i (outer_left, outer_top, outer_right, outer_bottom);
6882 else if (EQ (attribute, Qnative_edges))
6883 return list4i (native_left, native_top, native_right, native_bottom);
6884 else if (EQ (attribute, Qinner_edges))
6885 return list4i (inner_left, inner_top, inner_right, inner_bottom);
6886 else
6887 return
6888 list (Fcons (Qouter_position,
6889 Fcons (make_fixnum (outer_left),
6890 make_fixnum (outer_top))),
6891 Fcons (Qouter_size,
6892 Fcons (make_fixnum (outer_right - outer_left),
6893 make_fixnum (outer_bottom - outer_top))),
6894
6895 Fcons (Qexternal_border_size,
6896 Fcons (make_fixnum (right_off),
6897 make_fixnum (bottom_off))),
6898 Fcons (Qouter_border_width, make_fixnum (x_border_width)),
6899
6900 Fcons (Qtitle_bar_size,
6901 Fcons (make_fixnum (0),
6902 make_fixnum (top_off - bottom_off))),
6903 Fcons (Qmenu_bar_external, menu_bar_external ? Qt : Qnil),
6904 Fcons (Qmenu_bar_size,
6905 Fcons (make_fixnum (menu_bar_width),
6906 make_fixnum (menu_bar_height))),
6907 Fcons (Qtab_bar_size,
6908 Fcons (make_fixnum (tab_bar_width),
6909 make_fixnum (tab_bar_height))),
6910 Fcons (Qtool_bar_external, tool_bar_external ? Qt : Qnil),
6911 Fcons (Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f)),
6912 Fcons (Qtool_bar_size,
6913 Fcons (make_fixnum (tool_bar_width),
6914 make_fixnum (tool_bar_height))),
6915 Fcons (Qinternal_border_width,
6916 make_fixnum (internal_border_width)));
6917 }
6918
6919 DEFUN ("x-frame-geometry", Fx_frame_geometry, Sx_frame_geometry, 0, 1, 0,
6920 doc:
6921
6922
6923
6924
6925
6926
6927
6928
6929
6930
6931
6932
6933
6934
6935
6936
6937
6938
6939
6940
6941
6942
6943
6944
6945
6946
6947
6948
6949
6950
6951
6952
6953
6954
6955
6956
6957
6958
6959
6960
6961
6962 )
6963 (Lisp_Object frame)
6964 {
6965 return frame_geometry (frame, Qnil);
6966 }
6967
6968 DEFUN ("x-frame-edges", Fx_frame_edges, Sx_frame_edges, 0, 2, 0,
6969 doc:
6970
6971
6972
6973
6974
6975
6976
6977
6978
6979
6980
6981
6982
6983 )
6984 (Lisp_Object frame, Lisp_Object type)
6985 {
6986 return frame_geometry (frame, ((EQ (type, Qouter_edges)
6987 || EQ (type, Qinner_edges))
6988 ? type
6989 : Qnative_edges));
6990 }
6991
6992
6993
6994
6995
6996
6997
6998
6999 static Lisp_Object
7000 x_frame_list_z_order (struct x_display_info *dpyinfo, Window window)
7001 {
7002 Display *dpy;
7003 Window root, parent, *children;
7004 unsigned int nchildren;
7005 unsigned long i;
7006 Lisp_Object frames, val;
7007 Atom type;
7008 Window *toplevels;
7009 int format, rc;
7010 unsigned long nitems, bytes_after;
7011 unsigned char *data;
7012 struct frame *f;
7013
7014 dpy = dpyinfo->display;
7015 data = NULL;
7016 frames = Qnil;
7017
7018 if (window == dpyinfo->root_window
7019 && x_wm_supports_1 (dpyinfo,
7020 dpyinfo->Xatom_net_client_list_stacking))
7021 {
7022 rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window,
7023 dpyinfo->Xatom_net_client_list_stacking,
7024 0, LONG_MAX, False, XA_WINDOW, &type,
7025 &format, &nitems, &bytes_after, &data);
7026
7027 if (rc != Success)
7028 return Qnil;
7029
7030 if (format != 32 || type != XA_WINDOW)
7031 {
7032 XFree (data);
7033 return Qnil;
7034 }
7035
7036 toplevels = (Window *) data;
7037
7038 for (i = 0; i < nitems; ++i)
7039 {
7040 f = x_top_window_to_frame (dpyinfo, toplevels[i]);
7041
7042 if (f)
7043 {
7044 XSETFRAME (val, f);
7045 frames = Fcons (val, frames);
7046 }
7047 }
7048
7049 XFree (data);
7050 return frames;
7051 }
7052
7053 if (XQueryTree (dpy, window, &root, &parent, &children, &nchildren))
7054 {
7055 for (i = 0; i < nchildren; i++)
7056 {
7057 Lisp_Object frame, tail;
7058
7059 FOR_EACH_FRAME (tail, frame)
7060 {
7061 struct frame *cf = XFRAME (frame);
7062
7063
7064
7065 if (FRAME_X_P (cf)
7066 && (cf->output_data.x->parent_desc == children[i]
7067 || FRAME_OUTER_WINDOW (cf) == children[i]))
7068 frames = Fcons (frame, frames);
7069 }
7070 }
7071
7072 if (children)
7073 XFree (children);
7074 }
7075
7076 return frames;
7077 }
7078
7079
7080 DEFUN ("x-frame-list-z-order", Fx_frame_list_z_order,
7081 Sx_frame_list_z_order, 0, 1, 0,
7082 doc:
7083
7084
7085
7086
7087
7088
7089
7090
7091 )
7092 (Lisp_Object terminal)
7093 {
7094 struct x_display_info *dpyinfo = check_x_display_info (terminal);
7095 Window window;
7096
7097 if (FRAMEP (terminal) && FRAME_LIVE_P (XFRAME (terminal)))
7098 window = FRAME_X_WINDOW (XFRAME (terminal));
7099 else
7100 window = dpyinfo->root_window;
7101
7102 return x_frame_list_z_order (dpyinfo, window);
7103 }
7104
7105
7106
7107
7108
7109
7110
7111
7112
7113 static void
7114 x_frame_restack (struct frame *f1, struct frame *f2, bool above_flag)
7115 {
7116 #ifdef USE_GTK
7117 block_input ();
7118 xg_frame_restack (f1, f2, above_flag);
7119 unblock_input ();
7120 #else
7121 Display *dpy = FRAME_X_DISPLAY (f1);
7122 Window window1 = FRAME_OUTER_WINDOW (f1);
7123 XWindowChanges wc;
7124 unsigned long mask = (CWSibling | CWStackMode);
7125
7126 wc.sibling = FRAME_OUTER_WINDOW (f2);
7127 wc.stack_mode = above_flag ? Above : Below;
7128 block_input ();
7129
7130
7131 XReconfigureWMWindow (dpy, window1, FRAME_X_SCREEN_NUMBER (f1), mask, &wc);
7132 unblock_input ();
7133 #endif
7134 }
7135
7136
7137 DEFUN ("x-frame-restack", Fx_frame_restack, Sx_frame_restack, 2, 3, 0,
7138 doc:
7139
7140
7141
7142
7143
7144
7145
7146
7147
7148
7149
7150
7151
7152 )
7153 (Lisp_Object frame1, Lisp_Object frame2, Lisp_Object above)
7154 {
7155 struct frame *f1 = decode_live_frame (frame1);
7156 struct frame *f2 = decode_live_frame (frame2);
7157
7158 if (! (FRAME_OUTER_WINDOW (f1) && FRAME_OUTER_WINDOW (f2)))
7159 error ("Cannot restack frames");
7160 x_frame_restack (f1, f2, !NILP (above));
7161 return Qt;
7162 }
7163
7164
7165 DEFUN ("x-mouse-absolute-pixel-position", Fx_mouse_absolute_pixel_position,
7166 Sx_mouse_absolute_pixel_position, 0, 0, 0,
7167 doc:
7168
7169
7170 )
7171 (void)
7172 {
7173 struct frame *f = SELECTED_FRAME ();
7174 Window root, dummy_window;
7175 int x, y, dummy;
7176
7177 if (FRAME_INITIAL_P (f) || !FRAME_X_P (f))
7178 return Qnil;
7179
7180 block_input ();
7181 x_query_pointer (FRAME_X_DISPLAY (f),
7182 FRAME_DISPLAY_INFO (f)->root_window,
7183 &root, &dummy_window, &x, &y, &dummy, &dummy,
7184 (unsigned int *) &dummy);
7185 unblock_input ();
7186
7187 return Fcons (make_fixnum (x), make_fixnum (y));
7188 }
7189
7190 DEFUN ("x-set-mouse-absolute-pixel-position", Fx_set_mouse_absolute_pixel_position,
7191 Sx_set_mouse_absolute_pixel_position, 2, 2, 0,
7192 doc:
7193
7194 )
7195 (Lisp_Object x, Lisp_Object y)
7196 {
7197 struct frame *f = SELECTED_FRAME ();
7198
7199 if (FRAME_INITIAL_P (f) || !FRAME_X_P (f))
7200 return Qnil;
7201
7202 int xval = check_integer_range (x, INT_MIN, INT_MAX);
7203 int yval = check_integer_range (y, INT_MIN, INT_MAX);
7204
7205 block_input ();
7206 #ifdef HAVE_XINPUT2
7207 int deviceid;
7208
7209 deviceid = FRAME_DISPLAY_INFO (f)->client_pointer_device;
7210
7211 if (FRAME_DISPLAY_INFO (f)->supports_xi2
7212 && deviceid != -1)
7213 {
7214 x_catch_errors_for_lisp (FRAME_DISPLAY_INFO (f));
7215 XIWarpPointer (FRAME_X_DISPLAY (f), deviceid, None,
7216 FRAME_DISPLAY_INFO (f)->root_window,
7217 0, 0, 0, 0, xval, yval);
7218 x_uncatch_errors_for_lisp (FRAME_DISPLAY_INFO (f));
7219 }
7220 else
7221 #endif
7222 XWarpPointer (FRAME_X_DISPLAY (f), None,
7223 FRAME_DISPLAY_INFO (f)->root_window,
7224 0, 0, 0, 0, xval, yval);
7225 unblock_input ();
7226
7227 return Qnil;
7228 }
7229
7230 DEFUN ("x-begin-drag", Fx_begin_drag, Sx_begin_drag, 1, 6, 0,
7231 doc:
7232
7233
7234
7235
7236
7237
7238
7239
7240
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261
7262
7263
7264
7265
7266
7267
7268
7269
7270
7271
7272
7273
7274
7275
7276
7277
7278
7279
7280
7281
7282
7283
7284
7285
7286
7287
7288
7289 )
7290 (Lisp_Object targets, Lisp_Object action, Lisp_Object frame,
7291 Lisp_Object return_frame, Lisp_Object allow_current_frame,
7292 Lisp_Object follow_tooltip)
7293 {
7294 struct frame *f = decode_window_system_frame (frame);
7295 int ntargets = 0, nnames = 0;
7296 char *target_names[2048];
7297 Atom *target_atoms;
7298 Lisp_Object lval, original, targets_arg, tem, t1, t2;
7299 Atom xaction;
7300 Atom action_list[2048];
7301 char *name_list[2048];
7302
7303 USE_SAFE_ALLOCA;
7304
7305 CHECK_LIST (targets);
7306 original = targets;
7307 targets_arg = targets;
7308
7309 FOR_EACH_TAIL (targets)
7310 {
7311 CHECK_STRING (XCAR (targets));
7312
7313 if (ntargets < 2048)
7314 {
7315 SAFE_ALLOCA_STRING (target_names[ntargets],
7316 XCAR (targets));
7317 ntargets++;
7318 }
7319 else
7320 error ("Too many targets");
7321 }
7322
7323 CHECK_LIST_END (targets, original);
7324
7325 if (NILP (action) || EQ (action, QXdndActionCopy))
7326 xaction = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionCopy;
7327 else if (EQ (action, QXdndActionMove))
7328 xaction = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionMove;
7329 else if (EQ (action, QXdndActionLink))
7330 xaction = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionLink;
7331 else if (EQ (action, QXdndActionPrivate))
7332 xaction = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionPrivate;
7333 else if (EQ (action, QXdndActionAsk))
7334 xaction = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionAsk;
7335 else if (SYMBOLP (action))
7336
7337
7338
7339 xaction = symbol_to_x_atom (FRAME_DISPLAY_INFO (f), action);
7340 else if (CONSP (action))
7341 {
7342 xaction = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionAsk;
7343 original = action;
7344
7345 CHECK_LIST (action);
7346 FOR_EACH_TAIL (action)
7347 {
7348 tem = XCAR (action);
7349 CHECK_CONS (tem);
7350 t1 = XCAR (tem);
7351 t2 = XCDR (tem);
7352 CHECK_SYMBOL (t1);
7353 CHECK_STRING (t2);
7354
7355 if (nnames < 2048)
7356 {
7357 if (EQ (t1, QXdndActionCopy))
7358 action_list[nnames] = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionCopy;
7359 else if (EQ (t1, QXdndActionMove))
7360 action_list[nnames] = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionMove;
7361 else if (EQ (t1, QXdndActionLink))
7362 action_list[nnames] = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionLink;
7363 else if (EQ (t1, QXdndActionAsk))
7364 action_list[nnames] = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionAsk;
7365 else if (EQ (t1, QXdndActionPrivate))
7366 action_list[nnames] = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionPrivate;
7367 else
7368 signal_error ("Invalid drag-and-drop action", tem);
7369
7370 SAFE_ALLOCA_STRING (name_list[nnames],
7371 ENCODE_SYSTEM (t2));
7372
7373 nnames++;
7374 }
7375 else
7376 error ("Too many actions");
7377 }
7378 CHECK_LIST_END (action, original);
7379 }
7380 else
7381 signal_error ("Invalid drag-and-drop action", action);
7382
7383 target_atoms = SAFE_ALLOCA (ntargets * sizeof *target_atoms);
7384
7385
7386
7387 x_catch_errors (FRAME_X_DISPLAY (f));
7388 x_intern_atoms (FRAME_DISPLAY_INFO (f), target_names,
7389 ntargets, target_atoms);
7390 x_check_errors (FRAME_X_DISPLAY (f),
7391 "Failed to intern target atoms: %s");
7392 x_uncatch_errors_after_check ();
7393
7394 lval = x_dnd_begin_drag_and_drop (f, FRAME_DISPLAY_INFO (f)->last_user_time,
7395 xaction, return_frame, action_list,
7396 (const char **) &name_list, nnames,
7397 !NILP (allow_current_frame), target_atoms,
7398 ntargets, targets_arg, !NILP (follow_tooltip));
7399
7400 SAFE_FREE ();
7401 return lval;
7402 }
7403
7404
7405
7406
7407
7408
7409
7410
7411 static struct visual_class
7412 {
7413 const char *name;
7414 int class;
7415 }
7416 visual_classes[] =
7417 {
7418 {"StaticGray", StaticGray},
7419 {"GrayScale", GrayScale},
7420 {"StaticColor", StaticColor},
7421 {"PseudoColor", PseudoColor},
7422 {"TrueColor", TrueColor},
7423 {"DirectColor", DirectColor},
7424 {NULL, 0}
7425 };
7426
7427
7428 #ifndef HAVE_XSCREENNUMBEROFSCREEN
7429
7430
7431
7432
7433 int
7434 XScreenNumberOfScreen (Screen *scr)
7435 {
7436 Display *dpy = scr->display;
7437 int i;
7438
7439 for (i = 0; i < dpy->nscreens; ++i)
7440 if (scr == dpy->screens + i)
7441 break;
7442
7443 return i;
7444 }
7445
7446 #endif
7447
7448
7449
7450
7451
7452 void
7453 select_visual (struct x_display_info *dpyinfo)
7454 {
7455 Display *dpy = dpyinfo->display;
7456 Screen *screen = dpyinfo->screen;
7457
7458
7459 AUTO_STRING (visualClass, "visualClass");
7460 AUTO_STRING (VisualClass, "VisualClass");
7461 Lisp_Object value = gui_display_get_resource (dpyinfo, visualClass,
7462 VisualClass, Qnil, Qnil);
7463
7464 if (STRINGP (value))
7465 {
7466
7467
7468
7469 char *s = alloca (SBYTES (value) + 1);
7470 char *dash;
7471 int i, class = -1;
7472 XVisualInfo vinfo;
7473
7474 lispstpcpy (s, value);
7475 dash = strchr (s, '-');
7476 if (dash)
7477 {
7478 dpyinfo->n_planes = atoi (dash + 1);
7479 *dash = '\0';
7480 }
7481 else
7482
7483
7484 dpyinfo->n_planes = 0;
7485
7486
7487 for (i = 0; visual_classes[i].name; ++i)
7488 if (xstrcasecmp (s, visual_classes[i].name) == 0)
7489 {
7490 class = visual_classes[i].class;
7491 break;
7492 }
7493
7494
7495 if (class == -1
7496 || !XMatchVisualInfo (dpy, XScreenNumberOfScreen (screen),
7497 dpyinfo->n_planes, class, &vinfo))
7498 fatal ("Invalid visual specification '%s'",
7499 SSDATA (ENCODE_SYSTEM (value)));
7500
7501 dpyinfo->visual = vinfo.visual;
7502 dpyinfo->visual_info = vinfo;
7503 }
7504 else
7505 {
7506 int n_visuals;
7507 XVisualInfo *vinfo, vinfo_template;
7508
7509 vinfo_template.screen = XScreenNumberOfScreen (screen);
7510
7511 #if !defined USE_X_TOOLKIT && !(defined USE_GTK && !defined HAVE_GTK3) \
7512 && defined HAVE_XRENDER
7513 int i;
7514 XRenderPictFormat *format;
7515
7516
7517
7518
7519
7520
7521 if (dpyinfo->xrender_supported_p)
7522 {
7523
7524 vinfo = XGetVisualInfo (dpy, VisualScreenMask,
7525 &vinfo_template, &n_visuals);
7526
7527 for (i = 0; i < n_visuals; ++i)
7528 {
7529 format = XRenderFindVisualFormat (dpy, vinfo[i].visual);
7530
7531 if (format && format->type == PictTypeDirect
7532 && format->direct.alphaMask)
7533 {
7534 dpyinfo->n_planes = vinfo[i].depth;
7535 dpyinfo->visual = vinfo[i].visual;
7536 dpyinfo->visual_info = vinfo[i];
7537 dpyinfo->pict_format = format;
7538
7539 XFree (vinfo);
7540 return;
7541 }
7542 }
7543
7544 if (vinfo)
7545 XFree (vinfo);
7546 }
7547 #endif
7548
7549
7550
7551 dpyinfo->visual = DefaultVisualOfScreen (screen);
7552 vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
7553 vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
7554 &vinfo_template, &n_visuals);
7555 if (n_visuals <= 0)
7556 fatal ("Can't get proper X visual info");
7557 dpyinfo->visual_info = *vinfo;
7558 dpyinfo->n_planes = vinfo->depth;
7559 XFree (vinfo);
7560 }
7561 }
7562
7563
7564
7565
7566
7567 static struct x_display_info *
7568 x_display_info_for_name (Lisp_Object name)
7569 {
7570 struct x_display_info *dpyinfo;
7571
7572 CHECK_STRING (name);
7573
7574 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
7575 if (!NILP (Fstring_equal (XCAR (dpyinfo->name_list_element), name)))
7576 return dpyinfo;
7577
7578
7579 Vx_resource_name = Vinvocation_name;
7580
7581 validate_x_resource_name ();
7582
7583 dpyinfo = x_term_init (name, 0, SSDATA (Vx_resource_name));
7584
7585 if (dpyinfo == 0)
7586 error ("Cannot connect to X server %s", SDATA (name));
7587
7588 return dpyinfo;
7589 }
7590
7591
7592 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
7593 1, 3, 0,
7594 doc:
7595
7596
7597
7598
7599 )
7600 (Lisp_Object display, Lisp_Object xrm_string, Lisp_Object must_succeed)
7601 {
7602 char *xrm_option;
7603 struct x_display_info *dpyinfo;
7604
7605 CHECK_STRING (display);
7606 if (! NILP (xrm_string))
7607 CHECK_STRING (xrm_string);
7608
7609 xrm_option = NILP (xrm_string) ? 0 : SSDATA (xrm_string);
7610
7611 validate_x_resource_name ();
7612
7613
7614
7615 dpyinfo = x_term_init (display, xrm_option,
7616 SSDATA (Vx_resource_name));
7617
7618 if (dpyinfo == 0)
7619 {
7620 if (!NILP (must_succeed))
7621 fatal ("Cannot connect to X server %s.\n\
7622 Check the DISPLAY environment variable or use `-d'.\n\
7623 Also use the `xauth' program to verify that you have the proper\n\
7624 authorization information needed to connect the X server.\n\
7625 An insecure way to solve the problem may be to use `xhost'.\n",
7626 SDATA (display));
7627 else
7628 error ("Cannot connect to X server %s", SDATA (display));
7629 }
7630
7631 return Qnil;
7632 }
7633
7634 DEFUN ("x-close-connection", Fx_close_connection,
7635 Sx_close_connection, 1, 1, 0,
7636 doc:
7637
7638
7639 )
7640 (Lisp_Object terminal)
7641 {
7642 struct x_display_info *dpyinfo = check_x_display_info (terminal);
7643
7644 if (dpyinfo->reference_count > 0)
7645 error ("Display still has frames on it");
7646
7647 x_delete_terminal (dpyinfo->terminal);
7648
7649 return Qnil;
7650 }
7651
7652 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
7653 doc: )
7654 (void)
7655 {
7656 Lisp_Object result = Qnil;
7657 struct x_display_info *xdi;
7658
7659 for (xdi = x_display_list; xdi; xdi = xdi->next)
7660 result = Fcons (XCAR (xdi->name_list_element), result);
7661
7662 return result;
7663 }
7664
7665 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
7666 doc:
7667
7668
7669
7670
7671
7672
7673
7674
7675
7676 )
7677 (Lisp_Object on, Lisp_Object terminal)
7678 {
7679 struct x_display_info *dpyinfo = check_x_display_info (terminal);
7680
7681 XSynchronize (dpyinfo->display, !NILP (on));
7682
7683 return Qnil;
7684 }
7685
7686
7687
7688
7689
7690
7691 DEFUN ("x-change-window-property", Fx_change_window_property,
7692 Sx_change_window_property, 2, 7, 0,
7693 doc:
7694
7695
7696
7697
7698
7699
7700
7701
7702
7703
7704
7705
7706
7707
7708
7709
7710
7711
7712
7713
7714
7715
7716
7717
7718
7719
7720
7721
7722
7723
7724
7725 )
7726 (Lisp_Object prop, Lisp_Object value, Lisp_Object frame,
7727 Lisp_Object type, Lisp_Object format, Lisp_Object outer_p,
7728 Lisp_Object window_id)
7729 {
7730 struct frame *f;
7731 Atom prop_atom;
7732 Atom target_type = XA_STRING;
7733 int element_format = 8;
7734 unsigned char *data;
7735 int nelements;
7736 Window target_window;
7737 struct x_display_info *dpyinfo;
7738 #ifdef USE_XCB
7739 bool intern_prop;
7740 bool intern_target;
7741 xcb_intern_atom_cookie_t prop_atom_cookie;
7742 xcb_intern_atom_cookie_t target_type_cookie;
7743 xcb_intern_atom_reply_t *reply;
7744 xcb_generic_error_t *generic_error;
7745 bool rc;
7746 #endif
7747
7748 f = decode_window_system_frame (frame);
7749 dpyinfo = FRAME_DISPLAY_INFO (f);
7750
7751 CHECK_STRING (prop);
7752
7753 if (! NILP (format))
7754 {
7755 CHECK_FIXNUM (format);
7756
7757 if (XFIXNUM (format) != 8 && XFIXNUM (format) != 16
7758 && XFIXNUM (format) != 32)
7759 error ("FORMAT must be one of 8, 16 or 32");
7760 element_format = XFIXNUM (format);
7761 }
7762
7763 if (CONSP (value))
7764 {
7765 ptrdiff_t elsize;
7766
7767 nelements = x_check_property_data (value);
7768 if (nelements == -1)
7769 error ("Bad data in VALUE, must be number, string or cons");
7770
7771
7772
7773
7774
7775
7776 elsize = element_format == 32 ? sizeof (long) : element_format >> 3;
7777 data = xnmalloc (nelements, elsize);
7778
7779 x_fill_property_data (FRAME_DISPLAY_INFO (f), value, data, nelements,
7780 element_format);
7781 }
7782 else
7783 {
7784 ptrdiff_t elsize;
7785
7786 CHECK_STRING (value);
7787 data = SDATA (value);
7788 if (INT_MAX < SBYTES (value))
7789 error ("VALUE too long");
7790
7791
7792 elsize = element_format == 32 ? sizeof (long) : element_format >> 3;
7793 if (SBYTES (value) % elsize != 0)
7794 error ("VALUE must contain an integral number of octets for FORMAT");
7795 nelements = SBYTES (value) / elsize;
7796 }
7797
7798 if (! NILP (window_id))
7799 {
7800 CONS_TO_INTEGER (window_id, Window, target_window);
7801 if (! target_window)
7802 target_window = dpyinfo->root_window;
7803 }
7804 else
7805 {
7806 if (! NILP (outer_p))
7807 target_window = FRAME_OUTER_WINDOW (f);
7808 else
7809 target_window = FRAME_X_WINDOW (f);
7810 }
7811
7812 block_input ();
7813 #ifndef USE_XCB
7814 prop_atom = x_intern_cached_atom (dpyinfo, SSDATA (prop),
7815 false);
7816 if (! NILP (type))
7817 {
7818 CHECK_STRING (type);
7819 target_type = x_intern_cached_atom (dpyinfo, SSDATA (type),
7820 false);
7821 }
7822 #else
7823 rc = true;
7824 intern_target = true;
7825 intern_prop = true;
7826
7827 prop_atom = x_intern_cached_atom (dpyinfo, SSDATA (prop),
7828 true);
7829
7830 if (prop_atom != None)
7831 intern_prop = false;
7832 else
7833 prop_atom_cookie
7834 = xcb_intern_atom (dpyinfo->xcb_connection,
7835 0, SBYTES (prop), SSDATA (prop));
7836
7837 if (!NILP (type))
7838 {
7839 CHECK_STRING (type);
7840
7841 target_type = x_intern_cached_atom (dpyinfo, SSDATA (type),
7842 true);
7843
7844 if (target_type)
7845 intern_target = false;
7846 else
7847 target_type_cookie
7848 = xcb_intern_atom (dpyinfo->xcb_connection,
7849 0, SBYTES (type), SSDATA (type));
7850 }
7851
7852 if (intern_prop)
7853 {
7854 reply = xcb_intern_atom_reply (dpyinfo->xcb_connection,
7855 prop_atom_cookie, &generic_error);
7856
7857 if (reply)
7858 {
7859 prop_atom = (Atom) reply->atom;
7860 free (reply);
7861 }
7862 else
7863 {
7864 free (generic_error);
7865 rc = false;
7866 }
7867 }
7868
7869 if (!NILP (type) && intern_target)
7870 {
7871 reply = xcb_intern_atom_reply (dpyinfo->xcb_connection,
7872 target_type_cookie, &generic_error);
7873
7874 if (reply)
7875 {
7876 target_type = (Atom) reply->atom;
7877 free (reply);
7878 }
7879 else
7880 {
7881 free (generic_error);
7882 rc = false;
7883 }
7884 }
7885
7886 if (!rc)
7887 error ("Failed to intern type or property atom");
7888 #endif
7889
7890 x_catch_errors_for_lisp (dpyinfo);
7891
7892 XChangeProperty (dpyinfo->display, target_window,
7893 prop_atom, target_type, element_format,
7894 PropModeReplace, data, nelements);
7895
7896 if (CONSP (value))
7897 xfree (data);
7898
7899 x_check_errors_for_lisp (dpyinfo,
7900 "Couldn't change window property: %s");
7901 x_uncatch_errors_for_lisp (dpyinfo);
7902
7903 unblock_input ();
7904 return value;
7905 }
7906
7907
7908 DEFUN ("x-delete-window-property", Fx_delete_window_property,
7909 Sx_delete_window_property, 1, 3, 0,
7910 doc:
7911
7912
7913
7914
7915
7916
7917
7918
7919
7920
7921
7922 )
7923 (Lisp_Object prop, Lisp_Object frame, Lisp_Object window_id)
7924 {
7925 struct frame *f = decode_window_system_frame (frame);
7926 Window target_window = FRAME_X_WINDOW (f);
7927 Atom prop_atom;
7928
7929 CHECK_STRING (prop);
7930
7931 if (! NILP (window_id))
7932 {
7933 CONS_TO_INTEGER (window_id, Window, target_window);
7934 if (! target_window)
7935 target_window = FRAME_DISPLAY_INFO (f)->root_window;
7936 }
7937
7938 block_input ();
7939 prop_atom = x_intern_cached_atom (FRAME_DISPLAY_INFO (f),
7940 SSDATA (prop), false);
7941
7942 x_catch_errors_for_lisp (FRAME_DISPLAY_INFO (f));
7943 XDeleteProperty (FRAME_X_DISPLAY (f), target_window, prop_atom);
7944 x_check_errors_for_lisp (FRAME_DISPLAY_INFO (f),
7945 "Couldn't delete window property: %s");
7946 x_uncatch_errors_for_lisp (FRAME_DISPLAY_INFO (f));
7947
7948 unblock_input ();
7949 return prop;
7950 }
7951
7952
7953 static Lisp_Object
7954 x_window_property_intern (struct frame *f,
7955 Window target_window,
7956 Atom prop_atom,
7957 Atom target_type,
7958 Lisp_Object delete_p,
7959 Lisp_Object vector_ret_p,
7960 bool *found)
7961 {
7962 unsigned char *tmp_data = NULL;
7963 Lisp_Object prop_value = Qnil;
7964 Atom actual_type;
7965 int actual_format;
7966 unsigned long actual_size, bytes_remaining;
7967 int rc;
7968
7969 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
7970 prop_atom, 0, 0, False, target_type,
7971 &actual_type, &actual_format, &actual_size,
7972 &bytes_remaining, &tmp_data);
7973
7974 *found = actual_format != 0;
7975
7976 if (rc == Success && *found)
7977 {
7978 XFree (tmp_data);
7979 tmp_data = NULL;
7980
7981 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
7982 prop_atom, 0, bytes_remaining,
7983 ! NILP (delete_p), target_type,
7984 &actual_type, &actual_format,
7985 &actual_size, &bytes_remaining,
7986 &tmp_data);
7987 if (rc == Success && tmp_data)
7988 {
7989
7990
7991
7992
7993
7994
7995
7996
7997
7998
7999
8000
8001
8002
8003 if (LONG_WIDTH > 32 && actual_format == 32)
8004 {
8005 unsigned long i;
8006 int *idata = (int *) tmp_data;
8007 long *ldata = (long *) tmp_data;
8008
8009 for (i = 0; i < actual_size; ++i)
8010 idata[i] = (int) ldata[i];
8011 }
8012
8013 if (NILP (vector_ret_p))
8014 prop_value = make_string ((char *) tmp_data,
8015 (actual_format >> 3) * actual_size);
8016 else
8017 prop_value = x_property_data_to_lisp (f,
8018 tmp_data,
8019 actual_type,
8020 actual_format,
8021 actual_size);
8022 }
8023
8024 if (tmp_data) XFree (tmp_data);
8025 }
8026
8027 return prop_value;
8028 }
8029
8030 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
8031 1, 6, 0,
8032 doc:
8033
8034
8035
8036
8037
8038
8039
8040
8041
8042
8043
8044
8045
8046
8047
8048
8049
8050
8051
8052
8053
8054
8055
8056
8057
8058
8059
8060
8061
8062
8063
8064
8065
8066
8067
8068
8069
8070 )
8071 (Lisp_Object prop, Lisp_Object frame, Lisp_Object type,
8072 Lisp_Object window_id, Lisp_Object delete_p, Lisp_Object vector_ret_p)
8073 {
8074 struct frame *f = decode_window_system_frame (frame);
8075 Atom prop_atom;
8076 Lisp_Object prop_value = Qnil;
8077 Atom target_type = XA_STRING;
8078 Window target_window = FRAME_X_WINDOW (f);
8079 bool found;
8080
8081 CHECK_STRING (prop);
8082
8083 if (! NILP (window_id))
8084 {
8085 CONS_TO_INTEGER (window_id, Window, target_window);
8086 if (! target_window)
8087 target_window = FRAME_DISPLAY_INFO (f)->root_window;
8088 }
8089
8090 block_input ();
8091 x_catch_errors (FRAME_X_DISPLAY (f));
8092
8093 if (STRINGP (type))
8094 {
8095 if (strcmp ("AnyPropertyType", SSDATA (type)) == 0)
8096 target_type = AnyPropertyType;
8097 else
8098 target_type = x_intern_cached_atom (FRAME_DISPLAY_INFO (f),
8099 SSDATA (type), false);
8100 }
8101
8102 prop_atom = x_intern_cached_atom (FRAME_DISPLAY_INFO (f),
8103 SSDATA (prop), false);
8104 prop_value = x_window_property_intern (f,
8105 target_window,
8106 prop_atom,
8107 target_type,
8108 delete_p,
8109 vector_ret_p,
8110 &found);
8111 if (NILP (prop_value)
8112 && ! found
8113 && NILP (window_id)
8114 && target_window != FRAME_OUTER_WINDOW (f))
8115 {
8116 prop_value = x_window_property_intern (f,
8117 FRAME_OUTER_WINDOW (f),
8118 prop_atom,
8119 target_type,
8120 delete_p,
8121 vector_ret_p,
8122 &found);
8123 }
8124
8125 x_check_errors (FRAME_X_DISPLAY (f),
8126 "Can't retrieve window property: %s");
8127 x_uncatch_errors_after_check ();
8128
8129 unblock_input ();
8130 return prop_value;
8131 }
8132
8133 DEFUN ("x-window-property-attributes", Fx_window_property_attributes, Sx_window_property_attributes,
8134 1, 3, 0,
8135 doc:
8136
8137
8138
8139
8140
8141
8142
8143
8144
8145
8146
8147
8148
8149 )
8150 (Lisp_Object prop, Lisp_Object frame, Lisp_Object window_id)
8151 {
8152 struct frame *f = decode_window_system_frame (frame);
8153 Window target_window = FRAME_X_WINDOW (f);
8154 Atom prop_atom;
8155 Lisp_Object prop_attr = Qnil;
8156 Atom actual_type;
8157 int actual_format;
8158 unsigned long actual_size, bytes_remaining;
8159 unsigned char *tmp_data = NULL;
8160 int rc;
8161
8162 CHECK_STRING (prop);
8163
8164 if (! NILP (window_id))
8165 {
8166 CONS_TO_INTEGER (window_id, Window, target_window);
8167 if (! target_window)
8168 target_window = FRAME_DISPLAY_INFO (f)->root_window;
8169 }
8170
8171 block_input ();
8172
8173 x_catch_errors (FRAME_X_DISPLAY (f));
8174 prop_atom = x_intern_cached_atom (FRAME_DISPLAY_INFO (f),
8175 SSDATA (prop), false);
8176 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
8177 prop_atom, 0, 0, False, AnyPropertyType,
8178 &actual_type, &actual_format, &actual_size,
8179 &bytes_remaining, &tmp_data);
8180 if (rc == Success
8181 && actual_format == 0
8182 && NILP (window_id)
8183 && target_window != FRAME_OUTER_WINDOW (f))
8184 {
8185
8186
8187
8188 target_window = FRAME_OUTER_WINDOW (f);
8189 rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
8190 prop_atom, 0, 0, False, AnyPropertyType,
8191 &actual_type, &actual_format, &actual_size,
8192 &bytes_remaining, &tmp_data);
8193 }
8194
8195 if (rc == Success && actual_format != 0)
8196 {
8197 XFree (tmp_data);
8198
8199 prop_attr = CALLN (Fvector,
8200 make_fixnum (actual_type),
8201 make_fixnum (actual_format),
8202 make_fixnum (bytes_remaining / (actual_format >> 3)));
8203 }
8204
8205 x_check_errors (FRAME_X_DISPLAY (f),
8206 "Can't retrieve window property: %s");
8207 x_uncatch_errors_after_check ();
8208
8209 unblock_input ();
8210 return prop_attr;
8211 }
8212
8213
8214
8215
8216
8217
8218 DEFUN ("x-translate-coordinates", Fx_translate_coordinates,
8219 Sx_translate_coordinates,
8220 1, 6, 0, doc:
8221
8222
8223
8224
8225
8226
8227
8228
8229
8230
8231
8232
8233
8234
8235
8236
8237
8238
8239
8240 )
8241 (Lisp_Object frame, Lisp_Object source_window,
8242 Lisp_Object dest_window, Lisp_Object source_x,
8243 Lisp_Object source_y, Lisp_Object require_child)
8244 {
8245 struct x_display_info *dpyinfo;
8246 struct frame *source_frame;
8247 int dest_x, dest_y;
8248 Window child_return, src, dest;
8249 Bool rc;
8250 Lisp_Object temp_result;
8251
8252 dpyinfo = check_x_display_info (frame);
8253 dest_x = 0;
8254 dest_y = 0;
8255
8256 if (!NILP (source_x))
8257 {
8258 CHECK_FIXNUM (source_x);
8259 dest_x = XFIXNUM (source_x);
8260 }
8261
8262 if (!NILP (source_y))
8263 {
8264 CHECK_FIXNUM (source_y);
8265 dest_y = XFIXNUM (source_y);
8266 }
8267
8268 source_frame = NULL;
8269
8270 if (!NILP (source_window))
8271 CONS_TO_INTEGER (source_window, Window, src);
8272 else
8273 {
8274 source_frame = decode_window_system_frame (frame);
8275 src = FRAME_X_WINDOW (source_frame);
8276 }
8277
8278
8279
8280 if (NILP (require_child) && source_frame)
8281 {
8282 temp_result
8283 = x_handle_translate_coordinates (source_frame, dest_window, dest_x,
8284 dest_y);
8285 if (!NILP (temp_result))
8286 return temp_result;
8287 }
8288
8289 if (!src)
8290 src = dpyinfo->root_window;
8291
8292 if (!NILP (dest_window))
8293 CONS_TO_INTEGER (dest_window, Window, dest);
8294 else
8295 dest = dpyinfo->root_window;
8296
8297 block_input ();
8298 x_catch_errors (dpyinfo->display);
8299 rc = XTranslateCoordinates (dpyinfo->display, src, dest,
8300 dest_x, dest_y, &dest_x, &dest_y,
8301 &child_return);
8302 x_check_errors (dpyinfo->display,
8303 "Couldn't translate coordinates: %s");
8304 x_uncatch_errors_after_check ();
8305 unblock_input ();
8306
8307 if (!rc)
8308 return Qnil;
8309
8310 return list3 (make_int (dest_x),
8311 make_int (dest_y),
8312 (child_return != None
8313 ? make_uint (child_return)
8314 : Qnil));
8315 }
8316
8317
8318
8319
8320
8321 static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
8322 Lisp_Object, int, int, int *, int *);
8323
8324
8325 Lisp_Object tip_frame;
8326
8327
8328
8329 Window tip_window;
8330
8331
8332 Lisp_Object tip_dx, tip_dy;
8333
8334
8335
8336 static Lisp_Object tip_timer;
8337
8338
8339 static Lisp_Object tip_last_string;
8340
8341
8342 static Lisp_Object tip_last_frame;
8343
8344
8345 static Lisp_Object tip_last_parms;
8346
8347
8348 static void
8349 unwind_create_tip_frame (Lisp_Object frame)
8350 {
8351 Lisp_Object deleted;
8352
8353 deleted = unwind_create_frame (frame);
8354 if (EQ (deleted, Qt))
8355 {
8356 tip_window = None;
8357 tip_frame = Qnil;
8358 }
8359 }
8360
8361
8362
8363
8364
8365
8366
8367
8368
8369
8370
8371 static Lisp_Object
8372 x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms)
8373 {
8374 struct frame *f;
8375 Lisp_Object frame;
8376 Lisp_Object name;
8377 specpdl_ref count = SPECPDL_INDEX ();
8378 bool face_change_before = face_change;
8379
8380 if (!dpyinfo->terminal->name)
8381 error ("Terminal is not live, can't create new frames on it");
8382
8383 parms = Fcopy_alist (parms);
8384
8385
8386 name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name",
8387 RES_TYPE_STRING);
8388 if (!STRINGP (name)
8389 && !BASE_EQ (name, Qunbound)
8390 && !NILP (name))
8391 error ("Invalid frame name--not a string or nil");
8392
8393 frame = Qnil;
8394 f = make_frame (false);
8395 f->wants_modeline = false;
8396 XSETFRAME (frame, f);
8397 record_unwind_protect (unwind_create_tip_frame, frame);
8398
8399 f->terminal = dpyinfo->terminal;
8400
8401
8402
8403
8404
8405 f->output_method = output_x_window;
8406 f->output_data.x = xzalloc (sizeof *f->output_data.x);
8407 f->output_data.x->icon_bitmap = -1;
8408 FRAME_FONTSET (f) = -1;
8409 f->output_data.x->scroll_bar_foreground_pixel = -1;
8410 f->output_data.x->scroll_bar_background_pixel = -1;
8411 #if defined (USE_LUCID) && defined (USE_TOOLKIT_SCROLL_BARS)
8412 f->output_data.x->scroll_bar_top_shadow_pixel = -1;
8413 f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
8414 #endif
8415 f->output_data.x->white_relief.pixel = -1;
8416 f->output_data.x->black_relief.pixel = -1;
8417
8418 f->tooltip = true;
8419 fset_icon_name (f, Qnil);
8420 FRAME_DISPLAY_INFO (f) = dpyinfo;
8421 f->output_data.x->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
8422 f->output_data.x->explicit_parent = false;
8423
8424
8425
8426 {
8427 Lisp_Object black;
8428
8429
8430
8431
8432 FRAME_FOREGROUND_PIXEL (f) = -1;
8433 FRAME_BACKGROUND_PIXEL (f) = -1;
8434 f->output_data.x->cursor_pixel = -1;
8435 f->output_data.x->cursor_foreground_pixel = -1;
8436 f->output_data.x->border_pixel = -1;
8437 f->output_data.x->mouse_pixel = -1;
8438
8439 black = build_string ("black");
8440 FRAME_FOREGROUND_PIXEL (f)
8441 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
8442 FRAME_BACKGROUND_PIXEL (f)
8443 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
8444 f->output_data.x->cursor_pixel
8445 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
8446 f->output_data.x->cursor_foreground_pixel
8447 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
8448 f->output_data.x->border_pixel
8449 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
8450 f->output_data.x->mouse_pixel
8451 = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
8452 }
8453
8454
8455
8456 if (BASE_EQ (name, Qunbound) || NILP (name))
8457 {
8458 fset_name (f, build_string (dpyinfo->x_id_name));
8459 f->explicit_name = false;
8460 }
8461 else
8462 {
8463 fset_name (f, name);
8464 f->explicit_name = true;
8465
8466 specbind (Qx_resource_name, name);
8467 }
8468
8469 #ifdef USE_CAIRO
8470 register_font_driver (&ftcrfont_driver, f);
8471 #ifdef HAVE_HARFBUZZ
8472 register_font_driver (&ftcrhbfont_driver, f);
8473 #endif
8474 #else
8475 #ifdef HAVE_FREETYPE
8476 #ifdef HAVE_XFT
8477 register_font_driver (&xftfont_driver, f);
8478 #ifdef HAVE_HARFBUZZ
8479 register_font_driver (&xfthbfont_driver, f);
8480 #endif
8481 #endif
8482 #endif
8483 #endif
8484 register_font_driver (&xfont_driver, f);
8485
8486 image_cache_refcount =
8487 FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
8488 #ifdef GLYPH_DEBUG
8489 dpyinfo_refcount = dpyinfo->reference_count;
8490 #endif
8491
8492 gui_default_parameter (f, parms, Qfont_backend, Qnil,
8493 "fontBackend", "FontBackend", RES_TYPE_STRING);
8494
8495
8496
8497 x_default_font_parameter (f, parms);
8498
8499 gui_default_parameter (f, parms, Qborder_width, make_fixnum (0),
8500 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
8501
8502
8503
8504
8505 if (NILP (Fassq (Qinternal_border_width, parms)))
8506 {
8507 Lisp_Object value;
8508
8509 value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width,
8510 "internalBorder", "internalBorder",
8511 RES_TYPE_NUMBER);
8512 if (! BASE_EQ (value, Qunbound))
8513 parms = Fcons (Fcons (Qinternal_border_width, value),
8514 parms);
8515 }
8516
8517 gui_default_parameter (f, parms, Qinternal_border_width, make_fixnum (1),
8518 "internalBorderWidth", "internalBorderWidth",
8519 RES_TYPE_NUMBER);
8520 gui_default_parameter (f, parms, Qright_divider_width, make_fixnum (0),
8521 NULL, NULL, RES_TYPE_NUMBER);
8522 gui_default_parameter (f, parms, Qbottom_divider_width, make_fixnum (0),
8523 NULL, NULL, RES_TYPE_NUMBER);
8524
8525
8526 gui_default_parameter (f, parms, Qforeground_color, build_string ("black"),
8527 "foreground", "Foreground", RES_TYPE_STRING);
8528 gui_default_parameter (f, parms, Qbackground_color, build_string ("white"),
8529 "background", "Background", RES_TYPE_STRING);
8530 gui_default_parameter (f, parms, Qmouse_color, build_string ("black"),
8531 "pointerColor", "Foreground", RES_TYPE_STRING);
8532 gui_default_parameter (f, parms, Qcursor_color, build_string ("black"),
8533 "cursorColor", "Foreground", RES_TYPE_STRING);
8534 gui_default_parameter (f, parms, Qborder_color, build_string ("black"),
8535 "borderColor", "BorderColor", RES_TYPE_STRING);
8536 gui_default_parameter (f, parms, Qno_special_glyphs, Qnil,
8537 NULL, NULL, RES_TYPE_BOOLEAN);
8538
8539 {
8540 #ifndef USE_XCB
8541 XSetWindowAttributes attrs;
8542 unsigned long mask;
8543 Atom type = FRAME_DISPLAY_INFO (f)->Xatom_net_window_type_tooltip;
8544
8545 block_input ();
8546 mask = (CWBackPixel | CWOverrideRedirect | CWEventMask
8547 | CWCursor | CWColormap | CWBorderPixel);
8548 if (DoesSaveUnders (dpyinfo->screen))
8549 mask |= CWSaveUnder;
8550
8551
8552
8553
8554 attrs.override_redirect = True;
8555 attrs.save_under = True;
8556 attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
8557 attrs.colormap = FRAME_X_COLORMAP (f);
8558 attrs.cursor =
8559 f->output_data.x->current_cursor
8560 = f->output_data.x->text_cursor;
8561 attrs.border_pixel = f->output_data.x->border_pixel;
8562
8563 attrs.event_mask = StructureNotifyMask;
8564 tip_window
8565 = FRAME_X_WINDOW (f)
8566 = XCreateWindow (FRAME_X_DISPLAY (f),
8567 FRAME_DISPLAY_INFO (f)->root_window,
8568
8569 0, 0, 1, 1,
8570
8571 f->border_width,
8572 dpyinfo->n_planes, InputOutput,
8573 FRAME_X_VISUAL (f),
8574 mask, &attrs);
8575 initial_set_up_x_back_buffer (f);
8576 XChangeProperty (FRAME_X_DISPLAY (f), tip_window,
8577 FRAME_DISPLAY_INFO (f)->Xatom_net_window_type,
8578 XA_ATOM, 32, PropModeReplace,
8579 (unsigned char *)&type, 1);
8580 unblock_input ();
8581 #else
8582 uint32_t value_list[6];
8583 xcb_atom_t net_wm_window_type_tooltip
8584 = (xcb_atom_t) dpyinfo->Xatom_net_window_type_tooltip;
8585 xcb_visualid_t visual_id
8586 = (xcb_visualid_t) XVisualIDFromVisual (FRAME_X_VISUAL (f));
8587
8588 f->output_data.x->current_cursor = f->output_data.x->text_cursor;
8589
8590
8591 value_list[0] = FRAME_BACKGROUND_PIXEL (f);
8592 value_list[1] = f->output_data.x->border_pixel;
8593 value_list[2] = true;
8594 value_list[3] = XCB_EVENT_MASK_STRUCTURE_NOTIFY;
8595 value_list[4] = (xcb_colormap_t) FRAME_X_COLORMAP (f);
8596 value_list[5] = (xcb_cursor_t) f->output_data.x->text_cursor;
8597
8598 block_input ();
8599 tip_window
8600 = FRAME_X_WINDOW (f)
8601 = (Window) xcb_generate_id (dpyinfo->xcb_connection);
8602
8603 xcb_create_window (dpyinfo->xcb_connection,
8604 dpyinfo->n_planes,
8605 (xcb_window_t) tip_window,
8606 (xcb_window_t) dpyinfo->root_window,
8607 0, 0, 1, 1, f->border_width,
8608 XCB_WINDOW_CLASS_INPUT_OUTPUT,
8609 visual_id,
8610 (XCB_CW_BACK_PIXEL
8611 | XCB_CW_BORDER_PIXEL
8612 | XCB_CW_OVERRIDE_REDIRECT
8613 | XCB_CW_EVENT_MASK
8614 | XCB_CW_COLORMAP
8615 | XCB_CW_CURSOR),
8616 &value_list);
8617
8618 xcb_change_property (dpyinfo->xcb_connection,
8619 XCB_PROP_MODE_REPLACE,
8620 (xcb_window_t) tip_window,
8621 (xcb_atom_t) dpyinfo->Xatom_net_window_type,
8622 (xcb_atom_t) dpyinfo->Xatom_ATOM,
8623 32, 1, &net_wm_window_type_tooltip);
8624
8625 initial_set_up_x_back_buffer (f);
8626 unblock_input ();
8627 #endif
8628 }
8629
8630
8631
8632
8633 init_frame_faces (f);
8634
8635 gui_default_parameter (f, parms, Qinhibit_double_buffering, Qnil,
8636 "inhibitDoubleBuffering", "InhibitDoubleBuffering",
8637 RES_TYPE_BOOLEAN);
8638
8639 gui_figure_window_size (f, parms, false, false);
8640
8641 f->output_data.x->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
8642
8643 x_make_gc (f);
8644
8645 gui_default_parameter (f, parms, Qauto_raise, Qnil,
8646 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
8647 gui_default_parameter (f, parms, Qauto_lower, Qnil,
8648 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
8649 gui_default_parameter (f, parms, Qcursor_type, Qbox,
8650 "cursorType", "CursorType", RES_TYPE_SYMBOL);
8651 gui_default_parameter (f, parms, Qalpha, Qnil,
8652 "alpha", "Alpha", RES_TYPE_NUMBER);
8653 gui_default_parameter (f, parms, Qalpha_background, Qnil,
8654 "alphaBackground", "AlphaBackground", RES_TYPE_NUMBER);
8655
8656
8657 if (NILP (Fframe_parameter (frame, Qtooltip)))
8658 {
8659 AUTO_FRAME_ARG (arg, Qtooltip, Qt);
8660 Fmodify_frame_parameters (frame, arg);
8661 }
8662
8663
8664
8665
8666
8667 {
8668 Lisp_Object disptype;
8669
8670 if (FRAME_DISPLAY_INFO (f)->n_planes == 1)
8671 disptype = Qmono;
8672 else if (FRAME_X_VISUAL_INFO (f)->class == GrayScale
8673 || FRAME_X_VISUAL_INFO (f)->class == StaticGray)
8674 disptype = Qgrayscale;
8675 else
8676 disptype = Qcolor;
8677
8678 if (NILP (Fframe_parameter (frame, Qdisplay_type)))
8679 {
8680 AUTO_FRAME_ARG (arg, Qdisplay_type, disptype);
8681 Fmodify_frame_parameters (frame, arg);
8682 }
8683 }
8684
8685
8686
8687
8688
8689
8690
8691
8692
8693 {
8694 Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
8695
8696 call2 (Qface_set_after_frame_default, frame, Qnil);
8697
8698 if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
8699 {
8700 AUTO_FRAME_ARG (arg, Qbackground_color, bg);
8701 Fmodify_frame_parameters (frame, arg);
8702 }
8703 }
8704
8705 f->no_split = true;
8706
8707
8708
8709 FRAME_DISPLAY_INFO (f)->reference_count++;
8710 f->terminal->reference_count++;
8711
8712
8713
8714
8715 Vframe_list = Fcons (frame, Vframe_list);
8716 f->can_set_window_size = true;
8717 adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
8718 0, true, Qtip_frame);
8719
8720
8721
8722
8723
8724
8725 face_change = face_change_before;
8726
8727
8728 return unbind_to (count, frame);
8729 }
8730
8731
8732
8733
8734
8735
8736
8737
8738 static void
8739 compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx,
8740 Lisp_Object dy, int width, int height, int *root_x,
8741 int *root_y)
8742 {
8743 Lisp_Object left, top, right, bottom;
8744 int win_x, win_y;
8745 Window root, child;
8746 unsigned pmask;
8747 int min_x, min_y, max_x, max_y = -1;
8748
8749
8750 left = CDR (Fassq (Qleft, parms));
8751 top = CDR (Fassq (Qtop, parms));
8752 right = CDR (Fassq (Qright, parms));
8753 bottom = CDR (Fassq (Qbottom, parms));
8754
8755
8756
8757 if ((!FIXNUMP (left) && !FIXNUMP (right))
8758 || (!FIXNUMP (top) && !FIXNUMP (bottom)))
8759 {
8760 Lisp_Object frame, attributes, monitor, geometry;
8761
8762 block_input ();
8763 x_query_pointer (FRAME_X_DISPLAY (f), FRAME_DISPLAY_INFO (f)->root_window,
8764 &root, &child, root_x, root_y, &win_x, &win_y, &pmask);
8765 unblock_input ();
8766
8767 XSETFRAME (frame, f);
8768
8769 #if defined HAVE_XRANDR || defined USE_GTK
8770 if (!NILP (FRAME_DISPLAY_INFO (f)->last_monitor_attributes_list))
8771
8772
8773
8774
8775 attributes = FRAME_DISPLAY_INFO (f)->last_monitor_attributes_list;
8776 else
8777 #endif
8778 attributes = Fx_display_monitor_attributes_list (frame);
8779
8780
8781
8782 while (CONSP (attributes))
8783 {
8784 monitor = XCAR (attributes);
8785 geometry = Fassq (Qgeometry, monitor);
8786 if (CONSP (geometry))
8787 {
8788 min_x = XFIXNUM (Fnth (make_fixnum (1), geometry));
8789 min_y = XFIXNUM (Fnth (make_fixnum (2), geometry));
8790 max_x = min_x + XFIXNUM (Fnth (make_fixnum (3), geometry));
8791 max_y = min_y + XFIXNUM (Fnth (make_fixnum (4), geometry));
8792
8793 if (min_x <= *root_x && *root_x < max_x
8794 && min_y <= *root_y && *root_y < max_y)
8795 {
8796 break;
8797 }
8798
8799 max_y = -1;
8800 }
8801
8802 attributes = XCDR (attributes);
8803 }
8804 }
8805
8806
8807
8808 if (max_y < 0)
8809 {
8810 min_x = 0;
8811 min_y = 0;
8812 max_x = x_display_pixel_width (FRAME_DISPLAY_INFO (f));
8813 max_y = x_display_pixel_height (FRAME_DISPLAY_INFO (f));
8814 }
8815
8816 if (FIXNUMP (top))
8817 *root_y = XFIXNUM (top);
8818 else if (FIXNUMP (bottom))
8819 *root_y = XFIXNUM (bottom) - height;
8820 else if (*root_y + XFIXNUM (dy) <= min_y)
8821 *root_y = min_y;
8822 else if (*root_y + XFIXNUM (dy) + height <= max_y)
8823
8824 *root_y += XFIXNUM (dy);
8825 else if (height + XFIXNUM (dy) + min_y <= *root_y)
8826
8827 *root_y -= height + XFIXNUM (dy);
8828 else
8829
8830 *root_y = min_y;
8831
8832 if (FIXNUMP (left))
8833 *root_x = XFIXNUM (left);
8834 else if (FIXNUMP (right))
8835 *root_x = XFIXNUM (right) - width;
8836 else if (*root_x + XFIXNUM (dx) <= min_x)
8837 *root_x = 0;
8838 else if (*root_x + XFIXNUM (dx) + width <= max_x)
8839
8840 *root_x += XFIXNUM (dx);
8841 else if (width + XFIXNUM (dx) + min_x <= *root_x)
8842
8843 *root_x -= width + XFIXNUM (dx);
8844 else
8845
8846 *root_x = min_x;
8847 }
8848
8849
8850
8851
8852
8853
8854
8855
8856
8857
8858
8859
8860
8861
8862
8863 static Lisp_Object
8864 x_hide_tip (bool delete)
8865 {
8866 if (!NILP (tip_timer))
8867 {
8868 call1 (Qcancel_timer, tip_timer);
8869 tip_timer = Qnil;
8870 }
8871
8872 #ifdef USE_GTK
8873
8874
8875
8876
8877
8878 if ((NILP (tip_last_frame) && NILP (tip_frame))
8879 || (!use_system_tooltips
8880 && !delete
8881 && !NILP (tip_frame)
8882 && FRAME_LIVE_P (XFRAME (tip_frame))
8883 && !FRAME_VISIBLE_P (XFRAME (tip_frame))))
8884
8885
8886
8887 return Qnil;
8888 else
8889 {
8890 Lisp_Object was_open = Qnil;
8891
8892 specpdl_ref count = SPECPDL_INDEX ();
8893 specbind (Qinhibit_redisplay, Qt);
8894 specbind (Qinhibit_quit, Qt);
8895
8896
8897 if (!NILP (tip_last_frame))
8898 {
8899 struct frame *f = XFRAME (tip_last_frame);
8900
8901 if (FRAME_LIVE_P (f))
8902 {
8903 if (xg_hide_tooltip (f))
8904 was_open = Qt;
8905 }
8906 }
8907
8908
8909
8910
8911 if (use_system_tooltips)
8912 tip_last_frame = Qnil;
8913
8914
8915 if (!NILP (tip_frame))
8916 {
8917 struct frame *f = XFRAME (tip_frame);
8918
8919 if (FRAME_LIVE_P (f))
8920 {
8921 if (delete || use_system_tooltips)
8922 {
8923
8924
8925
8926 delete_frame (tip_frame, Qnil);
8927 tip_frame = Qnil;
8928 }
8929 else
8930 x_make_frame_invisible (f);
8931
8932 was_open = Qt;
8933 }
8934 else
8935 tip_frame = Qnil;
8936 }
8937 else
8938 tip_frame = Qnil;
8939
8940 return unbind_to (count, was_open);
8941 }
8942 #else
8943 if (NILP (tip_frame)
8944 || (!delete
8945 && !NILP (tip_frame)
8946 && FRAME_LIVE_P (XFRAME (tip_frame))
8947 && !FRAME_VISIBLE_P (XFRAME (tip_frame))))
8948 return Qnil;
8949 else
8950 {
8951 Lisp_Object was_open = Qnil;
8952
8953 specpdl_ref count = SPECPDL_INDEX ();
8954 specbind (Qinhibit_redisplay, Qt);
8955 specbind (Qinhibit_quit, Qt);
8956
8957 if (!NILP (tip_frame))
8958 {
8959 struct frame *f = XFRAME (tip_frame);
8960
8961 if (FRAME_LIVE_P (f))
8962 {
8963 if (delete)
8964 {
8965 delete_frame (tip_frame, Qnil);
8966 tip_frame = Qnil;
8967 }
8968 else
8969 x_make_frame_invisible (XFRAME (tip_frame));
8970
8971 was_open = Qt;
8972 }
8973 else
8974 tip_frame = Qnil;
8975 }
8976 else
8977 tip_frame = Qnil;
8978
8979 return unbind_to (count, was_open);
8980 }
8981 #endif
8982 }
8983
8984
8985 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
8986 doc:
8987
8988
8989
8990
8991
8992
8993
8994
8995
8996
8997
8998
8999
9000
9001
9002
9003
9004
9005
9006
9007
9008
9009
9010
9011
9012
9013
9014
9015 )
9016 (Lisp_Object string, Lisp_Object frame, Lisp_Object parms,
9017 Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy)
9018 {
9019 struct frame *f, *tip_f;
9020 struct window *w;
9021 int root_x, root_y;
9022 struct buffer *old_buffer;
9023 struct text_pos pos;
9024 int width, height;
9025 int old_windows_or_buffers_changed = windows_or_buffers_changed;
9026 specpdl_ref count = SPECPDL_INDEX ();
9027 Lisp_Object window, size, tip_buf;
9028 bool displayed;
9029 #ifdef ENABLE_CHECKING
9030 struct glyph_row *row, *end;
9031 #endif
9032 AUTO_STRING (tip, " *tip*");
9033
9034 specbind (Qinhibit_redisplay, Qt);
9035
9036 CHECK_STRING (string);
9037 if (SCHARS (string) == 0)
9038 string = make_unibyte_string (" ", 1);
9039
9040 if (NILP (frame))
9041 frame = selected_frame;
9042 f = decode_window_system_frame (frame);
9043
9044 if (NILP (timeout))
9045 timeout = Vx_show_tooltip_timeout;
9046 CHECK_FIXNAT (timeout);
9047
9048 if (NILP (dx))
9049 dx = make_fixnum (5);
9050 else
9051 CHECK_FIXNUM (dx);
9052
9053 if (NILP (dy))
9054 dy = make_fixnum (-10);
9055 else
9056 CHECK_FIXNUM (dy);
9057
9058 tip_dx = dx;
9059 tip_dy = dy;
9060
9061 #ifdef USE_GTK
9062 if (use_system_tooltips)
9063 {
9064 bool ok;
9065
9066
9067 Fx_hide_tip ();
9068
9069 block_input ();
9070 ok = xg_prepare_tooltip (f, string, &width, &height);
9071 if (ok)
9072 {
9073 compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
9074 xg_show_tooltip (f, root_x, root_y);
9075 tip_last_frame = frame;
9076 }
9077
9078 unblock_input ();
9079 if (ok) goto start_timer;
9080 }
9081 #endif
9082
9083 if (!NILP (tip_frame) && FRAME_LIVE_P (XFRAME (tip_frame)))
9084 {
9085 if (FRAME_VISIBLE_P (XFRAME (tip_frame))
9086 && (FRAME_X_DISPLAY (XFRAME (frame))
9087 == FRAME_X_DISPLAY (XFRAME (tip_last_frame)))
9088 && !NILP (Fequal_including_properties (tip_last_string, string))
9089 && !NILP (Fequal (tip_last_parms, parms)))
9090 {
9091
9092 tip_f = XFRAME (tip_frame);
9093 if (!NILP (tip_timer))
9094 {
9095 call1 (Qcancel_timer, tip_timer);
9096 tip_timer = Qnil;
9097 }
9098
9099 block_input ();
9100 compute_tip_xy (tip_f, parms, dx, dy, FRAME_PIXEL_WIDTH (tip_f),
9101 FRAME_PIXEL_HEIGHT (tip_f), &root_x, &root_y);
9102 XMoveWindow (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f),
9103 root_x, root_y);
9104 unblock_input ();
9105
9106 goto start_timer;
9107 }
9108 else if (tooltip_reuse_hidden_frame && BASE_EQ (frame, tip_last_frame))
9109 {
9110 bool delete = false;
9111 Lisp_Object tail, elt, parm, last;
9112
9113
9114
9115
9116 for (tail = parms; CONSP (tail); tail = XCDR (tail))
9117 {
9118 elt = XCAR (tail);
9119 parm = CAR (elt);
9120
9121
9122 if (!EQ (parm, Qleft) && !EQ (parm, Qtop)
9123 && !EQ (parm, Qright) && !EQ (parm, Qbottom))
9124 {
9125 last = Fassq (parm, tip_last_parms);
9126 if (NILP (Fequal (CDR (elt), CDR (last))))
9127 {
9128
9129 delete = true;
9130 break;
9131 }
9132 else
9133 tip_last_parms =
9134 call2 (Qassq_delete_all, parm, tip_last_parms);
9135 }
9136 else
9137 tip_last_parms =
9138 call2 (Qassq_delete_all, parm, tip_last_parms);
9139 }
9140
9141
9142
9143
9144 for (tail = tip_last_parms; CONSP (tail); tail = XCDR (tail))
9145 {
9146 elt = XCAR (tail);
9147 parm = CAR (elt);
9148 if (!EQ (parm, Qleft) && !EQ (parm, Qtop) && !EQ (parm, Qright)
9149 && !EQ (parm, Qbottom) && !NILP (CDR (elt)))
9150 {
9151
9152 delete = true;
9153 break;
9154 }
9155 }
9156
9157 x_hide_tip (delete);
9158 }
9159 else
9160 x_hide_tip (true);
9161 }
9162 else
9163 x_hide_tip (true);
9164
9165 tip_last_frame = frame;
9166 tip_last_string = string;
9167 tip_last_parms = parms;
9168
9169 if (NILP (tip_frame) || !FRAME_LIVE_P (XFRAME (tip_frame)))
9170 {
9171
9172 if (NILP (Fassq (Qname, parms)))
9173 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
9174 if (NILP (Fassq (Qinternal_border_width, parms)))
9175 parms = Fcons (Fcons (Qinternal_border_width, make_fixnum (3)), parms);
9176 if (NILP (Fassq (Qborder_width, parms)))
9177 parms = Fcons (Fcons (Qborder_width, make_fixnum (1)), parms);
9178 if (NILP (Fassq (Qborder_color, parms)))
9179 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
9180 if (NILP (Fassq (Qbackground_color, parms)))
9181 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
9182 parms);
9183
9184
9185
9186 if (NILP (tip_frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parms)))
9187
9188 return unbind_to (count, Qnil);
9189 }
9190
9191 tip_f = XFRAME (tip_frame);
9192 window = FRAME_ROOT_WINDOW (tip_f);
9193 tip_buf = Fget_buffer_create (tip, Qnil);
9194
9195
9196 bset_left_margin_cols (XBUFFER (tip_buf), make_fixnum (0));
9197 bset_right_margin_cols (XBUFFER (tip_buf), make_fixnum (0));
9198 set_window_buffer (window, tip_buf, false, false);
9199 w = XWINDOW (window);
9200 w->pseudo_window_p = true;
9201
9202 Fset_window_parameter (window, Qno_other_window, Qt);
9203
9204
9205
9206
9207
9208 w->left_col = 0;
9209 w->top_line = 0;
9210 w->pixel_left = 0;
9211 w->pixel_top = 0;
9212
9213 if (CONSP (Vx_max_tooltip_size)
9214 && RANGED_FIXNUMP (1, XCAR (Vx_max_tooltip_size), INT_MAX)
9215 && RANGED_FIXNUMP (1, XCDR (Vx_max_tooltip_size), INT_MAX))
9216 {
9217 w->total_cols = XFIXNAT (XCAR (Vx_max_tooltip_size));
9218 w->total_lines = XFIXNAT (XCDR (Vx_max_tooltip_size));
9219 }
9220 else
9221 {
9222 w->total_cols = 80;
9223 w->total_lines = 40;
9224 }
9225
9226 w->pixel_width = w->total_cols * FRAME_COLUMN_WIDTH (tip_f);
9227 w->pixel_height = w->total_lines * FRAME_LINE_HEIGHT (tip_f);
9228 FRAME_TOTAL_COLS (tip_f) = w->total_cols;
9229 adjust_frame_glyphs (tip_f);
9230
9231
9232
9233 specpdl_ref count_1 = SPECPDL_INDEX ();
9234 old_buffer = current_buffer;
9235 set_buffer_internal_1 (XBUFFER (w->contents));
9236 bset_truncate_lines (current_buffer, Qnil);
9237 specbind (Qinhibit_read_only, Qt);
9238 specbind (Qinhibit_modification_hooks, Qt);
9239 specbind (Qinhibit_point_motion_hooks, Qt);
9240 Ferase_buffer ();
9241 Finsert (1, &string);
9242 clear_glyph_matrix (w->desired_matrix);
9243 clear_glyph_matrix (w->current_matrix);
9244 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
9245 displayed = try_window (window, pos, TRY_WINDOW_IGNORE_FONTS_CHANGE);
9246
9247 if (!displayed && NILP (Vx_max_tooltip_size))
9248 {
9249 #ifdef ENABLE_CHECKING
9250 row = w->desired_matrix->rows;
9251 end = w->desired_matrix->rows + w->desired_matrix->nrows;
9252
9253 while (row < end)
9254 {
9255 if (!row->displays_text_p
9256 || row->ends_at_zv_p)
9257 break;
9258 ++row;
9259 }
9260
9261 eassert (row < end && row->ends_at_zv_p);
9262 #endif
9263 }
9264
9265
9266 size = Fwindow_text_pixel_size (window, Qnil, Qnil, Qnil,
9267 make_fixnum (w->pixel_height), Qnil,
9268 Qnil);
9269
9270 width = XFIXNUM (CAR (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
9271 height = XFIXNUM (CDR (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
9272
9273
9274 compute_tip_xy (tip_f, parms, dx, dy, width, height, &root_x, &root_y);
9275
9276
9277 block_input ();
9278 #ifndef USE_XCB
9279 XMoveResizeWindow (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f),
9280 root_x, root_y, width, height);
9281 XMapRaised (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f));
9282 #else
9283 uint32_t values[] = { root_x, root_y, width, height, XCB_STACK_MODE_ABOVE };
9284
9285 xcb_configure_window (FRAME_DISPLAY_INFO (tip_f)->xcb_connection,
9286 (xcb_window_t) FRAME_X_WINDOW (tip_f),
9287 (XCB_CONFIG_WINDOW_X
9288 | XCB_CONFIG_WINDOW_Y
9289 | XCB_CONFIG_WINDOW_WIDTH
9290 | XCB_CONFIG_WINDOW_HEIGHT
9291 | XCB_CONFIG_WINDOW_STACK_MODE), &values);
9292 xcb_map_window (FRAME_DISPLAY_INFO (tip_f)->xcb_connection,
9293 (xcb_window_t) FRAME_X_WINDOW (tip_f));
9294 #endif
9295 unblock_input ();
9296
9297 #ifdef USE_CAIRO
9298 x_cr_update_surface_desired_size (tip_f, width, height);
9299 #endif
9300
9301 w->must_be_updated_p = true;
9302 update_single_window (w);
9303 flush_frame (tip_f);
9304 set_buffer_internal_1 (old_buffer);
9305 unbind_to (count_1, Qnil);
9306 windows_or_buffers_changed = old_windows_or_buffers_changed;
9307
9308 start_timer:
9309
9310 tip_timer = call3 (Qrun_at_time, timeout, Qnil,
9311 Qx_hide_tip);
9312
9313 return unbind_to (count, Qnil);
9314 }
9315
9316
9317 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
9318 doc:
9319 )
9320 (void)
9321 {
9322 return x_hide_tip (!tooltip_reuse_hidden_frame);
9323 }
9324
9325 DEFUN ("x-double-buffered-p", Fx_double_buffered_p, Sx_double_buffered_p,
9326 0, 1, 0,
9327 doc: )
9328 (Lisp_Object frame)
9329 {
9330 #ifdef HAVE_XDBE
9331 struct frame *f = decode_live_frame (frame);
9332 return FRAME_X_DOUBLE_BUFFERED_P (f) ? Qt : Qnil;
9333 #else
9334 return Qnil;
9335 #endif
9336 }
9337
9338
9339
9340
9341
9342
9343 DEFUN ("x-uses-old-gtk-dialog", Fx_uses_old_gtk_dialog,
9344 Sx_uses_old_gtk_dialog,
9345 0, 0, 0,
9346 doc: )
9347 (void)
9348 {
9349 #ifdef USE_GTK
9350 if (use_dialog_box
9351 && use_file_dialog
9352 && window_system_available (SELECTED_FRAME ())
9353 && xg_uses_old_file_dialog ())
9354 return Qt;
9355 #endif
9356 return Qnil;
9357 }
9358
9359
9360 #ifdef USE_MOTIF
9361
9362
9363 static void
9364 file_dialog_cb (Widget widget, XtPointer client_data, XtPointer call_data)
9365 {
9366 int *result = client_data;
9367 XmAnyCallbackStruct *cb = call_data;
9368 *result = cb->reason;
9369 }
9370
9371
9372
9373
9374
9375
9376
9377 static void
9378 file_dialog_unmap_cb (Widget widget, XtPointer client_data, XtPointer call_data)
9379 {
9380 int *result = client_data;
9381 *result = XmCR_CANCEL;
9382 }
9383
9384 static void
9385 clean_up_file_dialog (void *arg)
9386 {
9387 Widget dialog = arg;
9388
9389
9390 block_input ();
9391 XtUnmanageChild (dialog);
9392 XtDestroyWidget (dialog);
9393 x_menu_set_in_use (false);
9394 unblock_input ();
9395 }
9396
9397
9398 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
9399 doc: )
9400 (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename,
9401 Lisp_Object mustmatch, Lisp_Object only_dir_p)
9402 {
9403 int result;
9404 struct frame *f = SELECTED_FRAME ();
9405 Lisp_Object file = Qnil;
9406 Lisp_Object decoded_file;
9407 Widget dialog, text, help;
9408 Arg al[10];
9409 int ac = 0;
9410 XmString dir_xmstring, pattern_xmstring;
9411 specpdl_ref count = SPECPDL_INDEX ();
9412
9413 check_window_system (f);
9414
9415 if (popup_activated ())
9416 error ("Trying to use a menu from within a menu-entry");
9417
9418 CHECK_STRING (prompt);
9419 CHECK_STRING (dir);
9420
9421
9422 specbind (Qinhibit_redisplay, Qt);
9423
9424
9425 DEFER_SELECTIONS;
9426
9427 block_input ();
9428
9429
9430
9431 dir = Fexpand_file_name (dir, Qnil);
9432 dir_xmstring = XmStringCreateLocalized (SSDATA (dir));
9433 pattern_xmstring = XmStringCreateLocalized ("*");
9434
9435 XtSetArg (al[ac], XmNtitle, SDATA (prompt)); ++ac;
9436 XtSetArg (al[ac], XmNdirectory, dir_xmstring); ++ac;
9437 XtSetArg (al[ac], XmNpattern, pattern_xmstring); ++ac;
9438 XtSetArg (al[ac], XmNresizePolicy, XmRESIZE_GROW); ++ac;
9439 XtSetArg (al[ac], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); ++ac;
9440 dialog = XmCreateFileSelectionDialog (f->output_data.x->widget,
9441 "fsb", al, ac);
9442 XmStringFree (dir_xmstring);
9443 XmStringFree (pattern_xmstring);
9444
9445
9446 XtAddCallback (dialog, XmNokCallback, file_dialog_cb,
9447 (XtPointer) &result);
9448 XtAddCallback (dialog, XmNcancelCallback, file_dialog_cb,
9449 (XtPointer) &result);
9450 XtAddCallback (dialog, XmNunmapCallback, file_dialog_unmap_cb,
9451 (XtPointer) &result);
9452
9453
9454 help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON);
9455 XtUnmanageChild (help);
9456
9457
9458 XtVaSetValues (XmFileSelectionBoxGetChild (dialog, XmDIALOG_OK_BUTTON),
9459 XmNshowAsDefault, True, NULL);
9460
9461
9462
9463
9464
9465 text = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
9466 if (!NILP (mustmatch))
9467 {
9468 Widget label;
9469 label = XmFileSelectionBoxGetChild (dialog, XmDIALOG_SELECTION_LABEL);
9470 XtSetSensitive (text, False);
9471 XtSetSensitive (label, False);
9472 }
9473
9474
9475 XtManageChild (dialog);
9476
9477 if (STRINGP (default_filename))
9478 {
9479 XmString default_xmstring;
9480 Widget wtext = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
9481 Widget list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
9482
9483 XmTextPosition last_pos = XmTextFieldGetLastPosition (wtext);
9484 XmTextFieldReplace (wtext, 0, last_pos,
9485 (SSDATA (Ffile_name_nondirectory (default_filename))));
9486
9487
9488
9489
9490 default_xmstring = XmStringCreateLocalized (SSDATA (default_filename));
9491
9492 if (XmListItemExists (list, default_xmstring))
9493 {
9494 int item_pos = XmListItemPos (list, default_xmstring);
9495
9496 XmListSelectPos (list, item_pos, True);
9497 XmListSetPos (list, item_pos);
9498 }
9499
9500 XmStringFree (default_xmstring);
9501 }
9502
9503 record_unwind_protect_ptr (clean_up_file_dialog, dialog);
9504
9505
9506 x_menu_set_in_use (true);
9507 result = 0;
9508 while (result == 0)
9509 {
9510 XEvent event, copy;
9511 x_menu_wait_for_event (0);
9512
9513 if (XtAppPending (Xt_app_con))
9514 {
9515 XtAppNextEvent (Xt_app_con, &event);
9516
9517 copy = event;
9518 if (event.type == KeyPress
9519 && FRAME_X_DISPLAY (f) == event.xkey.display)
9520 {
9521 KeySym keysym = XLookupKeysym (&event.xkey, 0);
9522
9523
9524 if (keysym == XK_g && (event.xkey.state & ControlMask) != 0)
9525 XtUnmanageChild (dialog);
9526 }
9527 #ifdef HAVE_XINPUT2
9528 else if (event.type == GenericEvent
9529 && FRAME_X_DISPLAY (f) == event.xgeneric.display
9530 && FRAME_DISPLAY_INFO (f)->supports_xi2
9531 && (event.xgeneric.extension
9532 == FRAME_DISPLAY_INFO (f)->xi2_opcode)
9533 && event.xgeneric.evtype == XI_KeyPress)
9534 {
9535 KeySym keysym;
9536 XIDeviceEvent *xev;
9537
9538 if (event.xcookie.data)
9539 emacs_abort ();
9540
9541 if (XGetEventData (FRAME_X_DISPLAY (f), &event.xcookie))
9542 {
9543 xev = (XIDeviceEvent *) event.xcookie.data;
9544
9545 copy.xkey.type = KeyPress;
9546 copy.xkey.serial = xev->serial;
9547 copy.xkey.send_event = xev->send_event;
9548 copy.xkey.display = FRAME_X_DISPLAY (f);
9549 copy.xkey.window = xev->event;
9550 copy.xkey.root = xev->root;
9551 copy.xkey.subwindow = xev->child;
9552 copy.xkey.time = xev->time;
9553 copy.xkey.x = lrint (xev->event_x);
9554 copy.xkey.y = lrint (xev->event_y);
9555 copy.xkey.x_root = lrint (xev->root_x);
9556 copy.xkey.y_root = lrint (xev->root_y);
9557 copy.xkey.state = xev->mods.effective;
9558 copy.xkey.keycode = xev->detail;
9559 copy.xkey.same_screen = True;
9560
9561 keysym = XLookupKeysym (©.xkey, 0);
9562
9563 if (keysym == XK_g
9564 && (copy.xkey.state & ControlMask) != 0)
9565 XtUnmanageChild (dialog);
9566
9567 XFreeEventData (FRAME_X_DISPLAY (f), &event.xcookie);
9568 }
9569 }
9570 #endif
9571
9572 (void) x_dispatch_event (©, FRAME_X_DISPLAY (f));
9573 }
9574 }
9575
9576
9577 if (result == XmCR_OK)
9578 {
9579 XmString text_string;
9580 String data;
9581
9582 XtVaGetValues (dialog, XmNtextString, &text_string, NULL);
9583 XmStringGetLtoR (text_string, XmFONTLIST_DEFAULT_TAG, &data);
9584 XmStringFree (text_string);
9585 file = build_string (data);
9586 XtFree (data);
9587 }
9588 else
9589 file = Qnil;
9590
9591 unblock_input ();
9592
9593
9594 if (NILP (file))
9595 quit ();
9596
9597 decoded_file = DECODE_FILE (file);
9598
9599 return unbind_to (count, decoded_file);
9600 }
9601
9602 #endif
9603
9604 #ifdef USE_GTK
9605
9606 static void
9607 clean_up_dialog (void)
9608 {
9609 x_menu_set_in_use (false);
9610 }
9611
9612 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
9613 doc:
9614
9615
9616
9617
9618
9619
9620
9621
9622
9623
9624 )
9625 (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename, Lisp_Object mustmatch, Lisp_Object only_dir_p)
9626 {
9627 struct frame *f = SELECTED_FRAME ();
9628 char *fn;
9629 Lisp_Object file = Qnil;
9630 Lisp_Object decoded_file;
9631 specpdl_ref count = SPECPDL_INDEX ();
9632 char *cdef_file;
9633
9634 check_window_system (f);
9635
9636 if (popup_activated ())
9637 error ("Trying to use a menu from within a menu-entry");
9638 else
9639 x_menu_set_in_use (true);
9640
9641 CHECK_STRING (prompt);
9642 CHECK_STRING (dir);
9643
9644
9645 specbind (Qinhibit_redisplay, Qt);
9646 record_unwind_protect_void (clean_up_dialog);
9647
9648 block_input ();
9649
9650 if (STRINGP (default_filename))
9651 cdef_file = SSDATA (default_filename);
9652 else
9653 cdef_file = SSDATA (dir);
9654
9655 fn = xg_get_file_name (f, SSDATA (prompt), cdef_file,
9656 ! NILP (mustmatch),
9657 ! NILP (only_dir_p));
9658
9659 if (fn)
9660 {
9661 file = build_string (fn);
9662 xfree (fn);
9663 }
9664
9665 unblock_input ();
9666
9667
9668 if (NILP (file))
9669 quit ();
9670
9671 decoded_file = DECODE_FILE (file);
9672
9673 return unbind_to (count, decoded_file);
9674 }
9675
9676
9677 #ifdef HAVE_FREETYPE
9678
9679 DEFUN ("x-select-font", Fx_select_font, Sx_select_font, 0, 2, 0,
9680 doc:
9681
9682
9683
9684
9685 )
9686 (Lisp_Object frame, Lisp_Object ignored)
9687 {
9688 struct frame *f = decode_window_system_frame (frame);
9689 Lisp_Object font;
9690 Lisp_Object font_param;
9691 char *default_name = NULL;
9692 specpdl_ref count = SPECPDL_INDEX ();
9693
9694 if (popup_activated ())
9695 error ("Trying to use a menu from within a menu-entry");
9696 else
9697 x_menu_set_in_use (true);
9698
9699
9700 specbind (Qinhibit_redisplay, Qt);
9701 record_unwind_protect_void (clean_up_dialog);
9702
9703 block_input ();
9704
9705 XSETFONT (font, FRAME_FONT (f));
9706 font_param = Ffont_get (font, QCname);
9707 if (STRINGP (font_param))
9708 default_name = xlispstrdup (font_param);
9709 else
9710 {
9711 font_param = Fframe_parameter (frame, Qfont_parameter);
9712 if (STRINGP (font_param))
9713 default_name = xlispstrdup (font_param);
9714 }
9715
9716 font = xg_get_font (f, default_name);
9717 xfree (default_name);
9718
9719 unblock_input ();
9720
9721 if (NILP (font))
9722 quit ();
9723
9724 return unbind_to (count, font);
9725 }
9726 #endif
9727
9728 #endif
9729
9730
9731
9732
9733
9734
9735 #ifdef HAVE_XKB
9736 #include <X11/XKBlib.h>
9737 #include <X11/keysym.h>
9738 #endif
9739
9740 DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p,
9741 Sx_backspace_delete_keys_p, 0, 1, 0,
9742 doc:
9743
9744
9745
9746 )
9747 (Lisp_Object frame)
9748 {
9749 #ifdef HAVE_XKB
9750 XkbDescPtr kb;
9751 struct frame *f;
9752 Display *dpy;
9753 Lisp_Object have_keys;
9754 int delete_keycode, backspace_keycode, i;
9755 #endif
9756
9757 #ifndef HAVE_XKB
9758 return Qlambda;
9759 #else
9760 delete_keycode = 0;
9761 backspace_keycode = 0;
9762 f = decode_window_system_frame (frame);
9763 dpy = FRAME_X_DISPLAY (f);
9764
9765 if (!FRAME_DISPLAY_INFO (f)->supports_xkb)
9766 return Qlambda;
9767
9768 block_input ();
9769
9770
9771
9772
9773
9774
9775
9776
9777
9778
9779
9780
9781
9782
9783
9784
9785
9786 have_keys = Qnil;
9787 kb = FRAME_DISPLAY_INFO (f)->xkb_desc;
9788 if (kb && kb->names)
9789 {
9790 for (i = kb->min_key_code; (i < kb->max_key_code
9791 && (delete_keycode == 0
9792 || backspace_keycode == 0));
9793 ++i)
9794 {
9795
9796
9797
9798 if (!memcmp ("DELE", kb->names->keys[i].name, 4))
9799 delete_keycode = i;
9800 else if (!memcmp ("BKSP", kb->names->keys[i].name, 4))
9801 backspace_keycode = i;
9802 }
9803
9804 if (delete_keycode && backspace_keycode
9805 && XKeysymToKeycode (dpy, XK_Delete) == delete_keycode
9806 && XKeysymToKeycode (dpy, XK_BackSpace) == backspace_keycode)
9807 have_keys = Qt;
9808 }
9809 else
9810
9811 have_keys = Qlambda;
9812 unblock_input ();
9813 return have_keys;
9814 #endif
9815 }
9816
9817 DEFUN ("x-get-modifier-masks", Fx_get_modifier_masks, Sx_get_modifier_masks,
9818 0, 1, 0,
9819 doc:
9820
9821
9822
9823
9824
9825
9826
9827 )
9828 (Lisp_Object terminal)
9829 {
9830 struct x_display_info *dpyinfo;
9831
9832 dpyinfo = check_x_display_info (terminal);
9833 return x_get_keyboard_modifiers (dpyinfo);
9834 }
9835
9836
9837
9838
9839
9840
9841 #ifdef USE_CAIRO
9842 DEFUN ("x-export-frames", Fx_export_frames, Sx_export_frames, 0, 2, 0,
9843 doc:
9844
9845
9846
9847
9848
9849
9850
9851 )
9852 (Lisp_Object frames, Lisp_Object type)
9853 {
9854 Lisp_Object rest, tmp;
9855 cairo_surface_type_t surface_type;
9856
9857 if (!CONSP (frames))
9858 frames = list1 (frames);
9859
9860 tmp = Qnil;
9861 for (rest = frames; CONSP (rest); rest = XCDR (rest))
9862 {
9863 struct frame *f = decode_window_system_frame (XCAR (rest));
9864 Lisp_Object frame;
9865
9866 XSETFRAME (frame, f);
9867 if (!FRAME_VISIBLE_P (f))
9868 error ("Frames to be exported must be visible.");
9869 tmp = Fcons (frame, tmp);
9870 }
9871 frames = Fnreverse (tmp);
9872
9873 #ifdef CAIRO_HAS_PDF_SURFACE
9874 if (NILP (type) || EQ (type, Qpdf))
9875 surface_type = CAIRO_SURFACE_TYPE_PDF;
9876 else
9877 #endif
9878 #ifdef CAIRO_HAS_PNG_FUNCTIONS
9879 if (EQ (type, Qpng))
9880 {
9881 if (!NILP (XCDR (frames)))
9882 error ("PNG export cannot handle multiple frames.");
9883 surface_type = CAIRO_SURFACE_TYPE_IMAGE;
9884 }
9885 else
9886 #endif
9887 #ifdef CAIRO_HAS_PS_SURFACE
9888 if (EQ (type, Qpostscript))
9889 surface_type = CAIRO_SURFACE_TYPE_PS;
9890 else
9891 #endif
9892 #ifdef CAIRO_HAS_SVG_SURFACE
9893 if (EQ (type, Qsvg))
9894 {
9895
9896 if (!NILP (XCDR (frames)))
9897 error ("SVG export cannot handle multiple frames.");
9898 surface_type = CAIRO_SURFACE_TYPE_SVG;
9899 }
9900 else
9901 #endif
9902 error ("Unsupported export type");
9903
9904 return x_cr_export_frames (frames, surface_type);
9905 }
9906
9907 #ifdef USE_GTK
9908 DEFUN ("x-page-setup-dialog", Fx_page_setup_dialog, Sx_page_setup_dialog, 0, 0, 0,
9909 doc:
9910 )
9911 (void)
9912 {
9913 block_input ();
9914 xg_page_setup_dialog ();
9915 unblock_input ();
9916
9917 return Qnil;
9918 }
9919
9920 DEFUN ("x-get-page-setup", Fx_get_page_setup, Sx_get_page_setup, 0, 0, 0,
9921 doc:
9922
9923
9924
9925
9926
9927
9928
9929
9930
9931
9932
9933
9934
9935
9936
9937 )
9938 (void)
9939 {
9940 Lisp_Object result;
9941
9942 block_input ();
9943 result = xg_get_page_setup ();
9944 unblock_input ();
9945
9946 return result;
9947 }
9948
9949 DEFUN ("x-print-frames-dialog", Fx_print_frames_dialog, Sx_print_frames_dialog, 0, 1, "",
9950 doc:
9951
9952
9953
9954
9955 )
9956 (Lisp_Object frames)
9957 {
9958 Lisp_Object rest, tmp;
9959
9960 if (!CONSP (frames))
9961 frames = list1 (frames);
9962
9963 tmp = Qnil;
9964 for (rest = frames; CONSP (rest); rest = XCDR (rest))
9965 {
9966 struct frame *f = decode_window_system_frame (XCAR (rest));
9967 Lisp_Object frame;
9968
9969 XSETFRAME (frame, f);
9970 if (!FRAME_VISIBLE_P (f))
9971 error ("Frames to be printed must be visible.");
9972 tmp = Fcons (frame, tmp);
9973 }
9974 frames = Fnreverse (tmp);
9975
9976
9977 specpdl_ref count = SPECPDL_INDEX ();
9978 specbind (Qredisplay_dont_pause, Qt);
9979 redisplay_preserve_echo_area (32);
9980 unbind_to (count, Qnil);
9981
9982 block_input ();
9983 xg_print_frames_dialog (frames);
9984 unblock_input ();
9985
9986 return Qnil;
9987 }
9988 #endif
9989 #endif
9990
9991 #ifdef USE_GTK
9992 #ifdef HAVE_GTK3
9993 #if GTK_CHECK_VERSION (3, 14, 0)
9994 DEFUN ("x-gtk-debug", Fx_gtk_debug, Sx_gtk_debug, 1, 1, 0,
9995 doc: )
9996 (Lisp_Object enable)
9997 {
9998 gboolean enable_debug = !NILP (enable);
9999
10000 block_input ();
10001 gtk_window_set_interactive_debugging (enable_debug);
10002 unblock_input ();
10003
10004 return NILP (enable) ? Qnil : Qt;
10005 }
10006 #endif
10007 #endif
10008 #endif
10009
10010 DEFUN ("x-display-set-last-user-time", Fx_display_last_user_time,
10011 Sx_display_set_last_user_time, 1, 2, 0,
10012 doc:
10013
10014
10015
10016
10017
10018
10019 )
10020 (Lisp_Object time_object, Lisp_Object terminal)
10021 {
10022 struct x_display_info *dpyinfo;
10023 uint32_t time;
10024
10025
10026
10027 dpyinfo = check_x_display_info (terminal);
10028 CONS_TO_INTEGER (time_object, uint32_t, time);
10029
10030 x_set_last_user_time_from_lisp (dpyinfo, time);
10031 return Qnil;
10032 }
10033
10034 DEFUN ("x-internal-focus-input-context", Fx_internal_focus_input_context,
10035 Sx_internal_focus_input_context, 1, 1, 0,
10036 doc:
10037
10038 )
10039 (Lisp_Object focus)
10040 {
10041 #ifdef USE_GTK
10042 struct x_display_info *dpyinfo;
10043 struct frame *f;
10044 GtkWidget *widget;
10045
10046 block_input ();
10047 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
10048 {
10049 f = dpyinfo->x_focus_frame;
10050
10051 if (f)
10052 {
10053 widget = FRAME_GTK_OUTER_WIDGET (f);
10054
10055 if (!NILP (focus))
10056 {
10057 gtk_im_context_focus_in (FRAME_X_OUTPUT (f)->im_context);
10058 gtk_im_context_set_client_window (FRAME_X_OUTPUT (f)->im_context,
10059 gtk_widget_get_window (widget));
10060 }
10061 else
10062 {
10063 gtk_im_context_focus_out (FRAME_X_OUTPUT (f)->im_context);
10064 gtk_im_context_set_client_window (FRAME_X_OUTPUT (f)->im_context,
10065 NULL);
10066 }
10067 }
10068 }
10069 unblock_input ();
10070 #endif
10071
10072 return Qnil;
10073 }
10074
10075 #if 0
10076
10077 DEFUN ("x-test-string-conversion", Fx_test_string_conversion,
10078 Sx_test_string_conversion, 5, 5, 0,
10079 doc: )
10080 (Lisp_Object frame, Lisp_Object position,
10081 Lisp_Object direction, Lisp_Object operation, Lisp_Object factor)
10082 {
10083 struct frame *f;
10084 XIMStringConversionCallbackStruct call_data;
10085 XIMStringConversionText text;
10086
10087 f = decode_window_system_frame (frame);
10088
10089 if (!FRAME_XIC (f))
10090 error ("No XIC on FRAME!");
10091
10092 CHECK_FIXNUM (position);
10093 CHECK_FIXNUM (direction);
10094 CHECK_FIXNUM (operation);
10095 CHECK_FIXNUM (factor);
10096
10097
10098
10099
10100 call_data.position = XFIXNUM (position);
10101 call_data.direction = XFIXNUM (direction);
10102 call_data.operation = XFIXNUM (operation);
10103 call_data.factor = XFIXNUM (factor);
10104 call_data.text = &text;
10105
10106 block_input ();
10107 xic_string_conversion_callback (FRAME_XIC (f), NULL,
10108 &call_data);
10109 unblock_input ();
10110
10111
10112
10113 while (1)
10114 maybe_quit ();
10115
10116 return Qnil;
10117 }
10118
10119 #endif
10120
10121
10122
10123
10124
10125
10126
10127
10128
10129 frame_parm_handler x_frame_parm_handlers[] =
10130 {
10131 gui_set_autoraise,
10132 gui_set_autolower,
10133 x_set_background_color,
10134 x_set_border_color,
10135 gui_set_border_width,
10136 x_set_cursor_color,
10137 x_set_cursor_type,
10138 gui_set_font,
10139 x_set_foreground_color,
10140 x_set_icon_name,
10141 x_set_icon_type,
10142 x_set_child_frame_border_width,
10143 x_set_internal_border_width,
10144 gui_set_right_divider_width,
10145 gui_set_bottom_divider_width,
10146 x_set_menu_bar_lines,
10147 x_set_mouse_color,
10148 x_explicitly_set_name,
10149 gui_set_scroll_bar_width,
10150 gui_set_scroll_bar_height,
10151 x_set_title,
10152 gui_set_unsplittable,
10153 gui_set_vertical_scroll_bars,
10154 gui_set_horizontal_scroll_bars,
10155 gui_set_visibility,
10156 x_set_tab_bar_lines,
10157 x_set_tool_bar_lines,
10158 x_set_scroll_bar_foreground,
10159 x_set_scroll_bar_background,
10160 gui_set_screen_gamma,
10161 gui_set_line_spacing,
10162 gui_set_left_fringe,
10163 gui_set_right_fringe,
10164 x_set_wait_for_wm,
10165 gui_set_fullscreen,
10166 gui_set_font_backend,
10167 x_set_alpha,
10168 x_set_sticky,
10169 x_set_tool_bar_position,
10170 #ifdef HAVE_XDBE
10171 x_set_inhibit_double_buffering,
10172 #else
10173 NULL,
10174 #endif
10175 x_set_undecorated,
10176 x_set_parent_frame,
10177 x_set_skip_taskbar,
10178 x_set_no_focus_on_map,
10179 x_set_no_accept_focus,
10180 x_set_z_group,
10181 x_set_override_redirect,
10182 gui_set_no_special_glyphs,
10183 x_set_alpha_background,
10184 x_set_use_frame_synchronization,
10185 x_set_shaded,
10186 };
10187
10188
10189
10190
10191 #ifdef HAVE_XKB
10192 #ifndef HAVE_XKBREFRESHKEYBOARDMAPPING
10193 Status
10194 XkbRefreshKeyboardMapping (XkbMapNotifyEvent *event)
10195 {
10196 return Success;
10197 }
10198 #endif
10199
10200 #ifndef HAVE_XKBFREENAMES
10201 void
10202 XkbFreeNames (XkbDescPtr xkb, unsigned int which, Bool free_map)
10203 {
10204 return;
10205 }
10206 #endif
10207 #endif
10208
10209 #ifndef HAVE_XDISPLAYCELLS
10210 int
10211 XDisplayCells (Display *dpy, int screen_number)
10212 {
10213 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
10214
10215 if (!dpyinfo)
10216 emacs_abort ();
10217
10218
10219
10220
10221 return dpyinfo->visual_info.colormap_size;
10222 }
10223 #endif
10224
10225 #ifndef HAVE_XDESTROYSUBWINDOWS
10226 int
10227 XDestroySubwindows (Display *dpy, Window w)
10228 {
10229 Window root, parent, *children;
10230 unsigned int nchildren, i;
10231
10232 if (XQueryTree (dpy, w, &root, &parent, &children,
10233 &nchildren))
10234 {
10235 for (i = 0; i < nchildren; ++i)
10236 XDestroyWindow (dpy, children[i]);
10237 XFree (children);
10238 }
10239
10240 return 0;
10241 }
10242 #endif
10243
10244 void
10245 syms_of_xfns (void)
10246 {
10247 DEFSYM (Qundefined_color, "undefined-color");
10248 DEFSYM (Qcompound_text, "compound-text");
10249 DEFSYM (Qcancel_timer, "cancel-timer");
10250 DEFSYM (Qfont_parameter, "font-parameter");
10251 DEFSYM (Qmono, "mono");
10252 DEFSYM (Qassq_delete_all, "assq-delete-all");
10253 DEFSYM (Qresize_mode, "resize-mode");
10254
10255 #ifdef USE_CAIRO
10256 DEFSYM (Qpdf, "pdf");
10257
10258 DEFSYM (Qorientation, "orientation");
10259 DEFSYM (Qtop_margin, "top-margin");
10260 DEFSYM (Qbottom_margin, "bottom-margin");
10261 DEFSYM (Qportrait, "portrait");
10262 DEFSYM (Qlandscape, "landscape");
10263 DEFSYM (Qreverse_portrait, "reverse-portrait");
10264 DEFSYM (Qreverse_landscape, "reverse-landscape");
10265 #endif
10266
10267 DEFSYM (QXdndActionCopy, "XdndActionCopy");
10268 DEFSYM (QXdndActionMove, "XdndActionMove");
10269 DEFSYM (QXdndActionLink, "XdndActionLink");
10270 DEFSYM (QXdndActionAsk, "XdndActionAsk");
10271 DEFSYM (QXdndActionPrivate, "XdndActionPrivate");
10272
10273 Fput (Qundefined_color, Qerror_conditions,
10274 pure_list (Qundefined_color, Qerror));
10275 Fput (Qundefined_color, Qerror_message,
10276 build_pure_c_string ("Undefined color"));
10277
10278 DEFVAR_LISP ("x-pointer-shape", Vx_pointer_shape,
10279 doc:
10280
10281 );
10282 Vx_pointer_shape = Qnil;
10283
10284 #if false
10285 DEFVAR_LISP ("x-nontext-pointer-shape", Vx_nontext_pointer_shape,
10286 doc:
10287
10288 );
10289 #endif
10290 Vx_nontext_pointer_shape = Qnil;
10291
10292 DEFVAR_LISP ("x-hourglass-pointer-shape", Vx_hourglass_pointer_shape,
10293 doc:
10294
10295 );
10296 Vx_hourglass_pointer_shape = Qnil;
10297
10298 #if false
10299 DEFVAR_LISP ("x-mode-pointer-shape", Vx_mode_pointer_shape,
10300 doc:
10301
10302 );
10303 #endif
10304 Vx_mode_pointer_shape = Qnil;
10305
10306 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
10307 Vx_sensitive_text_pointer_shape,
10308 doc:
10309
10310 );
10311 Vx_sensitive_text_pointer_shape = Qnil;
10312
10313 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
10314 Vx_window_horizontal_drag_shape,
10315 doc:
10316
10317 );
10318 Vx_window_horizontal_drag_shape = Qnil;
10319
10320 DEFVAR_LISP ("x-window-vertical-drag-cursor",
10321 Vx_window_vertical_drag_shape,
10322 doc:
10323
10324 );
10325 Vx_window_vertical_drag_shape = Qnil;
10326
10327 DEFVAR_LISP ("x-window-left-edge-cursor",
10328 Vx_window_left_edge_shape,
10329 doc:
10330
10331 );
10332 Vx_window_left_edge_shape = Qnil;
10333
10334 DEFVAR_LISP ("x-window-top-left-corner-cursor",
10335 Vx_window_top_left_corner_shape,
10336 doc:
10337
10338 );
10339 Vx_window_top_left_corner_shape = Qnil;
10340
10341 DEFVAR_LISP ("x-window-top-edge-cursor",
10342 Vx_window_top_edge_shape,
10343 doc:
10344
10345 );
10346 Vx_window_top_edge_shape = Qnil;
10347
10348 DEFVAR_LISP ("x-window-top-right-corner-cursor",
10349 Vx_window_top_right_corner_shape,
10350 doc:
10351
10352 );
10353 Vx_window_top_right_corner_shape = Qnil;
10354
10355 DEFVAR_LISP ("x-window-right-edge-cursor",
10356 Vx_window_right_edge_shape,
10357 doc:
10358
10359 );
10360 Vx_window_right_edge_shape = Qnil;
10361
10362 DEFVAR_LISP ("x-window-bottom-right-corner-cursor",
10363 Vx_window_bottom_right_corner_shape,
10364 doc:
10365
10366 );
10367 Vx_window_bottom_right_corner_shape = Qnil;
10368
10369 DEFVAR_LISP ("x-window-bottom-edge-cursor",
10370 Vx_window_bottom_edge_shape,
10371 doc:
10372
10373 );
10374 Vx_window_bottom_edge_shape = Qnil;
10375
10376 DEFVAR_LISP ("x-window-bottom-left-corner-cursor",
10377 Vx_window_bottom_left_corner_shape,
10378 doc:
10379
10380 );
10381 Vx_window_bottom_left_corner_shape = Qnil;
10382
10383 DEFVAR_LISP ("x-cursor-fore-pixel", Vx_cursor_fore_pixel,
10384 doc: );
10385 Vx_cursor_fore_pixel = Qnil;
10386
10387 DEFVAR_LISP ("x-max-tooltip-size", Vx_max_tooltip_size,
10388 doc:
10389 );
10390 Vx_max_tooltip_size = Qnil;
10391
10392 DEFVAR_LISP ("x-no-window-manager", Vx_no_window_manager,
10393 doc:
10394
10395 );
10396
10397
10398 Vx_no_window_manager = Qnil;
10399
10400 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
10401 Vx_pixel_size_width_font_regexp,
10402 doc:
10403
10404
10405
10406
10407 );
10408 Vx_pixel_size_width_font_regexp = Qnil;
10409
10410
10411 DEFVAR_BOOL ("x-gtk-use-old-file-dialog", x_gtk_use_old_file_dialog,
10412 doc:
10413
10414
10415 );
10416 x_gtk_use_old_file_dialog = false;
10417
10418 DEFVAR_BOOL ("x-gtk-show-hidden-files", x_gtk_show_hidden_files,
10419 doc:
10420
10421 );
10422 x_gtk_show_hidden_files = false;
10423
10424 DEFVAR_BOOL ("x-gtk-file-dialog-help-text", x_gtk_file_dialog_help_text,
10425 doc:
10426
10427 );
10428 x_gtk_file_dialog_help_text = true;
10429
10430 DEFVAR_LISP ("x-gtk-resize-child-frames", x_gtk_resize_child_frames,
10431 doc:
10432
10433
10434
10435
10436
10437
10438
10439
10440
10441
10442
10443
10444
10445
10446
10447
10448
10449 );
10450 x_gtk_resize_child_frames = Qnil;
10451
10452
10453 Fprovide (Qx, Qnil);
10454
10455
10456 DEFSYM (Qrun_at_time, "run-at-time");
10457 DEFSYM (Qx_hide_tip, "x-hide-tip");
10458
10459
10460 DEFSYM (Qalways, "always");
10461 DEFSYM (Qwhen_mapped, "when-mapped");
10462 DEFSYM (Qnot_useful, "not-useful");
10463 DEFSYM (Qstatic_gray, "static-gray");
10464 DEFSYM (Qgray_scale, "gray-scale");
10465 DEFSYM (Qstatic_color, "static-color");
10466 DEFSYM (Qpseudo_color, "pseudo-color");
10467 DEFSYM (Qtrue_color, "true-color");
10468 DEFSYM (Qdirect_color, "direct-color");
10469 DEFSYM (Qgrayscale, "grayscale");
10470 DEFSYM (Qcolor, "color");
10471
10472 #ifdef HAVE_XINPUT2
10473 DEFSYM (Qxinput2, "xinput2");
10474
10475 Fprovide (Qxinput2, Qnil);
10476 #endif
10477
10478 #ifdef USE_X_TOOLKIT
10479 Fprovide (intern_c_string ("x-toolkit"), Qnil);
10480 #ifdef USE_MOTIF
10481 Fprovide (intern_c_string ("motif"), Qnil);
10482
10483 DEFVAR_LISP ("motif-version-string", Vmotif_version_string,
10484 doc: );
10485 Vmotif_version_string = build_string (XmVERSION_STRING);
10486 #endif
10487 #endif
10488
10489 #ifdef USE_GTK
10490
10491
10492
10493
10494 Fprovide (intern_c_string ("x-toolkit"), Qnil);
10495 Fprovide (intern_c_string ("gtk"), Qnil);
10496
10497 DEFVAR_LISP ("gtk-version-string", Vgtk_version_string,
10498 doc: );
10499 {
10500 char gtk_version[sizeof ".." + 3 * INT_STRLEN_BOUND (int)];
10501 int len = sprintf (gtk_version, "%d.%d.%d",
10502 GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION);
10503 Vgtk_version_string = make_pure_string (gtk_version, len, len, false);
10504 }
10505 #endif
10506
10507 #ifdef USE_CAIRO
10508 Fprovide (intern_c_string ("cairo"), Qnil);
10509
10510 DEFVAR_LISP ("cairo-version-string", Vcairo_version_string,
10511 doc: );
10512 {
10513 char cairo_version[sizeof ".." + 3 * INT_STRLEN_BOUND (int)];
10514 int len = sprintf (cairo_version, "%d.%d.%d",
10515 CAIRO_VERSION_MAJOR, CAIRO_VERSION_MINOR,
10516 CAIRO_VERSION_MICRO);
10517 Vcairo_version_string = make_pure_string (cairo_version, len, len, false);
10518 }
10519 #endif
10520
10521
10522 defsubr (&Sx_change_window_property);
10523 defsubr (&Sx_delete_window_property);
10524 defsubr (&Sx_window_property);
10525 defsubr (&Sx_window_property_attributes);
10526
10527 defsubr (&Sxw_display_color_p);
10528 defsubr (&Sx_display_grayscale_p);
10529 defsubr (&Sxw_color_defined_p);
10530 defsubr (&Sxw_color_values);
10531 defsubr (&Sx_server_max_request_size);
10532 defsubr (&Sx_server_vendor);
10533 defsubr (&Sx_server_version);
10534 defsubr (&Sx_server_input_extension_version);
10535 defsubr (&Sx_display_pixel_width);
10536 defsubr (&Sx_display_pixel_height);
10537 defsubr (&Sx_display_mm_width);
10538 defsubr (&Sx_display_mm_height);
10539 defsubr (&Sx_display_screens);
10540 defsubr (&Sx_display_planes);
10541 defsubr (&Sx_display_color_cells);
10542 defsubr (&Sx_display_visual_class);
10543 defsubr (&Sx_display_backing_store);
10544 defsubr (&Sx_display_save_under);
10545 defsubr (&Sx_display_monitor_attributes_list);
10546 defsubr (&Sx_frame_geometry);
10547 defsubr (&Sx_frame_edges);
10548 defsubr (&Sx_frame_list_z_order);
10549 defsubr (&Sx_frame_restack);
10550 defsubr (&Sx_mouse_absolute_pixel_position);
10551 defsubr (&Sx_set_mouse_absolute_pixel_position);
10552 defsubr (&Sx_wm_set_size_hint);
10553 defsubr (&Sx_create_frame);
10554 defsubr (&Sx_open_connection);
10555 defsubr (&Sx_close_connection);
10556 defsubr (&Sx_display_list);
10557 defsubr (&Sx_synchronize);
10558 defsubr (&Sx_backspace_delete_keys_p);
10559 defsubr (&Sx_show_tip);
10560 defsubr (&Sx_hide_tip);
10561 defsubr (&Sx_double_buffered_p);
10562 defsubr (&Sx_begin_drag);
10563 defsubr (&Sx_display_set_last_user_time);
10564 defsubr (&Sx_translate_coordinates);
10565 defsubr (&Sx_get_modifier_masks);
10566 #if 0
10567 defsubr (&Sx_test_string_conversion);
10568 #endif
10569
10570 tip_timer = Qnil;
10571 staticpro (&tip_timer);
10572 tip_frame = Qnil;
10573 staticpro (&tip_frame);
10574 tip_last_frame = Qnil;
10575 staticpro (&tip_last_frame);
10576 tip_last_string = Qnil;
10577 staticpro (&tip_last_string);
10578 tip_last_parms = Qnil;
10579 staticpro (&tip_last_parms);
10580 tip_dx = Qnil;
10581 staticpro (&tip_dx);
10582 tip_dy = Qnil;
10583 staticpro (&tip_dy);
10584
10585 defsubr (&Sx_uses_old_gtk_dialog);
10586 #if defined (USE_MOTIF) || defined (USE_GTK)
10587 defsubr (&Sx_file_dialog);
10588 #endif
10589
10590 #if defined (USE_GTK) && defined (HAVE_FREETYPE)
10591 defsubr (&Sx_select_font);
10592 #endif
10593
10594 defsubr (&Sx_internal_focus_input_context);
10595
10596 #ifdef USE_CAIRO
10597 defsubr (&Sx_export_frames);
10598 #ifdef USE_GTK
10599 defsubr (&Sx_page_setup_dialog);
10600 defsubr (&Sx_get_page_setup);
10601 defsubr (&Sx_print_frames_dialog);
10602 #endif
10603 #endif
10604 #ifdef USE_GTK
10605 #ifdef HAVE_GTK3
10606 #if GTK_CHECK_VERSION (3, 14, 0)
10607 defsubr (&Sx_gtk_debug);
10608 #endif
10609 #endif
10610 #endif
10611 }