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