This source file includes following definitions.
- x_defer_selection_requests
- x_release_selection_requests
- x_release_selection_requests_and_flush
- xm_side_effect_from_action
- xm_operations_from_actions
- xm_read_targets_table_header
- xm_read_targets_table_rec
- xm_find_targets_table_idx
- x_atoms_compare
- xm_write_targets_table
- xm_write_drag_initiator_info
- xm_drag_window_error_handler
- xm_drag_window_io_error_handler
- x_special_window_exists_p
- xm_get_drag_window_1
- xm_get_drag_window
- xm_setup_dnd_targets
- xm_get_drag_atom_1
- xm_get_drag_atom
- xm_setup_drag_info
- xm_send_drop_message
- xm_send_top_level_enter_message
- xm_send_drag_motion_message
- xm_send_top_level_leave_message
- xm_read_drop_start_reply
- xm_read_drop_start_message
- xm_read_drag_receiver_info
- xm_read_drag_motion_message
- xm_read_drag_motion_reply
- x_dnd_send_xm_leave_for_drop
- x_dnd_free_toplevels
- x_dnd_compute_toplevels
- x_dnd_io_error_handler
- x_dnd_get_proxy_proto
- x_dnd_get_target_window_2
- x_dnd_get_target_window_1
- x_dnd_get_wm_state_and_proto
- x_dnd_do_unsupported_drop
- x_dnd_send_unsupported_drop
- x_dnd_fill_empty_target
- x_dnd_get_target_window
- x_dnd_get_window_proxy
- x_dnd_get_window_proto
- x_dnd_send_enter
- x_dnd_send_position
- x_dnd_send_leave
- x_dnd_send_drop
- x_dnd_do_drop
- x_set_dnd_targets
- x_free_dnd_targets
- x_clear_dnd_variables
- x_free_dnd_toplevels
- x_restore_events_after_dnd
- x_dnd_cancel_dnd_early
- x_dnd_cleanup_drag_and_drop
- x_dnd_note_self_position
- x_dnd_note_self_wheel
- x_dnd_note_self_drop
- x_flush
- x_drop_xrender_surfaces
- x_xr_ensure_picture
- record_event
- x_toolkit_position
- x_update_opaque_region
- x_gc_free_ext_data_private
- x_gc_get_ext_data
- x_extension_initialize
- xi_frame_selected_for
- xi_convert_button_state
- xi_convert_event_state
- xi_convert_event_keyboard_state
- x_free_xi_devices
- xi_populate_scroll_valuator
- xi_populate_device_from_info
- x_cache_xi_devices
- x_get_scroll_valuator_delta
- xi_device_from_id
- xi_link_touch_point
- xi_unlink_touch_point
- xi_unlink_touch_points
- xi_find_touch_point
- xi_reset_scroll_valuators_for_device_id
- x_cr_destroy_frame_context
- x_cr_update_surface_desired_size
- x_cr_gc_clip
- x_begin_cr_clip
- x_end_cr_clip
- x_set_cr_source_with_gc_foreground
- x_set_cr_source_with_gc_background
- x_cr_destroy_xlib_surface
- x_try_cr_xlib_drawable
- x_end_cr_xlib_drawable
- x_cr_define_fringe_bitmap
- x_cr_destroy_fringe_bitmap
- x_cr_draw_image
- x_cr_draw_frame
- x_cr_accumulate_data
- x_cr_destroy
- x_cr_export_frames
- x_xr_apply_ext_clip
- x_xr_reset_ext_clip
- x_set_clip_rectangles
- x_reset_clip_rectangles
- x_xrender_color_from_gc_foreground
- x_xrender_color_from_gc_background
- x_fill_rectangle
- x_clear_rectangle
- x_draw_rectangle
- x_clear_window
- x_fill_trapezoid_for_relief
- x_erase_corners_for_relief
- x_draw_horizontal_wave
- x_display_info_for_display
- x_find_topmost_parent
- x_set_frame_alpha
- x_if_event
- x_sync_get_monotonic_time
- x_sync_current_monotonic_time
- x_sync_note_frame_times
- x_sync_is_frame_drawn_event
- x_sync_wait_for_frame_drawn_event
- x_sync_update_begin
- x_sync_trigger_fence
- x_sync_init_fences
- x_sync_free_fences
- x_sync_update_finish
- x_sync_handle_frame_drawn
- x_update_begin
- x_draw_vertical_window_border
- x_draw_window_divider
- show_back_buffer
- x_flip_and_flush
- x_update_end
- XTframe_up_to_date
- XTbuffer_flipping_unblocked_hook
- x_clear_under_internal_border
- x_after_update_window_line
- x_premultiply_pixel
- x_draw_fringe_bitmap
- x_display_set_last_user_time
- x_set_gtk_user_time
- x_create_special_window
- x_update_frame_user_time_window
- x_set_last_user_time_from_lisp
- x_set_cursor_gc
- x_set_mouse_face_gc
- x_set_mode_line_face_gc
- x_set_glyph_string_gc
- x_set_glyph_string_clipping
- x_set_glyph_string_clipping_exactly
- x_compute_glyph_string_overhangs
- x_clear_glyph_string_rect
- x_clear_point
- x_draw_glyph_string_background
- x_draw_glyph_string_foreground
- x_draw_composite_glyph_string_foreground
- x_draw_glyphless_glyph_string_foreground
- x_frame_of_widget
- x_alloc_lighter_color_for_widget
- cvt_string_to_pixel
- cvt_pixel_dtor
- x_color_cells
- x_query_colors
- x_query_frame_background_color
- x_hash_string_ignore_case
- x_parse_color
- x_alloc_nearest_color_1
- x_alloc_nearest_color
- x_copy_color
- x_alloc_lighter_color
- x_setup_relief_color
- x_setup_relief_colors
- x_fill_triangle
- x_make_point
- x_inside_rect_p
- x_draw_relief_rect
- x_draw_box_rect
- x_draw_glyph_string_box
- x_composite_image
- x_draw_image_foreground
- x_draw_image_relief
- x_draw_image_foreground_1
- x_draw_glyph_string_bg_rect
- x_draw_image_glyph_string
- x_draw_stretch_glyph_string
- x_get_scale_factor
- x_draw_underwave
- x_draw_glyph_string
- x_shift_glyphs_for_insert
- x_delete_glyphs
- x_clear_area1
- x_clear_area
- x_clear_frame
- x_send_hourglass_message
- x_show_hourglass
- x_hide_hourglass
- XTflash
- XTring_bell
- x_ins_del_lines
- x_scroll_run
- x_frame_highlight
- x_frame_unhighlight
- x_new_focus_frame
- x_fixes_pointer_blanking_supported
- xfixes_toggle_visible_pointer
- make_invisible_cursor
- x_toggle_visible_pointer
- XTtoggle_invisible_pointer
- x_focus_changed
- x_window_to_frame
- x_tooltip_window_to_frame
- x_any_window_to_frame
- x_menubar_window_to_frame
- x_top_window_to_frame
- x_top_window_to_frame
- x_next_event_from_any_display
- x_handle_pending_selection_requests_1
- x_handle_pending_selection_requests
- x_push_selection_request
- x_detect_pending_selection_requests
- x_clear_dnd_action
- x_dnd_delete_action_list
- x_dnd_lose_ownership
- x_dnd_process_quit
- x_dnd_begin_drag_and_drop
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625 #include <config.h>
626 #include <stdlib.h>
627 #include <math.h>
628 #include <signal.h>
629
630 #include "lisp.h"
631 #include "blockinput.h"
632 #include "sysstdio.h"
633
634
635
636 #include "xterm.h"
637 #include <X11/cursorfont.h>
638
639 #ifdef HAVE_X_I18N
640 #include "textconv.h"
641 #endif
642
643 #ifdef USE_XCB
644 #include <xcb/xproto.h>
645 #include <xcb/xcb.h>
646 #endif
647
648
649 #ifdef HAVE_XFIXES
650 #include <X11/extensions/Xfixes.h>
651 #endif
652
653 #ifdef HAVE_XDBE
654 #include <X11/extensions/Xdbe.h>
655 #endif
656
657 #ifdef HAVE_XINPUT2
658 #include <X11/extensions/XInput2.h>
659 #endif
660
661 #ifdef HAVE_XRANDR
662 #include <X11/extensions/Xrandr.h>
663 #endif
664
665 #ifdef HAVE_XSYNC
666 #include <X11/extensions/sync.h>
667 #endif
668
669 #ifdef HAVE_XINERAMA
670 #include <X11/extensions/Xinerama.h>
671 #endif
672
673 #ifdef HAVE_XCOMPOSITE
674 #include <X11/extensions/Xcomposite.h>
675 #endif
676
677 #ifdef HAVE_XSHAPE
678 #include <X11/extensions/shape.h>
679 #endif
680
681 #ifdef HAVE_XCB_SHAPE
682 #include <xcb/shape.h>
683 #endif
684
685
686
687 #ifndef makedev
688 #include <sys/types.h>
689 #endif
690
691 #include <sys/ioctl.h>
692
693 #include "systime.h"
694
695 #include <fcntl.h>
696 #include <errno.h>
697 #include <sys/stat.h>
698 #include <flexmember.h>
699 #include <c-ctype.h>
700 #include <byteswap.h>
701
702 #include "character.h"
703 #include "coding.h"
704 #include "composite.h"
705 #include "frame.h"
706 #include "dispextern.h"
707 #include "xwidget.h"
708 #include "fontset.h"
709 #include "termhooks.h"
710 #include "termopts.h"
711 #include "termchar.h"
712 #include "emacs-icon.h"
713 #include "buffer.h"
714 #include "window.h"
715 #include "keyboard.h"
716 #include "atimer.h"
717 #include "font.h"
718 #include "xsettings.h"
719 #include "sysselect.h"
720 #include "menu.h"
721 #include "pdumper.h"
722
723 #ifdef USE_X_TOOLKIT
724 #include <X11/Shell.h>
725 #include <X11/ShellP.h>
726 #endif
727
728 #include <unistd.h>
729
730 #ifdef USE_GTK
731 #include "gtkutil.h"
732 #ifdef HAVE_GTK3
733 #include <X11/Xproto.h>
734 #endif
735 #endif
736
737 #if defined (USE_LUCID) || defined (USE_MOTIF)
738 #include "../lwlib/xlwmenu.h"
739 #endif
740
741 #ifdef HAVE_XWIDGETS
742 #include <cairo-xlib.h>
743 #endif
744
745 #ifdef USE_MOTIF
746 #include <Xm/Xm.h>
747 #include <Xm/CascadeB.h>
748 #endif
749
750 #ifdef USE_X_TOOLKIT
751
752
753 #ifdef USE_TOOLKIT_SCROLL_BARS
754 #if defined USE_MOTIF
755 #include <Xm/ScrollBar.h>
756 #else
757
758 #ifdef HAVE_XAW3D
759 #include <X11/Xaw3d/Simple.h>
760 #include <X11/Xaw3d/Scrollbar.h>
761 #include <X11/Xaw3d/ThreeD.h>
762 #else
763 #include <X11/Xaw/Simple.h>
764 #include <X11/Xaw/Scrollbar.h>
765 #endif
766 #ifndef XtNpickTop
767 #define XtNpickTop "pickTop"
768 #endif
769 #endif
770 #endif
771
772 #endif
773
774 #ifdef USE_X_TOOLKIT
775 #include "widget.h"
776 #ifndef XtNinitialState
777 #define XtNinitialState "initialState"
778 #endif
779 #endif
780
781 #ifdef USE_GTK
782 #include <xgselect.h>
783 #endif
784
785 #include "bitmaps/gray.xbm"
786
787 #ifdef HAVE_XKB
788 #include <X11/XKBlib.h>
789 #endif
790
791
792
793
794 typedef int (*Emacs_XErrorHandler) (Display *, XErrorEvent *);
795 typedef int (*Emacs_XIOErrorHandler) (Display *);
796
797 #if defined USE_XCB && defined USE_CAIRO_XCB
798 #define USE_CAIRO_XCB_SURFACE
799 #endif
800
801 #if XCB_SHAPE_MAJOR_VERSION > 1 \
802 || (XCB_SHAPE_MAJOR_VERSION == 1 && \
803 XCB_SHAPE_MINOR_VERSION >= 1)
804 #define HAVE_XCB_SHAPE_INPUT_RECTS
805 #endif
806
807 #ifdef USE_GTK
808
809
810
811
812
813
814
815 struct input_event xg_pending_quit_event = { .kind = NO_EVENT };
816 #endif
817
818
819
820
821 static bool any_help_event_p;
822
823
824
825
826 struct x_display_info *x_display_list;
827
828 #ifdef USE_X_TOOLKIT
829
830
831 XtAppContext Xt_app_con;
832 static String Xt_default_resources[] = {0};
833
834
835 static bool toolkit_scroll_bar_interaction;
836
837 #endif
838
839
840
841
842
843 static Time ignore_next_mouse_click_timeout;
844
845
846
847 static struct x_display_info *mouse_click_timeout_display;
848
849
850
851 static int x_noop_count;
852
853 #ifdef USE_GTK
854
855 static Lisp_Object xg_default_icon_file;
856 #endif
857
858 #ifdef HAVE_X_I18N
859
860 static char emacs_class[] = EMACS_CLASS;
861 #endif
862
863 #ifdef USE_GTK
864 static int current_count;
865 static int current_finish;
866 static struct input_event *current_hold_quit;
867 #endif
868
869 #ifdef HAVE_XINPUT2
870 #ifndef X_XIGrabDevice
871 #define X_XIGrabDevice 51
872 #endif
873
874 #ifndef X_XIUngrabDevice
875 #define X_XIUngrabDevice 52
876 #endif
877
878 #ifndef X_XIAllowEvents
879 #define X_XIAllowEvents 53
880 #endif
881 #endif
882
883
884
885 static int x_use_pending_selection_requests;
886
887
888 #define X_NEXT_KBD_EVENT(ptr) \
889 ((ptr) == kbd_buffer + KBD_BUFFER_SIZE - 1 ? kbd_buffer : (ptr) + 1)
890
891 static void x_push_selection_request (struct selection_input_event *);
892
893
894
895
896
897
898
899 void
900 x_defer_selection_requests (void)
901 {
902 union buffered_input_event *event;
903 bool between;
904
905 between = false;
906
907 block_input ();
908 if (!x_use_pending_selection_requests)
909 {
910 event = kbd_fetch_ptr;
911
912 while (event != kbd_store_ptr)
913 {
914 if (event->ie.kind == SELECTION_REQUEST_EVENT
915 || event->ie.kind == SELECTION_CLEAR_EVENT)
916 {
917 x_push_selection_request (&event->sie);
918
919
920 SELECTION_EVENT_DPYINFO (&event->sie) = NULL;
921
922
923
924
925
926 if (!between)
927 {
928 kbd_fetch_ptr = X_NEXT_KBD_EVENT (event);
929
930
931
932 input_pending = false;
933 }
934 }
935 else
936 between = true;
937
938 event = X_NEXT_KBD_EVENT (event);
939 }
940 }
941
942 x_use_pending_selection_requests++;
943 unblock_input ();
944 }
945
946 static void
947 x_release_selection_requests (void)
948 {
949 x_use_pending_selection_requests--;
950 }
951
952 void
953 x_release_selection_requests_and_flush (void)
954 {
955 x_release_selection_requests ();
956
957 if (!x_use_pending_selection_requests)
958 x_handle_pending_selection_requests ();
959 }
960
961 struct x_selection_request_event
962 {
963
964 struct selection_input_event se;
965
966
967 struct x_selection_request_event *next;
968 };
969
970
971
972
973
974 struct x_selection_request_event *pending_selection_requests;
975
976 struct x_atom_ref
977 {
978
979 const char *name;
980
981
982 int offset;
983 };
984
985
986
987 static const struct x_atom_ref x_atom_refs[] =
988 {
989 #define ATOM_REFS_INIT(string, member) \
990 { string, offsetof (struct x_display_info, member) },
991 ATOM_REFS_INIT ("WM_PROTOCOLS", Xatom_wm_protocols)
992 ATOM_REFS_INIT ("WM_TAKE_FOCUS", Xatom_wm_take_focus)
993 ATOM_REFS_INIT ("WM_SAVE_YOURSELF", Xatom_wm_save_yourself)
994 ATOM_REFS_INIT ("WM_DELETE_WINDOW", Xatom_wm_delete_window)
995 ATOM_REFS_INIT ("WM_CHANGE_STATE", Xatom_wm_change_state)
996 ATOM_REFS_INIT ("WM_STATE", Xatom_wm_state)
997 ATOM_REFS_INIT ("WM_CONFIGURE_DENIED", Xatom_wm_configure_denied)
998 ATOM_REFS_INIT ("WM_MOVED", Xatom_wm_window_moved)
999 ATOM_REFS_INIT ("WM_CLIENT_LEADER", Xatom_wm_client_leader)
1000 ATOM_REFS_INIT ("WM_TRANSIENT_FOR", Xatom_wm_transient_for)
1001 ATOM_REFS_INIT ("Editres", Xatom_editres)
1002 ATOM_REFS_INIT ("CLIPBOARD", Xatom_CLIPBOARD)
1003 ATOM_REFS_INIT ("TIMESTAMP", Xatom_TIMESTAMP)
1004 ATOM_REFS_INIT ("TEXT", Xatom_TEXT)
1005 ATOM_REFS_INIT ("COMPOUND_TEXT", Xatom_COMPOUND_TEXT)
1006 ATOM_REFS_INIT ("UTF8_STRING", Xatom_UTF8_STRING)
1007 ATOM_REFS_INIT ("DELETE", Xatom_DELETE)
1008 ATOM_REFS_INIT ("MULTIPLE", Xatom_MULTIPLE)
1009 ATOM_REFS_INIT ("INCR", Xatom_INCR)
1010 ATOM_REFS_INIT ("_EMACS_TMP_", Xatom_EMACS_TMP)
1011 ATOM_REFS_INIT ("_EMACS_SERVER_TIME_PROP", Xatom_EMACS_SERVER_TIME_PROP)
1012 ATOM_REFS_INIT ("TARGETS", Xatom_TARGETS)
1013 ATOM_REFS_INIT ("NULL", Xatom_NULL)
1014 ATOM_REFS_INIT ("ATOM", Xatom_ATOM)
1015 ATOM_REFS_INIT ("ATOM_PAIR", Xatom_ATOM_PAIR)
1016 ATOM_REFS_INIT ("CLIPBOARD_MANAGER", Xatom_CLIPBOARD_MANAGER)
1017 ATOM_REFS_INIT ("_XEMBED_INFO", Xatom_XEMBED_INFO)
1018 ATOM_REFS_INIT ("_MOTIF_WM_HINTS", Xatom_MOTIF_WM_HINTS)
1019 ATOM_REFS_INIT ("_EMACS_DRAG_ATOM", Xatom_EMACS_DRAG_ATOM)
1020
1021 ATOM_REFS_INIT ("PIXEL_SIZE", Xatom_PIXEL_SIZE)
1022 ATOM_REFS_INIT ("AVERAGE_WIDTH", Xatom_AVERAGE_WIDTH)
1023 ATOM_REFS_INIT ("_MULE_BASELINE_OFFSET", Xatom_MULE_BASELINE_OFFSET)
1024 ATOM_REFS_INIT ("_MULE_RELATIVE_COMPOSE", Xatom_MULE_RELATIVE_COMPOSE)
1025 ATOM_REFS_INIT ("_MULE_DEFAULT_ASCENT", Xatom_MULE_DEFAULT_ASCENT)
1026
1027 ATOM_REFS_INIT ("DONE", Xatom_DONE)
1028 ATOM_REFS_INIT ("PAGE", Xatom_PAGE)
1029 ATOM_REFS_INIT ("_EMACS_SCROLLBAR", Xatom_Scrollbar)
1030 ATOM_REFS_INIT ("_EMACS_HORIZONTAL_SCROLLBAR", Xatom_Horizontal_Scrollbar)
1031 ATOM_REFS_INIT ("_XEMBED", Xatom_XEMBED)
1032
1033 ATOM_REFS_INIT ("_NET_WM_STATE", Xatom_net_wm_state)
1034 ATOM_REFS_INIT ("_NET_WM_STATE_FULLSCREEN", Xatom_net_wm_state_fullscreen)
1035 ATOM_REFS_INIT ("_NET_WM_STATE_MAXIMIZED_HORZ",
1036 Xatom_net_wm_state_maximized_horz)
1037 ATOM_REFS_INIT ("_NET_WM_STATE_MAXIMIZED_VERT",
1038 Xatom_net_wm_state_maximized_vert)
1039 ATOM_REFS_INIT ("_NET_WM_STATE_STICKY", Xatom_net_wm_state_sticky)
1040 ATOM_REFS_INIT ("_NET_WM_STATE_SHADED", Xatom_net_wm_state_shaded)
1041 ATOM_REFS_INIT ("_NET_WM_STATE_HIDDEN", Xatom_net_wm_state_hidden)
1042 ATOM_REFS_INIT ("_NET_WM_WINDOW_TYPE", Xatom_net_window_type)
1043 ATOM_REFS_INIT ("_NET_WM_WINDOW_TYPE_TOOLTIP",
1044 Xatom_net_window_type_tooltip)
1045 ATOM_REFS_INIT ("_NET_WM_ICON_NAME", Xatom_net_wm_icon_name)
1046 ATOM_REFS_INIT ("_NET_WM_NAME", Xatom_net_wm_name)
1047 ATOM_REFS_INIT ("_NET_SUPPORTED", Xatom_net_supported)
1048 ATOM_REFS_INIT ("_NET_SUPPORTING_WM_CHECK", Xatom_net_supporting_wm_check)
1049 ATOM_REFS_INIT ("_NET_WM_WINDOW_OPACITY", Xatom_net_wm_window_opacity)
1050 ATOM_REFS_INIT ("_NET_ACTIVE_WINDOW", Xatom_net_active_window)
1051 ATOM_REFS_INIT ("_NET_FRAME_EXTENTS", Xatom_net_frame_extents)
1052 ATOM_REFS_INIT ("_NET_CURRENT_DESKTOP", Xatom_net_current_desktop)
1053 ATOM_REFS_INIT ("_NET_WORKAREA", Xatom_net_workarea)
1054 ATOM_REFS_INIT ("_NET_WM_SYNC_REQUEST", Xatom_net_wm_sync_request)
1055 ATOM_REFS_INIT ("_NET_WM_SYNC_REQUEST_COUNTER", Xatom_net_wm_sync_request_counter)
1056 ATOM_REFS_INIT ("_NET_WM_SYNC_FENCES", Xatom_net_wm_sync_fences)
1057 ATOM_REFS_INIT ("_NET_WM_BYPASS_COMPOSITOR", Xatom_net_wm_bypass_compositor)
1058 ATOM_REFS_INIT ("_NET_WM_FRAME_DRAWN", Xatom_net_wm_frame_drawn)
1059 ATOM_REFS_INIT ("_NET_WM_FRAME_TIMINGS", Xatom_net_wm_frame_timings)
1060 ATOM_REFS_INIT ("_NET_WM_USER_TIME", Xatom_net_wm_user_time)
1061 ATOM_REFS_INIT ("_NET_WM_USER_TIME_WINDOW", Xatom_net_wm_user_time_window)
1062 ATOM_REFS_INIT ("_NET_CLIENT_LIST_STACKING", Xatom_net_client_list_stacking)
1063
1064 ATOM_REFS_INIT ("SM_CLIENT_ID", Xatom_SM_CLIENT_ID)
1065 ATOM_REFS_INIT ("_XSETTINGS_SETTINGS", Xatom_xsettings_prop)
1066 ATOM_REFS_INIT ("MANAGER", Xatom_xsettings_mgr)
1067 ATOM_REFS_INIT ("_NET_WM_STATE_SKIP_TASKBAR", Xatom_net_wm_state_skip_taskbar)
1068 ATOM_REFS_INIT ("_NET_WM_STATE_ABOVE", Xatom_net_wm_state_above)
1069 ATOM_REFS_INIT ("_NET_WM_STATE_BELOW", Xatom_net_wm_state_below)
1070 ATOM_REFS_INIT ("_NET_WM_OPAQUE_REGION", Xatom_net_wm_opaque_region)
1071 ATOM_REFS_INIT ("_NET_WM_PING", Xatom_net_wm_ping)
1072 ATOM_REFS_INIT ("_NET_WM_PID", Xatom_net_wm_pid)
1073 #ifdef HAVE_XKB
1074 ATOM_REFS_INIT ("Meta", Xatom_Meta)
1075 ATOM_REFS_INIT ("Super", Xatom_Super)
1076 ATOM_REFS_INIT ("Hyper", Xatom_Hyper)
1077 ATOM_REFS_INIT ("ShiftLock", Xatom_ShiftLock)
1078 ATOM_REFS_INIT ("Alt", Xatom_Alt)
1079 #endif
1080
1081 ATOM_REFS_INIT ("XdndAware", Xatom_XdndAware)
1082 ATOM_REFS_INIT ("XdndSelection", Xatom_XdndSelection)
1083 ATOM_REFS_INIT ("XdndTypeList", Xatom_XdndTypeList)
1084 ATOM_REFS_INIT ("XdndActionCopy", Xatom_XdndActionCopy)
1085 ATOM_REFS_INIT ("XdndActionMove", Xatom_XdndActionMove)
1086 ATOM_REFS_INIT ("XdndActionLink", Xatom_XdndActionLink)
1087 ATOM_REFS_INIT ("XdndActionAsk", Xatom_XdndActionAsk)
1088 ATOM_REFS_INIT ("XdndActionPrivate", Xatom_XdndActionPrivate)
1089 ATOM_REFS_INIT ("XdndActionList", Xatom_XdndActionList)
1090 ATOM_REFS_INIT ("XdndActionDescription", Xatom_XdndActionDescription)
1091 ATOM_REFS_INIT ("XdndProxy", Xatom_XdndProxy)
1092 ATOM_REFS_INIT ("XdndEnter", Xatom_XdndEnter)
1093 ATOM_REFS_INIT ("XdndPosition", Xatom_XdndPosition)
1094 ATOM_REFS_INIT ("XdndStatus", Xatom_XdndStatus)
1095 ATOM_REFS_INIT ("XdndLeave", Xatom_XdndLeave)
1096 ATOM_REFS_INIT ("XdndDrop", Xatom_XdndDrop)
1097 ATOM_REFS_INIT ("XdndFinished", Xatom_XdndFinished)
1098
1099 ATOM_REFS_INIT ("XdndDirectSave0", Xatom_XdndDirectSave0)
1100 ATOM_REFS_INIT ("XdndActionDirectSave", Xatom_XdndActionDirectSave)
1101 ATOM_REFS_INIT ("text/plain", Xatom_text_plain)
1102
1103 ATOM_REFS_INIT ("_MOTIF_DRAG_WINDOW", Xatom_MOTIF_DRAG_WINDOW)
1104 ATOM_REFS_INIT ("_MOTIF_DRAG_TARGETS", Xatom_MOTIF_DRAG_TARGETS)
1105 ATOM_REFS_INIT ("_MOTIF_DRAG_AND_DROP_MESSAGE",
1106 Xatom_MOTIF_DRAG_AND_DROP_MESSAGE)
1107 ATOM_REFS_INIT ("_MOTIF_DRAG_INITIATOR_INFO",
1108 Xatom_MOTIF_DRAG_INITIATOR_INFO)
1109 ATOM_REFS_INIT ("_MOTIF_DRAG_RECEIVER_INFO",
1110 Xatom_MOTIF_DRAG_RECEIVER_INFO)
1111 ATOM_REFS_INIT ("XmTRANSFER_SUCCESS", Xatom_XmTRANSFER_SUCCESS)
1112 ATOM_REFS_INIT ("XmTRANSFER_FAILURE", Xatom_XmTRANSFER_FAILURE)
1113
1114 ATOM_REFS_INIT ("DndProtocol", Xatom_DndProtocol)
1115 ATOM_REFS_INIT ("_DND_PROTOCOL", Xatom_DND_PROTOCOL)
1116
1117
1118 ATOM_REFS_INIT ("text/plain;charset=utf-8", Xatom_text_plain_charset_utf_8)
1119 ATOM_REFS_INIT ("LENGTH", Xatom_LENGTH)
1120 ATOM_REFS_INIT ("FILE_NAME", Xatom_FILE_NAME)
1121 ATOM_REFS_INIT ("CHARACTER_POSITION", Xatom_CHARACTER_POSITION)
1122 ATOM_REFS_INIT ("LINE_NUMBER", Xatom_LINE_NUMBER)
1123 ATOM_REFS_INIT ("COLUMN_NUMBER", Xatom_COLUMN_NUMBER)
1124 ATOM_REFS_INIT ("OWNER_OS", Xatom_OWNER_OS)
1125 ATOM_REFS_INIT ("HOST_NAME", Xatom_HOST_NAME)
1126 ATOM_REFS_INIT ("USER", Xatom_USER)
1127 ATOM_REFS_INIT ("CLASS", Xatom_CLASS)
1128 ATOM_REFS_INIT ("NAME", Xatom_NAME)
1129 ATOM_REFS_INIT ("SAVE_TARGETS", Xatom_SAVE_TARGETS)
1130 };
1131
1132 enum
1133 {
1134 X_EVENT_NORMAL,
1135 X_EVENT_GOTO_OUT,
1136 X_EVENT_DROP
1137 };
1138
1139 enum xembed_info
1140 {
1141 XEMBED_MAPPED = 1 << 0
1142 };
1143
1144 enum xembed_message
1145 {
1146 XEMBED_EMBEDDED_NOTIFY = 0,
1147 XEMBED_WINDOW_ACTIVATE = 1,
1148 XEMBED_WINDOW_DEACTIVATE = 2,
1149 XEMBED_REQUEST_FOCUS = 3,
1150 XEMBED_FOCUS_IN = 4,
1151 XEMBED_FOCUS_OUT = 5,
1152 XEMBED_FOCUS_NEXT = 6,
1153 XEMBED_FOCUS_PREV = 7,
1154
1155 XEMBED_MODALITY_ON = 10,
1156 XEMBED_MODALITY_OFF = 11,
1157 XEMBED_REGISTER_ACCELERATOR = 12,
1158 XEMBED_UNREGISTER_ACCELERATOR = 13,
1159 XEMBED_ACTIVATE_ACCELERATOR = 14
1160 };
1161
1162 static bool x_alloc_nearest_color_1 (Display *, Colormap, XColor *);
1163 static void x_raise_frame (struct frame *);
1164 static void x_lower_frame (struct frame *);
1165 static int x_io_error_quitter (Display *);
1166 static struct terminal *x_create_terminal (struct x_display_info *);
1167 static void x_frame_rehighlight (struct x_display_info *);
1168
1169 static void x_clip_to_row (struct window *, struct glyph_row *,
1170 enum glyph_row_area, GC);
1171 static struct scroll_bar *x_window_to_scroll_bar (Display *, Window, int);
1172 static struct frame *x_window_to_frame (struct x_display_info *, int);
1173 static void x_scroll_bar_report_motion (struct frame **, Lisp_Object *,
1174 enum scroll_bar_part *,
1175 Lisp_Object *, Lisp_Object *,
1176 Time *);
1177 static void x_horizontal_scroll_bar_report_motion (struct frame **, Lisp_Object *,
1178 enum scroll_bar_part *,
1179 Lisp_Object *, Lisp_Object *,
1180 Time *);
1181 static bool x_handle_net_wm_state (struct frame *, const XPropertyEvent *);
1182 static void x_check_fullscreen (struct frame *);
1183 static void x_check_expected_move (struct frame *, int, int);
1184 static void x_sync_with_move (struct frame *, int, int, bool);
1185 #ifndef HAVE_XINPUT2
1186 static int handle_one_xevent (struct x_display_info *,
1187 const XEvent *, int *,
1188 struct input_event *);
1189 #else
1190 static int handle_one_xevent (struct x_display_info *,
1191 XEvent *, int *,
1192 struct input_event *);
1193 #endif
1194 #if ! (defined USE_X_TOOLKIT || defined USE_MOTIF) && defined USE_GTK
1195 static int x_dispatch_event (XEvent *, Display *);
1196 #endif
1197 static void x_wm_set_window_state (struct frame *, int);
1198 static void x_wm_set_icon_pixmap (struct frame *, ptrdiff_t);
1199 static void x_initialize (void);
1200
1201 static bool x_get_current_wm_state (struct frame *, Window, int *, bool *, bool *);
1202 static void x_update_opaque_region (struct frame *, XEvent *);
1203
1204 #ifdef HAVE_X_I18N
1205 static int x_filter_event (struct x_display_info *, XEvent *);
1206 #endif
1207 static void x_clean_failable_requests (struct x_display_info *);
1208
1209 static struct frame *x_tooltip_window_to_frame (struct x_display_info *,
1210 Window, bool *);
1211 static Window x_get_window_below (Display *, Window, int, int, int *, int *);
1212 static void x_set_input_focus (struct x_display_info *, Window, Time);
1213
1214 #ifndef USE_TOOLKIT_SCROLL_BARS
1215 static void x_scroll_bar_redraw (struct scroll_bar *);
1216 #endif
1217
1218
1219
1220
1221
1222
1223 bool x_dnd_in_progress;
1224
1225
1226 struct frame *x_dnd_frame;
1227
1228
1229
1230
1231 struct frame *x_dnd_finish_frame;
1232
1233
1234
1235
1236
1237 bool x_dnd_waiting_for_finish;
1238
1239
1240
1241
1242 static bool x_dnd_run_unsupported_drop_function;
1243
1244
1245 static Time x_dnd_unsupported_drop_time;
1246
1247
1248 static Window x_dnd_unsupported_drop_window;
1249
1250
1251 static Lisp_Object x_dnd_unsupported_drop_data;
1252
1253
1254
1255 static bool x_dnd_update_tooltip;
1256
1257
1258 static Lisp_Object x_dnd_monitors;
1259
1260
1261
1262 static Display *x_dnd_finish_display;
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273 static int x_dnd_waiting_for_motif_finish;
1274
1275
1276
1277 struct x_display_info *x_dnd_waiting_for_motif_finish_display;
1278
1279
1280
1281
1282
1283 static bool x_dnd_xm_use_help;
1284
1285
1286 static bool x_dnd_motif_setup_p;
1287
1288
1289 static Atom x_dnd_motif_atom;
1290
1291
1292
1293 static Window x_dnd_pending_finish_target;
1294
1295
1296 static int x_dnd_waiting_for_finish_proto;
1297
1298
1299
1300 static bool x_dnd_allow_current_frame;
1301
1302
1303
1304 static bool x_dnd_init_type_lists;
1305
1306
1307
1308
1309
1310
1311 static int x_dnd_return_frame;
1312
1313
1314
1315 static struct frame *x_dnd_return_frame_object;
1316
1317
1318
1319
1320 static Window x_dnd_last_seen_window;
1321
1322
1323 static Window x_dnd_last_seen_toplevel;
1324
1325
1326
1327 static Window x_dnd_end_window;
1328
1329
1330
1331 static int x_dnd_last_protocol_version;
1332
1333
1334
1335 static bool x_dnd_last_window_is_frame;
1336
1337
1338
1339
1340
1341
1342
1343 static int x_dnd_last_motif_style;
1344
1345
1346
1347 static Time x_dnd_selection_timestamp;
1348
1349
1350 static Window x_dnd_mouse_rect_target;
1351
1352
1353
1354 static XRectangle x_dnd_mouse_rect;
1355
1356
1357
1358 static Window x_dnd_waiting_for_status_window;
1359
1360
1361
1362 static XEvent x_dnd_pending_send_position;
1363
1364
1365 static bool x_dnd_pending_send_position_button;
1366
1367
1368 static int x_dnd_pending_send_position_root_x;
1369
1370
1371 static int x_dnd_pending_send_position_root_y;
1372
1373
1374
1375 static bool x_dnd_need_send_drop;
1376
1377
1378 static int x_dnd_send_drop_proto;
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390 static Atom x_dnd_action;
1391
1392
1393
1394 static Lisp_Object x_dnd_action_symbol;
1395
1396
1397
1398
1399 static Atom x_dnd_wanted_action;
1400
1401
1402
1403 static uint8_t x_dnd_motif_operations;
1404
1405
1406
1407 static uint8_t x_dnd_first_motif_operation;
1408
1409
1410 static Atom *x_dnd_targets;
1411
1412
1413 static int x_dnd_n_targets;
1414
1415
1416
1417
1418
1419 static XWindowAttributes x_dnd_old_window_attrs;
1420
1421
1422
1423 static bool x_dnd_unwind_flag;
1424
1425
1426 static struct frame *x_dnd_movement_frame;
1427
1428
1429
1430 static int x_dnd_movement_x, x_dnd_movement_y;
1431
1432
1433 static struct frame *x_dnd_wheel_frame;
1434
1435
1436 static int x_dnd_wheel_x, x_dnd_wheel_y;
1437
1438
1439 static int x_dnd_wheel_button;
1440
1441
1442 static int x_dnd_wheel_state;
1443
1444
1445 static Time x_dnd_wheel_time;
1446
1447 #ifdef HAVE_XKB
1448
1449 static unsigned int x_dnd_keyboard_state;
1450 #endif
1451
1452
1453
1454 static sigjmp_buf x_dnd_disconnect_handler;
1455
1456
1457
1458 static bool x_dnd_inside_handle_one_xevent;
1459
1460
1461
1462 static int x_dnd_recursion_depth;
1463
1464
1465
1466
1467 static Lisp_Object x_dnd_selection_alias_cell;
1468
1469
1470 static int x_dnd_last_tooltip_x, x_dnd_last_tooltip_y;
1471
1472
1473 static bool x_dnd_last_tooltip_valid;
1474
1475 #ifdef HAVE_XINPUT2
1476
1477
1478 static int x_dnd_pointer_device;
1479
1480
1481 static int x_dnd_keyboard_device;
1482 #endif
1483
1484
1485
1486 struct x_client_list_window
1487 {
1488
1489 Window window;
1490
1491
1492 Display *dpy;
1493
1494
1495 int x, y;
1496
1497
1498 int width, height;
1499
1500
1501
1502
1503 long previous_event_mask;
1504
1505
1506 unsigned long wm_state;
1507
1508
1509 struct x_client_list_window *next;
1510
1511
1512 int frame_extents_left;
1513 int frame_extents_right;
1514 int frame_extents_top;
1515 int frame_extents_bottom;
1516
1517 #ifdef HAVE_XSHAPE
1518
1519 int border_width;
1520
1521
1522 int n_input_rects;
1523
1524
1525 XRectangle *input_rects;
1526
1527
1528 XRectangle *bounding_rects;
1529
1530
1531 int n_bounding_rects;
1532 #endif
1533
1534
1535 uint8_t xm_protocol_style;
1536
1537
1538 bool mapped_p;
1539 };
1540
1541
1542 static struct x_client_list_window *x_dnd_toplevels;
1543
1544
1545
1546 static bool x_dnd_use_toplevels;
1547
1548
1549
1550
1551
1552
1553
1554 static volatile bool *xm_drag_window_error;
1555
1556 typedef enum xm_byte_order
1557 {
1558 XM_BYTE_ORDER_LSB_FIRST = 'l',
1559 XM_BYTE_ORDER_MSB_FIRST = 'B',
1560 #ifndef WORDS_BIGENDIAN
1561 XM_BYTE_ORDER_CUR_FIRST = 'l',
1562 #else
1563 XM_BYTE_ORDER_CUR_FIRST = 'B',
1564 #endif
1565 } xm_byte_order;
1566
1567 #ifdef ENABLE_CHECKING
1568
1569 #define SWAPCARD32(l) \
1570 { \
1571 struct { unsigned t : 32; } bit32; \
1572 char n, *tp = (char *) &bit32; \
1573 bit32.t = l; \
1574 n = tp[0]; tp[0] = tp[3]; tp[3] = n; \
1575 n = tp[1]; tp[1] = tp[2]; tp[2] = n; \
1576 l = bit32.t; \
1577 }
1578
1579 #define SWAPCARD16(s) \
1580 { \
1581 struct { unsigned t : 16; } bit16; \
1582 char n, *tp = (char *) &bit16; \
1583 bit16.t = s; \
1584 n = tp[0]; tp[0] = tp[1]; tp[1] = n; \
1585 s = bit16.t; \
1586 }
1587
1588 #else
1589 #define SWAPCARD32(l) ((l) = bswap_32 (l))
1590 #define SWAPCARD16(l) ((l) = bswap_16 (l))
1591 #endif
1592
1593 typedef struct xm_targets_table_header
1594 {
1595 uint8_t byte_order;
1596 uint8_t protocol;
1597
1598 uint16_t target_list_count;
1599 uint32_t total_data_size;
1600 } xm_targets_table_header;
1601
1602 typedef struct xm_targets_table_rec
1603 {
1604 uint16_t n_targets;
1605 uint32_t targets[FLEXIBLE_ARRAY_MEMBER];
1606 } xm_targets_table_rec;
1607
1608 typedef struct xm_drop_start_message
1609 {
1610 uint8_t reason;
1611 uint8_t byte_order;
1612
1613 uint16_t side_effects;
1614 uint32_t timestamp;
1615 uint16_t x, y;
1616 uint32_t index_atom;
1617 uint32_t source_window;
1618 } xm_drop_start_message;
1619
1620 typedef struct xm_drop_start_reply
1621 {
1622 uint8_t reason;
1623 uint8_t byte_order;
1624
1625 uint16_t side_effects;
1626 uint16_t better_x;
1627 uint16_t better_y;
1628 } xm_drop_start_reply;
1629
1630 typedef struct xm_drag_initiator_info
1631 {
1632 uint8_t byteorder;
1633 uint8_t protocol;
1634
1635 uint16_t table_index;
1636 uint32_t selection;
1637 } xm_drag_initiator_info;
1638
1639 typedef struct xm_drag_receiver_info
1640 {
1641 uint8_t byteorder;
1642 uint8_t protocol;
1643
1644 uint8_t protocol_style;
1645 uint8_t unspecified0;
1646 uint32_t unspecified1;
1647 uint32_t unspecified2;
1648 uint32_t unspecified3;
1649 } xm_drag_receiver_info;
1650
1651 typedef struct xm_top_level_enter_message
1652 {
1653 uint8_t reason;
1654 uint8_t byteorder;
1655
1656 uint16_t zero;
1657 uint32_t timestamp;
1658 uint32_t source_window;
1659 uint32_t index_atom;
1660 } xm_top_level_enter_message;
1661
1662 typedef struct xm_drag_motion_message
1663 {
1664 uint8_t reason;
1665 uint8_t byteorder;
1666
1667 uint16_t side_effects;
1668 uint32_t timestamp;
1669 uint16_t x, y;
1670 } xm_drag_motion_message;
1671
1672 typedef struct xm_drag_motion_reply
1673 {
1674 uint8_t reason;
1675 uint8_t byte_order;
1676
1677 uint16_t side_effects;
1678 uint32_t timestamp;
1679 uint16_t better_x;
1680 uint16_t better_y;
1681 } xm_drag_motion_reply;
1682
1683 typedef struct xm_top_level_leave_message
1684 {
1685 uint8_t reason;
1686 uint8_t byteorder;
1687
1688 uint16_t zero;
1689 uint32_t timestamp;
1690 uint32_t source_window;
1691 } xm_top_level_leave_message;
1692
1693 #define XM_DRAG_SIDE_EFFECT(op, site, ops, act) \
1694 ((op) | ((site) << 4) | ((ops) << 8) | ((act) << 12))
1695
1696
1697
1698 #define XM_DRAG_SIDE_EFFECT_OPERATION(effect) ((effect) & 0xf)
1699 #define XM_DRAG_SIDE_EFFECT_SITE_STATUS(effect) (((effect) & 0xf0) >> 4)
1700
1701 #define XM_DRAG_SIDE_EFFECT_DROP_ACTION(effect) (((effect) & 0xf000) >> 12)
1702
1703 enum xm_drag_operation
1704 {
1705 XM_DRAG_NOOP = 0,
1706 XM_DRAG_MOVE = (1L << 0),
1707 XM_DRAG_COPY = (1L << 1),
1708 XM_DRAG_LINK = (1L << 2),
1709 XM_DRAG_LINK_REC = 3,
1710 };
1711
1712 #define XM_DRAG_OPERATION_IS_LINK(op) ((op) == XM_DRAG_LINK \
1713 || (op) == XM_DRAG_LINK_REC)
1714
1715 enum xm_drag_action
1716 {
1717 XM_DROP_ACTION_DROP = 0,
1718 XM_DROP_ACTION_DROP_HELP = 1,
1719 XM_DROP_ACTION_DROP_CANCEL = 2,
1720 };
1721
1722 #define XM_DRAG_REASON(originator, code) ((code) | ((originator) << 7))
1723 #define XM_DRAG_REASON_ORIGINATOR(reason) (((reason) & 0x80) ? 1 : 0)
1724 #define XM_DRAG_REASON_CODE(reason) ((reason) & 0x7f)
1725
1726 enum xm_drag_reason
1727 {
1728 XM_DRAG_REASON_DROP_START = 5,
1729 XM_DRAG_REASON_TOP_LEVEL_ENTER = 0,
1730 XM_DRAG_REASON_TOP_LEVEL_LEAVE = 1,
1731 XM_DRAG_REASON_DRAG_MOTION = 2,
1732 };
1733
1734 enum xm_drag_originator
1735 {
1736 XM_DRAG_ORIGINATOR_INITIATOR = 0,
1737 XM_DRAG_ORIGINATOR_RECEIVER = 1,
1738 };
1739
1740 enum xm_drag_style
1741 {
1742
1743
1744 XM_DRAG_STYLE_NONE = 0,
1745 XM_DRAG_STYLE_DROP_ONLY = 1,
1746 XM_DRAG_STYLE_DROP_ONLY_REC = 3,
1747 XM_DRAG_STYLE_DYNAMIC = 5,
1748 XM_DRAG_STYLE_DYNAMIC_REC = 2,
1749 XM_DRAG_STYLE_DYNAMIC_REC1 = 4,
1750 };
1751
1752 #define XM_DRAG_STYLE_IS_DROP_ONLY(n) ((n) == XM_DRAG_STYLE_DROP_ONLY \
1753 || (n) == XM_DRAG_STYLE_DROP_ONLY_REC)
1754 #define XM_DRAG_STYLE_IS_DYNAMIC(n) ((n) == XM_DRAG_STYLE_DYNAMIC \
1755 || (n) == XM_DRAG_STYLE_DYNAMIC_REC \
1756 || (n) == XM_DRAG_STYLE_DYNAMIC_REC1)
1757
1758 enum xm_drop_site_status
1759 {
1760 XM_DROP_SITE_VALID = 3,
1761 XM_DROP_SITE_INVALID = 2,
1762 XM_DROP_SITE_NONE = 1,
1763 };
1764
1765
1766
1767 #define XM_DRAG_PROTOCOL_VERSION 0
1768
1769 static uint8_t
1770 xm_side_effect_from_action (struct x_display_info *dpyinfo, Atom action)
1771 {
1772 if (action == dpyinfo->Xatom_XdndActionCopy)
1773 return XM_DRAG_COPY;
1774 else if (action == dpyinfo->Xatom_XdndActionMove)
1775 return XM_DRAG_MOVE;
1776 else if (action == dpyinfo->Xatom_XdndActionLink)
1777 return XM_DRAG_LINK;
1778 else if (action == dpyinfo->Xatom_XdndActionAsk)
1779 return x_dnd_first_motif_operation;
1780
1781 return XM_DRAG_NOOP;
1782 }
1783
1784 static uint8_t
1785 xm_operations_from_actions (struct x_display_info *dpyinfo,
1786 Atom *ask_actions, int n_ask_actions)
1787 {
1788 int i;
1789 uint8_t flags;
1790
1791 flags = 0;
1792
1793 for (i = 0; i < n_ask_actions; ++i)
1794 {
1795 if (ask_actions[i] == dpyinfo->Xatom_XdndActionCopy)
1796 flags |= XM_DRAG_COPY;
1797 else if (ask_actions[i] == dpyinfo->Xatom_XdndActionMove)
1798 flags |= XM_DRAG_MOVE;
1799 else if (ask_actions[i] == dpyinfo->Xatom_XdndActionLink)
1800 flags |= XM_DRAG_LINK;
1801 }
1802
1803 return flags;
1804 }
1805
1806 static int
1807 xm_read_targets_table_header (uint8_t *bytes, ptrdiff_t length,
1808 xm_targets_table_header *header_return,
1809 xm_byte_order *byteorder_return)
1810 {
1811 if (length < 8)
1812 return -1;
1813
1814 header_return->byte_order = *byteorder_return = *(bytes++);
1815 header_return->protocol = *(bytes++);
1816
1817 header_return->target_list_count = *(uint16_t *) bytes;
1818 header_return->total_data_size = *(uint32_t *) (bytes + 2);
1819
1820 if (header_return->byte_order != XM_BYTE_ORDER_CUR_FIRST)
1821 {
1822 SWAPCARD16 (header_return->target_list_count);
1823 SWAPCARD32 (header_return->total_data_size);
1824 }
1825
1826 header_return->byte_order = XM_BYTE_ORDER_CUR_FIRST;
1827
1828 return 8;
1829 }
1830
1831 static xm_targets_table_rec *
1832 xm_read_targets_table_rec (uint8_t *bytes, ptrdiff_t length,
1833 xm_byte_order byteorder)
1834 {
1835 uint16_t nitems, i;
1836 xm_targets_table_rec *rec;
1837
1838 if (length < 2)
1839 return NULL;
1840
1841 nitems = *(uint16_t *) bytes;
1842
1843 if (byteorder != XM_BYTE_ORDER_CUR_FIRST)
1844 SWAPCARD16 (nitems);
1845
1846 if (length < 2 + nitems * 4)
1847 return NULL;
1848
1849 rec = xmalloc (FLEXSIZEOF (struct xm_targets_table_rec,
1850 targets, nitems * 4));
1851 rec->n_targets = nitems;
1852
1853 for (i = 0; i < nitems; ++i)
1854 {
1855 rec->targets[i] = ((uint32_t *) (bytes + 2))[i];
1856
1857 if (byteorder != XM_BYTE_ORDER_CUR_FIRST)
1858 SWAPCARD32 (rec->targets[i]);
1859 }
1860
1861 return rec;
1862 }
1863
1864 static int
1865 xm_find_targets_table_idx (xm_targets_table_header *header,
1866 xm_targets_table_rec **recs,
1867 Atom *sorted_targets, int ntargets)
1868 {
1869 int j;
1870 uint16_t i;
1871 uint32_t *targets;
1872
1873 targets = alloca (sizeof *targets * ntargets);
1874
1875 for (j = 0; j < ntargets; ++j)
1876 targets[j] = sorted_targets[j];
1877
1878 for (i = 0; i < header->target_list_count; ++i)
1879 {
1880 if (recs[i]->n_targets == ntargets
1881 && !memcmp (&recs[i]->targets, targets,
1882 sizeof *targets * ntargets))
1883 return i;
1884 }
1885
1886 return -1;
1887 }
1888
1889 static int
1890 x_atoms_compare (const void *a, const void *b)
1891 {
1892 return *(Atom *) a - *(Atom *) b;
1893 }
1894
1895 static void
1896 xm_write_targets_table (Display *dpy, Window wdesc,
1897 Atom targets_table_atom,
1898 xm_targets_table_header *header,
1899 xm_targets_table_rec **recs)
1900 {
1901 uint8_t *header_buffer, *ptr, *rec_buffer;
1902 ptrdiff_t rec_buffer_size;
1903 uint16_t i, j;
1904
1905 header_buffer = alloca (8);
1906 ptr = header_buffer;
1907
1908 *(header_buffer++) = header->byte_order;
1909 *(header_buffer++) = header->protocol;
1910 *((uint16_t *) header_buffer) = header->target_list_count;
1911 *((uint32_t *) (header_buffer + 2)) = header->total_data_size;
1912
1913 rec_buffer = xmalloc (600);
1914 rec_buffer_size = 600;
1915
1916 XChangeProperty (dpy, wdesc, targets_table_atom,
1917 targets_table_atom, 8, PropModeReplace,
1918 (unsigned char *) ptr, 8);
1919
1920 for (i = 0; i < header->target_list_count; ++i)
1921 {
1922 if (rec_buffer_size < 2 + recs[i]->n_targets * 4)
1923 {
1924 rec_buffer_size = 2 + recs[i]->n_targets * 4;
1925 rec_buffer = xrealloc (rec_buffer, rec_buffer_size);
1926 }
1927
1928 *((uint16_t *) rec_buffer) = recs[i]->n_targets;
1929
1930 for (j = 0; j < recs[i]->n_targets; ++j)
1931 ((uint32_t *) (rec_buffer + 2))[j] = recs[i]->targets[j];
1932
1933 XChangeProperty (dpy, wdesc, targets_table_atom,
1934 targets_table_atom, 8, PropModeAppend,
1935 (unsigned char *) rec_buffer,
1936 2 + recs[i]->n_targets * 4);
1937 }
1938
1939 xfree (rec_buffer);
1940 }
1941
1942 static void
1943 xm_write_drag_initiator_info (Display *dpy, Window wdesc,
1944 Atom prop_name, Atom type_name,
1945 xm_drag_initiator_info *info)
1946 {
1947 uint8_t *buf;
1948
1949 buf = alloca (8);
1950 buf[0] = info->byteorder;
1951 buf[1] = info->protocol;
1952
1953 if (info->byteorder != XM_BYTE_ORDER_CUR_FIRST)
1954 {
1955 SWAPCARD16 (info->table_index);
1956 SWAPCARD16 (info->selection);
1957 }
1958
1959 *((uint16_t *) (buf + 2)) = info->table_index;
1960 *((uint32_t *) (buf + 4)) = info->selection;
1961
1962 XChangeProperty (dpy, wdesc, prop_name, type_name, 8,
1963 PropModeReplace, (unsigned char *) buf, 8);
1964 }
1965
1966 static int
1967 xm_drag_window_error_handler (Display *display, XErrorEvent *event)
1968 {
1969 if (xm_drag_window_error)
1970 *xm_drag_window_error = true;
1971
1972 return 0;
1973 }
1974
1975 static _Noreturn int
1976 xm_drag_window_io_error_handler (Display *dpy)
1977 {
1978
1979
1980 siglongjmp (x_dnd_disconnect_handler, 1);
1981 }
1982
1983
1984
1985 static bool
1986 x_special_window_exists_p (struct x_display_info *dpyinfo,
1987 Window window)
1988 {
1989 bool rc;
1990
1991 x_catch_errors (dpyinfo->display);
1992 XSelectInput (dpyinfo->display, window,
1993 StructureNotifyMask);
1994 rc = !x_had_errors_p (dpyinfo->display);
1995 x_uncatch_errors_after_check ();
1996
1997 return rc;
1998 }
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020 static Window
2021 xm_get_drag_window_1 (struct x_display_info *dpyinfo)
2022 {
2023 Atom actual_type;
2024 int rc, actual_format;
2025 unsigned long nitems, bytes_remaining;
2026 unsigned char *tmp_data = NULL;
2027 Window drag_window;
2028 XSetWindowAttributes attrs;
2029 Display *temp_display;
2030 Emacs_XErrorHandler old_handler;
2031 Emacs_XIOErrorHandler old_io_handler;
2032
2033
2034
2035 volatile bool error;
2036
2037 drag_window = None;
2038 rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window,
2039 dpyinfo->Xatom_MOTIF_DRAG_WINDOW,
2040 0, 1, False, XA_WINDOW, &actual_type,
2041 &actual_format, &nitems, &bytes_remaining,
2042 &tmp_data) == Success;
2043
2044 if (rc && actual_type == XA_WINDOW
2045 && actual_format == 32 && nitems == 1
2046 && tmp_data)
2047 {
2048 drag_window = *(Window *) tmp_data;
2049
2050
2051
2052
2053 rc = x_special_window_exists_p (dpyinfo, drag_window);
2054
2055 if (!rc)
2056 drag_window = None;
2057 }
2058
2059 if (tmp_data)
2060 XFree (tmp_data);
2061
2062 if (drag_window == None)
2063 {
2064 block_input ();
2065 old_io_handler = XSetIOErrorHandler (xm_drag_window_io_error_handler);
2066
2067 if (sigsetjmp (x_dnd_disconnect_handler, 1))
2068 {
2069 XSetIOErrorHandler (old_io_handler);
2070 unblock_input ();
2071
2072 return None;
2073 }
2074
2075 unrequest_sigio ();
2076 temp_display = XOpenDisplay (XDisplayString (dpyinfo->display));
2077 request_sigio ();
2078
2079 if (!temp_display)
2080 {
2081 XSetIOErrorHandler (old_io_handler);
2082 unblock_input ();
2083
2084 return None;
2085 }
2086
2087 error = false;
2088 xm_drag_window_error = &error;
2089
2090 XSetCloseDownMode (temp_display, RetainPermanent);
2091 old_handler = XSetErrorHandler (xm_drag_window_error_handler);
2092
2093 attrs.override_redirect = True;
2094 drag_window = XCreateWindow (temp_display, DefaultRootWindow (temp_display),
2095 -1, -1, 1, 1, 0, CopyFromParent, InputOnly,
2096 CopyFromParent, CWOverrideRedirect, &attrs);
2097
2098
2099 XSync (temp_display, False);
2100
2101
2102
2103 if (error)
2104 {
2105 XSetCloseDownMode (temp_display, DestroyAll);
2106 drag_window = None;
2107 }
2108
2109 xm_drag_window_error = NULL;
2110
2111
2112
2113 unrequest_sigio ();
2114 XCloseDisplay (temp_display);
2115 request_sigio ();
2116
2117 XSetErrorHandler (old_handler);
2118 XSetIOErrorHandler (old_io_handler);
2119
2120
2121
2122
2123 if (!x_special_window_exists_p (dpyinfo, drag_window))
2124 drag_window = None;
2125 unblock_input ();
2126
2127 if (drag_window != None)
2128 {
2129 XGrabServer (dpyinfo->display);
2130
2131 x_catch_errors (dpyinfo->display);
2132 tmp_data = NULL;
2133
2134 rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window,
2135 dpyinfo->Xatom_MOTIF_DRAG_WINDOW,
2136 0, 1, False, XA_WINDOW, &actual_type,
2137 &actual_format, &nitems, &bytes_remaining,
2138 &tmp_data) == Success;
2139
2140 if (rc && actual_type == XA_WINDOW
2141 && actual_format == 32 && nitems == 1
2142 && tmp_data
2143 && x_special_window_exists_p (dpyinfo,
2144 *(Window *) tmp_data))
2145 {
2146
2147
2148 XKillClient (dpyinfo->display, drag_window);
2149 drag_window = *(Window *) tmp_data;
2150 }
2151 else
2152 XChangeProperty (dpyinfo->display, dpyinfo->root_window,
2153 dpyinfo->Xatom_MOTIF_DRAG_WINDOW,
2154 XA_WINDOW, 32, PropModeReplace,
2155 (unsigned char *) &drag_window, 1);
2156
2157 if (tmp_data)
2158 XFree (tmp_data);
2159
2160 if (x_had_errors_p (dpyinfo->display))
2161 drag_window = None;
2162 x_uncatch_errors ();
2163
2164 XUngrabServer (dpyinfo->display);
2165 }
2166 }
2167
2168 return drag_window;
2169 }
2170
2171 static Window
2172 xm_get_drag_window (struct x_display_info *dpyinfo)
2173 {
2174 if (dpyinfo->motif_drag_window != None)
2175 return dpyinfo->motif_drag_window;
2176
2177 dpyinfo->motif_drag_window = xm_get_drag_window_1 (dpyinfo);
2178 return dpyinfo->motif_drag_window;
2179 }
2180
2181 static int
2182 xm_setup_dnd_targets (struct x_display_info *dpyinfo,
2183 Atom *targets, int ntargets)
2184 {
2185 Window drag_window;
2186 Atom *targets_sorted, actual_type;
2187 unsigned char *tmp_data = NULL;
2188 unsigned long nitems, bytes_remaining;
2189 int rc, actual_format, idx;
2190 bool had_errors;
2191 xm_targets_table_header header;
2192 xm_targets_table_rec **recs UNINIT;
2193 xm_byte_order byteorder;
2194 uint8_t *data;
2195 ptrdiff_t total_bytes, total_items, i;
2196 uint32_t size, target_count;
2197
2198 retry_drag_window:
2199
2200 drag_window = xm_get_drag_window (dpyinfo);
2201
2202 if (drag_window == None || ntargets > 64)
2203 return -1;
2204
2205 targets_sorted = xmalloc (sizeof *targets * ntargets);
2206 memcpy (targets_sorted, targets,
2207 sizeof *targets * ntargets);
2208 qsort (targets_sorted, ntargets,
2209 sizeof (Atom), x_atoms_compare);
2210
2211 XGrabServer (dpyinfo->display);
2212
2213 x_catch_errors (dpyinfo->display);
2214 rc = XGetWindowProperty (dpyinfo->display, drag_window,
2215 dpyinfo->Xatom_MOTIF_DRAG_TARGETS,
2216 0L, LONG_MAX, False,
2217 dpyinfo->Xatom_MOTIF_DRAG_TARGETS,
2218 &actual_type, &actual_format, &nitems,
2219 &bytes_remaining, &tmp_data) == Success;
2220 had_errors = x_had_errors_p (dpyinfo->display);
2221 x_uncatch_errors_after_check ();
2222
2223
2224
2225 if (had_errors)
2226 {
2227 dpyinfo->motif_drag_window = None;
2228 XUngrabServer (dpyinfo->display);
2229
2230 goto retry_drag_window;
2231 }
2232
2233 if (rc && tmp_data && !bytes_remaining
2234 && actual_type == dpyinfo->Xatom_MOTIF_DRAG_TARGETS
2235 && actual_format == 8)
2236 {
2237 data = (uint8_t *) tmp_data;
2238 if (xm_read_targets_table_header ((uint8_t *) tmp_data,
2239 nitems, &header,
2240 &byteorder) == 8)
2241 {
2242 data += 8;
2243 nitems -= 8;
2244 total_bytes = 0;
2245 total_items = 0;
2246
2247
2248
2249 recs = xmalloc ((header.target_list_count + 1)
2250 * sizeof *recs);
2251
2252 while (total_items < header.target_list_count)
2253 {
2254 recs[total_items] = xm_read_targets_table_rec (data + total_bytes,
2255 nitems, byteorder);
2256
2257 if (!recs[total_items])
2258 break;
2259
2260 total_bytes += 2 + recs[total_items]->n_targets * 4;
2261 nitems -= 2 + recs[total_items]->n_targets * 4;
2262 total_items++;
2263 }
2264
2265 if (header.target_list_count != total_items
2266 || header.total_data_size != 8 + total_bytes)
2267 {
2268 for (i = 0; i < total_items; ++i)
2269 {
2270 if (recs[i])
2271 xfree (recs[i]);
2272 else
2273 break;
2274 }
2275
2276 xfree (recs);
2277
2278 rc = false;
2279 }
2280 }
2281 else
2282 rc = false;
2283 }
2284 else
2285 rc = false;
2286
2287 if (tmp_data)
2288 XFree (tmp_data);
2289
2290
2291
2292
2293 if (!rc)
2294 {
2295 header.byte_order = XM_BYTE_ORDER_CUR_FIRST;
2296 header.protocol = XM_DRAG_PROTOCOL_VERSION;
2297 header.target_list_count = 1;
2298 header.total_data_size = 8 + 2 + ntargets * 4;
2299
2300 recs = xmalloc (sizeof *recs);
2301 recs[0] = xmalloc (FLEXSIZEOF (struct xm_targets_table_rec,
2302 targets, ntargets * 4));
2303
2304 recs[0]->n_targets = ntargets;
2305
2306 for (i = 0; i < ntargets; ++i)
2307 recs[0]->targets[i] = targets_sorted[i];
2308
2309 idx = 0;
2310 }
2311 else
2312 {
2313 idx = xm_find_targets_table_idx (&header, recs,
2314 targets_sorted,
2315 ntargets);
2316
2317 if (idx == -1)
2318 {
2319 target_count = header.target_list_count;
2320 rc = false;
2321
2322 if (ckd_add (&header.target_list_count, header.target_list_count, 1)
2323 || ckd_mul (&size, ntargets, 4)
2324 || ckd_add (&header.total_data_size, header.total_data_size, size)
2325 || ckd_add (&header.total_data_size, header.total_data_size, 2))
2326 {
2327
2328
2329
2330
2331
2332 for (i = 0; i < target_count; ++i)
2333 xfree (recs[i]);
2334
2335 xfree (recs);
2336
2337 header.byte_order = XM_BYTE_ORDER_CUR_FIRST;
2338 header.protocol = XM_DRAG_PROTOCOL_VERSION;
2339 header.target_list_count = 1;
2340 header.total_data_size = 8 + 2 + ntargets * 4;
2341
2342 recs = xmalloc (sizeof *recs);
2343 recs[0] = xmalloc (FLEXSIZEOF (struct xm_targets_table_rec,
2344 targets, ntargets * 4));
2345
2346 recs[0]->n_targets = ntargets;
2347
2348 for (i = 0; i < ntargets; ++i)
2349 recs[0]->targets[i] = targets_sorted[i];
2350
2351 idx = 0;
2352 }
2353 else
2354 {
2355 recs[header.target_list_count - 1]
2356 = xmalloc (FLEXSIZEOF (struct xm_targets_table_rec,
2357 targets, ntargets * 4));
2358 recs[header.target_list_count - 1]->n_targets = ntargets;
2359
2360 for (i = 0; i < ntargets; ++i)
2361 recs[header.target_list_count - 1]->targets[i] = targets_sorted[i];
2362
2363 idx = header.target_list_count - 1;
2364 }
2365 }
2366 }
2367
2368 if (!rc)
2369 {
2370
2371
2372
2373
2374
2375 header.protocol = XM_DRAG_PROTOCOL_VERSION;
2376
2377 x_catch_errors (dpyinfo->display);
2378 xm_write_targets_table (dpyinfo->display, drag_window,
2379 dpyinfo->Xatom_MOTIF_DRAG_TARGETS,
2380 &header, recs);
2381
2382
2383 if (x_had_errors_p (dpyinfo->display))
2384 idx = -1;
2385 x_uncatch_errors_after_check ();
2386 }
2387
2388 XUngrabServer (dpyinfo->display);
2389
2390 for (i = 0; i < header.target_list_count; ++i)
2391 xfree (recs[i]);
2392
2393 xfree (recs);
2394 xfree (targets_sorted);
2395
2396 return idx;
2397 }
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408 static Atom
2409 xm_get_drag_atom_1 (struct x_display_info *dpyinfo,
2410 struct frame *source_frame)
2411 {
2412 Atom actual_type, *atoms, atom;
2413 unsigned long nitems, bytes_remaining;
2414 unsigned char *tmp_data;
2415 int rc, actual_format;
2416 unsigned long i;
2417 char *buffer;
2418 Window owner;
2419
2420
2421 XGrabServer (dpyinfo->display);
2422
2423 rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window,
2424 dpyinfo->Xatom_EMACS_DRAG_ATOM,
2425 0, LONG_MAX, False, XA_ATOM, &actual_type,
2426 &actual_format, &nitems, &bytes_remaining,
2427 &tmp_data);
2428 atom = None;
2429
2430
2431 i = 0;
2432
2433 if (rc == Success
2434 && actual_format == 32 && nitems
2435 && actual_type == XA_ATOM)
2436 {
2437 atoms = (Atom *) tmp_data;
2438
2439 x_catch_errors (dpyinfo->display);
2440
2441 for (i = 0; i < nitems; ++i)
2442 {
2443 owner = XGetSelectionOwner (dpyinfo->display, atoms[i]);
2444
2445 if (!x_had_errors_p (dpyinfo->display)
2446 && (owner == None
2447
2448
2449
2450
2451 || x_window_to_frame (dpyinfo, owner)))
2452 {
2453 atom = atoms[i];
2454
2455 break;
2456 }
2457 }
2458
2459 x_uncatch_errors ();
2460 }
2461
2462 if (tmp_data)
2463 XFree (tmp_data);
2464
2465 buffer = dpyinfo->motif_drag_atom_name;
2466
2467 if (atom)
2468 {
2469 sprintf (buffer, "_EMACS_ATOM_%lu", i + 1);
2470 XSetSelectionOwner (dpyinfo->display, atom,
2471 FRAME_X_WINDOW (source_frame),
2472 dpyinfo->last_user_time);
2473
2474
2475
2476 if (XGetSelectionOwner (dpyinfo->display, atom)
2477 != FRAME_X_WINDOW (source_frame))
2478 atom = None;
2479 }
2480
2481 while (!atom)
2482 {
2483 sprintf (buffer, "_EMACS_ATOM_%lu", nitems + 1);
2484 atom = XInternAtom (dpyinfo->display, buffer, False);
2485
2486 XSetSelectionOwner (dpyinfo->display, atom,
2487 FRAME_X_WINDOW (source_frame),
2488 dpyinfo->last_user_time);
2489
2490 XChangeProperty (dpyinfo->display, dpyinfo->root_window,
2491 dpyinfo->Xatom_EMACS_DRAG_ATOM, XA_ATOM, 32,
2492 (rc != Success
2493 || (actual_format != 32
2494 || actual_type != XA_ATOM)
2495 ? PropModeReplace : PropModeAppend),
2496 (unsigned char *) &atom, 1);
2497
2498 actual_format = 32;
2499 actual_type = XA_ATOM;
2500 rc = Success;
2501 nitems += 1;
2502
2503
2504
2505 if (XGetSelectionOwner (dpyinfo->display, atom)
2506 != FRAME_X_WINDOW (source_frame))
2507 atom = None;
2508 }
2509
2510 dpyinfo->motif_drag_atom_time = dpyinfo->last_user_time;
2511 dpyinfo->motif_drag_atom_owner = source_frame;
2512
2513 XUngrabServer (dpyinfo->display);
2514 return atom;
2515 }
2516
2517 static Atom
2518 xm_get_drag_atom (struct x_display_info *dpyinfo)
2519 {
2520 Atom atom;
2521
2522 if (dpyinfo->motif_drag_atom != None)
2523 atom = dpyinfo->motif_drag_atom;
2524 else
2525 atom = xm_get_drag_atom_1 (dpyinfo, x_dnd_frame);
2526
2527 dpyinfo->motif_drag_atom = atom;
2528 return atom;
2529 }
2530
2531 static void
2532 xm_setup_drag_info (struct x_display_info *dpyinfo,
2533 struct frame *source_frame)
2534 {
2535 Atom atom;
2536 xm_drag_initiator_info drag_initiator_info;
2537 int idx;
2538
2539 atom = xm_get_drag_atom (dpyinfo);
2540
2541 if (atom == None)
2542 return;
2543
2544 XSETCAR (x_dnd_selection_alias_cell,
2545 x_atom_to_symbol (dpyinfo, atom));
2546 XSETCDR (x_dnd_selection_alias_cell, QXdndSelection);
2547
2548 idx = xm_setup_dnd_targets (dpyinfo, x_dnd_targets,
2549 x_dnd_n_targets);
2550
2551 if (idx != -1)
2552 {
2553 drag_initiator_info.byteorder = XM_BYTE_ORDER_CUR_FIRST;
2554 drag_initiator_info.protocol = XM_DRAG_PROTOCOL_VERSION;
2555 drag_initiator_info.table_index = idx;
2556 drag_initiator_info.selection = atom;
2557
2558 xm_write_drag_initiator_info (dpyinfo->display,
2559 FRAME_X_WINDOW (source_frame), atom,
2560 dpyinfo->Xatom_MOTIF_DRAG_INITIATOR_INFO,
2561 &drag_initiator_info);
2562
2563 x_dnd_motif_setup_p = true;
2564 x_dnd_motif_atom = atom;
2565 }
2566 }
2567
2568 static void
2569 xm_send_drop_message (struct x_display_info *dpyinfo, Window source,
2570 Window target, xm_drop_start_message *dmsg)
2571 {
2572 XEvent msg;
2573
2574 msg.xclient.type = ClientMessage;
2575 msg.xclient.message_type
2576 = dpyinfo->Xatom_MOTIF_DRAG_AND_DROP_MESSAGE;
2577 msg.xclient.format = 8;
2578 msg.xclient.window = target;
2579 msg.xclient.data.b[0] = dmsg->reason;
2580 msg.xclient.data.b[1] = dmsg->byte_order;
2581 *((uint16_t *) &msg.xclient.data.b[2]) = dmsg->side_effects;
2582 *((uint32_t *) &msg.xclient.data.b[4]) = dmsg->timestamp;
2583 *((uint16_t *) &msg.xclient.data.b[8]) = dmsg->x;
2584 *((uint16_t *) &msg.xclient.data.b[10]) = dmsg->y;
2585 *((uint32_t *) &msg.xclient.data.b[12]) = dmsg->index_atom;
2586 *((uint32_t *) &msg.xclient.data.b[16]) = dmsg->source_window;
2587
2588 x_ignore_errors_for_next_request (dpyinfo, 0);
2589 XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg);
2590 x_stop_ignoring_errors (dpyinfo);
2591 }
2592
2593 static void
2594 xm_send_top_level_enter_message (struct x_display_info *dpyinfo, Window source,
2595 Window target, xm_top_level_enter_message *dmsg)
2596 {
2597 XEvent msg;
2598
2599 msg.xclient.type = ClientMessage;
2600 msg.xclient.message_type
2601 = dpyinfo->Xatom_MOTIF_DRAG_AND_DROP_MESSAGE;
2602 msg.xclient.format = 8;
2603 msg.xclient.window = target;
2604 msg.xclient.data.b[0] = dmsg->reason;
2605 msg.xclient.data.b[1] = dmsg->byteorder;
2606 *((uint16_t *) &msg.xclient.data.b[2]) = dmsg->zero;
2607 *((uint32_t *) &msg.xclient.data.b[4]) = dmsg->timestamp;
2608 *((uint32_t *) &msg.xclient.data.b[8]) = dmsg->source_window;
2609 *((uint32_t *) &msg.xclient.data.b[12]) = dmsg->index_atom;
2610 msg.xclient.data.b[16] = 0;
2611 msg.xclient.data.b[17] = 0;
2612 msg.xclient.data.b[18] = 0;
2613 msg.xclient.data.b[19] = 0;
2614
2615 x_ignore_errors_for_next_request (dpyinfo, 0);
2616 XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg);
2617 x_stop_ignoring_errors (dpyinfo);
2618 }
2619
2620 static void
2621 xm_send_drag_motion_message (struct x_display_info *dpyinfo, Window source,
2622 Window target, xm_drag_motion_message *dmsg)
2623 {
2624 XEvent msg;
2625
2626 msg.xclient.type = ClientMessage;
2627 msg.xclient.message_type
2628 = dpyinfo->Xatom_MOTIF_DRAG_AND_DROP_MESSAGE;
2629 msg.xclient.format = 8;
2630 msg.xclient.window = target;
2631 msg.xclient.data.b[0] = dmsg->reason;
2632 msg.xclient.data.b[1] = dmsg->byteorder;
2633 *((uint16_t *) &msg.xclient.data.b[2]) = dmsg->side_effects;
2634 *((uint32_t *) &msg.xclient.data.b[4]) = dmsg->timestamp;
2635 *((uint16_t *) &msg.xclient.data.b[8]) = dmsg->x;
2636 *((uint16_t *) &msg.xclient.data.b[10]) = dmsg->y;
2637 msg.xclient.data.b[12] = 0;
2638 msg.xclient.data.b[13] = 0;
2639 msg.xclient.data.b[14] = 0;
2640 msg.xclient.data.b[15] = 0;
2641 msg.xclient.data.b[16] = 0;
2642 msg.xclient.data.b[17] = 0;
2643 msg.xclient.data.b[18] = 0;
2644 msg.xclient.data.b[19] = 0;
2645
2646 x_ignore_errors_for_next_request (dpyinfo, 0);
2647 XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg);
2648 x_stop_ignoring_errors (dpyinfo);
2649 }
2650
2651 static void
2652 xm_send_top_level_leave_message (struct x_display_info *dpyinfo, Window source,
2653 Window target, xm_top_level_leave_message *dmsg)
2654 {
2655 XEvent msg;
2656 xm_drag_motion_message mmsg;
2657
2658
2659
2660
2661
2662
2663
2664
2665 if (x_dnd_fix_motif_leave)
2666 {
2667 mmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
2668 XM_DRAG_REASON_DRAG_MOTION);
2669 mmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
2670 mmsg.side_effects = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
2671 x_dnd_wanted_action),
2672 XM_DROP_SITE_NONE, x_dnd_motif_operations,
2673 XM_DROP_ACTION_DROP_CANCEL);
2674 mmsg.timestamp = dmsg->timestamp;
2675
2676
2677
2678
2679
2680 mmsg.x = X_SHRT_MAX;
2681 mmsg.y = X_SHRT_MAX;
2682
2683 xm_send_drag_motion_message (dpyinfo, source, target, &mmsg);
2684 }
2685
2686 msg.xclient.type = ClientMessage;
2687 msg.xclient.message_type
2688 = dpyinfo->Xatom_MOTIF_DRAG_AND_DROP_MESSAGE;
2689 msg.xclient.format = 8;
2690 msg.xclient.window = target;
2691 msg.xclient.data.b[0] = dmsg->reason;
2692 msg.xclient.data.b[1] = dmsg->byteorder;
2693 *((uint16_t *) &msg.xclient.data.b[2]) = dmsg->zero;
2694 *((uint32_t *) &msg.xclient.data.b[4]) = dmsg->timestamp;
2695 *((uint32_t *) &msg.xclient.data.b[8]) = dmsg->source_window;
2696 msg.xclient.data.b[12] = 0;
2697 msg.xclient.data.b[13] = 0;
2698 msg.xclient.data.b[14] = 0;
2699 msg.xclient.data.b[15] = 0;
2700 msg.xclient.data.b[16] = 0;
2701 msg.xclient.data.b[17] = 0;
2702 msg.xclient.data.b[18] = 0;
2703 msg.xclient.data.b[19] = 0;
2704
2705 x_ignore_errors_for_next_request (dpyinfo, 0);
2706 XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg);
2707 x_stop_ignoring_errors (dpyinfo);
2708 }
2709
2710 static int
2711 xm_read_drop_start_reply (const XEvent *msg, xm_drop_start_reply *reply)
2712 {
2713 const uint8_t *data;
2714
2715 data = (const uint8_t *) &msg->xclient.data.b[0];
2716
2717 if ((XM_DRAG_REASON_ORIGINATOR (data[0])
2718 != XM_DRAG_ORIGINATOR_RECEIVER)
2719 || (XM_DRAG_REASON_CODE (data[0])
2720 != XM_DRAG_REASON_DROP_START))
2721 return 1;
2722
2723 reply->reason = *(data++);
2724 reply->byte_order = *(data++);
2725 reply->side_effects = *(uint16_t *) data;
2726 reply->better_x = *(uint16_t *) (data + 2);
2727 reply->better_y = *(uint16_t *) (data + 4);
2728
2729 if (reply->byte_order != XM_BYTE_ORDER_CUR_FIRST)
2730 {
2731 SWAPCARD16 (reply->side_effects);
2732 SWAPCARD16 (reply->better_x);
2733 SWAPCARD16 (reply->better_y);
2734 }
2735
2736 reply->byte_order = XM_BYTE_ORDER_CUR_FIRST;
2737
2738 return 0;
2739 }
2740
2741 static int
2742 xm_read_drop_start_message (const XEvent *msg,
2743 xm_drop_start_message *dmsg)
2744 {
2745 const uint8_t *data;
2746
2747 data = (const uint8_t *) &msg->xclient.data.b[0];
2748
2749 if ((XM_DRAG_REASON_ORIGINATOR (data[0])
2750 != XM_DRAG_ORIGINATOR_INITIATOR)
2751 || (XM_DRAG_REASON_CODE (data[0])
2752 != XM_DRAG_REASON_DROP_START))
2753 return 1;
2754
2755 dmsg->reason = *(data++);
2756 dmsg->byte_order = *(data++);
2757 dmsg->side_effects = *(uint16_t *) data;
2758 dmsg->timestamp = *(uint32_t *) (data + 2);
2759 dmsg->x = *(uint16_t *) (data + 6);
2760 dmsg->y = *(uint16_t *) (data + 8);
2761 dmsg->index_atom = *(uint32_t *) (data + 10);
2762 dmsg->source_window = *(uint32_t *) (data + 14);
2763
2764 if (dmsg->byte_order != XM_BYTE_ORDER_CUR_FIRST)
2765 {
2766 SWAPCARD16 (dmsg->side_effects);
2767 SWAPCARD32 (dmsg->timestamp);
2768 SWAPCARD16 (dmsg->x);
2769 SWAPCARD16 (dmsg->y);
2770 SWAPCARD32 (dmsg->index_atom);
2771 SWAPCARD32 (dmsg->source_window);
2772 }
2773
2774 dmsg->byte_order = XM_BYTE_ORDER_CUR_FIRST;
2775
2776 return 0;
2777 }
2778
2779 static int
2780 xm_read_drag_receiver_info (struct x_display_info *dpyinfo,
2781 Window wdesc, xm_drag_receiver_info *rec)
2782 {
2783 Atom actual_type;
2784 int rc, actual_format;
2785 unsigned long nitems, bytes_remaining;
2786 unsigned char *tmp_data = NULL;
2787 uint8_t *data;
2788
2789 x_catch_errors (dpyinfo->display);
2790 rc = XGetWindowProperty (dpyinfo->display, wdesc,
2791 dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO,
2792 0, 4, False,
2793 dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO,
2794 &actual_type, &actual_format, &nitems,
2795 &bytes_remaining,
2796 &tmp_data) == Success;
2797
2798 if (x_had_errors_p (dpyinfo->display)
2799 || actual_format != 8 || nitems < 16 || !tmp_data
2800 || actual_type != dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO)
2801 rc = 0;
2802 x_uncatch_errors_after_check ();
2803
2804 if (rc)
2805 {
2806 data = (uint8_t *) tmp_data;
2807
2808 if (data[1] > XM_DRAG_PROTOCOL_VERSION)
2809 return 1;
2810
2811 rec->byteorder = data[0];
2812 rec->protocol = data[1];
2813 rec->protocol_style = data[2];
2814 rec->unspecified0 = data[3];
2815 rec->unspecified1 = *(uint32_t *) &data[4];
2816 rec->unspecified2 = *(uint32_t *) &data[8];
2817 rec->unspecified3 = *(uint32_t *) &data[12];
2818
2819 if (rec->byteorder != XM_BYTE_ORDER_CUR_FIRST)
2820 {
2821 SWAPCARD32 (rec->unspecified1);
2822 SWAPCARD32 (rec->unspecified2);
2823 SWAPCARD32 (rec->unspecified3);
2824 }
2825
2826 rec->byteorder = XM_BYTE_ORDER_CUR_FIRST;
2827 }
2828
2829 if (tmp_data)
2830 XFree (tmp_data);
2831
2832 return !rc;
2833 }
2834
2835 static int
2836 xm_read_drag_motion_message (const XEvent *msg,
2837 xm_drag_motion_message *dmsg)
2838 {
2839 const uint8_t *data;
2840
2841 data = (const uint8_t *) &msg->xclient.data.b[0];
2842
2843 if ((XM_DRAG_REASON_CODE (data[0])
2844 != XM_DRAG_REASON_DRAG_MOTION)
2845 || (XM_DRAG_REASON_ORIGINATOR (data[0])
2846 != XM_DRAG_ORIGINATOR_INITIATOR))
2847 return 1;
2848
2849 dmsg->reason = *(data++);
2850 dmsg->byteorder = *(data++);
2851 dmsg->side_effects = *(uint16_t *) data;
2852 dmsg->timestamp = *(uint32_t *) (data + 2);
2853 dmsg->x = *(uint16_t *) (data + 6);
2854 dmsg->y = *(uint16_t *) (data + 8);
2855
2856 if (dmsg->byteorder != XM_BYTE_ORDER_CUR_FIRST)
2857 {
2858 SWAPCARD16 (dmsg->side_effects);
2859 SWAPCARD32 (dmsg->timestamp);
2860 SWAPCARD16 (dmsg->x);
2861 SWAPCARD16 (dmsg->y);
2862 }
2863
2864 dmsg->byteorder = XM_BYTE_ORDER_CUR_FIRST;
2865
2866 return 0;
2867 }
2868
2869 static int
2870 xm_read_drag_motion_reply (const XEvent *msg, xm_drag_motion_reply *reply)
2871 {
2872 const uint8_t *data;
2873
2874 data = (const uint8_t *) &msg->xclient.data.b[0];
2875
2876 if ((XM_DRAG_REASON_CODE (data[0])
2877 != XM_DRAG_REASON_DRAG_MOTION)
2878 || (XM_DRAG_REASON_ORIGINATOR (data[0])
2879 != XM_DRAG_ORIGINATOR_RECEIVER))
2880 return 1;
2881
2882 reply->reason = *(data++);
2883 reply->byte_order = *(data++);
2884 reply->side_effects = *(uint16_t *) data;
2885 reply->timestamp = *(uint32_t *) (data + 2);
2886 reply->better_x = *(uint16_t *) (data + 6);
2887 reply->better_y = *(uint16_t *) (data + 8);
2888
2889 if (reply->byte_order != XM_BYTE_ORDER_CUR_FIRST)
2890 {
2891 SWAPCARD16 (reply->side_effects);
2892 SWAPCARD32 (reply->timestamp);
2893 SWAPCARD16 (reply->better_x);
2894 SWAPCARD16 (reply->better_y);
2895 }
2896
2897 reply->byte_order = XM_BYTE_ORDER_CUR_FIRST;
2898
2899 return 0;
2900 }
2901
2902 static void
2903 x_dnd_send_xm_leave_for_drop (struct x_display_info *dpyinfo,
2904 struct frame *f, Window wdesc,
2905 Time timestamp)
2906 {
2907 xm_top_level_leave_message lmsg;
2908
2909 lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
2910 XM_DRAG_REASON_TOP_LEVEL_LEAVE);
2911 lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
2912 lmsg.zero = 0;
2913 lmsg.timestamp = timestamp;
2914 lmsg.source_window = FRAME_X_WINDOW (f);
2915
2916 if (x_dnd_motif_setup_p)
2917 xm_send_top_level_leave_message (dpyinfo, FRAME_X_WINDOW (f),
2918 wdesc, &lmsg);
2919 }
2920
2921
2922
2923
2924
2925
2926 static void
2927 x_dnd_free_toplevels (bool display_alive)
2928 {
2929 struct x_client_list_window *last;
2930 struct x_client_list_window *tem = x_dnd_toplevels;
2931 ptrdiff_t n_windows, i, buffer_size;
2932 Window *destroy_windows UNINIT;
2933 unsigned long *prev_masks UNINIT;
2934 specpdl_ref count;
2935 Display *dpy UNINIT;
2936 struct x_display_info *dpyinfo;
2937
2938 if (!x_dnd_toplevels)
2939
2940 return;
2941
2942 if (display_alive)
2943 {
2944 buffer_size = 1024;
2945 destroy_windows = xmalloc (sizeof *destroy_windows
2946 * buffer_size);
2947 prev_masks = xmalloc (sizeof *prev_masks *
2948 buffer_size);
2949 n_windows = 0;
2950 }
2951
2952 block_input ();
2953 while (tem)
2954 {
2955 last = tem;
2956 tem = tem->next;
2957
2958 if (display_alive)
2959 {
2960 if (++n_windows >= buffer_size)
2961 {
2962 buffer_size += 1024;
2963 destroy_windows
2964 = xrealloc (destroy_windows, (sizeof *destroy_windows
2965 * buffer_size));
2966 prev_masks
2967 = xrealloc (prev_masks, (sizeof *prev_masks
2968 * buffer_size));
2969 }
2970
2971 dpy = last->dpy;
2972 prev_masks[n_windows - 1] = last->previous_event_mask;
2973 destroy_windows[n_windows - 1] = last->window;
2974 }
2975
2976 #ifdef HAVE_XSHAPE
2977 if (last->n_input_rects != -1)
2978 xfree (last->input_rects);
2979 if (last->n_bounding_rects != -1)
2980 xfree (last->bounding_rects);
2981 #endif
2982
2983 xfree (last);
2984 }
2985
2986 x_dnd_toplevels = NULL;
2987
2988 if (!display_alive)
2989 {
2990 unblock_input ();
2991 return;
2992 }
2993
2994 count = SPECPDL_INDEX ();
2995 record_unwind_protect_ptr (xfree, destroy_windows);
2996 record_unwind_protect_ptr (xfree, prev_masks);
2997
2998 if (display_alive)
2999 {
3000 dpyinfo = x_display_info_for_display (dpy);
3001
3002 if (n_windows)
3003 {
3004 eassume (dpyinfo);
3005 x_ignore_errors_for_next_request (dpyinfo, 0);
3006
3007 for (i = 0; i < n_windows; ++i)
3008 {
3009 XSelectInput (dpy, destroy_windows[i], prev_masks[i]);
3010 #ifdef HAVE_XSHAPE
3011 XShapeSelectInput (dpy, destroy_windows[i], None);
3012 #endif
3013 }
3014
3015 x_stop_ignoring_errors (dpyinfo);
3016 }
3017 }
3018
3019 unbind_to (count, Qnil);
3020 unblock_input ();
3021 }
3022
3023 static int
3024 x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
3025 {
3026 Atom type;
3027 Window *toplevels;
3028 int format, rc;
3029 unsigned long nitems, bytes_after;
3030 unsigned long i, real_nitems;
3031 unsigned char *data = NULL;
3032 int frame_extents[4];
3033
3034 #ifndef USE_XCB
3035 int dest_x, dest_y;
3036 unsigned long *wmstate;
3037 unsigned long wmstate_items, extent_items;
3038 unsigned char *wmstate_data = NULL, *extent_data = NULL;
3039 XWindowAttributes attrs;
3040 Window child;
3041 xm_drag_receiver_info xm_info;
3042 #else
3043 uint32_t *wmstate, *fextents;
3044 uint8_t *xmdata;
3045 xcb_get_window_attributes_cookie_t *window_attribute_cookies;
3046 xcb_translate_coordinates_cookie_t *translate_coordinate_cookies;
3047 xcb_get_property_cookie_t *get_property_cookies;
3048 xcb_get_property_cookie_t *xm_property_cookies;
3049 xcb_get_property_cookie_t *extent_property_cookies;
3050 xcb_get_geometry_cookie_t *get_geometry_cookies;
3051 xcb_get_window_attributes_reply_t attrs, *attrs_reply;
3052 xcb_translate_coordinates_reply_t *coordinates_reply;
3053 xcb_get_property_reply_t *property_reply;
3054 xcb_get_property_reply_t *xm_property_reply;
3055 xcb_get_property_reply_t *extent_property_reply;
3056 xcb_get_geometry_reply_t *geometry_reply;
3057 xcb_generic_error_t *error;
3058 #endif
3059
3060 #ifdef HAVE_XCB_SHAPE
3061 xcb_shape_get_rectangles_cookie_t *bounding_rect_cookies;
3062 xcb_shape_get_rectangles_reply_t *bounding_rect_reply;
3063 xcb_rectangle_iterator_t bounding_rect_iterator;
3064 #endif
3065
3066 #ifdef HAVE_XCB_SHAPE_INPUT_RECTS
3067 xcb_shape_get_rectangles_cookie_t *input_rect_cookies;
3068 xcb_shape_get_rectangles_reply_t *input_rect_reply;
3069 xcb_rectangle_iterator_t input_rect_iterator;
3070 #endif
3071
3072 struct x_client_list_window *tem;
3073 #if defined HAVE_XSHAPE && !defined HAVE_XCB_SHAPE_INPUT_RECTS
3074 int count, ordering;
3075 XRectangle *rects;
3076 #endif
3077
3078 rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window,
3079 dpyinfo->Xatom_net_client_list_stacking,
3080 0, LONG_MAX, False, XA_WINDOW, &type,
3081 &format, &nitems, &bytes_after, &data);
3082
3083 if (rc != Success)
3084 return 1;
3085
3086 if (format != 32 || type != XA_WINDOW)
3087 {
3088 XFree (data);
3089 return 1;
3090 }
3091
3092 toplevels = (Window *) data;
3093
3094 for (i = 0, real_nitems = 0; i < nitems; ++i)
3095 {
3096
3097
3098 if (!x_tooltip_window_to_frame (dpyinfo, toplevels[i], NULL))
3099 toplevels[real_nitems++] = toplevels[i];
3100 }
3101
3102 nitems = real_nitems;
3103
3104 #ifdef USE_XCB
3105 USE_SAFE_ALLOCA;
3106
3107 window_attribute_cookies
3108 = SAFE_ALLOCA (sizeof *window_attribute_cookies * nitems);
3109 translate_coordinate_cookies
3110 = SAFE_ALLOCA (sizeof *translate_coordinate_cookies * nitems);
3111 get_property_cookies
3112 = SAFE_ALLOCA (sizeof *get_property_cookies * nitems);
3113 xm_property_cookies
3114 = SAFE_ALLOCA (sizeof *xm_property_cookies * nitems);
3115 extent_property_cookies
3116 = SAFE_ALLOCA (sizeof *extent_property_cookies * nitems);
3117 get_geometry_cookies
3118 = SAFE_ALLOCA (sizeof *get_geometry_cookies * nitems);
3119
3120 #ifdef HAVE_XCB_SHAPE
3121 bounding_rect_cookies
3122 = SAFE_ALLOCA (sizeof *bounding_rect_cookies * nitems);
3123 #endif
3124
3125 #ifdef HAVE_XCB_SHAPE_INPUT_RECTS
3126 input_rect_cookies
3127 = SAFE_ALLOCA (sizeof *input_rect_cookies * nitems);
3128 #endif
3129
3130 for (i = 0; i < nitems; ++i)
3131 {
3132 window_attribute_cookies[i]
3133 = xcb_get_window_attributes (dpyinfo->xcb_connection,
3134 (xcb_window_t) toplevels[i]);
3135 translate_coordinate_cookies[i]
3136 = xcb_translate_coordinates (dpyinfo->xcb_connection,
3137 (xcb_window_t) toplevels[i],
3138 (xcb_window_t) dpyinfo->root_window,
3139 0, 0);
3140 get_property_cookies[i]
3141 = xcb_get_property (dpyinfo->xcb_connection, 0, (xcb_window_t) toplevels[i],
3142 (xcb_atom_t) dpyinfo->Xatom_wm_state, 0,
3143 0, 2);
3144 xm_property_cookies[i]
3145 = xcb_get_property (dpyinfo->xcb_connection, 0, (xcb_window_t) toplevels[i],
3146 (xcb_atom_t) dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO,
3147 (xcb_atom_t) dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO,
3148 0, 4);
3149 extent_property_cookies[i]
3150 = xcb_get_property (dpyinfo->xcb_connection, 0,
3151 (xcb_window_t) toplevels[i],
3152 (xcb_atom_t) dpyinfo->Xatom_net_frame_extents,
3153 XA_CARDINAL, 0, 4);
3154 get_geometry_cookies[i]
3155 = xcb_get_geometry (dpyinfo->xcb_connection, (xcb_window_t) toplevels[i]);
3156
3157 #ifdef HAVE_XCB_SHAPE
3158 bounding_rect_cookies[i]
3159 = xcb_shape_get_rectangles (dpyinfo->xcb_connection,
3160 (xcb_window_t) toplevels[i],
3161 XCB_SHAPE_SK_BOUNDING);
3162 #endif
3163
3164 #ifdef HAVE_XCB_SHAPE_INPUT_RECTS
3165 if (dpyinfo->xshape_major > 1
3166 || (dpyinfo->xshape_major == 1
3167 && dpyinfo->xshape_minor >= 1))
3168 input_rect_cookies[i]
3169 = xcb_shape_get_rectangles (dpyinfo->xcb_connection,
3170 (xcb_window_t) toplevels[i],
3171 XCB_SHAPE_SK_INPUT);
3172 #endif
3173 }
3174 #endif
3175
3176
3177
3178 for (i = 0; i < nitems; ++i)
3179 {
3180 frame_extents[0] = 0;
3181 frame_extents[1] = 0;
3182 frame_extents[2] = 0;
3183 frame_extents[3] = 0;
3184
3185 #ifndef USE_XCB
3186 x_catch_errors (dpyinfo->display);
3187 rc = (XGetWindowAttributes (dpyinfo->display,
3188 toplevels[i], &attrs)
3189 && !x_had_errors_p (dpyinfo->display));
3190
3191 if (rc)
3192 rc = (XTranslateCoordinates (dpyinfo->display, toplevels[i],
3193 attrs.root, -attrs.border_width,
3194 -attrs.border_width, &dest_x,
3195 &dest_y, &child)
3196 && !x_had_errors_p (dpyinfo->display));
3197 if (rc)
3198 rc = ((XGetWindowProperty (dpyinfo->display,
3199 toplevels[i],
3200 dpyinfo->Xatom_wm_state,
3201 0, 2, False, AnyPropertyType,
3202 &type, &format, &wmstate_items,
3203 &bytes_after, &wmstate_data)
3204 == Success)
3205 && !x_had_errors_p (dpyinfo->display)
3206 && wmstate_data && wmstate_items == 2 && format == 32);
3207
3208 if (XGetWindowProperty (dpyinfo->display, toplevels[i],
3209 dpyinfo->Xatom_net_frame_extents,
3210 0, 4, False, XA_CARDINAL, &type,
3211 &format, &extent_items, &bytes_after,
3212 &extent_data) == Success
3213 && !x_had_errors_p (dpyinfo->display)
3214 && extent_data && extent_items >= 4 && format == 32)
3215 {
3216 frame_extents[0] = ((unsigned long *) extent_data)[0];
3217 frame_extents[1] = ((unsigned long *) extent_data)[1];
3218 frame_extents[2] = ((unsigned long *) extent_data)[2];
3219 frame_extents[3] = ((unsigned long *) extent_data)[3];
3220 }
3221
3222 if (extent_data)
3223 XFree (extent_data);
3224
3225 x_uncatch_errors ();
3226 #else
3227 rc = true;
3228
3229 attrs_reply
3230 = xcb_get_window_attributes_reply (dpyinfo->xcb_connection,
3231 window_attribute_cookies[i],
3232 &error);
3233
3234 if (!attrs_reply)
3235 {
3236 rc = false;
3237 free (error);
3238 }
3239
3240 coordinates_reply
3241 = xcb_translate_coordinates_reply (dpyinfo->xcb_connection,
3242 translate_coordinate_cookies[i],
3243 &error);
3244
3245 if (!coordinates_reply)
3246 {
3247 rc = false;
3248 free (error);
3249 }
3250
3251 property_reply = xcb_get_property_reply (dpyinfo->xcb_connection,
3252 get_property_cookies[i],
3253 &error);
3254
3255 if (!property_reply)
3256 {
3257 rc = false;
3258 free (error);
3259 }
3260
3261
3262
3263
3264 xm_property_reply = xcb_get_property_reply (dpyinfo->xcb_connection,
3265 xm_property_cookies[i],
3266 &error);
3267
3268 if (!xm_property_reply)
3269 free (error);
3270
3271 extent_property_reply
3272 = xcb_get_property_reply (dpyinfo->xcb_connection,
3273 extent_property_cookies[i],
3274 &error);
3275
3276 if (!extent_property_reply)
3277 free (error);
3278 else
3279 {
3280 if (xcb_get_property_value_length (extent_property_reply) == 16
3281 && extent_property_reply->format == 32
3282 && extent_property_reply->type == XA_CARDINAL)
3283 {
3284 fextents = xcb_get_property_value (extent_property_reply);
3285 frame_extents[0] = fextents[0];
3286 frame_extents[1] = fextents[1];
3287 frame_extents[2] = fextents[2];
3288 frame_extents[3] = fextents[3];
3289 }
3290
3291 free (extent_property_reply);
3292 }
3293
3294 if (property_reply
3295 && (xcb_get_property_value_length (property_reply) != 8
3296 || property_reply->format != 32))
3297 rc = false;
3298
3299 geometry_reply = xcb_get_geometry_reply (dpyinfo->xcb_connection,
3300 get_geometry_cookies[i],
3301 &error);
3302
3303 if (!geometry_reply)
3304 {
3305 rc = false;
3306 free (error);
3307 }
3308 #endif
3309
3310 if (rc)
3311 {
3312 #ifdef USE_XCB
3313 wmstate = (uint32_t *) xcb_get_property_value (property_reply);
3314 attrs = *attrs_reply;
3315 #else
3316 wmstate = (unsigned long *) wmstate_data;
3317 #endif
3318
3319 tem = xmalloc (sizeof *tem);
3320 tem->window = toplevels[i];
3321 tem->dpy = dpyinfo->display;
3322 tem->frame_extents_left = frame_extents[0];
3323 tem->frame_extents_right = frame_extents[1];
3324 tem->frame_extents_top = frame_extents[2];
3325 tem->frame_extents_bottom = frame_extents[3];
3326
3327 #ifndef USE_XCB
3328 tem->x = dest_x;
3329 tem->y = dest_y;
3330 tem->width = attrs.width + attrs.border_width;
3331 tem->height = attrs.height + attrs.border_width;
3332 tem->mapped_p = (attrs.map_state != IsUnmapped);
3333 #else
3334 tem->x = (coordinates_reply->dst_x
3335 - geometry_reply->border_width);
3336 tem->y = (coordinates_reply->dst_y
3337 - geometry_reply->border_width);
3338 tem->width = (geometry_reply->width
3339 + geometry_reply->border_width);
3340 tem->height = (geometry_reply->height
3341 + geometry_reply->border_width);
3342 tem->mapped_p = (attrs.map_state != XCB_MAP_STATE_UNMAPPED);
3343 #endif
3344 tem->next = x_dnd_toplevels;
3345 tem->previous_event_mask = attrs.your_event_mask;
3346 tem->wm_state = wmstate[0];
3347 tem->xm_protocol_style = XM_DRAG_STYLE_NONE;
3348
3349 #ifndef USE_XCB
3350 if (!xm_read_drag_receiver_info (dpyinfo, toplevels[i], &xm_info))
3351 tem->xm_protocol_style = xm_info.protocol_style;
3352 #else
3353 if (xm_property_reply
3354 && xm_property_reply->format == 8
3355 && (xm_property_reply->type
3356 == dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO)
3357 && xcb_get_property_value_length (xm_property_reply) >= 4)
3358 {
3359 xmdata = xcb_get_property_value (xm_property_reply);
3360
3361 if (xmdata[1] <= XM_DRAG_PROTOCOL_VERSION)
3362 tem->xm_protocol_style = xmdata[2];
3363 }
3364 #endif
3365
3366 #ifdef HAVE_XSHAPE
3367 #ifndef USE_XCB
3368 tem->border_width = attrs.border_width;
3369 #else
3370 tem->border_width = geometry_reply->border_width;
3371 #endif
3372 tem->n_bounding_rects = -1;
3373 tem->n_input_rects = -1;
3374
3375 if (dpyinfo->xshape_supported_p)
3376 {
3377 x_ignore_errors_for_next_request (dpyinfo, 0);
3378 XShapeSelectInput (dpyinfo->display,
3379 toplevels[i],
3380 ShapeNotifyMask);
3381 x_stop_ignoring_errors (dpyinfo);
3382
3383 #ifndef HAVE_XCB_SHAPE
3384 x_catch_errors (dpyinfo->display);
3385 rects = XShapeGetRectangles (dpyinfo->display,
3386 toplevels[i],
3387 ShapeBounding,
3388 &count, &ordering);
3389 rc = x_had_errors_p (dpyinfo->display);
3390 x_uncatch_errors_after_check ();
3391
3392
3393
3394 if (!rc)
3395 {
3396 tem->n_bounding_rects = count;
3397 tem->bounding_rects
3398 = xmalloc (sizeof *tem->bounding_rects * count);
3399 memcpy (tem->bounding_rects, rects,
3400 sizeof *tem->bounding_rects * count);
3401
3402 XFree (rects);
3403 }
3404 #else
3405 bounding_rect_reply
3406 = xcb_shape_get_rectangles_reply (dpyinfo->xcb_connection,
3407 bounding_rect_cookies[i],
3408 &error);
3409
3410 if (bounding_rect_reply)
3411 {
3412 bounding_rect_iterator
3413 = xcb_shape_get_rectangles_rectangles_iterator (bounding_rect_reply);
3414 tem->n_bounding_rects = bounding_rect_iterator.rem + 1;
3415 tem->bounding_rects = xmalloc (tem->n_bounding_rects
3416 * sizeof *tem->bounding_rects);
3417 tem->n_bounding_rects = 0;
3418
3419 for (; bounding_rect_iterator.rem;
3420 xcb_rectangle_next (&bounding_rect_iterator))
3421 {
3422 tem->bounding_rects[tem->n_bounding_rects].x
3423 = bounding_rect_iterator.data->x;
3424 tem->bounding_rects[tem->n_bounding_rects].y
3425 = bounding_rect_iterator.data->y;
3426 tem->bounding_rects[tem->n_bounding_rects].width
3427 = bounding_rect_iterator.data->width;
3428 tem->bounding_rects[tem->n_bounding_rects].height
3429 = bounding_rect_iterator.data->height;
3430
3431 tem->n_bounding_rects++;
3432 }
3433
3434 free (bounding_rect_reply);
3435 }
3436 else
3437 free (error);
3438 #endif
3439
3440 #ifdef HAVE_XCB_SHAPE_INPUT_RECTS
3441 if (dpyinfo->xshape_major > 1
3442 || (dpyinfo->xshape_major == 1
3443 && dpyinfo->xshape_minor >= 1))
3444 {
3445 input_rect_reply
3446 = xcb_shape_get_rectangles_reply (dpyinfo->xcb_connection,
3447 input_rect_cookies[i],
3448 &error);
3449
3450 if (input_rect_reply)
3451 {
3452 input_rect_iterator
3453 = xcb_shape_get_rectangles_rectangles_iterator (input_rect_reply);
3454 tem->n_input_rects = input_rect_iterator.rem + 1;
3455 tem->input_rects = xmalloc (tem->n_input_rects
3456 * sizeof *tem->input_rects);
3457 tem->n_input_rects = 0;
3458
3459 for (; input_rect_iterator.rem;
3460 xcb_rectangle_next (&input_rect_iterator))
3461 {
3462 tem->input_rects[tem->n_input_rects].x
3463 = input_rect_iterator.data->x;
3464 tem->input_rects[tem->n_input_rects].y
3465 = input_rect_iterator.data->y;
3466 tem->input_rects[tem->n_input_rects].width
3467 = input_rect_iterator.data->width;
3468 tem->input_rects[tem->n_input_rects].height
3469 = input_rect_iterator.data->height;
3470
3471 tem->n_input_rects++;
3472 }
3473
3474 free (input_rect_reply);
3475 }
3476 else
3477 free (error);
3478 }
3479 #else
3480 #ifdef ShapeInput
3481 if (dpyinfo->xshape_major > 1
3482 || (dpyinfo->xshape_major == 1
3483 && dpyinfo->xshape_minor >= 1))
3484 {
3485 x_catch_errors (dpyinfo->display);
3486 rects = XShapeGetRectangles (dpyinfo->display,
3487 toplevels[i], ShapeInput,
3488 &count, &ordering);
3489 rc = x_had_errors_p (dpyinfo->display);
3490 x_uncatch_errors_after_check ();
3491
3492
3493
3494 if (!rc)
3495 {
3496 tem->n_input_rects = count;
3497 tem->input_rects
3498 = xmalloc (sizeof *tem->input_rects * count);
3499 memcpy (tem->input_rects, rects,
3500 sizeof *tem->input_rects * count);
3501
3502 XFree (rects);
3503 }
3504 }
3505 #endif
3506 #endif
3507 }
3508
3509
3510
3511
3512 if (tem->n_input_rects != -1
3513 && tem->n_bounding_rects == tem->n_input_rects
3514 && !memcmp (tem->bounding_rects, tem->input_rects,
3515 tem->n_input_rects * sizeof *tem->input_rects))
3516 {
3517 xfree (tem->input_rects);
3518 tem->n_input_rects = -1;
3519 }
3520
3521
3522
3523
3524 if (tem->n_input_rects == -1
3525 && tem->n_bounding_rects == 1
3526 #ifdef USE_XCB
3527 && (tem->bounding_rects[0].width
3528 == (geometry_reply->width
3529 + geometry_reply->border_width))
3530 && (tem->bounding_rects[0].height
3531 == (geometry_reply->height
3532 + geometry_reply->border_width))
3533 && (tem->bounding_rects[0].x
3534 == -geometry_reply->border_width)
3535 && (tem->bounding_rects[0].y
3536 == -geometry_reply->border_width)
3537 #else
3538 && (tem->bounding_rects[0].width
3539 == attrs.width + attrs.border_width)
3540 && (tem->bounding_rects[0].height
3541 == attrs.height + attrs.border_width)
3542 && (tem->bounding_rects[0].x
3543 == -attrs.border_width)
3544 && (tem->bounding_rects[0].y
3545 == -attrs.border_width)
3546 #endif
3547 )
3548 {
3549 xfree (tem->bounding_rects);
3550 tem->n_bounding_rects = -1;
3551 }
3552 #endif
3553
3554 x_ignore_errors_for_next_request (dpyinfo, 0);
3555 XSelectInput (dpyinfo->display, toplevels[i],
3556 (attrs.your_event_mask
3557 | StructureNotifyMask
3558 | PropertyChangeMask));
3559 x_stop_ignoring_errors (dpyinfo);
3560
3561 x_dnd_toplevels = tem;
3562 }
3563 else
3564 {
3565 #ifdef HAVE_XCB_SHAPE
3566 if (dpyinfo->xshape_supported_p)
3567 {
3568 bounding_rect_reply
3569 = xcb_shape_get_rectangles_reply (dpyinfo->xcb_connection,
3570 bounding_rect_cookies[i],
3571 &error);
3572
3573 if (bounding_rect_reply)
3574 free (bounding_rect_reply);
3575 else
3576 free (error);
3577 }
3578 #endif
3579
3580 #ifdef HAVE_XCB_SHAPE_INPUT_RECTS
3581 if (dpyinfo->xshape_supported_p
3582 && (dpyinfo->xshape_major > 1
3583 || (dpyinfo->xshape_major == 1
3584 && dpyinfo->xshape_minor >= 1)))
3585 {
3586 input_rect_reply
3587 = xcb_shape_get_rectangles_reply (dpyinfo->xcb_connection,
3588 input_rect_cookies[i],
3589 &error);
3590
3591 if (input_rect_reply)
3592 free (input_rect_reply);
3593 else
3594 free (error);
3595 }
3596 #endif
3597 }
3598
3599 #ifdef USE_XCB
3600 if (attrs_reply)
3601 free (attrs_reply);
3602
3603 if (coordinates_reply)
3604 free (coordinates_reply);
3605
3606 if (property_reply)
3607 free (property_reply);
3608
3609 if (xm_property_reply)
3610 free (xm_property_reply);
3611
3612 if (geometry_reply)
3613 free (geometry_reply);
3614 #endif
3615
3616 #ifndef USE_XCB
3617 if (wmstate_data)
3618 {
3619 XFree (wmstate_data);
3620 wmstate_data = NULL;
3621 }
3622 #endif
3623 }
3624
3625 #ifdef USE_XCB
3626 SAFE_FREE ();
3627 #endif
3628
3629 if (data)
3630 XFree (data);
3631
3632 return 0;
3633 }
3634
3635 static _Noreturn int
3636 x_dnd_io_error_handler (Display *display)
3637 {
3638 #ifdef USE_GTK
3639 emacs_abort ();
3640 #else
3641 siglongjmp (x_dnd_disconnect_handler, 1);
3642 #endif
3643 }
3644
3645 #define X_DND_SUPPORTED_VERSION 5
3646
3647 static int x_dnd_get_window_proto (struct x_display_info *, Window);
3648 static Window x_dnd_get_window_proxy (struct x_display_info *, Window);
3649 static void x_dnd_update_state (struct x_display_info *, Time);
3650
3651 #ifdef USE_XCB
3652 static void
3653 x_dnd_get_proxy_proto (struct x_display_info *dpyinfo, Window wdesc,
3654 Window *proxy_out, int *proto_out)
3655 {
3656 xcb_get_property_cookie_t xdnd_proto_cookie;
3657 xcb_get_property_cookie_t xdnd_proxy_cookie;
3658 xcb_get_property_reply_t *reply;
3659 xcb_generic_error_t *error;
3660
3661 if (proxy_out)
3662 *proxy_out = None;
3663
3664 if (proto_out)
3665 *proto_out = -1;
3666
3667 if (proxy_out)
3668 xdnd_proxy_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
3669 (xcb_window_t) wdesc,
3670 (xcb_atom_t) dpyinfo->Xatom_XdndProxy,
3671 XA_WINDOW, 0, 1);
3672
3673 if (proto_out)
3674 xdnd_proto_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
3675 (xcb_window_t) wdesc,
3676 (xcb_atom_t) dpyinfo->Xatom_XdndAware,
3677 XA_ATOM, 0, 1);
3678
3679 if (proxy_out)
3680 {
3681 reply = xcb_get_property_reply (dpyinfo->xcb_connection,
3682 xdnd_proxy_cookie, &error);
3683
3684 if (!reply)
3685 free (error);
3686 else
3687 {
3688 if (reply->format == 32
3689 && reply->type == XA_WINDOW
3690 && (xcb_get_property_value_length (reply) >= 4))
3691 *proxy_out = *(xcb_window_t *) xcb_get_property_value (reply);
3692
3693 free (reply);
3694 }
3695 }
3696
3697 if (proto_out)
3698 {
3699 reply = xcb_get_property_reply (dpyinfo->xcb_connection,
3700 xdnd_proto_cookie, &error);
3701
3702 if (!reply)
3703 free (error);
3704 else
3705 {
3706 if (reply->format == 32
3707 && reply->type == XA_ATOM
3708 && (xcb_get_property_value_length (reply) >= 4))
3709 *proto_out = (int) *(xcb_atom_t *) xcb_get_property_value (reply);
3710
3711 free (reply);
3712 }
3713 }
3714 }
3715 #endif
3716
3717 #ifdef HAVE_XSHAPE
3718 static bool
3719 x_dnd_get_target_window_2 (XRectangle *rects, int nrects,
3720 int x, int y)
3721 {
3722 int i;
3723 XRectangle *tem;
3724
3725 for (i = 0; i < nrects; ++i)
3726 {
3727 tem = &rects[i];
3728
3729 if (x >= tem->x && y >= tem->y
3730 && x < tem->x + tem->width
3731 && y < tem->y + tem->height)
3732 return true;
3733 }
3734
3735 return false;
3736 }
3737 #endif
3738
3739 static Window
3740 x_dnd_get_target_window_1 (struct x_display_info *dpyinfo,
3741 int root_x, int root_y, int *motif_out,
3742 bool *extents_p)
3743 {
3744 struct x_client_list_window *tem, *chosen = NULL;
3745
3746
3747
3748
3749 *motif_out = XM_DRAG_STYLE_NONE;
3750
3751 for (tem = x_dnd_toplevels; tem; tem = tem->next)
3752 {
3753 if (!tem->mapped_p || tem->wm_state != NormalState)
3754 continue;
3755
3756
3757
3758
3759 *extents_p = true;
3760 if (root_x > tem->x - tem->frame_extents_left
3761 && root_x < tem->x
3762 && root_y > tem->y - tem->frame_extents_top
3763 && root_y < (tem->y + tem->height - 1
3764 + tem->frame_extents_bottom))
3765 return None;
3766
3767 if (root_x > tem->x + tem->width
3768 && root_x < (tem->x + tem->width - 1
3769 + tem->frame_extents_right)
3770 && root_y > tem->y - tem->frame_extents_top
3771 && root_y < (tem->y + tem->height - 1
3772 + tem->frame_extents_bottom))
3773 return None;
3774
3775 if (root_y > tem->y - tem->frame_extents_top
3776 && root_y < tem->y
3777 && root_x > tem->x - tem->frame_extents_left
3778 && root_x < (tem->x + tem->width - 1
3779 + tem->frame_extents_right))
3780 return None;
3781
3782 if (root_y > tem->y + tem->height
3783 && root_y < (tem->y + tem->height - 1
3784 + tem->frame_extents_bottom)
3785 && root_x >= tem->x - tem->frame_extents_left
3786 && root_x < (tem->x + tem->width - 1
3787 + tem->frame_extents_right))
3788 return None;
3789 *extents_p = false;
3790
3791 if (root_x >= tem->x && root_y >= tem->y
3792 && root_x < tem->x + tem->width
3793 && root_y < tem->y + tem->height)
3794 {
3795 #ifdef HAVE_XSHAPE
3796 if (tem->n_bounding_rects == -1)
3797 #endif
3798 {
3799 chosen = tem;
3800 break;
3801 }
3802
3803 #ifdef HAVE_XSHAPE
3804 if (x_dnd_get_target_window_2 (tem->bounding_rects,
3805 tem->n_bounding_rects,
3806 tem->border_width + root_x - tem->x,
3807 tem->border_width + root_y - tem->y))
3808 {
3809 if (tem->n_input_rects == -1
3810 || x_dnd_get_target_window_2 (tem->input_rects,
3811 tem->n_input_rects,
3812 (tem->border_width
3813 + root_x - tem->x),
3814 (tem->border_width
3815 + root_y - tem->y)))
3816 {
3817 chosen = tem;
3818 break;
3819 }
3820 }
3821 #endif
3822 }
3823 }
3824
3825 if (chosen)
3826 {
3827 *motif_out = (x_dnd_disable_motif_protocol
3828 ? XM_DRAG_STYLE_NONE
3829 : chosen->xm_protocol_style);
3830 return chosen->window;
3831 }
3832 else
3833 *motif_out = XM_DRAG_STYLE_NONE;
3834
3835 return None;
3836 }
3837
3838 static int
3839 x_dnd_get_wm_state_and_proto (struct x_display_info *dpyinfo,
3840 Window window, int *wmstate_out,
3841 int *proto_out, int *motif_out,
3842 Window *proxy_out)
3843 {
3844 #ifndef USE_XCB
3845 Atom type;
3846 int format;
3847 unsigned long nitems, bytes_after;
3848 unsigned char *data = NULL;
3849 xm_drag_receiver_info xm_info;
3850 #else
3851 xcb_get_property_cookie_t wmstate_cookie;
3852 xcb_get_property_cookie_t xdnd_proto_cookie;
3853 xcb_get_property_cookie_t xdnd_proxy_cookie;
3854 xcb_get_property_cookie_t xm_style_cookie;
3855 xcb_get_property_reply_t *reply;
3856 xcb_generic_error_t *error;
3857 uint8_t *xmdata;
3858 #endif
3859 int rc;
3860
3861 #ifndef USE_XCB
3862 x_catch_errors (dpyinfo->display);
3863 rc = ((XGetWindowProperty (dpyinfo->display, window,
3864 dpyinfo->Xatom_wm_state,
3865 0, 2, False, AnyPropertyType,
3866 &type, &format, &nitems,
3867 &bytes_after, &data)
3868 == Success)
3869 && !x_had_errors_p (dpyinfo->display)
3870 && data && nitems == 2 && format == 32);
3871 x_uncatch_errors ();
3872
3873 if (rc)
3874 *wmstate_out = *(unsigned long *) data;
3875
3876 *proto_out = x_dnd_get_window_proto (dpyinfo, window);
3877
3878 if (!xm_read_drag_receiver_info (dpyinfo, window, &xm_info))
3879 *motif_out = xm_info.protocol_style;
3880 else
3881 *motif_out = XM_DRAG_STYLE_NONE;
3882
3883 *proxy_out = x_dnd_get_window_proxy (dpyinfo, window);
3884
3885 if (data)
3886 XFree (data);
3887 #else
3888 rc = true;
3889
3890 wmstate_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
3891 (xcb_window_t) window,
3892 (xcb_atom_t) dpyinfo->Xatom_wm_state,
3893 0, 0, 2);
3894 xdnd_proto_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
3895 (xcb_window_t) window,
3896 (xcb_atom_t) dpyinfo->Xatom_XdndAware,
3897 XA_ATOM, 0, 1);
3898 xdnd_proxy_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
3899 (xcb_window_t) window,
3900 (xcb_atom_t) dpyinfo->Xatom_XdndProxy,
3901 XA_WINDOW, 0, 1);
3902 xm_style_cookie
3903 = xcb_get_property (dpyinfo->xcb_connection, 0,
3904 (xcb_window_t) window,
3905 (xcb_atom_t) dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO,
3906 (xcb_atom_t) dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO,
3907 0, 4);
3908
3909 reply = xcb_get_property_reply (dpyinfo->xcb_connection,
3910 wmstate_cookie, &error);
3911
3912 if (!reply)
3913 free (error), rc = false;
3914 else
3915 {
3916 if (reply->format != 32
3917 || xcb_get_property_value_length (reply) != 8)
3918 rc = false;
3919 else
3920 *wmstate_out = *(uint32_t *) xcb_get_property_value (reply);
3921
3922 free (reply);
3923 }
3924
3925 reply = xcb_get_property_reply (dpyinfo->xcb_connection,
3926 xdnd_proto_cookie, &error);
3927
3928 *proto_out = -1;
3929 if (!reply)
3930 free (error);
3931 else
3932 {
3933 if (reply->format == 32
3934 && xcb_get_property_value_length (reply) >= 4)
3935 *proto_out = *(uint32_t *) xcb_get_property_value (reply);
3936
3937 free (reply);
3938 }
3939
3940 *proxy_out = None;
3941 reply = xcb_get_property_reply (dpyinfo->xcb_connection,
3942 xdnd_proxy_cookie, &error);
3943
3944 if (!reply)
3945 free (error);
3946 else
3947 {
3948 if (reply->format == 32
3949 && reply->type == XA_WINDOW
3950 && (xcb_get_property_value_length (reply) >= 4))
3951 *proxy_out = *(xcb_window_t *) xcb_get_property_value (reply);
3952
3953 free (reply);
3954 }
3955
3956 *motif_out = XM_DRAG_STYLE_NONE;
3957
3958 reply = xcb_get_property_reply (dpyinfo->xcb_connection,
3959 xm_style_cookie, &error);
3960
3961 if (!reply)
3962 free (error);
3963 else
3964 {
3965 if (reply->format == 8
3966 && reply->type == dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO
3967 && xcb_get_property_value_length (reply) >= 4)
3968 {
3969 xmdata = xcb_get_property_value (reply);
3970 *motif_out = xmdata[2];
3971 }
3972
3973 free (reply);
3974 }
3975 #endif
3976
3977 return rc;
3978 }
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004 void
4005 x_dnd_do_unsupported_drop (struct x_display_info *dpyinfo,
4006 Lisp_Object frame, Lisp_Object value,
4007 Lisp_Object targets, Window target_window,
4008 int root_x, int root_y, Time before)
4009 {
4010 XEvent event;
4011 int dest_x, dest_y;
4012 Window child_return, child, owner;
4013 Lisp_Object current_value;
4014 struct frame *f;
4015
4016 f = decode_window_system_frame (frame);
4017
4018 if (NILP (value))
4019 return;
4020
4021 if (!x_dnd_use_unsupported_drop)
4022 return;
4023
4024 event.xbutton.serial = 0;
4025 event.xbutton.send_event = True;
4026 event.xbutton.display = dpyinfo->display;
4027 event.xbutton.root = dpyinfo->root_window;
4028 event.xbutton.x_root = root_x;
4029 event.xbutton.y_root = root_y;
4030
4031 x_catch_errors (dpyinfo->display);
4032
4033 child = dpyinfo->root_window;
4034 dest_x = root_x;
4035 dest_y = root_y;
4036
4037 while (XTranslateCoordinates (dpyinfo->display, dpyinfo->root_window,
4038 child, root_x, root_y, &dest_x, &dest_y,
4039 &child_return)
4040 && child_return != None)
4041 child = child_return;
4042
4043 x_uncatch_errors ();
4044
4045 if (!CONSP (value))
4046 return;
4047
4048 current_value = assq_no_quit (QPRIMARY,
4049 dpyinfo->terminal->Vselection_alist);
4050
4051 if (!NILP (current_value))
4052 current_value = XCAR (XCDR (current_value));
4053
4054 x_own_selection (QPRIMARY, current_value, frame,
4055 XCAR (XCDR (value)), before);
4056
4057 owner = XGetSelectionOwner (dpyinfo->display, XA_PRIMARY);
4058
4059
4060
4061
4062 if (owner != FRAME_X_WINDOW (f))
4063 return;
4064
4065
4066
4067
4068
4069 Vdeactivate_mark = Qdont_save;
4070
4071 event.xbutton.window = child;
4072 event.xbutton.subwindow = None;
4073 event.xbutton.x = dest_x;
4074 event.xbutton.y = dest_y;
4075 event.xbutton.state = 0;
4076 event.xbutton.button = 2;
4077 event.xbutton.same_screen = True;
4078
4079 dpyinfo->pending_dnd_time = before;
4080
4081 event.xbutton.type = ButtonPress;
4082 event.xbutton.time = before + 1;
4083
4084 x_ignore_errors_for_next_request (dpyinfo, 0);
4085 XSendEvent (dpyinfo->display, child,
4086 True, ButtonPressMask, &event);
4087
4088 event.xbutton.type = ButtonRelease;
4089 event.xbutton.time = before + 2;
4090
4091 XSendEvent (dpyinfo->display, child,
4092 True, ButtonReleaseMask, &event);
4093 x_stop_ignoring_errors (dpyinfo);
4094
4095 x_dnd_action_symbol = QXdndActionPrivate;
4096
4097 return;
4098 }
4099
4100 static void
4101 x_dnd_send_unsupported_drop (struct x_display_info *dpyinfo, Window target_window,
4102 int root_x, int root_y, Time before)
4103 {
4104 Lisp_Object targets, arg;
4105 int i;
4106 char **atom_names, *name;
4107
4108 targets = Qnil;
4109 atom_names = alloca (sizeof *atom_names * x_dnd_n_targets);
4110
4111 if (!XGetAtomNames (dpyinfo->display, x_dnd_targets,
4112 x_dnd_n_targets, atom_names))
4113 return;
4114
4115 for (i = x_dnd_n_targets; i > 0; --i)
4116 {
4117 targets = Fcons (build_string (atom_names[i - 1]),
4118 targets);
4119 XFree (atom_names[i - 1]);
4120 }
4121
4122 name = x_get_atom_name (dpyinfo, x_dnd_wanted_action,
4123 NULL);
4124
4125 if (name)
4126 {
4127 arg = intern (name);
4128 xfree (name);
4129 }
4130 else
4131 arg = Qnil;
4132
4133 x_dnd_run_unsupported_drop_function = true;
4134 x_dnd_unsupported_drop_time = before;
4135 x_dnd_unsupported_drop_window = target_window;
4136 x_dnd_unsupported_drop_data
4137 = listn (5, assq_no_quit (QXdndSelection,
4138 dpyinfo->terminal->Vselection_alist),
4139 targets, arg, make_fixnum (root_x),
4140 make_fixnum (root_y));
4141
4142 x_dnd_waiting_for_finish = true;
4143 x_dnd_finish_display = dpyinfo->display;
4144 }
4145
4146 static Window
4147 x_dnd_fill_empty_target (int *proto_out, int *motif_out,
4148 Window *toplevel_out, bool *was_frame)
4149 {
4150 *proto_out = -1;
4151 *motif_out = XM_DRAG_STYLE_NONE;
4152 *toplevel_out = None;
4153 *was_frame = false;
4154
4155 return None;
4156 }
4157
4158 static Window
4159 x_dnd_get_target_window (struct x_display_info *dpyinfo,
4160 int root_x, int root_y, int *proto_out,
4161 int *motif_out, Window *toplevel_out,
4162 bool *was_frame)
4163 {
4164 Window child_return, child, proxy;
4165 int dest_x_return, dest_y_return, rc, proto, motif;
4166 int parent_x, parent_y;
4167 bool extents_p;
4168 #if defined HAVE_XCOMPOSITE && (XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR > 2)
4169 Window overlay_window;
4170 XWindowAttributes attrs;
4171 #endif
4172 int wmstate;
4173 struct frame *tooltip, *f;
4174 bool unrelated;
4175
4176 child_return = dpyinfo->root_window;
4177 dest_x_return = root_x;
4178 dest_y_return = root_y;
4179
4180 proto = -1;
4181 *motif_out = XM_DRAG_STYLE_NONE;
4182 *toplevel_out = None;
4183 *was_frame = false;
4184
4185 if (x_dnd_use_toplevels)
4186 {
4187 extents_p = false;
4188 child = x_dnd_get_target_window_1 (dpyinfo, root_x,
4189 root_y, motif_out,
4190 &extents_p);
4191
4192 if (!x_dnd_allow_current_frame
4193 && FRAME_X_WINDOW (x_dnd_frame) == child)
4194 *motif_out = XM_DRAG_STYLE_NONE;
4195
4196 f = x_top_window_to_frame (dpyinfo, child);
4197
4198 *toplevel_out = child;
4199
4200 if (child != None)
4201 {
4202 if (f)
4203 {
4204 *was_frame = true;
4205 *proto_out = -1;
4206 *motif_out = XM_DRAG_STYLE_NONE;
4207
4208 return child;
4209 }
4210
4211 #ifndef USE_XCB
4212 proxy = x_dnd_get_window_proxy (dpyinfo, child);
4213 #else
4214 x_dnd_get_proxy_proto (dpyinfo, child, &proxy, proto_out);
4215 #endif
4216
4217 if (proxy != None)
4218 {
4219 proto = x_dnd_get_window_proto (dpyinfo, proxy);
4220
4221 if (proto != -1)
4222 {
4223 *proto_out = proto;
4224 return proxy;
4225 }
4226 }
4227
4228 #ifndef USE_XCB
4229 *proto_out = x_dnd_get_window_proto (dpyinfo, child);
4230 #endif
4231 return child;
4232 }
4233
4234 if (extents_p)
4235 {
4236 *proto_out = -1;
4237 *motif_out = XM_DRAG_STYLE_NONE;
4238 *toplevel_out = None;
4239
4240 return None;
4241 }
4242
4243
4244 #if defined HAVE_XCOMPOSITE && (XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR > 2)
4245 if (dpyinfo->composite_supported_p
4246 && (dpyinfo->composite_major > 0
4247 || dpyinfo->composite_minor > 2))
4248 {
4249 if (XGetSelectionOwner (dpyinfo->display,
4250 dpyinfo->Xatom_NET_WM_CM_Sn) != None)
4251 {
4252 x_catch_errors (dpyinfo->display);
4253 XGrabServer (dpyinfo->display);
4254 overlay_window = XCompositeGetOverlayWindow (dpyinfo->display,
4255 dpyinfo->root_window);
4256 XCompositeReleaseOverlayWindow (dpyinfo->display,
4257 dpyinfo->root_window);
4258 XUngrabServer (dpyinfo->display);
4259
4260 if (!x_had_errors_p (dpyinfo->display))
4261 {
4262 XGetWindowAttributes (dpyinfo->display, overlay_window, &attrs);
4263
4264 if (attrs.map_state == IsViewable)
4265 {
4266 proxy = x_dnd_get_window_proxy (dpyinfo, overlay_window);
4267
4268 if (proxy != None)
4269 {
4270 proto = x_dnd_get_window_proto (dpyinfo, proxy);
4271
4272 if (proto != -1)
4273 {
4274 *proto_out = proto;
4275 *toplevel_out = overlay_window;
4276 x_uncatch_errors_after_check ();
4277
4278 return proxy;
4279 }
4280 }
4281 }
4282 }
4283 x_uncatch_errors_after_check ();
4284 }
4285 }
4286 #endif
4287
4288
4289
4290 proxy = x_dnd_get_window_proxy (dpyinfo, dpyinfo->root_window);
4291
4292 if (proxy != None)
4293 {
4294 proto = x_dnd_get_window_proto (dpyinfo, dpyinfo->root_window);
4295
4296 if (proto != -1)
4297 {
4298 *toplevel_out = dpyinfo->root_window;
4299 *proto_out = proto;
4300 return proxy;
4301 }
4302 }
4303
4304
4305
4306 *proto_out = -1;
4307 *toplevel_out = dpyinfo->root_window;
4308 return None;
4309 }
4310
4311
4312 child = dpyinfo->root_window;
4313
4314 while (child_return != None)
4315 {
4316 child = child_return;
4317 parent_x = dest_x_return;
4318 parent_y = dest_y_return;
4319
4320 x_catch_errors (dpyinfo->display);
4321 rc = XTranslateCoordinates (dpyinfo->display, dpyinfo->root_window,
4322 child_return, root_x, root_y, &dest_x_return,
4323 &dest_y_return, &child_return);
4324
4325 if (x_had_errors_p (dpyinfo->display) || !rc)
4326 {
4327 x_uncatch_errors_after_check ();
4328 break;
4329 }
4330
4331 if (child_return)
4332 {
4333
4334
4335
4336 tooltip = x_tooltip_window_to_frame (dpyinfo, child_return,
4337 &unrelated);
4338
4339 if (tooltip || unrelated)
4340 child_return = x_get_window_below (dpyinfo->display, child_return,
4341 parent_x, parent_y, &dest_x_return,
4342 &dest_y_return);
4343
4344 if (!child_return)
4345 {
4346 x_uncatch_errors ();
4347 break;
4348 }
4349
4350 f = x_top_window_to_frame (dpyinfo, child_return);
4351
4352 if (f)
4353 {
4354 *proto_out = -1;
4355 *motif_out = XM_DRAG_STYLE_NONE;
4356 *toplevel_out = child_return;
4357 *was_frame = true;
4358
4359 return child_return;
4360 }
4361
4362 if (x_dnd_get_wm_state_and_proto (dpyinfo, child_return,
4363 &wmstate, &proto, &motif,
4364 &proxy)
4365
4366
4367 || proto != -1 || motif != XM_DRAG_STYLE_NONE)
4368 {
4369 *proto_out = proto;
4370 *motif_out = (x_dnd_disable_motif_protocol
4371 ? XM_DRAG_STYLE_NONE : motif);
4372 *toplevel_out = child_return;
4373 x_uncatch_errors ();
4374
4375 return child_return;
4376 }
4377
4378 if (proxy != None)
4379 {
4380 proto = x_dnd_get_window_proto (dpyinfo, proxy);
4381
4382 if (proto != -1)
4383 {
4384 *proto_out = proto;
4385 *toplevel_out = child_return;
4386
4387 x_uncatch_errors ();
4388 return proxy;
4389 }
4390 }
4391 }
4392
4393 x_uncatch_errors ();
4394 }
4395
4396 #if defined HAVE_XCOMPOSITE && (XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR > 2)
4397 if (child != dpyinfo->root_window)
4398 {
4399 #endif
4400 if (child != None)
4401 {
4402 proxy = x_dnd_get_window_proxy (dpyinfo, child);
4403
4404 if (proxy)
4405 {
4406 proto = x_dnd_get_window_proto (dpyinfo, proxy);
4407
4408 if (proto != -1)
4409 {
4410 *proto_out = proto;
4411 *toplevel_out = child;
4412 return proxy;
4413 }
4414 }
4415 }
4416
4417 *proto_out = x_dnd_get_window_proto (dpyinfo, child);
4418 return child;
4419 #if defined HAVE_XCOMPOSITE && (XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR > 2)
4420 }
4421 else if (dpyinfo->composite_supported_p
4422 && (dpyinfo->composite_major > 0
4423 || dpyinfo->composite_minor > 2))
4424 {
4425
4426 if (XGetSelectionOwner (dpyinfo->display,
4427 dpyinfo->Xatom_NET_WM_CM_Sn) != None)
4428 {
4429 x_catch_errors (dpyinfo->display);
4430 XGrabServer (dpyinfo->display);
4431 overlay_window = XCompositeGetOverlayWindow (dpyinfo->display,
4432 dpyinfo->root_window);
4433 XCompositeReleaseOverlayWindow (dpyinfo->display,
4434 dpyinfo->root_window);
4435 XUngrabServer (dpyinfo->display);
4436
4437 if (!x_had_errors_p (dpyinfo->display))
4438 {
4439 XGetWindowAttributes (dpyinfo->display, overlay_window, &attrs);
4440
4441 if (attrs.map_state == IsViewable)
4442 {
4443 proxy = x_dnd_get_window_proxy (dpyinfo, overlay_window);
4444
4445 if (proxy != None)
4446 {
4447 proto = x_dnd_get_window_proto (dpyinfo, proxy);
4448
4449 if (proto != -1)
4450 {
4451 *proto_out = proto;
4452 *toplevel_out = overlay_window;
4453 x_uncatch_errors_after_check ();
4454
4455 return proxy;
4456 }
4457 }
4458 }
4459 }
4460 x_uncatch_errors_after_check ();
4461 }
4462 }
4463
4464 if (child != None)
4465 {
4466 proxy = x_dnd_get_window_proxy (dpyinfo, child);
4467
4468 if (proxy)
4469 {
4470 proto = x_dnd_get_window_proto (dpyinfo, proxy);
4471
4472 if (proto != -1)
4473 {
4474 *toplevel_out = child;
4475 *proto_out = proto;
4476 return proxy;
4477 }
4478 }
4479 }
4480
4481 *proto_out = x_dnd_get_window_proto (dpyinfo, child);
4482 *toplevel_out = child;
4483 return child;
4484 #endif
4485 }
4486
4487 static Window
4488 x_dnd_get_window_proxy (struct x_display_info *dpyinfo, Window wdesc)
4489 {
4490 int rc, actual_format;
4491 unsigned long actual_size, bytes_remaining;
4492 unsigned char *tmp_data = NULL;
4493 XWindowAttributes attrs;
4494 Atom actual_type;
4495 Window proxy;
4496
4497 proxy = None;
4498 x_catch_errors (dpyinfo->display);
4499 rc = XGetWindowProperty (dpyinfo->display, wdesc,
4500 dpyinfo->Xatom_XdndProxy,
4501 0, 1, False, XA_WINDOW,
4502 &actual_type, &actual_format,
4503 &actual_size, &bytes_remaining,
4504 &tmp_data);
4505
4506 if (!x_had_errors_p (dpyinfo->display)
4507 && rc == Success
4508 && tmp_data
4509 && actual_type == XA_WINDOW
4510 && actual_format == 32
4511 && actual_size == 1)
4512 {
4513 proxy = *(Window *) tmp_data;
4514
4515
4516 XGetWindowAttributes (dpyinfo->display, proxy, &attrs);
4517
4518 if (x_had_errors_p (dpyinfo->display))
4519 proxy = None;
4520 }
4521
4522 if (tmp_data)
4523 XFree (tmp_data);
4524 x_uncatch_errors_after_check ();
4525
4526 return proxy;
4527 }
4528
4529 static int
4530 x_dnd_get_window_proto (struct x_display_info *dpyinfo, Window wdesc)
4531 {
4532 Atom actual, value;
4533 unsigned char *tmp_data = NULL;
4534 int rc, format;
4535 unsigned long n, left;
4536 bool had_errors;
4537
4538 if (wdesc == None || (!x_dnd_allow_current_frame
4539 && wdesc == FRAME_OUTER_WINDOW (x_dnd_frame)))
4540 return -1;
4541
4542 x_catch_errors (dpyinfo->display);
4543 rc = XGetWindowProperty (dpyinfo->display, wdesc, dpyinfo->Xatom_XdndAware,
4544 0, 1, False, XA_ATOM, &actual, &format, &n, &left,
4545 &tmp_data);
4546 had_errors = x_had_errors_p (dpyinfo->display);
4547 x_uncatch_errors_after_check ();
4548
4549 if (had_errors || rc != Success || actual != XA_ATOM || format != 32 || n < 1
4550 || !tmp_data)
4551 {
4552 if (tmp_data)
4553 XFree (tmp_data);
4554 return -1;
4555 }
4556
4557 value = (int) *(Atom *) tmp_data;
4558 XFree (tmp_data);
4559
4560 return min (X_DND_SUPPORTED_VERSION, (int) value);
4561 }
4562
4563 static void
4564 x_dnd_send_enter (struct frame *f, Window target, Window toplevel,
4565 int supported)
4566 {
4567 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
4568 int i;
4569 XEvent msg;
4570
4571 msg.xclient.type = ClientMessage;
4572 msg.xclient.message_type = dpyinfo->Xatom_XdndEnter;
4573 msg.xclient.format = 32;
4574 msg.xclient.window = toplevel;
4575 msg.xclient.data.l[0] = FRAME_X_WINDOW (f);
4576 msg.xclient.data.l[1] = (((unsigned int) min (X_DND_SUPPORTED_VERSION,
4577 supported) << 24)
4578 | (x_dnd_n_targets > 3 ? 1 : 0));
4579 msg.xclient.data.l[2] = 0;
4580 msg.xclient.data.l[3] = 0;
4581 msg.xclient.data.l[4] = 0;
4582
4583 for (i = 0; i < min (3, x_dnd_n_targets); ++i)
4584 msg.xclient.data.l[i + 2] = x_dnd_targets[i];
4585
4586 if (x_dnd_n_targets > 3 && !x_dnd_init_type_lists)
4587 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4588 dpyinfo->Xatom_XdndTypeList, XA_ATOM, 32,
4589 PropModeReplace, (unsigned char *) x_dnd_targets,
4590 x_dnd_n_targets);
4591
4592
4593
4594 x_dnd_init_type_lists = true;
4595
4596 x_ignore_errors_for_next_request (dpyinfo, 0);
4597 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
4598 x_stop_ignoring_errors (dpyinfo);
4599 }
4600
4601 static void
4602 x_dnd_send_position (struct frame *f, Window target, Window toplevel,
4603 int supported, unsigned short root_x,
4604 unsigned short root_y, Time timestamp, Atom action,
4605 int button, unsigned state)
4606 {
4607 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
4608 XEvent msg;
4609
4610 msg.xclient.type = ClientMessage;
4611 msg.xclient.message_type = dpyinfo->Xatom_XdndPosition;
4612 msg.xclient.format = 32;
4613 msg.xclient.window = toplevel;
4614 msg.xclient.data.l[0] = FRAME_X_WINDOW (f);
4615 msg.xclient.data.l[1] = 0;
4616
4617
4618
4619
4620
4621
4622
4623 if (button >= 4 && button <= 7)
4624 {
4625 msg.xclient.data.l[1] |= (1 << 10);
4626 msg.xclient.data.l[1] |= (button - 4) << 8;
4627 }
4628 else if (button)
4629 return;
4630
4631 msg.xclient.data.l[1] |= state & 0xff;
4632
4633 msg.xclient.data.l[2] = (root_x << 16) | root_y;
4634 msg.xclient.data.l[3] = 0;
4635 msg.xclient.data.l[4] = 0;
4636
4637 if (supported >= 3)
4638 msg.xclient.data.l[3] = timestamp;
4639
4640 if (supported >= 4)
4641 msg.xclient.data.l[4] = action;
4642
4643 if (x_dnd_waiting_for_status_window == target)
4644 {
4645 x_dnd_pending_send_position = msg;
4646 x_dnd_pending_send_position_button = button;
4647 x_dnd_pending_send_position_root_x = root_x;
4648 x_dnd_pending_send_position_root_y = root_y;
4649 }
4650 else
4651 {
4652 if (target == x_dnd_mouse_rect_target
4653 && x_dnd_mouse_rect.width
4654 && x_dnd_mouse_rect.height
4655
4656
4657 && !button)
4658 {
4659 if (root_x >= x_dnd_mouse_rect.x
4660 && root_x < (x_dnd_mouse_rect.x
4661 + x_dnd_mouse_rect.width)
4662 && root_y >= x_dnd_mouse_rect.y
4663 && root_y < (x_dnd_mouse_rect.y
4664 + x_dnd_mouse_rect.height))
4665 return;
4666 }
4667
4668 x_ignore_errors_for_next_request (dpyinfo, 0);
4669 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
4670 x_stop_ignoring_errors (dpyinfo);
4671
4672 x_dnd_waiting_for_status_window = target;
4673 }
4674 }
4675
4676 static void
4677 x_dnd_send_leave (struct frame *f, Window target, Window toplevel)
4678 {
4679 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
4680 XEvent msg;
4681
4682 msg.xclient.type = ClientMessage;
4683 msg.xclient.message_type = dpyinfo->Xatom_XdndLeave;
4684 msg.xclient.format = 32;
4685 msg.xclient.window = toplevel;
4686 msg.xclient.data.l[0] = FRAME_X_WINDOW (f);
4687 msg.xclient.data.l[1] = 0;
4688 msg.xclient.data.l[2] = 0;
4689 msg.xclient.data.l[3] = 0;
4690 msg.xclient.data.l[4] = 0;
4691
4692 x_dnd_waiting_for_status_window = None;
4693 x_dnd_pending_send_position.type = 0;
4694
4695 x_ignore_errors_for_next_request (dpyinfo, 0);
4696 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
4697 x_stop_ignoring_errors (dpyinfo);
4698 }
4699
4700 static bool
4701 x_dnd_send_drop (struct frame *f, Window target, Window toplevel,
4702 Time timestamp, int supported)
4703 {
4704 struct x_display_info *dpyinfo;
4705 XEvent msg;
4706
4707 if (x_dnd_action == None)
4708 {
4709 x_dnd_send_leave (f, target, toplevel);
4710 return false;
4711 }
4712
4713 dpyinfo = FRAME_DISPLAY_INFO (f);
4714
4715 msg.xclient.type = ClientMessage;
4716 msg.xclient.message_type = dpyinfo->Xatom_XdndDrop;
4717 msg.xclient.format = 32;
4718 msg.xclient.window = toplevel;
4719 msg.xclient.data.l[0] = FRAME_X_WINDOW (f);
4720 msg.xclient.data.l[1] = 0;
4721 msg.xclient.data.l[2] = 0;
4722 msg.xclient.data.l[3] = 0;
4723 msg.xclient.data.l[4] = 0;
4724
4725 if (supported >= 1)
4726 msg.xclient.data.l[2] = timestamp;
4727
4728 x_ignore_errors_for_next_request (dpyinfo, 0);
4729 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
4730 x_stop_ignoring_errors (dpyinfo);
4731 return true;
4732 }
4733
4734 static bool
4735 x_dnd_do_drop (Window target, Window toplevel, int supported)
4736 {
4737 if (x_dnd_waiting_for_status_window != target)
4738 return x_dnd_send_drop (x_dnd_frame, target, toplevel,
4739 x_dnd_selection_timestamp, supported);
4740
4741 x_dnd_need_send_drop = true;
4742 x_dnd_send_drop_proto = supported;
4743
4744 return true;
4745 }
4746
4747 static void
4748 x_set_dnd_targets (Atom *targets, int ntargets)
4749 {
4750 if (x_dnd_targets)
4751 xfree (x_dnd_targets);
4752
4753 block_input ();
4754 x_dnd_targets = xmalloc (sizeof *targets * ntargets);
4755 x_dnd_n_targets = ntargets;
4756
4757 memcpy (x_dnd_targets, targets,
4758 sizeof *targets * ntargets);
4759 unblock_input ();
4760 }
4761
4762 static void
4763 x_free_dnd_targets (void)
4764 {
4765 if (!x_dnd_targets)
4766 return;
4767
4768 xfree (x_dnd_targets);
4769 x_dnd_targets = NULL;
4770 x_dnd_n_targets = 0;
4771 }
4772
4773
4774
4775
4776 static void
4777 x_clear_dnd_variables (void)
4778 {
4779 x_dnd_monitors = Qnil;
4780 x_dnd_unsupported_drop_data = Qnil;
4781 }
4782
4783 static void
4784 x_free_dnd_toplevels (void)
4785 {
4786 if (!x_dnd_use_toplevels || !x_dnd_toplevels)
4787 return;
4788
4789
4790
4791
4792 x_dnd_free_toplevels (true);
4793 }
4794
4795
4796
4797 static void
4798 x_restore_events_after_dnd (struct frame *f, XWindowAttributes *wa)
4799 {
4800 struct x_display_info *dpyinfo;
4801
4802 dpyinfo = FRAME_DISPLAY_INFO (f);
4803
4804
4805 XSelectInput (dpyinfo->display, dpyinfo->root_window,
4806 wa->your_event_mask);
4807 #ifdef HAVE_XKB
4808 if (dpyinfo->supports_xkb)
4809 XkbSelectEvents (dpyinfo->display, XkbUseCoreKbd,
4810 XkbStateNotifyMask, 0);
4811 #endif
4812
4813 if (x_dnd_motif_setup_p)
4814 XDeleteProperty (dpyinfo->display, FRAME_X_WINDOW (f),
4815 x_dnd_motif_atom);
4816
4817
4818 if (x_dnd_init_type_lists && x_dnd_n_targets > 3)
4819 XDeleteProperty (dpyinfo->display, FRAME_X_WINDOW (f),
4820 dpyinfo->Xatom_XdndTypeList);
4821 }
4822
4823 #ifdef HAVE_XINPUT2
4824
4825
4826
4827
4828
4829
4830 static void
4831 x_dnd_cancel_dnd_early (void)
4832 {
4833 struct frame *f;
4834 xm_drop_start_message dmsg;
4835
4836 eassert (x_dnd_frame && x_dnd_in_progress);
4837
4838 f = x_dnd_frame;
4839
4840 if (x_dnd_last_seen_window != None
4841 && x_dnd_last_protocol_version != -1)
4842 x_dnd_send_leave (x_dnd_frame,
4843 x_dnd_last_seen_window,
4844 x_dnd_last_seen_toplevel);
4845 else if (x_dnd_last_seen_window != None
4846 && !XM_DRAG_STYLE_IS_DROP_ONLY (x_dnd_last_motif_style)
4847 && x_dnd_last_motif_style != XM_DRAG_STYLE_NONE
4848 && x_dnd_motif_setup_p)
4849 {
4850 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
4851 XM_DRAG_REASON_DROP_START);
4852 dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST;
4853 dmsg.timestamp = FRAME_DISPLAY_INFO (f)->last_user_time;
4854 dmsg.side_effects
4855 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f),
4856 x_dnd_wanted_action),
4857 XM_DROP_SITE_VALID, x_dnd_motif_operations,
4858 XM_DROP_ACTION_DROP_CANCEL);
4859 dmsg.x = 0;
4860 dmsg.y = 0;
4861 dmsg.index_atom = x_dnd_motif_atom;
4862 dmsg.source_window = FRAME_X_WINDOW (f);
4863
4864 x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f,
4865 x_dnd_last_seen_window,
4866 FRAME_DISPLAY_INFO (f)->last_user_time);
4867 xm_send_drop_message (FRAME_DISPLAY_INFO (f), FRAME_X_WINDOW (f),
4868 x_dnd_last_seen_window, &dmsg);
4869 }
4870
4871 x_dnd_last_seen_window = None;
4872 x_dnd_last_seen_toplevel = None;
4873 x_dnd_in_progress = false;
4874 x_dnd_waiting_for_finish = false;
4875 x_dnd_return_frame_object = NULL;
4876 x_dnd_movement_frame = NULL;
4877 x_dnd_wheel_frame = NULL;
4878 x_dnd_frame = NULL;
4879 x_dnd_action = None;
4880 x_dnd_action_symbol = Qnil;
4881 }
4882
4883 #endif
4884
4885 static void
4886 x_dnd_cleanup_drag_and_drop (void *frame)
4887 {
4888 struct frame *f = frame;
4889 xm_drop_start_message dmsg;
4890
4891 if (!x_dnd_unwind_flag)
4892 return;
4893
4894 if (x_dnd_in_progress)
4895 {
4896 eassert (x_dnd_frame);
4897
4898 block_input ();
4899 if (x_dnd_last_seen_window != None
4900 && x_dnd_last_protocol_version != -1)
4901 x_dnd_send_leave (x_dnd_frame,
4902 x_dnd_last_seen_window,
4903 x_dnd_last_seen_toplevel);
4904 else if (x_dnd_last_seen_window != None
4905 && !XM_DRAG_STYLE_IS_DROP_ONLY (x_dnd_last_motif_style)
4906 && x_dnd_last_motif_style != XM_DRAG_STYLE_NONE
4907 && x_dnd_motif_setup_p)
4908 {
4909 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
4910 XM_DRAG_REASON_DROP_START);
4911 dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST;
4912 dmsg.timestamp = FRAME_DISPLAY_INFO (f)->last_user_time;
4913 dmsg.side_effects
4914 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f),
4915 x_dnd_wanted_action),
4916 XM_DROP_SITE_VALID, x_dnd_motif_operations,
4917 XM_DROP_ACTION_DROP_CANCEL);
4918 dmsg.x = 0;
4919 dmsg.y = 0;
4920 dmsg.index_atom = x_dnd_motif_atom;
4921 dmsg.source_window = FRAME_X_WINDOW (f);
4922
4923 x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f,
4924 x_dnd_last_seen_window,
4925 FRAME_DISPLAY_INFO (f)->last_user_time);
4926 xm_send_drop_message (FRAME_DISPLAY_INFO (f), FRAME_X_WINDOW (f),
4927 x_dnd_last_seen_window, &dmsg);
4928 }
4929 unblock_input ();
4930
4931 x_dnd_end_window = x_dnd_last_seen_window;
4932 x_dnd_last_seen_window = None;
4933 x_dnd_last_seen_toplevel = None;
4934 x_dnd_in_progress = false;
4935 }
4936
4937 x_dnd_waiting_for_finish = false;
4938
4939 FRAME_DISPLAY_INFO (f)->grabbed = 0;
4940 #ifdef USE_GTK
4941 current_hold_quit = NULL;
4942 #endif
4943 x_dnd_return_frame_object = NULL;
4944 x_dnd_movement_frame = NULL;
4945 x_dnd_wheel_frame = NULL;
4946 x_dnd_frame = NULL;
4947
4948 x_restore_events_after_dnd (f, &x_dnd_old_window_attrs);
4949 }
4950
4951
4952
4953
4954
4955
4956 static void
4957 x_dnd_note_self_position (struct x_display_info *dpyinfo, Window target,
4958 unsigned short root_x, unsigned short root_y)
4959 {
4960 struct frame *f;
4961 int dest_x, dest_y;
4962
4963 f = x_top_window_to_frame (dpyinfo, target);
4964
4965 if (f)
4966 {
4967 x_translate_coordinates (f, root_x, root_y, &dest_x, &dest_y);
4968
4969 x_dnd_movement_frame = f;
4970 x_dnd_movement_x = dest_x;
4971 x_dnd_movement_y = dest_y;
4972
4973 return;
4974 }
4975 }
4976
4977 static void
4978 x_dnd_note_self_wheel (struct x_display_info *dpyinfo, Window target,
4979 unsigned short root_x, unsigned short root_y,
4980 int button, unsigned int state, Time time)
4981 {
4982 struct frame *f;
4983 int dest_x, dest_y;
4984
4985 if (button < 4 || button > 7)
4986 return;
4987
4988 f = x_top_window_to_frame (dpyinfo, target);
4989
4990 if (f)
4991 {
4992 x_translate_coordinates (f, root_x, root_y, &dest_x, &dest_y);
4993
4994 x_dnd_wheel_frame = f;
4995 x_dnd_wheel_x = dest_x;
4996 x_dnd_wheel_y = dest_y;
4997 x_dnd_wheel_button = button;
4998 x_dnd_wheel_state = state;
4999 x_dnd_wheel_time = time;
5000
5001 return;
5002 }
5003 }
5004
5005 static void
5006 x_dnd_note_self_drop (struct x_display_info *dpyinfo, Window target,
5007 unsigned short root_x, unsigned short root_y,
5008 Time timestamp)
5009 {
5010 struct input_event ie;
5011 struct frame *f;
5012 Lisp_Object lval;
5013 char **atom_names;
5014 char *name;
5015 int win_x, win_y, i;
5016
5017 if (!x_dnd_allow_current_frame
5018 && (FRAME_OUTER_WINDOW (x_dnd_frame)
5019 == target))
5020 return;
5021
5022 f = x_top_window_to_frame (dpyinfo, target);
5023
5024 if (!f)
5025 return;
5026
5027 if (NILP (Vx_dnd_native_test_function))
5028 return;
5029
5030 x_translate_coordinates (f, root_x, root_y, &win_x, &win_y);
5031
5032
5033
5034
5035
5036 XSETFRAME (lval, f);
5037 x_dnd_action = None;
5038 x_dnd_action_symbol
5039 = safe_call2 (Vx_dnd_native_test_function,
5040 Fposn_at_x_y (make_fixnum (win_x),
5041 make_fixnum (win_y),
5042 lval, Qnil),
5043 x_atom_to_symbol (dpyinfo,
5044 x_dnd_wanted_action));
5045
5046 if (!SYMBOLP (x_dnd_action_symbol))
5047 return;
5048
5049 EVENT_INIT (ie);
5050
5051 ie.kind = DRAG_N_DROP_EVENT;
5052 XSETFRAME (ie.frame_or_window, f);
5053
5054 lval = Qnil;
5055 atom_names = alloca (x_dnd_n_targets * sizeof *atom_names);
5056 name = x_get_atom_name (dpyinfo, x_dnd_wanted_action, NULL);
5057
5058 if (!XGetAtomNames (dpyinfo->display, x_dnd_targets,
5059 x_dnd_n_targets, atom_names))
5060 {
5061 xfree (name);
5062 return;
5063 }
5064
5065 for (i = x_dnd_n_targets; i != 0; --i)
5066 {
5067 lval = Fcons (intern (atom_names[i - 1]), lval);
5068 XFree (atom_names[i - 1]);
5069 }
5070
5071 lval = Fcons (assq_no_quit (QXdndSelection,
5072 FRAME_TERMINAL (f)->Vselection_alist),
5073 lval);
5074 lval = Fcons (intern (name), lval);
5075 lval = Fcons (QXdndSelection, lval);
5076 ie.arg = lval;
5077 ie.timestamp = timestamp;
5078
5079 XSETINT (ie.x, win_x);
5080 XSETINT (ie.y, win_y);
5081
5082 xfree (name);
5083 kbd_buffer_store_event (&ie);
5084 }
5085
5086
5087
5088
5089
5090
5091
5092 static void
5093 x_flush (struct frame *f)
5094 {
5095 eassert (f && FRAME_X_P (f));
5096
5097
5098 if (!NILP (Vinhibit_redisplay))
5099 return;
5100
5101 block_input ();
5102 XFlush (FRAME_X_DISPLAY (f));
5103 unblock_input ();
5104 }
5105
5106 #ifdef HAVE_XDBE
5107 static void
5108 x_drop_xrender_surfaces (struct frame *f)
5109 {
5110 font_drop_xrender_surfaces (f);
5111
5112 #ifdef HAVE_XRENDER
5113 if (f && FRAME_X_DOUBLE_BUFFERED_P (f)
5114 && FRAME_X_PICTURE (f) != None)
5115 {
5116 XRenderFreePicture (FRAME_X_DISPLAY (f),
5117 FRAME_X_PICTURE (f));
5118 FRAME_X_PICTURE (f) = None;
5119 }
5120 #endif
5121 }
5122 #endif
5123
5124 #ifdef HAVE_XRENDER
5125 void
5126 x_xr_ensure_picture (struct frame *f)
5127 {
5128 if (FRAME_X_PICTURE (f) == None && FRAME_X_PICTURE_FORMAT (f))
5129 {
5130 XRenderPictureAttributes attrs;
5131 attrs.clip_mask = None;
5132 XRenderPictFormat *fmt = FRAME_X_PICTURE_FORMAT (f);
5133
5134 FRAME_X_PICTURE (f) = XRenderCreatePicture (FRAME_X_DISPLAY (f),
5135 FRAME_X_RAW_DRAWABLE (f),
5136 fmt, CPClipMask, &attrs);
5137 }
5138 }
5139 #endif
5140
5141
5142
5143
5144
5145
5146 #if false
5147
5148
5149
5150
5151 struct record
5152 {
5153 char *locus;
5154 int type;
5155 };
5156
5157 struct record event_record[100];
5158
5159 int event_record_index;
5160
5161 void
5162 record_event (char *locus, int type)
5163 {
5164 if (event_record_index == ARRAYELTS (event_record))
5165 event_record_index = 0;
5166
5167 event_record[event_record_index].locus = locus;
5168 event_record[event_record_index].type = type;
5169 event_record_index++;
5170 }
5171
5172 #endif
5173
5174
5175
5176
5177
5178 static void
5179 x_toolkit_position (struct frame *f, int x, int y,
5180 bool *menu_bar_p, bool *tool_bar_p)
5181 {
5182 #ifdef USE_GTK
5183 GdkRectangle test_rect;
5184 int scale;
5185
5186 y += (FRAME_MENUBAR_HEIGHT (f)
5187 + FRAME_TOOLBAR_TOP_HEIGHT (f));
5188 x += FRAME_TOOLBAR_LEFT_WIDTH (f);
5189
5190 if (FRAME_EXTERNAL_MENU_BAR (f))
5191 *menu_bar_p = (x >= 0 && x < FRAME_PIXEL_WIDTH (f)
5192 && y >= 0 && y < FRAME_MENUBAR_HEIGHT (f));
5193
5194 if (FRAME_X_OUTPUT (f)->toolbar_widget)
5195 {
5196 scale = xg_get_scale (f);
5197 test_rect.x = x / scale;
5198 test_rect.y = y / scale;
5199 test_rect.width = 1;
5200 test_rect.height = 1;
5201
5202 *tool_bar_p = gtk_widget_intersect (FRAME_X_OUTPUT (f)->toolbar_widget,
5203 &test_rect, NULL);
5204 }
5205 #elif defined USE_X_TOOLKIT
5206 *menu_bar_p = (x > 0 && x < FRAME_PIXEL_WIDTH (f)
5207 && (y < 0 && y >= -FRAME_MENUBAR_HEIGHT (f)));
5208 #else
5209 *menu_bar_p = (WINDOWP (f->menu_bar_window)
5210 && (x > 0 && x < FRAME_PIXEL_WIDTH (f)
5211 && (y > 0 && y < FRAME_MENU_BAR_HEIGHT (f))));
5212 #endif
5213 }
5214
5215 static void
5216 x_update_opaque_region (struct frame *f, XEvent *configure)
5217 {
5218 unsigned long opaque_region[] = {0, 0,
5219 (configure
5220 ? configure->xconfigure.width
5221 : FRAME_PIXEL_WIDTH (f)),
5222 (configure
5223 ? configure->xconfigure.height
5224 : FRAME_PIXEL_HEIGHT (f))};
5225 #ifdef HAVE_GTK3
5226 GObjectClass *object_class;
5227 GtkWidgetClass *class;
5228 #endif
5229
5230 if (!FRAME_DISPLAY_INFO (f)->alpha_bits)
5231 return;
5232
5233 if (f->alpha_background < 1.0)
5234 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5235 FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region,
5236 XA_CARDINAL, 32, PropModeReplace,
5237 NULL, 0);
5238 #ifndef HAVE_GTK3
5239 else
5240 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5241 FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region,
5242 XA_CARDINAL, 32, PropModeReplace,
5243 (unsigned char *) &opaque_region, 4);
5244 #else
5245 else if (FRAME_TOOLTIP_P (f))
5246 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5247 FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region,
5248 XA_CARDINAL, 32, PropModeReplace,
5249 (unsigned char *) &opaque_region, 4);
5250 else
5251 {
5252
5253
5254 if (!FRAME_PARENT_FRAME (f))
5255 {
5256 object_class = G_OBJECT_GET_CLASS (FRAME_GTK_OUTER_WIDGET (f));
5257 class = GTK_WIDGET_CLASS (object_class);
5258
5259 if (class->style_updated)
5260 class->style_updated (FRAME_GTK_OUTER_WIDGET (f));
5261 }
5262 }
5263 #endif
5264 }
5265
5266
5267 #if defined USE_CAIRO || defined HAVE_XRENDER
5268 static int
5269 x_gc_free_ext_data_private (XExtData *extension)
5270 {
5271 xfree (extension->private_data);
5272
5273 return 0;
5274 }
5275
5276 static struct x_gc_ext_data *
5277 x_gc_get_ext_data (struct frame *f, GC gc, int create_if_not_found_p)
5278 {
5279 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
5280 XEDataObject object;
5281 XExtData **head, *ext_data;
5282
5283 object.gc = gc;
5284 head = XEHeadOfExtensionList (object);
5285 ext_data = XFindOnExtensionList (head, dpyinfo->ext_codes->extension);
5286 if (ext_data == NULL)
5287 {
5288 if (!create_if_not_found_p)
5289 return NULL;
5290 else
5291 {
5292 ext_data = xzalloc (sizeof (*ext_data));
5293 ext_data->number = dpyinfo->ext_codes->extension;
5294 ext_data->private_data = xzalloc (sizeof (struct x_gc_ext_data));
5295 ext_data->free_private = x_gc_free_ext_data_private;
5296 XAddToExtensionList (head, ext_data);
5297 }
5298 }
5299 return (struct x_gc_ext_data *) ext_data->private_data;
5300 }
5301
5302 static void
5303 x_extension_initialize (struct x_display_info *dpyinfo)
5304 {
5305 XExtCodes *ext_codes = XAddExtension (dpyinfo->display);
5306
5307 dpyinfo->ext_codes = ext_codes;
5308 }
5309 #endif
5310
5311 #ifdef USE_CAIRO
5312
5313 #define FRAME_CR_CONTEXT(f) ((f)->output_data.x->cr_context)
5314 #define FRAME_CR_SURFACE_DESIRED_WIDTH(f) \
5315 ((f)->output_data.x->cr_surface_desired_width)
5316 #define FRAME_CR_SURFACE_DESIRED_HEIGHT(f) \
5317 ((f)->output_data.x->cr_surface_desired_height)
5318
5319 #endif
5320
5321
5322
5323
5324
5325 #ifdef HAVE_XINPUT2
5326
5327 bool
5328 xi_frame_selected_for (struct frame *f, unsigned long event)
5329 {
5330 XIEventMask *masks;
5331 int i;
5332
5333 masks = FRAME_X_OUTPUT (f)->xi_masks;
5334
5335 if (!masks)
5336 return false;
5337
5338 for (i = 0; i < FRAME_X_OUTPUT (f)->num_xi_masks; ++i)
5339 {
5340 if (masks[i].mask_len >= XIMaskLen (event)
5341 && XIMaskIsSet (masks[i].mask, event))
5342 return true;
5343 }
5344
5345 return false;
5346 }
5347
5348
5349
5350
5351 static void
5352 xi_convert_button_state (XIButtonState *in, unsigned int *out)
5353 {
5354 int i;
5355
5356 if (in->mask_len)
5357 {
5358 for (i = 1; i <= 8; ++i)
5359 {
5360 if (XIMaskIsSet (in->mask, i))
5361 *out |= (Button1Mask << (i - 1));
5362 }
5363 }
5364 }
5365
5366
5367
5368
5369
5370 #ifdef USE_GTK
5371 static
5372 #endif
5373 unsigned int
5374 xi_convert_event_state (XIDeviceEvent *xev)
5375 {
5376 unsigned int mods, buttons;
5377
5378 mods = xev->mods.effective;
5379 buttons = 0;
5380
5381 xi_convert_button_state (&xev->buttons, &buttons);
5382
5383 return mods | buttons;
5384 }
5385
5386
5387
5388
5389
5390 static unsigned int
5391 xi_convert_event_keyboard_state (XIDeviceEvent *xev)
5392 {
5393 return ((xev->mods.effective & ~(1 << 13 | 1 << 14))
5394 | (xev->group.effective << 13));
5395 }
5396
5397
5398
5399 static void
5400 x_free_xi_devices (struct x_display_info *dpyinfo)
5401 {
5402 #ifdef HAVE_XINPUT2_2
5403 struct xi_touch_point_t *tem, *last;
5404 #endif
5405
5406 block_input ();
5407
5408 if (dpyinfo->num_devices)
5409 {
5410 for (int i = 0; i < dpyinfo->num_devices; ++i)
5411 {
5412 #ifdef HAVE_XINPUT2_1
5413 xfree (dpyinfo->devices[i].valuators);
5414 #endif
5415
5416 #ifdef HAVE_XINPUT2_2
5417 tem = dpyinfo->devices[i].touchpoints;
5418 while (tem)
5419 {
5420 last = tem;
5421 tem = tem->next;
5422 xfree (last);
5423 }
5424 #endif
5425 }
5426
5427 xfree (dpyinfo->devices);
5428 dpyinfo->devices = NULL;
5429 dpyinfo->num_devices = 0;
5430 }
5431
5432 unblock_input ();
5433 }
5434
5435 #ifdef HAVE_XINPUT2_1
5436
5437 struct xi_known_valuator
5438 {
5439
5440 double current_value;
5441
5442
5443 int number;
5444
5445
5446 struct xi_known_valuator *next;
5447 };
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474 static void
5475 xi_populate_scroll_valuator (struct xi_device_t *device,
5476 int index, XIScrollClassInfo *info)
5477 {
5478 struct xi_scroll_valuator_t *valuator;
5479
5480 valuator = &device->valuators[index];
5481 valuator->horizontal
5482 = (info->scroll_type == XIScrollTypeHorizontal);
5483 valuator->invalid_p = true;
5484 valuator->emacs_value = DBL_MIN;
5485 valuator->increment = info->increment;
5486 valuator->number = info->number;
5487 }
5488
5489 #endif
5490
5491 static void
5492 xi_populate_device_from_info (struct x_display_info *dpyinfo,
5493 struct xi_device_t *xi_device,
5494 XIDeviceInfo *device)
5495 {
5496 #ifdef HAVE_XINPUT2_1
5497 struct xi_known_valuator *values, *tem;
5498 int actual_valuator_count, c;
5499 XIScrollClassInfo *info;
5500 XIValuatorClassInfo *valuator_info;
5501 #endif
5502 #ifdef HAVE_XINPUT2_2
5503 XITouchClassInfo *touch_info;
5504 #endif
5505
5506 #ifdef HAVE_XINPUT2_1
5507 USE_SAFE_ALLOCA;
5508 #endif
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564 xi_device->device_id = device->deviceid;
5565 xi_device->grab = 0;
5566 xi_device->use = device->use;
5567 xi_device->name = build_string (device->name);
5568 xi_device->attachment = device->attachment;
5569
5570
5571
5572
5573 #ifdef HAVE_XINPUT2_2
5574 xi_device->touchpoints = NULL;
5575 xi_device->direct_p = false;
5576 #endif
5577
5578 #ifdef HAVE_XINPUT2_1
5579 if (!dpyinfo->xi2_version)
5580 {
5581
5582
5583 xi_device->valuators = NULL;
5584 xi_device->scroll_valuator_count = 0;
5585
5586 SAFE_FREE ();
5587 return;
5588 }
5589
5590 actual_valuator_count = 0;
5591 xi_device->valuators = xnmalloc (device->num_classes,
5592 sizeof *xi_device->valuators);
5593 values = NULL;
5594
5595
5596
5597
5598
5599
5600
5601
5602 for (c = 0; c < device->num_classes; ++c)
5603 {
5604 switch (device->classes[c]->type)
5605 {
5606 case XIScrollClass:
5607 {
5608 info = (XIScrollClassInfo *) device->classes[c];
5609 xi_populate_scroll_valuator (xi_device, actual_valuator_count++,
5610 info);
5611 break;
5612 }
5613
5614 case XIValuatorClass:
5615 {
5616 valuator_info = (XIValuatorClassInfo *) device->classes[c];
5617 tem = SAFE_ALLOCA (sizeof *tem);
5618
5619
5620
5621
5622
5623
5624
5625
5626 if (valuator_info->value == 0.0
5627 && valuator_info->mode != XIModeAbsolute)
5628 continue;
5629
5630 tem->next = values;
5631 tem->number = valuator_info->number;
5632 tem->current_value = valuator_info->value;
5633
5634 values = tem;
5635 break;
5636 }
5637
5638 #ifdef HAVE_XINPUT2_2
5639 case XITouchClass:
5640 {
5641 touch_info = (XITouchClassInfo *) device->classes[c];
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664 if (touch_info->mode == XIDirectTouch)
5665 xi_device->direct_p = true;
5666 else
5667 xi_device->direct_p = false;
5668 }
5669 #endif
5670 default:
5671 break;
5672 }
5673 }
5674
5675 xi_device->scroll_valuator_count = actual_valuator_count;
5676
5677
5678
5679
5680
5681 for (tem = values; values; values = values->next)
5682 {
5683 for (c = 0; c < xi_device->scroll_valuator_count; ++c)
5684 {
5685 if (xi_device->valuators[c].number == tem->number)
5686 {
5687 xi_device->valuators[c].invalid_p = false;
5688 xi_device->valuators[c].current_value
5689 = tem->current_value;
5690 xi_device->valuators[c].emacs_value = 0.0;
5691 }
5692 }
5693 }
5694
5695 SAFE_FREE ();
5696 #endif
5697 }
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727 static void
5728 x_cache_xi_devices (struct x_display_info *dpyinfo)
5729 {
5730 int ndevices, actual_devices, i;
5731 XIDeviceInfo *infos;
5732
5733 actual_devices = 0;
5734 block_input ();
5735 x_free_xi_devices (dpyinfo);
5736 infos = XIQueryDevice (dpyinfo->display,
5737 XIAllDevices,
5738 &ndevices);
5739
5740 if (!ndevices)
5741 {
5742 XIFreeDeviceInfo (infos);
5743 unblock_input ();
5744 return;
5745 }
5746
5747 dpyinfo->devices = xzalloc (sizeof *dpyinfo->devices * ndevices);
5748
5749 for (i = 0; i < ndevices; ++i)
5750 {
5751 if (infos[i].enabled)
5752 xi_populate_device_from_info (dpyinfo,
5753 &dpyinfo->devices[actual_devices++],
5754 &infos[i]);
5755 }
5756
5757 dpyinfo->num_devices = actual_devices;
5758 XIFreeDeviceInfo (infos);
5759 unblock_input ();
5760 }
5761
5762 #ifdef HAVE_XINPUT2_1
5763
5764
5765
5766
5767
5768
5769 static double
5770 x_get_scroll_valuator_delta (struct x_display_info *dpyinfo,
5771 struct xi_device_t *device,
5772 int valuator_number, double value,
5773 struct xi_scroll_valuator_t **valuator_return)
5774 {
5775 struct xi_scroll_valuator_t *sv;
5776 double delta;
5777 int i;
5778
5779 for (i = 0; i < device->scroll_valuator_count; ++i)
5780 {
5781 sv = &device->valuators[i];
5782
5783 if (sv->number == valuator_number)
5784 {
5785 *valuator_return = sv;
5786
5787 if (sv->increment == 0)
5788 return DBL_MAX;
5789
5790 if (sv->invalid_p)
5791 {
5792 sv->current_value = value;
5793 sv->invalid_p = false;
5794
5795 return DBL_MAX;
5796 }
5797 else
5798 {
5799 delta = (sv->current_value - value) / sv->increment;
5800 sv->current_value = value;
5801
5802 return delta;
5803 }
5804 }
5805 }
5806
5807 *valuator_return = NULL;
5808 return DBL_MAX;
5809 }
5810
5811 #endif
5812
5813 struct xi_device_t *
5814 xi_device_from_id (struct x_display_info *dpyinfo, int deviceid)
5815 {
5816 for (int i = 0; i < dpyinfo->num_devices; ++i)
5817 {
5818 if (dpyinfo->devices[i].device_id == deviceid)
5819 return &dpyinfo->devices[i];
5820 }
5821
5822 return NULL;
5823 }
5824
5825 #ifdef HAVE_XINPUT2_2
5826
5827
5828
5829
5830
5831 static void
5832 xi_link_touch_point (struct xi_device_t *device,
5833 int detail, double x, double y,
5834 struct frame *frame)
5835 {
5836 struct xi_touch_point_t *touchpoint;
5837
5838 touchpoint = xmalloc (sizeof *touchpoint);
5839 touchpoint->next = device->touchpoints;
5840 touchpoint->x = lrint (x);
5841 touchpoint->y = lrint (y);
5842 touchpoint->number = detail;
5843 touchpoint->frame = frame;
5844 touchpoint->ownership = TOUCH_OWNERSHIP_NONE;
5845
5846 device->touchpoints = touchpoint;
5847 }
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857 static int
5858 xi_unlink_touch_point (int detail, struct xi_device_t *device)
5859 {
5860 struct xi_touch_point_t *last, *tem;
5861 enum xi_touch_ownership ownership;
5862
5863 for (last = NULL, tem = device->touchpoints; tem;
5864 last = tem, tem = tem->next)
5865 {
5866 if (tem->number == detail)
5867 {
5868 if (!last)
5869 device->touchpoints = tem->next;
5870 else
5871 last->next = tem->next;
5872
5873 ownership = tem->ownership;
5874 xfree (tem);
5875
5876 if (ownership == TOUCH_OWNERSHIP_SELF)
5877 return 2;
5878
5879 return 1;
5880 }
5881 }
5882
5883 return 0;
5884 }
5885
5886
5887
5888
5889
5890 static void
5891 xi_unlink_touch_points (struct frame *f)
5892 {
5893 struct xi_device_t *device;
5894 struct xi_touch_point_t **next, *last;
5895 int i;
5896
5897 for (i = 0; i < FRAME_DISPLAY_INFO (f)->num_devices; ++i)
5898 {
5899 device = &FRAME_DISPLAY_INFO (f)->devices[i];
5900
5901
5902
5903 for (next = &device->touchpoints; (last = *next);)
5904 {
5905 if (last->frame == f)
5906 {
5907 *next = last->next;
5908 xfree (last);
5909 }
5910 else
5911 next = &last->next;
5912 }
5913 }
5914 }
5915
5916
5917
5918
5919
5920 static struct xi_touch_point_t *
5921 xi_find_touch_point (struct xi_device_t *device, int detail)
5922 {
5923 struct xi_touch_point_t *point;
5924
5925 for (point = device->touchpoints; point; point = point->next)
5926 {
5927 if (point->number == detail)
5928 return point;
5929 }
5930
5931 return NULL;
5932 }
5933
5934 #endif
5935
5936 #ifdef HAVE_XINPUT2_1
5937
5938 static void
5939 xi_reset_scroll_valuators_for_device_id (struct x_display_info *dpyinfo,
5940 int id)
5941 {
5942 struct xi_device_t *device;
5943 struct xi_scroll_valuator_t *valuator;
5944 int i;
5945
5946 device = xi_device_from_id (dpyinfo, id);
5947
5948 if (!device)
5949 return;
5950
5951 if (!device->scroll_valuator_count)
5952 return;
5953
5954 for (i = 0; i < device->scroll_valuator_count; ++i)
5955 {
5956 valuator = &device->valuators[i];
5957 valuator->invalid_p = true;
5958 valuator->emacs_value = 0.0;
5959 }
5960
5961 return;
5962 }
5963
5964 #endif
5965 #endif
5966
5967
5968
5969
5970
5971
5972 #ifdef USE_CAIRO
5973
5974 void
5975 x_cr_destroy_frame_context (struct frame *f)
5976 {
5977 if (FRAME_CR_CONTEXT (f))
5978 {
5979 cairo_destroy (FRAME_CR_CONTEXT (f));
5980 FRAME_CR_CONTEXT (f) = NULL;
5981 }
5982 }
5983
5984 void
5985 x_cr_update_surface_desired_size (struct frame *f, int width, int height)
5986 {
5987 if (FRAME_CR_SURFACE_DESIRED_WIDTH (f) != width
5988 || FRAME_CR_SURFACE_DESIRED_HEIGHT (f) != height)
5989 {
5990 x_cr_destroy_frame_context (f);
5991 FRAME_CR_SURFACE_DESIRED_WIDTH (f) = width;
5992 FRAME_CR_SURFACE_DESIRED_HEIGHT (f) = height;
5993 }
5994 }
5995
5996 static void
5997 x_cr_gc_clip (cairo_t *cr, struct frame *f, GC gc)
5998 {
5999 if (gc)
6000 {
6001 struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 0);
6002
6003 if (gc_ext && gc_ext->n_clip_rects)
6004 {
6005 for (int i = 0; i < gc_ext->n_clip_rects; i++)
6006 cairo_rectangle (cr, gc_ext->clip_rects[i].x,
6007 gc_ext->clip_rects[i].y,
6008 gc_ext->clip_rects[i].width,
6009 gc_ext->clip_rects[i].height);
6010 cairo_clip (cr);
6011 }
6012 }
6013 }
6014
6015 cairo_t *
6016 x_begin_cr_clip (struct frame *f, GC gc)
6017 {
6018 cairo_t *cr = FRAME_CR_CONTEXT (f);
6019
6020 if (!cr)
6021 {
6022 int width = FRAME_CR_SURFACE_DESIRED_WIDTH (f);
6023 int height = FRAME_CR_SURFACE_DESIRED_HEIGHT (f);
6024 cairo_surface_t *surface;
6025 #ifdef USE_CAIRO_XCB_SURFACE
6026 if (FRAME_DISPLAY_INFO (f)->xcb_visual)
6027 surface = cairo_xcb_surface_create (FRAME_DISPLAY_INFO (f)->xcb_connection,
6028 (xcb_drawable_t) FRAME_X_RAW_DRAWABLE (f),
6029 FRAME_DISPLAY_INFO (f)->xcb_visual,
6030 width, height);
6031 else
6032 #endif
6033 surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
6034 FRAME_X_RAW_DRAWABLE (f),
6035 FRAME_X_VISUAL (f),
6036 width, height);
6037
6038 cr = FRAME_CR_CONTEXT (f) = cairo_create (surface);
6039 cairo_surface_destroy (surface);
6040 }
6041 cairo_save (cr);
6042 x_cr_gc_clip (cr, f, gc);
6043
6044 return cr;
6045 }
6046
6047 void
6048 x_end_cr_clip (struct frame *f)
6049 {
6050 cairo_restore (FRAME_CR_CONTEXT (f));
6051 #ifdef HAVE_XDBE
6052 if (FRAME_X_DOUBLE_BUFFERED_P (f))
6053 x_mark_frame_dirty (f);
6054 #endif
6055 }
6056
6057 void
6058 x_set_cr_source_with_gc_foreground (struct frame *f, GC gc,
6059 bool respect_alpha_background)
6060 {
6061 XGCValues xgcv;
6062 XColor color;
6063 unsigned int depth;
6064
6065 XGetGCValues (FRAME_X_DISPLAY (f), gc, GCForeground, &xgcv);
6066 color.pixel = xgcv.foreground;
6067 x_query_colors (f, &color, 1);
6068 depth = FRAME_DISPLAY_INFO (f)->n_planes;
6069
6070 if (f->alpha_background < 1.0 && depth == 32
6071 && respect_alpha_background)
6072 {
6073 cairo_set_source_rgba (FRAME_CR_CONTEXT (f), color.red / 65535.0,
6074 color.green / 65535.0, color.blue / 65535.0,
6075 f->alpha_background);
6076
6077 cairo_set_operator (FRAME_CR_CONTEXT (f), CAIRO_OPERATOR_SOURCE);
6078 }
6079 else
6080 {
6081 cairo_set_source_rgb (FRAME_CR_CONTEXT (f), color.red / 65535.0,
6082 color.green / 65535.0, color.blue / 65535.0);
6083 cairo_set_operator (FRAME_CR_CONTEXT (f), CAIRO_OPERATOR_OVER);
6084 }
6085 }
6086
6087 void
6088 x_set_cr_source_with_gc_background (struct frame *f, GC gc,
6089 bool respect_alpha_background)
6090 {
6091 XGCValues xgcv;
6092 XColor color;
6093 unsigned int depth;
6094
6095 XGetGCValues (FRAME_X_DISPLAY (f), gc, GCBackground, &xgcv);
6096 color.pixel = xgcv.background;
6097
6098 x_query_colors (f, &color, 1);
6099
6100 depth = FRAME_DISPLAY_INFO (f)->n_planes;
6101
6102 if (f->alpha_background < 1.0 && depth == 32
6103 && respect_alpha_background)
6104 {
6105 cairo_set_source_rgba (FRAME_CR_CONTEXT (f), color.red / 65535.0,
6106 color.green / 65535.0, color.blue / 65535.0,
6107 f->alpha_background);
6108
6109 cairo_set_operator (FRAME_CR_CONTEXT (f), CAIRO_OPERATOR_SOURCE);
6110 }
6111 else
6112 {
6113 cairo_set_source_rgb (FRAME_CR_CONTEXT (f), color.red / 65535.0,
6114 color.green / 65535.0, color.blue / 65535.0);
6115 cairo_set_operator (FRAME_CR_CONTEXT (f), CAIRO_OPERATOR_OVER);
6116 }
6117 }
6118
6119 static const cairo_user_data_key_t xlib_surface_key, saved_drawable_key;
6120
6121 static void
6122 x_cr_destroy_xlib_surface (cairo_surface_t *xlib_surface)
6123 {
6124 if (xlib_surface)
6125 {
6126 XFreePixmap (cairo_xlib_surface_get_display (xlib_surface),
6127 cairo_xlib_surface_get_drawable (xlib_surface));
6128 cairo_surface_destroy (xlib_surface);
6129 }
6130 }
6131
6132 static bool
6133 x_try_cr_xlib_drawable (struct frame *f, GC gc)
6134 {
6135 cairo_t *cr = FRAME_CR_CONTEXT (f);
6136 if (!cr)
6137 return true;
6138
6139 cairo_surface_t *surface = cairo_get_target (cr);
6140 switch (cairo_surface_get_type (surface))
6141 {
6142 case CAIRO_SURFACE_TYPE_XLIB:
6143 #ifdef USE_CAIRO_XCB_SURFACE
6144 case CAIRO_SURFACE_TYPE_XCB:
6145 #endif
6146 cairo_surface_flush (surface);
6147 return true;
6148
6149 case CAIRO_SURFACE_TYPE_IMAGE:
6150 break;
6151
6152 default:
6153 return false;
6154 }
6155
6156
6157
6158
6159 cairo_surface_t *xlib_surface = cairo_get_user_data (cr, &xlib_surface_key);
6160 int width = FRAME_CR_SURFACE_DESIRED_WIDTH (f);
6161 int height = FRAME_CR_SURFACE_DESIRED_HEIGHT (f);
6162 Pixmap pixmap;
6163 if (xlib_surface
6164 && cairo_xlib_surface_get_width (xlib_surface) == width
6165 && cairo_xlib_surface_get_height (xlib_surface) == height)
6166 pixmap = cairo_xlib_surface_get_drawable (xlib_surface);
6167 else
6168 {
6169 pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_RAW_DRAWABLE (f),
6170 width, height,
6171 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
6172 xlib_surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
6173 pixmap, FRAME_X_VISUAL (f),
6174 width, height);
6175 cairo_set_user_data (cr, &xlib_surface_key, xlib_surface,
6176 (cairo_destroy_func_t) x_cr_destroy_xlib_surface);
6177 }
6178
6179 cairo_t *buf = cairo_create (xlib_surface);
6180 cairo_set_source_surface (buf, surface, 0, 0);
6181 cairo_matrix_t matrix;
6182 cairo_get_matrix (cr, &matrix);
6183 cairo_pattern_set_matrix (cairo_get_source (cr), &matrix);
6184 cairo_set_operator (buf, CAIRO_OPERATOR_SOURCE);
6185 x_cr_gc_clip (buf, f, gc);
6186 cairo_paint (buf);
6187 cairo_destroy (buf);
6188
6189 cairo_set_user_data (cr, &saved_drawable_key,
6190 (void *) (uintptr_t) FRAME_X_RAW_DRAWABLE (f), NULL);
6191 FRAME_X_RAW_DRAWABLE (f) = pixmap;
6192 cairo_surface_flush (xlib_surface);
6193
6194 return true;
6195 }
6196
6197 static void
6198 x_end_cr_xlib_drawable (struct frame *f, GC gc)
6199 {
6200 cairo_t *cr = FRAME_CR_CONTEXT (f);
6201 if (!cr)
6202 return;
6203
6204 Drawable saved_drawable
6205 = (uintptr_t) cairo_get_user_data (cr, &saved_drawable_key);
6206 cairo_surface_t *surface = (saved_drawable
6207 ? cairo_get_user_data (cr, &xlib_surface_key)
6208 : cairo_get_target (cr));
6209 struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 0);
6210 if (gc_ext && gc_ext->n_clip_rects)
6211 for (int i = 0; i < gc_ext->n_clip_rects; i++)
6212 cairo_surface_mark_dirty_rectangle (surface, gc_ext->clip_rects[i].x,
6213 gc_ext->clip_rects[i].y,
6214 gc_ext->clip_rects[i].width,
6215 gc_ext->clip_rects[i].height);
6216 else
6217 cairo_surface_mark_dirty (surface);
6218 if (!saved_drawable)
6219 return;
6220
6221 cairo_save (cr);
6222 cairo_set_source_surface (cr, surface, 0, 0);
6223 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
6224 x_cr_gc_clip (cr, f, gc);
6225 cairo_paint (cr);
6226 cairo_restore (cr);
6227
6228 FRAME_X_RAW_DRAWABLE (f) = saved_drawable;
6229 cairo_set_user_data (cr, &saved_drawable_key, NULL, NULL);
6230 }
6231
6232
6233
6234 static int max_fringe_bmp = 0;
6235 static cairo_pattern_t **fringe_bmp = 0;
6236
6237 static void
6238 x_cr_define_fringe_bitmap (int which, unsigned short *bits, int h, int wd)
6239 {
6240 int i, stride;
6241 cairo_surface_t *surface;
6242 cairo_pattern_t *pattern;
6243 unsigned char *data;
6244
6245 if (which >= max_fringe_bmp)
6246 {
6247 i = max_fringe_bmp;
6248 max_fringe_bmp = which + 20;
6249 fringe_bmp = xrealloc (fringe_bmp, max_fringe_bmp * sizeof (*fringe_bmp));
6250 while (i < max_fringe_bmp)
6251 fringe_bmp[i++] = 0;
6252 }
6253
6254 block_input ();
6255
6256 surface = cairo_image_surface_create (CAIRO_FORMAT_A1, wd, h);
6257 stride = cairo_image_surface_get_stride (surface);
6258 data = cairo_image_surface_get_data (surface);
6259
6260 for (i = 0; i < h; i++)
6261 {
6262 *((unsigned short *) data) = bits[i];
6263 data += stride;
6264 }
6265
6266 cairo_surface_mark_dirty (surface);
6267 pattern = cairo_pattern_create_for_surface (surface);
6268 cairo_surface_destroy (surface);
6269
6270 unblock_input ();
6271
6272 fringe_bmp[which] = pattern;
6273 }
6274
6275 static void
6276 x_cr_destroy_fringe_bitmap (int which)
6277 {
6278 if (which >= max_fringe_bmp)
6279 return;
6280
6281 if (fringe_bmp[which])
6282 {
6283 block_input ();
6284 cairo_pattern_destroy (fringe_bmp[which]);
6285 unblock_input ();
6286 }
6287 fringe_bmp[which] = 0;
6288 }
6289
6290 static void
6291 x_cr_draw_image (struct frame *f, GC gc, cairo_pattern_t *image,
6292 int src_x, int src_y, int width, int height,
6293 int dest_x, int dest_y, bool overlay_p)
6294 {
6295 cairo_t *cr = x_begin_cr_clip (f, gc);
6296
6297 if (overlay_p)
6298 cairo_rectangle (cr, dest_x, dest_y, width, height);
6299 else
6300 {
6301 x_set_cr_source_with_gc_background (f, gc, false);
6302 cairo_rectangle (cr, dest_x, dest_y, width, height);
6303 cairo_fill_preserve (cr);
6304 }
6305
6306 cairo_translate (cr, dest_x - src_x, dest_y - src_y);
6307
6308 cairo_surface_t *surface;
6309 cairo_pattern_get_surface (image, &surface);
6310 cairo_format_t format = cairo_image_surface_get_format (surface);
6311 if (format != CAIRO_FORMAT_A8 && format != CAIRO_FORMAT_A1)
6312 {
6313 cairo_set_source (cr, image);
6314 cairo_fill (cr);
6315 }
6316 else
6317 {
6318 x_set_cr_source_with_gc_foreground (f, gc, false);
6319 cairo_clip (cr);
6320 cairo_mask (cr, image);
6321 }
6322
6323 x_end_cr_clip (f);
6324 }
6325
6326 void
6327 x_cr_draw_frame (cairo_t *cr, struct frame *f)
6328 {
6329 int width, height;
6330
6331 width = FRAME_PIXEL_WIDTH (f);
6332 height = FRAME_PIXEL_HEIGHT (f);
6333
6334 cairo_t *saved_cr = FRAME_CR_CONTEXT (f);
6335 FRAME_CR_CONTEXT (f) = cr;
6336 x_clear_area (f, 0, 0, width, height);
6337 expose_frame (f, 0, 0, width, height);
6338 FRAME_CR_CONTEXT (f) = saved_cr;
6339 }
6340
6341 static cairo_status_t
6342 x_cr_accumulate_data (void *closure, const unsigned char *data,
6343 unsigned int length)
6344 {
6345 Lisp_Object *acc = (Lisp_Object *) closure;
6346
6347 *acc = Fcons (make_unibyte_string ((char const *) data, length), *acc);
6348
6349 return CAIRO_STATUS_SUCCESS;
6350 }
6351
6352 static void
6353 x_cr_destroy (void *cr)
6354 {
6355 block_input ();
6356 cairo_destroy (cr);
6357 unblock_input ();
6358 }
6359
6360 Lisp_Object
6361 x_cr_export_frames (Lisp_Object frames, cairo_surface_type_t surface_type)
6362 {
6363 struct frame *f;
6364 cairo_surface_t *surface;
6365 cairo_t *cr;
6366 int width, height;
6367 void (*surface_set_size_func) (cairo_surface_t *, double, double) = NULL;
6368 Lisp_Object acc = Qnil;
6369 specpdl_ref count = SPECPDL_INDEX ();
6370
6371 specbind (Qredisplay_dont_pause, Qt);
6372 redisplay_preserve_echo_area (31);
6373
6374 f = XFRAME (XCAR (frames));
6375 frames = XCDR (frames);
6376 width = FRAME_PIXEL_WIDTH (f);
6377 height = FRAME_PIXEL_HEIGHT (f);
6378
6379 block_input ();
6380 #ifdef CAIRO_HAS_PDF_SURFACE
6381 if (surface_type == CAIRO_SURFACE_TYPE_PDF)
6382 {
6383 surface = cairo_pdf_surface_create_for_stream (x_cr_accumulate_data, &acc,
6384 width, height);
6385 surface_set_size_func = cairo_pdf_surface_set_size;
6386 }
6387 else
6388 #endif
6389 #ifdef CAIRO_HAS_PNG_FUNCTIONS
6390 if (surface_type == CAIRO_SURFACE_TYPE_IMAGE)
6391 surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height);
6392 else
6393 #endif
6394 #ifdef CAIRO_HAS_PS_SURFACE
6395 if (surface_type == CAIRO_SURFACE_TYPE_PS)
6396 {
6397 surface = cairo_ps_surface_create_for_stream (x_cr_accumulate_data, &acc,
6398 width, height);
6399 surface_set_size_func = cairo_ps_surface_set_size;
6400 }
6401 else
6402 #endif
6403 #ifdef CAIRO_HAS_SVG_SURFACE
6404 if (surface_type == CAIRO_SURFACE_TYPE_SVG)
6405 surface = cairo_svg_surface_create_for_stream (x_cr_accumulate_data, &acc,
6406 width, height);
6407 else
6408 #endif
6409 abort ();
6410
6411 cr = cairo_create (surface);
6412 cairo_surface_destroy (surface);
6413 record_unwind_protect_ptr (x_cr_destroy, cr);
6414
6415 while (1)
6416 {
6417 cairo_t *saved_cr = FRAME_CR_CONTEXT (f);
6418 FRAME_CR_CONTEXT (f) = cr;
6419 x_clear_area (f, 0, 0, width, height);
6420 expose_frame (f, 0, 0, width, height);
6421 FRAME_CR_CONTEXT (f) = saved_cr;
6422
6423 if (NILP (frames))
6424 break;
6425
6426 cairo_surface_show_page (surface);
6427 f = XFRAME (XCAR (frames));
6428 frames = XCDR (frames);
6429 width = FRAME_PIXEL_WIDTH (f);
6430 height = FRAME_PIXEL_HEIGHT (f);
6431 if (surface_set_size_func)
6432 (*surface_set_size_func) (surface, width, height);
6433
6434 unblock_input ();
6435 maybe_quit ();
6436 block_input ();
6437 }
6438
6439 #ifdef CAIRO_HAS_PNG_FUNCTIONS
6440 if (surface_type == CAIRO_SURFACE_TYPE_IMAGE)
6441 {
6442 cairo_surface_flush (surface);
6443 cairo_surface_write_to_png_stream (surface, x_cr_accumulate_data, &acc);
6444 }
6445 #endif
6446 unblock_input ();
6447
6448 unbind_to (count, Qnil);
6449
6450 return CALLN (Fapply, Qconcat, Fnreverse (acc));
6451 }
6452
6453 #endif
6454
6455 #if defined HAVE_XRENDER
6456
6457 void
6458 x_xr_apply_ext_clip (struct frame *f, GC gc)
6459 {
6460 eassert (FRAME_X_PICTURE (f) != None);
6461
6462 struct x_gc_ext_data *data = x_gc_get_ext_data (f, gc, 1);
6463
6464 if (data->n_clip_rects)
6465 XRenderSetPictureClipRectangles (FRAME_X_DISPLAY (f),
6466 FRAME_X_PICTURE (f),
6467 0, 0, data->clip_rects,
6468 data->n_clip_rects);
6469 }
6470
6471 void
6472 x_xr_reset_ext_clip (struct frame *f)
6473 {
6474 XRenderPictureAttributes attrs = { .clip_mask = None };
6475
6476 XRenderChangePicture (FRAME_X_DISPLAY (f),
6477 FRAME_X_PICTURE (f),
6478 CPClipMask, &attrs);
6479 }
6480
6481 #endif
6482
6483 static void
6484 x_set_clip_rectangles (struct frame *f, GC gc, XRectangle *rectangles, int n)
6485 {
6486 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, rectangles, n, Unsorted);
6487 #if defined USE_CAIRO || defined HAVE_XRENDER
6488 eassert (n >= 0 && n <= MAX_CLIP_RECTS);
6489
6490 {
6491 struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 1);
6492
6493 gc_ext->n_clip_rects = n;
6494 memcpy (gc_ext->clip_rects, rectangles, sizeof (XRectangle) * n);
6495 }
6496 #endif
6497 }
6498
6499 static void
6500 x_reset_clip_rectangles (struct frame *f, GC gc)
6501 {
6502 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
6503 #if defined USE_CAIRO || defined HAVE_XRENDER
6504 {
6505 struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 0);
6506
6507 if (gc_ext)
6508 gc_ext->n_clip_rects = 0;
6509 }
6510 #endif
6511 }
6512
6513 #ifdef HAVE_XRENDER
6514 # if !defined USE_CAIRO && (RENDER_MAJOR > 0 || RENDER_MINOR >= 2)
6515 static void
6516 x_xrender_color_from_gc_foreground (struct frame *f, GC gc, XRenderColor *color,
6517 bool apply_alpha_background)
6518 {
6519 XGCValues xgcv;
6520 XColor xc;
6521
6522 XGetGCValues (FRAME_X_DISPLAY (f), gc, GCForeground, &xgcv);
6523 xc.pixel = xgcv.foreground;
6524 x_query_colors (f, &xc, 1);
6525
6526 color->alpha = (apply_alpha_background
6527 ? 65535 * f->alpha_background
6528 : 65535);
6529
6530 if (color->alpha == 65535)
6531 {
6532 color->red = xc.red;
6533 color->blue = xc.blue;
6534 color->green = xc.green;
6535 }
6536 else
6537 {
6538 color->red = (xc.red * color->alpha) / 65535;
6539 color->blue = (xc.blue * color->alpha) / 65535;
6540 color->green = (xc.green * color->alpha) / 65535;
6541 }
6542 }
6543 # endif
6544
6545 void
6546 x_xrender_color_from_gc_background (struct frame *f, GC gc, XRenderColor *color,
6547 bool apply_alpha_background)
6548 {
6549 XGCValues xgcv;
6550 XColor xc;
6551
6552 XGetGCValues (FRAME_X_DISPLAY (f), gc, GCBackground, &xgcv);
6553 xc.pixel = xgcv.background;
6554 x_query_colors (f, &xc, 1);
6555
6556 color->alpha = (apply_alpha_background
6557 ? 65535 * f->alpha_background
6558 : 65535);
6559
6560 if (color->alpha == 65535)
6561 {
6562 color->red = xc.red;
6563 color->blue = xc.blue;
6564 color->green = xc.green;
6565 }
6566 else
6567 {
6568 color->red = (xc.red * color->alpha) / 65535;
6569 color->blue = (xc.blue * color->alpha) / 65535;
6570 color->green = (xc.green * color->alpha) / 65535;
6571 }
6572 }
6573 #endif
6574
6575 static void
6576 x_fill_rectangle (struct frame *f, GC gc, int x, int y, int width, int height,
6577 bool respect_alpha_background)
6578 {
6579 #ifdef USE_CAIRO
6580 Display *dpy = FRAME_X_DISPLAY (f);
6581 cairo_t *cr;
6582 XGCValues xgcv;
6583
6584 cr = x_begin_cr_clip (f, gc);
6585 XGetGCValues (dpy, gc, GCFillStyle | GCStipple, &xgcv);
6586 if (xgcv.fill_style == FillSolid
6587
6588
6589
6590
6591 || (xgcv.stipple & ((Pixmap) 7 << (sizeof (Pixmap) * CHAR_BIT - 3))))
6592 {
6593 x_set_cr_source_with_gc_foreground (f, gc, respect_alpha_background);
6594 cairo_rectangle (cr, x, y, width, height);
6595 cairo_fill (cr);
6596 }
6597 else
6598 {
6599 eassert (xgcv.fill_style == FillOpaqueStippled);
6600 eassert (xgcv.stipple != None);
6601 x_set_cr_source_with_gc_background (f, gc, respect_alpha_background);
6602 cairo_rectangle (cr, x, y, width, height);
6603 cairo_fill_preserve (cr);
6604
6605 cairo_pattern_t *pattern = x_bitmap_stipple (f, xgcv.stipple);
6606 if (pattern)
6607 {
6608 x_set_cr_source_with_gc_foreground (f, gc, respect_alpha_background);
6609 cairo_clip (cr);
6610 cairo_mask (cr, pattern);
6611 }
6612 }
6613 x_end_cr_clip (f);
6614 #else
6615 #if defined HAVE_XRENDER && (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2))
6616 if (respect_alpha_background
6617 && f->alpha_background != 1.0
6618 && FRAME_DISPLAY_INFO (f)->alpha_bits
6619 && FRAME_CHECK_XR_VERSION (f, 0, 2))
6620 {
6621 x_xr_ensure_picture (f);
6622
6623 if (FRAME_X_PICTURE (f) != None)
6624 {
6625 XRenderColor xc;
6626
6627 #if RENDER_MAJOR > 0 || (RENDER_MINOR >= 10)
6628 XGCValues xgcv;
6629 XRenderPictureAttributes attrs;
6630 XRenderColor alpha;
6631 Picture stipple, fill;
6632 #endif
6633
6634 x_xr_apply_ext_clip (f, gc);
6635
6636 #if RENDER_MAJOR > 0 || (RENDER_MINOR >= 10)
6637 XGetGCValues (FRAME_X_DISPLAY (f),
6638 gc, GCFillStyle | GCStipple, &xgcv);
6639
6640 if (xgcv.fill_style == FillOpaqueStippled
6641 && FRAME_CHECK_XR_VERSION (f, 0, 10))
6642 {
6643 x_xrender_color_from_gc_background (f, gc, &alpha, true);
6644 x_xrender_color_from_gc_foreground (f, gc, &xc, true);
6645 attrs.repeat = RepeatNormal;
6646
6647 stipple = XRenderCreatePicture (FRAME_X_DISPLAY (f),
6648 xgcv.stipple,
6649 XRenderFindStandardFormat (FRAME_X_DISPLAY (f),
6650 PictStandardA1),
6651 CPRepeat, &attrs);
6652
6653 XRenderFillRectangle (FRAME_X_DISPLAY (f), PictOpSrc,
6654 FRAME_X_PICTURE (f),
6655 &alpha, x, y, width, height);
6656
6657 fill = XRenderCreateSolidFill (FRAME_X_DISPLAY (f), &xc);
6658
6659 XRenderComposite (FRAME_X_DISPLAY (f), PictOpOver, fill, stipple,
6660 FRAME_X_PICTURE (f), 0, 0, x, y, x, y, width, height);
6661
6662 XRenderFreePicture (FRAME_X_DISPLAY (f), stipple);
6663 XRenderFreePicture (FRAME_X_DISPLAY (f), fill);
6664 }
6665 else
6666 #endif
6667 {
6668 x_xrender_color_from_gc_foreground (f, gc, &xc, true);
6669 XRenderFillRectangle (FRAME_X_DISPLAY (f),
6670 PictOpSrc, FRAME_X_PICTURE (f),
6671 &xc, x, y, width, height);
6672 }
6673 x_xr_reset_ext_clip (f);
6674 x_mark_frame_dirty (f);
6675
6676 return;
6677 }
6678 }
6679 #endif
6680 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
6681 gc, x, y, width, height);
6682 #endif
6683 }
6684
6685
6686
6687
6688
6689 static void
6690 x_clear_rectangle (struct frame *f, GC gc, int x, int y, int width, int height,
6691 bool respect_alpha_background)
6692 {
6693 #ifdef USE_CAIRO
6694 cairo_t *cr;
6695
6696 cr = x_begin_cr_clip (f, gc);
6697 x_set_cr_source_with_gc_background (f, gc, respect_alpha_background);
6698 cairo_rectangle (cr, x, y, width, height);
6699 cairo_fill (cr);
6700 x_end_cr_clip (f);
6701 #else
6702 #if defined HAVE_XRENDER && (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2))
6703 if (respect_alpha_background
6704 && f->alpha_background != 1.0
6705 && FRAME_DISPLAY_INFO (f)->alpha_bits
6706 && FRAME_CHECK_XR_VERSION (f, 0, 2))
6707 {
6708 x_xr_ensure_picture (f);
6709
6710 if (FRAME_X_PICTURE (f) != None)
6711 {
6712 XRenderColor xc;
6713
6714 x_xr_apply_ext_clip (f, gc);
6715 x_xrender_color_from_gc_background (f, gc, &xc, true);
6716 XRenderFillRectangle (FRAME_X_DISPLAY (f),
6717 PictOpSrc, FRAME_X_PICTURE (f),
6718 &xc, x, y, width, height);
6719 x_xr_reset_ext_clip (f);
6720 x_mark_frame_dirty (f);
6721
6722 return;
6723 }
6724 }
6725 #endif
6726
6727 XGCValues xgcv;
6728 Display *dpy = FRAME_X_DISPLAY (f);
6729 XGetGCValues (dpy, gc, GCBackground | GCForeground, &xgcv);
6730 XSetForeground (dpy, gc, xgcv.background);
6731 XFillRectangle (dpy, FRAME_X_DRAWABLE (f),
6732 gc, x, y, width, height);
6733 XSetForeground (dpy, gc, xgcv.foreground);
6734 #endif
6735 }
6736
6737 static void
6738 x_draw_rectangle (struct frame *f, GC gc, int x, int y, int width, int height)
6739 {
6740 #ifdef USE_CAIRO
6741 cairo_t *cr;
6742
6743 cr = x_begin_cr_clip (f, gc);
6744 x_set_cr_source_with_gc_foreground (f, gc, false);
6745 cairo_rectangle (cr, x + 0.5, y + 0.5, width, height);
6746 cairo_set_line_width (cr, 1);
6747 cairo_stroke (cr);
6748 x_end_cr_clip (f);
6749 #else
6750 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
6751 gc, x, y, width, height);
6752 #endif
6753 }
6754
6755 static void
6756 x_clear_window (struct frame *f)
6757 {
6758 #ifdef USE_CAIRO
6759 cairo_t *cr;
6760
6761 cr = x_begin_cr_clip (f, NULL);
6762 x_set_cr_source_with_gc_background (f, f->output_data.x->normal_gc, true);
6763 cairo_paint (cr);
6764 x_end_cr_clip (f);
6765 #else
6766 #ifndef USE_GTK
6767 if (f->alpha_background != 1.0
6768 #ifdef HAVE_XDBE
6769 || FRAME_X_DOUBLE_BUFFERED_P (f)
6770 #endif
6771 )
6772 #endif
6773 x_clear_area (f, 0, 0, FRAME_PIXEL_WIDTH (f),
6774 FRAME_PIXEL_HEIGHT (f));
6775 #ifndef USE_GTK
6776 else
6777 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
6778 #endif
6779 #endif
6780 }
6781
6782 #ifdef USE_CAIRO
6783 static void
6784 x_fill_trapezoid_for_relief (struct frame *f, GC gc, int x, int y,
6785 int width, int height, int top_p)
6786 {
6787 cairo_t *cr;
6788
6789 cr = x_begin_cr_clip (f, gc);
6790 x_set_cr_source_with_gc_foreground (f, gc, false);
6791 cairo_move_to (cr, top_p ? x : x + height, y);
6792 cairo_line_to (cr, x, y + height);
6793 cairo_line_to (cr, top_p ? x + width - height : x + width, y + height);
6794 cairo_line_to (cr, x + width, y);
6795 cairo_fill (cr);
6796 x_end_cr_clip (f);
6797 }
6798
6799 enum corners
6800 {
6801 CORNER_BOTTOM_RIGHT,
6802 CORNER_BOTTOM_LEFT,
6803 CORNER_TOP_LEFT,
6804 CORNER_TOP_RIGHT,
6805 CORNER_LAST
6806 };
6807
6808 static void
6809 x_erase_corners_for_relief (struct frame *f, GC gc, int x, int y,
6810 int width, int height,
6811 double radius, double margin, int corners)
6812 {
6813 cairo_t *cr;
6814 int i;
6815
6816 cr = x_begin_cr_clip (f, gc);
6817 x_set_cr_source_with_gc_background (f, gc, false);
6818 for (i = 0; i < CORNER_LAST; i++)
6819 if (corners & (1 << i))
6820 {
6821 double xm, ym, xc, yc;
6822
6823 if (i == CORNER_TOP_LEFT || i == CORNER_BOTTOM_LEFT)
6824 xm = x - margin, xc = xm + radius;
6825 else
6826 xm = x + width + margin, xc = xm - radius;
6827 if (i == CORNER_TOP_LEFT || i == CORNER_TOP_RIGHT)
6828 ym = y - margin, yc = ym + radius;
6829 else
6830 ym = y + height + margin, yc = ym - radius;
6831
6832 cairo_move_to (cr, xm, ym);
6833 cairo_arc (cr, xc, yc, radius, i * M_PI_2, (i + 1) * M_PI_2);
6834 }
6835 cairo_clip (cr);
6836 cairo_rectangle (cr, x, y, width, height);
6837 cairo_fill (cr);
6838 x_end_cr_clip (f);
6839 }
6840
6841 static void
6842 x_draw_horizontal_wave (struct frame *f, GC gc, int x, int y,
6843 int width, int height, int wave_length)
6844 {
6845 cairo_t *cr;
6846 double dx = wave_length, dy = height - 1;
6847 int xoffset, n;
6848
6849 cr = x_begin_cr_clip (f, gc);
6850 x_set_cr_source_with_gc_foreground (f, gc, false);
6851 cairo_rectangle (cr, x, y, width, height);
6852 cairo_clip (cr);
6853
6854 if (x >= 0)
6855 {
6856 xoffset = x % (wave_length * 2);
6857 if (xoffset == 0)
6858 xoffset = wave_length * 2;
6859 }
6860 else
6861 xoffset = x % (wave_length * 2) + wave_length * 2;
6862 n = (width + xoffset) / wave_length + 1;
6863 if (xoffset > wave_length)
6864 {
6865 xoffset -= wave_length;
6866 --n;
6867 y += height - 1;
6868 dy = -dy;
6869 }
6870
6871 cairo_move_to (cr, x - xoffset + 0.5, y + 0.5);
6872 while (--n >= 0)
6873 {
6874 cairo_rel_line_to (cr, dx, dy);
6875 dy = -dy;
6876 }
6877 cairo_set_line_width (cr, 1);
6878 cairo_stroke (cr);
6879 x_end_cr_clip (f);
6880 }
6881 #endif
6882
6883
6884
6885
6886 struct x_display_info *
6887 x_display_info_for_display (Display *dpy)
6888 {
6889 struct x_display_info *dpyinfo;
6890
6891 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
6892 if (dpyinfo->display == dpy)
6893 return dpyinfo;
6894
6895 return 0;
6896 }
6897
6898 static Window
6899 x_find_topmost_parent (struct frame *f)
6900 {
6901 struct x_output *x = f->output_data.x;
6902 Window win = None, wi = x->parent_desc;
6903 Display *dpy = FRAME_X_DISPLAY (f);
6904
6905 while (wi != FRAME_DISPLAY_INFO (f)->root_window)
6906 {
6907 Window root;
6908 Window *children;
6909 unsigned int nchildren;
6910
6911 win = wi;
6912 if (XQueryTree (dpy, win, &root, &wi, &children, &nchildren))
6913 XFree (children);
6914 else
6915 break;
6916 }
6917
6918 return win;
6919 }
6920
6921 #define OPAQUE 0xffffffff
6922
6923 static void
6924 x_set_frame_alpha (struct frame *f)
6925 {
6926 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
6927 Display *dpy = FRAME_X_DISPLAY (f);
6928 Window win = FRAME_OUTER_WINDOW (f);
6929 double alpha = 1.0;
6930 double alpha_min = 1.0;
6931 unsigned long opac;
6932 Window parent;
6933
6934 if (dpyinfo->highlight_frame == f)
6935 alpha = f->alpha[0];
6936 else
6937 alpha = f->alpha[1];
6938
6939 if (alpha < 0.0)
6940 return;
6941
6942 if (FLOATP (Vframe_alpha_lower_limit))
6943 alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit);
6944 else if (FIXNUMP (Vframe_alpha_lower_limit))
6945 alpha_min = (XFIXNUM (Vframe_alpha_lower_limit)) / 100.0;
6946
6947 if (alpha > 1.0)
6948 alpha = 1.0;
6949 else if (alpha < alpha_min && alpha_min <= 1.0)
6950 alpha = alpha_min;
6951
6952 opac = alpha * OPAQUE;
6953
6954
6955
6956
6957
6958
6959 x_ignore_errors_for_next_request (dpyinfo, 0);
6960
6961 if (!FRAME_PARENT_FRAME (f))
6962 {
6963 parent = x_find_topmost_parent (f);
6964
6965 if (parent != None)
6966 {
6967 XChangeProperty (dpy, parent,
6968 dpyinfo->Xatom_net_wm_window_opacity,
6969 XA_CARDINAL, 32, PropModeReplace,
6970 (unsigned char *) &opac, 1);
6971 }
6972 }
6973
6974 XChangeProperty (dpy, win, dpyinfo->Xatom_net_wm_window_opacity,
6975 XA_CARDINAL, 32, PropModeReplace,
6976 (unsigned char *) &opac, 1);
6977 x_stop_ignoring_errors (dpyinfo);
6978 }
6979
6980
6981
6982
6983
6984
6985
6986 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
6987
6988
6989
6990
6991
6992
6993
6994 static int
6995 x_if_event (Display *dpy, XEvent *event_return,
6996 Bool (*predicate) (Display *, XEvent *, XPointer),
6997 XPointer arg, struct timespec timeout)
6998 {
6999 struct timespec current_time, target;
7000 int fd;
7001 fd_set fds;
7002
7003 fd = ConnectionNumber (dpy);
7004 current_time = current_timespec ();
7005 target = timespec_add (current_time, timeout);
7006
7007
7008
7009 if (XCheckIfEvent (dpy, event_return, predicate, arg))
7010 return 0;
7011
7012 while (true)
7013 {
7014
7015 XSync (dpy, False);
7016
7017
7018 if (XCheckIfEvent (dpy, event_return, predicate, arg))
7019 return 0;
7020
7021
7022 current_time = current_timespec ();
7023 timeout = timespec_sub (target, current_time);
7024
7025
7026
7027 FD_ZERO (&fds);
7028 FD_SET (fd, &fds);
7029
7030
7031
7032 pselect (fd + 1, &fds, NULL, NULL, &timeout, NULL);
7033
7034
7035 current_time = current_timespec ();
7036 if (timespec_cmp (target, current_time) < 0)
7037 return 1;
7038 }
7039 }
7040
7041
7042
7043
7044
7045 static uint_fast64_t
7046 x_sync_get_monotonic_time (struct x_display_info *dpyinfo,
7047 uint_fast64_t timestamp)
7048 {
7049 if (dpyinfo->server_time_monotonic_p)
7050 return timestamp;
7051
7052
7053 if (!dpyinfo->server_time_offset)
7054 return 0;
7055
7056 uint_fast64_t t;
7057 return ckd_sub (&t, timestamp, dpyinfo->server_time_offset) ? 0 : t;
7058 }
7059
7060 # ifndef CLOCK_MONOTONIC
7061 # define CLOCK_MONOTONIC CLOCK_REALTIME
7062 # endif
7063
7064
7065
7066
7067 static uint_fast64_t
7068 x_sync_current_monotonic_time (void)
7069 {
7070 struct timespec time;
7071 uint_fast64_t t;
7072 return (((clock_gettime (CLOCK_MONOTONIC, &time) != 0
7073 && (CLOCK_MONOTONIC == CLOCK_REALTIME
7074 || clock_gettime (CLOCK_REALTIME, &time) != 0))
7075 || ckd_mul (&t, time.tv_sec, 1000000)
7076 || ckd_add (&t, t, time.tv_nsec / 1000))
7077 ? 0 : t);
7078 }
7079
7080
7081
7082
7083 static void
7084 x_sync_note_frame_times (struct x_display_info *dpyinfo,
7085 struct frame *f, XEvent *event)
7086 {
7087 uint_fast64_t low, high, time;
7088 struct x_output *output;
7089
7090 low = event->xclient.data.l[2];
7091 high = event->xclient.data.l[3];
7092 output = FRAME_X_OUTPUT (f);
7093
7094 time = x_sync_get_monotonic_time (dpyinfo, low | (high << 32));
7095
7096 if (!time || !output->temp_frame_time
7097 || ckd_sub (&output->last_frame_time, time, output->temp_frame_time))
7098 output->last_frame_time = 0;
7099
7100 #ifdef FRAME_DEBUG
7101 uint_fast64_t last_frame_ms = output->last_frame_time / 1000;
7102 fprintf (stderr,
7103 "Drawing the last frame took: %"PRIuFAST64" ms (%"PRIuFAST64")\n",
7104 last_frame_ms, time);
7105 #endif
7106 }
7107
7108 static Bool
7109 x_sync_is_frame_drawn_event (Display *dpy, XEvent *event,
7110 XPointer user_data)
7111 {
7112 struct frame *f;
7113 struct x_display_info *dpyinfo;
7114
7115 f = (struct frame *) user_data;
7116 dpyinfo = FRAME_DISPLAY_INFO (f);
7117
7118 if (event->type == ClientMessage
7119 && (event->xclient.message_type
7120 == dpyinfo->Xatom_net_wm_frame_drawn)
7121 && event->xclient.window == FRAME_OUTER_WINDOW (f))
7122 return True;
7123
7124 return False;
7125 }
7126
7127
7128
7129
7130
7131 static void
7132 x_sync_wait_for_frame_drawn_event (struct frame *f)
7133 {
7134 XEvent event;
7135 struct x_display_info *dpyinfo;
7136
7137 if (!FRAME_X_WAITING_FOR_DRAW (f)
7138
7139
7140 || !FRAME_VISIBLE_P (f))
7141 return;
7142
7143 dpyinfo = FRAME_DISPLAY_INFO (f);
7144
7145
7146 if (x_if_event (FRAME_X_DISPLAY (f), &event,
7147 x_sync_is_frame_drawn_event, (XPointer) f,
7148 make_timespec (1, 0)))
7149 {
7150
7151
7152
7153 if (FRAME_X_DRAW_JUST_HUNG (f))
7154 {
7155 fprintf (stderr, "Warning: compositing manager spent more than 1 "
7156 "second drawing a frame. Frame synchronization has "
7157 "been disabled\n");
7158 FRAME_X_OUTPUT (f)->use_vsync_p = false;
7159
7160
7161
7162 XDeleteProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
7163 dpyinfo->Xatom_net_wm_bypass_compositor);
7164
7165
7166
7167 store_frame_param (f, Quse_frame_synchronization, Qnil);
7168 }
7169 else
7170 {
7171 fprintf (stderr, "Warning: compositing manager spent more than 1 "
7172 "second drawing a frame. Frame synchronization will be "
7173 "disabled if this happens again\n");
7174 FRAME_X_DRAW_JUST_HUNG (f) = true;
7175 }
7176 }
7177 else
7178 x_sync_note_frame_times (dpyinfo, f, &event);
7179
7180 FRAME_X_WAITING_FOR_DRAW (f) = false;
7181 }
7182
7183
7184
7185
7186 static void
7187 x_sync_update_begin (struct frame *f)
7188 {
7189 XSyncValue value, add;
7190 Bool overflow;
7191
7192 if (FRAME_X_EXTENDED_COUNTER (f) == None)
7193 return;
7194
7195 value = FRAME_X_COUNTER_VALUE (f);
7196
7197 if (FRAME_X_OUTPUT (f)->ext_sync_end_pending_p)
7198 {
7199 FRAME_X_COUNTER_VALUE (f)
7200 = FRAME_X_OUTPUT (f)->resize_counter_value;
7201
7202 value = FRAME_X_COUNTER_VALUE (f);
7203
7204 if (XSyncValueLow32 (value) % 2)
7205 {
7206 XSyncIntToValue (&add, 1);
7207 XSyncValueAdd (&value, value, add, &overflow);
7208
7209 if (overflow)
7210 XSyncIntToValue (&value, 0);
7211 }
7212
7213 FRAME_X_OUTPUT (f)->ext_sync_end_pending_p = false;
7214 }
7215
7216
7217
7218 if (XSyncValueLow32 (value) % 2)
7219 return;
7220
7221
7222 x_sync_wait_for_frame_drawn_event (f);
7223
7224
7225
7226 FRAME_X_OUTPUT (f)->temp_frame_time = x_sync_current_monotonic_time ();
7227
7228
7229
7230 if (XSyncValueLow32 (value) % 4 == 2)
7231 XSyncIntToValue (&add, 3);
7232 else
7233 XSyncIntToValue (&add, 1);
7234
7235 XSyncValueAdd (&FRAME_X_COUNTER_VALUE (f),
7236 value, add, &overflow);
7237
7238 if (overflow)
7239 XSyncIntToValue (&FRAME_X_COUNTER_VALUE (f), 3);
7240
7241 eassert (XSyncValueLow32 (FRAME_X_COUNTER_VALUE (f)) % 4 == 1);
7242
7243 XSyncSetCounter (FRAME_X_DISPLAY (f),
7244 FRAME_X_EXTENDED_COUNTER (f),
7245 FRAME_X_COUNTER_VALUE (f));
7246 }
7247
7248 #ifdef HAVE_XSYNCTRIGGERFENCE
7249
7250
7251
7252
7253 static void
7254 x_sync_trigger_fence (struct frame *f, XSyncValue value)
7255 {
7256 uint_fast64_t n, low, high, idx;
7257
7258
7259 if (FRAME_DISPLAY_INFO (f)->xsync_major < 3
7260 || (FRAME_DISPLAY_INFO (f)->xsync_major == 3
7261 && FRAME_DISPLAY_INFO (f)->xsync_minor < 1))
7262 return;
7263
7264 low = XSyncValueLow32 (value);
7265 high = XSyncValueHigh32 (value);
7266
7267 n = low | (high << 32);
7268 idx = (n / 4) % 2;
7269
7270 #ifdef FRAME_DEBUG
7271 fprintf (stderr, "Triggering synchronization fence: %lu\n", idx);
7272 #endif
7273
7274 XSyncTriggerFence (FRAME_X_DISPLAY (f),
7275 FRAME_X_OUTPUT (f)->sync_fences[idx]);
7276 }
7277
7278
7279
7280 void
7281 x_sync_init_fences (struct frame *f)
7282 {
7283 struct x_output *output;
7284 struct x_display_info *dpyinfo;
7285
7286 output = FRAME_X_OUTPUT (f);
7287 dpyinfo = FRAME_DISPLAY_INFO (f);
7288
7289
7290 if (dpyinfo->xsync_major < 3
7291 || (dpyinfo->xsync_major == 3
7292 && dpyinfo->xsync_minor < 1))
7293 return;
7294
7295 output->sync_fences[0]
7296 = XSyncCreateFence (FRAME_X_DISPLAY (f),
7297
7298
7299
7300 FRAME_X_WINDOW (f),
7301 False);
7302 output->sync_fences[1]
7303 = XSyncCreateFence (FRAME_X_DISPLAY (f),
7304 FRAME_X_WINDOW (f),
7305 False);
7306
7307 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
7308 dpyinfo->Xatom_net_wm_sync_fences, XA_CARDINAL,
7309 32, PropModeReplace,
7310 (unsigned char *) &output->sync_fences, 2);
7311 }
7312
7313 static void
7314 x_sync_free_fences (struct frame *f)
7315 {
7316 if (FRAME_X_OUTPUT (f)->sync_fences[0] != None)
7317 XSyncDestroyFence (FRAME_X_DISPLAY (f),
7318 FRAME_X_OUTPUT (f)->sync_fences[0]);
7319
7320 if (FRAME_X_OUTPUT (f)->sync_fences[1] != None)
7321 XSyncDestroyFence (FRAME_X_DISPLAY (f),
7322 FRAME_X_OUTPUT (f)->sync_fences[1]);
7323 }
7324
7325 #endif
7326
7327
7328
7329
7330 static void
7331 x_sync_update_finish (struct frame *f)
7332 {
7333 XSyncValue value, add;
7334 Bool overflow;
7335
7336 if (FRAME_X_EXTENDED_COUNTER (f) == None)
7337 return;
7338
7339 value = FRAME_X_COUNTER_VALUE (f);
7340
7341 if (!(XSyncValueLow32 (value) % 2))
7342 return;
7343
7344 if ((XSyncValueLow32 (value) % 4) == 1)
7345
7346
7347 XSyncIntToValue (&add, 3);
7348 else
7349
7350
7351 XSyncIntToValue (&add, 1);
7352
7353 XSyncValueAdd (&FRAME_X_COUNTER_VALUE (f),
7354 value, add, &overflow);
7355
7356 if (overflow)
7357 XSyncIntToValue (&FRAME_X_COUNTER_VALUE (f), 0);
7358
7359
7360 #ifdef HAVE_XSYNCTRIGGERFENCE
7361 x_sync_trigger_fence (f, FRAME_X_COUNTER_VALUE (f));
7362 #endif
7363
7364 XSyncSetCounter (FRAME_X_DISPLAY (f),
7365 FRAME_X_EXTENDED_COUNTER (f),
7366 FRAME_X_COUNTER_VALUE (f));
7367
7368 if (FRAME_OUTPUT_DATA (f)->use_vsync_p)
7369 FRAME_X_WAITING_FOR_DRAW (f) = true;
7370 }
7371
7372
7373
7374 static void
7375 x_sync_handle_frame_drawn (struct x_display_info *dpyinfo,
7376 XEvent *message, struct frame *f)
7377 {
7378 XSyncValue value, counter;
7379
7380 if (FRAME_OUTER_WINDOW (f) == message->xclient.window)
7381 {
7382 counter = FRAME_X_COUNTER_VALUE (f);
7383
7384
7385
7386 XSyncIntsToValue (&value,
7387 message->xclient.data.l[0] & 0xffffffff,
7388 message->xclient.data.l[1] & 0xffffffff);
7389
7390 if (XSyncValueEqual (value, counter))
7391 FRAME_X_WAITING_FOR_DRAW (f) = false;
7392
7393
7394
7395
7396 FRAME_X_DRAW_JUST_HUNG (f) = false;
7397 }
7398
7399 x_sync_note_frame_times (dpyinfo, f, message);
7400 }
7401 #endif
7402
7403
7404
7405
7406
7407
7408
7409 static void
7410 x_update_begin (struct frame *f)
7411 {
7412 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
7413
7414
7415 #ifdef HAVE_XDBE
7416 if (!FRAME_X_DOUBLE_BUFFERED_P (f))
7417 #endif
7418 x_sync_update_begin (f);
7419 #else
7420
7421 #endif
7422
7423 #ifdef HAVE_XDBE
7424 if (FRAME_X_DOUBLE_BUFFERED_P (f))
7425
7426
7427 FRAME_X_COMPLETE_P (f) = false;
7428 #endif
7429 }
7430
7431
7432
7433 static void
7434 x_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
7435 {
7436 struct frame *f = XFRAME (WINDOW_FRAME (w));
7437 struct face *face;
7438
7439 face = FACE_FROM_ID_OR_NULL (f, VERTICAL_BORDER_FACE_ID);
7440 if (face)
7441 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
7442 face->foreground);
7443
7444 #ifdef USE_CAIRO
7445 x_fill_rectangle (f, f->output_data.x->normal_gc, x, y0, 1, y1 - y0, false);
7446 #else
7447 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
7448 f->output_data.x->normal_gc, x, y0, x, y1);
7449 #endif
7450 }
7451
7452
7453
7454 static void
7455 x_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
7456 {
7457 struct frame *f = XFRAME (WINDOW_FRAME (w));
7458 struct face *face = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FACE_ID);
7459 struct face *face_first
7460 = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID);
7461 struct face *face_last
7462 = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_LAST_PIXEL_FACE_ID);
7463 unsigned long color = face ? face->foreground : FRAME_FOREGROUND_PIXEL (f);
7464 unsigned long color_first = (face_first
7465 ? face_first->foreground
7466 : FRAME_FOREGROUND_PIXEL (f));
7467 unsigned long color_last = (face_last
7468 ? face_last->foreground
7469 : FRAME_FOREGROUND_PIXEL (f));
7470 Display *display = FRAME_X_DISPLAY (f);
7471
7472 if ((y1 - y0 > x1 - x0) && (x1 - x0 >= 3))
7473
7474
7475 {
7476 XSetForeground (display, f->output_data.x->normal_gc, color_first);
7477 x_fill_rectangle (f, f->output_data.x->normal_gc,
7478 x0, y0, 1, y1 - y0, false);
7479 XSetForeground (display, f->output_data.x->normal_gc, color);
7480 x_fill_rectangle (f, f->output_data.x->normal_gc,
7481 x0 + 1, y0, x1 - x0 - 2, y1 - y0, false);
7482 XSetForeground (display, f->output_data.x->normal_gc, color_last);
7483 x_fill_rectangle (f, f->output_data.x->normal_gc,
7484 x1 - 1, y0, 1, y1 - y0, false);
7485 }
7486 else if ((x1 - x0 > y1 - y0) && (y1 - y0 >= 3))
7487
7488
7489 {
7490 XSetForeground (display, f->output_data.x->normal_gc, color_first);
7491 x_fill_rectangle (f, f->output_data.x->normal_gc,
7492 x0, y0, x1 - x0, 1, false);
7493 XSetForeground (display, f->output_data.x->normal_gc, color);
7494 x_fill_rectangle (f, f->output_data.x->normal_gc,
7495 x0, y0 + 1, x1 - x0, y1 - y0 - 2, false);
7496 XSetForeground (display, f->output_data.x->normal_gc, color_last);
7497 x_fill_rectangle (f, f->output_data.x->normal_gc,
7498 x0, y1 - 1, x1 - x0, 1, false);
7499 }
7500 else
7501 {
7502
7503
7504 XSetForeground (display, f->output_data.x->normal_gc, color);
7505 x_fill_rectangle (f, f->output_data.x->normal_gc,
7506 x0, y0, x1 - x0, y1 - y0, false);
7507 }
7508 }
7509
7510 #ifdef HAVE_XDBE
7511
7512
7513
7514
7515
7516 static void
7517 show_back_buffer (struct frame *f)
7518 {
7519 XdbeSwapInfo swap_info;
7520 #ifdef USE_CAIRO
7521 cairo_t *cr;
7522 #endif
7523
7524 if (FRAME_X_DOUBLE_BUFFERED_P (f))
7525 {
7526 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
7527
7528
7529 x_sync_wait_for_frame_drawn_event (f);
7530
7531
7532 x_sync_update_begin (f);
7533 #endif
7534
7535 #ifdef USE_CAIRO
7536 cr = FRAME_CR_CONTEXT (f);
7537 if (cr)
7538 cairo_surface_flush (cairo_get_target (cr));
7539 #endif
7540 memset (&swap_info, 0, sizeof (swap_info));
7541 swap_info.swap_window = FRAME_X_WINDOW (f);
7542 swap_info.swap_action = XdbeCopied;
7543 XdbeSwapBuffers (FRAME_X_DISPLAY (f), &swap_info, 1);
7544
7545 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
7546
7547 x_sync_update_finish (f);
7548 #endif
7549 }
7550
7551 FRAME_X_NEED_BUFFER_FLIP (f) = false;
7552 }
7553
7554 #endif
7555
7556
7557
7558
7559 static void
7560 x_flip_and_flush (struct frame *f)
7561 {
7562
7563
7564
7565 if (!NILP (Vinhibit_redisplay)
7566
7567
7568 && !FRAME_TOOLTIP_P (f))
7569 return;
7570
7571 block_input ();
7572 #ifdef HAVE_XDBE
7573 if (FRAME_X_NEED_BUFFER_FLIP (f))
7574 show_back_buffer (f);
7575
7576
7577
7578 FRAME_X_COMPLETE_P (f) = true;
7579 #endif
7580 x_flush (f);
7581 unblock_input ();
7582 }
7583
7584
7585
7586
7587 static void
7588 x_update_end (struct frame *f)
7589 {
7590
7591 MOUSE_HL_INFO (f)->mouse_face_defer = false;
7592
7593 #ifdef USE_CAIRO
7594 # ifdef HAVE_XDBE
7595 if (!FRAME_X_DOUBLE_BUFFERED_P (f) && FRAME_CR_CONTEXT (f))
7596 cairo_surface_flush (cairo_get_target (FRAME_CR_CONTEXT (f)));
7597 # endif
7598 #endif
7599
7600
7601
7602
7603 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
7604 #ifdef HAVE_XDBE
7605 if (!FRAME_X_DOUBLE_BUFFERED_P (f))
7606 #endif
7607 x_sync_update_finish (f);
7608 #endif
7609 }
7610
7611
7612
7613
7614 static void
7615 XTframe_up_to_date (struct frame *f)
7616 {
7617 #if defined HAVE_XSYNC && defined HAVE_GTK3
7618 GtkWidget *widget;
7619 GdkWindow *window;
7620 GdkFrameClock *clock;
7621 #endif
7622
7623 eassert (FRAME_X_P (f));
7624 block_input ();
7625 FRAME_MOUSE_UPDATE (f);
7626
7627 #ifdef HAVE_XDBE
7628 if (!buffer_flipping_blocked_p ()
7629 && FRAME_X_NEED_BUFFER_FLIP (f))
7630 show_back_buffer (f);
7631
7632
7633 FRAME_X_COMPLETE_P (f) = true;
7634 #endif
7635
7636 #ifdef HAVE_XSYNC
7637 #ifndef HAVE_GTK3
7638 if (FRAME_X_OUTPUT (f)->sync_end_pending_p
7639 && FRAME_X_BASIC_COUNTER (f) != None)
7640 {
7641 XSyncSetCounter (FRAME_X_DISPLAY (f),
7642 FRAME_X_BASIC_COUNTER (f),
7643 FRAME_X_OUTPUT (f)->pending_basic_counter_value);
7644 FRAME_X_OUTPUT (f)->sync_end_pending_p = false;
7645 }
7646 #else
7647 if (FRAME_X_OUTPUT (f)->xg_sync_end_pending_p)
7648 {
7649 widget = FRAME_GTK_OUTER_WIDGET (f);
7650 window = gtk_widget_get_window (widget);
7651 eassert (window);
7652 clock = gdk_window_get_frame_clock (window);
7653 eassert (clock);
7654
7655 gdk_frame_clock_request_phase (clock,
7656 GDK_FRAME_CLOCK_PHASE_AFTER_PAINT);
7657 FRAME_X_OUTPUT (f)->xg_sync_end_pending_p = false;
7658 }
7659 #endif
7660 #endif
7661 unblock_input ();
7662 }
7663
7664 #ifdef HAVE_XDBE
7665 static void
7666 XTbuffer_flipping_unblocked_hook (struct frame *f)
7667 {
7668 block_input ();
7669
7670 if (FRAME_X_NEED_BUFFER_FLIP (f))
7671 show_back_buffer (f);
7672
7673 unblock_input ();
7674 }
7675 #endif
7676
7677
7678
7679
7680
7681
7682
7683
7684
7685 void
7686 x_clear_under_internal_border (struct frame *f)
7687 {
7688 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0)
7689 {
7690 int border = FRAME_INTERNAL_BORDER_WIDTH (f);
7691 int width = FRAME_PIXEL_WIDTH (f);
7692 int height = FRAME_PIXEL_HEIGHT (f);
7693 int margin = FRAME_TOP_MARGIN_HEIGHT (f);
7694 int bottom_margin = FRAME_BOTTOM_MARGIN_HEIGHT (f);
7695 int face_id = (FRAME_PARENT_FRAME (f)
7696 ? (!NILP (Vface_remapping_alist)
7697 ? lookup_basic_face (NULL, f,
7698 CHILD_FRAME_BORDER_FACE_ID)
7699 : CHILD_FRAME_BORDER_FACE_ID)
7700 : (!NILP (Vface_remapping_alist)
7701 ? lookup_basic_face (NULL, f,
7702 INTERNAL_BORDER_FACE_ID)
7703 : INTERNAL_BORDER_FACE_ID));
7704 struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
7705
7706 if (face)
7707 {
7708 unsigned long color = face->background;
7709 Display *display = FRAME_X_DISPLAY (f);
7710 GC gc = f->output_data.x->normal_gc;
7711
7712 XSetForeground (display, gc, color);
7713 x_fill_rectangle (f, gc, 0, margin, width, border, false);
7714 x_fill_rectangle (f, gc, 0, 0, border, height, false);
7715 x_fill_rectangle (f, gc, width - border, 0, border, height, false);
7716 x_fill_rectangle (f, gc, 0, height - bottom_margin - border,
7717 width, border, false);
7718 XSetForeground (display, gc, FRAME_FOREGROUND_PIXEL (f));
7719 }
7720 else
7721 {
7722 x_clear_area (f, 0, 0, border, height);
7723 x_clear_area (f, 0, margin, width, border);
7724 x_clear_area (f, width - border, 0, border, height);
7725 x_clear_area (f, 0, height - bottom_margin - border,
7726 width, border);
7727 }
7728 }
7729 }
7730
7731
7732
7733
7734
7735
7736
7737 static void
7738 x_after_update_window_line (struct window *w, struct glyph_row *desired_row)
7739 {
7740 eassert (w);
7741
7742 if (!desired_row->mode_line_p && !w->pseudo_window_p)
7743 desired_row->redraw_fringe_bitmaps_p = true;
7744
7745 #ifdef USE_X_TOOLKIT
7746
7747
7748
7749
7750
7751
7752 {
7753 struct frame *f;
7754 int width, height;
7755
7756 if (windows_or_buffers_changed
7757 && desired_row->full_width_p
7758 && (f = XFRAME (w->frame),
7759 width = FRAME_INTERNAL_BORDER_WIDTH (f),
7760 width != 0)
7761 && (height = desired_row->visible_height,
7762 height > 0))
7763 {
7764 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
7765 int face_id =
7766 (FRAME_PARENT_FRAME (f)
7767 ? (!NILP (Vface_remapping_alist)
7768 ? lookup_basic_face (NULL, f, CHILD_FRAME_BORDER_FACE_ID)
7769 : CHILD_FRAME_BORDER_FACE_ID)
7770 : (!NILP (Vface_remapping_alist)
7771 ? lookup_basic_face (NULL, f, INTERNAL_BORDER_FACE_ID)
7772 : INTERNAL_BORDER_FACE_ID));
7773 struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
7774
7775 if (face)
7776 {
7777 unsigned long color = face->background;
7778 Display *display = FRAME_X_DISPLAY (f);
7779 GC gc = f->output_data.x->normal_gc;
7780
7781 XSetForeground (display, gc, color);
7782 x_fill_rectangle (f, gc, 0, y, width, height, true);
7783 x_fill_rectangle (f, gc, FRAME_PIXEL_WIDTH (f) - width, y,
7784 width, height, true);
7785 XSetForeground (display, gc, FRAME_FOREGROUND_PIXEL (f));
7786 }
7787 else
7788 {
7789 x_clear_area (f, 0, y, width, height);
7790 x_clear_area (f, FRAME_PIXEL_WIDTH (f) - width, y, width, height);
7791 }
7792 }
7793 }
7794 #endif
7795 }
7796
7797
7798
7799
7800
7801
7802
7803
7804 #ifndef USE_CAIRO
7805
7806 static unsigned long
7807 x_premultiply_pixel (struct x_display_info *dpyinfo,
7808 XColor *color, double alpha)
7809 {
7810 unsigned long pixel;
7811
7812 eassert (dpyinfo->alpha_bits);
7813
7814
7815 color->red *= alpha;
7816 color->green *= alpha;
7817 color->blue *= alpha;
7818
7819
7820 pixel = x_make_truecolor_pixel (dpyinfo, color->red,
7821 color->green,
7822 color->blue);
7823
7824
7825 pixel &= ~dpyinfo->alpha_mask;
7826
7827
7828 pixel |= (((unsigned long) (alpha * 65535)
7829 >> (16 - dpyinfo->alpha_bits))
7830 << dpyinfo->alpha_offset);
7831
7832 return pixel;
7833 }
7834
7835 #endif
7836
7837 static void
7838 x_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
7839 struct draw_fringe_bitmap_params *p)
7840 {
7841 struct frame *f = XFRAME (WINDOW_FRAME (w));
7842 Display *display = FRAME_X_DISPLAY (f);
7843 GC gc = f->output_data.x->normal_gc;
7844 struct face *face = p->face;
7845
7846
7847 x_clip_to_row (w, row, ANY_AREA, gc);
7848
7849 if (p->bx >= 0 && !p->overlay_p)
7850 {
7851
7852
7853
7854
7855 if (face->stipple)
7856 {
7857 XSetFillStyle (display, face->gc, FillOpaqueStippled);
7858 x_fill_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny,
7859 true);
7860 XSetFillStyle (display, face->gc, FillSolid);
7861
7862 row->stipple_p = true;
7863 }
7864 else
7865 {
7866 XSetBackground (display, face->gc, face->background);
7867 x_clear_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny,
7868 true);
7869 XSetForeground (display, face->gc, face->foreground);
7870 }
7871 }
7872
7873 #ifdef USE_CAIRO
7874 if (p->which
7875 && p->which < max_fringe_bmp
7876 && p->which < max_used_fringe_bitmap)
7877 {
7878 XGCValues gcv;
7879
7880 XGetGCValues (display, gc, GCForeground | GCBackground, &gcv);
7881 XSetForeground (display, gc, (p->cursor_p
7882 ? (p->overlay_p ? face->background
7883 : f->output_data.x->cursor_pixel)
7884 : face->foreground));
7885 XSetBackground (display, gc, face->background);
7886 if (!fringe_bmp[p->which])
7887 {
7888
7889
7890
7891
7892
7893
7894 gui_define_fringe_bitmap (f, p->which);
7895 }
7896 x_cr_draw_image (f, gc, fringe_bmp[p->which], 0, p->dh,
7897 p->wd, p->h, p->x, p->y, p->overlay_p);
7898 XSetForeground (display, gc, gcv.foreground);
7899 XSetBackground (display, gc, gcv.background);
7900 }
7901 #else
7902 if (p->which)
7903 {
7904 Drawable drawable = FRAME_X_DRAWABLE (f);
7905 char *bits;
7906 Pixmap pixmap, clipmask = None;
7907 int depth = FRAME_DISPLAY_INFO (f)->n_planes;
7908 XGCValues gcv;
7909 unsigned long background = face->background;
7910 XColor bg;
7911 #ifdef HAVE_XRENDER
7912 Picture picture = None;
7913 XRenderPictureAttributes attrs;
7914
7915 memset (&attrs, 0, sizeof attrs);
7916 #endif
7917
7918 if (p->wd > 8)
7919 bits = (char *) (p->bits + p->dh);
7920 else
7921 bits = (char *) p->bits + p->dh;
7922
7923 if (FRAME_DISPLAY_INFO (f)->alpha_bits
7924 && f->alpha_background < 1.0)
7925 {
7926
7927
7928 bg.pixel = background;
7929 x_query_colors (f, &bg, 1);
7930
7931 background
7932 = x_premultiply_pixel (FRAME_DISPLAY_INFO (f),
7933 &bg,
7934 f->alpha_background);
7935 }
7936
7937
7938
7939 pixmap = XCreatePixmapFromBitmapData (display, drawable, bits, p->wd, p->h,
7940 (p->cursor_p
7941 ? (p->overlay_p ? face->background
7942 : f->output_data.x->cursor_pixel)
7943 : face->foreground),
7944 background, depth);
7945
7946 #ifdef HAVE_XRENDER
7947 if (FRAME_X_PICTURE_FORMAT (f)
7948 && (x_xr_ensure_picture (f), FRAME_X_PICTURE (f)))
7949 picture = XRenderCreatePicture (display, pixmap,
7950 FRAME_X_PICTURE_FORMAT (f),
7951 0, &attrs);
7952 #endif
7953
7954 if (p->overlay_p)
7955 {
7956 clipmask = XCreatePixmapFromBitmapData (display,
7957 FRAME_DISPLAY_INFO (f)->root_window,
7958 bits, p->wd, p->h,
7959 1, 0, 1);
7960
7961 #ifdef HAVE_XRENDER
7962 if (picture != None)
7963 {
7964 attrs.clip_mask = clipmask;
7965 attrs.clip_x_origin = p->x;
7966 attrs.clip_y_origin = p->y;
7967
7968 XRenderChangePicture (display, FRAME_X_PICTURE (f),
7969 CPClipMask | CPClipXOrigin | CPClipYOrigin,
7970 &attrs);
7971 }
7972 else
7973 #endif
7974 {
7975 gcv.clip_mask = clipmask;
7976 gcv.clip_x_origin = p->x;
7977 gcv.clip_y_origin = p->y;
7978 XChangeGC (display, gc, GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv);
7979 }
7980 }
7981
7982 #ifdef HAVE_XRENDER
7983 if (picture != None)
7984 {
7985 x_xr_apply_ext_clip (f, gc);
7986 XRenderComposite (display, PictOpSrc, picture,
7987 None, FRAME_X_PICTURE (f),
7988 0, 0, 0, 0, p->x, p->y, p->wd, p->h);
7989 x_xr_reset_ext_clip (f);
7990
7991 XRenderFreePicture (display, picture);
7992 }
7993 else
7994 #endif
7995 XCopyArea (display, pixmap, drawable, gc, 0, 0,
7996 p->wd, p->h, p->x, p->y);
7997 XFreePixmap (display, pixmap);
7998
7999 if (p->overlay_p)
8000 {
8001 gcv.clip_mask = (Pixmap) 0;
8002 XChangeGC (display, gc, GCClipMask, &gcv);
8003 XFreePixmap (display, clipmask);
8004 }
8005 }
8006 #endif
8007
8008 x_reset_clip_rectangles (f, gc);
8009 }
8010
8011
8012
8013
8014
8015 static bool x_alloc_lighter_color (struct frame *, Display *, Colormap,
8016 unsigned long *, double, int);
8017 static void x_scroll_bar_clear (struct frame *);
8018
8019 #ifdef GLYPH_DEBUG
8020 static void x_check_font (struct frame *, struct font *);
8021 #endif
8022
8023
8024
8025
8026
8027
8028
8029
8030
8031
8032
8033
8034
8035
8036
8037
8038
8039
8040
8041
8042
8043
8044
8045 static void
8046 x_display_set_last_user_time (struct x_display_info *dpyinfo, Time time,
8047 bool send_event, bool set_property)
8048 {
8049 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
8050 uint_fast64_t monotonic_time;
8051 uint_fast64_t monotonic_ms;
8052 int_fast64_t diff_ms;
8053 #endif
8054 #ifndef USE_GTK
8055 struct frame *focus_frame;
8056 Time old_time;
8057
8058 focus_frame = dpyinfo->x_focus_frame;
8059 old_time = dpyinfo->last_user_time;
8060 #endif
8061
8062 #ifdef ENABLE_CHECKING
8063 eassert (time <= X_ULONG_MAX);
8064 #endif
8065
8066 if (!send_event || time > dpyinfo->last_user_time)
8067 dpyinfo->last_user_time = time;
8068
8069 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
8070 if (!send_event)
8071 {
8072
8073
8074 monotonic_time = x_sync_current_monotonic_time ();
8075 monotonic_ms = monotonic_time / 1000;
8076
8077 dpyinfo->server_time_monotonic_p
8078 = (monotonic_time != 0
8079 && !ckd_sub (&diff_ms, time, monotonic_ms)
8080 && -500 < diff_ms && diff_ms < 500);
8081
8082 if (!dpyinfo->server_time_monotonic_p)
8083 {
8084
8085
8086
8087 if (!monotonic_time
8088 || ckd_mul (&dpyinfo->server_time_offset, time, 1000)
8089 || ckd_sub (&dpyinfo->server_time_offset,
8090 dpyinfo->server_time_offset, monotonic_time))
8091 dpyinfo->server_time_offset = 0;
8092
8093
8094
8095
8096
8097
8098 monotonic_ms = monotonic_ms & 0xffffffff;
8099 if (!ckd_sub (&diff_ms, time, monotonic_ms)
8100 && -500 < diff_ms && diff_ms < 500)
8101 {
8102
8103
8104
8105 if (ckd_sub (&dpyinfo->server_time_offset,
8106 monotonic_time / 1000, monotonic_ms)
8107 || ckd_mul (&dpyinfo->server_time_offset,
8108 dpyinfo->server_time_offset, 1000)
8109 || ckd_sub (&dpyinfo->server_time_offset,
8110 0, dpyinfo->server_time_offset))
8111 dpyinfo->server_time_offset = 0;
8112 }
8113 }
8114 }
8115 #endif
8116
8117 #ifndef USE_GTK
8118
8119 if (focus_frame && old_time != dpyinfo->last_user_time
8120 && set_property)
8121 {
8122 time = dpyinfo->last_user_time;
8123
8124 while (FRAME_PARENT_FRAME (focus_frame))
8125 focus_frame = FRAME_PARENT_FRAME (focus_frame);
8126
8127 if (FRAME_X_OUTPUT (focus_frame)->user_time_window != None)
8128 XChangeProperty (dpyinfo->display,
8129 FRAME_X_OUTPUT (focus_frame)->user_time_window,
8130 dpyinfo->Xatom_net_wm_user_time,
8131 XA_CARDINAL, 32, PropModeReplace,
8132 (unsigned char *) &time, 1);
8133 }
8134 #endif
8135 }
8136
8137 #ifdef USE_GTK
8138
8139 static void
8140 x_set_gtk_user_time (struct frame *f, Time time)
8141 {
8142 GtkWidget *widget;
8143 GdkWindow *window;
8144
8145 widget = FRAME_GTK_OUTER_WIDGET (f);
8146 window = gtk_widget_get_window (widget);
8147
8148
8149 if (!window)
8150 return;
8151
8152 gdk_x11_window_set_user_time (window, time);
8153 }
8154
8155 #endif
8156
8157 #if !defined USE_GTK || defined HAVE_XFIXES
8158
8159
8160
8161
8162
8163
8164 static Window
8165 x_create_special_window (struct x_display_info *dpyinfo,
8166 Window parent_window)
8167 {
8168 XSetWindowAttributes attrs;
8169
8170 attrs.override_redirect = True;
8171
8172 return XCreateWindow (dpyinfo->display, parent_window,
8173 -1, -1, 1, 1, 0, CopyFromParent, InputOnly,
8174 CopyFromParent, CWOverrideRedirect, &attrs);
8175 }
8176
8177 #endif
8178
8179
8180
8181
8182 #ifndef USE_GTK
8183
8184 static void
8185 x_update_frame_user_time_window (struct frame *f)
8186 {
8187 struct x_output *output;
8188 struct x_display_info *dpyinfo;
8189
8190 output = FRAME_X_OUTPUT (f);
8191 dpyinfo = FRAME_DISPLAY_INFO (f);
8192
8193 if (!NILP (Vx_no_window_manager)
8194 || !x_wm_supports (f, dpyinfo->Xatom_net_wm_user_time))
8195 {
8196 if (output->user_time_window != None
8197 && output->user_time_window != FRAME_OUTER_WINDOW (f))
8198 {
8199 XDestroyWindow (dpyinfo->display, output->user_time_window);
8200 XDeleteProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
8201 dpyinfo->Xatom_net_wm_user_time_window);
8202 }
8203 else
8204 XDeleteProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
8205 dpyinfo->Xatom_net_wm_user_time);
8206
8207 output->user_time_window = None;
8208 return;
8209 }
8210
8211 if (!x_wm_supports (f, dpyinfo->Xatom_net_wm_user_time_window))
8212 {
8213 if (output->user_time_window == None)
8214 output->user_time_window = FRAME_OUTER_WINDOW (f);
8215 else if (output->user_time_window != FRAME_OUTER_WINDOW (f))
8216 {
8217 XDestroyWindow (dpyinfo->display,
8218 output->user_time_window);
8219 XDeleteProperty (dpyinfo->display,
8220 FRAME_OUTER_WINDOW (f),
8221 dpyinfo->Xatom_net_wm_user_time_window);
8222 output->user_time_window = FRAME_OUTER_WINDOW (f);
8223 }
8224 }
8225 else
8226 {
8227 if (output->user_time_window == FRAME_OUTER_WINDOW (f)
8228 || output->user_time_window == None)
8229 {
8230
8231
8232
8233
8234
8235
8236
8237
8238 output->user_time_window
8239 = x_create_special_window (dpyinfo, FRAME_X_WINDOW (f));
8240
8241 XDeleteProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
8242 dpyinfo->Xatom_net_wm_user_time);
8243 XChangeProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
8244 dpyinfo->Xatom_net_wm_user_time_window,
8245 XA_WINDOW, 32, PropModeReplace,
8246 (unsigned char *) &output->user_time_window, 1);
8247 }
8248 }
8249 }
8250
8251 #endif
8252
8253 void
8254 x_set_last_user_time_from_lisp (struct x_display_info *dpyinfo,
8255 Time time)
8256 {
8257 x_display_set_last_user_time (dpyinfo, time, true, true);
8258 }
8259
8260
8261
8262
8263
8264 static void
8265 x_set_cursor_gc (struct glyph_string *s)
8266 {
8267 if (s->font == FRAME_FONT (s->f)
8268 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
8269 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
8270 && !s->cmp)
8271 s->gc = s->f->output_data.x->cursor_gc;
8272 else
8273 {
8274
8275 XGCValues xgcv;
8276 unsigned long mask;
8277 Display *display = FRAME_X_DISPLAY (s->f);
8278
8279 xgcv.background = s->f->output_data.x->cursor_pixel;
8280 xgcv.foreground = s->face->background;
8281
8282
8283 if (xgcv.foreground == xgcv.background)
8284 xgcv.foreground = s->face->foreground;
8285 if (xgcv.foreground == xgcv.background)
8286 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
8287 if (xgcv.foreground == xgcv.background)
8288 xgcv.foreground = s->face->foreground;
8289
8290
8291 if (xgcv.background == s->face->background
8292 && xgcv.foreground == s->face->foreground)
8293 {
8294 xgcv.background = s->face->foreground;
8295 xgcv.foreground = s->face->background;
8296 }
8297
8298 IF_DEBUG (x_check_font (s->f, s->font));
8299 xgcv.graphics_exposures = False;
8300 xgcv.line_width = 1;
8301 mask = (GCForeground | GCBackground
8302 | GCGraphicsExposures
8303 | GCLineWidth);
8304
8305 if (FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc)
8306 XChangeGC (display, FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc,
8307 mask, &xgcv);
8308 else
8309 FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc
8310 = XCreateGC (display, FRAME_X_DRAWABLE (s->f), mask, &xgcv);
8311
8312 s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc;
8313 }
8314 }
8315
8316
8317
8318
8319 static void
8320 x_set_mouse_face_gc (struct glyph_string *s)
8321 {
8322 if (s->font == s->face->font)
8323 s->gc = s->face->gc;
8324 else
8325 {
8326
8327
8328 XGCValues xgcv;
8329 unsigned long mask;
8330 Display *display = FRAME_X_DISPLAY (s->f);
8331
8332 xgcv.background = s->face->background;
8333 xgcv.foreground = s->face->foreground;
8334 xgcv.graphics_exposures = False;
8335 xgcv.line_width = 1;
8336
8337 mask = (GCForeground | GCBackground
8338 | GCGraphicsExposures
8339 | GCLineWidth);
8340
8341 if (FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc)
8342 XChangeGC (display, FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc,
8343 mask, &xgcv);
8344 else
8345 FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc
8346 = XCreateGC (display, FRAME_X_DRAWABLE (s->f), mask, &xgcv);
8347
8348 s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc;
8349
8350 }
8351 eassert (s->gc != 0);
8352 }
8353
8354
8355
8356
8357
8358
8359 static void
8360 x_set_mode_line_face_gc (struct glyph_string *s)
8361 {
8362 s->gc = s->face->gc;
8363 }
8364
8365
8366
8367
8368
8369
8370 static void
8371 x_set_glyph_string_gc (struct glyph_string *s)
8372 {
8373 prepare_face_for_display (s->f, s->face);
8374
8375 if (s->hl == DRAW_NORMAL_TEXT)
8376 {
8377 s->gc = s->face->gc;
8378 s->stippled_p = s->face->stipple != 0;
8379 }
8380 else if (s->hl == DRAW_INVERSE_VIDEO)
8381 {
8382 x_set_mode_line_face_gc (s);
8383 s->stippled_p = s->face->stipple != 0;
8384 }
8385 else if (s->hl == DRAW_CURSOR)
8386 {
8387 x_set_cursor_gc (s);
8388 s->stippled_p = false;
8389 }
8390 else if (s->hl == DRAW_MOUSE_FACE)
8391 {
8392 x_set_mouse_face_gc (s);
8393 s->stippled_p = s->face->stipple != 0;
8394 }
8395 else if (s->hl == DRAW_IMAGE_RAISED
8396 || s->hl == DRAW_IMAGE_SUNKEN)
8397 {
8398 s->gc = s->face->gc;
8399 s->stippled_p = s->face->stipple != 0;
8400 }
8401 else
8402 emacs_abort ();
8403
8404
8405 eassert (s->gc != 0);
8406 }
8407
8408
8409
8410
8411
8412 static void
8413 x_set_glyph_string_clipping (struct glyph_string *s)
8414 {
8415 XRectangle *r = s->clip;
8416 int n = get_glyph_string_clip_rects (s, r, 2);
8417
8418 if (n > 0)
8419 x_set_clip_rectangles (s->f, s->gc, r, n);
8420 s->num_clips = n;
8421 }
8422
8423
8424
8425
8426
8427
8428 static void
8429 x_set_glyph_string_clipping_exactly (struct glyph_string *src, struct glyph_string *dst)
8430 {
8431 XRectangle r;
8432
8433 r.x = src->x;
8434 r.width = src->width;
8435 r.y = src->y;
8436 r.height = src->height;
8437 dst->clip[0] = r;
8438 dst->num_clips = 1;
8439 x_set_clip_rectangles (dst->f, dst->gc, &r, 1);
8440 }
8441
8442
8443
8444
8445
8446 static void
8447 x_compute_glyph_string_overhangs (struct glyph_string *s)
8448 {
8449 if (s->cmp == NULL
8450 && (s->first_glyph->type == CHAR_GLYPH
8451 || s->first_glyph->type == COMPOSITE_GLYPH))
8452 {
8453 struct font_metrics metrics;
8454
8455 if (s->first_glyph->type == CHAR_GLYPH)
8456 {
8457 struct font *font = s->font;
8458 font->driver->text_extents (font, s->char2b, s->nchars, &metrics);
8459 }
8460 else
8461 {
8462 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
8463
8464 composition_gstring_width (gstring, s->cmp_from, s->cmp_to, &metrics);
8465 }
8466 s->right_overhang = (metrics.rbearing > metrics.width
8467 ? metrics.rbearing - metrics.width : 0);
8468 s->left_overhang = metrics.lbearing < 0 ? - metrics.lbearing : 0;
8469 }
8470 else if (s->cmp)
8471 {
8472 s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width;
8473 s->left_overhang = - s->cmp->lbearing;
8474 }
8475 }
8476
8477
8478
8479
8480 static void
8481 x_clear_glyph_string_rect (struct glyph_string *s, int x, int y, int w, int h)
8482 {
8483 x_clear_rectangle (s->f, s->gc, x, y, w, h, s->hl != DRAW_CURSOR);
8484 }
8485
8486 #ifndef USE_CAIRO
8487
8488 static void
8489 x_clear_point (struct frame *f, GC gc, int x, int y,
8490 bool respect_alpha_background)
8491 {
8492 XGCValues xgcv;
8493 Display *dpy;
8494
8495 dpy = FRAME_X_DISPLAY (f);
8496
8497 if (f->alpha_background != 1.0
8498 && respect_alpha_background)
8499 {
8500 x_clear_rectangle (f, gc, x, y, 1, 1, true);
8501 return;
8502 }
8503
8504 XGetGCValues (dpy, gc, GCBackground | GCForeground, &xgcv);
8505 XSetForeground (dpy, gc, xgcv.background);
8506 XDrawPoint (dpy, FRAME_X_DRAWABLE (f), gc, x, y);
8507 XSetForeground (dpy, gc, xgcv.foreground);
8508 }
8509
8510 #endif
8511
8512
8513
8514
8515
8516
8517
8518 static void
8519 x_draw_glyph_string_background (struct glyph_string *s, bool force_p)
8520 {
8521
8522
8523 if (!s->background_filled_p)
8524 {
8525 int box_line_width = max (s->face->box_horizontal_line_width, 0);
8526
8527 if (s->stippled_p)
8528 {
8529 Display *display = FRAME_X_DISPLAY (s->f);
8530
8531
8532 XSetFillStyle (display, s->gc, FillOpaqueStippled);
8533 x_fill_rectangle (s->f, s->gc, s->x,
8534 s->y + box_line_width,
8535 s->background_width,
8536 s->height - 2 * box_line_width,
8537 s->hl != DRAW_CURSOR);
8538 XSetFillStyle (display, s->gc, FillSolid);
8539 s->background_filled_p = true;
8540 }
8541 else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
8542
8543
8544
8545
8546 || FONT_TOO_HIGH (s->font)
8547 || s->font_not_found_p
8548 || s->extends_to_end_of_line_p
8549 || force_p)
8550 {
8551 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
8552 s->background_width,
8553 s->height - 2 * box_line_width);
8554 s->background_filled_p = true;
8555 }
8556 }
8557 }
8558
8559
8560
8561
8562 static void
8563 x_draw_glyph_string_foreground (struct glyph_string *s)
8564 {
8565 int i, x;
8566
8567
8568
8569 if (s->face->box != FACE_NO_BOX
8570 && s->first_glyph->left_box_line_p)
8571 x = s->x + max (s->face->box_vertical_line_width, 0);
8572 else
8573 x = s->x;
8574
8575
8576
8577 if (s->font_not_found_p)
8578 {
8579 for (i = 0; i < s->nchars; ++i)
8580 {
8581 struct glyph *g = s->first_glyph + i;
8582 x_draw_rectangle (s->f,
8583 s->gc, x, s->y, g->pixel_width - 1,
8584 s->height - 1);
8585 x += g->pixel_width;
8586 }
8587 }
8588 else
8589 {
8590 struct font *font = s->font;
8591 #ifdef USE_CAIRO
8592 if (!EQ (font->driver->type, Qx)
8593 || x_try_cr_xlib_drawable (s->f, s->gc))
8594 {
8595 #endif
8596 int boff = font->baseline_offset;
8597 int y;
8598
8599 if (font->vertical_centering)
8600 boff = VCENTER_BASELINE_OFFSET (font, s->f) - boff;
8601
8602 y = s->ybase - boff;
8603 if (s->for_overlaps
8604 || (s->background_filled_p && s->hl != DRAW_CURSOR))
8605 font->driver->draw (s, 0, s->nchars, x, y, false);
8606 else
8607 font->driver->draw (s, 0, s->nchars, x, y, true);
8608 if (s->face->overstrike)
8609 font->driver->draw (s, 0, s->nchars, x + 1, y, false);
8610 #ifdef USE_CAIRO
8611 if (EQ (font->driver->type, Qx))
8612 x_end_cr_xlib_drawable (s->f, s->gc);
8613 }
8614 else
8615 {
8616
8617
8618 if (!(s->for_overlaps
8619 || (s->background_filled_p && s->hl != DRAW_CURSOR)))
8620 {
8621 int box_line_width = max (s->face->box_horizontal_line_width, 0);
8622
8623 if (s->stippled_p)
8624 {
8625 Display *display = FRAME_X_DISPLAY (s->f);
8626
8627
8628 XSetFillStyle (display, s->gc, FillOpaqueStippled);
8629 x_fill_rectangle (s->f, s->gc, s->x,
8630 s->y + box_line_width,
8631 s->background_width,
8632 s->height - 2 * box_line_width,
8633 false);
8634 XSetFillStyle (display, s->gc, FillSolid);
8635 }
8636 else
8637 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
8638 s->background_width,
8639 s->height - 2 * box_line_width);
8640 }
8641 for (i = 0; i < s->nchars; ++i)
8642 {
8643 struct glyph *g = s->first_glyph + i;
8644 x_draw_rectangle (s->f,
8645 s->gc, x, s->y, g->pixel_width - 1,
8646 s->height - 1);
8647 x += g->pixel_width;
8648 }
8649 }
8650 #endif
8651 }
8652 }
8653
8654
8655
8656 static void
8657 x_draw_composite_glyph_string_foreground (struct glyph_string *s)
8658 {
8659 int i, j, x;
8660 struct font *font = s->font;
8661
8662
8663
8664 if (s->face && s->face->box != FACE_NO_BOX
8665 && s->first_glyph->left_box_line_p)
8666 x = s->x + max (s->face->box_vertical_line_width, 0);
8667 else
8668 x = s->x;
8669
8670
8671
8672
8673
8674
8675
8676
8677 if (s->font_not_found_p)
8678 {
8679 if (s->cmp_from == 0)
8680 x_draw_rectangle (s->f, s->gc, x, s->y,
8681 s->width - 1, s->height - 1);
8682 }
8683 else
8684 #ifdef USE_CAIRO
8685 if (!EQ (font->driver->type, Qx)
8686 || x_try_cr_xlib_drawable (s->f, s->gc))
8687 {
8688 #endif
8689 if (! s->first_glyph->u.cmp.automatic)
8690 {
8691 int y = s->ybase;
8692
8693 for (i = 0, j = s->cmp_from; i < s->nchars; i++, j++)
8694
8695
8696 if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
8697 {
8698 int xx = x + s->cmp->offsets[j * 2];
8699 int yy = y - s->cmp->offsets[j * 2 + 1];
8700
8701 font->driver->draw (s, j, j + 1, xx, yy, false);
8702 if (s->face->overstrike)
8703 font->driver->draw (s, j, j + 1, xx + 1, yy, false);
8704 }
8705 }
8706 else
8707 {
8708 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
8709 Lisp_Object glyph;
8710 int y = s->ybase;
8711 int width = 0;
8712
8713 for (i = j = s->cmp_from; i < s->cmp_to; i++)
8714 {
8715 glyph = LGSTRING_GLYPH (gstring, i);
8716 if (NILP (LGLYPH_ADJUSTMENT (glyph)))
8717 width += LGLYPH_WIDTH (glyph);
8718 else
8719 {
8720 int xoff, yoff, wadjust;
8721
8722 if (j < i)
8723 {
8724 font->driver->draw (s, j, i, x, y, false);
8725 if (s->face->overstrike)
8726 font->driver->draw (s, j, i, x + 1, y, false);
8727 x += width;
8728 }
8729 xoff = LGLYPH_XOFF (glyph);
8730 yoff = LGLYPH_YOFF (glyph);
8731 wadjust = LGLYPH_WADJUST (glyph);
8732 font->driver->draw (s, i, i + 1, x + xoff, y + yoff, false);
8733 if (s->face->overstrike)
8734 font->driver->draw (s, i, i + 1, x + xoff + 1, y + yoff,
8735 false);
8736 x += wadjust;
8737 j = i + 1;
8738 width = 0;
8739 }
8740 }
8741 if (j < i)
8742 {
8743 font->driver->draw (s, j, i, x, y, false);
8744 if (s->face->overstrike)
8745 font->driver->draw (s, j, i, x + 1, y, false);
8746 }
8747 }
8748 #ifdef USE_CAIRO
8749 if (EQ (font->driver->type, Qx))
8750 x_end_cr_xlib_drawable (s->f, s->gc);
8751 }
8752 else
8753 {
8754
8755
8756 if (s->cmp_from == 0)
8757 x_draw_rectangle (s->f, s->gc, x, s->y,
8758 s->width - 1, s->height - 1);
8759 }
8760 #endif
8761 }
8762
8763
8764
8765
8766 static void
8767 x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
8768 {
8769 struct glyph *glyph = s->first_glyph;
8770 unsigned char2b[8];
8771 int x, i, j;
8772
8773
8774
8775 if (s->face && s->face->box != FACE_NO_BOX
8776 && s->first_glyph->left_box_line_p)
8777 x = s->x + max (s->face->box_vertical_line_width, 0);
8778 else
8779 x = s->x;
8780
8781 s->char2b = char2b;
8782
8783 for (i = 0; i < s->nchars; i++, glyph++)
8784 {
8785 #ifdef GCC_LINT
8786 enum { PACIFY_GCC_BUG_81401 = 1 };
8787 #else
8788 enum { PACIFY_GCC_BUG_81401 = 0 };
8789 #endif
8790 char buf[7 + PACIFY_GCC_BUG_81401];
8791 char *str = NULL;
8792 int len = glyph->u.glyphless.len;
8793
8794 if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM)
8795 {
8796 if (len > 0
8797 && CHAR_TABLE_P (Vglyphless_char_display)
8798 && (CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display))
8799 >= 1))
8800 {
8801 Lisp_Object acronym
8802 = (! glyph->u.glyphless.for_no_font
8803 ? CHAR_TABLE_REF (Vglyphless_char_display,
8804 glyph->u.glyphless.ch)
8805 : XCHAR_TABLE (Vglyphless_char_display)->extras[0]);
8806 if (CONSP (acronym))
8807 acronym = XCAR (acronym);
8808 if (STRINGP (acronym))
8809 str = SSDATA (acronym);
8810 }
8811 }
8812 else if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE)
8813 {
8814 unsigned int ch = glyph->u.glyphless.ch;
8815 eassume (ch <= MAX_CHAR);
8816 sprintf (buf, "%0*X", ch < 0x10000 ? 4 : 6, ch);
8817 str = buf;
8818 }
8819
8820 if (str)
8821 {
8822 int upper_len = (len + 1) / 2;
8823
8824
8825 for (j = 0; j < len; j++)
8826 char2b[j] = s->font->driver->encode_char (s->font, str[j]) & 0xFFFF;
8827 s->font->driver->draw (s, 0, upper_len,
8828 x + glyph->slice.glyphless.upper_xoff,
8829 s->ybase + glyph->slice.glyphless.upper_yoff,
8830 false);
8831 s->font->driver->draw (s, upper_len, len,
8832 x + glyph->slice.glyphless.lower_xoff,
8833 s->ybase + glyph->slice.glyphless.lower_yoff,
8834 false);
8835 }
8836 if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE)
8837 x_draw_rectangle (s->f, s->gc,
8838 x, s->ybase - glyph->ascent,
8839 glyph->pixel_width - 1,
8840 glyph->ascent + glyph->descent - 1);
8841 x += glyph->pixel_width;
8842 }
8843
8844
8845
8846 s->char2b = NULL;
8847 }
8848
8849 #ifdef USE_X_TOOLKIT
8850
8851 #ifdef USE_LUCID
8852
8853
8854
8855
8856 static struct frame *
8857 x_frame_of_widget (Widget widget)
8858 {
8859 struct x_display_info *dpyinfo;
8860 Lisp_Object tail, frame;
8861 struct frame *f;
8862
8863 dpyinfo = x_display_info_for_display (XtDisplay (widget));
8864
8865
8866
8867
8868
8869 while (!XtIsTopLevelShell (widget))
8870 widget = XtParent (widget);
8871
8872
8873
8874 FOR_EACH_FRAME (tail, frame)
8875 {
8876 f = XFRAME (frame);
8877 if (FRAME_X_P (f)
8878 && FRAME_DISPLAY_INFO (f) == dpyinfo
8879 && f->output_data.x->widget == widget)
8880 return f;
8881 }
8882 emacs_abort ();
8883 }
8884
8885
8886
8887
8888
8889
8890
8891
8892 bool
8893 x_alloc_lighter_color_for_widget (Widget widget, Display *display, Colormap cmap,
8894 unsigned long *pixel, double factor, int delta)
8895 {
8896 struct frame *f = x_frame_of_widget (widget);
8897 return x_alloc_lighter_color (f, display, cmap, pixel, factor, delta);
8898 }
8899
8900 #endif
8901
8902
8903
8904
8905
8906 static XtConvertArgRec cvt_string_to_pixel_args[] =
8907 {
8908 {XtWidgetBaseOffset, (XtPointer) offsetof (WidgetRec, core.screen),
8909 sizeof (Screen *)},
8910 {XtWidgetBaseOffset, (XtPointer) offsetof (WidgetRec, core.colormap),
8911 sizeof (Colormap)}
8912 };
8913
8914
8915
8916
8917
8918 static Pixel cvt_string_to_pixel_value;
8919
8920
8921
8922
8923
8924
8925
8926
8927
8928
8929
8930
8931
8932
8933
8934
8935
8936
8937
8938 static Boolean
8939 cvt_string_to_pixel (Display *dpy, XrmValue *args, Cardinal *nargs,
8940 XrmValue *from, XrmValue *to,
8941 XtPointer *closure_ret)
8942 {
8943 Screen *screen;
8944 Colormap cmap;
8945 Pixel pixel;
8946 String color_name;
8947 XColor color;
8948
8949 if (*nargs != 2)
8950 {
8951 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
8952 "wrongParameters", "cvt_string_to_pixel",
8953 "XtToolkitError",
8954 "Screen and colormap args required", NULL, NULL);
8955 return False;
8956 }
8957
8958 screen = *(Screen **) args[0].addr;
8959 cmap = *(Colormap *) args[1].addr;
8960 color_name = (String) from->addr;
8961
8962 if (strcmp (color_name, XtDefaultBackground) == 0)
8963 {
8964 *closure_ret = (XtPointer) False;
8965 pixel = WhitePixelOfScreen (screen);
8966 }
8967 else if (strcmp (color_name, XtDefaultForeground) == 0)
8968 {
8969 *closure_ret = (XtPointer) False;
8970 pixel = BlackPixelOfScreen (screen);
8971 }
8972 else if (XParseColor (dpy, cmap, color_name, &color)
8973 && x_alloc_nearest_color_1 (dpy, cmap, &color))
8974 {
8975 pixel = color.pixel;
8976 *closure_ret = (XtPointer) True;
8977 }
8978 else
8979 {
8980 String params[1];
8981 Cardinal nparams = 1;
8982
8983 params[0] = color_name;
8984 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
8985 "badValue", "cvt_string_to_pixel",
8986 "XtToolkitError", "Invalid color '%s'",
8987 params, &nparams);
8988 return False;
8989 }
8990
8991 if (to->addr != NULL)
8992 {
8993 if (to->size < sizeof (Pixel))
8994 {
8995 to->size = sizeof (Pixel);
8996 return False;
8997 }
8998
8999 *(Pixel *) to->addr = pixel;
9000 }
9001 else
9002 {
9003 cvt_string_to_pixel_value = pixel;
9004 to->addr = (XtPointer) &cvt_string_to_pixel_value;
9005 }
9006
9007 to->size = sizeof (Pixel);
9008 return True;
9009 }
9010
9011
9012
9013
9014
9015
9016
9017
9018
9019
9020
9021
9022
9023
9024 static void
9025 cvt_pixel_dtor (XtAppContext app, XrmValuePtr to, XtPointer closure, XrmValuePtr args,
9026 Cardinal *nargs)
9027 {
9028 if (*nargs != 2)
9029 {
9030 XtAppWarningMsg (app, "wrongParameters", "cvt_pixel_dtor",
9031 "XtToolkitError",
9032 "Screen and colormap arguments required",
9033 NULL, NULL);
9034 }
9035 else if (closure != NULL)
9036 {
9037
9038 Screen *screen = *(Screen **) args[0].addr;
9039 Colormap cmap = *(Colormap *) args[1].addr;
9040 x_free_dpy_colors (DisplayOfScreen (screen), screen, cmap,
9041 (Pixel *) to->addr, 1);
9042 }
9043 }
9044
9045
9046 #endif
9047
9048
9049
9050
9051
9052
9053
9054 static const XColor *
9055 x_color_cells (Display *dpy, int *ncells)
9056 {
9057 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
9058 eassume (dpyinfo);
9059
9060 if (dpyinfo->color_cells == NULL)
9061 {
9062 int ncolor_cells = dpyinfo->visual_info.colormap_size;
9063 int i;
9064
9065 dpyinfo->color_cells = xnmalloc (ncolor_cells,
9066 sizeof *dpyinfo->color_cells);
9067 dpyinfo->ncolor_cells = ncolor_cells;
9068
9069 for (i = 0; i < ncolor_cells; ++i)
9070 dpyinfo->color_cells[i].pixel = i;
9071
9072 XQueryColors (dpy, dpyinfo->cmap,
9073 dpyinfo->color_cells, ncolor_cells);
9074 }
9075
9076 *ncells = dpyinfo->ncolor_cells;
9077 return dpyinfo->color_cells;
9078 }
9079
9080
9081
9082
9083
9084
9085
9086
9087
9088 void
9089 x_query_colors (struct frame *f, XColor *colors, int ncolors)
9090 {
9091 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
9092 int i;
9093
9094 if (dpyinfo->red_bits > 0)
9095 {
9096
9097
9098 unsigned int rmult, gmult, bmult;
9099 unsigned int rmask, gmask, bmask;
9100
9101 rmask = (1 << dpyinfo->red_bits) - 1;
9102 gmask = (1 << dpyinfo->green_bits) - 1;
9103 bmask = (1 << dpyinfo->blue_bits) - 1;
9104
9105
9106
9107
9108
9109
9110
9111
9112
9113
9114
9115
9116
9117 rmult = 0xffffffff / rmask;
9118 gmult = 0xffffffff / gmask;
9119 bmult = 0xffffffff / bmask;
9120
9121 for (i = 0; i < ncolors; ++i)
9122 {
9123 unsigned int r, g, b;
9124 unsigned long pixel = colors[i].pixel;
9125
9126 r = (pixel >> dpyinfo->red_offset) & rmask;
9127 g = (pixel >> dpyinfo->green_offset) & gmask;
9128 b = (pixel >> dpyinfo->blue_offset) & bmask;
9129
9130 colors[i].red = (r * rmult) >> 16;
9131 colors[i].green = (g * gmult) >> 16;
9132 colors[i].blue = (b * bmult) >> 16;
9133 }
9134
9135 return;
9136 }
9137
9138 if (dpyinfo->color_cells)
9139 {
9140 int i;
9141 for (i = 0; i < ncolors; ++i)
9142 {
9143 unsigned long pixel = colors[i].pixel;
9144 eassert (pixel < dpyinfo->ncolor_cells);
9145 eassert (dpyinfo->color_cells[pixel].pixel == pixel);
9146 colors[i] = dpyinfo->color_cells[pixel];
9147 }
9148 return;
9149 }
9150
9151 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
9152 }
9153
9154
9155
9156 static void
9157 x_query_frame_background_color (struct frame *f, XColor *bgcolor)
9158 {
9159 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
9160 #ifndef USE_CAIRO
9161 XColor bg;
9162 #endif
9163
9164 if (FRAME_DISPLAY_INFO (f)->alpha_bits)
9165 {
9166 #ifdef USE_CAIRO
9167 background = (background & ~FRAME_DISPLAY_INFO (f)->alpha_mask);
9168 background |= (((unsigned long) (f->alpha_background * 0xffff)
9169 >> (16 - FRAME_DISPLAY_INFO (f)->alpha_bits))
9170 << FRAME_DISPLAY_INFO (f)->alpha_offset);
9171 #else
9172 if (FRAME_DISPLAY_INFO (f)->alpha_bits
9173 && f->alpha_background < 1.0)
9174 {
9175 bg.pixel = background;
9176 x_query_colors (f, &bg, 1);
9177
9178 background
9179 = x_premultiply_pixel (FRAME_DISPLAY_INFO (f),
9180 &bg, f->alpha_background);
9181 }
9182 #endif
9183 }
9184
9185 bgcolor->pixel = background;
9186
9187 x_query_colors (f, bgcolor, 1);
9188 }
9189
9190 static unsigned int
9191 x_hash_string_ignore_case (const char *string)
9192 {
9193 unsigned int i;
9194
9195 i = 3323198485ul;
9196 for (; *string; ++string)
9197 {
9198 i ^= c_tolower (*string);
9199 i *= 0x5bd1e995;
9200 i ^= i >> 15;
9201 }
9202 return i;
9203 }
9204
9205
9206
9207
9208
9209
9210
9211 Status
9212 x_parse_color (struct frame *f, const char *color_name,
9213 XColor *color)
9214 {
9215 unsigned short r, g, b;
9216 Display *dpy;
9217 Colormap cmap;
9218 struct x_display_info *dpyinfo;
9219 struct color_name_cache_entry *cache_entry, *last;
9220 struct color_name_cache_entry *next, *color_entry;
9221 unsigned int hash, idx;
9222 int rc, i;
9223
9224
9225
9226
9227
9228
9229 if (parse_color_spec (color_name, &r, &g, &b))
9230 {
9231 color->red = r;
9232 color->green = g;
9233 color->blue = b;
9234
9235 return 1;
9236 }
9237
9238
9239 if (!strlen (color_name))
9240 return 0;
9241
9242 cmap = FRAME_X_COLORMAP (f);
9243 dpy = FRAME_X_DISPLAY (f);
9244 dpyinfo = FRAME_DISPLAY_INFO (f);
9245
9246 hash = x_hash_string_ignore_case (color_name);
9247 idx = hash % dpyinfo->color_names_size;
9248
9249 last = NULL;
9250
9251 for (cache_entry = dpyinfo->color_names[idx];
9252 cache_entry; cache_entry = cache_entry->next)
9253 {
9254 if (!xstrcasecmp (cache_entry->name, color_name))
9255 {
9256
9257
9258
9259 if (last)
9260 {
9261 last->next = cache_entry->next;
9262 cache_entry->next = dpyinfo->color_names[idx];
9263
9264 dpyinfo->color_names[idx] = cache_entry;
9265 }
9266
9267 if (cache_entry->valid)
9268 *color = cache_entry->rgb;
9269
9270 return cache_entry->valid;
9271 }
9272
9273 last = cache_entry;
9274 }
9275
9276 block_input ();
9277 rc = XParseColor (dpy, cmap, color_name, color);
9278 unblock_input ();
9279
9280 cache_entry = xzalloc (sizeof *cache_entry);
9281 dpyinfo->color_names_length[idx] += 1;
9282
9283 if (rc)
9284 cache_entry->rgb = *color;
9285
9286 cache_entry->valid = rc;
9287 cache_entry->name = xstrdup (color_name);
9288 cache_entry->next = dpyinfo->color_names[idx];
9289
9290 dpyinfo->color_names[idx] = cache_entry;
9291
9292
9293 if (dpyinfo->color_names_length[idx] > (x_color_cache_bucket_size > 0
9294 ? x_color_cache_bucket_size : 128))
9295 {
9296 i = 0;
9297
9298 for (last = dpyinfo->color_names[idx]; last; last = last->next)
9299 {
9300 if (++i == (x_color_cache_bucket_size > 0
9301 ? x_color_cache_bucket_size : 128))
9302 {
9303 next = last->next;
9304 last->next = NULL;
9305
9306 for (color_entry = next; color_entry; color_entry = last)
9307 {
9308 last = color_entry->next;
9309
9310 xfree (color_entry->name);
9311 xfree (color_entry);
9312
9313 dpyinfo->color_names_length[idx] -= 1;
9314 }
9315
9316 return rc;
9317 }
9318 }
9319 }
9320
9321 return rc;
9322 }
9323
9324
9325
9326
9327
9328
9329
9330 static bool
9331 x_alloc_nearest_color_1 (Display *dpy, Colormap cmap, XColor *color)
9332 {
9333 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
9334 bool rc;
9335
9336 eassume (dpyinfo);
9337 rc = XAllocColor (dpy, cmap, color) != 0;
9338
9339 if (dpyinfo->visual_info.class == DirectColor)
9340 return rc;
9341
9342 if (rc == 0)
9343 {
9344
9345
9346
9347
9348
9349 const XColor *cells;
9350 int no_cells;
9351 int nearest;
9352 long nearest_delta, trial_delta;
9353 int x;
9354 Status status;
9355 bool retry = false;
9356 int ncolor_cells, i;
9357 bool temp_allocated;
9358 XColor temp;
9359
9360 start:
9361 cells = x_color_cells (dpy, &no_cells);
9362 temp_allocated = false;
9363
9364 nearest = 0;
9365
9366 nearest_delta = ((((color->red >> 8) - (cells[0].red >> 8))
9367 * ((color->red >> 8) - (cells[0].red >> 8)))
9368 + (((color->green >> 8) - (cells[0].green >> 8))
9369 * ((color->green >> 8) - (cells[0].green >> 8)))
9370 + (((color->blue >> 8) - (cells[0].blue >> 8))
9371 * ((color->blue >> 8) - (cells[0].blue >> 8))));
9372 for (x = 1; x < no_cells; x++)
9373 {
9374 trial_delta = ((((color->red >> 8) - (cells[x].red >> 8))
9375 * ((color->red >> 8) - (cells[x].red >> 8)))
9376 + (((color->green >> 8) - (cells[x].green >> 8))
9377 * ((color->green >> 8) - (cells[x].green >> 8)))
9378 + (((color->blue >> 8) - (cells[x].blue >> 8))
9379 * ((color->blue >> 8) - (cells[x].blue >> 8))));
9380 if (trial_delta < nearest_delta)
9381 {
9382
9383 if (temp_allocated)
9384 {
9385 XFreeColors (dpy, cmap, &temp.pixel, 1, 0);
9386 temp_allocated = false;
9387 }
9388
9389 temp.red = cells[x].red;
9390 temp.green = cells[x].green;
9391 temp.blue = cells[x].blue;
9392 status = XAllocColor (dpy, cmap, &temp);
9393
9394 if (status)
9395 {
9396 temp_allocated = true;
9397 nearest = x;
9398 nearest_delta = trial_delta;
9399 }
9400 }
9401 }
9402 color->red = cells[nearest].red;
9403 color->green = cells[nearest].green;
9404 color->blue = cells[nearest].blue;
9405
9406 if (!temp_allocated)
9407 status = XAllocColor (dpy, cmap, color);
9408 else
9409 {
9410 *color = temp;
9411 status = 1;
9412 }
9413
9414 if (status == 0 && !retry)
9415 {
9416
9417
9418
9419
9420 retry = true;
9421 xfree (dpyinfo->color_cells);
9422
9423 ncolor_cells = dpyinfo->visual_info.colormap_size;
9424
9425 dpyinfo->color_cells = xnmalloc (ncolor_cells,
9426 sizeof *dpyinfo->color_cells);
9427 dpyinfo->ncolor_cells = ncolor_cells;
9428
9429 for (i = 0; i < ncolor_cells; ++i)
9430 dpyinfo->color_cells[i].pixel = i;
9431
9432 XQueryColors (dpy, dpyinfo->cmap,
9433 dpyinfo->color_cells, ncolor_cells);
9434
9435 goto start;
9436 }
9437
9438 rc = status != 0;
9439 }
9440 else
9441 {
9442
9443
9444
9445 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
9446 eassume (dpyinfo);
9447
9448 if (dpyinfo->color_cells)
9449 {
9450 XColor *cached_color = &dpyinfo->color_cells[color->pixel];
9451 if (cached_color->red != color->red
9452 || cached_color->blue != color->blue
9453 || cached_color->green != color->green)
9454 {
9455 xfree (dpyinfo->color_cells);
9456 dpyinfo->color_cells = NULL;
9457 dpyinfo->ncolor_cells = 0;
9458 }
9459 }
9460 }
9461
9462 #ifdef DEBUG_X_COLORS
9463 if (rc)
9464 register_color (color->pixel);
9465 #endif
9466
9467 return rc;
9468 }
9469
9470
9471
9472
9473
9474
9475
9476 bool
9477 x_alloc_nearest_color (struct frame *f, Colormap cmap, XColor *color)
9478 {
9479 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
9480
9481 gamma_correct (f, color);
9482
9483 if (dpyinfo->red_bits > 0)
9484 {
9485 color->pixel = x_make_truecolor_pixel (dpyinfo,
9486 color->red,
9487 color->green,
9488 color->blue);
9489 return true;
9490 }
9491
9492 return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f), cmap, color);
9493 }
9494
9495
9496
9497
9498
9499
9500 unsigned long
9501 x_copy_color (struct frame *f, unsigned long pixel)
9502 {
9503 XColor color;
9504
9505
9506
9507
9508
9509 if (!x_mutable_colormap (FRAME_X_VISUAL_INFO (f)))
9510 return pixel;
9511
9512 color.pixel = pixel;
9513 block_input ();
9514
9515 x_query_colors (f, &color, 1);
9516 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
9517 unblock_input ();
9518 #ifdef DEBUG_X_COLORS
9519 register_color (pixel);
9520 #endif
9521 return color.pixel;
9522 }
9523
9524
9525
9526
9527
9528
9529
9530
9531
9532
9533
9534
9535
9536 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
9537
9538
9539
9540
9541
9542
9543
9544
9545
9546 static bool
9547 x_alloc_lighter_color (struct frame *f, Display *display, Colormap cmap,
9548 unsigned long *pixel, double factor, int delta)
9549 {
9550 XColor color, new;
9551 long bright;
9552 bool success_p;
9553
9554
9555 color.pixel = *pixel;
9556 x_query_colors (f, &color, 1);
9557
9558
9559 eassert (factor >= 0);
9560 new.red = min (0xffff, factor * color.red);
9561 new.green = min (0xffff, factor * color.green);
9562 new.blue = min (0xffff, factor * color.blue);
9563
9564
9565 bright = (2 * color.red + 3 * color.green + color.blue) / 6;
9566
9567
9568
9569 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
9570
9571
9572 {
9573
9574 double dimness = 1 - (double) bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
9575
9576 int min_delta = delta * dimness * factor / 2;
9577
9578 if (factor < 1)
9579 {
9580 new.red = max (0, new.red - min_delta);
9581 new.green = max (0, new.green - min_delta);
9582 new.blue = max (0, new.blue - min_delta);
9583 }
9584 else
9585 {
9586 new.red = min (0xffff, min_delta + new.red);
9587 new.green = min (0xffff, min_delta + new.green);
9588 new.blue = min (0xffff, min_delta + new.blue);
9589 }
9590 }
9591
9592
9593 success_p = x_alloc_nearest_color (f, cmap, &new);
9594 if (success_p)
9595 {
9596 if (new.pixel == *pixel)
9597 {
9598
9599
9600 x_free_colors (f, &new.pixel, 1);
9601
9602 new.red = min (0xffff, delta + color.red);
9603 new.green = min (0xffff, delta + color.green);
9604 new.blue = min (0xffff, delta + color.blue);
9605 success_p = x_alloc_nearest_color (f, cmap, &new);
9606 }
9607 else
9608 success_p = true;
9609 *pixel = new.pixel;
9610 }
9611
9612 return success_p;
9613 }
9614
9615
9616
9617
9618
9619
9620
9621
9622
9623 static void
9624 x_setup_relief_color (struct frame *f, struct relief *relief, double factor,
9625 int delta, unsigned long default_pixel)
9626 {
9627 XGCValues xgcv;
9628 struct x_output *di = f->output_data.x;
9629 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
9630 unsigned long pixel;
9631 unsigned long background = di->relief_background;
9632 Colormap cmap = FRAME_X_COLORMAP (f);
9633 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
9634 Display *dpy = FRAME_X_DISPLAY (f);
9635
9636 xgcv.graphics_exposures = False;
9637 xgcv.line_width = 1;
9638
9639
9640
9641
9642 if (relief->gc && relief->pixel != -1)
9643 {
9644 x_free_colors (f, &relief->pixel, 1);
9645 relief->pixel = -1;
9646 }
9647
9648
9649 xgcv.foreground = default_pixel;
9650 pixel = background;
9651 if (dpyinfo->n_planes != 1
9652 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
9653 xgcv.foreground = relief->pixel = pixel;
9654
9655 if (relief->gc == 0)
9656 {
9657 xgcv.stipple = dpyinfo->gray;
9658 mask |= GCStipple;
9659 relief->gc = XCreateGC (dpy, FRAME_X_DRAWABLE (f), mask, &xgcv);
9660 }
9661 else
9662 XChangeGC (dpy, relief->gc, mask, &xgcv);
9663 }
9664
9665
9666
9667
9668 static void
9669 x_setup_relief_colors (struct glyph_string *s)
9670 {
9671 struct x_output *di = s->f->output_data.x;
9672 unsigned long color;
9673
9674 if (s->face->use_box_color_for_shadows_p)
9675 color = s->face->box_color;
9676 else if (s->first_glyph->type == IMAGE_GLYPH
9677 && s->img->pixmap
9678 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
9679 color = IMAGE_BACKGROUND (s->img, s->f, 0);
9680 else
9681 {
9682 XGCValues xgcv;
9683
9684
9685 XGetGCValues (FRAME_X_DISPLAY (s->f), s->gc, GCBackground, &xgcv);
9686 color = xgcv.background;
9687 }
9688
9689 if (di->white_relief.gc == 0
9690 || color != di->relief_background)
9691 {
9692 di->relief_background = color;
9693 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
9694 WHITE_PIX_DEFAULT (s->f));
9695 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
9696 BLACK_PIX_DEFAULT (s->f));
9697 }
9698 }
9699
9700 #ifndef USE_CAIRO
9701 static void
9702 x_fill_triangle (struct frame *f, GC gc, XPoint point1,
9703 XPoint point2, XPoint point3)
9704 {
9705 XPoint abc[3];
9706
9707 abc[0] = point1;
9708 abc[1] = point2;
9709 abc[2] = point3;
9710
9711 XFillPolygon (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
9712 gc, abc, 3, Convex, CoordModeOrigin);
9713 }
9714
9715 static XPoint
9716 x_make_point (int x, int y)
9717 {
9718 XPoint pt;
9719
9720 pt.x = x;
9721 pt.y = y;
9722
9723 return pt;
9724 }
9725
9726 static bool
9727 x_inside_rect_p (XRectangle *rects, int nrects, int x, int y)
9728 {
9729 int i;
9730
9731 for (i = 0; i < nrects; ++i)
9732 {
9733 if (x >= rects[i].x && y >= rects[i].y
9734 && x < rects[i].x + rects[i].width
9735 && y < rects[i].y + rects[i].height)
9736 return true;
9737 }
9738
9739 return false;
9740 }
9741 #endif
9742
9743
9744
9745
9746
9747
9748
9749
9750
9751
9752 static void
9753 x_draw_relief_rect (struct frame *f, int left_x, int top_y, int right_x,
9754 int bottom_y, int hwidth, int vwidth, bool raised_p,
9755 bool top_p, bool bot_p, bool left_p, bool right_p,
9756 XRectangle *clip_rect)
9757 {
9758 #ifdef USE_CAIRO
9759 GC top_left_gc, bottom_right_gc;
9760 int corners = 0;
9761
9762 if (raised_p)
9763 {
9764 top_left_gc = f->output_data.x->white_relief.gc;
9765 bottom_right_gc = f->output_data.x->black_relief.gc;
9766 }
9767 else
9768 {
9769 top_left_gc = f->output_data.x->black_relief.gc;
9770 bottom_right_gc = f->output_data.x->white_relief.gc;
9771 }
9772
9773 x_set_clip_rectangles (f, top_left_gc, clip_rect, 1);
9774 x_set_clip_rectangles (f, bottom_right_gc, clip_rect, 1);
9775
9776 if (left_p)
9777 {
9778 x_fill_rectangle (f, top_left_gc, left_x, top_y,
9779 vwidth, bottom_y + 1 - top_y, false);
9780 if (top_p)
9781 corners |= 1 << CORNER_TOP_LEFT;
9782 if (bot_p)
9783 corners |= 1 << CORNER_BOTTOM_LEFT;
9784 }
9785 if (right_p)
9786 {
9787 x_fill_rectangle (f, bottom_right_gc, right_x + 1 - vwidth, top_y,
9788 vwidth, bottom_y + 1 - top_y, false);
9789 if (top_p)
9790 corners |= 1 << CORNER_TOP_RIGHT;
9791 if (bot_p)
9792 corners |= 1 << CORNER_BOTTOM_RIGHT;
9793 }
9794 if (top_p)
9795 {
9796 if (!right_p)
9797 x_fill_rectangle (f, top_left_gc, left_x, top_y,
9798 right_x + 1 - left_x, hwidth, false);
9799 else
9800 x_fill_trapezoid_for_relief (f, top_left_gc, left_x, top_y,
9801 right_x + 1 - left_x, hwidth, 1);
9802 }
9803 if (bot_p)
9804 {
9805 if (!left_p)
9806 x_fill_rectangle (f, bottom_right_gc, left_x, bottom_y + 1 - hwidth,
9807 right_x + 1 - left_x, hwidth, false);
9808 else
9809 x_fill_trapezoid_for_relief (f, bottom_right_gc,
9810 left_x, bottom_y + 1 - hwidth,
9811 right_x + 1 - left_x, hwidth, 0);
9812 }
9813 if (left_p && vwidth > 1)
9814 x_fill_rectangle (f, bottom_right_gc, left_x, top_y,
9815 1, bottom_y + 1 - top_y, false);
9816 if (top_p && hwidth > 1)
9817 x_fill_rectangle (f, bottom_right_gc, left_x, top_y,
9818 right_x + 1 - left_x, 1, false);
9819 if (corners)
9820 {
9821 XSetBackground (FRAME_X_DISPLAY (f), top_left_gc,
9822 FRAME_BACKGROUND_PIXEL (f));
9823 x_erase_corners_for_relief (f, top_left_gc, left_x, top_y,
9824 right_x - left_x + 1, bottom_y - top_y + 1,
9825 6, 1, corners);
9826 }
9827
9828 x_reset_clip_rectangles (f, top_left_gc);
9829 x_reset_clip_rectangles (f, bottom_right_gc);
9830 #else
9831 GC gc, white_gc, black_gc, normal_gc;
9832 Drawable drawable;
9833 Display *dpy;
9834
9835
9836
9837
9838
9839
9840 white_gc = f->output_data.x->white_relief.gc;
9841 black_gc = f->output_data.x->black_relief.gc;
9842 normal_gc = f->output_data.x->normal_gc;
9843
9844 drawable = FRAME_X_DRAWABLE (f);
9845 dpy = FRAME_X_DISPLAY (f);
9846
9847 x_set_clip_rectangles (f, white_gc, clip_rect, 1);
9848 x_set_clip_rectangles (f, black_gc, clip_rect, 1);
9849
9850 if (raised_p)
9851 gc = white_gc;
9852 else
9853 gc = black_gc;
9854
9855
9856
9857 if (top_p)
9858 x_fill_rectangle (f, gc, left_x, top_y,
9859 right_x - left_x + 1, hwidth,
9860 false);
9861
9862 if (left_p)
9863 x_fill_rectangle (f, gc, left_x, top_y, vwidth,
9864 bottom_y - top_y + 1, false);
9865
9866 if (raised_p)
9867 gc = black_gc;
9868 else
9869 gc = white_gc;
9870
9871 if (bot_p)
9872 x_fill_rectangle (f, gc, left_x, bottom_y - hwidth + 1,
9873 right_x - left_x + 1, hwidth, false);
9874
9875 if (right_p)
9876 x_fill_rectangle (f, gc, right_x - vwidth + 1, top_y,
9877 vwidth, bottom_y - top_y + 1, false);
9878
9879
9880
9881 if (bot_p && left_p)
9882 x_fill_triangle (f, raised_p ? white_gc : black_gc,
9883 x_make_point (left_x, bottom_y - hwidth),
9884 x_make_point (left_x + vwidth, bottom_y - hwidth),
9885 x_make_point (left_x, bottom_y));
9886
9887 if (top_p && right_p)
9888 x_fill_triangle (f, raised_p ? white_gc : black_gc,
9889 x_make_point (right_x - vwidth, top_y),
9890 x_make_point (right_x, top_y),
9891 x_make_point (right_x - vwidth, top_y + hwidth));
9892
9893
9894
9895 if (top_p && left_p && bot_p && right_p
9896 && hwidth > 1 && vwidth > 1)
9897 x_draw_rectangle (f, black_gc, left_x, top_y,
9898 right_x - left_x, bottom_y - top_y);
9899 else
9900 {
9901 if (top_p && hwidth > 1)
9902 XDrawLine (dpy, drawable, black_gc, left_x, top_y,
9903 right_x + 1, top_y);
9904
9905 if (bot_p && hwidth > 1)
9906 XDrawLine (dpy, drawable, black_gc, left_x, bottom_y,
9907 right_x + 1, bottom_y);
9908
9909 if (left_p && vwidth > 1)
9910 XDrawLine (dpy, drawable, black_gc, left_x, top_y,
9911 left_x, bottom_y + 1);
9912
9913 if (right_p && vwidth > 1)
9914 XDrawLine (dpy, drawable, black_gc, right_x, top_y,
9915 right_x, bottom_y + 1);
9916 }
9917
9918
9919
9920 if (hwidth > 1 && vwidth > 1)
9921 {
9922 if (left_p && top_p && x_inside_rect_p (clip_rect, 1,
9923 left_x, top_y))
9924
9925
9926 x_clear_point (f, normal_gc, left_x, top_y, true);
9927
9928 if (left_p && bot_p && x_inside_rect_p (clip_rect, 1,
9929 left_x, bottom_y))
9930 x_clear_point (f, normal_gc, left_x, bottom_y, true);
9931
9932 if (right_p && top_p && x_inside_rect_p (clip_rect, 1,
9933 right_x, top_y))
9934 x_clear_point (f, normal_gc, right_x, top_y, true);
9935
9936 if (right_p && bot_p && x_inside_rect_p (clip_rect, 1,
9937 right_x, bottom_y))
9938 x_clear_point (f, normal_gc, right_x, bottom_y, true);
9939 }
9940
9941 x_reset_clip_rectangles (f, white_gc);
9942 x_reset_clip_rectangles (f, black_gc);
9943 #endif
9944 }
9945
9946
9947
9948
9949
9950
9951
9952
9953
9954 static void
9955 x_draw_box_rect (struct glyph_string *s,
9956 int left_x, int top_y, int right_x, int bottom_y, int hwidth,
9957 int vwidth, bool left_p, bool right_p, XRectangle *clip_rect)
9958 {
9959 Display *display = FRAME_X_DISPLAY (s->f);
9960 XGCValues xgcv;
9961
9962 XGetGCValues (display, s->gc, GCForeground, &xgcv);
9963 XSetForeground (display, s->gc, s->face->box_color);
9964 x_set_clip_rectangles (s->f, s->gc, clip_rect, 1);
9965
9966
9967 x_fill_rectangle (s->f, s->gc,
9968 left_x, top_y, right_x - left_x + 1, hwidth,
9969 false);
9970
9971
9972 if (left_p)
9973 x_fill_rectangle (s->f, s->gc,
9974 left_x, top_y, vwidth, bottom_y - top_y + 1,
9975 false);
9976
9977
9978 x_fill_rectangle (s->f, s->gc,
9979 left_x, bottom_y - hwidth + 1, right_x - left_x + 1, hwidth,
9980 false);
9981
9982
9983 if (right_p)
9984 x_fill_rectangle (s->f, s->gc,
9985 right_x - vwidth + 1, top_y, vwidth, bottom_y - top_y + 1,
9986 false);
9987
9988 XSetForeground (display, s->gc, xgcv.foreground);
9989 x_reset_clip_rectangles (s->f, s->gc);
9990 }
9991
9992
9993
9994
9995 static void
9996 x_draw_glyph_string_box (struct glyph_string *s)
9997 {
9998 int hwidth, vwidth, left_x, right_x, top_y, bottom_y, last_x;
9999 bool raised_p, left_p, right_p;
10000 struct glyph *last_glyph;
10001 XRectangle clip_rect;
10002
10003 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
10004 ? WINDOW_RIGHT_EDGE_X (s->w)
10005 : window_box_right (s->w, s->area));
10006
10007
10008
10009
10010 if (s->cmp || s->img)
10011 last_glyph = s->first_glyph;
10012 else if (s->first_glyph->type == COMPOSITE_GLYPH
10013 && s->first_glyph->u.cmp.automatic)
10014 {
10015
10016
10017 struct glyph *end = s->row->glyphs[s->area] + s->row->used[s->area];
10018 struct glyph *g = s->first_glyph;
10019 for (last_glyph = g++;
10020 g < end && g->u.cmp.automatic && g->u.cmp.id == s->cmp_id
10021 && g->slice.cmp.to < s->cmp_to;
10022 last_glyph = g++)
10023 ;
10024 }
10025 else
10026 last_glyph = s->first_glyph + s->nchars - 1;
10027
10028 vwidth = eabs (s->face->box_vertical_line_width);
10029 hwidth = eabs (s->face->box_horizontal_line_width);
10030 raised_p = s->face->box == FACE_RAISED_BOX;
10031 left_x = s->x;
10032 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
10033 ? last_x - 1
10034 : min (last_x, s->x + s->background_width) - 1);
10035 top_y = s->y;
10036 bottom_y = top_y + s->height - 1;
10037
10038 left_p = (s->first_glyph->left_box_line_p
10039 || (s->hl == DRAW_MOUSE_FACE
10040 && (s->prev == NULL
10041 || s->prev->hl != s->hl)));
10042 right_p = (last_glyph->right_box_line_p
10043 || (s->hl == DRAW_MOUSE_FACE
10044 && (s->next == NULL
10045 || s->next->hl != s->hl)));
10046
10047 get_glyph_string_clip_rect (s, &clip_rect);
10048
10049 if (s->face->box == FACE_SIMPLE_BOX)
10050 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, hwidth,
10051 vwidth, left_p, right_p, &clip_rect);
10052 else
10053 {
10054 x_setup_relief_colors (s);
10055 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y, hwidth,
10056 vwidth, raised_p, true, true, left_p, right_p,
10057 &clip_rect);
10058 }
10059 }
10060
10061
10062 #ifndef USE_CAIRO
10063
10064 static void
10065 x_composite_image (struct glyph_string *s, Pixmap dest,
10066 #ifdef HAVE_XRENDER
10067 Picture destination,
10068 #endif
10069 int srcX, int srcY, int dstX, int dstY,
10070 int width, int height)
10071 {
10072 Display *display;
10073 #ifdef HAVE_XRENDER
10074 XRenderPictFormat *default_format;
10075 XRenderPictureAttributes attr UNINIT;
10076 #endif
10077
10078 display = FRAME_X_DISPLAY (s->f);
10079
10080 #ifdef HAVE_XRENDER
10081 if (s->img->picture && FRAME_X_PICTURE_FORMAT (s->f))
10082 {
10083 if (destination == None)
10084 {
10085
10086
10087 default_format = FRAME_X_PICTURE_FORMAT (s->f);
10088 destination = XRenderCreatePicture (display, dest,
10089 default_format, 0, &attr);
10090
10091 XRenderComposite (display, (s->img->mask_picture
10092 ? PictOpOver : PictOpSrc),
10093 s->img->picture, s->img->mask_picture,
10094 destination, srcX, srcY, srcX, srcY,
10095 dstX, dstY, width, height);
10096
10097 XRenderFreePicture (display, destination);
10098 }
10099 else
10100 XRenderComposite (display, (s->img->mask_picture
10101 ? PictOpOver : PictOpSrc),
10102 s->img->picture, s->img->mask_picture,
10103 destination, srcX, srcY, srcX, srcY,
10104 dstX, dstY, width, height);
10105
10106 return;
10107 }
10108 #endif
10109
10110 XCopyArea (display, s->img->pixmap,
10111 dest, s->gc,
10112 srcX, srcY,
10113 width, height, dstX, dstY);
10114 }
10115
10116 #endif
10117
10118
10119
10120
10121 static void
10122 x_draw_image_foreground (struct glyph_string *s)
10123 {
10124 int x = s->x;
10125 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
10126
10127
10128
10129 if (s->face->box != FACE_NO_BOX
10130 && s->first_glyph->left_box_line_p
10131 && s->slice.x == 0)
10132 x += max (s->face->box_vertical_line_width, 0);
10133
10134
10135
10136 if (s->slice.x == 0)
10137 x += s->img->hmargin;
10138 if (s->slice.y == 0)
10139 y += s->img->vmargin;
10140
10141 #ifdef USE_CAIRO
10142 if (s->img->cr_data)
10143 {
10144 x_set_glyph_string_clipping (s);
10145 x_cr_draw_image (s->f, s->gc, s->img->cr_data,
10146 s->slice.x, s->slice.y, s->slice.width, s->slice.height,
10147 x, y, true);
10148 if (!s->img->mask)
10149 {
10150
10151
10152
10153
10154
10155
10156 if (s->hl == DRAW_CURSOR)
10157 {
10158 int relief = eabs (s->img->relief);
10159 x_draw_rectangle (s->f, s->gc, x - relief, y - relief,
10160 s->slice.width + relief*2 - 1,
10161 s->slice.height + relief*2 - 1);
10162 }
10163 }
10164 }
10165 #else
10166 if (s->img->pixmap)
10167 {
10168 if (s->img->mask)
10169 {
10170
10171
10172
10173
10174
10175
10176 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
10177 | GCFunction);
10178 XGCValues xgcv;
10179 XRectangle clip_rect, image_rect, r;
10180
10181 xgcv.clip_mask = s->img->mask;
10182 xgcv.clip_x_origin = x;
10183 xgcv.clip_y_origin = y;
10184 xgcv.function = GXcopy;
10185 XChangeGC (FRAME_X_DISPLAY (s->f), s->gc, mask, &xgcv);
10186
10187 get_glyph_string_clip_rect (s, &clip_rect);
10188 image_rect.x = x;
10189 image_rect.y = y;
10190 image_rect.width = s->slice.width;
10191 image_rect.height = s->slice.height;
10192 if (gui_intersect_rectangles (&clip_rect, &image_rect, &r))
10193 x_composite_image (s, FRAME_X_DRAWABLE (s->f),
10194 #ifdef HAVE_XRENDER
10195 FRAME_X_PICTURE (s->f),
10196 #endif
10197 s->slice.x + r.x - x, s->slice.y + r.y - y,
10198 r.x, r.y, r.width, r.height);
10199 }
10200 else
10201 {
10202 XRectangle clip_rect, image_rect, r;
10203
10204 get_glyph_string_clip_rect (s, &clip_rect);
10205 image_rect.x = x;
10206 image_rect.y = y;
10207 image_rect.width = s->slice.width;
10208 image_rect.height = s->slice.height;
10209 if (gui_intersect_rectangles (&clip_rect, &image_rect, &r))
10210 x_composite_image (s, FRAME_X_DRAWABLE (s->f),
10211 #ifdef HAVE_XRENDER
10212 FRAME_X_PICTURE (s->f),
10213 #endif
10214 s->slice.x + r.x - x,
10215 s->slice.y + r.y - y,
10216 r.x, r.y, r.width, r.height);
10217
10218
10219
10220
10221
10222
10223
10224 if (s->hl == DRAW_CURSOR)
10225 {
10226 int relief = eabs (s->img->relief);
10227 x_draw_rectangle (s->f, s->gc,
10228 x - relief, y - relief,
10229 s->slice.width + relief*2 - 1,
10230 s->slice.height + relief*2 - 1);
10231 }
10232 }
10233 }
10234 #endif
10235 else
10236
10237 x_draw_rectangle (s->f, s->gc, x, y,
10238 s->slice.width - 1, s->slice.height - 1);
10239 }
10240
10241
10242
10243
10244 static void
10245 x_draw_image_relief (struct glyph_string *s)
10246 {
10247 int x1, y1, thick;
10248 bool raised_p, top_p, bot_p, left_p, right_p;
10249 int extra_x, extra_y;
10250 XRectangle r;
10251 int x = s->x;
10252 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
10253
10254
10255
10256 if (s->face->box != FACE_NO_BOX
10257 && s->first_glyph->left_box_line_p
10258 && s->slice.x == 0)
10259 x += max (s->face->box_vertical_line_width, 0);
10260
10261
10262
10263 if (s->slice.x == 0)
10264 x += s->img->hmargin;
10265 if (s->slice.y == 0)
10266 y += s->img->vmargin;
10267
10268 if (s->hl == DRAW_IMAGE_SUNKEN
10269 || s->hl == DRAW_IMAGE_RAISED)
10270 {
10271 if (s->face->id == TAB_BAR_FACE_ID)
10272 thick = (tab_bar_button_relief < 0
10273 ? DEFAULT_TAB_BAR_BUTTON_RELIEF
10274 : min (tab_bar_button_relief, 1000000));
10275 else
10276 thick = (tool_bar_button_relief < 0
10277 ? DEFAULT_TOOL_BAR_BUTTON_RELIEF
10278 : min (tool_bar_button_relief, 1000000));
10279 raised_p = s->hl == DRAW_IMAGE_RAISED;
10280 }
10281 else
10282 {
10283 thick = eabs (s->img->relief);
10284 raised_p = s->img->relief > 0;
10285 }
10286
10287 x1 = x + s->slice.width - 1;
10288 y1 = y + s->slice.height - 1;
10289
10290 extra_x = extra_y = 0;
10291 if (s->face->id == TAB_BAR_FACE_ID)
10292 {
10293 if (CONSP (Vtab_bar_button_margin)
10294 && FIXNUMP (XCAR (Vtab_bar_button_margin))
10295 && FIXNUMP (XCDR (Vtab_bar_button_margin)))
10296 {
10297 extra_x = XFIXNUM (XCAR (Vtab_bar_button_margin)) - thick;
10298 extra_y = XFIXNUM (XCDR (Vtab_bar_button_margin)) - thick;
10299 }
10300 else if (FIXNUMP (Vtab_bar_button_margin))
10301 extra_x = extra_y = XFIXNUM (Vtab_bar_button_margin) - thick;
10302 }
10303
10304 if (s->face->id == TOOL_BAR_FACE_ID)
10305 {
10306 if (CONSP (Vtool_bar_button_margin)
10307 && FIXNUMP (XCAR (Vtool_bar_button_margin))
10308 && FIXNUMP (XCDR (Vtool_bar_button_margin)))
10309 {
10310 extra_x = XFIXNUM (XCAR (Vtool_bar_button_margin));
10311 extra_y = XFIXNUM (XCDR (Vtool_bar_button_margin));
10312 }
10313 else if (FIXNUMP (Vtool_bar_button_margin))
10314 extra_x = extra_y = XFIXNUM (Vtool_bar_button_margin);
10315 }
10316
10317 top_p = bot_p = left_p = right_p = false;
10318
10319 if (s->slice.x == 0)
10320 x -= thick + extra_x, left_p = true;
10321 if (s->slice.y == 0)
10322 y -= thick + extra_y, top_p = true;
10323 if (s->slice.x + s->slice.width == s->img->width)
10324 x1 += thick + extra_x, right_p = true;
10325 if (s->slice.y + s->slice.height == s->img->height)
10326 y1 += thick + extra_y, bot_p = true;
10327
10328 x_setup_relief_colors (s);
10329 get_glyph_string_clip_rect (s, &r);
10330 x_draw_relief_rect (s->f, x, y, x1, y1, thick, thick, raised_p,
10331 top_p, bot_p, left_p, right_p, &r);
10332 }
10333
10334
10335 #ifndef USE_CAIRO
10336
10337
10338 static void
10339 x_draw_image_foreground_1 (struct glyph_string *s, Pixmap pixmap)
10340 {
10341 int x = 0;
10342 int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
10343
10344
10345
10346 if (s->face->box != FACE_NO_BOX
10347 && s->first_glyph->left_box_line_p
10348 && s->slice.x == 0)
10349 x += max (s->face->box_vertical_line_width, 0);
10350
10351
10352
10353 if (s->slice.x == 0)
10354 x += s->img->hmargin;
10355 if (s->slice.y == 0)
10356 y += s->img->vmargin;
10357
10358 if (s->img->pixmap)
10359 {
10360 Display *display = FRAME_X_DISPLAY (s->f);
10361
10362 if (s->img->mask)
10363 {
10364
10365
10366
10367
10368
10369
10370 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
10371 | GCFunction);
10372 XGCValues xgcv;
10373
10374 xgcv.clip_mask = s->img->mask;
10375 xgcv.clip_x_origin = x - s->slice.x;
10376 xgcv.clip_y_origin = y - s->slice.y;
10377 xgcv.function = GXcopy;
10378 XChangeGC (display, s->gc, mask, &xgcv);
10379
10380 x_composite_image (s, pixmap,
10381 #ifdef HAVE_XRENDER
10382 None,
10383 #endif
10384 s->slice.x, s->slice.y, x, y,
10385 s->slice.width, s->slice.height);
10386 XSetClipMask (display, s->gc, None);
10387 }
10388 else
10389 {
10390 XCopyArea (display, s->img->pixmap, pixmap, s->gc,
10391 s->slice.x, s->slice.y,
10392 s->slice.width, s->slice.height, x, y);
10393
10394
10395
10396
10397
10398
10399
10400 if (s->hl == DRAW_CURSOR)
10401 {
10402 int r = eabs (s->img->relief);
10403 x_draw_rectangle (s->f, s->gc, x - r, y - r,
10404 s->slice.width + r*2 - 1,
10405 s->slice.height + r*2 - 1);
10406 }
10407 }
10408 }
10409 else
10410
10411 x_draw_rectangle (s->f, s->gc, x, y,
10412 s->slice.width - 1, s->slice.height - 1);
10413 }
10414 #endif
10415
10416
10417
10418
10419
10420 static void
10421 x_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w, int h)
10422 {
10423 if (s->stippled_p)
10424 {
10425 Display *display = FRAME_X_DISPLAY (s->f);
10426
10427
10428 XSetFillStyle (display, s->gc, FillOpaqueStippled);
10429 x_fill_rectangle (s->f, s->gc, x, y, w, h, true);
10430 XSetFillStyle (display, s->gc, FillSolid);
10431 }
10432 else
10433 x_clear_glyph_string_rect (s, x, y, w, h);
10434 }
10435
10436
10437
10438
10439
10440
10441
10442
10443
10444
10445
10446
10447
10448
10449
10450
10451 static void
10452 x_draw_image_glyph_string (struct glyph_string *s)
10453 {
10454 int box_line_hwidth = max (s->face->box_vertical_line_width, 0);
10455 int box_line_vwidth = max (s->face->box_horizontal_line_width, 0);
10456 int height;
10457 #ifndef USE_CAIRO
10458 Display *display = FRAME_X_DISPLAY (s->f);
10459 Pixmap pixmap = None;
10460 #endif
10461
10462 height = s->height;
10463 if (s->slice.y == 0)
10464 height -= box_line_vwidth;
10465 if (s->slice.y + s->slice.height >= s->img->height)
10466 height -= box_line_vwidth;
10467
10468
10469
10470
10471 s->stippled_p = s->face->stipple != 0;
10472 if (height > s->slice.height
10473 || s->img->hmargin
10474 || s->img->vmargin
10475 || s->img->mask
10476 || s->img->pixmap == 0
10477 || s->width != s->background_width)
10478 {
10479 if (s->stippled_p)
10480 s->row->stipple_p = true;
10481
10482 #ifndef USE_CAIRO
10483 if (s->img->mask)
10484 {
10485
10486
10487
10488 int depth = FRAME_DISPLAY_INFO (s->f)->n_planes;
10489
10490
10491 pixmap = XCreatePixmap (display, FRAME_X_DRAWABLE (s->f),
10492 s->background_width,
10493 s->height, depth);
10494
10495
10496
10497 XSetClipMask (display, s->gc, None);
10498
10499
10500 if (s->stippled_p)
10501 {
10502
10503 XSetFillStyle (display, s->gc, FillOpaqueStippled);
10504 XSetTSOrigin (display, s->gc, - s->x, - s->y);
10505 XFillRectangle (display, pixmap, s->gc,
10506 0, 0, s->background_width, s->height);
10507 XSetFillStyle (display, s->gc, FillSolid);
10508 XSetTSOrigin (display, s->gc, 0, 0);
10509 }
10510 else
10511 {
10512 XGCValues xgcv;
10513 #if defined HAVE_XRENDER && (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2))
10514 if (FRAME_DISPLAY_INFO (s->f)->alpha_bits
10515 && s->f->alpha_background != 1.0
10516 && FRAME_CHECK_XR_VERSION (s->f, 0, 2)
10517 && FRAME_X_PICTURE_FORMAT (s->f))
10518 {
10519 XRenderColor xc;
10520 XRenderPictureAttributes attrs;
10521 Picture pict;
10522 memset (&attrs, 0, sizeof attrs);
10523
10524 pict = XRenderCreatePicture (display, pixmap,
10525 FRAME_X_PICTURE_FORMAT (s->f),
10526 0, &attrs);
10527 x_xrender_color_from_gc_background (s->f, s->gc, &xc, true);
10528 XRenderFillRectangle (FRAME_X_DISPLAY (s->f), PictOpSrc, pict,
10529 &xc, 0, 0, s->background_width, s->height);
10530 XRenderFreePicture (display, pict);
10531 }
10532 else
10533 #endif
10534 {
10535 XGetGCValues (display, s->gc, GCForeground | GCBackground,
10536 &xgcv);
10537 XSetForeground (display, s->gc, xgcv.background);
10538 XFillRectangle (display, pixmap, s->gc,
10539 0, 0, s->background_width, s->height);
10540 XSetForeground (display, s->gc, xgcv.foreground);
10541 }
10542 }
10543 }
10544 else
10545 #endif
10546 {
10547 int x = s->x;
10548 int y = s->y;
10549 int width = s->background_width;
10550
10551 if (s->first_glyph->left_box_line_p
10552 && s->slice.x == 0)
10553 {
10554 x += box_line_hwidth;
10555 width -= box_line_hwidth;
10556 }
10557
10558 if (s->slice.y == 0)
10559 y += box_line_vwidth;
10560
10561 x_draw_glyph_string_bg_rect (s, x, y, width, height);
10562 }
10563
10564 s->background_filled_p = true;
10565 }
10566
10567
10568 #ifndef USE_CAIRO
10569 if (pixmap != None)
10570 {
10571 x_draw_image_foreground_1 (s, pixmap);
10572 x_set_glyph_string_clipping (s);
10573 XCopyArea (display, pixmap, FRAME_X_DRAWABLE (s->f), s->gc,
10574 0, 0, s->background_width, s->height, s->x, s->y);
10575 XFreePixmap (display, pixmap);
10576 }
10577 else
10578 #endif
10579 x_draw_image_foreground (s);
10580
10581
10582 if (s->img->relief
10583 || s->hl == DRAW_IMAGE_RAISED
10584 || s->hl == DRAW_IMAGE_SUNKEN)
10585 x_draw_image_relief (s);
10586 }
10587
10588
10589
10590
10591 static void
10592 x_draw_stretch_glyph_string (struct glyph_string *s)
10593 {
10594 eassert (s->first_glyph->type == STRETCH_GLYPH);
10595
10596 if (s->hl == DRAW_CURSOR
10597 && !x_stretch_cursor_p)
10598 {
10599
10600
10601 int width, background_width = s->background_width;
10602 int x = s->x;
10603
10604 if (!s->row->reversed_p)
10605 {
10606 int left_x = window_box_left_offset (s->w, TEXT_AREA);
10607
10608 if (x < left_x)
10609 {
10610 background_width -= left_x - x;
10611 x = left_x;
10612 }
10613 }
10614 else
10615 {
10616
10617
10618 int right_x = window_box_right (s->w, TEXT_AREA);
10619
10620 if (x + background_width > right_x)
10621 background_width -= x - right_x;
10622 x += background_width;
10623 }
10624 width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
10625 if (s->row->reversed_p)
10626 x -= width;
10627
10628
10629 x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
10630
10631
10632 if (width < background_width)
10633 {
10634 int y = s->y;
10635 int w = background_width - width, h = s->height;
10636 Display *display = FRAME_X_DISPLAY (s->f);
10637 XRectangle r;
10638 GC gc;
10639
10640 if (!s->row->reversed_p)
10641 x += width;
10642 else
10643 x = s->x;
10644 if (s->row->mouse_face_p
10645 && cursor_in_mouse_face_p (s->w))
10646 {
10647 x_set_mouse_face_gc (s);
10648 gc = s->gc;
10649 }
10650 else
10651 gc = s->face->gc;
10652
10653 get_glyph_string_clip_rect (s, &r);
10654 x_set_clip_rectangles (s->f, gc, &r, 1);
10655
10656 if (s->face->stipple)
10657 {
10658
10659 XSetFillStyle (display, gc, FillOpaqueStippled);
10660 x_fill_rectangle (s->f, gc, x, y, w, h, true);
10661 XSetFillStyle (display, gc, FillSolid);
10662
10663 s->row->stipple_p = true;
10664 }
10665 else
10666 {
10667 XGCValues xgcv;
10668 XGetGCValues (display, gc, GCForeground | GCBackground, &xgcv);
10669 XSetForeground (display, gc, xgcv.background);
10670 x_fill_rectangle (s->f, gc, x, y, w, h, true);
10671 XSetForeground (display, gc, xgcv.foreground);
10672 }
10673
10674 x_reset_clip_rectangles (s->f, gc);
10675 }
10676 }
10677 else if (!s->background_filled_p)
10678 {
10679 int background_width = s->background_width;
10680 int x = s->x, text_left_x = window_box_left (s->w, TEXT_AREA);
10681
10682
10683
10684 if (s->area == TEXT_AREA
10685 && x < text_left_x && !s->row->mode_line_p)
10686 {
10687 background_width -= text_left_x - x;
10688 x = text_left_x;
10689 }
10690
10691 if (!s->row->stipple_p)
10692 s->row->stipple_p = s->stippled_p;
10693
10694 if (background_width > 0)
10695 x_draw_glyph_string_bg_rect (s, x, s->y,
10696 background_width, s->height);
10697 }
10698
10699 s->background_filled_p = true;
10700 }
10701
10702 static void
10703 x_get_scale_factor (Display *disp, int *scale_x, int *scale_y)
10704 {
10705 const int base_res = 96;
10706 struct x_display_info * dpyinfo = x_display_info_for_display (disp);
10707
10708 *scale_x = *scale_y = 1;
10709
10710 if (dpyinfo)
10711 {
10712 if (dpyinfo->resx > base_res)
10713 *scale_x = floor (dpyinfo->resx / base_res);
10714 if (dpyinfo->resy > base_res)
10715 *scale_y = floor (dpyinfo->resy / base_res);
10716 }
10717 }
10718
10719
10720
10721
10722
10723
10724
10725
10726
10727
10728
10729 static void
10730 x_draw_underwave (struct glyph_string *s, int decoration_width)
10731 {
10732 Display *display = FRAME_X_DISPLAY (s->f);
10733
10734
10735 int scale_x, scale_y;
10736
10737 x_get_scale_factor (display, &scale_x, &scale_y);
10738
10739 int wave_height = 3 * scale_y, wave_length = 2 * scale_x;
10740
10741 #ifdef USE_CAIRO
10742 x_draw_horizontal_wave (s->f, s->gc, s->x, s->ybase - wave_height + 3,
10743 decoration_width, wave_height, wave_length);
10744 #else
10745 int dx, dy, x0, y0, width, x1, y1, x2, y2, xmax, thickness = scale_y;;
10746 bool odd;
10747 XRectangle wave_clip, string_clip, final_clip;
10748
10749 dx = wave_length;
10750 dy = wave_height - 1;
10751 x0 = s->x;
10752 y0 = s->ybase + wave_height / 2 - scale_y;
10753 width = decoration_width;
10754 xmax = x0 + width;
10755
10756
10757
10758 wave_clip.x = x0;
10759 wave_clip.y = y0;
10760 wave_clip.width = width;
10761 wave_clip.height = wave_height;
10762 get_glyph_string_clip_rect (s, &string_clip);
10763
10764 if (!gui_intersect_rectangles (&wave_clip, &string_clip, &final_clip))
10765 return;
10766
10767 XSetClipRectangles (display, s->gc, 0, 0, &final_clip, 1, Unsorted);
10768
10769
10770
10771 x1 = x0 - (x0 % dx);
10772 x2 = x1 + dx;
10773 odd = (x1 / dx) & 1;
10774 y1 = y2 = y0;
10775
10776 if (odd)
10777 y1 += dy;
10778 else
10779 y2 += dy;
10780
10781 if (INT_MAX - dx < xmax)
10782 emacs_abort ();
10783
10784 while (x1 <= xmax)
10785 {
10786 XSetLineAttributes (display, s->gc, thickness, LineSolid, CapButt,
10787 JoinRound);
10788 XDrawLine (display, FRAME_X_DRAWABLE (s->f), s->gc, x1, y1, x2, y2);
10789 x1 = x2, y1 = y2;
10790 x2 += dx, y2 = y0 + odd*dy;
10791 odd = !odd;
10792 }
10793
10794
10795 XSetClipRectangles (display, s->gc, 0, 0, s->clip, s->num_clips, Unsorted);
10796 #endif
10797 }
10798
10799
10800
10801
10802 static void
10803 x_draw_glyph_string (struct glyph_string *s)
10804 {
10805 bool relief_drawn_p = false;
10806
10807
10808
10809
10810 if (s->next && s->right_overhang && !s->for_overlaps)
10811 {
10812 int width;
10813 struct glyph_string *next;
10814
10815 for (width = 0, next = s->next;
10816 next && width < s->right_overhang;
10817 width += next->width, next = next->next)
10818 if (next->first_glyph->type != IMAGE_GLYPH)
10819 {
10820 x_set_glyph_string_gc (next);
10821 x_set_glyph_string_clipping (next);
10822 if (next->first_glyph->type == STRETCH_GLYPH)
10823 x_draw_stretch_glyph_string (next);
10824 else
10825 x_draw_glyph_string_background (next, true);
10826 next->num_clips = 0;
10827 }
10828 }
10829
10830
10831 x_set_glyph_string_gc (s);
10832
10833
10834
10835 if (!s->for_overlaps
10836 && s->face->box != FACE_NO_BOX
10837 && (s->first_glyph->type == CHAR_GLYPH
10838 || s->first_glyph->type == COMPOSITE_GLYPH))
10839
10840 {
10841 x_set_glyph_string_clipping (s);
10842 x_draw_glyph_string_background (s, true);
10843 x_draw_glyph_string_box (s);
10844 x_set_glyph_string_clipping (s);
10845 relief_drawn_p = true;
10846 }
10847 else if (!s->clip_head
10848 && !s->clip_tail
10849 && ((s->prev && s->prev->hl != s->hl && s->left_overhang)
10850 || (s->next && s->next->hl != s->hl && s->right_overhang)))
10851
10852
10853
10854 x_set_glyph_string_clipping_exactly (s, s);
10855 else
10856 x_set_glyph_string_clipping (s);
10857
10858 switch (s->first_glyph->type)
10859 {
10860 case IMAGE_GLYPH:
10861 x_draw_image_glyph_string (s);
10862 break;
10863
10864 case XWIDGET_GLYPH:
10865 x_draw_xwidget_glyph_string (s);
10866 break;
10867
10868 case STRETCH_GLYPH:
10869 x_draw_stretch_glyph_string (s);
10870 break;
10871
10872 case CHAR_GLYPH:
10873 if (s->for_overlaps)
10874 s->background_filled_p = true;
10875 else
10876 x_draw_glyph_string_background (s, false);
10877 x_draw_glyph_string_foreground (s);
10878 break;
10879
10880 case COMPOSITE_GLYPH:
10881 if (s->for_overlaps || (s->cmp_from > 0
10882 && ! s->first_glyph->u.cmp.automatic))
10883 s->background_filled_p = true;
10884 else
10885 x_draw_glyph_string_background (s, true);
10886 x_draw_composite_glyph_string_foreground (s);
10887 break;
10888
10889 case GLYPHLESS_GLYPH:
10890 if (s->for_overlaps)
10891 s->background_filled_p = true;
10892 else
10893 x_draw_glyph_string_background (s, true);
10894 x_draw_glyphless_glyph_string_foreground (s);
10895 break;
10896
10897 default:
10898 emacs_abort ();
10899 }
10900
10901 if (!s->for_overlaps)
10902 {
10903 int area_x, area_y, area_width, area_height;
10904 int area_max_x, decoration_width;
10905
10906
10907
10908 window_box (s->w, s->area, &area_x, &area_y,
10909 &area_width, &area_height);
10910 area_max_x = area_x + area_width - 1;
10911
10912 decoration_width = s->width;
10913 if (!s->row->mode_line_p
10914 && !s->row->tab_line_p
10915 && area_max_x < (s->x + decoration_width - 1))
10916 decoration_width -= (s->x + decoration_width - 1) - area_max_x;
10917
10918
10919 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
10920 x_draw_glyph_string_box (s);
10921
10922
10923 if (s->face->underline)
10924 {
10925 if (s->face->underline == FACE_UNDER_WAVE)
10926 {
10927 if (s->face->underline_defaulted_p)
10928 x_draw_underwave (s, decoration_width);
10929 else
10930 {
10931 Display *display = FRAME_X_DISPLAY (s->f);
10932 XGCValues xgcv;
10933 XGetGCValues (display, s->gc, GCForeground, &xgcv);
10934 XSetForeground (display, s->gc, s->face->underline_color);
10935 x_draw_underwave (s, decoration_width);
10936 XSetForeground (display, s->gc, xgcv.foreground);
10937 }
10938 }
10939 else if (s->face->underline == FACE_UNDER_LINE)
10940 {
10941 unsigned long thickness, position;
10942 int y;
10943
10944 if (s->prev
10945 && s->prev->face->underline == FACE_UNDER_LINE
10946 && (s->prev->face->underline_at_descent_line_p
10947 == s->face->underline_at_descent_line_p)
10948 && (s->prev->face->underline_pixels_above_descent_line
10949 == s->face->underline_pixels_above_descent_line))
10950 {
10951
10952 thickness = s->prev->underline_thickness;
10953 position = s->prev->underline_position;
10954 }
10955 else
10956 {
10957 struct font *font = font_for_underline_metrics (s);
10958 unsigned long minimum_offset;
10959 bool underline_at_descent_line;
10960 bool use_underline_position_properties;
10961 Lisp_Object val = (WINDOW_BUFFER_LOCAL_VALUE
10962 (Qunderline_minimum_offset, s->w));
10963
10964 if (FIXNUMP (val))
10965 minimum_offset = max (0, XFIXNUM (val));
10966 else
10967 minimum_offset = 1;
10968
10969 val = (WINDOW_BUFFER_LOCAL_VALUE
10970 (Qx_underline_at_descent_line, s->w));
10971 underline_at_descent_line
10972 = (!(NILP (val) || BASE_EQ (val, Qunbound))
10973 || s->face->underline_at_descent_line_p);
10974
10975 val = (WINDOW_BUFFER_LOCAL_VALUE
10976 (Qx_use_underline_position_properties, s->w));
10977 use_underline_position_properties
10978 = !(NILP (val) || BASE_EQ (val, Qunbound));
10979
10980
10981 if (font && font->underline_thickness > 0)
10982 thickness = font->underline_thickness;
10983 else
10984 thickness = 1;
10985 if (underline_at_descent_line)
10986 position = ((s->height - thickness)
10987 - (s->ybase - s->y)
10988 - s->face->underline_pixels_above_descent_line);
10989 else
10990 {
10991
10992
10993
10994
10995
10996
10997
10998
10999
11000 if (use_underline_position_properties
11001 && font && font->underline_position >= 0)
11002 position = font->underline_position;
11003 else if (font)
11004 position = (font->descent + 1) / 2;
11005 else
11006 position = minimum_offset;
11007 }
11008
11009
11010
11011 if (!s->face->underline_pixels_above_descent_line)
11012 position = max (position, minimum_offset);
11013 }
11014
11015
11016 if (s->y + s->height <= s->ybase + position)
11017 position = (s->height - 1) - (s->ybase - s->y);
11018 if (s->y + s->height < s->ybase + position + thickness)
11019 thickness = (s->y + s->height) - (s->ybase + position);
11020 s->underline_thickness = thickness;
11021 s->underline_position = position;
11022 y = s->ybase + position;
11023 if (s->face->underline_defaulted_p)
11024 x_fill_rectangle (s->f, s->gc,
11025 s->x, y, decoration_width, thickness,
11026 false);
11027 else
11028 {
11029 Display *display = FRAME_X_DISPLAY (s->f);
11030 XGCValues xgcv;
11031 XGetGCValues (display, s->gc, GCForeground, &xgcv);
11032 XSetForeground (display, s->gc, s->face->underline_color);
11033 x_fill_rectangle (s->f, s->gc,
11034 s->x, y, decoration_width, thickness,
11035 false);
11036 XSetForeground (display, s->gc, xgcv.foreground);
11037 }
11038 }
11039 }
11040
11041 if (s->face->overline_p)
11042 {
11043 unsigned long dy = 0, h = 1;
11044
11045 if (s->face->overline_color_defaulted_p)
11046 x_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
11047 decoration_width, h, false);
11048 else
11049 {
11050 Display *display = FRAME_X_DISPLAY (s->f);
11051 XGCValues xgcv;
11052 XGetGCValues (display, s->gc, GCForeground, &xgcv);
11053 XSetForeground (display, s->gc, s->face->overline_color);
11054 x_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
11055 decoration_width, h, false);
11056 XSetForeground (display, s->gc, xgcv.foreground);
11057 }
11058 }
11059
11060
11061 if (s->face->strike_through_p)
11062 {
11063
11064
11065
11066
11067
11068 int glyph_y = s->ybase - s->first_glyph->ascent;
11069 int glyph_height = s->first_glyph->ascent + s->first_glyph->descent;
11070
11071
11072 unsigned long h = 1;
11073 unsigned long dy = (glyph_height - h) / 2;
11074
11075 if (s->face->strike_through_color_defaulted_p)
11076 x_fill_rectangle (s->f, s->gc, s->x, glyph_y + dy,
11077 s->width, h, false);
11078 else
11079 {
11080 Display *display = FRAME_X_DISPLAY (s->f);
11081 XGCValues xgcv;
11082 XGetGCValues (display, s->gc, GCForeground, &xgcv);
11083 XSetForeground (display, s->gc, s->face->strike_through_color);
11084 x_fill_rectangle (s->f, s->gc, s->x, glyph_y + dy,
11085 decoration_width, h, false);
11086 XSetForeground (display, s->gc, xgcv.foreground);
11087 }
11088 }
11089
11090 if (s->prev)
11091 {
11092 struct glyph_string *prev;
11093
11094 for (prev = s->prev; prev; prev = prev->prev)
11095 if (prev->hl != s->hl
11096 && prev->x + prev->width + prev->right_overhang > s->x)
11097 {
11098
11099
11100 enum draw_glyphs_face save = prev->hl;
11101
11102 prev->hl = s->hl;
11103 x_set_glyph_string_gc (prev);
11104 x_set_glyph_string_clipping_exactly (s, prev);
11105 if (prev->first_glyph->type == CHAR_GLYPH)
11106 x_draw_glyph_string_foreground (prev);
11107 else
11108 x_draw_composite_glyph_string_foreground (prev);
11109 x_reset_clip_rectangles (prev->f, prev->gc);
11110 prev->hl = save;
11111 prev->num_clips = 0;
11112 }
11113 }
11114
11115 if (s->next)
11116 {
11117 struct glyph_string *next;
11118
11119 for (next = s->next; next; next = next->next)
11120 if (next->hl != s->hl
11121 && next->x - next->left_overhang < s->x + s->width)
11122 {
11123
11124
11125 enum draw_glyphs_face save = next->hl;
11126
11127 next->hl = s->hl;
11128 x_set_glyph_string_gc (next);
11129 x_set_glyph_string_clipping_exactly (s, next);
11130 if (next->first_glyph->type == CHAR_GLYPH)
11131 x_draw_glyph_string_foreground (next);
11132 else
11133 x_draw_composite_glyph_string_foreground (next);
11134 x_reset_clip_rectangles (next->f, next->gc);
11135 next->hl = save;
11136 next->num_clips = 0;
11137 next->clip_head = s->next;
11138 }
11139 }
11140 }
11141
11142
11143 x_reset_clip_rectangles (s->f, s->gc);
11144 s->num_clips = 0;
11145
11146
11147
11148
11149 if (s->first_glyph->type != STRETCH_GLYPH
11150 && s->first_glyph->type != IMAGE_GLYPH
11151 && !s->row->stipple_p)
11152 s->row->stipple_p = s->stippled_p;
11153 }
11154
11155
11156
11157 static void
11158 x_shift_glyphs_for_insert (struct frame *f, int x, int y, int width, int height, int shift_by)
11159 {
11160
11161
11162
11163 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), FRAME_X_DRAWABLE (f),
11164 f->output_data.x->normal_gc,
11165 x, y, width, height,
11166 x + shift_by, y);
11167 }
11168
11169
11170
11171
11172 static void
11173 x_delete_glyphs (struct frame *f, int n)
11174 {
11175 emacs_abort ();
11176 }
11177
11178
11179
11180
11181
11182 #if defined USE_GTK || !defined USE_CAIRO
11183 static void
11184 x_clear_area1 (Display *dpy, Window window,
11185 int x, int y, int width, int height, int exposures)
11186 {
11187 eassert (width > 0 && height > 0);
11188 XClearArea (dpy, window, x, y, width, height, exposures);
11189 }
11190 #endif
11191
11192 void
11193 x_clear_area (struct frame *f, int x, int y, int width, int height)
11194 {
11195 #ifdef USE_CAIRO
11196 cairo_t *cr;
11197
11198 eassert (width > 0 && height > 0);
11199
11200 cr = x_begin_cr_clip (f, NULL);
11201 x_set_cr_source_with_gc_background (f, f->output_data.x->normal_gc,
11202 true);
11203 cairo_rectangle (cr, x, y, width, height);
11204 cairo_fill (cr);
11205 x_end_cr_clip (f);
11206 #else
11207 #ifndef USE_GTK
11208 if (f->alpha_background != 1.0
11209 #ifdef HAVE_XDBE
11210 || FRAME_X_DOUBLE_BUFFERED_P (f)
11211 #endif
11212 )
11213 #endif
11214 {
11215 #if defined HAVE_XRENDER && \
11216 (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2))
11217 x_xr_ensure_picture (f);
11218 if (FRAME_DISPLAY_INFO (f)->alpha_bits
11219 && FRAME_X_PICTURE (f) != None
11220 && f->alpha_background != 1.0
11221 && FRAME_CHECK_XR_VERSION (f, 0, 2))
11222 {
11223 XRenderColor xc;
11224 GC gc = f->output_data.x->normal_gc;
11225
11226 x_xr_apply_ext_clip (f, gc);
11227 x_xrender_color_from_gc_background (f, gc, &xc, true);
11228 XRenderFillRectangle (FRAME_X_DISPLAY (f),
11229 PictOpSrc, FRAME_X_PICTURE (f),
11230 &xc, x, y, width, height);
11231 x_xr_reset_ext_clip (f);
11232 x_mark_frame_dirty (f);
11233 }
11234 else
11235 #endif
11236 XFillRectangle (FRAME_X_DISPLAY (f),
11237 FRAME_X_DRAWABLE (f),
11238 f->output_data.x->reverse_gc,
11239 x, y, width, height);
11240 }
11241 #ifndef USE_GTK
11242 else
11243 x_clear_area1 (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11244 x, y, width, height, False);
11245 #endif
11246 #endif
11247 }
11248
11249
11250
11251
11252 static void
11253 x_clear_frame (struct frame *f)
11254 {
11255
11256
11257 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
11258
11259 block_input ();
11260 font_drop_xrender_surfaces (f);
11261 x_clear_window (f);
11262
11263
11264
11265 x_scroll_bar_clear (f);
11266
11267 unblock_input ();
11268 }
11269
11270
11271
11272
11273
11274
11275 static void
11276 x_send_hourglass_message (struct frame *f, bool hourglass_enabled)
11277 {
11278 struct x_display_info *dpyinfo;
11279 XEvent msg;
11280
11281 dpyinfo = FRAME_DISPLAY_INFO (f);
11282 memset (&msg, 0, sizeof msg);
11283
11284 msg.xclient.type = ClientMessage;
11285 msg.xclient.message_type
11286 = dpyinfo->Xatom_EMACS_TMP;
11287 msg.xclient.format = 8;
11288 msg.xclient.window = FRAME_X_WINDOW (f);
11289 msg.xclient.data.b[0] = hourglass_enabled ? 1 : 0;
11290
11291 XSendEvent (dpyinfo->display, FRAME_X_WINDOW (f),
11292 False, NoEventMask, &msg);
11293 }
11294
11295
11296
11297 static void
11298 x_show_hourglass (struct frame *f)
11299 {
11300 Display *dpy = FRAME_X_DISPLAY (f);
11301
11302 if (dpy)
11303 {
11304 struct x_output *x = FRAME_X_OUTPUT (f);
11305
11306
11307
11308
11309
11310
11311
11312 if (popup_activated ())
11313 return;
11314
11315 x_send_hourglass_message (f, true);
11316
11317 #ifdef USE_X_TOOLKIT
11318 if (x->widget)
11319 #else
11320 if (FRAME_OUTER_WINDOW (f))
11321 #endif
11322 {
11323 if (!x->hourglass_window)
11324 {
11325 #ifndef USE_XCB
11326 unsigned long mask = CWCursor;
11327 XSetWindowAttributes attrs;
11328 #ifdef USE_GTK
11329 Window parent = FRAME_X_WINDOW (f);
11330 #else
11331 Window parent = FRAME_OUTER_WINDOW (f);
11332 #endif
11333 attrs.cursor = x->hourglass_cursor;
11334
11335 x->hourglass_window = XCreateWindow
11336 (dpy, parent, 0, 0, 32000, 32000, 0, 0,
11337 InputOnly, CopyFromParent, mask, &attrs);
11338 #else
11339 uint32_t cursor = (uint32_t) x->hourglass_cursor;
11340 #ifdef USE_GTK
11341 xcb_window_t parent = (xcb_window_t) FRAME_X_WINDOW (f);
11342 #else
11343 xcb_window_t parent = (xcb_window_t) FRAME_OUTER_WINDOW (f);
11344 #endif
11345 x->hourglass_window
11346 = (Window) xcb_generate_id (FRAME_DISPLAY_INFO (f)->xcb_connection);
11347
11348 xcb_create_window (FRAME_DISPLAY_INFO (f)->xcb_connection,
11349 XCB_COPY_FROM_PARENT,
11350 (xcb_window_t) x->hourglass_window,
11351 parent, 0, 0, FRAME_PIXEL_WIDTH (f),
11352 FRAME_PIXEL_HEIGHT (f), 0,
11353 XCB_WINDOW_CLASS_INPUT_ONLY,
11354 XCB_COPY_FROM_PARENT, XCB_CW_CURSOR,
11355 &cursor);
11356 #endif
11357 }
11358
11359 #ifndef USE_XCB
11360 XMapRaised (dpy, x->hourglass_window);
11361
11362 flush_frame (f);
11363 #else
11364 uint32_t value = XCB_STACK_MODE_ABOVE;
11365
11366 xcb_configure_window (FRAME_DISPLAY_INFO (f)->xcb_connection,
11367 (xcb_window_t) x->hourglass_window,
11368 XCB_CONFIG_WINDOW_STACK_MODE, &value);
11369 xcb_map_window (FRAME_DISPLAY_INFO (f)->xcb_connection,
11370 (xcb_window_t) x->hourglass_window);
11371 xcb_flush (FRAME_DISPLAY_INFO (f)->xcb_connection);
11372 #endif
11373 }
11374 }
11375 }
11376
11377
11378
11379 static void
11380 x_hide_hourglass (struct frame *f)
11381 {
11382 struct x_output *x = FRAME_X_OUTPUT (f);
11383
11384
11385 if (x->hourglass_window)
11386 {
11387 #ifndef USE_XCB
11388 XUnmapWindow (FRAME_X_DISPLAY (f), x->hourglass_window);
11389 #else
11390 xcb_unmap_window (FRAME_DISPLAY_INFO (f)->xcb_connection,
11391 (xcb_window_t) x->hourglass_window);
11392 #endif
11393 x_send_hourglass_message (f, false);
11394 }
11395 }
11396
11397
11398
11399 static void
11400 XTflash (struct frame *f)
11401 {
11402 GC gc;
11403 XGCValues values;
11404 fd_set fds;
11405 int fd, rc;
11406
11407 block_input ();
11408
11409 if (FRAME_X_VISUAL_INFO (f)->class == TrueColor)
11410 {
11411 values.function = GXxor;
11412 values.foreground = (FRAME_FOREGROUND_PIXEL (f)
11413 ^ FRAME_BACKGROUND_PIXEL (f));
11414
11415 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11416 GCFunction | GCForeground, &values);
11417 }
11418 else
11419 gc = FRAME_X_OUTPUT (f)->normal_gc;
11420
11421
11422
11423 int height = FRAME_PIXEL_HEIGHT (f);
11424
11425 int flash_height = FRAME_LINE_HEIGHT (f);
11426
11427 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
11428 int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
11429 int width = flash_right - flash_left;
11430
11431
11432 if (height > 3 * FRAME_LINE_HEIGHT (f))
11433 {
11434 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
11435 flash_left,
11436 (FRAME_INTERNAL_BORDER_WIDTH (f)
11437 + FRAME_TOP_MARGIN_HEIGHT (f)),
11438 width, flash_height);
11439 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
11440 flash_left,
11441 (height - flash_height
11442 - FRAME_INTERNAL_BORDER_WIDTH (f)
11443 - FRAME_BOTTOM_MARGIN_HEIGHT (f)),
11444 width, flash_height);
11445
11446 }
11447 else
11448
11449 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
11450 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
11451 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
11452
11453 x_flush (f);
11454
11455 struct timespec delay = make_timespec (0, 150 * 1000 * 1000);
11456 struct timespec wakeup = timespec_add (current_timespec (), delay);
11457 fd = ConnectionNumber (FRAME_X_DISPLAY (f));
11458
11459
11460
11461 while (! detect_input_pending ())
11462 {
11463 struct timespec current = current_timespec ();
11464 struct timespec timeout;
11465
11466
11467 if (timespec_cmp (wakeup, current) <= 0)
11468 break;
11469
11470
11471 timeout = make_timespec (0, 10 * 1000 * 1000);
11472
11473
11474
11475 FD_ZERO (&fds);
11476 FD_SET (fd, &fds);
11477
11478
11479 rc = pselect (fd + 1, &fds, NULL, NULL, &timeout, NULL);
11480
11481
11482 if (rc >= 0 && FD_ISSET (fd, &fds))
11483 break;
11484 }
11485
11486
11487 if (height > 3 * FRAME_LINE_HEIGHT (f))
11488 {
11489 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
11490 flash_left,
11491 (FRAME_INTERNAL_BORDER_WIDTH (f)
11492 + FRAME_TOP_MARGIN_HEIGHT (f)),
11493 width, flash_height);
11494 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
11495 flash_left,
11496 (height - flash_height
11497 - FRAME_INTERNAL_BORDER_WIDTH (f)
11498 - FRAME_BOTTOM_MARGIN_HEIGHT (f)),
11499 width, flash_height);
11500 }
11501 else
11502
11503 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
11504 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
11505 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
11506
11507 if (FRAME_X_VISUAL_INFO (f)->class == TrueColor)
11508 XFreeGC (FRAME_X_DISPLAY (f), gc);
11509 x_flush (f);
11510
11511 unblock_input ();
11512 }
11513
11514
11515
11516 static void
11517 XTring_bell (struct frame *f)
11518 {
11519 struct x_display_info *dpyinfo;
11520
11521 if (!FRAME_X_DISPLAY (f))
11522 return;
11523
11524 dpyinfo = FRAME_DISPLAY_INFO (f);
11525
11526 if (visible_bell)
11527 XTflash (f);
11528 else
11529 {
11530
11531
11532
11533
11534
11535 block_input ();
11536 x_ignore_errors_for_next_request (dpyinfo, 0);
11537 #ifdef HAVE_XKB
11538 XkbBell (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 0, None);
11539 #else
11540 XBell (FRAME_X_DISPLAY (f), 0);
11541 #endif
11542 XFlush (FRAME_X_DISPLAY (f));
11543 x_stop_ignoring_errors (dpyinfo);
11544 unblock_input ();
11545 }
11546 }
11547
11548
11549
11550
11551
11552
11553
11554
11555 static void
11556 x_ins_del_lines (struct frame *f, int vpos, int n)
11557 {
11558 emacs_abort ();
11559 }
11560
11561
11562
11563
11564 static void
11565 x_scroll_run (struct window *w, struct run *run)
11566 {
11567 struct frame *f = XFRAME (w->frame);
11568 int x, y, width, height, from_y, to_y, bottom_y;
11569
11570
11571
11572
11573 window_box (w, ANY_AREA, &x, &y, &width, &height);
11574
11575 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
11576 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
11577 bottom_y = y + height;
11578
11579 if (to_y < from_y)
11580 {
11581
11582
11583 if (from_y + run->height > bottom_y)
11584 height = bottom_y - from_y;
11585 else
11586 height = run->height;
11587 }
11588 else
11589 {
11590
11591
11592 if (to_y + run->height > bottom_y)
11593 height = bottom_y - to_y;
11594 else
11595 height = run->height;
11596 }
11597
11598 block_input ();
11599
11600
11601 gui_clear_cursor (w);
11602
11603 #ifdef HAVE_XWIDGETS
11604
11605 Display *dpy = FRAME_X_DISPLAY (f);
11606 Window window = FRAME_X_WINDOW (f);
11607
11608 Window root, parent, *children;
11609 unsigned int nchildren;
11610
11611 if (XQueryTree (dpy, window, &root, &parent, &children, &nchildren))
11612 {
11613
11614
11615 for (unsigned int i = 0; i < nchildren; ++i)
11616 {
11617 Window child = children[i];
11618 struct xwidget_view *view = xwidget_view_from_window (child);
11619
11620 if (view && !view->hidden)
11621 {
11622 int window_y = view->y + view->clip_top;
11623 int window_height = view->clip_bottom - view->clip_top;
11624
11625 Emacs_Rectangle r1, r2, result;
11626 r1.x = w->pixel_left;
11627 r1.y = from_y;
11628 r1.width = w->pixel_width;
11629 r1.height = height;
11630 r2 = r1;
11631 r2.y = window_y;
11632 r2.height = window_height;
11633
11634
11635 if (window_height == 0)
11636 {
11637 view->hidden = true;
11638 XUnmapWindow (dpy, child);
11639 continue;
11640 }
11641
11642 bool intersects_p =
11643 gui_intersect_rectangles (&r1, &r2, &result);
11644
11645 if (XWINDOW (view->w) == w && intersects_p)
11646 {
11647 int y = view->y + (to_y - from_y);
11648 int text_area_x, text_area_y, text_area_width, text_area_height;
11649 int clip_top, clip_bottom;
11650
11651 window_box (w, view->area, &text_area_x, &text_area_y,
11652 &text_area_width, &text_area_height);
11653
11654 view->y = y;
11655
11656 clip_top = 0;
11657 clip_bottom = XXWIDGET (view->model)->height;
11658
11659 if (y < text_area_y)
11660 clip_top = text_area_y - y;
11661
11662 if ((y + clip_bottom) > (text_area_y + text_area_height))
11663 {
11664 clip_bottom -= (y + clip_bottom) - (text_area_y + text_area_height);
11665 }
11666
11667 view->clip_top = clip_top;
11668 view->clip_bottom = clip_bottom;
11669
11670
11671
11672 if ((view->clip_bottom - view->clip_top) <= 0)
11673 {
11674 view->hidden = true;
11675 XUnmapWindow (dpy, child);
11676 }
11677 else
11678 {
11679 XMoveResizeWindow (dpy, child, view->x + view->clip_left,
11680 view->y + view->clip_top,
11681 view->clip_right - view->clip_left,
11682 view->clip_bottom - view->clip_top);
11683 cairo_xlib_surface_set_size (view->cr_surface,
11684 view->clip_right - view->clip_left,
11685 view->clip_bottom - view->clip_top);
11686 }
11687 xwidget_expose (view);
11688 }
11689 }
11690 }
11691 XFree (children);
11692 }
11693 #endif
11694
11695 #ifdef USE_CAIRO_XCB_SURFACE
11696
11697
11698
11699 XFlushGC (FRAME_X_DISPLAY (f),
11700 f->output_data.x->normal_gc);
11701 #endif
11702
11703 #ifdef USE_CAIRO
11704 if (FRAME_CR_CONTEXT (f))
11705 {
11706 cairo_surface_t *surface = cairo_get_target (FRAME_CR_CONTEXT (f));
11707 if (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_XLIB)
11708 {
11709 eassert (cairo_xlib_surface_get_display (surface)
11710 == FRAME_X_DISPLAY (f));
11711 eassert (cairo_xlib_surface_get_drawable (surface)
11712 == FRAME_X_RAW_DRAWABLE (f));
11713 cairo_surface_flush (surface);
11714 XCopyArea (FRAME_X_DISPLAY (f),
11715 FRAME_X_DRAWABLE (f), FRAME_X_DRAWABLE (f),
11716 f->output_data.x->normal_gc,
11717 x, from_y,
11718 width, height,
11719 x, to_y);
11720 cairo_surface_mark_dirty_rectangle (surface, x, to_y, width, height);
11721 }
11722 #ifdef USE_CAIRO_XCB_SURFACE
11723 else if (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_XCB)
11724 {
11725 cairo_surface_flush (surface);
11726 xcb_copy_area (FRAME_DISPLAY_INFO (f)->xcb_connection,
11727 (xcb_drawable_t) FRAME_X_DRAWABLE (f),
11728 (xcb_drawable_t) FRAME_X_DRAWABLE (f),
11729 (xcb_gcontext_t) XGContextFromGC (f->output_data.x->normal_gc),
11730 x, from_y, x, to_y, width, height);
11731 cairo_surface_mark_dirty_rectangle (surface, x, to_y, width, height);
11732 }
11733 #endif
11734 else
11735 {
11736 cairo_surface_t *s
11737 = cairo_surface_create_similar (surface,
11738 cairo_surface_get_content (surface),
11739 width, height);
11740 cairo_t *cr = cairo_create (s);
11741 cairo_set_source_surface (cr, surface, -x, -from_y);
11742 cairo_paint (cr);
11743 cairo_destroy (cr);
11744
11745 cr = FRAME_CR_CONTEXT (f);
11746 cairo_save (cr);
11747 cairo_set_source_surface (cr, s, x, to_y);
11748 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
11749 cairo_rectangle (cr, x, to_y, width, height);
11750 cairo_fill (cr);
11751 cairo_restore (cr);
11752 cairo_surface_destroy (s);
11753 }
11754 }
11755 else
11756 #endif
11757 XCopyArea (FRAME_X_DISPLAY (f),
11758 FRAME_X_DRAWABLE (f), FRAME_X_DRAWABLE (f),
11759 f->output_data.x->normal_gc,
11760 x, from_y,
11761 width, height,
11762 x, to_y);
11763
11764 unblock_input ();
11765 }
11766
11767
11768
11769
11770
11771
11772
11773
11774 static void
11775 x_frame_highlight (struct frame *f)
11776 {
11777 struct x_display_info *dpyinfo;
11778
11779 dpyinfo = FRAME_DISPLAY_INFO (f);
11780
11781
11782
11783
11784
11785 block_input ();
11786
11787
11788
11789
11790 x_ignore_errors_for_next_request (dpyinfo, 0);
11791 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11792 f->output_data.x->border_pixel);
11793 x_stop_ignoring_errors (dpyinfo);
11794 unblock_input ();
11795 gui_update_cursor (f, true);
11796 x_set_frame_alpha (f);
11797 }
11798
11799 static void
11800 x_frame_unhighlight (struct frame *f)
11801 {
11802 struct x_display_info *dpyinfo;
11803
11804 dpyinfo = FRAME_DISPLAY_INFO (f);
11805
11806
11807
11808
11809
11810
11811 block_input ();
11812
11813 x_ignore_errors_for_next_request (dpyinfo, 0);
11814 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11815 f->output_data.x->border_tile);
11816 x_stop_ignoring_errors (dpyinfo);
11817 unblock_input ();
11818
11819 gui_update_cursor (f, true);
11820 x_set_frame_alpha (f);
11821 }
11822
11823
11824
11825
11826
11827
11828
11829 static void
11830 x_new_focus_frame (struct x_display_info *dpyinfo, struct frame *frame)
11831 {
11832 struct frame *old_focus = dpyinfo->x_focus_frame;
11833 #if defined USE_GTK && !defined HAVE_GTK3 && defined HAVE_XINPUT2
11834 XIEventMask mask;
11835 ptrdiff_t l;
11836
11837 if (dpyinfo->supports_xi2)
11838 {
11839 l = XIMaskLen (XI_LASTEVENT);
11840 mask.mask = alloca (l);
11841 mask.mask_len = l;
11842 memset (mask.mask, 0, l);
11843
11844 mask.deviceid = XIAllDevices;
11845 }
11846 #endif
11847
11848 if (frame != dpyinfo->x_focus_frame)
11849 {
11850
11851
11852 dpyinfo->x_focus_frame = frame;
11853
11854
11855
11856
11857 #if defined USE_GTK && !defined HAVE_GTK3 && defined HAVE_XINPUT2
11858 if (frame && dpyinfo->supports_xi2)
11859 XISetMask (mask.mask, XI_RawKeyPress);
11860
11861 if (dpyinfo->supports_xi2)
11862 XISelectEvents (dpyinfo->display, dpyinfo->root_window, &mask, 1);
11863 #endif
11864
11865 if (old_focus && old_focus->auto_lower)
11866 x_lower_frame (old_focus);
11867
11868 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
11869 dpyinfo->x_pending_autoraise_frame = dpyinfo->x_focus_frame;
11870 else
11871 dpyinfo->x_pending_autoraise_frame = NULL;
11872 }
11873
11874 x_frame_rehighlight (dpyinfo);
11875 }
11876
11877 #if defined HAVE_XFIXES && XFIXES_VERSION >= 40000
11878
11879
11880
11881
11882 static bool
11883 x_fixes_pointer_blanking_supported (struct x_display_info *dpyinfo)
11884 {
11885 return (dpyinfo->xfixes_supported_p
11886 && dpyinfo->xfixes_major >= 4);
11887 }
11888
11889 #endif
11890
11891
11892
11893 #if defined HAVE_XFIXES && XFIXES_VERSION >= 40000
11894
11895 static void
11896 xfixes_toggle_visible_pointer (struct frame *f, bool invisible)
11897
11898 {
11899 if (invisible)
11900 XFixesHideCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11901 else
11902 XFixesShowCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11903 f->pointer_invisible = invisible;
11904 }
11905
11906 #endif
11907
11908
11909 static Cursor
11910 make_invisible_cursor (struct x_display_info *dpyinfo)
11911 {
11912 Display *dpy = dpyinfo->display;
11913 static char const no_data[] = { 0 };
11914 Pixmap pix;
11915 XColor col;
11916 Cursor c;
11917
11918 c = None;
11919
11920 x_catch_errors (dpy);
11921 pix = XCreateBitmapFromData (dpy, dpyinfo->root_window, no_data, 1, 1);
11922 if (!x_had_errors_p (dpy) && pix != None)
11923 {
11924 Cursor pixc;
11925 col.pixel = 0;
11926 col.red = col.green = col.blue = 0;
11927 col.flags = DoRed | DoGreen | DoBlue;
11928 pixc = XCreatePixmapCursor (dpy, pix, pix, &col, &col, 0, 0);
11929 if (! x_had_errors_p (dpy) && pixc != None)
11930 c = pixc;
11931 XFreePixmap (dpy, pix);
11932 }
11933
11934 x_uncatch_errors ();
11935
11936 return c;
11937 }
11938
11939
11940
11941 static void
11942 x_toggle_visible_pointer (struct frame *f, bool invisible)
11943 {
11944 struct x_display_info *dpyinfo;
11945
11946 dpyinfo = FRAME_DISPLAY_INFO (f);
11947
11948
11949
11950
11951 if (dpyinfo->invisible_cursor == None)
11952 dpyinfo->invisible_cursor = make_invisible_cursor (dpyinfo);
11953
11954 #if !defined HAVE_XFIXES || XFIXES_VERSION < 40000
11955 if (dpyinfo->invisible_cursor == None)
11956 invisible = false;
11957 #else
11958
11959 if (dpyinfo->invisible_cursor == None)
11960 {
11961 if (x_fixes_pointer_blanking_supported (dpyinfo))
11962 {
11963 dpyinfo->fixes_pointer_blanking = true;
11964 xfixes_toggle_visible_pointer (f, invisible);
11965
11966 return;
11967 }
11968 else
11969 invisible = false;
11970 }
11971 #endif
11972
11973 if (invisible)
11974 XDefineCursor (dpyinfo->display, FRAME_X_WINDOW (f),
11975 dpyinfo->invisible_cursor);
11976 else
11977 XDefineCursor (dpyinfo->display, FRAME_X_WINDOW (f),
11978 f->output_data.x->current_cursor);
11979
11980 f->pointer_invisible = invisible;
11981 }
11982
11983 static void
11984 XTtoggle_invisible_pointer (struct frame *f, bool invisible)
11985 {
11986 block_input ();
11987 #if defined HAVE_XFIXES && XFIXES_VERSION >= 40000
11988 if (FRAME_DISPLAY_INFO (f)->fixes_pointer_blanking
11989 && x_fixes_pointer_blanking_supported (FRAME_DISPLAY_INFO (f)))
11990 xfixes_toggle_visible_pointer (f, invisible);
11991 else
11992 #endif
11993 x_toggle_visible_pointer (f, invisible);
11994 unblock_input ();
11995 }
11996
11997
11998
11999
12000
12001
12002
12003
12004 static void
12005 x_focus_changed (int type, int state, struct x_display_info *dpyinfo,
12006 struct frame *frame, struct input_event *bufp)
12007 {
12008 if (type == FocusIn)
12009 {
12010 if (dpyinfo->x_focus_event_frame != frame)
12011 {
12012 x_new_focus_frame (dpyinfo, frame);
12013 dpyinfo->x_focus_event_frame = frame;
12014 bufp->kind = FOCUS_IN_EVENT;
12015 XSETFRAME (bufp->frame_or_window, frame);
12016 }
12017
12018 frame->output_data.x->focus_state |= state;
12019
12020 #ifdef HAVE_X_I18N
12021 if (FRAME_XIC (frame))
12022 XSetICFocus (FRAME_XIC (frame));
12023 #ifdef USE_GTK
12024 GtkWidget *widget;
12025
12026 if (x_gtk_use_native_input)
12027 {
12028 gtk_im_context_focus_in (FRAME_X_OUTPUT (frame)->im_context);
12029 widget = FRAME_GTK_OUTER_WIDGET (frame);
12030 gtk_im_context_set_client_window (FRAME_X_OUTPUT (frame)->im_context,
12031 gtk_widget_get_window (widget));
12032 }
12033 #endif
12034 #endif
12035 }
12036 else if (type == FocusOut)
12037 {
12038 frame->output_data.x->focus_state &= ~state;
12039
12040 if (dpyinfo->x_focus_event_frame == frame)
12041 {
12042 dpyinfo->x_focus_event_frame = 0;
12043 x_new_focus_frame (dpyinfo, 0);
12044
12045 bufp->kind = FOCUS_OUT_EVENT;
12046 XSETFRAME (bufp->frame_or_window, frame);
12047 }
12048
12049 if (!frame->output_data.x->focus_state)
12050 {
12051 #ifdef HAVE_X_I18N
12052 if (FRAME_XIC (frame))
12053 XUnsetICFocus (FRAME_XIC (frame));
12054 #ifdef USE_GTK
12055 if (x_gtk_use_native_input)
12056 {
12057 gtk_im_context_focus_out (FRAME_X_OUTPUT (frame)->im_context);
12058 gtk_im_context_set_client_window (FRAME_X_OUTPUT (frame)->im_context, NULL);
12059 }
12060 #endif
12061 #endif
12062 }
12063
12064 if (frame->pointer_invisible)
12065 XTtoggle_invisible_pointer (frame, false);
12066 }
12067 }
12068
12069
12070
12071
12072
12073 static struct frame *
12074 x_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
12075 {
12076 Lisp_Object tail, frame;
12077 struct frame *f;
12078
12079 if (wdesc == None)
12080 return NULL;
12081
12082 #ifdef HAVE_XWIDGETS
12083 struct xwidget_view *xvw = xwidget_view_from_window (wdesc);
12084
12085 if (xvw && xvw->frame)
12086 return xvw->frame;
12087 #endif
12088
12089 FOR_EACH_FRAME (tail, frame)
12090 {
12091 f = XFRAME (frame);
12092 if (!FRAME_X_P (f) || FRAME_DISPLAY_INFO (f) != dpyinfo)
12093 continue;
12094 if (f->output_data.x->hourglass_window == wdesc)
12095 return f;
12096 #ifdef USE_X_TOOLKIT
12097 if ((f->output_data.x->edit_widget
12098 && XtWindow (f->output_data.x->edit_widget) == wdesc)
12099
12100 || (!f->output_data.x->edit_widget
12101 && FRAME_X_WINDOW (f) == wdesc)
12102 || f->output_data.x->icon_desc == wdesc)
12103 return f;
12104 #else
12105 #ifdef USE_GTK
12106 if (f->output_data.x->edit_widget)
12107 {
12108 GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
12109 struct x_output *x = f->output_data.x;
12110 if (gwdesc != 0 && gwdesc == x->edit_widget)
12111 return f;
12112 }
12113 #endif
12114 if (FRAME_X_WINDOW (f) == wdesc
12115 || f->output_data.x->icon_desc == wdesc)
12116 return f;
12117 #endif
12118 }
12119 return 0;
12120 }
12121
12122
12123
12124
12125
12126 static struct frame *
12127 x_tooltip_window_to_frame (struct x_display_info *dpyinfo,
12128 Window wdesc, bool *unrelated_tooltip_p)
12129 {
12130 Lisp_Object tail, frame;
12131 struct frame *f;
12132 #ifdef USE_GTK
12133 GtkWidget *widget;
12134 GdkWindow *tooltip_window;
12135 #endif
12136
12137 if (unrelated_tooltip_p)
12138 *unrelated_tooltip_p = false;
12139
12140 FOR_EACH_FRAME (tail, frame)
12141 {
12142 f = XFRAME (frame);
12143
12144 if (FRAME_X_P (f) && FRAME_TOOLTIP_P (f)
12145 && FRAME_DISPLAY_INFO (f) == dpyinfo
12146 && FRAME_X_WINDOW (f) == wdesc)
12147 return f;
12148
12149 #ifdef USE_GTK
12150 if (!FRAME_X_P (f))
12151 continue;
12152
12153 if (FRAME_X_OUTPUT (f)->ttip_window)
12154 widget = GTK_WIDGET (FRAME_X_OUTPUT (f)->ttip_window);
12155 else
12156 widget = NULL;
12157
12158 if (widget)
12159 tooltip_window = gtk_widget_get_window (widget);
12160 else
12161 tooltip_window = NULL;
12162
12163 #ifdef HAVE_GTK3
12164 if (tooltip_window
12165 && (gdk_x11_window_get_xid (tooltip_window) == wdesc))
12166 {
12167 if (unrelated_tooltip_p)
12168 *unrelated_tooltip_p = true;
12169 break;
12170 }
12171 #else
12172 if (tooltip_window
12173 && (GDK_WINDOW_XID (tooltip_window) == wdesc))
12174 {
12175 if (unrelated_tooltip_p)
12176 *unrelated_tooltip_p = true;
12177 break;
12178 }
12179 #endif
12180 #endif
12181 }
12182
12183 return NULL;
12184 }
12185
12186 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
12187
12188
12189
12190
12191 static struct frame *
12192 x_any_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
12193 {
12194 Lisp_Object tail, frame;
12195 struct frame *f, *found = NULL;
12196 struct x_output *x;
12197
12198 if (wdesc == None)
12199 return NULL;
12200
12201 #ifdef HAVE_XWIDGETS
12202 struct xwidget_view *xv = xwidget_view_from_window (wdesc);
12203
12204 if (xv)
12205 return xv->frame;
12206 #endif
12207
12208 FOR_EACH_FRAME (tail, frame)
12209 {
12210 if (found)
12211 break;
12212 f = XFRAME (frame);
12213 if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) == dpyinfo)
12214 {
12215
12216 x = f->output_data.x;
12217 if (x->hourglass_window == wdesc)
12218 found = f;
12219 else if (x->widget)
12220 {
12221 #ifdef USE_GTK
12222 GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
12223 if (gwdesc != 0
12224 && gtk_widget_get_toplevel (gwdesc) == x->widget)
12225 found = f;
12226 #else
12227 if (wdesc == XtWindow (x->widget)
12228 || wdesc == XtWindow (x->column_widget)
12229 || wdesc == XtWindow (x->edit_widget))
12230 found = f;
12231
12232 else if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
12233 found = f;
12234 #endif
12235 }
12236 else if (FRAME_X_WINDOW (f) == wdesc)
12237
12238 found = f;
12239 }
12240 }
12241
12242 return found;
12243 }
12244
12245
12246
12247 static struct frame *
12248 x_menubar_window_to_frame (struct x_display_info *dpyinfo,
12249 const XEvent *event)
12250 {
12251 Window wdesc;
12252 #ifdef HAVE_XINPUT2
12253 if (event->type == GenericEvent
12254 && dpyinfo->supports_xi2
12255 && (event->xcookie.evtype == XI_ButtonPress
12256 || event->xcookie.evtype == XI_ButtonRelease))
12257 wdesc = ((XIDeviceEvent *) event->xcookie.data)->event;
12258 else
12259 #endif
12260 wdesc = event->xany.window;
12261 Lisp_Object tail, frame;
12262 struct frame *f;
12263 struct x_output *x;
12264
12265 if (wdesc == None)
12266 return NULL;
12267
12268 FOR_EACH_FRAME (tail, frame)
12269 {
12270 f = XFRAME (frame);
12271 if (!FRAME_X_P (f) || FRAME_DISPLAY_INFO (f) != dpyinfo)
12272 continue;
12273 x = f->output_data.x;
12274 #ifdef USE_GTK
12275 if (x->menubar_widget && xg_event_is_for_menubar (f, event))
12276 return f;
12277 #else
12278
12279 if (x->menubar_widget
12280 && lw_window_is_in_menubar (wdesc, x->menubar_widget))
12281 return f;
12282 #endif
12283 }
12284 return 0;
12285 }
12286
12287
12288
12289
12290 struct frame *
12291 x_top_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
12292 {
12293 Lisp_Object tail, frame;
12294 struct frame *f;
12295 struct x_output *x;
12296
12297 if (wdesc == None)
12298 return NULL;
12299
12300 FOR_EACH_FRAME (tail, frame)
12301 {
12302 f = XFRAME (frame);
12303 if (!FRAME_X_P (f) || FRAME_DISPLAY_INFO (f) != dpyinfo)
12304 continue;
12305 x = f->output_data.x;
12306
12307 if (x->widget)
12308 {
12309
12310 #ifdef USE_GTK
12311 GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
12312 if (gwdesc == x->widget)
12313 return f;
12314 #else
12315 if (wdesc == XtWindow (x->widget))
12316 return f;
12317 #endif
12318 }
12319 else if (FRAME_X_WINDOW (f) == wdesc)
12320
12321 return f;
12322 }
12323 return 0;
12324 }
12325
12326 #else
12327
12328 #define x_any_window_to_frame(d, i) x_window_to_frame (d, i)
12329
12330 struct frame *
12331 x_top_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
12332 {
12333 return x_window_to_frame (dpyinfo, wdesc);
12334 }
12335
12336 static void
12337 x_next_event_from_any_display (XEvent *event)
12338 {
12339 struct x_display_info *dpyinfo;
12340 fd_set fds, rfds;
12341 int fd, maxfd, rc;
12342
12343 rc = -1;
12344 FD_ZERO (&rfds);
12345
12346 while (true)
12347 {
12348 FD_ZERO (&fds);
12349 maxfd = -1;
12350
12351 for (dpyinfo = x_display_list; dpyinfo;
12352 dpyinfo = dpyinfo->next)
12353 {
12354 fd = ConnectionNumber (dpyinfo->display);
12355
12356 if ((rc < 0 || FD_ISSET (fd, &rfds))
12357 && XPending (dpyinfo->display))
12358 {
12359 XNextEvent (dpyinfo->display, event);
12360 return;
12361 }
12362
12363 if (fd > maxfd)
12364 maxfd = fd;
12365
12366 eassert (fd < FD_SETSIZE);
12367 FD_SET (fd, &fds);
12368 }
12369
12370 eassert (maxfd >= 0);
12371
12372
12373
12374
12375 rc = pselect (maxfd + 1, &fds, NULL, NULL, NULL, NULL);
12376
12377 if (rc >= 0)
12378 rfds = fds;
12379 }
12380 }
12381
12382 #endif
12383
12384 static void
12385 x_handle_pending_selection_requests_1 (struct x_selection_request_event *tem)
12386 {
12387 specpdl_ref count;
12388 struct selection_input_event se;
12389
12390 count = SPECPDL_INDEX ();
12391 se = tem->se;
12392
12393 record_unwind_protect_ptr (xfree, tem);
12394 x_handle_selection_event (&se);
12395 unbind_to (count, Qnil);
12396 }
12397
12398
12399
12400 void
12401 x_handle_pending_selection_requests (void)
12402 {
12403 struct x_selection_request_event *tem;
12404
12405 while (pending_selection_requests)
12406 {
12407 tem = pending_selection_requests;
12408 pending_selection_requests = tem->next;
12409
12410 x_handle_pending_selection_requests_1 (tem);
12411 }
12412 }
12413
12414 static void
12415 x_push_selection_request (struct selection_input_event *se)
12416 {
12417 struct x_selection_request_event *tem;
12418
12419 tem = xmalloc (sizeof *tem);
12420 tem->next = pending_selection_requests;
12421 tem->se = *se;
12422 pending_selection_requests = tem;
12423 }
12424
12425 bool
12426 x_detect_pending_selection_requests (void)
12427 {
12428 return !!pending_selection_requests;
12429 }
12430
12431 static void
12432 x_clear_dnd_action (void)
12433 {
12434 x_dnd_action_symbol = Qnil;
12435 }
12436
12437
12438 static void
12439 x_dnd_delete_action_list (Lisp_Object frame)
12440 {
12441 struct frame *f;
12442
12443
12444
12445
12446
12447
12448 f = XFRAME (frame);
12449
12450 if (!FRAME_LIVE_P (f) || !FRAME_DISPLAY_INFO (f)->display)
12451 return;
12452
12453 block_input ();
12454 XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12455 FRAME_DISPLAY_INFO (f)->Xatom_XdndActionList);
12456 XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12457 FRAME_DISPLAY_INFO (f)->Xatom_XdndActionDescription);
12458 unblock_input ();
12459 }
12460
12461 static void
12462 x_dnd_lose_ownership (Lisp_Object timestamp_and_frame)
12463 {
12464 struct frame *f;
12465
12466 f = XFRAME (XCDR (timestamp_and_frame));
12467
12468 if (FRAME_LIVE_P (f))
12469 Fx_disown_selection_internal (QXdndSelection,
12470 XCAR (timestamp_and_frame),
12471 XCDR (timestamp_and_frame));
12472 }
12473
12474
12475
12476
12477 static void
12478 x_dnd_process_quit (struct frame *f, Time timestamp)
12479 {
12480 xm_drop_start_message dmsg;
12481
12482 if (x_dnd_in_progress)
12483 {
12484 if (x_dnd_last_seen_window != None
12485 && x_dnd_last_protocol_version != -1)
12486 x_dnd_send_leave (f, x_dnd_last_seen_window,
12487 x_dnd_last_seen_toplevel);
12488 else if (x_dnd_last_seen_window != None
12489 && !XM_DRAG_STYLE_IS_DROP_ONLY (x_dnd_last_motif_style)
12490 && x_dnd_last_motif_style != XM_DRAG_STYLE_NONE
12491 && x_dnd_motif_setup_p)
12492 {
12493 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
12494 XM_DRAG_REASON_DROP_START);
12495 dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST;
12496 dmsg.timestamp = timestamp;
12497 dmsg.side_effects
12498 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f),
12499 x_dnd_wanted_action),
12500 XM_DROP_SITE_VALID, x_dnd_motif_operations,
12501 XM_DROP_ACTION_DROP_CANCEL);
12502 dmsg.x = 0;
12503 dmsg.y = 0;
12504 dmsg.index_atom = x_dnd_motif_atom;
12505 dmsg.source_window = FRAME_X_WINDOW (f);
12506
12507 x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f,
12508 x_dnd_last_seen_window,
12509 timestamp);
12510 xm_send_drop_message (FRAME_DISPLAY_INFO (f), FRAME_X_WINDOW (f),
12511 x_dnd_last_seen_window, &dmsg);
12512 }
12513
12514 x_dnd_end_window = x_dnd_last_seen_window;
12515 x_dnd_last_seen_window = None;
12516 x_dnd_last_seen_toplevel = None;
12517 x_dnd_in_progress = false;
12518 x_dnd_frame = NULL;
12519 }
12520
12521 x_dnd_waiting_for_finish = false;
12522 x_dnd_return_frame_object = NULL;
12523 x_dnd_movement_frame = NULL;
12524 x_dnd_wheel_frame = NULL;
12525 }
12526
12527
12528
12529
12530
12531
12532
12533
12534
12535
12536
12537
12538
12539
12540
12541
12542
12543
12544 Lisp_Object
12545 x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
12546 Lisp_Object return_frame, Atom *ask_action_list,
12547 const char **ask_action_names, size_t n_ask_actions,
12548 bool allow_current_frame, Atom *target_atoms,
12549 int ntargets, Lisp_Object selection_target_list,
12550 bool follow_tooltip)
12551 {
12552 #ifndef USE_GTK
12553 XEvent next_event;
12554 int finish;
12555 #endif
12556 XWindowAttributes root_window_attrs;
12557 struct input_event hold_quit;
12558 char *atom_name, *ask_actions;
12559 Lisp_Object action, ltimestamp, val;
12560 specpdl_ref ref, count, base;
12561 ptrdiff_t i, end, fill;
12562 XTextProperty prop;
12563 Lisp_Object frame_object, x, y, frame, local_value;
12564 bool signals_were_pending, need_sync;
12565 #ifdef HAVE_XKB
12566 XkbStateRec keyboard_state;
12567 #endif
12568 #ifndef USE_GTK
12569 struct x_display_info *event_display;
12570 #endif
12571 unsigned int additional_mask;
12572 #ifdef HAVE_XINPUT2
12573 struct xi_device_t *device;
12574 #endif
12575
12576 if (FRAME_DISPLAY_INFO (f)->untrusted)
12577
12578
12579
12580 error ("Drag-and-drop is not possible when the client is"
12581 " not trusted by the X server.");
12582
12583 base = SPECPDL_INDEX ();
12584
12585
12586
12587 specbind (Qx_dnd_targets_list, selection_target_list);
12588
12589 if (!FRAME_VISIBLE_P (f))
12590 error ("Frame must be visible");
12591
12592 XSETFRAME (frame, f);
12593 local_value = assq_no_quit (QXdndSelection,
12594 FRAME_TERMINAL (f)->Vselection_alist);
12595
12596 if (x_dnd_in_progress || x_dnd_waiting_for_finish)
12597 error ("A drag-and-drop session is already in progress");
12598
12599 DEFER_SELECTIONS;
12600
12601
12602
12603 if (NILP (local_value))
12604 error ("No local value for XdndSelection");
12605
12606 if (popup_activated ())
12607 error ("Trying to drag-and-drop from within a menu-entry");
12608
12609 x_set_dnd_targets (target_atoms, ntargets);
12610 record_unwind_protect_void (x_free_dnd_targets);
12611 record_unwind_protect_void (x_clear_dnd_action);
12612
12613 ltimestamp = x_timestamp_for_selection (FRAME_DISPLAY_INFO (f),
12614 QXdndSelection);
12615
12616 if (NILP (ltimestamp))
12617 error ("No local value for XdndSelection");
12618
12619 if (BIGNUMP (ltimestamp))
12620 x_dnd_selection_timestamp = bignum_to_intmax (ltimestamp);
12621 else
12622 x_dnd_selection_timestamp = XFIXNUM (ltimestamp);
12623
12624
12625
12626
12627
12628 if (!x_dnd_preserve_selection_data)
12629 record_unwind_protect (x_dnd_lose_ownership,
12630 Fcons (ltimestamp, frame));
12631
12632 x_dnd_motif_operations
12633 = xm_side_effect_from_action (FRAME_DISPLAY_INFO (f), xaction);
12634
12635 x_dnd_first_motif_operation = XM_DRAG_NOOP;
12636
12637 if (n_ask_actions)
12638 {
12639 x_dnd_motif_operations
12640 = xm_operations_from_actions (FRAME_DISPLAY_INFO (f),
12641 ask_action_list,
12642 n_ask_actions);
12643 x_dnd_first_motif_operation
12644 = xm_side_effect_from_action (FRAME_DISPLAY_INFO (f),
12645 ask_action_list[0]);
12646
12647 record_unwind_protect (x_dnd_delete_action_list, frame);
12648
12649 ask_actions = NULL;
12650 end = 0;
12651 count = SPECPDL_INDEX ();
12652
12653 for (i = 0; i < n_ask_actions; ++i)
12654 {
12655 fill = end;
12656 end += strlen (ask_action_names[i]) + 1;
12657
12658 if (ask_actions)
12659 ask_actions = xrealloc (ask_actions, end);
12660 else
12661 ask_actions = xmalloc (end);
12662
12663 strncpy (ask_actions + fill,
12664 ask_action_names[i],
12665 end - fill);
12666 }
12667
12668 prop.value = (unsigned char *) ask_actions;
12669 prop.encoding = XA_STRING;
12670 prop.format = 8;
12671 prop.nitems = end;
12672
12673 record_unwind_protect_ptr (xfree, ask_actions);
12674
12675
12676
12677 block_input ();
12678 x_catch_errors (FRAME_X_DISPLAY (f));
12679 XSetTextProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12680 &prop, FRAME_DISPLAY_INFO (f)->Xatom_XdndActionDescription);
12681
12682 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12683 FRAME_DISPLAY_INFO (f)->Xatom_XdndActionList, XA_ATOM, 32,
12684 PropModeReplace, (unsigned char *) ask_action_list,
12685 n_ask_actions);
12686 x_check_errors (FRAME_X_DISPLAY (f),
12687 "Can't set action descriptions: %s");
12688 x_uncatch_errors_after_check ();
12689 unblock_input ();
12690
12691 unbind_to (count, Qnil);
12692 }
12693
12694 record_unwind_protect_void (x_clear_dnd_variables);
12695
12696 if (follow_tooltip)
12697 {
12698 #if defined HAVE_XRANDR || defined USE_GTK
12699 x_dnd_monitors
12700 = FRAME_DISPLAY_INFO (f)->last_monitor_attributes_list;
12701
12702 if (NILP (x_dnd_monitors))
12703 #endif
12704 x_dnd_monitors
12705 = Fx_display_monitor_attributes_list (frame);
12706 }
12707
12708 x_dnd_update_tooltip = follow_tooltip;
12709
12710
12711 if (x_dnd_toplevels)
12712 x_dnd_free_toplevels (true);
12713
12714 #ifdef USE_GTK
12715
12716
12717 suppress_xg_select ();
12718 record_unwind_protect_void (release_xg_select);
12719 #endif
12720
12721
12722 XSETCAR (x_dnd_selection_alias_cell, QSECONDARY);
12723 XSETCDR (x_dnd_selection_alias_cell, QSECONDARY);
12724
12725
12726
12727 specbind (Qx_selection_alias_alist,
12728 Fcons (x_dnd_selection_alias_cell,
12729 Vx_selection_alias_alist));
12730
12731
12732 x_dnd_in_progress = true;
12733 x_dnd_recursion_depth = command_loop_level + minibuf_level;
12734 x_dnd_frame = f;
12735 x_dnd_last_seen_window = None;
12736 x_dnd_last_seen_toplevel = None;
12737 x_dnd_last_protocol_version = -1;
12738 x_dnd_last_window_is_frame = false;
12739 x_dnd_last_motif_style = XM_DRAG_STYLE_NONE;
12740 x_dnd_mouse_rect_target = None;
12741 x_dnd_action = None;
12742 x_dnd_action_symbol = Qnil;
12743 x_dnd_wanted_action = xaction;
12744 x_dnd_return_frame = 0;
12745 x_dnd_waiting_for_finish = false;
12746 x_dnd_waiting_for_motif_finish = 0;
12747 x_dnd_waiting_for_status_window = None;
12748 x_dnd_pending_send_position.type = 0;
12749 x_dnd_xm_use_help = false;
12750 x_dnd_motif_setup_p = false;
12751 x_dnd_end_window = None;
12752 x_dnd_run_unsupported_drop_function = false;
12753 x_dnd_use_toplevels
12754 = x_wm_supports (f, FRAME_DISPLAY_INFO (f)->Xatom_net_client_list_stacking);
12755 x_dnd_last_tooltip_valid = false;
12756 x_dnd_toplevels = NULL;
12757 x_dnd_allow_current_frame = allow_current_frame;
12758 x_dnd_movement_frame = NULL;
12759 x_dnd_wheel_frame = NULL;
12760 x_dnd_init_type_lists = false;
12761 x_dnd_need_send_drop = false;
12762
12763 #ifdef HAVE_XINPUT2
12764
12765 if (FRAME_DISPLAY_INFO (f)->supports_xi2)
12766 {
12767
12768
12769
12770 if (FRAME_DISPLAY_INFO (f)->client_pointer_device != -1)
12771 x_dnd_pointer_device
12772 = FRAME_DISPLAY_INFO (f)->client_pointer_device;
12773 else
12774
12775 XIGetClientPointer (FRAME_X_DISPLAY (f), None,
12776 &x_dnd_pointer_device);
12777
12778 x_dnd_keyboard_device = -1;
12779
12780 device = xi_device_from_id (FRAME_DISPLAY_INFO (f),
12781 x_dnd_pointer_device);
12782
12783 if (device)
12784 x_dnd_keyboard_device = device->attachment;
12785 }
12786 else
12787 {
12788 x_dnd_pointer_device = -1;
12789 x_dnd_keyboard_device = -1;
12790 }
12791
12792 #endif
12793
12794 #ifdef HAVE_XKB
12795 x_dnd_keyboard_state = 0;
12796
12797 if (FRAME_DISPLAY_INFO (f)->supports_xkb)
12798 {
12799 XkbSelectEvents (FRAME_X_DISPLAY (f), XkbUseCoreKbd,
12800 XkbStateNotifyMask, XkbStateNotifyMask);
12801 XkbGetState (FRAME_X_DISPLAY (f), XkbUseCoreKbd,
12802 &keyboard_state);
12803
12804 x_dnd_keyboard_state = (keyboard_state.mods
12805 | keyboard_state.ptr_buttons);
12806 }
12807 #endif
12808
12809 if (x_dnd_use_toplevels)
12810 {
12811 if (x_dnd_compute_toplevels (FRAME_DISPLAY_INFO (f)))
12812 {
12813 x_dnd_free_toplevels (true);
12814 x_dnd_use_toplevels = false;
12815 }
12816 else
12817 record_unwind_protect_void (x_free_dnd_toplevels);
12818 }
12819
12820 if (!NILP (return_frame))
12821 x_dnd_return_frame = 1;
12822
12823 if (EQ (return_frame, Qnow))
12824 x_dnd_return_frame = 2;
12825
12826
12827
12828
12829
12830 XGetWindowAttributes (FRAME_X_DISPLAY (f),
12831 FRAME_DISPLAY_INFO (f)->root_window,
12832 &root_window_attrs);
12833
12834 additional_mask = SubstructureNotifyMask;
12835
12836 if (x_dnd_use_toplevels)
12837 additional_mask |= PropertyChangeMask;
12838
12839 XSelectInput (FRAME_X_DISPLAY (f),
12840 FRAME_DISPLAY_INFO (f)->root_window,
12841 root_window_attrs.your_event_mask
12842 | additional_mask);
12843
12844 if (EQ (return_frame, Qnow))
12845 x_dnd_update_state (FRAME_DISPLAY_INFO (f), CurrentTime);
12846
12847 while (x_dnd_in_progress || x_dnd_waiting_for_finish)
12848 {
12849 EVENT_INIT (hold_quit);
12850
12851 #ifdef USE_GTK
12852 current_finish = X_EVENT_NORMAL;
12853 current_hold_quit = &hold_quit;
12854 current_count = 0;
12855 xg_pending_quit_event.kind = NO_EVENT;
12856 #endif
12857
12858 block_input ();
12859 x_dnd_inside_handle_one_xevent = true;
12860 #ifdef USE_GTK
12861 gtk_main_iteration ();
12862 #elif defined USE_X_TOOLKIT
12863 XtAppNextEvent (Xt_app_con, &next_event);
12864 #else
12865 x_next_event_from_any_display (&next_event);
12866 #endif
12867
12868 #ifndef USE_GTK
12869 event_display
12870 = x_display_info_for_display (next_event.xany.display);
12871
12872 if (event_display)
12873 {
12874 #ifdef HAVE_X_I18N
12875 #ifdef HAVE_XINPUT2
12876 if (next_event.type != GenericEvent
12877 || !event_display->supports_xi2
12878 || (next_event.xgeneric.extension
12879 != event_display->xi2_opcode))
12880 {
12881 #endif
12882 if (!x_filter_event (event_display, &next_event))
12883 handle_one_xevent (event_display,
12884 &next_event, &finish, &hold_quit);
12885 #ifdef HAVE_XINPUT2
12886 }
12887 else
12888 handle_one_xevent (event_display,
12889 &next_event, &finish, &hold_quit);
12890 #endif
12891 #else
12892 handle_one_xevent (event_display,
12893 &next_event, &finish, &hold_quit);
12894 #endif
12895 }
12896 #else
12897
12898 current_count = -1;
12899 current_hold_quit = NULL;
12900 #endif
12901 x_dnd_inside_handle_one_xevent = false;
12902
12903
12904 x_clean_failable_requests (FRAME_DISPLAY_INFO (f));
12905
12906
12907
12908
12909 signals_were_pending = pending_signals;
12910 unblock_input ();
12911 pending_signals = signals_were_pending;
12912
12913
12914
12915 #ifndef USE_GTK
12916 if (event_display == FRAME_DISPLAY_INFO (f))
12917 {
12918 #endif
12919 if (x_dnd_movement_frame
12920
12921
12922 && (FRAME_X_DISPLAY (x_dnd_movement_frame)
12923 == FRAME_X_DISPLAY (f))
12924
12925
12926
12927
12928 && (x_dnd_in_progress || x_dnd_waiting_for_finish))
12929 {
12930 XSETFRAME (frame_object, x_dnd_movement_frame);
12931 XSETINT (x, x_dnd_movement_x);
12932 XSETINT (y, x_dnd_movement_y);
12933 x_dnd_movement_frame = NULL;
12934
12935 if (!NILP (Vx_dnd_movement_function)
12936 && FRAME_LIVE_P (XFRAME (frame_object))
12937 && !FRAME_TOOLTIP_P (XFRAME (frame_object))
12938 && x_dnd_movement_x >= 0
12939 && x_dnd_movement_y >= 0
12940 && x_dnd_frame
12941 && (XFRAME (frame_object) != x_dnd_frame
12942 || x_dnd_allow_current_frame))
12943 {
12944 x_dnd_old_window_attrs = root_window_attrs;
12945 x_dnd_unwind_flag = true;
12946
12947 ref = SPECPDL_INDEX ();
12948 record_unwind_protect_ptr (x_dnd_cleanup_drag_and_drop, f);
12949 call2 (Vx_dnd_movement_function, frame_object,
12950 Fposn_at_x_y (x, y, frame_object, Qnil));
12951 x_dnd_unwind_flag = false;
12952 unbind_to (ref, Qnil);
12953
12954
12955
12956
12957 redisplay_preserve_echo_area (33);
12958 }
12959 }
12960
12961 if (x_dnd_wheel_frame
12962 && (x_dnd_in_progress || x_dnd_waiting_for_finish))
12963 {
12964 XSETFRAME (frame_object, x_dnd_wheel_frame);
12965 XSETINT (x, x_dnd_wheel_x);
12966 XSETINT (y, x_dnd_wheel_y);
12967 x_dnd_wheel_frame = NULL;
12968
12969 if (!NILP (Vx_dnd_wheel_function)
12970 && FRAME_LIVE_P (XFRAME (frame_object))
12971 && !FRAME_TOOLTIP_P (XFRAME (frame_object))
12972 && x_dnd_movement_x >= 0
12973 && x_dnd_movement_y >= 0
12974 && x_dnd_frame
12975 && (XFRAME (frame_object) != x_dnd_frame
12976 || x_dnd_allow_current_frame))
12977 {
12978 x_dnd_old_window_attrs = root_window_attrs;
12979 x_dnd_unwind_flag = true;
12980
12981 ref = SPECPDL_INDEX ();
12982 record_unwind_protect_ptr (x_dnd_cleanup_drag_and_drop, f);
12983 call4 (Vx_dnd_wheel_function,
12984 Fposn_at_x_y (x, y, frame_object, Qnil),
12985 make_fixnum (x_dnd_wheel_button),
12986 make_uint (x_dnd_wheel_state),
12987 make_uint (x_dnd_wheel_time));
12988 x_dnd_unwind_flag = false;
12989 unbind_to (ref, Qnil);
12990
12991
12992
12993
12994 redisplay_preserve_echo_area (33);
12995 }
12996 }
12997
12998 if (hold_quit.kind != NO_EVENT)
12999 {
13000 x_dnd_process_quit (f, hold_quit.timestamp);
13001 #ifdef USE_GTK
13002 current_hold_quit = NULL;
13003 #endif
13004
13005 x_restore_events_after_dnd (f, &root_window_attrs);
13006
13007
13008
13009
13010 kbd_buffer_store_event (&hold_quit);
13011
13012 quit ();
13013 }
13014
13015 if (pending_selection_requests
13016 && (x_dnd_in_progress || x_dnd_waiting_for_finish))
13017 {
13018 x_dnd_old_window_attrs = root_window_attrs;
13019 x_dnd_unwind_flag = true;
13020
13021 ref = SPECPDL_INDEX ();
13022 record_unwind_protect_ptr (x_dnd_cleanup_drag_and_drop, f);
13023 x_handle_pending_selection_requests ();
13024 x_dnd_unwind_flag = false;
13025 unbind_to (ref, Qnil);
13026 }
13027
13028
13029
13030
13031 if (!NILP (Vquit_flag) && !NILP (Vinhibit_quit))
13032 {
13033 x_dnd_process_quit (f, FRAME_DISPLAY_INFO (f)->last_user_time);
13034 #ifdef USE_GTK
13035 current_hold_quit = NULL;
13036 #endif
13037 x_restore_events_after_dnd (f, &root_window_attrs);
13038 quit ();
13039 }
13040
13041 if (x_dnd_run_unsupported_drop_function
13042 && x_dnd_waiting_for_finish)
13043 {
13044 x_dnd_run_unsupported_drop_function = false;
13045 x_dnd_waiting_for_finish = false;
13046 x_dnd_unwind_flag = true;
13047
13048 ref = SPECPDL_INDEX ();
13049 record_unwind_protect_ptr (x_dnd_cleanup_drag_and_drop, f);
13050
13051 if (!NILP (Vx_dnd_unsupported_drop_function))
13052 val = call8 (Vx_dnd_unsupported_drop_function,
13053 XCAR (XCDR (x_dnd_unsupported_drop_data)),
13054 Fnth (make_fixnum (3), x_dnd_unsupported_drop_data),
13055 Fnth (make_fixnum (4), x_dnd_unsupported_drop_data),
13056 Fnth (make_fixnum (2), x_dnd_unsupported_drop_data),
13057 make_uint (x_dnd_unsupported_drop_window),
13058 frame, make_uint (x_dnd_unsupported_drop_time),
13059 Fcopy_sequence (XCAR (x_dnd_unsupported_drop_data)));
13060 else
13061 val = Qnil;
13062
13063 if (NILP (val))
13064 x_dnd_do_unsupported_drop (FRAME_DISPLAY_INFO (f),
13065 frame, XCAR (x_dnd_unsupported_drop_data),
13066 XCAR (XCDR (x_dnd_unsupported_drop_data)),
13067 x_dnd_unsupported_drop_window,
13068 XFIXNUM (Fnth (make_fixnum (3),
13069 x_dnd_unsupported_drop_data)),
13070 XFIXNUM (Fnth (make_fixnum (4),
13071 x_dnd_unsupported_drop_data)),
13072 x_dnd_unsupported_drop_time);
13073 else if (SYMBOLP (val))
13074 x_dnd_action_symbol = val;
13075
13076 x_dnd_unwind_flag = false;
13077 unbind_to (ref, Qnil);
13078
13079
13080
13081 break;
13082 }
13083
13084 #ifdef USE_GTK
13085 if (xg_pending_quit_event.kind != NO_EVENT)
13086 {
13087 xg_pending_quit_event.kind = NO_EVENT;
13088 current_hold_quit = NULL;
13089
13090 x_dnd_process_quit (f, FRAME_DISPLAY_INFO (f)->last_user_time);
13091 x_restore_events_after_dnd (f, &root_window_attrs);
13092 quit ();
13093 }
13094 #else
13095 }
13096 else
13097 {
13098 if (x_dnd_movement_frame)
13099 x_dnd_movement_frame = NULL;
13100
13101 if (x_dnd_wheel_frame)
13102 x_dnd_wheel_frame = NULL;
13103
13104 if (hold_quit.kind != NO_EVENT)
13105 EVENT_INIT (hold_quit);
13106 }
13107 #endif
13108 }
13109
13110 x_dnd_waiting_for_finish = false;
13111
13112 #ifdef USE_GTK
13113 current_hold_quit = NULL;
13114 #endif
13115 x_dnd_movement_frame = NULL;
13116 x_dnd_wheel_frame = NULL;
13117 x_restore_events_after_dnd (f, &root_window_attrs);
13118
13119 if (x_dnd_return_frame == 3
13120 && FRAME_LIVE_P (x_dnd_return_frame_object))
13121 {
13122
13123
13124
13125 if (x_dnd_return_frame_object != x_dnd_frame)
13126 x_dnd_return_frame_object->last_mouse_device = Qnil;
13127
13128 x_dnd_return_frame_object->mouse_moved = true;
13129
13130 XSETFRAME (action, x_dnd_return_frame_object);
13131 x_dnd_return_frame_object = NULL;
13132
13133 return unbind_to (base, action);
13134 }
13135
13136 x_dnd_return_frame_object = NULL;
13137 FRAME_DISPLAY_INFO (f)->grabbed = 0;
13138
13139 if (!NILP (x_dnd_action_symbol))
13140 return unbind_to (base, x_dnd_action_symbol);
13141
13142 if (x_dnd_action != None)
13143 {
13144 block_input ();
13145 x_catch_errors (FRAME_X_DISPLAY (f));
13146 atom_name = x_get_atom_name (FRAME_DISPLAY_INFO (f),
13147 x_dnd_action, &need_sync);
13148
13149 if (need_sync)
13150 x_uncatch_errors ();
13151 else
13152
13153
13154 x_uncatch_errors_after_check ();
13155
13156 if (atom_name)
13157 {
13158 action = intern (atom_name);
13159 xfree (atom_name);
13160 }
13161 else
13162 action = Qnil;
13163 unblock_input ();
13164
13165 return unbind_to (base, action);
13166 }
13167
13168 return unbind_to (base, Qnil);
13169 }
13170
13171 #ifdef HAVE_XINPUT2
13172
13173
13174
13175
13176
13177
13178
13179
13180
13181
13182
13183 static void
13184 xi_handle_focus_change (struct x_display_info *dpyinfo)
13185 {
13186 struct input_event ie;
13187 struct frame *focus, *new;
13188 struct xi_device_t *device, *source = NULL;
13189 ptrdiff_t i;
13190 Time time;
13191 #ifdef USE_GTK
13192 struct x_output *output;
13193 GtkWidget *widget;
13194 #endif
13195
13196 focus = dpyinfo->x_focus_frame;
13197 new = NULL;
13198 time = 0;
13199
13200 dpyinfo->client_pointer_device = -1;
13201
13202 for (i = 0; i < dpyinfo->num_devices; ++i)
13203 {
13204 device = &dpyinfo->devices[i];
13205
13206 if (device->focus_frame
13207 && device->focus_frame_time > time)
13208 {
13209 new = device->focus_frame;
13210 time = device->focus_frame_time;
13211 source = device;
13212
13213
13214
13215
13216 if (device->use == XIMasterKeyboard)
13217 dpyinfo->client_pointer_device = device->attachment;
13218 else
13219 dpyinfo->client_pointer_device = device->device_id;
13220 }
13221
13222
13223
13224 else if (device->focus_implicit_frame
13225 && device->focus_implicit_time > time)
13226 {
13227 new = device->focus_implicit_frame;
13228 time = device->focus_implicit_time;
13229 source = device;
13230
13231
13232
13233
13234 if (device->use == XIMasterKeyboard)
13235 dpyinfo->client_pointer_device = device->attachment;
13236 else
13237 dpyinfo->client_pointer_device = device->device_id;
13238 }
13239 }
13240
13241 if (new != focus && focus)
13242 {
13243 #ifdef HAVE_X_I18N
13244 if (FRAME_XIC (focus))
13245 XUnsetICFocus (FRAME_XIC (focus));
13246 #endif
13247
13248 #ifdef USE_GTK
13249 output = FRAME_X_OUTPUT (focus);
13250
13251 if (x_gtk_use_native_input)
13252 {
13253 gtk_im_context_focus_out (output->im_context);
13254 gtk_im_context_set_client_window (output->im_context,
13255 NULL);
13256 }
13257 #endif
13258
13259 EVENT_INIT (ie);
13260 ie.kind = FOCUS_OUT_EVENT;
13261 XSETFRAME (ie.frame_or_window, focus);
13262
13263 kbd_buffer_store_event (&ie);
13264 }
13265
13266 if (new != focus && new)
13267 {
13268 #ifdef HAVE_X_I18N
13269 if (FRAME_XIC (new))
13270 XSetICFocus (FRAME_XIC (new));
13271 #endif
13272
13273 #ifdef USE_GTK
13274 output = FRAME_X_OUTPUT (new);
13275
13276 if (x_gtk_use_native_input)
13277 {
13278 widget = FRAME_GTK_OUTER_WIDGET (new);
13279
13280 gtk_im_context_focus_in (output->im_context);
13281 gtk_im_context_set_client_window (output->im_context,
13282 gtk_widget_get_window (widget));
13283 }
13284 #endif
13285
13286 EVENT_INIT (ie);
13287 ie.kind = FOCUS_IN_EVENT;
13288 ie.device = source->name;
13289 XSETFRAME (ie.frame_or_window, new);
13290
13291 kbd_buffer_store_event (&ie);
13292 }
13293
13294 x_new_focus_frame (dpyinfo, new);
13295 }
13296
13297 static void
13298 xi_focus_handle_for_device (struct x_display_info *dpyinfo,
13299 struct frame *mentioned_frame,
13300 XIEvent *base_event)
13301 {
13302 struct xi_device_t *device;
13303 XIEnterEvent *event;
13304
13305
13306
13307 event = (XIEnterEvent *) base_event;
13308 device = xi_device_from_id (dpyinfo, event->deviceid);
13309
13310 if (!device)
13311 return;
13312
13313 switch (event->evtype)
13314 {
13315 case XI_FocusIn:
13316
13317
13318 x_display_set_last_user_time (dpyinfo, event->time,
13319 event->send_event, true);
13320
13321 device->focus_frame = mentioned_frame;
13322 device->focus_frame_time = event->time;
13323 break;
13324
13325 case XI_FocusOut:
13326
13327
13328 x_display_set_last_user_time (dpyinfo, event->time,
13329 event->send_event, false);
13330
13331 device->focus_frame = NULL;
13332
13333
13334
13335
13336
13337
13338
13339
13340
13341
13342
13343
13344
13345
13346
13347
13348
13349
13350 device->focus_implicit_frame = NULL;
13351 break;
13352
13353 case XI_Enter:
13354 if (!event->focus)
13355 break;
13356
13357 if (device->use == XIMasterPointer)
13358 device = xi_device_from_id (dpyinfo, device->attachment);
13359
13360 if (!device)
13361 break;
13362
13363 device->focus_implicit_frame = mentioned_frame;
13364 device->focus_implicit_time = event->time;
13365 break;
13366
13367 case XI_Leave:
13368 if (!event->focus)
13369 break;
13370
13371 if (device->use == XIMasterPointer)
13372 device = xi_device_from_id (dpyinfo, device->attachment);
13373
13374 if (!device)
13375 break;
13376
13377 device->focus_implicit_frame = NULL;
13378 break;
13379 }
13380
13381 xi_handle_focus_change (dpyinfo);
13382 }
13383
13384 static void
13385 xi_handle_delete_frame (struct x_display_info *dpyinfo,
13386 struct frame *f)
13387 {
13388 struct xi_device_t *device;
13389 ptrdiff_t i;
13390
13391 for (i = 0; i < dpyinfo->num_devices; ++i)
13392 {
13393 device = &dpyinfo->devices[i];
13394
13395 if (device->focus_frame == f)
13396 device->focus_frame = NULL;
13397
13398 if (device->focus_implicit_frame == f)
13399 device->focus_implicit_frame = NULL;
13400 }
13401 }
13402
13403
13404
13405
13406
13407 static void
13408 xi_handle_interaction (struct x_display_info *dpyinfo,
13409 struct frame *f, struct xi_device_t *device,
13410 Time time)
13411 {
13412 bool change;
13413
13414
13415 if (device->use == XIMasterPointer)
13416 device = xi_device_from_id (dpyinfo, device->attachment);
13417
13418 if (!device)
13419 return;
13420
13421 change = false;
13422
13423 if (device->focus_frame == f)
13424 {
13425 device->focus_frame_time = time;
13426 change = true;
13427 }
13428
13429 if (device->focus_implicit_frame == f)
13430 {
13431 device->focus_implicit_time = time;
13432 change = true;
13433 }
13434
13435
13436 if (change && f != dpyinfo->x_focus_frame)
13437 xi_handle_focus_change (dpyinfo);
13438 }
13439
13440
13441
13442
13443
13444
13445
13446 static bool
13447 xi_position_changed (struct xi_device_t *device, XIDeviceEvent *xev)
13448 {
13449 bool changed;
13450
13451 changed = true;
13452
13453 if (xev->event != device->last_motion_window)
13454 goto out;
13455
13456 if (lrint (xev->event_x) == device->last_motion_x
13457 && lrint (xev->event_y) == device->last_motion_y)
13458 {
13459 changed = false;
13460 goto out;
13461 }
13462
13463 out:
13464 device->last_motion_x = lrint (xev->event_x);
13465 device->last_motion_y = lrint (xev->event_y);
13466 device->last_motion_window = xev->event;
13467
13468 return changed;
13469 }
13470
13471 static void
13472 xi_report_motion_window_clear (struct xi_device_t *device)
13473 {
13474 device->last_motion_window = None;
13475 }
13476
13477 #ifdef HAVE_XINPUT2_1
13478
13479
13480
13481 static struct xi_scroll_valuator_t *
13482 xi_get_scroll_valuator (struct xi_device_t *device, int number)
13483 {
13484 int i;
13485
13486 for (i = 0; i < device->scroll_valuator_count; ++i)
13487 {
13488 if (device->valuators[i].number == number)
13489 return &device->valuators[i];
13490 }
13491
13492 return NULL;
13493 }
13494
13495
13496
13497
13498 static bool
13499 xi_has_scroll_valuators (XIDeviceChangedEvent *event)
13500 {
13501 int i;
13502
13503 for (i = 0; i < event->num_classes; ++i)
13504 {
13505 if (event->classes[i]->type == XIScrollClass)
13506 return true;
13507 }
13508
13509 return false;
13510 }
13511
13512
13513
13514
13515
13516
13517
13518
13519 static void
13520 xi_handle_new_classes (struct x_display_info *dpyinfo, struct xi_device_t *device,
13521 XIAnyClassInfo **classes, int num_classes)
13522 {
13523 XIScrollClassInfo *scroll;
13524 struct xi_scroll_valuator_t *valuator;
13525 XIValuatorClassInfo *valuator_info;
13526 int i;
13527 #ifdef HAVE_XINPUT2_2
13528 XITouchClassInfo *touch;
13529 #endif
13530
13531 if (dpyinfo->xi2_version < 1)
13532
13533
13534 return;
13535
13536 device->valuators = xnmalloc (num_classes,
13537 sizeof *device->valuators);
13538 device->scroll_valuator_count = 0;
13539 #ifdef HAVE_XINPUT2_2
13540 device->direct_p = false;
13541 #endif
13542
13543 for (i = 0; i < num_classes; ++i)
13544 {
13545 switch (classes[i]->type)
13546 {
13547 case XIScrollClass:
13548 scroll = (XIScrollClassInfo *) classes[i];
13549
13550 xi_populate_scroll_valuator (device,
13551 device->scroll_valuator_count++,
13552 scroll);
13553 break;
13554
13555 #ifdef HAVE_XINPUT2_2
13556 case XITouchClass:
13557 touch = (XITouchClassInfo *) classes[i];
13558
13559
13560
13561
13562
13563
13564
13565
13566
13567
13568
13569
13570
13571
13572
13573
13574
13575
13576
13577
13578
13579
13580 if (touch->mode == XIDirectTouch)
13581 device->direct_p = true;
13582 else
13583 device->direct_p = false;
13584
13585 break;
13586 #endif
13587 }
13588 }
13589
13590
13591
13592
13593 for (i = 0; i < num_classes; ++i)
13594 {
13595 if (classes[i]->type != XIValuatorClass)
13596 continue;
13597
13598 valuator_info = (XIValuatorClassInfo *) classes[i];
13599
13600
13601
13602
13603
13604
13605
13606 if (valuator_info->value == 0.0
13607 && valuator_info->mode != XIModeAbsolute)
13608 continue;
13609
13610 valuator = xi_get_scroll_valuator (device,
13611 valuator_info->number);
13612
13613 if (!valuator)
13614 continue;
13615
13616 valuator->invalid_p = false;
13617 valuator->current_value = valuator_info->value;
13618 valuator->emacs_value = 0;
13619
13620 break;
13621 }
13622 }
13623
13624 #endif
13625
13626
13627
13628
13629 static void
13630 xi_handle_device_changed (struct x_display_info *dpyinfo,
13631 struct xi_device_t *device,
13632 XIDeviceChangedEvent *event)
13633 {
13634 #ifdef HAVE_XINPUT2_1
13635 int ndevices;
13636 XIDeviceInfo *info;
13637 #endif
13638 #ifdef HAVE_XINPUT2_2
13639 struct xi_touch_point_t *tem, *last;
13640 #endif
13641
13642 #ifdef HAVE_XINPUT2_1
13643 if (xi_has_scroll_valuators (event))
13644
13645
13646
13647
13648
13649
13650
13651 xi_handle_new_classes (dpyinfo, device, event->classes,
13652 event->num_classes);
13653 else
13654 {
13655
13656
13657
13658
13659
13660
13661 x_catch_errors (dpyinfo->display);
13662 info = XIQueryDevice (dpyinfo->display, event->deviceid,
13663
13664
13665
13666 &ndevices);
13667 x_uncatch_errors ();
13668
13669 if (!info)
13670 return;
13671
13672
13673
13674 xi_handle_new_classes (dpyinfo, device, info->classes,
13675 info->num_classes);
13676 }
13677 #endif
13678
13679 #ifdef HAVE_XINPUT2_2
13680
13681
13682 if (!device->direct_p)
13683 {
13684 tem = device->touchpoints;
13685
13686 while (tem)
13687 {
13688 last = tem;
13689 tem = tem->next;
13690 xfree (last);
13691 }
13692
13693 device->touchpoints = NULL;
13694 }
13695 #endif
13696 }
13697
13698
13699
13700
13701
13702
13703 static void
13704 xi_disable_devices (struct x_display_info *dpyinfo,
13705 int *to_disable, int n_disabled)
13706 {
13707 struct xi_device_t *devices;
13708 int ndevices, i, j;
13709 #ifdef HAVE_XINPUT2_2
13710 struct xi_touch_point_t *tem, *last;
13711 #endif
13712 #if defined HAVE_XINPUT2_2 && !defined HAVE_EXT_TOOL_BAR
13713 struct x_output *output;
13714 Lisp_Object tail, frame;
13715 #endif
13716
13717
13718
13719 if (!n_disabled)
13720 return;
13721
13722 ndevices = 0;
13723 devices = xzalloc (sizeof *devices * dpyinfo->num_devices);
13724
13725
13726
13727
13728
13729 for (i = 0; i < dpyinfo->num_devices; ++i)
13730 {
13731 for (j = 0; j < n_disabled; ++j)
13732 {
13733 if (to_disable[j] == dpyinfo->devices[i].device_id)
13734 {
13735 if (x_dnd_in_progress
13736
13737
13738
13739 && to_disable[j] == x_dnd_pointer_device)
13740 x_dnd_cancel_dnd_early ();
13741
13742
13743
13744 #ifdef HAVE_XINPUT2_1
13745 xfree (dpyinfo->devices[i].valuators);
13746 #endif
13747
13748
13749
13750 #ifdef HAVE_XINPUT2_2
13751 tem = dpyinfo->devices[i].touchpoints;
13752 while (tem)
13753 {
13754 last = tem;
13755 tem = tem->next;
13756 xfree (last);
13757 }
13758
13759 #ifndef HAVE_EXT_TOOL_BAR
13760
13761
13762
13763
13764
13765 FOR_EACH_FRAME (tail, frame)
13766 {
13767 if (!FRAME_X_P (XFRAME (frame))
13768 || (FRAME_DISPLAY_INFO (XFRAME (frame))
13769 != dpyinfo))
13770 continue;
13771
13772 output = FRAME_OUTPUT_DATA (XFRAME (frame));
13773
13774 if (output->tool_bar_touch_device
13775 == dpyinfo->devices[i].device_id)
13776 {
13777 if (XFRAME (frame)->last_tool_bar_item != -1
13778 && WINDOWP (XFRAME (frame)->tool_bar_window))
13779 handle_tool_bar_click (XFRAME (frame), 0, 0,
13780 false, 0);
13781
13782 output->tool_bar_touch_device = 0;
13783 }
13784 }
13785 #endif
13786 #endif
13787
13788 goto out;
13789 }
13790
13791 devices[ndevices++] = dpyinfo->devices[i];
13792
13793 out:
13794 continue;
13795 }
13796 }
13797
13798
13799 xfree (dpyinfo->devices);
13800
13801 dpyinfo->devices = devices;
13802 dpyinfo->num_devices = ndevices;
13803 }
13804
13805 #endif
13806
13807
13808
13809
13810
13811
13812 static void
13813 x_detect_focus_change (struct x_display_info *dpyinfo, struct frame *frame,
13814 const XEvent *event, struct input_event *bufp)
13815 {
13816 if (!frame)
13817 return;
13818
13819 switch (event->type)
13820 {
13821 case EnterNotify:
13822 case LeaveNotify:
13823 {
13824 struct frame *focus_frame = dpyinfo->x_focus_event_frame;
13825 int focus_state
13826 = focus_frame ? focus_frame->output_data.x->focus_state : 0;
13827
13828 if (event->xcrossing.detail != NotifyInferior
13829 && event->xcrossing.focus
13830 && ! (focus_state & FOCUS_EXPLICIT))
13831 x_focus_changed ((event->type == EnterNotify ? FocusIn : FocusOut),
13832 FOCUS_IMPLICIT,
13833 dpyinfo, frame, bufp);
13834 }
13835 break;
13836
13837 case FocusIn:
13838 case FocusOut:
13839
13840
13841
13842
13843
13844
13845
13846 if (event->xfocus.mode == NotifyGrab
13847 || event->xfocus.mode == NotifyUngrab)
13848 return;
13849 x_focus_changed (event->type,
13850 (event->xfocus.detail == NotifyPointer ?
13851 FOCUS_IMPLICIT : FOCUS_EXPLICIT),
13852 dpyinfo, frame, bufp);
13853 break;
13854
13855 case ClientMessage:
13856 if (event->xclient.message_type == dpyinfo->Xatom_XEMBED)
13857 {
13858 enum xembed_message msg = event->xclient.data.l[1];
13859 x_focus_changed ((msg == XEMBED_FOCUS_IN ? FocusIn : FocusOut),
13860 FOCUS_EXPLICIT, dpyinfo, frame, bufp);
13861 }
13862 break;
13863 }
13864 }
13865
13866
13867 #if (defined USE_LUCID && defined HAVE_XINPUT2) \
13868 || (!defined USE_X_TOOLKIT && !defined USE_GTK)
13869
13870
13871 void
13872 x_mouse_leave (struct x_display_info *dpyinfo)
13873 {
13874 #if defined HAVE_XINPUT2 && !defined USE_X_TOOLKIT
13875 struct xi_device_t *device;
13876 #endif
13877 Mouse_HLInfo *hlinfo;
13878
13879 hlinfo = &dpyinfo->mouse_highlight;
13880
13881 if (hlinfo->mouse_face_mouse_frame)
13882 {
13883 clear_mouse_face (hlinfo);
13884 hlinfo->mouse_face_mouse_frame = NULL;
13885 }
13886
13887 #if defined HAVE_XINPUT2 && !defined USE_X_TOOLKIT
13888 if (!dpyinfo->supports_xi2)
13889
13890
13891
13892
13893
13894
13895 #endif
13896 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
13897 #if defined HAVE_XINPUT2 && !defined USE_X_TOOLKIT
13898 else
13899 {
13900 if (dpyinfo->client_pointer_device == -1)
13901
13902
13903 return;
13904
13905 device = xi_device_from_id (dpyinfo, dpyinfo->client_pointer_device);
13906
13907 if (device && device->focus_implicit_frame)
13908 {
13909 device->focus_implicit_frame = NULL;
13910
13911
13912 xi_handle_focus_change (dpyinfo);
13913 }
13914 }
13915 #endif
13916 }
13917 #endif
13918
13919
13920
13921
13922
13923
13924
13925
13926
13927 static void
13928 XTframe_rehighlight (struct frame *frame)
13929 {
13930 x_frame_rehighlight (FRAME_DISPLAY_INFO (frame));
13931 }
13932
13933 static void
13934 x_frame_rehighlight (struct x_display_info *dpyinfo)
13935 {
13936 struct frame *old_highlight = dpyinfo->highlight_frame;
13937
13938 if (dpyinfo->x_focus_frame)
13939 {
13940 dpyinfo->highlight_frame
13941 = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
13942 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
13943 : dpyinfo->x_focus_frame);
13944 if (! FRAME_LIVE_P (dpyinfo->highlight_frame))
13945 {
13946 fset_focus_frame (dpyinfo->x_focus_frame, Qnil);
13947 dpyinfo->highlight_frame = dpyinfo->x_focus_frame;
13948 }
13949 }
13950 else
13951 dpyinfo->highlight_frame = 0;
13952
13953 if (dpyinfo->highlight_frame != old_highlight)
13954 {
13955 if (old_highlight)
13956 x_frame_unhighlight (old_highlight);
13957 if (dpyinfo->highlight_frame)
13958 x_frame_highlight (dpyinfo->highlight_frame);
13959 }
13960 }
13961
13962
13963
13964
13965
13966
13967 static void
13968 x_find_modifier_meanings (struct x_display_info *dpyinfo)
13969 {
13970 int min_code, max_code;
13971 KeySym *syms;
13972 int syms_per_code;
13973 XModifierKeymap *mods;
13974 #ifdef HAVE_XKB
13975 int i;
13976 int found_meta_p = false;
13977 unsigned int vmodmask;
13978 #endif
13979
13980 dpyinfo->meta_mod_mask = 0;
13981 dpyinfo->shift_lock_mask = 0;
13982 dpyinfo->alt_mod_mask = 0;
13983 dpyinfo->super_mod_mask = 0;
13984 dpyinfo->hyper_mod_mask = 0;
13985
13986 #ifdef HAVE_XKB
13987 if (dpyinfo->xkb_desc
13988 && dpyinfo->xkb_desc->server)
13989 {
13990 for (i = 0; i < XkbNumVirtualMods; i++)
13991 {
13992 vmodmask = dpyinfo->xkb_desc->server->vmods[i];
13993
13994 if (dpyinfo->xkb_desc->names->vmods[i] == dpyinfo->Xatom_Meta)
13995 {
13996 dpyinfo->meta_mod_mask |= vmodmask;
13997
13998 if (vmodmask)
13999 found_meta_p = true;
14000 }
14001 else if (dpyinfo->xkb_desc->names->vmods[i] == dpyinfo->Xatom_Alt)
14002 dpyinfo->alt_mod_mask |= vmodmask;
14003 else if (dpyinfo->xkb_desc->names->vmods[i] == dpyinfo->Xatom_Super)
14004 dpyinfo->super_mod_mask |= vmodmask;
14005 else if (dpyinfo->xkb_desc->names->vmods[i] == dpyinfo->Xatom_Hyper)
14006 dpyinfo->hyper_mod_mask |= vmodmask;
14007 else if (dpyinfo->xkb_desc->names->vmods[i] == dpyinfo->Xatom_ShiftLock)
14008 dpyinfo->shift_lock_mask |= vmodmask;
14009 }
14010
14011 if (!found_meta_p)
14012 {
14013 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
14014 dpyinfo->alt_mod_mask = 0;
14015 }
14016
14017 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
14018 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
14019
14020 if (dpyinfo->hyper_mod_mask & dpyinfo->super_mod_mask)
14021 dpyinfo->hyper_mod_mask &= ~dpyinfo->super_mod_mask;
14022
14023 return;
14024 }
14025 #endif
14026
14027 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
14028
14029 syms = XGetKeyboardMapping (dpyinfo->display,
14030 min_code, max_code - min_code + 1,
14031 &syms_per_code);
14032
14033 if (!syms)
14034 {
14035 dpyinfo->meta_mod_mask = Mod1Mask;
14036 dpyinfo->super_mod_mask = Mod2Mask;
14037 return;
14038 }
14039
14040 mods = XGetModifierMapping (dpyinfo->display);
14041
14042
14043
14044 {
14045 int row, col;
14046 bool found_alt_or_meta;
14047
14048 for (row = 3; row < 8; row++)
14049 {
14050 found_alt_or_meta = false;
14051 for (col = 0; col < mods->max_keypermod; col++)
14052 {
14053 KeyCode code = mods->modifiermap[(row * mods->max_keypermod) + col];
14054
14055
14056 if (code == 0)
14057 continue;
14058
14059
14060 {
14061 int code_col;
14062
14063 for (code_col = 0; code_col < syms_per_code; code_col++)
14064 {
14065 int sym = syms[((code - min_code) * syms_per_code) + code_col];
14066
14067 switch (sym)
14068 {
14069 case XK_Meta_L:
14070 case XK_Meta_R:
14071 found_alt_or_meta = true;
14072 dpyinfo->meta_mod_mask |= (1 << row);
14073 break;
14074
14075 case XK_Alt_L:
14076 case XK_Alt_R:
14077 found_alt_or_meta = true;
14078 dpyinfo->alt_mod_mask |= (1 << row);
14079 break;
14080
14081 case XK_Hyper_L:
14082 case XK_Hyper_R:
14083 if (!found_alt_or_meta)
14084 dpyinfo->hyper_mod_mask |= (1 << row);
14085 code_col = syms_per_code;
14086 col = mods->max_keypermod;
14087 break;
14088
14089 case XK_Super_L:
14090 case XK_Super_R:
14091 if (!found_alt_or_meta)
14092 dpyinfo->super_mod_mask |= (1 << row);
14093 code_col = syms_per_code;
14094 col = mods->max_keypermod;
14095 break;
14096
14097 case XK_Shift_Lock:
14098
14099 if (!found_alt_or_meta && ((1 << row) == LockMask))
14100 dpyinfo->shift_lock_mask = LockMask;
14101 code_col = syms_per_code;
14102 col = mods->max_keypermod;
14103 break;
14104 }
14105 }
14106 }
14107 }
14108 }
14109 }
14110
14111
14112 if (! dpyinfo->meta_mod_mask)
14113 {
14114 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
14115 dpyinfo->alt_mod_mask = 0;
14116 }
14117
14118
14119
14120 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
14121 {
14122 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
14123 }
14124
14125
14126
14127
14128 if (dpyinfo->hyper_mod_mask & dpyinfo->super_mod_mask)
14129 dpyinfo->hyper_mod_mask &= ~dpyinfo->super_mod_mask;
14130
14131 XFree (syms);
14132
14133 if (dpyinfo->modmap)
14134 XFreeModifiermap (dpyinfo->modmap);
14135 dpyinfo->modmap = mods;
14136 }
14137
14138
14139
14140
14141 int
14142 x_x_to_emacs_modifiers (struct x_display_info *dpyinfo, int state)
14143 {
14144 int mod_ctrl = ctrl_modifier;
14145 int mod_meta = meta_modifier;
14146 int mod_alt = alt_modifier;
14147 int mod_hyper = hyper_modifier;
14148 int mod_super = super_modifier;
14149 Lisp_Object tem;
14150
14151 tem = Fget (Vx_ctrl_keysym, Qmodifier_value);
14152 if (FIXNUMP (tem)) mod_ctrl = XFIXNUM (tem) & INT_MAX;
14153 tem = Fget (Vx_alt_keysym, Qmodifier_value);
14154 if (FIXNUMP (tem)) mod_alt = XFIXNUM (tem) & INT_MAX;
14155 tem = Fget (Vx_meta_keysym, Qmodifier_value);
14156 if (FIXNUMP (tem)) mod_meta = XFIXNUM (tem) & INT_MAX;
14157 tem = Fget (Vx_hyper_keysym, Qmodifier_value);
14158 if (FIXNUMP (tem)) mod_hyper = XFIXNUM (tem) & INT_MAX;
14159 tem = Fget (Vx_super_keysym, Qmodifier_value);
14160 if (FIXNUMP (tem)) mod_super = XFIXNUM (tem) & INT_MAX;
14161
14162 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
14163 | ((state & ControlMask) ? mod_ctrl : 0)
14164 | ((state & dpyinfo->meta_mod_mask) ? mod_meta : 0)
14165 | ((state & dpyinfo->alt_mod_mask) ? mod_alt : 0)
14166 | ((state & dpyinfo->super_mod_mask) ? mod_super : 0)
14167 | ((state & dpyinfo->hyper_mod_mask) ? mod_hyper : 0));
14168 }
14169
14170 int
14171 x_emacs_to_x_modifiers (struct x_display_info *dpyinfo, intmax_t state)
14172 {
14173 EMACS_INT mod_ctrl = ctrl_modifier;
14174 EMACS_INT mod_meta = meta_modifier;
14175 EMACS_INT mod_alt = alt_modifier;
14176 EMACS_INT mod_hyper = hyper_modifier;
14177 EMACS_INT mod_super = super_modifier;
14178
14179 Lisp_Object tem;
14180
14181 tem = Fget (Vx_ctrl_keysym, Qmodifier_value);
14182 if (FIXNUMP (tem)) mod_ctrl = XFIXNUM (tem);
14183 tem = Fget (Vx_alt_keysym, Qmodifier_value);
14184 if (FIXNUMP (tem)) mod_alt = XFIXNUM (tem);
14185 tem = Fget (Vx_meta_keysym, Qmodifier_value);
14186 if (FIXNUMP (tem)) mod_meta = XFIXNUM (tem);
14187 tem = Fget (Vx_hyper_keysym, Qmodifier_value);
14188 if (FIXNUMP (tem)) mod_hyper = XFIXNUM (tem);
14189 tem = Fget (Vx_super_keysym, Qmodifier_value);
14190 if (FIXNUMP (tem)) mod_super = XFIXNUM (tem);
14191
14192
14193 return ( ((state & mod_alt) ? dpyinfo->alt_mod_mask : 0)
14194 | ((state & mod_super) ? dpyinfo->super_mod_mask : 0)
14195 | ((state & mod_hyper) ? dpyinfo->hyper_mod_mask : 0)
14196 | ((state & shift_modifier) ? ShiftMask : 0)
14197 | ((state & mod_ctrl) ? ControlMask : 0)
14198 | ((state & mod_meta) ? dpyinfo->meta_mod_mask : 0));
14199 }
14200
14201
14202
14203 char *
14204 get_keysym_name (int keysym)
14205 {
14206 char *value;
14207
14208 block_input ();
14209 value = XKeysymToString (keysym);
14210 unblock_input ();
14211
14212 return value;
14213 }
14214
14215
14216
14217
14218
14219
14220
14221 static void
14222 x_compute_root_window_offset (struct frame *f, int root_x, int root_y,
14223 int event_x, int event_y)
14224 {
14225 FRAME_X_OUTPUT (f)->window_offset_certain_p = true;
14226 FRAME_X_OUTPUT (f)->root_x = root_x - event_x;
14227 FRAME_X_OUTPUT (f)->root_y = root_y - event_y;
14228 }
14229
14230
14231
14232
14233
14234
14235
14236 void
14237 x_translate_coordinates (struct frame *f, int root_x, int root_y,
14238 int *x_out, int *y_out)
14239 {
14240 struct x_output *output;
14241 Window dummy;
14242
14243 output = FRAME_X_OUTPUT (f);
14244
14245 if (output->window_offset_certain_p)
14246 {
14247
14248 *x_out = root_x - output->root_x;
14249 *y_out = root_y - output->root_y;
14250
14251 return;
14252 }
14253
14254
14255
14256 if (!XTranslateCoordinates (FRAME_X_DISPLAY (f),
14257 FRAME_DISPLAY_INFO (f)->root_window,
14258 FRAME_X_WINDOW (f), root_x, root_y,
14259 x_out, y_out, &dummy))
14260
14261
14262 *x_out = 0, *y_out = 0;
14263 else
14264 {
14265
14266 output->window_offset_certain_p = true;
14267 output->root_x = root_x - *x_out;
14268 output->root_y = root_y - *y_out;
14269 }
14270 }
14271
14272
14273
14274
14275
14276 void
14277 x_translate_coordinates_to_root (struct frame *f, int x, int y,
14278 int *x_out, int *y_out)
14279 {
14280 struct x_output *output;
14281 Window dummy;
14282
14283 output = FRAME_X_OUTPUT (f);
14284
14285 if (output->window_offset_certain_p)
14286 {
14287
14288 *x_out = x + output->root_x;
14289 *y_out = y + output->root_y;
14290
14291 return;
14292 }
14293
14294
14295
14296 if (!XTranslateCoordinates (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
14297 FRAME_DISPLAY_INFO (f)->root_window,
14298 x, y, x_out, y_out, &dummy))
14299 *x_out = 0, *y_out = 0;
14300 else
14301 {
14302
14303 output->window_offset_certain_p = true;
14304 output->root_x = *x_out - x;
14305 output->root_y = *y_out - y;
14306 }
14307 }
14308
14309
14310
14311
14312
14313 Lisp_Object
14314 x_handle_translate_coordinates (struct frame *f, Lisp_Object dest_window,
14315 int source_x, int source_y)
14316 {
14317 if (NILP (dest_window))
14318 {
14319
14320
14321
14322
14323 if (!FRAME_X_OUTPUT (f)->window_offset_certain_p)
14324 return Qnil;
14325
14326 return list3 (make_fixnum (source_x + FRAME_X_OUTPUT (f)->root_x),
14327 make_fixnum (source_y + FRAME_X_OUTPUT (f)->root_y),
14328 Qnil);
14329 }
14330
14331 return Qnil;
14332 }
14333
14334
14335
14336 #ifdef HAVE_XINPUT2
14337
14338 static void
14339 xi_compute_root_window_offset (struct frame *f, XIDeviceEvent *xev)
14340 {
14341
14342
14343 x_compute_root_window_offset (f, xev->root_x, xev->root_y,
14344 xev->event_x, xev->event_y);
14345 }
14346
14347 static void
14348 xi_compute_root_window_offset_enter (struct frame *f, XIEnterEvent *enter)
14349 {
14350 x_compute_root_window_offset (f, enter->root_x, enter->root_y,
14351 enter->event_x, enter->event_y);
14352 }
14353
14354 #ifdef HAVE_XINPUT2_4
14355
14356 static void
14357 xi_compute_root_window_offset_pinch (struct frame *f, XIGesturePinchEvent *pev)
14358 {
14359
14360
14361 x_compute_root_window_offset (f, pev->root_x, pev->root_y,
14362 pev->event_x, pev->event_y);
14363 }
14364
14365 #endif
14366
14367 #endif
14368
14369 static Bool
14370 x_query_pointer_1 (struct x_display_info *dpyinfo,
14371 int client_pointer_device, Window w,
14372 Window *root_return, Window *child_return,
14373 int *root_x_return, int *root_y_return,
14374 int *win_x_return, int *win_y_return,
14375 unsigned int *mask_return)
14376 {
14377 Bool rc;
14378 Display *dpy;
14379 #ifdef HAVE_XINPUT2
14380 bool had_errors;
14381 XIModifierState modifiers;
14382 XIButtonState buttons;
14383 XIGroupState group;
14384 double root_x, root_y, win_x, win_y;
14385 unsigned int state;
14386 #endif
14387
14388 dpy = dpyinfo->display;
14389
14390 #ifdef HAVE_XINPUT2
14391 if (client_pointer_device != -1)
14392 {
14393
14394
14395 x_catch_errors (dpy);
14396 rc = XIQueryPointer (dpyinfo->display,
14397 dpyinfo->client_pointer_device,
14398 w, root_return, child_return,
14399 &root_x, &root_y, &win_x, &win_y,
14400 &buttons, &modifiers, &group);
14401 had_errors = x_had_errors_p (dpy);
14402 x_uncatch_errors_after_check ();
14403
14404 if (had_errors)
14405 {
14406
14407
14408
14409
14410
14411 if (client_pointer_device == dpyinfo->client_pointer_device)
14412 dpyinfo->client_pointer_device = -1;
14413
14414 rc = XQueryPointer (dpyinfo->display, w, root_return,
14415 child_return, root_x_return,
14416 root_y_return, win_x_return,
14417 win_y_return, mask_return);
14418 }
14419 else
14420 {
14421 state = 0;
14422
14423 xi_convert_button_state (&buttons, &state);
14424 *mask_return = state | modifiers.effective;
14425
14426 XFree (buttons.mask);
14427
14428 *root_x_return = lrint (root_x);
14429 *root_y_return = lrint (root_y);
14430 *win_x_return = lrint (win_x);
14431 *win_y_return = lrint (win_y);
14432 }
14433 }
14434 else
14435 #endif
14436 rc = XQueryPointer (dpy, w, root_return, child_return,
14437 root_x_return, root_y_return, win_x_return,
14438 win_y_return, mask_return);
14439
14440 return rc;
14441 }
14442
14443 Bool
14444 x_query_pointer (Display *dpy, Window w, Window *root_return,
14445 Window *child_return, int *root_x_return,
14446 int *root_y_return, int *win_x_return,
14447 int *win_y_return, unsigned int *mask_return)
14448 {
14449 struct x_display_info *dpyinfo;
14450
14451 dpyinfo = x_display_info_for_display (dpy);
14452
14453 if (!dpyinfo)
14454 emacs_abort ();
14455
14456 #ifdef HAVE_XINPUT2
14457 return x_query_pointer_1 (dpyinfo, dpyinfo->client_pointer_device,
14458 w, root_return, child_return, root_x_return,
14459 root_y_return, win_x_return, win_y_return,
14460 mask_return);
14461 #else
14462 return x_query_pointer_1 (dpyinfo, -1, w, root_return, child_return,
14463 root_x_return, root_y_return, win_x_return,
14464 win_y_return, mask_return);
14465 #endif
14466 }
14467
14468
14469
14470
14471
14472
14473
14474
14475
14476
14477
14478
14479
14480
14481
14482
14483
14484
14485
14486
14487
14488
14489
14490
14491
14492
14493
14494
14495
14496
14497
14498
14499
14500
14501
14502 static Lisp_Object
14503 x_construct_mouse_click (struct input_event *result,
14504 const XButtonEvent *event,
14505 struct frame *f)
14506 {
14507 int x = event->x;
14508 int y = event->y;
14509
14510
14511
14512 result->kind = MOUSE_CLICK_EVENT;
14513 result->code = event->button - Button1;
14514 result->timestamp = event->time;
14515 result->modifiers = (x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO (f),
14516 event->state)
14517 | (event->type == ButtonRelease
14518 ? up_modifier
14519 : down_modifier));
14520
14521
14522
14523
14524 if (event->window != FRAME_X_WINDOW (f))
14525 x_translate_coordinates (f, event->x_root, event->y_root,
14526 &x, &y);
14527
14528 XSETINT (result->x, x);
14529 XSETINT (result->y, y);
14530 XSETFRAME (result->frame_or_window, f);
14531 result->arg = Qnil;
14532 return Qnil;
14533 }
14534
14535
14536
14537
14538
14539
14540
14541
14542
14543
14544
14545
14546
14547
14548
14549
14550
14551
14552 static bool
14553 x_note_mouse_movement (struct frame *frame, const XMotionEvent *event,
14554 Lisp_Object device)
14555 {
14556 XRectangle *r;
14557 struct x_display_info *dpyinfo;
14558
14559 if (!FRAME_X_OUTPUT (frame))
14560 return false;
14561
14562 dpyinfo = FRAME_DISPLAY_INFO (frame);
14563 dpyinfo->last_mouse_movement_time = event->time;
14564 dpyinfo->last_mouse_movement_time_send_event = event->send_event;
14565 dpyinfo->last_mouse_motion_frame = frame;
14566 dpyinfo->last_mouse_motion_x = event->x;
14567 dpyinfo->last_mouse_motion_y = event->y;
14568
14569 if (event->window != FRAME_X_WINDOW (frame))
14570 {
14571 frame->mouse_moved = true;
14572 frame->last_mouse_device = device;
14573 dpyinfo->last_mouse_scroll_bar = NULL;
14574 note_mouse_highlight (frame, -1, -1);
14575 dpyinfo->last_mouse_glyph_frame = NULL;
14576 return true;
14577 }
14578
14579
14580
14581 r = &dpyinfo->last_mouse_glyph;
14582 if (frame != dpyinfo->last_mouse_glyph_frame
14583 || event->x < r->x || event->x >= r->x + r->width
14584 || event->y < r->y || event->y >= r->y + r->height)
14585 {
14586 frame->mouse_moved = true;
14587 frame->last_mouse_device = device;
14588 dpyinfo->last_mouse_scroll_bar = NULL;
14589 note_mouse_highlight (frame, event->x, event->y);
14590
14591 remember_mouse_glyph (frame, event->x, event->y, r);
14592 dpyinfo->last_mouse_glyph_frame = frame;
14593 return true;
14594 }
14595
14596 return false;
14597 }
14598
14599
14600 static Window
14601 x_get_window_below (Display *dpy, Window window,
14602 int parent_x, int parent_y,
14603 int *inner_x, int *inner_y)
14604 {
14605 int rc, i, cx, cy;
14606 XWindowAttributes attrs;
14607 unsigned int nchildren;
14608 Window root, parent, *children, value;
14609 bool window_seen;
14610
14611
14612
14613 children = NULL;
14614 window_seen = false;
14615 value = None;
14616
14617 rc = XQueryTree (dpy, window, &root, &parent,
14618 &children, &nchildren);
14619
14620 if (rc)
14621 {
14622 if (children)
14623 XFree (children);
14624
14625 rc = XQueryTree (dpy, parent, &root,
14626 &parent, &children, &nchildren);
14627 }
14628
14629 if (rc)
14630 {
14631 for (i = nchildren - 1; i >= 0; --i)
14632 {
14633 if (children[i] == window)
14634 {
14635 window_seen = true;
14636 continue;
14637 }
14638
14639 if (!window_seen)
14640 continue;
14641
14642 rc = XGetWindowAttributes (dpy, children[i], &attrs);
14643
14644 if (rc && attrs.map_state != IsViewable)
14645 continue;
14646
14647 if (rc && parent_x >= attrs.x
14648 && parent_y >= attrs.y
14649 && parent_x < attrs.x + attrs.width
14650 && parent_y < attrs.y + attrs.height)
14651 {
14652 value = children[i];
14653 cx = parent_x - attrs.x;
14654 cy = parent_y - attrs.y;
14655
14656 break;
14657 }
14658 }
14659 }
14660
14661 if (children)
14662 XFree (children);
14663
14664 if (value)
14665 {
14666 *inner_x = cx;
14667 *inner_y = cy;
14668 }
14669
14670 return value;
14671 }
14672
14673
14674
14675 static void
14676 x_fast_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
14677 enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
14678 Time *timestamp)
14679 {
14680 int root_x, root_y, win_x, win_y;
14681 unsigned int mask;
14682 Window dummy;
14683 struct scroll_bar *bar;
14684 struct x_display_info *dpyinfo;
14685 Lisp_Object tail, frame;
14686 struct frame *f1;
14687
14688 dpyinfo = FRAME_DISPLAY_INFO (*fp);
14689
14690 if (dpyinfo->last_mouse_scroll_bar && !insist)
14691 {
14692 bar = dpyinfo->last_mouse_scroll_bar;
14693
14694 if (bar->horizontal)
14695 x_horizontal_scroll_bar_report_motion (fp, bar_window, part,
14696 x, y, timestamp);
14697 else
14698 x_scroll_bar_report_motion (fp, bar_window, part,
14699 x, y, timestamp);
14700
14701 return;
14702 }
14703
14704 if (!EQ (Vx_use_fast_mouse_position, Qreally_fast))
14705 {
14706
14707
14708
14709
14710
14711
14712 FOR_EACH_FRAME (tail, frame)
14713 {
14714 if (FRAME_X_P (XFRAME (frame))
14715 && (FRAME_DISPLAY_INFO (XFRAME (frame))
14716 == dpyinfo))
14717 XFRAME (frame)->mouse_moved = false;
14718 }
14719
14720 if (gui_mouse_grabbed (dpyinfo)
14721 && !EQ (track_mouse, Qdropping)
14722 && !EQ (track_mouse, Qdrag_source))
14723
14724 f1 = dpyinfo->last_mouse_frame;
14725 else
14726
14727 f1 = dpyinfo->last_mouse_motion_frame;
14728
14729 if (!f1 && (FRAME_X_P (SELECTED_FRAME ())
14730 && (FRAME_DISPLAY_INFO (SELECTED_FRAME ())
14731 == dpyinfo)))
14732 f1 = SELECTED_FRAME ();
14733
14734 if (!f1 || (!FRAME_X_P (f1) && (insist > 0)))
14735 FOR_EACH_FRAME (tail, frame)
14736 if (FRAME_X_P (XFRAME (frame))
14737 && (FRAME_DISPLAY_INFO (XFRAME (frame))
14738 == dpyinfo)
14739 && !FRAME_TOOLTIP_P (XFRAME (frame)))
14740 f1 = XFRAME (frame);
14741
14742 if (f1 && FRAME_TOOLTIP_P (f1))
14743 f1 = NULL;
14744
14745 if (f1 && FRAME_X_P (f1) && FRAME_X_WINDOW (f1))
14746 {
14747 if (!x_query_pointer (dpyinfo->display, FRAME_X_WINDOW (f1),
14748 &dummy, &dummy, &root_x, &root_y,
14749 &win_x, &win_y, &mask))
14750
14751 return;
14752
14753 remember_mouse_glyph (f1, win_x, win_y,
14754 &dpyinfo->last_mouse_glyph);
14755 dpyinfo->last_mouse_glyph_frame = f1;
14756
14757 *bar_window = Qnil;
14758 *part = scroll_bar_nowhere;
14759
14760
14761
14762
14763 if (EQ (track_mouse, Qdrag_source)
14764 && (win_x < 0 || win_y < 0
14765 || win_x >= FRAME_PIXEL_WIDTH (f1)
14766 || win_y >= FRAME_PIXEL_HEIGHT (f1)))
14767 *fp = NULL;
14768 else
14769 *fp = f1;
14770
14771 *timestamp = dpyinfo->last_mouse_movement_time;
14772 XSETINT (*x, win_x);
14773 XSETINT (*y, win_y);
14774 }
14775 }
14776 else
14777 {
14778
14779
14780
14781 if (dpyinfo->last_mouse_motion_frame)
14782 {
14783 *fp = dpyinfo->last_mouse_motion_frame;
14784 *timestamp = dpyinfo->last_mouse_movement_time;
14785 *x = make_fixnum (dpyinfo->last_mouse_motion_x);
14786 *y = make_fixnum (dpyinfo->last_mouse_motion_y);
14787 *bar_window = Qnil;
14788 *part = scroll_bar_nowhere;
14789
14790 FOR_EACH_FRAME (tail, frame)
14791 {
14792 if (FRAME_X_P (XFRAME (frame))
14793 && (FRAME_DISPLAY_INFO (XFRAME (frame))
14794 == dpyinfo))
14795 XFRAME (frame)->mouse_moved = false;
14796 }
14797
14798 dpyinfo->last_mouse_motion_frame->mouse_moved = false;
14799 }
14800 }
14801 }
14802
14803
14804
14805
14806
14807
14808
14809
14810
14811
14812
14813
14814
14815
14816
14817
14818
14819
14820
14821
14822
14823 static void
14824 XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
14825 enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
14826 Time *timestamp)
14827 {
14828 struct frame *f1, *maybe_tooltip;
14829 struct x_display_info *dpyinfo;
14830 bool unrelated_tooltip;
14831
14832 dpyinfo = FRAME_DISPLAY_INFO (*fp);
14833
14834 if (!NILP (Vx_use_fast_mouse_position))
14835 {
14836
14837
14838
14839
14840
14841
14842
14843
14844
14845 x_fast_mouse_position (fp, insist, bar_window, part, x,
14846 y, timestamp);
14847 return;
14848 }
14849
14850 block_input ();
14851
14852 if (dpyinfo->last_mouse_scroll_bar && insist == 0)
14853 {
14854 struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar;
14855
14856 if (bar->horizontal)
14857 x_horizontal_scroll_bar_report_motion (fp, bar_window, part, x, y, timestamp);
14858 else
14859 x_scroll_bar_report_motion (fp, bar_window, part, x, y, timestamp);
14860 }
14861 else
14862 {
14863 Window root;
14864 int root_x, root_y;
14865
14866 Window dummy_window;
14867 int dummy;
14868
14869 Lisp_Object frame, tail;
14870
14871
14872 FOR_EACH_FRAME (tail, frame)
14873 if (FRAME_X_P (XFRAME (frame))
14874 && FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
14875 XFRAME (frame)->mouse_moved = false;
14876
14877 dpyinfo->last_mouse_scroll_bar = NULL;
14878
14879
14880 x_query_pointer (FRAME_X_DISPLAY (*fp),
14881 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
14882
14883 &root,
14884
14885
14886 &dummy_window,
14887
14888 &root_x, &root_y,
14889
14890 &dummy, &dummy,
14891
14892
14893 (unsigned int *) &dummy);
14894
14895
14896
14897 {
14898 Window win, child;
14899 #ifdef USE_GTK
14900 Window first_win = 0;
14901 #endif
14902 int win_x, win_y;
14903 int parent_x, parent_y;
14904
14905 win = root;
14906 parent_x = root_x;
14907 parent_y = root_y;
14908
14909
14910
14911
14912
14913 x_catch_errors (FRAME_X_DISPLAY (*fp));
14914
14915 if (gui_mouse_grabbed (dpyinfo) && !EQ (track_mouse, Qdropping)
14916 && !EQ (track_mouse, Qdrag_source))
14917 {
14918
14919
14920 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
14921
14922 root,
14923
14924 FRAME_X_WINDOW (dpyinfo->last_mouse_frame),
14925
14926 root_x, root_y, &win_x, &win_y,
14927
14928 &child);
14929 f1 = dpyinfo->last_mouse_frame;
14930 }
14931 else
14932 {
14933 while (true)
14934 {
14935 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
14936
14937 root, win,
14938
14939 root_x, root_y, &win_x, &win_y,
14940
14941 &child);
14942
14943
14944
14945 if (child != None
14946 && (EQ (track_mouse, Qdrag_source)
14947 || EQ (track_mouse, Qdropping)))
14948 {
14949 maybe_tooltip = x_tooltip_window_to_frame (dpyinfo, child,
14950 &unrelated_tooltip);
14951
14952 if (maybe_tooltip || unrelated_tooltip)
14953 child = x_get_window_below (dpyinfo->display, child,
14954 parent_x, parent_y, &win_x,
14955 &win_y);
14956 }
14957
14958 if (child == None || child == win)
14959 {
14960 #ifdef USE_GTK
14961
14962
14963 struct frame *f = x_window_to_frame (dpyinfo, win);
14964
14965 if (f && FRAME_PARENT_FRAME (f))
14966 first_win = win;
14967 #endif
14968 break;
14969 }
14970 #ifdef USE_GTK
14971
14972
14973
14974
14975 if (x_window_to_frame (dpyinfo, win))
14976
14977
14978 first_win = win;
14979 #endif
14980 win = child;
14981 parent_x = win_x;
14982 parent_y = win_y;
14983 }
14984
14985 #ifdef USE_GTK
14986 if (first_win)
14987 win = first_win;
14988 #endif
14989
14990
14991
14992
14993
14994
14995
14996
14997
14998
14999
15000
15001 #ifdef USE_GTK
15002
15003
15004 f1 = x_window_to_frame (dpyinfo, win);
15005 #else
15006
15007 f1 = x_any_window_to_frame (dpyinfo, win);
15008 #endif
15009
15010 #ifdef USE_X_TOOLKIT
15011
15012
15013 if (f1 != NULL
15014 && f1->output_data.x->menubar_widget
15015 && win == XtWindow (f1->output_data.x->menubar_widget))
15016 f1 = NULL;
15017 #endif
15018 }
15019
15020
15021
15022
15023 if ((EQ (track_mouse, Qdrag_source)
15024 || EQ (track_mouse, Qdropping))
15025 && (dpyinfo->last_user_time
15026 < dpyinfo->last_mouse_movement_time))
15027 x_display_set_last_user_time (dpyinfo,
15028 dpyinfo->last_mouse_movement_time,
15029 dpyinfo->last_mouse_movement_time_send_event,
15030 true);
15031
15032 if ((!f1 || FRAME_TOOLTIP_P (f1))
15033 && (EQ (track_mouse, Qdropping)
15034 || EQ (track_mouse, Qdrag_source))
15035 && gui_mouse_grabbed (dpyinfo))
15036 {
15037
15038
15039
15040
15041 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
15042
15043 root,
15044
15045 FRAME_X_WINDOW (dpyinfo->last_mouse_frame),
15046
15047 root_x, root_y, &win_x, &win_y,
15048
15049 &child);
15050
15051 if (!EQ (track_mouse, Qdrag_source)
15052
15053 || (f1 && FRAME_TOOLTIP_P (f1)))
15054 f1 = dpyinfo->last_mouse_frame;
15055 else
15056 {
15057
15058
15059
15060 *bar_window = Qnil;
15061 *part = 0;
15062 *fp = NULL;
15063 XSETINT (*x, win_x);
15064 XSETINT (*y, win_y);
15065 *timestamp = dpyinfo->last_mouse_movement_time;
15066 }
15067 }
15068 else if (f1 && FRAME_TOOLTIP_P (f1))
15069 f1 = NULL;
15070
15071 if (x_had_errors_p (dpyinfo->display))
15072 f1 = NULL;
15073
15074 x_uncatch_errors_after_check ();
15075
15076
15077 if (!f1)
15078 {
15079 struct scroll_bar *bar;
15080
15081 bar = x_window_to_scroll_bar (dpyinfo->display, win, 2);
15082
15083 if (bar)
15084 {
15085 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
15086 win_x = parent_x;
15087 win_y = parent_y;
15088 }
15089 }
15090
15091 if (!f1 && insist > 0)
15092 f1 = SELECTED_FRAME ();
15093
15094 if (f1 && FRAME_X_P (f1))
15095 {
15096
15097
15098
15099
15100
15101
15102
15103
15104 dpyinfo = FRAME_DISPLAY_INFO (f1);
15105 remember_mouse_glyph (f1, win_x, win_y, &dpyinfo->last_mouse_glyph);
15106 dpyinfo->last_mouse_glyph_frame = f1;
15107
15108 *bar_window = Qnil;
15109 *part = 0;
15110 *fp = f1;
15111 XSETINT (*x, win_x);
15112 XSETINT (*y, win_y);
15113 *timestamp = dpyinfo->last_mouse_movement_time;
15114 }
15115 }
15116 }
15117
15118 unblock_input ();
15119 }
15120
15121
15122
15123
15124
15125
15126
15127
15128
15129 #if defined HAVE_XINPUT2
15130
15131
15132
15133
15134
15135 MAYBE_UNUSED static void
15136 xi_select_scroll_bar_events (struct x_display_info *dpyinfo,
15137 Window scroll_bar)
15138 {
15139 XIEventMask mask;
15140 unsigned char *m;
15141 ptrdiff_t length;
15142
15143 length = XIMaskLen (XI_LASTEVENT);
15144 mask.mask = m = alloca (length);
15145 memset (m, 0, length);
15146 mask.mask_len = length;
15147
15148 mask.deviceid = XIAllMasterDevices;
15149 XISetMask (m, XI_ButtonPress);
15150 XISetMask (m, XI_ButtonRelease);
15151 XISetMask (m, XI_Motion);
15152 XISetMask (m, XI_Enter);
15153 XISetMask (m, XI_Leave);
15154
15155 XISelectEvents (dpyinfo->display, scroll_bar, &mask, 1);
15156 }
15157
15158 #endif
15159
15160
15161
15162
15163
15164
15165 static struct scroll_bar *
15166 x_window_to_scroll_bar (Display *display, Window window_id, int type)
15167 {
15168 Lisp_Object tail, frame;
15169
15170 #if defined (USE_GTK) && !defined (HAVE_GTK3) && defined (USE_TOOLKIT_SCROLL_BARS)
15171 window_id = (Window) xg_get_scroll_id_for_window (display, window_id);
15172 #endif
15173
15174 FOR_EACH_FRAME (tail, frame)
15175 {
15176 Lisp_Object bar, condemned;
15177
15178 if (! FRAME_X_P (XFRAME (frame)))
15179 continue;
15180
15181
15182
15183 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
15184 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
15185
15186
15187 ! NILP (bar) || (bar = condemned,
15188 condemned = Qnil,
15189 ! NILP (bar));
15190 bar = XSCROLL_BAR (bar)->next)
15191 if (XSCROLL_BAR (bar)->x_window == window_id
15192 && FRAME_X_DISPLAY (XFRAME (frame)) == display
15193 && (type == 2
15194 || (type == 1 && XSCROLL_BAR (bar)->horizontal)
15195 || (type == 0 && !XSCROLL_BAR (bar)->horizontal)))
15196 return XSCROLL_BAR (bar);
15197 }
15198
15199 return NULL;
15200 }
15201
15202
15203 #if defined USE_LUCID
15204
15205
15206
15207
15208 static Widget
15209 x_window_to_menu_bar (Window window)
15210 {
15211 Lisp_Object tail, frame;
15212
15213 FOR_EACH_FRAME (tail, frame)
15214 if (FRAME_X_P (XFRAME (frame)))
15215 {
15216 Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
15217
15218 if (menu_bar && xlwmenu_window_p (menu_bar, window))
15219 return menu_bar;
15220 }
15221 return NULL;
15222 }
15223
15224 #endif
15225
15226
15227
15228
15229
15230
15231 #ifdef USE_TOOLKIT_SCROLL_BARS
15232
15233 static void x_send_scroll_bar_event (Lisp_Object, enum scroll_bar_part,
15234 int, int, bool);
15235
15236
15237
15238
15239 static Lisp_Object window_being_scrolled;
15240
15241 static Time
15242 x_get_last_toolkit_time (struct x_display_info *dpyinfo)
15243 {
15244 #ifdef USE_X_TOOLKIT
15245 return XtLastTimestampProcessed (dpyinfo->display);
15246 #else
15247 return dpyinfo->last_user_time;
15248 #endif
15249 }
15250
15251 #ifndef USE_GTK
15252
15253
15254
15255 static XtActionHookId action_hook_id;
15256 static XtActionHookId horizontal_action_hook_id;
15257
15258
15259
15260
15261 static Boolean xaw3d_arrow_scroll;
15262
15263
15264
15265
15266
15267 static Boolean xaw3d_pick_top;
15268
15269
15270
15271
15272
15273
15274 static void
15275 xt_action_hook (Widget widget, XtPointer client_data, String action_name,
15276 XEvent *event, String *params, Cardinal *num_params)
15277 {
15278 bool scroll_bar_p;
15279 const char *end_action;
15280
15281 #ifdef USE_MOTIF
15282 scroll_bar_p = XmIsScrollBar (widget);
15283 end_action = "Release";
15284 #else
15285 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
15286 end_action = "EndScroll";
15287 #endif
15288
15289 if (scroll_bar_p
15290 && strcmp (action_name, end_action) == 0
15291 && WINDOWP (window_being_scrolled))
15292 {
15293 struct window *w;
15294 struct scroll_bar *bar;
15295
15296 x_send_scroll_bar_event (window_being_scrolled,
15297 scroll_bar_end_scroll, 0, 0, false);
15298 w = XWINDOW (window_being_scrolled);
15299 bar = XSCROLL_BAR (w->vertical_scroll_bar);
15300
15301 if (bar->dragging != -1)
15302 {
15303 bar->dragging = -1;
15304
15305 set_vertical_scroll_bar (w);
15306 }
15307 window_being_scrolled = Qnil;
15308 #if defined (USE_LUCID)
15309 bar->last_seen_part = scroll_bar_nowhere;
15310 #endif
15311
15312 toolkit_scroll_bar_interaction = false;
15313 }
15314 }
15315
15316
15317 static void
15318 xt_horizontal_action_hook (Widget widget, XtPointer client_data, String action_name,
15319 XEvent *event, String *params, Cardinal *num_params)
15320 {
15321 bool scroll_bar_p;
15322 const char *end_action;
15323
15324 #ifdef USE_MOTIF
15325 scroll_bar_p = XmIsScrollBar (widget);
15326 end_action = "Release";
15327 #else
15328 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
15329 end_action = "EndScroll";
15330 #endif
15331
15332 if (scroll_bar_p
15333 && strcmp (action_name, end_action) == 0
15334 && WINDOWP (window_being_scrolled))
15335 {
15336 struct window *w;
15337 struct scroll_bar *bar;
15338
15339 x_send_scroll_bar_event (window_being_scrolled,
15340 scroll_bar_end_scroll, 0, 0, true);
15341 w = XWINDOW (window_being_scrolled);
15342 if (!NILP (w->horizontal_scroll_bar))
15343 {
15344 bar = XSCROLL_BAR (w->horizontal_scroll_bar);
15345 if (bar->dragging != -1)
15346 {
15347 bar->dragging = -1;
15348
15349 set_horizontal_scroll_bar (w);
15350 }
15351 window_being_scrolled = Qnil;
15352 #if defined (USE_LUCID)
15353 bar->last_seen_part = scroll_bar_nowhere;
15354 #endif
15355
15356 toolkit_scroll_bar_interaction = false;
15357 }
15358 }
15359 }
15360 #endif
15361
15362
15363
15364
15365 static bool
15366 x_protect_window_for_callback (struct x_display_info *dpyinfo,
15367 Lisp_Object window)
15368 {
15369 if (dpyinfo->n_protected_windows + 1
15370 >= dpyinfo->protected_windows_max)
15371 return false;
15372
15373 dpyinfo->protected_windows[dpyinfo->n_protected_windows++]
15374 = window;
15375 return true;
15376 }
15377
15378 static Lisp_Object
15379 x_unprotect_window_for_callback (struct x_display_info *dpyinfo)
15380 {
15381 Lisp_Object window;
15382
15383 if (!dpyinfo->n_protected_windows)
15384 return Qnil;
15385
15386 window = dpyinfo->protected_windows[0];
15387
15388 dpyinfo->n_protected_windows--;
15389
15390 if (dpyinfo->n_protected_windows)
15391 memmove (dpyinfo->protected_windows, &dpyinfo->protected_windows[1],
15392 sizeof (Lisp_Object) * dpyinfo->n_protected_windows);
15393
15394 return window;
15395 }
15396
15397
15398
15399
15400
15401
15402 static void
15403 x_send_scroll_bar_event (Lisp_Object window, enum scroll_bar_part part,
15404 int portion, int whole, bool horizontal)
15405 {
15406 XEvent event;
15407 XClientMessageEvent *ev = &event.xclient;
15408 struct window *w = XWINDOW (window);
15409 struct frame *f = XFRAME (w->frame);
15410 verify (INTPTR_WIDTH <= 64);
15411
15412
15413
15414 if (!x_protect_window_for_callback (FRAME_DISPLAY_INFO (f), window))
15415 return;
15416
15417 block_input ();
15418
15419 ev->type = ClientMessage;
15420 ev->message_type = (horizontal
15421 ? FRAME_DISPLAY_INFO (f)->Xatom_Horizontal_Scrollbar
15422 : FRAME_DISPLAY_INFO (f)->Xatom_Scrollbar);
15423 ev->display = FRAME_X_DISPLAY (f);
15424 ev->window = FRAME_X_WINDOW (f);
15425 ev->format = 32;
15426
15427
15428
15429
15430 ev->data.l[0] = 0;
15431 ev->data.l[1] = 0;
15432 ev->data.l[2] = part;
15433 ev->data.l[3] = portion;
15434 ev->data.l[4] = whole;
15435
15436
15437 #ifdef USE_X_TOOLKIT
15438 toolkit_scroll_bar_interaction = true;
15439 x_activate_timeout_atimer ();
15440 #endif
15441
15442
15443
15444
15445 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False,
15446 NoEventMask, &event);
15447 unblock_input ();
15448 }
15449
15450
15451
15452
15453
15454 static void
15455 x_scroll_bar_to_input_event (struct x_display_info *dpyinfo,
15456 const XEvent *event,
15457 struct input_event *ievent)
15458 {
15459 Lisp_Object window;
15460
15461
15462
15463
15464
15465 window = x_unprotect_window_for_callback (dpyinfo);
15466
15467 if (NILP (window))
15468 {
15469
15470
15471 EVENT_INIT (*ievent);
15472 return;
15473 }
15474
15475 ievent->kind = SCROLL_BAR_CLICK_EVENT;
15476 ievent->frame_or_window = window;
15477 ievent->arg = Qnil;
15478 ievent->timestamp = x_get_last_toolkit_time (dpyinfo);
15479 ievent->code = 0;
15480 ievent->part = event->xclient.data.l[2];
15481 ievent->x = make_fixnum (event->xclient.data.l[3]);
15482 ievent->y = make_fixnum (event->xclient.data.l[4]);
15483 ievent->modifiers = 0;
15484 }
15485
15486
15487
15488
15489 static void
15490 x_horizontal_scroll_bar_to_input_event (struct x_display_info *dpyinfo,
15491 const XEvent *event,
15492 struct input_event *ievent)
15493 {
15494 Lisp_Object window;
15495
15496
15497
15498
15499
15500 window = x_unprotect_window_for_callback (dpyinfo);
15501
15502 if (NILP (window))
15503 {
15504
15505
15506 EVENT_INIT (*ievent);
15507 return;
15508 }
15509
15510 ievent->kind = HORIZONTAL_SCROLL_BAR_CLICK_EVENT;
15511 ievent->frame_or_window = window;
15512 ievent->arg = Qnil;
15513 ievent->timestamp = x_get_last_toolkit_time (dpyinfo);
15514 ievent->code = 0;
15515 ievent->part = event->xclient.data.l[2];
15516 ievent->x = make_fixnum (event->xclient.data.l[3]);
15517 ievent->y = make_fixnum (event->xclient.data.l[4]);
15518 ievent->modifiers = 0;
15519 }
15520
15521
15522 #ifdef USE_MOTIF
15523
15524
15525
15526 #define XM_SB_MAX 10000000
15527
15528
15529
15530
15531
15532 static void
15533 xm_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data)
15534 {
15535 struct scroll_bar *bar = client_data;
15536 XmScrollBarCallbackStruct *cs = call_data;
15537 enum scroll_bar_part part = scroll_bar_nowhere;
15538 bool horizontal = bar->horizontal;
15539 int whole = 0, portion = 0;
15540
15541 switch (cs->reason)
15542 {
15543 case XmCR_DECREMENT:
15544 bar->dragging = -1;
15545 part = horizontal ? scroll_bar_left_arrow : scroll_bar_up_arrow;
15546 break;
15547
15548 case XmCR_INCREMENT:
15549 bar->dragging = -1;
15550 part = horizontal ? scroll_bar_right_arrow : scroll_bar_down_arrow;
15551 break;
15552
15553 case XmCR_PAGE_DECREMENT:
15554 bar->dragging = -1;
15555 part = horizontal ? scroll_bar_before_handle : scroll_bar_above_handle;
15556 break;
15557
15558 case XmCR_PAGE_INCREMENT:
15559 bar->dragging = -1;
15560 part = horizontal ? scroll_bar_after_handle : scroll_bar_below_handle;
15561 break;
15562
15563 case XmCR_TO_TOP:
15564 bar->dragging = -1;
15565 part = horizontal ? scroll_bar_to_leftmost : scroll_bar_to_top;
15566 break;
15567
15568 case XmCR_TO_BOTTOM:
15569 bar->dragging = -1;
15570 part = horizontal ? scroll_bar_to_rightmost : scroll_bar_to_bottom;
15571 break;
15572
15573 case XmCR_DRAG:
15574 {
15575 int slider_size;
15576
15577 block_input ();
15578 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
15579 unblock_input ();
15580
15581 if (horizontal)
15582 {
15583 portion = bar->whole * ((float)cs->value / XM_SB_MAX);
15584 whole = bar->whole * ((float)(XM_SB_MAX - slider_size) / XM_SB_MAX);
15585 portion = min (portion, whole);
15586 part = scroll_bar_horizontal_handle;
15587 }
15588 else
15589 {
15590 whole = XM_SB_MAX - slider_size;
15591 portion = min (cs->value, whole);
15592 part = scroll_bar_handle;
15593 }
15594
15595 bar->dragging = cs->value;
15596 }
15597 break;
15598
15599 case XmCR_VALUE_CHANGED:
15600 break;
15601 };
15602
15603 if (part != scroll_bar_nowhere)
15604 {
15605 window_being_scrolled = bar->window;
15606 x_send_scroll_bar_event (bar->window, part, portion, whole,
15607 bar->horizontal);
15608 }
15609 }
15610
15611 #elif defined USE_GTK
15612
15613
15614
15615
15616 static gboolean
15617 xg_scroll_callback (GtkRange *range, GtkScrollType scroll,
15618 gdouble value, gpointer user_data)
15619 {
15620 int whole, portion;
15621 struct scroll_bar *bar;
15622 enum scroll_bar_part part;
15623 GtkAdjustment *adj;
15624 struct frame *f;
15625 guint32 time;
15626 struct x_display_info *dpyinfo;
15627
15628 if (xg_ignore_gtk_scrollbar) return false;
15629
15630 whole = 0;
15631 portion = 0;
15632 bar = user_data;
15633 part = scroll_bar_nowhere;
15634 adj = GTK_ADJUSTMENT (gtk_range_get_adjustment (range));
15635 f = g_object_get_data (G_OBJECT (range), XG_FRAME_DATA);
15636 time = gtk_get_current_event_time ();
15637 dpyinfo = FRAME_DISPLAY_INFO (f);
15638
15639 if (time != GDK_CURRENT_TIME)
15640 x_display_set_last_user_time (dpyinfo, time, true,
15641 true);
15642
15643 switch (scroll)
15644 {
15645 case GTK_SCROLL_JUMP:
15646
15647 if (FRAME_DISPLAY_INFO (f)->grabbed != 0
15648 && FRAME_DISPLAY_INFO (f)->grabbed < (1 << 4))
15649 {
15650 if (bar->horizontal)
15651 {
15652 part = scroll_bar_horizontal_handle;
15653 whole = (int)(gtk_adjustment_get_upper (adj) -
15654 gtk_adjustment_get_page_size (adj));
15655 portion = min ((int)value, whole);
15656 bar->dragging = portion;
15657 }
15658 else
15659 {
15660 part = scroll_bar_handle;
15661 whole = gtk_adjustment_get_upper (adj) -
15662 gtk_adjustment_get_page_size (adj);
15663 portion = min ((int)value, whole);
15664 bar->dragging = portion;
15665 }
15666 }
15667 break;
15668 case GTK_SCROLL_STEP_BACKWARD:
15669 part = (bar->horizontal
15670 ? scroll_bar_left_arrow : scroll_bar_up_arrow);
15671 bar->dragging = -1;
15672 break;
15673 case GTK_SCROLL_STEP_FORWARD:
15674 part = (bar->horizontal
15675 ? scroll_bar_right_arrow : scroll_bar_down_arrow);
15676 bar->dragging = -1;
15677 break;
15678 case GTK_SCROLL_PAGE_BACKWARD:
15679 part = (bar->horizontal
15680 ? scroll_bar_before_handle : scroll_bar_above_handle);
15681 bar->dragging = -1;
15682 break;
15683 case GTK_SCROLL_PAGE_FORWARD:
15684 part = (bar->horizontal
15685 ? scroll_bar_after_handle : scroll_bar_below_handle);
15686 bar->dragging = -1;
15687 break;
15688 default:
15689 break;
15690 }
15691
15692 if (part != scroll_bar_nowhere)
15693 {
15694 window_being_scrolled = bar->window;
15695 x_send_scroll_bar_event (bar->window, part, portion, whole,
15696 bar->horizontal);
15697 }
15698
15699 return false;
15700 }
15701
15702
15703
15704 static gboolean
15705 xg_end_scroll_callback (GtkWidget *widget,
15706 GdkEventButton *event,
15707 gpointer user_data)
15708 {
15709 struct scroll_bar *bar;
15710
15711 bar = user_data;
15712 bar->dragging = -1;
15713
15714 if (WINDOWP (window_being_scrolled))
15715 {
15716 x_send_scroll_bar_event (window_being_scrolled,
15717 scroll_bar_end_scroll, 0, 0, bar->horizontal);
15718 window_being_scrolled = Qnil;
15719 }
15720
15721 return false;
15722 }
15723
15724
15725 #else
15726
15727
15728
15729
15730
15731
15732 static void
15733 xaw_jump_callback (Widget widget, XtPointer client_data, XtPointer call_data)
15734 {
15735 struct scroll_bar *bar = client_data;
15736 float *top_addr = call_data;
15737 float top = *top_addr;
15738 float shown;
15739 int whole, portion, height, width;
15740 enum scroll_bar_part part;
15741 bool horizontal = bar->horizontal;
15742
15743 if (horizontal)
15744 {
15745
15746 block_input ();
15747 XtVaGetValues (widget, XtNshown, &shown, XtNwidth, &width, NULL);
15748 unblock_input ();
15749
15750 if (shown < 1)
15751 {
15752 whole = bar->whole - (shown * bar->whole);
15753 portion = min (top * bar->whole, whole);
15754 }
15755 else
15756 {
15757 whole = bar->whole;
15758 portion = 0;
15759 }
15760
15761 part = scroll_bar_horizontal_handle;
15762 }
15763 else
15764 {
15765
15766 block_input ();
15767 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
15768 unblock_input ();
15769
15770 whole = 10000000;
15771 portion = shown < 1 ? top * whole : 0;
15772
15773 if (shown < 1 && (eabs (top + shown - 1) < 1.0f / height))
15774
15775
15776
15777
15778
15779 part = scroll_bar_down_arrow;
15780 else
15781 part = scroll_bar_handle;
15782 }
15783
15784 window_being_scrolled = bar->window;
15785 bar->dragging = portion;
15786 bar->last_seen_part = part;
15787 x_send_scroll_bar_event (bar->window, part, portion, whole, bar->horizontal);
15788 }
15789
15790
15791
15792
15793
15794
15795
15796
15797
15798
15799 static void
15800 xaw_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data)
15801 {
15802 struct scroll_bar *bar = client_data;
15803
15804 int position = (intptr_t) call_data;
15805 Dimension height, width;
15806 enum scroll_bar_part part;
15807
15808 if (bar->horizontal)
15809 {
15810
15811 block_input ();
15812 XtVaGetValues (widget, XtNwidth, &width, NULL);
15813 unblock_input ();
15814
15815 if (eabs (position) >= width)
15816 part = (position < 0) ? scroll_bar_before_handle : scroll_bar_after_handle;
15817
15818
15819
15820 else if (xaw3d_arrow_scroll && eabs (position) <= max (5, width / 20))
15821 part = (position < 0) ? scroll_bar_left_arrow : scroll_bar_right_arrow;
15822 else
15823 part = scroll_bar_move_ratio;
15824
15825 window_being_scrolled = bar->window;
15826 bar->dragging = -1;
15827 bar->last_seen_part = part;
15828 x_send_scroll_bar_event (bar->window, part, position, width,
15829 bar->horizontal);
15830 }
15831 else
15832 {
15833
15834
15835 block_input ();
15836 XtVaGetValues (widget, XtNheight, &height, NULL);
15837 unblock_input ();
15838
15839 if (eabs (position) >= height)
15840 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
15841
15842
15843
15844 else if (xaw3d_arrow_scroll && eabs (position) <= max (5, height / 20))
15845 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
15846 else
15847 part = scroll_bar_move_ratio;
15848
15849 window_being_scrolled = bar->window;
15850 bar->dragging = -1;
15851 bar->last_seen_part = part;
15852 x_send_scroll_bar_event (bar->window, part, position, height,
15853 bar->horizontal);
15854 }
15855 }
15856
15857 #endif
15858
15859 #define SCROLL_BAR_NAME "verticalScrollBar"
15860 #define SCROLL_BAR_HORIZONTAL_NAME "horizontalScrollBar"
15861
15862
15863
15864
15865 #ifdef USE_GTK
15866 static void
15867 x_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
15868 {
15869 const char *scroll_bar_name = SCROLL_BAR_NAME;
15870
15871 block_input ();
15872 xg_create_scroll_bar (f, bar, G_CALLBACK (xg_scroll_callback),
15873 G_CALLBACK (xg_end_scroll_callback),
15874 scroll_bar_name);
15875 unblock_input ();
15876 }
15877
15878 static void
15879 x_create_horizontal_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
15880 {
15881 const char *scroll_bar_name = SCROLL_BAR_HORIZONTAL_NAME;
15882
15883 block_input ();
15884 xg_create_horizontal_scroll_bar (f, bar, G_CALLBACK (xg_scroll_callback),
15885 G_CALLBACK (xg_end_scroll_callback),
15886 scroll_bar_name);
15887 unblock_input ();
15888 }
15889
15890 #else
15891
15892 static void
15893 x_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
15894 {
15895 Window xwindow;
15896 Widget widget;
15897 Arg av[20];
15898 int ac = 0;
15899 const char *scroll_bar_name = SCROLL_BAR_NAME;
15900 unsigned long pixel;
15901
15902 block_input ();
15903
15904 #ifdef USE_MOTIF
15905
15906 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
15907 XtSetArg (av[ac], XmNminimum, 0); ++ac;
15908 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
15909 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
15910 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
15911 XtSetArg (av[ac], XmNincrement, 1); ++ac;
15912 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
15913
15914
15915
15916 pixel = f->output_data.x->scroll_bar_foreground_pixel;
15917 if (pixel != -1)
15918 {
15919 XtSetArg (av[ac], XmNbackground, pixel);
15920 ++ac;
15921 }
15922
15923 pixel = f->output_data.x->scroll_bar_background_pixel;
15924 if (pixel != -1)
15925 {
15926 XtSetArg (av[ac], XmNtroughColor, pixel);
15927 ++ac;
15928 }
15929
15930 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
15931 (char *) scroll_bar_name, av, ac);
15932
15933
15934 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
15935 (XtPointer) bar);
15936 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
15937 (XtPointer) bar);
15938 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
15939 (XtPointer) bar);
15940 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
15941 (XtPointer) bar);
15942 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
15943 (XtPointer) bar);
15944 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
15945 (XtPointer) bar);
15946 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
15947 (XtPointer) bar);
15948
15949
15950 XtRealizeWidget (widget);
15951
15952
15953
15954 XDefineCursor (XtDisplay (widget), XtWindow (widget),
15955 f->output_data.x->nontext_cursor);
15956
15957 #ifdef HAVE_XINPUT2
15958
15959
15960 if (FRAME_DISPLAY_INFO (f)->supports_xi2)
15961 xi_select_scroll_bar_events (FRAME_DISPLAY_INFO (f),
15962 XtWindow (widget));
15963 #endif
15964 #else
15965
15966
15967
15968
15969
15970 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
15971 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
15972
15973
15974
15975 pixel = f->output_data.x->scroll_bar_foreground_pixel;
15976 if (pixel != -1)
15977 {
15978 XtSetArg (av[ac], XtNforeground, pixel);
15979 ++ac;
15980 }
15981
15982 pixel = f->output_data.x->scroll_bar_background_pixel;
15983 if (pixel != -1)
15984 {
15985 XtSetArg (av[ac], XtNbackground, pixel);
15986 ++ac;
15987 }
15988
15989
15990
15991
15992 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1)
15993 {
15994 pixel = f->output_data.x->scroll_bar_background_pixel;
15995 if (pixel != -1)
15996 {
15997 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
15998 FRAME_X_COLORMAP (f),
15999 &pixel, 1.2, 0x8000))
16000 pixel = -1;
16001 f->output_data.x->scroll_bar_top_shadow_pixel = pixel;
16002 }
16003 }
16004 if (f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
16005 {
16006 pixel = f->output_data.x->scroll_bar_background_pixel;
16007 if (pixel != -1)
16008 {
16009 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
16010 FRAME_X_COLORMAP (f),
16011 &pixel, 0.6, 0x4000))
16012 pixel = -1;
16013 f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
16014 }
16015 }
16016
16017 #ifdef XtNbeNiceToColormap
16018
16019 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1
16020 || f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
16021
16022
16023
16024
16025 {
16026 XtSetArg (av[ac], (String) XtNbeNiceToColormap,
16027 DefaultDepthOfScreen (FRAME_X_SCREEN (f)) < 16);
16028 ++ac;
16029 }
16030 else
16031
16032
16033
16034 {
16035
16036
16037 XtSetArg (av[ac], (String) XtNbeNiceToColormap, False);
16038 ++ac;
16039
16040
16041 pixel = f->output_data.x->scroll_bar_top_shadow_pixel;
16042 if (pixel != -1)
16043 {
16044 XtSetArg (av[ac], (String) XtNtopShadowPixel, pixel);
16045 ++ac;
16046 }
16047 pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel;
16048 if (pixel != -1)
16049 {
16050 XtSetArg (av[ac], (String) XtNbottomShadowPixel, pixel);
16051 ++ac;
16052 }
16053 }
16054 #endif
16055
16056 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
16057 f->output_data.x->edit_widget, av, ac);
16058
16059 {
16060 char const *initial = "";
16061 char const *val = initial;
16062 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
16063 #ifdef XtNarrowScrollbars
16064 XtNarrowScrollbars, (XtPointer) &xaw3d_arrow_scroll,
16065 #endif
16066 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
16067 if (xaw3d_arrow_scroll || val == initial)
16068 {
16069 xaw3d_arrow_scroll = True;
16070
16071 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
16072 }
16073 }
16074
16075
16076 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
16077 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
16078 (XtPointer) bar);
16079
16080
16081 XtRealizeWidget (widget);
16082
16083 #endif
16084
16085
16086
16087 if (action_hook_id == 0)
16088 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
16089
16090
16091 SET_SCROLL_BAR_X_WIDGET (bar, widget);
16092 xwindow = XtWindow (widget);
16093 bar->x_window = xwindow;
16094 bar->whole = 1;
16095 bar->horizontal = false;
16096
16097 unblock_input ();
16098 }
16099
16100 static void
16101 x_create_horizontal_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
16102 {
16103 Window xwindow;
16104 Widget widget;
16105 Arg av[20];
16106 int ac = 0;
16107 const char *scroll_bar_name = SCROLL_BAR_HORIZONTAL_NAME;
16108 unsigned long pixel;
16109
16110 block_input ();
16111
16112 #ifdef USE_MOTIF
16113
16114 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
16115 XtSetArg (av[ac], XmNminimum, 0); ++ac;
16116 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
16117 XtSetArg (av[ac], XmNorientation, XmHORIZONTAL); ++ac;
16118 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_RIGHT), ++ac;
16119 XtSetArg (av[ac], XmNincrement, 1); ++ac;
16120 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
16121
16122
16123
16124 pixel = f->output_data.x->scroll_bar_foreground_pixel;
16125 if (pixel != -1)
16126 {
16127 XtSetArg (av[ac], XmNbackground, pixel);
16128 ++ac;
16129 }
16130
16131 pixel = f->output_data.x->scroll_bar_background_pixel;
16132 if (pixel != -1)
16133 {
16134 XtSetArg (av[ac], XmNtroughColor, pixel);
16135 ++ac;
16136 }
16137
16138 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
16139 (char *) scroll_bar_name, av, ac);
16140
16141
16142 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
16143 (XtPointer) bar);
16144 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
16145 (XtPointer) bar);
16146 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
16147 (XtPointer) bar);
16148 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
16149 (XtPointer) bar);
16150 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
16151 (XtPointer) bar);
16152 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
16153 (XtPointer) bar);
16154 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
16155 (XtPointer) bar);
16156
16157
16158 XtRealizeWidget (widget);
16159
16160
16161
16162 XDefineCursor (XtDisplay (widget), XtWindow (widget),
16163 f->output_data.x->nontext_cursor);
16164
16165 #ifdef HAVE_XINPUT2
16166
16167
16168 if (FRAME_DISPLAY_INFO (f)->supports_xi2)
16169 xi_select_scroll_bar_events (FRAME_DISPLAY_INFO (f),
16170 XtWindow (widget));
16171 #endif
16172 #else
16173
16174
16175
16176
16177
16178 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
16179 XtSetArg (av[ac], XtNorientation, XtorientHorizontal); ++ac;
16180
16181
16182
16183 pixel = f->output_data.x->scroll_bar_foreground_pixel;
16184 if (pixel != -1)
16185 {
16186 XtSetArg (av[ac], XtNforeground, pixel);
16187 ++ac;
16188 }
16189
16190 pixel = f->output_data.x->scroll_bar_background_pixel;
16191 if (pixel != -1)
16192 {
16193 XtSetArg (av[ac], XtNbackground, pixel);
16194 ++ac;
16195 }
16196
16197
16198
16199
16200 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1)
16201 {
16202 pixel = f->output_data.x->scroll_bar_background_pixel;
16203 if (pixel != -1)
16204 {
16205 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
16206 FRAME_X_COLORMAP (f),
16207 &pixel, 1.2, 0x8000))
16208 pixel = -1;
16209 f->output_data.x->scroll_bar_top_shadow_pixel = pixel;
16210 }
16211 }
16212 if (f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
16213 {
16214 pixel = f->output_data.x->scroll_bar_background_pixel;
16215 if (pixel != -1)
16216 {
16217 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
16218 FRAME_X_COLORMAP (f),
16219 &pixel, 0.6, 0x4000))
16220 pixel = -1;
16221 f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
16222 }
16223 }
16224
16225 #ifdef XtNbeNiceToColormap
16226
16227 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1
16228 || f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
16229
16230
16231
16232
16233 {
16234 XtSetArg (av[ac], (String) XtNbeNiceToColormap,
16235 DefaultDepthOfScreen (FRAME_X_SCREEN (f)) < 16);
16236 ++ac;
16237 }
16238 else
16239
16240
16241
16242 {
16243
16244
16245 XtSetArg (av[ac], (String) XtNbeNiceToColormap, False);
16246 ++ac;
16247
16248
16249 pixel = f->output_data.x->scroll_bar_top_shadow_pixel;
16250 if (pixel != -1)
16251 {
16252 XtSetArg (av[ac], (String) XtNtopShadowPixel, pixel);
16253 ++ac;
16254 }
16255 pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel;
16256 if (pixel != -1)
16257 {
16258 XtSetArg (av[ac], (String) XtNbottomShadowPixel, pixel);
16259 ++ac;
16260 }
16261 }
16262 #endif
16263
16264 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
16265 f->output_data.x->edit_widget, av, ac);
16266
16267 {
16268 char const *initial = "";
16269 char const *val = initial;
16270 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
16271 #ifdef XtNarrowScrollbars
16272 XtNarrowScrollbars, (XtPointer) &xaw3d_arrow_scroll,
16273 #endif
16274 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
16275 if (xaw3d_arrow_scroll || val == initial)
16276 {
16277 xaw3d_arrow_scroll = True;
16278
16279 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
16280 }
16281 }
16282
16283
16284 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
16285 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
16286 (XtPointer) bar);
16287
16288
16289 XtRealizeWidget (widget);
16290
16291 #endif
16292
16293
16294
16295 if (horizontal_action_hook_id == 0)
16296 horizontal_action_hook_id
16297 = XtAppAddActionHook (Xt_app_con, xt_horizontal_action_hook, 0);
16298
16299
16300 SET_SCROLL_BAR_X_WIDGET (bar, widget);
16301 xwindow = XtWindow (widget);
16302 bar->x_window = xwindow;
16303 bar->whole = 1;
16304 bar->horizontal = true;
16305
16306 unblock_input ();
16307 }
16308 #endif
16309
16310
16311
16312
16313
16314 #ifdef USE_GTK
16315 static void
16316 x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position, int whole)
16317 {
16318 xg_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
16319 }
16320
16321 static void
16322 x_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position, int whole)
16323 {
16324 xg_set_toolkit_horizontal_scroll_bar_thumb (bar, portion, position, whole);
16325 }
16326
16327 #else
16328 static void
16329 x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position,
16330 int whole)
16331 {
16332 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
16333 Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
16334 float top, shown;
16335
16336 block_input ();
16337
16338 #ifdef USE_MOTIF
16339
16340 if (scroll_bar_adjust_thumb_portion_p)
16341 {
16342
16343
16344
16345
16346
16347
16348
16349
16350
16351
16352
16353 portion = WINDOW_TOTAL_LINES (XWINDOW (bar->window)) * 30;
16354
16355
16356 whole += portion;
16357 }
16358
16359 if (whole <= 0)
16360 top = 0, shown = 1;
16361 else
16362 {
16363 top = (float) position / whole;
16364 shown = (float) portion / whole;
16365 }
16366
16367 if (bar->dragging == -1)
16368 {
16369 int size, value;
16370
16371
16372
16373
16374 size = clip_to_bounds (1, shown * XM_SB_MAX, XM_SB_MAX);
16375
16376
16377 value = top * XM_SB_MAX;
16378 value = min (value, XM_SB_MAX - size);
16379
16380 XmScrollBarSetValues (widget, value, size, 0, 0, False);
16381 }
16382 #else
16383
16384 if (whole == 0)
16385 top = 0, shown = 1;
16386 else
16387 {
16388 top = (float) position / whole;
16389 shown = (float) portion / whole;
16390 }
16391
16392 {
16393 float old_top, old_shown;
16394 Dimension height;
16395 XtVaGetValues (widget,
16396 XtNtopOfThumb, &old_top,
16397 XtNshown, &old_shown,
16398 XtNheight, &height,
16399 NULL);
16400
16401
16402 if (bar->dragging == -1 || bar->last_seen_part == scroll_bar_down_arrow)
16403 top = max (0, min (1, top));
16404 else
16405 top = old_top;
16406 #if ! defined (HAVE_XAW3D)
16407
16408
16409 top = min (top, 0.99f);
16410 #endif
16411
16412 shown = max (0, min (1 - top - (2.0f / height), shown));
16413 #if ! defined (HAVE_XAW3D)
16414
16415 shown = max (shown, 0.01f);
16416 #endif
16417
16418
16419
16420
16421 if (top != old_top || shown != old_shown)
16422 {
16423 if (bar->dragging == -1)
16424 XawScrollbarSetThumb (widget, top, shown);
16425 else
16426 {
16427
16428 if (!xaw3d_pick_top)
16429 shown = min (shown, old_shown);
16430
16431 XawScrollbarSetThumb (widget, top, shown);
16432 }
16433 }
16434 }
16435 #endif
16436
16437 unblock_input ();
16438 }
16439
16440 static void
16441 x_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position,
16442 int whole)
16443 {
16444 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
16445 Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
16446 float top, shown;
16447
16448 block_input ();
16449
16450 #ifdef USE_MOTIF
16451 bar->whole = whole;
16452 shown = (float) portion / whole;
16453 top = (float) position / (whole - portion);
16454 {
16455 int size = clip_to_bounds (1, shown * XM_SB_MAX, XM_SB_MAX);
16456 int value = clip_to_bounds (0, top * (XM_SB_MAX - size), XM_SB_MAX - size);
16457
16458 XmScrollBarSetValues (widget, value, size, 0, 0, False);
16459 }
16460 #else
16461 bar->whole = whole;
16462 if (whole == 0)
16463 top = 0, shown = 1;
16464 else
16465 {
16466 top = (float) position / whole;
16467 shown = (float) portion / whole;
16468 }
16469
16470 {
16471 float old_top, old_shown;
16472 Dimension height;
16473 XtVaGetValues (widget,
16474 XtNtopOfThumb, &old_top,
16475 XtNshown, &old_shown,
16476 XtNheight, &height,
16477 NULL);
16478
16479 #if false
16480
16481 if (bar->dragging == -1 || bar->last_seen_part == scroll_bar_down_arrow)
16482 top = max (0, min (1, top));
16483 else
16484 top = old_top;
16485 #if ! defined (HAVE_XAW3D)
16486
16487
16488 top = min (top, 0.99f);
16489 #endif
16490
16491 shown = max (0, min (1 - top - (2.0f / height), shown));
16492 #if ! defined (HAVE_XAW3D)
16493
16494 shown = max (shown, 0.01f);
16495 #endif
16496 #endif
16497
16498
16499
16500
16501 XawScrollbarSetThumb (widget, top, shown);
16502 #if false
16503 if (top != old_top || shown != old_shown)
16504 {
16505 if (bar->dragging == -1)
16506 XawScrollbarSetThumb (widget, top, shown);
16507 else
16508 {
16509
16510 if (!xaw3d_pick_top)
16511 shown = min (shown, old_shown);
16512
16513 XawScrollbarSetThumb (widget, top, shown);
16514 }
16515 }
16516 #endif
16517 }
16518 #endif
16519
16520 unblock_input ();
16521 }
16522 #endif
16523
16524 #endif
16525
16526
16527
16528
16529
16530
16531
16532
16533
16534
16535
16536
16537 static struct scroll_bar *
16538 x_scroll_bar_create (struct window *w, int top, int left,
16539 int width, int height, bool horizontal)
16540 {
16541 struct frame *f = XFRAME (w->frame);
16542 struct scroll_bar *bar = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, prev,
16543 PVEC_OTHER);
16544 Lisp_Object barobj;
16545
16546 block_input ();
16547
16548 #ifdef USE_TOOLKIT_SCROLL_BARS
16549 if (horizontal)
16550 x_create_horizontal_toolkit_scroll_bar (f, bar);
16551 else
16552 x_create_toolkit_scroll_bar (f, bar);
16553 #else
16554 {
16555 XSetWindowAttributes a;
16556 unsigned long mask;
16557 Window window;
16558
16559 a.event_mask = (ButtonPressMask | ButtonReleaseMask
16560 | ButtonMotionMask | PointerMotionHintMask);
16561 a.cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
16562
16563 mask = (CWEventMask | CWCursor);
16564
16565
16566
16567
16568 if (width > 0 && window_box_height (w) > 0)
16569 x_clear_area (f, left, top, width, window_box_height (w));
16570
16571
16572
16573
16574 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
16575
16576 left, top, width, height,
16577
16578 0,
16579
16580 CopyFromParent,
16581
16582 InputOnly,
16583
16584 CopyFromParent,
16585
16586 mask, &a);
16587
16588 #ifdef HAVE_XINPUT2
16589
16590
16591 if (FRAME_DISPLAY_INFO (f)->supports_xi2)
16592 xi_select_scroll_bar_events (FRAME_DISPLAY_INFO (f),
16593 window);
16594 #endif
16595
16596 bar->x_window = window;
16597 }
16598 #endif
16599
16600 XSETWINDOW (bar->window, w);
16601 bar->top = top;
16602 bar->left = left;
16603 bar->width = width;
16604 bar->height = height;
16605 bar->start = 0;
16606 bar->end = 0;
16607 bar->dragging = -1;
16608 bar->horizontal = horizontal;
16609 #if defined (USE_TOOLKIT_SCROLL_BARS) && defined (USE_LUCID)
16610 bar->last_seen_part = scroll_bar_nowhere;
16611 #endif
16612
16613
16614 bar->next = FRAME_SCROLL_BARS (f);
16615 bar->prev = Qnil;
16616 XSETVECTOR (barobj, bar);
16617 fset_scroll_bars (f, barobj);
16618 if (!NILP (bar->next))
16619 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
16620
16621
16622 #ifdef USE_TOOLKIT_SCROLL_BARS
16623 {
16624 #ifdef USE_GTK
16625 if (horizontal)
16626 xg_update_horizontal_scrollbar_pos (f, bar->x_window, top,
16627 left, width, max (height, 1));
16628 else
16629 xg_update_scrollbar_pos (f, bar->x_window, top,
16630 left, width, max (height, 1));
16631 #else
16632 Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
16633 XtConfigureWidget (scroll_bar, left, top, width, max (height, 1), 0);
16634 XtMapWidget (scroll_bar);
16635
16636 XLowerWindow (FRAME_X_DISPLAY (f), bar->x_window);
16637 #endif
16638 }
16639 #else
16640 XMapWindow (FRAME_X_DISPLAY (f), bar->x_window);
16641
16642 XLowerWindow (FRAME_X_DISPLAY (f), bar->x_window);
16643 #endif
16644
16645 unblock_input ();
16646 return bar;
16647 }
16648
16649
16650 #ifndef USE_TOOLKIT_SCROLL_BARS
16651
16652
16653
16654
16655
16656
16657
16658
16659
16660
16661
16662
16663
16664
16665 static void
16666 x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end,
16667 bool rebuild)
16668 {
16669 bool dragging;
16670 struct frame *f;
16671 Drawable w;
16672 GC gc;
16673 int inside_width, inside_height, top_range, length;
16674
16675
16676 if (! rebuild
16677 && start == bar->start
16678 && end == bar->end)
16679 return;
16680
16681 f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
16682 dragging = bar->dragging != -1;
16683 gc = f->output_data.x->normal_gc;
16684 w = FRAME_X_DRAWABLE (f);
16685
16686 block_input ();
16687
16688 inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, bar->width);
16689 inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, bar->height);
16690 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
16691
16692
16693
16694 length = end - start;
16695
16696 if (start < 0)
16697 start = 0;
16698 else if (start > top_range)
16699 start = top_range;
16700 end = start + length;
16701
16702 if (end < start)
16703 end = start;
16704 else if (end > top_range && ! dragging)
16705 end = top_range;
16706
16707
16708 bar->start = start;
16709 bar->end = end;
16710
16711
16712 if (end > top_range)
16713 end = top_range;
16714
16715
16716
16717
16718 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
16719
16720
16721
16722 if ((inside_width > 0) && (start > 0))
16723 {
16724 if (f->output_data.x->scroll_bar_background_pixel != -1)
16725 XSetForeground (FRAME_X_DISPLAY (f), gc,
16726 f->output_data.x->scroll_bar_background_pixel);
16727 else
16728 XSetForeground (FRAME_X_DISPLAY (f), gc,
16729 FRAME_BACKGROUND_PIXEL (f));
16730
16731 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
16732 bar->left + VERTICAL_SCROLL_BAR_LEFT_BORDER,
16733 bar->top + VERTICAL_SCROLL_BAR_TOP_BORDER,
16734 inside_width, start);
16735
16736 XSetForeground (FRAME_X_DISPLAY (f), gc,
16737 FRAME_FOREGROUND_PIXEL (f));
16738 }
16739
16740
16741 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
16742 XSetForeground (FRAME_X_DISPLAY (f), gc,
16743 f->output_data.x->scroll_bar_foreground_pixel);
16744
16745
16746 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
16747
16748 bar->left + VERTICAL_SCROLL_BAR_LEFT_BORDER,
16749 bar->top + VERTICAL_SCROLL_BAR_TOP_BORDER + start,
16750 inside_width, end - start);
16751
16752
16753
16754
16755 if ((inside_width > 0) && (end < inside_height))
16756 {
16757 if (f->output_data.x->scroll_bar_background_pixel != -1)
16758 XSetForeground (FRAME_X_DISPLAY (f), gc,
16759 f->output_data.x->scroll_bar_background_pixel);
16760 else
16761 XSetForeground (FRAME_X_DISPLAY (f), gc,
16762 FRAME_BACKGROUND_PIXEL (f));
16763
16764 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
16765 bar->left + VERTICAL_SCROLL_BAR_LEFT_BORDER,
16766 bar->top + VERTICAL_SCROLL_BAR_TOP_BORDER + end,
16767 inside_width, inside_height - end);
16768
16769 XSetForeground (FRAME_X_DISPLAY (f), gc,
16770 FRAME_FOREGROUND_PIXEL (f));
16771 }
16772
16773
16774 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
16775 XSetForeground (FRAME_X_DISPLAY (f), gc,
16776 FRAME_FOREGROUND_PIXEL (f));
16777
16778 unblock_input ();
16779 }
16780
16781 #endif
16782
16783
16784
16785
16786 static void
16787 x_scroll_bar_remove (struct scroll_bar *bar)
16788 {
16789 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
16790 block_input ();
16791
16792 #ifdef USE_TOOLKIT_SCROLL_BARS
16793 #ifdef USE_GTK
16794 xg_remove_scroll_bar (f, bar->x_window);
16795 #else
16796 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));
16797 #endif
16798 #else
16799 XDestroyWindow (FRAME_X_DISPLAY (f), bar->x_window);
16800 #endif
16801
16802
16803 if (bar->horizontal)
16804 wset_horizontal_scroll_bar (XWINDOW (bar->window), Qnil);
16805 else
16806 wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil);
16807
16808 unblock_input ();
16809 }
16810
16811
16812
16813
16814
16815
16816
16817 static void
16818 XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int position)
16819 {
16820 struct frame *f = XFRAME (w->frame);
16821 Lisp_Object barobj;
16822 struct scroll_bar *bar;
16823 int top, height, left, width;
16824 int window_y, window_height;
16825
16826
16827 window_box (w, ANY_AREA, 0, &window_y, 0, &window_height);
16828 top = window_y;
16829 height = window_height;
16830 left = WINDOW_SCROLL_BAR_AREA_X (w);
16831 width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
16832
16833
16834 if (NILP (w->vertical_scroll_bar))
16835 {
16836 if (width > 0 && height > 0)
16837 {
16838 block_input ();
16839 x_clear_area (f, left, top, width, height);
16840 unblock_input ();
16841 }
16842
16843 bar = x_scroll_bar_create (w, top, left, width, max (height, 1), false);
16844 #ifndef USE_TOOLKIT_SCROLL_BARS
16845
16846
16847
16848 x_scroll_bar_redraw (bar);
16849 #endif
16850 }
16851 else
16852 {
16853
16854 unsigned int mask = 0;
16855
16856 bar = XSCROLL_BAR (w->vertical_scroll_bar);
16857
16858 block_input ();
16859
16860 if (left != bar->left)
16861 mask |= CWX;
16862 if (top != bar->top)
16863 mask |= CWY;
16864 if (width != bar->width)
16865 mask |= CWWidth;
16866 if (height != bar->height)
16867 mask |= CWHeight;
16868
16869 #ifdef USE_TOOLKIT_SCROLL_BARS
16870
16871
16872 if (mask)
16873 {
16874
16875
16876 if (width > 0 && height > 0)
16877 x_clear_area (f, left, top, width, height);
16878 #ifdef USE_GTK
16879 xg_update_scrollbar_pos (f, bar->x_window, top,
16880 left, width, max (height, 1));
16881 #else
16882 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
16883 left, top, width, max (height, 1), 0);
16884 #endif
16885 }
16886 #else
16887
16888
16889 if (mask)
16890 {
16891 XWindowChanges wc;
16892
16893 wc.x = left;
16894 wc.y = top;
16895 wc.width = width;
16896 wc.height = height;
16897 XConfigureWindow (FRAME_X_DISPLAY (f), bar->x_window,
16898 mask, &wc);
16899 }
16900
16901 #endif
16902
16903
16904 bar->left = left;
16905 bar->top = top;
16906 bar->width = width;
16907 bar->height = height;
16908
16909 #ifndef USE_TOOLKIT_SCROLL_BARS
16910
16911 x_scroll_bar_redraw (bar);
16912 #endif
16913
16914 unblock_input ();
16915 }
16916
16917 #ifdef USE_TOOLKIT_SCROLL_BARS
16918 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
16919 #else
16920
16921
16922 if (bar->dragging == -1)
16923 {
16924 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
16925
16926 if (whole == 0)
16927 x_scroll_bar_set_handle (bar, 0, top_range, false);
16928 else
16929 {
16930 int start = ((double) position * top_range) / whole;
16931 int end = ((double) (position + portion) * top_range) / whole;
16932 x_scroll_bar_set_handle (bar, start, end, false);
16933 }
16934 }
16935 #endif
16936
16937 XSETVECTOR (barobj, bar);
16938 wset_vertical_scroll_bar (w, barobj);
16939 }
16940
16941
16942 static void
16943 XTset_horizontal_scroll_bar (struct window *w, int portion, int whole, int position)
16944 {
16945 struct frame *f = XFRAME (w->frame);
16946 Lisp_Object barobj;
16947 struct scroll_bar *bar;
16948 int top, height, left, width;
16949 int window_x, window_width;
16950 int pixel_width = WINDOW_PIXEL_WIDTH (w);
16951
16952
16953 window_box (w, ANY_AREA, &window_x, 0, &window_width, 0);
16954 left = window_x;
16955 width = window_width;
16956 top = WINDOW_SCROLL_BAR_AREA_Y (w);
16957 height = WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
16958
16959
16960 if (NILP (w->horizontal_scroll_bar))
16961 {
16962 if (width > 0 && height > 0)
16963 {
16964 block_input ();
16965
16966
16967
16968 x_clear_area (f, left, top, pixel_width, height);
16969 unblock_input ();
16970 }
16971
16972 bar = x_scroll_bar_create (w, top, left, width, height, true);
16973 }
16974 else
16975 {
16976
16977 unsigned int mask = 0;
16978
16979 bar = XSCROLL_BAR (w->horizontal_scroll_bar);
16980
16981 block_input ();
16982
16983 if (left != bar->left)
16984 mask |= CWX;
16985 if (top != bar->top)
16986 mask |= CWY;
16987 if (width != bar->width)
16988 mask |= CWWidth;
16989 if (height != bar->height)
16990 mask |= CWHeight;
16991
16992 #ifdef USE_TOOLKIT_SCROLL_BARS
16993
16994 if (mask)
16995 {
16996
16997
16998 if (width > 0 && height > 0)
16999 x_clear_area (f,
17000 WINDOW_LEFT_EDGE_X (w), top,
17001 pixel_width - WINDOW_RIGHT_DIVIDER_WIDTH (w), height);
17002 #ifdef USE_GTK
17003 xg_update_horizontal_scrollbar_pos (f, bar->x_window, top, left,
17004 width, height);
17005 #else
17006 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
17007 left, top, width, height, 0);
17008 #endif
17009 }
17010 #else
17011
17012
17013
17014
17015
17016 {
17017 int area_height = WINDOW_CONFIG_SCROLL_BAR_HEIGHT (w);
17018 int rest = area_height - height;
17019 if (rest > 0 && width > 0)
17020 x_clear_area (f, left, top, width, rest);
17021 }
17022
17023
17024 if (mask)
17025 {
17026 XWindowChanges wc;
17027
17028 wc.x = left;
17029 wc.y = top;
17030 wc.width = width;
17031 wc.height = height;
17032 XConfigureWindow (FRAME_X_DISPLAY (f), bar->x_window,
17033 mask, &wc);
17034 }
17035
17036 #endif
17037
17038
17039 bar->left = left;
17040 bar->top = top;
17041 bar->width = width;
17042 bar->height = height;
17043
17044 unblock_input ();
17045 }
17046
17047 #ifdef USE_TOOLKIT_SCROLL_BARS
17048 x_set_toolkit_horizontal_scroll_bar_thumb (bar, portion, position, whole);
17049 #else
17050
17051
17052 if (bar->dragging == -1)
17053 {
17054 int left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, width);
17055
17056 if (whole == 0)
17057 x_scroll_bar_set_handle (bar, 0, left_range, false);
17058 else
17059 {
17060 int start = ((double) position * left_range) / whole;
17061 int end = ((double) (position + portion) * left_range) / whole;
17062 x_scroll_bar_set_handle (bar, start, end, false);
17063 }
17064 }
17065 #endif
17066
17067 XSETVECTOR (barobj, bar);
17068 wset_horizontal_scroll_bar (w, barobj);
17069 }
17070
17071
17072
17073
17074
17075
17076
17077
17078
17079
17080
17081
17082
17083
17084 static void
17085 XTcondemn_scroll_bars (struct frame *frame)
17086 {
17087 if (!NILP (FRAME_SCROLL_BARS (frame)))
17088 {
17089 if (!NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
17090 {
17091
17092 Lisp_Object last = FRAME_SCROLL_BARS (frame);
17093
17094 while (!NILP (XSCROLL_BAR (last)->next))
17095 last = XSCROLL_BAR (last)->next;
17096
17097 XSCROLL_BAR (last)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
17098 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = last;
17099 }
17100
17101 fset_condemned_scroll_bars (frame, FRAME_SCROLL_BARS (frame));
17102 fset_scroll_bars (frame, Qnil);
17103 }
17104 }
17105
17106
17107
17108
17109
17110 static void
17111 XTredeem_scroll_bar (struct window *w)
17112 {
17113 struct scroll_bar *bar;
17114 Lisp_Object barobj;
17115 struct frame *f;
17116
17117
17118 if (NILP (w->vertical_scroll_bar) && NILP (w->horizontal_scroll_bar))
17119 emacs_abort ();
17120
17121 if (!NILP (w->vertical_scroll_bar) && WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
17122 {
17123 bar = XSCROLL_BAR (w->vertical_scroll_bar);
17124
17125 f = XFRAME (WINDOW_FRAME (w));
17126 if (NILP (bar->prev))
17127 {
17128
17129
17130 if (EQ (FRAME_SCROLL_BARS (f), w->vertical_scroll_bar))
17131
17132 goto horizontal;
17133 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
17134 w->vertical_scroll_bar))
17135 fset_condemned_scroll_bars (f, bar->next);
17136 else
17137
17138
17139 emacs_abort ();
17140 }
17141 else
17142 XSCROLL_BAR (bar->prev)->next = bar->next;
17143
17144 if (! NILP (bar->next))
17145 XSCROLL_BAR (bar->next)->prev = bar->prev;
17146
17147 bar->next = FRAME_SCROLL_BARS (f);
17148 bar->prev = Qnil;
17149 XSETVECTOR (barobj, bar);
17150 fset_scroll_bars (f, barobj);
17151 if (! NILP (bar->next))
17152 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
17153 }
17154
17155 horizontal:
17156 if (!NILP (w->horizontal_scroll_bar) && WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
17157 {
17158 bar = XSCROLL_BAR (w->horizontal_scroll_bar);
17159
17160 f = XFRAME (WINDOW_FRAME (w));
17161 if (NILP (bar->prev))
17162 {
17163
17164
17165 if (EQ (FRAME_SCROLL_BARS (f), w->horizontal_scroll_bar))
17166
17167 return;
17168 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
17169 w->horizontal_scroll_bar))
17170 fset_condemned_scroll_bars (f, bar->next);
17171 else
17172
17173
17174 emacs_abort ();
17175 }
17176 else
17177 XSCROLL_BAR (bar->prev)->next = bar->next;
17178
17179 if (! NILP (bar->next))
17180 XSCROLL_BAR (bar->next)->prev = bar->prev;
17181
17182 bar->next = FRAME_SCROLL_BARS (f);
17183 bar->prev = Qnil;
17184 XSETVECTOR (barobj, bar);
17185 fset_scroll_bars (f, barobj);
17186 if (! NILP (bar->next))
17187 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
17188 }
17189 }
17190
17191
17192
17193
17194 static void
17195 XTjudge_scroll_bars (struct frame *f)
17196 {
17197 Lisp_Object bar, next;
17198
17199 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
17200
17201
17202
17203 fset_condemned_scroll_bars (f, Qnil);
17204
17205 for (; ! NILP (bar); bar = next)
17206 {
17207 struct scroll_bar *b = XSCROLL_BAR (bar);
17208
17209 x_scroll_bar_remove (b);
17210
17211 next = b->next;
17212 b->next = b->prev = Qnil;
17213 }
17214
17215
17216
17217 }
17218
17219
17220 #ifndef USE_TOOLKIT_SCROLL_BARS
17221
17222
17223
17224 static void
17225 x_scroll_bar_handle_exposure (struct frame *f, XEvent *event)
17226 {
17227 int x, y, width, height;
17228 XRectangle rect, scroll_bar_rect, intersection;
17229 Lisp_Object bar, condemned;
17230 struct scroll_bar *b;
17231
17232 if (event->type == GraphicsExpose)
17233 {
17234 x = event->xgraphicsexpose.x;
17235 y = event->xgraphicsexpose.y;
17236 width = event->xgraphicsexpose.width;
17237 height = event->xgraphicsexpose.height;
17238 }
17239 else
17240 {
17241 x = event->xexpose.x;
17242 y = event->xexpose.y;
17243 width = event->xexpose.width;
17244 height = event->xexpose.height;
17245 }
17246
17247 rect.x = x;
17248 rect.y = y;
17249 rect.width = width;
17250 rect.height = height;
17251
17252
17253
17254 condemned = FRAME_CONDEMNED_SCROLL_BARS (f);
17255 for (bar = FRAME_SCROLL_BARS (f);
17256
17257
17258 !NILP (bar) || (bar = condemned,
17259 condemned = Qnil,
17260 !NILP (bar));
17261 bar = XSCROLL_BAR (bar)->next)
17262 {
17263 b = XSCROLL_BAR (bar);
17264
17265 scroll_bar_rect.x = b->left;
17266 scroll_bar_rect.y = b->top;
17267 scroll_bar_rect.width = b->width;
17268 scroll_bar_rect.height = b->height;
17269
17270 if (gui_intersect_rectangles (&rect,
17271 &scroll_bar_rect,
17272 &intersection))
17273 x_scroll_bar_redraw (b);
17274 }
17275 }
17276
17277
17278
17279
17280
17281 static void
17282 x_scroll_bar_redraw (struct scroll_bar *bar)
17283 {
17284 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
17285 GC gc = f->output_data.x->normal_gc;
17286
17287 if (f->output_data.x->scroll_bar_background_pixel != -1)
17288 XSetForeground (FRAME_X_DISPLAY (f), gc,
17289 f->output_data.x->scroll_bar_background_pixel);
17290 else
17291 XSetForeground (FRAME_X_DISPLAY (f), gc,
17292 FRAME_BACKGROUND_PIXEL (f));
17293
17294 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), gc,
17295 bar->left, bar->top, bar->width, bar->height);
17296
17297 XSetForeground (FRAME_X_DISPLAY (f), gc,
17298 FRAME_FOREGROUND_PIXEL (f));
17299
17300 x_scroll_bar_set_handle (bar, bar->start, bar->end, true);
17301
17302
17303 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
17304 XSetForeground (FRAME_X_DISPLAY (f), gc,
17305 f->output_data.x->scroll_bar_foreground_pixel);
17306
17307
17308 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), gc,
17309 bar->left, bar->top, bar->width - 1, bar->height - 1);
17310
17311
17312 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
17313 XSetForeground (FRAME_X_DISPLAY (f), gc,
17314 FRAME_FOREGROUND_PIXEL (f));
17315 }
17316 #endif
17317
17318
17319
17320
17321
17322
17323
17324
17325 static void
17326 x_scroll_bar_handle_click (struct scroll_bar *bar,
17327 const XEvent *event,
17328 struct input_event *emacs_event,
17329 Lisp_Object device)
17330 {
17331 int left_range, x, top_range, y;
17332 #ifndef USE_TOOLKIT_SCROLL_BARS
17333 int new_start, new_end;
17334 #endif
17335
17336 if (! WINDOWP (bar->window))
17337 emacs_abort ();
17338
17339 emacs_event->kind = (bar->horizontal
17340 ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT
17341 : SCROLL_BAR_CLICK_EVENT);
17342 emacs_event->code = event->xbutton.button - Button1;
17343 emacs_event->modifiers
17344 = (x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO
17345 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
17346 event->xbutton.state)
17347 | (event->type == ButtonRelease
17348 ? up_modifier
17349 : down_modifier));
17350 emacs_event->frame_or_window = bar->window;
17351 emacs_event->arg = Qnil;
17352 emacs_event->timestamp = event->xbutton.time;
17353
17354 if (!NILP (device))
17355 emacs_event->device = device;
17356
17357 if (bar->horizontal)
17358 {
17359
17360 left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width);
17361 x = event->xbutton.x - HORIZONTAL_SCROLL_BAR_LEFT_BORDER;
17362
17363 if (x < 0) x = 0;
17364 if (x > left_range) x = left_range;
17365
17366 if (x < bar->start)
17367 emacs_event->part = scroll_bar_before_handle;
17368 else if (x < bar->end + HORIZONTAL_SCROLL_BAR_MIN_HANDLE)
17369 emacs_event->part = scroll_bar_horizontal_handle;
17370 else
17371 emacs_event->part = scroll_bar_after_handle;
17372
17373 #ifndef USE_TOOLKIT_SCROLL_BARS
17374
17375 if (event->type == ButtonRelease && bar->dragging != -1)
17376 {
17377 new_start = - bar->dragging;
17378 new_end = new_start + bar->end - bar->start;
17379
17380 x_scroll_bar_set_handle (bar, new_start, new_end, false);
17381 bar->dragging = -1;
17382 }
17383 #endif
17384
17385 XSETINT (emacs_event->x, left_range);
17386 XSETINT (emacs_event->y, x);
17387 }
17388 else
17389 {
17390 top_range
17391 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
17392 y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
17393
17394 if (y < 0) y = 0;
17395 if (y > top_range) y = top_range;
17396
17397 if (y < bar->start)
17398 emacs_event->part = scroll_bar_above_handle;
17399 else if (y < bar->end + VERTICAL_SCROLL_BAR_MIN_HANDLE)
17400 emacs_event->part = scroll_bar_handle;
17401 else
17402 emacs_event->part = scroll_bar_below_handle;
17403
17404 #ifndef USE_TOOLKIT_SCROLL_BARS
17405
17406 if (event->type == ButtonRelease && bar->dragging != -1)
17407 {
17408 new_start = y - bar->dragging;
17409 new_end = new_start + bar->end - bar->start;
17410
17411 x_scroll_bar_set_handle (bar, new_start, new_end, false);
17412 bar->dragging = -1;
17413 }
17414 #endif
17415
17416 XSETINT (emacs_event->x, y);
17417 XSETINT (emacs_event->y, top_range);
17418 }
17419 }
17420
17421 #ifndef USE_TOOLKIT_SCROLL_BARS
17422
17423
17424
17425
17426
17427
17428 static void
17429 x_scroll_bar_note_movement (struct scroll_bar *bar,
17430 const XMotionEvent *event)
17431 {
17432 struct frame *f = XFRAME (XWINDOW (bar->window)->frame);
17433 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
17434
17435 dpyinfo->last_mouse_movement_time = event->time;
17436 dpyinfo->last_mouse_movement_time_send_event = event->send_event;
17437 dpyinfo->last_mouse_scroll_bar = bar;
17438 f->mouse_moved = true;
17439
17440
17441 if (bar->dragging != -1)
17442 {
17443
17444 int new_start = event->y - bar->dragging;
17445
17446 if (new_start != bar->start)
17447 {
17448 int new_end = new_start + bar->end - bar->start;
17449
17450 x_scroll_bar_set_handle (bar, new_start, new_end, false);
17451 }
17452 }
17453 }
17454
17455 #endif
17456
17457
17458
17459
17460 static void
17461 x_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
17462 enum scroll_bar_part *part, Lisp_Object *x,
17463 Lisp_Object *y, Time *timestamp)
17464 {
17465 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp);
17466 struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar;
17467 Window w = bar->x_window;
17468 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
17469 int win_x, win_y;
17470 Window dummy_window;
17471 int dummy_coord;
17472 unsigned int dummy_mask;
17473
17474 block_input ();
17475
17476
17477
17478 if (x_query_pointer (FRAME_X_DISPLAY (f), w,
17479
17480
17481 &dummy_window, &dummy_window,
17482 &dummy_coord, &dummy_coord,
17483
17484
17485 &win_x, &win_y,
17486
17487
17488 &dummy_mask))
17489 {
17490 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
17491
17492 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
17493
17494 if (bar->dragging != -1)
17495 win_y -= bar->dragging;
17496
17497 if (win_y < 0)
17498 win_y = 0;
17499 if (win_y > top_range)
17500 win_y = top_range;
17501
17502 *fp = f;
17503 *bar_window = bar->window;
17504
17505 if (bar->dragging != -1)
17506 *part = scroll_bar_handle;
17507 else if (win_y < bar->start)
17508 *part = scroll_bar_above_handle;
17509 else if (win_y < bar->end + VERTICAL_SCROLL_BAR_MIN_HANDLE)
17510 *part = scroll_bar_handle;
17511 else
17512 *part = scroll_bar_below_handle;
17513
17514 XSETINT (*x, win_y);
17515 XSETINT (*y, top_range);
17516
17517 f->mouse_moved = false;
17518 dpyinfo->last_mouse_scroll_bar = NULL;
17519 *timestamp = dpyinfo->last_mouse_movement_time;
17520 }
17521
17522 unblock_input ();
17523 }
17524
17525
17526
17527
17528
17529 static void
17530 x_horizontal_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
17531 enum scroll_bar_part *part, Lisp_Object *x,
17532 Lisp_Object *y, Time *timestamp)
17533 {
17534 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp);
17535 struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar;
17536 Window w = bar->x_window;
17537 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
17538 int win_x, win_y;
17539 Window dummy_window;
17540 int dummy_coord;
17541 unsigned int dummy_mask;
17542
17543 block_input ();
17544
17545
17546
17547 if (x_query_pointer (FRAME_X_DISPLAY (f), w,
17548
17549
17550 &dummy_window, &dummy_window,
17551 &dummy_coord, &dummy_coord,
17552
17553
17554 &win_x, &win_y,
17555
17556
17557 &dummy_mask))
17558 {
17559 int left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width);
17560
17561 win_x -= HORIZONTAL_SCROLL_BAR_LEFT_BORDER;
17562
17563 if (bar->dragging != -1)
17564 win_x -= bar->dragging;
17565
17566 if (win_x < 0)
17567 win_x = 0;
17568 if (win_x > left_range)
17569 win_x = left_range;
17570
17571 *fp = f;
17572 *bar_window = bar->window;
17573
17574 if (bar->dragging != -1)
17575 *part = scroll_bar_horizontal_handle;
17576 else if (win_x < bar->start)
17577 *part = scroll_bar_before_handle;
17578 else if (win_x < bar->end + HORIZONTAL_SCROLL_BAR_MIN_HANDLE)
17579 *part = scroll_bar_handle;
17580 else
17581 *part = scroll_bar_after_handle;
17582
17583 XSETINT (*y, win_x);
17584 XSETINT (*x, left_range);
17585
17586 f->mouse_moved = false;
17587 dpyinfo->last_mouse_scroll_bar = NULL;
17588 *timestamp = dpyinfo->last_mouse_movement_time;
17589 }
17590
17591 unblock_input ();
17592 }
17593
17594
17595
17596
17597
17598
17599 static void
17600 x_scroll_bar_clear (struct frame *f)
17601 {
17602 #ifndef USE_TOOLKIT_SCROLL_BARS
17603 Lisp_Object bar, condemned;
17604 GC gc = f->output_data.x->normal_gc;
17605
17606 if (f->output_data.x->scroll_bar_background_pixel != -1)
17607 XSetForeground (FRAME_X_DISPLAY (f), gc,
17608 f->output_data.x->scroll_bar_background_pixel);
17609 else
17610 XSetForeground (FRAME_X_DISPLAY (f), gc,
17611 FRAME_BACKGROUND_PIXEL (f));
17612
17613
17614
17615
17616 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
17617 {
17618 condemned = FRAME_CONDEMNED_SCROLL_BARS (f);
17619 for (bar = FRAME_SCROLL_BARS (f);
17620
17621
17622 !NILP (bar) || (bar = condemned,
17623 condemned = Qnil,
17624 !NILP (bar));
17625 bar = XSCROLL_BAR (bar)->next)
17626 x_scroll_bar_redraw (XSCROLL_BAR (bar));
17627 }
17628
17629 XSetForeground (FRAME_X_DISPLAY (f), gc,
17630 FRAME_FOREGROUND_PIXEL (f));
17631 #endif
17632 }
17633
17634 #ifdef ENABLE_CHECKING
17635
17636
17637
17638
17639 static int temp_index;
17640 static short temp_buffer[100];
17641
17642 #define STORE_KEYSYM_FOR_DEBUG(keysym) \
17643 if (temp_index == ARRAYELTS (temp_buffer)) \
17644 temp_index = 0; \
17645 temp_buffer[temp_index++] = (keysym)
17646
17647 #else
17648
17649 #define STORE_KEYSYM_FOR_DEBUG(keysym) ((void)0)
17650
17651 #endif
17652
17653
17654
17655
17656 static struct x_display_info *XTread_socket_fake_io_error;
17657
17658
17659
17660
17661
17662
17663 static struct x_display_info *next_noop_dpyinfo;
17664
17665
17666
17667
17668
17669
17670
17671
17672
17673 #ifdef HAVE_X_I18N
17674 static int
17675 x_filter_event (struct x_display_info *dpyinfo, XEvent *event)
17676 {
17677
17678
17679
17680
17681
17682 struct frame *f1;
17683
17684 #if defined HAVE_XINPUT2 && defined USE_GTK
17685 bool xinput_event = false;
17686 if (dpyinfo->supports_xi2
17687 && event->type == GenericEvent
17688 && (event->xgeneric.extension
17689 == dpyinfo->xi2_opcode)
17690 && ((event->xgeneric.evtype
17691 == XI_KeyPress)
17692 || (event->xgeneric.evtype
17693 == XI_KeyRelease)))
17694 {
17695 f1 = x_any_window_to_frame (dpyinfo,
17696 ((XIDeviceEvent *)
17697 event->xcookie.data)->event);
17698 xinput_event = true;
17699 }
17700 else
17701 #endif
17702 f1 = x_any_window_to_frame (dpyinfo,
17703 event->xclient.window);
17704
17705 #ifdef USE_GTK
17706 if (!x_gtk_use_native_input
17707 && !dpyinfo->prefer_native_input)
17708 {
17709 #endif
17710 return XFilterEvent (event, f1 ? FRAME_X_WINDOW (f1) : None);
17711 #ifdef USE_GTK
17712 }
17713 else if (f1 && (event->type == KeyPress
17714 || event->type == KeyRelease
17715 #ifdef HAVE_XINPUT2
17716 || xinput_event
17717 #endif
17718 ))
17719 {
17720 bool result;
17721
17722 block_input ();
17723 result = xg_filter_key (f1, event);
17724 unblock_input ();
17725
17726
17727
17728
17729
17730 if (popup_activated ())
17731 xg_pending_quit_event.kind = NO_EVENT;
17732
17733 if (result && f1)
17734
17735
17736 XNoOp (FRAME_X_DISPLAY (f1));
17737
17738 return result;
17739 }
17740
17741 return 0;
17742 #endif
17743 }
17744 #endif
17745
17746 #ifdef USE_GTK
17747
17748
17749
17750 static GdkFilterReturn
17751 event_handler_gdk (GdkXEvent *gxev, GdkEvent *ev, gpointer data)
17752 {
17753 XEvent *xev = (XEvent *) gxev;
17754
17755 block_input ();
17756 if (current_count >= 0)
17757 {
17758 struct x_display_info *dpyinfo;
17759
17760 dpyinfo = x_display_info_for_display (xev->xany.display);
17761
17762 #ifdef HAVE_X_I18N
17763
17764
17765
17766 if ((xev->type == KeyPress || xev->type == KeyRelease)
17767 && dpyinfo
17768 && x_filter_event (dpyinfo, xev))
17769 {
17770 unblock_input ();
17771 return GDK_FILTER_REMOVE;
17772 }
17773 #elif USE_GTK
17774 if (dpyinfo && (dpyinfo->prefer_native_input
17775 || x_gtk_use_native_input)
17776 && (xev->type == KeyPress
17777 #ifdef HAVE_XINPUT2
17778
17779
17780 || (dpyinfo->supports_xi2
17781 && xev->type == GenericEvent
17782 && (xev->xgeneric.extension
17783 == dpyinfo->xi2_opcode)
17784 && ((xev->xgeneric.evtype
17785 == XI_KeyPress)
17786 || (xev->xgeneric.evtype
17787 == XI_KeyRelease)))
17788 #endif
17789 ))
17790 {
17791 struct frame *f;
17792
17793 #ifdef HAVE_XINPUT2
17794 if (xev->type == GenericEvent)
17795 f = x_any_window_to_frame (dpyinfo,
17796 ((XIDeviceEvent *) xev->xcookie.data)->event);
17797 else
17798 #endif
17799 f = x_any_window_to_frame (dpyinfo, xev->xany.window);
17800
17801 if (f && xg_filter_key (f, xev))
17802 {
17803 unblock_input ();
17804 return GDK_FILTER_REMOVE;
17805 }
17806 }
17807 #endif
17808
17809 if (! dpyinfo)
17810 current_finish = X_EVENT_NORMAL;
17811 else
17812 current_count
17813 += handle_one_xevent (dpyinfo, xev, ¤t_finish,
17814 current_hold_quit);
17815 }
17816 else
17817 current_finish = x_dispatch_event (xev, xev->xany.display);
17818
17819 unblock_input ();
17820
17821 if (current_finish == X_EVENT_GOTO_OUT || current_finish == X_EVENT_DROP)
17822 return GDK_FILTER_REMOVE;
17823
17824 return GDK_FILTER_CONTINUE;
17825 }
17826 #endif
17827
17828
17829 static void xembed_send_message (struct frame *f, Time,
17830 enum xembed_message,
17831 long detail, long data1, long data2);
17832
17833 static void
17834 x_net_wm_state (struct frame *f, Window window)
17835 {
17836 int value = FULLSCREEN_NONE;
17837 Lisp_Object lval = Qnil;
17838 bool sticky = false, shaded = false;
17839
17840 x_get_current_wm_state (f, window, &value, &sticky, &shaded);
17841
17842 switch (value)
17843 {
17844 case FULLSCREEN_WIDTH:
17845 lval = Qfullwidth;
17846 break;
17847 case FULLSCREEN_HEIGHT:
17848 lval = Qfullheight;
17849 break;
17850 case FULLSCREEN_BOTH:
17851 lval = Qfullboth;
17852 break;
17853 case FULLSCREEN_MAXIMIZED:
17854 lval = Qmaximized;
17855 break;
17856 }
17857
17858 store_frame_param (f, Qfullscreen, lval);
17859 store_frame_param (f, Qsticky, sticky ? Qt : Qnil);
17860 store_frame_param (f, Qshaded, shaded ? Qt : Qnil);
17861 }
17862
17863
17864
17865 static void
17866 x_flush_dirty_back_buffer_on (struct frame *f)
17867 {
17868 #ifdef HAVE_XDBE
17869 if (FRAME_GARBAGED_P (f)
17870 || buffer_flipping_blocked_p ()
17871
17872
17873 || !FRAME_X_COMPLETE_P (f)
17874 || !FRAME_X_NEED_BUFFER_FLIP (f))
17875 return;
17876
17877 show_back_buffer (f);
17878 #endif
17879 }
17880
17881 #ifdef HAVE_GTK3
17882 void
17883 x_scroll_bar_configure (GdkEvent *event)
17884 {
17885 XEvent configure;
17886 GdkDisplay *gdpy;
17887 Display *dpy;
17888
17889 configure.xconfigure.type = ConfigureNotify;
17890 configure.xconfigure.serial = 0;
17891 configure.xconfigure.send_event = event->configure.send_event;
17892 configure.xconfigure.x = event->configure.x;
17893 configure.xconfigure.y = event->configure.y;
17894 configure.xconfigure.width = event->configure.width;
17895 configure.xconfigure.height = event->configure.height;
17896 configure.xconfigure.border_width = 0;
17897 configure.xconfigure.event = GDK_WINDOW_XID (event->configure.window);
17898 configure.xconfigure.window = GDK_WINDOW_XID (event->configure.window);
17899 configure.xconfigure.above = None;
17900 configure.xconfigure.override_redirect = False;
17901
17902 gdpy = gdk_window_get_display (event->configure.window);
17903 dpy = gdk_x11_display_get_xdisplay (gdpy);
17904
17905 x_dispatch_event (&configure, dpy);
17906 }
17907 #endif
17908
17909
17910
17911
17912
17913
17914
17915
17916
17917 static struct frame *
17918 mouse_or_wdesc_frame (struct x_display_info *dpyinfo, int wdesc)
17919 {
17920 struct frame *lm_f = (gui_mouse_grabbed (dpyinfo)
17921 ? dpyinfo->last_mouse_frame
17922 : NULL);
17923
17924 if (lm_f && !EQ (track_mouse, Qdropping)
17925 && !EQ (track_mouse, Qdrag_source))
17926 return lm_f;
17927 else
17928 {
17929 struct frame *w_f = x_window_to_frame (dpyinfo, wdesc);
17930
17931
17932 if (!w_f || FRAME_TOOLTIP_P (w_f))
17933 return EQ (track_mouse, Qdropping) ? lm_f : NULL;
17934 else
17935
17936
17937 return w_f;
17938 }
17939 }
17940
17941 static void
17942 x_dnd_compute_tip_xy (int *root_x, int *root_y, Lisp_Object attributes)
17943 {
17944 Lisp_Object monitor, geometry;
17945 int min_x, min_y, max_x, max_y;
17946 int width, height;
17947
17948 width = FRAME_PIXEL_WIDTH (XFRAME (tip_frame));
17949 height = FRAME_PIXEL_HEIGHT (XFRAME (tip_frame));
17950
17951 max_y = -1;
17952
17953
17954
17955 while (CONSP (attributes))
17956 {
17957 monitor = XCAR (attributes);
17958 geometry = assq_no_quit (Qgeometry, monitor);
17959
17960 if (CONSP (geometry))
17961 {
17962 min_x = XFIXNUM (Fnth (make_fixnum (1), geometry));
17963 min_y = XFIXNUM (Fnth (make_fixnum (2), geometry));
17964 max_x = min_x + XFIXNUM (Fnth (make_fixnum (3), geometry));
17965 max_y = min_y + XFIXNUM (Fnth (make_fixnum (4), geometry));
17966
17967 if (min_x <= *root_x && *root_x < max_x
17968 && min_y <= *root_y && *root_y < max_y)
17969 break;
17970
17971 max_y = -1;
17972 }
17973
17974 attributes = XCDR (attributes);
17975 }
17976
17977
17978
17979 if (max_y < 0)
17980 {
17981 min_x = 0;
17982 min_y = 0;
17983 max_x = x_display_pixel_width (FRAME_DISPLAY_INFO (x_dnd_frame));
17984 max_y = x_display_pixel_height (FRAME_DISPLAY_INFO (x_dnd_frame));
17985 }
17986
17987 if (*root_y + XFIXNUM (tip_dy) <= min_y)
17988 *root_y = min_y;
17989 else if (*root_y + XFIXNUM (tip_dy) + height <= max_y)
17990
17991 *root_y += XFIXNUM (tip_dy);
17992 else if (height + XFIXNUM (tip_dy) + min_y <= *root_y)
17993
17994 *root_y -= height + XFIXNUM (tip_dy);
17995 else
17996
17997 *root_y = min_y;
17998
17999 if (*root_x + XFIXNUM (tip_dx) <= min_x)
18000 *root_x = 0;
18001 else if (*root_x + XFIXNUM (tip_dx) + width <= max_x)
18002
18003 *root_x += XFIXNUM (tip_dx);
18004 else if (width + XFIXNUM (tip_dx) + min_x <= *root_x)
18005
18006 *root_x -= width + XFIXNUM (tip_dx);
18007 else
18008
18009 *root_x = min_x;
18010 }
18011
18012 static void
18013 x_dnd_update_tooltip_position (int root_x, int root_y)
18014 {
18015 struct frame *tip_f;
18016
18017 if (!x_dnd_in_progress || !x_dnd_update_tooltip)
18018 return;
18019
18020 if (!FRAMEP (tip_frame))
18021 return;
18022
18023 tip_f = XFRAME (tip_frame);
18024
18025 if (!FRAME_LIVE_P (tip_f)
18026 || !FRAME_VISIBLE_P (tip_f)
18027 || (FRAME_X_DISPLAY (tip_f)
18028 != FRAME_X_DISPLAY (x_dnd_frame)))
18029 return;
18030
18031 if (tip_window != None
18032 && FIXNUMP (tip_dx) && FIXNUMP (tip_dy))
18033 {
18034 x_dnd_compute_tip_xy (&root_x, &root_y,
18035 x_dnd_monitors);
18036
18037 if (x_dnd_last_tooltip_valid
18038 && root_x == x_dnd_last_tooltip_x
18039 && root_y == x_dnd_last_tooltip_y)
18040 return;
18041
18042 x_dnd_last_tooltip_x = root_x;
18043 x_dnd_last_tooltip_y = root_y;
18044 x_dnd_last_tooltip_valid = true;
18045
18046 XMoveWindow (FRAME_X_DISPLAY (x_dnd_frame),
18047 tip_window, root_x, root_y);
18048 }
18049 }
18050
18051 static void
18052 x_dnd_update_tooltip_now (void)
18053 {
18054 int root_x, root_y;
18055 Window root, child;
18056 int win_x, win_y;
18057 unsigned int mask;
18058 Bool rc;
18059 struct x_display_info *dpyinfo;
18060
18061 if (!x_dnd_in_progress || !x_dnd_update_tooltip)
18062 return;
18063
18064 dpyinfo = FRAME_DISPLAY_INFO (x_dnd_frame);
18065
18066 #ifndef HAVE_XINPUT2
18067 rc = XQueryPointer (dpyinfo->display,
18068 dpyinfo->root_window,
18069 &root, &child, &root_x,
18070 &root_y, &win_x, &win_y,
18071 &mask);
18072 #else
18073 rc = x_query_pointer_1 (dpyinfo, x_dnd_pointer_device,
18074 dpyinfo->root_window,
18075 &root, &child, &root_x,
18076 &root_y, &win_x, &win_y,
18077 &mask);
18078 #endif
18079
18080 if (rc)
18081 x_dnd_update_tooltip_position (root_x, root_y);
18082 }
18083
18084
18085
18086 static void
18087 x_dnd_update_state (struct x_display_info *dpyinfo, Time timestamp)
18088 {
18089 int root_x, root_y, dummy_x, dummy_y, target_proto, motif_style;
18090 unsigned int dummy_mask;
18091 Window dummy, dummy_child, target, toplevel;
18092 xm_top_level_leave_message lmsg;
18093 xm_top_level_enter_message emsg;
18094 xm_drag_motion_message dmsg;
18095 xm_drop_start_message dsmsg;
18096 bool was_frame;
18097
18098 if (x_query_pointer_1 (dpyinfo,
18099 #ifdef HAVE_XINPUT2
18100 x_dnd_pointer_device,
18101 #else
18102 -1,
18103 #endif
18104 dpyinfo->root_window,
18105 &dummy, &dummy_child,
18106 &root_x, &root_y,
18107 &dummy_x, &dummy_y,
18108 &dummy_mask))
18109 {
18110 target = x_dnd_get_target_window (dpyinfo, root_x,
18111 root_y, &target_proto,
18112 &motif_style, &toplevel,
18113 &was_frame);
18114
18115 if (toplevel != x_dnd_last_seen_toplevel)
18116 {
18117 if (toplevel != FRAME_OUTER_WINDOW (x_dnd_frame)
18118 && x_dnd_return_frame == 1)
18119 x_dnd_return_frame = 2;
18120
18121 if (x_dnd_return_frame == 2
18122 && x_any_window_to_frame (dpyinfo, toplevel))
18123 {
18124 if (x_dnd_last_seen_window != None
18125 && x_dnd_last_protocol_version != -1
18126 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
18127 x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window,
18128 x_dnd_last_seen_toplevel);
18129 else if (x_dnd_last_seen_window != None
18130 && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
18131 && !x_dnd_disable_motif_drag
18132 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
18133 {
18134 if (!x_dnd_motif_setup_p)
18135 xm_setup_drag_info (dpyinfo, x_dnd_frame);
18136
18137 lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
18138 XM_DRAG_REASON_TOP_LEVEL_LEAVE);
18139 lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
18140 lmsg.zero = 0;
18141 lmsg.timestamp = timestamp;
18142 lmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
18143
18144 if (x_dnd_motif_setup_p)
18145 xm_send_top_level_leave_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
18146 x_dnd_last_seen_window, &lmsg);
18147 }
18148
18149 x_dnd_end_window = x_dnd_last_seen_window;
18150 x_dnd_last_seen_window = None;
18151 x_dnd_last_seen_toplevel = None;
18152 x_dnd_in_progress = false;
18153 x_dnd_return_frame_object
18154 = x_any_window_to_frame (dpyinfo, toplevel);
18155 x_dnd_return_frame = 3;
18156 x_dnd_waiting_for_finish = false;
18157 target = None;
18158 }
18159 }
18160
18161 if (target != x_dnd_last_seen_window)
18162 {
18163 if (x_dnd_last_seen_window != None
18164 && x_dnd_last_protocol_version != -1
18165 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
18166 x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window,
18167 x_dnd_last_seen_toplevel);
18168 else if (x_dnd_last_seen_window != None
18169 && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
18170 && !x_dnd_disable_motif_drag
18171 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
18172 {
18173 if (!x_dnd_motif_setup_p)
18174 xm_setup_drag_info (dpyinfo, x_dnd_frame);
18175
18176 lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
18177 XM_DRAG_REASON_TOP_LEVEL_LEAVE);
18178 lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
18179 lmsg.zero = 0;
18180 lmsg.timestamp = timestamp;
18181 lmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
18182
18183 if (x_dnd_motif_setup_p)
18184 xm_send_top_level_leave_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
18185 x_dnd_last_seen_window, &lmsg);
18186 }
18187
18188 x_dnd_action = None;
18189 x_dnd_last_seen_toplevel = toplevel;
18190 x_dnd_last_seen_window = target;
18191 x_dnd_last_protocol_version = target_proto;
18192 x_dnd_last_motif_style = motif_style;
18193 x_dnd_last_window_is_frame = was_frame;
18194
18195 if (target != None && x_dnd_last_protocol_version != -1)
18196 x_dnd_send_enter (x_dnd_frame, target, x_dnd_last_seen_toplevel,
18197 x_dnd_last_protocol_version);
18198 else if (target != None && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
18199 && !x_dnd_disable_motif_drag)
18200 {
18201 if (!x_dnd_motif_setup_p)
18202 xm_setup_drag_info (dpyinfo, x_dnd_frame);
18203
18204 emsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
18205 XM_DRAG_REASON_TOP_LEVEL_ENTER);
18206 emsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
18207 emsg.zero = 0;
18208 emsg.timestamp = timestamp;
18209 emsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
18210 emsg.index_atom = x_dnd_motif_atom;
18211
18212 if (x_dnd_motif_setup_p)
18213 xm_send_top_level_enter_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
18214 target, &emsg);
18215 }
18216 }
18217 else
18218 x_dnd_last_seen_toplevel = toplevel;
18219
18220 if (x_dnd_last_window_is_frame && target != None)
18221 x_dnd_note_self_position (dpyinfo, target, root_x, root_y);
18222 else if (x_dnd_last_protocol_version != -1 && target != None)
18223 x_dnd_send_position (x_dnd_frame, target,
18224 x_dnd_last_seen_toplevel,
18225 x_dnd_last_protocol_version,
18226 root_x, root_y,
18227 x_dnd_selection_timestamp,
18228 x_dnd_wanted_action, 0,
18229 #ifdef HAVE_XKB
18230 x_dnd_keyboard_state
18231 #else
18232 0
18233 #endif
18234 );
18235 else if (XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) && target != None
18236 && !x_dnd_disable_motif_drag)
18237 {
18238 if (!x_dnd_motif_setup_p)
18239 xm_setup_drag_info (dpyinfo, x_dnd_frame);
18240
18241 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
18242 XM_DRAG_REASON_DRAG_MOTION);
18243 dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
18244 dmsg.side_effects
18245 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
18246 x_dnd_wanted_action),
18247 XM_DROP_SITE_VALID, x_dnd_motif_operations,
18248 (!x_dnd_xm_use_help
18249 ? XM_DROP_ACTION_DROP
18250 : XM_DROP_ACTION_DROP_HELP));
18251 dmsg.timestamp = timestamp;
18252 dmsg.x = root_x;
18253 dmsg.y = root_y;
18254
18255 if (x_dnd_motif_setup_p)
18256 xm_send_drag_motion_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
18257 target, &dmsg);
18258 }
18259
18260 x_dnd_update_tooltip_position (root_x, root_y);
18261 }
18262
18263 else if (x_dnd_last_protocol_version != -1)
18264 {
18265 if (x_dnd_last_seen_window != None
18266 && x_dnd_last_protocol_version != -1)
18267 x_dnd_send_leave (x_dnd_frame,
18268 x_dnd_last_seen_window,
18269 x_dnd_last_seen_toplevel);
18270 else if (x_dnd_last_seen_window != None
18271 && !XM_DRAG_STYLE_IS_DROP_ONLY (x_dnd_last_motif_style)
18272 && x_dnd_last_motif_style != XM_DRAG_STYLE_NONE
18273 && x_dnd_motif_setup_p)
18274 {
18275 dsmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
18276 XM_DRAG_REASON_DROP_START);
18277 dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
18278 dsmsg.timestamp = timestamp;
18279 dsmsg.side_effects
18280 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
18281 x_dnd_wanted_action),
18282 XM_DROP_SITE_VALID, x_dnd_motif_operations,
18283 XM_DROP_ACTION_DROP_CANCEL);
18284 dsmsg.x = 0;
18285 dsmsg.y = 0;
18286 dsmsg.index_atom = x_dnd_motif_atom;
18287 dsmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
18288
18289 x_dnd_send_xm_leave_for_drop (dpyinfo, x_dnd_frame,
18290 x_dnd_last_seen_window, timestamp);
18291 xm_send_drop_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
18292 x_dnd_last_seen_window, &dsmsg);
18293 }
18294
18295 x_dnd_end_window = x_dnd_last_seen_window;
18296 x_dnd_last_seen_window = None;
18297 x_dnd_last_seen_toplevel = None;
18298 x_dnd_in_progress = false;
18299 x_dnd_waiting_for_finish = false;
18300 x_dnd_frame = NULL;
18301 }
18302 }
18303
18304 int
18305 x_display_pixel_height (struct x_display_info *dpyinfo)
18306 {
18307 if (dpyinfo->screen_height)
18308 return dpyinfo->screen_height;
18309
18310 return HeightOfScreen (dpyinfo->screen);
18311 }
18312
18313 int
18314 x_display_pixel_width (struct x_display_info *dpyinfo)
18315 {
18316 if (dpyinfo->screen_width)
18317 return dpyinfo->screen_width;
18318
18319 return WidthOfScreen (dpyinfo->screen);
18320 }
18321
18322
18323
18324 void
18325 x_wait_for_cell_change (Lisp_Object cell, struct timespec timeout)
18326 {
18327 struct x_display_info *dpyinfo;
18328 fd_set fds;
18329 int fd, maxfd;
18330 #ifndef USE_GTK
18331 int finish, rc;
18332 XEvent event;
18333 fd_set rfds;
18334 #endif
18335 struct input_event hold_quit;
18336 struct timespec current, at;
18337
18338 at = timespec_add (current_timespec (), timeout);
18339
18340 #ifndef USE_GTK
18341 FD_ZERO (&rfds);
18342 rc = -1;
18343 #endif
18344
18345 while (true)
18346 {
18347 FD_ZERO (&fds);
18348 maxfd = -1;
18349
18350 for (dpyinfo = x_display_list; dpyinfo;
18351 dpyinfo = dpyinfo->next)
18352 {
18353 fd = ConnectionNumber (dpyinfo->display);
18354
18355 #ifndef USE_GTK
18356 if ((rc < 0 || FD_ISSET (fd, &rfds))
18357
18358
18359 && XPending (dpyinfo->display))
18360 {
18361 while (XPending (dpyinfo->display))
18362 {
18363 EVENT_INIT (hold_quit);
18364
18365 XNextEvent (dpyinfo->display, &event);
18366 handle_one_xevent (dpyinfo, &event,
18367 &finish, &hold_quit);
18368
18369 if (!NILP (XCAR (cell)))
18370 return;
18371
18372 if (finish == X_EVENT_GOTO_OUT)
18373 break;
18374
18375
18376 if (hold_quit.kind != NO_EVENT)
18377 kbd_buffer_store_event (&hold_quit);
18378 }
18379 }
18380 #endif
18381
18382 if (fd > maxfd)
18383 maxfd = fd;
18384
18385 eassert (fd < FD_SETSIZE);
18386 FD_SET (fd, &fds);
18387 }
18388
18389
18390
18391 #ifdef USE_GTK
18392 while (gtk_events_pending ())
18393 {
18394 EVENT_INIT (hold_quit);
18395 current_count = 0;
18396 current_hold_quit = &hold_quit;
18397 current_finish = X_EVENT_NORMAL;
18398
18399 gtk_main_iteration ();
18400
18401 current_count = -1;
18402 current_hold_quit = NULL;
18403
18404
18405 if (hold_quit.kind != NO_EVENT)
18406 kbd_buffer_store_event (&hold_quit);
18407
18408 if (!NILP (XCAR (cell)))
18409 return;
18410
18411 if (current_finish == X_EVENT_GOTO_OUT)
18412 break;
18413 }
18414 #endif
18415
18416 eassert (maxfd >= 0);
18417
18418 current = current_timespec ();
18419
18420 if (timespec_cmp (at, current) < 0
18421 || !NILP (XCAR (cell)))
18422 return;
18423
18424 timeout = timespec_sub (at, current);
18425
18426 #ifndef USE_GTK
18427 rc = pselect (maxfd + 1, &fds, NULL, NULL, &timeout, NULL);
18428
18429 if (rc >= 0)
18430 rfds = fds;
18431 #else
18432 pselect (maxfd + 1, &fds, NULL, NULL, &timeout, NULL);
18433 #endif
18434 }
18435 }
18436
18437
18438
18439
18440
18441 static bool
18442 x_find_monitors_changed_event (struct x_display_info *dpyinfo)
18443 {
18444 union buffered_input_event *event;
18445
18446 event = kbd_fetch_ptr;
18447
18448 while (event != kbd_store_ptr)
18449 {
18450 if (event->ie.kind == MONITORS_CHANGED_EVENT
18451 && XTERMINAL (event->ie.arg) == dpyinfo->terminal)
18452 return true;
18453
18454 event = X_NEXT_KBD_EVENT (event);
18455 }
18456
18457 return false;
18458 }
18459
18460 #ifdef USE_GTK
18461 static void
18462 x_monitors_changed_cb (GdkScreen *gscr, gpointer user_data)
18463 {
18464 struct x_display_info *dpyinfo;
18465 struct input_event ie;
18466 Lisp_Object current_monitors, terminal;
18467 GdkDisplay *gdpy;
18468 Display *dpy;
18469
18470 gdpy = gdk_screen_get_display (gscr);
18471 dpy = gdk_x11_display_get_xdisplay (gdpy);
18472 dpyinfo = x_display_info_for_display (dpy);
18473
18474 if (!dpyinfo)
18475 return;
18476
18477 if (x_find_monitors_changed_event (dpyinfo))
18478 return;
18479
18480 XSETTERMINAL (terminal, dpyinfo->terminal);
18481
18482 current_monitors
18483 = Fx_display_monitor_attributes_list (terminal);
18484
18485 if (NILP (Fequal (current_monitors,
18486 dpyinfo->last_monitor_attributes_list)))
18487 {
18488 EVENT_INIT (ie);
18489 ie.kind = MONITORS_CHANGED_EVENT;
18490 ie.arg = terminal;
18491
18492 kbd_buffer_store_event (&ie);
18493
18494 if (x_dnd_in_progress && x_dnd_update_tooltip)
18495 x_dnd_monitors = current_monitors;
18496
18497 x_dnd_update_tooltip_now ();
18498 }
18499
18500 dpyinfo->last_monitor_attributes_list = current_monitors;
18501 }
18502 #endif
18503
18504
18505
18506
18507 static bool
18508 x_coords_from_dnd_message (struct x_display_info *dpyinfo,
18509 XEvent *event, int *x_out, int *y_out)
18510 {
18511 xm_drag_motion_message dmsg;
18512 xm_drag_motion_reply dreply;
18513 xm_drop_start_message smsg;
18514 xm_drop_start_reply reply;
18515 unsigned long kde_data;
18516
18517 if (event->type != ClientMessage)
18518 return false;
18519
18520 if (event->xclient.message_type == dpyinfo->Xatom_XdndPosition)
18521 {
18522 if (event->xclient.format != 32)
18523 return false;
18524
18525 *x_out = (((unsigned long) event->xclient.data.l[2]) >> 16
18526 & 0xffff);
18527 *y_out = (event->xclient.data.l[2] & 0xffff);
18528
18529 return true;
18530 }
18531
18532 if ((event->xclient.message_type
18533 == dpyinfo->Xatom_MOTIF_DRAG_AND_DROP_MESSAGE)
18534 && event->xclient.format == 8)
18535 {
18536 if (!xm_read_drag_motion_message (event, &dmsg))
18537 {
18538 *x_out = dmsg.x;
18539 *y_out = dmsg.y;
18540
18541 return true;
18542 }
18543 else if (!xm_read_drag_motion_reply (event, &dreply))
18544 {
18545 *x_out = dreply.better_x;
18546 *y_out = dreply.better_y;
18547
18548 return true;
18549 }
18550 else if (!xm_read_drop_start_message (event, &smsg))
18551 {
18552 *x_out = smsg.x;
18553 *y_out = smsg.y;
18554
18555 return true;
18556 }
18557 else if (!xm_read_drop_start_reply (event, &reply))
18558 {
18559 *x_out = reply.better_x;
18560 *y_out = reply.better_y;
18561
18562 return true;
18563 }
18564 }
18565
18566 if (((event->xclient.message_type
18567 == dpyinfo->Xatom_DndProtocol)
18568 || (event->xclient.message_type
18569 == dpyinfo->Xatom_DND_PROTOCOL))
18570 && event->xclient.format == 32
18571
18572
18573 && event->xclient.data.l[4])
18574 {
18575 kde_data = (unsigned long) event->xclient.data.l[3];
18576
18577 *x_out = (kde_data & 0xffff);
18578 *y_out = (kde_data >> 16 & 0xffff);
18579
18580 return true;
18581 }
18582
18583 return false;
18584 }
18585
18586 static void
18587 x_handle_wm_state (struct frame *f, struct input_event *ie)
18588 {
18589 struct x_display_info *dpyinfo;
18590 Atom type;
18591 int format;
18592 unsigned long nitems, bytes_after;
18593 unsigned char *data;
18594 unsigned long *state;
18595
18596 data = NULL;
18597 dpyinfo = FRAME_DISPLAY_INFO (f);
18598
18599 if (XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
18600 dpyinfo->Xatom_wm_state, 0, 2, False,
18601 AnyPropertyType, &type, &format, &nitems,
18602 &bytes_after, &data) != Success)
18603 return;
18604
18605 if (!data || nitems != 2 || format != 32)
18606 {
18607 if (data)
18608 XFree (data);
18609
18610 return;
18611 }
18612
18613 state = (unsigned long *) data;
18614
18615 if (state[0] == NormalState && FRAME_ICONIFIED_P (f))
18616 {
18617
18618
18619 SET_FRAME_VISIBLE (f, 1);
18620 SET_FRAME_ICONIFIED (f, false);
18621 f->output_data.x->has_been_visible = true;
18622
18623 ie->kind = DEICONIFY_EVENT;
18624 XSETFRAME (ie->frame_or_window, f);
18625 }
18626 else if (state[0] == IconicState
18627
18628
18629 && !x_wm_supports (f, dpyinfo->Xatom_net_wm_state_hidden))
18630 {
18631
18632
18633
18634 SET_FRAME_VISIBLE (f, 0);
18635 SET_FRAME_ICONIFIED (f, true);
18636
18637 ie->kind = ICONIFY_EVENT;
18638 XSETFRAME (ie->frame_or_window, f);
18639 }
18640
18641
18642
18643
18644
18645
18646 XFree (data);
18647 }
18648
18649 #ifdef HAVE_XFIXES
18650
18651 static bool
18652 x_handle_selection_monitor_event (struct x_display_info *dpyinfo,
18653 const XEvent *event)
18654 {
18655 XFixesSelectionNotifyEvent *notify;
18656 int i;
18657
18658 notify = (XFixesSelectionNotifyEvent *) event;
18659
18660 if (notify->window != dpyinfo->selection_tracking_window)
18661 return false;
18662
18663 for (i = 0; i < dpyinfo->n_monitored_selections; ++i)
18664 {
18665
18666 if (notify->selection == dpyinfo->monitored_selections[i].name)
18667 dpyinfo->monitored_selections[i].owner = notify->owner;
18668 }
18669
18670 return true;
18671 }
18672
18673 Window
18674 x_find_selection_owner (struct x_display_info *dpyinfo, Atom selection)
18675 {
18676 int i;
18677
18678 for (i = 0; i < dpyinfo->n_monitored_selections; ++i)
18679 {
18680 if (selection == dpyinfo->monitored_selections[i].name)
18681 return dpyinfo->monitored_selections[i].owner;
18682 }
18683
18684 return X_INVALID_WINDOW;
18685 }
18686
18687 #endif
18688
18689
18690
18691
18692
18693
18694
18695
18696
18697
18698 static int
18699 handle_one_xevent (struct x_display_info *dpyinfo,
18700 #ifndef HAVE_XINPUT2
18701 const XEvent *event,
18702 #else
18703 XEvent *event,
18704 #endif
18705 int *finish, struct input_event *hold_quit)
18706 {
18707 union buffered_input_event inev;
18708 int count = 0;
18709 int do_help = 0;
18710 #ifdef HAVE_XINPUT2
18711 struct xi_device_t *gen_help_device;
18712 Time gen_help_time UNINIT;
18713 #endif
18714 ptrdiff_t nbytes = 0;
18715 struct frame *any, *f = NULL, *mouse_frame;
18716 Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
18717
18718
18719
18720
18721 static XComposeStatus compose_status;
18722 XEvent configureEvent;
18723 XEvent next_event;
18724 Lisp_Object coding;
18725 #if defined USE_X_TOOLKIT && defined HAVE_XINPUT2
18726
18727
18728
18729 bool use_copy = false;
18730 XEvent copy;
18731 #elif defined USE_GTK && !defined HAVE_GTK3 && defined HAVE_XINPUT2
18732 GdkEvent *copy = NULL;
18733 GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display);
18734 #endif
18735 int dx, dy;
18736
18737
18738 #if defined HAVE_XINPUT2 || defined HAVE_XKB || defined HAVE_X_I18N
18739 USE_SAFE_ALLOCA;
18740 #endif
18741
18742
18743
18744
18745 if (!input_blocked_p ())
18746 emacs_abort ();
18747
18748 *finish = X_EVENT_NORMAL;
18749
18750 EVENT_INIT (inev.ie);
18751 inev.ie.kind = NO_EVENT;
18752 inev.ie.arg = Qnil;
18753 #ifdef HAVE_XINPUT2
18754 gen_help_device = NULL;
18755 #endif
18756
18757
18758
18759 if (event->type < LASTEvent)
18760 {
18761 #ifdef HAVE_XINPUT2
18762 if (event->type != GenericEvent)
18763 #endif
18764 any = x_any_window_to_frame (dpyinfo, event->xany.window);
18765 #ifdef HAVE_XINPUT2
18766 else
18767 any = NULL;
18768 #endif
18769 }
18770 else
18771 any = NULL;
18772
18773 if (any && any->wait_event_type == event->type)
18774 any->wait_event_type = 0;
18775
18776 switch (event->type)
18777 {
18778 case ClientMessage:
18779 {
18780 int rc;
18781
18782 if (((x_dnd_in_progress
18783 && FRAME_DISPLAY_INFO (x_dnd_frame) == dpyinfo)
18784 || (x_dnd_waiting_for_finish
18785 && FRAME_DISPLAY_INFO (x_dnd_finish_frame) == dpyinfo))
18786 && event->xclient.message_type == dpyinfo->Xatom_XdndStatus)
18787 {
18788 Window target;
18789 unsigned long r1, r2;
18790 int root_x, root_y;
18791 bool button;
18792
18793 target = event->xclient.data.l[0];
18794
18795 if (x_dnd_last_protocol_version != -1
18796 && x_dnd_in_progress
18797 && target == x_dnd_last_seen_toplevel
18798
18799
18800
18801
18802
18803 && !(event->xclient.data.l[1] & 2))
18804 {
18805 r1 = event->xclient.data.l[2];
18806 r2 = event->xclient.data.l[3];
18807
18808 x_dnd_mouse_rect_target = target;
18809 x_dnd_mouse_rect.x = (r1 & 0xffff0000) >> 16;
18810 x_dnd_mouse_rect.y = (r1 & 0xffff);
18811 x_dnd_mouse_rect.width = (r2 & 0xffff0000) >> 16;
18812 x_dnd_mouse_rect.height = (r2 & 0xffff);
18813 }
18814 else
18815 x_dnd_mouse_rect_target = None;
18816
18817 if (x_dnd_last_protocol_version != -1
18818 && (x_dnd_in_progress
18819 && target == x_dnd_last_seen_window))
18820 {
18821 if (event->xclient.data.l[1] & 1)
18822 {
18823 if (x_dnd_last_protocol_version >= 2)
18824 x_dnd_action = event->xclient.data.l[4];
18825 else
18826 x_dnd_action = dpyinfo->Xatom_XdndActionCopy;
18827 }
18828 else
18829 x_dnd_action = None;
18830 }
18831
18832
18833 if (x_dnd_waiting_for_status_window == target)
18834 {
18835 if (x_dnd_pending_send_position.type != 0)
18836 {
18837
18838
18839
18840
18841
18842 root_x = x_dnd_pending_send_position_root_x;
18843 root_y = x_dnd_pending_send_position_root_y;
18844 button = x_dnd_pending_send_position_button;
18845
18846 if (target == x_dnd_mouse_rect_target
18847 && x_dnd_mouse_rect.width
18848 && x_dnd_mouse_rect.height
18849
18850
18851
18852 && !button
18853 && (root_x >= x_dnd_mouse_rect.x
18854 && root_x < (x_dnd_mouse_rect.x
18855 + x_dnd_mouse_rect.width)
18856 && root_y >= x_dnd_mouse_rect.y
18857 && root_y < (x_dnd_mouse_rect.y
18858 + x_dnd_mouse_rect.height)))
18859 x_dnd_waiting_for_status_window = None;
18860 else
18861 {
18862 x_ignore_errors_for_next_request (dpyinfo, 0);
18863 XSendEvent (dpyinfo->display, target,
18864 False, NoEventMask,
18865 &x_dnd_pending_send_position);
18866 x_stop_ignoring_errors (dpyinfo);
18867 x_dnd_pending_send_position.type = 0;
18868
18869
18870
18871
18872
18873 }
18874 }
18875 else
18876 x_dnd_waiting_for_status_window = None;
18877
18878
18879 if (x_dnd_waiting_for_finish && x_dnd_need_send_drop
18880 && x_dnd_waiting_for_status_window == None)
18881 {
18882 if (event->xclient.data.l[1] & 1)
18883 {
18884 if (x_dnd_send_drop_proto >= 2)
18885 x_dnd_action = event->xclient.data.l[4];
18886 else
18887 x_dnd_action = dpyinfo->Xatom_XdndActionCopy;
18888 }
18889 else
18890 x_dnd_action = None;
18891
18892 x_dnd_waiting_for_finish
18893 = x_dnd_send_drop (x_dnd_finish_frame,
18894 target,
18895 x_dnd_last_seen_toplevel,
18896 x_dnd_selection_timestamp,
18897 x_dnd_send_drop_proto);
18898 }
18899 }
18900
18901 goto done;
18902 }
18903
18904 if (event->xclient.message_type == dpyinfo->Xatom_XdndFinished
18905 && (x_dnd_waiting_for_finish && !x_dnd_waiting_for_motif_finish)
18906
18907
18908
18909 && dpyinfo->display == x_dnd_finish_display
18910 && event->xclient.data.l[0] == x_dnd_pending_finish_target)
18911 {
18912 x_dnd_waiting_for_finish = false;
18913
18914 if (x_dnd_waiting_for_finish_proto >= 5)
18915 x_dnd_action = event->xclient.data.l[2];
18916
18917 if (x_dnd_waiting_for_finish_proto >= 5
18918 && !(event->xclient.data.l[1] & 1))
18919 x_dnd_action = None;
18920
18921 goto done;
18922 }
18923
18924 if ((event->xclient.message_type
18925 == dpyinfo->Xatom_MOTIF_DRAG_AND_DROP_MESSAGE)
18926 && x_dnd_waiting_for_finish
18927 && x_dnd_waiting_for_motif_finish == 1
18928 && dpyinfo == x_dnd_waiting_for_motif_finish_display)
18929 {
18930 xm_drop_start_reply reply;
18931 uint16_t operation, status, action;
18932
18933 if (!xm_read_drop_start_reply (event, &reply))
18934 {
18935 operation = XM_DRAG_SIDE_EFFECT_OPERATION (reply.side_effects);
18936 status = XM_DRAG_SIDE_EFFECT_SITE_STATUS (reply.side_effects);
18937 action = XM_DRAG_SIDE_EFFECT_DROP_ACTION (reply.side_effects);
18938
18939 if (operation != XM_DRAG_MOVE
18940 && operation != XM_DRAG_COPY
18941 && XM_DRAG_OPERATION_IS_LINK (operation))
18942 {
18943 x_dnd_waiting_for_finish = false;
18944 goto done;
18945 }
18946
18947 if (status != XM_DROP_SITE_VALID
18948 || (action == XM_DROP_ACTION_DROP_CANCEL
18949 || action == XM_DROP_ACTION_DROP_HELP))
18950 {
18951 x_dnd_waiting_for_finish = false;
18952 goto done;
18953 }
18954
18955 switch (operation)
18956 {
18957 case XM_DRAG_MOVE:
18958 x_dnd_action_symbol = QXdndActionMove;
18959 break;
18960
18961 case XM_DRAG_COPY:
18962 x_dnd_action_symbol = QXdndActionCopy;
18963 break;
18964
18965
18966 default:
18967 x_dnd_action_symbol = QXdndActionLink;
18968 break;
18969 }
18970
18971 x_dnd_waiting_for_motif_finish = 2;
18972 goto done;
18973 }
18974 }
18975
18976 if (event->xclient.message_type == dpyinfo->Xatom_EMACS_TMP
18977 && event->xclient.format == 8)
18978 {
18979
18980
18981
18982 if (any)
18983 FRAME_X_OUTPUT (any)->hourglass_p = event->xclient.data.b[0];
18984 }
18985
18986 if (event->xclient.message_type == dpyinfo->Xatom_wm_protocols
18987 && event->xclient.format == 32)
18988 {
18989 if (event->xclient.data.l[0] == dpyinfo->Xatom_wm_take_focus)
18990 {
18991
18992
18993
18994 f = any;
18995 #ifdef HAVE_X_I18N
18996
18997 if (f && FRAME_XIC (f))
18998 XSetICFocus (FRAME_XIC (f));
18999 #endif
19000 #if false
19001
19002
19003
19004
19005
19006
19007
19008
19009
19010
19011
19012
19013
19014
19015
19016
19017 if (f)
19018 {
19019 Display *d = event->xclient.display;
19020
19021
19022 x_catch_errors (d);
19023 XSetInputFocus (d, event->xclient.window,
19024
19025
19026 RevertToParent,
19027 event->xclient.data.l[1]);
19028 x_uncatch_errors ();
19029 }
19030
19031 #endif
19032
19033
19034
19035
19036
19037
19038
19039 x_display_set_last_user_time (dpyinfo, (event->xclient.data.l[1]
19040 & 0xffffffff),
19041 true, true);
19042 goto done;
19043 }
19044
19045 if (event->xclient.data.l[0] == dpyinfo->Xatom_wm_save_yourself)
19046 {
19047
19048
19049
19050
19051
19052
19053
19054
19055 #ifdef HAVE_X_SM
19056 if (! x_session_have_connection ())
19057 #endif
19058 {
19059 f = x_top_window_to_frame (dpyinfo,
19060 event->xclient.window);
19061
19062
19063 if (f == SELECTED_FRAME ())
19064 XSetCommand (FRAME_X_DISPLAY (f),
19065 event->xclient.window,
19066 initial_argv, initial_argc);
19067 else if (f)
19068 XSetCommand (FRAME_X_DISPLAY (f),
19069 event->xclient.window,
19070 0, 0);
19071 }
19072 goto done;
19073 }
19074
19075 if (event->xclient.data.l[0] == dpyinfo->Xatom_wm_delete_window)
19076 {
19077 f = x_top_window_to_frame (dpyinfo,
19078 event->xclient.window);
19079
19080 if (!f)
19081 goto OTHER;
19082
19083 inev.ie.kind = DELETE_WINDOW_EVENT;
19084 inev.ie.timestamp = event->xclient.data.l[1];
19085 XSETFRAME (inev.ie.frame_or_window, f);
19086 goto done;
19087 }
19088
19089
19090 if (event->xclient.data.l[0] == dpyinfo->Xatom_net_wm_ping
19091
19092
19093
19094
19095
19096
19097
19098 && (!(x_dnd_in_progress
19099 || x_dnd_waiting_for_finish)
19100 || event->xclient.window != dpyinfo->root_window)
19101 && event->xclient.format == 32)
19102 {
19103 XEvent send_event = *event;
19104
19105 send_event.xclient.window = dpyinfo->root_window;
19106 XSendEvent (dpyinfo->display, dpyinfo->root_window, False,
19107 SubstructureRedirectMask | SubstructureNotifyMask,
19108 &send_event);
19109
19110 *finish = X_EVENT_DROP;
19111 goto done;
19112 }
19113
19114 #if defined HAVE_XSYNC
19115 if (event->xclient.data.l[0] == dpyinfo->Xatom_net_wm_sync_request
19116 && event->xclient.format == 32
19117 && dpyinfo->xsync_supported_p)
19118 {
19119 struct frame *f
19120 = x_top_window_to_frame (dpyinfo,
19121 event->xclient.window);
19122 #if defined HAVE_GTK3
19123 GtkWidget *widget;
19124 GdkWindow *window;
19125 GdkFrameClock *frame_clock;
19126 #endif
19127
19128 if (f)
19129 {
19130 #ifndef HAVE_GTK3
19131 if (event->xclient.data.l[4] == 0)
19132 {
19133 XSyncIntsToValue (&FRAME_X_OUTPUT (f)->pending_basic_counter_value,
19134 event->xclient.data.l[2], event->xclient.data.l[3]);
19135 FRAME_X_OUTPUT (f)->sync_end_pending_p = true;
19136 }
19137 else if (event->xclient.data.l[4] == 1)
19138 {
19139 XSyncIntsToValue (&FRAME_X_OUTPUT (f)->resize_counter_value,
19140 event->xclient.data.l[2],
19141 event->xclient.data.l[3]);
19142
19143 FRAME_X_OUTPUT (f)->ext_sync_end_pending_p = true;
19144 }
19145
19146 *finish = X_EVENT_DROP;
19147 #else
19148 widget = FRAME_GTK_OUTER_WIDGET (f);
19149 window = gtk_widget_get_window (widget);
19150 eassert (window);
19151
19152
19153
19154
19155 gdk_x11_window_set_frame_sync_enabled (window, TRUE);
19156
19157 if (widget && !FRAME_X_OUTPUT (f)->xg_sync_end_pending_p)
19158 {
19159 frame_clock = gdk_window_get_frame_clock (window);
19160 eassert (frame_clock);
19161
19162 gdk_frame_clock_request_phase (frame_clock,
19163 GDK_FRAME_CLOCK_PHASE_BEFORE_PAINT);
19164 FRAME_X_OUTPUT (f)->xg_sync_end_pending_p = true;
19165 }
19166 #endif
19167 goto done;
19168 }
19169 }
19170 #endif
19171
19172 goto done;
19173 }
19174
19175 if (event->xclient.message_type == dpyinfo->Xatom_wm_configure_denied)
19176 goto done;
19177
19178 if (event->xclient.message_type == dpyinfo->Xatom_wm_window_moved)
19179 {
19180 int new_x, new_y;
19181 f = x_window_to_frame (dpyinfo, event->xclient.window);
19182
19183 new_x = event->xclient.data.s[0];
19184 new_y = event->xclient.data.s[1];
19185
19186 if (f)
19187 {
19188 f->left_pos = new_x;
19189 f->top_pos = new_y;
19190 }
19191 goto done;
19192 }
19193
19194 #ifdef X_TOOLKIT_EDITRES
19195 if (event->xclient.message_type == dpyinfo->Xatom_editres)
19196 {
19197 f = any;
19198 if (f)
19199 {
19200 _XEditResCheckMessages (f->output_data.x->widget,
19201 NULL, (XEvent *) event, NULL);
19202 goto done;
19203 }
19204
19205 goto OTHER;
19206 }
19207 #endif
19208
19209 if (event->xclient.message_type == dpyinfo->Xatom_DONE
19210 || event->xclient.message_type == dpyinfo->Xatom_PAGE)
19211 {
19212
19213
19214
19215
19216 f = x_window_to_frame (dpyinfo, event->xclient.window);
19217 if (!f)
19218 goto OTHER;
19219 #ifndef USE_CAIRO
19220 Pixmap pixmap = (Pixmap) event->xclient.data.l[1];
19221
19222
19223 x_catch_errors (dpyinfo->display);
19224 x_kill_gs_process (pixmap, f);
19225 x_uncatch_errors ();
19226 expose_frame (f, 0, 0, 0, 0);
19227 #endif
19228 goto done;
19229 }
19230
19231 #ifdef USE_TOOLKIT_SCROLL_BARS
19232
19233
19234 if (event->xclient.message_type == dpyinfo->Xatom_Scrollbar)
19235 {
19236
19237
19238
19239 x_scroll_bar_to_input_event (dpyinfo, event, &inev.ie);
19240
19241 *finish = X_EVENT_GOTO_OUT;
19242 goto done;
19243 }
19244 else if (event->xclient.message_type == dpyinfo->Xatom_Horizontal_Scrollbar)
19245 {
19246
19247
19248
19249 x_horizontal_scroll_bar_to_input_event (dpyinfo, event,
19250 &inev.ie);
19251
19252 *finish = X_EVENT_GOTO_OUT;
19253 goto done;
19254 }
19255 #endif
19256
19257
19258 if (event->xclient.message_type == dpyinfo->Xatom_XEMBED)
19259 {
19260 enum xembed_message msg = event->xclient.data.l[1];
19261 if (msg == XEMBED_FOCUS_IN || msg == XEMBED_FOCUS_OUT)
19262 x_detect_focus_change (dpyinfo, any, event, &inev.ie);
19263
19264 *finish = X_EVENT_GOTO_OUT;
19265 goto done;
19266 }
19267
19268 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
19269
19270
19271 if (event->xclient.message_type
19272 == dpyinfo->Xatom_net_wm_frame_drawn)
19273 {
19274 if (any)
19275 x_sync_handle_frame_drawn (dpyinfo, (XEvent *) event, any);
19276
19277 goto done;
19278 }
19279
19280 if (event->xclient.message_type
19281 == dpyinfo->Xatom_net_wm_frame_timings)
19282 goto done;
19283 #endif
19284
19285 if (xft_settings_event (dpyinfo, event))
19286 goto done;
19287
19288 f = any;
19289
19290 if (!f || FRAME_TOOLTIP_P (f))
19291 goto OTHER;
19292
19293
19294
19295 dx = 0;
19296 dy = 0;
19297
19298 rc = x_coords_from_dnd_message (dpyinfo, (XEvent *) event,
19299 &dx, &dy);
19300
19301 if (x_handle_dnd_message (f, &event->xclient, dpyinfo, &inev.ie,
19302 rc, dx, dy))
19303 *finish = X_EVENT_DROP;
19304 }
19305 break;
19306
19307 case SelectionNotify:
19308 #if defined USE_X_TOOLKIT || defined USE_GTK
19309 if (!x_window_to_frame (dpyinfo, event->xselection.requestor))
19310 goto OTHER;
19311 #endif
19312 #ifdef HAVE_GTK3
19313
19314
19315
19316 *finish = X_EVENT_DROP;
19317 #endif
19318 x_handle_selection_notify (&event->xselection);
19319 break;
19320
19321 case SelectionClear:
19322 #if defined USE_X_TOOLKIT || defined USE_GTK
19323 if (!x_window_to_frame (dpyinfo, event->xselectionclear.window))
19324 goto OTHER;
19325 #endif
19326 #ifdef HAVE_GTK3
19327 *finish = X_EVENT_DROP;
19328 #endif
19329 {
19330 const XSelectionClearEvent *eventp = &event->xselectionclear;
19331
19332 if (eventp->selection == dpyinfo->motif_drag_atom
19333 && (eventp->time == CurrentTime
19334 || dpyinfo->motif_drag_atom_time <= eventp->time))
19335 dpyinfo->motif_drag_atom = None;
19336
19337 inev.sie.kind = SELECTION_CLEAR_EVENT;
19338 SELECTION_EVENT_DPYINFO (&inev.sie) = dpyinfo;
19339 SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
19340 SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
19341
19342 if (x_use_pending_selection_requests)
19343 {
19344 x_push_selection_request (&inev.sie);
19345 EVENT_INIT (inev.ie);
19346 }
19347 }
19348 break;
19349
19350 case SelectionRequest:
19351 #ifdef USE_X_TOOLKIT
19352 if (!x_window_to_frame (dpyinfo, event->xselectionrequest.owner))
19353 goto OTHER;
19354 #endif
19355 #ifdef HAVE_GTK3
19356 *finish = X_EVENT_DROP;
19357 #endif
19358 {
19359 const XSelectionRequestEvent *eventp = &event->xselectionrequest;
19360
19361 inev.sie.kind = SELECTION_REQUEST_EVENT;
19362 SELECTION_EVENT_DPYINFO (&inev.sie) = dpyinfo;
19363 SELECTION_EVENT_REQUESTOR (&inev.sie) = eventp->requestor;
19364 SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
19365 SELECTION_EVENT_TARGET (&inev.sie) = eventp->target;
19366 SELECTION_EVENT_PROPERTY (&inev.sie) = eventp->property;
19367 SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
19368
19369
19370
19371
19372
19373 if (x_use_pending_selection_requests)
19374 {
19375 x_push_selection_request (&inev.sie);
19376 EVENT_INIT (inev.ie);
19377 }
19378
19379 if (x_dnd_waiting_for_finish
19380 && x_dnd_waiting_for_motif_finish == 2
19381 && dpyinfo == x_dnd_waiting_for_motif_finish_display
19382 && eventp->selection == x_dnd_motif_atom
19383 && (eventp->target == dpyinfo->Xatom_XmTRANSFER_SUCCESS
19384 || eventp->target == dpyinfo->Xatom_XmTRANSFER_FAILURE))
19385 {
19386 x_dnd_waiting_for_finish = false;
19387
19388
19389
19390 if (eventp->target == dpyinfo->Xatom_XmTRANSFER_FAILURE)
19391 x_dnd_action = None;
19392 }
19393 }
19394 break;
19395
19396 case PropertyNotify:
19397 if (x_dnd_in_progress && x_dnd_use_toplevels
19398 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame)
19399 && event->xproperty.atom == dpyinfo->Xatom_wm_state)
19400 {
19401 struct x_client_list_window *tem, *last;
19402
19403 for (last = NULL, tem = x_dnd_toplevels; tem;
19404 last = tem, tem = tem->next)
19405 {
19406 if (tem->window == event->xproperty.window)
19407 {
19408 Atom actual_type;
19409 int actual_format, rc;
19410 unsigned long nitems, bytesafter;
19411 unsigned char *data = NULL;
19412
19413 if (event->xproperty.state == PropertyDelete)
19414 {
19415 if (!last)
19416 x_dnd_toplevels = tem->next;
19417 else
19418 last->next = tem->next;
19419
19420 #ifdef HAVE_XSHAPE
19421 if (tem->n_input_rects != -1)
19422 xfree (tem->input_rects);
19423 if (tem->n_bounding_rects != -1)
19424 xfree (tem->bounding_rects);
19425 #endif
19426 xfree (tem);
19427 }
19428 else
19429 {
19430 x_catch_errors (dpyinfo->display);
19431 rc = XGetWindowProperty (dpyinfo->display,
19432 event->xproperty.window,
19433 dpyinfo->Xatom_wm_state,
19434 0, 2, False, AnyPropertyType,
19435 &actual_type, &actual_format,
19436 &nitems, &bytesafter, &data);
19437
19438 if (!x_had_errors_p (dpyinfo->display) && rc == Success && data
19439 && nitems == 2 && actual_format == 32)
19440 tem->wm_state = ((unsigned long *) data)[0];
19441 else
19442 tem->wm_state = WithdrawnState;
19443
19444 if (data)
19445 XFree (data);
19446 x_uncatch_errors_after_check ();
19447 }
19448
19449 x_dnd_update_state (dpyinfo, event->xproperty.time);
19450 break;
19451 }
19452 }
19453 }
19454
19455 f = x_top_window_to_frame (dpyinfo, event->xproperty.window);
19456 if (f && event->xproperty.atom == dpyinfo->Xatom_net_wm_state
19457
19458 && !FRAME_X_EMBEDDED_P (f))
19459 {
19460 bool not_hidden = x_handle_net_wm_state (f, &event->xproperty);
19461
19462 if (not_hidden && FRAME_ICONIFIED_P (f))
19463 {
19464 if (CONSP (frame_size_history))
19465 frame_size_history_plain
19466 (f, build_string ("PropertyNotify, not hidden & iconified"));
19467
19468
19469
19470
19471 SET_FRAME_VISIBLE (f, 1);
19472 SET_FRAME_ICONIFIED (f, false);
19473
19474 f->output_data.x->has_been_visible = true;
19475 inev.ie.kind = DEICONIFY_EVENT;
19476 #if defined USE_GTK && defined HAVE_GTK3
19477
19478
19479 if (f->was_invisible)
19480 {
19481 xg_frame_set_char_size
19482 (f, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f));
19483 f->was_invisible = false;
19484 }
19485 #endif
19486 XSETFRAME (inev.ie.frame_or_window, f);
19487 }
19488 else if (!not_hidden && !FRAME_ICONIFIED_P (f))
19489 {
19490 if (CONSP (frame_size_history))
19491 frame_size_history_plain
19492 (f, build_string ("PropertyNotify, hidden & not iconified"));
19493
19494 SET_FRAME_VISIBLE (f, 0);
19495 SET_FRAME_ICONIFIED (f, true);
19496 inev.ie.kind = ICONIFY_EVENT;
19497 XSETFRAME (inev.ie.frame_or_window, f);
19498 }
19499 }
19500
19501 if (f && event->xproperty.atom == dpyinfo->Xatom_wm_state
19502 && !FRAME_X_EMBEDDED_P (f) && !FRAME_PARENT_FRAME (f))
19503
19504
19505
19506
19507
19508
19509
19510
19511
19512 x_handle_wm_state (f, &inev.ie);
19513
19514 if (f && FRAME_X_OUTPUT (f)->alpha_identical_p
19515 && (event->xproperty.atom
19516 == dpyinfo->Xatom_net_wm_window_opacity))
19517 {
19518 #ifndef USE_XCB
19519 int rc, actual_format;
19520 Atom actual;
19521 unsigned char *tmp_data;
19522 unsigned long n, left, opacity;
19523
19524 tmp_data = NULL;
19525 #else
19526 xcb_get_property_cookie_t opacity_cookie;
19527 xcb_get_property_reply_t *opacity_reply;
19528 xcb_generic_error_t *error;
19529 bool rc;
19530 uint32_t value;
19531 #endif
19532
19533 if (event->xproperty.state == PropertyDelete)
19534 {
19535 f->alpha[0] = 1.0;
19536 f->alpha[1] = 1.0;
19537
19538 store_frame_param (f, Qalpha, Qnil);
19539 }
19540 else
19541 {
19542 #ifndef USE_XCB
19543 rc = XGetWindowProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
19544 dpyinfo->Xatom_net_wm_window_opacity,
19545 0, 1, False, AnyPropertyType, &actual,
19546 &actual_format, &n, &left, &tmp_data);
19547
19548 if (rc == Success && actual_format == 32
19549 && (actual == XA_CARDINAL
19550
19551
19552
19553 || actual == XA_ATOM
19554 || actual == XA_WINDOW) && n)
19555 {
19556 opacity = *(unsigned long *) tmp_data & OPAQUE;
19557 f->alpha[0] = (double) opacity / (double) OPAQUE;
19558 f->alpha[1] = (double) opacity / (double) OPAQUE;
19559
19560 store_frame_param (f, Qalpha, make_float (f->alpha[0]));
19561 }
19562 else
19563 {
19564 f->alpha[0] = 1.0;
19565 f->alpha[1] = 1.0;
19566
19567 store_frame_param (f, Qalpha, Qnil);
19568 }
19569 #else
19570 opacity_cookie
19571 = xcb_get_property (dpyinfo->xcb_connection, 0,
19572 (xcb_window_t) FRAME_OUTER_WINDOW (f),
19573 (xcb_atom_t) dpyinfo->Xatom_net_wm_window_opacity,
19574 XA_CARDINAL, 0, 1);
19575 opacity_reply
19576 = xcb_get_property_reply (dpyinfo->xcb_connection,
19577 opacity_cookie, &error);
19578
19579 if (!opacity_reply)
19580 free (error), rc = false;
19581 else
19582 rc = (opacity_reply->format == 32
19583 && (opacity_reply->type == XA_CARDINAL
19584 || opacity_reply->type == XA_ATOM
19585 || opacity_reply->type == XA_WINDOW)
19586 && (xcb_get_property_value_length (opacity_reply) >= 4));
19587
19588 if (rc)
19589 {
19590 value = *(uint32_t *) xcb_get_property_value (opacity_reply);
19591
19592 f->alpha[0] = (double) value / (double) OPAQUE;
19593 f->alpha[1] = (double) value / (double) OPAQUE;
19594 store_frame_param (f, Qalpha, make_float (f->alpha[0]));
19595 }
19596 else
19597 {
19598 f->alpha[0] = 1.0;
19599 f->alpha[1] = 1.0;
19600
19601 store_frame_param (f, Qalpha, Qnil);
19602 }
19603
19604 if (opacity_reply)
19605 free (opacity_reply);
19606 #endif
19607 }
19608
19609 #ifndef USE_XCB
19610 if (tmp_data)
19611 XFree (tmp_data);
19612 #endif
19613 }
19614
19615 if (event->xproperty.window == dpyinfo->root_window
19616 && (event->xproperty.atom == dpyinfo->Xatom_net_client_list_stacking
19617 || event->xproperty.atom == dpyinfo->Xatom_net_current_desktop)
19618 && x_dnd_in_progress
19619 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
19620 {
19621 if (x_dnd_use_toplevels)
19622 {
19623 x_dnd_free_toplevels (true);
19624
19625 if (x_dnd_compute_toplevels (dpyinfo))
19626 {
19627 x_dnd_free_toplevels (true);
19628 x_dnd_use_toplevels = false;
19629 }
19630 }
19631
19632 x_dnd_update_state (dpyinfo, event->xproperty.time);
19633 }
19634
19635 x_handle_property_notify (&event->xproperty);
19636 xft_settings_event (dpyinfo, event);
19637 goto OTHER;
19638
19639 case ReparentNotify:
19640 f = x_top_window_to_frame (dpyinfo, event->xreparent.window);
19641 if (f)
19642 {
19643 #ifndef USE_GTK
19644 if (FRAME_OUTPUT_DATA (f)->parent_desc
19645 && FRAME_X_EMBEDDED_P (f))
19646 {
19647
19648
19649
19650
19651
19652 FRAME_X_OUTPUT (f)->explicit_parent = false;
19653
19654
19655 XDeleteProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
19656 dpyinfo->Xatom_XEMBED_INFO);
19657 x_make_frame_visible (f);
19658 }
19659 #endif
19660
19661
19662 f->output_data.x->parent_desc = event->xreparent.parent;
19663
19664 if (!FRAME_PARENT_FRAME (f))
19665 {
19666 x_real_positions (f, &f->left_pos, &f->top_pos);
19667
19668
19669 dpyinfo->wm_type = X_WMTYPE_UNKNOWN;
19670 dpyinfo->net_supported_window = 0;
19671
19672 #ifndef USE_GTK
19673
19674
19675
19676
19677
19678
19679 if (FRAME_X_OUTPUT (f)->has_been_visible)
19680 x_update_frame_user_time_window (f);
19681 #endif
19682 }
19683 else
19684 {
19685 Window root;
19686 unsigned int dummy_uint;
19687
19688 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
19689 &root, &f->left_pos, &f->top_pos,
19690 &dummy_uint, &dummy_uint, &dummy_uint, &dummy_uint);
19691 }
19692
19693 x_set_frame_alpha (f);
19694 }
19695 goto OTHER;
19696
19697 case Expose:
19698
19699 #ifdef HAVE_XWIDGETS
19700 {
19701 struct xwidget_view *xv;
19702
19703 xv = xwidget_view_from_window (event->xexpose.window);
19704
19705 if (xv)
19706 {
19707 xwidget_expose (xv);
19708 goto OTHER;
19709 }
19710 }
19711 #endif
19712
19713 f = x_window_to_frame (dpyinfo, event->xexpose.window);
19714 if (f)
19715 {
19716 if (!FRAME_VISIBLE_P (f))
19717 {
19718
19719
19720
19721
19722
19723 if (EQ (x_set_frame_visibility_more_laxly, Qexpose)
19724 || EQ (x_set_frame_visibility_more_laxly, Qt))
19725 {
19726 SET_FRAME_VISIBLE (f, 1);
19727 SET_FRAME_ICONIFIED (f, false);
19728 }
19729
19730 #ifdef HAVE_XDBE
19731 if (FRAME_X_DOUBLE_BUFFERED_P (f))
19732 x_drop_xrender_surfaces (f);
19733 #endif
19734 f->output_data.x->has_been_visible = true;
19735 SET_FRAME_GARBAGED (f);
19736 }
19737 else if (FRAME_GARBAGED_P (f))
19738 {
19739 #ifdef USE_GTK
19740
19741
19742
19743
19744
19745
19746 x_clear_area1 (FRAME_X_DISPLAY (f),
19747 FRAME_X_WINDOW (f),
19748 event->xexpose.x, event->xexpose.y,
19749 event->xexpose.width, event->xexpose.height,
19750 0);
19751 x_clear_under_internal_border (f);
19752 #endif
19753 }
19754
19755 if (!FRAME_GARBAGED_P (f))
19756 {
19757 #if defined USE_X_TOOLKIT && defined USE_TOOLKIT_SCROLL_BARS
19758 if (f->output_data.x->edit_widget)
19759
19760
19761 goto OTHER;
19762 #endif
19763 #ifdef USE_GTK
19764
19765
19766 x_clear_area (f,
19767 event->xexpose.x, event->xexpose.y,
19768 event->xexpose.width, event->xexpose.height);
19769 #endif
19770 expose_frame (f, event->xexpose.x, event->xexpose.y,
19771 event->xexpose.width, event->xexpose.height);
19772 #ifndef USE_TOOLKIT_SCROLL_BARS
19773 x_scroll_bar_handle_exposure (f, (XEvent *) event);
19774 #endif
19775 #ifdef USE_GTK
19776 x_clear_under_internal_border (f);
19777 #endif
19778 }
19779 #ifndef USE_TOOLKIT_SCROLL_BARS
19780 else
19781 x_scroll_bar_handle_exposure (f, (XEvent *) event);
19782 #endif
19783
19784 #ifdef HAVE_XDBE
19785 if (!FRAME_GARBAGED_P (f))
19786 show_back_buffer (f);
19787 #endif
19788 }
19789 else
19790 {
19791 #if defined USE_LUCID
19792
19793
19794
19795 {
19796 Widget widget = x_window_to_menu_bar (event->xexpose.window);
19797 if (widget)
19798 xlwmenu_redisplay (widget);
19799 }
19800 #endif
19801
19802
19803 goto OTHER;
19804 }
19805 break;
19806
19807 case GraphicsExpose:
19808
19809
19810 f = x_window_to_frame (dpyinfo, event->xgraphicsexpose.drawable);
19811 if (f)
19812 {
19813 expose_frame (f, event->xgraphicsexpose.x,
19814 event->xgraphicsexpose.y,
19815 event->xgraphicsexpose.width,
19816 event->xgraphicsexpose.height);
19817 #ifndef USE_TOOLKIT_SCROLL_BARS
19818 x_scroll_bar_handle_exposure (f, (XEvent *) event);
19819 #endif
19820 #ifdef USE_GTK
19821 x_clear_under_internal_border (f);
19822 #endif
19823 #ifdef HAVE_XDBE
19824 show_back_buffer (f);
19825 #endif
19826 }
19827 #ifdef USE_X_TOOLKIT
19828 else
19829 goto OTHER;
19830 #endif
19831 break;
19832
19833 case NoExpose:
19834
19835
19836 #ifdef USE_X_TOOLKIT
19837 *finish = X_EVENT_DROP;
19838 #endif
19839 break;
19840
19841 case UnmapNotify:
19842 if (x_dnd_in_progress && x_dnd_use_toplevels
19843 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
19844 {
19845 for (struct x_client_list_window *tem = x_dnd_toplevels; tem;
19846 tem = tem->next)
19847 {
19848 if (tem->window == event->xunmap.window)
19849 {
19850 tem->mapped_p = false;
19851 break;
19852 }
19853 }
19854 }
19855
19856
19857 if (event->xunmap.window == tip_window)
19858 {
19859 tip_window = None;
19860 gui_redo_mouse_highlight (dpyinfo);
19861 }
19862
19863 f = x_top_window_to_frame (dpyinfo, event->xunmap.window);
19864 if (f)
19865
19866 {
19867 bool visible = FRAME_VISIBLE_P (f);
19868
19869 #ifdef USE_LUCID
19870
19871
19872
19873 if (FRAME_TOOLTIP_P (f) && popup_activated ())
19874 {
19875 Widget w;
19876 Lisp_Object tail, frame;
19877 struct frame *f1;
19878
19879 FOR_EACH_FRAME (tail, frame)
19880 {
19881 if (!FRAME_X_P (XFRAME (frame)))
19882 continue;
19883
19884 f1 = XFRAME (frame);
19885
19886 if (FRAME_LIVE_P (f1))
19887 {
19888 w = FRAME_X_OUTPUT (f1)->menubar_widget;
19889
19890 if (w && !DoesSaveUnders (FRAME_DISPLAY_INFO (f1)->screen))
19891 xlwmenu_redisplay (w);
19892 }
19893 }
19894 }
19895 #endif
19896
19897
19898
19899
19900 SET_FRAME_VISIBLE (f, 0);
19901
19902
19903
19904
19905
19906
19907 if (visible || FRAME_ICONIFIED_P (f))
19908 {
19909 if (CONSP (frame_size_history))
19910 frame_size_history_plain
19911 (f, build_string ("UnmapNotify, visible | iconified"));
19912
19913 SET_FRAME_ICONIFIED (f, true);
19914 inev.ie.kind = ICONIFY_EVENT;
19915 XSETFRAME (inev.ie.frame_or_window, f);
19916 }
19917 else if (CONSP (frame_size_history))
19918 frame_size_history_plain
19919 (f, build_string ("UnmapNotify, not visible & not iconified"));
19920 }
19921 goto OTHER;
19922
19923 case MapNotify:
19924 #if defined HAVE_XINPUT2 && defined HAVE_GTK3
19925 if (xg_is_menu_window (dpyinfo->display, event->xmap.window))
19926 popup_activated_flag = 1;
19927 #endif
19928
19929 if (x_dnd_in_progress
19930
19931
19932
19933
19934 && !x_dnd_use_toplevels
19935 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
19936 x_dnd_update_state (dpyinfo, dpyinfo->last_user_time);
19937
19938 if (x_dnd_in_progress && x_dnd_use_toplevels
19939 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
19940 {
19941 for (struct x_client_list_window *tem = x_dnd_toplevels; tem;
19942 tem = tem->next)
19943 {
19944 if (tem->window == event->xmap.window)
19945 {
19946 tem->mapped_p = true;
19947 break;
19948 }
19949 }
19950 }
19951
19952
19953
19954
19955 f = x_top_window_to_frame (dpyinfo, event->xmap.window);
19956 if (f)
19957 {
19958 bool iconified = FRAME_ICONIFIED_P (f);
19959 int value;
19960 bool sticky, shaded;
19961 bool not_hidden = x_get_current_wm_state (f, event->xmap.window, &value, &sticky,
19962 &shaded);
19963
19964 if (CONSP (frame_size_history))
19965 frame_size_history_extra
19966 (f,
19967 iconified
19968 ? (not_hidden
19969 ? build_string ("MapNotify, not hidden & iconified")
19970 : build_string ("MapNotify, hidden & iconified"))
19971 : (not_hidden
19972 ? build_string ("MapNotify, not hidden & not iconified")
19973 : build_string ("MapNotify, hidden & not iconified")),
19974 FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f),
19975 -1, -1, f->new_width, f->new_height);
19976
19977
19978
19979 if (!f->output_data.x->has_been_visible)
19980 {
19981
19982 x_check_fullscreen (f);
19983 #ifndef USE_GTK
19984
19985
19986 if (FRAME_SKIP_TASKBAR (f))
19987 x_set_skip_taskbar (f, Qt, Qnil);
19988 #endif
19989 }
19990
19991 if (!iconified)
19992 {
19993
19994
19995 if (FRAME_Z_GROUP (f) == z_group_above)
19996 x_set_z_group (f, Qabove, Qnil);
19997 else if (FRAME_Z_GROUP (f) == z_group_below)
19998 x_set_z_group (f, Qbelow, Qnil);
19999 }
20000
20001
20002
20003 if (not_hidden || FRAME_X_EMBEDDED_P (f))
20004 {
20005 SET_FRAME_VISIBLE (f, 1);
20006 SET_FRAME_ICONIFIED (f, false);
20007 #if defined USE_GTK && defined HAVE_GTK3
20008
20009
20010 if (f->was_invisible)
20011 {
20012 xg_frame_set_char_size
20013 (f, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f));
20014 f->was_invisible = false;
20015 }
20016 #endif
20017 f->output_data.x->has_been_visible = true;
20018 }
20019
20020 x_update_opaque_region (f, NULL);
20021
20022 if ((not_hidden || FRAME_X_EMBEDDED_P (f)) && iconified)
20023 {
20024 inev.ie.kind = DEICONIFY_EVENT;
20025 XSETFRAME (inev.ie.frame_or_window, f);
20026 }
20027 }
20028 goto OTHER;
20029
20030 case KeyPress:
20031 x_display_set_last_user_time (dpyinfo, event->xkey.time,
20032 event->xkey.send_event,
20033 true);
20034 ignore_next_mouse_click_timeout = 0;
20035
20036 coding = Qlatin_1;
20037
20038 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
20039
20040 if (popup_activated ())
20041 goto OTHER;
20042 #endif
20043
20044 f = any;
20045
20046 #ifdef USE_GTK
20047 if (f)
20048 x_set_gtk_user_time (f, event->xkey.time);
20049 #endif
20050
20051
20052
20053 if (!hlinfo->mouse_face_hidden && FIXNUMP (Vmouse_highlight)
20054 && (f == 0
20055 #if ! defined (USE_GTK)
20056 || !EQ (f->tool_bar_window, hlinfo->mouse_face_window)
20057 #endif
20058 || !EQ (f->tab_bar_window, hlinfo->mouse_face_window))
20059 )
20060 {
20061 mouse_frame = hlinfo->mouse_face_mouse_frame;
20062
20063 clear_mouse_face (hlinfo);
20064 hlinfo->mouse_face_hidden = true;
20065
20066 if (mouse_frame)
20067 x_flush_dirty_back_buffer_on (mouse_frame);
20068 }
20069
20070 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
20071 if (f == 0)
20072 {
20073
20074
20075 Widget widget = XtWindowToWidget (dpyinfo->display,
20076 event->xkey.window);
20077 if (widget && XmIsScrollBar (widget))
20078 {
20079 widget = XtParent (widget);
20080 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
20081 }
20082 }
20083 #endif
20084
20085 if (f != 0)
20086 {
20087 KeySym keysym, orig_keysym;
20088
20089
20090
20091
20092
20093
20094
20095
20096
20097
20098
20099 unsigned char copy_buffer[513];
20100 unsigned char *copy_bufptr = copy_buffer;
20101 int copy_bufsiz = sizeof (copy_buffer);
20102 int modifiers;
20103 Lisp_Object c;
20104
20105
20106 XKeyEvent xkey = event->xkey;
20107
20108 if (event->xkey.window == FRAME_X_WINDOW (f))
20109
20110
20111 x_compute_root_window_offset (f, event->xkey.x_root,
20112 event->xkey.y_root,
20113 event->xkey.x, event->xkey.y);
20114
20115 #ifdef HAVE_XINPUT2
20116 Time pending_keystroke_time;
20117 struct xi_device_t *source;
20118
20119 pending_keystroke_time = dpyinfo->pending_keystroke_time;
20120
20121 if (event->xkey.time >= pending_keystroke_time)
20122 {
20123 #if defined USE_GTK && !defined HAVE_GTK3
20124 if (!dpyinfo->pending_keystroke_time_special_p)
20125 #endif
20126 dpyinfo->pending_keystroke_time = 0;
20127 #if defined USE_GTK && !defined HAVE_GTK3
20128 else
20129 dpyinfo->pending_keystroke_time_special_p = false;
20130 #endif
20131 }
20132 #endif
20133
20134 #ifdef USE_GTK
20135
20136
20137
20138
20139 *finish = X_EVENT_DROP;
20140 #endif
20141
20142 xkey.state |= x_emacs_to_x_modifiers (dpyinfo,
20143 extra_keyboard_modifiers);
20144 modifiers = xkey.state;
20145
20146
20147
20148
20149
20150 xkey.state &= ~ControlMask;
20151 xkey.state &= ~(dpyinfo->meta_mod_mask
20152 | dpyinfo->super_mod_mask
20153 | dpyinfo->hyper_mod_mask
20154 | dpyinfo->alt_mod_mask);
20155
20156
20157
20158
20159
20160
20161 if (modifiers & dpyinfo->meta_mod_mask)
20162 memset (&compose_status, 0, sizeof (compose_status));
20163
20164 #ifdef HAVE_X_I18N
20165 if (FRAME_XIC (f))
20166 {
20167 Status status_return;
20168
20169 nbytes = XmbLookupString (FRAME_XIC (f),
20170 &xkey, (char *) copy_bufptr,
20171 copy_bufsiz, &keysym,
20172 &status_return);
20173 coding = FRAME_X_XIM_CODING (f);
20174 if (status_return == XBufferOverflow)
20175 {
20176 copy_bufsiz = nbytes + 1;
20177 copy_bufptr = SAFE_ALLOCA (copy_bufsiz);
20178 nbytes = XmbLookupString (FRAME_XIC (f),
20179 &xkey, (char *) copy_bufptr,
20180 copy_bufsiz, &keysym,
20181 &status_return);
20182 }
20183
20184 if (status_return == XLookupNone)
20185 break;
20186 else if (status_return == XLookupChars)
20187 {
20188 keysym = NoSymbol;
20189 modifiers = 0;
20190 }
20191 else if (status_return != XLookupKeySym
20192 && status_return != XLookupBoth)
20193 emacs_abort ();
20194 }
20195 else
20196 #endif
20197 {
20198 #ifdef HAVE_XKB
20199 int overflow;
20200 unsigned int consumed;
20201 KeySym sym;
20202
20203 if (dpyinfo->xkb_desc)
20204 {
20205
20206
20207
20208
20209
20210
20211 if (!XkbTranslateKeyCode (dpyinfo->xkb_desc,
20212 xkey.keycode, xkey.state,
20213 &consumed, &keysym))
20214 goto done_keysym;
20215
20216
20217
20218 sym = keysym, overflow = 0;
20219
20220 nbytes = XkbTranslateKeySym (dpyinfo->display, &keysym,
20221 xkey.state & ~consumed,
20222 (char *) copy_bufptr,
20223 copy_bufsiz, &overflow);
20224
20225 if (overflow)
20226 {
20227 copy_bufptr = SAFE_ALLOCA ((copy_bufsiz += overflow)
20228 * sizeof *copy_bufptr);
20229 overflow = 0;
20230
20231
20232
20233
20234 nbytes = XkbTranslateKeySym (dpyinfo->display, &sym,
20235 xkey.state & ~consumed,
20236 (char *) copy_bufptr,
20237 copy_bufsiz, &overflow);
20238
20239 if (overflow)
20240 nbytes = 0;
20241 }
20242
20243 if (nbytes)
20244 coding = Qnil;
20245 }
20246 else
20247 #endif
20248 nbytes = XLookupString (&xkey, (char *) copy_bufptr,
20249 copy_bufsiz, &keysym,
20250 &compose_status);
20251 }
20252
20253 #ifdef XK_F1
20254 if (x_dnd_in_progress && keysym == XK_F1)
20255 {
20256 x_dnd_xm_use_help = true;
20257 goto done_keysym;
20258 }
20259 #endif
20260
20261
20262
20263 if (keysym == dpyinfo->quit_keysym
20264 && (xkey.time - dpyinfo->quit_keysym_time
20265 <= 350))
20266 {
20267 Vquit_flag = Qt;
20268 goto done_keysym;
20269 }
20270
20271 if (keysym == dpyinfo->quit_keysym)
20272 {
20273
20274
20275 dpyinfo->quit_keysym_time = xkey.time;
20276 goto done_keysym;
20277 }
20278
20279
20280
20281 if (compose_status.chars_matched > 0 && nbytes == 0)
20282 break;
20283
20284 memset (&compose_status, 0, sizeof (compose_status));
20285 orig_keysym = keysym;
20286
20287
20288 XSETFRAME (inev.ie.frame_or_window, f);
20289 inev.ie.modifiers
20290 = x_x_to_emacs_modifiers (dpyinfo, modifiers);
20291 inev.ie.timestamp = xkey.time;
20292
20293
20294
20295 if (keysym >= 32 && keysym < 128)
20296
20297 {
20298 inev.ie.kind = ASCII_KEYSTROKE_EVENT;
20299 inev.ie.code = keysym;
20300
20301 #ifdef HAVE_XINPUT2
20302 if (event->xkey.time == pending_keystroke_time)
20303 {
20304 source = xi_device_from_id (dpyinfo,
20305 dpyinfo->pending_keystroke_source);
20306
20307 if (source)
20308 inev.ie.device = source->name;
20309 }
20310 #endif
20311
20312 goto done_keysym;
20313 }
20314
20315
20316 if (keysym >= 0x01000000 && keysym <= 0x0110FFFF)
20317 {
20318 if (keysym < 0x01000080)
20319 inev.ie.kind = ASCII_KEYSTROKE_EVENT;
20320 else
20321 inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
20322 inev.ie.code = keysym & 0xFFFFFF;
20323
20324 #ifdef HAVE_XINPUT2
20325 if (event->xkey.time == pending_keystroke_time)
20326 {
20327 source = xi_device_from_id (dpyinfo,
20328 dpyinfo->pending_keystroke_source);
20329
20330 if (source)
20331 inev.ie.device = source->name;
20332 }
20333 #endif
20334
20335 goto done_keysym;
20336 }
20337
20338
20339 if (HASH_TABLE_P (Vx_keysym_table)
20340 && (c = Fgethash (make_fixnum (keysym),
20341 Vx_keysym_table,
20342 Qnil),
20343 FIXNATP (c)))
20344 {
20345 inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFIXNAT (c))
20346 ? ASCII_KEYSTROKE_EVENT
20347 : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
20348 inev.ie.code = XFIXNAT (c);
20349
20350 #ifdef HAVE_XINPUT2
20351 if (event->xkey.time == pending_keystroke_time)
20352 {
20353 source = xi_device_from_id (dpyinfo,
20354 dpyinfo->pending_keystroke_source);
20355
20356 if (source)
20357 inev.ie.device = source->name;
20358 }
20359 #endif
20360
20361 goto done_keysym;
20362 }
20363
20364
20365 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
20366 || keysym == XK_Delete
20367 #ifdef XK_ISO_Left_Tab
20368 || (keysym >= XK_ISO_Left_Tab
20369 && keysym <= XK_ISO_Enter)
20370 #endif
20371 || IsCursorKey (keysym)
20372 || IsMiscFunctionKey (keysym)
20373 #ifdef HPUX
20374
20375
20376
20377
20378 || (XK_Select <= keysym && keysym < XK_KP_Space)
20379 #endif
20380 #ifdef XK_dead_circumflex
20381 || orig_keysym == XK_dead_circumflex
20382 #endif
20383 #ifdef XK_dead_grave
20384 || orig_keysym == XK_dead_grave
20385 #endif
20386 #ifdef XK_dead_tilde
20387 || orig_keysym == XK_dead_tilde
20388 #endif
20389 #ifdef XK_dead_diaeresis
20390 || orig_keysym == XK_dead_diaeresis
20391 #endif
20392 #ifdef XK_dead_macron
20393 || orig_keysym == XK_dead_macron
20394 #endif
20395 #ifdef XK_dead_degree
20396 || orig_keysym == XK_dead_degree
20397 #endif
20398 #ifdef XK_dead_acute
20399 || orig_keysym == XK_dead_acute
20400 #endif
20401 #ifdef XK_dead_cedilla
20402 || orig_keysym == XK_dead_cedilla
20403 #endif
20404 #ifdef XK_dead_breve
20405 || orig_keysym == XK_dead_breve
20406 #endif
20407 #ifdef XK_dead_ogonek
20408 || orig_keysym == XK_dead_ogonek
20409 #endif
20410 #ifdef XK_dead_caron
20411 || orig_keysym == XK_dead_caron
20412 #endif
20413 #ifdef XK_dead_doubleacute
20414 || orig_keysym == XK_dead_doubleacute
20415 #endif
20416 #ifdef XK_dead_abovedot
20417 || orig_keysym == XK_dead_abovedot
20418 #endif
20419 #ifdef XK_dead_abovering
20420 || orig_keysym == XK_dead_abovering
20421 #endif
20422 #ifdef XK_dead_belowdot
20423 || orig_keysym == XK_dead_belowdot
20424 #endif
20425 #ifdef XK_dead_voiced_sound
20426 || orig_keysym == XK_dead_voiced_sound
20427 #endif
20428 #ifdef XK_dead_semivoiced_sound
20429 || orig_keysym == XK_dead_semivoiced_sound
20430 #endif
20431 #ifdef XK_dead_hook
20432 || orig_keysym == XK_dead_hook
20433 #endif
20434 #ifdef XK_dead_horn
20435 || orig_keysym == XK_dead_horn
20436 #endif
20437 #ifdef XK_dead_stroke
20438 || orig_keysym == XK_dead_stroke
20439 #endif
20440 #ifdef XK_dead_abovecomma
20441 || orig_keysym == XK_dead_abovecomma
20442 #endif
20443 || IsKeypadKey (keysym)
20444 || IsFunctionKey (keysym)
20445
20446 || (orig_keysym & (1 << 28))
20447 || (keysym != NoSymbol && nbytes == 0))
20448 && ! (IsModifierKey (orig_keysym)
20449
20450
20451
20452
20453
20454 #if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
20455 || (XK_ISO_Lock <= orig_keysym
20456 && orig_keysym <= XK_ISO_Last_Group_Lock)
20457 #endif
20458 ))
20459 {
20460 STORE_KEYSYM_FOR_DEBUG (keysym);
20461
20462
20463 inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
20464 inev.ie.code = keysym;
20465
20466 #ifdef HAVE_XINPUT2
20467 if (event->xkey.time == pending_keystroke_time)
20468 {
20469 source = xi_device_from_id (dpyinfo,
20470 dpyinfo->pending_keystroke_source);
20471
20472 if (source)
20473 inev.ie.device = source->name;
20474 }
20475 #endif
20476
20477 goto done_keysym;
20478 }
20479
20480 {
20481 ptrdiff_t i;
20482
20483 for (i = 0; i < nbytes; i++)
20484 {
20485 STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]);
20486 }
20487
20488 if (nbytes)
20489 {
20490 inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
20491 inev.ie.arg = make_unibyte_string ((char *) copy_bufptr, nbytes);
20492
20493 Fput_text_property (make_fixnum (0), make_fixnum (nbytes),
20494 Qcoding, coding, inev.ie.arg);
20495
20496 #ifdef HAVE_XINPUT2
20497 if (event->xkey.time == pending_keystroke_time
20498
20499
20500
20501
20502 || (pending_keystroke_time && !event->xkey.time))
20503 {
20504 source = xi_device_from_id (dpyinfo,
20505 dpyinfo->pending_keystroke_source);
20506
20507 if (source)
20508 inev.ie.device = source->name;
20509 }
20510 #endif
20511 }
20512
20513 if (keysym == NoSymbol)
20514 break;
20515 }
20516 }
20517 done_keysym:
20518 #ifdef HAVE_X_I18N
20519 if (f)
20520 {
20521 struct window *w = XWINDOW (f->selected_window);
20522 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
20523
20524 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
20525 xic_set_statusarea (f);
20526 }
20527
20528
20529
20530
20531 break;
20532 #else
20533 goto OTHER;
20534 #endif
20535
20536 case KeyRelease:
20537 #ifdef HAVE_X_I18N
20538
20539
20540
20541 break;
20542 #else
20543 goto OTHER;
20544 #endif
20545
20546 case EnterNotify:
20547 x_display_set_last_user_time (dpyinfo, event->xcrossing.time,
20548 event->xcrossing.send_event,
20549 false);
20550
20551 #ifdef HAVE_XWIDGETS
20552 {
20553 struct xwidget_view *xvw;
20554 Mouse_HLInfo *hlinfo;
20555
20556 xvw = xwidget_view_from_window (event->xcrossing.window);
20557
20558 if (xvw)
20559 {
20560 xwidget_motion_or_crossing (xvw, event);
20561 hlinfo = MOUSE_HL_INFO (xvw->frame);
20562
20563 if (xvw->frame == hlinfo->mouse_face_mouse_frame)
20564 {
20565 clear_mouse_face (hlinfo);
20566 hlinfo->mouse_face_mouse_frame = 0;
20567 x_flush_dirty_back_buffer_on (xvw->frame);
20568 }
20569
20570 if (any_help_event_p)
20571 do_help = -1;
20572
20573 goto OTHER;
20574 }
20575 }
20576 #endif
20577
20578 #ifdef HAVE_XINPUT2
20579
20580
20581
20582
20583
20584
20585
20586 if (dpyinfo->supports_xi2)
20587 goto OTHER;
20588 #endif
20589
20590 if (x_top_window_to_frame (dpyinfo, event->xcrossing.window))
20591 x_detect_focus_change (dpyinfo, any, event, &inev.ie);
20592
20593 f = any;
20594
20595 if (f && event->xcrossing.window == FRAME_X_WINDOW (f))
20596 x_compute_root_window_offset (f, event->xcrossing.x_root,
20597 event->xcrossing.y_root,
20598 event->xcrossing.x,
20599 event->xcrossing.y);
20600
20601
20602
20603
20604
20605 if (f && x_mouse_click_focus_ignore_position)
20606 {
20607 ignore_next_mouse_click_timeout = (event->xmotion.time
20608 + x_mouse_click_focus_ignore_time);
20609 mouse_click_timeout_display = dpyinfo;
20610 }
20611
20612
20613
20614 if (f && !f->output_data.x->hourglass_p)
20615 x_note_mouse_movement (f, &event->xmotion, Qnil);
20616 #ifdef USE_GTK
20617
20618
20619 if (!f && dpyinfo->last_mouse_glyph_frame)
20620 x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &event->xmotion,
20621 Qnil);
20622 #endif
20623 goto OTHER;
20624
20625 case FocusIn:
20626 #if defined HAVE_XINPUT2 \
20627 && (defined HAVE_GTK3 || (!defined USE_GTK && !defined USE_X_TOOLKIT))
20628
20629
20630
20631
20632
20633
20634
20635
20636
20637
20638 if (dpyinfo->supports_xi2)
20639 goto OTHER;
20640 #endif
20641 #ifdef USE_GTK
20642
20643
20644
20645
20646
20647
20648
20649
20650
20651
20652
20653
20654 if (EQ (x_set_frame_visibility_more_laxly, Qfocus_in)
20655 || EQ (x_set_frame_visibility_more_laxly, Qt))
20656 #endif
20657 {
20658 f = any;
20659 if (f && FRAME_ICONIFIED_P (f))
20660 {
20661 SET_FRAME_VISIBLE (f, 1);
20662 SET_FRAME_ICONIFIED (f, false);
20663 f->output_data.x->has_been_visible = true;
20664 inev.ie.kind = DEICONIFY_EVENT;
20665 XSETFRAME (inev.ie.frame_or_window, f);
20666 }
20667 }
20668
20669 x_detect_focus_change (dpyinfo, any, event, &inev.ie);
20670 goto OTHER;
20671
20672 case LeaveNotify:
20673 x_display_set_last_user_time (dpyinfo, event->xcrossing.time,
20674 event->xcrossing.send_event, false);
20675
20676 #ifdef HAVE_XINPUT2
20677
20678
20679
20680
20681
20682
20683
20684 if (dpyinfo->supports_xi2)
20685 {
20686 #if !defined USE_X_TOOLKIT && (!defined USE_GTK || defined HAVE_GTK3)
20687 goto OTHER;
20688 #else
20689
20690
20691
20692
20693
20694
20695
20696 goto just_clear_mouse_face;
20697 #endif
20698 }
20699 #endif
20700
20701 #ifdef HAVE_XWIDGETS
20702 {
20703 struct xwidget_view *xvw;
20704
20705 xvw = xwidget_view_from_window (event->xcrossing.window);
20706
20707 if (xvw)
20708 {
20709 xwidget_motion_or_crossing (xvw, event);
20710 goto OTHER;
20711 }
20712 }
20713 #endif
20714
20715 if (x_top_window_to_frame (dpyinfo, event->xcrossing.window))
20716 x_detect_focus_change (dpyinfo, any, event, &inev.ie);
20717
20718 #if defined HAVE_XINPUT2 \
20719 && (defined USE_X_TOOLKIT || (defined USE_GTK && !defined HAVE_GTK3))
20720 just_clear_mouse_face:
20721 #endif
20722
20723 #if defined USE_X_TOOLKIT
20724
20725
20726 f = x_window_to_frame (dpyinfo, event->xcrossing.window);
20727
20728 if (!f)
20729 f = x_top_window_to_frame (dpyinfo, event->xcrossing.window);
20730 #else
20731 f = x_top_window_to_frame (dpyinfo, event->xcrossing.window);
20732 #endif
20733
20734 if (f)
20735 {
20736
20737
20738
20739
20740
20741 if (f == dpyinfo->last_mouse_motion_frame)
20742 dpyinfo->last_mouse_motion_frame = NULL;
20743
20744
20745
20746 if (f == dpyinfo->last_mouse_glyph_frame)
20747 dpyinfo->last_mouse_glyph_frame = NULL;
20748
20749 if (f == hlinfo->mouse_face_mouse_frame)
20750 {
20751
20752
20753 clear_mouse_face (hlinfo);
20754 hlinfo->mouse_face_mouse_frame = 0;
20755 x_flush_dirty_back_buffer_on (f);
20756 }
20757
20758
20759
20760
20761
20762 if (any_help_event_p
20763
20764
20765
20766 && !((EQ (track_mouse, Qdrag_source)
20767 || EQ (track_mouse, Qdropping))
20768 && gui_mouse_grabbed (dpyinfo)))
20769 do_help = -1;
20770
20771 if (event->xcrossing.window == FRAME_X_WINDOW (f))
20772 x_compute_root_window_offset (f, event->xcrossing.x_root,
20773 event->xcrossing.y_root,
20774 event->xcrossing.x,
20775 event->xcrossing.y);
20776
20777 }
20778 #ifdef USE_GTK
20779
20780 else if (dpyinfo->last_mouse_glyph_frame)
20781 x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame,
20782 &event->xmotion, Qnil);
20783 #endif
20784 goto OTHER;
20785
20786 case FocusOut:
20787 #if defined HAVE_XINPUT2 \
20788 && (defined HAVE_GTK3 || (!defined USE_GTK && !defined USE_X_TOOLKIT))
20789
20790
20791
20792
20793
20794
20795
20796
20797
20798
20799 if (dpyinfo->supports_xi2)
20800 goto OTHER;
20801 #endif
20802 x_detect_focus_change (dpyinfo, any, event, &inev.ie);
20803 goto OTHER;
20804
20805 case MotionNotify:
20806 {
20807 XMotionEvent xmotion = event->xmotion;
20808
20809 previous_help_echo_string = help_echo_string;
20810 help_echo_string = Qnil;
20811
20812 if (hlinfo->mouse_face_hidden)
20813 {
20814 hlinfo->mouse_face_hidden = false;
20815 clear_mouse_face (hlinfo);
20816 }
20817
20818 f = mouse_or_wdesc_frame (dpyinfo, event->xmotion.window);
20819
20820 if (f && event->xmotion.window == FRAME_X_WINDOW (f))
20821
20822
20823 x_compute_root_window_offset (f, event->xmotion.x_root,
20824 event->xmotion.y_root,
20825 event->xmotion.x,
20826 event->xmotion.y);
20827
20828 if (x_dnd_in_progress
20829
20830
20831
20832
20833
20834 && (command_loop_level + minibuf_level
20835 <= x_dnd_recursion_depth)
20836 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
20837 {
20838 Window target, toplevel;
20839 int target_proto, motif_style;
20840 xm_top_level_leave_message lmsg;
20841 xm_top_level_enter_message emsg;
20842 xm_drag_motion_message dmsg;
20843 XRectangle *r;
20844 bool was_frame;
20845
20846
20847 clear_mouse_face (hlinfo);
20848 hlinfo->mouse_face_hidden = true;
20849
20850
20851
20852
20853
20854
20855 if (f)
20856 {
20857 XTtoggle_invisible_pointer (f, false);
20858
20859 r = &dpyinfo->last_mouse_glyph;
20860
20861
20862
20863 if (f != dpyinfo->last_mouse_glyph_frame
20864 || event->xmotion.x < r->x
20865 || event->xmotion.x >= r->x + r->width
20866 || event->xmotion.y < r->y
20867 || event->xmotion.y >= r->y + r->height)
20868 {
20869 f->mouse_moved = true;
20870 f->last_mouse_device = Qnil;
20871 dpyinfo->last_mouse_scroll_bar = NULL;
20872
20873 remember_mouse_glyph (f, event->xmotion.x,
20874 event->xmotion.y, r);
20875 dpyinfo->last_mouse_glyph_frame = f;
20876 }
20877 }
20878
20879 if (event->xmotion.same_screen)
20880 target = x_dnd_get_target_window (dpyinfo,
20881 event->xmotion.x_root,
20882 event->xmotion.y_root,
20883 &target_proto,
20884 &motif_style, &toplevel,
20885 &was_frame);
20886 else
20887 target = x_dnd_fill_empty_target (&target_proto, &motif_style,
20888 &toplevel, &was_frame);
20889
20890 if (toplevel != x_dnd_last_seen_toplevel)
20891 {
20892 if (toplevel != FRAME_OUTER_WINDOW (x_dnd_frame)
20893 && x_dnd_return_frame == 1)
20894 x_dnd_return_frame = 2;
20895
20896 if (x_dnd_return_frame == 2
20897 && x_any_window_to_frame (dpyinfo, toplevel))
20898 {
20899 if (x_dnd_last_seen_window != None
20900 && x_dnd_last_protocol_version != -1
20901 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
20902 x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window,
20903 x_dnd_last_seen_toplevel);
20904 else if (x_dnd_last_seen_window != None
20905 && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
20906 && !x_dnd_disable_motif_drag
20907 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
20908 {
20909 if (!x_dnd_motif_setup_p)
20910 xm_setup_drag_info (dpyinfo, x_dnd_frame);
20911
20912 lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
20913 XM_DRAG_REASON_TOP_LEVEL_LEAVE);
20914 lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
20915 lmsg.zero = 0;
20916 lmsg.timestamp = event->xmotion.time;
20917 lmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
20918
20919 if (x_dnd_motif_setup_p)
20920 xm_send_top_level_leave_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
20921 x_dnd_last_seen_window, &lmsg);
20922 }
20923
20924 x_dnd_end_window = x_dnd_last_seen_window;
20925 x_dnd_last_seen_window = None;
20926 x_dnd_last_seen_toplevel = None;
20927 x_dnd_in_progress = false;
20928 x_dnd_return_frame_object
20929 = x_any_window_to_frame (dpyinfo, toplevel);
20930 x_dnd_return_frame = 3;
20931 x_dnd_waiting_for_finish = false;
20932 target = None;
20933 }
20934 }
20935
20936 if (target != x_dnd_last_seen_window)
20937 {
20938 if (x_dnd_last_seen_window != None
20939 && x_dnd_last_protocol_version != -1
20940 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
20941 x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window,
20942 x_dnd_last_seen_toplevel);
20943 else if (x_dnd_last_seen_window != None
20944 && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
20945 && x_dnd_disable_motif_drag
20946 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
20947 {
20948 if (!x_dnd_motif_setup_p)
20949 xm_setup_drag_info (dpyinfo, x_dnd_frame);
20950
20951
20952
20953
20954
20955
20956
20957 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
20958 XM_DRAG_REASON_DRAG_MOTION);
20959 dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
20960 dmsg.side_effects = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
20961 x_dnd_wanted_action),
20962 XM_DROP_SITE_NONE, x_dnd_motif_operations,
20963 XM_DROP_ACTION_DROP_CANCEL);
20964 dmsg.timestamp = event->xmotion.time;
20965 dmsg.x = event->xmotion.x_root;
20966 dmsg.y = event->xmotion.y_root;
20967
20968 lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
20969 XM_DRAG_REASON_TOP_LEVEL_LEAVE);
20970 lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
20971 lmsg.zero = 0;
20972 lmsg.timestamp = event->xbutton.time;
20973 lmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
20974
20975 if (x_dnd_motif_setup_p)
20976 {
20977 xm_send_drag_motion_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
20978 x_dnd_last_seen_window, &dmsg);
20979 xm_send_top_level_leave_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
20980 x_dnd_last_seen_window, &lmsg);
20981 }
20982 }
20983
20984 x_dnd_action = None;
20985 x_dnd_last_seen_toplevel = toplevel;
20986 x_dnd_last_seen_window = target;
20987 x_dnd_last_protocol_version = target_proto;
20988 x_dnd_last_motif_style = motif_style;
20989 x_dnd_last_window_is_frame = was_frame;
20990
20991 if (target != None && x_dnd_last_protocol_version != -1)
20992 x_dnd_send_enter (x_dnd_frame, target,
20993 x_dnd_last_seen_toplevel,
20994 x_dnd_last_protocol_version);
20995 else if (target != None && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
20996 && !x_dnd_disable_motif_drag)
20997 {
20998 if (!x_dnd_motif_setup_p)
20999 xm_setup_drag_info (dpyinfo, x_dnd_frame);
21000
21001 emsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
21002 XM_DRAG_REASON_TOP_LEVEL_ENTER);
21003 emsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
21004 emsg.zero = 0;
21005 emsg.timestamp = event->xbutton.time;
21006 emsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
21007 emsg.index_atom = x_dnd_motif_atom;
21008
21009 if (x_dnd_motif_setup_p)
21010 xm_send_top_level_enter_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
21011 target, &emsg);
21012 }
21013 }
21014 else
21015 x_dnd_last_seen_toplevel = toplevel;
21016
21017 if (x_dnd_last_window_is_frame && target != None)
21018 x_dnd_note_self_position (dpyinfo, target,
21019 event->xbutton.x_root,
21020 event->xbutton.y_root);
21021 else if (x_dnd_last_protocol_version != -1 && target != None)
21022 x_dnd_send_position (x_dnd_frame, target,
21023 x_dnd_last_seen_toplevel,
21024 x_dnd_last_protocol_version,
21025 event->xmotion.x_root,
21026 event->xmotion.y_root,
21027 x_dnd_selection_timestamp,
21028 x_dnd_wanted_action, 0,
21029 event->xmotion.state);
21030 else if (XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) && target != None
21031 && !x_dnd_disable_motif_drag)
21032 {
21033 if (!x_dnd_motif_setup_p)
21034 xm_setup_drag_info (dpyinfo, x_dnd_frame);
21035
21036 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
21037 XM_DRAG_REASON_DRAG_MOTION);
21038 dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
21039 dmsg.side_effects = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
21040 x_dnd_wanted_action),
21041 XM_DROP_SITE_VALID, x_dnd_motif_operations,
21042 (!x_dnd_xm_use_help
21043 ? XM_DROP_ACTION_DROP
21044 : XM_DROP_ACTION_DROP_HELP));
21045 dmsg.timestamp = event->xbutton.time;
21046 dmsg.x = event->xmotion.x_root;
21047 dmsg.y = event->xmotion.y_root;
21048
21049 if (x_dnd_motif_setup_p)
21050 xm_send_drag_motion_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
21051 target, &dmsg);
21052 }
21053
21054 x_dnd_update_tooltip_position (event->xmotion.x_root,
21055 event->xmotion.y_root);
21056
21057 goto OTHER;
21058 }
21059
21060 #ifdef USE_GTK
21061 if (f && xg_event_is_for_scrollbar (f, event, false))
21062 f = 0;
21063 #endif
21064 #ifdef HAVE_XWIDGETS
21065 struct xwidget_view *xvw;
21066
21067 xvw = xwidget_view_from_window (event->xmotion.window);
21068
21069 if (xvw)
21070 xwidget_motion_or_crossing (xvw, event);
21071 #endif
21072 if (f)
21073 {
21074
21075
21076
21077 if (!NILP (Vmouse_autoselect_window)
21078 && !popup_activated ()
21079
21080
21081
21082
21083
21084 && !MINI_WINDOW_P (XWINDOW (selected_window))
21085
21086
21087 && (f == XFRAME (selected_frame)
21088 || !NILP (focus_follows_mouse)))
21089 {
21090 static Lisp_Object last_mouse_window;
21091
21092 if (xmotion.window != FRAME_X_WINDOW (f))
21093 {
21094 x_translate_coordinates (f, xmotion.x_root, xmotion.y_root,
21095 &xmotion.x, &xmotion.y);
21096 xmotion.window = FRAME_X_WINDOW (f);
21097 }
21098
21099 Lisp_Object window = window_from_coordinates
21100 (f, xmotion.x, xmotion.y, 0, false, false);
21101
21102
21103
21104
21105
21106
21107
21108
21109
21110 if (WINDOWP (window)
21111 && !EQ (window, last_mouse_window)
21112 && !EQ (window, selected_window))
21113 {
21114 inev.ie.kind = SELECT_WINDOW_EVENT;
21115 inev.ie.frame_or_window = window;
21116 }
21117
21118
21119 last_mouse_window = window;
21120 }
21121
21122 if (!x_note_mouse_movement (f, &xmotion, Qnil))
21123 help_echo_string = previous_help_echo_string;
21124 }
21125 else
21126 {
21127 #ifndef USE_TOOLKIT_SCROLL_BARS
21128 struct scroll_bar *bar
21129 = x_window_to_scroll_bar (event->xmotion.display,
21130 event->xmotion.window, 2);
21131
21132 if (bar)
21133 x_scroll_bar_note_movement (bar, &event->xmotion);
21134 #endif
21135
21136
21137
21138 clear_mouse_face (hlinfo);
21139 }
21140
21141
21142
21143 if (!NILP (help_echo_string)
21144 || !NILP (previous_help_echo_string))
21145 do_help = 1;
21146
21147 if (f)
21148 x_flush_dirty_back_buffer_on (f);
21149 goto OTHER;
21150 }
21151
21152 case ConfigureNotify:
21153
21154
21155
21156
21157
21158
21159
21160
21161
21162
21163
21164
21165 configureEvent = *event;
21166 while (XPending (dpyinfo->display))
21167 {
21168 XNextEvent (dpyinfo->display, &next_event);
21169 if (next_event.type != ConfigureNotify
21170 || next_event.xconfigure.window != event->xconfigure.window
21171
21172
21173
21174 || next_event.xconfigure.width != event->xconfigure.width
21175 || next_event.xconfigure.height != event->xconfigure.height)
21176 {
21177 XPutBackEvent (dpyinfo->display, &next_event);
21178 break;
21179 }
21180 else
21181 configureEvent = next_event;
21182 }
21183
21184
21185
21186
21187 if (configureEvent.xconfigure.window == dpyinfo->root_window)
21188 {
21189 #ifdef HAVE_XRANDR
21190
21191
21192 XRRUpdateConfiguration (&configureEvent);
21193 #elif !defined USE_GTK
21194
21195
21196
21197 if (configureEvent.xconfigure.width != dpyinfo->screen_width
21198 || configureEvent.xconfigure.height != dpyinfo->screen_height)
21199 {
21200
21201
21202
21203
21204 if (!x_find_monitors_changed_event (dpyinfo))
21205 {
21206 inev.ie.kind = MONITORS_CHANGED_EVENT;
21207 XSETTERMINAL (inev.ie.arg, dpyinfo->terminal);
21208
21209
21210
21211 kbd_buffer_store_event (&inev.ie);
21212 inev.ie.kind = NO_EVENT;
21213 }
21214
21215
21216
21217 x_dnd_update_tooltip_now ();
21218 }
21219 #endif
21220
21221 dpyinfo->screen_width = configureEvent.xconfigure.width;
21222 dpyinfo->screen_height = configureEvent.xconfigure.height;
21223 }
21224
21225 if (x_dnd_in_progress && x_dnd_use_toplevels
21226 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
21227 {
21228 int rc, dest_x, dest_y;
21229 Window child;
21230 struct x_client_list_window *tem, *last = NULL;
21231
21232 for (tem = x_dnd_toplevels; tem; last = tem, tem = tem->next)
21233 {
21234
21235
21236
21237 if (tem->window == configureEvent.xconfigure.window)
21238 {
21239 x_catch_errors (dpyinfo->display);
21240 rc = (XTranslateCoordinates (dpyinfo->display,
21241 configureEvent.xconfigure.window,
21242 dpyinfo->root_window,
21243 -configureEvent.xconfigure.border_width,
21244 -configureEvent.xconfigure.border_width,
21245 &dest_x, &dest_y, &child)
21246 && !x_had_errors_p (dpyinfo->display));
21247 x_uncatch_errors_after_check ();
21248
21249 if (rc)
21250 {
21251 tem->x = dest_x;
21252 tem->y = dest_y;
21253 tem->width = (configureEvent.xconfigure.width
21254 + configureEvent.xconfigure.border_width);
21255 tem->height = (configureEvent.xconfigure.height
21256 + configureEvent.xconfigure.border_width);
21257 }
21258 else
21259 {
21260
21261
21262
21263 if (!last)
21264 x_dnd_toplevels = tem->next;
21265 else
21266 last->next = tem->next;
21267
21268 #ifdef HAVE_XSHAPE
21269 if (tem->n_input_rects != -1)
21270 xfree (tem->input_rects);
21271 if (tem->n_bounding_rects != -1)
21272 xfree (tem->bounding_rects);
21273 #endif
21274 xfree (tem);
21275 }
21276
21277 break;
21278 }
21279 }
21280 }
21281
21282 #if defined HAVE_GTK3 && defined USE_TOOLKIT_SCROLL_BARS
21283 struct scroll_bar *bar = x_window_to_scroll_bar (dpyinfo->display,
21284 configureEvent.xconfigure.window, 2);
21285
21286
21287
21288 if (bar)
21289 {
21290
21291
21292 while (XPending (dpyinfo->display))
21293 {
21294 XNextEvent (dpyinfo->display, &next_event);
21295 if (next_event.type != ConfigureNotify
21296 || next_event.xconfigure.window != event->xconfigure.window)
21297 {
21298 XPutBackEvent (dpyinfo->display, &next_event);
21299 break;
21300 }
21301 else
21302 configureEvent = next_event;
21303 }
21304
21305 if (configureEvent.xconfigure.width != max (bar->width, 1)
21306 || configureEvent.xconfigure.height != max (bar->height, 1))
21307 {
21308 XResizeWindow (dpyinfo->display, bar->x_window,
21309 max (bar->width, 1), max (bar->height, 1));
21310 x_flush (WINDOW_XFRAME (XWINDOW (bar->window)));
21311 }
21312
21313 #ifdef HAVE_XDBE
21314 if (f && FRAME_X_DOUBLE_BUFFERED_P (f))
21315 x_drop_xrender_surfaces (f);
21316 #endif
21317
21318 goto OTHER;
21319 }
21320 #endif
21321
21322 f = x_top_window_to_frame (dpyinfo, configureEvent.xconfigure.window);
21323
21324
21325
21326 if (any)
21327 FRAME_X_OUTPUT (any)->window_offset_certain_p = false;
21328
21329
21330
21331
21332
21333
21334 #ifdef HAVE_XDBE
21335 if (f && FRAME_X_DOUBLE_BUFFERED_P (f))
21336 x_drop_xrender_surfaces (f);
21337 #endif
21338 #if defined USE_CAIRO && !defined USE_GTK
21339 if (f)
21340 x_cr_update_surface_desired_size (f, configureEvent.xconfigure.width,
21341 configureEvent.xconfigure.height);
21342 else if (any && configureEvent.xconfigure.window == FRAME_X_WINDOW (any))
21343 x_cr_update_surface_desired_size (any,
21344 configureEvent.xconfigure.width,
21345 configureEvent.xconfigure.height);
21346 #endif
21347
21348 #if !defined USE_X_TOOLKIT && !defined USE_GTK
21349
21350
21351
21352
21353
21354
21355
21356
21357 if (f || (any && configureEvent.xconfigure.window
21358 == FRAME_OUTER_WINDOW (any)))
21359 x_update_opaque_region (f ? f : any, &configureEvent);
21360
21361 #endif
21362
21363 #ifdef USE_GTK
21364 if (!f
21365 && (f = any)
21366 && configureEvent.xconfigure.window == FRAME_X_WINDOW (f)
21367 && (FRAME_VISIBLE_P (f)
21368 || !(configureEvent.xconfigure.width <= 1
21369 && configureEvent.xconfigure.height <= 1)))
21370 {
21371
21372 if (CONSP (frame_size_history))
21373 frame_size_history_extra
21374 (f, build_string ("ConfigureNotify"),
21375 FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f),
21376 configureEvent.xconfigure.width,
21377 configureEvent.xconfigure.height,
21378 f->new_width, f->new_height);
21379
21380 #ifdef HAVE_XDBE
21381 if (FRAME_X_DOUBLE_BUFFERED_P (f))
21382 x_drop_xrender_surfaces (f);
21383 #endif
21384 xg_frame_resized (f, configureEvent.xconfigure.width,
21385 configureEvent.xconfigure.height);
21386 #ifdef USE_CAIRO
21387 x_cr_update_surface_desired_size (f, configureEvent.xconfigure.width,
21388 configureEvent.xconfigure.height);
21389 #endif
21390 x_update_opaque_region (f, &configureEvent);
21391 f = 0;
21392 }
21393 #endif
21394 if (f && (FRAME_VISIBLE_P (f)
21395 || !(configureEvent.xconfigure.width <= 1
21396 && configureEvent.xconfigure.height <= 1)))
21397 {
21398 #ifdef USE_GTK
21399
21400
21401 if (configureEvent.xconfigure.window == FRAME_X_WINDOW (f))
21402 #endif
21403 x_net_wm_state (f, configureEvent.xconfigure.window);
21404
21405 #if defined USE_X_TOOLKIT || defined USE_GTK
21406
21407 if (FRAME_TOOLTIP_P (f))
21408 {
21409 if (FRAME_PIXEL_HEIGHT (f) != configureEvent.xconfigure.height
21410 || FRAME_PIXEL_WIDTH (f) != configureEvent.xconfigure.width)
21411 SET_FRAME_GARBAGED (f);
21412
21413 FRAME_PIXEL_HEIGHT (f) = configureEvent.xconfigure.height;
21414 FRAME_PIXEL_WIDTH (f) = configureEvent.xconfigure.width;
21415 }
21416 #endif
21417
21418 #ifndef USE_X_TOOLKIT
21419 #ifndef USE_GTK
21420 int width = configureEvent.xconfigure.width;
21421 int height = configureEvent.xconfigure.height;
21422
21423 if (CONSP (frame_size_history))
21424 frame_size_history_extra
21425 (f, build_string ("ConfigureNotify"),
21426 FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f),
21427 width, height, f->new_width, f->new_height);
21428
21429
21430
21431
21432
21433
21434
21435
21436
21437 if (width != FRAME_PIXEL_WIDTH (f)
21438 || height != FRAME_PIXEL_HEIGHT (f)
21439 || (f->new_size_p
21440 && ((f->new_width >= 0 && width != f->new_width)
21441 || (f->new_height >= 0 && height != f->new_height))))
21442 {
21443 change_frame_size (f, width, height, false, true, false);
21444 x_clear_under_internal_border (f);
21445 SET_FRAME_GARBAGED (f);
21446 cancel_mouse_face (f);
21447 }
21448 #endif
21449 #endif
21450
21451 #ifdef USE_GTK
21452
21453
21454 if (FRAME_GTK_OUTER_WIDGET (f)
21455 && gtk_widget_get_mapped (FRAME_GTK_OUTER_WIDGET (f)))
21456 #endif
21457 {
21458 int old_left = f->left_pos;
21459 int old_top = f->top_pos;
21460 Lisp_Object frame;
21461
21462 XSETFRAME (frame, f);
21463
21464 if (!FRAME_PARENT_FRAME (f))
21465 x_real_positions (f, &f->left_pos, &f->top_pos);
21466 else
21467 {
21468 Window root;
21469 unsigned int dummy_uint;
21470
21471 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
21472 &root, &f->left_pos, &f->top_pos,
21473 &dummy_uint, &dummy_uint, &dummy_uint, &dummy_uint);
21474 }
21475
21476 if (!FRAME_TOOLTIP_P (f)
21477 && (old_left != f->left_pos || old_top != f->top_pos))
21478 {
21479 inev.ie.kind = MOVE_FRAME_EVENT;
21480 XSETFRAME (inev.ie.frame_or_window, f);
21481 }
21482 }
21483
21484
21485 #ifdef HAVE_X_I18N
21486 if (f)
21487 {
21488 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
21489 xic_set_statusarea (f);
21490
21491 struct window *w = XWINDOW (f->selected_window);
21492 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
21493 }
21494 #endif
21495
21496 #ifdef HAVE_XINPUT2
21497 if (f && dpyinfo->supports_xi2)
21498 {
21499 Mouse_HLInfo *hlinfo;
21500
21501
21502
21503
21504
21505
21506
21507
21508 if (dpyinfo->last_mouse_motion_frame == f)
21509 dpyinfo->last_mouse_motion_frame = NULL;
21510
21511 hlinfo = MOUSE_HL_INFO (f);
21512
21513 if (hlinfo->mouse_face_mouse_frame == f)
21514 reset_mouse_highlight (hlinfo);
21515 }
21516 #endif
21517
21518 }
21519
21520 if (x_dnd_in_progress
21521 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
21522 x_dnd_update_state (dpyinfo, dpyinfo->last_user_time);
21523 goto OTHER;
21524
21525 case ButtonRelease:
21526 case ButtonPress:
21527 {
21528 if (event->xbutton.type == ButtonPress)
21529 x_display_set_last_user_time (dpyinfo, event->xbutton.time,
21530 event->xbutton.send_event, true);
21531
21532 #ifdef HAVE_XWIDGETS
21533 struct xwidget_view *xvw;
21534
21535 xvw = xwidget_view_from_window (event->xbutton.window);
21536
21537 if (xvw)
21538 {
21539 xwidget_button (xvw, event->type == ButtonPress,
21540 event->xbutton.x, event->xbutton.y,
21541 event->xbutton.button, event->xbutton.state,
21542 event->xbutton.time);
21543
21544 if (!EQ (selected_window, xvw->w) && (event->xbutton.button < 4))
21545 {
21546 inev.ie.kind = SELECT_WINDOW_EVENT;
21547 inev.ie.frame_or_window = xvw->w;
21548 }
21549
21550 *finish = X_EVENT_DROP;
21551 goto OTHER;
21552 }
21553 #endif
21554
21555
21556 Lisp_Object tab_bar_arg = Qnil;
21557 bool tab_bar_p = false;
21558 bool tool_bar_p = false;
21559 bool dnd_grab = false;
21560
21561 if (x_dnd_in_progress
21562
21563
21564
21565
21566
21567 && (command_loop_level + minibuf_level
21568 <= x_dnd_recursion_depth)
21569 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
21570 {
21571 f = mouse_or_wdesc_frame (dpyinfo, event->xbutton.window);
21572
21573 if (f && event->xbutton.window == FRAME_X_WINDOW (f))
21574
21575
21576 x_compute_root_window_offset (f, event->xbutton.x_root,
21577 event->xbutton.y_root,
21578 event->xbutton.x,
21579 event->xbutton.y);
21580
21581 if (event->type == ButtonPress)
21582 {
21583 x_display_set_last_user_time (dpyinfo, event->xbutton.time,
21584 event->xbutton.send_event, true);
21585
21586 dpyinfo->grabbed |= (1 << event->xbutton.button);
21587 dpyinfo->last_mouse_frame = f;
21588
21589 if (f)
21590 f->last_tab_bar_item = -1;
21591 #if ! defined (USE_GTK)
21592 if (f)
21593 f->last_tool_bar_item = -1;
21594 #endif
21595 }
21596 else
21597 dpyinfo->grabbed &= ~(1 << event->xbutton.button);
21598
21599 if (event->xbutton.type == ButtonPress
21600 && x_dnd_last_seen_window != None)
21601 {
21602 if (x_dnd_last_window_is_frame)
21603 x_dnd_note_self_wheel (dpyinfo,
21604 x_dnd_last_seen_window,
21605 event->xbutton.x_root,
21606 event->xbutton.y_root,
21607 event->xbutton.button,
21608 event->xbutton.state,
21609 event->xbutton.time);
21610 else if (x_dnd_last_protocol_version != -1)
21611 x_dnd_send_position (x_dnd_frame,
21612 x_dnd_last_seen_window,
21613 x_dnd_last_seen_toplevel,
21614 x_dnd_last_protocol_version,
21615 event->xbutton.x_root,
21616 event->xbutton.y_root,
21617 event->xbutton.time,
21618 x_dnd_wanted_action,
21619 event->xbutton.button,
21620 event->xbutton.state);
21621
21622 goto OTHER;
21623 }
21624
21625 if (event->xbutton.type == ButtonRelease)
21626 {
21627 for (int i = 1; i < 8; ++i)
21628 {
21629 if (i != event->xbutton.button
21630 && event->xbutton.state & (Button1Mask << (i - 1)))
21631 dnd_grab = true;
21632 }
21633
21634 if (!dnd_grab)
21635 {
21636 x_dnd_end_window = x_dnd_last_seen_window;
21637 x_dnd_in_progress = false;
21638
21639 if (x_dnd_update_tooltip
21640 && FRAMEP (tip_frame)
21641 && FRAME_LIVE_P (XFRAME (tip_frame))
21642 && (FRAME_X_DISPLAY (XFRAME (tip_frame))
21643 == FRAME_X_DISPLAY (x_dnd_frame)))
21644 Fx_hide_tip ();
21645
21646 x_dnd_finish_frame = x_dnd_frame;
21647
21648 if (x_dnd_last_seen_window != None
21649 && x_dnd_last_window_is_frame)
21650 {
21651 x_dnd_waiting_for_finish = false;
21652 x_dnd_note_self_drop (dpyinfo,
21653 x_dnd_last_seen_window,
21654 event->xbutton.x_root,
21655 event->xbutton.y_root,
21656 event->xbutton.time);
21657 }
21658 else if (x_dnd_last_seen_window != None
21659 && x_dnd_last_protocol_version != -1)
21660 {
21661 x_dnd_pending_finish_target = x_dnd_last_seen_toplevel;
21662 x_dnd_waiting_for_finish_proto = x_dnd_last_protocol_version;
21663
21664 x_dnd_waiting_for_finish
21665 = x_dnd_do_drop (x_dnd_last_seen_window,
21666 x_dnd_last_seen_toplevel,
21667 x_dnd_last_protocol_version);
21668 x_dnd_finish_display = dpyinfo->display;
21669 }
21670 else if (x_dnd_last_seen_window != None)
21671 {
21672 xm_drop_start_message dmsg;
21673 xm_drag_receiver_info drag_receiver_info;
21674
21675 if (!xm_read_drag_receiver_info (dpyinfo, x_dnd_last_seen_window,
21676 &drag_receiver_info)
21677 && !x_dnd_disable_motif_protocol
21678 && drag_receiver_info.protocol_style != XM_DRAG_STYLE_NONE
21679 && (x_dnd_allow_current_frame
21680 || x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame)))
21681 {
21682 if (!x_dnd_motif_setup_p)
21683 xm_setup_drag_info (dpyinfo, x_dnd_frame);
21684
21685 if (x_dnd_motif_setup_p)
21686 {
21687 memset (&dmsg, 0, sizeof dmsg);
21688
21689 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
21690 XM_DRAG_REASON_DROP_START);
21691 dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST;
21692 dmsg.side_effects
21693 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
21694 x_dnd_wanted_action),
21695 XM_DROP_SITE_VALID, x_dnd_motif_operations,
21696 (!x_dnd_xm_use_help
21697 ? XM_DROP_ACTION_DROP
21698 : XM_DROP_ACTION_DROP_HELP));
21699 dmsg.timestamp = event->xbutton.time;
21700 dmsg.x = event->xbutton.x_root;
21701 dmsg.y = event->xbutton.y_root;
21702 dmsg.index_atom = x_dnd_motif_atom;
21703 dmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
21704
21705 if (!XM_DRAG_STYLE_IS_DROP_ONLY (drag_receiver_info.protocol_style))
21706 x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (x_dnd_frame),
21707 x_dnd_frame, x_dnd_last_seen_window,
21708 event->xbutton.time);
21709
21710 xm_send_drop_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
21711 x_dnd_last_seen_window, &dmsg);
21712
21713 x_dnd_waiting_for_finish = true;
21714 x_dnd_waiting_for_motif_finish_display = dpyinfo;
21715 x_dnd_waiting_for_motif_finish = 1;
21716 x_dnd_finish_display = dpyinfo->display;
21717 }
21718 }
21719 else
21720 x_dnd_send_unsupported_drop (dpyinfo, (x_dnd_last_seen_toplevel != None
21721 ? x_dnd_last_seen_toplevel
21722 : x_dnd_last_seen_window),
21723 event->xbutton.x_root, event->xbutton.y_root,
21724 event->xbutton.time);
21725 }
21726 else if (x_dnd_last_seen_toplevel != None)
21727 x_dnd_send_unsupported_drop (dpyinfo, x_dnd_last_seen_toplevel,
21728 event->xbutton.x_root,
21729 event->xbutton.y_root,
21730 event->xbutton.time);
21731
21732
21733 x_dnd_last_protocol_version = -1;
21734 x_dnd_last_motif_style = XM_DRAG_STYLE_NONE;
21735 x_dnd_last_seen_window = None;
21736 x_dnd_last_seen_toplevel = None;
21737 x_dnd_last_window_is_frame = false;
21738 x_dnd_frame = NULL;
21739 }
21740 }
21741
21742 goto OTHER;
21743 }
21744
21745 if (x_dnd_in_progress
21746 && (command_loop_level + minibuf_level
21747 <= x_dnd_recursion_depth))
21748 goto OTHER;
21749
21750 memset (&compose_status, 0, sizeof (compose_status));
21751 dpyinfo->last_mouse_glyph_frame = NULL;
21752
21753 f = mouse_or_wdesc_frame (dpyinfo, event->xbutton.window);
21754
21755 if (f && event->xbutton.window == FRAME_X_WINDOW (f))
21756
21757
21758 x_compute_root_window_offset (f, event->xbutton.x_root,
21759 event->xbutton.y_root,
21760 event->xbutton.x,
21761 event->xbutton.y);
21762
21763 if (f && event->xbutton.type == ButtonPress
21764 && !popup_activated ()
21765 && !x_window_to_scroll_bar (event->xbutton.display,
21766 event->xbutton.window, 2)
21767 && !FRAME_NO_ACCEPT_FOCUS (f))
21768 {
21769
21770
21771
21772
21773 struct frame *hf = dpyinfo->highlight_frame;
21774
21775 if (FRAME_PARENT_FRAME (f) || (hf && frame_ancestor_p (f, hf)))
21776 {
21777 x_ignore_errors_for_next_request (dpyinfo, 0);
21778 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
21779 RevertToParent, event->xbutton.time);
21780 x_stop_ignoring_errors (dpyinfo);
21781
21782 if (FRAME_PARENT_FRAME (f))
21783 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
21784 }
21785 }
21786
21787 #ifdef USE_GTK
21788 if (!f)
21789 {
21790 f = x_any_window_to_frame (dpyinfo, event->xbutton.window);
21791
21792 if (event->xbutton.button > 3
21793 && event->xbutton.button < 8
21794 && f)
21795 {
21796 if (ignore_next_mouse_click_timeout
21797 && dpyinfo == mouse_click_timeout_display)
21798 {
21799 if (event->type == ButtonPress
21800 && event->xbutton.time > ignore_next_mouse_click_timeout)
21801 {
21802 ignore_next_mouse_click_timeout = 0;
21803 x_construct_mouse_click (&inev.ie, &event->xbutton, f);
21804 }
21805 if (event->type == ButtonRelease)
21806 ignore_next_mouse_click_timeout = 0;
21807 }
21808 else
21809 x_construct_mouse_click (&inev.ie, &event->xbutton, f);
21810
21811 *finish = X_EVENT_DROP;
21812 goto OTHER;
21813 }
21814 else
21815 f = NULL;
21816 }
21817
21818 if (f && xg_event_is_for_scrollbar (f, event, false))
21819 f = 0;
21820 #endif
21821 if (f)
21822 {
21823
21824 if (WINDOWP (f->tab_bar_window)
21825 && WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window)))
21826 {
21827 Lisp_Object window;
21828 int x = event->xbutton.x;
21829 int y = event->xbutton.y;
21830
21831 window = window_from_coordinates (f, x, y, 0, true, true);
21832 tab_bar_p = EQ (window, f->tab_bar_window);
21833
21834 if (tab_bar_p)
21835 {
21836 tab_bar_arg = handle_tab_bar_click
21837 (f, x, y, event->xbutton.type == ButtonPress,
21838 x_x_to_emacs_modifiers (dpyinfo, event->xbutton.state));
21839 x_flush_dirty_back_buffer_on (f);
21840 }
21841 }
21842
21843 #if ! defined (USE_GTK)
21844
21845 if (WINDOWP (f->tool_bar_window)
21846 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
21847 {
21848 Lisp_Object window;
21849 int x = event->xbutton.x;
21850 int y = event->xbutton.y;
21851
21852 window = window_from_coordinates (f, x, y, 0, true, true);
21853 tool_bar_p = (EQ (window, f->tool_bar_window)
21854 && (event->xbutton.type != ButtonRelease
21855 || f->last_tool_bar_item != -1));
21856
21857 if (tool_bar_p && event->xbutton.button < 4)
21858 {
21859 handle_tool_bar_click
21860 (f, x, y, event->xbutton.type == ButtonPress,
21861 x_x_to_emacs_modifiers (dpyinfo, event->xbutton.state));
21862 x_flush_dirty_back_buffer_on (f);
21863 }
21864 }
21865 #endif
21866
21867 if (!(tab_bar_p && NILP (tab_bar_arg)) && !tool_bar_p)
21868 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
21869 if (! popup_activated ())
21870 #endif
21871 {
21872 if (ignore_next_mouse_click_timeout
21873 && dpyinfo == mouse_click_timeout_display)
21874 {
21875 if (event->type == ButtonPress
21876 && event->xbutton.time > ignore_next_mouse_click_timeout)
21877 {
21878 ignore_next_mouse_click_timeout = 0;
21879 x_construct_mouse_click (&inev.ie, &event->xbutton, f);
21880 }
21881 if (event->type == ButtonRelease)
21882 ignore_next_mouse_click_timeout = 0;
21883 }
21884 else
21885 x_construct_mouse_click (&inev.ie, &event->xbutton, f);
21886
21887 if (!NILP (tab_bar_arg))
21888 inev.ie.arg = tab_bar_arg;
21889 }
21890
21891 if (FRAME_X_EMBEDDED_P (f)
21892 && !FRAME_NO_ACCEPT_FOCUS (f))
21893 xembed_send_message (f, event->xbutton.time,
21894 XEMBED_REQUEST_FOCUS, 0, 0, 0);
21895 }
21896 else
21897 {
21898 struct scroll_bar *bar
21899 = x_window_to_scroll_bar (event->xbutton.display,
21900 event->xbutton.window, 2);
21901
21902 #ifdef USE_TOOLKIT_SCROLL_BARS
21903
21904
21905 if (bar && event->xbutton.state & ControlMask)
21906 {
21907 x_scroll_bar_handle_click (bar, event, &inev.ie, Qnil);
21908 *finish = X_EVENT_DROP;
21909 }
21910 #else
21911 if (bar)
21912 x_scroll_bar_handle_click (bar, event, &inev.ie, Qnil);
21913 #endif
21914 }
21915
21916 if (event->type == ButtonPress)
21917 {
21918 dpyinfo->grabbed |= (1 << event->xbutton.button);
21919 dpyinfo->last_mouse_frame = f;
21920 if (f && !tab_bar_p)
21921 f->last_tab_bar_item = -1;
21922 #if ! defined (USE_GTK)
21923 if (f && !tool_bar_p)
21924 f->last_tool_bar_item = -1;
21925 #endif
21926 }
21927 else
21928 dpyinfo->grabbed &= ~(1 << event->xbutton.button);
21929
21930
21931
21932
21933 if (f != 0)
21934 f->mouse_moved = false;
21935
21936 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
21937 f = x_menubar_window_to_frame (dpyinfo, event);
21938
21939
21940
21941
21942 if (! popup_activated ()
21943 #ifdef USE_GTK
21944
21945 && event->xbutton.button < 3
21946 #endif
21947 && f && event->type == ButtonPress
21948
21949
21950 && event->xbutton.x >= 0
21951 && event->xbutton.x < FRAME_PIXEL_WIDTH (f)
21952 && event->xbutton.y >= 0
21953 && event->xbutton.y < FRAME_MENUBAR_HEIGHT (f)
21954 && event->xbutton.same_screen)
21955 {
21956 #ifdef USE_MOTIF
21957 Widget widget;
21958
21959 widget = XtWindowToWidget (dpyinfo->display,
21960 event->xbutton.window);
21961
21962 if (widget && XmIsCascadeButton (widget)
21963 && XtIsSensitive (widget))
21964 {
21965 #endif
21966 if (!f->output_data.x->saved_menu_event)
21967 f->output_data.x->saved_menu_event = xmalloc (sizeof *event);
21968 *f->output_data.x->saved_menu_event = *event;
21969 inev.ie.kind = MENU_BAR_ACTIVATE_EVENT;
21970 XSETFRAME (inev.ie.frame_or_window, f);
21971 *finish = X_EVENT_DROP;
21972 #ifdef USE_MOTIF
21973 }
21974 #endif
21975 }
21976 else
21977 goto OTHER;
21978 #endif
21979 }
21980 break;
21981
21982 case CirculateNotify:
21983 if (x_dnd_in_progress
21984
21985
21986
21987
21988 && !x_dnd_use_toplevels
21989 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
21990 x_dnd_update_state (dpyinfo, dpyinfo->last_user_time);
21991 goto OTHER;
21992
21993 case CirculateRequest:
21994 goto OTHER;
21995
21996 case VisibilityNotify:
21997 f = x_top_window_to_frame (dpyinfo, event->xvisibility.window);
21998
21999 if (f)
22000 FRAME_X_OUTPUT (f)->visibility_state = event->xvisibility.state;
22001
22002 goto OTHER;
22003
22004 case MappingNotify:
22005
22006
22007 switch (event->xmapping.request)
22008 {
22009 case MappingModifier:
22010 x_find_modifier_meanings (dpyinfo);
22011 FALLTHROUGH;
22012 case MappingKeyboard:
22013 XRefreshKeyboardMapping ((XMappingEvent *) &event->xmapping);
22014 }
22015 goto OTHER;
22016
22017 case DestroyNotify:
22018 if (event->xdestroywindow.window
22019 == dpyinfo->net_supported_window)
22020 dpyinfo->net_supported_window = None;
22021
22022 if (event->xdestroywindow.window
22023 == dpyinfo->motif_drag_window)
22024
22025
22026
22027
22028
22029 dpyinfo->motif_drag_window = None;
22030
22031 xft_settings_event (dpyinfo, event);
22032 break;
22033
22034 #ifdef HAVE_XINPUT2
22035 case GenericEvent:
22036 {
22037 if (!dpyinfo->supports_xi2)
22038 goto OTHER;
22039
22040 if (event->xgeneric.extension != dpyinfo->xi2_opcode)
22041
22042 goto OTHER;
22043
22044 bool must_free_data = false;
22045 XIEvent *xi_event = (XIEvent *) event->xcookie.data;
22046
22047
22048
22049 if (!xi_event)
22050 {
22051 if (XGetEventData (dpyinfo->display, &event->xcookie))
22052 must_free_data = true;
22053
22054 xi_event = (XIEvent *) event->xcookie.data;
22055 }
22056
22057 XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
22058
22059 if (!xi_event)
22060 {
22061
22062
22063
22064
22065
22066
22067
22068
22069
22070
22071
22072
22073
22074
22075
22076
22077
22078 if (must_free_data)
22079 XFreeEventData (dpyinfo->display, &event->xcookie);
22080 goto OTHER;
22081 }
22082
22083 switch (event->xcookie.evtype)
22084 {
22085 case XI_FocusIn:
22086 {
22087 XIFocusInEvent *focusin;
22088
22089 focusin = (XIFocusInEvent *) xi_event;
22090 any = x_any_window_to_frame (dpyinfo, focusin->event);
22091
22092 #ifdef USE_GTK
22093
22094
22095
22096
22097
22098
22099
22100
22101
22102
22103
22104
22105 if (EQ (x_set_frame_visibility_more_laxly, Qfocus_in)
22106 || EQ (x_set_frame_visibility_more_laxly, Qt))
22107 #endif
22108 {
22109 f = any;
22110 if (f && FRAME_ICONIFIED_P (f))
22111 {
22112 SET_FRAME_VISIBLE (f, 1);
22113 SET_FRAME_ICONIFIED (f, false);
22114 f->output_data.x->has_been_visible = true;
22115 inev.ie.kind = DEICONIFY_EVENT;
22116 XSETFRAME (inev.ie.frame_or_window, f);
22117 }
22118 }
22119
22120 xi_focus_handle_for_device (dpyinfo, any, xi_event);
22121
22122 goto XI_OTHER;
22123 }
22124
22125 case XI_FocusOut:
22126 {
22127 XIFocusOutEvent *focusout;
22128
22129 focusout = (XIFocusOutEvent *) xi_event;
22130 any = x_any_window_to_frame (dpyinfo, focusout->event);
22131 xi_focus_handle_for_device (dpyinfo, any, xi_event);
22132
22133 goto XI_OTHER;
22134 }
22135
22136 case XI_Enter:
22137 {
22138 XIEnterEvent *enter = (XIEnterEvent *) xi_event;
22139 XMotionEvent ev;
22140 struct xi_device_t *source;
22141
22142 any = x_top_window_to_frame (dpyinfo, enter->event);
22143 source = xi_device_from_id (dpyinfo, enter->sourceid);
22144
22145 ev.x = lrint (enter->event_x);
22146 ev.y = lrint (enter->event_y);
22147 ev.window = enter->event;
22148 ev.time = enter->time;
22149 ev.send_event = enter->send_event;
22150
22151 x_display_set_last_user_time (dpyinfo, enter->time,
22152 enter->send_event, false);
22153
22154 #ifdef USE_MOTIF
22155 use_copy = true;
22156
22157 copy.xcrossing.type = EnterNotify;
22158 copy.xcrossing.serial = enter->serial;
22159 copy.xcrossing.send_event = enter->send_event;
22160 copy.xcrossing.display = dpyinfo->display;
22161 copy.xcrossing.window = enter->event;
22162 copy.xcrossing.root = enter->root;
22163 copy.xcrossing.subwindow = enter->child;
22164 copy.xcrossing.time = enter->time;
22165 copy.xcrossing.x = lrint (enter->event_x);
22166 copy.xcrossing.y = lrint (enter->event_y);
22167 copy.xcrossing.x_root = lrint (enter->root_x);
22168 copy.xcrossing.y_root = lrint (enter->root_y);
22169 copy.xcrossing.mode = enter->mode;
22170 copy.xcrossing.detail = enter->detail;
22171 copy.xcrossing.focus = enter->focus;
22172 copy.xcrossing.state = 0;
22173 copy.xcrossing.same_screen = True;
22174 #endif
22175
22176
22177
22178
22179
22180 if (any)
22181 xi_focus_handle_for_device (dpyinfo, any, xi_event);
22182
22183 if (!any)
22184 any = x_any_window_to_frame (dpyinfo, enter->event);
22185
22186 #ifdef HAVE_XINPUT2_1
22187
22188
22189
22190
22191
22192
22193
22194
22195
22196 if (enter->mode != XINotifyUngrab
22197 && enter->mode != XINotifyGrab
22198 && enter->mode != XINotifyPassiveGrab
22199 && enter->mode != XINotifyPassiveUngrab)
22200 xi_reset_scroll_valuators_for_device_id (dpyinfo,
22201 enter->deviceid);
22202 #endif
22203
22204 {
22205 #ifdef HAVE_XWIDGETS
22206 struct xwidget_view *xwidget_view;
22207
22208 xwidget_view = xwidget_view_from_window (enter->event);
22209
22210 if (xwidget_view)
22211 {
22212 xwidget_motion_or_crossing (xwidget_view, event);
22213
22214 goto XI_OTHER;
22215 }
22216 #endif
22217 }
22218
22219 f = any;
22220
22221 if (f && enter->event == FRAME_X_WINDOW (f))
22222 xi_compute_root_window_offset_enter (f, enter);
22223
22224 if (f && x_mouse_click_focus_ignore_position)
22225 {
22226 ignore_next_mouse_click_timeout = (enter->time
22227 + x_mouse_click_focus_ignore_time);
22228 mouse_click_timeout_display = dpyinfo;
22229 }
22230
22231
22232
22233 if (f && !f->output_data.x->hourglass_p)
22234 x_note_mouse_movement (f, &ev, source ? source->name : Qnil);
22235 #ifdef USE_GTK
22236
22237
22238 if (!f && dpyinfo->last_mouse_glyph_frame)
22239 x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &ev,
22240 source ? source->name : Qnil);
22241 #endif
22242 goto XI_OTHER;
22243 }
22244
22245 case XI_Leave:
22246 {
22247 XILeaveEvent *leave;
22248 struct xi_device_t *device;
22249
22250 leave = (XILeaveEvent *) xi_event;
22251 #ifdef USE_GTK
22252 struct xi_device_t *source;
22253 XMotionEvent ev;
22254
22255 ev.x = lrint (leave->event_x);
22256 ev.y = lrint (leave->event_y);
22257 ev.window = leave->event;
22258 ev.time = leave->time;
22259 ev.send_event = leave->send_event;
22260 #endif
22261
22262 any = x_top_window_to_frame (dpyinfo, leave->event);
22263
22264 #ifdef USE_GTK
22265 source = xi_device_from_id (dpyinfo, leave->sourceid);
22266 #endif
22267 device = xi_device_from_id (dpyinfo, leave->deviceid);
22268
22269 if (device)
22270 xi_report_motion_window_clear (device);
22271
22272
22273
22274
22275
22276
22277 #ifdef USE_X_TOOLKIT
22278 if (popup_activated ()
22279 && (leave->mode == XINotifyPassiveUngrab
22280 || leave->mode == XINotifyUngrab))
22281 any = x_any_window_to_frame (dpyinfo, leave->event);
22282 #endif
22283
22284 #ifdef USE_MOTIF
22285 use_copy = true;
22286
22287 copy.xcrossing.type = LeaveNotify;
22288 copy.xcrossing.serial = leave->serial;
22289 copy.xcrossing.send_event = leave->send_event;
22290 copy.xcrossing.display = dpyinfo->display;
22291 copy.xcrossing.window = leave->event;
22292 copy.xcrossing.root = leave->root;
22293 copy.xcrossing.subwindow = leave->child;
22294 copy.xcrossing.time = leave->time;
22295 copy.xcrossing.x = lrint (leave->event_x);
22296 copy.xcrossing.y = lrint (leave->event_y);
22297 copy.xcrossing.x_root = lrint (leave->root_x);
22298 copy.xcrossing.y_root = lrint (leave->root_y);
22299 copy.xcrossing.mode = leave->mode;
22300 copy.xcrossing.detail = leave->detail;
22301 copy.xcrossing.focus = leave->focus;
22302 copy.xcrossing.state = 0;
22303 copy.xcrossing.same_screen = True;
22304 #endif
22305
22306
22307
22308
22309
22310
22311
22312
22313
22314
22315
22316
22317
22318
22319
22320
22321
22322
22323
22324 #ifdef HAVE_XINPUT2_1
22325
22326
22327
22328
22329
22330
22331
22332
22333
22334 if (leave->mode != XINotifyUngrab
22335 && leave->mode != XINotifyGrab
22336 && leave->mode != XINotifyPassiveUngrab
22337 && leave->mode != XINotifyPassiveGrab)
22338 xi_reset_scroll_valuators_for_device_id (dpyinfo,
22339 leave->deviceid);
22340 #endif
22341
22342 x_display_set_last_user_time (dpyinfo, leave->time,
22343 leave->send_event, false);
22344
22345 #ifdef HAVE_XWIDGETS
22346 {
22347 struct xwidget_view *xvw;
22348
22349 xvw = xwidget_view_from_window (leave->event);
22350
22351 if (xvw)
22352 {
22353 *finish = X_EVENT_DROP;
22354 xwidget_motion_or_crossing (xvw, event);
22355
22356 goto XI_OTHER;
22357 }
22358 }
22359 #endif
22360
22361 if (any)
22362 xi_focus_handle_for_device (dpyinfo, any, xi_event);
22363
22364 #ifndef USE_X_TOOLKIT
22365 f = x_top_window_to_frame (dpyinfo, leave->event);
22366 #else
22367
22368
22369 f = x_window_to_frame (dpyinfo, leave->event);
22370
22371 if (!f)
22372 f = x_top_window_to_frame (dpyinfo, leave->event);
22373 #endif
22374
22375 if (f)
22376 {
22377
22378
22379
22380
22381
22382 if (f == dpyinfo->last_mouse_motion_frame)
22383 dpyinfo->last_mouse_motion_frame = NULL;
22384
22385
22386
22387 if (f == dpyinfo->last_mouse_glyph_frame)
22388 dpyinfo->last_mouse_glyph_frame = NULL;
22389
22390 if (f == hlinfo->mouse_face_mouse_frame)
22391 {
22392
22393
22394 clear_mouse_face (hlinfo);
22395 hlinfo->mouse_face_mouse_frame = 0;
22396 x_flush_dirty_back_buffer_on (f);
22397 }
22398
22399
22400
22401
22402
22403 if (any_help_event_p
22404
22405
22406
22407
22408 && !((EQ (track_mouse, Qdrag_source)
22409 || EQ (track_mouse, Qdropping))
22410 && gui_mouse_grabbed (dpyinfo)))
22411 do_help = -1;
22412
22413 if (f && leave->event == FRAME_X_WINDOW (f))
22414 xi_compute_root_window_offset_enter (f, leave);
22415 }
22416 #ifdef USE_GTK
22417
22418 else if (dpyinfo->last_mouse_glyph_frame)
22419 x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &ev,
22420 source ? source->name : Qnil);
22421 #endif
22422 goto XI_OTHER;
22423 }
22424
22425 case XI_Motion:
22426 {
22427 struct xi_device_t *device, *source;
22428 #ifdef HAVE_XINPUT2_1
22429 XIValuatorState *states;
22430 double *values;
22431 bool found_valuator = false;
22432 bool other_valuators_found = false;
22433 #endif
22434
22435 XMotionEvent ev;
22436 xm_top_level_leave_message lmsg;
22437 xm_top_level_enter_message emsg;
22438 xm_drag_motion_message dmsg;
22439 unsigned int dnd_state;
22440
22441 source = xi_device_from_id (dpyinfo, xev->sourceid);
22442
22443 #ifdef HAVE_XINPUT2_1
22444 states = &xev->valuators;
22445 values = states->values;
22446 #endif
22447
22448 device = xi_device_from_id (dpyinfo, xev->deviceid);
22449
22450 if (!device)
22451 goto XI_OTHER;
22452
22453 #ifdef HAVE_XINPUT2_2
22454 if (xev->flags & XIPointerEmulated)
22455 goto XI_OTHER;
22456 #endif
22457
22458 #ifdef HAVE_XINPUT2_1
22459 #ifdef HAVE_XWIDGETS
22460 struct xwidget_view *xv = xwidget_view_from_window (xev->event);
22461 double xv_total_x = 0.0;
22462 double xv_total_y = 0.0;
22463 #endif
22464 double total_x = 0.0;
22465 double total_y = 0.0;
22466
22467 int real_x, real_y;
22468
22469 for (int i = 0; i < states->mask_len * 8; i++)
22470 {
22471 if (XIMaskIsSet (states->mask, i))
22472 {
22473 struct xi_scroll_valuator_t *val;
22474 double delta, scroll_unit;
22475 int scroll_height;
22476 Lisp_Object window;
22477 struct scroll_bar *bar;
22478
22479 bar = NULL;
22480
22481
22482
22483
22484 delta = x_get_scroll_valuator_delta (dpyinfo, device,
22485 i, *values, &val);
22486 values++;
22487
22488 if (!val)
22489 {
22490 other_valuators_found = true;
22491 continue;
22492 }
22493
22494 if (delta != DBL_MAX)
22495 {
22496 if (!f)
22497 {
22498 f = x_any_window_to_frame (dpyinfo, xev->event);
22499
22500 if (!f)
22501 {
22502 #if defined USE_MOTIF || !defined USE_TOOLKIT_SCROLL_BARS
22503 bar = x_window_to_scroll_bar (dpyinfo->display,
22504 xev->event, 2);
22505
22506 if (bar)
22507 f = WINDOW_XFRAME (XWINDOW (bar->window));
22508
22509 if (!f)
22510 #endif
22511 goto XI_OTHER;
22512 }
22513 }
22514
22515 #ifdef USE_GTK
22516 if (f && xg_event_is_for_scrollbar (f, event, true))
22517 *finish = X_EVENT_DROP;
22518 #endif
22519
22520 if (FRAME_X_WINDOW (f) != xev->event)
22521 {
22522 if (!bar)
22523 bar = x_window_to_scroll_bar (dpyinfo->display, xev->event, 2);
22524
22525
22526
22527
22528
22529 if (bar)
22530 {
22531 real_x = lrint (xev->event_x + bar->left);
22532 real_y = lrint (xev->event_y + bar->top);
22533 }
22534 else
22535 x_translate_coordinates (f,
22536 lrint (xev->root_x),
22537 lrint (xev->root_y),
22538 &real_x, &real_y);
22539 }
22540 else
22541 {
22542 real_x = lrint (xev->event_x);
22543 real_y = lrint (xev->event_y);
22544 }
22545
22546 #ifdef HAVE_XWIDGETS
22547 if (xv)
22548 {
22549 if (val->horizontal)
22550 xv_total_x += delta;
22551 else
22552 xv_total_y += delta;
22553
22554 found_valuator = true;
22555 continue;
22556 }
22557 #endif
22558
22559 if (delta == 0.0)
22560 found_valuator = true;
22561
22562 if (signbit (delta) != signbit (val->emacs_value))
22563 val->emacs_value = 0;
22564
22565 val->emacs_value += delta;
22566
22567 if (mwheel_coalesce_scroll_events
22568 && (fabs (val->emacs_value) < 1)
22569 && (fabs (delta) > 0))
22570 continue;
22571
22572 window = window_from_coordinates (f, real_x, real_y, NULL,
22573 false, false);
22574
22575 if (WINDOWP (window))
22576 scroll_height = XWINDOW (window)->pixel_height;
22577 else
22578
22579
22580
22581 scroll_height = FRAME_PIXEL_HEIGHT (f);
22582
22583 scroll_unit = pow (scroll_height, 2.0 / 3.0);
22584
22585 if (NUMBERP (Vx_scroll_event_delta_factor))
22586 scroll_unit *= XFLOATINT (Vx_scroll_event_delta_factor);
22587
22588 if (val->horizontal)
22589 total_x += val->emacs_value * scroll_unit;
22590 else
22591 total_y += val->emacs_value * scroll_unit;
22592
22593 found_valuator = true;
22594 val->emacs_value = 0;
22595 }
22596 }
22597 }
22598
22599 #ifdef HAVE_XWIDGETS
22600 if (xv)
22601 {
22602 unsigned int state;
22603
22604 state = xi_convert_event_state (xev);
22605 x_display_set_last_user_time (dpyinfo, xev->time,
22606 xev->send_event, true);
22607
22608 if (found_valuator)
22609 xwidget_scroll (xv, xev->event_x, xev->event_y,
22610 -xv_total_x, -xv_total_y, state,
22611 xev->time, (xv_total_x == 0.0
22612 && xv_total_y == 0.0));
22613 else
22614 xwidget_motion_notify (xv, xev->event_x, xev->event_y,
22615 xev->root_x, xev->root_y, state,
22616 xev->time);
22617
22618 goto XI_OTHER;
22619 }
22620 else
22621 {
22622 #endif
22623 if (found_valuator)
22624 {
22625 x_display_set_last_user_time (dpyinfo, xev->time,
22626 xev->send_event, true);
22627
22628
22629 #if defined USE_GTK && !defined HAVE_GTK3
22630
22631
22632
22633
22634
22635
22636
22637
22638 if (xev->child != None
22639 && xev->child != FRAME_X_WINDOW (f))
22640 goto XI_OTHER;
22641 #endif
22642
22643
22644
22645
22646 if (x_dnd_in_progress
22647
22648
22649
22650
22651
22652 && xev->deviceid == x_dnd_pointer_device
22653 && (command_loop_level + minibuf_level
22654 <= x_dnd_recursion_depth)
22655 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
22656 goto XI_OTHER;
22657
22658 if (fabs (total_x) > 0 || fabs (total_y) > 0)
22659 {
22660 inev.ie.kind = (fabs (total_y) >= fabs (total_x)
22661 ? WHEEL_EVENT : HORIZ_WHEEL_EVENT);
22662 inev.ie.timestamp = xev->time;
22663
22664 XSETINT (inev.ie.x, lrint (real_x));
22665 XSETINT (inev.ie.y, lrint (real_y));
22666 XSETFRAME (inev.ie.frame_or_window, f);
22667
22668 inev.ie.modifiers = (signbit (fabs (total_y) >= fabs (total_x)
22669 ? total_y : total_x)
22670 ? down_modifier : up_modifier);
22671 inev.ie.modifiers
22672 |= x_x_to_emacs_modifiers (dpyinfo,
22673 xev->mods.effective);
22674 inev.ie.arg = list3 (Qnil,
22675 make_float (total_x),
22676 make_float (total_y));
22677 }
22678 else
22679 {
22680 inev.ie.kind = TOUCH_END_EVENT;
22681 inev.ie.timestamp = xev->time;
22682
22683 XSETINT (inev.ie.x, lrint (real_x));
22684 XSETINT (inev.ie.y, lrint (real_y));
22685 XSETFRAME (inev.ie.frame_or_window, f);
22686 }
22687
22688 if (source && !NILP (source->name))
22689 inev.ie.device = source->name;
22690
22691 if (!other_valuators_found)
22692 goto XI_OTHER;
22693 }
22694 #ifdef HAVE_XWIDGETS
22695 }
22696 #endif
22697 #endif
22698
22699 if (!xi_position_changed (device, xev))
22700 goto XI_OTHER;
22701
22702 ev.x = lrint (xev->event_x);
22703 ev.y = lrint (xev->event_y);
22704 ev.window = xev->event;
22705 ev.time = xev->time;
22706 ev.send_event = xev->send_event;
22707
22708 #ifdef USE_MOTIF
22709 use_copy = true;
22710
22711 copy.xmotion.type = MotionNotify;
22712 copy.xmotion.serial = xev->serial;
22713 copy.xmotion.send_event = xev->send_event;
22714 copy.xmotion.display = dpyinfo->display;
22715 copy.xmotion.window = xev->event;
22716 copy.xmotion.root = xev->root;
22717 copy.xmotion.subwindow = xev->child;
22718 copy.xmotion.time = xev->time;
22719 copy.xmotion.x = lrint (xev->event_x);
22720 copy.xmotion.y = lrint (xev->event_y);
22721 copy.xmotion.x_root = lrint (xev->root_x);
22722 copy.xmotion.y_root = lrint (xev->root_y);
22723 copy.xmotion.state = xi_convert_event_state (xev);
22724
22725 copy.xmotion.is_hint = False;
22726 copy.xmotion.same_screen = True;
22727 #endif
22728
22729 previous_help_echo_string = help_echo_string;
22730 help_echo_string = Qnil;
22731
22732 if (hlinfo->mouse_face_hidden)
22733 {
22734 hlinfo->mouse_face_hidden = false;
22735 clear_mouse_face (hlinfo);
22736 }
22737
22738 f = mouse_or_wdesc_frame (dpyinfo, xev->event);
22739
22740 if (f && xev->event == FRAME_X_WINDOW (f))
22741
22742
22743 xi_compute_root_window_offset (f, xev);
22744
22745 if (x_dnd_in_progress
22746
22747
22748
22749
22750
22751 && (command_loop_level + minibuf_level
22752 <= x_dnd_recursion_depth)
22753 && xev->deviceid == x_dnd_pointer_device
22754 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
22755 {
22756 Window target, toplevel;
22757 int target_proto, motif_style;
22758 XRectangle *r;
22759 bool was_frame;
22760
22761
22762 clear_mouse_face (hlinfo);
22763 hlinfo->mouse_face_hidden = true;
22764
22765
22766
22767
22768
22769
22770 if (f)
22771 {
22772 XTtoggle_invisible_pointer (f, false);
22773
22774 r = &dpyinfo->last_mouse_glyph;
22775
22776
22777
22778 if (f != dpyinfo->last_mouse_glyph_frame
22779 || lrint (xev->event_x) < r->x
22780 || lrint (xev->event_x) >= r->x + r->width
22781 || lrint (xev->event_y) < r->y
22782 || lrint (xev->event_y) >= r->y + r->height)
22783 {
22784 f->mouse_moved = true;
22785 f->last_mouse_device = (source ? source->name
22786 : Qnil);
22787 dpyinfo->last_mouse_scroll_bar = NULL;
22788
22789 remember_mouse_glyph (f, lrint (xev->event_x),
22790 lrint (xev->event_y), r);
22791 dpyinfo->last_mouse_glyph_frame = f;
22792 }
22793 }
22794
22795 if (xev->root == dpyinfo->root_window)
22796 target = x_dnd_get_target_window (dpyinfo,
22797 lrint (xev->root_x),
22798 lrint (xev->root_y),
22799 &target_proto,
22800 &motif_style,
22801 &toplevel,
22802 &was_frame);
22803 else
22804 target = x_dnd_fill_empty_target (&target_proto,
22805 &motif_style,
22806 &toplevel,
22807 &was_frame);
22808
22809 if (toplevel != x_dnd_last_seen_toplevel)
22810 {
22811 if (toplevel != FRAME_OUTER_WINDOW (x_dnd_frame)
22812 && x_dnd_return_frame == 1)
22813 x_dnd_return_frame = 2;
22814
22815 if (x_dnd_return_frame == 2
22816 && x_any_window_to_frame (dpyinfo, toplevel))
22817 {
22818 if (x_dnd_last_seen_window != None
22819 && x_dnd_last_protocol_version != -1
22820 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
22821 x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window,
22822 x_dnd_last_seen_toplevel);
22823 else if (x_dnd_last_seen_window != None
22824 && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
22825 && !x_dnd_disable_motif_drag
22826 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
22827 {
22828 if (!x_dnd_motif_setup_p)
22829 xm_setup_drag_info (dpyinfo, x_dnd_frame);
22830
22831 lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
22832 XM_DRAG_REASON_TOP_LEVEL_LEAVE);
22833 lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
22834 lmsg.zero = 0;
22835 lmsg.timestamp = xev->time;
22836 lmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
22837
22838 if (x_dnd_motif_setup_p)
22839 xm_send_top_level_leave_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
22840 x_dnd_last_seen_window, &lmsg);
22841 }
22842
22843 x_dnd_end_window = x_dnd_last_seen_window;
22844 x_dnd_last_seen_window = None;
22845 x_dnd_last_seen_toplevel = None;
22846 x_dnd_in_progress = false;
22847 x_dnd_return_frame_object
22848 = x_any_window_to_frame (dpyinfo, toplevel);
22849 x_dnd_return_frame = 3;
22850 x_dnd_waiting_for_finish = false;
22851 target = None;
22852 }
22853 }
22854
22855 if (target != x_dnd_last_seen_window)
22856 {
22857 if (x_dnd_last_seen_window != None
22858 && x_dnd_last_protocol_version != -1
22859 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
22860 x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window,
22861 x_dnd_last_seen_toplevel);
22862 else if (x_dnd_last_seen_window != None
22863 && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
22864 && !x_dnd_disable_motif_drag
22865 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
22866 {
22867 if (!x_dnd_motif_setup_p)
22868 xm_setup_drag_info (dpyinfo, x_dnd_frame);
22869
22870
22871
22872
22873
22874
22875
22876
22877 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
22878 XM_DRAG_REASON_DRAG_MOTION);
22879 dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
22880 dmsg.side_effects
22881 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
22882 x_dnd_wanted_action),
22883 XM_DROP_SITE_NONE, x_dnd_motif_operations,
22884 XM_DROP_ACTION_DROP_CANCEL);
22885 dmsg.timestamp = xev->time;
22886 dmsg.x = lrint (xev->root_x);
22887 dmsg.y = lrint (xev->root_y);
22888
22889 lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
22890 XM_DRAG_REASON_TOP_LEVEL_LEAVE);
22891 lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
22892 lmsg.zero = 0;
22893 lmsg.timestamp = xev->time;
22894 lmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
22895
22896 if (x_dnd_motif_setup_p)
22897 {
22898 xm_send_drag_motion_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
22899 x_dnd_last_seen_window, &dmsg);
22900 xm_send_top_level_leave_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
22901 x_dnd_last_seen_window, &lmsg);
22902 }
22903 }
22904
22905 x_dnd_action = None;
22906 x_dnd_last_seen_toplevel = toplevel;
22907 x_dnd_last_seen_window = target;
22908 x_dnd_last_protocol_version = target_proto;
22909 x_dnd_last_motif_style = motif_style;
22910 x_dnd_last_window_is_frame = was_frame;
22911
22912 if (target != None && x_dnd_last_protocol_version != -1)
22913 x_dnd_send_enter (x_dnd_frame, target,
22914 x_dnd_last_seen_toplevel,
22915 x_dnd_last_protocol_version);
22916 else if (target != None && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
22917 && !x_dnd_disable_motif_drag)
22918 {
22919 if (!x_dnd_motif_setup_p)
22920 xm_setup_drag_info (dpyinfo, x_dnd_frame);
22921
22922 emsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
22923 XM_DRAG_REASON_TOP_LEVEL_ENTER);
22924 emsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
22925 emsg.zero = 0;
22926 emsg.timestamp = xev->time;
22927 emsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
22928 emsg.index_atom = x_dnd_motif_atom;
22929
22930 if (x_dnd_motif_setup_p)
22931 xm_send_top_level_enter_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
22932 target, &emsg);
22933 }
22934 }
22935 else
22936 x_dnd_last_seen_toplevel = toplevel;
22937
22938 if (x_dnd_last_window_is_frame && target != None)
22939 x_dnd_note_self_position (dpyinfo, target,
22940 lrint (xev->root_x),
22941 lrint (xev->root_y));
22942 else if (x_dnd_last_protocol_version != -1 && target != None)
22943 {
22944 dnd_state = xi_convert_event_state (xev);
22945
22946 x_dnd_send_position (x_dnd_frame, target,
22947 x_dnd_last_seen_toplevel,
22948 x_dnd_last_protocol_version,
22949 lrint (xev->root_x),
22950 lrint (xev->root_y),
22951 x_dnd_selection_timestamp,
22952 x_dnd_wanted_action, 0,
22953 dnd_state);
22954 }
22955 else if (XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) && target != None
22956 && !x_dnd_disable_motif_drag)
22957 {
22958 if (!x_dnd_motif_setup_p)
22959 xm_setup_drag_info (dpyinfo, x_dnd_frame);
22960
22961 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
22962 XM_DRAG_REASON_DRAG_MOTION);
22963 dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
22964 dmsg.side_effects
22965 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
22966 x_dnd_wanted_action),
22967 XM_DROP_SITE_VALID, x_dnd_motif_operations,
22968 (!x_dnd_xm_use_help
22969 ? XM_DROP_ACTION_DROP
22970 : XM_DROP_ACTION_DROP_HELP));
22971 dmsg.timestamp = xev->time;
22972 dmsg.x = lrint (xev->root_x);
22973 dmsg.y = lrint (xev->root_y);
22974
22975 if (x_dnd_motif_setup_p)
22976 xm_send_drag_motion_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
22977 target, &dmsg);
22978 }
22979
22980 x_dnd_update_tooltip_position (xev->root_x, xev->root_y);
22981
22982 goto XI_OTHER;
22983 }
22984
22985 #ifdef USE_GTK
22986 if (f && xg_event_is_for_scrollbar (f, event, false))
22987 f = 0;
22988 #endif
22989 if (f)
22990 {
22991 if (xev->event != FRAME_X_WINDOW (f))
22992 {
22993 x_translate_coordinates (f, lrint (xev->root_x),
22994 lrint (xev->root_y),
22995 &ev.x, &ev.y);
22996 ev.window = FRAME_X_WINDOW (f);
22997 }
22998
22999
23000
23001
23002 if (!NILP (Vmouse_autoselect_window)
23003 && !popup_activated ()
23004
23005
23006
23007
23008
23009 && !MINI_WINDOW_P (XWINDOW (selected_window))
23010
23011
23012 && (f == XFRAME (selected_frame)
23013 || !NILP (focus_follows_mouse)))
23014 {
23015 static Lisp_Object last_mouse_window;
23016 Lisp_Object window = window_from_coordinates (f, ev.x, ev.y, 0, false, false);
23017
23018
23019
23020
23021
23022
23023
23024
23025
23026 if (WINDOWP (window)
23027 && !EQ (window, last_mouse_window)
23028 && !EQ (window, selected_window))
23029 {
23030 inev.ie.kind = SELECT_WINDOW_EVENT;
23031 inev.ie.frame_or_window = window;
23032
23033 if (source)
23034 inev.ie.device = source->name;
23035 }
23036
23037
23038 last_mouse_window = window;
23039 }
23040
23041 if (!x_note_mouse_movement (f, &ev, source ? source->name : Qnil))
23042 help_echo_string = previous_help_echo_string;
23043 }
23044 else
23045 {
23046 #ifndef USE_TOOLKIT_SCROLL_BARS
23047 struct scroll_bar *bar
23048 = x_window_to_scroll_bar (dpyinfo->display, xev->event, 2);
23049
23050 if (bar)
23051 x_scroll_bar_note_movement (bar, &ev);
23052 #endif
23053
23054
23055
23056 clear_mouse_face (hlinfo);
23057 }
23058
23059
23060
23061 if (!NILP (help_echo_string)
23062 || !NILP (previous_help_echo_string))
23063 {
23064
23065
23066
23067 gen_help_device = device;
23068 gen_help_time = xev->time;
23069
23070 do_help = 1;
23071 }
23072
23073 if (f)
23074 x_flush_dirty_back_buffer_on (f);
23075 goto XI_OTHER;
23076 }
23077
23078 case XI_ButtonRelease:
23079 case XI_ButtonPress:
23080 {
23081
23082
23083 Lisp_Object tab_bar_arg = Qnil;
23084 bool tab_bar_p = false;
23085 bool tool_bar_p = false;
23086 struct xi_device_t *device, *source;
23087 #ifdef HAVE_XWIDGETS
23088 struct xwidget_view *xvw;
23089 #endif
23090
23091 XButtonEvent bv;
23092 bool dnd_grab = false;
23093 int dnd_state;
23094
23095 if (x_dnd_in_progress
23096 && (command_loop_level + minibuf_level
23097 <= x_dnd_recursion_depth)
23098 && xev->deviceid == x_dnd_pointer_device
23099 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
23100 {
23101 f = mouse_or_wdesc_frame (dpyinfo, xev->event);
23102 device = xi_device_from_id (dpyinfo, xev->deviceid);
23103
23104 if (f && xev->event == FRAME_X_WINDOW (f))
23105
23106
23107
23108 xi_compute_root_window_offset (f, xev);
23109
23110
23111
23112
23113 #ifdef XIPointerEmulated
23114 if (!(xev->flags & XIPointerEmulated))
23115 {
23116 #endif
23117 if (xev->evtype == XI_ButtonPress)
23118 {
23119 x_display_set_last_user_time (dpyinfo, xev->time,
23120 xev->send_event, true);
23121
23122 dpyinfo->grabbed |= (1 << xev->detail);
23123 dpyinfo->last_mouse_frame = f;
23124
23125 if (device)
23126 device->grab |= (1 << xev->detail);
23127
23128 if (f)
23129 f->last_tab_bar_item = -1;
23130 #if ! defined (USE_GTK)
23131 if (f)
23132 f->last_tool_bar_item = -1;
23133 #endif
23134 }
23135 else
23136 {
23137 dpyinfo->grabbed &= ~(1 << xev->detail);
23138 if (device)
23139 device->grab &= ~(1 << xev->detail);
23140 }
23141 #ifdef XIPointerEmulated
23142 }
23143 #endif
23144
23145 if (f && device)
23146 xi_handle_interaction (dpyinfo, f, device,
23147 xev->time);
23148
23149 if (xev->evtype == XI_ButtonPress
23150 && x_dnd_last_seen_window != None)
23151 {
23152 dnd_state = xi_convert_event_state (xev);
23153
23154 if (x_dnd_last_window_is_frame)
23155 {
23156 #ifdef XI_PointerEmulated
23157
23158
23159
23160
23161 if (xev->flags & XIPointerEmulated)
23162 x_display_set_last_user_time (dpyinfo, xev->time,
23163 xev->send_event, true);
23164 #endif
23165 x_dnd_note_self_wheel (dpyinfo,
23166 x_dnd_last_seen_window,
23167 lrint (xev->root_x),
23168 lrint (xev->root_y),
23169 xev->detail, dnd_state,
23170 xev->time);
23171 }
23172 else
23173 x_dnd_send_position (x_dnd_frame,
23174 x_dnd_last_seen_window,
23175 x_dnd_last_seen_toplevel,
23176 x_dnd_last_protocol_version,
23177 lrint (xev->root_x),
23178 lrint (xev->root_y),
23179 xev->time, x_dnd_wanted_action,
23180 xev->detail, dnd_state);
23181
23182 goto OTHER;
23183 }
23184
23185 if (xev->evtype == XI_ButtonRelease)
23186 {
23187 for (int i = 0; i < xev->buttons.mask_len * 8; ++i)
23188 {
23189 if (i != xev->detail && XIMaskIsSet (xev->buttons.mask, i))
23190 dnd_grab = true;
23191 }
23192
23193 if (!dnd_grab)
23194 {
23195 x_dnd_end_window = x_dnd_last_seen_window;
23196 x_dnd_in_progress = false;
23197
23198
23199
23200
23201 if (x_dnd_update_tooltip
23202 && FRAMEP (tip_frame)
23203 && FRAME_LIVE_P (XFRAME (tip_frame))
23204 && (FRAME_X_DISPLAY (XFRAME (tip_frame))
23205 == FRAME_X_DISPLAY (x_dnd_frame)))
23206 Fx_hide_tip ();
23207
23208
23209
23210
23211
23212
23213
23214 x_dnd_finish_frame = x_dnd_frame;
23215
23216 if (x_dnd_last_seen_window != None
23217 && x_dnd_last_window_is_frame)
23218 {
23219 x_dnd_waiting_for_finish = false;
23220 x_dnd_note_self_drop (dpyinfo, x_dnd_last_seen_window,
23221 lrint (xev->root_x),
23222 lrint (xev->root_y), xev->time);
23223 }
23224 else if (x_dnd_last_seen_window != None
23225 && x_dnd_last_protocol_version != -1)
23226 {
23227 x_dnd_pending_finish_target = x_dnd_last_seen_toplevel;
23228 x_dnd_waiting_for_finish_proto = x_dnd_last_protocol_version;
23229
23230 x_dnd_waiting_for_finish
23231 = x_dnd_do_drop (x_dnd_last_seen_window,
23232 x_dnd_last_seen_toplevel,
23233 x_dnd_last_protocol_version);
23234 x_dnd_finish_display = dpyinfo->display;
23235 }
23236 else if (x_dnd_last_seen_window != None)
23237 {
23238 xm_drop_start_message dmsg;
23239 xm_drag_receiver_info drag_receiver_info;
23240
23241 if (!xm_read_drag_receiver_info (dpyinfo, x_dnd_last_seen_window,
23242 &drag_receiver_info)
23243 && !x_dnd_disable_motif_protocol
23244 && drag_receiver_info.protocol_style != XM_DRAG_STYLE_NONE
23245 && (x_dnd_allow_current_frame
23246 || x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame)))
23247 {
23248 if (!x_dnd_motif_setup_p)
23249 xm_setup_drag_info (dpyinfo, x_dnd_frame);
23250
23251 if (x_dnd_motif_setup_p)
23252 {
23253 memset (&dmsg, 0, sizeof dmsg);
23254
23255 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
23256 XM_DRAG_REASON_DROP_START);
23257 dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST;
23258 dmsg.side_effects
23259 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
23260 x_dnd_wanted_action),
23261 XM_DROP_SITE_VALID, x_dnd_motif_operations,
23262 (!x_dnd_xm_use_help
23263 ? XM_DROP_ACTION_DROP
23264 : XM_DROP_ACTION_DROP_HELP));
23265 dmsg.timestamp = xev->time;
23266 dmsg.x = lrint (xev->root_x);
23267 dmsg.y = lrint (xev->root_y);
23268
23269
23270
23271
23272
23273
23274
23275
23276
23277 dmsg.index_atom = x_dnd_motif_atom;
23278 dmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
23279
23280 if (!XM_DRAG_STYLE_IS_DROP_ONLY (drag_receiver_info.protocol_style))
23281 x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (x_dnd_frame),
23282 x_dnd_frame, x_dnd_last_seen_window,
23283 xev->time);
23284
23285 xm_send_drop_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
23286 x_dnd_last_seen_window, &dmsg);
23287
23288 x_dnd_waiting_for_finish = true;
23289 x_dnd_waiting_for_motif_finish_display = dpyinfo;
23290 x_dnd_waiting_for_motif_finish = 1;
23291 x_dnd_finish_display = dpyinfo->display;
23292 }
23293 }
23294 else
23295 x_dnd_send_unsupported_drop (dpyinfo, (x_dnd_last_seen_toplevel != None
23296 ? x_dnd_last_seen_toplevel
23297 : x_dnd_last_seen_window),
23298 lrint (xev->root_x),
23299 lrint (xev->root_y), xev->time);
23300 }
23301 else if (x_dnd_last_seen_toplevel != None)
23302 x_dnd_send_unsupported_drop (dpyinfo,
23303 x_dnd_last_seen_toplevel,
23304 lrint (xev->root_x),
23305 lrint (xev->root_y),
23306 xev->time);
23307
23308 x_dnd_last_protocol_version = -1;
23309 x_dnd_last_motif_style = XM_DRAG_STYLE_NONE;
23310 x_dnd_last_seen_window = None;
23311 x_dnd_last_seen_toplevel = None;
23312 x_dnd_last_window_is_frame = false;
23313 x_dnd_frame = NULL;
23314
23315 goto XI_OTHER;
23316 }
23317 }
23318 }
23319
23320 if (x_dnd_in_progress
23321 && (command_loop_level + minibuf_level
23322 <= x_dnd_recursion_depth))
23323 goto XI_OTHER;
23324
23325 #ifdef USE_MOTIF
23326 #ifdef USE_TOOLKIT_SCROLL_BARS
23327 struct scroll_bar *bar
23328 = x_window_to_scroll_bar (dpyinfo->display,
23329 xev->event, 2);
23330 #endif
23331
23332 use_copy = true;
23333 copy.xbutton.type = (xev->evtype == XI_ButtonPress
23334 ? ButtonPress : ButtonRelease);
23335 copy.xbutton.serial = xev->serial;
23336 copy.xbutton.send_event = xev->send_event;
23337 copy.xbutton.display = dpyinfo->display;
23338 copy.xbutton.window = xev->event;
23339 copy.xbutton.root = xev->root;
23340 copy.xbutton.subwindow = xev->child;
23341 copy.xbutton.time = xev->time;
23342 copy.xbutton.x = lrint (xev->event_x);
23343 copy.xbutton.y = lrint (xev->event_y);
23344 copy.xbutton.x_root = lrint (xev->root_x);
23345 copy.xbutton.y_root = lrint (xev->root_y);
23346 copy.xbutton.state = xi_convert_event_state (xev);
23347 copy.xbutton.button = xev->detail;
23348 copy.xbutton.same_screen = True;
23349
23350 #elif defined USE_GTK && !defined HAVE_GTK3
23351 copy = gdk_event_new (xev->evtype == XI_ButtonPress
23352 ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE);
23353
23354 copy->button.window = gdk_x11_window_lookup_for_display (gdpy, xev->event);
23355 copy->button.send_event = xev->send_event;
23356 copy->button.time = xev->time;
23357 copy->button.x = xev->event_x;
23358 copy->button.y = xev->event_y;
23359 copy->button.x_root = xev->root_x;
23360 copy->button.y_root = xev->root_y;
23361 copy->button.state = xi_convert_event_state (xev);
23362 copy->button.button = xev->detail;
23363
23364 if (!copy->button.window)
23365 emacs_abort ();
23366
23367 g_object_ref (copy->button.window);
23368
23369 if (popup_activated ())
23370 {
23371
23372
23373
23374 if (xev->detail > 3)
23375 *finish = X_EVENT_DROP;
23376
23377 if (xev->evtype == XI_ButtonRelease)
23378 goto XI_OTHER;
23379 }
23380 #endif
23381
23382 #ifdef HAVE_XINPUT2_1
23383
23384
23385 if (xev->flags & XIPointerEmulated)
23386 {
23387 #if !defined USE_MOTIF || !defined USE_TOOLKIT_SCROLL_BARS
23388 *finish = X_EVENT_DROP;
23389 #else
23390 if (bar)
23391 *finish = X_EVENT_DROP;
23392 #endif
23393 goto XI_OTHER;
23394 }
23395 #endif
23396
23397 if (xev->evtype == XI_ButtonPress)
23398 x_display_set_last_user_time (dpyinfo, xev->time,
23399 xev->send_event, true);
23400
23401 source = xi_device_from_id (dpyinfo, xev->sourceid);
23402 device = xi_device_from_id (dpyinfo, xev->deviceid);
23403
23404 #ifdef HAVE_XWIDGETS
23405 xvw = xwidget_view_from_window (xev->event);
23406 if (xvw)
23407 {
23408
23409
23410
23411 if (device)
23412 xi_handle_interaction (dpyinfo, xvw->frame,
23413 device, xev->time);
23414
23415 xwidget_button (xvw, xev->evtype == XI_ButtonPress,
23416 lrint (xev->event_x), lrint (xev->event_y),
23417 xev->detail, xi_convert_event_state (xev),
23418 xev->time);
23419
23420 if (!EQ (selected_window, xvw->w) && (xev->detail < 4))
23421 {
23422 inev.ie.kind = SELECT_WINDOW_EVENT;
23423 inev.ie.frame_or_window = xvw->w;
23424
23425 if (source)
23426 inev.ie.device = source->name;
23427 }
23428
23429 *finish = X_EVENT_DROP;
23430 goto XI_OTHER;
23431 }
23432 #endif
23433
23434 if (!device)
23435 goto XI_OTHER;
23436
23437 bv.button = xev->detail;
23438 bv.type = xev->evtype == XI_ButtonPress ? ButtonPress : ButtonRelease;
23439 bv.x = lrint (xev->event_x);
23440 bv.y = lrint (xev->event_y);
23441 bv.x_root = lrint (xev->root_x);
23442 bv.y_root = lrint (xev->root_y);
23443 bv.window = xev->event;
23444 bv.state = xi_convert_event_state (xev);
23445 bv.time = xev->time;
23446
23447 dpyinfo->last_mouse_glyph_frame = NULL;
23448
23449 f = mouse_or_wdesc_frame (dpyinfo, xev->event);
23450
23451 if (f && xev->event == FRAME_X_WINDOW (f))
23452
23453
23454 xi_compute_root_window_offset (f, xev);
23455
23456 if (f && xev->evtype == XI_ButtonPress
23457 && !popup_activated ()
23458 && !x_window_to_scroll_bar (dpyinfo->display, xev->event, 2)
23459 && !FRAME_NO_ACCEPT_FOCUS (f))
23460 {
23461
23462
23463
23464
23465 struct frame *hf = dpyinfo->highlight_frame;
23466
23467 if (FRAME_PARENT_FRAME (f) || (hf && frame_ancestor_p (f, hf)))
23468 {
23469 #if defined HAVE_GTK3 || (!defined USE_GTK && !defined USE_X_TOOLKIT)
23470 if (device)
23471 {
23472
23473
23474
23475 x_ignore_errors_for_next_request (dpyinfo, 0);
23476 XISetFocus (dpyinfo->display, device->attachment,
23477
23478
23479
23480 FRAME_OUTER_WINDOW (f), xev->time);
23481 x_stop_ignoring_errors (dpyinfo);
23482 }
23483 #else
23484
23485
23486
23487
23488 x_ignore_errors_for_next_request (dpyinfo, 0);
23489 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
23490 RevertToParent, xev->time);
23491 x_stop_ignoring_errors (dpyinfo);
23492 #endif
23493 if (FRAME_PARENT_FRAME (f))
23494 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
23495 }
23496 }
23497
23498 if (f)
23499 {
23500
23501
23502
23503 if (device)
23504 xi_handle_interaction (dpyinfo, f, device,
23505 xev->time);
23506 }
23507
23508 #ifdef USE_GTK
23509 if (!f)
23510 {
23511 int real_x = lrint (xev->root_x);
23512 int real_y = lrint (xev->root_y);
23513
23514 f = x_any_window_to_frame (dpyinfo, xev->event);
23515
23516 if (xev->detail > 3 && xev->detail < 8 && f)
23517 {
23518 if (xev->evtype == XI_ButtonRelease)
23519 {
23520 if (FRAME_X_WINDOW (f) != xev->event)
23521 x_translate_coordinates (f, real_x, real_y,
23522 &real_x, &real_y);
23523
23524 if (xev->detail <= 5)
23525 inev.ie.kind = WHEEL_EVENT;
23526 else
23527 inev.ie.kind = HORIZ_WHEEL_EVENT;
23528
23529 if (source)
23530 inev.ie.device = source->name;
23531
23532 inev.ie.timestamp = xev->time;
23533
23534 XSETINT (inev.ie.x, real_x);
23535 XSETINT (inev.ie.y, real_y);
23536 XSETFRAME (inev.ie.frame_or_window, f);
23537
23538 inev.ie.modifiers
23539 |= x_x_to_emacs_modifiers (dpyinfo,
23540 xev->mods.effective);
23541
23542 inev.ie.modifiers |= xev->detail % 2 ? down_modifier : up_modifier;
23543 }
23544
23545 *finish = X_EVENT_DROP;
23546 goto XI_OTHER;
23547 }
23548 else
23549 f = NULL;
23550 }
23551
23552 if (f && xg_event_is_for_scrollbar (f, event, false))
23553 f = 0;
23554 #endif
23555
23556 if (f)
23557 {
23558 if (xev->detail >= 4 && xev->detail < 8)
23559 {
23560 if (xev->evtype == XI_ButtonRelease)
23561 {
23562 if (xev->detail <= 5)
23563 inev.ie.kind = WHEEL_EVENT;
23564 else
23565 inev.ie.kind = HORIZ_WHEEL_EVENT;
23566
23567 if (source)
23568 inev.ie.device = source->name;
23569
23570 inev.ie.timestamp = xev->time;
23571
23572 XSETINT (inev.ie.x, lrint (xev->event_x));
23573 XSETINT (inev.ie.y, lrint (xev->event_y));
23574 XSETFRAME (inev.ie.frame_or_window, f);
23575
23576 inev.ie.modifiers
23577 |= x_x_to_emacs_modifiers (dpyinfo,
23578 xev->mods.effective);
23579
23580 inev.ie.modifiers |= xev->detail % 2 ? down_modifier : up_modifier;
23581 }
23582
23583 goto XI_OTHER;
23584 }
23585
23586
23587 if (WINDOWP (f->tab_bar_window)
23588 && WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window)))
23589 {
23590 Lisp_Object window;
23591 int x = bv.x;
23592 int y = bv.y;
23593
23594 window = window_from_coordinates (f, x, y, 0, true, true);
23595 tab_bar_p = EQ (window, f->tab_bar_window);
23596
23597 if (tab_bar_p)
23598 {
23599 tab_bar_arg = handle_tab_bar_click
23600 (f, x, y, xev->evtype == XI_ButtonPress,
23601 x_x_to_emacs_modifiers (dpyinfo, bv.state));
23602 x_flush_dirty_back_buffer_on (f);
23603 }
23604 }
23605
23606 #if ! defined (USE_GTK)
23607
23608 if (WINDOWP (f->tool_bar_window)
23609 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
23610 {
23611 Lisp_Object window;
23612 int x = bv.x;
23613 int y = bv.y;
23614
23615 window = window_from_coordinates (f, x, y, 0, true, true);
23616
23617
23618
23619
23620
23621
23622
23623 tool_bar_p = (EQ (window, f->tool_bar_window)
23624 && (xev->evtype != XI_ButtonRelease
23625 || f->last_tool_bar_item != -1));
23626
23627 if (tool_bar_p && xev->detail < 4)
23628 {
23629 handle_tool_bar_click_with_device
23630 (f, x, y, xev->evtype == XI_ButtonPress,
23631 x_x_to_emacs_modifiers (dpyinfo, bv.state),
23632 source ? source->name : Qt);
23633 x_flush_dirty_back_buffer_on (f);
23634 }
23635 }
23636 #endif
23637
23638 if (!(tab_bar_p && NILP (tab_bar_arg)) && !tool_bar_p)
23639 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
23640 if (! popup_activated ())
23641 #endif
23642 {
23643 if (ignore_next_mouse_click_timeout)
23644 {
23645 if (xev->evtype == XI_ButtonPress
23646 && xev->time > ignore_next_mouse_click_timeout)
23647 {
23648 ignore_next_mouse_click_timeout = 0;
23649 x_construct_mouse_click (&inev.ie, &bv, f);
23650 }
23651 if (xev->evtype == XI_ButtonRelease)
23652 ignore_next_mouse_click_timeout = 0;
23653 }
23654 else
23655 x_construct_mouse_click (&inev.ie, &bv, f);
23656
23657 if (!NILP (tab_bar_arg))
23658 inev.ie.arg = tab_bar_arg;
23659 }
23660
23661 if (FRAME_X_EMBEDDED_P (f)
23662 && !FRAME_NO_ACCEPT_FOCUS (f))
23663 xembed_send_message (f, xev->time,
23664 XEMBED_REQUEST_FOCUS, 0, 0, 0);
23665 }
23666 else
23667 {
23668 struct scroll_bar *bar
23669 = x_window_to_scroll_bar (dpyinfo->display,
23670 xev->event, 2);
23671
23672 #ifndef USE_TOOLKIT_SCROLL_BARS
23673 if (bar)
23674 x_scroll_bar_handle_click (bar, (XEvent *) &bv, &inev.ie,
23675 source ? source->name : Qnil);
23676 #else
23677
23678
23679 if (bar && xev->mods.effective & ControlMask)
23680 {
23681 x_scroll_bar_handle_click (bar, (XEvent *) &bv, &inev.ie,
23682 source ? source->name : Qnil);
23683 *finish = X_EVENT_DROP;
23684 }
23685 #endif
23686 }
23687
23688 if (xev->evtype == XI_ButtonPress)
23689 {
23690 dpyinfo->grabbed |= (1 << xev->detail);
23691 device->grab |= (1 << xev->detail);
23692 dpyinfo->last_mouse_frame = f;
23693 if (f && !tab_bar_p)
23694 f->last_tab_bar_item = -1;
23695 #if ! defined (USE_GTK)
23696 if (f && !tool_bar_p)
23697 f->last_tool_bar_item = -1;
23698 #endif
23699
23700 }
23701 else
23702 {
23703 dpyinfo->grabbed &= ~(1 << xev->detail);
23704 device->grab &= ~(1 << xev->detail);
23705 }
23706
23707 if (source && inev.ie.kind != NO_EVENT)
23708 inev.ie.device = source->name;
23709
23710 if (f)
23711 f->mouse_moved = false;
23712
23713 #if defined (USE_GTK)
23714
23715
23716 f = x_menubar_window_to_frame (dpyinfo, event);
23717 if (f
23718 && xev->detail < 3)
23719 {
23720
23721
23722 bool was_waiting_for_input = waiting_for_input;
23723
23724
23725
23726 if (waiting_for_input)
23727 waiting_for_input = 0;
23728 set_frame_menubar (f, true);
23729 waiting_for_input = was_waiting_for_input;
23730 }
23731 #endif
23732 goto XI_OTHER;
23733 }
23734
23735 case XI_KeyPress:
23736 {
23737 int state = xev->mods.effective;
23738 Lisp_Object c;
23739 #ifdef HAVE_XKB
23740 unsigned int mods_rtrn;
23741 #endif
23742 int keycode = xev->detail;
23743 KeySym keysym;
23744 char copy_buffer[81];
23745 char *copy_bufptr = copy_buffer;
23746 int copy_bufsiz = sizeof (copy_buffer);
23747 ptrdiff_t i;
23748 unsigned int old_state;
23749 struct xi_device_t *device, *source;
23750 XKeyPressedEvent xkey;
23751
23752 coding = Qlatin_1;
23753
23754
23755
23756
23757
23758
23759
23760
23761
23762
23763
23764
23765
23766
23767
23768
23769
23770
23771
23772
23773
23774
23775
23776
23777
23778
23779
23780
23781
23782
23783
23784
23785
23786
23787
23788
23789
23790
23791
23792
23793
23794
23795
23796
23797
23798
23799
23800
23801
23802
23803
23804
23805
23806
23807
23808
23809
23810
23811
23812
23813
23814
23815
23816
23817
23818
23819
23820
23821
23822
23823
23824
23825
23826
23827
23828
23829
23830
23831
23832
23833
23834
23835
23836
23837
23838
23839
23840
23841
23842
23843
23844
23845
23846
23847
23848
23849
23850
23851
23852
23853
23854
23855 device = xi_device_from_id (dpyinfo, xev->deviceid);
23856 source = xi_device_from_id (dpyinfo, xev->sourceid);
23857
23858 if (!device)
23859 goto XI_OTHER;
23860
23861
23862
23863
23864
23865 state = xi_convert_event_keyboard_state (xev);
23866
23867 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
23868
23869 if (popup_activated ())
23870 {
23871 #ifdef USE_LUCID
23872
23873 use_copy = true;
23874 copy.xkey.type = KeyPress;
23875 copy.xkey.serial = xev->serial;
23876 copy.xkey.send_event = xev->send_event;
23877 copy.xkey.display = dpyinfo->display;
23878 copy.xkey.window = xev->event;
23879 copy.xkey.root = xev->root;
23880 copy.xkey.subwindow = xev->child;
23881 copy.xkey.time = xev->time;
23882 copy.xkey.state = state;
23883 xi_convert_button_state (&xev->buttons, ©.xkey.state);
23884
23885 copy.xkey.x = lrint (xev->event_x);
23886 copy.xkey.y = lrint (xev->event_y);
23887 copy.xkey.x_root = lrint (xev->root_x);
23888 copy.xkey.y_root = lrint (xev->root_y);
23889 copy.xkey.keycode = xev->detail;
23890 copy.xkey.same_screen = True;
23891 #endif
23892 goto XI_OTHER;
23893 }
23894 #endif
23895
23896 x_display_set_last_user_time (dpyinfo, xev->time,
23897 xev->send_event, true);
23898 ignore_next_mouse_click_timeout = 0;
23899
23900 f = x_any_window_to_frame (dpyinfo, xev->event);
23901
23902 if (f && xev->event == FRAME_X_WINDOW (f))
23903
23904
23905 xi_compute_root_window_offset (f, xev);
23906
23907
23908
23909
23910
23911 #ifdef USE_GTK
23912 if (f)
23913 x_set_gtk_user_time (f, xev->time);
23914 #endif
23915
23916 if (f)
23917 {
23918
23919
23920
23921 if (device)
23922 xi_handle_interaction (dpyinfo, f, device,
23923 xev->time);
23924 }
23925
23926
23927
23928
23929
23930 memset (&xkey, 0, sizeof xkey);
23931
23932 xkey.type = KeyPress;
23933 xkey.serial = xev->serial;
23934 xkey.send_event = xev->send_event;
23935 xkey.display = dpyinfo->display;
23936 xkey.window = xev->event;
23937 xkey.root = xev->root;
23938 xkey.subwindow = xev->child;
23939 xkey.time = xev->time;
23940 xkey.state = state;
23941 xkey.x = lrint (xev->event_x);
23942 xkey.y = lrint (xev->event_y);
23943 xkey.x_root = lrint (xev->root_x);
23944 xkey.y_root = lrint (xev->root_y);
23945
23946
23947
23948 xi_convert_button_state (&xev->buttons, &xkey.state);
23949
23950 xkey.keycode = xev->detail;
23951 xkey.same_screen = True;
23952
23953 #ifdef HAVE_X_I18N
23954 #ifdef USE_GTK
23955 if ((!x_gtk_use_native_input
23956 && x_filter_event (dpyinfo, (XEvent *) &xkey))
23957 || (x_gtk_use_native_input
23958 && x_filter_event (dpyinfo, event)))
23959 {
23960
23961
23962
23963 dpyinfo->pending_keystroke_time = xev->time;
23964 dpyinfo->pending_keystroke_source = xev->sourceid;
23965
23966 *finish = X_EVENT_DROP;
23967 goto XI_OTHER;
23968 }
23969 #else
23970 if (x_filter_event (dpyinfo, (XEvent *) &xkey))
23971 {
23972
23973
23974
23975 dpyinfo->pending_keystroke_time = xev->time;
23976 dpyinfo->pending_keystroke_source = xev->sourceid;
23977
23978 *finish = X_EVENT_DROP;
23979 goto XI_OTHER;
23980 }
23981 #endif
23982 #elif USE_GTK
23983 if ((x_gtk_use_native_input
23984 || dpyinfo->prefer_native_input)
23985 && xg_filter_key (any, event))
23986 {
23987
23988
23989
23990 dpyinfo->pending_keystroke_time = xev->time;
23991 dpyinfo->pending_keystroke_source = xev->sourceid;
23992
23993 *finish = X_EVENT_DROP;
23994 goto XI_OTHER;
23995 }
23996 #endif
23997
23998 state |= x_emacs_to_x_modifiers (dpyinfo, extra_keyboard_modifiers);
23999
24000
24001
24002 if (!hlinfo->mouse_face_hidden && FIXNUMP (Vmouse_highlight)
24003 && (f == 0
24004 #if ! defined (USE_GTK)
24005 || !EQ (f->tool_bar_window, hlinfo->mouse_face_window)
24006 #endif
24007 || !EQ (f->tab_bar_window, hlinfo->mouse_face_window))
24008 )
24009 {
24010 mouse_frame = hlinfo->mouse_face_mouse_frame;
24011
24012 clear_mouse_face (hlinfo);
24013 hlinfo->mouse_face_hidden = true;
24014
24015 if (mouse_frame)
24016 x_flush_dirty_back_buffer_on (mouse_frame);
24017 }
24018
24019 if (f != 0)
24020 {
24021 #ifdef USE_GTK
24022
24023
24024
24025
24026 *finish = X_EVENT_DROP;
24027 #endif
24028
24029 XSETFRAME (inev.ie.frame_or_window, f);
24030 inev.ie.timestamp = xev->time;
24031
24032 #ifdef HAVE_X_I18N
24033 if (FRAME_XIC (f))
24034 {
24035 Status status_return;
24036 nbytes = XmbLookupString (FRAME_XIC (f),
24037 &xkey, (char *) copy_bufptr,
24038 copy_bufsiz, &keysym,
24039 &status_return);
24040 coding = FRAME_X_XIM_CODING (f);
24041
24042 if (status_return == XBufferOverflow)
24043 {
24044 copy_bufsiz = nbytes + 1;
24045 copy_bufptr = SAFE_ALLOCA (copy_bufsiz);
24046 nbytes = XmbLookupString (FRAME_XIC (f),
24047 &xkey, (char *) copy_bufptr,
24048 copy_bufsiz, &keysym,
24049 &status_return);
24050 }
24051
24052 if (status_return == XLookupNone)
24053 goto xi_done_keysym;
24054 else if (status_return == XLookupChars)
24055 {
24056 keysym = NoSymbol;
24057 state = 0;
24058 }
24059 else if (status_return != XLookupKeySym
24060 && status_return != XLookupBoth)
24061 emacs_abort ();
24062 }
24063 else
24064 #endif
24065 {
24066 #ifdef HAVE_XKB
24067 if (dpyinfo->xkb_desc)
24068 {
24069 KeySym sym;
24070 int overflow;
24071
24072
24073
24074
24075
24076
24077
24078
24079 if (!XkbTranslateKeyCode (dpyinfo->xkb_desc,
24080 keycode, state,
24081 &mods_rtrn, &keysym))
24082 goto xi_done_keysym;
24083
24084
24085
24086 sym = keysym, overflow = 0;
24087
24088
24089
24090
24091 nbytes = XkbTranslateKeySym (dpyinfo->display,
24092 &keysym,
24093 state & ~mods_rtrn,
24094 copy_bufptr,
24095 copy_bufsiz,
24096 &overflow);
24097 if (overflow)
24098 {
24099 copy_bufptr
24100 = SAFE_ALLOCA ((copy_bufsiz += overflow)
24101 * sizeof *copy_bufptr);
24102 overflow = 0;
24103
24104
24105
24106 nbytes = XkbTranslateKeySym (dpyinfo->display,
24107 &sym,
24108 state & ~mods_rtrn,
24109 copy_bufptr,
24110 copy_bufsiz,
24111 &overflow);
24112
24113 if (overflow)
24114 nbytes = 0;
24115 }
24116
24117 coding = Qnil;
24118 }
24119 else
24120 #endif
24121 {
24122
24123
24124
24125
24126
24127
24128 old_state = xkey.state;
24129 xkey.state &= ~ControlMask;
24130 xkey.state &= ~(dpyinfo->meta_mod_mask
24131 | dpyinfo->super_mod_mask
24132 | dpyinfo->hyper_mod_mask
24133 | dpyinfo->alt_mod_mask);
24134
24135 nbytes = XLookupString (&xkey, copy_bufptr,
24136 copy_bufsiz, &keysym,
24137 NULL);
24138
24139 xkey.state = old_state;
24140 }
24141 }
24142
24143 inev.ie.modifiers = x_x_to_emacs_modifiers (dpyinfo, state);
24144
24145 #ifdef XK_F1
24146 if (x_dnd_in_progress
24147 && xev->deviceid == x_dnd_keyboard_device
24148 && keysym == XK_F1)
24149 {
24150 x_dnd_xm_use_help = true;
24151 goto xi_done_keysym;
24152 }
24153 #endif
24154
24155
24156
24157 if (keysym == dpyinfo->quit_keysym
24158 && (xev->time - dpyinfo->quit_keysym_time
24159 <= 350))
24160 {
24161 Vquit_flag = Qt;
24162 goto xi_done_keysym;
24163 }
24164
24165 if (keysym == dpyinfo->quit_keysym)
24166 {
24167
24168
24169 dpyinfo->quit_keysym_time = xev->time;
24170 goto xi_done_keysym;
24171 }
24172
24173
24174
24175 if (keysym >= 32 && keysym < 128)
24176
24177 {
24178 inev.ie.kind = ASCII_KEYSTROKE_EVENT;
24179 inev.ie.code = keysym;
24180
24181 if (source)
24182 inev.ie.device = source->name;
24183
24184 goto xi_done_keysym;
24185 }
24186
24187
24188 if (keysym >= 0x01000000 && keysym <= 0x0110FFFF)
24189 {
24190 if (keysym < 0x01000080)
24191 inev.ie.kind = ASCII_KEYSTROKE_EVENT;
24192 else
24193 inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
24194
24195 if (source)
24196 inev.ie.device = source->name;
24197
24198 inev.ie.code = keysym & 0xFFFFFF;
24199 goto xi_done_keysym;
24200 }
24201
24202
24203 if (HASH_TABLE_P (Vx_keysym_table)
24204 && (c = Fgethash (make_fixnum (keysym),
24205 Vx_keysym_table,
24206 Qnil),
24207 FIXNATP (c)))
24208 {
24209 inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFIXNAT (c))
24210 ? ASCII_KEYSTROKE_EVENT
24211 : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
24212 inev.ie.code = XFIXNAT (c);
24213
24214 if (source)
24215 inev.ie.device = source->name;
24216
24217 goto xi_done_keysym;
24218 }
24219
24220
24221 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
24222 || keysym == XK_Delete
24223 #ifdef XK_ISO_Left_Tab
24224 || (keysym >= XK_ISO_Left_Tab
24225 && keysym <= XK_ISO_Enter)
24226 #endif
24227 || IsCursorKey (keysym)
24228 || IsMiscFunctionKey (keysym)
24229 #ifdef HPUX
24230
24231
24232
24233
24234 || (XK_Select <= keysym && keysym < XK_KP_Space)
24235 #endif
24236 #ifdef XK_dead_circumflex
24237 || keysym == XK_dead_circumflex
24238 #endif
24239 #ifdef XK_dead_grave
24240 || keysym == XK_dead_grave
24241 #endif
24242 #ifdef XK_dead_tilde
24243 || keysym == XK_dead_tilde
24244 #endif
24245 #ifdef XK_dead_diaeresis
24246 || keysym == XK_dead_diaeresis
24247 #endif
24248 #ifdef XK_dead_macron
24249 || keysym == XK_dead_macron
24250 #endif
24251 #ifdef XK_dead_degree
24252 || keysym == XK_dead_degree
24253 #endif
24254 #ifdef XK_dead_acute
24255 || keysym == XK_dead_acute
24256 #endif
24257 #ifdef XK_dead_cedilla
24258 || keysym == XK_dead_cedilla
24259 #endif
24260 #ifdef XK_dead_breve
24261 || keysym == XK_dead_breve
24262 #endif
24263 #ifdef XK_dead_ogonek
24264 || keysym == XK_dead_ogonek
24265 #endif
24266 #ifdef XK_dead_caron
24267 || keysym == XK_dead_caron
24268 #endif
24269 #ifdef XK_dead_doubleacute
24270 || keysym == XK_dead_doubleacute
24271 #endif
24272 #ifdef XK_dead_abovedot
24273 || keysym == XK_dead_abovedot
24274 #endif
24275 #ifdef XK_dead_abovering
24276 || keysym == XK_dead_abovering
24277 #endif
24278 #ifdef XK_dead_belowdot
24279 || keysym == XK_dead_belowdot
24280 #endif
24281 #ifdef XK_dead_voiced_sound
24282 || keysym == XK_dead_voiced_sound
24283 #endif
24284 #ifdef XK_dead_semivoiced_sound
24285 || keysym == XK_dead_semivoiced_sound
24286 #endif
24287 #ifdef XK_dead_hook
24288 || keysym == XK_dead_hook
24289 #endif
24290 #ifdef XK_dead_horn
24291 || keysym == XK_dead_horn
24292 #endif
24293 #ifdef XK_dead_stroke
24294 || keysym == XK_dead_stroke
24295 #endif
24296 #ifdef XK_dead_abovecomma
24297 || keysym == XK_dead_abovecomma
24298 #endif
24299 || IsKeypadKey (keysym)
24300 || IsFunctionKey (keysym)
24301
24302 || (keysym & (1 << 28))
24303 || (keysym != NoSymbol && nbytes == 0))
24304 && ! (IsModifierKey (keysym)
24305
24306
24307
24308
24309
24310 #if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
24311 || (XK_ISO_Lock <= keysym
24312 && keysym <= XK_ISO_Last_Group_Lock)
24313 #endif
24314 ))
24315 {
24316 STORE_KEYSYM_FOR_DEBUG (keysym);
24317
24318
24319 inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
24320 inev.ie.code = keysym;
24321
24322 if (source)
24323 inev.ie.device = source->name;
24324
24325 goto xi_done_keysym;
24326 }
24327
24328 for (i = 0; i < nbytes; i++)
24329 {
24330 STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]);
24331 }
24332
24333 if (nbytes)
24334 {
24335 inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
24336 inev.ie.arg = make_unibyte_string (copy_bufptr, nbytes);
24337
24338 Fput_text_property (make_fixnum (0), make_fixnum (nbytes),
24339 Qcoding, coding, inev.ie.arg);
24340
24341 if (source)
24342 inev.ie.device = source->name;
24343 }
24344 goto xi_done_keysym;
24345 }
24346
24347 goto XI_OTHER;
24348 }
24349
24350 #if defined USE_GTK && !defined HAVE_GTK3
24351 case XI_RawKeyPress:
24352 {
24353 XIRawEvent *raw_event = (XIRawEvent *) xi_event;
24354
24355
24356
24357
24358 dpyinfo->pending_keystroke_time = raw_event->time;
24359 dpyinfo->pending_keystroke_source = raw_event->sourceid;
24360 dpyinfo->pending_keystroke_time_special_p = true;
24361 goto XI_OTHER;
24362 }
24363 #endif
24364
24365 case XI_KeyRelease:
24366 #if defined HAVE_X_I18N || defined USE_GTK || defined USE_LUCID
24367 {
24368 XKeyPressedEvent xkey;
24369
24370 memset (&xkey, 0, sizeof xkey);
24371
24372 xkey.type = KeyRelease;
24373 xkey.serial = xev->serial;
24374 xkey.send_event = xev->send_event;
24375 xkey.display = dpyinfo->display;
24376 xkey.window = xev->event;
24377 xkey.root = xev->root;
24378 xkey.subwindow = xev->child;
24379 xkey.time = xev->time;
24380 xkey.state = xi_convert_event_keyboard_state (xev);
24381 xkey.x = lrint (xev->event_x);
24382 xkey.y = lrint (xev->event_y);
24383 xkey.x_root = lrint (xev->root_x);
24384 xkey.y_root = lrint (xev->root_y);
24385
24386
24387
24388 xi_convert_button_state (&xev->buttons, &xkey.state);
24389
24390 xkey.keycode = xev->detail;
24391 xkey.same_screen = True;
24392
24393 #ifdef USE_LUCID
24394 if (!popup_activated ())
24395 {
24396 #endif
24397 #ifdef HAVE_X_I18N
24398 if (x_filter_event (dpyinfo, (XEvent *) &xkey))
24399 *finish = X_EVENT_DROP;
24400 #elif defined USE_GTK
24401 f = x_any_window_to_frame (xkey->event);
24402
24403 if (f && xg_filter_key (f, event))
24404 *finish = X_EVENT_DROP;
24405 #endif
24406 #ifdef USE_LUCID
24407 }
24408 else
24409 {
24410
24411
24412
24413
24414
24415
24416
24417 }
24418 #endif
24419 }
24420 #endif
24421
24422 goto XI_OTHER;
24423
24424 case XI_PropertyEvent:
24425 goto XI_OTHER;
24426
24427 case XI_HierarchyChanged:
24428 {
24429 XIHierarchyEvent *hev;
24430 XIDeviceInfo *info;
24431 int i, ndevices, n_disabled, *disabled;
24432 struct xi_device_t *device;
24433 bool any_changed;
24434
24435 any_changed = false;
24436 hev = (XIHierarchyEvent *) xi_event;
24437 disabled = SAFE_ALLOCA (sizeof *disabled * hev->num_info);
24438 n_disabled = 0;
24439
24440 for (i = 0; i < hev->num_info; ++i)
24441 {
24442 if (hev->info[i].flags & XIDeviceEnabled)
24443 {
24444
24445
24446
24447 if (n_disabled)
24448 {
24449 xi_disable_devices (dpyinfo, disabled, n_disabled);
24450 n_disabled = 0;
24451
24452
24453
24454
24455 any_changed = true;
24456 }
24457
24458
24459
24460
24461
24462
24463
24464 if (!xi_device_from_id (dpyinfo,
24465 hev->info[i].deviceid))
24466 {
24467 x_catch_errors (dpyinfo->display);
24468 info = XIQueryDevice (dpyinfo->display,
24469 hev->info[i].deviceid,
24470 &ndevices);
24471 x_uncatch_errors ();
24472
24473 if (info && info->enabled)
24474 {
24475 dpyinfo->devices
24476 = xrealloc (dpyinfo->devices,
24477 (sizeof *dpyinfo->devices
24478 * ++dpyinfo->num_devices));
24479 memset (dpyinfo->devices + dpyinfo->num_devices - 1,
24480 0, sizeof *dpyinfo->devices);
24481 device = &dpyinfo->devices[dpyinfo->num_devices - 1];
24482 xi_populate_device_from_info (dpyinfo, device, info);
24483 }
24484
24485 if (info)
24486 XIFreeDeviceInfo (info);
24487 }
24488 }
24489 else if (hev->info[i].flags & XIDeviceDisabled)
24490 disabled[n_disabled++] = hev->info[i].deviceid;
24491 else if (hev->info[i].flags & XISlaveDetached
24492 || hev->info[i].flags & XISlaveAttached)
24493 {
24494 device = xi_device_from_id (dpyinfo, hev->info[i].deviceid);
24495 x_catch_errors (dpyinfo->display);
24496 info = XIQueryDevice (dpyinfo->display, hev->info[i].deviceid,
24497 &ndevices);
24498 x_uncatch_errors ();
24499
24500 if (info)
24501 {
24502 if (device)
24503 {
24504 device->use = info->use;
24505 device->attachment = info->attachment;
24506 }
24507
24508
24509
24510
24511
24512
24513 XIFreeDeviceInfo (info);
24514 }
24515 }
24516 }
24517
24518
24519
24520 xi_disable_devices (dpyinfo, disabled, n_disabled);
24521
24522
24523
24524
24525
24526 if (any_changed || n_disabled)
24527 xi_handle_focus_change (dpyinfo);
24528
24529 goto XI_OTHER;
24530 }
24531
24532 case XI_DeviceChanged:
24533 {
24534 XIDeviceChangedEvent *device_changed;
24535 struct xi_device_t *device;
24536
24537 device_changed = (XIDeviceChangedEvent *) xi_event;
24538 device = xi_device_from_id (dpyinfo, device_changed->deviceid);
24539
24540
24541
24542
24543 if (!device)
24544 goto XI_OTHER;
24545
24546
24547
24548 xi_handle_device_changed (dpyinfo, device, device_changed);
24549 goto XI_OTHER;
24550 }
24551
24552 #ifdef HAVE_XINPUT2_2
24553 case XI_TouchBegin:
24554 {
24555 struct xi_device_t *device, *source;
24556 bool menu_bar_p = false, tool_bar_p = false;
24557 #ifdef HAVE_GTK3
24558 GdkRectangle test_rect;
24559 #endif
24560 device = xi_device_from_id (dpyinfo, xev->deviceid);
24561 source = xi_device_from_id (dpyinfo, xev->sourceid);
24562 x_display_set_last_user_time (dpyinfo, xev->time,
24563 xev->send_event, true);
24564
24565
24566
24567
24568
24569
24570
24571 if (!device || device->use == XIMasterPointer)
24572 goto XI_OTHER;
24573
24574 if (xi_find_touch_point (device, xev->detail))
24575 emacs_abort ();
24576
24577 f = x_window_to_frame (dpyinfo, xev->event);
24578
24579 if (f)
24580
24581
24582 xi_compute_root_window_offset (f, xev);
24583
24584 #ifdef HAVE_GTK3
24585 menu_bar_p = (f && FRAME_X_OUTPUT (f)->menubar_widget
24586 && xg_event_is_for_menubar (f, event));
24587 if (f && FRAME_X_OUTPUT (f)->toolbar_widget)
24588 {
24589 int scale = xg_get_scale (f);
24590
24591 test_rect.x = xev->event_x / scale;
24592 test_rect.y = xev->event_y / scale;
24593 test_rect.width = 1;
24594 test_rect.height = 1;
24595
24596 tool_bar_p = gtk_widget_intersect (FRAME_X_OUTPUT (f)->toolbar_widget,
24597 &test_rect, NULL);
24598 }
24599 #endif
24600
24601 #ifndef HAVE_EXT_TOOL_BAR
24602
24603
24604 if (device->direct_p
24605 && WINDOWP (f->tool_bar_window)
24606 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
24607 {
24608 Lisp_Object window;
24609 int x = xev->event_x;
24610 int y = xev->event_y;
24611
24612 window = window_from_coordinates (f, x, y, 0, true, true);
24613
24614
24615
24616
24617
24618
24619
24620 tool_bar_p = EQ (window, f->tool_bar_window);
24621
24622
24623
24624
24625
24626 if (tool_bar_p)
24627 {
24628
24629
24630
24631
24632
24633
24634
24635 if (!NILP (Vmouse_highlight))
24636 {
24637 note_mouse_highlight (f, x, y);
24638
24639
24640
24641
24642 memset (&dpyinfo->last_mouse_glyph, 0,
24643 sizeof dpyinfo->last_mouse_glyph);
24644 dpyinfo->last_mouse_glyph_frame = f;
24645 }
24646
24647 handle_tool_bar_click_with_device (f, x, y, true, 0,
24648 (source
24649 ? source->name : Qt));
24650
24651
24652
24653 x_flush_dirty_back_buffer_on (f);
24654
24655
24656
24657
24658
24659 FRAME_OUTPUT_DATA (f)->tool_bar_touch_device
24660 = device->device_id;
24661 FRAME_OUTPUT_DATA (f)->tool_bar_touch_id = xev->detail;
24662
24663 goto XI_OTHER;
24664 }
24665 }
24666 #endif
24667
24668 if (!menu_bar_p && !tool_bar_p)
24669 {
24670 if (f && device->direct_p)
24671 {
24672 *finish = X_EVENT_DROP;
24673
24674 x_catch_errors (dpyinfo->display);
24675
24676 if (x_input_grab_touch_events)
24677 XIAllowTouchEvents (dpyinfo->display,
24678 xev->deviceid,
24679 xev->detail, xev->event,
24680 XIAcceptTouch);
24681
24682 if (!x_had_errors_p (dpyinfo->display))
24683 {
24684 xi_link_touch_point (device, xev->detail,
24685 xev->event_x,
24686 xev->event_y, f);
24687
24688 inev.ie.kind = TOUCHSCREEN_BEGIN_EVENT;
24689 inev.ie.timestamp = xev->time;
24690 XSETFRAME (inev.ie.frame_or_window, f);
24691 XSETINT (inev.ie.x, lrint (xev->event_x));
24692 XSETINT (inev.ie.y, lrint (xev->event_y));
24693 XSETINT (inev.ie.arg, xev->detail);
24694
24695 if (source)
24696 inev.ie.device = source->name;
24697 }
24698
24699 x_uncatch_errors ();
24700 }
24701 #ifndef HAVE_GTK3
24702 else if (x_input_grab_touch_events)
24703 {
24704 x_ignore_errors_for_next_request (dpyinfo, 0);
24705 XIAllowTouchEvents (dpyinfo->display, xev->deviceid,
24706 xev->detail, xev->event, XIRejectTouch);
24707 x_stop_ignoring_errors (dpyinfo);
24708 }
24709 #endif
24710 }
24711 else
24712 {
24713 #ifdef HAVE_GTK3
24714 bool was_waiting_for_input = waiting_for_input;
24715
24716
24717
24718 if (waiting_for_input)
24719 waiting_for_input = 0;
24720 set_frame_menubar (f, true);
24721 waiting_for_input = was_waiting_for_input;
24722 #endif
24723 }
24724
24725 goto XI_OTHER;
24726 }
24727
24728 case XI_TouchOwnership:
24729 {
24730 struct xi_device_t *device;
24731 struct xi_touch_point_t *touchpoint;
24732 XITouchOwnershipEvent *event;
24733
24734
24735
24736
24737 event = (XITouchOwnershipEvent *) xi_event;
24738 device = xi_device_from_id (dpyinfo, event->deviceid);
24739
24740 if (!device || device->use == XIMasterPointer)
24741 goto XI_OTHER;
24742
24743 touchpoint = xi_find_touch_point (device, event->touchid);
24744
24745 if (!touchpoint)
24746 goto XI_OTHER;
24747
24748
24749
24750 touchpoint->ownership = TOUCH_OWNERSHIP_SELF;
24751
24752 goto XI_OTHER;
24753 }
24754
24755 case XI_TouchUpdate:
24756 {
24757 struct xi_device_t *device, *source;
24758 struct xi_touch_point_t *touchpoint;
24759 Lisp_Object arg = Qnil;
24760
24761
24762
24763
24764
24765
24766
24767
24768
24769 if (xev->flags & XITouchPendingEnd)
24770 goto XI_OTHER;
24771
24772 device = xi_device_from_id (dpyinfo, xev->deviceid);
24773 source = xi_device_from_id (dpyinfo, xev->sourceid);
24774 x_display_set_last_user_time (dpyinfo, xev->time,
24775 xev->send_event, true);
24776
24777
24778
24779
24780
24781
24782
24783 if (!device || device->use == XIMasterPointer)
24784 goto XI_OTHER;
24785
24786 touchpoint = xi_find_touch_point (device, xev->detail);
24787
24788 if (!touchpoint
24789
24790
24791 || (touchpoint->x == lrint (xev->event_x)
24792 && touchpoint->y == lrint (xev->event_y)))
24793 goto XI_OTHER;
24794
24795 touchpoint->x = lrint (xev->event_x);
24796 touchpoint->y = lrint (xev->event_y);
24797
24798 f = x_window_to_frame (dpyinfo, xev->event);
24799
24800 if (f && device->direct_p)
24801 {
24802 inev.ie.kind = TOUCHSCREEN_UPDATE_EVENT;
24803 inev.ie.timestamp = xev->time;
24804 XSETFRAME (inev.ie.frame_or_window, f);
24805
24806 for (touchpoint = device->touchpoints;
24807 touchpoint; touchpoint = touchpoint->next)
24808 {
24809 if (touchpoint->frame == f)
24810 arg = Fcons (list3i (touchpoint->x, touchpoint->y,
24811 lrint (touchpoint->number)),
24812 arg);
24813 }
24814
24815 if (source)
24816 inev.ie.device = source->name;
24817
24818 inev.ie.arg = arg;
24819 }
24820
24821 goto XI_OTHER;
24822 }
24823
24824 case XI_TouchEnd:
24825 {
24826 struct xi_device_t *device, *source;
24827 int state;
24828
24829 device = xi_device_from_id (dpyinfo, xev->deviceid);
24830 source = xi_device_from_id (dpyinfo, xev->sourceid);
24831 x_display_set_last_user_time (dpyinfo, xev->time,
24832 xev->send_event, true);
24833
24834
24835
24836
24837
24838
24839
24840 if (!device || device->use == XIMasterPointer)
24841 goto XI_OTHER;
24842
24843 state = xi_unlink_touch_point (xev->detail, device);
24844
24845 if (state)
24846 {
24847 f = x_window_to_frame (dpyinfo, xev->event);
24848
24849 if (f && device->direct_p)
24850 {
24851 inev.ie.kind = TOUCHSCREEN_END_EVENT;
24852 inev.ie.timestamp = xev->time;
24853 inev.ie.modifiers = state != 2;
24854
24855 XSETFRAME (inev.ie.frame_or_window, f);
24856 XSETINT (inev.ie.x, lrint (xev->event_x));
24857 XSETINT (inev.ie.y, lrint (xev->event_y));
24858 XSETINT (inev.ie.arg, xev->detail);
24859
24860 if (source)
24861 inev.ie.device = source->name;
24862 }
24863 }
24864
24865 #ifndef HAVE_EXT_TOOL_BAR
24866
24867
24868
24869 if (!f)
24870 f = x_window_to_frame (dpyinfo, xev->event);
24871
24872 if (f && (FRAME_OUTPUT_DATA (f)->tool_bar_touch_id
24873 == xev->detail))
24874 {
24875 if (f->last_tool_bar_item != -1)
24876 handle_tool_bar_click_with_device (f, xev->event_x,
24877 xev->event_y,
24878 false, 0,
24879 (source
24880 ? source->name
24881 : Qnil));
24882
24883
24884 note_mouse_highlight (f, -1, -1);
24885 x_flush_dirty_back_buffer_on (f);
24886
24887
24888 FRAME_OUTPUT_DATA (f)->tool_bar_touch_device = 0;
24889 }
24890 #endif
24891
24892 goto XI_OTHER;
24893 }
24894
24895 #endif
24896
24897 #ifdef HAVE_XINPUT2_4
24898 case XI_GesturePinchBegin:
24899 case XI_GesturePinchUpdate:
24900 {
24901 XIGesturePinchEvent *pev = (XIGesturePinchEvent *) xi_event;
24902 struct xi_device_t *device, *source;
24903
24904 device = xi_device_from_id (dpyinfo, pev->deviceid);
24905 source = xi_device_from_id (dpyinfo, pev->sourceid);
24906 x_display_set_last_user_time (dpyinfo, pev->time,
24907 pev->send_event, true);
24908
24909 if (!device || device->use != XIMasterPointer)
24910 goto XI_OTHER;
24911
24912 #ifdef HAVE_XWIDGETS
24913 struct xwidget_view *xvw = xwidget_view_from_window (pev->event);
24914
24915 if (xvw)
24916 {
24917 *finish = X_EVENT_DROP;
24918 xwidget_pinch (xvw, pev);
24919 goto XI_OTHER;
24920 }
24921 #endif
24922
24923 any = x_window_to_frame (dpyinfo, pev->event);
24924
24925 if (any)
24926 {
24927 if (pev->event == FRAME_X_WINDOW (any))
24928 xi_compute_root_window_offset_pinch (any, pev);
24929
24930 inev.ie.kind = PINCH_EVENT;
24931 inev.ie.modifiers
24932 = x_x_to_emacs_modifiers (dpyinfo, pev->mods.effective);
24933
24934 XSETINT (inev.ie.x, lrint (pev->event_x));
24935 XSETINT (inev.ie.y, lrint (pev->event_y));
24936 XSETFRAME (inev.ie.frame_or_window, any);
24937 inev.ie.arg = list4 (make_float (pev->delta_x),
24938 make_float (pev->delta_y),
24939 make_float (pev->scale),
24940 make_float (pev->delta_angle));
24941
24942 if (source)
24943 inev.ie.device = source->name;
24944 }
24945
24946
24947
24948 *finish = X_EVENT_DROP;
24949 goto XI_OTHER;
24950 }
24951
24952 case XI_GesturePinchEnd:
24953 {
24954 #if defined HAVE_XWIDGETS
24955 XIGesturePinchEvent *pev = (XIGesturePinchEvent *) xi_event;
24956 struct xwidget_view *xvw = xwidget_view_from_window (pev->event);
24957
24958 if (xvw)
24959 xwidget_pinch (xvw, pev);
24960 #endif
24961 *finish = X_EVENT_DROP;
24962 goto XI_OTHER;
24963 }
24964 #endif
24965 default:
24966 goto XI_OTHER;
24967 }
24968
24969 xi_done_keysym:
24970 #ifdef HAVE_X_I18N
24971 if (f)
24972 {
24973 struct window *w = XWINDOW (f->selected_window);
24974 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
24975
24976 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
24977 xic_set_statusarea (f);
24978 }
24979 #endif
24980 if (must_free_data)
24981 XFreeEventData (dpyinfo->display, &event->xcookie);
24982 goto done_keysym;
24983
24984 XI_OTHER:
24985 if (must_free_data)
24986 XFreeEventData (dpyinfo->display, &event->xcookie);
24987 goto OTHER;
24988 }
24989 #endif
24990
24991 default:
24992 #ifdef HAVE_XKB
24993 if (dpyinfo->supports_xkb
24994 && event->type == dpyinfo->xkb_event_type)
24995 {
24996 XkbEvent *xkbevent = (XkbEvent *) event;
24997
24998 if (xkbevent->any.xkb_type == XkbNewKeyboardNotify
24999 || xkbevent->any.xkb_type == XkbMapNotify)
25000 {
25001 XkbRefreshKeyboardMapping (&xkbevent->map);
25002
25003 if (dpyinfo->xkb_desc)
25004 {
25005 if (XkbGetUpdatedMap (dpyinfo->display,
25006 (XkbKeySymsMask
25007 | XkbKeyTypesMask
25008 | XkbModifierMapMask
25009 | XkbVirtualModsMask),
25010 dpyinfo->xkb_desc) == Success)
25011 XkbGetNames (dpyinfo->display, XkbAllNamesMask,
25012 dpyinfo->xkb_desc);
25013 else
25014 {
25015 XkbFreeKeyboard (dpyinfo->xkb_desc,
25016 XkbAllComponentsMask, True);
25017 dpyinfo->xkb_desc = NULL;
25018 }
25019 }
25020 else
25021 {
25022 dpyinfo->xkb_desc = XkbGetMap (dpyinfo->display,
25023 (XkbKeySymsMask
25024 | XkbKeyTypesMask
25025 | XkbModifierMapMask
25026 | XkbVirtualModsMask),
25027 XkbUseCoreKbd);
25028
25029 if (dpyinfo->xkb_desc)
25030 XkbGetNames (dpyinfo->display, XkbAllNamesMask,
25031 dpyinfo->xkb_desc);
25032 }
25033
25034 x_find_modifier_meanings (dpyinfo);
25035 }
25036 else if (x_dnd_in_progress
25037 && xkbevent->any.xkb_type == XkbStateNotify)
25038 x_dnd_keyboard_state = (xkbevent->state.mods
25039 | xkbevent->state.ptr_buttons);
25040 }
25041 #endif
25042 #ifdef HAVE_XSHAPE
25043 if (dpyinfo->xshape_supported_p
25044 && event->type == dpyinfo->xshape_event_base + ShapeNotify
25045 && x_dnd_in_progress && x_dnd_use_toplevels
25046 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
25047 {
25048 #ifndef USE_GTK
25049 XEvent xevent;
25050 #endif
25051 XShapeEvent *xse = (XShapeEvent *) event;
25052 #if defined HAVE_XCB_SHAPE && defined HAVE_XCB_SHAPE_INPUT_RECTS
25053 xcb_shape_get_rectangles_cookie_t bounding_rect_cookie;
25054 xcb_shape_get_rectangles_reply_t *bounding_rect_reply;
25055 xcb_rectangle_iterator_t bounding_rect_iterator;
25056
25057 xcb_shape_get_rectangles_cookie_t input_rect_cookie;
25058 xcb_shape_get_rectangles_reply_t *input_rect_reply;
25059 xcb_rectangle_iterator_t input_rect_iterator;
25060
25061 xcb_generic_error_t *error;
25062 #else
25063 XRectangle *rects;
25064 int rc, ordering;
25065 #endif
25066
25067
25068
25069
25070 #ifndef USE_GTK
25071 while (XPending (dpyinfo->display))
25072 {
25073 XNextEvent (dpyinfo->display, &xevent);
25074
25075 if (xevent.type == dpyinfo->xshape_event_base + ShapeNotify
25076 && ((XShapeEvent *) &xevent)->window == xse->window)
25077 xse = (XShapeEvent *) &xevent;
25078 else
25079 {
25080 XPutBackEvent (dpyinfo->display, &xevent);
25081 break;
25082 }
25083 }
25084 #endif
25085
25086 for (struct x_client_list_window *tem = x_dnd_toplevels; tem;
25087 tem = tem->next)
25088 {
25089 if (tem->window == xse->window)
25090 {
25091 if (tem->n_input_rects != -1)
25092 xfree (tem->input_rects);
25093 if (tem->n_bounding_rects != -1)
25094 xfree (tem->bounding_rects);
25095
25096 tem->n_input_rects = -1;
25097 tem->n_bounding_rects = -1;
25098
25099 #if defined HAVE_XCB_SHAPE && defined HAVE_XCB_SHAPE_INPUT_RECTS
25100 bounding_rect_cookie = xcb_shape_get_rectangles (dpyinfo->xcb_connection,
25101 (xcb_window_t) xse->window,
25102 XCB_SHAPE_SK_BOUNDING);
25103 if (dpyinfo->xshape_major > 1
25104 || (dpyinfo->xshape_major == 1
25105 && dpyinfo->xshape_minor >= 1))
25106 input_rect_cookie
25107 = xcb_shape_get_rectangles (dpyinfo->xcb_connection,
25108 (xcb_window_t) xse->window,
25109 XCB_SHAPE_SK_INPUT);
25110
25111 bounding_rect_reply = xcb_shape_get_rectangles_reply (dpyinfo->xcb_connection,
25112 bounding_rect_cookie,
25113 &error);
25114
25115 if (bounding_rect_reply)
25116 {
25117 bounding_rect_iterator
25118 = xcb_shape_get_rectangles_rectangles_iterator (bounding_rect_reply);
25119 tem->n_bounding_rects = bounding_rect_iterator.rem + 1;
25120 tem->bounding_rects = xmalloc (tem->n_bounding_rects
25121 * sizeof *tem->bounding_rects);
25122 tem->n_bounding_rects = 0;
25123
25124 for (; bounding_rect_iterator.rem; xcb_rectangle_next (&bounding_rect_iterator))
25125 {
25126 tem->bounding_rects[tem->n_bounding_rects].x
25127 = bounding_rect_iterator.data->x;
25128 tem->bounding_rects[tem->n_bounding_rects].y
25129 = bounding_rect_iterator.data->y;
25130 tem->bounding_rects[tem->n_bounding_rects].width
25131 = bounding_rect_iterator.data->width;
25132 tem->bounding_rects[tem->n_bounding_rects].height
25133 = bounding_rect_iterator.data->height;
25134
25135 tem->n_bounding_rects++;
25136 }
25137
25138 free (bounding_rect_reply);
25139 }
25140 else
25141 free (error);
25142
25143 if (dpyinfo->xshape_major > 1
25144 || (dpyinfo->xshape_major == 1
25145 && dpyinfo->xshape_minor >= 1))
25146 {
25147 input_rect_reply = xcb_shape_get_rectangles_reply (dpyinfo->xcb_connection,
25148 input_rect_cookie, &error);
25149
25150 if (input_rect_reply)
25151 {
25152 input_rect_iterator
25153 = xcb_shape_get_rectangles_rectangles_iterator (input_rect_reply);
25154 tem->n_input_rects = input_rect_iterator.rem + 1;
25155 tem->input_rects = xmalloc (tem->n_input_rects
25156 * sizeof *tem->input_rects);
25157 tem->n_input_rects = 0;
25158
25159 for (; input_rect_iterator.rem; xcb_rectangle_next (&input_rect_iterator))
25160 {
25161 tem->input_rects[tem->n_input_rects].x
25162 = input_rect_iterator.data->x;
25163 tem->input_rects[tem->n_input_rects].y
25164 = input_rect_iterator.data->y;
25165 tem->input_rects[tem->n_input_rects].width
25166 = input_rect_iterator.data->width;
25167 tem->input_rects[tem->n_input_rects].height
25168 = input_rect_iterator.data->height;
25169
25170 tem->n_input_rects++;
25171 }
25172
25173 free (input_rect_reply);
25174 }
25175 else
25176 free (error);
25177 }
25178 #else
25179 x_catch_errors (dpyinfo->display);
25180 rects = XShapeGetRectangles (dpyinfo->display,
25181 xse->window,
25182 ShapeBounding,
25183 &count, &ordering);
25184 rc = x_had_errors_p (dpyinfo->display);
25185 x_uncatch_errors_after_check ();
25186
25187
25188
25189 if (!rc)
25190 {
25191 tem->n_bounding_rects = count;
25192 tem->bounding_rects
25193 = xmalloc (sizeof *tem->bounding_rects * count);
25194 memcpy (tem->bounding_rects, rects,
25195 sizeof *tem->bounding_rects * count);
25196
25197 XFree (rects);
25198 }
25199
25200 #ifdef ShapeInput
25201 if (dpyinfo->xshape_major > 1
25202 || (dpyinfo->xshape_major == 1
25203 && dpyinfo->xshape_minor >= 1))
25204 {
25205 x_catch_errors (dpyinfo->display);
25206 rects = XShapeGetRectangles (dpyinfo->display,
25207 xse->window, ShapeInput,
25208 &count, &ordering);
25209 rc = x_had_errors_p (dpyinfo->display);
25210 x_uncatch_errors_after_check ();
25211
25212
25213
25214 if (!rc)
25215 {
25216 tem->n_input_rects = count;
25217 tem->input_rects
25218 = xmalloc (sizeof *tem->input_rects * count);
25219 memcpy (tem->input_rects, rects,
25220 sizeof *tem->input_rects * count);
25221
25222 XFree (rects);
25223 }
25224 }
25225 #endif
25226 #endif
25227
25228
25229
25230
25231 if (tem->n_input_rects != -1
25232 && tem->n_bounding_rects == tem->n_input_rects
25233 && !memcmp (tem->bounding_rects, tem->input_rects,
25234 tem->n_input_rects * sizeof *tem->input_rects))
25235 {
25236 xfree (tem->input_rects);
25237 tem->n_input_rects = -1;
25238 }
25239
25240
25241
25242
25243 if (tem->n_input_rects == -1
25244 && tem->n_bounding_rects == 1
25245 && tem->bounding_rects[0].width == tem->width
25246 && tem->bounding_rects[0].height == tem->height
25247 && tem->bounding_rects[0].x == -tem->border_width
25248 && tem->bounding_rects[0].y == -tem->border_width)
25249 {
25250 xfree (tem->bounding_rects);
25251 tem->n_bounding_rects = -1;
25252 }
25253
25254 break;
25255 }
25256 }
25257 }
25258 #endif
25259 #if defined HAVE_XRANDR && !defined USE_GTK
25260 if (dpyinfo->xrandr_supported_p
25261 && (event->type == (dpyinfo->xrandr_event_base
25262 + RRScreenChangeNotify)
25263 || event->type == (dpyinfo->xrandr_event_base
25264 + RRNotify)))
25265 {
25266 Time timestamp;
25267 Lisp_Object current_monitors;
25268 XRRScreenChangeNotifyEvent *notify;
25269
25270 if (event->type == (dpyinfo->xrandr_event_base
25271 + RRScreenChangeNotify))
25272 XRRUpdateConfiguration ((XEvent *) event);
25273
25274 if (event->type == (dpyinfo->xrandr_event_base
25275 + RRScreenChangeNotify))
25276 {
25277 notify = ((XRRScreenChangeNotifyEvent *) event);
25278 timestamp = notify->timestamp;
25279
25280
25281
25282 if (notify->root == dpyinfo->root_window)
25283 {
25284 dpyinfo->screen_width = notify->width;
25285 dpyinfo->screen_height = notify->height;
25286 dpyinfo->screen_mm_width = notify->mwidth;
25287 dpyinfo->screen_mm_height = notify->mheight;
25288 }
25289 }
25290 else
25291 timestamp = 0;
25292
25293 if (x_find_monitors_changed_event (dpyinfo))
25294
25295
25296 goto OTHER;
25297
25298 inev.ie.kind = MONITORS_CHANGED_EVENT;
25299 inev.ie.timestamp = timestamp;
25300 XSETTERMINAL (inev.ie.arg, dpyinfo->terminal);
25301
25302
25303
25304
25305 current_monitors
25306 = Fx_display_monitor_attributes_list (inev.ie.arg);
25307
25308 if (!NILP (Fequal (current_monitors,
25309 dpyinfo->last_monitor_attributes_list)))
25310 inev.ie.kind = NO_EVENT;
25311
25312 dpyinfo->last_monitor_attributes_list = current_monitors;
25313
25314 if (x_dnd_in_progress && x_dnd_update_tooltip)
25315 x_dnd_monitors = current_monitors;
25316
25317 if (inev.ie.kind != NO_EVENT)
25318 x_dnd_update_tooltip_now ();
25319 }
25320 #endif
25321 #ifdef HAVE_XFIXES
25322 if (dpyinfo->xfixes_supported_p
25323 && event->type == (dpyinfo->xfixes_event_base
25324 + XFixesSelectionNotify)
25325 && x_handle_selection_monitor_event (dpyinfo, event))
25326
25327
25328
25329
25330 *finish = X_EVENT_DROP;
25331 #endif
25332 OTHER:
25333 #ifdef USE_X_TOOLKIT
25334 if (*finish != X_EVENT_DROP)
25335 {
25336
25337
25338
25339 if (event->type != ConfigureNotify
25340 || (event->xconfigure.width != 0
25341 && event->xconfigure.height != 0))
25342 {
25343 #if defined USE_X_TOOLKIT && defined HAVE_XINPUT2
25344 XtDispatchEvent (use_copy ? © : (XEvent *) event);
25345 #else
25346 XtDispatchEvent ((XEvent *) event);
25347 #endif
25348 }
25349 }
25350 #endif
25351 #if defined USE_GTK && !defined HAVE_GTK3 && defined HAVE_XINPUT2
25352 if (*finish != X_EVENT_DROP && copy)
25353 {
25354 gtk_main_do_event (copy);
25355 *finish = X_EVENT_DROP;
25356 }
25357
25358 if (copy)
25359 gdk_event_free (copy);
25360 #endif
25361 break;
25362 }
25363
25364 done:
25365 if (inev.ie.kind != NO_EVENT)
25366 {
25367 kbd_buffer_store_buffered_event (&inev, hold_quit);
25368 count++;
25369 }
25370
25371 if (do_help
25372 && !(hold_quit && hold_quit->kind != NO_EVENT))
25373 {
25374 Lisp_Object frame;
25375
25376 if (f)
25377 XSETFRAME (frame, f);
25378 else
25379 frame = Qnil;
25380
25381 if (do_help > 0)
25382 {
25383 any_help_event_p = true;
25384 #ifdef HAVE_XINPUT2
25385 if (gen_help_device)
25386 xi_handle_interaction (dpyinfo, f,
25387 gen_help_device,
25388 gen_help_time);
25389 #endif
25390 gen_help_event (help_echo_string, frame, help_echo_window,
25391 help_echo_object, help_echo_pos);
25392 }
25393 else
25394 {
25395 help_echo_string = Qnil;
25396 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
25397 }
25398 count++;
25399 }
25400
25401 #if defined HAVE_XINPUT2 || defined HAVE_XKB || defined HAVE_X_I18N
25402 SAFE_FREE ();
25403 #endif
25404
25405 return count;
25406 }
25407
25408
25409
25410
25411
25412
25413
25414 #ifdef USE_GTK
25415 static int
25416 #else
25417 int
25418 #endif
25419 x_dispatch_event (XEvent *event, Display *display)
25420 {
25421 struct x_display_info *dpyinfo;
25422 int finish = X_EVENT_NORMAL;
25423
25424 dpyinfo = x_display_info_for_display (display);
25425
25426 if (dpyinfo)
25427 {
25428
25429 block_input ();
25430 handle_one_xevent (dpyinfo, event, &finish, 0);
25431 unblock_input ();
25432 }
25433
25434 return finish;
25435 }
25436
25437
25438
25439
25440
25441
25442
25443
25444
25445 static int
25446 XTread_socket (struct terminal *terminal, struct input_event *hold_quit)
25447 {
25448 int count = 0;
25449 bool event_found = false;
25450 struct x_display_info *dpyinfo = terminal->display_info.x;
25451
25452
25453
25454
25455
25456
25457
25458
25459
25460
25461
25462 if (!x_dnd_unwind_flag
25463 && ((x_dnd_in_progress
25464 && dpyinfo->display == FRAME_X_DISPLAY (x_dnd_frame))
25465 || (x_dnd_waiting_for_finish
25466 && dpyinfo->display == x_dnd_finish_display)))
25467 return 0;
25468
25469 x_clean_failable_requests (dpyinfo);
25470
25471 block_input ();
25472
25473
25474 if (dpyinfo == XTread_socket_fake_io_error)
25475 {
25476 XTread_socket_fake_io_error = 0;
25477 x_io_error_quitter (dpyinfo->display);
25478 }
25479
25480 #ifndef USE_GTK
25481 while (XPending (dpyinfo->display))
25482 {
25483 int finish;
25484 XEvent event;
25485
25486 XNextEvent (dpyinfo->display, &event);
25487
25488 #ifdef HAVE_X_I18N
25489
25490 #ifdef HAVE_XINPUT2
25491 if (event.type != GenericEvent
25492 || !dpyinfo->supports_xi2
25493 || event.xgeneric.extension != dpyinfo->xi2_opcode)
25494 {
25495
25496
25497 #endif
25498 if (x_filter_event (dpyinfo, &event))
25499 continue;
25500 #ifdef HAVE_XINPUT2
25501 }
25502 #endif
25503 #endif
25504 event_found = true;
25505
25506 count += handle_one_xevent (dpyinfo, &event, &finish, hold_quit);
25507
25508 if (finish == X_EVENT_GOTO_OUT)
25509 break;
25510 }
25511
25512 #else
25513
25514
25515
25516
25517
25518
25519
25520
25521
25522 while (gtk_events_pending ())
25523 {
25524 current_count = count;
25525 current_hold_quit = hold_quit;
25526
25527 gtk_main_iteration ();
25528
25529 count = current_count;
25530 current_count = -1;
25531 current_hold_quit = 0;
25532
25533 if (current_finish == X_EVENT_GOTO_OUT)
25534 break;
25535 }
25536
25537
25538 if (xg_pending_quit_event.kind != NO_EVENT)
25539 {
25540
25541
25542 if (FRAME_LIVE_P (XFRAME (xg_pending_quit_event.frame_or_window)))
25543
25544
25545 *hold_quit = xg_pending_quit_event;
25546
25547
25548 xg_pending_quit_event.kind = NO_EVENT;
25549 }
25550 #endif
25551
25552
25553
25554 if (! event_found)
25555 {
25556
25557
25558
25559 x_noop_count++;
25560 if (x_noop_count >= 100)
25561 {
25562 x_noop_count=0;
25563
25564 if (next_noop_dpyinfo == 0)
25565 next_noop_dpyinfo = x_display_list;
25566
25567 XNoOp (next_noop_dpyinfo->display);
25568
25569
25570 next_noop_dpyinfo = next_noop_dpyinfo->next;
25571 }
25572 }
25573
25574
25575
25576 if (dpyinfo->x_pending_autoraise_frame)
25577 {
25578 x_raise_frame (dpyinfo->x_pending_autoraise_frame);
25579 dpyinfo->x_pending_autoraise_frame = NULL;
25580 }
25581
25582 unblock_input ();
25583
25584 return count;
25585 }
25586
25587
25588
25589
25590
25591
25592
25593
25594
25595
25596
25597
25598
25599
25600
25601 static void
25602 x_clip_to_row (struct window *w, struct glyph_row *row,
25603 enum glyph_row_area area, GC gc)
25604 {
25605 struct frame *f = XFRAME (WINDOW_FRAME (w));
25606 XRectangle clip_rect;
25607 int window_x, window_y, window_width;
25608
25609 window_box (w, area, &window_x, &window_y, &window_width, 0);
25610
25611 clip_rect.x = window_x;
25612 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y));
25613 clip_rect.y = max (clip_rect.y, window_y);
25614 clip_rect.width = window_width;
25615 clip_rect.height = row->visible_height;
25616
25617 x_set_clip_rectangles (f, gc, &clip_rect, 1);
25618 }
25619
25620
25621
25622
25623 static void
25624 x_draw_hollow_cursor (struct window *w, struct glyph_row *row)
25625 {
25626 struct frame *f = XFRAME (WINDOW_FRAME (w));
25627 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
25628 Display *dpy = FRAME_X_DISPLAY (f);
25629 int x, y, wd, h;
25630 XGCValues xgcv;
25631 struct glyph *cursor_glyph;
25632 GC gc;
25633
25634
25635
25636 cursor_glyph = get_phys_cursor_glyph (w);
25637 if (cursor_glyph == NULL)
25638 return;
25639
25640
25641 get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h);
25642 wd = w->phys_cursor_width - 1;
25643
25644
25645
25646 xgcv.foreground = f->output_data.x->cursor_pixel;
25647 xgcv.line_width = 1;
25648 if (dpyinfo->scratch_cursor_gc)
25649 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground | GCLineWidth, &xgcv);
25650 else
25651 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_DRAWABLE (f),
25652 GCForeground | GCLineWidth, &xgcv);
25653 gc = dpyinfo->scratch_cursor_gc;
25654
25655
25656
25657
25658 if ((cursor_glyph->resolved_level & 1) != 0
25659 && cursor_glyph->pixel_width > wd)
25660 {
25661 x += cursor_glyph->pixel_width - wd;
25662 if (wd > 0)
25663 wd -= 1;
25664 }
25665
25666 x_clip_to_row (w, row, TEXT_AREA, gc);
25667 x_draw_rectangle (f, gc, x, y, wd, h - 1);
25668 x_reset_clip_rectangles (f, gc);
25669 }
25670
25671
25672
25673
25674
25675
25676
25677
25678
25679 static void
25680 x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text_cursor_kinds kind)
25681 {
25682 struct frame *f = XFRAME (w->frame);
25683 struct glyph *cursor_glyph;
25684
25685
25686
25687
25688 cursor_glyph = get_phys_cursor_glyph (w);
25689 if (cursor_glyph == NULL)
25690 return;
25691
25692
25693 if (cursor_glyph->type == XWIDGET_GLYPH)
25694 return;
25695
25696
25697
25698
25699 if (cursor_glyph->type == IMAGE_GLYPH)
25700 {
25701 struct glyph_row *r;
25702 r = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
25703 draw_phys_cursor_glyph (w, r, DRAW_CURSOR);
25704 }
25705 else
25706 {
25707 Display *dpy = FRAME_X_DISPLAY (f);
25708 Drawable drawable = FRAME_X_DRAWABLE (f);
25709 GC gc = FRAME_DISPLAY_INFO (f)->scratch_cursor_gc;
25710 unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures;
25711 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
25712 XGCValues xgcv;
25713
25714
25715
25716
25717
25718
25719 if (face->background == f->output_data.x->cursor_pixel)
25720 xgcv.background = xgcv.foreground = face->foreground;
25721 else
25722 xgcv.background = xgcv.foreground = f->output_data.x->cursor_pixel;
25723 xgcv.graphics_exposures = False;
25724 xgcv.line_width = 1;
25725
25726 mask |= GCLineWidth;
25727
25728 if (gc)
25729 XChangeGC (dpy, gc, mask, &xgcv);
25730 else
25731 {
25732 gc = XCreateGC (dpy, drawable, mask, &xgcv);
25733 FRAME_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
25734 }
25735
25736 x_clip_to_row (w, row, TEXT_AREA, gc);
25737
25738 if (kind == BAR_CURSOR)
25739 {
25740 int x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
25741
25742 if (width < 0)
25743 width = FRAME_CURSOR_WIDTH (f);
25744 width = min (cursor_glyph->pixel_width, width);
25745
25746 w->phys_cursor_width = width;
25747
25748
25749
25750 if ((cursor_glyph->resolved_level & 1) != 0)
25751 x += cursor_glyph->pixel_width - width;
25752
25753 x_fill_rectangle (f, gc, x,
25754 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
25755 width, row->height, false);
25756 }
25757 else
25758 {
25759 int dummy_x, dummy_y, dummy_h;
25760 int x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
25761
25762 if (width < 0)
25763 width = row->height;
25764
25765 width = min (row->height, width);
25766
25767 get_phys_cursor_geometry (w, row, cursor_glyph, &dummy_x,
25768 &dummy_y, &dummy_h);
25769
25770 if ((cursor_glyph->resolved_level & 1) != 0
25771 && cursor_glyph->pixel_width > w->phys_cursor_width - 1)
25772 x += cursor_glyph->pixel_width - w->phys_cursor_width + 1;
25773 x_fill_rectangle (f, gc, x,
25774 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
25775 row->height - width),
25776 w->phys_cursor_width - 1, width, false);
25777 }
25778
25779 x_reset_clip_rectangles (f, gc);
25780 }
25781 }
25782
25783
25784
25785
25786 static void
25787 x_define_frame_cursor (struct frame *f, Emacs_Cursor cursor)
25788 {
25789 if (!f->pointer_invisible
25790 && f->output_data.x->current_cursor != cursor)
25791 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
25792 f->output_data.x->current_cursor = cursor;
25793 }
25794
25795
25796
25797
25798 static void
25799 x_clear_frame_area (struct frame *f, int x, int y, int width, int height)
25800 {
25801 x_clear_area (f, x, y, width, height);
25802 }
25803
25804
25805
25806
25807 static void
25808 x_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x,
25809 int y, enum text_cursor_kinds cursor_type,
25810 int cursor_width, bool on_p, bool active_p)
25811 {
25812 #ifdef HAVE_X_I18N
25813 struct frame *f = XFRAME (WINDOW_FRAME (w));
25814 #endif
25815
25816 if (on_p)
25817 {
25818 w->phys_cursor_type = cursor_type;
25819 w->phys_cursor_on_p = true;
25820
25821 if (glyph_row->exact_window_width_line_p
25822 && (glyph_row->reversed_p
25823 ? (w->phys_cursor.hpos < 0)
25824 : (w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])))
25825 {
25826 glyph_row->cursor_in_fringe_p = true;
25827 draw_fringe_bitmap (w, glyph_row, glyph_row->reversed_p);
25828 }
25829 else
25830 {
25831 switch (cursor_type)
25832 {
25833 case HOLLOW_BOX_CURSOR:
25834 x_draw_hollow_cursor (w, glyph_row);
25835 break;
25836
25837 case FILLED_BOX_CURSOR:
25838 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
25839 break;
25840
25841 case BAR_CURSOR:
25842 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
25843 break;
25844
25845 case HBAR_CURSOR:
25846 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
25847 break;
25848
25849 case NO_CURSOR:
25850 w->phys_cursor_width = 0;
25851 break;
25852
25853 default:
25854 emacs_abort ();
25855 }
25856 }
25857
25858 #ifdef HAVE_X_I18N
25859 if (w == XWINDOW (f->selected_window))
25860 xic_set_preeditarea (w, x, y);
25861 #endif
25862 }
25863 }
25864
25865
25866
25867
25868
25869
25870 static bool
25871 x_bitmap_icon (struct frame *f, Lisp_Object file)
25872 {
25873 ptrdiff_t bitmap_id;
25874
25875 if (FRAME_X_WINDOW (f) == 0)
25876 return true;
25877
25878
25879 if (f->output_data.x->icon_bitmap > 0)
25880 image_destroy_bitmap (f, f->output_data.x->icon_bitmap);
25881 f->output_data.x->icon_bitmap = 0;
25882
25883 if (STRINGP (file))
25884 {
25885 #ifdef USE_GTK
25886
25887
25888 if (xg_set_icon (f, file))
25889 return false;
25890 #endif
25891 bitmap_id = image_create_bitmap_from_file (f, file);
25892 x_create_bitmap_mask (f, bitmap_id);
25893 }
25894 else
25895 {
25896
25897 if (FRAME_DISPLAY_INFO (f)->icon_bitmap_id < 0)
25898 {
25899 ptrdiff_t rc = -1;
25900
25901 #ifdef USE_GTK
25902
25903 if (xg_set_icon (f, xg_default_icon_file)
25904 || xg_set_icon_from_xpm_data (f, gnu_xpm_bits))
25905 {
25906 FRAME_DISPLAY_INFO (f)->icon_bitmap_id = -2;
25907 return false;
25908 }
25909
25910 #elif defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
25911
25912 if ((FRAME_X_VISUAL_INFO (f)->class == TrueColor
25913 || FRAME_X_VISUAL_INFO (f)->class == StaticColor
25914 || FRAME_X_VISUAL_INFO (f)->class == StaticGray)
25915
25916
25917
25918 || FRAME_X_VISUAL_INFO (f)->colormap_size >= (240 * 4))
25919 {
25920 rc = x_create_bitmap_from_xpm_data (f, gnu_xpm_bits);
25921 if (rc != -1)
25922 FRAME_DISPLAY_INFO (f)->icon_bitmap_id = rc;
25923 }
25924 #endif
25925
25926
25927 if (rc == -1)
25928 {
25929 rc = image_create_bitmap_from_data (f,
25930 (char *) gnu_xbm_bits,
25931 gnu_xbm_width,
25932 gnu_xbm_height);
25933 if (rc == -1)
25934 return true;
25935
25936 FRAME_DISPLAY_INFO (f)->icon_bitmap_id = rc;
25937 x_create_bitmap_mask (f, FRAME_DISPLAY_INFO (f)->icon_bitmap_id);
25938 }
25939 }
25940
25941
25942
25943
25944
25945 image_reference_bitmap (f, FRAME_DISPLAY_INFO (f)->icon_bitmap_id);
25946
25947 bitmap_id = FRAME_DISPLAY_INFO (f)->icon_bitmap_id;
25948 }
25949
25950 x_wm_set_icon_pixmap (f, bitmap_id);
25951 f->output_data.x->icon_bitmap = bitmap_id;
25952
25953 return false;
25954 }
25955
25956
25957
25958
25959
25960 bool
25961 x_text_icon (struct frame *f, const char *icon_name)
25962 {
25963 if (FRAME_X_WINDOW (f) == 0)
25964 return true;
25965
25966 {
25967 XTextProperty text;
25968 text.value = (unsigned char *) icon_name;
25969 text.encoding = XA_STRING;
25970 text.format = 8;
25971 text.nitems = strlen (icon_name);
25972 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text);
25973 }
25974
25975 if (f->output_data.x->icon_bitmap > 0)
25976 image_destroy_bitmap (f, f->output_data.x->icon_bitmap);
25977 f->output_data.x->icon_bitmap = 0;
25978 x_wm_set_icon_pixmap (f, 0);
25979
25980 return false;
25981 }
25982
25983
25984 struct x_error_message_stack
25985 {
25986
25987
25988 char *string;
25989
25990
25991 Display *dpy;
25992
25993
25994 x_special_error_handler handler;
25995
25996
25997 void *handler_data;
25998
25999
26000 struct x_error_message_stack *prev;
26001
26002
26003
26004
26005 unsigned long first_request;
26006 };
26007
26008
26009
26010
26011
26012
26013
26014
26015
26016 static struct x_error_message_stack *x_error_message;
26017
26018
26019 int x_error_message_count;
26020
26021
26022
26023
26024
26025
26026
26027 static bool
26028 x_is_serial_more_than (unsigned int a, unsigned int b)
26029 {
26030 if (a > b)
26031 return true;
26032
26033 return (b - a > X_ULONG_MAX / 2);
26034 }
26035
26036 static bool
26037 x_is_serial_more_than_or_equal_to (unsigned int a, unsigned int b)
26038 {
26039 if (a >= b)
26040 return true;
26041
26042 return (b - a > X_ULONG_MAX / 2);
26043 }
26044
26045 static bool
26046 x_is_serial_less_than (unsigned int a, unsigned int b)
26047 {
26048 if (a < b)
26049 return true;
26050
26051 return (a - b > X_ULONG_MAX / 2);
26052 }
26053
26054 static bool
26055 x_is_serial_less_than_or_equal_to (unsigned int a, unsigned int b)
26056 {
26057 if (a <= b)
26058 return true;
26059
26060 return (a - b > X_ULONG_MAX / 2);
26061 }
26062
26063 static struct x_error_message_stack *
26064 x_find_error_handler (Display *dpy, XErrorEvent *event)
26065 {
26066 struct x_error_message_stack *stack;
26067
26068 stack = x_error_message;
26069
26070 while (stack)
26071 {
26072 if (x_is_serial_more_than_or_equal_to (event->serial,
26073 stack->first_request)
26074 && dpy == stack->dpy)
26075 return stack;
26076
26077 stack = stack->prev;
26078 }
26079
26080 return NULL;
26081 }
26082
26083 void
26084 x_unwind_errors_to (int depth)
26085 {
26086 while (x_error_message_count > depth)
26087
26088
26089 x_uncatch_errors ();
26090 }
26091
26092 #define X_ERROR_MESSAGE_SIZE 200
26093
26094
26095
26096
26097
26098
26099 static void
26100 x_error_catcher (Display *display, XErrorEvent *event,
26101 struct x_error_message_stack *stack)
26102 {
26103 char buf[X_ERROR_MESSAGE_SIZE];
26104
26105 XGetErrorText (display, event->error_code,
26106 buf, X_ERROR_MESSAGE_SIZE);
26107
26108 if (stack->string)
26109 xfree (stack->string);
26110
26111 stack->string = xstrdup (buf);
26112
26113 if (stack->handler)
26114 stack->handler (display, event, stack->string,
26115 stack->handler_data);
26116 }
26117
26118
26119
26120
26121
26122
26123
26124
26125
26126
26127
26128
26129
26130
26131
26132
26133
26134
26135
26136
26137
26138
26139
26140
26141 void
26142 x_catch_errors_with_handler (Display *dpy, x_special_error_handler handler,
26143 void *handler_data)
26144 {
26145 struct x_error_message_stack *data;
26146
26147 data = xzalloc (sizeof *data);
26148 data->dpy = dpy;
26149 data->handler = handler;
26150 data->handler_data = handler_data;
26151 data->prev = x_error_message;
26152 data->first_request = XNextRequest (dpy);
26153 x_error_message = data;
26154
26155 ++x_error_message_count;
26156 }
26157
26158 void
26159 x_catch_errors (Display *dpy)
26160 {
26161 x_catch_errors_with_handler (dpy, NULL, NULL);
26162 }
26163
26164
26165
26166 static struct x_failable_request *
26167 x_request_can_fail (struct x_display_info *dpyinfo,
26168 unsigned long request)
26169 {
26170 struct x_failable_request *failable_requests;
26171
26172 for (failable_requests = dpyinfo->failable_requests;
26173 failable_requests < dpyinfo->next_failable_request;
26174 failable_requests++)
26175 {
26176 if (x_is_serial_more_than_or_equal_to (request,
26177 failable_requests->start)
26178 && (!failable_requests->end
26179 || x_is_serial_less_than_or_equal_to (request,
26180 failable_requests->end)))
26181 return failable_requests;
26182 }
26183
26184 return NULL;
26185 }
26186
26187
26188
26189 static void
26190 x_clean_failable_requests (struct x_display_info *dpyinfo)
26191 {
26192 struct x_failable_request *first, *last;
26193
26194 last = dpyinfo->next_failable_request;
26195
26196 for (first = dpyinfo->failable_requests; first < last; first++)
26197 {
26198 if (x_is_serial_more_than (first->start,
26199 LastKnownRequestProcessed (dpyinfo->display))
26200 || !first->end
26201 || x_is_serial_more_than (first->end,
26202 LastKnownRequestProcessed (dpyinfo->display)))
26203 break;
26204 }
26205
26206 if (first != last)
26207 memmove (&dpyinfo->failable_requests, first,
26208 sizeof *first * (last - first));
26209
26210 dpyinfo->next_failable_request = (dpyinfo->failable_requests
26211 + (last - first));
26212 }
26213
26214
26215
26216
26217
26218
26219
26220
26221
26222
26223
26224
26225
26226
26227
26228
26229
26230
26231
26232 void
26233 x_ignore_errors_for_next_request (struct x_display_info *dpyinfo,
26234 unsigned int selection_serial)
26235 {
26236 struct x_failable_request *request, *max;
26237 unsigned long next_request;
26238 #ifdef HAVE_GTK3
26239 GdkDisplay *gdpy;
26240 #endif
26241
26242
26243
26244 block_input ();
26245
26246 #ifdef HAVE_GTK3
26247
26248
26249
26250
26251
26252 gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display);
26253
26254 if (gdpy)
26255 gdk_x11_display_error_trap_push (gdpy);
26256 #endif
26257
26258 if ((dpyinfo->next_failable_request
26259 != dpyinfo->failable_requests)
26260 && (dpyinfo->next_failable_request - 1)->end == 0)
26261
26262
26263 emacs_abort ();
26264
26265 request = dpyinfo->next_failable_request;
26266 max = dpyinfo->failable_requests + N_FAILABLE_REQUESTS;
26267 next_request = XNextRequest (dpyinfo->display);
26268
26269 if (request >= max)
26270 {
26271
26272
26273 if ((LastKnownRequestProcessed (dpyinfo->display)
26274 != next_request - 1))
26275 XSync (dpyinfo->display, False);
26276
26277 x_clean_failable_requests (dpyinfo);
26278 request = dpyinfo->next_failable_request;
26279 }
26280
26281 if (request >= max)
26282
26283
26284 emacs_abort ();
26285
26286 request->start = next_request;
26287 request->end = 0;
26288 request->selection_serial = selection_serial;
26289
26290 dpyinfo->next_failable_request++;
26291 }
26292
26293 void
26294 x_stop_ignoring_errors (struct x_display_info *dpyinfo)
26295 {
26296 struct x_failable_request *range;
26297 #ifdef HAVE_GTK3
26298 GdkDisplay *gdpy;
26299 #endif
26300
26301 range = dpyinfo->next_failable_request - 1;
26302 range->end = XNextRequest (dpyinfo->display) - 1;
26303
26304
26305
26306
26307 if (x_is_serial_less_than (range->end, range->start))
26308 emacs_abort ();
26309
26310 #ifdef HAVE_GTK3
26311 gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display);
26312
26313 if (gdpy)
26314 gdk_x11_display_error_trap_pop_ignored (gdpy);
26315 #endif
26316
26317 unblock_input ();
26318 }
26319
26320
26321
26322
26323
26324
26325
26326
26327 void
26328 x_uncatch_errors_after_check (void)
26329 {
26330 struct x_error_message_stack *tmp;
26331
26332 block_input ();
26333 tmp = x_error_message;
26334 x_error_message = x_error_message->prev;
26335 --x_error_message_count;
26336 if (tmp->string)
26337 xfree (tmp->string);
26338 xfree (tmp);
26339 unblock_input ();
26340 }
26341
26342
26343
26344 void
26345 x_uncatch_errors (void)
26346 {
26347 struct x_error_message_stack *tmp;
26348 struct x_display_info *dpyinfo;
26349
26350
26351
26352
26353
26354 if (x_error_message == NULL)
26355 return;
26356
26357 block_input ();
26358
26359 dpyinfo = x_display_info_for_display (x_error_message->dpy);
26360
26361
26362
26363 if (dpyinfo != 0
26364
26365
26366 && (LastKnownRequestProcessed (x_error_message->dpy)
26367 != XNextRequest (x_error_message->dpy) - 1)
26368
26369
26370 && (NextRequest (x_error_message->dpy)
26371 > x_error_message->first_request))
26372 {
26373 XSync (x_error_message->dpy, False);
26374 x_clean_failable_requests (dpyinfo);
26375 }
26376
26377 tmp = x_error_message;
26378 x_error_message = x_error_message->prev;
26379 --x_error_message_count;
26380 if (tmp->string)
26381 xfree (tmp->string);
26382 xfree (tmp);
26383 unblock_input ();
26384 }
26385
26386
26387
26388
26389
26390 void
26391 x_check_errors (Display *dpy, const char *format)
26392 {
26393 struct x_display_info *dpyinfo;
26394 char *string;
26395
26396
26397
26398 if (dpy != x_error_message->dpy)
26399 emacs_abort ();
26400
26401
26402
26403 if ((LastKnownRequestProcessed (dpy)
26404 != XNextRequest (dpy) - 1)
26405 && (NextRequest (dpy)
26406 > x_error_message->first_request))
26407 XSync (dpy, False);
26408
26409 dpyinfo = x_display_info_for_display (dpy);
26410
26411
26412 if (dpyinfo)
26413 x_clean_failable_requests (dpyinfo);
26414
26415 if (x_error_message->string)
26416 {
26417 string = alloca (strlen (x_error_message->string) + 1);
26418 strcpy (string, x_error_message->string);
26419
26420 error (format, string);
26421 }
26422 }
26423
26424
26425
26426
26427 bool
26428 x_had_errors_p (Display *dpy)
26429 {
26430 struct x_display_info *dpyinfo;
26431
26432
26433
26434 if (dpy != x_error_message->dpy)
26435 emacs_abort ();
26436
26437
26438 if ((LastKnownRequestProcessed (dpy)
26439 != XNextRequest (dpy) - 1)
26440 && (NextRequest (dpy)
26441 > x_error_message->first_request))
26442 XSync (dpy, False);
26443
26444 dpyinfo = x_display_info_for_display (dpy);
26445
26446
26447 if (dpyinfo)
26448 x_clean_failable_requests (dpyinfo);
26449
26450 return !!x_error_message->string;
26451 }
26452
26453
26454
26455
26456 void
26457 x_clear_errors (Display *dpy)
26458 {
26459
26460
26461 if (dpy != x_error_message->dpy)
26462 emacs_abort ();
26463
26464 xfree (x_error_message->string);
26465 x_error_message->string = NULL;
26466 }
26467
26468 #if false
26469
26470
26471
26472
26473 void
26474 x_fully_uncatch_errors (void)
26475 {
26476 while (x_error_message)
26477 x_uncatch_errors ();
26478 }
26479 #endif
26480
26481 #if false
26482 static unsigned int x_wire_count;
26483
26484 static int
26485 x_trace_wire (Display *dpy)
26486 {
26487 fprintf (stderr, "Lib call: %u\n", ++x_wire_count);
26488 return 0;
26489 }
26490 #endif
26491
26492
26493
26494
26495
26496
26497
26498
26499 static char *error_msg;
26500
26501
26502
26503
26504
26505 static void
26506 x_try_restore_frame (void)
26507 {
26508 Lisp_Object tail, frame;
26509
26510 FOR_EACH_FRAME (tail, frame)
26511 {
26512 if (!NILP (do_switch_frame (frame, 0, 1, Qnil)))
26513 return;
26514 }
26515 }
26516
26517
26518
26519
26520 static void
26521 x_connection_closed (Display *dpy, const char *error_message, bool ioerror)
26522 {
26523 struct x_display_info *dpyinfo;
26524 Lisp_Object frame, tail;
26525 specpdl_ref idx = SPECPDL_INDEX ();
26526 Emacs_XIOErrorHandler io_error_handler;
26527 xm_drop_start_message dmsg;
26528 struct frame *f;
26529 Lisp_Object minibuf_frame, tmp;
26530 struct x_failable_request *failable;
26531 struct x_error_message_stack *stack;
26532 static Display *current_display;
26533
26534
26535
26536
26537 if (current_display == dpy)
26538 return;
26539
26540 current_display = dpy;
26541
26542 dpyinfo = x_display_info_for_display (dpy);
26543 error_msg = alloca (strlen (error_message) + 1);
26544 strcpy (error_msg, error_message);
26545
26546
26547 specbind (Qinhibit_redisplay, Qt);
26548
26549
26550
26551
26552
26553
26554 if (x_dnd_in_progress || x_dnd_waiting_for_finish)
26555 {
26556 if (!ioerror)
26557 {
26558
26559
26560 io_error_handler = XSetIOErrorHandler (x_dnd_io_error_handler);
26561
26562 if (!!sigsetjmp (x_dnd_disconnect_handler, 1)
26563 && x_dnd_in_progress
26564 && dpy == (x_dnd_waiting_for_finish
26565 ? x_dnd_finish_display
26566 : FRAME_X_DISPLAY (x_dnd_frame)))
26567 {
26568
26569
26570 f = x_dnd_frame;
26571
26572 if (x_dnd_last_seen_window != None
26573 && x_dnd_last_protocol_version != -1)
26574 x_dnd_send_leave (x_dnd_frame,
26575 x_dnd_last_seen_window,
26576 x_dnd_last_seen_toplevel);
26577 else if (x_dnd_last_seen_window != None
26578 && !XM_DRAG_STYLE_IS_DROP_ONLY (x_dnd_last_motif_style)
26579 && x_dnd_last_motif_style != XM_DRAG_STYLE_NONE
26580 && x_dnd_motif_setup_p)
26581 {
26582 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
26583 XM_DRAG_REASON_DROP_START);
26584 dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST;
26585 dmsg.timestamp = FRAME_DISPLAY_INFO (f)->last_user_time;
26586 dmsg.side_effects
26587 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f),
26588 x_dnd_wanted_action),
26589 XM_DROP_SITE_VALID, x_dnd_motif_operations,
26590 XM_DROP_ACTION_DROP_CANCEL);
26591 dmsg.x = 0;
26592 dmsg.y = 0;
26593 dmsg.index_atom = x_dnd_motif_atom;
26594 dmsg.source_window = FRAME_X_WINDOW (f);
26595
26596 x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f,
26597 x_dnd_last_seen_window, 0);
26598 xm_send_drop_message (FRAME_DISPLAY_INFO (f), FRAME_X_WINDOW (f),
26599 x_dnd_last_seen_window, &dmsg);
26600 }
26601 }
26602
26603 XSetIOErrorHandler (io_error_handler);
26604 }
26605
26606 dpyinfo = x_display_info_for_display (dpy);
26607
26608 x_dnd_last_seen_window = None;
26609 x_dnd_last_seen_toplevel = None;
26610 x_dnd_in_progress = false;
26611 x_dnd_waiting_for_finish = false;
26612
26613 if (x_dnd_use_toplevels)
26614 x_dnd_free_toplevels (!ioerror);
26615
26616 x_dnd_return_frame_object = NULL;
26617 x_dnd_movement_frame = NULL;
26618 x_dnd_wheel_frame = NULL;
26619 x_dnd_frame = NULL;
26620 }
26621
26622 if (dpyinfo)
26623 {
26624
26625
26626 dpyinfo->reference_count++;
26627 dpyinfo->terminal->reference_count++;
26628 if (ioerror)
26629 dpyinfo->display = 0;
26630 }
26631
26632
26633
26634
26635
26636 block_input ();
26637
26638
26639
26640 FOR_EACH_FRAME (tail, frame)
26641 {
26642
26643
26644 if (FRAME_TOOLTIP_P (XFRAME (frame)))
26645 continue;
26646
26647 minibuf_frame
26648 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
26649
26650 if (FRAME_X_P (XFRAME (frame))
26651 && FRAME_X_P (XFRAME (minibuf_frame))
26652 && ! EQ (frame, minibuf_frame)
26653 && FRAME_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
26654 delete_frame (frame, Qnoelisp);
26655 }
26656
26657
26658
26659
26660 FOR_EACH_FRAME (tail, frame)
26661 if (FRAME_X_P (XFRAME (frame))
26662 && FRAME_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
26663 {
26664
26665
26666 kset_default_minibuffer_frame (FRAME_KBOARD (XFRAME (frame)), Qt);
26667 delete_frame (frame, Qnoelisp);
26668 }
26669
26670
26671
26672 if (dpyinfo)
26673 {
26674
26675
26676
26677 #ifdef USE_GTK
26678
26679
26680
26681
26682 shut_down_emacs (0, Qnil);
26683 fprintf (stderr, "%s\n\
26684 When compiled with GTK, Emacs cannot recover from X disconnects.\n\
26685 This is a GTK bug: https://gitlab.gnome.org/GNOME/gtk/issues/221\n\
26686 For details, see etc/PROBLEMS.\n",
26687 error_msg);
26688 emacs_abort ();
26689 #endif
26690
26691
26692 dpyinfo->display = 0;
26693
26694 dpyinfo->reference_count--;
26695 dpyinfo->terminal->reference_count--;
26696 if (dpyinfo->reference_count != 0)
26697
26698 emacs_abort ();
26699
26700
26701
26702 if (dpyinfo->terminal == terminal_list
26703 && !terminal_list->next_terminal)
26704 {
26705 fprintf (stderr, "%s\n", error_msg);
26706
26707 if (!ioerror && dpyinfo)
26708 {
26709
26710
26711
26712 if ((dpyinfo->failable_requests
26713 != dpyinfo->next_failable_request) || x_error_message)
26714 fprintf (stderr, "X error handlers currently installed:\n");
26715
26716 for (failable = dpyinfo->failable_requests;
26717 failable < dpyinfo->next_failable_request;
26718 ++failable)
26719 {
26720 if (failable->end)
26721 fprintf (stderr, "Ignoring errors between %lu to %lu\n",
26722 failable->start, failable->end);
26723 else
26724 fprintf (stderr, "Ignoring errors from %lu onwards\n",
26725 failable->start);
26726 }
26727
26728 for (stack = x_error_message; stack; stack = stack->prev)
26729 fprintf (stderr, "Trapping errors from %lu\n",
26730 stack->first_request);
26731 }
26732 }
26733
26734 XSETTERMINAL (tmp, dpyinfo->terminal);
26735 Fdelete_terminal (tmp, Qnoelisp);
26736 }
26737
26738
26739
26740 if (NILP (selected_frame))
26741 x_try_restore_frame ();
26742
26743 unblock_input ();
26744
26745
26746
26747
26748
26749 if (terminal_list == 0 || NILP (selected_frame))
26750 Fkill_emacs (make_fixnum (70), Qnil);
26751
26752 totally_unblock_input ();
26753
26754 unbind_to (idx, Qnil);
26755 clear_waiting_for_input ();
26756
26757
26758
26759
26760 current_display = NULL;
26761 error ("%s", error_msg);
26762 }
26763
26764 static void x_error_quitter (Display *, XErrorEvent *);
26765
26766
26767
26768
26769 static int
26770 x_error_handler (Display *display, XErrorEvent *event)
26771 {
26772 struct x_error_message_stack *stack;
26773 struct x_display_info *dpyinfo;
26774 struct x_failable_request *fail, *last;
26775
26776 #if defined USE_GTK && defined HAVE_GTK3
26777 if ((event->error_code == BadMatch
26778 || event->error_code == BadWindow)
26779 && event->request_code == X_SetInputFocus)
26780 return 0;
26781 #endif
26782
26783 dpyinfo = x_display_info_for_display (display);
26784
26785 if (dpyinfo)
26786 {
26787 fail = x_request_can_fail (dpyinfo, event->serial);
26788
26789 if (fail)
26790 {
26791
26792
26793
26794 if (event->serial == fail->end)
26795 {
26796 last = dpyinfo->next_failable_request;
26797 memmove (&dpyinfo->failable_requests, fail,
26798 sizeof *fail * (last - fail));
26799 dpyinfo->next_failable_request = (dpyinfo->failable_requests
26800 + (last - fail));
26801 }
26802
26803
26804
26805
26806 if (fail->selection_serial)
26807 {
26808 x_handle_selection_error (fail->selection_serial,
26809 event);
26810
26811
26812
26813
26814
26815 fail->selection_serial = 0;
26816 }
26817
26818 return 0;
26819 }
26820 }
26821
26822
26823
26824
26825 #ifdef HAVE_XINPUT2
26826
26827
26828 if (dpyinfo && dpyinfo->supports_xi2
26829 && event->request_code == dpyinfo->xi2_opcode
26830 && (event->minor_code == X_XIGrabDevice
26831 || event->minor_code == X_XIUngrabDevice
26832 || event->minor_code == X_XIAllowEvents))
26833 return 0;
26834 #endif
26835
26836 stack = x_find_error_handler (display, event);
26837
26838 if (stack)
26839 x_error_catcher (display, event, stack);
26840 else
26841 x_error_quitter (display, event);
26842 return 0;
26843 }
26844
26845
26846
26847
26848
26849
26850
26851 static void NO_INLINE
26852 x_error_quitter (Display *display, XErrorEvent *event)
26853 {
26854 char buf[256], buf1[800 + INT_STRLEN_BOUND (int)
26855 + INT_STRLEN_BOUND (unsigned long)
26856 + INT_STRLEN_BOUND (XID)
26857 + INT_STRLEN_BOUND (int)];
26858
26859
26860
26861
26862 if (event->error_code == BadName)
26863 return;
26864
26865
26866
26867
26868 XGetErrorText (display, event->error_code, buf, sizeof (buf));
26869 sprintf (buf1, "X protocol error: %s on protocol request %d\n"
26870 "Serial no: %lu\n"
26871 "Failing resource ID (if any): 0x%lx\n"
26872 "Minor code: %d\n"
26873 "This is a bug! Please report this to bug-gnu-emacs@gnu.org!\n",
26874 buf, event->request_code, event->serial, event->resourceid,
26875 event->minor_code);
26876 x_connection_closed (display, buf1, false);
26877 }
26878
26879
26880
26881
26882
26883
26884 static int NO_INLINE
26885 x_io_error_quitter (Display *display)
26886 {
26887 char buf[256];
26888
26889 snprintf (buf, sizeof buf, "Connection lost to X server '%s'",
26890 DisplayString (display));
26891 x_connection_closed (display, buf, true);
26892
26893 return 0;
26894 }
26895
26896
26897
26898
26899
26900
26901
26902
26903
26904 static Lisp_Object
26905 x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
26906 {
26907 struct font *font = XFONT_OBJECT (font_object);
26908 int unit, font_ascent, font_descent;
26909
26910 if (fontset < 0)
26911 fontset = fontset_from_font (font_object);
26912 FRAME_FONTSET (f) = fontset;
26913 if (FRAME_FONT (f) == font)
26914
26915
26916 return font_object;
26917
26918 FRAME_FONT (f) = font;
26919 FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
26920 FRAME_COLUMN_WIDTH (f) = font->average_width;
26921 get_font_ascent_descent (font, &font_ascent, &font_descent);
26922 FRAME_LINE_HEIGHT (f) = font_ascent + font_descent;
26923
26924 #ifndef USE_X_TOOLKIT
26925 FRAME_MENU_BAR_HEIGHT (f) = FRAME_MENU_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
26926 #endif
26927
26928 FRAME_TAB_BAR_HEIGHT (f) = FRAME_TAB_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
26929
26930
26931
26932
26933
26934 unit = FRAME_COLUMN_WIDTH (f);
26935 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
26936 FRAME_CONFIG_SCROLL_BAR_COLS (f)
26937 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + unit - 1) / unit;
26938 else
26939 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit;
26940
26941
26942
26943
26944
26945 if (FRAME_X_WINDOW (f) != 0 && !FRAME_TOOLTIP_P (f))
26946 adjust_frame_size
26947 (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
26948 FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3, false, Qfont);
26949
26950 #ifdef HAVE_X_I18N
26951 if (FRAME_XIC (f)
26952 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
26953 {
26954 block_input ();
26955 xic_set_xfontset (f, SSDATA (fontset_ascii (fontset)));
26956 unblock_input ();
26957 }
26958 #endif
26959
26960 return font_object;
26961 }
26962
26963
26964
26965
26966
26967
26968 #ifdef HAVE_X_I18N
26969
26970 #ifdef HAVE_X11R6
26971
26972
26973
26974
26975
26976
26977
26978 #ifdef HAVE_X11R6_XIM
26979
26980
26981
26982
26983
26984
26985
26986 static void
26987 x_maybe_clear_preedit (struct frame *f)
26988 {
26989 struct x_output *output;
26990 struct input_event ie;
26991
26992 output = FRAME_X_OUTPUT (f);
26993
26994 if (!output->preedit_chars)
26995 return;
26996
26997 EVENT_INIT (ie);
26998 ie.kind = PREEDIT_TEXT_EVENT;
26999 ie.arg = Qnil;
27000 XSETFRAME (ie.frame_or_window, f);
27001 XSETINT (ie.x, 0);
27002 XSETINT (ie.y, 0);
27003 kbd_buffer_store_event (&ie);
27004
27005 xfree (output->preedit_chars);
27006
27007 output->preedit_size = 0;
27008 output->preedit_active = false;
27009 output->preedit_chars = NULL;
27010 output->preedit_caret = 0;
27011 }
27012
27013
27014
27015
27016
27017 static void
27018 xim_destroy_callback (XIM xim, XPointer client_data, XPointer call_data)
27019 {
27020 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
27021 Lisp_Object frame, tail;
27022
27023 block_input ();
27024
27025
27026 FOR_EACH_FRAME (tail, frame)
27027 {
27028 struct frame *f = XFRAME (frame);
27029 if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) == dpyinfo)
27030 {
27031 FRAME_XIC (f) = NULL;
27032 xic_free_xfontset (f);
27033
27034
27035 x_maybe_clear_preedit (f);
27036 }
27037 }
27038
27039
27040 dpyinfo->xim = NULL;
27041
27042
27043
27044 if (dpyinfo->xim_styles)
27045 XFree (dpyinfo->xim_styles);
27046 dpyinfo->xim_styles = NULL;
27047 unblock_input ();
27048 }
27049
27050 #endif
27051
27052 #endif
27053
27054
27055
27056
27057 static void
27058 xim_open_dpy (struct x_display_info *dpyinfo, char *resource_name)
27059 {
27060 #ifdef HAVE_XIM
27061 XIM xim;
27062 const char *locale;
27063
27064 if (dpyinfo->use_xim)
27065 {
27066 if (dpyinfo->xim)
27067 {
27068 XCloseIM (dpyinfo->xim);
27069
27070
27071
27072
27073 if (dpyinfo->xim_styles)
27074 XFree (dpyinfo->xim_styles);
27075 dpyinfo->xim_styles = NULL;
27076 }
27077
27078 xim = XOpenIM (dpyinfo->display, dpyinfo->rdb, resource_name,
27079 emacs_class);
27080 dpyinfo->xim = xim;
27081
27082 if (xim)
27083 {
27084 #ifdef HAVE_X11R6_XIM
27085 XIMCallback destroy;
27086 #endif
27087
27088
27089 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
27090
27091 #ifdef HAVE_X11R6_XIM
27092 destroy.callback = xim_destroy_callback;
27093 destroy.client_data = (XPointer)dpyinfo;
27094 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
27095 #endif
27096
27097 locale = XLocaleOfIM (xim);
27098
27099
27100
27101
27102 dpyinfo->xim_coding = safe_call1 (Vx_input_coding_function,
27103 build_string (locale));
27104 }
27105 }
27106 else
27107 #endif
27108 dpyinfo->xim = NULL;
27109 }
27110
27111
27112 #ifdef HAVE_X11R6_XIM
27113
27114
27115
27116
27117
27118
27119 static void
27120 xim_instantiate_callback (Display *display, XPointer client_data, XPointer call_data)
27121 {
27122 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
27123 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
27124
27125 if (x_dnd_in_progress)
27126 return;
27127
27128
27129 if (dpyinfo->xim)
27130 return;
27131
27132 xim_open_dpy (dpyinfo, xim_inst->resource_name);
27133
27134
27135
27136 if (dpyinfo->xim && dpyinfo->reference_count > 0)
27137 {
27138 Lisp_Object tail, frame;
27139
27140 block_input ();
27141 FOR_EACH_FRAME (tail, frame)
27142 {
27143 struct frame *f = XFRAME (frame);
27144
27145 if (FRAME_X_P (f)
27146 && FRAME_DISPLAY_INFO (f) == xim_inst->dpyinfo)
27147 if (FRAME_XIC (f) == NULL)
27148 {
27149 create_frame_xic (f);
27150 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
27151 xic_set_statusarea (f);
27152 struct window *w = XWINDOW (f->selected_window);
27153 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
27154 }
27155 }
27156
27157 unblock_input ();
27158 }
27159 }
27160
27161 #endif
27162
27163
27164
27165
27166
27167
27168
27169 static void
27170 xim_initialize (struct x_display_info *dpyinfo, char *resource_name)
27171 {
27172 dpyinfo->xim = NULL;
27173 #ifdef HAVE_XIM
27174 if (dpyinfo->use_xim)
27175 {
27176 #ifdef HAVE_X11R6_XIM
27177 struct xim_inst_t *xim_inst = xmalloc (sizeof *xim_inst);
27178 Bool ret;
27179
27180 dpyinfo->xim_callback_data = xim_inst;
27181 xim_inst->dpyinfo = dpyinfo;
27182 xim_inst->resource_name = xstrdup (resource_name);
27183
27184
27185
27186
27187
27188
27189 ret = XRegisterIMInstantiateCallback (dpyinfo->display,
27190 dpyinfo->rdb,
27191 xim_inst->resource_name,
27192 emacs_class,
27193 xim_instantiate_callback,
27194 (void *) xim_inst);
27195 eassert (ret);
27196 #else
27197 xim_open_dpy (dpyinfo, resource_name);
27198 #endif
27199 }
27200 #endif
27201 }
27202
27203
27204
27205
27206
27207
27208
27209 static void
27210 xim_close_dpy (struct x_display_info *dpyinfo)
27211 {
27212 #ifdef HAVE_XIM
27213 #ifdef HAVE_X11R6_XIM
27214 struct xim_inst_t *xim_inst;
27215 Bool rc;
27216
27217
27218
27219
27220
27221 if (dpyinfo->xim_callback_data)
27222 {
27223 xim_inst = dpyinfo->xim_callback_data;
27224
27225 if (dpyinfo->display)
27226 {
27227 rc = XUnregisterIMInstantiateCallback (dpyinfo->display,
27228 dpyinfo->rdb,
27229 xim_inst->resource_name,
27230 emacs_class,
27231 xim_instantiate_callback,
27232 (void *) xim_inst);
27233 eassert (rc);
27234 }
27235
27236 xfree (xim_inst->resource_name);
27237 xfree (xim_inst);
27238 }
27239 #endif
27240
27241
27242
27243
27244
27245 if (dpyinfo->display && dpyinfo->xim)
27246 XCloseIM (dpyinfo->xim);
27247 dpyinfo->xim = NULL;
27248
27249
27250
27251 if (dpyinfo->xim_styles)
27252 XFree (dpyinfo->xim_styles);
27253 dpyinfo->xim_styles = NULL;
27254 #endif
27255 }
27256
27257 #endif
27258
27259
27260
27261
27262
27263
27264 static void
27265 x_calc_absolute_position (struct frame *f)
27266 {
27267 int flags = f->size_hint_flags;
27268 struct frame *p = FRAME_PARENT_FRAME (f);
27269
27270
27271
27272 if (! ((flags & XNegative) || (flags & YNegative)))
27273 return;
27274
27275
27276
27277 if ((flags & XNegative) && (f->left_pos <= 0))
27278 {
27279 int width = FRAME_PIXEL_WIDTH (f);
27280
27281
27282
27283 if (f->output_data.x->has_been_visible && !p)
27284 {
27285 Lisp_Object frame;
27286 Lisp_Object edges = Qnil;
27287
27288 XSETFRAME (frame, f);
27289 edges = Fx_frame_edges (frame, Qouter_edges);
27290 if (!NILP (edges))
27291 width = (XFIXNUM (Fnth (make_fixnum (2), edges))
27292 - XFIXNUM (Fnth (make_fixnum (0), edges)));
27293 }
27294
27295 if (p)
27296 f->left_pos = (FRAME_PIXEL_WIDTH (p) - width - 2 * f->border_width
27297 + f->left_pos);
27298 else
27299 f->left_pos = (x_display_pixel_width (FRAME_DISPLAY_INFO (f))
27300 - width + f->left_pos);
27301
27302 }
27303
27304 if ((flags & YNegative) && (f->top_pos <= 0))
27305 {
27306 int height = FRAME_PIXEL_HEIGHT (f);
27307
27308 #if defined USE_X_TOOLKIT && defined USE_MOTIF
27309
27310
27311
27312
27313
27314
27315
27316
27317
27318
27319
27320
27321 XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
27322 #endif
27323
27324 if (f->output_data.x->has_been_visible && !p)
27325 {
27326 Lisp_Object frame;
27327 Lisp_Object edges = Qnil;
27328
27329 XSETFRAME (frame, f);
27330 if (NILP (edges))
27331 edges = Fx_frame_edges (frame, Qouter_edges);
27332 if (!NILP (edges))
27333 height = (XFIXNUM (Fnth (make_fixnum (3), edges))
27334 - XFIXNUM (Fnth (make_fixnum (1), edges)));
27335 }
27336
27337 if (p)
27338 f->top_pos = (FRAME_PIXEL_HEIGHT (p) - height - 2 * f->border_width
27339 + f->top_pos);
27340 else
27341 f->top_pos = (x_display_pixel_height (FRAME_DISPLAY_INFO (f))
27342 - height + f->top_pos);
27343 }
27344
27345
27346
27347
27348 f->size_hint_flags &= ~ (XNegative | YNegative);
27349 }
27350
27351
27352
27353
27354
27355
27356
27357 static void
27358 x_set_offset (struct frame *f, int xoff, int yoff, int change_gravity)
27359 {
27360 int modified_top, modified_left;
27361 #ifdef USE_GTK
27362 int scale = xg_get_scale (f);
27363 #endif
27364
27365 if (change_gravity > 0)
27366 {
27367 f->top_pos = yoff;
27368 f->left_pos = xoff;
27369 f->size_hint_flags &= ~ (XNegative | YNegative);
27370 if (xoff < 0)
27371 f->size_hint_flags |= XNegative;
27372 if (yoff < 0)
27373 f->size_hint_flags |= YNegative;
27374 f->win_gravity = NorthWestGravity;
27375 }
27376
27377 x_calc_absolute_position (f);
27378
27379 block_input ();
27380 x_wm_set_size_hint (f, 0, false);
27381
27382 #ifdef USE_GTK
27383 if (x_gtk_use_window_move)
27384 {
27385
27386
27387
27388
27389 if (change_gravity != 0 && FRAME_GTK_OUTER_WIDGET (f))
27390 gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
27391 f->left_pos / scale, f->top_pos / scale);
27392 unblock_input ();
27393 return;
27394 }
27395 #endif
27396
27397 modified_left = f->left_pos;
27398 modified_top = f->top_pos;
27399
27400 if (change_gravity != 0 && FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A)
27401 {
27402
27403
27404
27405 modified_left += FRAME_X_OUTPUT (f)->move_offset_left;
27406 modified_top += FRAME_X_OUTPUT (f)->move_offset_top;
27407 }
27408
27409 #ifdef USE_GTK
27410
27411 gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
27412 modified_left / scale, modified_top / scale);
27413 #else
27414 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
27415 modified_left, modified_top);
27416 #endif
27417
27418
27419
27420 if (NILP (Vx_lax_frame_positioning))
27421 {
27422
27423 if (!FRAME_PARENT_FRAME (f)
27424
27425
27426
27427 && NILP (Vx_no_window_manager))
27428 {
27429 x_sync_with_move (f, f->left_pos, f->top_pos,
27430 FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN);
27431
27432
27433
27434
27435
27436
27437
27438
27439
27440
27441
27442 if (change_gravity != 0
27443 && (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
27444 || (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A
27445 && (FRAME_X_OUTPUT (f)->move_offset_left == 0
27446 && FRAME_X_OUTPUT (f)->move_offset_top == 0))))
27447 x_check_expected_move (f, modified_left, modified_top);
27448 }
27449
27450
27451
27452 else
27453 XSync (FRAME_X_DISPLAY (f), False);
27454 }
27455
27456 unblock_input ();
27457 }
27458
27459 static Window
27460 x_get_wm_check_window (struct x_display_info *dpyinfo)
27461 {
27462 Window result;
27463 unsigned char *tmp_data = NULL;
27464 int rc, actual_format;
27465 unsigned long actual_size, bytes_remaining;
27466 Atom actual_type;
27467
27468 rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window,
27469 dpyinfo->Xatom_net_supporting_wm_check,
27470 0, 1, False, XA_WINDOW, &actual_type,
27471 &actual_format, &actual_size,
27472 &bytes_remaining, &tmp_data);
27473
27474 if (rc != Success || actual_type != XA_WINDOW
27475 || actual_format != 32 || actual_size != 1)
27476 {
27477 if (tmp_data)
27478 XFree (tmp_data);
27479
27480 return None;
27481 }
27482
27483 result = *(Window *) tmp_data;
27484 XFree (tmp_data);
27485
27486 return result;
27487 }
27488
27489
27490
27491
27492
27493
27494
27495 bool
27496 x_wm_supports_1 (struct x_display_info *dpyinfo, Atom want_atom)
27497 {
27498 Atom actual_type;
27499 unsigned long actual_size, bytes_remaining;
27500 int i, rc, actual_format;
27501 bool ret;
27502 Window wmcheck_window;
27503 Window target_window = dpyinfo->root_window;
27504 int max_len = 65536;
27505 Display *dpy = dpyinfo->display;
27506 unsigned char *tmp_data = NULL;
27507 Atom target_type = XA_WINDOW;
27508
27509
27510
27511 if (!NILP (Vx_no_window_manager))
27512 return false;
27513
27514
27515
27516
27517 if (dpyinfo->untrusted)
27518 return false;
27519
27520 block_input ();
27521
27522 x_catch_errors (dpy);
27523
27524 wmcheck_window = dpyinfo->net_supported_window;
27525
27526 if (wmcheck_window == None)
27527 wmcheck_window = x_get_wm_check_window (dpyinfo);
27528
27529 if (!x_special_window_exists_p (dpyinfo, wmcheck_window))
27530 {
27531 if (dpyinfo->net_supported_window != None)
27532 {
27533 dpyinfo->net_supported_window = None;
27534 wmcheck_window = x_get_wm_check_window (dpyinfo);
27535
27536 if (!x_special_window_exists_p (dpyinfo, wmcheck_window))
27537 {
27538 x_uncatch_errors ();
27539 unblock_input ();
27540 return false;
27541 }
27542 }
27543 else
27544 {
27545 x_uncatch_errors ();
27546 unblock_input ();
27547 return false;
27548 }
27549 }
27550
27551 if (dpyinfo->net_supported_window != wmcheck_window)
27552 {
27553
27554 if (dpyinfo->net_supported_atoms != NULL)
27555 XFree (dpyinfo->net_supported_atoms);
27556 dpyinfo->net_supported_atoms = NULL;
27557 dpyinfo->nr_net_supported_atoms = 0;
27558 dpyinfo->net_supported_window = 0;
27559
27560 target_type = XA_ATOM;
27561 tmp_data = NULL;
27562 rc = XGetWindowProperty (dpy, target_window,
27563 dpyinfo->Xatom_net_supported,
27564 0, max_len, False, target_type,
27565 &actual_type, &actual_format, &actual_size,
27566 &bytes_remaining, &tmp_data);
27567
27568 if (rc != Success || actual_type != XA_ATOM || x_had_errors_p (dpy))
27569 {
27570 if (tmp_data)
27571 XFree (tmp_data);
27572 x_uncatch_errors ();
27573 unblock_input ();
27574 return false;
27575 }
27576
27577 dpyinfo->net_supported_atoms = (Atom *) tmp_data;
27578 dpyinfo->nr_net_supported_atoms = actual_size;
27579 dpyinfo->net_supported_window = wmcheck_window;
27580 }
27581
27582 ret = false;
27583
27584 for (i = 0; !ret && i < dpyinfo->nr_net_supported_atoms; ++i)
27585 ret = dpyinfo->net_supported_atoms[i] == want_atom;
27586
27587 x_uncatch_errors ();
27588 unblock_input ();
27589
27590 return ret;
27591 }
27592
27593 bool
27594 x_wm_supports (struct frame *f, Atom want_atom)
27595 {
27596 return x_wm_supports_1 (FRAME_DISPLAY_INFO (f),
27597 want_atom);
27598 }
27599
27600 static void
27601 set_wm_state (Lisp_Object frame, bool add, Atom atom, Atom value)
27602 {
27603 struct x_display_info *dpyinfo;
27604 XEvent msg;
27605
27606 dpyinfo = FRAME_DISPLAY_INFO (XFRAME (frame));
27607 msg.xclient.type = ClientMessage;
27608 msg.xclient.window = FRAME_OUTER_WINDOW (XFRAME (frame));
27609 msg.xclient.message_type = dpyinfo->Xatom_net_wm_state;
27610 msg.xclient.format = 32;
27611
27612 msg.xclient.data.l[0] = add ? 1 : 0;
27613 msg.xclient.data.l[1] = atom;
27614 msg.xclient.data.l[2] = value;
27615 msg.xclient.data.l[3] = 1;
27616 msg.xclient.data.l[4] = 0;
27617
27618 block_input ();
27619 XSendEvent (dpyinfo->display, dpyinfo->root_window,
27620 False, (SubstructureRedirectMask
27621 | SubstructureNotifyMask), &msg);
27622 unblock_input ();
27623 }
27624
27625 void
27626 x_set_sticky (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
27627 {
27628 Lisp_Object frame;
27629 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
27630
27631 XSETFRAME (frame, f);
27632
27633 set_wm_state (frame, !NILP (new_value),
27634 dpyinfo->Xatom_net_wm_state_sticky, None);
27635 }
27636
27637 void
27638 x_set_shaded (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
27639 {
27640 Lisp_Object frame;
27641 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
27642
27643 XSETFRAME (frame, f);
27644
27645 set_wm_state (frame, !NILP (new_value),
27646 dpyinfo->Xatom_net_wm_state_shaded, None);
27647 }
27648
27649
27650
27651
27652
27653
27654
27655
27656
27657
27658
27659 void
27660 x_set_skip_taskbar (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
27661 {
27662 if (!EQ (new_value, old_value))
27663 {
27664 #ifdef USE_GTK
27665 xg_set_skip_taskbar (f, new_value);
27666 #else
27667 Lisp_Object frame;
27668 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
27669
27670 XSETFRAME (frame, f);
27671 set_wm_state (frame, !NILP (new_value),
27672 dpyinfo->Xatom_net_wm_state_skip_taskbar, None);
27673 #endif
27674 FRAME_SKIP_TASKBAR (f) = !NILP (new_value);
27675 }
27676 }
27677
27678
27679
27680
27681
27682
27683
27684
27685
27686
27687
27688
27689
27690
27691
27692
27693
27694 void
27695 x_set_z_group (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
27696 {
27697
27698
27699 Lisp_Object frame;
27700 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
27701
27702 XSETFRAME (frame, f);
27703
27704 if (NILP (new_value))
27705 {
27706 set_wm_state (frame, false,
27707 dpyinfo->Xatom_net_wm_state_above, None);
27708 set_wm_state (frame, false,
27709 dpyinfo->Xatom_net_wm_state_below, None);
27710 FRAME_Z_GROUP (f) = z_group_none;
27711 }
27712 else if (EQ (new_value, Qabove))
27713 {
27714 set_wm_state (frame, true,
27715 dpyinfo->Xatom_net_wm_state_above, None);
27716 set_wm_state (frame, false,
27717 dpyinfo->Xatom_net_wm_state_below, None);
27718 FRAME_Z_GROUP (f) = z_group_above;
27719 }
27720 else if (EQ (new_value, Qbelow))
27721 {
27722 set_wm_state (frame, false,
27723 dpyinfo->Xatom_net_wm_state_above, None);
27724 set_wm_state (frame, true,
27725 dpyinfo->Xatom_net_wm_state_below, None);
27726 FRAME_Z_GROUP (f) = z_group_below;
27727 }
27728 else if (EQ (new_value, Qabove_suspended))
27729 {
27730 set_wm_state (frame, false,
27731 dpyinfo->Xatom_net_wm_state_above, None);
27732 FRAME_Z_GROUP (f) = z_group_above_suspended;
27733 }
27734 else
27735 error ("Invalid z-group specification");
27736 }
27737
27738
27739
27740
27741
27742
27743
27744
27745 static bool
27746 x_get_current_wm_state (struct frame *f,
27747 Window window,
27748 int *size_state,
27749 bool *sticky,
27750 bool *shaded)
27751 {
27752 unsigned long actual_size;
27753 int i;
27754 bool is_hidden = false;
27755 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
27756 long max_len = 65536;
27757 Atom target_type = XA_ATOM;
27758
27759 #ifdef USE_XCB
27760 xcb_get_property_cookie_t prop_cookie;
27761 xcb_get_property_reply_t *prop;
27762 typedef xcb_atom_t reply_data_object;
27763 #else
27764 Display *dpy = FRAME_X_DISPLAY (f);
27765 unsigned long bytes_remaining;
27766 int rc, actual_format;
27767 Atom actual_type;
27768 unsigned char *tmp_data = NULL;
27769 typedef Atom reply_data_object;
27770 #endif
27771 reply_data_object *reply_data;
27772 # if defined GCC_LINT || defined lint
27773 reply_data_object reply_data_dummy;
27774 reply_data = &reply_data_dummy;
27775 # endif
27776
27777 *sticky = false;
27778 *size_state = FULLSCREEN_NONE;
27779 *shaded = false;
27780
27781 block_input ();
27782
27783 #ifdef USE_XCB
27784 prop_cookie = xcb_get_property (dpyinfo->xcb_connection, 0, window,
27785 dpyinfo->Xatom_net_wm_state,
27786 target_type, 0, max_len);
27787 prop = xcb_get_property_reply (dpyinfo->xcb_connection, prop_cookie, NULL);
27788 if (prop && prop->type == target_type)
27789 {
27790 int actual_bytes = xcb_get_property_value_length (prop);
27791 eassume (0 <= actual_bytes);
27792 actual_size = actual_bytes / sizeof *reply_data;
27793 reply_data = xcb_get_property_value (prop);
27794 }
27795 else
27796 {
27797 actual_size = 0;
27798 is_hidden = FRAME_ICONIFIED_P (f);
27799 }
27800 #else
27801 x_catch_errors (dpy);
27802 rc = XGetWindowProperty (dpy, window, dpyinfo->Xatom_net_wm_state,
27803 0, max_len, False, target_type,
27804 &actual_type, &actual_format, &actual_size,
27805 &bytes_remaining, &tmp_data);
27806
27807 if (rc == Success && actual_type == target_type && ! x_had_errors_p (dpy))
27808 reply_data = (Atom *) tmp_data;
27809 else
27810 {
27811 actual_size = 0;
27812 is_hidden = FRAME_ICONIFIED_P (f);
27813 }
27814
27815 x_uncatch_errors ();
27816 #endif
27817
27818 for (i = 0; i < actual_size; ++i)
27819 {
27820 Atom a = reply_data[i];
27821 if (a == dpyinfo->Xatom_net_wm_state_hidden)
27822 is_hidden = true;
27823 else if (a == dpyinfo->Xatom_net_wm_state_maximized_horz)
27824 {
27825 if (*size_state == FULLSCREEN_HEIGHT)
27826 *size_state = FULLSCREEN_MAXIMIZED;
27827 else
27828 *size_state = FULLSCREEN_WIDTH;
27829 }
27830 else if (a == dpyinfo->Xatom_net_wm_state_maximized_vert)
27831 {
27832 if (*size_state == FULLSCREEN_WIDTH)
27833 *size_state = FULLSCREEN_MAXIMIZED;
27834 else
27835 *size_state = FULLSCREEN_HEIGHT;
27836 }
27837 else if (a == dpyinfo->Xatom_net_wm_state_fullscreen)
27838 *size_state = FULLSCREEN_BOTH;
27839 else if (a == dpyinfo->Xatom_net_wm_state_sticky)
27840 *sticky = true;
27841 else if (a == dpyinfo->Xatom_net_wm_state_shaded)
27842 *shaded = true;
27843 }
27844
27845 #ifdef USE_XCB
27846 free (prop);
27847 #else
27848 if (tmp_data) XFree (tmp_data);
27849 #endif
27850
27851 unblock_input ();
27852 return ! is_hidden;
27853 }
27854
27855
27856
27857 static bool
27858 do_ewmh_fullscreen (struct frame *f)
27859 {
27860 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
27861 bool have_net_atom = x_wm_supports (f, dpyinfo->Xatom_net_wm_state);
27862 int cur;
27863 bool dummy;
27864
27865 x_get_current_wm_state (f, FRAME_OUTER_WINDOW (f), &cur, &dummy, &dummy);
27866
27867
27868
27869 if (!have_net_atom)
27870 have_net_atom = x_wm_supports (f, dpyinfo->Xatom_net_wm_state_fullscreen);
27871
27872 if (have_net_atom && cur != f->want_fullscreen)
27873 {
27874 Lisp_Object frame;
27875
27876 XSETFRAME (frame, f);
27877
27878
27879
27880
27881 switch (f->want_fullscreen)
27882 {
27883 case FULLSCREEN_BOTH:
27884 if (cur != FULLSCREEN_BOTH)
27885 set_wm_state (frame, true, dpyinfo->Xatom_net_wm_state_fullscreen,
27886 None);
27887 break;
27888 case FULLSCREEN_WIDTH:
27889 if (x_frame_normalize_before_maximize && cur == FULLSCREEN_MAXIMIZED)
27890 {
27891 set_wm_state (frame, false,
27892 dpyinfo->Xatom_net_wm_state_maximized_horz,
27893 dpyinfo->Xatom_net_wm_state_maximized_vert);
27894 set_wm_state (frame, true,
27895 dpyinfo->Xatom_net_wm_state_maximized_horz, None);
27896 }
27897 else
27898 {
27899 if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_HEIGHT
27900 || cur == FULLSCREEN_MAXIMIZED)
27901 set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
27902 dpyinfo->Xatom_net_wm_state_maximized_vert);
27903 if (cur != FULLSCREEN_MAXIMIZED || x_frame_normalize_before_maximize)
27904 set_wm_state (frame, true,
27905 dpyinfo->Xatom_net_wm_state_maximized_horz, None);
27906 }
27907 break;
27908 case FULLSCREEN_HEIGHT:
27909 if (x_frame_normalize_before_maximize && cur == FULLSCREEN_MAXIMIZED)
27910 {
27911 set_wm_state (frame, false,
27912 dpyinfo->Xatom_net_wm_state_maximized_horz,
27913 dpyinfo->Xatom_net_wm_state_maximized_vert);
27914 set_wm_state (frame, true,
27915 dpyinfo->Xatom_net_wm_state_maximized_vert, None);
27916 }
27917 else
27918 {
27919 if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_WIDTH
27920 || cur == FULLSCREEN_MAXIMIZED)
27921 set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
27922 dpyinfo->Xatom_net_wm_state_maximized_horz);
27923 if (cur != FULLSCREEN_MAXIMIZED || x_frame_normalize_before_maximize)
27924 set_wm_state (frame, true,
27925 dpyinfo->Xatom_net_wm_state_maximized_vert, None);
27926 }
27927 break;
27928 case FULLSCREEN_MAXIMIZED:
27929 if (x_frame_normalize_before_maximize && cur == FULLSCREEN_BOTH)
27930 {
27931 set_wm_state (frame, false,
27932 dpyinfo->Xatom_net_wm_state_fullscreen, None);
27933 set_wm_state (frame, true,
27934 dpyinfo->Xatom_net_wm_state_maximized_horz,
27935 dpyinfo->Xatom_net_wm_state_maximized_vert);
27936 }
27937 else if (x_frame_normalize_before_maximize && cur == FULLSCREEN_WIDTH)
27938 {
27939 set_wm_state (frame, false,
27940 dpyinfo->Xatom_net_wm_state_maximized_horz, None);
27941 set_wm_state (frame, true,
27942 dpyinfo->Xatom_net_wm_state_maximized_horz,
27943 dpyinfo->Xatom_net_wm_state_maximized_vert);
27944 }
27945 else if (x_frame_normalize_before_maximize && cur == FULLSCREEN_HEIGHT)
27946 {
27947 set_wm_state (frame, false,
27948 dpyinfo->Xatom_net_wm_state_maximized_vert, None);
27949 set_wm_state (frame, true,
27950 dpyinfo->Xatom_net_wm_state_maximized_horz,
27951 dpyinfo->Xatom_net_wm_state_maximized_vert);
27952 }
27953 else
27954 {
27955 if (cur == FULLSCREEN_BOTH)
27956 set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
27957 None);
27958 else if (cur == FULLSCREEN_HEIGHT)
27959 set_wm_state (frame, true,
27960 dpyinfo->Xatom_net_wm_state_maximized_horz, None);
27961 else if (cur == FULLSCREEN_WIDTH)
27962 set_wm_state (frame, true, None,
27963 dpyinfo->Xatom_net_wm_state_maximized_vert);
27964 else
27965 set_wm_state (frame, true,
27966 dpyinfo->Xatom_net_wm_state_maximized_horz,
27967 dpyinfo->Xatom_net_wm_state_maximized_vert);
27968 }
27969 break;
27970 case FULLSCREEN_NONE:
27971 if (cur == FULLSCREEN_BOTH)
27972 set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
27973 None);
27974 else
27975 set_wm_state (frame, false,
27976 dpyinfo->Xatom_net_wm_state_maximized_horz,
27977 dpyinfo->Xatom_net_wm_state_maximized_vert);
27978 }
27979
27980 f->want_fullscreen = FULLSCREEN_NONE;
27981
27982 }
27983
27984 return have_net_atom;
27985 }
27986
27987 static void
27988 XTfullscreen_hook (struct frame *f)
27989 {
27990 if (!FRAME_VISIBLE_P (f))
27991 return;
27992
27993 block_input ();
27994 x_check_fullscreen (f);
27995 unblock_input ();
27996 }
27997
27998
27999 static bool
28000 x_handle_net_wm_state (struct frame *f, const XPropertyEvent *event)
28001 {
28002 int value = FULLSCREEN_NONE;
28003 Lisp_Object lval;
28004 bool sticky = false, shaded = false;
28005 bool not_hidden = x_get_current_wm_state (f, event->window,
28006 &value, &sticky,
28007 &shaded);
28008
28009 lval = Qnil;
28010 switch (value)
28011 {
28012 case FULLSCREEN_WIDTH:
28013 lval = Qfullwidth;
28014 break;
28015 case FULLSCREEN_HEIGHT:
28016 lval = Qfullheight;
28017 break;
28018 case FULLSCREEN_BOTH:
28019 lval = Qfullboth;
28020 break;
28021 case FULLSCREEN_MAXIMIZED:
28022 lval = Qmaximized;
28023 break;
28024 }
28025
28026 store_frame_param (f, Qfullscreen, lval);
28027 store_frame_param (f, Qsticky, sticky ? Qt : Qnil);
28028 store_frame_param (f, Qshaded, shaded ? Qt : Qnil);
28029
28030 return not_hidden;
28031 }
28032
28033
28034
28035 static void
28036 x_check_fullscreen (struct frame *f)
28037 {
28038 Lisp_Object lval = Qnil;
28039
28040 if (do_ewmh_fullscreen (f))
28041 return;
28042
28043 if (f->output_data.x->parent_desc != FRAME_DISPLAY_INFO (f)->root_window)
28044 return;
28045
28046
28047
28048
28049
28050 if (f->want_fullscreen != FULLSCREEN_NONE)
28051 {
28052 int width = FRAME_PIXEL_WIDTH (f), height = FRAME_PIXEL_HEIGHT (f);
28053 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
28054
28055 switch (f->want_fullscreen)
28056 {
28057
28058 case FULLSCREEN_MAXIMIZED:
28059 lval = Qmaximized;
28060 width = x_display_pixel_width (dpyinfo);
28061 height = x_display_pixel_height (dpyinfo);
28062 break;
28063 case FULLSCREEN_BOTH:
28064 lval = Qfullboth;
28065 width = x_display_pixel_width (dpyinfo);
28066 height = x_display_pixel_height (dpyinfo);
28067 break;
28068 case FULLSCREEN_WIDTH:
28069 lval = Qfullwidth;
28070 width = x_display_pixel_width (dpyinfo);
28071 height = height + FRAME_MENUBAR_HEIGHT (f);
28072 break;
28073 case FULLSCREEN_HEIGHT:
28074 lval = Qfullheight;
28075 height = x_display_pixel_height (dpyinfo);
28076 break;
28077 default:
28078 emacs_abort ();
28079 }
28080
28081 x_wm_set_size_hint (f, 0, false);
28082
28083 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
28084 width, height);
28085
28086 if (FRAME_VISIBLE_P (f))
28087 x_wait_for_event (f, ConfigureNotify);
28088 else
28089 change_frame_size (f, width, height, false, true, false);
28090 }
28091
28092
28093
28094 store_frame_param (f, Qfullscreen, lval);
28095 }
28096
28097
28098
28099
28100
28101
28102
28103
28104
28105 static void
28106 x_check_expected_move (struct frame *f, int expected_left, int expected_top)
28107 {
28108 int current_left = 0, current_top = 0;
28109
28110
28111
28112
28113 x_real_positions (f, ¤t_left, ¤t_top);
28114
28115 if (current_left != expected_left || current_top != expected_top)
28116 {
28117
28118
28119 int adjusted_left;
28120 int adjusted_top;
28121
28122 FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_A;
28123 FRAME_X_OUTPUT (f)->move_offset_left = expected_left - current_left;
28124 FRAME_X_OUTPUT (f)->move_offset_top = expected_top - current_top;
28125
28126
28127
28128 adjusted_left = expected_left + FRAME_X_OUTPUT (f)->move_offset_left;
28129 adjusted_top = expected_top + FRAME_X_OUTPUT (f)->move_offset_top;
28130
28131 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
28132 adjusted_left, adjusted_top);
28133
28134 x_sync_with_move (f, expected_left, expected_top, false);
28135 }
28136 else
28137
28138
28139 FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_B;
28140 }
28141
28142
28143
28144
28145
28146
28147
28148
28149 static void
28150 x_sync_with_move (struct frame *f, int left, int top, bool fuzzy)
28151 {
28152 sigset_t emptyset;
28153 int count, current_left, current_top;
28154 struct timespec fallback;
28155
28156 sigemptyset (&emptyset);
28157 count = 0;
28158
28159 while (count++ < 50)
28160 {
28161 current_left = 0;
28162 current_top = 0;
28163
28164
28165
28166
28167 x_real_positions (f, ¤t_left, ¤t_top);
28168
28169 if (fuzzy)
28170 {
28171
28172
28173
28174 if (eabs (current_left - left) <= 10
28175 && eabs (current_top - top) <= 40)
28176 return;
28177 }
28178 else if (current_left == left && current_top == top)
28179 return;
28180 }
28181
28182
28183
28184
28185 fallback = dtotimespec (0.5);
28186
28187
28188
28189 if (input_blocked_p ())
28190 pselect (0, NULL, NULL, NULL, &fallback, &emptyset);
28191 else
28192 wait_reading_process_output (0, 500000000, 0, false, Qnil, NULL, 0);
28193 }
28194
28195
28196 void
28197 x_wait_for_event (struct frame *f, int eventtype)
28198 {
28199 if (!FLOATP (Vx_wait_for_event_timeout))
28200 return;
28201
28202 int level = interrupt_input_blocked;
28203 fd_set fds;
28204 struct timespec tmo, tmo_at, time_now;
28205 int fd = ConnectionNumber (FRAME_X_DISPLAY (f));
28206
28207 f->wait_event_type = eventtype;
28208
28209
28210 double timeout = XFLOAT_DATA (Vx_wait_for_event_timeout);
28211 time_t timeout_seconds = (time_t) timeout;
28212 tmo = make_timespec
28213 (timeout_seconds, (long int) ((timeout - timeout_seconds)
28214 * 1000 * 1000 * 1000));
28215 tmo_at = timespec_add (current_timespec (), tmo);
28216
28217 while (f->wait_event_type)
28218 {
28219 pending_signals = true;
28220 totally_unblock_input ();
28221
28222 block_input ();
28223 interrupt_input_blocked = level;
28224
28225 FD_ZERO (&fds);
28226 FD_SET (fd, &fds);
28227
28228 time_now = current_timespec ();
28229 if (timespec_cmp (tmo_at, time_now) < 0)
28230 break;
28231
28232 tmo = timespec_sub (tmo_at, time_now);
28233 if (pselect (fd + 1, &fds, NULL, NULL, &tmo, NULL) == 0)
28234 break;
28235 }
28236
28237 f->wait_event_type = 0;
28238 }
28239
28240
28241
28242
28243
28244
28245
28246 static void
28247 x_set_window_size_1 (struct frame *f, bool change_gravity,
28248 int width, int height)
28249 {
28250 if (change_gravity)
28251 f->win_gravity = NorthWestGravity;
28252 x_wm_set_size_hint (f, 0, false);
28253
28254 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
28255 width, height + FRAME_MENUBAR_HEIGHT (f));
28256
28257
28258
28259
28260
28261 SET_FRAME_GARBAGED (f);
28262
28263
28264
28265
28266 if (!NILP (Vx_lax_frame_positioning))
28267 return;
28268
28269
28270
28271
28272
28273
28274
28275
28276
28277
28278
28279
28280
28281
28282
28283
28284
28285
28286 if (FRAME_VISIBLE_P (f))
28287 {
28288 x_wait_for_event (f, ConfigureNotify);
28289
28290 if (CONSP (frame_size_history))
28291 frame_size_history_extra
28292 (f, build_string ("x_set_window_size_1, visible"),
28293 FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), width, height,
28294 f->new_width, f->new_height);
28295 }
28296 else
28297 {
28298 if (CONSP (frame_size_history))
28299 frame_size_history_extra
28300 (f, build_string ("x_set_window_size_1, invisible"),
28301 FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), width, height,
28302 f->new_width, f->new_height);
28303
28304
28305
28306 adjust_frame_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, width),
28307 FRAME_PIXEL_TO_TEXT_HEIGHT (f, height),
28308 5, 0, Qx_set_window_size_1);
28309 }
28310 }
28311
28312
28313
28314
28315
28316
28317
28318 void
28319 x_set_window_size (struct frame *f, bool change_gravity,
28320 int width, int height)
28321 {
28322 block_input ();
28323
28324 #ifdef USE_GTK
28325 if (FRAME_GTK_WIDGET (f))
28326 xg_frame_set_char_size (f, width, height);
28327 else
28328 x_set_window_size_1 (f, change_gravity, width, height);
28329 #else
28330 x_set_window_size_1 (f, change_gravity, width, height);
28331 x_clear_under_internal_border (f);
28332 #endif
28333
28334
28335 mark_window_cursors_off (XWINDOW (f->root_window));
28336
28337
28338
28339
28340
28341 cancel_mouse_face (f);
28342
28343 unblock_input ();
28344
28345 do_pending_window_change (false);
28346 }
28347
28348
28349
28350 void
28351 frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
28352 {
28353 #ifdef HAVE_XINPUT2
28354 int deviceid;
28355
28356 deviceid = FRAME_DISPLAY_INFO (f)->client_pointer_device;
28357
28358 if (FRAME_DISPLAY_INFO (f)->supports_xi2
28359 && deviceid != -1)
28360 {
28361 block_input ();
28362 x_ignore_errors_for_next_request (FRAME_DISPLAY_INFO (f), 0);
28363 XIWarpPointer (FRAME_X_DISPLAY (f), deviceid, None,
28364 FRAME_X_WINDOW (f), 0, 0, 0, 0, pix_x, pix_y);
28365 x_stop_ignoring_errors (FRAME_DISPLAY_INFO (f));
28366 unblock_input ();
28367 }
28368 else
28369 #endif
28370 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
28371 0, 0, 0, 0, pix_x, pix_y);
28372 }
28373
28374
28375
28376 static void
28377 x_raise_frame (struct frame *f)
28378 {
28379 block_input ();
28380
28381 if (FRAME_VISIBLE_P (f))
28382 {
28383 XRaiseWindow (FRAME_X_DISPLAY (f),
28384 FRAME_OUTER_WINDOW (f));
28385 XFlush (FRAME_X_DISPLAY (f));
28386 }
28387
28388 unblock_input ();
28389 }
28390
28391 static void
28392 x_lower_frame_1 (struct frame *f)
28393 {
28394 Window *windows;
28395 Lisp_Object frame, tail;
28396 struct frame *sibling;
28397
28398 windows = alloca (2 * sizeof *windows);
28399
28400
28401
28402
28403
28404 FOR_EACH_FRAME (tail, frame)
28405 {
28406 sibling = XFRAME (frame);
28407
28408 if (sibling == f)
28409 continue;
28410
28411 if (FRAME_PARENT_FRAME (sibling)
28412 != FRAME_PARENT_FRAME (f))
28413 continue;
28414
28415 windows[0] = FRAME_OUTER_WINDOW (sibling);
28416 windows[1] = FRAME_OUTER_WINDOW (f);
28417
28418 XRestackWindows (FRAME_X_DISPLAY (f), windows, 2);
28419 }
28420 }
28421
28422
28423
28424 static void
28425 x_lower_frame (struct frame *f)
28426 {
28427 if (FRAME_PARENT_FRAME (f)
28428 && (FRAME_HAS_VERTICAL_SCROLL_BARS (FRAME_PARENT_FRAME (f))
28429 || FRAME_HAS_HORIZONTAL_SCROLL_BARS (FRAME_PARENT_FRAME (f))))
28430 x_lower_frame_1 (f);
28431 else
28432 XLowerWindow (FRAME_X_DISPLAY (f),
28433 FRAME_OUTER_WINDOW (f));
28434
28435 #ifdef HAVE_XWIDGETS
28436
28437
28438
28439 if (FRAME_PARENT_FRAME (f))
28440 lower_frame_xwidget_views (FRAME_PARENT_FRAME (f));
28441 #endif
28442
28443 XFlush (FRAME_X_DISPLAY (f));
28444 }
28445
28446 static void
28447 XTframe_raise_lower (struct frame *f, bool raise_flag)
28448 {
28449 if (raise_flag)
28450 x_raise_frame (f);
28451 else
28452 x_lower_frame (f);
28453 }
28454
28455
28456
28457 static void
28458 xembed_request_focus (struct frame *f)
28459 {
28460
28461
28462 if (FRAME_VISIBLE_P (f))
28463 xembed_send_message (f, CurrentTime,
28464 XEMBED_REQUEST_FOCUS, 0, 0, 0);
28465 }
28466
28467 static Bool
28468 server_timestamp_predicate (Display *display, XEvent *xevent,
28469 XPointer arg)
28470 {
28471 XID *args = (XID *) arg;
28472
28473 if (xevent->type == PropertyNotify
28474 && xevent->xproperty.window == args[0]
28475 && xevent->xproperty.atom == args[1])
28476 return True;
28477
28478 return False;
28479 }
28480
28481
28482
28483
28484 static Time
28485 x_get_server_time (struct frame *f)
28486 {
28487 Atom property_atom;
28488 XEvent property_dummy;
28489 struct x_display_info *dpyinfo;
28490 XID client_data[2];
28491 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
28492 uint_fast64_t current_monotonic_time;
28493 #endif
28494
28495
28496
28497
28498 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
28499 if (FRAME_DISPLAY_INFO (f)->server_time_monotonic_p)
28500 {
28501 current_monotonic_time = x_sync_current_monotonic_time ();
28502
28503 if (current_monotonic_time)
28504
28505 return (current_monotonic_time / 1000) & X_ULONG_MAX;
28506 }
28507 #endif
28508
28509 dpyinfo = FRAME_DISPLAY_INFO (f);
28510 property_atom = dpyinfo->Xatom_EMACS_SERVER_TIME_PROP;
28511 client_data[0] = FRAME_OUTER_WINDOW (f);
28512 client_data[1] = property_atom;
28513
28514 XChangeProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
28515 property_atom, XA_ATOM, 32,
28516 PropModeReplace,
28517 (unsigned char *) &property_atom, 1);
28518
28519 XIfEvent (dpyinfo->display, &property_dummy,
28520 server_timestamp_predicate, (XPointer) client_data);
28521
28522 return property_dummy.xproperty.time;
28523 }
28524
28525
28526
28527 static void
28528 x_ewmh_activate_frame (struct frame *f)
28529 {
28530 XEvent msg;
28531 struct x_display_info *dpyinfo;
28532 Time time;
28533
28534 dpyinfo = FRAME_DISPLAY_INFO (f);
28535
28536 if (FRAME_VISIBLE_P (f))
28537 {
28538
28539
28540
28541 msg.xclient.type = ClientMessage;
28542 msg.xclient.window = FRAME_OUTER_WINDOW (f);
28543 msg.xclient.message_type = dpyinfo->Xatom_net_active_window;
28544 msg.xclient.format = 32;
28545 msg.xclient.data.l[0] = 1;
28546 msg.xclient.data.l[1] = dpyinfo->last_user_time;
28547 msg.xclient.data.l[2] = (!dpyinfo->x_focus_frame
28548 ? None
28549 : FRAME_OUTER_WINDOW (dpyinfo->x_focus_frame));
28550 msg.xclient.data.l[3] = 0;
28551 msg.xclient.data.l[4] = 0;
28552
28553
28554
28555
28556 if (!dpyinfo->x_focus_frame)
28557 {
28558 if (EQ (Vx_allow_focus_stealing, Qimitate_pager))
28559 msg.xclient.data.l[0] = 2;
28560 else if (EQ (Vx_allow_focus_stealing, Qnewer_time))
28561 {
28562 block_input ();
28563 time = x_get_server_time (f);
28564 #ifdef USE_GTK
28565 x_set_gtk_user_time (f, time);
28566 #endif
28567
28568
28569 dpyinfo->x_focus_frame = f;
28570 x_display_set_last_user_time (dpyinfo, time, true, true);
28571 dpyinfo->x_focus_frame = NULL;
28572 unblock_input ();
28573
28574 msg.xclient.data.l[1] = time;
28575 }
28576 else if (EQ (Vx_allow_focus_stealing, Qraise_and_focus))
28577 {
28578 time = x_get_server_time (f);
28579
28580 x_set_input_focus (FRAME_DISPLAY_INFO (f),
28581 FRAME_OUTER_WINDOW (f),
28582 time);
28583 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
28584
28585 return;
28586 }
28587 }
28588
28589 XSendEvent (dpyinfo->display, dpyinfo->root_window,
28590 False, (SubstructureRedirectMask
28591 | SubstructureNotifyMask), &msg);
28592 }
28593 }
28594
28595 static Lisp_Object
28596 x_get_focus_frame (struct frame *f)
28597 {
28598 Lisp_Object lisp_focus;
28599
28600 struct frame *focus = FRAME_DISPLAY_INFO (f)->x_focus_frame;
28601
28602 if (!focus)
28603 return Qnil;
28604
28605 XSETFRAME (lisp_focus, focus);
28606 return lisp_focus;
28607 }
28608
28609
28610
28611
28612 static struct frame *
28613 x_get_toplevel_parent (struct frame *f)
28614 {
28615 struct frame *parent;
28616
28617 if (!FRAME_PARENT_FRAME (f))
28618 return NULL;
28619
28620 parent = FRAME_PARENT_FRAME (f);
28621
28622 while (FRAME_PARENT_FRAME (parent))
28623 parent = FRAME_PARENT_FRAME (parent);
28624
28625 return parent;
28626 }
28627
28628 static void
28629 x_set_input_focus (struct x_display_info *dpyinfo, Window window,
28630 Time time)
28631 {
28632 #ifdef HAVE_XINPUT2
28633 struct xi_device_t *device;
28634 #endif
28635
28636
28637
28638
28639
28640
28641
28642
28643
28644
28645
28646 #ifdef HAVE_XINPUT2
28647 if (dpyinfo->supports_xi2
28648 && dpyinfo->client_pointer_device != -1)
28649 {
28650 device = xi_device_from_id (dpyinfo, dpyinfo->client_pointer_device);
28651
28652
28653
28654
28655 if (device)
28656 {
28657 eassert (device->use == XIMasterPointer);
28658
28659 x_ignore_errors_for_next_request (dpyinfo, 0);
28660 XISetFocus (dpyinfo->display, device->attachment,
28661
28662
28663
28664 window, time);
28665 x_stop_ignoring_errors (dpyinfo);
28666
28667 return;
28668 }
28669 }
28670 #endif
28671
28672
28673
28674 x_ignore_errors_for_next_request (dpyinfo, 0);
28675 XSetInputFocus (dpyinfo->display, window, RevertToParent, time);
28676 x_stop_ignoring_errors (dpyinfo);
28677 }
28678
28679
28680
28681
28682
28683
28684
28685
28686
28687
28688 static void
28689 x_focus_frame (struct frame *f, bool noactivate)
28690 {
28691 struct x_display_info *dpyinfo;
28692 Time time;
28693
28694 dpyinfo = FRAME_DISPLAY_INFO (f);
28695
28696 if (dpyinfo->untrusted)
28697
28698
28699 return;
28700
28701
28702
28703 block_input ();
28704
28705 if (FRAME_X_EMBEDDED_P (f))
28706
28707
28708
28709 xembed_request_focus (f);
28710 else
28711 {
28712 if (!noactivate
28713
28714
28715
28716 && !FRAME_OVERRIDE_REDIRECT (f)
28717
28718
28719 && !FRAME_PARENT_FRAME (f)
28720
28721
28722 && (!dpyinfo->x_focus_frame
28723 || (x_get_toplevel_parent (dpyinfo->x_focus_frame)
28724 != f))
28725 && x_wm_supports (f, dpyinfo->Xatom_net_active_window))
28726 {
28727
28728
28729
28730
28731
28732 x_ewmh_activate_frame (f);
28733 goto out;
28734 }
28735
28736 if (NILP (Vx_no_window_manager))
28737 {
28738
28739
28740
28741
28742
28743
28744
28745 time = dpyinfo->last_user_time;
28746
28747
28748
28749 if (EQ (Vx_allow_focus_stealing, Qnewer_time)
28750 && !dpyinfo->x_focus_frame)
28751 time = x_get_server_time (f);
28752
28753
28754
28755
28756
28757 x_set_input_focus (FRAME_DISPLAY_INFO (f), FRAME_OUTER_WINDOW (f),
28758 time);
28759 }
28760 else
28761 x_set_input_focus (FRAME_DISPLAY_INFO (f), FRAME_OUTER_WINDOW (f),
28762
28763
28764
28765 CurrentTime);
28766 }
28767
28768 out:
28769 unblock_input ();
28770 }
28771
28772
28773
28774
28775 #if defined USE_X_TOOLKIT || ! defined USE_GTK
28776
28777
28778
28779 #define XEMBED_VERSION 0
28780
28781 static void
28782 xembed_set_info (struct frame *f, enum xembed_info flags)
28783 {
28784 unsigned long data[2];
28785 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
28786
28787 data[0] = XEMBED_VERSION;
28788 data[1] = flags;
28789
28790 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
28791 dpyinfo->Xatom_XEMBED_INFO, dpyinfo->Xatom_XEMBED_INFO,
28792 32, PropModeReplace, (unsigned char *) data, 2);
28793 }
28794 #endif
28795
28796 static void
28797 xembed_send_message (struct frame *f, Time t, enum xembed_message msg,
28798 long int detail, long int data1, long int data2)
28799 {
28800 XEvent event;
28801
28802 event.xclient.type = ClientMessage;
28803 event.xclient.window = FRAME_X_OUTPUT (f)->parent_desc;
28804 event.xclient.message_type = FRAME_DISPLAY_INFO (f)->Xatom_XEMBED;
28805 event.xclient.format = 32;
28806 event.xclient.data.l[0] = t;
28807 event.xclient.data.l[1] = msg;
28808 event.xclient.data.l[2] = detail;
28809 event.xclient.data.l[3] = data1;
28810 event.xclient.data.l[4] = data2;
28811
28812
28813
28814
28815
28816 x_ignore_errors_for_next_request (FRAME_DISPLAY_INFO (f), 0);
28817 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_OUTPUT (f)->parent_desc,
28818 False, NoEventMask, &event);
28819 x_stop_ignoring_errors (FRAME_DISPLAY_INFO (f));
28820 }
28821
28822
28823
28824
28825
28826
28827
28828
28829
28830
28831
28832 void
28833 x_make_frame_visible (struct frame *f)
28834 {
28835 #ifndef USE_GTK
28836 struct x_display_info *dpyinfo;
28837 struct x_output *output;
28838 #endif
28839 bool output_flushed;
28840
28841 if (FRAME_PARENT_FRAME (f))
28842 {
28843 if (!FRAME_VISIBLE_P (f))
28844 {
28845 block_input ();
28846 #ifdef USE_GTK
28847 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
28848 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
28849 f->left_pos, f->top_pos);
28850 #else
28851 XMapRaised (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
28852 #endif
28853 unblock_input ();
28854
28855 SET_FRAME_VISIBLE (f, true);
28856 SET_FRAME_ICONIFIED (f, false);
28857 }
28858 return;
28859 }
28860
28861 block_input ();
28862
28863 gui_set_bitmap_icon (f);
28864
28865 #ifndef USE_GTK
28866 dpyinfo = FRAME_DISPLAY_INFO (f);
28867 #endif
28868
28869 if (! FRAME_VISIBLE_P (f))
28870 {
28871
28872
28873
28874
28875 if (! FRAME_ICONIFIED_P (f)
28876 && ! FRAME_X_EMBEDDED_P (f)
28877 && ! f->output_data.x->asked_for_visible)
28878 x_set_offset (f, f->left_pos, f->top_pos, 0);
28879
28880 #ifndef USE_GTK
28881 output = FRAME_X_OUTPUT (f);
28882 x_update_frame_user_time_window (f);
28883
28884
28885
28886 if (output->user_time_window != None)
28887 {
28888 if (dpyinfo->last_user_time)
28889 XChangeProperty (dpyinfo->display, output->user_time_window,
28890 dpyinfo->Xatom_net_wm_user_time,
28891 XA_CARDINAL, 32, PropModeReplace,
28892 (unsigned char *) &dpyinfo->last_user_time, 1);
28893 else
28894 XDeleteProperty (dpyinfo->display, output->user_time_window,
28895 dpyinfo->Xatom_net_wm_user_time);
28896 }
28897 #endif
28898
28899 f->output_data.x->asked_for_visible = true;
28900
28901 if (! EQ (Vx_no_window_manager, Qt))
28902 x_wm_set_window_state (f, NormalState);
28903 #ifdef USE_X_TOOLKIT
28904 if (FRAME_X_EMBEDDED_P (f))
28905 xembed_set_info (f, XEMBED_MAPPED);
28906 else
28907 {
28908
28909 XtMapWidget (f->output_data.x->widget);
28910 }
28911 #else
28912 #ifdef USE_GTK
28913 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
28914 gtk_window_deiconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
28915 #else
28916 if (FRAME_X_EMBEDDED_P (f))
28917 xembed_set_info (f, XEMBED_MAPPED);
28918 else
28919 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
28920 #endif
28921 #endif
28922
28923 if (FRAME_X_EMBEDDED_P (f))
28924 {
28925 SET_FRAME_VISIBLE (f, true);
28926 SET_FRAME_ICONIFIED (f, false);
28927 }
28928 }
28929
28930
28931
28932
28933 {
28934 Lisp_Object frame;
28935
28936
28937
28938 bool previously_visible = f->output_data.x->has_been_visible;
28939
28940 XSETFRAME (frame, f);
28941
28942 int original_left = f->left_pos;
28943 int original_top = f->top_pos;
28944
28945
28946 unblock_input ();
28947
28948
28949
28950 output_flushed = false;
28951
28952
28953
28954
28955
28956
28957
28958
28959
28960
28961
28962
28963 if (!FRAME_VISIBLE_P (f)
28964 && !FRAME_ICONIFIED_P (f)
28965 && !FRAME_X_EMBEDDED_P (f)
28966 && !FRAME_PARENT_FRAME (f)
28967 && NILP (Vx_lax_frame_positioning)
28968 && f->win_gravity == NorthWestGravity
28969 && previously_visible)
28970 {
28971 Drawable rootw;
28972 int x, y;
28973 unsigned int width, height, border, depth;
28974
28975 block_input ();
28976
28977
28978
28979
28980
28981
28982
28983
28984 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
28985 &rootw, &x, &y, &width, &height, &border, &depth);
28986 output_flushed = true;
28987
28988 if (original_left != x || original_top != y)
28989 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
28990 original_left, original_top);
28991
28992 unblock_input ();
28993 }
28994
28995
28996
28997
28998
28999 #ifdef CYGWIN
29000
29001
29002
29003
29004
29005
29006
29007
29008
29009 int old_poll_suppress_count = poll_suppress_count;
29010 poll_suppress_count = 1;
29011 poll_for_input_1 ();
29012 poll_suppress_count = old_poll_suppress_count;
29013 #endif
29014
29015 if (!FRAME_VISIBLE_P (f)
29016 && NILP (Vx_lax_frame_positioning))
29017 {
29018 if (CONSP (frame_size_history))
29019 frame_size_history_plain
29020 (f, build_string ("x_make_frame_visible"));
29021
29022 x_wait_for_event (f, MapNotify);
29023 output_flushed = true;
29024 }
29025
29026 if (!output_flushed)
29027 x_flush (f);
29028 }
29029 }
29030
29031
29032
29033
29034
29035 void
29036 x_make_frame_invisible (struct frame *f)
29037 {
29038 Window window;
29039
29040
29041 window = FRAME_OUTER_WINDOW (f);
29042
29043
29044 if (FRAME_DISPLAY_INFO (f)->highlight_frame == f)
29045 FRAME_DISPLAY_INFO (f)->highlight_frame = 0;
29046
29047 block_input ();
29048
29049 #ifdef HAVE_XINPUT2_2
29050
29051 xi_unlink_touch_points (f);
29052 #endif
29053
29054
29055
29056
29057
29058
29059 x_wm_set_size_hint (f, 0, true);
29060
29061 #ifdef USE_GTK
29062 if (FRAME_GTK_OUTER_WIDGET (f))
29063 gtk_widget_hide (FRAME_GTK_OUTER_WIDGET (f));
29064 else
29065 #else
29066 if (FRAME_X_EMBEDDED_P (f))
29067 xembed_set_info (f, 0);
29068 else
29069 #endif
29070
29071 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
29072 DefaultScreen (FRAME_X_DISPLAY (f))))
29073 {
29074 unblock_input ();
29075 error ("Can't notify window manager of window withdrawal");
29076 }
29077
29078
29079
29080 if (NILP (Vx_lax_frame_positioning))
29081 XSync (FRAME_X_DISPLAY (f), False);
29082
29083
29084
29085
29086
29087
29088 SET_FRAME_VISIBLE (f, 0);
29089 SET_FRAME_ICONIFIED (f, false);
29090
29091 if (CONSP (frame_size_history))
29092 frame_size_history_plain (f, build_string ("x_make_frame_invisible"));
29093
29094 unblock_input ();
29095 }
29096
29097 static void
29098 x_make_frame_visible_invisible (struct frame *f, bool visible)
29099 {
29100 if (visible)
29101 x_make_frame_visible (f);
29102 else
29103 x_make_frame_invisible (f);
29104 }
29105
29106 Cursor
29107 x_create_font_cursor (struct x_display_info *dpyinfo, int glyph)
29108 {
29109 if (glyph <= 65535)
29110 return XCreateFontCursor (dpyinfo->display, glyph);
29111
29112
29113
29114 return make_invisible_cursor (dpyinfo);
29115 }
29116
29117
29118
29119
29120 void
29121 x_iconify_frame (struct frame *f)
29122 {
29123 #ifdef USE_X_TOOLKIT
29124 int result;
29125 #endif
29126
29127
29128 if (FRAME_DISPLAY_INFO (f)->highlight_frame == f)
29129 FRAME_DISPLAY_INFO (f)->highlight_frame = 0;
29130
29131 if (FRAME_ICONIFIED_P (f))
29132 return;
29133
29134 block_input ();
29135
29136 gui_set_bitmap_icon (f);
29137
29138 #if defined (USE_GTK)
29139 if (FRAME_GTK_OUTER_WIDGET (f))
29140 {
29141 if (! FRAME_VISIBLE_P (f))
29142 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
29143
29144 gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
29145 SET_FRAME_VISIBLE (f, 0);
29146 SET_FRAME_ICONIFIED (f, true);
29147 unblock_input ();
29148 return;
29149 }
29150 #endif
29151
29152 #ifdef USE_X_TOOLKIT
29153
29154 if (! FRAME_VISIBLE_P (f))
29155 {
29156 if (! EQ (Vx_no_window_manager, Qt))
29157 x_wm_set_window_state (f, IconicState);
29158
29159 XtMapWidget (f->output_data.x->widget);
29160
29161
29162
29163 SET_FRAME_VISIBLE (f, 0);
29164 SET_FRAME_ICONIFIED (f, true);
29165 unblock_input ();
29166 return;
29167 }
29168
29169 result = XIconifyWindow (FRAME_X_DISPLAY (f),
29170 XtWindow (f->output_data.x->widget),
29171 DefaultScreen (FRAME_X_DISPLAY (f)));
29172 unblock_input ();
29173
29174 if (!result)
29175 error ("Can't notify window manager of iconification");
29176
29177 SET_FRAME_ICONIFIED (f, true);
29178 SET_FRAME_VISIBLE (f, 0);
29179
29180 block_input ();
29181 XFlush (FRAME_X_DISPLAY (f));
29182 unblock_input ();
29183 #else
29184
29185
29186
29187 if (! FRAME_VISIBLE_P (f)
29188 && ! FRAME_ICONIFIED_P (f)
29189 && ! FRAME_X_EMBEDDED_P (f))
29190 x_set_offset (f, f->left_pos, f->top_pos, 0);
29191
29192
29193
29194
29195
29196
29197 {
29198 XEvent msg;
29199
29200 msg.xclient.window = FRAME_X_WINDOW (f);
29201 msg.xclient.type = ClientMessage;
29202 msg.xclient.message_type = FRAME_DISPLAY_INFO (f)->Xatom_wm_change_state;
29203 msg.xclient.format = 32;
29204 msg.xclient.data.l[0] = IconicState;
29205 msg.xclient.data.l[1] = 0;
29206 msg.xclient.data.l[2] = 0;
29207 msg.xclient.data.l[3] = 0;
29208 msg.xclient.data.l[4] = 0;
29209
29210 if (! XSendEvent (FRAME_X_DISPLAY (f),
29211 FRAME_DISPLAY_INFO (f)->root_window,
29212 False,
29213 SubstructureRedirectMask | SubstructureNotifyMask,
29214 &msg))
29215 {
29216 unblock_input ();
29217 error ("Can't notify window manager of iconification");
29218 }
29219 }
29220
29221
29222
29223 x_wm_set_window_state (f, IconicState);
29224
29225 if (!FRAME_VISIBLE_P (f))
29226 {
29227
29228 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
29229 }
29230
29231 SET_FRAME_ICONIFIED (f, true);
29232 SET_FRAME_VISIBLE (f, 0);
29233
29234 XFlush (FRAME_X_DISPLAY (f));
29235 unblock_input ();
29236 #endif
29237 }
29238
29239
29240
29241
29242 void
29243 x_free_frame_resources (struct frame *f)
29244 {
29245 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
29246 Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
29247 #ifdef USE_X_TOOLKIT
29248 Lisp_Object bar;
29249 struct scroll_bar *b;
29250 #endif
29251
29252 block_input ();
29253
29254 #ifdef HAVE_XINPUT2
29255
29256 xi_handle_delete_frame (dpyinfo, f);
29257 #endif
29258
29259 #ifdef HAVE_XINPUT2_2
29260
29261 xi_unlink_touch_points (f);
29262 #endif
29263
29264
29265
29266 if (dpyinfo->display)
29267 {
29268
29269
29270 if (f->pointer_invisible)
29271 XTtoggle_invisible_pointer (f, 0);
29272
29273
29274
29275
29276 free_frame_faces (f);
29277 tear_down_x_back_buffer (f);
29278
29279 if (f->output_data.x->icon_desc)
29280 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
29281
29282 #ifdef USE_X_TOOLKIT
29283
29284
29285
29286
29287 for (bar = FRAME_SCROLL_BARS (f); !NILP (bar); bar = b->next)
29288 {
29289 b = XSCROLL_BAR (bar);
29290 x_scroll_bar_remove (b);
29291 }
29292 #endif
29293
29294 #ifdef HAVE_X_I18N
29295 if (FRAME_XIC (f))
29296 free_frame_xic (f);
29297 #endif
29298
29299 #ifdef USE_CAIRO
29300 x_cr_destroy_frame_context (f);
29301 #endif
29302 #ifdef USE_X_TOOLKIT
29303 if (f->output_data.x->widget)
29304 {
29305 XtDestroyWidget (f->output_data.x->widget);
29306 f->output_data.x->widget = NULL;
29307 }
29308
29309
29310 else if (FRAME_X_WINDOW (f))
29311 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
29312
29313 free_frame_menubar (f);
29314
29315 if (f->shell_position)
29316 xfree (f->shell_position);
29317 #else
29318
29319 #ifdef HAVE_XWIDGETS
29320 kill_frame_xwidget_views (f);
29321 #endif
29322
29323 #ifdef USE_GTK
29324 xg_free_frame_widgets (f);
29325 #endif
29326
29327 tear_down_x_back_buffer (f);
29328 if (FRAME_X_WINDOW (f))
29329 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
29330 #endif
29331
29332 #ifdef HAVE_XSYNC
29333 if (FRAME_X_BASIC_COUNTER (f) != None)
29334 XSyncDestroyCounter (FRAME_X_DISPLAY (f),
29335 FRAME_X_BASIC_COUNTER (f));
29336
29337 if (FRAME_X_EXTENDED_COUNTER (f) != None)
29338 XSyncDestroyCounter (FRAME_X_DISPLAY (f),
29339 FRAME_X_EXTENDED_COUNTER (f));
29340 #endif
29341
29342 unload_color (f, FRAME_FOREGROUND_PIXEL (f));
29343 unload_color (f, FRAME_BACKGROUND_PIXEL (f));
29344 unload_color (f, f->output_data.x->cursor_pixel);
29345 unload_color (f, f->output_data.x->cursor_foreground_pixel);
29346 unload_color (f, f->output_data.x->border_pixel);
29347 unload_color (f, f->output_data.x->mouse_pixel);
29348
29349 if (f->output_data.x->scroll_bar_background_pixel != -1)
29350 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
29351 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
29352 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
29353 #if defined (USE_LUCID) && defined (USE_TOOLKIT_SCROLL_BARS)
29354
29355 if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
29356 unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
29357 if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
29358 unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
29359 #endif
29360 if (f->output_data.x->white_relief.pixel != -1)
29361 unload_color (f, f->output_data.x->white_relief.pixel);
29362 if (f->output_data.x->black_relief.pixel != -1)
29363 unload_color (f, f->output_data.x->black_relief.pixel);
29364
29365 x_free_gcs (f);
29366
29367
29368 if (f->output_data.x->white_relief.gc)
29369 {
29370 XFreeGC (dpyinfo->display, f->output_data.x->white_relief.gc);
29371 f->output_data.x->white_relief.gc = 0;
29372 }
29373 if (f->output_data.x->black_relief.gc)
29374 {
29375 XFreeGC (dpyinfo->display, f->output_data.x->black_relief.gc);
29376 f->output_data.x->black_relief.gc = 0;
29377 }
29378
29379
29380 if (f->output_data.x->text_cursor != 0)
29381 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->text_cursor);
29382 if (f->output_data.x->nontext_cursor != 0)
29383 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->nontext_cursor);
29384 if (f->output_data.x->modeline_cursor != 0)
29385 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->modeline_cursor);
29386 if (f->output_data.x->hand_cursor != 0)
29387 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->hand_cursor);
29388 if (f->output_data.x->hourglass_cursor != 0)
29389 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->hourglass_cursor);
29390 if (f->output_data.x->horizontal_drag_cursor != 0)
29391 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->horizontal_drag_cursor);
29392 if (f->output_data.x->vertical_drag_cursor != 0)
29393 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->vertical_drag_cursor);
29394 if (f->output_data.x->left_edge_cursor != 0)
29395 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->left_edge_cursor);
29396 if (f->output_data.x->top_left_corner_cursor != 0)
29397 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->top_left_corner_cursor);
29398 if (f->output_data.x->top_edge_cursor != 0)
29399 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->top_edge_cursor);
29400 if (f->output_data.x->top_right_corner_cursor != 0)
29401 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->top_right_corner_cursor);
29402 if (f->output_data.x->right_edge_cursor != 0)
29403 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->right_edge_cursor);
29404 if (f->output_data.x->bottom_right_corner_cursor != 0)
29405 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->bottom_right_corner_cursor);
29406 if (f->output_data.x->bottom_edge_cursor != 0)
29407 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->bottom_edge_cursor);
29408 if (f->output_data.x->bottom_left_corner_cursor != 0)
29409 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->bottom_left_corner_cursor);
29410
29411
29412 #if defined HAVE_XSYNCTRIGGERFENCE && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
29413 x_sync_free_fences (f);
29414 #endif
29415
29416 #ifdef USE_TOOLKIT_SCROLL_BARS
29417
29418
29419
29420 dpyinfo->n_protected_windows = 0;
29421 #endif
29422 }
29423
29424 #ifdef HAVE_GTK3
29425 if (FRAME_OUTPUT_DATA (f)->scrollbar_background_css_provider)
29426 g_object_unref (FRAME_OUTPUT_DATA (f)->scrollbar_background_css_provider);
29427
29428 if (FRAME_OUTPUT_DATA (f)->scrollbar_foreground_css_provider)
29429 g_object_unref (FRAME_OUTPUT_DATA (f)->scrollbar_foreground_css_provider);
29430 #endif
29431
29432 if (f == dpyinfo->motif_drag_atom_owner)
29433 {
29434 dpyinfo->motif_drag_atom_owner = NULL;
29435 dpyinfo->motif_drag_atom = None;
29436 }
29437
29438 if (f == dpyinfo->x_focus_frame)
29439 dpyinfo->x_focus_frame = 0;
29440 if (f == dpyinfo->x_focus_event_frame)
29441 dpyinfo->x_focus_event_frame = 0;
29442 if (f == dpyinfo->highlight_frame)
29443 dpyinfo->highlight_frame = 0;
29444 if (f == hlinfo->mouse_face_mouse_frame)
29445 reset_mouse_highlight (hlinfo);
29446
29447
29448
29449 if (f == dpyinfo->last_mouse_motion_frame)
29450 dpyinfo->last_mouse_motion_frame = NULL;
29451 if (f == dpyinfo->last_mouse_frame)
29452 dpyinfo->last_mouse_frame = NULL;
29453
29454 #ifdef HAVE_XINPUT2
29455
29456
29457
29458
29459
29460 if (dpyinfo->supports_xi2)
29461 xi_handle_focus_change (dpyinfo);
29462 #endif
29463
29464 unblock_input ();
29465 }
29466
29467
29468
29469
29470 static void
29471 x_destroy_window (struct frame *f)
29472 {
29473 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
29474
29475
29476
29477 if (dpyinfo->display != 0)
29478 x_free_frame_resources (f);
29479
29480 xfree (f->output_data.x->saved_menu_event);
29481
29482 #ifdef HAVE_X_I18N
29483 if (f->output_data.x->preedit_chars)
29484 xfree (f->output_data.x->preedit_chars);
29485 #endif
29486
29487 #ifdef HAVE_XINPUT2
29488 #ifdef HAVE_XINPUT2_1
29489 if (f->output_data.x->xi_masks)
29490 XFree (f->output_data.x->xi_masks);
29491 #else
29492
29493
29494 if (f->output_data.x->xi_masks)
29495 xfree (f->output_data.x->xi_masks);
29496 #endif
29497 #endif
29498
29499 xfree (f->output_data.x);
29500 f->output_data.x = NULL;
29501
29502 dpyinfo->reference_count--;
29503 }
29504
29505
29506
29507
29508
29509
29510 Atom
29511 x_intern_cached_atom (struct x_display_info *dpyinfo,
29512 const char *name, bool predefined_only)
29513 {
29514 int i;
29515 char *ptr;
29516 Atom *atom;
29517
29518
29519 char xsettings_atom_name[sizeof "_XSETTINGS_S%d" - 2
29520 + INT_STRLEN_BOUND (int)];
29521 char cm_atom_name[sizeof "_NET_WM_CM_S%d" - 2
29522 + INT_STRLEN_BOUND (int)];
29523
29524 sprintf (xsettings_atom_name, "_XSETTINGS_S%d",
29525 XScreenNumberOfScreen (dpyinfo->screen));
29526 sprintf (cm_atom_name, "_NET_WM_CM_S%d",
29527 XScreenNumberOfScreen (dpyinfo->screen));
29528
29529 if (!strcmp (name, xsettings_atom_name))
29530 return dpyinfo->Xatom_xsettings_sel;
29531
29532 if (!strcmp (name, cm_atom_name))
29533 return dpyinfo->Xatom_NET_WM_CM_Sn;
29534
29535
29536 if (!strcmp (name, "PRIMARY"))
29537 return XA_PRIMARY;
29538
29539 if (!strcmp (name, "SECONDARY"))
29540 return XA_SECONDARY;
29541
29542 if (!strcmp (name, "STRING"))
29543 return XA_STRING;
29544
29545 if (!strcmp (name, "INTEGER"))
29546 return XA_INTEGER;
29547
29548 if (!strcmp (name, "ATOM"))
29549 return XA_ATOM;
29550
29551 if (!strcmp (name, "WINDOW"))
29552 return XA_WINDOW;
29553
29554 if (!strcmp (name, "DRAWABLE"))
29555 return XA_DRAWABLE;
29556
29557 if (!strcmp (name, "BITMAP"))
29558 return XA_BITMAP;
29559
29560 if (!strcmp (name, "CARDINAL"))
29561 return XA_CARDINAL;
29562
29563 if (!strcmp (name, "COLORMAP"))
29564 return XA_COLORMAP;
29565
29566 if (!strcmp (name, "CURSOR"))
29567 return XA_CURSOR;
29568
29569 if (!strcmp (name, "FONT"))
29570 return XA_FONT;
29571
29572 if (dpyinfo->motif_drag_atom != None
29573 && !strcmp (name, dpyinfo->motif_drag_atom_name))
29574 return dpyinfo->motif_drag_atom;
29575
29576 for (i = 0; i < ARRAYELTS (x_atom_refs); ++i)
29577 {
29578 ptr = (char *) dpyinfo;
29579
29580 if (!strcmp (x_atom_refs[i].name, name))
29581 {
29582 atom = (Atom *) (ptr + x_atom_refs[i].offset);
29583
29584 return *atom;
29585 }
29586 }
29587
29588 if (predefined_only)
29589 return None;
29590
29591 return XInternAtom (dpyinfo->display, name, False);
29592 }
29593
29594
29595
29596
29597 char *
29598 x_get_atom_name (struct x_display_info *dpyinfo, Atom atom,
29599 bool *need_sync)
29600 {
29601 char *dpyinfo_pointer, *name, *value, *buffer;
29602 int i;
29603 Atom ref_atom;
29604
29605 dpyinfo_pointer = (char *) dpyinfo;
29606 value = NULL;
29607
29608 if (need_sync)
29609 *need_sync = false;
29610
29611 buffer = alloca (45 + INT_STRLEN_BOUND (int));
29612
29613 switch (atom)
29614 {
29615 case XA_PRIMARY:
29616 return xstrdup ("PRIMARY");
29617
29618 case XA_SECONDARY:
29619 return xstrdup ("SECONDARY");
29620
29621 case XA_INTEGER:
29622 return xstrdup ("INTEGER");
29623
29624 case XA_ATOM:
29625 return xstrdup ("ATOM");
29626
29627 case XA_CARDINAL:
29628 return xstrdup ("CARDINAL");
29629
29630 case XA_WINDOW:
29631 return xstrdup ("WINDOW");
29632
29633 case XA_DRAWABLE:
29634 return xstrdup ("DRAWABLE");
29635
29636 case XA_BITMAP:
29637 return xstrdup ("BITMAP");
29638
29639 case XA_COLORMAP:
29640 return xstrdup ("COLORMAP");
29641
29642 case XA_FONT:
29643 return xstrdup ("FONT");
29644
29645 default:
29646 if (dpyinfo->motif_drag_atom
29647 && atom == dpyinfo->motif_drag_atom)
29648 return xstrdup (dpyinfo->motif_drag_atom_name);
29649
29650 if (atom == dpyinfo->Xatom_xsettings_sel)
29651 {
29652 sprintf (buffer, "_XSETTINGS_S%d",
29653 XScreenNumberOfScreen (dpyinfo->screen));
29654 return xstrdup (buffer);
29655 }
29656
29657 if (atom == dpyinfo->Xatom_NET_WM_CM_Sn)
29658 {
29659 sprintf (buffer, "_NET_WM_CM_S%d",
29660 XScreenNumberOfScreen (dpyinfo->screen));
29661 return xstrdup (buffer);
29662 }
29663
29664 for (i = 0; i < ARRAYELTS (x_atom_refs); ++i)
29665 {
29666 ref_atom = *(Atom *) (dpyinfo_pointer
29667 + x_atom_refs[i].offset);
29668
29669 if (atom == ref_atom)
29670 return xstrdup (x_atom_refs[i].name);
29671 }
29672
29673 name = XGetAtomName (dpyinfo->display, atom);
29674
29675 if (need_sync)
29676 *need_sync = true;
29677
29678 if (name)
29679 {
29680 value = xstrdup (name);
29681 XFree (name);
29682 }
29683
29684 break;
29685 }
29686
29687 return value;
29688 }
29689
29690
29691
29692
29693
29694
29695
29696
29697 void
29698 x_intern_atoms (struct x_display_info *dpyinfo, char **names, int count,
29699 Atom *atoms_return)
29700 {
29701 int i, j, indices[256];
29702 char *new_names[256];
29703 Atom results[256], candidate;
29704
29705 if (count > 256)
29706
29707
29708 XInternAtoms (dpyinfo->display, new_names, count, False, atoms_return);
29709 else
29710 {
29711 for (i = 0, j = 0; i < count; ++i)
29712 {
29713 candidate = x_intern_cached_atom (dpyinfo, names[i],
29714 true);
29715
29716 if (candidate)
29717 atoms_return[i] = candidate;
29718 else
29719 {
29720 indices[j++] = i;
29721 new_names[j - 1] = names[i];
29722 }
29723 }
29724
29725 if (!j)
29726 return;
29727
29728
29729 XInternAtoms (dpyinfo->display, new_names, j, False,
29730 results);
29731
29732 for (i = 0; i < j; ++i)
29733 atoms_return[indices[i]] = results[i];
29734 }
29735 }
29736
29737 #ifndef USE_GTK
29738
29739
29740
29741
29742 bool
29743 x_embed_frame (struct x_display_info *dpyinfo, struct frame *f)
29744 {
29745 bool rc;
29746
29747 x_catch_errors (dpyinfo->display);
29748
29749 XReparentWindow (dpyinfo->display, FRAME_OUTER_WINDOW (f),
29750 FRAME_OUTPUT_DATA (f)->parent_desc, 0, 0);
29751 rc = x_had_errors_p (dpyinfo->display);
29752 x_uncatch_errors_after_check ();
29753
29754 if (rc)
29755 return false;
29756
29757 return true;
29758 }
29759
29760 #endif
29761
29762
29763
29764
29765
29766
29767
29768
29769
29770
29771
29772 void
29773 x_wm_set_size_hint (struct frame *f, long flags, bool user_position)
29774 {
29775 #ifndef USE_GTK
29776 XSizeHints size_hints;
29777 Window window = FRAME_OUTER_WINDOW (f);
29778 #ifdef USE_X_TOOLKIT
29779 WMShellWidget shell;
29780 #ifndef USE_MOTIF
29781 bool hints_changed;
29782 #endif
29783 #endif
29784
29785 if (!window)
29786 return;
29787
29788 #ifdef USE_X_TOOLKIT
29789 if (f->output_data.x->widget)
29790 {
29791
29792
29793
29794 eassert (XtIsWMShell (f->output_data.x->widget));
29795 shell = (WMShellWidget) f->output_data.x->widget;
29796
29797 if (flags)
29798 {
29799 shell->wm.size_hints.flags &= ~(PPosition | USPosition);
29800 shell->wm.size_hints.flags |= flags & (PPosition | USPosition);
29801 }
29802
29803 if (user_position)
29804 {
29805 shell->wm.size_hints.flags &= ~PPosition;
29806 shell->wm.size_hints.flags |= USPosition;
29807 }
29808
29809 #ifndef USE_MOTIF
29810 hints_changed
29811 = widget_update_wm_size_hints (f->output_data.x->widget,
29812 f->output_data.x->edit_widget);
29813 #else
29814 widget_update_wm_size_hints (f->output_data.x->widget,
29815 f->output_data.x->edit_widget);
29816
29817
29818
29819 shell->wm.size_hints.flags &= ~(PPosition | USPosition);
29820 shell->wm.size_hints.flags |= flags & (PPosition | USPosition);
29821
29822 if (user_position)
29823 {
29824 shell->wm.size_hints.flags &= ~PPosition;
29825 shell->wm.size_hints.flags |= USPosition;
29826 }
29827 #endif
29828
29829
29830 size_hints.flags = shell->wm.size_hints.flags;
29831 size_hints.x = shell->wm.size_hints.x;
29832 size_hints.y = shell->wm.size_hints.y;
29833 size_hints.width = shell->wm.size_hints.width;
29834 size_hints.height = shell->wm.size_hints.height;
29835 size_hints.min_width = shell->wm.size_hints.min_width;
29836 size_hints.min_height = shell->wm.size_hints.min_height;
29837 size_hints.max_width = shell->wm.size_hints.max_width;
29838 size_hints.max_height = shell->wm.size_hints.max_height;
29839 size_hints.width_inc = shell->wm.size_hints.width_inc;
29840 size_hints.height_inc = shell->wm.size_hints.height_inc;
29841 size_hints.min_aspect.x = shell->wm.size_hints.min_aspect.x;
29842 size_hints.min_aspect.y = shell->wm.size_hints.min_aspect.y;
29843 size_hints.max_aspect.x = shell->wm.size_hints.max_aspect.x;
29844 size_hints.max_aspect.y = shell->wm.size_hints.max_aspect.y;
29845 size_hints.base_width = shell->wm.base_width;
29846 size_hints.base_height = shell->wm.base_height;
29847 size_hints.win_gravity = shell->wm.win_gravity;
29848
29849 #ifdef USE_MOTIF
29850 XSetWMNormalHints (XtDisplay (f->output_data.x->widget),
29851 XtWindow (f->output_data.x->widget),
29852 &size_hints);
29853 #else
29854
29855
29856
29857
29858 if (!hints_changed)
29859 XSetWMNormalHints (XtDisplay (f->output_data.x->widget),
29860 XtWindow (f->output_data.x->widget),
29861 &size_hints);
29862 #endif
29863
29864 return;
29865 }
29866 #endif
29867
29868
29869 size_hints.flags = PResizeInc | PMinSize ;
29870
29871 size_hints.x = f->left_pos;
29872 size_hints.y = f->top_pos;
29873
29874 size_hints.width = FRAME_PIXEL_WIDTH (f);
29875 size_hints.height = FRAME_PIXEL_HEIGHT (f);
29876
29877 size_hints.width_inc = frame_resize_pixelwise ? 1 : FRAME_COLUMN_WIDTH (f);
29878 size_hints.height_inc = frame_resize_pixelwise ? 1 : FRAME_LINE_HEIGHT (f);
29879
29880 size_hints.max_width = x_display_pixel_width (FRAME_DISPLAY_INFO (f))
29881 - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
29882 size_hints.max_height = x_display_pixel_height (FRAME_DISPLAY_INFO (f))
29883 - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
29884
29885
29886 {
29887 int base_width, base_height;
29888
29889 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
29890 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
29891
29892
29893
29894
29895
29896
29897
29898 size_hints.flags |= PBaseSize;
29899 size_hints.base_width = base_width;
29900 size_hints.base_height = base_height + FRAME_MENUBAR_HEIGHT (f);
29901 size_hints.min_width = base_width;
29902 size_hints.min_height = base_height;
29903 }
29904
29905
29906 if (flags)
29907 {
29908 size_hints.flags |= flags;
29909 goto no_read;
29910 }
29911
29912 {
29913 XSizeHints hints;
29914 long supplied_return;
29915 int value;
29916
29917 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
29918 &supplied_return);
29919
29920 if (flags)
29921 size_hints.flags |= flags;
29922 else
29923 {
29924 if (value == 0)
29925 hints.flags = 0;
29926 if (hints.flags & PSize)
29927 size_hints.flags |= PSize;
29928 if (hints.flags & PPosition)
29929 size_hints.flags |= PPosition;
29930 if (hints.flags & USPosition)
29931 size_hints.flags |= USPosition;
29932 if (hints.flags & USSize)
29933 size_hints.flags |= USSize;
29934 }
29935 }
29936
29937 no_read:
29938
29939 #ifdef PWinGravity
29940 size_hints.win_gravity = f->win_gravity;
29941 size_hints.flags |= PWinGravity;
29942
29943 if (user_position)
29944 {
29945 size_hints.flags &= ~ PPosition;
29946 size_hints.flags |= USPosition;
29947 }
29948 #endif
29949
29950 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
29951 #else
29952 xg_wm_set_size_hint (f, flags, user_position);
29953 #endif
29954 }
29955
29956
29957
29958 static void
29959 x_wm_set_window_state (struct frame *f, int state)
29960 {
29961 #ifdef USE_X_TOOLKIT
29962 Arg al[1];
29963
29964 XtSetArg (al[0], XtNinitialState, state);
29965 XtSetValues (f->output_data.x->widget, al, 1);
29966 #else
29967 Window window = FRAME_X_WINDOW (f);
29968
29969 f->output_data.x->wm_hints.flags |= StateHint;
29970 f->output_data.x->wm_hints.initial_state = state;
29971
29972 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
29973 #endif
29974 }
29975
29976 static void
29977 x_wm_set_icon_pixmap (struct frame *f, ptrdiff_t pixmap_id)
29978 {
29979 Pixmap icon_pixmap, icon_mask;
29980
29981 #if !defined USE_X_TOOLKIT && !defined USE_GTK
29982 Window window = FRAME_OUTER_WINDOW (f);
29983 #endif
29984
29985 if (pixmap_id > 0)
29986 {
29987 icon_pixmap = image_bitmap_pixmap (f, pixmap_id);
29988 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
29989 icon_mask = x_bitmap_mask (f, pixmap_id);
29990 f->output_data.x->wm_hints.icon_mask = icon_mask;
29991 }
29992 else
29993 {
29994
29995
29996 return;
29997 }
29998
29999
30000 #ifdef USE_GTK
30001 {
30002 xg_set_frame_icon (f, icon_pixmap, icon_mask);
30003 return;
30004 }
30005
30006 #elif defined (USE_X_TOOLKIT)
30007
30008 {
30009 Arg al[1];
30010 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
30011 XtSetValues (f->output_data.x->widget, al, 1);
30012 XtSetArg (al[0], XtNiconMask, icon_mask);
30013 XtSetValues (f->output_data.x->widget, al, 1);
30014 }
30015
30016 #else
30017
30018 f->output_data.x->wm_hints.flags |= (IconPixmapHint | IconMaskHint);
30019 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
30020
30021 #endif
30022 }
30023
30024 void
30025 x_wm_set_icon_position (struct frame *f, int icon_x, int icon_y)
30026 {
30027 Window window = FRAME_OUTER_WINDOW (f);
30028
30029 f->output_data.x->wm_hints.flags |= IconPositionHint;
30030 f->output_data.x->wm_hints.icon_x = icon_x;
30031 f->output_data.x->wm_hints.icon_y = icon_y;
30032
30033 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
30034 }
30035
30036
30037
30038
30039
30040
30041 #ifdef GLYPH_DEBUG
30042
30043
30044
30045
30046 static void
30047 x_check_font (struct frame *f, struct font *font)
30048 {
30049 eassert (font != NULL && ! NILP (font->props[FONT_TYPE_INDEX]));
30050 if (font->driver->check)
30051 eassert (font->driver->check (f, font) == 0);
30052 }
30053
30054 #endif
30055
30056
30057
30058
30059
30060
30061 static void
30062 x_free_pixmap (struct frame *f, Emacs_Pixmap pixmap)
30063 {
30064 #ifdef USE_CAIRO
30065 if (pixmap)
30066 {
30067 xfree (pixmap->data);
30068 xfree (pixmap);
30069 }
30070 #else
30071 XFreePixmap (FRAME_X_DISPLAY (f), pixmap);
30072 #endif
30073 }
30074
30075
30076
30077
30078
30079
30080 #ifdef USE_X_TOOLKIT
30081 static XrmOptionDescRec emacs_options[] = {
30082 {(char *) "-geometry", (char *) ".geometry", XrmoptionSepArg, NULL},
30083 {(char *) "-iconic", (char *) ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
30084
30085 {(char *) "-internal-border-width",
30086 (char *) "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
30087 {(char *) "-ib", (char *) "*EmacsScreen.internalBorderWidth",
30088 XrmoptionSepArg, NULL},
30089 {(char *) "-T", (char *) "*EmacsShell.title", XrmoptionSepArg, NULL},
30090 {(char *) "-wn", (char *) "*EmacsShell.title", XrmoptionSepArg, NULL},
30091 {(char *) "-title", (char *) "*EmacsShell.title", XrmoptionSepArg, NULL},
30092 {(char *) "-iconname", (char *) "*EmacsShell.iconName",
30093 XrmoptionSepArg, NULL},
30094 {(char *) "-in", (char *) "*EmacsShell.iconName", XrmoptionSepArg, NULL},
30095 {(char *) "-mc", (char *) "*pointerColor", XrmoptionSepArg, NULL},
30096 {(char *) "-cr", (char *) "*cursorColor", XrmoptionSepArg, NULL}
30097 };
30098
30099
30100
30101 static bool x_timeout_atimer_activated_flag;
30102
30103 #endif
30104
30105 static int x_initialized;
30106
30107
30108
30109 static bool
30110 same_x_server (const char *name1, const char *name2)
30111 {
30112 bool seen_colon = false;
30113 Lisp_Object sysname = Fsystem_name ();
30114 if (! STRINGP (sysname))
30115 sysname = empty_unibyte_string;
30116 const char *system_name = SSDATA (sysname);
30117 ptrdiff_t system_name_length = SBYTES (sysname);
30118 ptrdiff_t length_until_period = 0;
30119
30120 while (system_name[length_until_period] != 0
30121 && system_name[length_until_period] != '.')
30122 length_until_period++;
30123
30124
30125 if (! strncmp (name1, "unix:", 5))
30126 name1 += 4;
30127 if (! strncmp (name2, "unix:", 5))
30128 name2 += 4;
30129
30130 if (! strncmp (name1, system_name, system_name_length)
30131 && name1[system_name_length] == ':')
30132 name1 += system_name_length;
30133 if (! strncmp (name2, system_name, system_name_length)
30134 && name2[system_name_length] == ':')
30135 name2 += system_name_length;
30136
30137 if (! strncmp (name1, system_name, length_until_period)
30138 && name1[length_until_period] == ':')
30139 name1 += length_until_period;
30140 if (! strncmp (name2, system_name, length_until_period)
30141 && name2[length_until_period] == ':')
30142 name2 += length_until_period;
30143
30144 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
30145 {
30146 if (*name1 == ':')
30147 seen_colon = true;
30148 if (seen_colon && *name1 == '.')
30149 return true;
30150 }
30151 return (seen_colon
30152 && (*name1 == '.' || *name1 == '\0')
30153 && (*name2 == '.' || *name2 == '\0'));
30154 }
30155
30156
30157
30158
30159 static void
30160 get_bits_and_offset (unsigned long mask, int *bits, int *offset)
30161 {
30162 int nr = 0;
30163 int off = 0;
30164
30165 while (!(mask & 1))
30166 {
30167 off++;
30168 mask >>= 1;
30169 }
30170
30171 while (mask & 1)
30172 {
30173 nr++;
30174 mask >>= 1;
30175 }
30176
30177 *offset = off;
30178 *bits = nr;
30179 }
30180
30181
30182
30183
30184 bool
30185 x_display_ok (const char *display)
30186 {
30187
30188 unrequest_sigio ();
30189 Display *dpy = XOpenDisplay (display);
30190 request_sigio ();
30191 if (!dpy)
30192 return false;
30193 XCloseDisplay (dpy);
30194 return true;
30195 }
30196
30197 #ifdef USE_GTK
30198 static void
30199 my_log_handler (const gchar *log_domain, GLogLevelFlags log_level,
30200 const gchar *msg, gpointer user_data)
30201 {
30202 if (!strstr (msg, "g_set_prgname"))
30203 fprintf (stderr, "%s-WARNING **: %s\n", log_domain, msg);
30204 }
30205 #endif
30206
30207
30208
30209 static unsigned x_display_id;
30210
30211 #if defined HAVE_XINPUT2 && !defined HAVE_GTK3
30212
30213
30214
30215
30216 static void
30217 xi_select_hierarchy_events (struct x_display_info *dpyinfo)
30218 {
30219 XIEventMask mask;
30220 ptrdiff_t l;
30221 unsigned char *m;
30222
30223 l = XIMaskLen (XI_LASTEVENT);
30224 mask.mask = m = alloca (l);
30225 memset (m, 0, l);
30226 mask.mask_len = l;
30227
30228 mask.deviceid = XIAllDevices;
30229
30230 XISetMask (m, XI_PropertyEvent);
30231 XISetMask (m, XI_HierarchyChanged);
30232 XISetMask (m, XI_DeviceChanged);
30233
30234 XISelectEvents (dpyinfo->display, dpyinfo->root_window,
30235 &mask, 1);
30236 }
30237
30238 #endif
30239
30240 #if defined HAVE_XINPUT2 && defined HAVE_GTK3
30241
30242
30243
30244
30245
30246
30247
30248
30249
30250 static int
30251 xi_check_toolkit (Display *display)
30252 {
30253 GdkDisplay *gdpy;
30254 GdkDeviceManager *manager;
30255
30256 gdpy = gdk_x11_lookup_xdisplay (display);
30257 eassume (gdpy);
30258 manager = gdk_display_get_device_manager (gdpy);
30259
30260 if (!strcmp (G_OBJECT_TYPE_NAME (manager),
30261 "GdkX11DeviceManagerXI2"))
30262 return 1;
30263
30264 if (!strcmp (G_OBJECT_TYPE_NAME (manager),
30265 "GdkX11DeviceManagerCore"))
30266 return 0;
30267
30268
30269
30270
30271 return 2;
30272 }
30273
30274 #endif
30275
30276
30277
30278
30279
30280
30281 struct x_display_info *
30282 x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
30283 {
30284 Display *dpy;
30285 XKeyboardState keyboard_state;
30286 struct terminal *terminal;
30287 struct x_display_info *dpyinfo;
30288 XrmDatabase xrdb;
30289 Lisp_Object tem, quit_keysym;
30290 #ifdef USE_XCB
30291 xcb_connection_t *xcb_conn;
30292 #endif
30293 static char const cm_atom_fmt[] = "_NET_WM_CM_S%d";
30294 char cm_atom_sprintf[sizeof cm_atom_fmt - 2 + INT_STRLEN_BOUND (int)];
30295 #ifdef USE_GTK
30296 GdkDisplay *gdpy;
30297 GdkScreen *gscr;
30298 #endif
30299 #ifdef HAVE_XFIXES
30300 Lisp_Object lisp_name;
30301 int num_fast_selections;
30302 Atom selection_name;
30303 #ifdef USE_XCB
30304 xcb_get_selection_owner_cookie_t *selection_cookies;
30305 xcb_get_selection_owner_reply_t *selection_reply;
30306 xcb_generic_error_t *selection_error;
30307 #endif
30308 #endif
30309 int i;
30310
30311 #if defined HAVE_XFIXES && defined USE_XCB
30312 USE_SAFE_ALLOCA;
30313 #endif
30314
30315 block_input ();
30316
30317 if (!x_initialized)
30318 {
30319 x_initialize ();
30320 ++x_initialized;
30321 }
30322
30323 #if defined USE_X_TOOLKIT || defined USE_GTK
30324
30325 if (!x_display_ok (SSDATA (display_name)))
30326 error ("Display %s can't be opened", SSDATA (display_name));
30327
30328 #endif
30329
30330 #ifdef USE_GTK
30331 {
30332 #define NUM_ARGV 10
30333 int argc;
30334 char *argv[NUM_ARGV];
30335 char **argv2 = argv;
30336 guint id;
30337
30338 if (x_initialized++ > 1)
30339 {
30340 xg_display_open (SSDATA (display_name), &dpy);
30341 }
30342 else
30343 {
30344 static char display_opt[] = "--display";
30345 static char name_opt[] = "--name";
30346
30347 for (argc = 0; argc < NUM_ARGV; ++argc)
30348 argv[argc] = 0;
30349
30350 argc = 0;
30351 argv[argc++] = initial_argv[0];
30352
30353 if (! NILP (display_name))
30354 {
30355 argv[argc++] = display_opt;
30356 argv[argc++] = SSDATA (display_name);
30357 }
30358
30359 argv[argc++] = name_opt;
30360 argv[argc++] = resource_name;
30361
30362 XSetLocaleModifiers ("");
30363
30364
30365
30366 id = g_log_set_handler ("GLib", G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL
30367 | G_LOG_FLAG_RECURSION, my_log_handler, NULL);
30368
30369
30370
30371 gdk_window_add_filter (NULL, event_handler_gdk, NULL);
30372
30373
30374 fixup_locale ();
30375 unrequest_sigio ();
30376 gtk_init (&argc, &argv2);
30377 request_sigio ();
30378
30379 g_log_remove_handler ("GLib", id);
30380
30381 xg_initialize ();
30382
30383
30384
30385
30386 fixup_locale ();
30387
30388 dpy = DEFAULT_GDK_DISPLAY ();
30389
30390 #ifndef HAVE_GTK3
30391
30392 {
30393 const char *file = "~/.emacs.d/gtkrc";
30394 Lisp_Object s, abs_file;
30395
30396 s = build_string (file);
30397 abs_file = Fexpand_file_name (s, Qnil);
30398
30399 if (! NILP (abs_file) && !NILP (Ffile_readable_p (abs_file)))
30400 gtk_rc_parse (SSDATA (abs_file));
30401 }
30402 #endif
30403
30404 XSetErrorHandler (x_error_handler);
30405 XSetIOErrorHandler (x_io_error_quitter);
30406 }
30407 }
30408 #else
30409 #ifdef USE_X_TOOLKIT
30410
30411
30412
30413
30414
30415 #ifdef HAVE_X11XTR6
30416 XtSetLanguageProc (NULL, NULL, NULL);
30417 #endif
30418
30419 {
30420 int argc = 0;
30421 char *argv[3];
30422
30423 argv[0] = (char *) "";
30424 argc = 1;
30425 if (xrm_option)
30426 {
30427 argv[argc++] = (char *) "-xrm";
30428 argv[argc++] = xrm_option;
30429 }
30430 turn_on_atimers (false);
30431 unrequest_sigio ();
30432 dpy = XtOpenDisplay (Xt_app_con, SSDATA (display_name),
30433 resource_name, EMACS_CLASS,
30434 emacs_options, XtNumber (emacs_options),
30435 &argc, argv);
30436 request_sigio ();
30437 turn_on_atimers (true);
30438
30439 #ifdef HAVE_X11XTR6
30440
30441 fixup_locale ();
30442 #endif
30443 }
30444
30445 #else
30446 XSetLocaleModifiers ("");
30447 unrequest_sigio ();
30448 dpy = XOpenDisplay (SSDATA (display_name));
30449 request_sigio ();
30450 #endif
30451 #endif
30452
30453
30454 if (dpy == 0)
30455 {
30456 #if !defined USE_X_TOOLKIT && !defined USE_GTK
30457
30458
30459
30460
30461
30462 error ("Display %s can't be opened", SSDATA (display_name));
30463 #endif
30464
30465 unblock_input ();
30466
30467 #if defined HAVE_XFIXES && defined USE_XCB
30468 SAFE_FREE ();
30469 #endif
30470 return 0;
30471 }
30472
30473 #ifdef USE_XCB
30474 xcb_conn = XGetXCBConnection (dpy);
30475 if (!xcb_conn)
30476 {
30477 #ifdef USE_GTK
30478 xg_display_close (dpy);
30479 #else
30480 #ifdef USE_X_TOOLKIT
30481 XtCloseDisplay (dpy);
30482 #else
30483 XCloseDisplay (dpy);
30484 #endif
30485 #endif
30486
30487 unblock_input ();
30488
30489 #if defined HAVE_XFIXES && defined USE_XCB
30490 SAFE_FREE ();
30491 #endif
30492 return 0;
30493 }
30494 #endif
30495
30496
30497
30498
30499 XSelectInput (dpy, DefaultRootWindow (dpy), StructureNotifyMask);
30500
30501
30502
30503 dpyinfo = xzalloc (sizeof *dpyinfo);
30504 terminal = x_create_terminal (dpyinfo);
30505
30506 if (!NILP (Vx_detect_server_trust))
30507 {
30508
30509
30510
30511 XGrabServer (dpy);
30512 XGetKeyboardControl (dpy, &keyboard_state);
30513
30514 x_catch_errors (dpy);
30515
30516
30517
30518
30519
30520 if (keyboard_state.global_auto_repeat
30521 == AutoRepeatModeOn)
30522 XAutoRepeatOn (dpy);
30523 else
30524 XAutoRepeatOff (dpy);
30525
30526 if (x_had_errors_p (dpy))
30527 dpyinfo->untrusted = true;
30528 x_uncatch_errors_after_check ();
30529 XUngrabServer (dpy);
30530 }
30531
30532 dpyinfo->next_failable_request = dpyinfo->failable_requests;
30533
30534 {
30535 struct x_display_info *share;
30536
30537 for (share = x_display_list; share; share = share->next)
30538 if (same_x_server (SSDATA (XCAR (share->name_list_element)),
30539 SSDATA (display_name)))
30540 break;
30541 if (share)
30542 terminal->kboard = share->terminal->kboard;
30543 else
30544 {
30545 terminal->kboard = allocate_kboard (Qx);
30546
30547 if (!BASE_EQ (XSYMBOL (Qvendor_specific_keysyms)->u.s.function,
30548 Qunbound))
30549 {
30550 char *vendor = ServerVendor (dpy);
30551
30552
30553
30554
30555
30556 terminal_list = terminal->next_terminal;
30557 unblock_input ();
30558 kset_system_key_alist (terminal->kboard,
30559 safe_call1 (Qvendor_specific_keysyms,
30560 (vendor
30561 ? build_string (vendor)
30562 : empty_unibyte_string)));
30563 block_input ();
30564 terminal->next_terminal = terminal_list;
30565 terminal_list = terminal;
30566 }
30567
30568
30569
30570
30571 if (current_kboard == initial_kboard)
30572 current_kboard = terminal->kboard;
30573 }
30574 terminal->kboard->reference_count++;
30575 }
30576
30577
30578
30579 tem = Vx_quit_keysym;
30580 FOR_EACH_TAIL_SAFE (tem)
30581 {
30582 quit_keysym = XCAR (tem);
30583
30584
30585
30586
30587 if (!CONSP (quit_keysym) || !FIXNUMP (XCDR (quit_keysym))
30588 || !STRINGP (XCAR (quit_keysym)))
30589 continue;
30590
30591
30592
30593 if (strcmp (SSDATA (XCAR (quit_keysym)), ServerVendor (dpy)))
30594 continue;
30595
30596 dpyinfo->quit_keysym = XFIXNUM (XCDR (quit_keysym));
30597 }
30598
30599
30600 dpyinfo->next = x_display_list;
30601 x_display_list = dpyinfo;
30602
30603 dpyinfo->name_list_element = Fcons (display_name, Qnil);
30604 dpyinfo->display = dpy;
30605 dpyinfo->connection = ConnectionNumber (dpyinfo->display);
30606 #ifdef USE_XCB
30607 dpyinfo->xcb_connection = xcb_conn;
30608 #endif
30609
30610
30611 dpyinfo->smallest_font_height = 1;
30612 dpyinfo->smallest_char_width = 1;
30613
30614 dpyinfo->color_names_size = 256;
30615 dpyinfo->color_names = xzalloc (dpyinfo->color_names_size
30616 * sizeof *dpyinfo->color_names);
30617 dpyinfo->color_names_length = xzalloc (dpyinfo->color_names_size
30618 * sizeof *dpyinfo->color_names_length);
30619
30620
30621 terminal->name = xlispstrdup (display_name);
30622
30623 #if false
30624 XSetAfterFunction (dpyinfo->display, x_trace_wire);
30625 #endif
30626
30627 Lisp_Object system_name = Fsystem_name ();
30628 static char const title[] = "GNU Emacs";
30629 if (STRINGP (system_name))
30630 {
30631 static char const at[] = " at ";
30632 ptrdiff_t nbytes = sizeof (title) + sizeof (at);
30633 if (ckd_add (&nbytes, nbytes, SBYTES (system_name)))
30634 memory_full (SIZE_MAX);
30635 dpyinfo->x_id_name = xmalloc (nbytes);
30636 sprintf (dpyinfo->x_id_name, "%s%s%s", title, at, SDATA (system_name));
30637 }
30638 else
30639 {
30640 dpyinfo->x_id_name = xmalloc (sizeof (title));
30641 strcpy (dpyinfo->x_id_name, title);
30642 }
30643
30644 dpyinfo->x_id = ++x_display_id;
30645
30646 #ifndef HAVE_XKB
30647
30648 x_find_modifier_meanings (dpyinfo);
30649 #endif
30650
30651
30652 #ifdef USE_GTK
30653
30654 dpyinfo->xg_cursor = xg_create_default_cursor (dpyinfo->display);
30655 #endif
30656
30657 dpyinfo->vertical_scroll_bar_cursor
30658 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
30659
30660 dpyinfo->horizontal_scroll_bar_cursor
30661 = XCreateFontCursor (dpyinfo->display, XC_sb_h_double_arrow);
30662
30663 xrdb = x_load_resources (dpyinfo->display, xrm_option,
30664 resource_name, EMACS_CLASS);
30665 #ifdef HAVE_XRMSETDATABASE
30666 XrmSetDatabase (dpyinfo->display, xrdb);
30667 #else
30668 dpyinfo->display->db = xrdb;
30669 #endif
30670
30671 #ifdef HAVE_XRENDER
30672 int event_base, error_base;
30673 dpyinfo->xrender_supported_p
30674 = XRenderQueryExtension (dpyinfo->display, &event_base, &error_base);
30675
30676 if (dpyinfo->xrender_supported_p)
30677 dpyinfo->xrender_supported_p
30678 = XRenderQueryVersion (dpyinfo->display, &dpyinfo->xrender_major,
30679 &dpyinfo->xrender_minor);
30680 #endif
30681
30682
30683 #ifdef HAVE_XCOMPOSITE
30684 int composite_event_base, composite_error_base;
30685 dpyinfo->composite_supported_p = XCompositeQueryExtension (dpyinfo->display,
30686 &composite_event_base,
30687 &composite_error_base);
30688
30689 if (dpyinfo->composite_supported_p)
30690 dpyinfo->composite_supported_p
30691 = XCompositeQueryVersion (dpyinfo->display,
30692 &dpyinfo->composite_major,
30693 &dpyinfo->composite_minor);
30694 #endif
30695
30696 #ifdef HAVE_XSHAPE
30697 dpyinfo->xshape_supported_p
30698 = XShapeQueryExtension (dpyinfo->display,
30699 &dpyinfo->xshape_event_base,
30700 &dpyinfo->xshape_error_base);
30701
30702 if (dpyinfo->xshape_supported_p)
30703 dpyinfo->xshape_supported_p
30704 = XShapeQueryVersion (dpyinfo->display,
30705 &dpyinfo->xshape_major,
30706 &dpyinfo->xshape_minor);
30707 #endif
30708
30709
30710
30711 dpyinfo->rdb = xrdb;
30712
30713 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
30714 DefaultScreen (dpyinfo->display));
30715 select_visual (dpyinfo);
30716 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
30717 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
30718 dpyinfo->icon_bitmap_id = -1;
30719 dpyinfo->wm_type = X_WMTYPE_UNKNOWN;
30720
30721 reset_mouse_highlight (&dpyinfo->mouse_highlight);
30722
30723 #ifdef HAVE_XRENDER
30724 if (dpyinfo->xrender_supported_p
30725
30726
30727 && !dpyinfo->pict_format)
30728 dpyinfo->pict_format = XRenderFindVisualFormat (dpyinfo->display,
30729 dpyinfo->visual);
30730 #endif
30731
30732 #ifdef HAVE_XSYNC
30733 int xsync_event_base, xsync_error_base;
30734 dpyinfo->xsync_supported_p
30735 = XSyncQueryExtension (dpyinfo->display,
30736 &xsync_event_base,
30737 &xsync_error_base);
30738
30739 if (dpyinfo->xsync_supported_p)
30740 dpyinfo->xsync_supported_p = XSyncInitialize (dpyinfo->display,
30741 &dpyinfo->xsync_major,
30742 &dpyinfo->xsync_minor);
30743
30744 {
30745 AUTO_STRING (synchronizeResize, "synchronizeResize");
30746 AUTO_STRING (SynchronizeResize, "SynchronizeResize");
30747
30748 Lisp_Object value = gui_display_get_resource (dpyinfo,
30749 synchronizeResize,
30750 SynchronizeResize,
30751 Qnil, Qnil);
30752
30753 if (STRINGP (value)
30754 && (!strcmp (SSDATA (value), "false")
30755 || !strcmp (SSDATA (value), "off")))
30756 dpyinfo->xsync_supported_p = false;
30757 }
30758 #endif
30759
30760 #ifdef HAVE_XINERAMA
30761 int xin_event_base, xin_error_base;
30762 dpyinfo->xinerama_supported_p
30763 = XineramaQueryExtension (dpy, &xin_event_base, &xin_error_base);
30764 #endif
30765
30766
30767 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
30768 {
30769 if (dpyinfo->visual_info.class == PseudoColor)
30770 {
30771 AUTO_STRING (privateColormap, "privateColormap");
30772 AUTO_STRING (PrivateColormap, "PrivateColormap");
30773 Lisp_Object value
30774 = gui_display_get_resource (dpyinfo, privateColormap,
30775 PrivateColormap, Qnil, Qnil);
30776 if (STRINGP (value)
30777 && (!strcmp (SSDATA (value), "true")
30778 || !strcmp (SSDATA (value), "on")))
30779 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
30780 }
30781 }
30782 else
30783 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
30784 dpyinfo->visual, AllocNone);
30785
30786
30787 if (dpyinfo->visual_info.class == TrueColor)
30788 {
30789 get_bits_and_offset (dpyinfo->visual_info.red_mask,
30790 &dpyinfo->red_bits, &dpyinfo->red_offset);
30791 get_bits_and_offset (dpyinfo->visual_info.blue_mask,
30792 &dpyinfo->blue_bits, &dpyinfo->blue_offset);
30793 get_bits_and_offset (dpyinfo->visual_info.green_mask,
30794 &dpyinfo->green_bits, &dpyinfo->green_offset);
30795
30796 #ifdef HAVE_XRENDER
30797 if (dpyinfo->pict_format)
30798 {
30799 unsigned long channel_mask
30800 = ((unsigned long) dpyinfo->pict_format->direct.alphaMask
30801 << dpyinfo->pict_format->direct.alpha);
30802
30803 if (channel_mask)
30804 get_bits_and_offset (channel_mask, &dpyinfo->alpha_bits,
30805 &dpyinfo->alpha_offset);
30806 dpyinfo->alpha_mask = channel_mask;
30807 }
30808 else
30809 #endif
30810 {
30811 XColor xc;
30812 unsigned long alpha_mask;
30813 xc.red = 65535;
30814 xc.green = 65535;
30815 xc.blue = 65535;
30816
30817 if (XAllocColor (dpyinfo->display,
30818 dpyinfo->cmap, &xc) != 0)
30819 {
30820 alpha_mask = xc.pixel & ~(dpyinfo->visual_info.red_mask
30821 | dpyinfo->visual_info.blue_mask
30822 | dpyinfo->visual_info.green_mask);
30823
30824 if (alpha_mask)
30825 get_bits_and_offset (alpha_mask, &dpyinfo->alpha_bits,
30826 &dpyinfo->alpha_offset);
30827 dpyinfo->alpha_mask = alpha_mask;
30828 }
30829 }
30830 }
30831
30832 #ifdef HAVE_XDBE
30833 dpyinfo->supports_xdbe = false;
30834 int xdbe_major;
30835 int xdbe_minor;
30836 if (XdbeQueryExtension (dpyinfo->display, &xdbe_major, &xdbe_minor))
30837 dpyinfo->supports_xdbe = true;
30838 #endif
30839
30840 #ifdef USE_XCB
30841 xcb_screen_t *xcb_screen = NULL;
30842 xcb_screen_iterator_t iter;
30843 xcb_visualid_t wanted = { XVisualIDFromVisual (dpyinfo->visual) };
30844 xcb_depth_iterator_t depth_iter;
30845 xcb_visualtype_iterator_t visual_iter;
30846
30847 int screen = DefaultScreen (dpyinfo->display);
30848
30849 iter = xcb_setup_roots_iterator (xcb_get_setup (dpyinfo->xcb_connection));
30850 for (; iter.rem; --screen, xcb_screen_next (&iter))
30851 {
30852 if (!screen)
30853 xcb_screen = iter.data;
30854 }
30855
30856 if (xcb_screen)
30857 {
30858 depth_iter = xcb_screen_allowed_depths_iterator (xcb_screen);
30859 for (; depth_iter.rem; xcb_depth_next (&depth_iter))
30860 {
30861 visual_iter = xcb_depth_visuals_iterator (depth_iter.data);
30862 for (; visual_iter.rem; xcb_visualtype_next (&visual_iter))
30863 {
30864 if (wanted == visual_iter.data->visual_id)
30865 {
30866 dpyinfo->xcb_visual = visual_iter.data;
30867 break;
30868 }
30869 }
30870 }
30871 }
30872 #endif
30873
30874 #ifdef HAVE_XINPUT2
30875 dpyinfo->supports_xi2 = false;
30876 int rc;
30877 int major = 2;
30878 int xi_first_event, xi_first_error;
30879
30880 #ifndef HAVE_GTK3
30881 {
30882 AUTO_STRING (disableInputExtension, "disableInputExtension");
30883 AUTO_STRING (DisableInputExtension, "DisableInputExtension");
30884
30885 Lisp_Object value = gui_display_get_resource (dpyinfo,
30886 disableInputExtension,
30887 DisableInputExtension,
30888 Qnil, Qnil);
30889
30890 if (STRINGP (value)
30891 && (!strcmp (SSDATA (value), "on")
30892 || !strcmp (SSDATA (value), "true")))
30893 goto skip_xi_setup;
30894 }
30895 #endif
30896
30897 #ifdef HAVE_XINPUT2_4
30898 int minor = 4;
30899 #elif defined HAVE_XINPUT2_3
30900 int minor = 3;
30901 #elif defined HAVE_XINPUT2_2
30902 int minor = 2;
30903 #elif defined HAVE_XINPUT2_1
30904 int minor = 1;
30905 #else
30906 int minor = 0;
30907 #endif
30908
30909 dpyinfo->client_pointer_device = -1;
30910
30911 #ifdef HAVE_GTK3
30912
30913
30914
30915
30916 rc = xi_check_toolkit (dpyinfo->display);
30917
30918 if (!rc)
30919 goto skip_xi_setup;
30920 #endif
30921
30922 if (XQueryExtension (dpyinfo->display, "XInputExtension",
30923 &dpyinfo->xi2_opcode, &xi_first_event,
30924 &xi_first_error))
30925 {
30926 #ifdef HAVE_GTK3
30927 bool move_backwards = false;
30928 int original_minor = minor;
30929
30930 query:
30931
30932
30933
30934
30935
30936
30937
30938
30939
30940
30941
30942
30943 #endif
30944
30945 x_catch_errors (dpyinfo->display);
30946
30947 rc = XIQueryVersion (dpyinfo->display, &major, &minor);
30948
30949 #ifdef HAVE_GTK3
30950
30951
30952
30953
30954
30955 if (x_had_errors_p (dpyinfo->display))
30956 {
30957 x_uncatch_errors_after_check ();
30958
30959
30960
30961
30962
30963 if (minor >= 2)
30964 {
30965 move_backwards = true;
30966 minor = original_minor;
30967
30968 if (--minor < 0)
30969 rc = BadRequest;
30970 else
30971 goto query;
30972 }
30973 else
30974 {
30975 if (!move_backwards)
30976 {
30977 minor++;
30978 goto query;
30979 }
30980
30981 if (--minor < 0)
30982 rc = BadRequest;
30983 else
30984 goto query;
30985
30986 }
30987 }
30988 else
30989 x_uncatch_errors_after_check ();
30990
30991
30992
30993
30994
30995 if (minor > original_minor)
30996 minor = original_minor;
30997 #else
30998 if (x_had_errors_p (dpyinfo->display))
30999 rc = BadRequest;
31000
31001 x_uncatch_errors_after_check ();
31002 #endif
31003
31004 if (rc == Success)
31005 {
31006 dpyinfo->supports_xi2 = true;
31007 #ifndef HAVE_GTK3
31008
31009
31010 xi_select_hierarchy_events (dpyinfo);
31011 #endif
31012
31013 dpyinfo->xi2_version = minor;
31014 x_cache_xi_devices (dpyinfo);
31015 }
31016 }
31017 skip_xi_setup:
31018 ;
31019 #endif
31020
31021 #if defined HAVE_XRANDR || defined USE_GTK
31022 Lisp_Object term;
31023
31024 XSETTERMINAL (term, terminal);
31025 #endif
31026
31027 #ifdef HAVE_XRANDR
31028 dpyinfo->xrandr_supported_p
31029 = XRRQueryExtension (dpy, &dpyinfo->xrandr_event_base,
31030 &dpyinfo->xrandr_error_base);
31031
31032 #ifndef USE_GTK
31033 dpyinfo->last_monitor_attributes_list = Qnil;
31034 #endif
31035
31036 if (dpyinfo->xrandr_supported_p)
31037 {
31038 XRRQueryVersion (dpy, &dpyinfo->xrandr_major_version,
31039 &dpyinfo->xrandr_minor_version);
31040
31041 #ifndef USE_GTK
31042 if (dpyinfo->xrandr_major_version == 1
31043 && dpyinfo->xrandr_minor_version >= 2)
31044 {
31045 XRRSelectInput (dpyinfo->display,
31046 dpyinfo->root_window,
31047 (RRScreenChangeNotifyMask
31048 | RRCrtcChangeNotifyMask
31049 | RROutputChangeNotifyMask
31050 #ifdef USE_GTK
31051
31052
31053
31054 | RROutputPropertyNotifyMask
31055 #endif
31056 ));
31057
31058 dpyinfo->last_monitor_attributes_list
31059 = Fx_display_monitor_attributes_list (term);
31060 }
31061 #endif
31062 }
31063 #endif
31064
31065 #ifdef USE_GTK
31066 dpyinfo->last_monitor_attributes_list
31067 = Fx_display_monitor_attributes_list (term);
31068
31069 gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display);
31070 gscr = gdk_display_get_default_screen (gdpy);
31071
31072 g_signal_connect (G_OBJECT (gscr), "monitors-changed",
31073 G_CALLBACK (x_monitors_changed_cb),
31074 NULL);
31075 #endif
31076
31077 #ifdef HAVE_XKB
31078 int xkb_major, xkb_minor, xkb_op, xkb_error_code;
31079 xkb_major = XkbMajorVersion;
31080 xkb_minor = XkbMinorVersion;
31081
31082 if (XkbLibraryVersion (&xkb_major, &xkb_minor)
31083 && XkbQueryExtension (dpyinfo->display, &xkb_op, &dpyinfo->xkb_event_type,
31084 &xkb_error_code, &xkb_major, &xkb_minor))
31085 {
31086 dpyinfo->supports_xkb = true;
31087 dpyinfo->xkb_desc = XkbGetMap (dpyinfo->display,
31088 (XkbKeySymsMask
31089 | XkbKeyTypesMask
31090 | XkbModifierMapMask
31091 | XkbVirtualModsMask),
31092 XkbUseCoreKbd);
31093
31094 if (dpyinfo->xkb_desc)
31095 XkbGetNames (dpyinfo->display, XkbAllNamesMask,
31096 dpyinfo->xkb_desc);
31097
31098 XkbSelectEvents (dpyinfo->display, XkbUseCoreKbd,
31099 XkbNewKeyboardNotifyMask | XkbMapNotifyMask,
31100 XkbNewKeyboardNotifyMask | XkbMapNotifyMask);
31101 }
31102
31103
31104
31105
31106
31107
31108
31109 #ifdef XkbLC_ControlFallback
31110 XkbSetXlibControls (dpyinfo->display, XkbLC_ControlFallback, 0);
31111 #endif
31112 #endif
31113
31114 #ifdef HAVE_XFIXES
31115 int xfixes_error_base;
31116 dpyinfo->xfixes_supported_p
31117 = XFixesQueryExtension (dpyinfo->display,
31118 &dpyinfo->xfixes_event_base,
31119 &xfixes_error_base);
31120
31121 if (dpyinfo->xfixes_supported_p)
31122 {
31123 if (!XFixesQueryVersion (dpyinfo->display, &dpyinfo->xfixes_major,
31124 &dpyinfo->xfixes_minor))
31125 dpyinfo->xfixes_supported_p = false;
31126 }
31127 #endif
31128
31129 #if defined USE_CAIRO || defined HAVE_XFT
31130 {
31131
31132
31133
31134
31135
31136
31137
31138
31139
31140
31141
31142
31143
31144
31145 char *v = XGetDefault (dpyinfo->display, "Xft", "dpi");
31146 double d;
31147 if (v != NULL && sscanf (v, "%lf", &d) == 1)
31148 dpyinfo->resy = dpyinfo->resx = d;
31149 }
31150 #endif
31151
31152 if (dpyinfo->resy < 1)
31153 {
31154 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
31155 double pixels = DisplayHeight (dpyinfo->display, screen_number);
31156 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
31157
31158 dpyinfo->resy = (mm < 1) ? 100 : pixels * 25.4 / mm;
31159 pixels = DisplayWidth (dpyinfo->display, screen_number);
31160 mm = DisplayWidthMM (dpyinfo->display, screen_number);
31161
31162 dpyinfo->resx = (mm < 1) ? 100 : pixels * 25.4 / mm;
31163 }
31164
31165 sprintf (cm_atom_sprintf, cm_atom_fmt,
31166 XScreenNumberOfScreen (dpyinfo->screen));
31167
31168 {
31169 enum { atom_count = ARRAYELTS (x_atom_refs) };
31170
31171 enum { total_atom_count = 2 + atom_count };
31172 Atom atoms_return[total_atom_count];
31173 char *atom_names[total_atom_count];
31174 static char const xsettings_fmt[] = "_XSETTINGS_S%d";
31175 char xsettings_atom_name[sizeof xsettings_fmt - 2
31176 + INT_STRLEN_BOUND (int)];
31177
31178 for (i = 0; i < atom_count; i++)
31179 atom_names[i] = (char *) x_atom_refs[i].name;
31180
31181
31182 sprintf (xsettings_atom_name, xsettings_fmt,
31183 XScreenNumberOfScreen (dpyinfo->screen));
31184 atom_names[i] = xsettings_atom_name;
31185 atom_names[i + 1] = cm_atom_sprintf;
31186
31187 XInternAtoms (dpyinfo->display, atom_names, total_atom_count,
31188 False, atoms_return);
31189
31190 for (i = 0; i < atom_count; i++)
31191 *(Atom *) ((char *) dpyinfo + x_atom_refs[i].offset) = atoms_return[i];
31192
31193
31194 dpyinfo->Xatom_xsettings_sel = atoms_return[i];
31195 dpyinfo->Xatom_NET_WM_CM_Sn = atoms_return[i + 1];
31196 }
31197
31198 #ifdef HAVE_XKB
31199
31200 x_find_modifier_meanings (dpyinfo);
31201 #endif
31202
31203 dpyinfo->x_dnd_atoms_size = 16;
31204 dpyinfo->x_dnd_atoms = xmalloc (sizeof *dpyinfo->x_dnd_atoms
31205 * dpyinfo->x_dnd_atoms_size);
31206 dpyinfo->gray
31207 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
31208 gray_bits, gray_width, gray_height,
31209 1, 0, 1);
31210
31211 dpyinfo->invisible_cursor = make_invisible_cursor (dpyinfo);
31212 #if defined HAVE_XFIXES && XFIXES_VERSION >= 40000
31213 dpyinfo->fixes_pointer_blanking = (egetenv ("EMACS_XFIXES") != NULL);
31214 #endif
31215
31216 xsettings_initialize (dpyinfo);
31217
31218
31219 if (dpyinfo->connection != 0)
31220 add_keyboard_wait_descriptor (dpyinfo->connection);
31221
31222 #ifdef F_SETOWN
31223 fcntl (dpyinfo->connection, F_SETOWN, getpid ());
31224 #endif
31225
31226 if (interrupt_input)
31227 init_sigio (dpyinfo->connection);
31228
31229 #ifdef USE_LUCID
31230 {
31231 XrmValue d, fr, to;
31232 Font font;
31233 XFontStruct *query_result;
31234
31235 dpy = dpyinfo->display;
31236 d.addr = (XPointer) &dpy;
31237 d.size = sizeof (Display *);
31238 fr.addr = (char *) XtDefaultFont;
31239 fr.size = sizeof (XtDefaultFont);
31240 to.size = sizeof (Font *);
31241 to.addr = (XPointer) &font;
31242 x_catch_errors (dpy);
31243 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
31244 emacs_abort ();
31245 query_result = XQueryFont (dpy, font);
31246
31247
31248
31249 if (x_had_errors_p (dpy) || !font)
31250 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
31251
31252
31253
31254
31255
31256 XFreeFontInfo (NULL, query_result, 1);
31257 x_uncatch_errors ();
31258 }
31259 #endif
31260
31261
31262
31263 {
31264 AUTO_STRING (synchronous, "synchronous");
31265 AUTO_STRING (Synchronous, "Synchronous");
31266 Lisp_Object value = gui_display_get_resource (dpyinfo, synchronous,
31267 Synchronous, Qnil, Qnil);
31268 if (STRINGP (value)
31269 && (!strcmp (SSDATA (value), "true")
31270 || !strcmp (SSDATA (value), "on")))
31271 XSynchronize (dpyinfo->display, True);
31272 }
31273
31274 #ifdef HAVE_X_I18N
31275 {
31276 AUTO_STRING (useXIM, "useXIM");
31277 AUTO_STRING (UseXIM, "UseXIM");
31278 Lisp_Object value = gui_display_get_resource (dpyinfo, useXIM, UseXIM,
31279 Qnil, Qnil);
31280
31281
31282
31283
31284 #ifdef USE_XIM
31285 dpyinfo->use_xim = true;
31286
31287 if (STRINGP (value)
31288 && (!strcmp (SSDATA (value), "false")
31289 || !strcmp (SSDATA (value), "off")))
31290 dpyinfo->use_xim = false;
31291 #else
31292 dpyinfo->use_xim = false;
31293
31294 if (STRINGP (value)
31295 && (!strcmp (SSDATA (value), "true")
31296 || !strcmp (SSDATA (value), "on")))
31297 dpyinfo->use_xim = true;
31298 #endif
31299 }
31300
31301 {
31302 AUTO_STRING (inputStyle, "inputStyle");
31303 AUTO_STRING (InputStyle, "InputStyle");
31304 Lisp_Object value = gui_display_get_resource (dpyinfo, inputStyle, InputStyle,
31305 Qnil, Qnil);
31306
31307 if (STRINGP (value))
31308 {
31309 if (!strcmp (SSDATA (value), "callback"))
31310 dpyinfo->preferred_xim_style = STYLE_CALLBACK;
31311 else if (!strcmp (SSDATA (value), "none"))
31312 dpyinfo->preferred_xim_style = STYLE_NONE;
31313 else if (!strcmp (SSDATA (value), "overthespot"))
31314 dpyinfo->preferred_xim_style = STYLE_OVERTHESPOT;
31315 else if (!strcmp (SSDATA (value), "offthespot"))
31316 dpyinfo->preferred_xim_style = STYLE_OFFTHESPOT;
31317 else if (!strcmp (SSDATA (value), "root"))
31318 dpyinfo->preferred_xim_style = STYLE_ROOT;
31319 #ifdef USE_GTK
31320 else if (!strcmp (SSDATA (value), "native"))
31321 dpyinfo->prefer_native_input = true;
31322 #endif
31323 }
31324 }
31325
31326
31327
31328
31329
31330
31331
31332 if (XSupportsLocale ())
31333 xim_initialize (dpyinfo, resource_name);
31334 #endif
31335
31336 #ifdef HAVE_X_SM
31337
31338
31339
31340 if (!dpyinfo->next && ! IS_DAEMON)
31341 x_session_initialize (dpyinfo);
31342 #endif
31343
31344 #if defined USE_CAIRO || defined HAVE_XRENDER
31345 x_extension_initialize (dpyinfo);
31346 #endif
31347
31348 #ifdef USE_TOOLKIT_SCROLL_BARS
31349 dpyinfo->protected_windows = xmalloc (sizeof (Lisp_Object) * 256);
31350 dpyinfo->n_protected_windows = 0;
31351 dpyinfo->protected_windows_max = 256;
31352 #endif
31353
31354 #ifdef HAVE_XFIXES
31355
31356
31357
31358 if (CONSP (Vx_fast_selection_list)
31359 && dpyinfo->xfixes_supported_p
31360 && dpyinfo->xfixes_major >= 1)
31361 {
31362 num_fast_selections = 0;
31363 tem = Vx_fast_selection_list;
31364
31365 FOR_EACH_TAIL_SAFE (tem)
31366 {
31367 if (!SYMBOLP (XCAR (tem)))
31368 continue;
31369
31370 num_fast_selections++;
31371 }
31372
31373 dpyinfo->n_monitored_selections = num_fast_selections;
31374 dpyinfo->selection_tracking_window
31375 = x_create_special_window (dpyinfo, dpyinfo->root_window);
31376 dpyinfo->monitored_selections
31377 = xmalloc (num_fast_selections
31378 * sizeof *dpyinfo->monitored_selections);
31379
31380 num_fast_selections = 0;
31381 tem = Vx_fast_selection_list;
31382
31383 FOR_EACH_TAIL_SAFE (tem)
31384 {
31385 lisp_name = XCAR (tem);
31386
31387 if (!SYMBOLP (lisp_name))
31388 continue;
31389
31390 selection_name = symbol_to_x_atom (dpyinfo, lisp_name);
31391 dpyinfo->monitored_selections[num_fast_selections++].name
31392 = selection_name;
31393 dpyinfo->monitored_selections[num_fast_selections - 1].owner
31394 = X_INVALID_WINDOW;
31395
31396
31397 XFixesSelectSelectionInput (dpyinfo->display,
31398 dpyinfo->selection_tracking_window,
31399 selection_name,
31400 (XFixesSetSelectionOwnerNotifyMask
31401 | XFixesSetSelectionOwnerNotifyMask
31402 | XFixesSelectionClientCloseNotifyMask));
31403 }
31404
31405 #ifdef USE_XCB
31406 selection_cookies = SAFE_ALLOCA (sizeof *selection_cookies
31407 * num_fast_selections);
31408 #endif
31409
31410
31411 for (i = 0; i < num_fast_selections; ++i)
31412 {
31413 #ifdef USE_XCB
31414 selection_cookies[i]
31415 = xcb_get_selection_owner (dpyinfo->xcb_connection,
31416 dpyinfo->monitored_selections[i].name);
31417 #else
31418 dpyinfo->monitored_selections[i].owner
31419 = XGetSelectionOwner (dpyinfo->display,
31420 dpyinfo->monitored_selections[i].name);
31421 #endif
31422 }
31423
31424 #ifdef USE_XCB
31425 for (i = 0; i < num_fast_selections; ++i)
31426 {
31427 selection_reply
31428 = xcb_get_selection_owner_reply (dpyinfo->xcb_connection,
31429 selection_cookies[i],
31430 &selection_error);
31431
31432 if (selection_reply)
31433 {
31434 dpyinfo->monitored_selections[i].owner
31435 = selection_reply->owner;
31436 free (selection_reply);
31437 }
31438 else if (selection_error)
31439 free (selection_error);
31440 }
31441 #endif
31442 }
31443 #endif
31444
31445 unblock_input ();
31446
31447 #if defined HAVE_XFIXES && defined USE_XCB
31448 SAFE_FREE ();
31449 #endif
31450 return dpyinfo;
31451 }
31452
31453
31454
31455
31456
31457
31458 static void
31459 x_delete_selection_requests (struct x_display_info *dpyinfo)
31460 {
31461 union buffered_input_event *event;
31462 int moved_events;
31463
31464 for (event = kbd_fetch_ptr; event != kbd_store_ptr;
31465 event = X_NEXT_KBD_EVENT (event))
31466 {
31467 if (event->kind == SELECTION_REQUEST_EVENT
31468 || event->kind == SELECTION_CLEAR_EVENT)
31469 {
31470 if (SELECTION_EVENT_DPYINFO (&event->sie) != dpyinfo)
31471 continue;
31472
31473
31474
31475
31476
31477
31478
31479 if (event < kbd_fetch_ptr)
31480 {
31481 memmove (kbd_buffer + 1, kbd_buffer,
31482 (event - kbd_buffer) * sizeof *kbd_buffer);
31483 kbd_buffer[0] = kbd_buffer[KBD_BUFFER_SIZE - 1];
31484 moved_events = kbd_buffer + KBD_BUFFER_SIZE - 1 - kbd_fetch_ptr;
31485 }
31486 else
31487 moved_events = event - kbd_fetch_ptr;
31488
31489 memmove (kbd_fetch_ptr + 1, kbd_fetch_ptr,
31490 moved_events * sizeof *kbd_fetch_ptr);
31491 kbd_fetch_ptr = X_NEXT_KBD_EVENT (kbd_fetch_ptr);
31492
31493
31494
31495 input_pending = false;
31496 }
31497 }
31498 }
31499
31500
31501
31502
31503 static void
31504 x_delete_display (struct x_display_info *dpyinfo)
31505 {
31506 struct terminal *t;
31507 struct color_name_cache_entry *color_entry, *next_color_entry;
31508 int i;
31509 struct x_selection_request_event *ie, *last, *temp;
31510
31511
31512
31513 for (t = terminal_list; t; t = t->next_terminal)
31514 if (t->type == output_x_window && t->display_info.x == dpyinfo)
31515 {
31516 #ifdef HAVE_X_SM
31517
31518 if (t->id == 1 && x_session_have_connection ())
31519 x_session_close ();
31520 #endif
31521 delete_terminal (t);
31522 break;
31523 }
31524
31525
31526
31527
31528 last = NULL;
31529
31530 for (ie = pending_selection_requests; ie; ie = ie->next)
31531 {
31532 again:
31533
31534 if (SELECTION_EVENT_DPYINFO (&ie->se) == dpyinfo)
31535 {
31536 if (last)
31537 last->next = ie->next;
31538
31539 temp = ie;
31540 ie = ie->next;
31541 xfree (temp);
31542
31543 goto again;
31544 }
31545
31546 last = ie;
31547 }
31548
31549
31550
31551 x_delete_selection_requests (dpyinfo);
31552
31553
31554 x_remove_selection_transfers (dpyinfo);
31555
31556 if (next_noop_dpyinfo == dpyinfo)
31557 next_noop_dpyinfo = dpyinfo->next;
31558
31559 if (mouse_click_timeout_display == dpyinfo)
31560 mouse_click_timeout_display = NULL;
31561
31562 if (x_display_list == dpyinfo)
31563 x_display_list = dpyinfo->next;
31564 else
31565 {
31566 struct x_display_info *tail;
31567
31568 for (tail = x_display_list; tail; tail = tail->next)
31569 if (tail->next == dpyinfo)
31570 tail->next = tail->next->next;
31571 }
31572
31573 for (i = 0; i < dpyinfo->color_names_size; ++i)
31574 {
31575 for (color_entry = dpyinfo->color_names[i];
31576 color_entry; color_entry = next_color_entry)
31577 {
31578 next_color_entry = color_entry->next;
31579
31580 xfree (color_entry->name);
31581 xfree (color_entry);
31582 }
31583 }
31584
31585 if (dpyinfo->net_supported_atoms)
31586 XFree (dpyinfo->net_supported_atoms);
31587
31588 xfree (dpyinfo->color_names);
31589 xfree (dpyinfo->color_names_length);
31590 xfree (dpyinfo->x_id_name);
31591 xfree (dpyinfo->x_dnd_atoms);
31592 xfree (dpyinfo->color_cells);
31593 #ifdef HAVE_XFIXES
31594 if (dpyinfo->monitored_selections)
31595 xfree (dpyinfo->monitored_selections);
31596 #endif
31597 #ifdef USE_TOOLKIT_SCROLL_BARS
31598 xfree (dpyinfo->protected_windows);
31599 #endif
31600 #ifdef HAVE_XINPUT2
31601 if (dpyinfo->supports_xi2)
31602 x_free_xi_devices (dpyinfo);
31603 #endif
31604 xfree (dpyinfo);
31605 }
31606
31607 #ifdef USE_X_TOOLKIT
31608
31609
31610
31611
31612
31613
31614 static void
31615 x_process_timeouts (struct atimer *timer)
31616 {
31617 block_input ();
31618 x_timeout_atimer_activated_flag = false;
31619 if (toolkit_scroll_bar_interaction || popup_activated ())
31620 {
31621 while (XtAppPending (Xt_app_con) & XtIMTimer)
31622 XtAppProcessEvent (Xt_app_con, XtIMTimer);
31623
31624 x_activate_timeout_atimer ();
31625 }
31626 unblock_input ();
31627 }
31628
31629
31630
31631
31632
31633
31634
31635
31636
31637 void
31638 x_activate_timeout_atimer (void)
31639 {
31640 block_input ();
31641 if (!x_timeout_atimer_activated_flag)
31642 {
31643 struct timespec interval = make_timespec (0, 100 * 1000 * 1000);
31644 start_atimer (ATIMER_RELATIVE, interval, x_process_timeouts, 0);
31645 x_timeout_atimer_activated_flag = true;
31646 }
31647 unblock_input ();
31648 }
31649
31650 #endif
31651
31652
31653
31654
31655 extern frame_parm_handler x_frame_parm_handlers[];
31656
31657 static struct redisplay_interface x_redisplay_interface =
31658 {
31659 x_frame_parm_handlers,
31660 gui_produce_glyphs,
31661 gui_write_glyphs,
31662 gui_insert_glyphs,
31663 gui_clear_end_of_line,
31664 x_scroll_run,
31665 x_after_update_window_line,
31666 NULL,
31667 NULL,
31668 x_flip_and_flush,
31669 gui_clear_window_mouse_face,
31670 gui_get_glyph_overhangs,
31671 gui_fix_overlapping_area,
31672 x_draw_fringe_bitmap,
31673 #ifdef USE_CAIRO
31674 x_cr_define_fringe_bitmap,
31675 x_cr_destroy_fringe_bitmap,
31676 #else
31677 0,
31678 0,
31679 #endif
31680 x_compute_glyph_string_overhangs,
31681 x_draw_glyph_string,
31682 x_define_frame_cursor,
31683 x_clear_frame_area,
31684 x_clear_under_internal_border,
31685 x_draw_window_cursor,
31686 x_draw_vertical_window_border,
31687 x_draw_window_divider,
31688 x_shift_glyphs_for_insert,
31689 x_show_hourglass,
31690 x_hide_hourglass,
31691 x_default_font_parameter
31692 };
31693
31694
31695
31696 void
31697 x_delete_terminal (struct terminal *terminal)
31698 {
31699 struct x_display_info *dpyinfo;
31700 struct frame *f;
31701 Lisp_Object tail, frame;
31702
31703 dpyinfo = terminal->display_info.x;
31704
31705
31706
31707 if (!terminal->name)
31708 return;
31709
31710 block_input ();
31711
31712
31713
31714
31715 FOR_EACH_FRAME (tail, frame)
31716 {
31717 f = XFRAME (frame);
31718
31719 if (FRAME_LIVE_P (f) && f->terminal == terminal)
31720
31721 delete_frame (frame, Qnoelisp);
31722 }
31723
31724 #ifdef HAVE_X_I18N
31725
31726
31727 xim_close_dpy (dpyinfo);
31728 #endif
31729
31730
31731 image_destroy_all_bitmaps (dpyinfo);
31732
31733
31734 xfree (dpyinfo->bitmaps);
31735
31736
31737 dpyinfo->bitmaps = NULL;
31738 dpyinfo->bitmaps_last = 0;
31739
31740
31741 if (dpyinfo->display)
31742 {
31743 XSetCloseDownMode (dpyinfo->display, DestroyAll);
31744
31745
31746 if (dpyinfo->scratch_cursor_gc)
31747 XFreeGC (dpyinfo->display, dpyinfo->scratch_cursor_gc);
31748
31749
31750
31751 if ((x_dnd_in_progress || x_dnd_waiting_for_finish)
31752 && dpyinfo->display == (x_dnd_waiting_for_finish
31753 ? x_dnd_finish_display
31754 : FRAME_X_DISPLAY (x_dnd_frame)))
31755 {
31756 x_dnd_last_seen_window = None;
31757 x_dnd_last_seen_toplevel = None;
31758 x_dnd_in_progress = false;
31759 x_dnd_waiting_for_finish = false;
31760
31761
31762
31763 if (x_dnd_use_toplevels)
31764 x_dnd_free_toplevels (false);
31765
31766 x_dnd_return_frame_object = NULL;
31767 x_dnd_movement_frame = NULL;
31768 x_dnd_wheel_frame = NULL;
31769 x_dnd_frame = NULL;
31770 }
31771
31772
31773
31774
31775
31776
31777
31778
31779
31780
31781
31782
31783
31784
31785
31786 #if false
31787 #ifdef HAVE_XRMSETDATABASE
31788 XrmSetDatabase (dpyinfo->display, NULL);
31789 #else
31790 dpyinfo->display->db = NULL;
31791 #endif
31792
31793
31794
31795 XrmDestroyDatabase (dpyinfo->rdb);
31796 #endif
31797 #ifdef USE_GTK
31798 xg_display_close (dpyinfo->display);
31799 #else
31800 #ifdef USE_X_TOOLKIT
31801 XtCloseDisplay (dpyinfo->display);
31802 #else
31803 XCloseDisplay (dpyinfo->display);
31804 #endif
31805 #endif
31806
31807
31808 dpyinfo->display = NULL;
31809 }
31810
31811
31812
31813
31814
31815 else if (dpyinfo->connection >= 0)
31816 emacs_close (dpyinfo->connection);
31817
31818
31819
31820
31821
31822 #ifdef HAVE_XKB
31823 if (dpyinfo->xkb_desc)
31824 XkbFreeKeyboard (dpyinfo->xkb_desc, XkbAllComponentsMask, True);
31825 #endif
31826
31827 if (dpyinfo->modmap)
31828 XFreeModifiermap (dpyinfo->modmap);
31829
31830
31831 delete_keyboard_wait_descriptor (dpyinfo->connection);
31832
31833 dpyinfo->connection = -1;
31834
31835 x_delete_display (dpyinfo);
31836 unblock_input ();
31837 }
31838
31839 #ifdef HAVE_XINPUT2
31840 static bool
31841 x_have_any_grab (struct x_display_info *dpyinfo)
31842 {
31843 int i;
31844
31845 if (!dpyinfo->supports_xi2)
31846 return false;
31847
31848 for (i = 0; i < dpyinfo->num_devices; ++i)
31849 {
31850 if (dpyinfo->devices[i].grab)
31851 return true;
31852 }
31853
31854 return false;
31855 }
31856 #endif
31857
31858
31859
31860
31861 static struct terminal *
31862 x_create_terminal (struct x_display_info *dpyinfo)
31863 {
31864 struct terminal *terminal;
31865
31866 terminal = create_terminal (output_x_window, &x_redisplay_interface);
31867
31868 terminal->display_info.x = dpyinfo;
31869 dpyinfo->terminal = terminal;
31870
31871
31872
31873 terminal->clear_frame_hook = x_clear_frame;
31874 terminal->ins_del_lines_hook = x_ins_del_lines;
31875 terminal->delete_glyphs_hook = x_delete_glyphs;
31876 terminal->ring_bell_hook = XTring_bell;
31877 terminal->toggle_invisible_pointer_hook = XTtoggle_invisible_pointer;
31878 terminal->update_begin_hook = x_update_begin;
31879 terminal->update_end_hook = x_update_end;
31880 terminal->read_socket_hook = XTread_socket;
31881 terminal->frame_up_to_date_hook = XTframe_up_to_date;
31882 #ifdef HAVE_XDBE
31883 terminal->buffer_flipping_unblocked_hook = XTbuffer_flipping_unblocked_hook;
31884 #endif
31885 terminal->defined_color_hook = x_defined_color;
31886 terminal->query_frame_background_color = x_query_frame_background_color;
31887 terminal->query_colors = x_query_colors;
31888 terminal->mouse_position_hook = XTmouse_position;
31889 terminal->get_focus_frame = x_get_focus_frame;
31890 terminal->focus_frame_hook = x_focus_frame;
31891 terminal->frame_rehighlight_hook = XTframe_rehighlight;
31892 terminal->frame_raise_lower_hook = XTframe_raise_lower;
31893 terminal->frame_visible_invisible_hook = x_make_frame_visible_invisible;
31894 terminal->fullscreen_hook = XTfullscreen_hook;
31895 terminal->iconify_frame_hook = x_iconify_frame;
31896 terminal->set_window_size_hook = x_set_window_size;
31897 terminal->set_frame_offset_hook = x_set_offset;
31898 terminal->set_frame_alpha_hook = x_set_frame_alpha;
31899 terminal->set_new_font_hook = x_new_font;
31900 terminal->set_bitmap_icon_hook = x_bitmap_icon;
31901 terminal->implicit_set_name_hook = x_implicitly_set_name;
31902 terminal->menu_show_hook = x_menu_show;
31903 #ifdef HAVE_EXT_MENU_BAR
31904 terminal->activate_menubar_hook = x_activate_menubar;
31905 #endif
31906 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
31907 terminal->popup_dialog_hook = xw_popup_dialog;
31908 #endif
31909 terminal->change_tab_bar_height_hook = x_change_tab_bar_height;
31910 #ifndef HAVE_EXT_TOOL_BAR
31911 terminal->change_tool_bar_height_hook = x_change_tool_bar_height;
31912 #endif
31913 terminal->set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
31914 terminal->set_horizontal_scroll_bar_hook = XTset_horizontal_scroll_bar;
31915 terminal->set_scroll_bar_default_width_hook = x_set_scroll_bar_default_width;
31916 terminal->set_scroll_bar_default_height_hook = x_set_scroll_bar_default_height;
31917 terminal->condemn_scroll_bars_hook = XTcondemn_scroll_bars;
31918 terminal->redeem_scroll_bar_hook = XTredeem_scroll_bar;
31919 terminal->judge_scroll_bars_hook = XTjudge_scroll_bars;
31920 terminal->get_string_resource_hook = x_get_string_resource;
31921 terminal->free_pixmap = x_free_pixmap;
31922 terminal->delete_frame_hook = x_destroy_window;
31923 terminal->delete_terminal_hook = x_delete_terminal;
31924 terminal->toolkit_position_hook = x_toolkit_position;
31925 #ifdef HAVE_XINPUT2
31926 terminal->any_grab_hook = x_have_any_grab;
31927 #endif
31928
31929
31930 return terminal;
31931 }
31932
31933 static void
31934 x_initialize (void)
31935 {
31936 baud_rate = 19200;
31937
31938 x_noop_count = 0;
31939 any_help_event_p = false;
31940 ignore_next_mouse_click_timeout = 0;
31941 mouse_click_timeout_display = NULL;
31942
31943 #ifdef USE_GTK
31944 current_count = -1;
31945 #endif
31946
31947
31948 Fset_input_interrupt_mode (Qt);
31949
31950 #if THREADS_ENABLED
31951
31952 if (XInitThreads () == 0)
31953 fputs ("Warning: An error occurred initializing X11 thread support!\n",
31954 stderr);
31955 #endif
31956
31957 #ifdef USE_X_TOOLKIT
31958 XtToolkitInitialize ();
31959
31960 Xt_app_con = XtCreateApplicationContext ();
31961
31962
31963
31964 XtAppSetTypeConverter (Xt_app_con,
31965 XtRString, XtRPixel, cvt_string_to_pixel,
31966 cvt_string_to_pixel_args,
31967 XtNumber (cvt_string_to_pixel_args),
31968 XtCacheByDisplay, cvt_pixel_dtor);
31969
31970 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
31971 #endif
31972
31973 #ifdef USE_TOOLKIT_SCROLL_BARS
31974 #ifndef USE_GTK
31975 xaw3d_arrow_scroll = False;
31976 xaw3d_pick_top = True;
31977 #endif
31978 #endif
31979
31980 #ifdef USE_CAIRO
31981 gui_init_fringe (&x_redisplay_interface);
31982 #endif
31983
31984
31985
31986 XSetErrorHandler (x_error_handler);
31987 XSetIOErrorHandler (x_io_error_quitter);
31988 }
31989
31990 #ifdef HAVE_X_I18N
31991
31992
31993
31994
31995 static void
31996 x_reset_conversion (struct frame *f)
31997 {
31998 char *string;
31999
32000 if (FRAME_XIC (f))
32001 {
32002 string = XmbResetIC (FRAME_XIC (f));
32003
32004
32005
32006
32007 if (string)
32008 XFree (string);
32009 }
32010 }
32011
32012
32013
32014 static struct textconv_interface text_conversion_interface =
32015 {
32016 x_reset_conversion,
32017 };
32018
32019 #endif
32020
32021 void
32022 init_xterm (void)
32023 {
32024 #ifndef HAVE_XINPUT2
32025
32026
32027
32028 #ifndef HAVE_GTK3
32029 xputenv ("GDK_CORE_DEVICE_EVENTS=1");
32030 #else
32031 gdk_disable_multidevice ();
32032 #endif
32033 #endif
32034
32035 #ifdef HAVE_X_I18N
32036 register_textconv_interface (&text_conversion_interface);
32037 #endif
32038 }
32039
32040 void
32041 mark_xterm (void)
32042 {
32043 Lisp_Object val;
32044 #if defined HAVE_XINPUT2 || defined USE_TOOLKIT_SCROLL_BARS \
32045 || defined HAVE_XRANDR || defined USE_GTK || defined HAVE_X_I18N
32046 struct x_display_info *dpyinfo;
32047 #if defined HAVE_XINPUT2 || defined USE_TOOLKIT_SCROLL_BARS
32048 int i;
32049 #endif
32050 #endif
32051
32052 if (x_dnd_return_frame_object)
32053 {
32054 XSETFRAME (val, x_dnd_return_frame_object);
32055 mark_object (val);
32056 }
32057
32058 if (x_dnd_movement_frame)
32059 {
32060 XSETFRAME (val, x_dnd_movement_frame);
32061 mark_object (val);
32062 }
32063
32064 if (x_dnd_wheel_frame)
32065 {
32066 XSETFRAME (val, x_dnd_wheel_frame);
32067 mark_object (val);
32068 }
32069
32070 #if defined HAVE_XINPUT2 || defined USE_TOOLKIT_SCROLL_BARS \
32071 || defined HAVE_XRANDR || defined USE_GTK || defined HAVE_X_I18N
32072 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
32073 {
32074 #ifdef HAVE_XINPUT2
32075 for (i = 0; i < dpyinfo->num_devices; ++i)
32076 mark_object (dpyinfo->devices[i].name);
32077 #endif
32078 #ifdef USE_TOOLKIT_SCROLL_BARS
32079 for (i = 0; i < dpyinfo->n_protected_windows; ++i)
32080 mark_object (dpyinfo->protected_windows[i]);
32081 #endif
32082 #if defined HAVE_XRANDR || defined USE_GTK
32083 mark_object (dpyinfo->last_monitor_attributes_list);
32084 #endif
32085 #if defined HAVE_X_I18N
32086 mark_object (dpyinfo->xim_coding);
32087 #endif
32088 }
32089 #endif
32090 }
32091
32092
32093
32094
32095
32096 void
32097 x_catch_errors_for_lisp (struct x_display_info *dpyinfo)
32098 {
32099 if (!x_fast_protocol_requests)
32100 x_catch_errors (dpyinfo->display);
32101 else
32102 x_ignore_errors_for_next_request (dpyinfo, 0);
32103 }
32104
32105 void
32106 x_check_errors_for_lisp (struct x_display_info *dpyinfo,
32107 const char *format)
32108 {
32109 if (!x_fast_protocol_requests)
32110 x_check_errors (dpyinfo->display, format);
32111 }
32112
32113 void
32114 x_uncatch_errors_for_lisp (struct x_display_info *dpyinfo)
32115 {
32116 if (!x_fast_protocol_requests)
32117 x_uncatch_errors ();
32118 else
32119 x_stop_ignoring_errors (dpyinfo);
32120 }
32121
32122
32123
32124
32125
32126 void
32127 x_preserve_selections (struct x_display_info *dpyinfo, Lisp_Object lost,
32128 Lisp_Object current_owner)
32129 {
32130 Lisp_Object tail, frame, new_owner;
32131 Time timestamp;
32132 Window *owners;
32133 Atom *names;
32134 ptrdiff_t nowners, counter;
32135 struct selection_input_event clear;
32136 #ifdef USE_XCB
32137 xcb_get_selection_owner_cookie_t *cookies;
32138 xcb_generic_error_t *error;
32139 xcb_get_selection_owner_reply_t *reply;
32140 #endif
32141
32142 new_owner = Qnil;
32143
32144 FOR_EACH_FRAME (tail, frame)
32145 {
32146 if (FRAME_X_P (XFRAME (frame))
32147 && !EQ (frame, current_owner)
32148 && FRAME_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
32149 {
32150 new_owner = frame;
32151 break;
32152 }
32153 }
32154
32155 tail = lost;
32156 nowners = 0;
32157
32158 FOR_EACH_TAIL_SAFE (tail)
32159 {
32160 Lisp_Object tem = XCAR (tail);
32161 ++nowners;
32162
32163
32164
32165 if (NILP (new_owner))
32166 CALLN (Frun_hook_with_args, Qx_lost_selection_functions,
32167 XCAR (tem));
32168 else
32169 {
32170 CONS_TO_INTEGER (XCAR (XCDR (XCDR (tem))), Time, timestamp);
32171
32172
32173
32174 x_own_selection (XCAR (tem), XCAR (XCDR (tem)),
32175 new_owner, XCAR (XCDR (XCDR (XCDR (XCDR (tem))))),
32176 timestamp);
32177 }
32178 }
32179
32180 if (!NILP (new_owner))
32181 {
32182 owners = alloca (sizeof *owners * nowners);
32183 names = alloca (sizeof *names * nowners);
32184 #ifdef USE_XCB
32185 cookies = alloca (sizeof *cookies * nowners);
32186 #endif
32187
32188 tail = lost;
32189 nowners = 0;
32190 counter = 0;
32191
32192 FOR_EACH_TAIL_SAFE (tail)
32193 {
32194 Lisp_Object tem = XCAR (tail);
32195
32196
32197
32198 names[counter++] = symbol_to_x_atom (dpyinfo, XCAR (tem));
32199
32200 #ifndef USE_XCB
32201 owners[nowners++] = XGetSelectionOwner (dpyinfo->display,
32202 names[counter - 1]);
32203 #else
32204 cookies[nowners++]
32205 = xcb_get_selection_owner (dpyinfo->xcb_connection,
32206 names[counter - 1]);
32207 }
32208
32209 nowners = 0;
32210 tail = lost;
32211
32212 FOR_EACH_TAIL_SAFE (tail)
32213 {
32214 Lisp_Object tem = XCAR (tail);
32215
32216 reply = xcb_get_selection_owner_reply (dpyinfo->xcb_connection,
32217 cookies[nowners++], &error);
32218 if (reply)
32219 owners[nowners - 1] = reply->owner;
32220 else
32221 owners[nowners - 1] = None;
32222
32223 free (reply ? (void *) reply : (void *) error);
32224 #endif
32225
32226 if (owners[nowners - 1] != FRAME_X_WINDOW (XFRAME (new_owner)))
32227 {
32228
32229
32230 CONS_TO_INTEGER (XCAR (XCDR (XCDR (tem))), Time, timestamp);
32231
32232 clear.kind = SELECTION_CLEAR_EVENT;
32233
32234 SELECTION_EVENT_DPYINFO (&clear) = dpyinfo;
32235 SELECTION_EVENT_SELECTION (&clear) = names[nowners - 1];
32236 SELECTION_EVENT_TIME (&clear) = timestamp;
32237
32238 x_handle_selection_event (&clear);
32239 }
32240 }
32241
32242 tail = lost;
32243 nowners = 0;
32244
32245 FOR_EACH_TAIL_SAFE (tail)
32246 {
32247 Lisp_Object tem = XCAR (tail);
32248
32249
32250
32251 if (owners[nowners++] != FRAME_X_WINDOW (XFRAME (new_owner)))
32252 CALLN (Frun_hook_with_args, Qx_lost_selection_functions,
32253 XCAR (tem));
32254 }
32255 }
32256 }
32257
32258
32259
32260
32261
32262
32263 Lisp_Object
32264 x_get_keyboard_modifiers (struct x_display_info *dpyinfo)
32265 {
32266
32267
32268
32269
32270 #ifdef HAVE_XKB
32271 if (!dpyinfo->xkb_desc && !dpyinfo->modmap)
32272 x_find_modifier_meanings (dpyinfo);
32273 #else
32274 if (!dpyinfo->modmap)
32275 x_find_modifier_meanings (dpyinfo);
32276 #endif
32277
32278 return list5 (make_uint (dpyinfo->hyper_mod_mask),
32279 make_uint (dpyinfo->super_mod_mask),
32280 make_uint (dpyinfo->alt_mod_mask),
32281 make_uint (dpyinfo->shift_lock_mask),
32282 make_uint (dpyinfo->meta_mod_mask));
32283 }
32284
32285 void
32286 syms_of_xterm (void)
32287 {
32288 x_error_message = NULL;
32289 PDUMPER_IGNORE (x_error_message);
32290
32291 x_dnd_monitors = Qnil;
32292 staticpro (&x_dnd_monitors);
32293
32294 x_dnd_action_symbol = Qnil;
32295 staticpro (&x_dnd_action_symbol);
32296
32297 x_dnd_selection_alias_cell = Fcons (Qnil, Qnil);
32298 staticpro (&x_dnd_selection_alias_cell);
32299
32300 x_dnd_unsupported_drop_data = Qnil;
32301 staticpro (&x_dnd_unsupported_drop_data);
32302
32303
32304 DEFSYM (Qconcat, "concat");
32305
32306 DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms");
32307 DEFSYM (Qlatin_1, "latin-1");
32308 DEFSYM (Qnow, "now");
32309 DEFSYM (Qx_dnd_targets_list, "x-dnd-targets-list");
32310 DEFSYM (Qx_auto_preserve_selections, "x-auto-preserve-selections");
32311 DEFSYM (Qexpose, "expose");
32312 DEFSYM (Qdont_save, "dont-save");
32313
32314 #ifdef USE_GTK
32315 xg_default_icon_file = build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg");
32316 staticpro (&xg_default_icon_file);
32317
32318 DEFSYM (Qx_gtk_map_stock, "x-gtk-map-stock");
32319 #endif
32320
32321 DEFVAR_BOOL ("x-use-underline-position-properties",
32322 x_use_underline_position_properties,
32323 doc:
32324
32325
32326
32327 );
32328 x_use_underline_position_properties = true;
32329 DEFSYM (Qx_use_underline_position_properties,
32330 "x-use-underline-position-properties");
32331
32332 DEFVAR_BOOL ("x-underline-at-descent-line",
32333 x_underline_at_descent_line,
32334 doc:
32335
32336
32337
32338
32339 );
32340 x_underline_at_descent_line = false;
32341 DEFSYM (Qx_underline_at_descent_line, "x-underline-at-descent-line");
32342
32343 DEFVAR_BOOL ("x-mouse-click-focus-ignore-position",
32344 x_mouse_click_focus_ignore_position,
32345 doc:
32346
32347
32348
32349
32350
32351
32352
32353
32354
32355 );
32356 x_mouse_click_focus_ignore_position = false;
32357
32358 DEFVAR_INT ("x-mouse-click-focus-ignore-time", x_mouse_click_focus_ignore_time,
32359 doc:
32360
32361
32362 );
32363 x_mouse_click_focus_ignore_time = 200;
32364
32365 DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
32366 doc:
32367
32368
32369
32370
32371
32372 );
32373 #ifdef USE_TOOLKIT_SCROLL_BARS
32374 #ifdef USE_MOTIF
32375 Vx_toolkit_scroll_bars = intern_c_string ("motif");
32376 #elif defined HAVE_XAW3D
32377 Vx_toolkit_scroll_bars = intern_c_string ("xaw3d");
32378 #elif USE_GTK
32379 Vx_toolkit_scroll_bars = intern_c_string ("gtk");
32380 #else
32381 Vx_toolkit_scroll_bars = intern_c_string ("xaw");
32382 #endif
32383 #else
32384 Vx_toolkit_scroll_bars = Qnil;
32385 #endif
32386
32387 DEFSYM (Qmodifier_value, "modifier-value");
32388 DEFSYM (Qctrl, "ctrl");
32389 Fput (Qctrl, Qmodifier_value, make_fixnum (ctrl_modifier));
32390 DEFSYM (Qalt, "alt");
32391 Fput (Qalt, Qmodifier_value, make_fixnum (alt_modifier));
32392 DEFSYM (Qhyper, "hyper");
32393 Fput (Qhyper, Qmodifier_value, make_fixnum (hyper_modifier));
32394 DEFSYM (Qmeta, "meta");
32395 Fput (Qmeta, Qmodifier_value, make_fixnum (meta_modifier));
32396 DEFSYM (Qsuper, "super");
32397 Fput (Qsuper, Qmodifier_value, make_fixnum (super_modifier));
32398 DEFSYM (QXdndSelection, "XdndSelection");
32399 DEFSYM (Qx_selection_alias_alist, "x-selection-alias-alist");
32400 DEFSYM (Qimitate_pager, "imitate-pager");
32401 DEFSYM (Qnewer_time, "newer-time");
32402 DEFSYM (Qraise_and_focus, "raise-and-focus");
32403 DEFSYM (Qreally_fast, "really-fast");
32404
32405 DEFVAR_LISP ("x-ctrl-keysym", Vx_ctrl_keysym,
32406 doc:
32407
32408
32409 );
32410 Vx_ctrl_keysym = Qnil;
32411
32412 DEFVAR_LISP ("x-alt-keysym", Vx_alt_keysym,
32413 doc:
32414
32415
32416 );
32417 Vx_alt_keysym = Qnil;
32418
32419 DEFVAR_LISP ("x-hyper-keysym", Vx_hyper_keysym,
32420 doc:
32421
32422
32423 );
32424 Vx_hyper_keysym = Qnil;
32425
32426 DEFVAR_LISP ("x-meta-keysym", Vx_meta_keysym,
32427 doc:
32428
32429
32430 );
32431 Vx_meta_keysym = Qnil;
32432
32433 DEFVAR_LISP ("x-super-keysym", Vx_super_keysym,
32434 doc:
32435
32436
32437 );
32438 Vx_super_keysym = Qnil;
32439
32440 DEFVAR_LISP ("x-wait-for-event-timeout", Vx_wait_for_event_timeout,
32441 doc:
32442
32443
32444
32445
32446
32447
32448 );
32449 Vx_wait_for_event_timeout = make_float (0.1);
32450
32451 DEFVAR_LISP ("x-keysym-table", Vx_keysym_table,
32452 doc: );
32453 Vx_keysym_table = make_hash_table (hashtest_eql, 900,
32454 DEFAULT_REHASH_SIZE,
32455 DEFAULT_REHASH_THRESHOLD,
32456 Qnil, false);
32457
32458 DEFVAR_BOOL ("x-frame-normalize-before-maximize",
32459 x_frame_normalize_before_maximize,
32460 doc:
32461
32462
32463
32464
32465
32466
32467
32468 );
32469 x_frame_normalize_before_maximize = false;
32470
32471 DEFVAR_BOOL ("x-gtk-use-window-move", x_gtk_use_window_move,
32472 doc:
32473
32474
32475
32476 );
32477 x_gtk_use_window_move = true;
32478
32479 DEFVAR_LISP ("x-scroll-event-delta-factor", Vx_scroll_event_delta_factor,
32480 doc:
32481
32482 );
32483 Vx_scroll_event_delta_factor = make_float (1.0);
32484
32485 DEFVAR_BOOL ("x-gtk-use-native-input", x_gtk_use_native_input,
32486 doc:
32487
32488 );
32489 x_gtk_use_native_input = false;
32490
32491 DEFVAR_LISP ("x-set-frame-visibility-more-laxly",
32492 x_set_frame_visibility_more_laxly,
32493 doc:
32494
32495
32496
32497
32498
32499
32500
32501
32502
32503 );
32504 x_set_frame_visibility_more_laxly = Qnil;
32505
32506 DEFVAR_BOOL ("x-input-grab-touch-events", x_input_grab_touch_events,
32507 doc:
32508
32509
32510
32511
32512
32513 );
32514 x_input_grab_touch_events = true;
32515
32516 DEFVAR_BOOL ("x-dnd-fix-motif-leave", x_dnd_fix_motif_leave,
32517 doc:
32518
32519
32520
32521 );
32522 x_dnd_fix_motif_leave = true;
32523
32524 DEFVAR_BOOL ("x-dnd-disable-motif-drag", x_dnd_disable_motif_drag,
32525 doc:
32526
32527
32528 );
32529 x_dnd_disable_motif_drag = false;
32530
32531 DEFVAR_LISP ("x-dnd-movement-function", Vx_dnd_movement_function,
32532 doc:
32533
32534
32535 );
32536 Vx_dnd_movement_function = Qnil;
32537
32538 DEFVAR_LISP ("x-dnd-wheel-function", Vx_dnd_wheel_function,
32539 doc:
32540
32541
32542
32543
32544 );
32545 Vx_dnd_wheel_function = Qnil;
32546
32547 DEFVAR_LISP ("x-dnd-unsupported-drop-function", Vx_dnd_unsupported_drop_function,
32548 doc:
32549
32550
32551
32552
32553
32554
32555
32556
32557
32558
32559
32560
32561
32562
32563
32564
32565 );
32566 Vx_dnd_unsupported_drop_function = Qnil;
32567
32568 DEFVAR_INT ("x-color-cache-bucket-size", x_color_cache_bucket_size,
32569 doc:
32570 );
32571 x_color_cache_bucket_size = 128;
32572
32573 DEFVAR_LISP ("x-dnd-targets-list", Vx_dnd_targets_list,
32574 doc:
32575
32576
32577 );
32578 Vx_dnd_targets_list = Qnil;
32579
32580 DEFVAR_LISP ("x-dnd-native-test-function", Vx_dnd_native_test_function,
32581 doc:
32582
32583
32584
32585
32586
32587
32588
32589
32590 );
32591 Vx_dnd_native_test_function = Qnil;
32592
32593 DEFVAR_BOOL ("x-dnd-preserve-selection-data", x_dnd_preserve_selection_data,
32594 doc:
32595
32596
32597 );
32598 x_dnd_preserve_selection_data = false;
32599
32600 DEFVAR_BOOL ("x-dnd-disable-motif-protocol", x_dnd_disable_motif_protocol,
32601 doc:
32602
32603 );
32604 x_dnd_disable_motif_protocol = false;
32605
32606 DEFVAR_BOOL ("x-dnd-use-unsupported-drop", x_dnd_use_unsupported_drop,
32607 doc:
32608
32609
32610 );
32611 x_dnd_use_unsupported_drop = true;
32612
32613 DEFVAR_BOOL ("x-fast-protocol-requests", x_fast_protocol_requests,
32614 doc:
32615
32616
32617
32618
32619 );
32620 x_fast_protocol_requests = false;
32621
32622 DEFVAR_LISP ("x-auto-preserve-selections", Vx_auto_preserve_selections,
32623 doc:
32624
32625
32626
32627
32628
32629 );
32630 Vx_auto_preserve_selections = list2 (QCLIPBOARD, QPRIMARY);
32631
32632 DEFVAR_LISP ("x-input-coding-system", Vx_input_coding_system,
32633 doc:
32634
32635
32636 );
32637 Vx_input_coding_system = Qnil;
32638
32639 DEFVAR_LISP ("x-input-coding-function", Vx_input_coding_function,
32640 doc:
32641
32642
32643 );
32644 Vx_input_coding_function = Qnil;
32645
32646 DEFVAR_LISP ("x-fast-selection-list", Vx_fast_selection_list,
32647 doc:
32648
32649
32650
32651
32652
32653
32654 );
32655
32656
32657 Vx_fast_selection_list = list1 (QCLIPBOARD);
32658
32659 DEFVAR_LISP ("x-allow-focus-stealing", Vx_allow_focus_stealing,
32660 doc:
32661
32662
32663
32664
32665
32666
32667
32668
32669
32670
32671
32672
32673
32674
32675
32676
32677
32678
32679
32680
32681
32682 );
32683 Vx_allow_focus_stealing = Qnewer_time;
32684
32685 DEFVAR_LISP ("x-use-fast-mouse-position", Vx_use_fast_mouse_position,
32686 doc:
32687
32688
32689
32690
32691
32692
32693
32694
32695
32696
32697 );
32698 Vx_use_fast_mouse_position = Qnil;
32699
32700 DEFVAR_LISP ("x-detect-server-trust", Vx_detect_server_trust,
32701 doc:
32702
32703
32704
32705
32706
32707 );
32708 Vx_detect_server_trust = Qnil;
32709
32710 DEFVAR_LISP ("x-lax-frame-positioning", Vx_lax_frame_positioning,
32711 doc:
32712
32713
32714
32715
32716
32717
32718
32719 );
32720 Vx_lax_frame_positioning = Qnil;
32721
32722 DEFVAR_LISP ("x-quit-keysym", Vx_quit_keysym,
32723 doc:
32724
32725
32726
32727
32728
32729
32730
32731
32732
32733
32734 );
32735 Vx_quit_keysym
32736 = list2 (Fcons (build_string ("The X.Org Foundation"),
32737 make_int (269025041)),
32738 Fcons (build_string ("The XFree86 Project, Inc."),
32739 make_int (269025041)));
32740 }