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
- xi_frame_selected_for
- x_toolkit_position
- x_update_opaque_region
- x_gc_free_ext_data_private
- x_gc_get_ext_data
- x_extension_initialize
- 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 bool x_dnd_in_progress;
1222
1223
1224 struct frame *x_dnd_frame;
1225
1226
1227
1228
1229 struct frame *x_dnd_finish_frame;
1230
1231
1232
1233
1234
1235 bool x_dnd_waiting_for_finish;
1236
1237
1238
1239
1240 static bool x_dnd_run_unsupported_drop_function;
1241
1242
1243 static Time x_dnd_unsupported_drop_time;
1244
1245
1246 static Window x_dnd_unsupported_drop_window;
1247
1248
1249 static Lisp_Object x_dnd_unsupported_drop_data;
1250
1251
1252
1253 static bool x_dnd_update_tooltip;
1254
1255
1256 static Lisp_Object x_dnd_monitors;
1257
1258
1259
1260 static Display *x_dnd_finish_display;
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271 static int x_dnd_waiting_for_motif_finish;
1272
1273
1274
1275 struct x_display_info *x_dnd_waiting_for_motif_finish_display;
1276
1277
1278
1279
1280
1281 static bool x_dnd_xm_use_help;
1282
1283
1284 static bool x_dnd_motif_setup_p;
1285
1286
1287 static Atom x_dnd_motif_atom;
1288
1289
1290
1291 static Window x_dnd_pending_finish_target;
1292
1293
1294 static int x_dnd_waiting_for_finish_proto;
1295
1296
1297
1298 static bool x_dnd_allow_current_frame;
1299
1300
1301
1302 static bool x_dnd_init_type_lists;
1303
1304
1305
1306
1307
1308
1309 static int x_dnd_return_frame;
1310
1311
1312
1313 static struct frame *x_dnd_return_frame_object;
1314
1315
1316
1317
1318 static Window x_dnd_last_seen_window;
1319
1320
1321 static Window x_dnd_last_seen_toplevel;
1322
1323
1324
1325 static Window x_dnd_end_window;
1326
1327
1328
1329 static int x_dnd_last_protocol_version;
1330
1331
1332
1333 static bool x_dnd_last_window_is_frame;
1334
1335
1336
1337
1338
1339
1340
1341 static int x_dnd_last_motif_style;
1342
1343
1344
1345 static Time x_dnd_selection_timestamp;
1346
1347
1348 static Window x_dnd_mouse_rect_target;
1349
1350
1351
1352 static XRectangle x_dnd_mouse_rect;
1353
1354
1355
1356 static Window x_dnd_waiting_for_status_window;
1357
1358
1359
1360 static XEvent x_dnd_pending_send_position;
1361
1362
1363 static bool x_dnd_pending_send_position_button;
1364
1365
1366 static int x_dnd_pending_send_position_root_x;
1367
1368
1369 static int x_dnd_pending_send_position_root_y;
1370
1371
1372
1373 static bool x_dnd_need_send_drop;
1374
1375
1376 static int x_dnd_send_drop_proto;
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388 static Atom x_dnd_action;
1389
1390
1391
1392 static Lisp_Object x_dnd_action_symbol;
1393
1394
1395
1396
1397 static Atom x_dnd_wanted_action;
1398
1399
1400
1401 static uint8_t x_dnd_motif_operations;
1402
1403
1404
1405 static uint8_t x_dnd_first_motif_operation;
1406
1407
1408 static Atom *x_dnd_targets;
1409
1410
1411 static int x_dnd_n_targets;
1412
1413
1414
1415
1416
1417 static XWindowAttributes x_dnd_old_window_attrs;
1418
1419
1420
1421 static bool x_dnd_unwind_flag;
1422
1423
1424 static struct frame *x_dnd_movement_frame;
1425
1426
1427
1428 static int x_dnd_movement_x, x_dnd_movement_y;
1429
1430
1431 static struct frame *x_dnd_wheel_frame;
1432
1433
1434 static int x_dnd_wheel_x, x_dnd_wheel_y;
1435
1436
1437 static int x_dnd_wheel_button;
1438
1439
1440 static int x_dnd_wheel_state;
1441
1442
1443 static Time x_dnd_wheel_time;
1444
1445 #ifdef HAVE_XKB
1446
1447 static unsigned int x_dnd_keyboard_state;
1448 #endif
1449
1450
1451
1452 static sigjmp_buf x_dnd_disconnect_handler;
1453
1454
1455
1456 static bool x_dnd_inside_handle_one_xevent;
1457
1458
1459
1460 static int x_dnd_recursion_depth;
1461
1462
1463
1464
1465 static Lisp_Object x_dnd_selection_alias_cell;
1466
1467
1468 static int x_dnd_last_tooltip_x, x_dnd_last_tooltip_y;
1469
1470
1471 static bool x_dnd_last_tooltip_valid;
1472
1473 #ifdef HAVE_XINPUT2
1474
1475
1476 static int x_dnd_pointer_device;
1477
1478
1479 static int x_dnd_keyboard_device;
1480 #endif
1481
1482
1483
1484 struct x_client_list_window
1485 {
1486
1487 Window window;
1488
1489
1490 Display *dpy;
1491
1492
1493 int x, y;
1494
1495
1496 int width, height;
1497
1498
1499
1500
1501 long previous_event_mask;
1502
1503
1504 unsigned long wm_state;
1505
1506
1507 struct x_client_list_window *next;
1508
1509
1510 int frame_extents_left;
1511 int frame_extents_right;
1512 int frame_extents_top;
1513 int frame_extents_bottom;
1514
1515 #ifdef HAVE_XSHAPE
1516
1517 int border_width;
1518
1519
1520 int n_input_rects;
1521
1522
1523 XRectangle *input_rects;
1524
1525
1526 XRectangle *bounding_rects;
1527
1528
1529 int n_bounding_rects;
1530 #endif
1531
1532
1533 uint8_t xm_protocol_style;
1534
1535
1536 bool mapped_p;
1537 };
1538
1539
1540 static struct x_client_list_window *x_dnd_toplevels;
1541
1542
1543
1544 static bool x_dnd_use_toplevels;
1545
1546
1547
1548
1549
1550 static volatile bool *xm_drag_window_error;
1551
1552 typedef enum xm_byte_order
1553 {
1554 XM_BYTE_ORDER_LSB_FIRST = 'l',
1555 XM_BYTE_ORDER_MSB_FIRST = 'B',
1556 #ifndef WORDS_BIGENDIAN
1557 XM_BYTE_ORDER_CUR_FIRST = 'l',
1558 #else
1559 XM_BYTE_ORDER_CUR_FIRST = 'B',
1560 #endif
1561 } xm_byte_order;
1562
1563 #ifdef ENABLE_CHECKING
1564
1565 #define SWAPCARD32(l) \
1566 { \
1567 struct { unsigned t : 32; } bit32; \
1568 char n, *tp = (char *) &bit32; \
1569 bit32.t = l; \
1570 n = tp[0]; tp[0] = tp[3]; tp[3] = n; \
1571 n = tp[1]; tp[1] = tp[2]; tp[2] = n; \
1572 l = bit32.t; \
1573 }
1574
1575 #define SWAPCARD16(s) \
1576 { \
1577 struct { unsigned t : 16; } bit16; \
1578 char n, *tp = (char *) &bit16; \
1579 bit16.t = s; \
1580 n = tp[0]; tp[0] = tp[1]; tp[1] = n; \
1581 s = bit16.t; \
1582 }
1583
1584 #else
1585 #define SWAPCARD32(l) ((l) = bswap_32 (l))
1586 #define SWAPCARD16(l) ((l) = bswap_16 (l))
1587 #endif
1588
1589 typedef struct xm_targets_table_header
1590 {
1591 uint8_t byte_order;
1592 uint8_t protocol;
1593
1594 uint16_t target_list_count;
1595 uint32_t total_data_size;
1596 } xm_targets_table_header;
1597
1598 typedef struct xm_targets_table_rec
1599 {
1600 uint16_t n_targets;
1601 uint32_t targets[FLEXIBLE_ARRAY_MEMBER];
1602 } xm_targets_table_rec;
1603
1604 typedef struct xm_drop_start_message
1605 {
1606 uint8_t reason;
1607 uint8_t byte_order;
1608
1609 uint16_t side_effects;
1610 uint32_t timestamp;
1611 uint16_t x, y;
1612 uint32_t index_atom;
1613 uint32_t source_window;
1614 } xm_drop_start_message;
1615
1616 typedef struct xm_drop_start_reply
1617 {
1618 uint8_t reason;
1619 uint8_t byte_order;
1620
1621 uint16_t side_effects;
1622 uint16_t better_x;
1623 uint16_t better_y;
1624 } xm_drop_start_reply;
1625
1626 typedef struct xm_drag_initiator_info
1627 {
1628 uint8_t byteorder;
1629 uint8_t protocol;
1630
1631 uint16_t table_index;
1632 uint32_t selection;
1633 } xm_drag_initiator_info;
1634
1635 typedef struct xm_drag_receiver_info
1636 {
1637 uint8_t byteorder;
1638 uint8_t protocol;
1639
1640 uint8_t protocol_style;
1641 uint8_t unspecified0;
1642 uint32_t unspecified1;
1643 uint32_t unspecified2;
1644 uint32_t unspecified3;
1645 } xm_drag_receiver_info;
1646
1647 typedef struct xm_top_level_enter_message
1648 {
1649 uint8_t reason;
1650 uint8_t byteorder;
1651
1652 uint16_t zero;
1653 uint32_t timestamp;
1654 uint32_t source_window;
1655 uint32_t index_atom;
1656 } xm_top_level_enter_message;
1657
1658 typedef struct xm_drag_motion_message
1659 {
1660 uint8_t reason;
1661 uint8_t byteorder;
1662
1663 uint16_t side_effects;
1664 uint32_t timestamp;
1665 uint16_t x, y;
1666 } xm_drag_motion_message;
1667
1668 typedef struct xm_drag_motion_reply
1669 {
1670 uint8_t reason;
1671 uint8_t byte_order;
1672
1673 uint16_t side_effects;
1674 uint32_t timestamp;
1675 uint16_t better_x;
1676 uint16_t better_y;
1677 } xm_drag_motion_reply;
1678
1679 typedef struct xm_top_level_leave_message
1680 {
1681 uint8_t reason;
1682 uint8_t byteorder;
1683
1684 uint16_t zero;
1685 uint32_t timestamp;
1686 uint32_t source_window;
1687 } xm_top_level_leave_message;
1688
1689 #define XM_DRAG_SIDE_EFFECT(op, site, ops, act) \
1690 ((op) | ((site) << 4) | ((ops) << 8) | ((act) << 12))
1691
1692
1693
1694 #define XM_DRAG_SIDE_EFFECT_OPERATION(effect) ((effect) & 0xf)
1695 #define XM_DRAG_SIDE_EFFECT_SITE_STATUS(effect) (((effect) & 0xf0) >> 4)
1696
1697 #define XM_DRAG_SIDE_EFFECT_DROP_ACTION(effect) (((effect) & 0xf000) >> 12)
1698
1699 enum xm_drag_operation
1700 {
1701 XM_DRAG_NOOP = 0,
1702 XM_DRAG_MOVE = (1L << 0),
1703 XM_DRAG_COPY = (1L << 1),
1704 XM_DRAG_LINK = (1L << 2),
1705 XM_DRAG_LINK_REC = 3,
1706 };
1707
1708 #define XM_DRAG_OPERATION_IS_LINK(op) ((op) == XM_DRAG_LINK \
1709 || (op) == XM_DRAG_LINK_REC)
1710
1711 enum xm_drag_action
1712 {
1713 XM_DROP_ACTION_DROP = 0,
1714 XM_DROP_ACTION_DROP_HELP = 1,
1715 XM_DROP_ACTION_DROP_CANCEL = 2,
1716 };
1717
1718 #define XM_DRAG_REASON(originator, code) ((code) | ((originator) << 7))
1719 #define XM_DRAG_REASON_ORIGINATOR(reason) (((reason) & 0x80) ? 1 : 0)
1720 #define XM_DRAG_REASON_CODE(reason) ((reason) & 0x7f)
1721
1722 enum xm_drag_reason
1723 {
1724 XM_DRAG_REASON_DROP_START = 5,
1725 XM_DRAG_REASON_TOP_LEVEL_ENTER = 0,
1726 XM_DRAG_REASON_TOP_LEVEL_LEAVE = 1,
1727 XM_DRAG_REASON_DRAG_MOTION = 2,
1728 };
1729
1730 enum xm_drag_originator
1731 {
1732 XM_DRAG_ORIGINATOR_INITIATOR = 0,
1733 XM_DRAG_ORIGINATOR_RECEIVER = 1,
1734 };
1735
1736 enum xm_drag_style
1737 {
1738
1739
1740 XM_DRAG_STYLE_NONE = 0,
1741 XM_DRAG_STYLE_DROP_ONLY = 1,
1742 XM_DRAG_STYLE_DROP_ONLY_REC = 3,
1743 XM_DRAG_STYLE_DYNAMIC = 5,
1744 XM_DRAG_STYLE_DYNAMIC_REC = 2,
1745 XM_DRAG_STYLE_DYNAMIC_REC1 = 4,
1746 };
1747
1748 #define XM_DRAG_STYLE_IS_DROP_ONLY(n) ((n) == XM_DRAG_STYLE_DROP_ONLY \
1749 || (n) == XM_DRAG_STYLE_DROP_ONLY_REC)
1750 #define XM_DRAG_STYLE_IS_DYNAMIC(n) ((n) == XM_DRAG_STYLE_DYNAMIC \
1751 || (n) == XM_DRAG_STYLE_DYNAMIC_REC \
1752 || (n) == XM_DRAG_STYLE_DYNAMIC_REC1)
1753
1754 enum xm_drop_site_status
1755 {
1756 XM_DROP_SITE_VALID = 3,
1757 XM_DROP_SITE_INVALID = 2,
1758 XM_DROP_SITE_NONE = 1,
1759 };
1760
1761
1762
1763 #define XM_DRAG_PROTOCOL_VERSION 0
1764
1765 static uint8_t
1766 xm_side_effect_from_action (struct x_display_info *dpyinfo, Atom action)
1767 {
1768 if (action == dpyinfo->Xatom_XdndActionCopy)
1769 return XM_DRAG_COPY;
1770 else if (action == dpyinfo->Xatom_XdndActionMove)
1771 return XM_DRAG_MOVE;
1772 else if (action == dpyinfo->Xatom_XdndActionLink)
1773 return XM_DRAG_LINK;
1774 else if (action == dpyinfo->Xatom_XdndActionAsk)
1775 return x_dnd_first_motif_operation;
1776
1777 return XM_DRAG_NOOP;
1778 }
1779
1780 static uint8_t
1781 xm_operations_from_actions (struct x_display_info *dpyinfo,
1782 Atom *ask_actions, int n_ask_actions)
1783 {
1784 int i;
1785 uint8_t flags;
1786
1787 flags = 0;
1788
1789 for (i = 0; i < n_ask_actions; ++i)
1790 {
1791 if (ask_actions[i] == dpyinfo->Xatom_XdndActionCopy)
1792 flags |= XM_DRAG_COPY;
1793 else if (ask_actions[i] == dpyinfo->Xatom_XdndActionMove)
1794 flags |= XM_DRAG_MOVE;
1795 else if (ask_actions[i] == dpyinfo->Xatom_XdndActionLink)
1796 flags |= XM_DRAG_LINK;
1797 }
1798
1799 return flags;
1800 }
1801
1802 static int
1803 xm_read_targets_table_header (uint8_t *bytes, ptrdiff_t length,
1804 xm_targets_table_header *header_return,
1805 xm_byte_order *byteorder_return)
1806 {
1807 if (length < 8)
1808 return -1;
1809
1810 header_return->byte_order = *byteorder_return = *(bytes++);
1811 header_return->protocol = *(bytes++);
1812
1813 header_return->target_list_count = *(uint16_t *) bytes;
1814 header_return->total_data_size = *(uint32_t *) (bytes + 2);
1815
1816 if (header_return->byte_order != XM_BYTE_ORDER_CUR_FIRST)
1817 {
1818 SWAPCARD16 (header_return->target_list_count);
1819 SWAPCARD32 (header_return->total_data_size);
1820 }
1821
1822 header_return->byte_order = XM_BYTE_ORDER_CUR_FIRST;
1823
1824 return 8;
1825 }
1826
1827 static xm_targets_table_rec *
1828 xm_read_targets_table_rec (uint8_t *bytes, ptrdiff_t length,
1829 xm_byte_order byteorder)
1830 {
1831 uint16_t nitems, i;
1832 xm_targets_table_rec *rec;
1833
1834 if (length < 2)
1835 return NULL;
1836
1837 nitems = *(uint16_t *) bytes;
1838
1839 if (byteorder != XM_BYTE_ORDER_CUR_FIRST)
1840 SWAPCARD16 (nitems);
1841
1842 if (length < 2 + nitems * 4)
1843 return NULL;
1844
1845 rec = xmalloc (FLEXSIZEOF (struct xm_targets_table_rec,
1846 targets, nitems * 4));
1847 rec->n_targets = nitems;
1848
1849 for (i = 0; i < nitems; ++i)
1850 {
1851 rec->targets[i] = ((uint32_t *) (bytes + 2))[i];
1852
1853 if (byteorder != XM_BYTE_ORDER_CUR_FIRST)
1854 SWAPCARD32 (rec->targets[i]);
1855 }
1856
1857 return rec;
1858 }
1859
1860 static int
1861 xm_find_targets_table_idx (xm_targets_table_header *header,
1862 xm_targets_table_rec **recs,
1863 Atom *sorted_targets, int ntargets)
1864 {
1865 int j;
1866 uint16_t i;
1867 uint32_t *targets;
1868
1869 targets = alloca (sizeof *targets * ntargets);
1870
1871 for (j = 0; j < ntargets; ++j)
1872 targets[j] = sorted_targets[j];
1873
1874 for (i = 0; i < header->target_list_count; ++i)
1875 {
1876 if (recs[i]->n_targets == ntargets
1877 && !memcmp (&recs[i]->targets, targets,
1878 sizeof *targets * ntargets))
1879 return i;
1880 }
1881
1882 return -1;
1883 }
1884
1885 static int
1886 x_atoms_compare (const void *a, const void *b)
1887 {
1888 return *(Atom *) a - *(Atom *) b;
1889 }
1890
1891 static void
1892 xm_write_targets_table (Display *dpy, Window wdesc,
1893 Atom targets_table_atom,
1894 xm_targets_table_header *header,
1895 xm_targets_table_rec **recs)
1896 {
1897 uint8_t *header_buffer, *ptr, *rec_buffer;
1898 ptrdiff_t rec_buffer_size;
1899 uint16_t i, j;
1900
1901 header_buffer = alloca (8);
1902 ptr = header_buffer;
1903
1904 *(header_buffer++) = header->byte_order;
1905 *(header_buffer++) = header->protocol;
1906 *((uint16_t *) header_buffer) = header->target_list_count;
1907 *((uint32_t *) (header_buffer + 2)) = header->total_data_size;
1908
1909 rec_buffer = xmalloc (600);
1910 rec_buffer_size = 600;
1911
1912 XChangeProperty (dpy, wdesc, targets_table_atom,
1913 targets_table_atom, 8, PropModeReplace,
1914 (unsigned char *) ptr, 8);
1915
1916 for (i = 0; i < header->target_list_count; ++i)
1917 {
1918 if (rec_buffer_size < 2 + recs[i]->n_targets * 4)
1919 {
1920 rec_buffer_size = 2 + recs[i]->n_targets * 4;
1921 rec_buffer = xrealloc (rec_buffer, rec_buffer_size);
1922 }
1923
1924 *((uint16_t *) rec_buffer) = recs[i]->n_targets;
1925
1926 for (j = 0; j < recs[i]->n_targets; ++j)
1927 ((uint32_t *) (rec_buffer + 2))[j] = recs[i]->targets[j];
1928
1929 XChangeProperty (dpy, wdesc, targets_table_atom,
1930 targets_table_atom, 8, PropModeAppend,
1931 (unsigned char *) rec_buffer,
1932 2 + recs[i]->n_targets * 4);
1933 }
1934
1935 xfree (rec_buffer);
1936 }
1937
1938 static void
1939 xm_write_drag_initiator_info (Display *dpy, Window wdesc,
1940 Atom prop_name, Atom type_name,
1941 xm_drag_initiator_info *info)
1942 {
1943 uint8_t *buf;
1944
1945 buf = alloca (8);
1946 buf[0] = info->byteorder;
1947 buf[1] = info->protocol;
1948
1949 if (info->byteorder != XM_BYTE_ORDER_CUR_FIRST)
1950 {
1951 SWAPCARD16 (info->table_index);
1952 SWAPCARD16 (info->selection);
1953 }
1954
1955 *((uint16_t *) (buf + 2)) = info->table_index;
1956 *((uint32_t *) (buf + 4)) = info->selection;
1957
1958 XChangeProperty (dpy, wdesc, prop_name, type_name, 8,
1959 PropModeReplace, (unsigned char *) buf, 8);
1960 }
1961
1962 static int
1963 xm_drag_window_error_handler (Display *display, XErrorEvent *event)
1964 {
1965 if (xm_drag_window_error)
1966 *xm_drag_window_error = true;
1967
1968 return 0;
1969 }
1970
1971 static _Noreturn int
1972 xm_drag_window_io_error_handler (Display *dpy)
1973 {
1974
1975
1976 siglongjmp (x_dnd_disconnect_handler, 1);
1977 }
1978
1979
1980
1981 static bool
1982 x_special_window_exists_p (struct x_display_info *dpyinfo,
1983 Window window)
1984 {
1985 bool rc;
1986
1987 x_catch_errors (dpyinfo->display);
1988 XSelectInput (dpyinfo->display, window,
1989 StructureNotifyMask);
1990 rc = !x_had_errors_p (dpyinfo->display);
1991 x_uncatch_errors_after_check ();
1992
1993 return rc;
1994 }
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016 static Window
2017 xm_get_drag_window_1 (struct x_display_info *dpyinfo)
2018 {
2019 Atom actual_type;
2020 int rc, actual_format;
2021 unsigned long nitems, bytes_remaining;
2022 unsigned char *tmp_data = NULL;
2023 Window drag_window;
2024 XSetWindowAttributes attrs;
2025 Display *temp_display;
2026 Emacs_XErrorHandler old_handler;
2027 Emacs_XIOErrorHandler old_io_handler;
2028
2029
2030
2031 volatile bool error;
2032
2033 drag_window = None;
2034 rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window,
2035 dpyinfo->Xatom_MOTIF_DRAG_WINDOW,
2036 0, 1, False, XA_WINDOW, &actual_type,
2037 &actual_format, &nitems, &bytes_remaining,
2038 &tmp_data) == Success;
2039
2040 if (rc && actual_type == XA_WINDOW
2041 && actual_format == 32 && nitems == 1
2042 && tmp_data)
2043 {
2044 drag_window = *(Window *) tmp_data;
2045
2046
2047
2048
2049 rc = x_special_window_exists_p (dpyinfo, drag_window);
2050
2051 if (!rc)
2052 drag_window = None;
2053 }
2054
2055 if (tmp_data)
2056 XFree (tmp_data);
2057
2058 if (drag_window == None)
2059 {
2060 block_input ();
2061 old_io_handler = XSetIOErrorHandler (xm_drag_window_io_error_handler);
2062
2063 if (sigsetjmp (x_dnd_disconnect_handler, 1))
2064 {
2065 XSetIOErrorHandler (old_io_handler);
2066 unblock_input ();
2067
2068 return None;
2069 }
2070
2071 unrequest_sigio ();
2072 temp_display = XOpenDisplay (XDisplayString (dpyinfo->display));
2073 request_sigio ();
2074
2075 if (!temp_display)
2076 {
2077 XSetIOErrorHandler (old_io_handler);
2078 unblock_input ();
2079
2080 return None;
2081 }
2082
2083 error = false;
2084 xm_drag_window_error = &error;
2085
2086 XSetCloseDownMode (temp_display, RetainPermanent);
2087 old_handler = XSetErrorHandler (xm_drag_window_error_handler);
2088
2089 attrs.override_redirect = True;
2090 drag_window = XCreateWindow (temp_display, DefaultRootWindow (temp_display),
2091 -1, -1, 1, 1, 0, CopyFromParent, InputOnly,
2092 CopyFromParent, CWOverrideRedirect, &attrs);
2093
2094
2095 XSync (temp_display, False);
2096
2097
2098
2099 if (error)
2100 {
2101 XSetCloseDownMode (temp_display, DestroyAll);
2102 drag_window = None;
2103 }
2104
2105 xm_drag_window_error = NULL;
2106
2107
2108
2109 unrequest_sigio ();
2110 XCloseDisplay (temp_display);
2111 request_sigio ();
2112
2113 XSetErrorHandler (old_handler);
2114 XSetIOErrorHandler (old_io_handler);
2115
2116
2117
2118
2119 if (!x_special_window_exists_p (dpyinfo, drag_window))
2120 drag_window = None;
2121 unblock_input ();
2122
2123 if (drag_window != None)
2124 {
2125 XGrabServer (dpyinfo->display);
2126
2127 x_catch_errors (dpyinfo->display);
2128 tmp_data = NULL;
2129
2130 rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window,
2131 dpyinfo->Xatom_MOTIF_DRAG_WINDOW,
2132 0, 1, False, XA_WINDOW, &actual_type,
2133 &actual_format, &nitems, &bytes_remaining,
2134 &tmp_data) == Success;
2135
2136 if (rc && actual_type == XA_WINDOW
2137 && actual_format == 32 && nitems == 1
2138 && tmp_data
2139 && x_special_window_exists_p (dpyinfo,
2140 *(Window *) tmp_data))
2141 {
2142
2143
2144 XKillClient (dpyinfo->display, drag_window);
2145 drag_window = *(Window *) tmp_data;
2146 }
2147 else
2148 XChangeProperty (dpyinfo->display, dpyinfo->root_window,
2149 dpyinfo->Xatom_MOTIF_DRAG_WINDOW,
2150 XA_WINDOW, 32, PropModeReplace,
2151 (unsigned char *) &drag_window, 1);
2152
2153 if (tmp_data)
2154 XFree (tmp_data);
2155
2156 if (x_had_errors_p (dpyinfo->display))
2157 drag_window = None;
2158 x_uncatch_errors ();
2159
2160 XUngrabServer (dpyinfo->display);
2161 }
2162 }
2163
2164 return drag_window;
2165 }
2166
2167 static Window
2168 xm_get_drag_window (struct x_display_info *dpyinfo)
2169 {
2170 if (dpyinfo->motif_drag_window != None)
2171 return dpyinfo->motif_drag_window;
2172
2173 dpyinfo->motif_drag_window = xm_get_drag_window_1 (dpyinfo);
2174 return dpyinfo->motif_drag_window;
2175 }
2176
2177 static int
2178 xm_setup_dnd_targets (struct x_display_info *dpyinfo,
2179 Atom *targets, int ntargets)
2180 {
2181 Window drag_window;
2182 Atom *targets_sorted, actual_type;
2183 unsigned char *tmp_data = NULL;
2184 unsigned long nitems, bytes_remaining;
2185 int rc, actual_format, idx;
2186 bool had_errors;
2187 xm_targets_table_header header;
2188 xm_targets_table_rec **recs UNINIT;
2189 xm_byte_order byteorder;
2190 uint8_t *data;
2191 ptrdiff_t total_bytes, total_items, i;
2192 uint32_t size, target_count;
2193
2194 retry_drag_window:
2195
2196 drag_window = xm_get_drag_window (dpyinfo);
2197
2198 if (drag_window == None || ntargets > 64)
2199 return -1;
2200
2201 targets_sorted = xmalloc (sizeof *targets * ntargets);
2202 memcpy (targets_sorted, targets,
2203 sizeof *targets * ntargets);
2204 qsort (targets_sorted, ntargets,
2205 sizeof (Atom), x_atoms_compare);
2206
2207 XGrabServer (dpyinfo->display);
2208
2209 x_catch_errors (dpyinfo->display);
2210 rc = XGetWindowProperty (dpyinfo->display, drag_window,
2211 dpyinfo->Xatom_MOTIF_DRAG_TARGETS,
2212 0L, LONG_MAX, False,
2213 dpyinfo->Xatom_MOTIF_DRAG_TARGETS,
2214 &actual_type, &actual_format, &nitems,
2215 &bytes_remaining, &tmp_data) == Success;
2216 had_errors = x_had_errors_p (dpyinfo->display);
2217 x_uncatch_errors_after_check ();
2218
2219
2220
2221 if (had_errors)
2222 {
2223 dpyinfo->motif_drag_window = None;
2224 XUngrabServer (dpyinfo->display);
2225
2226 goto retry_drag_window;
2227 }
2228
2229 if (rc && tmp_data && !bytes_remaining
2230 && actual_type == dpyinfo->Xatom_MOTIF_DRAG_TARGETS
2231 && actual_format == 8)
2232 {
2233 data = (uint8_t *) tmp_data;
2234 if (xm_read_targets_table_header ((uint8_t *) tmp_data,
2235 nitems, &header,
2236 &byteorder) == 8)
2237 {
2238 data += 8;
2239 nitems -= 8;
2240 total_bytes = 0;
2241 total_items = 0;
2242
2243
2244
2245 recs = xmalloc ((header.target_list_count + 1)
2246 * sizeof *recs);
2247
2248 while (total_items < header.target_list_count)
2249 {
2250 recs[total_items] = xm_read_targets_table_rec (data + total_bytes,
2251 nitems, byteorder);
2252
2253 if (!recs[total_items])
2254 break;
2255
2256 total_bytes += 2 + recs[total_items]->n_targets * 4;
2257 nitems -= 2 + recs[total_items]->n_targets * 4;
2258 total_items++;
2259 }
2260
2261 if (header.target_list_count != total_items
2262 || header.total_data_size != 8 + total_bytes)
2263 {
2264 for (i = 0; i < total_items; ++i)
2265 {
2266 if (recs[i])
2267 xfree (recs[i]);
2268 else
2269 break;
2270 }
2271
2272 xfree (recs);
2273
2274 rc = false;
2275 }
2276 }
2277 else
2278 rc = false;
2279 }
2280 else
2281 rc = false;
2282
2283 if (tmp_data)
2284 XFree (tmp_data);
2285
2286
2287
2288
2289 if (!rc)
2290 {
2291 header.byte_order = XM_BYTE_ORDER_CUR_FIRST;
2292 header.protocol = XM_DRAG_PROTOCOL_VERSION;
2293 header.target_list_count = 1;
2294 header.total_data_size = 8 + 2 + ntargets * 4;
2295
2296 recs = xmalloc (sizeof *recs);
2297 recs[0] = xmalloc (FLEXSIZEOF (struct xm_targets_table_rec,
2298 targets, ntargets * 4));
2299
2300 recs[0]->n_targets = ntargets;
2301
2302 for (i = 0; i < ntargets; ++i)
2303 recs[0]->targets[i] = targets_sorted[i];
2304
2305 idx = 0;
2306 }
2307 else
2308 {
2309 idx = xm_find_targets_table_idx (&header, recs,
2310 targets_sorted,
2311 ntargets);
2312
2313 if (idx == -1)
2314 {
2315 target_count = header.target_list_count;
2316 rc = false;
2317
2318 if (ckd_add (&header.target_list_count, header.target_list_count, 1)
2319 || ckd_mul (&size, ntargets, 4)
2320 || ckd_add (&header.total_data_size, header.total_data_size, size)
2321 || ckd_add (&header.total_data_size, header.total_data_size, 2))
2322 {
2323
2324
2325
2326
2327
2328 for (i = 0; i < target_count; ++i)
2329 xfree (recs[i]);
2330
2331 xfree (recs);
2332
2333 header.byte_order = XM_BYTE_ORDER_CUR_FIRST;
2334 header.protocol = XM_DRAG_PROTOCOL_VERSION;
2335 header.target_list_count = 1;
2336 header.total_data_size = 8 + 2 + ntargets * 4;
2337
2338 recs = xmalloc (sizeof *recs);
2339 recs[0] = xmalloc (FLEXSIZEOF (struct xm_targets_table_rec,
2340 targets, ntargets * 4));
2341
2342 recs[0]->n_targets = ntargets;
2343
2344 for (i = 0; i < ntargets; ++i)
2345 recs[0]->targets[i] = targets_sorted[i];
2346
2347 idx = 0;
2348 }
2349 else
2350 {
2351 recs[header.target_list_count - 1]
2352 = xmalloc (FLEXSIZEOF (struct xm_targets_table_rec,
2353 targets, ntargets * 4));
2354 recs[header.target_list_count - 1]->n_targets = ntargets;
2355
2356 for (i = 0; i < ntargets; ++i)
2357 recs[header.target_list_count - 1]->targets[i] = targets_sorted[i];
2358
2359 idx = header.target_list_count - 1;
2360 }
2361 }
2362 }
2363
2364 if (!rc)
2365 {
2366
2367
2368
2369
2370
2371 header.protocol = XM_DRAG_PROTOCOL_VERSION;
2372
2373 x_catch_errors (dpyinfo->display);
2374 xm_write_targets_table (dpyinfo->display, drag_window,
2375 dpyinfo->Xatom_MOTIF_DRAG_TARGETS,
2376 &header, recs);
2377
2378
2379 if (x_had_errors_p (dpyinfo->display))
2380 idx = -1;
2381 x_uncatch_errors_after_check ();
2382 }
2383
2384 XUngrabServer (dpyinfo->display);
2385
2386 for (i = 0; i < header.target_list_count; ++i)
2387 xfree (recs[i]);
2388
2389 xfree (recs);
2390 xfree (targets_sorted);
2391
2392 return idx;
2393 }
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404 static Atom
2405 xm_get_drag_atom_1 (struct x_display_info *dpyinfo,
2406 struct frame *source_frame)
2407 {
2408 Atom actual_type, *atoms, atom;
2409 unsigned long nitems, bytes_remaining;
2410 unsigned char *tmp_data;
2411 int rc, actual_format;
2412 unsigned long i;
2413 char *buffer;
2414 Window owner;
2415
2416
2417 XGrabServer (dpyinfo->display);
2418
2419 rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window,
2420 dpyinfo->Xatom_EMACS_DRAG_ATOM,
2421 0, LONG_MAX, False, XA_ATOM, &actual_type,
2422 &actual_format, &nitems, &bytes_remaining,
2423 &tmp_data);
2424 atom = None;
2425
2426
2427 i = 0;
2428
2429 if (rc == Success
2430 && actual_format == 32 && nitems
2431 && actual_type == XA_ATOM)
2432 {
2433 atoms = (Atom *) tmp_data;
2434
2435 x_catch_errors (dpyinfo->display);
2436
2437 for (i = 0; i < nitems; ++i)
2438 {
2439 owner = XGetSelectionOwner (dpyinfo->display, atoms[i]);
2440
2441 if (!x_had_errors_p (dpyinfo->display)
2442 && (owner == None
2443
2444
2445
2446
2447 || x_window_to_frame (dpyinfo, owner)))
2448 {
2449 atom = atoms[i];
2450
2451 break;
2452 }
2453 }
2454
2455 x_uncatch_errors ();
2456 }
2457
2458 if (tmp_data)
2459 XFree (tmp_data);
2460
2461 buffer = dpyinfo->motif_drag_atom_name;
2462
2463 if (atom)
2464 {
2465 sprintf (buffer, "_EMACS_ATOM_%lu", i + 1);
2466 XSetSelectionOwner (dpyinfo->display, atom,
2467 FRAME_X_WINDOW (source_frame),
2468 dpyinfo->last_user_time);
2469
2470
2471
2472 if (XGetSelectionOwner (dpyinfo->display, atom)
2473 != FRAME_X_WINDOW (source_frame))
2474 atom = None;
2475 }
2476
2477 while (!atom)
2478 {
2479 sprintf (buffer, "_EMACS_ATOM_%lu", nitems + 1);
2480 atom = XInternAtom (dpyinfo->display, buffer, False);
2481
2482 XSetSelectionOwner (dpyinfo->display, atom,
2483 FRAME_X_WINDOW (source_frame),
2484 dpyinfo->last_user_time);
2485
2486 XChangeProperty (dpyinfo->display, dpyinfo->root_window,
2487 dpyinfo->Xatom_EMACS_DRAG_ATOM, XA_ATOM, 32,
2488 (rc != Success
2489 || (actual_format != 32
2490 || actual_type != XA_ATOM)
2491 ? PropModeReplace : PropModeAppend),
2492 (unsigned char *) &atom, 1);
2493
2494 actual_format = 32;
2495 actual_type = XA_ATOM;
2496 rc = Success;
2497 nitems += 1;
2498
2499
2500
2501 if (XGetSelectionOwner (dpyinfo->display, atom)
2502 != FRAME_X_WINDOW (source_frame))
2503 atom = None;
2504 }
2505
2506 dpyinfo->motif_drag_atom_time = dpyinfo->last_user_time;
2507 dpyinfo->motif_drag_atom_owner = source_frame;
2508
2509 XUngrabServer (dpyinfo->display);
2510 return atom;
2511 }
2512
2513 static Atom
2514 xm_get_drag_atom (struct x_display_info *dpyinfo)
2515 {
2516 Atom atom;
2517
2518 if (dpyinfo->motif_drag_atom != None)
2519 atom = dpyinfo->motif_drag_atom;
2520 else
2521 atom = xm_get_drag_atom_1 (dpyinfo, x_dnd_frame);
2522
2523 dpyinfo->motif_drag_atom = atom;
2524 return atom;
2525 }
2526
2527 static void
2528 xm_setup_drag_info (struct x_display_info *dpyinfo,
2529 struct frame *source_frame)
2530 {
2531 Atom atom;
2532 xm_drag_initiator_info drag_initiator_info;
2533 int idx;
2534
2535 atom = xm_get_drag_atom (dpyinfo);
2536
2537 if (atom == None)
2538 return;
2539
2540 XSETCAR (x_dnd_selection_alias_cell,
2541 x_atom_to_symbol (dpyinfo, atom));
2542 XSETCDR (x_dnd_selection_alias_cell, QXdndSelection);
2543
2544 idx = xm_setup_dnd_targets (dpyinfo, x_dnd_targets,
2545 x_dnd_n_targets);
2546
2547 if (idx != -1)
2548 {
2549 drag_initiator_info.byteorder = XM_BYTE_ORDER_CUR_FIRST;
2550 drag_initiator_info.protocol = XM_DRAG_PROTOCOL_VERSION;
2551 drag_initiator_info.table_index = idx;
2552 drag_initiator_info.selection = atom;
2553
2554 xm_write_drag_initiator_info (dpyinfo->display,
2555 FRAME_X_WINDOW (source_frame), atom,
2556 dpyinfo->Xatom_MOTIF_DRAG_INITIATOR_INFO,
2557 &drag_initiator_info);
2558
2559 x_dnd_motif_setup_p = true;
2560 x_dnd_motif_atom = atom;
2561 }
2562 }
2563
2564 static void
2565 xm_send_drop_message (struct x_display_info *dpyinfo, Window source,
2566 Window target, xm_drop_start_message *dmsg)
2567 {
2568 XEvent msg;
2569
2570 msg.xclient.type = ClientMessage;
2571 msg.xclient.message_type
2572 = dpyinfo->Xatom_MOTIF_DRAG_AND_DROP_MESSAGE;
2573 msg.xclient.format = 8;
2574 msg.xclient.window = target;
2575 msg.xclient.data.b[0] = dmsg->reason;
2576 msg.xclient.data.b[1] = dmsg->byte_order;
2577 *((uint16_t *) &msg.xclient.data.b[2]) = dmsg->side_effects;
2578 *((uint32_t *) &msg.xclient.data.b[4]) = dmsg->timestamp;
2579 *((uint16_t *) &msg.xclient.data.b[8]) = dmsg->x;
2580 *((uint16_t *) &msg.xclient.data.b[10]) = dmsg->y;
2581 *((uint32_t *) &msg.xclient.data.b[12]) = dmsg->index_atom;
2582 *((uint32_t *) &msg.xclient.data.b[16]) = dmsg->source_window;
2583
2584 x_ignore_errors_for_next_request (dpyinfo, 0);
2585 XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg);
2586 x_stop_ignoring_errors (dpyinfo);
2587 }
2588
2589 static void
2590 xm_send_top_level_enter_message (struct x_display_info *dpyinfo, Window source,
2591 Window target, xm_top_level_enter_message *dmsg)
2592 {
2593 XEvent msg;
2594
2595 msg.xclient.type = ClientMessage;
2596 msg.xclient.message_type
2597 = dpyinfo->Xatom_MOTIF_DRAG_AND_DROP_MESSAGE;
2598 msg.xclient.format = 8;
2599 msg.xclient.window = target;
2600 msg.xclient.data.b[0] = dmsg->reason;
2601 msg.xclient.data.b[1] = dmsg->byteorder;
2602 *((uint16_t *) &msg.xclient.data.b[2]) = dmsg->zero;
2603 *((uint32_t *) &msg.xclient.data.b[4]) = dmsg->timestamp;
2604 *((uint32_t *) &msg.xclient.data.b[8]) = dmsg->source_window;
2605 *((uint32_t *) &msg.xclient.data.b[12]) = dmsg->index_atom;
2606 msg.xclient.data.b[16] = 0;
2607 msg.xclient.data.b[17] = 0;
2608 msg.xclient.data.b[18] = 0;
2609 msg.xclient.data.b[19] = 0;
2610
2611 x_ignore_errors_for_next_request (dpyinfo, 0);
2612 XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg);
2613 x_stop_ignoring_errors (dpyinfo);
2614 }
2615
2616 static void
2617 xm_send_drag_motion_message (struct x_display_info *dpyinfo, Window source,
2618 Window target, xm_drag_motion_message *dmsg)
2619 {
2620 XEvent msg;
2621
2622 msg.xclient.type = ClientMessage;
2623 msg.xclient.message_type
2624 = dpyinfo->Xatom_MOTIF_DRAG_AND_DROP_MESSAGE;
2625 msg.xclient.format = 8;
2626 msg.xclient.window = target;
2627 msg.xclient.data.b[0] = dmsg->reason;
2628 msg.xclient.data.b[1] = dmsg->byteorder;
2629 *((uint16_t *) &msg.xclient.data.b[2]) = dmsg->side_effects;
2630 *((uint32_t *) &msg.xclient.data.b[4]) = dmsg->timestamp;
2631 *((uint16_t *) &msg.xclient.data.b[8]) = dmsg->x;
2632 *((uint16_t *) &msg.xclient.data.b[10]) = dmsg->y;
2633 msg.xclient.data.b[12] = 0;
2634 msg.xclient.data.b[13] = 0;
2635 msg.xclient.data.b[14] = 0;
2636 msg.xclient.data.b[15] = 0;
2637 msg.xclient.data.b[16] = 0;
2638 msg.xclient.data.b[17] = 0;
2639 msg.xclient.data.b[18] = 0;
2640 msg.xclient.data.b[19] = 0;
2641
2642 x_ignore_errors_for_next_request (dpyinfo, 0);
2643 XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg);
2644 x_stop_ignoring_errors (dpyinfo);
2645 }
2646
2647 static void
2648 xm_send_top_level_leave_message (struct x_display_info *dpyinfo, Window source,
2649 Window target, xm_top_level_leave_message *dmsg)
2650 {
2651 XEvent msg;
2652 xm_drag_motion_message mmsg;
2653
2654
2655
2656
2657
2658
2659
2660
2661 if (x_dnd_fix_motif_leave)
2662 {
2663 mmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
2664 XM_DRAG_REASON_DRAG_MOTION);
2665 mmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
2666 mmsg.side_effects = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
2667 x_dnd_wanted_action),
2668 XM_DROP_SITE_NONE, x_dnd_motif_operations,
2669 XM_DROP_ACTION_DROP_CANCEL);
2670 mmsg.timestamp = dmsg->timestamp;
2671
2672
2673
2674
2675
2676 mmsg.x = X_SHRT_MAX;
2677 mmsg.y = X_SHRT_MAX;
2678
2679 xm_send_drag_motion_message (dpyinfo, source, target, &mmsg);
2680 }
2681
2682 msg.xclient.type = ClientMessage;
2683 msg.xclient.message_type
2684 = dpyinfo->Xatom_MOTIF_DRAG_AND_DROP_MESSAGE;
2685 msg.xclient.format = 8;
2686 msg.xclient.window = target;
2687 msg.xclient.data.b[0] = dmsg->reason;
2688 msg.xclient.data.b[1] = dmsg->byteorder;
2689 *((uint16_t *) &msg.xclient.data.b[2]) = dmsg->zero;
2690 *((uint32_t *) &msg.xclient.data.b[4]) = dmsg->timestamp;
2691 *((uint32_t *) &msg.xclient.data.b[8]) = dmsg->source_window;
2692 msg.xclient.data.b[12] = 0;
2693 msg.xclient.data.b[13] = 0;
2694 msg.xclient.data.b[14] = 0;
2695 msg.xclient.data.b[15] = 0;
2696 msg.xclient.data.b[16] = 0;
2697 msg.xclient.data.b[17] = 0;
2698 msg.xclient.data.b[18] = 0;
2699 msg.xclient.data.b[19] = 0;
2700
2701 x_ignore_errors_for_next_request (dpyinfo, 0);
2702 XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg);
2703 x_stop_ignoring_errors (dpyinfo);
2704 }
2705
2706 static int
2707 xm_read_drop_start_reply (const XEvent *msg, xm_drop_start_reply *reply)
2708 {
2709 const uint8_t *data;
2710
2711 data = (const uint8_t *) &msg->xclient.data.b[0];
2712
2713 if ((XM_DRAG_REASON_ORIGINATOR (data[0])
2714 != XM_DRAG_ORIGINATOR_RECEIVER)
2715 || (XM_DRAG_REASON_CODE (data[0])
2716 != XM_DRAG_REASON_DROP_START))
2717 return 1;
2718
2719 reply->reason = *(data++);
2720 reply->byte_order = *(data++);
2721 reply->side_effects = *(uint16_t *) data;
2722 reply->better_x = *(uint16_t *) (data + 2);
2723 reply->better_y = *(uint16_t *) (data + 4);
2724
2725 if (reply->byte_order != XM_BYTE_ORDER_CUR_FIRST)
2726 {
2727 SWAPCARD16 (reply->side_effects);
2728 SWAPCARD16 (reply->better_x);
2729 SWAPCARD16 (reply->better_y);
2730 }
2731
2732 reply->byte_order = XM_BYTE_ORDER_CUR_FIRST;
2733
2734 return 0;
2735 }
2736
2737 static int
2738 xm_read_drop_start_message (const XEvent *msg,
2739 xm_drop_start_message *dmsg)
2740 {
2741 const uint8_t *data;
2742
2743 data = (const uint8_t *) &msg->xclient.data.b[0];
2744
2745 if ((XM_DRAG_REASON_ORIGINATOR (data[0])
2746 != XM_DRAG_ORIGINATOR_INITIATOR)
2747 || (XM_DRAG_REASON_CODE (data[0])
2748 != XM_DRAG_REASON_DROP_START))
2749 return 1;
2750
2751 dmsg->reason = *(data++);
2752 dmsg->byte_order = *(data++);
2753 dmsg->side_effects = *(uint16_t *) data;
2754 dmsg->timestamp = *(uint32_t *) (data + 2);
2755 dmsg->x = *(uint16_t *) (data + 6);
2756 dmsg->y = *(uint16_t *) (data + 8);
2757 dmsg->index_atom = *(uint32_t *) (data + 10);
2758 dmsg->source_window = *(uint32_t *) (data + 14);
2759
2760 if (dmsg->byte_order != XM_BYTE_ORDER_CUR_FIRST)
2761 {
2762 SWAPCARD16 (dmsg->side_effects);
2763 SWAPCARD32 (dmsg->timestamp);
2764 SWAPCARD16 (dmsg->x);
2765 SWAPCARD16 (dmsg->y);
2766 SWAPCARD32 (dmsg->index_atom);
2767 SWAPCARD32 (dmsg->source_window);
2768 }
2769
2770 dmsg->byte_order = XM_BYTE_ORDER_CUR_FIRST;
2771
2772 return 0;
2773 }
2774
2775 static int
2776 xm_read_drag_receiver_info (struct x_display_info *dpyinfo,
2777 Window wdesc, xm_drag_receiver_info *rec)
2778 {
2779 Atom actual_type;
2780 int rc, actual_format;
2781 unsigned long nitems, bytes_remaining;
2782 unsigned char *tmp_data = NULL;
2783 uint8_t *data;
2784
2785 x_catch_errors (dpyinfo->display);
2786 rc = XGetWindowProperty (dpyinfo->display, wdesc,
2787 dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO,
2788 0, 4, False,
2789 dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO,
2790 &actual_type, &actual_format, &nitems,
2791 &bytes_remaining,
2792 &tmp_data) == Success;
2793
2794 if (x_had_errors_p (dpyinfo->display)
2795 || actual_format != 8 || nitems < 16 || !tmp_data
2796 || actual_type != dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO)
2797 rc = 0;
2798 x_uncatch_errors_after_check ();
2799
2800 if (rc)
2801 {
2802 data = (uint8_t *) tmp_data;
2803
2804 if (data[1] > XM_DRAG_PROTOCOL_VERSION)
2805 return 1;
2806
2807 rec->byteorder = data[0];
2808 rec->protocol = data[1];
2809 rec->protocol_style = data[2];
2810 rec->unspecified0 = data[3];
2811 rec->unspecified1 = *(uint32_t *) &data[4];
2812 rec->unspecified2 = *(uint32_t *) &data[8];
2813 rec->unspecified3 = *(uint32_t *) &data[12];
2814
2815 if (rec->byteorder != XM_BYTE_ORDER_CUR_FIRST)
2816 {
2817 SWAPCARD32 (rec->unspecified1);
2818 SWAPCARD32 (rec->unspecified2);
2819 SWAPCARD32 (rec->unspecified3);
2820 }
2821
2822 rec->byteorder = XM_BYTE_ORDER_CUR_FIRST;
2823 }
2824
2825 if (tmp_data)
2826 XFree (tmp_data);
2827
2828 return !rc;
2829 }
2830
2831 static int
2832 xm_read_drag_motion_message (const XEvent *msg,
2833 xm_drag_motion_message *dmsg)
2834 {
2835 const uint8_t *data;
2836
2837 data = (const uint8_t *) &msg->xclient.data.b[0];
2838
2839 if ((XM_DRAG_REASON_CODE (data[0])
2840 != XM_DRAG_REASON_DRAG_MOTION)
2841 || (XM_DRAG_REASON_ORIGINATOR (data[0])
2842 != XM_DRAG_ORIGINATOR_INITIATOR))
2843 return 1;
2844
2845 dmsg->reason = *(data++);
2846 dmsg->byteorder = *(data++);
2847 dmsg->side_effects = *(uint16_t *) data;
2848 dmsg->timestamp = *(uint32_t *) (data + 2);
2849 dmsg->x = *(uint16_t *) (data + 6);
2850 dmsg->y = *(uint16_t *) (data + 8);
2851
2852 if (dmsg->byteorder != XM_BYTE_ORDER_CUR_FIRST)
2853 {
2854 SWAPCARD16 (dmsg->side_effects);
2855 SWAPCARD32 (dmsg->timestamp);
2856 SWAPCARD16 (dmsg->x);
2857 SWAPCARD16 (dmsg->y);
2858 }
2859
2860 dmsg->byteorder = XM_BYTE_ORDER_CUR_FIRST;
2861
2862 return 0;
2863 }
2864
2865 static int
2866 xm_read_drag_motion_reply (const XEvent *msg, xm_drag_motion_reply *reply)
2867 {
2868 const uint8_t *data;
2869
2870 data = (const uint8_t *) &msg->xclient.data.b[0];
2871
2872 if ((XM_DRAG_REASON_CODE (data[0])
2873 != XM_DRAG_REASON_DRAG_MOTION)
2874 || (XM_DRAG_REASON_ORIGINATOR (data[0])
2875 != XM_DRAG_ORIGINATOR_RECEIVER))
2876 return 1;
2877
2878 reply->reason = *(data++);
2879 reply->byte_order = *(data++);
2880 reply->side_effects = *(uint16_t *) data;
2881 reply->timestamp = *(uint32_t *) (data + 2);
2882 reply->better_x = *(uint16_t *) (data + 6);
2883 reply->better_y = *(uint16_t *) (data + 8);
2884
2885 if (reply->byte_order != XM_BYTE_ORDER_CUR_FIRST)
2886 {
2887 SWAPCARD16 (reply->side_effects);
2888 SWAPCARD32 (reply->timestamp);
2889 SWAPCARD16 (reply->better_x);
2890 SWAPCARD16 (reply->better_y);
2891 }
2892
2893 reply->byte_order = XM_BYTE_ORDER_CUR_FIRST;
2894
2895 return 0;
2896 }
2897
2898 static void
2899 x_dnd_send_xm_leave_for_drop (struct x_display_info *dpyinfo,
2900 struct frame *f, Window wdesc,
2901 Time timestamp)
2902 {
2903 xm_top_level_leave_message lmsg;
2904
2905 lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
2906 XM_DRAG_REASON_TOP_LEVEL_LEAVE);
2907 lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
2908 lmsg.zero = 0;
2909 lmsg.timestamp = timestamp;
2910 lmsg.source_window = FRAME_X_WINDOW (f);
2911
2912 if (x_dnd_motif_setup_p)
2913 xm_send_top_level_leave_message (dpyinfo, FRAME_X_WINDOW (f),
2914 wdesc, &lmsg);
2915 }
2916
2917 static void
2918 x_dnd_free_toplevels (bool display_alive)
2919 {
2920 struct x_client_list_window *last;
2921 struct x_client_list_window *tem = x_dnd_toplevels;
2922 ptrdiff_t n_windows, i, buffer_size;
2923 Window *destroy_windows UNINIT;
2924 unsigned long *prev_masks UNINIT;
2925 specpdl_ref count;
2926 Display *dpy UNINIT;
2927 struct x_display_info *dpyinfo;
2928
2929 if (!x_dnd_toplevels)
2930
2931 return;
2932
2933 if (display_alive)
2934 {
2935 buffer_size = 1024;
2936 destroy_windows = xmalloc (sizeof *destroy_windows
2937 * buffer_size);
2938 prev_masks = xmalloc (sizeof *prev_masks *
2939 buffer_size);
2940 n_windows = 0;
2941 }
2942
2943 block_input ();
2944 while (tem)
2945 {
2946 last = tem;
2947 tem = tem->next;
2948
2949 if (display_alive)
2950 {
2951 if (++n_windows >= buffer_size)
2952 {
2953 buffer_size += 1024;
2954 destroy_windows
2955 = xrealloc (destroy_windows, (sizeof *destroy_windows
2956 * buffer_size));
2957 prev_masks
2958 = xrealloc (prev_masks, (sizeof *prev_masks
2959 * buffer_size));
2960 }
2961
2962 dpy = last->dpy;
2963 prev_masks[n_windows - 1] = last->previous_event_mask;
2964 destroy_windows[n_windows - 1] = last->window;
2965 }
2966
2967 #ifdef HAVE_XSHAPE
2968 if (last->n_input_rects != -1)
2969 xfree (last->input_rects);
2970 if (last->n_bounding_rects != -1)
2971 xfree (last->bounding_rects);
2972 #endif
2973
2974 xfree (last);
2975 }
2976
2977 x_dnd_toplevels = NULL;
2978
2979 if (!display_alive)
2980 {
2981 unblock_input ();
2982 return;
2983 }
2984
2985 count = SPECPDL_INDEX ();
2986 record_unwind_protect_ptr (xfree, destroy_windows);
2987 record_unwind_protect_ptr (xfree, prev_masks);
2988
2989 if (display_alive)
2990 {
2991 dpyinfo = x_display_info_for_display (dpy);
2992
2993 if (n_windows)
2994 {
2995 eassume (dpyinfo);
2996 x_ignore_errors_for_next_request (dpyinfo, 0);
2997
2998 for (i = 0; i < n_windows; ++i)
2999 {
3000 XSelectInput (dpy, destroy_windows[i], prev_masks[i]);
3001 #ifdef HAVE_XSHAPE
3002 XShapeSelectInput (dpy, destroy_windows[i], None);
3003 #endif
3004 }
3005
3006 x_stop_ignoring_errors (dpyinfo);
3007 }
3008 }
3009
3010 unbind_to (count, Qnil);
3011 unblock_input ();
3012 }
3013
3014 static int
3015 x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
3016 {
3017 Atom type;
3018 Window *toplevels;
3019 int format, rc;
3020 unsigned long nitems, bytes_after;
3021 unsigned long i, real_nitems;
3022 unsigned char *data = NULL;
3023 int frame_extents[4];
3024
3025 #ifndef USE_XCB
3026 int dest_x, dest_y;
3027 unsigned long *wmstate;
3028 unsigned long wmstate_items, extent_items;
3029 unsigned char *wmstate_data = NULL, *extent_data = NULL;
3030 XWindowAttributes attrs;
3031 Window child;
3032 xm_drag_receiver_info xm_info;
3033 #else
3034 uint32_t *wmstate, *fextents;
3035 uint8_t *xmdata;
3036 xcb_get_window_attributes_cookie_t *window_attribute_cookies;
3037 xcb_translate_coordinates_cookie_t *translate_coordinate_cookies;
3038 xcb_get_property_cookie_t *get_property_cookies;
3039 xcb_get_property_cookie_t *xm_property_cookies;
3040 xcb_get_property_cookie_t *extent_property_cookies;
3041 xcb_get_geometry_cookie_t *get_geometry_cookies;
3042 xcb_get_window_attributes_reply_t attrs, *attrs_reply;
3043 xcb_translate_coordinates_reply_t *coordinates_reply;
3044 xcb_get_property_reply_t *property_reply;
3045 xcb_get_property_reply_t *xm_property_reply;
3046 xcb_get_property_reply_t *extent_property_reply;
3047 xcb_get_geometry_reply_t *geometry_reply;
3048 xcb_generic_error_t *error;
3049 #endif
3050
3051 #ifdef HAVE_XCB_SHAPE
3052 xcb_shape_get_rectangles_cookie_t *bounding_rect_cookies;
3053 xcb_shape_get_rectangles_reply_t *bounding_rect_reply;
3054 xcb_rectangle_iterator_t bounding_rect_iterator;
3055 #endif
3056
3057 #ifdef HAVE_XCB_SHAPE_INPUT_RECTS
3058 xcb_shape_get_rectangles_cookie_t *input_rect_cookies;
3059 xcb_shape_get_rectangles_reply_t *input_rect_reply;
3060 xcb_rectangle_iterator_t input_rect_iterator;
3061 #endif
3062
3063 struct x_client_list_window *tem;
3064 #if defined HAVE_XSHAPE && !defined HAVE_XCB_SHAPE_INPUT_RECTS
3065 int count, ordering;
3066 XRectangle *rects;
3067 #endif
3068
3069 rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window,
3070 dpyinfo->Xatom_net_client_list_stacking,
3071 0, LONG_MAX, False, XA_WINDOW, &type,
3072 &format, &nitems, &bytes_after, &data);
3073
3074 if (rc != Success)
3075 return 1;
3076
3077 if (format != 32 || type != XA_WINDOW)
3078 {
3079 XFree (data);
3080 return 1;
3081 }
3082
3083 toplevels = (Window *) data;
3084
3085 for (i = 0, real_nitems = 0; i < nitems; ++i)
3086 {
3087
3088
3089 if (!x_tooltip_window_to_frame (dpyinfo, toplevels[i], NULL))
3090 toplevels[real_nitems++] = toplevels[i];
3091 }
3092
3093 nitems = real_nitems;
3094
3095 #ifdef USE_XCB
3096 USE_SAFE_ALLOCA;
3097
3098 window_attribute_cookies
3099 = SAFE_ALLOCA (sizeof *window_attribute_cookies * nitems);
3100 translate_coordinate_cookies
3101 = SAFE_ALLOCA (sizeof *translate_coordinate_cookies * nitems);
3102 get_property_cookies
3103 = SAFE_ALLOCA (sizeof *get_property_cookies * nitems);
3104 xm_property_cookies
3105 = SAFE_ALLOCA (sizeof *xm_property_cookies * nitems);
3106 extent_property_cookies
3107 = SAFE_ALLOCA (sizeof *extent_property_cookies * nitems);
3108 get_geometry_cookies
3109 = SAFE_ALLOCA (sizeof *get_geometry_cookies * nitems);
3110
3111 #ifdef HAVE_XCB_SHAPE
3112 bounding_rect_cookies
3113 = SAFE_ALLOCA (sizeof *bounding_rect_cookies * nitems);
3114 #endif
3115
3116 #ifdef HAVE_XCB_SHAPE_INPUT_RECTS
3117 input_rect_cookies
3118 = SAFE_ALLOCA (sizeof *input_rect_cookies * nitems);
3119 #endif
3120
3121 for (i = 0; i < nitems; ++i)
3122 {
3123 window_attribute_cookies[i]
3124 = xcb_get_window_attributes (dpyinfo->xcb_connection,
3125 (xcb_window_t) toplevels[i]);
3126 translate_coordinate_cookies[i]
3127 = xcb_translate_coordinates (dpyinfo->xcb_connection,
3128 (xcb_window_t) toplevels[i],
3129 (xcb_window_t) dpyinfo->root_window,
3130 0, 0);
3131 get_property_cookies[i]
3132 = xcb_get_property (dpyinfo->xcb_connection, 0, (xcb_window_t) toplevels[i],
3133 (xcb_atom_t) dpyinfo->Xatom_wm_state, 0,
3134 0, 2);
3135 xm_property_cookies[i]
3136 = xcb_get_property (dpyinfo->xcb_connection, 0, (xcb_window_t) toplevels[i],
3137 (xcb_atom_t) dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO,
3138 (xcb_atom_t) dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO,
3139 0, 4);
3140 extent_property_cookies[i]
3141 = xcb_get_property (dpyinfo->xcb_connection, 0,
3142 (xcb_window_t) toplevels[i],
3143 (xcb_atom_t) dpyinfo->Xatom_net_frame_extents,
3144 XA_CARDINAL, 0, 4);
3145 get_geometry_cookies[i]
3146 = xcb_get_geometry (dpyinfo->xcb_connection, (xcb_window_t) toplevels[i]);
3147
3148 #ifdef HAVE_XCB_SHAPE
3149 bounding_rect_cookies[i]
3150 = xcb_shape_get_rectangles (dpyinfo->xcb_connection,
3151 (xcb_window_t) toplevels[i],
3152 XCB_SHAPE_SK_BOUNDING);
3153 #endif
3154
3155 #ifdef HAVE_XCB_SHAPE_INPUT_RECTS
3156 if (dpyinfo->xshape_major > 1
3157 || (dpyinfo->xshape_major == 1
3158 && dpyinfo->xshape_minor >= 1))
3159 input_rect_cookies[i]
3160 = xcb_shape_get_rectangles (dpyinfo->xcb_connection,
3161 (xcb_window_t) toplevels[i],
3162 XCB_SHAPE_SK_INPUT);
3163 #endif
3164 }
3165 #endif
3166
3167
3168
3169 for (i = 0; i < nitems; ++i)
3170 {
3171 frame_extents[0] = 0;
3172 frame_extents[1] = 0;
3173 frame_extents[2] = 0;
3174 frame_extents[3] = 0;
3175
3176 #ifndef USE_XCB
3177 x_catch_errors (dpyinfo->display);
3178 rc = (XGetWindowAttributes (dpyinfo->display,
3179 toplevels[i], &attrs)
3180 && !x_had_errors_p (dpyinfo->display));
3181
3182 if (rc)
3183 rc = (XTranslateCoordinates (dpyinfo->display, toplevels[i],
3184 attrs.root, -attrs.border_width,
3185 -attrs.border_width, &dest_x,
3186 &dest_y, &child)
3187 && !x_had_errors_p (dpyinfo->display));
3188 if (rc)
3189 rc = ((XGetWindowProperty (dpyinfo->display,
3190 toplevels[i],
3191 dpyinfo->Xatom_wm_state,
3192 0, 2, False, AnyPropertyType,
3193 &type, &format, &wmstate_items,
3194 &bytes_after, &wmstate_data)
3195 == Success)
3196 && !x_had_errors_p (dpyinfo->display)
3197 && wmstate_data && wmstate_items == 2 && format == 32);
3198
3199 if (XGetWindowProperty (dpyinfo->display, toplevels[i],
3200 dpyinfo->Xatom_net_frame_extents,
3201 0, 4, False, XA_CARDINAL, &type,
3202 &format, &extent_items, &bytes_after,
3203 &extent_data) == Success
3204 && !x_had_errors_p (dpyinfo->display)
3205 && extent_data && extent_items >= 4 && format == 32)
3206 {
3207 frame_extents[0] = ((unsigned long *) extent_data)[0];
3208 frame_extents[1] = ((unsigned long *) extent_data)[1];
3209 frame_extents[2] = ((unsigned long *) extent_data)[2];
3210 frame_extents[3] = ((unsigned long *) extent_data)[3];
3211 }
3212
3213 if (extent_data)
3214 XFree (extent_data);
3215
3216 x_uncatch_errors ();
3217 #else
3218 rc = true;
3219
3220 attrs_reply
3221 = xcb_get_window_attributes_reply (dpyinfo->xcb_connection,
3222 window_attribute_cookies[i],
3223 &error);
3224
3225 if (!attrs_reply)
3226 {
3227 rc = false;
3228 free (error);
3229 }
3230
3231 coordinates_reply
3232 = xcb_translate_coordinates_reply (dpyinfo->xcb_connection,
3233 translate_coordinate_cookies[i],
3234 &error);
3235
3236 if (!coordinates_reply)
3237 {
3238 rc = false;
3239 free (error);
3240 }
3241
3242 property_reply = xcb_get_property_reply (dpyinfo->xcb_connection,
3243 get_property_cookies[i],
3244 &error);
3245
3246 if (!property_reply)
3247 {
3248 rc = false;
3249 free (error);
3250 }
3251
3252
3253
3254
3255 xm_property_reply = xcb_get_property_reply (dpyinfo->xcb_connection,
3256 xm_property_cookies[i],
3257 &error);
3258
3259 if (!xm_property_reply)
3260 free (error);
3261
3262 extent_property_reply = xcb_get_property_reply (dpyinfo->xcb_connection,
3263 extent_property_cookies[i],
3264 &error);
3265
3266 if (!extent_property_reply)
3267 free (error);
3268 else
3269 {
3270 if (xcb_get_property_value_length (extent_property_reply) == 16
3271 && extent_property_reply->format == 32
3272 && extent_property_reply->type == XA_CARDINAL)
3273 {
3274 fextents = xcb_get_property_value (extent_property_reply);
3275 frame_extents[0] = fextents[0];
3276 frame_extents[1] = fextents[1];
3277 frame_extents[2] = fextents[2];
3278 frame_extents[3] = fextents[3];
3279 }
3280
3281 free (extent_property_reply);
3282 }
3283
3284 if (property_reply
3285 && (xcb_get_property_value_length (property_reply) != 8
3286 || property_reply->format != 32))
3287 rc = false;
3288
3289 geometry_reply = xcb_get_geometry_reply (dpyinfo->xcb_connection,
3290 get_geometry_cookies[i],
3291 &error);
3292
3293 if (!geometry_reply)
3294 {
3295 rc = false;
3296 free (error);
3297 }
3298 #endif
3299
3300 if (rc)
3301 {
3302 #ifdef USE_XCB
3303 wmstate = (uint32_t *) xcb_get_property_value (property_reply);
3304 attrs = *attrs_reply;
3305 #else
3306 wmstate = (unsigned long *) wmstate_data;
3307 #endif
3308
3309 tem = xmalloc (sizeof *tem);
3310 tem->window = toplevels[i];
3311 tem->dpy = dpyinfo->display;
3312 tem->frame_extents_left = frame_extents[0];
3313 tem->frame_extents_right = frame_extents[1];
3314 tem->frame_extents_top = frame_extents[2];
3315 tem->frame_extents_bottom = frame_extents[3];
3316
3317 #ifndef USE_XCB
3318 tem->x = dest_x;
3319 tem->y = dest_y;
3320 tem->width = attrs.width + attrs.border_width;
3321 tem->height = attrs.height + attrs.border_width;
3322 tem->mapped_p = (attrs.map_state != IsUnmapped);
3323 #else
3324 tem->x = (coordinates_reply->dst_x
3325 - geometry_reply->border_width);
3326 tem->y = (coordinates_reply->dst_y
3327 - geometry_reply->border_width);
3328 tem->width = (geometry_reply->width
3329 + geometry_reply->border_width);
3330 tem->height = (geometry_reply->height
3331 + geometry_reply->border_width);
3332 tem->mapped_p = (attrs.map_state != XCB_MAP_STATE_UNMAPPED);
3333 #endif
3334 tem->next = x_dnd_toplevels;
3335 tem->previous_event_mask = attrs.your_event_mask;
3336 tem->wm_state = wmstate[0];
3337 tem->xm_protocol_style = XM_DRAG_STYLE_NONE;
3338
3339 #ifndef USE_XCB
3340 if (!xm_read_drag_receiver_info (dpyinfo, toplevels[i], &xm_info))
3341 tem->xm_protocol_style = xm_info.protocol_style;
3342 #else
3343 if (xm_property_reply
3344 && xm_property_reply->format == 8
3345 && xm_property_reply->type == dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO
3346 && xcb_get_property_value_length (xm_property_reply) >= 4)
3347 {
3348 xmdata = xcb_get_property_value (xm_property_reply);
3349
3350 if (xmdata[1] <= XM_DRAG_PROTOCOL_VERSION)
3351 tem->xm_protocol_style = xmdata[2];
3352 }
3353 #endif
3354
3355 #ifdef HAVE_XSHAPE
3356 #ifndef USE_XCB
3357 tem->border_width = attrs.border_width;
3358 #else
3359 tem->border_width = geometry_reply->border_width;
3360 #endif
3361 tem->n_bounding_rects = -1;
3362 tem->n_input_rects = -1;
3363
3364 if (dpyinfo->xshape_supported_p)
3365 {
3366 x_ignore_errors_for_next_request (dpyinfo, 0);
3367 XShapeSelectInput (dpyinfo->display,
3368 toplevels[i],
3369 ShapeNotifyMask);
3370 x_stop_ignoring_errors (dpyinfo);
3371
3372 #ifndef HAVE_XCB_SHAPE
3373 x_catch_errors (dpyinfo->display);
3374 rects = XShapeGetRectangles (dpyinfo->display,
3375 toplevels[i],
3376 ShapeBounding,
3377 &count, &ordering);
3378 rc = x_had_errors_p (dpyinfo->display);
3379 x_uncatch_errors_after_check ();
3380
3381
3382
3383 if (!rc)
3384 {
3385 tem->n_bounding_rects = count;
3386 tem->bounding_rects
3387 = xmalloc (sizeof *tem->bounding_rects * count);
3388 memcpy (tem->bounding_rects, rects,
3389 sizeof *tem->bounding_rects * count);
3390
3391 XFree (rects);
3392 }
3393 #else
3394 bounding_rect_reply = xcb_shape_get_rectangles_reply (dpyinfo->xcb_connection,
3395 bounding_rect_cookies[i],
3396 &error);
3397
3398 if (bounding_rect_reply)
3399 {
3400 bounding_rect_iterator
3401 = xcb_shape_get_rectangles_rectangles_iterator (bounding_rect_reply);
3402 tem->n_bounding_rects = bounding_rect_iterator.rem + 1;
3403 tem->bounding_rects = xmalloc (tem->n_bounding_rects
3404 * sizeof *tem->bounding_rects);
3405 tem->n_bounding_rects = 0;
3406
3407 for (; bounding_rect_iterator.rem; xcb_rectangle_next (&bounding_rect_iterator))
3408 {
3409 tem->bounding_rects[tem->n_bounding_rects].x
3410 = bounding_rect_iterator.data->x;
3411 tem->bounding_rects[tem->n_bounding_rects].y
3412 = bounding_rect_iterator.data->y;
3413 tem->bounding_rects[tem->n_bounding_rects].width
3414 = bounding_rect_iterator.data->width;
3415 tem->bounding_rects[tem->n_bounding_rects].height
3416 = bounding_rect_iterator.data->height;
3417
3418 tem->n_bounding_rects++;
3419 }
3420
3421 free (bounding_rect_reply);
3422 }
3423 else
3424 free (error);
3425 #endif
3426
3427 #ifdef HAVE_XCB_SHAPE_INPUT_RECTS
3428 if (dpyinfo->xshape_major > 1
3429 || (dpyinfo->xshape_major == 1
3430 && dpyinfo->xshape_minor >= 1))
3431 {
3432 input_rect_reply = xcb_shape_get_rectangles_reply (dpyinfo->xcb_connection,
3433 input_rect_cookies[i],
3434 &error);
3435
3436 if (input_rect_reply)
3437 {
3438 input_rect_iterator
3439 = xcb_shape_get_rectangles_rectangles_iterator (input_rect_reply);
3440 tem->n_input_rects = input_rect_iterator.rem + 1;
3441 tem->input_rects = xmalloc (tem->n_input_rects
3442 * sizeof *tem->input_rects);
3443 tem->n_input_rects = 0;
3444
3445 for (; input_rect_iterator.rem; xcb_rectangle_next (&input_rect_iterator))
3446 {
3447 tem->input_rects[tem->n_input_rects].x
3448 = input_rect_iterator.data->x;
3449 tem->input_rects[tem->n_input_rects].y
3450 = input_rect_iterator.data->y;
3451 tem->input_rects[tem->n_input_rects].width
3452 = input_rect_iterator.data->width;
3453 tem->input_rects[tem->n_input_rects].height
3454 = input_rect_iterator.data->height;
3455
3456 tem->n_input_rects++;
3457 }
3458
3459 free (input_rect_reply);
3460 }
3461 else
3462 free (error);
3463 }
3464 #else
3465 #ifdef ShapeInput
3466 if (dpyinfo->xshape_major > 1
3467 || (dpyinfo->xshape_major == 1
3468 && dpyinfo->xshape_minor >= 1))
3469 {
3470 x_catch_errors (dpyinfo->display);
3471 rects = XShapeGetRectangles (dpyinfo->display,
3472 toplevels[i], ShapeInput,
3473 &count, &ordering);
3474 rc = x_had_errors_p (dpyinfo->display);
3475 x_uncatch_errors_after_check ();
3476
3477
3478
3479 if (!rc)
3480 {
3481 tem->n_input_rects = count;
3482 tem->input_rects
3483 = xmalloc (sizeof *tem->input_rects * count);
3484 memcpy (tem->input_rects, rects,
3485 sizeof *tem->input_rects * count);
3486
3487 XFree (rects);
3488 }
3489 }
3490 #endif
3491 #endif
3492 }
3493
3494
3495
3496
3497 if (tem->n_input_rects != -1
3498 && tem->n_bounding_rects == tem->n_input_rects
3499 && !memcmp (tem->bounding_rects, tem->input_rects,
3500 tem->n_input_rects * sizeof *tem->input_rects))
3501 {
3502 xfree (tem->input_rects);
3503 tem->n_input_rects = -1;
3504 }
3505
3506
3507
3508
3509 if (tem->n_input_rects == -1
3510 && tem->n_bounding_rects == 1
3511 #ifdef USE_XCB
3512 && tem->bounding_rects[0].width == (geometry_reply->width
3513 + geometry_reply->border_width)
3514 && tem->bounding_rects[0].height == (geometry_reply->height
3515 + geometry_reply->border_width)
3516 && tem->bounding_rects[0].x == -geometry_reply->border_width
3517 && tem->bounding_rects[0].y == -geometry_reply->border_width
3518 #else
3519 && tem->bounding_rects[0].width == attrs.width + attrs.border_width
3520 && tem->bounding_rects[0].height == attrs.height + attrs.border_width
3521 && tem->bounding_rects[0].x == -attrs.border_width
3522 && tem->bounding_rects[0].y == -attrs.border_width
3523 #endif
3524 )
3525 {
3526 xfree (tem->bounding_rects);
3527 tem->n_bounding_rects = -1;
3528 }
3529 #endif
3530
3531 x_ignore_errors_for_next_request (dpyinfo, 0);
3532 XSelectInput (dpyinfo->display, toplevels[i],
3533 (attrs.your_event_mask
3534 | StructureNotifyMask
3535 | PropertyChangeMask));
3536 x_stop_ignoring_errors (dpyinfo);
3537
3538 x_dnd_toplevels = tem;
3539 }
3540 else
3541 {
3542 #ifdef HAVE_XCB_SHAPE
3543 if (dpyinfo->xshape_supported_p)
3544 {
3545 bounding_rect_reply = xcb_shape_get_rectangles_reply (dpyinfo->xcb_connection,
3546 bounding_rect_cookies[i],
3547 &error);
3548
3549 if (bounding_rect_reply)
3550 free (bounding_rect_reply);
3551 else
3552 free (error);
3553 }
3554 #endif
3555
3556 #ifdef HAVE_XCB_SHAPE_INPUT_RECTS
3557 if (dpyinfo->xshape_supported_p
3558 && (dpyinfo->xshape_major > 1
3559 || (dpyinfo->xshape_major == 1
3560 && dpyinfo->xshape_minor >= 1)))
3561 {
3562 input_rect_reply = xcb_shape_get_rectangles_reply (dpyinfo->xcb_connection,
3563 input_rect_cookies[i],
3564 &error);
3565
3566 if (input_rect_reply)
3567 free (input_rect_reply);
3568 else
3569 free (error);
3570 }
3571 #endif
3572 }
3573
3574 #ifdef USE_XCB
3575 if (attrs_reply)
3576 free (attrs_reply);
3577
3578 if (coordinates_reply)
3579 free (coordinates_reply);
3580
3581 if (property_reply)
3582 free (property_reply);
3583
3584 if (xm_property_reply)
3585 free (xm_property_reply);
3586
3587 if (geometry_reply)
3588 free (geometry_reply);
3589 #endif
3590
3591 #ifndef USE_XCB
3592 if (wmstate_data)
3593 {
3594 XFree (wmstate_data);
3595 wmstate_data = NULL;
3596 }
3597 #endif
3598 }
3599
3600 #ifdef USE_XCB
3601 SAFE_FREE ();
3602 #endif
3603
3604 if (data)
3605 XFree (data);
3606
3607 return 0;
3608 }
3609
3610 static _Noreturn int
3611 x_dnd_io_error_handler (Display *display)
3612 {
3613 #ifdef USE_GTK
3614 emacs_abort ();
3615 #else
3616 siglongjmp (x_dnd_disconnect_handler, 1);
3617 #endif
3618 }
3619
3620 #define X_DND_SUPPORTED_VERSION 5
3621
3622 static int x_dnd_get_window_proto (struct x_display_info *, Window);
3623 static Window x_dnd_get_window_proxy (struct x_display_info *, Window);
3624 static void x_dnd_update_state (struct x_display_info *, Time);
3625
3626 #ifdef USE_XCB
3627 static void
3628 x_dnd_get_proxy_proto (struct x_display_info *dpyinfo, Window wdesc,
3629 Window *proxy_out, int *proto_out)
3630 {
3631 xcb_get_property_cookie_t xdnd_proto_cookie;
3632 xcb_get_property_cookie_t xdnd_proxy_cookie;
3633 xcb_get_property_reply_t *reply;
3634 xcb_generic_error_t *error;
3635
3636 if (proxy_out)
3637 *proxy_out = None;
3638
3639 if (proto_out)
3640 *proto_out = -1;
3641
3642 if (proxy_out)
3643 xdnd_proxy_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
3644 (xcb_window_t) wdesc,
3645 (xcb_atom_t) dpyinfo->Xatom_XdndProxy,
3646 XA_WINDOW, 0, 1);
3647
3648 if (proto_out)
3649 xdnd_proto_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
3650 (xcb_window_t) wdesc,
3651 (xcb_atom_t) dpyinfo->Xatom_XdndAware,
3652 XA_ATOM, 0, 1);
3653
3654 if (proxy_out)
3655 {
3656 reply = xcb_get_property_reply (dpyinfo->xcb_connection,
3657 xdnd_proxy_cookie, &error);
3658
3659 if (!reply)
3660 free (error);
3661 else
3662 {
3663 if (reply->format == 32
3664 && reply->type == XA_WINDOW
3665 && (xcb_get_property_value_length (reply) >= 4))
3666 *proxy_out = *(xcb_window_t *) xcb_get_property_value (reply);
3667
3668 free (reply);
3669 }
3670 }
3671
3672 if (proto_out)
3673 {
3674 reply = xcb_get_property_reply (dpyinfo->xcb_connection,
3675 xdnd_proto_cookie, &error);
3676
3677 if (!reply)
3678 free (error);
3679 else
3680 {
3681 if (reply->format == 32
3682 && reply->type == XA_ATOM
3683 && (xcb_get_property_value_length (reply) >= 4))
3684 *proto_out = (int) *(xcb_atom_t *) xcb_get_property_value (reply);
3685
3686 free (reply);
3687 }
3688 }
3689 }
3690 #endif
3691
3692 #ifdef HAVE_XSHAPE
3693 static bool
3694 x_dnd_get_target_window_2 (XRectangle *rects, int nrects,
3695 int x, int y)
3696 {
3697 int i;
3698 XRectangle *tem;
3699
3700 for (i = 0; i < nrects; ++i)
3701 {
3702 tem = &rects[i];
3703
3704 if (x >= tem->x && y >= tem->y
3705 && x < tem->x + tem->width
3706 && y < tem->y + tem->height)
3707 return true;
3708 }
3709
3710 return false;
3711 }
3712 #endif
3713
3714 static Window
3715 x_dnd_get_target_window_1 (struct x_display_info *dpyinfo,
3716 int root_x, int root_y, int *motif_out,
3717 bool *extents_p)
3718 {
3719 struct x_client_list_window *tem, *chosen = NULL;
3720
3721
3722
3723
3724 *motif_out = XM_DRAG_STYLE_NONE;
3725
3726 for (tem = x_dnd_toplevels; tem; tem = tem->next)
3727 {
3728 if (!tem->mapped_p || tem->wm_state != NormalState)
3729 continue;
3730
3731
3732
3733
3734 *extents_p = true;
3735 if (root_x > tem->x - tem->frame_extents_left
3736 && root_x < tem->x
3737 && root_y > tem->y - tem->frame_extents_top
3738 && root_y < (tem->y + tem->height - 1
3739 + tem->frame_extents_bottom))
3740 return None;
3741
3742 if (root_x > tem->x + tem->width
3743 && root_x < (tem->x + tem->width - 1
3744 + tem->frame_extents_right)
3745 && root_y > tem->y - tem->frame_extents_top
3746 && root_y < (tem->y + tem->height - 1
3747 + tem->frame_extents_bottom))
3748 return None;
3749
3750 if (root_y > tem->y - tem->frame_extents_top
3751 && root_y < tem->y
3752 && root_x > tem->x - tem->frame_extents_left
3753 && root_x < (tem->x + tem->width - 1
3754 + tem->frame_extents_right))
3755 return None;
3756
3757 if (root_y > tem->y + tem->height
3758 && root_y < (tem->y + tem->height - 1
3759 + tem->frame_extents_bottom)
3760 && root_x >= tem->x - tem->frame_extents_left
3761 && root_x < (tem->x + tem->width - 1
3762 + tem->frame_extents_right))
3763 return None;
3764 *extents_p = false;
3765
3766 if (root_x >= tem->x && root_y >= tem->y
3767 && root_x < tem->x + tem->width
3768 && root_y < tem->y + tem->height)
3769 {
3770 #ifdef HAVE_XSHAPE
3771 if (tem->n_bounding_rects == -1)
3772 #endif
3773 {
3774 chosen = tem;
3775 break;
3776 }
3777
3778 #ifdef HAVE_XSHAPE
3779 if (x_dnd_get_target_window_2 (tem->bounding_rects,
3780 tem->n_bounding_rects,
3781 tem->border_width + root_x - tem->x,
3782 tem->border_width + root_y - tem->y))
3783 {
3784 if (tem->n_input_rects == -1
3785 || x_dnd_get_target_window_2 (tem->input_rects,
3786 tem->n_input_rects,
3787 tem->border_width + root_x - tem->x,
3788 tem->border_width + root_y - tem->y))
3789 {
3790 chosen = tem;
3791 break;
3792 }
3793 }
3794 #endif
3795 }
3796 }
3797
3798 if (chosen)
3799 {
3800 *motif_out = (x_dnd_disable_motif_protocol
3801 ? XM_DRAG_STYLE_NONE
3802 : chosen->xm_protocol_style);
3803 return chosen->window;
3804 }
3805 else
3806 *motif_out = XM_DRAG_STYLE_NONE;
3807
3808 return None;
3809 }
3810
3811 static int
3812 x_dnd_get_wm_state_and_proto (struct x_display_info *dpyinfo,
3813 Window window, int *wmstate_out,
3814 int *proto_out, int *motif_out,
3815 Window *proxy_out)
3816 {
3817 #ifndef USE_XCB
3818 Atom type;
3819 int format;
3820 unsigned long nitems, bytes_after;
3821 unsigned char *data = NULL;
3822 xm_drag_receiver_info xm_info;
3823 #else
3824 xcb_get_property_cookie_t wmstate_cookie;
3825 xcb_get_property_cookie_t xdnd_proto_cookie;
3826 xcb_get_property_cookie_t xdnd_proxy_cookie;
3827 xcb_get_property_cookie_t xm_style_cookie;
3828 xcb_get_property_reply_t *reply;
3829 xcb_generic_error_t *error;
3830 uint8_t *xmdata;
3831 #endif
3832 int rc;
3833
3834 #ifndef USE_XCB
3835 x_catch_errors (dpyinfo->display);
3836 rc = ((XGetWindowProperty (dpyinfo->display, window,
3837 dpyinfo->Xatom_wm_state,
3838 0, 2, False, AnyPropertyType,
3839 &type, &format, &nitems,
3840 &bytes_after, &data)
3841 == Success)
3842 && !x_had_errors_p (dpyinfo->display)
3843 && data && nitems == 2 && format == 32);
3844 x_uncatch_errors ();
3845
3846 if (rc)
3847 *wmstate_out = *(unsigned long *) data;
3848
3849 *proto_out = x_dnd_get_window_proto (dpyinfo, window);
3850
3851 if (!xm_read_drag_receiver_info (dpyinfo, window, &xm_info))
3852 *motif_out = xm_info.protocol_style;
3853 else
3854 *motif_out = XM_DRAG_STYLE_NONE;
3855
3856 *proxy_out = x_dnd_get_window_proxy (dpyinfo, window);
3857
3858 if (data)
3859 XFree (data);
3860 #else
3861 rc = true;
3862
3863 wmstate_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
3864 (xcb_window_t) window,
3865 (xcb_atom_t) dpyinfo->Xatom_wm_state,
3866 0, 0, 2);
3867 xdnd_proto_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
3868 (xcb_window_t) window,
3869 (xcb_atom_t) dpyinfo->Xatom_XdndAware,
3870 XA_ATOM, 0, 1);
3871 xdnd_proxy_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
3872 (xcb_window_t) window,
3873 (xcb_atom_t) dpyinfo->Xatom_XdndProxy,
3874 XA_WINDOW, 0, 1);
3875 xm_style_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
3876 (xcb_window_t) window,
3877 (xcb_atom_t) dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO,
3878 (xcb_atom_t) dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO,
3879 0, 4);
3880
3881 reply = xcb_get_property_reply (dpyinfo->xcb_connection,
3882 wmstate_cookie, &error);
3883
3884 if (!reply)
3885 free (error), rc = false;
3886 else
3887 {
3888 if (reply->format != 32
3889 || xcb_get_property_value_length (reply) != 8)
3890 rc = false;
3891 else
3892 *wmstate_out = *(uint32_t *) xcb_get_property_value (reply);
3893
3894 free (reply);
3895 }
3896
3897 reply = xcb_get_property_reply (dpyinfo->xcb_connection,
3898 xdnd_proto_cookie, &error);
3899
3900 *proto_out = -1;
3901 if (!reply)
3902 free (error);
3903 else
3904 {
3905 if (reply->format == 32
3906 && xcb_get_property_value_length (reply) >= 4)
3907 *proto_out = *(uint32_t *) xcb_get_property_value (reply);
3908
3909 free (reply);
3910 }
3911
3912 *proxy_out = None;
3913 reply = xcb_get_property_reply (dpyinfo->xcb_connection,
3914 xdnd_proxy_cookie, &error);
3915
3916 if (!reply)
3917 free (error);
3918 else
3919 {
3920 if (reply->format == 32
3921 && reply->type == XA_WINDOW
3922 && (xcb_get_property_value_length (reply) >= 4))
3923 *proxy_out = *(xcb_window_t *) xcb_get_property_value (reply);
3924
3925 free (reply);
3926 }
3927
3928 *motif_out = XM_DRAG_STYLE_NONE;
3929
3930 reply = xcb_get_property_reply (dpyinfo->xcb_connection,
3931 xm_style_cookie, &error);
3932
3933 if (!reply)
3934 free (error);
3935 else
3936 {
3937 if (reply->format == 8
3938 && reply->type == dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO
3939 && xcb_get_property_value_length (reply) >= 4)
3940 {
3941 xmdata = xcb_get_property_value (reply);
3942 *motif_out = xmdata[2];
3943 }
3944
3945 free (reply);
3946 }
3947 #endif
3948
3949 return rc;
3950 }
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976 void
3977 x_dnd_do_unsupported_drop (struct x_display_info *dpyinfo,
3978 Lisp_Object frame, Lisp_Object value,
3979 Lisp_Object targets, Window target_window,
3980 int root_x, int root_y, Time before)
3981 {
3982 XEvent event;
3983 int dest_x, dest_y;
3984 Window child_return, child, owner;
3985 Lisp_Object current_value;
3986 struct frame *f;
3987
3988 f = decode_window_system_frame (frame);
3989
3990 if (NILP (value))
3991 return;
3992
3993 if (!x_dnd_use_unsupported_drop)
3994 return;
3995
3996 event.xbutton.serial = 0;
3997 event.xbutton.send_event = True;
3998 event.xbutton.display = dpyinfo->display;
3999 event.xbutton.root = dpyinfo->root_window;
4000 event.xbutton.x_root = root_x;
4001 event.xbutton.y_root = root_y;
4002
4003 x_catch_errors (dpyinfo->display);
4004
4005 child = dpyinfo->root_window;
4006 dest_x = root_x;
4007 dest_y = root_y;
4008
4009 while (XTranslateCoordinates (dpyinfo->display, dpyinfo->root_window,
4010 child, root_x, root_y, &dest_x, &dest_y,
4011 &child_return)
4012 && child_return != None)
4013 child = child_return;
4014
4015 x_uncatch_errors ();
4016
4017 if (!CONSP (value))
4018 return;
4019
4020 current_value = assq_no_quit (QPRIMARY,
4021 dpyinfo->terminal->Vselection_alist);
4022
4023 if (!NILP (current_value))
4024 current_value = XCAR (XCDR (current_value));
4025
4026 x_own_selection (QPRIMARY, current_value, frame,
4027 XCAR (XCDR (value)), before);
4028
4029 owner = XGetSelectionOwner (dpyinfo->display, XA_PRIMARY);
4030
4031
4032
4033
4034 if (owner != FRAME_X_WINDOW (f))
4035 return;
4036
4037
4038
4039
4040
4041 Vdeactivate_mark = Qdont_save;
4042
4043 event.xbutton.window = child;
4044 event.xbutton.subwindow = None;
4045 event.xbutton.x = dest_x;
4046 event.xbutton.y = dest_y;
4047 event.xbutton.state = 0;
4048 event.xbutton.button = 2;
4049 event.xbutton.same_screen = True;
4050
4051 dpyinfo->pending_dnd_time = before;
4052
4053 event.xbutton.type = ButtonPress;
4054 event.xbutton.time = before + 1;
4055
4056 x_ignore_errors_for_next_request (dpyinfo, 0);
4057 XSendEvent (dpyinfo->display, child,
4058 True, ButtonPressMask, &event);
4059
4060 event.xbutton.type = ButtonRelease;
4061 event.xbutton.time = before + 2;
4062
4063 XSendEvent (dpyinfo->display, child,
4064 True, ButtonReleaseMask, &event);
4065 x_stop_ignoring_errors (dpyinfo);
4066
4067 x_dnd_action_symbol = QXdndActionPrivate;
4068
4069 return;
4070 }
4071
4072 static void
4073 x_dnd_send_unsupported_drop (struct x_display_info *dpyinfo, Window target_window,
4074 int root_x, int root_y, Time before)
4075 {
4076 Lisp_Object targets, arg;
4077 int i;
4078 char **atom_names, *name;
4079
4080 targets = Qnil;
4081 atom_names = alloca (sizeof *atom_names * x_dnd_n_targets);
4082
4083 if (!XGetAtomNames (dpyinfo->display, x_dnd_targets,
4084 x_dnd_n_targets, atom_names))
4085 return;
4086
4087 for (i = x_dnd_n_targets; i > 0; --i)
4088 {
4089 targets = Fcons (build_string (atom_names[i - 1]),
4090 targets);
4091 XFree (atom_names[i - 1]);
4092 }
4093
4094 name = x_get_atom_name (dpyinfo, x_dnd_wanted_action,
4095 NULL);
4096
4097 if (name)
4098 {
4099 arg = intern (name);
4100 xfree (name);
4101 }
4102 else
4103 arg = Qnil;
4104
4105 x_dnd_run_unsupported_drop_function = true;
4106 x_dnd_unsupported_drop_time = before;
4107 x_dnd_unsupported_drop_window = target_window;
4108 x_dnd_unsupported_drop_data
4109 = listn (5, assq_no_quit (QXdndSelection,
4110 dpyinfo->terminal->Vselection_alist),
4111 targets, arg, make_fixnum (root_x),
4112 make_fixnum (root_y));
4113
4114 x_dnd_waiting_for_finish = true;
4115 x_dnd_finish_display = dpyinfo->display;
4116 }
4117
4118 static Window
4119 x_dnd_fill_empty_target (int *proto_out, int *motif_out,
4120 Window *toplevel_out, bool *was_frame)
4121 {
4122 *proto_out = -1;
4123 *motif_out = XM_DRAG_STYLE_NONE;
4124 *toplevel_out = None;
4125 *was_frame = false;
4126
4127 return None;
4128 }
4129
4130 static Window
4131 x_dnd_get_target_window (struct x_display_info *dpyinfo,
4132 int root_x, int root_y, int *proto_out,
4133 int *motif_out, Window *toplevel_out,
4134 bool *was_frame)
4135 {
4136 Window child_return, child, proxy;
4137 int dest_x_return, dest_y_return, rc, proto, motif;
4138 int parent_x, parent_y;
4139 bool extents_p;
4140 #if defined HAVE_XCOMPOSITE && (XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR > 2)
4141 Window overlay_window;
4142 XWindowAttributes attrs;
4143 #endif
4144 int wmstate;
4145 struct frame *tooltip, *f;
4146 bool unrelated;
4147
4148 child_return = dpyinfo->root_window;
4149 dest_x_return = root_x;
4150 dest_y_return = root_y;
4151
4152 proto = -1;
4153 *motif_out = XM_DRAG_STYLE_NONE;
4154 *toplevel_out = None;
4155 *was_frame = false;
4156
4157 if (x_dnd_use_toplevels)
4158 {
4159 extents_p = false;
4160 child = x_dnd_get_target_window_1 (dpyinfo, root_x,
4161 root_y, motif_out,
4162 &extents_p);
4163
4164 if (!x_dnd_allow_current_frame
4165 && FRAME_X_WINDOW (x_dnd_frame) == child)
4166 *motif_out = XM_DRAG_STYLE_NONE;
4167
4168 f = x_top_window_to_frame (dpyinfo, child);
4169
4170 *toplevel_out = child;
4171
4172 if (child != None)
4173 {
4174 if (f)
4175 {
4176 *was_frame = true;
4177 *proto_out = -1;
4178 *motif_out = XM_DRAG_STYLE_NONE;
4179
4180 return child;
4181 }
4182
4183 #ifndef USE_XCB
4184 proxy = x_dnd_get_window_proxy (dpyinfo, child);
4185 #else
4186 x_dnd_get_proxy_proto (dpyinfo, child, &proxy, proto_out);
4187 #endif
4188
4189 if (proxy != None)
4190 {
4191 proto = x_dnd_get_window_proto (dpyinfo, proxy);
4192
4193 if (proto != -1)
4194 {
4195 *proto_out = proto;
4196 return proxy;
4197 }
4198 }
4199
4200 #ifndef USE_XCB
4201 *proto_out = x_dnd_get_window_proto (dpyinfo, child);
4202 #endif
4203 return child;
4204 }
4205
4206 if (extents_p)
4207 {
4208 *proto_out = -1;
4209 *motif_out = XM_DRAG_STYLE_NONE;
4210 *toplevel_out = None;
4211
4212 return None;
4213 }
4214
4215
4216 #if defined HAVE_XCOMPOSITE && (XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR > 2)
4217 if (dpyinfo->composite_supported_p
4218 && (dpyinfo->composite_major > 0
4219 || dpyinfo->composite_minor > 2))
4220 {
4221 if (XGetSelectionOwner (dpyinfo->display,
4222 dpyinfo->Xatom_NET_WM_CM_Sn) != None)
4223 {
4224 x_catch_errors (dpyinfo->display);
4225 XGrabServer (dpyinfo->display);
4226 overlay_window = XCompositeGetOverlayWindow (dpyinfo->display,
4227 dpyinfo->root_window);
4228 XCompositeReleaseOverlayWindow (dpyinfo->display,
4229 dpyinfo->root_window);
4230 XUngrabServer (dpyinfo->display);
4231
4232 if (!x_had_errors_p (dpyinfo->display))
4233 {
4234 XGetWindowAttributes (dpyinfo->display, overlay_window, &attrs);
4235
4236 if (attrs.map_state == IsViewable)
4237 {
4238 proxy = x_dnd_get_window_proxy (dpyinfo, overlay_window);
4239
4240 if (proxy != None)
4241 {
4242 proto = x_dnd_get_window_proto (dpyinfo, proxy);
4243
4244 if (proto != -1)
4245 {
4246 *proto_out = proto;
4247 *toplevel_out = overlay_window;
4248 x_uncatch_errors_after_check ();
4249
4250 return proxy;
4251 }
4252 }
4253 }
4254 }
4255 x_uncatch_errors_after_check ();
4256 }
4257 }
4258 #endif
4259
4260
4261
4262 proxy = x_dnd_get_window_proxy (dpyinfo, dpyinfo->root_window);
4263
4264 if (proxy != None)
4265 {
4266 proto = x_dnd_get_window_proto (dpyinfo, dpyinfo->root_window);
4267
4268 if (proto != -1)
4269 {
4270 *toplevel_out = dpyinfo->root_window;
4271 *proto_out = proto;
4272 return proxy;
4273 }
4274 }
4275
4276
4277
4278 *proto_out = -1;
4279 *toplevel_out = dpyinfo->root_window;
4280 return None;
4281 }
4282
4283
4284 child = dpyinfo->root_window;
4285
4286 while (child_return != None)
4287 {
4288 child = child_return;
4289 parent_x = dest_x_return;
4290 parent_y = dest_y_return;
4291
4292 x_catch_errors (dpyinfo->display);
4293 rc = XTranslateCoordinates (dpyinfo->display, dpyinfo->root_window,
4294 child_return, root_x, root_y, &dest_x_return,
4295 &dest_y_return, &child_return);
4296
4297 if (x_had_errors_p (dpyinfo->display) || !rc)
4298 {
4299 x_uncatch_errors_after_check ();
4300 break;
4301 }
4302
4303 if (child_return)
4304 {
4305
4306
4307
4308 tooltip = x_tooltip_window_to_frame (dpyinfo, child_return,
4309 &unrelated);
4310
4311 if (tooltip || unrelated)
4312 child_return = x_get_window_below (dpyinfo->display, child_return,
4313 parent_x, parent_y, &dest_x_return,
4314 &dest_y_return);
4315
4316 if (!child_return)
4317 {
4318 x_uncatch_errors ();
4319 break;
4320 }
4321
4322 f = x_top_window_to_frame (dpyinfo, child_return);
4323
4324 if (f)
4325 {
4326 *proto_out = -1;
4327 *motif_out = XM_DRAG_STYLE_NONE;
4328 *toplevel_out = child_return;
4329 *was_frame = true;
4330
4331 return child_return;
4332 }
4333
4334 if (x_dnd_get_wm_state_and_proto (dpyinfo, child_return,
4335 &wmstate, &proto, &motif,
4336 &proxy)
4337
4338
4339 || proto != -1 || motif != XM_DRAG_STYLE_NONE)
4340 {
4341 *proto_out = proto;
4342 *motif_out = (x_dnd_disable_motif_protocol
4343 ? XM_DRAG_STYLE_NONE : motif);
4344 *toplevel_out = child_return;
4345 x_uncatch_errors ();
4346
4347 return child_return;
4348 }
4349
4350 if (proxy != None)
4351 {
4352 proto = x_dnd_get_window_proto (dpyinfo, proxy);
4353
4354 if (proto != -1)
4355 {
4356 *proto_out = proto;
4357 *toplevel_out = child_return;
4358
4359 x_uncatch_errors ();
4360 return proxy;
4361 }
4362 }
4363 }
4364
4365 x_uncatch_errors ();
4366 }
4367
4368 #if defined HAVE_XCOMPOSITE && (XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR > 2)
4369 if (child != dpyinfo->root_window)
4370 {
4371 #endif
4372 if (child != None)
4373 {
4374 proxy = x_dnd_get_window_proxy (dpyinfo, child);
4375
4376 if (proxy)
4377 {
4378 proto = x_dnd_get_window_proto (dpyinfo, proxy);
4379
4380 if (proto != -1)
4381 {
4382 *proto_out = proto;
4383 *toplevel_out = child;
4384 return proxy;
4385 }
4386 }
4387 }
4388
4389 *proto_out = x_dnd_get_window_proto (dpyinfo, child);
4390 return child;
4391 #if defined HAVE_XCOMPOSITE && (XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR > 2)
4392 }
4393 else if (dpyinfo->composite_supported_p
4394 && (dpyinfo->composite_major > 0
4395 || dpyinfo->composite_minor > 2))
4396 {
4397
4398 if (XGetSelectionOwner (dpyinfo->display,
4399 dpyinfo->Xatom_NET_WM_CM_Sn) != None)
4400 {
4401 x_catch_errors (dpyinfo->display);
4402 XGrabServer (dpyinfo->display);
4403 overlay_window = XCompositeGetOverlayWindow (dpyinfo->display,
4404 dpyinfo->root_window);
4405 XCompositeReleaseOverlayWindow (dpyinfo->display,
4406 dpyinfo->root_window);
4407 XUngrabServer (dpyinfo->display);
4408
4409 if (!x_had_errors_p (dpyinfo->display))
4410 {
4411 XGetWindowAttributes (dpyinfo->display, overlay_window, &attrs);
4412
4413 if (attrs.map_state == IsViewable)
4414 {
4415 proxy = x_dnd_get_window_proxy (dpyinfo, overlay_window);
4416
4417 if (proxy != None)
4418 {
4419 proto = x_dnd_get_window_proto (dpyinfo, proxy);
4420
4421 if (proto != -1)
4422 {
4423 *proto_out = proto;
4424 *toplevel_out = overlay_window;
4425 x_uncatch_errors_after_check ();
4426
4427 return proxy;
4428 }
4429 }
4430 }
4431 }
4432 x_uncatch_errors_after_check ();
4433 }
4434 }
4435
4436 if (child != None)
4437 {
4438 proxy = x_dnd_get_window_proxy (dpyinfo, child);
4439
4440 if (proxy)
4441 {
4442 proto = x_dnd_get_window_proto (dpyinfo, proxy);
4443
4444 if (proto != -1)
4445 {
4446 *toplevel_out = child;
4447 *proto_out = proto;
4448 return proxy;
4449 }
4450 }
4451 }
4452
4453 *proto_out = x_dnd_get_window_proto (dpyinfo, child);
4454 *toplevel_out = child;
4455 return child;
4456 #endif
4457 }
4458
4459 static Window
4460 x_dnd_get_window_proxy (struct x_display_info *dpyinfo, Window wdesc)
4461 {
4462 int rc, actual_format;
4463 unsigned long actual_size, bytes_remaining;
4464 unsigned char *tmp_data = NULL;
4465 XWindowAttributes attrs;
4466 Atom actual_type;
4467 Window proxy;
4468
4469 proxy = None;
4470 x_catch_errors (dpyinfo->display);
4471 rc = XGetWindowProperty (dpyinfo->display, wdesc,
4472 dpyinfo->Xatom_XdndProxy,
4473 0, 1, False, XA_WINDOW,
4474 &actual_type, &actual_format,
4475 &actual_size, &bytes_remaining,
4476 &tmp_data);
4477
4478 if (!x_had_errors_p (dpyinfo->display)
4479 && rc == Success
4480 && tmp_data
4481 && actual_type == XA_WINDOW
4482 && actual_format == 32
4483 && actual_size == 1)
4484 {
4485 proxy = *(Window *) tmp_data;
4486
4487
4488 XGetWindowAttributes (dpyinfo->display, proxy, &attrs);
4489
4490 if (x_had_errors_p (dpyinfo->display))
4491 proxy = None;
4492 }
4493
4494 if (tmp_data)
4495 XFree (tmp_data);
4496 x_uncatch_errors_after_check ();
4497
4498 return proxy;
4499 }
4500
4501 static int
4502 x_dnd_get_window_proto (struct x_display_info *dpyinfo, Window wdesc)
4503 {
4504 Atom actual, value;
4505 unsigned char *tmp_data = NULL;
4506 int rc, format;
4507 unsigned long n, left;
4508 bool had_errors;
4509
4510 if (wdesc == None || (!x_dnd_allow_current_frame
4511 && wdesc == FRAME_OUTER_WINDOW (x_dnd_frame)))
4512 return -1;
4513
4514 x_catch_errors (dpyinfo->display);
4515 rc = XGetWindowProperty (dpyinfo->display, wdesc, dpyinfo->Xatom_XdndAware,
4516 0, 1, False, XA_ATOM, &actual, &format, &n, &left,
4517 &tmp_data);
4518 had_errors = x_had_errors_p (dpyinfo->display);
4519 x_uncatch_errors_after_check ();
4520
4521 if (had_errors || rc != Success || actual != XA_ATOM || format != 32 || n < 1
4522 || !tmp_data)
4523 {
4524 if (tmp_data)
4525 XFree (tmp_data);
4526 return -1;
4527 }
4528
4529 value = (int) *(Atom *) tmp_data;
4530 XFree (tmp_data);
4531
4532 return min (X_DND_SUPPORTED_VERSION, (int) value);
4533 }
4534
4535 static void
4536 x_dnd_send_enter (struct frame *f, Window target, Window toplevel,
4537 int supported)
4538 {
4539 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
4540 int i;
4541 XEvent msg;
4542
4543 msg.xclient.type = ClientMessage;
4544 msg.xclient.message_type = dpyinfo->Xatom_XdndEnter;
4545 msg.xclient.format = 32;
4546 msg.xclient.window = toplevel;
4547 msg.xclient.data.l[0] = FRAME_X_WINDOW (f);
4548 msg.xclient.data.l[1] = (((unsigned int) min (X_DND_SUPPORTED_VERSION,
4549 supported) << 24)
4550 | (x_dnd_n_targets > 3 ? 1 : 0));
4551 msg.xclient.data.l[2] = 0;
4552 msg.xclient.data.l[3] = 0;
4553 msg.xclient.data.l[4] = 0;
4554
4555 for (i = 0; i < min (3, x_dnd_n_targets); ++i)
4556 msg.xclient.data.l[i + 2] = x_dnd_targets[i];
4557
4558 if (x_dnd_n_targets > 3 && !x_dnd_init_type_lists)
4559 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4560 dpyinfo->Xatom_XdndTypeList, XA_ATOM, 32,
4561 PropModeReplace, (unsigned char *) x_dnd_targets,
4562 x_dnd_n_targets);
4563
4564
4565
4566 x_dnd_init_type_lists = true;
4567
4568 x_ignore_errors_for_next_request (dpyinfo, 0);
4569 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
4570 x_stop_ignoring_errors (dpyinfo);
4571 }
4572
4573 static void
4574 x_dnd_send_position (struct frame *f, Window target, Window toplevel,
4575 int supported, unsigned short root_x,
4576 unsigned short root_y, Time timestamp, Atom action,
4577 int button, unsigned state)
4578 {
4579 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
4580 XEvent msg;
4581
4582 msg.xclient.type = ClientMessage;
4583 msg.xclient.message_type = dpyinfo->Xatom_XdndPosition;
4584 msg.xclient.format = 32;
4585 msg.xclient.window = toplevel;
4586 msg.xclient.data.l[0] = FRAME_X_WINDOW (f);
4587 msg.xclient.data.l[1] = 0;
4588
4589
4590
4591
4592
4593
4594
4595 if (button >= 4 && button <= 7)
4596 {
4597 msg.xclient.data.l[1] |= (1 << 10);
4598 msg.xclient.data.l[1] |= (button - 4) << 8;
4599 }
4600 else if (button)
4601 return;
4602
4603 msg.xclient.data.l[1] |= state & 0xff;
4604
4605 msg.xclient.data.l[2] = (root_x << 16) | root_y;
4606 msg.xclient.data.l[3] = 0;
4607 msg.xclient.data.l[4] = 0;
4608
4609 if (supported >= 3)
4610 msg.xclient.data.l[3] = timestamp;
4611
4612 if (supported >= 4)
4613 msg.xclient.data.l[4] = action;
4614
4615 if (x_dnd_waiting_for_status_window == target)
4616 {
4617 x_dnd_pending_send_position = msg;
4618 x_dnd_pending_send_position_button = button;
4619 x_dnd_pending_send_position_root_x = root_x;
4620 x_dnd_pending_send_position_root_y = root_y;
4621 }
4622 else
4623 {
4624 if (target == x_dnd_mouse_rect_target
4625 && x_dnd_mouse_rect.width
4626 && x_dnd_mouse_rect.height
4627
4628
4629 && !button)
4630 {
4631 if (root_x >= x_dnd_mouse_rect.x
4632 && root_x < (x_dnd_mouse_rect.x
4633 + x_dnd_mouse_rect.width)
4634 && root_y >= x_dnd_mouse_rect.y
4635 && root_y < (x_dnd_mouse_rect.y
4636 + x_dnd_mouse_rect.height))
4637 return;
4638 }
4639
4640 x_ignore_errors_for_next_request (dpyinfo, 0);
4641 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
4642 x_stop_ignoring_errors (dpyinfo);
4643
4644 x_dnd_waiting_for_status_window = target;
4645 }
4646 }
4647
4648 static void
4649 x_dnd_send_leave (struct frame *f, Window target, Window toplevel)
4650 {
4651 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
4652 XEvent msg;
4653
4654 msg.xclient.type = ClientMessage;
4655 msg.xclient.message_type = dpyinfo->Xatom_XdndLeave;
4656 msg.xclient.format = 32;
4657 msg.xclient.window = toplevel;
4658 msg.xclient.data.l[0] = FRAME_X_WINDOW (f);
4659 msg.xclient.data.l[1] = 0;
4660 msg.xclient.data.l[2] = 0;
4661 msg.xclient.data.l[3] = 0;
4662 msg.xclient.data.l[4] = 0;
4663
4664 x_dnd_waiting_for_status_window = None;
4665 x_dnd_pending_send_position.type = 0;
4666
4667 x_ignore_errors_for_next_request (dpyinfo, 0);
4668 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
4669 x_stop_ignoring_errors (dpyinfo);
4670 }
4671
4672 static bool
4673 x_dnd_send_drop (struct frame *f, Window target, Window toplevel,
4674 Time timestamp, int supported)
4675 {
4676 struct x_display_info *dpyinfo;
4677 XEvent msg;
4678
4679 if (x_dnd_action == None)
4680 {
4681 x_dnd_send_leave (f, target, toplevel);
4682 return false;
4683 }
4684
4685 dpyinfo = FRAME_DISPLAY_INFO (f);
4686
4687 msg.xclient.type = ClientMessage;
4688 msg.xclient.message_type = dpyinfo->Xatom_XdndDrop;
4689 msg.xclient.format = 32;
4690 msg.xclient.window = toplevel;
4691 msg.xclient.data.l[0] = FRAME_X_WINDOW (f);
4692 msg.xclient.data.l[1] = 0;
4693 msg.xclient.data.l[2] = 0;
4694 msg.xclient.data.l[3] = 0;
4695 msg.xclient.data.l[4] = 0;
4696
4697 if (supported >= 1)
4698 msg.xclient.data.l[2] = timestamp;
4699
4700 x_ignore_errors_for_next_request (dpyinfo, 0);
4701 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
4702 x_stop_ignoring_errors (dpyinfo);
4703 return true;
4704 }
4705
4706 static bool
4707 x_dnd_do_drop (Window target, Window toplevel, int supported)
4708 {
4709 if (x_dnd_waiting_for_status_window != target)
4710 return x_dnd_send_drop (x_dnd_frame, target, toplevel,
4711 x_dnd_selection_timestamp, supported);
4712
4713 x_dnd_need_send_drop = true;
4714 x_dnd_send_drop_proto = supported;
4715
4716 return true;
4717 }
4718
4719 static void
4720 x_set_dnd_targets (Atom *targets, int ntargets)
4721 {
4722 if (x_dnd_targets)
4723 xfree (x_dnd_targets);
4724
4725 block_input ();
4726 x_dnd_targets = xmalloc (sizeof *targets * ntargets);
4727 x_dnd_n_targets = ntargets;
4728
4729 memcpy (x_dnd_targets, targets,
4730 sizeof *targets * ntargets);
4731 unblock_input ();
4732 }
4733
4734 static void
4735 x_free_dnd_targets (void)
4736 {
4737 if (!x_dnd_targets)
4738 return;
4739
4740 xfree (x_dnd_targets);
4741 x_dnd_targets = NULL;
4742 x_dnd_n_targets = 0;
4743 }
4744
4745
4746
4747
4748 static void
4749 x_clear_dnd_variables (void)
4750 {
4751 x_dnd_monitors = Qnil;
4752 x_dnd_unsupported_drop_data = Qnil;
4753 }
4754
4755 static void
4756 x_free_dnd_toplevels (void)
4757 {
4758 if (!x_dnd_use_toplevels || !x_dnd_toplevels)
4759 return;
4760
4761
4762
4763
4764 x_dnd_free_toplevels (true);
4765 }
4766
4767
4768
4769 static void
4770 x_restore_events_after_dnd (struct frame *f, XWindowAttributes *wa)
4771 {
4772 struct x_display_info *dpyinfo;
4773
4774 dpyinfo = FRAME_DISPLAY_INFO (f);
4775
4776
4777 XSelectInput (dpyinfo->display, dpyinfo->root_window,
4778 wa->your_event_mask);
4779 #ifdef HAVE_XKB
4780 if (dpyinfo->supports_xkb)
4781 XkbSelectEvents (dpyinfo->display, XkbUseCoreKbd,
4782 XkbStateNotifyMask, 0);
4783 #endif
4784
4785 if (x_dnd_motif_setup_p)
4786 XDeleteProperty (dpyinfo->display, FRAME_X_WINDOW (f),
4787 x_dnd_motif_atom);
4788
4789
4790 if (x_dnd_init_type_lists && x_dnd_n_targets > 3)
4791 XDeleteProperty (dpyinfo->display, FRAME_X_WINDOW (f),
4792 dpyinfo->Xatom_XdndTypeList);
4793 }
4794
4795 #ifdef HAVE_XINPUT2
4796
4797
4798
4799
4800
4801
4802 static void
4803 x_dnd_cancel_dnd_early (void)
4804 {
4805 struct frame *f;
4806 xm_drop_start_message dmsg;
4807
4808 eassert (x_dnd_frame && x_dnd_in_progress);
4809
4810 f = x_dnd_frame;
4811
4812 if (x_dnd_last_seen_window != None
4813 && x_dnd_last_protocol_version != -1)
4814 x_dnd_send_leave (x_dnd_frame,
4815 x_dnd_last_seen_window,
4816 x_dnd_last_seen_toplevel);
4817 else if (x_dnd_last_seen_window != None
4818 && !XM_DRAG_STYLE_IS_DROP_ONLY (x_dnd_last_motif_style)
4819 && x_dnd_last_motif_style != XM_DRAG_STYLE_NONE
4820 && x_dnd_motif_setup_p)
4821 {
4822 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
4823 XM_DRAG_REASON_DROP_START);
4824 dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST;
4825 dmsg.timestamp = FRAME_DISPLAY_INFO (f)->last_user_time;
4826 dmsg.side_effects
4827 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f),
4828 x_dnd_wanted_action),
4829 XM_DROP_SITE_VALID, x_dnd_motif_operations,
4830 XM_DROP_ACTION_DROP_CANCEL);
4831 dmsg.x = 0;
4832 dmsg.y = 0;
4833 dmsg.index_atom = x_dnd_motif_atom;
4834 dmsg.source_window = FRAME_X_WINDOW (f);
4835
4836 x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f,
4837 x_dnd_last_seen_window,
4838 FRAME_DISPLAY_INFO (f)->last_user_time);
4839 xm_send_drop_message (FRAME_DISPLAY_INFO (f), FRAME_X_WINDOW (f),
4840 x_dnd_last_seen_window, &dmsg);
4841 }
4842
4843 x_dnd_last_seen_window = None;
4844 x_dnd_last_seen_toplevel = None;
4845 x_dnd_in_progress = false;
4846 x_dnd_waiting_for_finish = false;
4847 x_dnd_return_frame_object = NULL;
4848 x_dnd_movement_frame = NULL;
4849 x_dnd_wheel_frame = NULL;
4850 x_dnd_frame = NULL;
4851 x_dnd_action = None;
4852 x_dnd_action_symbol = Qnil;
4853 }
4854
4855 #endif
4856
4857 static void
4858 x_dnd_cleanup_drag_and_drop (void *frame)
4859 {
4860 struct frame *f = frame;
4861 xm_drop_start_message dmsg;
4862
4863 if (!x_dnd_unwind_flag)
4864 return;
4865
4866 if (x_dnd_in_progress)
4867 {
4868 eassert (x_dnd_frame);
4869
4870 block_input ();
4871 if (x_dnd_last_seen_window != None
4872 && x_dnd_last_protocol_version != -1)
4873 x_dnd_send_leave (x_dnd_frame,
4874 x_dnd_last_seen_window,
4875 x_dnd_last_seen_toplevel);
4876 else if (x_dnd_last_seen_window != None
4877 && !XM_DRAG_STYLE_IS_DROP_ONLY (x_dnd_last_motif_style)
4878 && x_dnd_last_motif_style != XM_DRAG_STYLE_NONE
4879 && x_dnd_motif_setup_p)
4880 {
4881 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
4882 XM_DRAG_REASON_DROP_START);
4883 dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST;
4884 dmsg.timestamp = FRAME_DISPLAY_INFO (f)->last_user_time;
4885 dmsg.side_effects
4886 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f),
4887 x_dnd_wanted_action),
4888 XM_DROP_SITE_VALID, x_dnd_motif_operations,
4889 XM_DROP_ACTION_DROP_CANCEL);
4890 dmsg.x = 0;
4891 dmsg.y = 0;
4892 dmsg.index_atom = x_dnd_motif_atom;
4893 dmsg.source_window = FRAME_X_WINDOW (f);
4894
4895 x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f,
4896 x_dnd_last_seen_window,
4897 FRAME_DISPLAY_INFO (f)->last_user_time);
4898 xm_send_drop_message (FRAME_DISPLAY_INFO (f), FRAME_X_WINDOW (f),
4899 x_dnd_last_seen_window, &dmsg);
4900 }
4901 unblock_input ();
4902
4903 x_dnd_end_window = x_dnd_last_seen_window;
4904 x_dnd_last_seen_window = None;
4905 x_dnd_last_seen_toplevel = None;
4906 x_dnd_in_progress = false;
4907 }
4908
4909 x_dnd_waiting_for_finish = false;
4910
4911 FRAME_DISPLAY_INFO (f)->grabbed = 0;
4912 #ifdef USE_GTK
4913 current_hold_quit = NULL;
4914 #endif
4915 x_dnd_return_frame_object = NULL;
4916 x_dnd_movement_frame = NULL;
4917 x_dnd_wheel_frame = NULL;
4918 x_dnd_frame = NULL;
4919
4920 x_restore_events_after_dnd (f, &x_dnd_old_window_attrs);
4921 }
4922
4923 static void
4924 x_dnd_note_self_position (struct x_display_info *dpyinfo, Window target,
4925 unsigned short root_x, unsigned short root_y)
4926 {
4927 struct frame *f;
4928 int dest_x, dest_y;
4929
4930 f = x_top_window_to_frame (dpyinfo, target);
4931
4932 if (f)
4933 {
4934 x_translate_coordinates (f, root_x, root_y, &dest_x, &dest_y);
4935
4936 x_dnd_movement_frame = f;
4937 x_dnd_movement_x = dest_x;
4938 x_dnd_movement_y = dest_y;
4939
4940 return;
4941 }
4942 }
4943
4944 static void
4945 x_dnd_note_self_wheel (struct x_display_info *dpyinfo, Window target,
4946 unsigned short root_x, unsigned short root_y,
4947 int button, unsigned int state, Time time)
4948 {
4949 struct frame *f;
4950 int dest_x, dest_y;
4951
4952 if (button < 4 || button > 7)
4953 return;
4954
4955 f = x_top_window_to_frame (dpyinfo, target);
4956
4957 if (f)
4958 {
4959 x_translate_coordinates (f, root_x, root_y, &dest_x, &dest_y);
4960
4961 x_dnd_wheel_frame = f;
4962 x_dnd_wheel_x = dest_x;
4963 x_dnd_wheel_y = dest_y;
4964 x_dnd_wheel_button = button;
4965 x_dnd_wheel_state = state;
4966 x_dnd_wheel_time = time;
4967
4968 return;
4969 }
4970 }
4971
4972 static void
4973 x_dnd_note_self_drop (struct x_display_info *dpyinfo, Window target,
4974 unsigned short root_x, unsigned short root_y,
4975 Time timestamp)
4976 {
4977 struct input_event ie;
4978 struct frame *f;
4979 Lisp_Object lval;
4980 char **atom_names;
4981 char *name;
4982 int win_x, win_y, i;
4983
4984 if (!x_dnd_allow_current_frame
4985 && (FRAME_OUTER_WINDOW (x_dnd_frame)
4986 == target))
4987 return;
4988
4989 f = x_top_window_to_frame (dpyinfo, target);
4990
4991 if (!f)
4992 return;
4993
4994 if (NILP (Vx_dnd_native_test_function))
4995 return;
4996
4997 x_translate_coordinates (f, root_x, root_y, &win_x, &win_y);
4998
4999
5000
5001
5002
5003 XSETFRAME (lval, f);
5004 x_dnd_action = None;
5005 x_dnd_action_symbol
5006 = safe_call2 (Vx_dnd_native_test_function,
5007 Fposn_at_x_y (make_fixnum (win_x),
5008 make_fixnum (win_y),
5009 lval, Qnil),
5010 x_atom_to_symbol (dpyinfo,
5011 x_dnd_wanted_action));
5012
5013 if (!SYMBOLP (x_dnd_action_symbol))
5014 return;
5015
5016 EVENT_INIT (ie);
5017
5018 ie.kind = DRAG_N_DROP_EVENT;
5019 XSETFRAME (ie.frame_or_window, f);
5020
5021 lval = Qnil;
5022 atom_names = alloca (x_dnd_n_targets * sizeof *atom_names);
5023 name = x_get_atom_name (dpyinfo, x_dnd_wanted_action, NULL);
5024
5025 if (!XGetAtomNames (dpyinfo->display, x_dnd_targets,
5026 x_dnd_n_targets, atom_names))
5027 {
5028 xfree (name);
5029 return;
5030 }
5031
5032 for (i = x_dnd_n_targets; i != 0; --i)
5033 {
5034 lval = Fcons (intern (atom_names[i - 1]), lval);
5035 XFree (atom_names[i - 1]);
5036 }
5037
5038 lval = Fcons (assq_no_quit (QXdndSelection,
5039 FRAME_TERMINAL (f)->Vselection_alist),
5040 lval);
5041 lval = Fcons (intern (name), lval);
5042 lval = Fcons (QXdndSelection, lval);
5043 ie.arg = lval;
5044 ie.timestamp = timestamp;
5045
5046 XSETINT (ie.x, win_x);
5047 XSETINT (ie.y, win_y);
5048
5049 xfree (name);
5050 kbd_buffer_store_event (&ie);
5051 }
5052
5053
5054
5055 static void
5056 x_flush (struct frame *f)
5057 {
5058 eassert (f && FRAME_X_P (f));
5059
5060
5061 if (!NILP (Vinhibit_redisplay))
5062 return;
5063
5064 block_input ();
5065 XFlush (FRAME_X_DISPLAY (f));
5066 unblock_input ();
5067 }
5068
5069 #ifdef HAVE_XDBE
5070 static void
5071 x_drop_xrender_surfaces (struct frame *f)
5072 {
5073 font_drop_xrender_surfaces (f);
5074
5075 #ifdef HAVE_XRENDER
5076 if (f && FRAME_X_DOUBLE_BUFFERED_P (f)
5077 && FRAME_X_PICTURE (f) != None)
5078 {
5079 XRenderFreePicture (FRAME_X_DISPLAY (f),
5080 FRAME_X_PICTURE (f));
5081 FRAME_X_PICTURE (f) = None;
5082 }
5083 #endif
5084 }
5085 #endif
5086
5087 #ifdef HAVE_XRENDER
5088 void
5089 x_xr_ensure_picture (struct frame *f)
5090 {
5091 if (FRAME_X_PICTURE (f) == None && FRAME_X_PICTURE_FORMAT (f))
5092 {
5093 XRenderPictureAttributes attrs;
5094 attrs.clip_mask = None;
5095 XRenderPictFormat *fmt = FRAME_X_PICTURE_FORMAT (f);
5096
5097 FRAME_X_PICTURE (f) = XRenderCreatePicture (FRAME_X_DISPLAY (f),
5098 FRAME_X_RAW_DRAWABLE (f),
5099 fmt, CPClipMask, &attrs);
5100 }
5101 }
5102 #endif
5103
5104
5105
5106
5107
5108
5109 #if false
5110
5111
5112
5113
5114 struct record
5115 {
5116 char *locus;
5117 int type;
5118 };
5119
5120 struct record event_record[100];
5121
5122 int event_record_index;
5123
5124 void
5125 record_event (char *locus, int type)
5126 {
5127 if (event_record_index == ARRAYELTS (event_record))
5128 event_record_index = 0;
5129
5130 event_record[event_record_index].locus = locus;
5131 event_record[event_record_index].type = type;
5132 event_record_index++;
5133 }
5134
5135 #endif
5136
5137 #ifdef HAVE_XINPUT2
5138 bool
5139 xi_frame_selected_for (struct frame *f, unsigned long event)
5140 {
5141 XIEventMask *masks;
5142 int i;
5143
5144 masks = FRAME_X_OUTPUT (f)->xi_masks;
5145
5146 if (!masks)
5147 return false;
5148
5149 for (i = 0; i < FRAME_X_OUTPUT (f)->num_xi_masks; ++i)
5150 {
5151 if (masks[i].mask_len >= XIMaskLen (event)
5152 && XIMaskIsSet (masks[i].mask, event))
5153 return true;
5154 }
5155
5156 return false;
5157 }
5158 #endif
5159
5160 static void
5161 x_toolkit_position (struct frame *f, int x, int y,
5162 bool *menu_bar_p, bool *tool_bar_p)
5163 {
5164 #ifdef USE_GTK
5165 GdkRectangle test_rect;
5166 int scale;
5167
5168 y += (FRAME_MENUBAR_HEIGHT (f)
5169 + FRAME_TOOLBAR_TOP_HEIGHT (f));
5170 x += FRAME_TOOLBAR_LEFT_WIDTH (f);
5171
5172 if (FRAME_EXTERNAL_MENU_BAR (f))
5173 *menu_bar_p = (x >= 0 && x < FRAME_PIXEL_WIDTH (f)
5174 && y >= 0 && y < FRAME_MENUBAR_HEIGHT (f));
5175
5176 if (FRAME_X_OUTPUT (f)->toolbar_widget)
5177 {
5178 scale = xg_get_scale (f);
5179 test_rect.x = x / scale;
5180 test_rect.y = y / scale;
5181 test_rect.width = 1;
5182 test_rect.height = 1;
5183
5184 *tool_bar_p = gtk_widget_intersect (FRAME_X_OUTPUT (f)->toolbar_widget,
5185 &test_rect, NULL);
5186 }
5187 #elif defined USE_X_TOOLKIT
5188 *menu_bar_p = (x > 0 && x < FRAME_PIXEL_WIDTH (f)
5189 && (y < 0 && y >= -FRAME_MENUBAR_HEIGHT (f)));
5190 #else
5191 *menu_bar_p = (WINDOWP (f->menu_bar_window)
5192 && (x > 0 && x < FRAME_PIXEL_WIDTH (f)
5193 && (y > 0 && y < FRAME_MENU_BAR_HEIGHT (f))));
5194 #endif
5195 }
5196
5197 static void
5198 x_update_opaque_region (struct frame *f, XEvent *configure)
5199 {
5200 unsigned long opaque_region[] = {0, 0,
5201 (configure
5202 ? configure->xconfigure.width
5203 : FRAME_PIXEL_WIDTH (f)),
5204 (configure
5205 ? configure->xconfigure.height
5206 : FRAME_PIXEL_HEIGHT (f))};
5207 #ifdef HAVE_GTK3
5208 GObjectClass *object_class;
5209 GtkWidgetClass *class;
5210 #endif
5211
5212 if (!FRAME_DISPLAY_INFO (f)->alpha_bits)
5213 return;
5214
5215 if (f->alpha_background < 1.0)
5216 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5217 FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region,
5218 XA_CARDINAL, 32, PropModeReplace,
5219 NULL, 0);
5220 #ifndef HAVE_GTK3
5221 else
5222 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5223 FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region,
5224 XA_CARDINAL, 32, PropModeReplace,
5225 (unsigned char *) &opaque_region, 4);
5226 #else
5227 else if (FRAME_TOOLTIP_P (f))
5228 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5229 FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region,
5230 XA_CARDINAL, 32, PropModeReplace,
5231 (unsigned char *) &opaque_region, 4);
5232 else
5233 {
5234
5235
5236 if (!FRAME_PARENT_FRAME (f))
5237 {
5238 object_class = G_OBJECT_GET_CLASS (FRAME_GTK_OUTER_WIDGET (f));
5239 class = GTK_WIDGET_CLASS (object_class);
5240
5241 if (class->style_updated)
5242 class->style_updated (FRAME_GTK_OUTER_WIDGET (f));
5243 }
5244 }
5245 #endif
5246 }
5247
5248
5249 #if defined USE_CAIRO || defined HAVE_XRENDER
5250 static int
5251 x_gc_free_ext_data_private (XExtData *extension)
5252 {
5253 xfree (extension->private_data);
5254
5255 return 0;
5256 }
5257
5258 static struct x_gc_ext_data *
5259 x_gc_get_ext_data (struct frame *f, GC gc, int create_if_not_found_p)
5260 {
5261 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
5262 XEDataObject object;
5263 XExtData **head, *ext_data;
5264
5265 object.gc = gc;
5266 head = XEHeadOfExtensionList (object);
5267 ext_data = XFindOnExtensionList (head, dpyinfo->ext_codes->extension);
5268 if (ext_data == NULL)
5269 {
5270 if (!create_if_not_found_p)
5271 return NULL;
5272 else
5273 {
5274 ext_data = xzalloc (sizeof (*ext_data));
5275 ext_data->number = dpyinfo->ext_codes->extension;
5276 ext_data->private_data = xzalloc (sizeof (struct x_gc_ext_data));
5277 ext_data->free_private = x_gc_free_ext_data_private;
5278 XAddToExtensionList (head, ext_data);
5279 }
5280 }
5281 return (struct x_gc_ext_data *) ext_data->private_data;
5282 }
5283
5284 static void
5285 x_extension_initialize (struct x_display_info *dpyinfo)
5286 {
5287 XExtCodes *ext_codes = XAddExtension (dpyinfo->display);
5288
5289 dpyinfo->ext_codes = ext_codes;
5290 }
5291 #endif
5292
5293 #ifdef USE_CAIRO
5294
5295 #define FRAME_CR_CONTEXT(f) ((f)->output_data.x->cr_context)
5296 #define FRAME_CR_SURFACE_DESIRED_WIDTH(f) \
5297 ((f)->output_data.x->cr_surface_desired_width)
5298 #define FRAME_CR_SURFACE_DESIRED_HEIGHT(f) \
5299 ((f)->output_data.x->cr_surface_desired_height)
5300
5301 #endif
5302
5303 #ifdef HAVE_XINPUT2
5304
5305
5306
5307 static void
5308 xi_convert_button_state (XIButtonState *in, unsigned int *out)
5309 {
5310 int i;
5311
5312 if (in->mask_len)
5313 {
5314 for (i = 1; i <= 8; ++i)
5315 {
5316 if (XIMaskIsSet (in->mask, i))
5317 *out |= (Button1Mask << (i - 1));
5318 }
5319 }
5320 }
5321
5322
5323
5324
5325
5326 #ifdef USE_GTK
5327 static
5328 #endif
5329 unsigned int
5330 xi_convert_event_state (XIDeviceEvent *xev)
5331 {
5332 unsigned int mods, buttons;
5333
5334 mods = xev->mods.effective;
5335 buttons = 0;
5336
5337 xi_convert_button_state (&xev->buttons, &buttons);
5338
5339 return mods | buttons;
5340 }
5341
5342
5343
5344
5345
5346 static unsigned int
5347 xi_convert_event_keyboard_state (XIDeviceEvent *xev)
5348 {
5349 return ((xev->mods.effective & ~(1 << 13 | 1 << 14))
5350 | (xev->group.effective << 13));
5351 }
5352
5353
5354 static void
5355 x_free_xi_devices (struct x_display_info *dpyinfo)
5356 {
5357 #ifdef HAVE_XINPUT2_2
5358 struct xi_touch_point_t *tem, *last;
5359 #endif
5360
5361 block_input ();
5362
5363 if (dpyinfo->num_devices)
5364 {
5365 for (int i = 0; i < dpyinfo->num_devices; ++i)
5366 {
5367 #ifdef HAVE_XINPUT2_1
5368 xfree (dpyinfo->devices[i].valuators);
5369 #endif
5370
5371 #ifdef HAVE_XINPUT2_2
5372 tem = dpyinfo->devices[i].touchpoints;
5373 while (tem)
5374 {
5375 last = tem;
5376 tem = tem->next;
5377 xfree (last);
5378 }
5379 #endif
5380 }
5381
5382 xfree (dpyinfo->devices);
5383 dpyinfo->devices = NULL;
5384 dpyinfo->num_devices = 0;
5385 }
5386
5387 unblock_input ();
5388 }
5389
5390 #ifdef HAVE_XINPUT2_1
5391
5392 struct xi_known_valuator
5393 {
5394
5395 double current_value;
5396
5397
5398 int number;
5399
5400
5401 struct xi_known_valuator *next;
5402 };
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429 static void
5430 xi_populate_scroll_valuator (struct xi_device_t *device,
5431 int index, XIScrollClassInfo *info)
5432 {
5433 struct xi_scroll_valuator_t *valuator;
5434
5435 valuator = &device->valuators[index];
5436 valuator->horizontal
5437 = (info->scroll_type == XIScrollTypeHorizontal);
5438 valuator->invalid_p = true;
5439 valuator->emacs_value = DBL_MIN;
5440 valuator->increment = info->increment;
5441 valuator->number = info->number;
5442 }
5443
5444 #endif
5445
5446 static void
5447 xi_populate_device_from_info (struct x_display_info *dpyinfo,
5448 struct xi_device_t *xi_device,
5449 XIDeviceInfo *device)
5450 {
5451 #ifdef HAVE_XINPUT2_1
5452 struct xi_known_valuator *values, *tem;
5453 int actual_valuator_count, c;
5454 XIScrollClassInfo *info;
5455 XIValuatorClassInfo *valuator_info;
5456 #endif
5457 #ifdef HAVE_XINPUT2_2
5458 XITouchClassInfo *touch_info;
5459 #endif
5460
5461 #ifdef HAVE_XINPUT2_1
5462 USE_SAFE_ALLOCA;
5463 #endif
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519 xi_device->device_id = device->deviceid;
5520 xi_device->grab = 0;
5521 xi_device->use = device->use;
5522 xi_device->name = build_string (device->name);
5523 xi_device->attachment = device->attachment;
5524
5525
5526
5527
5528 #ifdef HAVE_XINPUT2_2
5529 xi_device->touchpoints = NULL;
5530 xi_device->direct_p = false;
5531 #endif
5532
5533 #ifdef HAVE_XINPUT2_1
5534 if (!dpyinfo->xi2_version)
5535 {
5536
5537
5538 xi_device->valuators = NULL;
5539 xi_device->scroll_valuator_count = 0;
5540
5541 SAFE_FREE ();
5542 return;
5543 }
5544
5545 actual_valuator_count = 0;
5546 xi_device->valuators = xnmalloc (device->num_classes,
5547 sizeof *xi_device->valuators);
5548 values = NULL;
5549
5550
5551
5552
5553
5554
5555
5556
5557 for (c = 0; c < device->num_classes; ++c)
5558 {
5559 switch (device->classes[c]->type)
5560 {
5561 case XIScrollClass:
5562 {
5563 info = (XIScrollClassInfo *) device->classes[c];
5564 xi_populate_scroll_valuator (xi_device, actual_valuator_count++,
5565 info);
5566 break;
5567 }
5568
5569 case XIValuatorClass:
5570 {
5571 valuator_info = (XIValuatorClassInfo *) device->classes[c];
5572 tem = SAFE_ALLOCA (sizeof *tem);
5573
5574
5575
5576
5577
5578
5579
5580
5581 if (valuator_info->value == 0.0
5582 && valuator_info->mode != XIModeAbsolute)
5583 continue;
5584
5585 tem->next = values;
5586 tem->number = valuator_info->number;
5587 tem->current_value = valuator_info->value;
5588
5589 values = tem;
5590 break;
5591 }
5592
5593 #ifdef HAVE_XINPUT2_2
5594 case XITouchClass:
5595 {
5596 touch_info = (XITouchClassInfo *) device->classes[c];
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619 if (touch_info->mode == XIDirectTouch)
5620 xi_device->direct_p = true;
5621 else
5622 xi_device->direct_p = false;
5623 }
5624 #endif
5625 default:
5626 break;
5627 }
5628 }
5629
5630 xi_device->scroll_valuator_count = actual_valuator_count;
5631
5632
5633
5634
5635
5636 for (tem = values; values; values = values->next)
5637 {
5638 for (c = 0; c < xi_device->scroll_valuator_count; ++c)
5639 {
5640 if (xi_device->valuators[c].number == tem->number)
5641 {
5642 xi_device->valuators[c].invalid_p = false;
5643 xi_device->valuators[c].current_value
5644 = tem->current_value;
5645 xi_device->valuators[c].emacs_value = 0.0;
5646 }
5647 }
5648 }
5649
5650 SAFE_FREE ();
5651 #endif
5652 }
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682 static void
5683 x_cache_xi_devices (struct x_display_info *dpyinfo)
5684 {
5685 int ndevices, actual_devices, i;
5686 XIDeviceInfo *infos;
5687
5688 actual_devices = 0;
5689 block_input ();
5690 x_free_xi_devices (dpyinfo);
5691 infos = XIQueryDevice (dpyinfo->display,
5692 XIAllDevices,
5693 &ndevices);
5694
5695 if (!ndevices)
5696 {
5697 XIFreeDeviceInfo (infos);
5698 unblock_input ();
5699 return;
5700 }
5701
5702 dpyinfo->devices = xzalloc (sizeof *dpyinfo->devices * ndevices);
5703
5704 for (i = 0; i < ndevices; ++i)
5705 {
5706 if (infos[i].enabled)
5707 xi_populate_device_from_info (dpyinfo,
5708 &dpyinfo->devices[actual_devices++],
5709 &infos[i]);
5710 }
5711
5712 dpyinfo->num_devices = actual_devices;
5713 XIFreeDeviceInfo (infos);
5714 unblock_input ();
5715 }
5716
5717 #ifdef HAVE_XINPUT2_1
5718
5719
5720
5721
5722
5723
5724 static double
5725 x_get_scroll_valuator_delta (struct x_display_info *dpyinfo,
5726 struct xi_device_t *device,
5727 int valuator_number, double value,
5728 struct xi_scroll_valuator_t **valuator_return)
5729 {
5730 struct xi_scroll_valuator_t *sv;
5731 double delta;
5732 int i;
5733
5734 for (i = 0; i < device->scroll_valuator_count; ++i)
5735 {
5736 sv = &device->valuators[i];
5737
5738 if (sv->number == valuator_number)
5739 {
5740 *valuator_return = sv;
5741
5742 if (sv->increment == 0)
5743 return DBL_MAX;
5744
5745 if (sv->invalid_p)
5746 {
5747 sv->current_value = value;
5748 sv->invalid_p = false;
5749
5750 return DBL_MAX;
5751 }
5752 else
5753 {
5754 delta = (sv->current_value - value) / sv->increment;
5755 sv->current_value = value;
5756
5757 return delta;
5758 }
5759 }
5760 }
5761
5762 *valuator_return = NULL;
5763 return DBL_MAX;
5764 }
5765
5766 #endif
5767
5768 struct xi_device_t *
5769 xi_device_from_id (struct x_display_info *dpyinfo, int deviceid)
5770 {
5771 for (int i = 0; i < dpyinfo->num_devices; ++i)
5772 {
5773 if (dpyinfo->devices[i].device_id == deviceid)
5774 return &dpyinfo->devices[i];
5775 }
5776
5777 return NULL;
5778 }
5779
5780 #ifdef HAVE_XINPUT2_2
5781
5782
5783
5784
5785
5786 static void
5787 xi_link_touch_point (struct xi_device_t *device,
5788 int detail, double x, double y,
5789 struct frame *frame)
5790 {
5791 struct xi_touch_point_t *touchpoint;
5792
5793 touchpoint = xmalloc (sizeof *touchpoint);
5794 touchpoint->next = device->touchpoints;
5795 touchpoint->x = lrint (x);
5796 touchpoint->y = lrint (y);
5797 touchpoint->number = detail;
5798 touchpoint->frame = frame;
5799 touchpoint->ownership = TOUCH_OWNERSHIP_NONE;
5800
5801 device->touchpoints = touchpoint;
5802 }
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812 static int
5813 xi_unlink_touch_point (int detail, struct xi_device_t *device)
5814 {
5815 struct xi_touch_point_t *last, *tem;
5816 enum xi_touch_ownership ownership;
5817
5818 for (last = NULL, tem = device->touchpoints; tem;
5819 last = tem, tem = tem->next)
5820 {
5821 if (tem->number == detail)
5822 {
5823 if (!last)
5824 device->touchpoints = tem->next;
5825 else
5826 last->next = tem->next;
5827
5828 ownership = tem->ownership;
5829 xfree (tem);
5830
5831 if (ownership == TOUCH_OWNERSHIP_SELF)
5832 return 2;
5833
5834 return 1;
5835 }
5836 }
5837
5838 return 0;
5839 }
5840
5841
5842
5843
5844
5845 static void
5846 xi_unlink_touch_points (struct frame *f)
5847 {
5848 struct xi_device_t *device;
5849 struct xi_touch_point_t **next, *last;
5850 int i;
5851
5852 for (i = 0; i < FRAME_DISPLAY_INFO (f)->num_devices; ++i)
5853 {
5854 device = &FRAME_DISPLAY_INFO (f)->devices[i];
5855
5856
5857
5858 for (next = &device->touchpoints; (last = *next);)
5859 {
5860 if (last->frame == f)
5861 {
5862 *next = last->next;
5863 xfree (last);
5864 }
5865 else
5866 next = &last->next;
5867 }
5868 }
5869 }
5870
5871
5872
5873
5874
5875 static struct xi_touch_point_t *
5876 xi_find_touch_point (struct xi_device_t *device, int detail)
5877 {
5878 struct xi_touch_point_t *point;
5879
5880 for (point = device->touchpoints; point; point = point->next)
5881 {
5882 if (point->number == detail)
5883 return point;
5884 }
5885
5886 return NULL;
5887 }
5888
5889 #endif
5890
5891 #ifdef HAVE_XINPUT2_1
5892
5893 static void
5894 xi_reset_scroll_valuators_for_device_id (struct x_display_info *dpyinfo,
5895 int id)
5896 {
5897 struct xi_device_t *device;
5898 struct xi_scroll_valuator_t *valuator;
5899 int i;
5900
5901 device = xi_device_from_id (dpyinfo, id);
5902
5903 if (!device)
5904 return;
5905
5906 if (!device->scroll_valuator_count)
5907 return;
5908
5909 for (i = 0; i < device->scroll_valuator_count; ++i)
5910 {
5911 valuator = &device->valuators[i];
5912 valuator->invalid_p = true;
5913 valuator->emacs_value = 0.0;
5914 }
5915
5916 return;
5917 }
5918
5919 #endif
5920
5921 #endif
5922
5923 #ifdef USE_CAIRO
5924
5925 void
5926 x_cr_destroy_frame_context (struct frame *f)
5927 {
5928 if (FRAME_CR_CONTEXT (f))
5929 {
5930 cairo_destroy (FRAME_CR_CONTEXT (f));
5931 FRAME_CR_CONTEXT (f) = NULL;
5932 }
5933 }
5934
5935 void
5936 x_cr_update_surface_desired_size (struct frame *f, int width, int height)
5937 {
5938 if (FRAME_CR_SURFACE_DESIRED_WIDTH (f) != width
5939 || FRAME_CR_SURFACE_DESIRED_HEIGHT (f) != height)
5940 {
5941 x_cr_destroy_frame_context (f);
5942 FRAME_CR_SURFACE_DESIRED_WIDTH (f) = width;
5943 FRAME_CR_SURFACE_DESIRED_HEIGHT (f) = height;
5944 }
5945 }
5946
5947 static void
5948 x_cr_gc_clip (cairo_t *cr, struct frame *f, GC gc)
5949 {
5950 if (gc)
5951 {
5952 struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 0);
5953
5954 if (gc_ext && gc_ext->n_clip_rects)
5955 {
5956 for (int i = 0; i < gc_ext->n_clip_rects; i++)
5957 cairo_rectangle (cr, gc_ext->clip_rects[i].x,
5958 gc_ext->clip_rects[i].y,
5959 gc_ext->clip_rects[i].width,
5960 gc_ext->clip_rects[i].height);
5961 cairo_clip (cr);
5962 }
5963 }
5964 }
5965
5966 cairo_t *
5967 x_begin_cr_clip (struct frame *f, GC gc)
5968 {
5969 cairo_t *cr = FRAME_CR_CONTEXT (f);
5970
5971 if (!cr)
5972 {
5973 int width = FRAME_CR_SURFACE_DESIRED_WIDTH (f);
5974 int height = FRAME_CR_SURFACE_DESIRED_HEIGHT (f);
5975 cairo_surface_t *surface;
5976 #ifdef USE_CAIRO_XCB_SURFACE
5977 if (FRAME_DISPLAY_INFO (f)->xcb_visual)
5978 surface = cairo_xcb_surface_create (FRAME_DISPLAY_INFO (f)->xcb_connection,
5979 (xcb_drawable_t) FRAME_X_RAW_DRAWABLE (f),
5980 FRAME_DISPLAY_INFO (f)->xcb_visual,
5981 width, height);
5982 else
5983 #endif
5984 surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
5985 FRAME_X_RAW_DRAWABLE (f),
5986 FRAME_X_VISUAL (f),
5987 width, height);
5988
5989 cr = FRAME_CR_CONTEXT (f) = cairo_create (surface);
5990 cairo_surface_destroy (surface);
5991 }
5992 cairo_save (cr);
5993 x_cr_gc_clip (cr, f, gc);
5994
5995 return cr;
5996 }
5997
5998 void
5999 x_end_cr_clip (struct frame *f)
6000 {
6001 cairo_restore (FRAME_CR_CONTEXT (f));
6002 #ifdef HAVE_XDBE
6003 if (FRAME_X_DOUBLE_BUFFERED_P (f))
6004 x_mark_frame_dirty (f);
6005 #endif
6006 }
6007
6008 void
6009 x_set_cr_source_with_gc_foreground (struct frame *f, GC gc,
6010 bool respect_alpha_background)
6011 {
6012 XGCValues xgcv;
6013 XColor color;
6014 unsigned int depth;
6015
6016 XGetGCValues (FRAME_X_DISPLAY (f), gc, GCForeground, &xgcv);
6017 color.pixel = xgcv.foreground;
6018 x_query_colors (f, &color, 1);
6019 depth = FRAME_DISPLAY_INFO (f)->n_planes;
6020
6021 if (f->alpha_background < 1.0 && depth == 32
6022 && respect_alpha_background)
6023 {
6024 cairo_set_source_rgba (FRAME_CR_CONTEXT (f), color.red / 65535.0,
6025 color.green / 65535.0, color.blue / 65535.0,
6026 f->alpha_background);
6027
6028 cairo_set_operator (FRAME_CR_CONTEXT (f), CAIRO_OPERATOR_SOURCE);
6029 }
6030 else
6031 {
6032 cairo_set_source_rgb (FRAME_CR_CONTEXT (f), color.red / 65535.0,
6033 color.green / 65535.0, color.blue / 65535.0);
6034 cairo_set_operator (FRAME_CR_CONTEXT (f), CAIRO_OPERATOR_OVER);
6035 }
6036 }
6037
6038 void
6039 x_set_cr_source_with_gc_background (struct frame *f, GC gc,
6040 bool respect_alpha_background)
6041 {
6042 XGCValues xgcv;
6043 XColor color;
6044 unsigned int depth;
6045
6046 XGetGCValues (FRAME_X_DISPLAY (f), gc, GCBackground, &xgcv);
6047 color.pixel = xgcv.background;
6048
6049 x_query_colors (f, &color, 1);
6050
6051 depth = FRAME_DISPLAY_INFO (f)->n_planes;
6052
6053 if (f->alpha_background < 1.0 && depth == 32
6054 && respect_alpha_background)
6055 {
6056 cairo_set_source_rgba (FRAME_CR_CONTEXT (f), color.red / 65535.0,
6057 color.green / 65535.0, color.blue / 65535.0,
6058 f->alpha_background);
6059
6060 cairo_set_operator (FRAME_CR_CONTEXT (f), CAIRO_OPERATOR_SOURCE);
6061 }
6062 else
6063 {
6064 cairo_set_source_rgb (FRAME_CR_CONTEXT (f), color.red / 65535.0,
6065 color.green / 65535.0, color.blue / 65535.0);
6066 cairo_set_operator (FRAME_CR_CONTEXT (f), CAIRO_OPERATOR_OVER);
6067 }
6068 }
6069
6070 static const cairo_user_data_key_t xlib_surface_key, saved_drawable_key;
6071
6072 static void
6073 x_cr_destroy_xlib_surface (cairo_surface_t *xlib_surface)
6074 {
6075 if (xlib_surface)
6076 {
6077 XFreePixmap (cairo_xlib_surface_get_display (xlib_surface),
6078 cairo_xlib_surface_get_drawable (xlib_surface));
6079 cairo_surface_destroy (xlib_surface);
6080 }
6081 }
6082
6083 static bool
6084 x_try_cr_xlib_drawable (struct frame *f, GC gc)
6085 {
6086 cairo_t *cr = FRAME_CR_CONTEXT (f);
6087 if (!cr)
6088 return true;
6089
6090 cairo_surface_t *surface = cairo_get_target (cr);
6091 switch (cairo_surface_get_type (surface))
6092 {
6093 case CAIRO_SURFACE_TYPE_XLIB:
6094 #ifdef USE_CAIRO_XCB_SURFACE
6095 case CAIRO_SURFACE_TYPE_XCB:
6096 #endif
6097 cairo_surface_flush (surface);
6098 return true;
6099
6100 case CAIRO_SURFACE_TYPE_IMAGE:
6101 break;
6102
6103 default:
6104 return false;
6105 }
6106
6107
6108
6109
6110 cairo_surface_t *xlib_surface = cairo_get_user_data (cr, &xlib_surface_key);
6111 int width = FRAME_CR_SURFACE_DESIRED_WIDTH (f);
6112 int height = FRAME_CR_SURFACE_DESIRED_HEIGHT (f);
6113 Pixmap pixmap;
6114 if (xlib_surface
6115 && cairo_xlib_surface_get_width (xlib_surface) == width
6116 && cairo_xlib_surface_get_height (xlib_surface) == height)
6117 pixmap = cairo_xlib_surface_get_drawable (xlib_surface);
6118 else
6119 {
6120 pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_RAW_DRAWABLE (f),
6121 width, height,
6122 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
6123 xlib_surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
6124 pixmap, FRAME_X_VISUAL (f),
6125 width, height);
6126 cairo_set_user_data (cr, &xlib_surface_key, xlib_surface,
6127 (cairo_destroy_func_t) x_cr_destroy_xlib_surface);
6128 }
6129
6130 cairo_t *buf = cairo_create (xlib_surface);
6131 cairo_set_source_surface (buf, surface, 0, 0);
6132 cairo_matrix_t matrix;
6133 cairo_get_matrix (cr, &matrix);
6134 cairo_pattern_set_matrix (cairo_get_source (cr), &matrix);
6135 cairo_set_operator (buf, CAIRO_OPERATOR_SOURCE);
6136 x_cr_gc_clip (buf, f, gc);
6137 cairo_paint (buf);
6138 cairo_destroy (buf);
6139
6140 cairo_set_user_data (cr, &saved_drawable_key,
6141 (void *) (uintptr_t) FRAME_X_RAW_DRAWABLE (f), NULL);
6142 FRAME_X_RAW_DRAWABLE (f) = pixmap;
6143 cairo_surface_flush (xlib_surface);
6144
6145 return true;
6146 }
6147
6148 static void
6149 x_end_cr_xlib_drawable (struct frame *f, GC gc)
6150 {
6151 cairo_t *cr = FRAME_CR_CONTEXT (f);
6152 if (!cr)
6153 return;
6154
6155 Drawable saved_drawable
6156 = (uintptr_t) cairo_get_user_data (cr, &saved_drawable_key);
6157 cairo_surface_t *surface = (saved_drawable
6158 ? cairo_get_user_data (cr, &xlib_surface_key)
6159 : cairo_get_target (cr));
6160 struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 0);
6161 if (gc_ext && gc_ext->n_clip_rects)
6162 for (int i = 0; i < gc_ext->n_clip_rects; i++)
6163 cairo_surface_mark_dirty_rectangle (surface, gc_ext->clip_rects[i].x,
6164 gc_ext->clip_rects[i].y,
6165 gc_ext->clip_rects[i].width,
6166 gc_ext->clip_rects[i].height);
6167 else
6168 cairo_surface_mark_dirty (surface);
6169 if (!saved_drawable)
6170 return;
6171
6172 cairo_save (cr);
6173 cairo_set_source_surface (cr, surface, 0, 0);
6174 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
6175 x_cr_gc_clip (cr, f, gc);
6176 cairo_paint (cr);
6177 cairo_restore (cr);
6178
6179 FRAME_X_RAW_DRAWABLE (f) = saved_drawable;
6180 cairo_set_user_data (cr, &saved_drawable_key, NULL, NULL);
6181 }
6182
6183
6184
6185 static int max_fringe_bmp = 0;
6186 static cairo_pattern_t **fringe_bmp = 0;
6187
6188 static void
6189 x_cr_define_fringe_bitmap (int which, unsigned short *bits, int h, int wd)
6190 {
6191 int i, stride;
6192 cairo_surface_t *surface;
6193 cairo_pattern_t *pattern;
6194 unsigned char *data;
6195
6196 if (which >= max_fringe_bmp)
6197 {
6198 i = max_fringe_bmp;
6199 max_fringe_bmp = which + 20;
6200 fringe_bmp = xrealloc (fringe_bmp, max_fringe_bmp * sizeof (*fringe_bmp));
6201 while (i < max_fringe_bmp)
6202 fringe_bmp[i++] = 0;
6203 }
6204
6205 block_input ();
6206
6207 surface = cairo_image_surface_create (CAIRO_FORMAT_A1, wd, h);
6208 stride = cairo_image_surface_get_stride (surface);
6209 data = cairo_image_surface_get_data (surface);
6210
6211 for (i = 0; i < h; i++)
6212 {
6213 *((unsigned short *) data) = bits[i];
6214 data += stride;
6215 }
6216
6217 cairo_surface_mark_dirty (surface);
6218 pattern = cairo_pattern_create_for_surface (surface);
6219 cairo_surface_destroy (surface);
6220
6221 unblock_input ();
6222
6223 fringe_bmp[which] = pattern;
6224 }
6225
6226 static void
6227 x_cr_destroy_fringe_bitmap (int which)
6228 {
6229 if (which >= max_fringe_bmp)
6230 return;
6231
6232 if (fringe_bmp[which])
6233 {
6234 block_input ();
6235 cairo_pattern_destroy (fringe_bmp[which]);
6236 unblock_input ();
6237 }
6238 fringe_bmp[which] = 0;
6239 }
6240
6241 static void
6242 x_cr_draw_image (struct frame *f, GC gc, cairo_pattern_t *image,
6243 int src_x, int src_y, int width, int height,
6244 int dest_x, int dest_y, bool overlay_p)
6245 {
6246 cairo_t *cr = x_begin_cr_clip (f, gc);
6247
6248 if (overlay_p)
6249 cairo_rectangle (cr, dest_x, dest_y, width, height);
6250 else
6251 {
6252 x_set_cr_source_with_gc_background (f, gc, false);
6253 cairo_rectangle (cr, dest_x, dest_y, width, height);
6254 cairo_fill_preserve (cr);
6255 }
6256
6257 cairo_translate (cr, dest_x - src_x, dest_y - src_y);
6258
6259 cairo_surface_t *surface;
6260 cairo_pattern_get_surface (image, &surface);
6261 cairo_format_t format = cairo_image_surface_get_format (surface);
6262 if (format != CAIRO_FORMAT_A8 && format != CAIRO_FORMAT_A1)
6263 {
6264 cairo_set_source (cr, image);
6265 cairo_fill (cr);
6266 }
6267 else
6268 {
6269 x_set_cr_source_with_gc_foreground (f, gc, false);
6270 cairo_clip (cr);
6271 cairo_mask (cr, image);
6272 }
6273
6274 x_end_cr_clip (f);
6275 }
6276
6277 void
6278 x_cr_draw_frame (cairo_t *cr, struct frame *f)
6279 {
6280 int width, height;
6281
6282 width = FRAME_PIXEL_WIDTH (f);
6283 height = FRAME_PIXEL_HEIGHT (f);
6284
6285 cairo_t *saved_cr = FRAME_CR_CONTEXT (f);
6286 FRAME_CR_CONTEXT (f) = cr;
6287 x_clear_area (f, 0, 0, width, height);
6288 expose_frame (f, 0, 0, width, height);
6289 FRAME_CR_CONTEXT (f) = saved_cr;
6290 }
6291
6292 static cairo_status_t
6293 x_cr_accumulate_data (void *closure, const unsigned char *data,
6294 unsigned int length)
6295 {
6296 Lisp_Object *acc = (Lisp_Object *) closure;
6297
6298 *acc = Fcons (make_unibyte_string ((char const *) data, length), *acc);
6299
6300 return CAIRO_STATUS_SUCCESS;
6301 }
6302
6303 static void
6304 x_cr_destroy (void *cr)
6305 {
6306 block_input ();
6307 cairo_destroy (cr);
6308 unblock_input ();
6309 }
6310
6311 Lisp_Object
6312 x_cr_export_frames (Lisp_Object frames, cairo_surface_type_t surface_type)
6313 {
6314 struct frame *f;
6315 cairo_surface_t *surface;
6316 cairo_t *cr;
6317 int width, height;
6318 void (*surface_set_size_func) (cairo_surface_t *, double, double) = NULL;
6319 Lisp_Object acc = Qnil;
6320 specpdl_ref count = SPECPDL_INDEX ();
6321
6322 specbind (Qredisplay_dont_pause, Qt);
6323 redisplay_preserve_echo_area (31);
6324
6325 f = XFRAME (XCAR (frames));
6326 frames = XCDR (frames);
6327 width = FRAME_PIXEL_WIDTH (f);
6328 height = FRAME_PIXEL_HEIGHT (f);
6329
6330 block_input ();
6331 #ifdef CAIRO_HAS_PDF_SURFACE
6332 if (surface_type == CAIRO_SURFACE_TYPE_PDF)
6333 {
6334 surface = cairo_pdf_surface_create_for_stream (x_cr_accumulate_data, &acc,
6335 width, height);
6336 surface_set_size_func = cairo_pdf_surface_set_size;
6337 }
6338 else
6339 #endif
6340 #ifdef CAIRO_HAS_PNG_FUNCTIONS
6341 if (surface_type == CAIRO_SURFACE_TYPE_IMAGE)
6342 surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height);
6343 else
6344 #endif
6345 #ifdef CAIRO_HAS_PS_SURFACE
6346 if (surface_type == CAIRO_SURFACE_TYPE_PS)
6347 {
6348 surface = cairo_ps_surface_create_for_stream (x_cr_accumulate_data, &acc,
6349 width, height);
6350 surface_set_size_func = cairo_ps_surface_set_size;
6351 }
6352 else
6353 #endif
6354 #ifdef CAIRO_HAS_SVG_SURFACE
6355 if (surface_type == CAIRO_SURFACE_TYPE_SVG)
6356 surface = cairo_svg_surface_create_for_stream (x_cr_accumulate_data, &acc,
6357 width, height);
6358 else
6359 #endif
6360 abort ();
6361
6362 cr = cairo_create (surface);
6363 cairo_surface_destroy (surface);
6364 record_unwind_protect_ptr (x_cr_destroy, cr);
6365
6366 while (1)
6367 {
6368 cairo_t *saved_cr = FRAME_CR_CONTEXT (f);
6369 FRAME_CR_CONTEXT (f) = cr;
6370 x_clear_area (f, 0, 0, width, height);
6371 expose_frame (f, 0, 0, width, height);
6372 FRAME_CR_CONTEXT (f) = saved_cr;
6373
6374 if (NILP (frames))
6375 break;
6376
6377 cairo_surface_show_page (surface);
6378 f = XFRAME (XCAR (frames));
6379 frames = XCDR (frames);
6380 width = FRAME_PIXEL_WIDTH (f);
6381 height = FRAME_PIXEL_HEIGHT (f);
6382 if (surface_set_size_func)
6383 (*surface_set_size_func) (surface, width, height);
6384
6385 unblock_input ();
6386 maybe_quit ();
6387 block_input ();
6388 }
6389
6390 #ifdef CAIRO_HAS_PNG_FUNCTIONS
6391 if (surface_type == CAIRO_SURFACE_TYPE_IMAGE)
6392 {
6393 cairo_surface_flush (surface);
6394 cairo_surface_write_to_png_stream (surface, x_cr_accumulate_data, &acc);
6395 }
6396 #endif
6397 unblock_input ();
6398
6399 unbind_to (count, Qnil);
6400
6401 return CALLN (Fapply, Qconcat, Fnreverse (acc));
6402 }
6403
6404 #endif
6405
6406 #if defined HAVE_XRENDER
6407 void
6408 x_xr_apply_ext_clip (struct frame *f, GC gc)
6409 {
6410 eassert (FRAME_X_PICTURE (f) != None);
6411
6412 struct x_gc_ext_data *data = x_gc_get_ext_data (f, gc, 1);
6413
6414 if (data->n_clip_rects)
6415 XRenderSetPictureClipRectangles (FRAME_X_DISPLAY (f),
6416 FRAME_X_PICTURE (f),
6417 0, 0, data->clip_rects,
6418 data->n_clip_rects);
6419 }
6420
6421 void
6422 x_xr_reset_ext_clip (struct frame *f)
6423 {
6424 XRenderPictureAttributes attrs = { .clip_mask = None };
6425
6426 XRenderChangePicture (FRAME_X_DISPLAY (f),
6427 FRAME_X_PICTURE (f),
6428 CPClipMask, &attrs);
6429 }
6430 #endif
6431
6432 static void
6433 x_set_clip_rectangles (struct frame *f, GC gc, XRectangle *rectangles, int n)
6434 {
6435 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, rectangles, n, Unsorted);
6436 #if defined USE_CAIRO || defined HAVE_XRENDER
6437 eassert (n >= 0 && n <= MAX_CLIP_RECTS);
6438
6439 {
6440 struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 1);
6441
6442 gc_ext->n_clip_rects = n;
6443 memcpy (gc_ext->clip_rects, rectangles, sizeof (XRectangle) * n);
6444 }
6445 #endif
6446 }
6447
6448 static void
6449 x_reset_clip_rectangles (struct frame *f, GC gc)
6450 {
6451 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
6452 #if defined USE_CAIRO || defined HAVE_XRENDER
6453 {
6454 struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 0);
6455
6456 if (gc_ext)
6457 gc_ext->n_clip_rects = 0;
6458 }
6459 #endif
6460 }
6461
6462 #ifdef HAVE_XRENDER
6463 # if !defined USE_CAIRO && (RENDER_MAJOR > 0 || RENDER_MINOR >= 2)
6464 static void
6465 x_xrender_color_from_gc_foreground (struct frame *f, GC gc, XRenderColor *color,
6466 bool apply_alpha_background)
6467 {
6468 XGCValues xgcv;
6469 XColor xc;
6470
6471 XGetGCValues (FRAME_X_DISPLAY (f), gc, GCForeground, &xgcv);
6472 xc.pixel = xgcv.foreground;
6473 x_query_colors (f, &xc, 1);
6474
6475 color->alpha = (apply_alpha_background
6476 ? 65535 * f->alpha_background
6477 : 65535);
6478
6479 if (color->alpha == 65535)
6480 {
6481 color->red = xc.red;
6482 color->blue = xc.blue;
6483 color->green = xc.green;
6484 }
6485 else
6486 {
6487 color->red = (xc.red * color->alpha) / 65535;
6488 color->blue = (xc.blue * color->alpha) / 65535;
6489 color->green = (xc.green * color->alpha) / 65535;
6490 }
6491 }
6492 # endif
6493
6494 void
6495 x_xrender_color_from_gc_background (struct frame *f, GC gc, XRenderColor *color,
6496 bool apply_alpha_background)
6497 {
6498 XGCValues xgcv;
6499 XColor xc;
6500
6501 XGetGCValues (FRAME_X_DISPLAY (f), gc, GCBackground, &xgcv);
6502 xc.pixel = xgcv.background;
6503 x_query_colors (f, &xc, 1);
6504
6505 color->alpha = (apply_alpha_background
6506 ? 65535 * f->alpha_background
6507 : 65535);
6508
6509 if (color->alpha == 65535)
6510 {
6511 color->red = xc.red;
6512 color->blue = xc.blue;
6513 color->green = xc.green;
6514 }
6515 else
6516 {
6517 color->red = (xc.red * color->alpha) / 65535;
6518 color->blue = (xc.blue * color->alpha) / 65535;
6519 color->green = (xc.green * color->alpha) / 65535;
6520 }
6521 }
6522 #endif
6523
6524 static void
6525 x_fill_rectangle (struct frame *f, GC gc, int x, int y, int width, int height,
6526 bool respect_alpha_background)
6527 {
6528 #ifdef USE_CAIRO
6529 Display *dpy = FRAME_X_DISPLAY (f);
6530 cairo_t *cr;
6531 XGCValues xgcv;
6532
6533 cr = x_begin_cr_clip (f, gc);
6534 XGetGCValues (dpy, gc, GCFillStyle | GCStipple, &xgcv);
6535 if (xgcv.fill_style == FillSolid
6536
6537
6538
6539
6540 || (xgcv.stipple & ((Pixmap) 7 << (sizeof (Pixmap) * CHAR_BIT - 3))))
6541 {
6542 x_set_cr_source_with_gc_foreground (f, gc, respect_alpha_background);
6543 cairo_rectangle (cr, x, y, width, height);
6544 cairo_fill (cr);
6545 }
6546 else
6547 {
6548 eassert (xgcv.fill_style == FillOpaqueStippled);
6549 eassert (xgcv.stipple != None);
6550 x_set_cr_source_with_gc_background (f, gc, respect_alpha_background);
6551 cairo_rectangle (cr, x, y, width, height);
6552 cairo_fill_preserve (cr);
6553
6554 cairo_pattern_t *pattern = x_bitmap_stipple (f, xgcv.stipple);
6555 if (pattern)
6556 {
6557 x_set_cr_source_with_gc_foreground (f, gc, respect_alpha_background);
6558 cairo_clip (cr);
6559 cairo_mask (cr, pattern);
6560 }
6561 }
6562 x_end_cr_clip (f);
6563 #else
6564 #if defined HAVE_XRENDER && (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2))
6565 if (respect_alpha_background
6566 && f->alpha_background != 1.0
6567 && FRAME_DISPLAY_INFO (f)->alpha_bits
6568 && FRAME_CHECK_XR_VERSION (f, 0, 2))
6569 {
6570 x_xr_ensure_picture (f);
6571
6572 if (FRAME_X_PICTURE (f) != None)
6573 {
6574 XRenderColor xc;
6575
6576 #if RENDER_MAJOR > 0 || (RENDER_MINOR >= 10)
6577 XGCValues xgcv;
6578 XRenderPictureAttributes attrs;
6579 XRenderColor alpha;
6580 Picture stipple, fill;
6581 #endif
6582
6583 x_xr_apply_ext_clip (f, gc);
6584
6585 #if RENDER_MAJOR > 0 || (RENDER_MINOR >= 10)
6586 XGetGCValues (FRAME_X_DISPLAY (f),
6587 gc, GCFillStyle | GCStipple, &xgcv);
6588
6589 if (xgcv.fill_style == FillOpaqueStippled
6590 && FRAME_CHECK_XR_VERSION (f, 0, 10))
6591 {
6592 x_xrender_color_from_gc_background (f, gc, &alpha, true);
6593 x_xrender_color_from_gc_foreground (f, gc, &xc, true);
6594 attrs.repeat = RepeatNormal;
6595
6596 stipple = XRenderCreatePicture (FRAME_X_DISPLAY (f),
6597 xgcv.stipple,
6598 XRenderFindStandardFormat (FRAME_X_DISPLAY (f),
6599 PictStandardA1),
6600 CPRepeat, &attrs);
6601
6602 XRenderFillRectangle (FRAME_X_DISPLAY (f), PictOpSrc,
6603 FRAME_X_PICTURE (f),
6604 &alpha, x, y, width, height);
6605
6606 fill = XRenderCreateSolidFill (FRAME_X_DISPLAY (f), &xc);
6607
6608 XRenderComposite (FRAME_X_DISPLAY (f), PictOpOver, fill, stipple,
6609 FRAME_X_PICTURE (f), 0, 0, x, y, x, y, width, height);
6610
6611 XRenderFreePicture (FRAME_X_DISPLAY (f), stipple);
6612 XRenderFreePicture (FRAME_X_DISPLAY (f), fill);
6613 }
6614 else
6615 #endif
6616 {
6617 x_xrender_color_from_gc_foreground (f, gc, &xc, true);
6618 XRenderFillRectangle (FRAME_X_DISPLAY (f),
6619 PictOpSrc, FRAME_X_PICTURE (f),
6620 &xc, x, y, width, height);
6621 }
6622 x_xr_reset_ext_clip (f);
6623 x_mark_frame_dirty (f);
6624
6625 return;
6626 }
6627 }
6628 #endif
6629 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
6630 gc, x, y, width, height);
6631 #endif
6632 }
6633
6634
6635 static void
6636 x_clear_rectangle (struct frame *f, GC gc, int x, int y, int width, int height,
6637 bool respect_alpha_background)
6638 {
6639 #ifdef USE_CAIRO
6640 cairo_t *cr;
6641
6642 cr = x_begin_cr_clip (f, gc);
6643 x_set_cr_source_with_gc_background (f, gc, respect_alpha_background);
6644 cairo_rectangle (cr, x, y, width, height);
6645 cairo_fill (cr);
6646 x_end_cr_clip (f);
6647 #else
6648 #if defined HAVE_XRENDER && (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2))
6649 if (respect_alpha_background
6650 && f->alpha_background != 1.0
6651 && FRAME_DISPLAY_INFO (f)->alpha_bits
6652 && FRAME_CHECK_XR_VERSION (f, 0, 2))
6653 {
6654 x_xr_ensure_picture (f);
6655
6656 if (FRAME_X_PICTURE (f) != None)
6657 {
6658 XRenderColor xc;
6659
6660 x_xr_apply_ext_clip (f, gc);
6661 x_xrender_color_from_gc_background (f, gc, &xc, true);
6662 XRenderFillRectangle (FRAME_X_DISPLAY (f),
6663 PictOpSrc, FRAME_X_PICTURE (f),
6664 &xc, x, y, width, height);
6665 x_xr_reset_ext_clip (f);
6666 x_mark_frame_dirty (f);
6667
6668 return;
6669 }
6670 }
6671 #endif
6672
6673 XGCValues xgcv;
6674 Display *dpy = FRAME_X_DISPLAY (f);
6675 XGetGCValues (dpy, gc, GCBackground | GCForeground, &xgcv);
6676 XSetForeground (dpy, gc, xgcv.background);
6677 XFillRectangle (dpy, FRAME_X_DRAWABLE (f),
6678 gc, x, y, width, height);
6679 XSetForeground (dpy, gc, xgcv.foreground);
6680 #endif
6681 }
6682
6683 static void
6684 x_draw_rectangle (struct frame *f, GC gc, int x, int y, int width, int height)
6685 {
6686 #ifdef USE_CAIRO
6687 cairo_t *cr;
6688
6689 cr = x_begin_cr_clip (f, gc);
6690 x_set_cr_source_with_gc_foreground (f, gc, false);
6691 cairo_rectangle (cr, x + 0.5, y + 0.5, width, height);
6692 cairo_set_line_width (cr, 1);
6693 cairo_stroke (cr);
6694 x_end_cr_clip (f);
6695 #else
6696 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
6697 gc, x, y, width, height);
6698 #endif
6699 }
6700
6701 static void
6702 x_clear_window (struct frame *f)
6703 {
6704 #ifdef USE_CAIRO
6705 cairo_t *cr;
6706
6707 cr = x_begin_cr_clip (f, NULL);
6708 x_set_cr_source_with_gc_background (f, f->output_data.x->normal_gc, true);
6709 cairo_paint (cr);
6710 x_end_cr_clip (f);
6711 #else
6712 #ifndef USE_GTK
6713 if (f->alpha_background != 1.0
6714 #ifdef HAVE_XDBE
6715 || FRAME_X_DOUBLE_BUFFERED_P (f)
6716 #endif
6717 )
6718 #endif
6719 x_clear_area (f, 0, 0, FRAME_PIXEL_WIDTH (f),
6720 FRAME_PIXEL_HEIGHT (f));
6721 #ifndef USE_GTK
6722 else
6723 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
6724 #endif
6725 #endif
6726 }
6727
6728 #ifdef USE_CAIRO
6729 static void
6730 x_fill_trapezoid_for_relief (struct frame *f, GC gc, int x, int y,
6731 int width, int height, int top_p)
6732 {
6733 cairo_t *cr;
6734
6735 cr = x_begin_cr_clip (f, gc);
6736 x_set_cr_source_with_gc_foreground (f, gc, false);
6737 cairo_move_to (cr, top_p ? x : x + height, y);
6738 cairo_line_to (cr, x, y + height);
6739 cairo_line_to (cr, top_p ? x + width - height : x + width, y + height);
6740 cairo_line_to (cr, x + width, y);
6741 cairo_fill (cr);
6742 x_end_cr_clip (f);
6743 }
6744
6745 enum corners
6746 {
6747 CORNER_BOTTOM_RIGHT,
6748 CORNER_BOTTOM_LEFT,
6749 CORNER_TOP_LEFT,
6750 CORNER_TOP_RIGHT,
6751 CORNER_LAST
6752 };
6753
6754 static void
6755 x_erase_corners_for_relief (struct frame *f, GC gc, int x, int y,
6756 int width, int height,
6757 double radius, double margin, int corners)
6758 {
6759 cairo_t *cr;
6760 int i;
6761
6762 cr = x_begin_cr_clip (f, gc);
6763 x_set_cr_source_with_gc_background (f, gc, false);
6764 for (i = 0; i < CORNER_LAST; i++)
6765 if (corners & (1 << i))
6766 {
6767 double xm, ym, xc, yc;
6768
6769 if (i == CORNER_TOP_LEFT || i == CORNER_BOTTOM_LEFT)
6770 xm = x - margin, xc = xm + radius;
6771 else
6772 xm = x + width + margin, xc = xm - radius;
6773 if (i == CORNER_TOP_LEFT || i == CORNER_TOP_RIGHT)
6774 ym = y - margin, yc = ym + radius;
6775 else
6776 ym = y + height + margin, yc = ym - radius;
6777
6778 cairo_move_to (cr, xm, ym);
6779 cairo_arc (cr, xc, yc, radius, i * M_PI_2, (i + 1) * M_PI_2);
6780 }
6781 cairo_clip (cr);
6782 cairo_rectangle (cr, x, y, width, height);
6783 cairo_fill (cr);
6784 x_end_cr_clip (f);
6785 }
6786
6787 static void
6788 x_draw_horizontal_wave (struct frame *f, GC gc, int x, int y,
6789 int width, int height, int wave_length)
6790 {
6791 cairo_t *cr;
6792 double dx = wave_length, dy = height - 1;
6793 int xoffset, n;
6794
6795 cr = x_begin_cr_clip (f, gc);
6796 x_set_cr_source_with_gc_foreground (f, gc, false);
6797 cairo_rectangle (cr, x, y, width, height);
6798 cairo_clip (cr);
6799
6800 if (x >= 0)
6801 {
6802 xoffset = x % (wave_length * 2);
6803 if (xoffset == 0)
6804 xoffset = wave_length * 2;
6805 }
6806 else
6807 xoffset = x % (wave_length * 2) + wave_length * 2;
6808 n = (width + xoffset) / wave_length + 1;
6809 if (xoffset > wave_length)
6810 {
6811 xoffset -= wave_length;
6812 --n;
6813 y += height - 1;
6814 dy = -dy;
6815 }
6816
6817 cairo_move_to (cr, x - xoffset + 0.5, y + 0.5);
6818 while (--n >= 0)
6819 {
6820 cairo_rel_line_to (cr, dx, dy);
6821 dy = -dy;
6822 }
6823 cairo_set_line_width (cr, 1);
6824 cairo_stroke (cr);
6825 x_end_cr_clip (f);
6826 }
6827 #endif
6828
6829
6830
6831
6832 struct x_display_info *
6833 x_display_info_for_display (Display *dpy)
6834 {
6835 struct x_display_info *dpyinfo;
6836
6837 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
6838 if (dpyinfo->display == dpy)
6839 return dpyinfo;
6840
6841 return 0;
6842 }
6843
6844 static Window
6845 x_find_topmost_parent (struct frame *f)
6846 {
6847 struct x_output *x = f->output_data.x;
6848 Window win = None, wi = x->parent_desc;
6849 Display *dpy = FRAME_X_DISPLAY (f);
6850
6851 while (wi != FRAME_DISPLAY_INFO (f)->root_window)
6852 {
6853 Window root;
6854 Window *children;
6855 unsigned int nchildren;
6856
6857 win = wi;
6858 if (XQueryTree (dpy, win, &root, &wi, &children, &nchildren))
6859 XFree (children);
6860 else
6861 break;
6862 }
6863
6864 return win;
6865 }
6866
6867 #define OPAQUE 0xffffffff
6868
6869 static void
6870 x_set_frame_alpha (struct frame *f)
6871 {
6872 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
6873 Display *dpy = FRAME_X_DISPLAY (f);
6874 Window win = FRAME_OUTER_WINDOW (f);
6875 double alpha = 1.0;
6876 double alpha_min = 1.0;
6877 unsigned long opac;
6878 Window parent;
6879
6880 if (dpyinfo->highlight_frame == f)
6881 alpha = f->alpha[0];
6882 else
6883 alpha = f->alpha[1];
6884
6885 if (alpha < 0.0)
6886 return;
6887
6888 if (FLOATP (Vframe_alpha_lower_limit))
6889 alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit);
6890 else if (FIXNUMP (Vframe_alpha_lower_limit))
6891 alpha_min = (XFIXNUM (Vframe_alpha_lower_limit)) / 100.0;
6892
6893 if (alpha > 1.0)
6894 alpha = 1.0;
6895 else if (alpha < alpha_min && alpha_min <= 1.0)
6896 alpha = alpha_min;
6897
6898 opac = alpha * OPAQUE;
6899
6900
6901
6902
6903
6904
6905 x_ignore_errors_for_next_request (dpyinfo, 0);
6906
6907 if (!FRAME_PARENT_FRAME (f))
6908 {
6909 parent = x_find_topmost_parent (f);
6910
6911 if (parent != None)
6912 {
6913 XChangeProperty (dpy, parent,
6914 dpyinfo->Xatom_net_wm_window_opacity,
6915 XA_CARDINAL, 32, PropModeReplace,
6916 (unsigned char *) &opac, 1);
6917 }
6918 }
6919
6920 XChangeProperty (dpy, win, dpyinfo->Xatom_net_wm_window_opacity,
6921 XA_CARDINAL, 32, PropModeReplace,
6922 (unsigned char *) &opac, 1);
6923 x_stop_ignoring_errors (dpyinfo);
6924 }
6925
6926
6927
6928
6929
6930 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
6931
6932
6933
6934
6935
6936
6937
6938 static int
6939 x_if_event (Display *dpy, XEvent *event_return,
6940 Bool (*predicate) (Display *, XEvent *, XPointer),
6941 XPointer arg, struct timespec timeout)
6942 {
6943 struct timespec current_time, target;
6944 int fd;
6945 fd_set fds;
6946
6947 fd = ConnectionNumber (dpy);
6948 current_time = current_timespec ();
6949 target = timespec_add (current_time, timeout);
6950
6951
6952
6953 if (XCheckIfEvent (dpy, event_return, predicate, arg))
6954 return 0;
6955
6956 while (true)
6957 {
6958
6959 XSync (dpy, False);
6960
6961
6962 if (XCheckIfEvent (dpy, event_return, predicate, arg))
6963 return 0;
6964
6965
6966 current_time = current_timespec ();
6967 timeout = timespec_sub (target, current_time);
6968
6969
6970
6971 FD_ZERO (&fds);
6972 FD_SET (fd, &fds);
6973
6974
6975
6976 pselect (fd + 1, &fds, NULL, NULL, &timeout, NULL);
6977
6978
6979 current_time = current_timespec ();
6980 if (timespec_cmp (target, current_time) < 0)
6981 return 1;
6982 }
6983 }
6984
6985
6986
6987
6988
6989 static uint_fast64_t
6990 x_sync_get_monotonic_time (struct x_display_info *dpyinfo,
6991 uint_fast64_t timestamp)
6992 {
6993 if (dpyinfo->server_time_monotonic_p)
6994 return timestamp;
6995
6996
6997 if (!dpyinfo->server_time_offset)
6998 return 0;
6999
7000 uint_fast64_t t;
7001 return ckd_sub (&t, timestamp, dpyinfo->server_time_offset) ? 0 : t;
7002 }
7003
7004 # ifndef CLOCK_MONOTONIC
7005 # define CLOCK_MONOTONIC CLOCK_REALTIME
7006 # endif
7007
7008
7009
7010
7011 static uint_fast64_t
7012 x_sync_current_monotonic_time (void)
7013 {
7014 struct timespec time;
7015 uint_fast64_t t;
7016 return (((clock_gettime (CLOCK_MONOTONIC, &time) != 0
7017 && (CLOCK_MONOTONIC == CLOCK_REALTIME
7018 || clock_gettime (CLOCK_REALTIME, &time) != 0))
7019 || ckd_mul (&t, time.tv_sec, 1000000)
7020 || ckd_add (&t, t, time.tv_nsec / 1000))
7021 ? 0 : t);
7022 }
7023
7024
7025
7026
7027 static void
7028 x_sync_note_frame_times (struct x_display_info *dpyinfo,
7029 struct frame *f, XEvent *event)
7030 {
7031 uint_fast64_t low, high, time;
7032 struct x_output *output;
7033
7034 low = event->xclient.data.l[2];
7035 high = event->xclient.data.l[3];
7036 output = FRAME_X_OUTPUT (f);
7037
7038 time = x_sync_get_monotonic_time (dpyinfo, low | (high << 32));
7039
7040 if (!time || !output->temp_frame_time
7041 || ckd_sub (&output->last_frame_time, time, output->temp_frame_time))
7042 output->last_frame_time = 0;
7043
7044 #ifdef FRAME_DEBUG
7045 uint_fast64_t last_frame_ms = output->last_frame_time / 1000;
7046 fprintf (stderr,
7047 "Drawing the last frame took: %"PRIuFAST64" ms (%"PRIuFAST64")\n",
7048 last_frame_ms, time);
7049 #endif
7050 }
7051
7052 static Bool
7053 x_sync_is_frame_drawn_event (Display *dpy, XEvent *event,
7054 XPointer user_data)
7055 {
7056 struct frame *f;
7057 struct x_display_info *dpyinfo;
7058
7059 f = (struct frame *) user_data;
7060 dpyinfo = FRAME_DISPLAY_INFO (f);
7061
7062 if (event->type == ClientMessage
7063 && (event->xclient.message_type
7064 == dpyinfo->Xatom_net_wm_frame_drawn)
7065 && event->xclient.window == FRAME_OUTER_WINDOW (f))
7066 return True;
7067
7068 return False;
7069 }
7070
7071
7072
7073
7074
7075 static void
7076 x_sync_wait_for_frame_drawn_event (struct frame *f)
7077 {
7078 XEvent event;
7079 struct x_display_info *dpyinfo;
7080
7081 if (!FRAME_X_WAITING_FOR_DRAW (f)
7082
7083
7084 || !FRAME_VISIBLE_P (f))
7085 return;
7086
7087 dpyinfo = FRAME_DISPLAY_INFO (f);
7088
7089
7090 if (x_if_event (FRAME_X_DISPLAY (f), &event,
7091 x_sync_is_frame_drawn_event, (XPointer) f,
7092 make_timespec (1, 0)))
7093 {
7094
7095
7096
7097 if (FRAME_X_DRAW_JUST_HUNG (f))
7098 {
7099 fprintf (stderr, "Warning: compositing manager spent more than 1 "
7100 "second drawing a frame. Frame synchronization has "
7101 "been disabled\n");
7102 FRAME_X_OUTPUT (f)->use_vsync_p = false;
7103
7104
7105
7106 XDeleteProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
7107 dpyinfo->Xatom_net_wm_bypass_compositor);
7108
7109
7110
7111 store_frame_param (f, Quse_frame_synchronization, Qnil);
7112 }
7113 else
7114 {
7115 fprintf (stderr, "Warning: compositing manager spent more than 1 "
7116 "second drawing a frame. Frame synchronization will be "
7117 "disabled if this happens again\n");
7118 FRAME_X_DRAW_JUST_HUNG (f) = true;
7119 }
7120 }
7121 else
7122 x_sync_note_frame_times (dpyinfo, f, &event);
7123
7124 FRAME_X_WAITING_FOR_DRAW (f) = false;
7125 }
7126
7127
7128
7129
7130 static void
7131 x_sync_update_begin (struct frame *f)
7132 {
7133 XSyncValue value, add;
7134 Bool overflow;
7135
7136 if (FRAME_X_EXTENDED_COUNTER (f) == None)
7137 return;
7138
7139 value = FRAME_X_COUNTER_VALUE (f);
7140
7141 if (FRAME_X_OUTPUT (f)->ext_sync_end_pending_p)
7142 {
7143 FRAME_X_COUNTER_VALUE (f)
7144 = FRAME_X_OUTPUT (f)->resize_counter_value;
7145
7146 value = FRAME_X_COUNTER_VALUE (f);
7147
7148 if (XSyncValueLow32 (value) % 2)
7149 {
7150 XSyncIntToValue (&add, 1);
7151 XSyncValueAdd (&value, value, add, &overflow);
7152
7153 if (overflow)
7154 XSyncIntToValue (&value, 0);
7155 }
7156
7157 FRAME_X_OUTPUT (f)->ext_sync_end_pending_p = false;
7158 }
7159
7160
7161
7162 if (XSyncValueLow32 (value) % 2)
7163 return;
7164
7165
7166 x_sync_wait_for_frame_drawn_event (f);
7167
7168
7169
7170 FRAME_X_OUTPUT (f)->temp_frame_time = x_sync_current_monotonic_time ();
7171
7172
7173
7174 if (XSyncValueLow32 (value) % 4 == 2)
7175 XSyncIntToValue (&add, 3);
7176 else
7177 XSyncIntToValue (&add, 1);
7178
7179 XSyncValueAdd (&FRAME_X_COUNTER_VALUE (f),
7180 value, add, &overflow);
7181
7182 if (overflow)
7183 XSyncIntToValue (&FRAME_X_COUNTER_VALUE (f), 3);
7184
7185 eassert (XSyncValueLow32 (FRAME_X_COUNTER_VALUE (f)) % 4 == 1);
7186
7187 XSyncSetCounter (FRAME_X_DISPLAY (f),
7188 FRAME_X_EXTENDED_COUNTER (f),
7189 FRAME_X_COUNTER_VALUE (f));
7190 }
7191
7192 #ifdef HAVE_XSYNCTRIGGERFENCE
7193
7194
7195
7196
7197 static void
7198 x_sync_trigger_fence (struct frame *f, XSyncValue value)
7199 {
7200 uint_fast64_t n, low, high, idx;
7201
7202
7203 if (FRAME_DISPLAY_INFO (f)->xsync_major < 3
7204 || (FRAME_DISPLAY_INFO (f)->xsync_major == 3
7205 && FRAME_DISPLAY_INFO (f)->xsync_minor < 1))
7206 return;
7207
7208 low = XSyncValueLow32 (value);
7209 high = XSyncValueHigh32 (value);
7210
7211 n = low | (high << 32);
7212 idx = (n / 4) % 2;
7213
7214 #ifdef FRAME_DEBUG
7215 fprintf (stderr, "Triggering synchronization fence: %lu\n", idx);
7216 #endif
7217
7218 XSyncTriggerFence (FRAME_X_DISPLAY (f),
7219 FRAME_X_OUTPUT (f)->sync_fences[idx]);
7220 }
7221
7222
7223
7224 void
7225 x_sync_init_fences (struct frame *f)
7226 {
7227 struct x_output *output;
7228 struct x_display_info *dpyinfo;
7229
7230 output = FRAME_X_OUTPUT (f);
7231 dpyinfo = FRAME_DISPLAY_INFO (f);
7232
7233
7234 if (dpyinfo->xsync_major < 3
7235 || (dpyinfo->xsync_major == 3
7236 && dpyinfo->xsync_minor < 1))
7237 return;
7238
7239 output->sync_fences[0]
7240 = XSyncCreateFence (FRAME_X_DISPLAY (f),
7241
7242
7243
7244 FRAME_X_WINDOW (f),
7245 False);
7246 output->sync_fences[1]
7247 = XSyncCreateFence (FRAME_X_DISPLAY (f),
7248 FRAME_X_WINDOW (f),
7249 False);
7250
7251 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
7252 dpyinfo->Xatom_net_wm_sync_fences, XA_CARDINAL,
7253 32, PropModeReplace,
7254 (unsigned char *) &output->sync_fences, 2);
7255 }
7256
7257 static void
7258 x_sync_free_fences (struct frame *f)
7259 {
7260 if (FRAME_X_OUTPUT (f)->sync_fences[0] != None)
7261 XSyncDestroyFence (FRAME_X_DISPLAY (f),
7262 FRAME_X_OUTPUT (f)->sync_fences[0]);
7263
7264 if (FRAME_X_OUTPUT (f)->sync_fences[1] != None)
7265 XSyncDestroyFence (FRAME_X_DISPLAY (f),
7266 FRAME_X_OUTPUT (f)->sync_fences[1]);
7267 }
7268
7269 #endif
7270
7271
7272
7273
7274 static void
7275 x_sync_update_finish (struct frame *f)
7276 {
7277 XSyncValue value, add;
7278 Bool overflow;
7279
7280 if (FRAME_X_EXTENDED_COUNTER (f) == None)
7281 return;
7282
7283 value = FRAME_X_COUNTER_VALUE (f);
7284
7285 if (!(XSyncValueLow32 (value) % 2))
7286 return;
7287
7288 if ((XSyncValueLow32 (value) % 4) == 1)
7289
7290
7291 XSyncIntToValue (&add, 3);
7292 else
7293
7294
7295 XSyncIntToValue (&add, 1);
7296
7297 XSyncValueAdd (&FRAME_X_COUNTER_VALUE (f),
7298 value, add, &overflow);
7299
7300 if (overflow)
7301 XSyncIntToValue (&FRAME_X_COUNTER_VALUE (f), 0);
7302
7303
7304 #ifdef HAVE_XSYNCTRIGGERFENCE
7305 x_sync_trigger_fence (f, FRAME_X_COUNTER_VALUE (f));
7306 #endif
7307
7308 XSyncSetCounter (FRAME_X_DISPLAY (f),
7309 FRAME_X_EXTENDED_COUNTER (f),
7310 FRAME_X_COUNTER_VALUE (f));
7311
7312 if (FRAME_OUTPUT_DATA (f)->use_vsync_p)
7313 FRAME_X_WAITING_FOR_DRAW (f) = true;
7314 }
7315
7316
7317
7318 static void
7319 x_sync_handle_frame_drawn (struct x_display_info *dpyinfo,
7320 XEvent *message, struct frame *f)
7321 {
7322 XSyncValue value, counter;
7323
7324 if (FRAME_OUTER_WINDOW (f) == message->xclient.window)
7325 {
7326 counter = FRAME_X_COUNTER_VALUE (f);
7327
7328
7329
7330 XSyncIntsToValue (&value,
7331 message->xclient.data.l[0] & 0xffffffff,
7332 message->xclient.data.l[1] & 0xffffffff);
7333
7334 if (XSyncValueEqual (value, counter))
7335 FRAME_X_WAITING_FOR_DRAW (f) = false;
7336
7337
7338
7339
7340 FRAME_X_DRAW_JUST_HUNG (f) = false;
7341 }
7342
7343 x_sync_note_frame_times (dpyinfo, f, message);
7344 }
7345 #endif
7346
7347
7348
7349
7350
7351
7352
7353 static void
7354 x_update_begin (struct frame *f)
7355 {
7356 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
7357
7358
7359 #ifdef HAVE_XDBE
7360 if (!FRAME_X_DOUBLE_BUFFERED_P (f))
7361 #endif
7362 x_sync_update_begin (f);
7363 #else
7364
7365 #endif
7366
7367 #ifdef HAVE_XDBE
7368 if (FRAME_X_DOUBLE_BUFFERED_P (f))
7369
7370
7371 FRAME_X_COMPLETE_P (f) = false;
7372 #endif
7373 }
7374
7375
7376
7377 static void
7378 x_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
7379 {
7380 struct frame *f = XFRAME (WINDOW_FRAME (w));
7381 struct face *face;
7382
7383 face = FACE_FROM_ID_OR_NULL (f, VERTICAL_BORDER_FACE_ID);
7384 if (face)
7385 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
7386 face->foreground);
7387
7388 #ifdef USE_CAIRO
7389 x_fill_rectangle (f, f->output_data.x->normal_gc, x, y0, 1, y1 - y0, false);
7390 #else
7391 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
7392 f->output_data.x->normal_gc, x, y0, x, y1);
7393 #endif
7394 }
7395
7396
7397
7398 static void
7399 x_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
7400 {
7401 struct frame *f = XFRAME (WINDOW_FRAME (w));
7402 struct face *face = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FACE_ID);
7403 struct face *face_first
7404 = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID);
7405 struct face *face_last
7406 = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_LAST_PIXEL_FACE_ID);
7407 unsigned long color = face ? face->foreground : FRAME_FOREGROUND_PIXEL (f);
7408 unsigned long color_first = (face_first
7409 ? face_first->foreground
7410 : FRAME_FOREGROUND_PIXEL (f));
7411 unsigned long color_last = (face_last
7412 ? face_last->foreground
7413 : FRAME_FOREGROUND_PIXEL (f));
7414 Display *display = FRAME_X_DISPLAY (f);
7415
7416 if ((y1 - y0 > x1 - x0) && (x1 - x0 >= 3))
7417
7418
7419 {
7420 XSetForeground (display, f->output_data.x->normal_gc, color_first);
7421 x_fill_rectangle (f, f->output_data.x->normal_gc,
7422 x0, y0, 1, y1 - y0, false);
7423 XSetForeground (display, f->output_data.x->normal_gc, color);
7424 x_fill_rectangle (f, f->output_data.x->normal_gc,
7425 x0 + 1, y0, x1 - x0 - 2, y1 - y0, false);
7426 XSetForeground (display, f->output_data.x->normal_gc, color_last);
7427 x_fill_rectangle (f, f->output_data.x->normal_gc,
7428 x1 - 1, y0, 1, y1 - y0, false);
7429 }
7430 else if ((x1 - x0 > y1 - y0) && (y1 - y0 >= 3))
7431
7432
7433 {
7434 XSetForeground (display, f->output_data.x->normal_gc, color_first);
7435 x_fill_rectangle (f, f->output_data.x->normal_gc,
7436 x0, y0, x1 - x0, 1, false);
7437 XSetForeground (display, f->output_data.x->normal_gc, color);
7438 x_fill_rectangle (f, f->output_data.x->normal_gc,
7439 x0, y0 + 1, x1 - x0, y1 - y0 - 2, false);
7440 XSetForeground (display, f->output_data.x->normal_gc, color_last);
7441 x_fill_rectangle (f, f->output_data.x->normal_gc,
7442 x0, y1 - 1, x1 - x0, 1, false);
7443 }
7444 else
7445 {
7446
7447
7448 XSetForeground (display, f->output_data.x->normal_gc, color);
7449 x_fill_rectangle (f, f->output_data.x->normal_gc,
7450 x0, y0, x1 - x0, y1 - y0, false);
7451 }
7452 }
7453
7454 #ifdef HAVE_XDBE
7455
7456
7457
7458
7459
7460 static void
7461 show_back_buffer (struct frame *f)
7462 {
7463 XdbeSwapInfo swap_info;
7464 #ifdef USE_CAIRO
7465 cairo_t *cr;
7466 #endif
7467
7468 if (FRAME_X_DOUBLE_BUFFERED_P (f))
7469 {
7470 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
7471
7472
7473 x_sync_wait_for_frame_drawn_event (f);
7474
7475
7476 x_sync_update_begin (f);
7477 #endif
7478
7479 #ifdef USE_CAIRO
7480 cr = FRAME_CR_CONTEXT (f);
7481 if (cr)
7482 cairo_surface_flush (cairo_get_target (cr));
7483 #endif
7484 memset (&swap_info, 0, sizeof (swap_info));
7485 swap_info.swap_window = FRAME_X_WINDOW (f);
7486 swap_info.swap_action = XdbeCopied;
7487 XdbeSwapBuffers (FRAME_X_DISPLAY (f), &swap_info, 1);
7488
7489 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
7490
7491 x_sync_update_finish (f);
7492 #endif
7493 }
7494
7495 FRAME_X_NEED_BUFFER_FLIP (f) = false;
7496 }
7497
7498 #endif
7499
7500
7501
7502
7503 static void
7504 x_flip_and_flush (struct frame *f)
7505 {
7506
7507
7508
7509 if (!NILP (Vinhibit_redisplay)
7510
7511
7512 && !FRAME_TOOLTIP_P (f))
7513 return;
7514
7515 block_input ();
7516 #ifdef HAVE_XDBE
7517 if (FRAME_X_NEED_BUFFER_FLIP (f))
7518 show_back_buffer (f);
7519
7520
7521
7522 FRAME_X_COMPLETE_P (f) = true;
7523 #endif
7524 x_flush (f);
7525 unblock_input ();
7526 }
7527
7528
7529
7530
7531 static void
7532 x_update_end (struct frame *f)
7533 {
7534
7535 MOUSE_HL_INFO (f)->mouse_face_defer = false;
7536
7537 #ifdef USE_CAIRO
7538 # ifdef HAVE_XDBE
7539 if (!FRAME_X_DOUBLE_BUFFERED_P (f) && FRAME_CR_CONTEXT (f))
7540 cairo_surface_flush (cairo_get_target (FRAME_CR_CONTEXT (f)));
7541 # endif
7542 #endif
7543
7544
7545
7546
7547 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
7548 #ifdef HAVE_XDBE
7549 if (!FRAME_X_DOUBLE_BUFFERED_P (f))
7550 #endif
7551 x_sync_update_finish (f);
7552 #endif
7553 }
7554
7555
7556
7557
7558 static void
7559 XTframe_up_to_date (struct frame *f)
7560 {
7561 #if defined HAVE_XSYNC && defined HAVE_GTK3
7562 GtkWidget *widget;
7563 GdkWindow *window;
7564 GdkFrameClock *clock;
7565 #endif
7566
7567 eassert (FRAME_X_P (f));
7568 block_input ();
7569 FRAME_MOUSE_UPDATE (f);
7570
7571 #ifdef HAVE_XDBE
7572 if (!buffer_flipping_blocked_p ()
7573 && FRAME_X_NEED_BUFFER_FLIP (f))
7574 show_back_buffer (f);
7575
7576
7577 FRAME_X_COMPLETE_P (f) = true;
7578 #endif
7579
7580 #ifdef HAVE_XSYNC
7581 #ifndef HAVE_GTK3
7582 if (FRAME_X_OUTPUT (f)->sync_end_pending_p
7583 && FRAME_X_BASIC_COUNTER (f) != None)
7584 {
7585 XSyncSetCounter (FRAME_X_DISPLAY (f),
7586 FRAME_X_BASIC_COUNTER (f),
7587 FRAME_X_OUTPUT (f)->pending_basic_counter_value);
7588 FRAME_X_OUTPUT (f)->sync_end_pending_p = false;
7589 }
7590 #else
7591 if (FRAME_X_OUTPUT (f)->xg_sync_end_pending_p)
7592 {
7593 widget = FRAME_GTK_OUTER_WIDGET (f);
7594 window = gtk_widget_get_window (widget);
7595 eassert (window);
7596 clock = gdk_window_get_frame_clock (window);
7597 eassert (clock);
7598
7599 gdk_frame_clock_request_phase (clock,
7600 GDK_FRAME_CLOCK_PHASE_AFTER_PAINT);
7601 FRAME_X_OUTPUT (f)->xg_sync_end_pending_p = false;
7602 }
7603 #endif
7604 #endif
7605 unblock_input ();
7606 }
7607
7608 #ifdef HAVE_XDBE
7609 static void
7610 XTbuffer_flipping_unblocked_hook (struct frame *f)
7611 {
7612 block_input ();
7613
7614 if (FRAME_X_NEED_BUFFER_FLIP (f))
7615 show_back_buffer (f);
7616
7617 unblock_input ();
7618 }
7619 #endif
7620
7621
7622
7623
7624
7625
7626
7627 void
7628 x_clear_under_internal_border (struct frame *f)
7629 {
7630 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0)
7631 {
7632 int border = FRAME_INTERNAL_BORDER_WIDTH (f);
7633 int width = FRAME_PIXEL_WIDTH (f);
7634 int height = FRAME_PIXEL_HEIGHT (f);
7635 int margin = FRAME_TOP_MARGIN_HEIGHT (f);
7636 int bottom_margin = FRAME_BOTTOM_MARGIN_HEIGHT (f);
7637 int face_id = (FRAME_PARENT_FRAME (f)
7638 ? (!NILP (Vface_remapping_alist)
7639 ? lookup_basic_face (NULL, f,
7640 CHILD_FRAME_BORDER_FACE_ID)
7641 : CHILD_FRAME_BORDER_FACE_ID)
7642 : (!NILP (Vface_remapping_alist)
7643 ? lookup_basic_face (NULL, f,
7644 INTERNAL_BORDER_FACE_ID)
7645 : INTERNAL_BORDER_FACE_ID));
7646 struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
7647
7648 if (face)
7649 {
7650 unsigned long color = face->background;
7651 Display *display = FRAME_X_DISPLAY (f);
7652 GC gc = f->output_data.x->normal_gc;
7653
7654 XSetForeground (display, gc, color);
7655 x_fill_rectangle (f, gc, 0, margin, width, border, false);
7656 x_fill_rectangle (f, gc, 0, 0, border, height, false);
7657 x_fill_rectangle (f, gc, width - border, 0, border, height, false);
7658 x_fill_rectangle (f, gc, 0, height - bottom_margin - border,
7659 width, border, false);
7660 XSetForeground (display, gc, FRAME_FOREGROUND_PIXEL (f));
7661 }
7662 else
7663 {
7664 x_clear_area (f, 0, 0, border, height);
7665 x_clear_area (f, 0, margin, width, border);
7666 x_clear_area (f, width - border, 0, border, height);
7667 x_clear_area (f, 0, height - bottom_margin - border,
7668 width, border);
7669 }
7670 }
7671 }
7672
7673
7674
7675
7676
7677
7678
7679 static void
7680 x_after_update_window_line (struct window *w, struct glyph_row *desired_row)
7681 {
7682 eassert (w);
7683
7684 if (!desired_row->mode_line_p && !w->pseudo_window_p)
7685 desired_row->redraw_fringe_bitmaps_p = true;
7686
7687 #ifdef USE_X_TOOLKIT
7688
7689
7690
7691
7692
7693
7694 {
7695 struct frame *f;
7696 int width, height;
7697
7698 if (windows_or_buffers_changed
7699 && desired_row->full_width_p
7700 && (f = XFRAME (w->frame),
7701 width = FRAME_INTERNAL_BORDER_WIDTH (f),
7702 width != 0)
7703 && (height = desired_row->visible_height,
7704 height > 0))
7705 {
7706 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
7707 int face_id =
7708 (FRAME_PARENT_FRAME (f)
7709 ? (!NILP (Vface_remapping_alist)
7710 ? lookup_basic_face (NULL, f, CHILD_FRAME_BORDER_FACE_ID)
7711 : CHILD_FRAME_BORDER_FACE_ID)
7712 : (!NILP (Vface_remapping_alist)
7713 ? lookup_basic_face (NULL, f, INTERNAL_BORDER_FACE_ID)
7714 : INTERNAL_BORDER_FACE_ID));
7715 struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
7716
7717 if (face)
7718 {
7719 unsigned long color = face->background;
7720 Display *display = FRAME_X_DISPLAY (f);
7721 GC gc = f->output_data.x->normal_gc;
7722
7723 XSetForeground (display, gc, color);
7724 x_fill_rectangle (f, gc, 0, y, width, height, true);
7725 x_fill_rectangle (f, gc, FRAME_PIXEL_WIDTH (f) - width, y,
7726 width, height, true);
7727 XSetForeground (display, gc, FRAME_FOREGROUND_PIXEL (f));
7728 }
7729 else
7730 {
7731 x_clear_area (f, 0, y, width, height);
7732 x_clear_area (f, FRAME_PIXEL_WIDTH (f) - width, y, width, height);
7733 }
7734 }
7735 }
7736 #endif
7737 }
7738
7739
7740
7741
7742
7743
7744
7745
7746 #ifndef USE_CAIRO
7747
7748 static unsigned long
7749 x_premultiply_pixel (struct x_display_info *dpyinfo,
7750 XColor *color, double alpha)
7751 {
7752 unsigned long pixel;
7753
7754 eassert (dpyinfo->alpha_bits);
7755
7756
7757 color->red *= alpha;
7758 color->green *= alpha;
7759 color->blue *= alpha;
7760
7761
7762 pixel = x_make_truecolor_pixel (dpyinfo, color->red,
7763 color->green,
7764 color->blue);
7765
7766
7767 pixel &= ~dpyinfo->alpha_mask;
7768
7769
7770 pixel |= (((unsigned long) (alpha * 65535)
7771 >> (16 - dpyinfo->alpha_bits))
7772 << dpyinfo->alpha_offset);
7773
7774 return pixel;
7775 }
7776
7777 #endif
7778
7779 static void
7780 x_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
7781 struct draw_fringe_bitmap_params *p)
7782 {
7783 struct frame *f = XFRAME (WINDOW_FRAME (w));
7784 Display *display = FRAME_X_DISPLAY (f);
7785 GC gc = f->output_data.x->normal_gc;
7786 struct face *face = p->face;
7787
7788
7789 x_clip_to_row (w, row, ANY_AREA, gc);
7790
7791 if (p->bx >= 0 && !p->overlay_p)
7792 {
7793
7794
7795
7796
7797 if (face->stipple)
7798 {
7799 XSetFillStyle (display, face->gc, FillOpaqueStippled);
7800 x_fill_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny,
7801 true);
7802 XSetFillStyle (display, face->gc, FillSolid);
7803
7804 row->stipple_p = true;
7805 }
7806 else
7807 {
7808 XSetBackground (display, face->gc, face->background);
7809 x_clear_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny,
7810 true);
7811 XSetForeground (display, face->gc, face->foreground);
7812 }
7813 }
7814
7815 #ifdef USE_CAIRO
7816 if (p->which
7817 && p->which < max_fringe_bmp
7818 && p->which < max_used_fringe_bitmap)
7819 {
7820 XGCValues gcv;
7821
7822 XGetGCValues (display, gc, GCForeground | GCBackground, &gcv);
7823 XSetForeground (display, gc, (p->cursor_p
7824 ? (p->overlay_p ? face->background
7825 : f->output_data.x->cursor_pixel)
7826 : face->foreground));
7827 XSetBackground (display, gc, face->background);
7828 if (!fringe_bmp[p->which])
7829 {
7830
7831
7832
7833
7834
7835
7836 gui_define_fringe_bitmap (f, p->which);
7837 }
7838 x_cr_draw_image (f, gc, fringe_bmp[p->which], 0, p->dh,
7839 p->wd, p->h, p->x, p->y, p->overlay_p);
7840 XSetForeground (display, gc, gcv.foreground);
7841 XSetBackground (display, gc, gcv.background);
7842 }
7843 #else
7844 if (p->which)
7845 {
7846 Drawable drawable = FRAME_X_DRAWABLE (f);
7847 char *bits;
7848 Pixmap pixmap, clipmask = None;
7849 int depth = FRAME_DISPLAY_INFO (f)->n_planes;
7850 XGCValues gcv;
7851 unsigned long background = face->background;
7852 XColor bg;
7853 #ifdef HAVE_XRENDER
7854 Picture picture = None;
7855 XRenderPictureAttributes attrs;
7856
7857 memset (&attrs, 0, sizeof attrs);
7858 #endif
7859
7860 if (p->wd > 8)
7861 bits = (char *) (p->bits + p->dh);
7862 else
7863 bits = (char *) p->bits + p->dh;
7864
7865 if (FRAME_DISPLAY_INFO (f)->alpha_bits
7866 && f->alpha_background < 1.0)
7867 {
7868
7869
7870 bg.pixel = background;
7871 x_query_colors (f, &bg, 1);
7872
7873 background
7874 = x_premultiply_pixel (FRAME_DISPLAY_INFO (f),
7875 &bg,
7876 f->alpha_background);
7877 }
7878
7879
7880
7881 pixmap = XCreatePixmapFromBitmapData (display, drawable, bits, p->wd, p->h,
7882 (p->cursor_p
7883 ? (p->overlay_p ? face->background
7884 : f->output_data.x->cursor_pixel)
7885 : face->foreground),
7886 background, depth);
7887
7888 #ifdef HAVE_XRENDER
7889 if (FRAME_X_PICTURE_FORMAT (f)
7890 && (x_xr_ensure_picture (f), FRAME_X_PICTURE (f)))
7891 picture = XRenderCreatePicture (display, pixmap,
7892 FRAME_X_PICTURE_FORMAT (f),
7893 0, &attrs);
7894 #endif
7895
7896 if (p->overlay_p)
7897 {
7898 clipmask = XCreatePixmapFromBitmapData (display,
7899 FRAME_DISPLAY_INFO (f)->root_window,
7900 bits, p->wd, p->h,
7901 1, 0, 1);
7902
7903 #ifdef HAVE_XRENDER
7904 if (picture != None)
7905 {
7906 attrs.clip_mask = clipmask;
7907 attrs.clip_x_origin = p->x;
7908 attrs.clip_y_origin = p->y;
7909
7910 XRenderChangePicture (display, FRAME_X_PICTURE (f),
7911 CPClipMask | CPClipXOrigin | CPClipYOrigin,
7912 &attrs);
7913 }
7914 else
7915 #endif
7916 {
7917 gcv.clip_mask = clipmask;
7918 gcv.clip_x_origin = p->x;
7919 gcv.clip_y_origin = p->y;
7920 XChangeGC (display, gc, GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv);
7921 }
7922 }
7923
7924 #ifdef HAVE_XRENDER
7925 if (picture != None)
7926 {
7927 x_xr_apply_ext_clip (f, gc);
7928 XRenderComposite (display, PictOpSrc, picture,
7929 None, FRAME_X_PICTURE (f),
7930 0, 0, 0, 0, p->x, p->y, p->wd, p->h);
7931 x_xr_reset_ext_clip (f);
7932
7933 XRenderFreePicture (display, picture);
7934 }
7935 else
7936 #endif
7937 XCopyArea (display, pixmap, drawable, gc, 0, 0,
7938 p->wd, p->h, p->x, p->y);
7939 XFreePixmap (display, pixmap);
7940
7941 if (p->overlay_p)
7942 {
7943 gcv.clip_mask = (Pixmap) 0;
7944 XChangeGC (display, gc, GCClipMask, &gcv);
7945 XFreePixmap (display, clipmask);
7946 }
7947 }
7948 #endif
7949
7950 x_reset_clip_rectangles (f, gc);
7951 }
7952
7953
7954
7955
7956
7957 static bool x_alloc_lighter_color (struct frame *, Display *, Colormap,
7958 unsigned long *, double, int);
7959 static void x_scroll_bar_clear (struct frame *);
7960
7961 #ifdef GLYPH_DEBUG
7962 static void x_check_font (struct frame *, struct font *);
7963 #endif
7964
7965
7966
7967
7968
7969
7970
7971
7972
7973
7974
7975
7976
7977
7978
7979
7980
7981
7982
7983
7984
7985
7986
7987 static void
7988 x_display_set_last_user_time (struct x_display_info *dpyinfo, Time time,
7989 bool send_event, bool set_property)
7990 {
7991 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
7992 uint_fast64_t monotonic_time;
7993 uint_fast64_t monotonic_ms;
7994 int_fast64_t diff_ms;
7995 #endif
7996 #ifndef USE_GTK
7997 struct frame *focus_frame;
7998 Time old_time;
7999
8000 focus_frame = dpyinfo->x_focus_frame;
8001 old_time = dpyinfo->last_user_time;
8002 #endif
8003
8004 #ifdef ENABLE_CHECKING
8005 eassert (time <= X_ULONG_MAX);
8006 #endif
8007
8008 if (!send_event || time > dpyinfo->last_user_time)
8009 dpyinfo->last_user_time = time;
8010
8011 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
8012 if (!send_event)
8013 {
8014
8015
8016 monotonic_time = x_sync_current_monotonic_time ();
8017 monotonic_ms = monotonic_time / 1000;
8018
8019 dpyinfo->server_time_monotonic_p
8020 = (monotonic_time != 0
8021 && !ckd_sub (&diff_ms, time, monotonic_ms)
8022 && -500 < diff_ms && diff_ms < 500);
8023
8024 if (!dpyinfo->server_time_monotonic_p)
8025 {
8026
8027
8028
8029 if (!monotonic_time
8030 || ckd_mul (&dpyinfo->server_time_offset, time, 1000)
8031 || ckd_sub (&dpyinfo->server_time_offset,
8032 dpyinfo->server_time_offset, monotonic_time))
8033 dpyinfo->server_time_offset = 0;
8034
8035
8036
8037
8038
8039
8040 monotonic_ms = monotonic_ms & 0xffffffff;
8041 if (!ckd_sub (&diff_ms, time, monotonic_ms)
8042 && -500 < diff_ms && diff_ms < 500)
8043 {
8044
8045
8046
8047 if (ckd_sub (&dpyinfo->server_time_offset,
8048 monotonic_time / 1000, monotonic_ms)
8049 || ckd_mul (&dpyinfo->server_time_offset,
8050 dpyinfo->server_time_offset, 1000)
8051 || ckd_sub (&dpyinfo->server_time_offset,
8052 0, dpyinfo->server_time_offset))
8053 dpyinfo->server_time_offset = 0;
8054 }
8055 }
8056 }
8057 #endif
8058
8059 #ifndef USE_GTK
8060
8061 if (focus_frame && old_time != dpyinfo->last_user_time
8062 && set_property)
8063 {
8064 time = dpyinfo->last_user_time;
8065
8066 while (FRAME_PARENT_FRAME (focus_frame))
8067 focus_frame = FRAME_PARENT_FRAME (focus_frame);
8068
8069 if (FRAME_X_OUTPUT (focus_frame)->user_time_window != None)
8070 XChangeProperty (dpyinfo->display,
8071 FRAME_X_OUTPUT (focus_frame)->user_time_window,
8072 dpyinfo->Xatom_net_wm_user_time,
8073 XA_CARDINAL, 32, PropModeReplace,
8074 (unsigned char *) &time, 1);
8075 }
8076 #endif
8077 }
8078
8079 #ifdef USE_GTK
8080
8081 static void
8082 x_set_gtk_user_time (struct frame *f, Time time)
8083 {
8084 GtkWidget *widget;
8085 GdkWindow *window;
8086
8087 widget = FRAME_GTK_OUTER_WIDGET (f);
8088 window = gtk_widget_get_window (widget);
8089
8090
8091 if (!window)
8092 return;
8093
8094 gdk_x11_window_set_user_time (window, time);
8095 }
8096
8097 #endif
8098
8099 #if !defined USE_GTK || defined HAVE_XFIXES
8100
8101
8102
8103
8104
8105
8106 static Window
8107 x_create_special_window (struct x_display_info *dpyinfo,
8108 Window parent_window)
8109 {
8110 XSetWindowAttributes attrs;
8111
8112 attrs.override_redirect = True;
8113
8114 return XCreateWindow (dpyinfo->display, parent_window,
8115 -1, -1, 1, 1, 0, CopyFromParent, InputOnly,
8116 CopyFromParent, CWOverrideRedirect, &attrs);
8117 }
8118
8119 #endif
8120
8121
8122
8123
8124 #ifndef USE_GTK
8125
8126 static void
8127 x_update_frame_user_time_window (struct frame *f)
8128 {
8129 struct x_output *output;
8130 struct x_display_info *dpyinfo;
8131
8132 output = FRAME_X_OUTPUT (f);
8133 dpyinfo = FRAME_DISPLAY_INFO (f);
8134
8135 if (!NILP (Vx_no_window_manager)
8136 || !x_wm_supports (f, dpyinfo->Xatom_net_wm_user_time))
8137 {
8138 if (output->user_time_window != None
8139 && output->user_time_window != FRAME_OUTER_WINDOW (f))
8140 {
8141 XDestroyWindow (dpyinfo->display, output->user_time_window);
8142 XDeleteProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
8143 dpyinfo->Xatom_net_wm_user_time_window);
8144 }
8145 else
8146 XDeleteProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
8147 dpyinfo->Xatom_net_wm_user_time);
8148
8149 output->user_time_window = None;
8150 return;
8151 }
8152
8153 if (!x_wm_supports (f, dpyinfo->Xatom_net_wm_user_time_window))
8154 {
8155 if (output->user_time_window == None)
8156 output->user_time_window = FRAME_OUTER_WINDOW (f);
8157 else if (output->user_time_window != FRAME_OUTER_WINDOW (f))
8158 {
8159 XDestroyWindow (dpyinfo->display,
8160 output->user_time_window);
8161 XDeleteProperty (dpyinfo->display,
8162 FRAME_OUTER_WINDOW (f),
8163 dpyinfo->Xatom_net_wm_user_time_window);
8164 output->user_time_window = FRAME_OUTER_WINDOW (f);
8165 }
8166 }
8167 else
8168 {
8169 if (output->user_time_window == FRAME_OUTER_WINDOW (f)
8170 || output->user_time_window == None)
8171 {
8172
8173
8174
8175
8176
8177
8178
8179
8180 output->user_time_window
8181 = x_create_special_window (dpyinfo, FRAME_X_WINDOW (f));
8182
8183 XDeleteProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
8184 dpyinfo->Xatom_net_wm_user_time);
8185 XChangeProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
8186 dpyinfo->Xatom_net_wm_user_time_window,
8187 XA_WINDOW, 32, PropModeReplace,
8188 (unsigned char *) &output->user_time_window, 1);
8189 }
8190 }
8191 }
8192
8193 #endif
8194
8195 void
8196 x_set_last_user_time_from_lisp (struct x_display_info *dpyinfo,
8197 Time time)
8198 {
8199 x_display_set_last_user_time (dpyinfo, time, true, true);
8200 }
8201
8202
8203
8204
8205
8206 static void
8207 x_set_cursor_gc (struct glyph_string *s)
8208 {
8209 if (s->font == FRAME_FONT (s->f)
8210 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
8211 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
8212 && !s->cmp)
8213 s->gc = s->f->output_data.x->cursor_gc;
8214 else
8215 {
8216
8217 XGCValues xgcv;
8218 unsigned long mask;
8219 Display *display = FRAME_X_DISPLAY (s->f);
8220
8221 xgcv.background = s->f->output_data.x->cursor_pixel;
8222 xgcv.foreground = s->face->background;
8223
8224
8225 if (xgcv.foreground == xgcv.background)
8226 xgcv.foreground = s->face->foreground;
8227 if (xgcv.foreground == xgcv.background)
8228 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
8229 if (xgcv.foreground == xgcv.background)
8230 xgcv.foreground = s->face->foreground;
8231
8232
8233 if (xgcv.background == s->face->background
8234 && xgcv.foreground == s->face->foreground)
8235 {
8236 xgcv.background = s->face->foreground;
8237 xgcv.foreground = s->face->background;
8238 }
8239
8240 IF_DEBUG (x_check_font (s->f, s->font));
8241 xgcv.graphics_exposures = False;
8242 xgcv.line_width = 1;
8243 mask = (GCForeground | GCBackground
8244 | GCGraphicsExposures
8245 | GCLineWidth);
8246
8247 if (FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc)
8248 XChangeGC (display, FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc,
8249 mask, &xgcv);
8250 else
8251 FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc
8252 = XCreateGC (display, FRAME_X_DRAWABLE (s->f), mask, &xgcv);
8253
8254 s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc;
8255 }
8256 }
8257
8258
8259
8260
8261 static void
8262 x_set_mouse_face_gc (struct glyph_string *s)
8263 {
8264 if (s->font == s->face->font)
8265 s->gc = s->face->gc;
8266 else
8267 {
8268
8269
8270 XGCValues xgcv;
8271 unsigned long mask;
8272 Display *display = FRAME_X_DISPLAY (s->f);
8273
8274 xgcv.background = s->face->background;
8275 xgcv.foreground = s->face->foreground;
8276 xgcv.graphics_exposures = False;
8277 xgcv.line_width = 1;
8278
8279 mask = (GCForeground | GCBackground
8280 | GCGraphicsExposures
8281 | GCLineWidth);
8282
8283 if (FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc)
8284 XChangeGC (display, FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc,
8285 mask, &xgcv);
8286 else
8287 FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc
8288 = XCreateGC (display, FRAME_X_DRAWABLE (s->f), mask, &xgcv);
8289
8290 s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc;
8291
8292 }
8293 eassert (s->gc != 0);
8294 }
8295
8296
8297
8298
8299
8300
8301 static void
8302 x_set_mode_line_face_gc (struct glyph_string *s)
8303 {
8304 s->gc = s->face->gc;
8305 }
8306
8307
8308
8309
8310
8311
8312 static void
8313 x_set_glyph_string_gc (struct glyph_string *s)
8314 {
8315 prepare_face_for_display (s->f, s->face);
8316
8317 if (s->hl == DRAW_NORMAL_TEXT)
8318 {
8319 s->gc = s->face->gc;
8320 s->stippled_p = s->face->stipple != 0;
8321 }
8322 else if (s->hl == DRAW_INVERSE_VIDEO)
8323 {
8324 x_set_mode_line_face_gc (s);
8325 s->stippled_p = s->face->stipple != 0;
8326 }
8327 else if (s->hl == DRAW_CURSOR)
8328 {
8329 x_set_cursor_gc (s);
8330 s->stippled_p = false;
8331 }
8332 else if (s->hl == DRAW_MOUSE_FACE)
8333 {
8334 x_set_mouse_face_gc (s);
8335 s->stippled_p = s->face->stipple != 0;
8336 }
8337 else if (s->hl == DRAW_IMAGE_RAISED
8338 || s->hl == DRAW_IMAGE_SUNKEN)
8339 {
8340 s->gc = s->face->gc;
8341 s->stippled_p = s->face->stipple != 0;
8342 }
8343 else
8344 emacs_abort ();
8345
8346
8347 eassert (s->gc != 0);
8348 }
8349
8350
8351
8352
8353
8354 static void
8355 x_set_glyph_string_clipping (struct glyph_string *s)
8356 {
8357 XRectangle *r = s->clip;
8358 int n = get_glyph_string_clip_rects (s, r, 2);
8359
8360 if (n > 0)
8361 x_set_clip_rectangles (s->f, s->gc, r, n);
8362 s->num_clips = n;
8363 }
8364
8365
8366
8367
8368
8369
8370 static void
8371 x_set_glyph_string_clipping_exactly (struct glyph_string *src, struct glyph_string *dst)
8372 {
8373 XRectangle r;
8374
8375 r.x = src->x;
8376 r.width = src->width;
8377 r.y = src->y;
8378 r.height = src->height;
8379 dst->clip[0] = r;
8380 dst->num_clips = 1;
8381 x_set_clip_rectangles (dst->f, dst->gc, &r, 1);
8382 }
8383
8384
8385
8386
8387
8388 static void
8389 x_compute_glyph_string_overhangs (struct glyph_string *s)
8390 {
8391 if (s->cmp == NULL
8392 && (s->first_glyph->type == CHAR_GLYPH
8393 || s->first_glyph->type == COMPOSITE_GLYPH))
8394 {
8395 struct font_metrics metrics;
8396
8397 if (s->first_glyph->type == CHAR_GLYPH)
8398 {
8399 struct font *font = s->font;
8400 font->driver->text_extents (font, s->char2b, s->nchars, &metrics);
8401 }
8402 else
8403 {
8404 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
8405
8406 composition_gstring_width (gstring, s->cmp_from, s->cmp_to, &metrics);
8407 }
8408 s->right_overhang = (metrics.rbearing > metrics.width
8409 ? metrics.rbearing - metrics.width : 0);
8410 s->left_overhang = metrics.lbearing < 0 ? - metrics.lbearing : 0;
8411 }
8412 else if (s->cmp)
8413 {
8414 s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width;
8415 s->left_overhang = - s->cmp->lbearing;
8416 }
8417 }
8418
8419
8420
8421
8422 static void
8423 x_clear_glyph_string_rect (struct glyph_string *s, int x, int y, int w, int h)
8424 {
8425 x_clear_rectangle (s->f, s->gc, x, y, w, h, s->hl != DRAW_CURSOR);
8426 }
8427
8428 #ifndef USE_CAIRO
8429
8430 static void
8431 x_clear_point (struct frame *f, GC gc, int x, int y,
8432 bool respect_alpha_background)
8433 {
8434 XGCValues xgcv;
8435 Display *dpy;
8436
8437 dpy = FRAME_X_DISPLAY (f);
8438
8439 if (f->alpha_background != 1.0
8440 && respect_alpha_background)
8441 {
8442 x_clear_rectangle (f, gc, x, y, 1, 1, true);
8443 return;
8444 }
8445
8446 XGetGCValues (dpy, gc, GCBackground | GCForeground, &xgcv);
8447 XSetForeground (dpy, gc, xgcv.background);
8448 XDrawPoint (dpy, FRAME_X_DRAWABLE (f), gc, x, y);
8449 XSetForeground (dpy, gc, xgcv.foreground);
8450 }
8451
8452 #endif
8453
8454
8455
8456
8457
8458
8459
8460 static void
8461 x_draw_glyph_string_background (struct glyph_string *s, bool force_p)
8462 {
8463
8464
8465 if (!s->background_filled_p)
8466 {
8467 int box_line_width = max (s->face->box_horizontal_line_width, 0);
8468
8469 if (s->stippled_p)
8470 {
8471 Display *display = FRAME_X_DISPLAY (s->f);
8472
8473
8474 XSetFillStyle (display, s->gc, FillOpaqueStippled);
8475 x_fill_rectangle (s->f, s->gc, s->x,
8476 s->y + box_line_width,
8477 s->background_width,
8478 s->height - 2 * box_line_width,
8479 s->hl != DRAW_CURSOR);
8480 XSetFillStyle (display, s->gc, FillSolid);
8481 s->background_filled_p = true;
8482 }
8483 else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
8484
8485
8486
8487
8488 || FONT_TOO_HIGH (s->font)
8489 || s->font_not_found_p
8490 || s->extends_to_end_of_line_p
8491 || force_p)
8492 {
8493 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
8494 s->background_width,
8495 s->height - 2 * box_line_width);
8496 s->background_filled_p = true;
8497 }
8498 }
8499 }
8500
8501
8502
8503
8504 static void
8505 x_draw_glyph_string_foreground (struct glyph_string *s)
8506 {
8507 int i, x;
8508
8509
8510
8511 if (s->face->box != FACE_NO_BOX
8512 && s->first_glyph->left_box_line_p)
8513 x = s->x + max (s->face->box_vertical_line_width, 0);
8514 else
8515 x = s->x;
8516
8517
8518
8519 if (s->font_not_found_p)
8520 {
8521 for (i = 0; i < s->nchars; ++i)
8522 {
8523 struct glyph *g = s->first_glyph + i;
8524 x_draw_rectangle (s->f,
8525 s->gc, x, s->y, g->pixel_width - 1,
8526 s->height - 1);
8527 x += g->pixel_width;
8528 }
8529 }
8530 else
8531 {
8532 struct font *font = s->font;
8533 #ifdef USE_CAIRO
8534 if (!EQ (font->driver->type, Qx)
8535 || x_try_cr_xlib_drawable (s->f, s->gc))
8536 {
8537 #endif
8538 int boff = font->baseline_offset;
8539 int y;
8540
8541 if (font->vertical_centering)
8542 boff = VCENTER_BASELINE_OFFSET (font, s->f) - boff;
8543
8544 y = s->ybase - boff;
8545 if (s->for_overlaps
8546 || (s->background_filled_p && s->hl != DRAW_CURSOR))
8547 font->driver->draw (s, 0, s->nchars, x, y, false);
8548 else
8549 font->driver->draw (s, 0, s->nchars, x, y, true);
8550 if (s->face->overstrike)
8551 font->driver->draw (s, 0, s->nchars, x + 1, y, false);
8552 #ifdef USE_CAIRO
8553 if (EQ (font->driver->type, Qx))
8554 x_end_cr_xlib_drawable (s->f, s->gc);
8555 }
8556 else
8557 {
8558
8559
8560 if (!(s->for_overlaps
8561 || (s->background_filled_p && s->hl != DRAW_CURSOR)))
8562 {
8563 int box_line_width = max (s->face->box_horizontal_line_width, 0);
8564
8565 if (s->stippled_p)
8566 {
8567 Display *display = FRAME_X_DISPLAY (s->f);
8568
8569
8570 XSetFillStyle (display, s->gc, FillOpaqueStippled);
8571 x_fill_rectangle (s->f, s->gc, s->x,
8572 s->y + box_line_width,
8573 s->background_width,
8574 s->height - 2 * box_line_width,
8575 false);
8576 XSetFillStyle (display, s->gc, FillSolid);
8577 }
8578 else
8579 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
8580 s->background_width,
8581 s->height - 2 * box_line_width);
8582 }
8583 for (i = 0; i < s->nchars; ++i)
8584 {
8585 struct glyph *g = s->first_glyph + i;
8586 x_draw_rectangle (s->f,
8587 s->gc, x, s->y, g->pixel_width - 1,
8588 s->height - 1);
8589 x += g->pixel_width;
8590 }
8591 }
8592 #endif
8593 }
8594 }
8595
8596
8597
8598 static void
8599 x_draw_composite_glyph_string_foreground (struct glyph_string *s)
8600 {
8601 int i, j, x;
8602 struct font *font = s->font;
8603
8604
8605
8606 if (s->face && s->face->box != FACE_NO_BOX
8607 && s->first_glyph->left_box_line_p)
8608 x = s->x + max (s->face->box_vertical_line_width, 0);
8609 else
8610 x = s->x;
8611
8612
8613
8614
8615
8616
8617
8618
8619 if (s->font_not_found_p)
8620 {
8621 if (s->cmp_from == 0)
8622 x_draw_rectangle (s->f, s->gc, x, s->y,
8623 s->width - 1, s->height - 1);
8624 }
8625 else
8626 #ifdef USE_CAIRO
8627 if (!EQ (font->driver->type, Qx)
8628 || x_try_cr_xlib_drawable (s->f, s->gc))
8629 {
8630 #endif
8631 if (! s->first_glyph->u.cmp.automatic)
8632 {
8633 int y = s->ybase;
8634
8635 for (i = 0, j = s->cmp_from; i < s->nchars; i++, j++)
8636
8637
8638 if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
8639 {
8640 int xx = x + s->cmp->offsets[j * 2];
8641 int yy = y - s->cmp->offsets[j * 2 + 1];
8642
8643 font->driver->draw (s, j, j + 1, xx, yy, false);
8644 if (s->face->overstrike)
8645 font->driver->draw (s, j, j + 1, xx + 1, yy, false);
8646 }
8647 }
8648 else
8649 {
8650 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
8651 Lisp_Object glyph;
8652 int y = s->ybase;
8653 int width = 0;
8654
8655 for (i = j = s->cmp_from; i < s->cmp_to; i++)
8656 {
8657 glyph = LGSTRING_GLYPH (gstring, i);
8658 if (NILP (LGLYPH_ADJUSTMENT (glyph)))
8659 width += LGLYPH_WIDTH (glyph);
8660 else
8661 {
8662 int xoff, yoff, wadjust;
8663
8664 if (j < i)
8665 {
8666 font->driver->draw (s, j, i, x, y, false);
8667 if (s->face->overstrike)
8668 font->driver->draw (s, j, i, x + 1, y, false);
8669 x += width;
8670 }
8671 xoff = LGLYPH_XOFF (glyph);
8672 yoff = LGLYPH_YOFF (glyph);
8673 wadjust = LGLYPH_WADJUST (glyph);
8674 font->driver->draw (s, i, i + 1, x + xoff, y + yoff, false);
8675 if (s->face->overstrike)
8676 font->driver->draw (s, i, i + 1, x + xoff + 1, y + yoff,
8677 false);
8678 x += wadjust;
8679 j = i + 1;
8680 width = 0;
8681 }
8682 }
8683 if (j < i)
8684 {
8685 font->driver->draw (s, j, i, x, y, false);
8686 if (s->face->overstrike)
8687 font->driver->draw (s, j, i, x + 1, y, false);
8688 }
8689 }
8690 #ifdef USE_CAIRO
8691 if (EQ (font->driver->type, Qx))
8692 x_end_cr_xlib_drawable (s->f, s->gc);
8693 }
8694 else
8695 {
8696
8697
8698 if (s->cmp_from == 0)
8699 x_draw_rectangle (s->f, s->gc, x, s->y,
8700 s->width - 1, s->height - 1);
8701 }
8702 #endif
8703 }
8704
8705
8706
8707
8708 static void
8709 x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
8710 {
8711 struct glyph *glyph = s->first_glyph;
8712 unsigned char2b[8];
8713 int x, i, j;
8714
8715
8716
8717 if (s->face && s->face->box != FACE_NO_BOX
8718 && s->first_glyph->left_box_line_p)
8719 x = s->x + max (s->face->box_vertical_line_width, 0);
8720 else
8721 x = s->x;
8722
8723 s->char2b = char2b;
8724
8725 for (i = 0; i < s->nchars; i++, glyph++)
8726 {
8727 #ifdef GCC_LINT
8728 enum { PACIFY_GCC_BUG_81401 = 1 };
8729 #else
8730 enum { PACIFY_GCC_BUG_81401 = 0 };
8731 #endif
8732 char buf[7 + PACIFY_GCC_BUG_81401];
8733 char *str = NULL;
8734 int len = glyph->u.glyphless.len;
8735
8736 if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM)
8737 {
8738 if (len > 0
8739 && CHAR_TABLE_P (Vglyphless_char_display)
8740 && (CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display))
8741 >= 1))
8742 {
8743 Lisp_Object acronym
8744 = (! glyph->u.glyphless.for_no_font
8745 ? CHAR_TABLE_REF (Vglyphless_char_display,
8746 glyph->u.glyphless.ch)
8747 : XCHAR_TABLE (Vglyphless_char_display)->extras[0]);
8748 if (CONSP (acronym))
8749 acronym = XCAR (acronym);
8750 if (STRINGP (acronym))
8751 str = SSDATA (acronym);
8752 }
8753 }
8754 else if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE)
8755 {
8756 unsigned int ch = glyph->u.glyphless.ch;
8757 eassume (ch <= MAX_CHAR);
8758 sprintf (buf, "%0*X", ch < 0x10000 ? 4 : 6, ch);
8759 str = buf;
8760 }
8761
8762 if (str)
8763 {
8764 int upper_len = (len + 1) / 2;
8765
8766
8767 for (j = 0; j < len; j++)
8768 char2b[j] = s->font->driver->encode_char (s->font, str[j]) & 0xFFFF;
8769 s->font->driver->draw (s, 0, upper_len,
8770 x + glyph->slice.glyphless.upper_xoff,
8771 s->ybase + glyph->slice.glyphless.upper_yoff,
8772 false);
8773 s->font->driver->draw (s, upper_len, len,
8774 x + glyph->slice.glyphless.lower_xoff,
8775 s->ybase + glyph->slice.glyphless.lower_yoff,
8776 false);
8777 }
8778 if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE)
8779 x_draw_rectangle (s->f, s->gc,
8780 x, s->ybase - glyph->ascent,
8781 glyph->pixel_width - 1,
8782 glyph->ascent + glyph->descent - 1);
8783 x += glyph->pixel_width;
8784 }
8785
8786
8787
8788 s->char2b = NULL;
8789 }
8790
8791 #ifdef USE_X_TOOLKIT
8792
8793 #ifdef USE_LUCID
8794
8795
8796
8797
8798 static struct frame *
8799 x_frame_of_widget (Widget widget)
8800 {
8801 struct x_display_info *dpyinfo;
8802 Lisp_Object tail, frame;
8803 struct frame *f;
8804
8805 dpyinfo = x_display_info_for_display (XtDisplay (widget));
8806
8807
8808
8809
8810
8811 while (!XtIsTopLevelShell (widget))
8812 widget = XtParent (widget);
8813
8814
8815
8816 FOR_EACH_FRAME (tail, frame)
8817 {
8818 f = XFRAME (frame);
8819 if (FRAME_X_P (f)
8820 && FRAME_DISPLAY_INFO (f) == dpyinfo
8821 && f->output_data.x->widget == widget)
8822 return f;
8823 }
8824 emacs_abort ();
8825 }
8826
8827
8828
8829
8830
8831
8832
8833
8834 bool
8835 x_alloc_lighter_color_for_widget (Widget widget, Display *display, Colormap cmap,
8836 unsigned long *pixel, double factor, int delta)
8837 {
8838 struct frame *f = x_frame_of_widget (widget);
8839 return x_alloc_lighter_color (f, display, cmap, pixel, factor, delta);
8840 }
8841
8842 #endif
8843
8844
8845
8846
8847
8848 static XtConvertArgRec cvt_string_to_pixel_args[] =
8849 {
8850 {XtWidgetBaseOffset, (XtPointer) offsetof (WidgetRec, core.screen),
8851 sizeof (Screen *)},
8852 {XtWidgetBaseOffset, (XtPointer) offsetof (WidgetRec, core.colormap),
8853 sizeof (Colormap)}
8854 };
8855
8856
8857
8858
8859
8860 static Pixel cvt_string_to_pixel_value;
8861
8862
8863
8864
8865
8866
8867
8868
8869
8870
8871
8872
8873
8874
8875
8876
8877
8878
8879
8880 static Boolean
8881 cvt_string_to_pixel (Display *dpy, XrmValue *args, Cardinal *nargs,
8882 XrmValue *from, XrmValue *to,
8883 XtPointer *closure_ret)
8884 {
8885 Screen *screen;
8886 Colormap cmap;
8887 Pixel pixel;
8888 String color_name;
8889 XColor color;
8890
8891 if (*nargs != 2)
8892 {
8893 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
8894 "wrongParameters", "cvt_string_to_pixel",
8895 "XtToolkitError",
8896 "Screen and colormap args required", NULL, NULL);
8897 return False;
8898 }
8899
8900 screen = *(Screen **) args[0].addr;
8901 cmap = *(Colormap *) args[1].addr;
8902 color_name = (String) from->addr;
8903
8904 if (strcmp (color_name, XtDefaultBackground) == 0)
8905 {
8906 *closure_ret = (XtPointer) False;
8907 pixel = WhitePixelOfScreen (screen);
8908 }
8909 else if (strcmp (color_name, XtDefaultForeground) == 0)
8910 {
8911 *closure_ret = (XtPointer) False;
8912 pixel = BlackPixelOfScreen (screen);
8913 }
8914 else if (XParseColor (dpy, cmap, color_name, &color)
8915 && x_alloc_nearest_color_1 (dpy, cmap, &color))
8916 {
8917 pixel = color.pixel;
8918 *closure_ret = (XtPointer) True;
8919 }
8920 else
8921 {
8922 String params[1];
8923 Cardinal nparams = 1;
8924
8925 params[0] = color_name;
8926 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
8927 "badValue", "cvt_string_to_pixel",
8928 "XtToolkitError", "Invalid color '%s'",
8929 params, &nparams);
8930 return False;
8931 }
8932
8933 if (to->addr != NULL)
8934 {
8935 if (to->size < sizeof (Pixel))
8936 {
8937 to->size = sizeof (Pixel);
8938 return False;
8939 }
8940
8941 *(Pixel *) to->addr = pixel;
8942 }
8943 else
8944 {
8945 cvt_string_to_pixel_value = pixel;
8946 to->addr = (XtPointer) &cvt_string_to_pixel_value;
8947 }
8948
8949 to->size = sizeof (Pixel);
8950 return True;
8951 }
8952
8953
8954
8955
8956
8957
8958
8959
8960
8961
8962
8963
8964
8965
8966 static void
8967 cvt_pixel_dtor (XtAppContext app, XrmValuePtr to, XtPointer closure, XrmValuePtr args,
8968 Cardinal *nargs)
8969 {
8970 if (*nargs != 2)
8971 {
8972 XtAppWarningMsg (app, "wrongParameters", "cvt_pixel_dtor",
8973 "XtToolkitError",
8974 "Screen and colormap arguments required",
8975 NULL, NULL);
8976 }
8977 else if (closure != NULL)
8978 {
8979
8980 Screen *screen = *(Screen **) args[0].addr;
8981 Colormap cmap = *(Colormap *) args[1].addr;
8982 x_free_dpy_colors (DisplayOfScreen (screen), screen, cmap,
8983 (Pixel *) to->addr, 1);
8984 }
8985 }
8986
8987
8988 #endif
8989
8990
8991
8992
8993
8994
8995
8996 static const XColor *
8997 x_color_cells (Display *dpy, int *ncells)
8998 {
8999 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
9000 eassume (dpyinfo);
9001
9002 if (dpyinfo->color_cells == NULL)
9003 {
9004 int ncolor_cells = dpyinfo->visual_info.colormap_size;
9005 int i;
9006
9007 dpyinfo->color_cells = xnmalloc (ncolor_cells,
9008 sizeof *dpyinfo->color_cells);
9009 dpyinfo->ncolor_cells = ncolor_cells;
9010
9011 for (i = 0; i < ncolor_cells; ++i)
9012 dpyinfo->color_cells[i].pixel = i;
9013
9014 XQueryColors (dpy, dpyinfo->cmap,
9015 dpyinfo->color_cells, ncolor_cells);
9016 }
9017
9018 *ncells = dpyinfo->ncolor_cells;
9019 return dpyinfo->color_cells;
9020 }
9021
9022
9023
9024
9025
9026
9027
9028
9029
9030 void
9031 x_query_colors (struct frame *f, XColor *colors, int ncolors)
9032 {
9033 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
9034 int i;
9035
9036 if (dpyinfo->red_bits > 0)
9037 {
9038
9039
9040 unsigned int rmult, gmult, bmult;
9041 unsigned int rmask, gmask, bmask;
9042
9043 rmask = (1 << dpyinfo->red_bits) - 1;
9044 gmask = (1 << dpyinfo->green_bits) - 1;
9045 bmask = (1 << dpyinfo->blue_bits) - 1;
9046
9047
9048
9049
9050
9051
9052
9053
9054
9055
9056
9057
9058
9059 rmult = 0xffffffff / rmask;
9060 gmult = 0xffffffff / gmask;
9061 bmult = 0xffffffff / bmask;
9062
9063 for (i = 0; i < ncolors; ++i)
9064 {
9065 unsigned int r, g, b;
9066 unsigned long pixel = colors[i].pixel;
9067
9068 r = (pixel >> dpyinfo->red_offset) & rmask;
9069 g = (pixel >> dpyinfo->green_offset) & gmask;
9070 b = (pixel >> dpyinfo->blue_offset) & bmask;
9071
9072 colors[i].red = (r * rmult) >> 16;
9073 colors[i].green = (g * gmult) >> 16;
9074 colors[i].blue = (b * bmult) >> 16;
9075 }
9076
9077 return;
9078 }
9079
9080 if (dpyinfo->color_cells)
9081 {
9082 int i;
9083 for (i = 0; i < ncolors; ++i)
9084 {
9085 unsigned long pixel = colors[i].pixel;
9086 eassert (pixel < dpyinfo->ncolor_cells);
9087 eassert (dpyinfo->color_cells[pixel].pixel == pixel);
9088 colors[i] = dpyinfo->color_cells[pixel];
9089 }
9090 return;
9091 }
9092
9093 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
9094 }
9095
9096
9097
9098 static void
9099 x_query_frame_background_color (struct frame *f, XColor *bgcolor)
9100 {
9101 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
9102 #ifndef USE_CAIRO
9103 XColor bg;
9104 #endif
9105
9106 if (FRAME_DISPLAY_INFO (f)->alpha_bits)
9107 {
9108 #ifdef USE_CAIRO
9109 background = (background & ~FRAME_DISPLAY_INFO (f)->alpha_mask);
9110 background |= (((unsigned long) (f->alpha_background * 0xffff)
9111 >> (16 - FRAME_DISPLAY_INFO (f)->alpha_bits))
9112 << FRAME_DISPLAY_INFO (f)->alpha_offset);
9113 #else
9114 if (FRAME_DISPLAY_INFO (f)->alpha_bits
9115 && f->alpha_background < 1.0)
9116 {
9117 bg.pixel = background;
9118 x_query_colors (f, &bg, 1);
9119
9120 background
9121 = x_premultiply_pixel (FRAME_DISPLAY_INFO (f),
9122 &bg, f->alpha_background);
9123 }
9124 #endif
9125 }
9126
9127 bgcolor->pixel = background;
9128
9129 x_query_colors (f, bgcolor, 1);
9130 }
9131
9132 static unsigned int
9133 x_hash_string_ignore_case (const char *string)
9134 {
9135 unsigned int i;
9136
9137 i = 3323198485ul;
9138 for (; *string; ++string)
9139 {
9140 i ^= c_tolower (*string);
9141 i *= 0x5bd1e995;
9142 i ^= i >> 15;
9143 }
9144 return i;
9145 }
9146
9147
9148
9149
9150
9151
9152
9153 Status
9154 x_parse_color (struct frame *f, const char *color_name,
9155 XColor *color)
9156 {
9157 unsigned short r, g, b;
9158 Display *dpy;
9159 Colormap cmap;
9160 struct x_display_info *dpyinfo;
9161 struct color_name_cache_entry *cache_entry, *last;
9162 struct color_name_cache_entry *next, *color_entry;
9163 unsigned int hash, idx;
9164 int rc, i;
9165
9166
9167
9168
9169
9170
9171 if (parse_color_spec (color_name, &r, &g, &b))
9172 {
9173 color->red = r;
9174 color->green = g;
9175 color->blue = b;
9176
9177 return 1;
9178 }
9179
9180
9181 if (!strlen (color_name))
9182 return 0;
9183
9184 cmap = FRAME_X_COLORMAP (f);
9185 dpy = FRAME_X_DISPLAY (f);
9186 dpyinfo = FRAME_DISPLAY_INFO (f);
9187
9188 hash = x_hash_string_ignore_case (color_name);
9189 idx = hash % dpyinfo->color_names_size;
9190
9191 last = NULL;
9192
9193 for (cache_entry = dpyinfo->color_names[idx];
9194 cache_entry; cache_entry = cache_entry->next)
9195 {
9196 if (!xstrcasecmp (cache_entry->name, color_name))
9197 {
9198
9199
9200
9201 if (last)
9202 {
9203 last->next = cache_entry->next;
9204 cache_entry->next = dpyinfo->color_names[idx];
9205
9206 dpyinfo->color_names[idx] = cache_entry;
9207 }
9208
9209 if (cache_entry->valid)
9210 *color = cache_entry->rgb;
9211
9212 return cache_entry->valid;
9213 }
9214
9215 last = cache_entry;
9216 }
9217
9218 block_input ();
9219 rc = XParseColor (dpy, cmap, color_name, color);
9220 unblock_input ();
9221
9222 cache_entry = xzalloc (sizeof *cache_entry);
9223 dpyinfo->color_names_length[idx] += 1;
9224
9225 if (rc)
9226 cache_entry->rgb = *color;
9227
9228 cache_entry->valid = rc;
9229 cache_entry->name = xstrdup (color_name);
9230 cache_entry->next = dpyinfo->color_names[idx];
9231
9232 dpyinfo->color_names[idx] = cache_entry;
9233
9234
9235 if (dpyinfo->color_names_length[idx] > (x_color_cache_bucket_size > 0
9236 ? x_color_cache_bucket_size : 128))
9237 {
9238 i = 0;
9239
9240 for (last = dpyinfo->color_names[idx]; last; last = last->next)
9241 {
9242 if (++i == (x_color_cache_bucket_size > 0
9243 ? x_color_cache_bucket_size : 128))
9244 {
9245 next = last->next;
9246 last->next = NULL;
9247
9248 for (color_entry = next; color_entry; color_entry = last)
9249 {
9250 last = color_entry->next;
9251
9252 xfree (color_entry->name);
9253 xfree (color_entry);
9254
9255 dpyinfo->color_names_length[idx] -= 1;
9256 }
9257
9258 return rc;
9259 }
9260 }
9261 }
9262
9263 return rc;
9264 }
9265
9266
9267
9268
9269
9270
9271
9272 static bool
9273 x_alloc_nearest_color_1 (Display *dpy, Colormap cmap, XColor *color)
9274 {
9275 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
9276 bool rc;
9277
9278 eassume (dpyinfo);
9279 rc = XAllocColor (dpy, cmap, color) != 0;
9280
9281 if (dpyinfo->visual_info.class == DirectColor)
9282 return rc;
9283
9284 if (rc == 0)
9285 {
9286
9287
9288
9289
9290
9291 const XColor *cells;
9292 int no_cells;
9293 int nearest;
9294 long nearest_delta, trial_delta;
9295 int x;
9296 Status status;
9297 bool retry = false;
9298 int ncolor_cells, i;
9299 bool temp_allocated;
9300 XColor temp;
9301
9302 start:
9303 cells = x_color_cells (dpy, &no_cells);
9304 temp_allocated = false;
9305
9306 nearest = 0;
9307
9308 nearest_delta = ((((color->red >> 8) - (cells[0].red >> 8))
9309 * ((color->red >> 8) - (cells[0].red >> 8)))
9310 + (((color->green >> 8) - (cells[0].green >> 8))
9311 * ((color->green >> 8) - (cells[0].green >> 8)))
9312 + (((color->blue >> 8) - (cells[0].blue >> 8))
9313 * ((color->blue >> 8) - (cells[0].blue >> 8))));
9314 for (x = 1; x < no_cells; x++)
9315 {
9316 trial_delta = ((((color->red >> 8) - (cells[x].red >> 8))
9317 * ((color->red >> 8) - (cells[x].red >> 8)))
9318 + (((color->green >> 8) - (cells[x].green >> 8))
9319 * ((color->green >> 8) - (cells[x].green >> 8)))
9320 + (((color->blue >> 8) - (cells[x].blue >> 8))
9321 * ((color->blue >> 8) - (cells[x].blue >> 8))));
9322 if (trial_delta < nearest_delta)
9323 {
9324
9325 if (temp_allocated)
9326 {
9327 XFreeColors (dpy, cmap, &temp.pixel, 1, 0);
9328 temp_allocated = false;
9329 }
9330
9331 temp.red = cells[x].red;
9332 temp.green = cells[x].green;
9333 temp.blue = cells[x].blue;
9334 status = XAllocColor (dpy, cmap, &temp);
9335
9336 if (status)
9337 {
9338 temp_allocated = true;
9339 nearest = x;
9340 nearest_delta = trial_delta;
9341 }
9342 }
9343 }
9344 color->red = cells[nearest].red;
9345 color->green = cells[nearest].green;
9346 color->blue = cells[nearest].blue;
9347
9348 if (!temp_allocated)
9349 status = XAllocColor (dpy, cmap, color);
9350 else
9351 {
9352 *color = temp;
9353 status = 1;
9354 }
9355
9356 if (status == 0 && !retry)
9357 {
9358
9359
9360
9361
9362 retry = true;
9363 xfree (dpyinfo->color_cells);
9364
9365 ncolor_cells = dpyinfo->visual_info.colormap_size;
9366
9367 dpyinfo->color_cells = xnmalloc (ncolor_cells,
9368 sizeof *dpyinfo->color_cells);
9369 dpyinfo->ncolor_cells = ncolor_cells;
9370
9371 for (i = 0; i < ncolor_cells; ++i)
9372 dpyinfo->color_cells[i].pixel = i;
9373
9374 XQueryColors (dpy, dpyinfo->cmap,
9375 dpyinfo->color_cells, ncolor_cells);
9376
9377 goto start;
9378 }
9379
9380 rc = status != 0;
9381 }
9382 else
9383 {
9384
9385
9386
9387 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
9388 eassume (dpyinfo);
9389
9390 if (dpyinfo->color_cells)
9391 {
9392 XColor *cached_color = &dpyinfo->color_cells[color->pixel];
9393 if (cached_color->red != color->red
9394 || cached_color->blue != color->blue
9395 || cached_color->green != color->green)
9396 {
9397 xfree (dpyinfo->color_cells);
9398 dpyinfo->color_cells = NULL;
9399 dpyinfo->ncolor_cells = 0;
9400 }
9401 }
9402 }
9403
9404 #ifdef DEBUG_X_COLORS
9405 if (rc)
9406 register_color (color->pixel);
9407 #endif
9408
9409 return rc;
9410 }
9411
9412
9413
9414
9415
9416
9417
9418 bool
9419 x_alloc_nearest_color (struct frame *f, Colormap cmap, XColor *color)
9420 {
9421 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
9422
9423 gamma_correct (f, color);
9424
9425 if (dpyinfo->red_bits > 0)
9426 {
9427 color->pixel = x_make_truecolor_pixel (dpyinfo,
9428 color->red,
9429 color->green,
9430 color->blue);
9431 return true;
9432 }
9433
9434 return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f), cmap, color);
9435 }
9436
9437
9438
9439
9440
9441
9442 unsigned long
9443 x_copy_color (struct frame *f, unsigned long pixel)
9444 {
9445 XColor color;
9446
9447
9448
9449
9450
9451 if (!x_mutable_colormap (FRAME_X_VISUAL_INFO (f)))
9452 return pixel;
9453
9454 color.pixel = pixel;
9455 block_input ();
9456
9457 x_query_colors (f, &color, 1);
9458 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
9459 unblock_input ();
9460 #ifdef DEBUG_X_COLORS
9461 register_color (pixel);
9462 #endif
9463 return color.pixel;
9464 }
9465
9466
9467
9468
9469
9470
9471
9472
9473
9474
9475
9476
9477
9478 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
9479
9480
9481
9482
9483
9484
9485
9486
9487
9488 static bool
9489 x_alloc_lighter_color (struct frame *f, Display *display, Colormap cmap,
9490 unsigned long *pixel, double factor, int delta)
9491 {
9492 XColor color, new;
9493 long bright;
9494 bool success_p;
9495
9496
9497 color.pixel = *pixel;
9498 x_query_colors (f, &color, 1);
9499
9500
9501 eassert (factor >= 0);
9502 new.red = min (0xffff, factor * color.red);
9503 new.green = min (0xffff, factor * color.green);
9504 new.blue = min (0xffff, factor * color.blue);
9505
9506
9507 bright = (2 * color.red + 3 * color.green + color.blue) / 6;
9508
9509
9510
9511 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
9512
9513
9514 {
9515
9516 double dimness = 1 - (double) bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
9517
9518 int min_delta = delta * dimness * factor / 2;
9519
9520 if (factor < 1)
9521 {
9522 new.red = max (0, new.red - min_delta);
9523 new.green = max (0, new.green - min_delta);
9524 new.blue = max (0, new.blue - min_delta);
9525 }
9526 else
9527 {
9528 new.red = min (0xffff, min_delta + new.red);
9529 new.green = min (0xffff, min_delta + new.green);
9530 new.blue = min (0xffff, min_delta + new.blue);
9531 }
9532 }
9533
9534
9535 success_p = x_alloc_nearest_color (f, cmap, &new);
9536 if (success_p)
9537 {
9538 if (new.pixel == *pixel)
9539 {
9540
9541
9542 x_free_colors (f, &new.pixel, 1);
9543
9544 new.red = min (0xffff, delta + color.red);
9545 new.green = min (0xffff, delta + color.green);
9546 new.blue = min (0xffff, delta + color.blue);
9547 success_p = x_alloc_nearest_color (f, cmap, &new);
9548 }
9549 else
9550 success_p = true;
9551 *pixel = new.pixel;
9552 }
9553
9554 return success_p;
9555 }
9556
9557
9558
9559
9560
9561
9562
9563
9564
9565 static void
9566 x_setup_relief_color (struct frame *f, struct relief *relief, double factor,
9567 int delta, unsigned long default_pixel)
9568 {
9569 XGCValues xgcv;
9570 struct x_output *di = f->output_data.x;
9571 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
9572 unsigned long pixel;
9573 unsigned long background = di->relief_background;
9574 Colormap cmap = FRAME_X_COLORMAP (f);
9575 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
9576 Display *dpy = FRAME_X_DISPLAY (f);
9577
9578 xgcv.graphics_exposures = False;
9579 xgcv.line_width = 1;
9580
9581
9582
9583
9584 if (relief->gc && relief->pixel != -1)
9585 {
9586 x_free_colors (f, &relief->pixel, 1);
9587 relief->pixel = -1;
9588 }
9589
9590
9591 xgcv.foreground = default_pixel;
9592 pixel = background;
9593 if (dpyinfo->n_planes != 1
9594 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
9595 xgcv.foreground = relief->pixel = pixel;
9596
9597 if (relief->gc == 0)
9598 {
9599 xgcv.stipple = dpyinfo->gray;
9600 mask |= GCStipple;
9601 relief->gc = XCreateGC (dpy, FRAME_X_DRAWABLE (f), mask, &xgcv);
9602 }
9603 else
9604 XChangeGC (dpy, relief->gc, mask, &xgcv);
9605 }
9606
9607
9608
9609
9610 static void
9611 x_setup_relief_colors (struct glyph_string *s)
9612 {
9613 struct x_output *di = s->f->output_data.x;
9614 unsigned long color;
9615
9616 if (s->face->use_box_color_for_shadows_p)
9617 color = s->face->box_color;
9618 else if (s->first_glyph->type == IMAGE_GLYPH
9619 && s->img->pixmap
9620 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
9621 color = IMAGE_BACKGROUND (s->img, s->f, 0);
9622 else
9623 {
9624 XGCValues xgcv;
9625
9626
9627 XGetGCValues (FRAME_X_DISPLAY (s->f), s->gc, GCBackground, &xgcv);
9628 color = xgcv.background;
9629 }
9630
9631 if (di->white_relief.gc == 0
9632 || color != di->relief_background)
9633 {
9634 di->relief_background = color;
9635 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
9636 WHITE_PIX_DEFAULT (s->f));
9637 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
9638 BLACK_PIX_DEFAULT (s->f));
9639 }
9640 }
9641
9642 #ifndef USE_CAIRO
9643 static void
9644 x_fill_triangle (struct frame *f, GC gc, XPoint point1,
9645 XPoint point2, XPoint point3)
9646 {
9647 XPoint abc[3];
9648
9649 abc[0] = point1;
9650 abc[1] = point2;
9651 abc[2] = point3;
9652
9653 XFillPolygon (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
9654 gc, abc, 3, Convex, CoordModeOrigin);
9655 }
9656
9657 static XPoint
9658 x_make_point (int x, int y)
9659 {
9660 XPoint pt;
9661
9662 pt.x = x;
9663 pt.y = y;
9664
9665 return pt;
9666 }
9667
9668 static bool
9669 x_inside_rect_p (XRectangle *rects, int nrects, int x, int y)
9670 {
9671 int i;
9672
9673 for (i = 0; i < nrects; ++i)
9674 {
9675 if (x >= rects[i].x && y >= rects[i].y
9676 && x < rects[i].x + rects[i].width
9677 && y < rects[i].y + rects[i].height)
9678 return true;
9679 }
9680
9681 return false;
9682 }
9683 #endif
9684
9685
9686
9687
9688
9689
9690
9691
9692
9693
9694 static void
9695 x_draw_relief_rect (struct frame *f, int left_x, int top_y, int right_x,
9696 int bottom_y, int hwidth, int vwidth, bool raised_p,
9697 bool top_p, bool bot_p, bool left_p, bool right_p,
9698 XRectangle *clip_rect)
9699 {
9700 #ifdef USE_CAIRO
9701 GC top_left_gc, bottom_right_gc;
9702 int corners = 0;
9703
9704 if (raised_p)
9705 {
9706 top_left_gc = f->output_data.x->white_relief.gc;
9707 bottom_right_gc = f->output_data.x->black_relief.gc;
9708 }
9709 else
9710 {
9711 top_left_gc = f->output_data.x->black_relief.gc;
9712 bottom_right_gc = f->output_data.x->white_relief.gc;
9713 }
9714
9715 x_set_clip_rectangles (f, top_left_gc, clip_rect, 1);
9716 x_set_clip_rectangles (f, bottom_right_gc, clip_rect, 1);
9717
9718 if (left_p)
9719 {
9720 x_fill_rectangle (f, top_left_gc, left_x, top_y,
9721 vwidth, bottom_y + 1 - top_y, false);
9722 if (top_p)
9723 corners |= 1 << CORNER_TOP_LEFT;
9724 if (bot_p)
9725 corners |= 1 << CORNER_BOTTOM_LEFT;
9726 }
9727 if (right_p)
9728 {
9729 x_fill_rectangle (f, bottom_right_gc, right_x + 1 - vwidth, top_y,
9730 vwidth, bottom_y + 1 - top_y, false);
9731 if (top_p)
9732 corners |= 1 << CORNER_TOP_RIGHT;
9733 if (bot_p)
9734 corners |= 1 << CORNER_BOTTOM_RIGHT;
9735 }
9736 if (top_p)
9737 {
9738 if (!right_p)
9739 x_fill_rectangle (f, top_left_gc, left_x, top_y,
9740 right_x + 1 - left_x, hwidth, false);
9741 else
9742 x_fill_trapezoid_for_relief (f, top_left_gc, left_x, top_y,
9743 right_x + 1 - left_x, hwidth, 1);
9744 }
9745 if (bot_p)
9746 {
9747 if (!left_p)
9748 x_fill_rectangle (f, bottom_right_gc, left_x, bottom_y + 1 - hwidth,
9749 right_x + 1 - left_x, hwidth, false);
9750 else
9751 x_fill_trapezoid_for_relief (f, bottom_right_gc,
9752 left_x, bottom_y + 1 - hwidth,
9753 right_x + 1 - left_x, hwidth, 0);
9754 }
9755 if (left_p && vwidth > 1)
9756 x_fill_rectangle (f, bottom_right_gc, left_x, top_y,
9757 1, bottom_y + 1 - top_y, false);
9758 if (top_p && hwidth > 1)
9759 x_fill_rectangle (f, bottom_right_gc, left_x, top_y,
9760 right_x + 1 - left_x, 1, false);
9761 if (corners)
9762 {
9763 XSetBackground (FRAME_X_DISPLAY (f), top_left_gc,
9764 FRAME_BACKGROUND_PIXEL (f));
9765 x_erase_corners_for_relief (f, top_left_gc, left_x, top_y,
9766 right_x - left_x + 1, bottom_y - top_y + 1,
9767 6, 1, corners);
9768 }
9769
9770 x_reset_clip_rectangles (f, top_left_gc);
9771 x_reset_clip_rectangles (f, bottom_right_gc);
9772 #else
9773 GC gc, white_gc, black_gc, normal_gc;
9774 Drawable drawable;
9775 Display *dpy;
9776
9777
9778
9779
9780
9781
9782 white_gc = f->output_data.x->white_relief.gc;
9783 black_gc = f->output_data.x->black_relief.gc;
9784 normal_gc = f->output_data.x->normal_gc;
9785
9786 drawable = FRAME_X_DRAWABLE (f);
9787 dpy = FRAME_X_DISPLAY (f);
9788
9789 x_set_clip_rectangles (f, white_gc, clip_rect, 1);
9790 x_set_clip_rectangles (f, black_gc, clip_rect, 1);
9791
9792 if (raised_p)
9793 gc = white_gc;
9794 else
9795 gc = black_gc;
9796
9797
9798
9799 if (top_p)
9800 x_fill_rectangle (f, gc, left_x, top_y,
9801 right_x - left_x + 1, hwidth,
9802 false);
9803
9804 if (left_p)
9805 x_fill_rectangle (f, gc, left_x, top_y, vwidth,
9806 bottom_y - top_y + 1, false);
9807
9808 if (raised_p)
9809 gc = black_gc;
9810 else
9811 gc = white_gc;
9812
9813 if (bot_p)
9814 x_fill_rectangle (f, gc, left_x, bottom_y - hwidth + 1,
9815 right_x - left_x + 1, hwidth, false);
9816
9817 if (right_p)
9818 x_fill_rectangle (f, gc, right_x - vwidth + 1, top_y,
9819 vwidth, bottom_y - top_y + 1, false);
9820
9821
9822
9823 if (bot_p && left_p)
9824 x_fill_triangle (f, raised_p ? white_gc : black_gc,
9825 x_make_point (left_x, bottom_y - hwidth),
9826 x_make_point (left_x + vwidth, bottom_y - hwidth),
9827 x_make_point (left_x, bottom_y));
9828
9829 if (top_p && right_p)
9830 x_fill_triangle (f, raised_p ? white_gc : black_gc,
9831 x_make_point (right_x - vwidth, top_y),
9832 x_make_point (right_x, top_y),
9833 x_make_point (right_x - vwidth, top_y + hwidth));
9834
9835
9836
9837 if (top_p && left_p && bot_p && right_p
9838 && hwidth > 1 && vwidth > 1)
9839 x_draw_rectangle (f, black_gc, left_x, top_y,
9840 right_x - left_x, bottom_y - top_y);
9841 else
9842 {
9843 if (top_p && hwidth > 1)
9844 XDrawLine (dpy, drawable, black_gc, left_x, top_y,
9845 right_x + 1, top_y);
9846
9847 if (bot_p && hwidth > 1)
9848 XDrawLine (dpy, drawable, black_gc, left_x, bottom_y,
9849 right_x + 1, bottom_y);
9850
9851 if (left_p && vwidth > 1)
9852 XDrawLine (dpy, drawable, black_gc, left_x, top_y,
9853 left_x, bottom_y + 1);
9854
9855 if (right_p && vwidth > 1)
9856 XDrawLine (dpy, drawable, black_gc, right_x, top_y,
9857 right_x, bottom_y + 1);
9858 }
9859
9860
9861
9862 if (hwidth > 1 && vwidth > 1)
9863 {
9864 if (left_p && top_p && x_inside_rect_p (clip_rect, 1,
9865 left_x, top_y))
9866
9867
9868 x_clear_point (f, normal_gc, left_x, top_y, true);
9869
9870 if (left_p && bot_p && x_inside_rect_p (clip_rect, 1,
9871 left_x, bottom_y))
9872 x_clear_point (f, normal_gc, left_x, bottom_y, true);
9873
9874 if (right_p && top_p && x_inside_rect_p (clip_rect, 1,
9875 right_x, top_y))
9876 x_clear_point (f, normal_gc, right_x, top_y, true);
9877
9878 if (right_p && bot_p && x_inside_rect_p (clip_rect, 1,
9879 right_x, bottom_y))
9880 x_clear_point (f, normal_gc, right_x, bottom_y, true);
9881 }
9882
9883 x_reset_clip_rectangles (f, white_gc);
9884 x_reset_clip_rectangles (f, black_gc);
9885 #endif
9886 }
9887
9888
9889
9890
9891
9892
9893
9894
9895
9896 static void
9897 x_draw_box_rect (struct glyph_string *s,
9898 int left_x, int top_y, int right_x, int bottom_y, int hwidth,
9899 int vwidth, bool left_p, bool right_p, XRectangle *clip_rect)
9900 {
9901 Display *display = FRAME_X_DISPLAY (s->f);
9902 XGCValues xgcv;
9903
9904 XGetGCValues (display, s->gc, GCForeground, &xgcv);
9905 XSetForeground (display, s->gc, s->face->box_color);
9906 x_set_clip_rectangles (s->f, s->gc, clip_rect, 1);
9907
9908
9909 x_fill_rectangle (s->f, s->gc,
9910 left_x, top_y, right_x - left_x + 1, hwidth,
9911 false);
9912
9913
9914 if (left_p)
9915 x_fill_rectangle (s->f, s->gc,
9916 left_x, top_y, vwidth, bottom_y - top_y + 1,
9917 false);
9918
9919
9920 x_fill_rectangle (s->f, s->gc,
9921 left_x, bottom_y - hwidth + 1, right_x - left_x + 1, hwidth,
9922 false);
9923
9924
9925 if (right_p)
9926 x_fill_rectangle (s->f, s->gc,
9927 right_x - vwidth + 1, top_y, vwidth, bottom_y - top_y + 1,
9928 false);
9929
9930 XSetForeground (display, s->gc, xgcv.foreground);
9931 x_reset_clip_rectangles (s->f, s->gc);
9932 }
9933
9934
9935
9936
9937 static void
9938 x_draw_glyph_string_box (struct glyph_string *s)
9939 {
9940 int hwidth, vwidth, left_x, right_x, top_y, bottom_y, last_x;
9941 bool raised_p, left_p, right_p;
9942 struct glyph *last_glyph;
9943 XRectangle clip_rect;
9944
9945 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
9946 ? WINDOW_RIGHT_EDGE_X (s->w)
9947 : window_box_right (s->w, s->area));
9948
9949
9950
9951
9952 if (s->cmp || s->img)
9953 last_glyph = s->first_glyph;
9954 else if (s->first_glyph->type == COMPOSITE_GLYPH
9955 && s->first_glyph->u.cmp.automatic)
9956 {
9957
9958
9959 struct glyph *end = s->row->glyphs[s->area] + s->row->used[s->area];
9960 struct glyph *g = s->first_glyph;
9961 for (last_glyph = g++;
9962 g < end && g->u.cmp.automatic && g->u.cmp.id == s->cmp_id
9963 && g->slice.cmp.to < s->cmp_to;
9964 last_glyph = g++)
9965 ;
9966 }
9967 else
9968 last_glyph = s->first_glyph + s->nchars - 1;
9969
9970 vwidth = eabs (s->face->box_vertical_line_width);
9971 hwidth = eabs (s->face->box_horizontal_line_width);
9972 raised_p = s->face->box == FACE_RAISED_BOX;
9973 left_x = s->x;
9974 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
9975 ? last_x - 1
9976 : min (last_x, s->x + s->background_width) - 1);
9977 top_y = s->y;
9978 bottom_y = top_y + s->height - 1;
9979
9980 left_p = (s->first_glyph->left_box_line_p
9981 || (s->hl == DRAW_MOUSE_FACE
9982 && (s->prev == NULL
9983 || s->prev->hl != s->hl)));
9984 right_p = (last_glyph->right_box_line_p
9985 || (s->hl == DRAW_MOUSE_FACE
9986 && (s->next == NULL
9987 || s->next->hl != s->hl)));
9988
9989 get_glyph_string_clip_rect (s, &clip_rect);
9990
9991 if (s->face->box == FACE_SIMPLE_BOX)
9992 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, hwidth,
9993 vwidth, left_p, right_p, &clip_rect);
9994 else
9995 {
9996 x_setup_relief_colors (s);
9997 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y, hwidth,
9998 vwidth, raised_p, true, true, left_p, right_p,
9999 &clip_rect);
10000 }
10001 }
10002
10003
10004 #ifndef USE_CAIRO
10005
10006 static void
10007 x_composite_image (struct glyph_string *s, Pixmap dest,
10008 #ifdef HAVE_XRENDER
10009 Picture destination,
10010 #endif
10011 int srcX, int srcY, int dstX, int dstY,
10012 int width, int height)
10013 {
10014 Display *display;
10015 #ifdef HAVE_XRENDER
10016 XRenderPictFormat *default_format;
10017 XRenderPictureAttributes attr UNINIT;
10018 #endif
10019
10020 display = FRAME_X_DISPLAY (s->f);
10021
10022 #ifdef HAVE_XRENDER
10023 if (s->img->picture && FRAME_X_PICTURE_FORMAT (s->f))
10024 {
10025 if (destination == None)
10026 {
10027
10028
10029 default_format = FRAME_X_PICTURE_FORMAT (s->f);
10030 destination = XRenderCreatePicture (display, dest,
10031 default_format, 0, &attr);
10032
10033 XRenderComposite (display, (s->img->mask_picture
10034 ? PictOpOver : PictOpSrc),
10035 s->img->picture, s->img->mask_picture,
10036 destination, srcX, srcY, srcX, srcY,
10037 dstX, dstY, width, height);
10038
10039 XRenderFreePicture (display, destination);
10040 }
10041 else
10042 XRenderComposite (display, (s->img->mask_picture
10043 ? PictOpOver : PictOpSrc),
10044 s->img->picture, s->img->mask_picture,
10045 destination, srcX, srcY, srcX, srcY,
10046 dstX, dstY, width, height);
10047
10048 return;
10049 }
10050 #endif
10051
10052 XCopyArea (display, s->img->pixmap,
10053 dest, s->gc,
10054 srcX, srcY,
10055 width, height, dstX, dstY);
10056 }
10057
10058 #endif
10059
10060
10061
10062
10063 static void
10064 x_draw_image_foreground (struct glyph_string *s)
10065 {
10066 int x = s->x;
10067 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
10068
10069
10070
10071 if (s->face->box != FACE_NO_BOX
10072 && s->first_glyph->left_box_line_p
10073 && s->slice.x == 0)
10074 x += max (s->face->box_vertical_line_width, 0);
10075
10076
10077
10078 if (s->slice.x == 0)
10079 x += s->img->hmargin;
10080 if (s->slice.y == 0)
10081 y += s->img->vmargin;
10082
10083 #ifdef USE_CAIRO
10084 if (s->img->cr_data)
10085 {
10086 x_set_glyph_string_clipping (s);
10087 x_cr_draw_image (s->f, s->gc, s->img->cr_data,
10088 s->slice.x, s->slice.y, s->slice.width, s->slice.height,
10089 x, y, true);
10090 if (!s->img->mask)
10091 {
10092
10093
10094
10095
10096
10097
10098 if (s->hl == DRAW_CURSOR)
10099 {
10100 int relief = eabs (s->img->relief);
10101 x_draw_rectangle (s->f, s->gc, x - relief, y - relief,
10102 s->slice.width + relief*2 - 1,
10103 s->slice.height + relief*2 - 1);
10104 }
10105 }
10106 }
10107 #else
10108 if (s->img->pixmap)
10109 {
10110 if (s->img->mask)
10111 {
10112
10113
10114
10115
10116
10117
10118 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
10119 | GCFunction);
10120 XGCValues xgcv;
10121 XRectangle clip_rect, image_rect, r;
10122
10123 xgcv.clip_mask = s->img->mask;
10124 xgcv.clip_x_origin = x;
10125 xgcv.clip_y_origin = y;
10126 xgcv.function = GXcopy;
10127 XChangeGC (FRAME_X_DISPLAY (s->f), s->gc, mask, &xgcv);
10128
10129 get_glyph_string_clip_rect (s, &clip_rect);
10130 image_rect.x = x;
10131 image_rect.y = y;
10132 image_rect.width = s->slice.width;
10133 image_rect.height = s->slice.height;
10134 if (gui_intersect_rectangles (&clip_rect, &image_rect, &r))
10135 x_composite_image (s, FRAME_X_DRAWABLE (s->f),
10136 #ifdef HAVE_XRENDER
10137 FRAME_X_PICTURE (s->f),
10138 #endif
10139 s->slice.x + r.x - x, s->slice.y + r.y - y,
10140 r.x, r.y, r.width, r.height);
10141 }
10142 else
10143 {
10144 XRectangle clip_rect, image_rect, r;
10145
10146 get_glyph_string_clip_rect (s, &clip_rect);
10147 image_rect.x = x;
10148 image_rect.y = y;
10149 image_rect.width = s->slice.width;
10150 image_rect.height = s->slice.height;
10151 if (gui_intersect_rectangles (&clip_rect, &image_rect, &r))
10152 x_composite_image (s, FRAME_X_DRAWABLE (s->f),
10153 #ifdef HAVE_XRENDER
10154 FRAME_X_PICTURE (s->f),
10155 #endif
10156 s->slice.x + r.x - x,
10157 s->slice.y + r.y - y,
10158 r.x, r.y, r.width, r.height);
10159
10160
10161
10162
10163
10164
10165
10166 if (s->hl == DRAW_CURSOR)
10167 {
10168 int relief = eabs (s->img->relief);
10169 x_draw_rectangle (s->f, s->gc,
10170 x - relief, y - relief,
10171 s->slice.width + relief*2 - 1,
10172 s->slice.height + relief*2 - 1);
10173 }
10174 }
10175 }
10176 #endif
10177 else
10178
10179 x_draw_rectangle (s->f, s->gc, x, y,
10180 s->slice.width - 1, s->slice.height - 1);
10181 }
10182
10183
10184
10185
10186 static void
10187 x_draw_image_relief (struct glyph_string *s)
10188 {
10189 int x1, y1, thick;
10190 bool raised_p, top_p, bot_p, left_p, right_p;
10191 int extra_x, extra_y;
10192 XRectangle r;
10193 int x = s->x;
10194 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
10195
10196
10197
10198 if (s->face->box != FACE_NO_BOX
10199 && s->first_glyph->left_box_line_p
10200 && s->slice.x == 0)
10201 x += max (s->face->box_vertical_line_width, 0);
10202
10203
10204
10205 if (s->slice.x == 0)
10206 x += s->img->hmargin;
10207 if (s->slice.y == 0)
10208 y += s->img->vmargin;
10209
10210 if (s->hl == DRAW_IMAGE_SUNKEN
10211 || s->hl == DRAW_IMAGE_RAISED)
10212 {
10213 if (s->face->id == TAB_BAR_FACE_ID)
10214 thick = (tab_bar_button_relief < 0
10215 ? DEFAULT_TAB_BAR_BUTTON_RELIEF
10216 : min (tab_bar_button_relief, 1000000));
10217 else
10218 thick = (tool_bar_button_relief < 0
10219 ? DEFAULT_TOOL_BAR_BUTTON_RELIEF
10220 : min (tool_bar_button_relief, 1000000));
10221 raised_p = s->hl == DRAW_IMAGE_RAISED;
10222 }
10223 else
10224 {
10225 thick = eabs (s->img->relief);
10226 raised_p = s->img->relief > 0;
10227 }
10228
10229 x1 = x + s->slice.width - 1;
10230 y1 = y + s->slice.height - 1;
10231
10232 extra_x = extra_y = 0;
10233 if (s->face->id == TAB_BAR_FACE_ID)
10234 {
10235 if (CONSP (Vtab_bar_button_margin)
10236 && FIXNUMP (XCAR (Vtab_bar_button_margin))
10237 && FIXNUMP (XCDR (Vtab_bar_button_margin)))
10238 {
10239 extra_x = XFIXNUM (XCAR (Vtab_bar_button_margin)) - thick;
10240 extra_y = XFIXNUM (XCDR (Vtab_bar_button_margin)) - thick;
10241 }
10242 else if (FIXNUMP (Vtab_bar_button_margin))
10243 extra_x = extra_y = XFIXNUM (Vtab_bar_button_margin) - thick;
10244 }
10245
10246 if (s->face->id == TOOL_BAR_FACE_ID)
10247 {
10248 if (CONSP (Vtool_bar_button_margin)
10249 && FIXNUMP (XCAR (Vtool_bar_button_margin))
10250 && FIXNUMP (XCDR (Vtool_bar_button_margin)))
10251 {
10252 extra_x = XFIXNUM (XCAR (Vtool_bar_button_margin));
10253 extra_y = XFIXNUM (XCDR (Vtool_bar_button_margin));
10254 }
10255 else if (FIXNUMP (Vtool_bar_button_margin))
10256 extra_x = extra_y = XFIXNUM (Vtool_bar_button_margin);
10257 }
10258
10259 top_p = bot_p = left_p = right_p = false;
10260
10261 if (s->slice.x == 0)
10262 x -= thick + extra_x, left_p = true;
10263 if (s->slice.y == 0)
10264 y -= thick + extra_y, top_p = true;
10265 if (s->slice.x + s->slice.width == s->img->width)
10266 x1 += thick + extra_x, right_p = true;
10267 if (s->slice.y + s->slice.height == s->img->height)
10268 y1 += thick + extra_y, bot_p = true;
10269
10270 x_setup_relief_colors (s);
10271 get_glyph_string_clip_rect (s, &r);
10272 x_draw_relief_rect (s->f, x, y, x1, y1, thick, thick, raised_p,
10273 top_p, bot_p, left_p, right_p, &r);
10274 }
10275
10276
10277 #ifndef USE_CAIRO
10278
10279
10280 static void
10281 x_draw_image_foreground_1 (struct glyph_string *s, Pixmap pixmap)
10282 {
10283 int x = 0;
10284 int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
10285
10286
10287
10288 if (s->face->box != FACE_NO_BOX
10289 && s->first_glyph->left_box_line_p
10290 && s->slice.x == 0)
10291 x += max (s->face->box_vertical_line_width, 0);
10292
10293
10294
10295 if (s->slice.x == 0)
10296 x += s->img->hmargin;
10297 if (s->slice.y == 0)
10298 y += s->img->vmargin;
10299
10300 if (s->img->pixmap)
10301 {
10302 Display *display = FRAME_X_DISPLAY (s->f);
10303
10304 if (s->img->mask)
10305 {
10306
10307
10308
10309
10310
10311
10312 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
10313 | GCFunction);
10314 XGCValues xgcv;
10315
10316 xgcv.clip_mask = s->img->mask;
10317 xgcv.clip_x_origin = x - s->slice.x;
10318 xgcv.clip_y_origin = y - s->slice.y;
10319 xgcv.function = GXcopy;
10320 XChangeGC (display, s->gc, mask, &xgcv);
10321
10322 x_composite_image (s, pixmap,
10323 #ifdef HAVE_XRENDER
10324 None,
10325 #endif
10326 s->slice.x, s->slice.y, x, y,
10327 s->slice.width, s->slice.height);
10328 XSetClipMask (display, s->gc, None);
10329 }
10330 else
10331 {
10332 XCopyArea (display, s->img->pixmap, pixmap, s->gc,
10333 s->slice.x, s->slice.y,
10334 s->slice.width, s->slice.height, x, y);
10335
10336
10337
10338
10339
10340
10341
10342 if (s->hl == DRAW_CURSOR)
10343 {
10344 int r = eabs (s->img->relief);
10345 x_draw_rectangle (s->f, s->gc, x - r, y - r,
10346 s->slice.width + r*2 - 1,
10347 s->slice.height + r*2 - 1);
10348 }
10349 }
10350 }
10351 else
10352
10353 x_draw_rectangle (s->f, s->gc, x, y,
10354 s->slice.width - 1, s->slice.height - 1);
10355 }
10356 #endif
10357
10358
10359
10360
10361
10362 static void
10363 x_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w, int h)
10364 {
10365 if (s->stippled_p)
10366 {
10367 Display *display = FRAME_X_DISPLAY (s->f);
10368
10369
10370 XSetFillStyle (display, s->gc, FillOpaqueStippled);
10371 x_fill_rectangle (s->f, s->gc, x, y, w, h, true);
10372 XSetFillStyle (display, s->gc, FillSolid);
10373 }
10374 else
10375 x_clear_glyph_string_rect (s, x, y, w, h);
10376 }
10377
10378
10379
10380
10381
10382
10383
10384
10385
10386
10387
10388
10389
10390
10391
10392
10393 static void
10394 x_draw_image_glyph_string (struct glyph_string *s)
10395 {
10396 int box_line_hwidth = max (s->face->box_vertical_line_width, 0);
10397 int box_line_vwidth = max (s->face->box_horizontal_line_width, 0);
10398 int height;
10399 #ifndef USE_CAIRO
10400 Display *display = FRAME_X_DISPLAY (s->f);
10401 Pixmap pixmap = None;
10402 #endif
10403
10404 height = s->height;
10405 if (s->slice.y == 0)
10406 height -= box_line_vwidth;
10407 if (s->slice.y + s->slice.height >= s->img->height)
10408 height -= box_line_vwidth;
10409
10410
10411
10412
10413 s->stippled_p = s->face->stipple != 0;
10414 if (height > s->slice.height
10415 || s->img->hmargin
10416 || s->img->vmargin
10417 || s->img->mask
10418 || s->img->pixmap == 0
10419 || s->width != s->background_width)
10420 {
10421 if (s->stippled_p)
10422 s->row->stipple_p = true;
10423
10424 #ifndef USE_CAIRO
10425 if (s->img->mask)
10426 {
10427
10428
10429
10430 int depth = FRAME_DISPLAY_INFO (s->f)->n_planes;
10431
10432
10433 pixmap = XCreatePixmap (display, FRAME_X_DRAWABLE (s->f),
10434 s->background_width,
10435 s->height, depth);
10436
10437
10438
10439 XSetClipMask (display, s->gc, None);
10440
10441
10442 if (s->stippled_p)
10443 {
10444
10445 XSetFillStyle (display, s->gc, FillOpaqueStippled);
10446 XSetTSOrigin (display, s->gc, - s->x, - s->y);
10447 XFillRectangle (display, pixmap, s->gc,
10448 0, 0, s->background_width, s->height);
10449 XSetFillStyle (display, s->gc, FillSolid);
10450 XSetTSOrigin (display, s->gc, 0, 0);
10451 }
10452 else
10453 {
10454 XGCValues xgcv;
10455 #if defined HAVE_XRENDER && (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2))
10456 if (FRAME_DISPLAY_INFO (s->f)->alpha_bits
10457 && s->f->alpha_background != 1.0
10458 && FRAME_CHECK_XR_VERSION (s->f, 0, 2)
10459 && FRAME_X_PICTURE_FORMAT (s->f))
10460 {
10461 XRenderColor xc;
10462 XRenderPictureAttributes attrs;
10463 Picture pict;
10464 memset (&attrs, 0, sizeof attrs);
10465
10466 pict = XRenderCreatePicture (display, pixmap,
10467 FRAME_X_PICTURE_FORMAT (s->f),
10468 0, &attrs);
10469 x_xrender_color_from_gc_background (s->f, s->gc, &xc, true);
10470 XRenderFillRectangle (FRAME_X_DISPLAY (s->f), PictOpSrc, pict,
10471 &xc, 0, 0, s->background_width, s->height);
10472 XRenderFreePicture (display, pict);
10473 }
10474 else
10475 #endif
10476 {
10477 XGetGCValues (display, s->gc, GCForeground | GCBackground,
10478 &xgcv);
10479 XSetForeground (display, s->gc, xgcv.background);
10480 XFillRectangle (display, pixmap, s->gc,
10481 0, 0, s->background_width, s->height);
10482 XSetForeground (display, s->gc, xgcv.foreground);
10483 }
10484 }
10485 }
10486 else
10487 #endif
10488 {
10489 int x = s->x;
10490 int y = s->y;
10491 int width = s->background_width;
10492
10493 if (s->first_glyph->left_box_line_p
10494 && s->slice.x == 0)
10495 {
10496 x += box_line_hwidth;
10497 width -= box_line_hwidth;
10498 }
10499
10500 if (s->slice.y == 0)
10501 y += box_line_vwidth;
10502
10503 x_draw_glyph_string_bg_rect (s, x, y, width, height);
10504 }
10505
10506 s->background_filled_p = true;
10507 }
10508
10509
10510 #ifndef USE_CAIRO
10511 if (pixmap != None)
10512 {
10513 x_draw_image_foreground_1 (s, pixmap);
10514 x_set_glyph_string_clipping (s);
10515 XCopyArea (display, pixmap, FRAME_X_DRAWABLE (s->f), s->gc,
10516 0, 0, s->background_width, s->height, s->x, s->y);
10517 XFreePixmap (display, pixmap);
10518 }
10519 else
10520 #endif
10521 x_draw_image_foreground (s);
10522
10523
10524 if (s->img->relief
10525 || s->hl == DRAW_IMAGE_RAISED
10526 || s->hl == DRAW_IMAGE_SUNKEN)
10527 x_draw_image_relief (s);
10528 }
10529
10530
10531
10532
10533 static void
10534 x_draw_stretch_glyph_string (struct glyph_string *s)
10535 {
10536 eassert (s->first_glyph->type == STRETCH_GLYPH);
10537
10538 if (s->hl == DRAW_CURSOR
10539 && !x_stretch_cursor_p)
10540 {
10541
10542
10543 int width, background_width = s->background_width;
10544 int x = s->x;
10545
10546 if (!s->row->reversed_p)
10547 {
10548 int left_x = window_box_left_offset (s->w, TEXT_AREA);
10549
10550 if (x < left_x)
10551 {
10552 background_width -= left_x - x;
10553 x = left_x;
10554 }
10555 }
10556 else
10557 {
10558
10559
10560 int right_x = window_box_right (s->w, TEXT_AREA);
10561
10562 if (x + background_width > right_x)
10563 background_width -= x - right_x;
10564 x += background_width;
10565 }
10566 width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
10567 if (s->row->reversed_p)
10568 x -= width;
10569
10570
10571 x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
10572
10573
10574 if (width < background_width)
10575 {
10576 int y = s->y;
10577 int w = background_width - width, h = s->height;
10578 Display *display = FRAME_X_DISPLAY (s->f);
10579 XRectangle r;
10580 GC gc;
10581
10582 if (!s->row->reversed_p)
10583 x += width;
10584 else
10585 x = s->x;
10586 if (s->row->mouse_face_p
10587 && cursor_in_mouse_face_p (s->w))
10588 {
10589 x_set_mouse_face_gc (s);
10590 gc = s->gc;
10591 }
10592 else
10593 gc = s->face->gc;
10594
10595 get_glyph_string_clip_rect (s, &r);
10596 x_set_clip_rectangles (s->f, gc, &r, 1);
10597
10598 if (s->face->stipple)
10599 {
10600
10601 XSetFillStyle (display, gc, FillOpaqueStippled);
10602 x_fill_rectangle (s->f, gc, x, y, w, h, true);
10603 XSetFillStyle (display, gc, FillSolid);
10604
10605 s->row->stipple_p = true;
10606 }
10607 else
10608 {
10609 XGCValues xgcv;
10610 XGetGCValues (display, gc, GCForeground | GCBackground, &xgcv);
10611 XSetForeground (display, gc, xgcv.background);
10612 x_fill_rectangle (s->f, gc, x, y, w, h, true);
10613 XSetForeground (display, gc, xgcv.foreground);
10614 }
10615
10616 x_reset_clip_rectangles (s->f, gc);
10617 }
10618 }
10619 else if (!s->background_filled_p)
10620 {
10621 int background_width = s->background_width;
10622 int x = s->x, text_left_x = window_box_left (s->w, TEXT_AREA);
10623
10624
10625
10626 if (s->area == TEXT_AREA
10627 && x < text_left_x && !s->row->mode_line_p)
10628 {
10629 background_width -= text_left_x - x;
10630 x = text_left_x;
10631 }
10632
10633 if (!s->row->stipple_p)
10634 s->row->stipple_p = s->stippled_p;
10635
10636 if (background_width > 0)
10637 x_draw_glyph_string_bg_rect (s, x, s->y,
10638 background_width, s->height);
10639 }
10640
10641 s->background_filled_p = true;
10642 }
10643
10644 static void
10645 x_get_scale_factor (Display *disp, int *scale_x, int *scale_y)
10646 {
10647 const int base_res = 96;
10648 struct x_display_info * dpyinfo = x_display_info_for_display (disp);
10649
10650 *scale_x = *scale_y = 1;
10651
10652 if (dpyinfo)
10653 {
10654 if (dpyinfo->resx > base_res)
10655 *scale_x = floor (dpyinfo->resx / base_res);
10656 if (dpyinfo->resy > base_res)
10657 *scale_y = floor (dpyinfo->resy / base_res);
10658 }
10659 }
10660
10661
10662
10663
10664
10665
10666
10667
10668
10669
10670
10671 static void
10672 x_draw_underwave (struct glyph_string *s, int decoration_width)
10673 {
10674 Display *display = FRAME_X_DISPLAY (s->f);
10675
10676
10677 int scale_x, scale_y;
10678
10679 x_get_scale_factor (display, &scale_x, &scale_y);
10680
10681 int wave_height = 3 * scale_y, wave_length = 2 * scale_x;
10682
10683 #ifdef USE_CAIRO
10684 x_draw_horizontal_wave (s->f, s->gc, s->x, s->ybase - wave_height + 3,
10685 decoration_width, wave_height, wave_length);
10686 #else
10687 int dx, dy, x0, y0, width, x1, y1, x2, y2, xmax, thickness = scale_y;;
10688 bool odd;
10689 XRectangle wave_clip, string_clip, final_clip;
10690
10691 dx = wave_length;
10692 dy = wave_height - 1;
10693 x0 = s->x;
10694 y0 = s->ybase + wave_height / 2 - scale_y;
10695 width = decoration_width;
10696 xmax = x0 + width;
10697
10698
10699
10700 wave_clip.x = x0;
10701 wave_clip.y = y0;
10702 wave_clip.width = width;
10703 wave_clip.height = wave_height;
10704 get_glyph_string_clip_rect (s, &string_clip);
10705
10706 if (!gui_intersect_rectangles (&wave_clip, &string_clip, &final_clip))
10707 return;
10708
10709 XSetClipRectangles (display, s->gc, 0, 0, &final_clip, 1, Unsorted);
10710
10711
10712
10713 x1 = x0 - (x0 % dx);
10714 x2 = x1 + dx;
10715 odd = (x1 / dx) & 1;
10716 y1 = y2 = y0;
10717
10718 if (odd)
10719 y1 += dy;
10720 else
10721 y2 += dy;
10722
10723 if (INT_MAX - dx < xmax)
10724 emacs_abort ();
10725
10726 while (x1 <= xmax)
10727 {
10728 XSetLineAttributes (display, s->gc, thickness, LineSolid, CapButt,
10729 JoinRound);
10730 XDrawLine (display, FRAME_X_DRAWABLE (s->f), s->gc, x1, y1, x2, y2);
10731 x1 = x2, y1 = y2;
10732 x2 += dx, y2 = y0 + odd*dy;
10733 odd = !odd;
10734 }
10735
10736
10737 XSetClipRectangles (display, s->gc, 0, 0, s->clip, s->num_clips, Unsorted);
10738 #endif
10739 }
10740
10741
10742
10743
10744 static void
10745 x_draw_glyph_string (struct glyph_string *s)
10746 {
10747 bool relief_drawn_p = false;
10748
10749
10750
10751
10752 if (s->next && s->right_overhang && !s->for_overlaps)
10753 {
10754 int width;
10755 struct glyph_string *next;
10756
10757 for (width = 0, next = s->next;
10758 next && width < s->right_overhang;
10759 width += next->width, next = next->next)
10760 if (next->first_glyph->type != IMAGE_GLYPH)
10761 {
10762 x_set_glyph_string_gc (next);
10763 x_set_glyph_string_clipping (next);
10764 if (next->first_glyph->type == STRETCH_GLYPH)
10765 x_draw_stretch_glyph_string (next);
10766 else
10767 x_draw_glyph_string_background (next, true);
10768 next->num_clips = 0;
10769 }
10770 }
10771
10772
10773 x_set_glyph_string_gc (s);
10774
10775
10776
10777 if (!s->for_overlaps
10778 && s->face->box != FACE_NO_BOX
10779 && (s->first_glyph->type == CHAR_GLYPH
10780 || s->first_glyph->type == COMPOSITE_GLYPH))
10781
10782 {
10783 x_set_glyph_string_clipping (s);
10784 x_draw_glyph_string_background (s, true);
10785 x_draw_glyph_string_box (s);
10786 x_set_glyph_string_clipping (s);
10787 relief_drawn_p = true;
10788 }
10789 else if (!s->clip_head
10790 && !s->clip_tail
10791 && ((s->prev && s->prev->hl != s->hl && s->left_overhang)
10792 || (s->next && s->next->hl != s->hl && s->right_overhang)))
10793
10794
10795
10796 x_set_glyph_string_clipping_exactly (s, s);
10797 else
10798 x_set_glyph_string_clipping (s);
10799
10800 switch (s->first_glyph->type)
10801 {
10802 case IMAGE_GLYPH:
10803 x_draw_image_glyph_string (s);
10804 break;
10805
10806 case XWIDGET_GLYPH:
10807 x_draw_xwidget_glyph_string (s);
10808 break;
10809
10810 case STRETCH_GLYPH:
10811 x_draw_stretch_glyph_string (s);
10812 break;
10813
10814 case CHAR_GLYPH:
10815 if (s->for_overlaps)
10816 s->background_filled_p = true;
10817 else
10818 x_draw_glyph_string_background (s, false);
10819 x_draw_glyph_string_foreground (s);
10820 break;
10821
10822 case COMPOSITE_GLYPH:
10823 if (s->for_overlaps || (s->cmp_from > 0
10824 && ! s->first_glyph->u.cmp.automatic))
10825 s->background_filled_p = true;
10826 else
10827 x_draw_glyph_string_background (s, true);
10828 x_draw_composite_glyph_string_foreground (s);
10829 break;
10830
10831 case GLYPHLESS_GLYPH:
10832 if (s->for_overlaps)
10833 s->background_filled_p = true;
10834 else
10835 x_draw_glyph_string_background (s, true);
10836 x_draw_glyphless_glyph_string_foreground (s);
10837 break;
10838
10839 default:
10840 emacs_abort ();
10841 }
10842
10843 if (!s->for_overlaps)
10844 {
10845 int area_x, area_y, area_width, area_height;
10846 int area_max_x, decoration_width;
10847
10848
10849
10850 window_box (s->w, s->area, &area_x, &area_y,
10851 &area_width, &area_height);
10852 area_max_x = area_x + area_width - 1;
10853
10854 decoration_width = s->width;
10855 if (!s->row->mode_line_p
10856 && !s->row->tab_line_p
10857 && area_max_x < (s->x + decoration_width - 1))
10858 decoration_width -= (s->x + decoration_width - 1) - area_max_x;
10859
10860
10861 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
10862 x_draw_glyph_string_box (s);
10863
10864
10865 if (s->face->underline)
10866 {
10867 if (s->face->underline == FACE_UNDER_WAVE)
10868 {
10869 if (s->face->underline_defaulted_p)
10870 x_draw_underwave (s, decoration_width);
10871 else
10872 {
10873 Display *display = FRAME_X_DISPLAY (s->f);
10874 XGCValues xgcv;
10875 XGetGCValues (display, s->gc, GCForeground, &xgcv);
10876 XSetForeground (display, s->gc, s->face->underline_color);
10877 x_draw_underwave (s, decoration_width);
10878 XSetForeground (display, s->gc, xgcv.foreground);
10879 }
10880 }
10881 else if (s->face->underline == FACE_UNDER_LINE)
10882 {
10883 unsigned long thickness, position;
10884 int y;
10885
10886 if (s->prev
10887 && s->prev->face->underline == FACE_UNDER_LINE
10888 && (s->prev->face->underline_at_descent_line_p
10889 == s->face->underline_at_descent_line_p)
10890 && (s->prev->face->underline_pixels_above_descent_line
10891 == s->face->underline_pixels_above_descent_line))
10892 {
10893
10894 thickness = s->prev->underline_thickness;
10895 position = s->prev->underline_position;
10896 }
10897 else
10898 {
10899 struct font *font = font_for_underline_metrics (s);
10900 unsigned long minimum_offset;
10901 bool underline_at_descent_line;
10902 bool use_underline_position_properties;
10903 Lisp_Object val = (WINDOW_BUFFER_LOCAL_VALUE
10904 (Qunderline_minimum_offset, s->w));
10905
10906 if (FIXNUMP (val))
10907 minimum_offset = max (0, XFIXNUM (val));
10908 else
10909 minimum_offset = 1;
10910
10911 val = (WINDOW_BUFFER_LOCAL_VALUE
10912 (Qx_underline_at_descent_line, s->w));
10913 underline_at_descent_line
10914 = (!(NILP (val) || BASE_EQ (val, Qunbound))
10915 || s->face->underline_at_descent_line_p);
10916
10917 val = (WINDOW_BUFFER_LOCAL_VALUE
10918 (Qx_use_underline_position_properties, s->w));
10919 use_underline_position_properties
10920 = !(NILP (val) || BASE_EQ (val, Qunbound));
10921
10922
10923 if (font && font->underline_thickness > 0)
10924 thickness = font->underline_thickness;
10925 else
10926 thickness = 1;
10927 if (underline_at_descent_line)
10928 position = ((s->height - thickness)
10929 - (s->ybase - s->y)
10930 - s->face->underline_pixels_above_descent_line);
10931 else
10932 {
10933
10934
10935
10936
10937
10938
10939
10940
10941
10942 if (use_underline_position_properties
10943 && font && font->underline_position >= 0)
10944 position = font->underline_position;
10945 else if (font)
10946 position = (font->descent + 1) / 2;
10947 else
10948 position = minimum_offset;
10949 }
10950
10951
10952
10953 if (!s->face->underline_pixels_above_descent_line)
10954 position = max (position, minimum_offset);
10955 }
10956
10957
10958 if (s->y + s->height <= s->ybase + position)
10959 position = (s->height - 1) - (s->ybase - s->y);
10960 if (s->y + s->height < s->ybase + position + thickness)
10961 thickness = (s->y + s->height) - (s->ybase + position);
10962 s->underline_thickness = thickness;
10963 s->underline_position = position;
10964 y = s->ybase + position;
10965 if (s->face->underline_defaulted_p)
10966 x_fill_rectangle (s->f, s->gc,
10967 s->x, y, decoration_width, thickness,
10968 false);
10969 else
10970 {
10971 Display *display = FRAME_X_DISPLAY (s->f);
10972 XGCValues xgcv;
10973 XGetGCValues (display, s->gc, GCForeground, &xgcv);
10974 XSetForeground (display, s->gc, s->face->underline_color);
10975 x_fill_rectangle (s->f, s->gc,
10976 s->x, y, decoration_width, thickness,
10977 false);
10978 XSetForeground (display, s->gc, xgcv.foreground);
10979 }
10980 }
10981 }
10982
10983 if (s->face->overline_p)
10984 {
10985 unsigned long dy = 0, h = 1;
10986
10987 if (s->face->overline_color_defaulted_p)
10988 x_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
10989 decoration_width, h, false);
10990 else
10991 {
10992 Display *display = FRAME_X_DISPLAY (s->f);
10993 XGCValues xgcv;
10994 XGetGCValues (display, s->gc, GCForeground, &xgcv);
10995 XSetForeground (display, s->gc, s->face->overline_color);
10996 x_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
10997 decoration_width, h, false);
10998 XSetForeground (display, s->gc, xgcv.foreground);
10999 }
11000 }
11001
11002
11003 if (s->face->strike_through_p)
11004 {
11005
11006
11007
11008
11009
11010 int glyph_y = s->ybase - s->first_glyph->ascent;
11011 int glyph_height = s->first_glyph->ascent + s->first_glyph->descent;
11012
11013
11014 unsigned long h = 1;
11015 unsigned long dy = (glyph_height - h) / 2;
11016
11017 if (s->face->strike_through_color_defaulted_p)
11018 x_fill_rectangle (s->f, s->gc, s->x, glyph_y + dy,
11019 s->width, h, false);
11020 else
11021 {
11022 Display *display = FRAME_X_DISPLAY (s->f);
11023 XGCValues xgcv;
11024 XGetGCValues (display, s->gc, GCForeground, &xgcv);
11025 XSetForeground (display, s->gc, s->face->strike_through_color);
11026 x_fill_rectangle (s->f, s->gc, s->x, glyph_y + dy,
11027 decoration_width, h, false);
11028 XSetForeground (display, s->gc, xgcv.foreground);
11029 }
11030 }
11031
11032 if (s->prev)
11033 {
11034 struct glyph_string *prev;
11035
11036 for (prev = s->prev; prev; prev = prev->prev)
11037 if (prev->hl != s->hl
11038 && prev->x + prev->width + prev->right_overhang > s->x)
11039 {
11040
11041
11042 enum draw_glyphs_face save = prev->hl;
11043
11044 prev->hl = s->hl;
11045 x_set_glyph_string_gc (prev);
11046 x_set_glyph_string_clipping_exactly (s, prev);
11047 if (prev->first_glyph->type == CHAR_GLYPH)
11048 x_draw_glyph_string_foreground (prev);
11049 else
11050 x_draw_composite_glyph_string_foreground (prev);
11051 x_reset_clip_rectangles (prev->f, prev->gc);
11052 prev->hl = save;
11053 prev->num_clips = 0;
11054 }
11055 }
11056
11057 if (s->next)
11058 {
11059 struct glyph_string *next;
11060
11061 for (next = s->next; next; next = next->next)
11062 if (next->hl != s->hl
11063 && next->x - next->left_overhang < s->x + s->width)
11064 {
11065
11066
11067 enum draw_glyphs_face save = next->hl;
11068
11069 next->hl = s->hl;
11070 x_set_glyph_string_gc (next);
11071 x_set_glyph_string_clipping_exactly (s, next);
11072 if (next->first_glyph->type == CHAR_GLYPH)
11073 x_draw_glyph_string_foreground (next);
11074 else
11075 x_draw_composite_glyph_string_foreground (next);
11076 x_reset_clip_rectangles (next->f, next->gc);
11077 next->hl = save;
11078 next->num_clips = 0;
11079 next->clip_head = s->next;
11080 }
11081 }
11082 }
11083
11084
11085 x_reset_clip_rectangles (s->f, s->gc);
11086 s->num_clips = 0;
11087
11088
11089
11090
11091 if (s->first_glyph->type != STRETCH_GLYPH
11092 && s->first_glyph->type != IMAGE_GLYPH
11093 && !s->row->stipple_p)
11094 s->row->stipple_p = s->stippled_p;
11095 }
11096
11097
11098
11099 static void
11100 x_shift_glyphs_for_insert (struct frame *f, int x, int y, int width, int height, int shift_by)
11101 {
11102
11103
11104
11105 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), FRAME_X_DRAWABLE (f),
11106 f->output_data.x->normal_gc,
11107 x, y, width, height,
11108 x + shift_by, y);
11109 }
11110
11111
11112
11113
11114 static void
11115 x_delete_glyphs (struct frame *f, int n)
11116 {
11117 emacs_abort ();
11118 }
11119
11120
11121
11122
11123
11124 #if defined USE_GTK || !defined USE_CAIRO
11125 static void
11126 x_clear_area1 (Display *dpy, Window window,
11127 int x, int y, int width, int height, int exposures)
11128 {
11129 eassert (width > 0 && height > 0);
11130 XClearArea (dpy, window, x, y, width, height, exposures);
11131 }
11132 #endif
11133
11134 void
11135 x_clear_area (struct frame *f, int x, int y, int width, int height)
11136 {
11137 #ifdef USE_CAIRO
11138 cairo_t *cr;
11139
11140 eassert (width > 0 && height > 0);
11141
11142 cr = x_begin_cr_clip (f, NULL);
11143 x_set_cr_source_with_gc_background (f, f->output_data.x->normal_gc,
11144 true);
11145 cairo_rectangle (cr, x, y, width, height);
11146 cairo_fill (cr);
11147 x_end_cr_clip (f);
11148 #else
11149 #ifndef USE_GTK
11150 if (f->alpha_background != 1.0
11151 #ifdef HAVE_XDBE
11152 || FRAME_X_DOUBLE_BUFFERED_P (f)
11153 #endif
11154 )
11155 #endif
11156 {
11157 #if defined HAVE_XRENDER && \
11158 (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2))
11159 x_xr_ensure_picture (f);
11160 if (FRAME_DISPLAY_INFO (f)->alpha_bits
11161 && FRAME_X_PICTURE (f) != None
11162 && f->alpha_background != 1.0
11163 && FRAME_CHECK_XR_VERSION (f, 0, 2))
11164 {
11165 XRenderColor xc;
11166 GC gc = f->output_data.x->normal_gc;
11167
11168 x_xr_apply_ext_clip (f, gc);
11169 x_xrender_color_from_gc_background (f, gc, &xc, true);
11170 XRenderFillRectangle (FRAME_X_DISPLAY (f),
11171 PictOpSrc, FRAME_X_PICTURE (f),
11172 &xc, x, y, width, height);
11173 x_xr_reset_ext_clip (f);
11174 x_mark_frame_dirty (f);
11175 }
11176 else
11177 #endif
11178 XFillRectangle (FRAME_X_DISPLAY (f),
11179 FRAME_X_DRAWABLE (f),
11180 f->output_data.x->reverse_gc,
11181 x, y, width, height);
11182 }
11183 #ifndef USE_GTK
11184 else
11185 x_clear_area1 (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11186 x, y, width, height, False);
11187 #endif
11188 #endif
11189 }
11190
11191
11192
11193
11194 static void
11195 x_clear_frame (struct frame *f)
11196 {
11197
11198
11199 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
11200
11201 block_input ();
11202 font_drop_xrender_surfaces (f);
11203 x_clear_window (f);
11204
11205
11206
11207 x_scroll_bar_clear (f);
11208
11209 unblock_input ();
11210 }
11211
11212
11213
11214
11215
11216
11217 static void
11218 x_send_hourglass_message (struct frame *f, bool hourglass_enabled)
11219 {
11220 struct x_display_info *dpyinfo;
11221 XEvent msg;
11222
11223 dpyinfo = FRAME_DISPLAY_INFO (f);
11224 memset (&msg, 0, sizeof msg);
11225
11226 msg.xclient.type = ClientMessage;
11227 msg.xclient.message_type
11228 = dpyinfo->Xatom_EMACS_TMP;
11229 msg.xclient.format = 8;
11230 msg.xclient.window = FRAME_X_WINDOW (f);
11231 msg.xclient.data.b[0] = hourglass_enabled ? 1 : 0;
11232
11233 XSendEvent (dpyinfo->display, FRAME_X_WINDOW (f),
11234 False, NoEventMask, &msg);
11235 }
11236
11237
11238
11239 static void
11240 x_show_hourglass (struct frame *f)
11241 {
11242 Display *dpy = FRAME_X_DISPLAY (f);
11243
11244 if (dpy)
11245 {
11246 struct x_output *x = FRAME_X_OUTPUT (f);
11247
11248
11249
11250
11251
11252
11253
11254 if (popup_activated ())
11255 return;
11256
11257 x_send_hourglass_message (f, true);
11258
11259 #ifdef USE_X_TOOLKIT
11260 if (x->widget)
11261 #else
11262 if (FRAME_OUTER_WINDOW (f))
11263 #endif
11264 {
11265 if (!x->hourglass_window)
11266 {
11267 #ifndef USE_XCB
11268 unsigned long mask = CWCursor;
11269 XSetWindowAttributes attrs;
11270 #ifdef USE_GTK
11271 Window parent = FRAME_X_WINDOW (f);
11272 #else
11273 Window parent = FRAME_OUTER_WINDOW (f);
11274 #endif
11275 attrs.cursor = x->hourglass_cursor;
11276
11277 x->hourglass_window = XCreateWindow
11278 (dpy, parent, 0, 0, 32000, 32000, 0, 0,
11279 InputOnly, CopyFromParent, mask, &attrs);
11280 #else
11281 uint32_t cursor = (uint32_t) x->hourglass_cursor;
11282 #ifdef USE_GTK
11283 xcb_window_t parent = (xcb_window_t) FRAME_X_WINDOW (f);
11284 #else
11285 xcb_window_t parent = (xcb_window_t) FRAME_OUTER_WINDOW (f);
11286 #endif
11287 x->hourglass_window
11288 = (Window) xcb_generate_id (FRAME_DISPLAY_INFO (f)->xcb_connection);
11289
11290 xcb_create_window (FRAME_DISPLAY_INFO (f)->xcb_connection,
11291 XCB_COPY_FROM_PARENT,
11292 (xcb_window_t) x->hourglass_window,
11293 parent, 0, 0, FRAME_PIXEL_WIDTH (f),
11294 FRAME_PIXEL_HEIGHT (f), 0,
11295 XCB_WINDOW_CLASS_INPUT_ONLY,
11296 XCB_COPY_FROM_PARENT, XCB_CW_CURSOR,
11297 &cursor);
11298 #endif
11299 }
11300
11301 #ifndef USE_XCB
11302 XMapRaised (dpy, x->hourglass_window);
11303
11304 flush_frame (f);
11305 #else
11306 uint32_t value = XCB_STACK_MODE_ABOVE;
11307
11308 xcb_configure_window (FRAME_DISPLAY_INFO (f)->xcb_connection,
11309 (xcb_window_t) x->hourglass_window,
11310 XCB_CONFIG_WINDOW_STACK_MODE, &value);
11311 xcb_map_window (FRAME_DISPLAY_INFO (f)->xcb_connection,
11312 (xcb_window_t) x->hourglass_window);
11313 xcb_flush (FRAME_DISPLAY_INFO (f)->xcb_connection);
11314 #endif
11315 }
11316 }
11317 }
11318
11319
11320
11321 static void
11322 x_hide_hourglass (struct frame *f)
11323 {
11324 struct x_output *x = FRAME_X_OUTPUT (f);
11325
11326
11327 if (x->hourglass_window)
11328 {
11329 #ifndef USE_XCB
11330 XUnmapWindow (FRAME_X_DISPLAY (f), x->hourglass_window);
11331 #else
11332 xcb_unmap_window (FRAME_DISPLAY_INFO (f)->xcb_connection,
11333 (xcb_window_t) x->hourglass_window);
11334 #endif
11335 x_send_hourglass_message (f, false);
11336 }
11337 }
11338
11339
11340
11341 static void
11342 XTflash (struct frame *f)
11343 {
11344 GC gc;
11345 XGCValues values;
11346 fd_set fds;
11347 int fd, rc;
11348
11349 block_input ();
11350
11351 if (FRAME_X_VISUAL_INFO (f)->class == TrueColor)
11352 {
11353 values.function = GXxor;
11354 values.foreground = (FRAME_FOREGROUND_PIXEL (f)
11355 ^ FRAME_BACKGROUND_PIXEL (f));
11356
11357 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11358 GCFunction | GCForeground, &values);
11359 }
11360 else
11361 gc = FRAME_X_OUTPUT (f)->normal_gc;
11362
11363
11364
11365 int height = FRAME_PIXEL_HEIGHT (f);
11366
11367 int flash_height = FRAME_LINE_HEIGHT (f);
11368
11369 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
11370 int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
11371 int width = flash_right - flash_left;
11372
11373
11374 if (height > 3 * FRAME_LINE_HEIGHT (f))
11375 {
11376 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
11377 flash_left,
11378 (FRAME_INTERNAL_BORDER_WIDTH (f)
11379 + FRAME_TOP_MARGIN_HEIGHT (f)),
11380 width, flash_height);
11381 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
11382 flash_left,
11383 (height - flash_height
11384 - FRAME_INTERNAL_BORDER_WIDTH (f)
11385 - FRAME_BOTTOM_MARGIN_HEIGHT (f)),
11386 width, flash_height);
11387
11388 }
11389 else
11390
11391 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
11392 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
11393 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
11394
11395 x_flush (f);
11396
11397 struct timespec delay = make_timespec (0, 150 * 1000 * 1000);
11398 struct timespec wakeup = timespec_add (current_timespec (), delay);
11399 fd = ConnectionNumber (FRAME_X_DISPLAY (f));
11400
11401
11402
11403 while (! detect_input_pending ())
11404 {
11405 struct timespec current = current_timespec ();
11406 struct timespec timeout;
11407
11408
11409 if (timespec_cmp (wakeup, current) <= 0)
11410 break;
11411
11412
11413 timeout = make_timespec (0, 10 * 1000 * 1000);
11414
11415
11416
11417 FD_ZERO (&fds);
11418 FD_SET (fd, &fds);
11419
11420
11421 rc = pselect (fd + 1, &fds, NULL, NULL, &timeout, NULL);
11422
11423
11424 if (rc >= 0 && FD_ISSET (fd, &fds))
11425 break;
11426 }
11427
11428
11429 if (height > 3 * FRAME_LINE_HEIGHT (f))
11430 {
11431 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
11432 flash_left,
11433 (FRAME_INTERNAL_BORDER_WIDTH (f)
11434 + FRAME_TOP_MARGIN_HEIGHT (f)),
11435 width, flash_height);
11436 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
11437 flash_left,
11438 (height - flash_height
11439 - FRAME_INTERNAL_BORDER_WIDTH (f)
11440 - FRAME_BOTTOM_MARGIN_HEIGHT (f)),
11441 width, flash_height);
11442 }
11443 else
11444
11445 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
11446 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
11447 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
11448
11449 if (FRAME_X_VISUAL_INFO (f)->class == TrueColor)
11450 XFreeGC (FRAME_X_DISPLAY (f), gc);
11451 x_flush (f);
11452
11453 unblock_input ();
11454 }
11455
11456
11457
11458 static void
11459 XTring_bell (struct frame *f)
11460 {
11461 struct x_display_info *dpyinfo;
11462
11463 if (!FRAME_X_DISPLAY (f))
11464 return;
11465
11466 dpyinfo = FRAME_DISPLAY_INFO (f);
11467
11468 if (visible_bell)
11469 XTflash (f);
11470 else
11471 {
11472
11473
11474
11475
11476
11477 block_input ();
11478 x_ignore_errors_for_next_request (dpyinfo, 0);
11479 #ifdef HAVE_XKB
11480 XkbBell (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 0, None);
11481 #else
11482 XBell (FRAME_X_DISPLAY (f), 0);
11483 #endif
11484 XFlush (FRAME_X_DISPLAY (f));
11485 x_stop_ignoring_errors (dpyinfo);
11486 unblock_input ();
11487 }
11488 }
11489
11490
11491
11492
11493
11494
11495
11496
11497 static void
11498 x_ins_del_lines (struct frame *f, int vpos, int n)
11499 {
11500 emacs_abort ();
11501 }
11502
11503
11504
11505
11506 static void
11507 x_scroll_run (struct window *w, struct run *run)
11508 {
11509 struct frame *f = XFRAME (w->frame);
11510 int x, y, width, height, from_y, to_y, bottom_y;
11511
11512
11513
11514
11515 window_box (w, ANY_AREA, &x, &y, &width, &height);
11516
11517 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
11518 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
11519 bottom_y = y + height;
11520
11521 if (to_y < from_y)
11522 {
11523
11524
11525 if (from_y + run->height > bottom_y)
11526 height = bottom_y - from_y;
11527 else
11528 height = run->height;
11529 }
11530 else
11531 {
11532
11533
11534 if (to_y + run->height > bottom_y)
11535 height = bottom_y - to_y;
11536 else
11537 height = run->height;
11538 }
11539
11540 block_input ();
11541
11542
11543 gui_clear_cursor (w);
11544
11545 #ifdef HAVE_XWIDGETS
11546
11547 Display *dpy = FRAME_X_DISPLAY (f);
11548 Window window = FRAME_X_WINDOW (f);
11549
11550 Window root, parent, *children;
11551 unsigned int nchildren;
11552
11553 if (XQueryTree (dpy, window, &root, &parent, &children, &nchildren))
11554 {
11555
11556
11557 for (unsigned int i = 0; i < nchildren; ++i)
11558 {
11559 Window child = children[i];
11560 struct xwidget_view *view = xwidget_view_from_window (child);
11561
11562 if (view && !view->hidden)
11563 {
11564 int window_y = view->y + view->clip_top;
11565 int window_height = view->clip_bottom - view->clip_top;
11566
11567 Emacs_Rectangle r1, r2, result;
11568 r1.x = w->pixel_left;
11569 r1.y = from_y;
11570 r1.width = w->pixel_width;
11571 r1.height = height;
11572 r2 = r1;
11573 r2.y = window_y;
11574 r2.height = window_height;
11575
11576
11577 if (window_height == 0)
11578 {
11579 view->hidden = true;
11580 XUnmapWindow (dpy, child);
11581 continue;
11582 }
11583
11584 bool intersects_p =
11585 gui_intersect_rectangles (&r1, &r2, &result);
11586
11587 if (XWINDOW (view->w) == w && intersects_p)
11588 {
11589 int y = view->y + (to_y - from_y);
11590 int text_area_x, text_area_y, text_area_width, text_area_height;
11591 int clip_top, clip_bottom;
11592
11593 window_box (w, view->area, &text_area_x, &text_area_y,
11594 &text_area_width, &text_area_height);
11595
11596 view->y = y;
11597
11598 clip_top = 0;
11599 clip_bottom = XXWIDGET (view->model)->height;
11600
11601 if (y < text_area_y)
11602 clip_top = text_area_y - y;
11603
11604 if ((y + clip_bottom) > (text_area_y + text_area_height))
11605 {
11606 clip_bottom -= (y + clip_bottom) - (text_area_y + text_area_height);
11607 }
11608
11609 view->clip_top = clip_top;
11610 view->clip_bottom = clip_bottom;
11611
11612
11613
11614 if ((view->clip_bottom - view->clip_top) <= 0)
11615 {
11616 view->hidden = true;
11617 XUnmapWindow (dpy, child);
11618 }
11619 else
11620 {
11621 XMoveResizeWindow (dpy, child, view->x + view->clip_left,
11622 view->y + view->clip_top,
11623 view->clip_right - view->clip_left,
11624 view->clip_bottom - view->clip_top);
11625 cairo_xlib_surface_set_size (view->cr_surface,
11626 view->clip_right - view->clip_left,
11627 view->clip_bottom - view->clip_top);
11628 }
11629 xwidget_expose (view);
11630 }
11631 }
11632 }
11633 XFree (children);
11634 }
11635 #endif
11636
11637 #ifdef USE_CAIRO_XCB_SURFACE
11638
11639
11640
11641 XFlushGC (FRAME_X_DISPLAY (f),
11642 f->output_data.x->normal_gc);
11643 #endif
11644
11645 #ifdef USE_CAIRO
11646 if (FRAME_CR_CONTEXT (f))
11647 {
11648 cairo_surface_t *surface = cairo_get_target (FRAME_CR_CONTEXT (f));
11649 if (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_XLIB)
11650 {
11651 eassert (cairo_xlib_surface_get_display (surface)
11652 == FRAME_X_DISPLAY (f));
11653 eassert (cairo_xlib_surface_get_drawable (surface)
11654 == FRAME_X_RAW_DRAWABLE (f));
11655 cairo_surface_flush (surface);
11656 XCopyArea (FRAME_X_DISPLAY (f),
11657 FRAME_X_DRAWABLE (f), FRAME_X_DRAWABLE (f),
11658 f->output_data.x->normal_gc,
11659 x, from_y,
11660 width, height,
11661 x, to_y);
11662 cairo_surface_mark_dirty_rectangle (surface, x, to_y, width, height);
11663 }
11664 #ifdef USE_CAIRO_XCB_SURFACE
11665 else if (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_XCB)
11666 {
11667 cairo_surface_flush (surface);
11668 xcb_copy_area (FRAME_DISPLAY_INFO (f)->xcb_connection,
11669 (xcb_drawable_t) FRAME_X_DRAWABLE (f),
11670 (xcb_drawable_t) FRAME_X_DRAWABLE (f),
11671 (xcb_gcontext_t) XGContextFromGC (f->output_data.x->normal_gc),
11672 x, from_y, x, to_y, width, height);
11673 cairo_surface_mark_dirty_rectangle (surface, x, to_y, width, height);
11674 }
11675 #endif
11676 else
11677 {
11678 cairo_surface_t *s
11679 = cairo_surface_create_similar (surface,
11680 cairo_surface_get_content (surface),
11681 width, height);
11682 cairo_t *cr = cairo_create (s);
11683 cairo_set_source_surface (cr, surface, -x, -from_y);
11684 cairo_paint (cr);
11685 cairo_destroy (cr);
11686
11687 cr = FRAME_CR_CONTEXT (f);
11688 cairo_save (cr);
11689 cairo_set_source_surface (cr, s, x, to_y);
11690 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
11691 cairo_rectangle (cr, x, to_y, width, height);
11692 cairo_fill (cr);
11693 cairo_restore (cr);
11694 cairo_surface_destroy (s);
11695 }
11696 }
11697 else
11698 #endif
11699 XCopyArea (FRAME_X_DISPLAY (f),
11700 FRAME_X_DRAWABLE (f), FRAME_X_DRAWABLE (f),
11701 f->output_data.x->normal_gc,
11702 x, from_y,
11703 width, height,
11704 x, to_y);
11705
11706 unblock_input ();
11707 }
11708
11709
11710
11711
11712
11713
11714
11715
11716 static void
11717 x_frame_highlight (struct frame *f)
11718 {
11719 struct x_display_info *dpyinfo;
11720
11721 dpyinfo = FRAME_DISPLAY_INFO (f);
11722
11723
11724
11725
11726
11727 block_input ();
11728
11729
11730
11731
11732 x_ignore_errors_for_next_request (dpyinfo, 0);
11733 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11734 f->output_data.x->border_pixel);
11735 x_stop_ignoring_errors (dpyinfo);
11736 unblock_input ();
11737 gui_update_cursor (f, true);
11738 x_set_frame_alpha (f);
11739 }
11740
11741 static void
11742 x_frame_unhighlight (struct frame *f)
11743 {
11744 struct x_display_info *dpyinfo;
11745
11746 dpyinfo = FRAME_DISPLAY_INFO (f);
11747
11748
11749
11750
11751
11752
11753 block_input ();
11754
11755 x_ignore_errors_for_next_request (dpyinfo, 0);
11756 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11757 f->output_data.x->border_tile);
11758 x_stop_ignoring_errors (dpyinfo);
11759 unblock_input ();
11760
11761 gui_update_cursor (f, true);
11762 x_set_frame_alpha (f);
11763 }
11764
11765
11766
11767
11768
11769
11770
11771 static void
11772 x_new_focus_frame (struct x_display_info *dpyinfo, struct frame *frame)
11773 {
11774 struct frame *old_focus = dpyinfo->x_focus_frame;
11775 #if defined USE_GTK && !defined HAVE_GTK3 && defined HAVE_XINPUT2
11776 XIEventMask mask;
11777 ptrdiff_t l;
11778
11779 if (dpyinfo->supports_xi2)
11780 {
11781 l = XIMaskLen (XI_LASTEVENT);
11782 mask.mask = alloca (l);
11783 mask.mask_len = l;
11784 memset (mask.mask, 0, l);
11785
11786 mask.deviceid = XIAllDevices;
11787 }
11788 #endif
11789
11790 if (frame != dpyinfo->x_focus_frame)
11791 {
11792
11793
11794 dpyinfo->x_focus_frame = frame;
11795
11796
11797
11798
11799 #if defined USE_GTK && !defined HAVE_GTK3 && defined HAVE_XINPUT2
11800 if (frame && dpyinfo->supports_xi2)
11801 XISetMask (mask.mask, XI_RawKeyPress);
11802
11803 if (dpyinfo->supports_xi2)
11804 XISelectEvents (dpyinfo->display, dpyinfo->root_window, &mask, 1);
11805 #endif
11806
11807 if (old_focus && old_focus->auto_lower)
11808 x_lower_frame (old_focus);
11809
11810 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
11811 dpyinfo->x_pending_autoraise_frame = dpyinfo->x_focus_frame;
11812 else
11813 dpyinfo->x_pending_autoraise_frame = NULL;
11814 }
11815
11816 x_frame_rehighlight (dpyinfo);
11817 }
11818
11819 #if defined HAVE_XFIXES && XFIXES_VERSION >= 40000
11820
11821
11822
11823
11824 static bool
11825 x_fixes_pointer_blanking_supported (struct x_display_info *dpyinfo)
11826 {
11827 return (dpyinfo->xfixes_supported_p
11828 && dpyinfo->xfixes_major >= 4);
11829 }
11830
11831 #endif
11832
11833
11834
11835 #if defined HAVE_XFIXES && XFIXES_VERSION >= 40000
11836
11837 static void
11838 xfixes_toggle_visible_pointer (struct frame *f, bool invisible)
11839
11840 {
11841 if (invisible)
11842 XFixesHideCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11843 else
11844 XFixesShowCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11845 f->pointer_invisible = invisible;
11846 }
11847
11848 #endif
11849
11850
11851 static Cursor
11852 make_invisible_cursor (struct x_display_info *dpyinfo)
11853 {
11854 Display *dpy = dpyinfo->display;
11855 static char const no_data[] = { 0 };
11856 Pixmap pix;
11857 XColor col;
11858 Cursor c;
11859
11860 c = None;
11861
11862 x_catch_errors (dpy);
11863 pix = XCreateBitmapFromData (dpy, dpyinfo->root_window, no_data, 1, 1);
11864 if (!x_had_errors_p (dpy) && pix != None)
11865 {
11866 Cursor pixc;
11867 col.pixel = 0;
11868 col.red = col.green = col.blue = 0;
11869 col.flags = DoRed | DoGreen | DoBlue;
11870 pixc = XCreatePixmapCursor (dpy, pix, pix, &col, &col, 0, 0);
11871 if (! x_had_errors_p (dpy) && pixc != None)
11872 c = pixc;
11873 XFreePixmap (dpy, pix);
11874 }
11875
11876 x_uncatch_errors ();
11877
11878 return c;
11879 }
11880
11881
11882
11883 static void
11884 x_toggle_visible_pointer (struct frame *f, bool invisible)
11885 {
11886 struct x_display_info *dpyinfo;
11887
11888 dpyinfo = FRAME_DISPLAY_INFO (f);
11889
11890
11891
11892
11893 if (dpyinfo->invisible_cursor == None)
11894 dpyinfo->invisible_cursor = make_invisible_cursor (dpyinfo);
11895
11896 #if !defined HAVE_XFIXES || XFIXES_VERSION < 40000
11897 if (dpyinfo->invisible_cursor == None)
11898 invisible = false;
11899 #else
11900
11901 if (dpyinfo->invisible_cursor == None)
11902 {
11903 if (x_fixes_pointer_blanking_supported (dpyinfo))
11904 {
11905 dpyinfo->fixes_pointer_blanking = true;
11906 xfixes_toggle_visible_pointer (f, invisible);
11907
11908 return;
11909 }
11910 else
11911 invisible = false;
11912 }
11913 #endif
11914
11915 if (invisible)
11916 XDefineCursor (dpyinfo->display, FRAME_X_WINDOW (f),
11917 dpyinfo->invisible_cursor);
11918 else
11919 XDefineCursor (dpyinfo->display, FRAME_X_WINDOW (f),
11920 f->output_data.x->current_cursor);
11921
11922 f->pointer_invisible = invisible;
11923 }
11924
11925 static void
11926 XTtoggle_invisible_pointer (struct frame *f, bool invisible)
11927 {
11928 block_input ();
11929 #if defined HAVE_XFIXES && XFIXES_VERSION >= 40000
11930 if (FRAME_DISPLAY_INFO (f)->fixes_pointer_blanking
11931 && x_fixes_pointer_blanking_supported (FRAME_DISPLAY_INFO (f)))
11932 xfixes_toggle_visible_pointer (f, invisible);
11933 else
11934 #endif
11935 x_toggle_visible_pointer (f, invisible);
11936 unblock_input ();
11937 }
11938
11939
11940
11941
11942
11943
11944
11945
11946 static void
11947 x_focus_changed (int type, int state, struct x_display_info *dpyinfo,
11948 struct frame *frame, struct input_event *bufp)
11949 {
11950 if (type == FocusIn)
11951 {
11952 if (dpyinfo->x_focus_event_frame != frame)
11953 {
11954 x_new_focus_frame (dpyinfo, frame);
11955 dpyinfo->x_focus_event_frame = frame;
11956 bufp->kind = FOCUS_IN_EVENT;
11957 XSETFRAME (bufp->frame_or_window, frame);
11958 }
11959
11960 frame->output_data.x->focus_state |= state;
11961
11962 #ifdef HAVE_X_I18N
11963 if (FRAME_XIC (frame))
11964 XSetICFocus (FRAME_XIC (frame));
11965 #ifdef USE_GTK
11966 GtkWidget *widget;
11967
11968 if (x_gtk_use_native_input)
11969 {
11970 gtk_im_context_focus_in (FRAME_X_OUTPUT (frame)->im_context);
11971 widget = FRAME_GTK_OUTER_WIDGET (frame);
11972 gtk_im_context_set_client_window (FRAME_X_OUTPUT (frame)->im_context,
11973 gtk_widget_get_window (widget));
11974 }
11975 #endif
11976 #endif
11977 }
11978 else if (type == FocusOut)
11979 {
11980 frame->output_data.x->focus_state &= ~state;
11981
11982 if (dpyinfo->x_focus_event_frame == frame)
11983 {
11984 dpyinfo->x_focus_event_frame = 0;
11985 x_new_focus_frame (dpyinfo, 0);
11986
11987 bufp->kind = FOCUS_OUT_EVENT;
11988 XSETFRAME (bufp->frame_or_window, frame);
11989 }
11990
11991 if (!frame->output_data.x->focus_state)
11992 {
11993 #ifdef HAVE_X_I18N
11994 if (FRAME_XIC (frame))
11995 XUnsetICFocus (FRAME_XIC (frame));
11996 #ifdef USE_GTK
11997 if (x_gtk_use_native_input)
11998 {
11999 gtk_im_context_focus_out (FRAME_X_OUTPUT (frame)->im_context);
12000 gtk_im_context_set_client_window (FRAME_X_OUTPUT (frame)->im_context, NULL);
12001 }
12002 #endif
12003 #endif
12004 }
12005
12006 if (frame->pointer_invisible)
12007 XTtoggle_invisible_pointer (frame, false);
12008 }
12009 }
12010
12011
12012
12013
12014
12015 static struct frame *
12016 x_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
12017 {
12018 Lisp_Object tail, frame;
12019 struct frame *f;
12020
12021 if (wdesc == None)
12022 return NULL;
12023
12024 #ifdef HAVE_XWIDGETS
12025 struct xwidget_view *xvw = xwidget_view_from_window (wdesc);
12026
12027 if (xvw && xvw->frame)
12028 return xvw->frame;
12029 #endif
12030
12031 FOR_EACH_FRAME (tail, frame)
12032 {
12033 f = XFRAME (frame);
12034 if (!FRAME_X_P (f) || FRAME_DISPLAY_INFO (f) != dpyinfo)
12035 continue;
12036 if (f->output_data.x->hourglass_window == wdesc)
12037 return f;
12038 #ifdef USE_X_TOOLKIT
12039 if ((f->output_data.x->edit_widget
12040 && XtWindow (f->output_data.x->edit_widget) == wdesc)
12041
12042 || (!f->output_data.x->edit_widget
12043 && FRAME_X_WINDOW (f) == wdesc)
12044 || f->output_data.x->icon_desc == wdesc)
12045 return f;
12046 #else
12047 #ifdef USE_GTK
12048 if (f->output_data.x->edit_widget)
12049 {
12050 GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
12051 struct x_output *x = f->output_data.x;
12052 if (gwdesc != 0 && gwdesc == x->edit_widget)
12053 return f;
12054 }
12055 #endif
12056 if (FRAME_X_WINDOW (f) == wdesc
12057 || f->output_data.x->icon_desc == wdesc)
12058 return f;
12059 #endif
12060 }
12061 return 0;
12062 }
12063
12064
12065
12066
12067
12068 static struct frame *
12069 x_tooltip_window_to_frame (struct x_display_info *dpyinfo,
12070 Window wdesc, bool *unrelated_tooltip_p)
12071 {
12072 Lisp_Object tail, frame;
12073 struct frame *f;
12074 #ifdef USE_GTK
12075 GtkWidget *widget;
12076 GdkWindow *tooltip_window;
12077 #endif
12078
12079 if (unrelated_tooltip_p)
12080 *unrelated_tooltip_p = false;
12081
12082 FOR_EACH_FRAME (tail, frame)
12083 {
12084 f = XFRAME (frame);
12085
12086 if (FRAME_X_P (f) && FRAME_TOOLTIP_P (f)
12087 && FRAME_DISPLAY_INFO (f) == dpyinfo
12088 && FRAME_X_WINDOW (f) == wdesc)
12089 return f;
12090
12091 #ifdef USE_GTK
12092 if (!FRAME_X_P (f))
12093 continue;
12094
12095 if (FRAME_X_OUTPUT (f)->ttip_window)
12096 widget = GTK_WIDGET (FRAME_X_OUTPUT (f)->ttip_window);
12097 else
12098 widget = NULL;
12099
12100 if (widget)
12101 tooltip_window = gtk_widget_get_window (widget);
12102 else
12103 tooltip_window = NULL;
12104
12105 #ifdef HAVE_GTK3
12106 if (tooltip_window
12107 && (gdk_x11_window_get_xid (tooltip_window) == wdesc))
12108 {
12109 if (unrelated_tooltip_p)
12110 *unrelated_tooltip_p = true;
12111 break;
12112 }
12113 #else
12114 if (tooltip_window
12115 && (GDK_WINDOW_XID (tooltip_window) == wdesc))
12116 {
12117 if (unrelated_tooltip_p)
12118 *unrelated_tooltip_p = true;
12119 break;
12120 }
12121 #endif
12122 #endif
12123 }
12124
12125 return NULL;
12126 }
12127
12128 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
12129
12130
12131
12132
12133 static struct frame *
12134 x_any_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
12135 {
12136 Lisp_Object tail, frame;
12137 struct frame *f, *found = NULL;
12138 struct x_output *x;
12139
12140 if (wdesc == None)
12141 return NULL;
12142
12143 #ifdef HAVE_XWIDGETS
12144 struct xwidget_view *xv = xwidget_view_from_window (wdesc);
12145
12146 if (xv)
12147 return xv->frame;
12148 #endif
12149
12150 FOR_EACH_FRAME (tail, frame)
12151 {
12152 if (found)
12153 break;
12154 f = XFRAME (frame);
12155 if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) == dpyinfo)
12156 {
12157
12158 x = f->output_data.x;
12159 if (x->hourglass_window == wdesc)
12160 found = f;
12161 else if (x->widget)
12162 {
12163 #ifdef USE_GTK
12164 GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
12165 if (gwdesc != 0
12166 && gtk_widget_get_toplevel (gwdesc) == x->widget)
12167 found = f;
12168 #else
12169 if (wdesc == XtWindow (x->widget)
12170 || wdesc == XtWindow (x->column_widget)
12171 || wdesc == XtWindow (x->edit_widget))
12172 found = f;
12173
12174 else if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
12175 found = f;
12176 #endif
12177 }
12178 else if (FRAME_X_WINDOW (f) == wdesc)
12179
12180 found = f;
12181 }
12182 }
12183
12184 return found;
12185 }
12186
12187
12188
12189 static struct frame *
12190 x_menubar_window_to_frame (struct x_display_info *dpyinfo,
12191 const XEvent *event)
12192 {
12193 Window wdesc;
12194 #ifdef HAVE_XINPUT2
12195 if (event->type == GenericEvent
12196 && dpyinfo->supports_xi2
12197 && (event->xcookie.evtype == XI_ButtonPress
12198 || event->xcookie.evtype == XI_ButtonRelease))
12199 wdesc = ((XIDeviceEvent *) event->xcookie.data)->event;
12200 else
12201 #endif
12202 wdesc = event->xany.window;
12203 Lisp_Object tail, frame;
12204 struct frame *f;
12205 struct x_output *x;
12206
12207 if (wdesc == None)
12208 return NULL;
12209
12210 FOR_EACH_FRAME (tail, frame)
12211 {
12212 f = XFRAME (frame);
12213 if (!FRAME_X_P (f) || FRAME_DISPLAY_INFO (f) != dpyinfo)
12214 continue;
12215 x = f->output_data.x;
12216 #ifdef USE_GTK
12217 if (x->menubar_widget && xg_event_is_for_menubar (f, event))
12218 return f;
12219 #else
12220
12221 if (x->menubar_widget
12222 && lw_window_is_in_menubar (wdesc, x->menubar_widget))
12223 return f;
12224 #endif
12225 }
12226 return 0;
12227 }
12228
12229
12230
12231
12232 struct frame *
12233 x_top_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
12234 {
12235 Lisp_Object tail, frame;
12236 struct frame *f;
12237 struct x_output *x;
12238
12239 if (wdesc == None)
12240 return NULL;
12241
12242 FOR_EACH_FRAME (tail, frame)
12243 {
12244 f = XFRAME (frame);
12245 if (!FRAME_X_P (f) || FRAME_DISPLAY_INFO (f) != dpyinfo)
12246 continue;
12247 x = f->output_data.x;
12248
12249 if (x->widget)
12250 {
12251
12252 #ifdef USE_GTK
12253 GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
12254 if (gwdesc == x->widget)
12255 return f;
12256 #else
12257 if (wdesc == XtWindow (x->widget))
12258 return f;
12259 #endif
12260 }
12261 else if (FRAME_X_WINDOW (f) == wdesc)
12262
12263 return f;
12264 }
12265 return 0;
12266 }
12267
12268 #else
12269
12270 #define x_any_window_to_frame(d, i) x_window_to_frame (d, i)
12271
12272 struct frame *
12273 x_top_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
12274 {
12275 return x_window_to_frame (dpyinfo, wdesc);
12276 }
12277
12278 static void
12279 x_next_event_from_any_display (XEvent *event)
12280 {
12281 struct x_display_info *dpyinfo;
12282 fd_set fds, rfds;
12283 int fd, maxfd, rc;
12284
12285 rc = -1;
12286 FD_ZERO (&rfds);
12287
12288 while (true)
12289 {
12290 FD_ZERO (&fds);
12291 maxfd = -1;
12292
12293 for (dpyinfo = x_display_list; dpyinfo;
12294 dpyinfo = dpyinfo->next)
12295 {
12296 fd = ConnectionNumber (dpyinfo->display);
12297
12298 if ((rc < 0 || FD_ISSET (fd, &rfds))
12299 && XPending (dpyinfo->display))
12300 {
12301 XNextEvent (dpyinfo->display, event);
12302 return;
12303 }
12304
12305 if (fd > maxfd)
12306 maxfd = fd;
12307
12308 eassert (fd < FD_SETSIZE);
12309 FD_SET (fd, &fds);
12310 }
12311
12312 eassert (maxfd >= 0);
12313
12314
12315
12316
12317 rc = pselect (maxfd + 1, &fds, NULL, NULL, NULL, NULL);
12318
12319 if (rc >= 0)
12320 rfds = fds;
12321 }
12322 }
12323
12324 #endif
12325
12326 static void
12327 x_handle_pending_selection_requests_1 (struct x_selection_request_event *tem)
12328 {
12329 specpdl_ref count;
12330 struct selection_input_event se;
12331
12332 count = SPECPDL_INDEX ();
12333 se = tem->se;
12334
12335 record_unwind_protect_ptr (xfree, tem);
12336 x_handle_selection_event (&se);
12337 unbind_to (count, Qnil);
12338 }
12339
12340
12341
12342 void
12343 x_handle_pending_selection_requests (void)
12344 {
12345 struct x_selection_request_event *tem;
12346
12347 while (pending_selection_requests)
12348 {
12349 tem = pending_selection_requests;
12350 pending_selection_requests = tem->next;
12351
12352 x_handle_pending_selection_requests_1 (tem);
12353 }
12354 }
12355
12356 static void
12357 x_push_selection_request (struct selection_input_event *se)
12358 {
12359 struct x_selection_request_event *tem;
12360
12361 tem = xmalloc (sizeof *tem);
12362 tem->next = pending_selection_requests;
12363 tem->se = *se;
12364 pending_selection_requests = tem;
12365 }
12366
12367 bool
12368 x_detect_pending_selection_requests (void)
12369 {
12370 return !!pending_selection_requests;
12371 }
12372
12373 static void
12374 x_clear_dnd_action (void)
12375 {
12376 x_dnd_action_symbol = Qnil;
12377 }
12378
12379
12380 static void
12381 x_dnd_delete_action_list (Lisp_Object frame)
12382 {
12383 struct frame *f;
12384
12385
12386
12387
12388
12389
12390 f = XFRAME (frame);
12391
12392 if (!FRAME_LIVE_P (f) || !FRAME_DISPLAY_INFO (f)->display)
12393 return;
12394
12395 block_input ();
12396 XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12397 FRAME_DISPLAY_INFO (f)->Xatom_XdndActionList);
12398 XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12399 FRAME_DISPLAY_INFO (f)->Xatom_XdndActionDescription);
12400 unblock_input ();
12401 }
12402
12403 static void
12404 x_dnd_lose_ownership (Lisp_Object timestamp_and_frame)
12405 {
12406 struct frame *f;
12407
12408 f = XFRAME (XCDR (timestamp_and_frame));
12409
12410 if (FRAME_LIVE_P (f))
12411 Fx_disown_selection_internal (QXdndSelection,
12412 XCAR (timestamp_and_frame),
12413 XCDR (timestamp_and_frame));
12414 }
12415
12416
12417
12418
12419 static void
12420 x_dnd_process_quit (struct frame *f, Time timestamp)
12421 {
12422 xm_drop_start_message dmsg;
12423
12424 if (x_dnd_in_progress)
12425 {
12426 if (x_dnd_last_seen_window != None
12427 && x_dnd_last_protocol_version != -1)
12428 x_dnd_send_leave (f, x_dnd_last_seen_window,
12429 x_dnd_last_seen_toplevel);
12430 else if (x_dnd_last_seen_window != None
12431 && !XM_DRAG_STYLE_IS_DROP_ONLY (x_dnd_last_motif_style)
12432 && x_dnd_last_motif_style != XM_DRAG_STYLE_NONE
12433 && x_dnd_motif_setup_p)
12434 {
12435 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
12436 XM_DRAG_REASON_DROP_START);
12437 dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST;
12438 dmsg.timestamp = timestamp;
12439 dmsg.side_effects
12440 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f),
12441 x_dnd_wanted_action),
12442 XM_DROP_SITE_VALID, x_dnd_motif_operations,
12443 XM_DROP_ACTION_DROP_CANCEL);
12444 dmsg.x = 0;
12445 dmsg.y = 0;
12446 dmsg.index_atom = x_dnd_motif_atom;
12447 dmsg.source_window = FRAME_X_WINDOW (f);
12448
12449 x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f,
12450 x_dnd_last_seen_window,
12451 timestamp);
12452 xm_send_drop_message (FRAME_DISPLAY_INFO (f), FRAME_X_WINDOW (f),
12453 x_dnd_last_seen_window, &dmsg);
12454 }
12455
12456 x_dnd_end_window = x_dnd_last_seen_window;
12457 x_dnd_last_seen_window = None;
12458 x_dnd_last_seen_toplevel = None;
12459 x_dnd_in_progress = false;
12460 x_dnd_frame = NULL;
12461 }
12462
12463 x_dnd_waiting_for_finish = false;
12464 x_dnd_return_frame_object = NULL;
12465 x_dnd_movement_frame = NULL;
12466 x_dnd_wheel_frame = NULL;
12467 }
12468
12469
12470
12471
12472
12473
12474
12475
12476
12477
12478
12479
12480
12481
12482
12483
12484
12485
12486 Lisp_Object
12487 x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
12488 Lisp_Object return_frame, Atom *ask_action_list,
12489 const char **ask_action_names, size_t n_ask_actions,
12490 bool allow_current_frame, Atom *target_atoms,
12491 int ntargets, Lisp_Object selection_target_list,
12492 bool follow_tooltip)
12493 {
12494 #ifndef USE_GTK
12495 XEvent next_event;
12496 int finish;
12497 #endif
12498 XWindowAttributes root_window_attrs;
12499 struct input_event hold_quit;
12500 char *atom_name, *ask_actions;
12501 Lisp_Object action, ltimestamp, val;
12502 specpdl_ref ref, count, base;
12503 ptrdiff_t i, end, fill;
12504 XTextProperty prop;
12505 Lisp_Object frame_object, x, y, frame, local_value;
12506 bool signals_were_pending, need_sync;
12507 #ifdef HAVE_XKB
12508 XkbStateRec keyboard_state;
12509 #endif
12510 #ifndef USE_GTK
12511 struct x_display_info *event_display;
12512 #endif
12513 unsigned int additional_mask;
12514 #ifdef HAVE_XINPUT2
12515 struct xi_device_t *device;
12516 #endif
12517
12518 if (FRAME_DISPLAY_INFO (f)->untrusted)
12519
12520
12521
12522 error ("Drag-and-drop is not possible when the client is"
12523 " not trusted by the X server.");
12524
12525 base = SPECPDL_INDEX ();
12526
12527
12528
12529 specbind (Qx_dnd_targets_list, selection_target_list);
12530
12531 if (!FRAME_VISIBLE_P (f))
12532 error ("Frame must be visible");
12533
12534 XSETFRAME (frame, f);
12535 local_value = assq_no_quit (QXdndSelection,
12536 FRAME_TERMINAL (f)->Vselection_alist);
12537
12538 if (x_dnd_in_progress || x_dnd_waiting_for_finish)
12539 error ("A drag-and-drop session is already in progress");
12540
12541 DEFER_SELECTIONS;
12542
12543
12544
12545 if (NILP (local_value))
12546 error ("No local value for XdndSelection");
12547
12548 if (popup_activated ())
12549 error ("Trying to drag-and-drop from within a menu-entry");
12550
12551 x_set_dnd_targets (target_atoms, ntargets);
12552 record_unwind_protect_void (x_free_dnd_targets);
12553 record_unwind_protect_void (x_clear_dnd_action);
12554
12555 ltimestamp = x_timestamp_for_selection (FRAME_DISPLAY_INFO (f),
12556 QXdndSelection);
12557
12558 if (NILP (ltimestamp))
12559 error ("No local value for XdndSelection");
12560
12561 if (BIGNUMP (ltimestamp))
12562 x_dnd_selection_timestamp = bignum_to_intmax (ltimestamp);
12563 else
12564 x_dnd_selection_timestamp = XFIXNUM (ltimestamp);
12565
12566
12567
12568
12569
12570 if (!x_dnd_preserve_selection_data)
12571 record_unwind_protect (x_dnd_lose_ownership,
12572 Fcons (ltimestamp, frame));
12573
12574 x_dnd_motif_operations
12575 = xm_side_effect_from_action (FRAME_DISPLAY_INFO (f), xaction);
12576
12577 x_dnd_first_motif_operation = XM_DRAG_NOOP;
12578
12579 if (n_ask_actions)
12580 {
12581 x_dnd_motif_operations
12582 = xm_operations_from_actions (FRAME_DISPLAY_INFO (f),
12583 ask_action_list,
12584 n_ask_actions);
12585 x_dnd_first_motif_operation
12586 = xm_side_effect_from_action (FRAME_DISPLAY_INFO (f),
12587 ask_action_list[0]);
12588
12589 record_unwind_protect (x_dnd_delete_action_list, frame);
12590
12591 ask_actions = NULL;
12592 end = 0;
12593 count = SPECPDL_INDEX ();
12594
12595 for (i = 0; i < n_ask_actions; ++i)
12596 {
12597 fill = end;
12598 end += strlen (ask_action_names[i]) + 1;
12599
12600 if (ask_actions)
12601 ask_actions = xrealloc (ask_actions, end);
12602 else
12603 ask_actions = xmalloc (end);
12604
12605 strncpy (ask_actions + fill,
12606 ask_action_names[i],
12607 end - fill);
12608 }
12609
12610 prop.value = (unsigned char *) ask_actions;
12611 prop.encoding = XA_STRING;
12612 prop.format = 8;
12613 prop.nitems = end;
12614
12615 record_unwind_protect_ptr (xfree, ask_actions);
12616
12617
12618
12619 block_input ();
12620 x_catch_errors (FRAME_X_DISPLAY (f));
12621 XSetTextProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12622 &prop, FRAME_DISPLAY_INFO (f)->Xatom_XdndActionDescription);
12623
12624 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12625 FRAME_DISPLAY_INFO (f)->Xatom_XdndActionList, XA_ATOM, 32,
12626 PropModeReplace, (unsigned char *) ask_action_list,
12627 n_ask_actions);
12628 x_check_errors (FRAME_X_DISPLAY (f),
12629 "Can't set action descriptions: %s");
12630 x_uncatch_errors_after_check ();
12631 unblock_input ();
12632
12633 unbind_to (count, Qnil);
12634 }
12635
12636 record_unwind_protect_void (x_clear_dnd_variables);
12637
12638 if (follow_tooltip)
12639 {
12640 #if defined HAVE_XRANDR || defined USE_GTK
12641 x_dnd_monitors
12642 = FRAME_DISPLAY_INFO (f)->last_monitor_attributes_list;
12643
12644 if (NILP (x_dnd_monitors))
12645 #endif
12646 x_dnd_monitors
12647 = Fx_display_monitor_attributes_list (frame);
12648 }
12649
12650 x_dnd_update_tooltip = follow_tooltip;
12651
12652
12653 if (x_dnd_toplevels)
12654 x_dnd_free_toplevels (true);
12655
12656 #ifdef USE_GTK
12657
12658
12659 suppress_xg_select ();
12660 record_unwind_protect_void (release_xg_select);
12661 #endif
12662
12663
12664 XSETCAR (x_dnd_selection_alias_cell, QSECONDARY);
12665 XSETCDR (x_dnd_selection_alias_cell, QSECONDARY);
12666
12667
12668
12669 specbind (Qx_selection_alias_alist,
12670 Fcons (x_dnd_selection_alias_cell,
12671 Vx_selection_alias_alist));
12672
12673
12674 x_dnd_in_progress = true;
12675 x_dnd_recursion_depth = command_loop_level + minibuf_level;
12676 x_dnd_frame = f;
12677 x_dnd_last_seen_window = None;
12678 x_dnd_last_seen_toplevel = None;
12679 x_dnd_last_protocol_version = -1;
12680 x_dnd_last_window_is_frame = false;
12681 x_dnd_last_motif_style = XM_DRAG_STYLE_NONE;
12682 x_dnd_mouse_rect_target = None;
12683 x_dnd_action = None;
12684 x_dnd_action_symbol = Qnil;
12685 x_dnd_wanted_action = xaction;
12686 x_dnd_return_frame = 0;
12687 x_dnd_waiting_for_finish = false;
12688 x_dnd_waiting_for_motif_finish = 0;
12689 x_dnd_waiting_for_status_window = None;
12690 x_dnd_pending_send_position.type = 0;
12691 x_dnd_xm_use_help = false;
12692 x_dnd_motif_setup_p = false;
12693 x_dnd_end_window = None;
12694 x_dnd_run_unsupported_drop_function = false;
12695 x_dnd_use_toplevels
12696 = x_wm_supports (f, FRAME_DISPLAY_INFO (f)->Xatom_net_client_list_stacking);
12697 x_dnd_last_tooltip_valid = false;
12698 x_dnd_toplevels = NULL;
12699 x_dnd_allow_current_frame = allow_current_frame;
12700 x_dnd_movement_frame = NULL;
12701 x_dnd_wheel_frame = NULL;
12702 x_dnd_init_type_lists = false;
12703 x_dnd_need_send_drop = false;
12704
12705 #ifdef HAVE_XINPUT2
12706
12707 if (FRAME_DISPLAY_INFO (f)->supports_xi2)
12708 {
12709
12710
12711
12712 if (FRAME_DISPLAY_INFO (f)->client_pointer_device != -1)
12713 x_dnd_pointer_device
12714 = FRAME_DISPLAY_INFO (f)->client_pointer_device;
12715 else
12716
12717 XIGetClientPointer (FRAME_X_DISPLAY (f), None,
12718 &x_dnd_pointer_device);
12719
12720 x_dnd_keyboard_device = -1;
12721
12722 device = xi_device_from_id (FRAME_DISPLAY_INFO (f),
12723 x_dnd_pointer_device);
12724
12725 if (device)
12726 x_dnd_keyboard_device = device->attachment;
12727 }
12728 else
12729 {
12730 x_dnd_pointer_device = -1;
12731 x_dnd_keyboard_device = -1;
12732 }
12733
12734 #endif
12735
12736 #ifdef HAVE_XKB
12737 x_dnd_keyboard_state = 0;
12738
12739 if (FRAME_DISPLAY_INFO (f)->supports_xkb)
12740 {
12741 XkbSelectEvents (FRAME_X_DISPLAY (f), XkbUseCoreKbd,
12742 XkbStateNotifyMask, XkbStateNotifyMask);
12743 XkbGetState (FRAME_X_DISPLAY (f), XkbUseCoreKbd,
12744 &keyboard_state);
12745
12746 x_dnd_keyboard_state = (keyboard_state.mods
12747 | keyboard_state.ptr_buttons);
12748 }
12749 #endif
12750
12751 if (x_dnd_use_toplevels)
12752 {
12753 if (x_dnd_compute_toplevels (FRAME_DISPLAY_INFO (f)))
12754 {
12755 x_dnd_free_toplevels (true);
12756 x_dnd_use_toplevels = false;
12757 }
12758 else
12759 record_unwind_protect_void (x_free_dnd_toplevels);
12760 }
12761
12762 if (!NILP (return_frame))
12763 x_dnd_return_frame = 1;
12764
12765 if (EQ (return_frame, Qnow))
12766 x_dnd_return_frame = 2;
12767
12768
12769
12770
12771
12772 XGetWindowAttributes (FRAME_X_DISPLAY (f),
12773 FRAME_DISPLAY_INFO (f)->root_window,
12774 &root_window_attrs);
12775
12776 additional_mask = SubstructureNotifyMask;
12777
12778 if (x_dnd_use_toplevels)
12779 additional_mask |= PropertyChangeMask;
12780
12781 XSelectInput (FRAME_X_DISPLAY (f),
12782 FRAME_DISPLAY_INFO (f)->root_window,
12783 root_window_attrs.your_event_mask
12784 | additional_mask);
12785
12786 if (EQ (return_frame, Qnow))
12787 x_dnd_update_state (FRAME_DISPLAY_INFO (f), CurrentTime);
12788
12789 while (x_dnd_in_progress || x_dnd_waiting_for_finish)
12790 {
12791 EVENT_INIT (hold_quit);
12792
12793 #ifdef USE_GTK
12794 current_finish = X_EVENT_NORMAL;
12795 current_hold_quit = &hold_quit;
12796 current_count = 0;
12797 xg_pending_quit_event.kind = NO_EVENT;
12798 #endif
12799
12800 block_input ();
12801 x_dnd_inside_handle_one_xevent = true;
12802 #ifdef USE_GTK
12803 gtk_main_iteration ();
12804 #elif defined USE_X_TOOLKIT
12805 XtAppNextEvent (Xt_app_con, &next_event);
12806 #else
12807 x_next_event_from_any_display (&next_event);
12808 #endif
12809
12810 #ifndef USE_GTK
12811 event_display
12812 = x_display_info_for_display (next_event.xany.display);
12813
12814 if (event_display)
12815 {
12816 #ifdef HAVE_X_I18N
12817 #ifdef HAVE_XINPUT2
12818 if (next_event.type != GenericEvent
12819 || !event_display->supports_xi2
12820 || (next_event.xgeneric.extension
12821 != event_display->xi2_opcode))
12822 {
12823 #endif
12824 if (!x_filter_event (event_display, &next_event))
12825 handle_one_xevent (event_display,
12826 &next_event, &finish, &hold_quit);
12827 #ifdef HAVE_XINPUT2
12828 }
12829 else
12830 handle_one_xevent (event_display,
12831 &next_event, &finish, &hold_quit);
12832 #endif
12833 #else
12834 handle_one_xevent (event_display,
12835 &next_event, &finish, &hold_quit);
12836 #endif
12837 }
12838 #else
12839
12840 current_count = -1;
12841 current_hold_quit = NULL;
12842 #endif
12843 x_dnd_inside_handle_one_xevent = false;
12844
12845
12846 x_clean_failable_requests (FRAME_DISPLAY_INFO (f));
12847
12848
12849
12850
12851 signals_were_pending = pending_signals;
12852 unblock_input ();
12853 pending_signals = signals_were_pending;
12854
12855
12856
12857 #ifndef USE_GTK
12858 if (event_display == FRAME_DISPLAY_INFO (f))
12859 {
12860 #endif
12861 if (x_dnd_movement_frame
12862
12863
12864 && (FRAME_X_DISPLAY (x_dnd_movement_frame)
12865 == FRAME_X_DISPLAY (f))
12866
12867
12868
12869
12870 && (x_dnd_in_progress || x_dnd_waiting_for_finish))
12871 {
12872 XSETFRAME (frame_object, x_dnd_movement_frame);
12873 XSETINT (x, x_dnd_movement_x);
12874 XSETINT (y, x_dnd_movement_y);
12875 x_dnd_movement_frame = NULL;
12876
12877 if (!NILP (Vx_dnd_movement_function)
12878 && FRAME_LIVE_P (XFRAME (frame_object))
12879 && !FRAME_TOOLTIP_P (XFRAME (frame_object))
12880 && x_dnd_movement_x >= 0
12881 && x_dnd_movement_y >= 0
12882 && x_dnd_frame
12883 && (XFRAME (frame_object) != x_dnd_frame
12884 || x_dnd_allow_current_frame))
12885 {
12886 x_dnd_old_window_attrs = root_window_attrs;
12887 x_dnd_unwind_flag = true;
12888
12889 ref = SPECPDL_INDEX ();
12890 record_unwind_protect_ptr (x_dnd_cleanup_drag_and_drop, f);
12891 call2 (Vx_dnd_movement_function, frame_object,
12892 Fposn_at_x_y (x, y, frame_object, Qnil));
12893 x_dnd_unwind_flag = false;
12894 unbind_to (ref, Qnil);
12895
12896
12897
12898
12899 redisplay_preserve_echo_area (33);
12900 }
12901 }
12902
12903 if (x_dnd_wheel_frame
12904 && (x_dnd_in_progress || x_dnd_waiting_for_finish))
12905 {
12906 XSETFRAME (frame_object, x_dnd_wheel_frame);
12907 XSETINT (x, x_dnd_wheel_x);
12908 XSETINT (y, x_dnd_wheel_y);
12909 x_dnd_wheel_frame = NULL;
12910
12911 if (!NILP (Vx_dnd_wheel_function)
12912 && FRAME_LIVE_P (XFRAME (frame_object))
12913 && !FRAME_TOOLTIP_P (XFRAME (frame_object))
12914 && x_dnd_movement_x >= 0
12915 && x_dnd_movement_y >= 0
12916 && x_dnd_frame
12917 && (XFRAME (frame_object) != x_dnd_frame
12918 || x_dnd_allow_current_frame))
12919 {
12920 x_dnd_old_window_attrs = root_window_attrs;
12921 x_dnd_unwind_flag = true;
12922
12923 ref = SPECPDL_INDEX ();
12924 record_unwind_protect_ptr (x_dnd_cleanup_drag_and_drop, f);
12925 call4 (Vx_dnd_wheel_function,
12926 Fposn_at_x_y (x, y, frame_object, Qnil),
12927 make_fixnum (x_dnd_wheel_button),
12928 make_uint (x_dnd_wheel_state),
12929 make_uint (x_dnd_wheel_time));
12930 x_dnd_unwind_flag = false;
12931 unbind_to (ref, Qnil);
12932
12933
12934
12935
12936 redisplay_preserve_echo_area (33);
12937 }
12938 }
12939
12940 if (hold_quit.kind != NO_EVENT)
12941 {
12942 x_dnd_process_quit (f, hold_quit.timestamp);
12943 #ifdef USE_GTK
12944 current_hold_quit = NULL;
12945 #endif
12946
12947 x_restore_events_after_dnd (f, &root_window_attrs);
12948
12949
12950
12951
12952 kbd_buffer_store_event (&hold_quit);
12953
12954 quit ();
12955 }
12956
12957 if (pending_selection_requests
12958 && (x_dnd_in_progress || x_dnd_waiting_for_finish))
12959 {
12960 x_dnd_old_window_attrs = root_window_attrs;
12961 x_dnd_unwind_flag = true;
12962
12963 ref = SPECPDL_INDEX ();
12964 record_unwind_protect_ptr (x_dnd_cleanup_drag_and_drop, f);
12965 x_handle_pending_selection_requests ();
12966 x_dnd_unwind_flag = false;
12967 unbind_to (ref, Qnil);
12968 }
12969
12970
12971
12972
12973 if (!NILP (Vquit_flag) && !NILP (Vinhibit_quit))
12974 {
12975 x_dnd_process_quit (f, FRAME_DISPLAY_INFO (f)->last_user_time);
12976 #ifdef USE_GTK
12977 current_hold_quit = NULL;
12978 #endif
12979 x_restore_events_after_dnd (f, &root_window_attrs);
12980 quit ();
12981 }
12982
12983 if (x_dnd_run_unsupported_drop_function
12984 && x_dnd_waiting_for_finish)
12985 {
12986 x_dnd_run_unsupported_drop_function = false;
12987 x_dnd_waiting_for_finish = false;
12988 x_dnd_unwind_flag = true;
12989
12990 ref = SPECPDL_INDEX ();
12991 record_unwind_protect_ptr (x_dnd_cleanup_drag_and_drop, f);
12992
12993 if (!NILP (Vx_dnd_unsupported_drop_function))
12994 val = call8 (Vx_dnd_unsupported_drop_function,
12995 XCAR (XCDR (x_dnd_unsupported_drop_data)),
12996 Fnth (make_fixnum (3), x_dnd_unsupported_drop_data),
12997 Fnth (make_fixnum (4), x_dnd_unsupported_drop_data),
12998 Fnth (make_fixnum (2), x_dnd_unsupported_drop_data),
12999 make_uint (x_dnd_unsupported_drop_window),
13000 frame, make_uint (x_dnd_unsupported_drop_time),
13001 Fcopy_sequence (XCAR (x_dnd_unsupported_drop_data)));
13002 else
13003 val = Qnil;
13004
13005 if (NILP (val))
13006 x_dnd_do_unsupported_drop (FRAME_DISPLAY_INFO (f),
13007 frame, XCAR (x_dnd_unsupported_drop_data),
13008 XCAR (XCDR (x_dnd_unsupported_drop_data)),
13009 x_dnd_unsupported_drop_window,
13010 XFIXNUM (Fnth (make_fixnum (3),
13011 x_dnd_unsupported_drop_data)),
13012 XFIXNUM (Fnth (make_fixnum (4),
13013 x_dnd_unsupported_drop_data)),
13014 x_dnd_unsupported_drop_time);
13015 else if (SYMBOLP (val))
13016 x_dnd_action_symbol = val;
13017
13018 x_dnd_unwind_flag = false;
13019 unbind_to (ref, Qnil);
13020
13021
13022
13023 break;
13024 }
13025
13026 #ifdef USE_GTK
13027 if (xg_pending_quit_event.kind != NO_EVENT)
13028 {
13029 xg_pending_quit_event.kind = NO_EVENT;
13030 current_hold_quit = NULL;
13031
13032 x_dnd_process_quit (f, FRAME_DISPLAY_INFO (f)->last_user_time);
13033 x_restore_events_after_dnd (f, &root_window_attrs);
13034 quit ();
13035 }
13036 #else
13037 }
13038 else
13039 {
13040 if (x_dnd_movement_frame)
13041 x_dnd_movement_frame = NULL;
13042
13043 if (x_dnd_wheel_frame)
13044 x_dnd_wheel_frame = NULL;
13045
13046 if (hold_quit.kind != NO_EVENT)
13047 EVENT_INIT (hold_quit);
13048 }
13049 #endif
13050 }
13051
13052 x_dnd_waiting_for_finish = false;
13053
13054 #ifdef USE_GTK
13055 current_hold_quit = NULL;
13056 #endif
13057 x_dnd_movement_frame = NULL;
13058 x_dnd_wheel_frame = NULL;
13059 x_restore_events_after_dnd (f, &root_window_attrs);
13060
13061 if (x_dnd_return_frame == 3
13062 && FRAME_LIVE_P (x_dnd_return_frame_object))
13063 {
13064
13065
13066
13067 if (x_dnd_return_frame_object != x_dnd_frame)
13068 x_dnd_return_frame_object->last_mouse_device = Qnil;
13069
13070 x_dnd_return_frame_object->mouse_moved = true;
13071
13072 XSETFRAME (action, x_dnd_return_frame_object);
13073 x_dnd_return_frame_object = NULL;
13074
13075 return unbind_to (base, action);
13076 }
13077
13078 x_dnd_return_frame_object = NULL;
13079 FRAME_DISPLAY_INFO (f)->grabbed = 0;
13080
13081 if (!NILP (x_dnd_action_symbol))
13082 return unbind_to (base, x_dnd_action_symbol);
13083
13084 if (x_dnd_action != None)
13085 {
13086 block_input ();
13087 x_catch_errors (FRAME_X_DISPLAY (f));
13088 atom_name = x_get_atom_name (FRAME_DISPLAY_INFO (f),
13089 x_dnd_action, &need_sync);
13090
13091 if (need_sync)
13092 x_uncatch_errors ();
13093 else
13094
13095
13096 x_uncatch_errors_after_check ();
13097
13098 if (atom_name)
13099 {
13100 action = intern (atom_name);
13101 xfree (atom_name);
13102 }
13103 else
13104 action = Qnil;
13105 unblock_input ();
13106
13107 return unbind_to (base, action);
13108 }
13109
13110 return unbind_to (base, Qnil);
13111 }
13112
13113 #ifdef HAVE_XINPUT2
13114
13115
13116
13117
13118
13119
13120
13121
13122
13123
13124
13125 static void
13126 xi_handle_focus_change (struct x_display_info *dpyinfo)
13127 {
13128 struct input_event ie;
13129 struct frame *focus, *new;
13130 struct xi_device_t *device, *source = NULL;
13131 ptrdiff_t i;
13132 Time time;
13133 #ifdef USE_GTK
13134 struct x_output *output;
13135 GtkWidget *widget;
13136 #endif
13137
13138 focus = dpyinfo->x_focus_frame;
13139 new = NULL;
13140 time = 0;
13141
13142 dpyinfo->client_pointer_device = -1;
13143
13144 for (i = 0; i < dpyinfo->num_devices; ++i)
13145 {
13146 device = &dpyinfo->devices[i];
13147
13148 if (device->focus_frame
13149 && device->focus_frame_time > time)
13150 {
13151 new = device->focus_frame;
13152 time = device->focus_frame_time;
13153 source = device;
13154
13155
13156
13157
13158 if (device->use == XIMasterKeyboard)
13159 dpyinfo->client_pointer_device = device->attachment;
13160 else
13161 dpyinfo->client_pointer_device = device->device_id;
13162 }
13163
13164
13165
13166 else if (device->focus_implicit_frame
13167 && device->focus_implicit_time > time)
13168 {
13169 new = device->focus_implicit_frame;
13170 time = device->focus_implicit_time;
13171 source = device;
13172
13173
13174
13175
13176 if (device->use == XIMasterKeyboard)
13177 dpyinfo->client_pointer_device = device->attachment;
13178 else
13179 dpyinfo->client_pointer_device = device->device_id;
13180 }
13181 }
13182
13183 if (new != focus && focus)
13184 {
13185 #ifdef HAVE_X_I18N
13186 if (FRAME_XIC (focus))
13187 XUnsetICFocus (FRAME_XIC (focus));
13188 #endif
13189
13190 #ifdef USE_GTK
13191 output = FRAME_X_OUTPUT (focus);
13192
13193 if (x_gtk_use_native_input)
13194 {
13195 gtk_im_context_focus_out (output->im_context);
13196 gtk_im_context_set_client_window (output->im_context,
13197 NULL);
13198 }
13199 #endif
13200
13201 EVENT_INIT (ie);
13202 ie.kind = FOCUS_OUT_EVENT;
13203 XSETFRAME (ie.frame_or_window, focus);
13204
13205 kbd_buffer_store_event (&ie);
13206 }
13207
13208 if (new != focus && new)
13209 {
13210 #ifdef HAVE_X_I18N
13211 if (FRAME_XIC (new))
13212 XSetICFocus (FRAME_XIC (new));
13213 #endif
13214
13215 #ifdef USE_GTK
13216 output = FRAME_X_OUTPUT (new);
13217
13218 if (x_gtk_use_native_input)
13219 {
13220 widget = FRAME_GTK_OUTER_WIDGET (new);
13221
13222 gtk_im_context_focus_in (output->im_context);
13223 gtk_im_context_set_client_window (output->im_context,
13224 gtk_widget_get_window (widget));
13225 }
13226 #endif
13227
13228 EVENT_INIT (ie);
13229 ie.kind = FOCUS_IN_EVENT;
13230 ie.device = source->name;
13231 XSETFRAME (ie.frame_or_window, new);
13232
13233 kbd_buffer_store_event (&ie);
13234 }
13235
13236 x_new_focus_frame (dpyinfo, new);
13237 }
13238
13239 static void
13240 xi_focus_handle_for_device (struct x_display_info *dpyinfo,
13241 struct frame *mentioned_frame,
13242 XIEvent *base_event)
13243 {
13244 struct xi_device_t *device;
13245 XIEnterEvent *event;
13246
13247
13248
13249 event = (XIEnterEvent *) base_event;
13250 device = xi_device_from_id (dpyinfo, event->deviceid);
13251
13252 if (!device)
13253 return;
13254
13255 switch (event->evtype)
13256 {
13257 case XI_FocusIn:
13258
13259
13260 x_display_set_last_user_time (dpyinfo, event->time,
13261 event->send_event, true);
13262
13263 device->focus_frame = mentioned_frame;
13264 device->focus_frame_time = event->time;
13265 break;
13266
13267 case XI_FocusOut:
13268
13269
13270 x_display_set_last_user_time (dpyinfo, event->time,
13271 event->send_event, false);
13272
13273 device->focus_frame = NULL;
13274
13275
13276
13277
13278
13279
13280
13281
13282
13283
13284
13285
13286
13287
13288
13289
13290
13291
13292 device->focus_implicit_frame = NULL;
13293 break;
13294
13295 case XI_Enter:
13296 if (!event->focus)
13297 break;
13298
13299 if (device->use == XIMasterPointer)
13300 device = xi_device_from_id (dpyinfo, device->attachment);
13301
13302 if (!device)
13303 break;
13304
13305 device->focus_implicit_frame = mentioned_frame;
13306 device->focus_implicit_time = event->time;
13307 break;
13308
13309 case XI_Leave:
13310 if (!event->focus)
13311 break;
13312
13313 if (device->use == XIMasterPointer)
13314 device = xi_device_from_id (dpyinfo, device->attachment);
13315
13316 if (!device)
13317 break;
13318
13319 device->focus_implicit_frame = NULL;
13320 break;
13321 }
13322
13323 xi_handle_focus_change (dpyinfo);
13324 }
13325
13326 static void
13327 xi_handle_delete_frame (struct x_display_info *dpyinfo,
13328 struct frame *f)
13329 {
13330 struct xi_device_t *device;
13331 ptrdiff_t i;
13332
13333 for (i = 0; i < dpyinfo->num_devices; ++i)
13334 {
13335 device = &dpyinfo->devices[i];
13336
13337 if (device->focus_frame == f)
13338 device->focus_frame = NULL;
13339
13340 if (device->focus_implicit_frame == f)
13341 device->focus_implicit_frame = NULL;
13342 }
13343 }
13344
13345
13346
13347
13348
13349 static void
13350 xi_handle_interaction (struct x_display_info *dpyinfo,
13351 struct frame *f, struct xi_device_t *device,
13352 Time time)
13353 {
13354 bool change;
13355
13356
13357 if (device->use == XIMasterPointer)
13358 device = xi_device_from_id (dpyinfo, device->attachment);
13359
13360 if (!device)
13361 return;
13362
13363 change = false;
13364
13365 if (device->focus_frame == f)
13366 {
13367 device->focus_frame_time = time;
13368 change = true;
13369 }
13370
13371 if (device->focus_implicit_frame == f)
13372 {
13373 device->focus_implicit_time = time;
13374 change = true;
13375 }
13376
13377
13378 if (change && f != dpyinfo->x_focus_frame)
13379 xi_handle_focus_change (dpyinfo);
13380 }
13381
13382
13383
13384
13385
13386
13387
13388 static bool
13389 xi_position_changed (struct xi_device_t *device, XIDeviceEvent *xev)
13390 {
13391 bool changed;
13392
13393 changed = true;
13394
13395 if (xev->event != device->last_motion_window)
13396 goto out;
13397
13398 if (lrint (xev->event_x) == device->last_motion_x
13399 && lrint (xev->event_y) == device->last_motion_y)
13400 {
13401 changed = false;
13402 goto out;
13403 }
13404
13405 out:
13406 device->last_motion_x = lrint (xev->event_x);
13407 device->last_motion_y = lrint (xev->event_y);
13408 device->last_motion_window = xev->event;
13409
13410 return changed;
13411 }
13412
13413 static void
13414 xi_report_motion_window_clear (struct xi_device_t *device)
13415 {
13416 device->last_motion_window = None;
13417 }
13418
13419 #ifdef HAVE_XINPUT2_1
13420
13421
13422
13423 static struct xi_scroll_valuator_t *
13424 xi_get_scroll_valuator (struct xi_device_t *device, int number)
13425 {
13426 int i;
13427
13428 for (i = 0; i < device->scroll_valuator_count; ++i)
13429 {
13430 if (device->valuators[i].number == number)
13431 return &device->valuators[i];
13432 }
13433
13434 return NULL;
13435 }
13436
13437
13438
13439
13440 static bool
13441 xi_has_scroll_valuators (XIDeviceChangedEvent *event)
13442 {
13443 int i;
13444
13445 for (i = 0; i < event->num_classes; ++i)
13446 {
13447 if (event->classes[i]->type == XIScrollClass)
13448 return true;
13449 }
13450
13451 return false;
13452 }
13453
13454
13455
13456
13457
13458
13459
13460
13461 static void
13462 xi_handle_new_classes (struct x_display_info *dpyinfo, struct xi_device_t *device,
13463 XIAnyClassInfo **classes, int num_classes)
13464 {
13465 XIScrollClassInfo *scroll;
13466 struct xi_scroll_valuator_t *valuator;
13467 XIValuatorClassInfo *valuator_info;
13468 int i;
13469 #ifdef HAVE_XINPUT2_2
13470 XITouchClassInfo *touch;
13471 #endif
13472
13473 if (dpyinfo->xi2_version < 1)
13474
13475
13476 return;
13477
13478 device->valuators = xnmalloc (num_classes,
13479 sizeof *device->valuators);
13480 device->scroll_valuator_count = 0;
13481 #ifdef HAVE_XINPUT2_2
13482 device->direct_p = false;
13483 #endif
13484
13485 for (i = 0; i < num_classes; ++i)
13486 {
13487 switch (classes[i]->type)
13488 {
13489 case XIScrollClass:
13490 scroll = (XIScrollClassInfo *) classes[i];
13491
13492 xi_populate_scroll_valuator (device,
13493 device->scroll_valuator_count++,
13494 scroll);
13495 break;
13496
13497 #ifdef HAVE_XINPUT2_2
13498 case XITouchClass:
13499 touch = (XITouchClassInfo *) classes[i];
13500
13501
13502
13503
13504
13505
13506
13507
13508
13509
13510
13511
13512
13513
13514
13515
13516
13517
13518
13519
13520
13521
13522 if (touch->mode == XIDirectTouch)
13523 device->direct_p = true;
13524 else
13525 device->direct_p = false;
13526
13527 break;
13528 #endif
13529 }
13530 }
13531
13532
13533
13534
13535 for (i = 0; i < num_classes; ++i)
13536 {
13537 if (classes[i]->type != XIValuatorClass)
13538 continue;
13539
13540 valuator_info = (XIValuatorClassInfo *) classes[i];
13541
13542
13543
13544
13545
13546
13547
13548 if (valuator_info->value == 0.0
13549 && valuator_info->mode != XIModeAbsolute)
13550 continue;
13551
13552 valuator = xi_get_scroll_valuator (device,
13553 valuator_info->number);
13554
13555 if (!valuator)
13556 continue;
13557
13558 valuator->invalid_p = false;
13559 valuator->current_value = valuator_info->value;
13560 valuator->emacs_value = 0;
13561
13562 break;
13563 }
13564 }
13565
13566 #endif
13567
13568
13569
13570
13571 static void
13572 xi_handle_device_changed (struct x_display_info *dpyinfo,
13573 struct xi_device_t *device,
13574 XIDeviceChangedEvent *event)
13575 {
13576 #ifdef HAVE_XINPUT2_1
13577 int ndevices;
13578 XIDeviceInfo *info;
13579 #endif
13580 #ifdef HAVE_XINPUT2_2
13581 struct xi_touch_point_t *tem, *last;
13582 #endif
13583
13584 #ifdef HAVE_XINPUT2_1
13585 if (xi_has_scroll_valuators (event))
13586
13587
13588
13589
13590
13591
13592
13593 xi_handle_new_classes (dpyinfo, device, event->classes,
13594 event->num_classes);
13595 else
13596 {
13597
13598
13599
13600
13601
13602
13603 x_catch_errors (dpyinfo->display);
13604 info = XIQueryDevice (dpyinfo->display, event->deviceid,
13605
13606
13607
13608 &ndevices);
13609 x_uncatch_errors ();
13610
13611 if (!info)
13612 return;
13613
13614
13615
13616 xi_handle_new_classes (dpyinfo, device, info->classes,
13617 info->num_classes);
13618 }
13619 #endif
13620
13621 #ifdef HAVE_XINPUT2_2
13622
13623
13624 if (!device->direct_p)
13625 {
13626 tem = device->touchpoints;
13627
13628 while (tem)
13629 {
13630 last = tem;
13631 tem = tem->next;
13632 xfree (last);
13633 }
13634
13635 device->touchpoints = NULL;
13636 }
13637 #endif
13638 }
13639
13640
13641
13642
13643
13644
13645 static void
13646 xi_disable_devices (struct x_display_info *dpyinfo,
13647 int *to_disable, int n_disabled)
13648 {
13649 struct xi_device_t *devices;
13650 int ndevices, i, j;
13651 #ifdef HAVE_XINPUT2_2
13652 struct xi_touch_point_t *tem, *last;
13653 #endif
13654 #if defined HAVE_XINPUT2_2 && !defined HAVE_EXT_TOOL_BAR
13655 struct x_output *output;
13656 Lisp_Object tail, frame;
13657 #endif
13658
13659
13660
13661 if (!n_disabled)
13662 return;
13663
13664 ndevices = 0;
13665 devices = xzalloc (sizeof *devices * dpyinfo->num_devices);
13666
13667
13668
13669
13670
13671 for (i = 0; i < dpyinfo->num_devices; ++i)
13672 {
13673 for (j = 0; j < n_disabled; ++j)
13674 {
13675 if (to_disable[j] == dpyinfo->devices[i].device_id)
13676 {
13677 if (x_dnd_in_progress
13678
13679
13680
13681 && to_disable[j] == x_dnd_pointer_device)
13682 x_dnd_cancel_dnd_early ();
13683
13684
13685
13686 #ifdef HAVE_XINPUT2_1
13687 xfree (dpyinfo->devices[i].valuators);
13688 #endif
13689
13690
13691
13692 #ifdef HAVE_XINPUT2_2
13693 tem = dpyinfo->devices[i].touchpoints;
13694 while (tem)
13695 {
13696 last = tem;
13697 tem = tem->next;
13698 xfree (last);
13699 }
13700
13701 #ifndef HAVE_EXT_TOOL_BAR
13702
13703
13704
13705
13706
13707 FOR_EACH_FRAME (tail, frame)
13708 {
13709 if (!FRAME_X_P (XFRAME (frame))
13710 || (FRAME_DISPLAY_INFO (XFRAME (frame))
13711 != dpyinfo))
13712 continue;
13713
13714 output = FRAME_OUTPUT_DATA (XFRAME (frame));
13715
13716 if (output->tool_bar_touch_device
13717 == dpyinfo->devices[i].device_id)
13718 {
13719 if (XFRAME (frame)->last_tool_bar_item != -1
13720 && WINDOWP (XFRAME (frame)->tool_bar_window))
13721 handle_tool_bar_click (XFRAME (frame), 0, 0,
13722 false, 0);
13723
13724 output->tool_bar_touch_device = 0;
13725 }
13726 }
13727 #endif
13728 #endif
13729
13730 goto out;
13731 }
13732
13733 devices[ndevices++] = dpyinfo->devices[i];
13734
13735 out:
13736 continue;
13737 }
13738 }
13739
13740
13741 xfree (dpyinfo->devices);
13742
13743 dpyinfo->devices = devices;
13744 dpyinfo->num_devices = ndevices;
13745 }
13746
13747 #endif
13748
13749
13750
13751
13752
13753
13754 static void
13755 x_detect_focus_change (struct x_display_info *dpyinfo, struct frame *frame,
13756 const XEvent *event, struct input_event *bufp)
13757 {
13758 if (!frame)
13759 return;
13760
13761 switch (event->type)
13762 {
13763 case EnterNotify:
13764 case LeaveNotify:
13765 {
13766 struct frame *focus_frame = dpyinfo->x_focus_event_frame;
13767 int focus_state
13768 = focus_frame ? focus_frame->output_data.x->focus_state : 0;
13769
13770 if (event->xcrossing.detail != NotifyInferior
13771 && event->xcrossing.focus
13772 && ! (focus_state & FOCUS_EXPLICIT))
13773 x_focus_changed ((event->type == EnterNotify ? FocusIn : FocusOut),
13774 FOCUS_IMPLICIT,
13775 dpyinfo, frame, bufp);
13776 }
13777 break;
13778
13779 case FocusIn:
13780 case FocusOut:
13781
13782
13783
13784
13785
13786
13787
13788 if (event->xfocus.mode == NotifyGrab
13789 || event->xfocus.mode == NotifyUngrab)
13790 return;
13791 x_focus_changed (event->type,
13792 (event->xfocus.detail == NotifyPointer ?
13793 FOCUS_IMPLICIT : FOCUS_EXPLICIT),
13794 dpyinfo, frame, bufp);
13795 break;
13796
13797 case ClientMessage:
13798 if (event->xclient.message_type == dpyinfo->Xatom_XEMBED)
13799 {
13800 enum xembed_message msg = event->xclient.data.l[1];
13801 x_focus_changed ((msg == XEMBED_FOCUS_IN ? FocusIn : FocusOut),
13802 FOCUS_EXPLICIT, dpyinfo, frame, bufp);
13803 }
13804 break;
13805 }
13806 }
13807
13808
13809 #if (defined USE_LUCID && defined HAVE_XINPUT2) \
13810 || (!defined USE_X_TOOLKIT && !defined USE_GTK)
13811
13812
13813 void
13814 x_mouse_leave (struct x_display_info *dpyinfo)
13815 {
13816 #if defined HAVE_XINPUT2 && !defined USE_X_TOOLKIT
13817 struct xi_device_t *device;
13818 #endif
13819 Mouse_HLInfo *hlinfo;
13820
13821 hlinfo = &dpyinfo->mouse_highlight;
13822
13823 if (hlinfo->mouse_face_mouse_frame)
13824 {
13825 clear_mouse_face (hlinfo);
13826 hlinfo->mouse_face_mouse_frame = NULL;
13827 }
13828
13829 #if defined HAVE_XINPUT2 && !defined USE_X_TOOLKIT
13830 if (!dpyinfo->supports_xi2)
13831
13832
13833
13834
13835
13836
13837 #endif
13838 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
13839 #if defined HAVE_XINPUT2 && !defined USE_X_TOOLKIT
13840 else
13841 {
13842 if (dpyinfo->client_pointer_device == -1)
13843
13844
13845 return;
13846
13847 device = xi_device_from_id (dpyinfo, dpyinfo->client_pointer_device);
13848
13849 if (device && device->focus_implicit_frame)
13850 {
13851 device->focus_implicit_frame = NULL;
13852
13853
13854 xi_handle_focus_change (dpyinfo);
13855 }
13856 }
13857 #endif
13858 }
13859 #endif
13860
13861
13862
13863
13864
13865
13866
13867
13868
13869 static void
13870 XTframe_rehighlight (struct frame *frame)
13871 {
13872 x_frame_rehighlight (FRAME_DISPLAY_INFO (frame));
13873 }
13874
13875 static void
13876 x_frame_rehighlight (struct x_display_info *dpyinfo)
13877 {
13878 struct frame *old_highlight = dpyinfo->highlight_frame;
13879
13880 if (dpyinfo->x_focus_frame)
13881 {
13882 dpyinfo->highlight_frame
13883 = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
13884 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
13885 : dpyinfo->x_focus_frame);
13886 if (! FRAME_LIVE_P (dpyinfo->highlight_frame))
13887 {
13888 fset_focus_frame (dpyinfo->x_focus_frame, Qnil);
13889 dpyinfo->highlight_frame = dpyinfo->x_focus_frame;
13890 }
13891 }
13892 else
13893 dpyinfo->highlight_frame = 0;
13894
13895 if (dpyinfo->highlight_frame != old_highlight)
13896 {
13897 if (old_highlight)
13898 x_frame_unhighlight (old_highlight);
13899 if (dpyinfo->highlight_frame)
13900 x_frame_highlight (dpyinfo->highlight_frame);
13901 }
13902 }
13903
13904
13905
13906
13907
13908
13909 static void
13910 x_find_modifier_meanings (struct x_display_info *dpyinfo)
13911 {
13912 int min_code, max_code;
13913 KeySym *syms;
13914 int syms_per_code;
13915 XModifierKeymap *mods;
13916 #ifdef HAVE_XKB
13917 int i;
13918 int found_meta_p = false;
13919 unsigned int vmodmask;
13920 #endif
13921
13922 dpyinfo->meta_mod_mask = 0;
13923 dpyinfo->shift_lock_mask = 0;
13924 dpyinfo->alt_mod_mask = 0;
13925 dpyinfo->super_mod_mask = 0;
13926 dpyinfo->hyper_mod_mask = 0;
13927
13928 #ifdef HAVE_XKB
13929 if (dpyinfo->xkb_desc
13930 && dpyinfo->xkb_desc->server)
13931 {
13932 for (i = 0; i < XkbNumVirtualMods; i++)
13933 {
13934 vmodmask = dpyinfo->xkb_desc->server->vmods[i];
13935
13936 if (dpyinfo->xkb_desc->names->vmods[i] == dpyinfo->Xatom_Meta)
13937 {
13938 dpyinfo->meta_mod_mask |= vmodmask;
13939
13940 if (vmodmask)
13941 found_meta_p = true;
13942 }
13943 else if (dpyinfo->xkb_desc->names->vmods[i] == dpyinfo->Xatom_Alt)
13944 dpyinfo->alt_mod_mask |= vmodmask;
13945 else if (dpyinfo->xkb_desc->names->vmods[i] == dpyinfo->Xatom_Super)
13946 dpyinfo->super_mod_mask |= vmodmask;
13947 else if (dpyinfo->xkb_desc->names->vmods[i] == dpyinfo->Xatom_Hyper)
13948 dpyinfo->hyper_mod_mask |= vmodmask;
13949 else if (dpyinfo->xkb_desc->names->vmods[i] == dpyinfo->Xatom_ShiftLock)
13950 dpyinfo->shift_lock_mask |= vmodmask;
13951 }
13952
13953 if (!found_meta_p)
13954 {
13955 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
13956 dpyinfo->alt_mod_mask = 0;
13957 }
13958
13959 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
13960 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
13961
13962 if (dpyinfo->hyper_mod_mask & dpyinfo->super_mod_mask)
13963 dpyinfo->hyper_mod_mask &= ~dpyinfo->super_mod_mask;
13964
13965 return;
13966 }
13967 #endif
13968
13969 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
13970
13971 syms = XGetKeyboardMapping (dpyinfo->display,
13972 min_code, max_code - min_code + 1,
13973 &syms_per_code);
13974
13975 if (!syms)
13976 {
13977 dpyinfo->meta_mod_mask = Mod1Mask;
13978 dpyinfo->super_mod_mask = Mod2Mask;
13979 return;
13980 }
13981
13982 mods = XGetModifierMapping (dpyinfo->display);
13983
13984
13985
13986 {
13987 int row, col;
13988 bool found_alt_or_meta;
13989
13990 for (row = 3; row < 8; row++)
13991 {
13992 found_alt_or_meta = false;
13993 for (col = 0; col < mods->max_keypermod; col++)
13994 {
13995 KeyCode code = mods->modifiermap[(row * mods->max_keypermod) + col];
13996
13997
13998 if (code == 0)
13999 continue;
14000
14001
14002 {
14003 int code_col;
14004
14005 for (code_col = 0; code_col < syms_per_code; code_col++)
14006 {
14007 int sym = syms[((code - min_code) * syms_per_code) + code_col];
14008
14009 switch (sym)
14010 {
14011 case XK_Meta_L:
14012 case XK_Meta_R:
14013 found_alt_or_meta = true;
14014 dpyinfo->meta_mod_mask |= (1 << row);
14015 break;
14016
14017 case XK_Alt_L:
14018 case XK_Alt_R:
14019 found_alt_or_meta = true;
14020 dpyinfo->alt_mod_mask |= (1 << row);
14021 break;
14022
14023 case XK_Hyper_L:
14024 case XK_Hyper_R:
14025 if (!found_alt_or_meta)
14026 dpyinfo->hyper_mod_mask |= (1 << row);
14027 code_col = syms_per_code;
14028 col = mods->max_keypermod;
14029 break;
14030
14031 case XK_Super_L:
14032 case XK_Super_R:
14033 if (!found_alt_or_meta)
14034 dpyinfo->super_mod_mask |= (1 << row);
14035 code_col = syms_per_code;
14036 col = mods->max_keypermod;
14037 break;
14038
14039 case XK_Shift_Lock:
14040
14041 if (!found_alt_or_meta && ((1 << row) == LockMask))
14042 dpyinfo->shift_lock_mask = LockMask;
14043 code_col = syms_per_code;
14044 col = mods->max_keypermod;
14045 break;
14046 }
14047 }
14048 }
14049 }
14050 }
14051 }
14052
14053
14054 if (! dpyinfo->meta_mod_mask)
14055 {
14056 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
14057 dpyinfo->alt_mod_mask = 0;
14058 }
14059
14060
14061
14062 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
14063 {
14064 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
14065 }
14066
14067
14068
14069
14070 if (dpyinfo->hyper_mod_mask & dpyinfo->super_mod_mask)
14071 dpyinfo->hyper_mod_mask &= ~dpyinfo->super_mod_mask;
14072
14073 XFree (syms);
14074
14075 if (dpyinfo->modmap)
14076 XFreeModifiermap (dpyinfo->modmap);
14077 dpyinfo->modmap = mods;
14078 }
14079
14080
14081
14082
14083 int
14084 x_x_to_emacs_modifiers (struct x_display_info *dpyinfo, int state)
14085 {
14086 int mod_ctrl = ctrl_modifier;
14087 int mod_meta = meta_modifier;
14088 int mod_alt = alt_modifier;
14089 int mod_hyper = hyper_modifier;
14090 int mod_super = super_modifier;
14091 Lisp_Object tem;
14092
14093 tem = Fget (Vx_ctrl_keysym, Qmodifier_value);
14094 if (FIXNUMP (tem)) mod_ctrl = XFIXNUM (tem) & INT_MAX;
14095 tem = Fget (Vx_alt_keysym, Qmodifier_value);
14096 if (FIXNUMP (tem)) mod_alt = XFIXNUM (tem) & INT_MAX;
14097 tem = Fget (Vx_meta_keysym, Qmodifier_value);
14098 if (FIXNUMP (tem)) mod_meta = XFIXNUM (tem) & INT_MAX;
14099 tem = Fget (Vx_hyper_keysym, Qmodifier_value);
14100 if (FIXNUMP (tem)) mod_hyper = XFIXNUM (tem) & INT_MAX;
14101 tem = Fget (Vx_super_keysym, Qmodifier_value);
14102 if (FIXNUMP (tem)) mod_super = XFIXNUM (tem) & INT_MAX;
14103
14104 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
14105 | ((state & ControlMask) ? mod_ctrl : 0)
14106 | ((state & dpyinfo->meta_mod_mask) ? mod_meta : 0)
14107 | ((state & dpyinfo->alt_mod_mask) ? mod_alt : 0)
14108 | ((state & dpyinfo->super_mod_mask) ? mod_super : 0)
14109 | ((state & dpyinfo->hyper_mod_mask) ? mod_hyper : 0));
14110 }
14111
14112 int
14113 x_emacs_to_x_modifiers (struct x_display_info *dpyinfo, intmax_t state)
14114 {
14115 EMACS_INT mod_ctrl = ctrl_modifier;
14116 EMACS_INT mod_meta = meta_modifier;
14117 EMACS_INT mod_alt = alt_modifier;
14118 EMACS_INT mod_hyper = hyper_modifier;
14119 EMACS_INT mod_super = super_modifier;
14120
14121 Lisp_Object tem;
14122
14123 tem = Fget (Vx_ctrl_keysym, Qmodifier_value);
14124 if (FIXNUMP (tem)) mod_ctrl = XFIXNUM (tem);
14125 tem = Fget (Vx_alt_keysym, Qmodifier_value);
14126 if (FIXNUMP (tem)) mod_alt = XFIXNUM (tem);
14127 tem = Fget (Vx_meta_keysym, Qmodifier_value);
14128 if (FIXNUMP (tem)) mod_meta = XFIXNUM (tem);
14129 tem = Fget (Vx_hyper_keysym, Qmodifier_value);
14130 if (FIXNUMP (tem)) mod_hyper = XFIXNUM (tem);
14131 tem = Fget (Vx_super_keysym, Qmodifier_value);
14132 if (FIXNUMP (tem)) mod_super = XFIXNUM (tem);
14133
14134
14135 return ( ((state & mod_alt) ? dpyinfo->alt_mod_mask : 0)
14136 | ((state & mod_super) ? dpyinfo->super_mod_mask : 0)
14137 | ((state & mod_hyper) ? dpyinfo->hyper_mod_mask : 0)
14138 | ((state & shift_modifier) ? ShiftMask : 0)
14139 | ((state & mod_ctrl) ? ControlMask : 0)
14140 | ((state & mod_meta) ? dpyinfo->meta_mod_mask : 0));
14141 }
14142
14143
14144
14145 char *
14146 get_keysym_name (int keysym)
14147 {
14148 char *value;
14149
14150 block_input ();
14151 value = XKeysymToString (keysym);
14152 unblock_input ();
14153
14154 return value;
14155 }
14156
14157
14158
14159
14160
14161
14162
14163 static void
14164 x_compute_root_window_offset (struct frame *f, int root_x, int root_y,
14165 int event_x, int event_y)
14166 {
14167 FRAME_X_OUTPUT (f)->window_offset_certain_p = true;
14168 FRAME_X_OUTPUT (f)->root_x = root_x - event_x;
14169 FRAME_X_OUTPUT (f)->root_y = root_y - event_y;
14170 }
14171
14172
14173
14174
14175
14176
14177
14178 void
14179 x_translate_coordinates (struct frame *f, int root_x, int root_y,
14180 int *x_out, int *y_out)
14181 {
14182 struct x_output *output;
14183 Window dummy;
14184
14185 output = FRAME_X_OUTPUT (f);
14186
14187 if (output->window_offset_certain_p)
14188 {
14189
14190 *x_out = root_x - output->root_x;
14191 *y_out = root_y - output->root_y;
14192
14193 return;
14194 }
14195
14196
14197
14198 if (!XTranslateCoordinates (FRAME_X_DISPLAY (f),
14199 FRAME_DISPLAY_INFO (f)->root_window,
14200 FRAME_X_WINDOW (f), root_x, root_y,
14201 x_out, y_out, &dummy))
14202
14203
14204 *x_out = 0, *y_out = 0;
14205 else
14206 {
14207
14208 output->window_offset_certain_p = true;
14209 output->root_x = root_x - *x_out;
14210 output->root_y = root_y - *y_out;
14211 }
14212 }
14213
14214
14215
14216
14217
14218 void
14219 x_translate_coordinates_to_root (struct frame *f, int x, int y,
14220 int *x_out, int *y_out)
14221 {
14222 struct x_output *output;
14223 Window dummy;
14224
14225 output = FRAME_X_OUTPUT (f);
14226
14227 if (output->window_offset_certain_p)
14228 {
14229
14230 *x_out = x + output->root_x;
14231 *y_out = y + output->root_y;
14232
14233 return;
14234 }
14235
14236
14237
14238 if (!XTranslateCoordinates (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
14239 FRAME_DISPLAY_INFO (f)->root_window,
14240 x, y, x_out, y_out, &dummy))
14241 *x_out = 0, *y_out = 0;
14242 else
14243 {
14244
14245 output->window_offset_certain_p = true;
14246 output->root_x = *x_out - x;
14247 output->root_y = *y_out - y;
14248 }
14249 }
14250
14251
14252
14253
14254
14255 Lisp_Object
14256 x_handle_translate_coordinates (struct frame *f, Lisp_Object dest_window,
14257 int source_x, int source_y)
14258 {
14259 if (NILP (dest_window))
14260 {
14261
14262
14263
14264
14265 if (!FRAME_X_OUTPUT (f)->window_offset_certain_p)
14266 return Qnil;
14267
14268 return list3 (make_fixnum (source_x + FRAME_X_OUTPUT (f)->root_x),
14269 make_fixnum (source_y + FRAME_X_OUTPUT (f)->root_y),
14270 Qnil);
14271 }
14272
14273 return Qnil;
14274 }
14275
14276
14277
14278 #ifdef HAVE_XINPUT2
14279
14280 static void
14281 xi_compute_root_window_offset (struct frame *f, XIDeviceEvent *xev)
14282 {
14283
14284
14285 x_compute_root_window_offset (f, xev->root_x, xev->root_y,
14286 xev->event_x, xev->event_y);
14287 }
14288
14289 static void
14290 xi_compute_root_window_offset_enter (struct frame *f, XIEnterEvent *enter)
14291 {
14292 x_compute_root_window_offset (f, enter->root_x, enter->root_y,
14293 enter->event_x, enter->event_y);
14294 }
14295
14296 #ifdef HAVE_XINPUT2_4
14297
14298 static void
14299 xi_compute_root_window_offset_pinch (struct frame *f, XIGesturePinchEvent *pev)
14300 {
14301
14302
14303 x_compute_root_window_offset (f, pev->root_x, pev->root_y,
14304 pev->event_x, pev->event_y);
14305 }
14306
14307 #endif
14308
14309 #endif
14310
14311 static Bool
14312 x_query_pointer_1 (struct x_display_info *dpyinfo,
14313 int client_pointer_device, Window w,
14314 Window *root_return, Window *child_return,
14315 int *root_x_return, int *root_y_return,
14316 int *win_x_return, int *win_y_return,
14317 unsigned int *mask_return)
14318 {
14319 Bool rc;
14320 Display *dpy;
14321 #ifdef HAVE_XINPUT2
14322 bool had_errors;
14323 XIModifierState modifiers;
14324 XIButtonState buttons;
14325 XIGroupState group;
14326 double root_x, root_y, win_x, win_y;
14327 unsigned int state;
14328 #endif
14329
14330 dpy = dpyinfo->display;
14331
14332 #ifdef HAVE_XINPUT2
14333 if (client_pointer_device != -1)
14334 {
14335
14336
14337 x_catch_errors (dpy);
14338 rc = XIQueryPointer (dpyinfo->display,
14339 dpyinfo->client_pointer_device,
14340 w, root_return, child_return,
14341 &root_x, &root_y, &win_x, &win_y,
14342 &buttons, &modifiers, &group);
14343 had_errors = x_had_errors_p (dpy);
14344 x_uncatch_errors_after_check ();
14345
14346 if (had_errors)
14347 {
14348
14349
14350
14351
14352
14353 if (client_pointer_device == dpyinfo->client_pointer_device)
14354 dpyinfo->client_pointer_device = -1;
14355
14356 rc = XQueryPointer (dpyinfo->display, w, root_return,
14357 child_return, root_x_return,
14358 root_y_return, win_x_return,
14359 win_y_return, mask_return);
14360 }
14361 else
14362 {
14363 state = 0;
14364
14365 xi_convert_button_state (&buttons, &state);
14366 *mask_return = state | modifiers.effective;
14367
14368 XFree (buttons.mask);
14369
14370 *root_x_return = lrint (root_x);
14371 *root_y_return = lrint (root_y);
14372 *win_x_return = lrint (win_x);
14373 *win_y_return = lrint (win_y);
14374 }
14375 }
14376 else
14377 #endif
14378 rc = XQueryPointer (dpy, w, root_return, child_return,
14379 root_x_return, root_y_return, win_x_return,
14380 win_y_return, mask_return);
14381
14382 return rc;
14383 }
14384
14385 Bool
14386 x_query_pointer (Display *dpy, Window w, Window *root_return,
14387 Window *child_return, int *root_x_return,
14388 int *root_y_return, int *win_x_return,
14389 int *win_y_return, unsigned int *mask_return)
14390 {
14391 struct x_display_info *dpyinfo;
14392
14393 dpyinfo = x_display_info_for_display (dpy);
14394
14395 if (!dpyinfo)
14396 emacs_abort ();
14397
14398 #ifdef HAVE_XINPUT2
14399 return x_query_pointer_1 (dpyinfo, dpyinfo->client_pointer_device,
14400 w, root_return, child_return, root_x_return,
14401 root_y_return, win_x_return, win_y_return,
14402 mask_return);
14403 #else
14404 return x_query_pointer_1 (dpyinfo, -1, w, root_return, child_return,
14405 root_x_return, root_y_return, win_x_return,
14406 win_y_return, mask_return);
14407 #endif
14408 }
14409
14410
14411
14412
14413
14414
14415
14416
14417
14418
14419
14420
14421
14422
14423
14424
14425
14426
14427
14428
14429
14430
14431
14432
14433
14434
14435
14436
14437
14438
14439
14440
14441
14442
14443
14444 static Lisp_Object
14445 x_construct_mouse_click (struct input_event *result,
14446 const XButtonEvent *event,
14447 struct frame *f)
14448 {
14449 int x = event->x;
14450 int y = event->y;
14451
14452
14453
14454 result->kind = MOUSE_CLICK_EVENT;
14455 result->code = event->button - Button1;
14456 result->timestamp = event->time;
14457 result->modifiers = (x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO (f),
14458 event->state)
14459 | (event->type == ButtonRelease
14460 ? up_modifier
14461 : down_modifier));
14462
14463
14464
14465
14466 if (event->window != FRAME_X_WINDOW (f))
14467 x_translate_coordinates (f, event->x_root, event->y_root,
14468 &x, &y);
14469
14470 XSETINT (result->x, x);
14471 XSETINT (result->y, y);
14472 XSETFRAME (result->frame_or_window, f);
14473 result->arg = Qnil;
14474 return Qnil;
14475 }
14476
14477
14478
14479
14480
14481
14482
14483
14484
14485
14486
14487
14488
14489
14490
14491
14492
14493
14494 static bool
14495 x_note_mouse_movement (struct frame *frame, const XMotionEvent *event,
14496 Lisp_Object device)
14497 {
14498 XRectangle *r;
14499 struct x_display_info *dpyinfo;
14500
14501 if (!FRAME_X_OUTPUT (frame))
14502 return false;
14503
14504 dpyinfo = FRAME_DISPLAY_INFO (frame);
14505 dpyinfo->last_mouse_movement_time = event->time;
14506 dpyinfo->last_mouse_movement_time_send_event = event->send_event;
14507 dpyinfo->last_mouse_motion_frame = frame;
14508 dpyinfo->last_mouse_motion_x = event->x;
14509 dpyinfo->last_mouse_motion_y = event->y;
14510
14511 if (event->window != FRAME_X_WINDOW (frame))
14512 {
14513 frame->mouse_moved = true;
14514 frame->last_mouse_device = device;
14515 dpyinfo->last_mouse_scroll_bar = NULL;
14516 note_mouse_highlight (frame, -1, -1);
14517 dpyinfo->last_mouse_glyph_frame = NULL;
14518 return true;
14519 }
14520
14521
14522
14523 r = &dpyinfo->last_mouse_glyph;
14524 if (frame != dpyinfo->last_mouse_glyph_frame
14525 || event->x < r->x || event->x >= r->x + r->width
14526 || event->y < r->y || event->y >= r->y + r->height)
14527 {
14528 frame->mouse_moved = true;
14529 frame->last_mouse_device = device;
14530 dpyinfo->last_mouse_scroll_bar = NULL;
14531 note_mouse_highlight (frame, event->x, event->y);
14532
14533 remember_mouse_glyph (frame, event->x, event->y, r);
14534 dpyinfo->last_mouse_glyph_frame = frame;
14535 return true;
14536 }
14537
14538 return false;
14539 }
14540
14541
14542 static Window
14543 x_get_window_below (Display *dpy, Window window,
14544 int parent_x, int parent_y,
14545 int *inner_x, int *inner_y)
14546 {
14547 int rc, i, cx, cy;
14548 XWindowAttributes attrs;
14549 unsigned int nchildren;
14550 Window root, parent, *children, value;
14551 bool window_seen;
14552
14553
14554
14555 children = NULL;
14556 window_seen = false;
14557 value = None;
14558
14559 rc = XQueryTree (dpy, window, &root, &parent,
14560 &children, &nchildren);
14561
14562 if (rc)
14563 {
14564 if (children)
14565 XFree (children);
14566
14567 rc = XQueryTree (dpy, parent, &root,
14568 &parent, &children, &nchildren);
14569 }
14570
14571 if (rc)
14572 {
14573 for (i = nchildren - 1; i >= 0; --i)
14574 {
14575 if (children[i] == window)
14576 {
14577 window_seen = true;
14578 continue;
14579 }
14580
14581 if (!window_seen)
14582 continue;
14583
14584 rc = XGetWindowAttributes (dpy, children[i], &attrs);
14585
14586 if (rc && attrs.map_state != IsViewable)
14587 continue;
14588
14589 if (rc && parent_x >= attrs.x
14590 && parent_y >= attrs.y
14591 && parent_x < attrs.x + attrs.width
14592 && parent_y < attrs.y + attrs.height)
14593 {
14594 value = children[i];
14595 cx = parent_x - attrs.x;
14596 cy = parent_y - attrs.y;
14597
14598 break;
14599 }
14600 }
14601 }
14602
14603 if (children)
14604 XFree (children);
14605
14606 if (value)
14607 {
14608 *inner_x = cx;
14609 *inner_y = cy;
14610 }
14611
14612 return value;
14613 }
14614
14615
14616
14617 static void
14618 x_fast_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
14619 enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
14620 Time *timestamp)
14621 {
14622 int root_x, root_y, win_x, win_y;
14623 unsigned int mask;
14624 Window dummy;
14625 struct scroll_bar *bar;
14626 struct x_display_info *dpyinfo;
14627 Lisp_Object tail, frame;
14628 struct frame *f1;
14629
14630 dpyinfo = FRAME_DISPLAY_INFO (*fp);
14631
14632 if (dpyinfo->last_mouse_scroll_bar && !insist)
14633 {
14634 bar = dpyinfo->last_mouse_scroll_bar;
14635
14636 if (bar->horizontal)
14637 x_horizontal_scroll_bar_report_motion (fp, bar_window, part,
14638 x, y, timestamp);
14639 else
14640 x_scroll_bar_report_motion (fp, bar_window, part,
14641 x, y, timestamp);
14642
14643 return;
14644 }
14645
14646 if (!EQ (Vx_use_fast_mouse_position, Qreally_fast))
14647 {
14648
14649
14650
14651
14652
14653
14654 FOR_EACH_FRAME (tail, frame)
14655 {
14656 if (FRAME_X_P (XFRAME (frame))
14657 && (FRAME_DISPLAY_INFO (XFRAME (frame))
14658 == dpyinfo))
14659 XFRAME (frame)->mouse_moved = false;
14660 }
14661
14662 if (gui_mouse_grabbed (dpyinfo)
14663 && !EQ (track_mouse, Qdropping)
14664 && !EQ (track_mouse, Qdrag_source))
14665
14666 f1 = dpyinfo->last_mouse_frame;
14667 else
14668
14669 f1 = dpyinfo->last_mouse_motion_frame;
14670
14671 if (!f1 && (FRAME_X_P (SELECTED_FRAME ())
14672 && (FRAME_DISPLAY_INFO (SELECTED_FRAME ())
14673 == dpyinfo)))
14674 f1 = SELECTED_FRAME ();
14675
14676 if (!f1 || (!FRAME_X_P (f1) && (insist > 0)))
14677 FOR_EACH_FRAME (tail, frame)
14678 if (FRAME_X_P (XFRAME (frame))
14679 && (FRAME_DISPLAY_INFO (XFRAME (frame))
14680 == dpyinfo)
14681 && !FRAME_TOOLTIP_P (XFRAME (frame)))
14682 f1 = XFRAME (frame);
14683
14684 if (f1 && FRAME_TOOLTIP_P (f1))
14685 f1 = NULL;
14686
14687 if (f1 && FRAME_X_P (f1) && FRAME_X_WINDOW (f1))
14688 {
14689 if (!x_query_pointer (dpyinfo->display, FRAME_X_WINDOW (f1),
14690 &dummy, &dummy, &root_x, &root_y,
14691 &win_x, &win_y, &mask))
14692
14693 return;
14694
14695 remember_mouse_glyph (f1, win_x, win_y,
14696 &dpyinfo->last_mouse_glyph);
14697 dpyinfo->last_mouse_glyph_frame = f1;
14698
14699 *bar_window = Qnil;
14700 *part = scroll_bar_nowhere;
14701
14702
14703
14704
14705 if (EQ (track_mouse, Qdrag_source)
14706 && (win_x < 0 || win_y < 0
14707 || win_x >= FRAME_PIXEL_WIDTH (f1)
14708 || win_y >= FRAME_PIXEL_HEIGHT (f1)))
14709 *fp = NULL;
14710 else
14711 *fp = f1;
14712
14713 *timestamp = dpyinfo->last_mouse_movement_time;
14714 XSETINT (*x, win_x);
14715 XSETINT (*y, win_y);
14716 }
14717 }
14718 else
14719 {
14720
14721
14722
14723 if (dpyinfo->last_mouse_motion_frame)
14724 {
14725 *fp = dpyinfo->last_mouse_motion_frame;
14726 *timestamp = dpyinfo->last_mouse_movement_time;
14727 *x = make_fixnum (dpyinfo->last_mouse_motion_x);
14728 *y = make_fixnum (dpyinfo->last_mouse_motion_y);
14729 *bar_window = Qnil;
14730 *part = scroll_bar_nowhere;
14731
14732 FOR_EACH_FRAME (tail, frame)
14733 {
14734 if (FRAME_X_P (XFRAME (frame))
14735 && (FRAME_DISPLAY_INFO (XFRAME (frame))
14736 == dpyinfo))
14737 XFRAME (frame)->mouse_moved = false;
14738 }
14739
14740 dpyinfo->last_mouse_motion_frame->mouse_moved = false;
14741 }
14742 }
14743 }
14744
14745
14746
14747
14748
14749
14750
14751
14752
14753
14754
14755
14756
14757
14758
14759
14760
14761
14762
14763
14764
14765 static void
14766 XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
14767 enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
14768 Time *timestamp)
14769 {
14770 struct frame *f1, *maybe_tooltip;
14771 struct x_display_info *dpyinfo;
14772 bool unrelated_tooltip;
14773
14774 dpyinfo = FRAME_DISPLAY_INFO (*fp);
14775
14776 if (!NILP (Vx_use_fast_mouse_position))
14777 {
14778
14779
14780
14781
14782
14783
14784
14785
14786
14787 x_fast_mouse_position (fp, insist, bar_window, part, x,
14788 y, timestamp);
14789 return;
14790 }
14791
14792 block_input ();
14793
14794 if (dpyinfo->last_mouse_scroll_bar && insist == 0)
14795 {
14796 struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar;
14797
14798 if (bar->horizontal)
14799 x_horizontal_scroll_bar_report_motion (fp, bar_window, part, x, y, timestamp);
14800 else
14801 x_scroll_bar_report_motion (fp, bar_window, part, x, y, timestamp);
14802 }
14803 else
14804 {
14805 Window root;
14806 int root_x, root_y;
14807
14808 Window dummy_window;
14809 int dummy;
14810
14811 Lisp_Object frame, tail;
14812
14813
14814 FOR_EACH_FRAME (tail, frame)
14815 if (FRAME_X_P (XFRAME (frame))
14816 && FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
14817 XFRAME (frame)->mouse_moved = false;
14818
14819 dpyinfo->last_mouse_scroll_bar = NULL;
14820
14821
14822 x_query_pointer (FRAME_X_DISPLAY (*fp),
14823 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
14824
14825 &root,
14826
14827
14828 &dummy_window,
14829
14830 &root_x, &root_y,
14831
14832 &dummy, &dummy,
14833
14834
14835 (unsigned int *) &dummy);
14836
14837
14838
14839 {
14840 Window win, child;
14841 #ifdef USE_GTK
14842 Window first_win = 0;
14843 #endif
14844 int win_x, win_y;
14845 int parent_x, parent_y;
14846
14847 win = root;
14848 parent_x = root_x;
14849 parent_y = root_y;
14850
14851
14852
14853
14854
14855 x_catch_errors (FRAME_X_DISPLAY (*fp));
14856
14857 if (gui_mouse_grabbed (dpyinfo) && !EQ (track_mouse, Qdropping)
14858 && !EQ (track_mouse, Qdrag_source))
14859 {
14860
14861
14862 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
14863
14864 root,
14865
14866 FRAME_X_WINDOW (dpyinfo->last_mouse_frame),
14867
14868 root_x, root_y, &win_x, &win_y,
14869
14870 &child);
14871 f1 = dpyinfo->last_mouse_frame;
14872 }
14873 else
14874 {
14875 while (true)
14876 {
14877 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
14878
14879 root, win,
14880
14881 root_x, root_y, &win_x, &win_y,
14882
14883 &child);
14884
14885
14886
14887 if (child != None
14888 && (EQ (track_mouse, Qdrag_source)
14889 || EQ (track_mouse, Qdropping)))
14890 {
14891 maybe_tooltip = x_tooltip_window_to_frame (dpyinfo, child,
14892 &unrelated_tooltip);
14893
14894 if (maybe_tooltip || unrelated_tooltip)
14895 child = x_get_window_below (dpyinfo->display, child,
14896 parent_x, parent_y, &win_x,
14897 &win_y);
14898 }
14899
14900 if (child == None || child == win)
14901 {
14902 #ifdef USE_GTK
14903
14904
14905 struct frame *f = x_window_to_frame (dpyinfo, win);
14906
14907 if (f && FRAME_PARENT_FRAME (f))
14908 first_win = win;
14909 #endif
14910 break;
14911 }
14912 #ifdef USE_GTK
14913
14914
14915
14916
14917 if (x_window_to_frame (dpyinfo, win))
14918
14919
14920 first_win = win;
14921 #endif
14922 win = child;
14923 parent_x = win_x;
14924 parent_y = win_y;
14925 }
14926
14927 #ifdef USE_GTK
14928 if (first_win)
14929 win = first_win;
14930 #endif
14931
14932
14933
14934
14935
14936
14937
14938
14939
14940
14941
14942
14943 #ifdef USE_GTK
14944
14945
14946 f1 = x_window_to_frame (dpyinfo, win);
14947 #else
14948
14949 f1 = x_any_window_to_frame (dpyinfo, win);
14950 #endif
14951
14952 #ifdef USE_X_TOOLKIT
14953
14954
14955 if (f1 != NULL
14956 && f1->output_data.x->menubar_widget
14957 && win == XtWindow (f1->output_data.x->menubar_widget))
14958 f1 = NULL;
14959 #endif
14960 }
14961
14962
14963
14964
14965 if ((EQ (track_mouse, Qdrag_source)
14966 || EQ (track_mouse, Qdropping))
14967 && (dpyinfo->last_user_time
14968 < dpyinfo->last_mouse_movement_time))
14969 x_display_set_last_user_time (dpyinfo,
14970 dpyinfo->last_mouse_movement_time,
14971 dpyinfo->last_mouse_movement_time_send_event,
14972 true);
14973
14974 if ((!f1 || FRAME_TOOLTIP_P (f1))
14975 && (EQ (track_mouse, Qdropping)
14976 || EQ (track_mouse, Qdrag_source))
14977 && gui_mouse_grabbed (dpyinfo))
14978 {
14979
14980
14981
14982
14983 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
14984
14985 root,
14986
14987 FRAME_X_WINDOW (dpyinfo->last_mouse_frame),
14988
14989 root_x, root_y, &win_x, &win_y,
14990
14991 &child);
14992
14993 if (!EQ (track_mouse, Qdrag_source)
14994
14995 || (f1 && FRAME_TOOLTIP_P (f1)))
14996 f1 = dpyinfo->last_mouse_frame;
14997 else
14998 {
14999
15000
15001
15002 *bar_window = Qnil;
15003 *part = 0;
15004 *fp = NULL;
15005 XSETINT (*x, win_x);
15006 XSETINT (*y, win_y);
15007 *timestamp = dpyinfo->last_mouse_movement_time;
15008 }
15009 }
15010 else if (f1 && FRAME_TOOLTIP_P (f1))
15011 f1 = NULL;
15012
15013 if (x_had_errors_p (dpyinfo->display))
15014 f1 = NULL;
15015
15016 x_uncatch_errors_after_check ();
15017
15018
15019 if (!f1)
15020 {
15021 struct scroll_bar *bar;
15022
15023 bar = x_window_to_scroll_bar (dpyinfo->display, win, 2);
15024
15025 if (bar)
15026 {
15027 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
15028 win_x = parent_x;
15029 win_y = parent_y;
15030 }
15031 }
15032
15033 if (!f1 && insist > 0)
15034 f1 = SELECTED_FRAME ();
15035
15036 if (f1 && FRAME_X_P (f1))
15037 {
15038
15039
15040
15041
15042
15043
15044
15045
15046 dpyinfo = FRAME_DISPLAY_INFO (f1);
15047 remember_mouse_glyph (f1, win_x, win_y, &dpyinfo->last_mouse_glyph);
15048 dpyinfo->last_mouse_glyph_frame = f1;
15049
15050 *bar_window = Qnil;
15051 *part = 0;
15052 *fp = f1;
15053 XSETINT (*x, win_x);
15054 XSETINT (*y, win_y);
15055 *timestamp = dpyinfo->last_mouse_movement_time;
15056 }
15057 }
15058 }
15059
15060 unblock_input ();
15061 }
15062
15063
15064
15065
15066
15067
15068
15069
15070
15071 #if defined HAVE_XINPUT2
15072
15073
15074
15075
15076
15077 MAYBE_UNUSED static void
15078 xi_select_scroll_bar_events (struct x_display_info *dpyinfo,
15079 Window scroll_bar)
15080 {
15081 XIEventMask mask;
15082 unsigned char *m;
15083 ptrdiff_t length;
15084
15085 length = XIMaskLen (XI_LASTEVENT);
15086 mask.mask = m = alloca (length);
15087 memset (m, 0, length);
15088 mask.mask_len = length;
15089
15090 mask.deviceid = XIAllMasterDevices;
15091 XISetMask (m, XI_ButtonPress);
15092 XISetMask (m, XI_ButtonRelease);
15093 XISetMask (m, XI_Motion);
15094 XISetMask (m, XI_Enter);
15095 XISetMask (m, XI_Leave);
15096
15097 XISelectEvents (dpyinfo->display, scroll_bar, &mask, 1);
15098 }
15099
15100 #endif
15101
15102
15103
15104
15105
15106
15107 static struct scroll_bar *
15108 x_window_to_scroll_bar (Display *display, Window window_id, int type)
15109 {
15110 Lisp_Object tail, frame;
15111
15112 #if defined (USE_GTK) && !defined (HAVE_GTK3) && defined (USE_TOOLKIT_SCROLL_BARS)
15113 window_id = (Window) xg_get_scroll_id_for_window (display, window_id);
15114 #endif
15115
15116 FOR_EACH_FRAME (tail, frame)
15117 {
15118 Lisp_Object bar, condemned;
15119
15120 if (! FRAME_X_P (XFRAME (frame)))
15121 continue;
15122
15123
15124
15125 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
15126 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
15127
15128
15129 ! NILP (bar) || (bar = condemned,
15130 condemned = Qnil,
15131 ! NILP (bar));
15132 bar = XSCROLL_BAR (bar)->next)
15133 if (XSCROLL_BAR (bar)->x_window == window_id
15134 && FRAME_X_DISPLAY (XFRAME (frame)) == display
15135 && (type == 2
15136 || (type == 1 && XSCROLL_BAR (bar)->horizontal)
15137 || (type == 0 && !XSCROLL_BAR (bar)->horizontal)))
15138 return XSCROLL_BAR (bar);
15139 }
15140
15141 return NULL;
15142 }
15143
15144
15145 #if defined USE_LUCID
15146
15147
15148
15149
15150 static Widget
15151 x_window_to_menu_bar (Window window)
15152 {
15153 Lisp_Object tail, frame;
15154
15155 FOR_EACH_FRAME (tail, frame)
15156 if (FRAME_X_P (XFRAME (frame)))
15157 {
15158 Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
15159
15160 if (menu_bar && xlwmenu_window_p (menu_bar, window))
15161 return menu_bar;
15162 }
15163 return NULL;
15164 }
15165
15166 #endif
15167
15168
15169
15170
15171
15172
15173 #ifdef USE_TOOLKIT_SCROLL_BARS
15174
15175 static void x_send_scroll_bar_event (Lisp_Object, enum scroll_bar_part,
15176 int, int, bool);
15177
15178
15179
15180
15181 static Lisp_Object window_being_scrolled;
15182
15183 static Time
15184 x_get_last_toolkit_time (struct x_display_info *dpyinfo)
15185 {
15186 #ifdef USE_X_TOOLKIT
15187 return XtLastTimestampProcessed (dpyinfo->display);
15188 #else
15189 return dpyinfo->last_user_time;
15190 #endif
15191 }
15192
15193 #ifndef USE_GTK
15194
15195
15196
15197 static XtActionHookId action_hook_id;
15198 static XtActionHookId horizontal_action_hook_id;
15199
15200
15201
15202
15203 static Boolean xaw3d_arrow_scroll;
15204
15205
15206
15207
15208
15209 static Boolean xaw3d_pick_top;
15210
15211
15212
15213
15214
15215
15216 static void
15217 xt_action_hook (Widget widget, XtPointer client_data, String action_name,
15218 XEvent *event, String *params, Cardinal *num_params)
15219 {
15220 bool scroll_bar_p;
15221 const char *end_action;
15222
15223 #ifdef USE_MOTIF
15224 scroll_bar_p = XmIsScrollBar (widget);
15225 end_action = "Release";
15226 #else
15227 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
15228 end_action = "EndScroll";
15229 #endif
15230
15231 if (scroll_bar_p
15232 && strcmp (action_name, end_action) == 0
15233 && WINDOWP (window_being_scrolled))
15234 {
15235 struct window *w;
15236 struct scroll_bar *bar;
15237
15238 x_send_scroll_bar_event (window_being_scrolled,
15239 scroll_bar_end_scroll, 0, 0, false);
15240 w = XWINDOW (window_being_scrolled);
15241 bar = XSCROLL_BAR (w->vertical_scroll_bar);
15242
15243 if (bar->dragging != -1)
15244 {
15245 bar->dragging = -1;
15246
15247 set_vertical_scroll_bar (w);
15248 }
15249 window_being_scrolled = Qnil;
15250 #if defined (USE_LUCID)
15251 bar->last_seen_part = scroll_bar_nowhere;
15252 #endif
15253
15254 toolkit_scroll_bar_interaction = false;
15255 }
15256 }
15257
15258
15259 static void
15260 xt_horizontal_action_hook (Widget widget, XtPointer client_data, String action_name,
15261 XEvent *event, String *params, Cardinal *num_params)
15262 {
15263 bool scroll_bar_p;
15264 const char *end_action;
15265
15266 #ifdef USE_MOTIF
15267 scroll_bar_p = XmIsScrollBar (widget);
15268 end_action = "Release";
15269 #else
15270 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
15271 end_action = "EndScroll";
15272 #endif
15273
15274 if (scroll_bar_p
15275 && strcmp (action_name, end_action) == 0
15276 && WINDOWP (window_being_scrolled))
15277 {
15278 struct window *w;
15279 struct scroll_bar *bar;
15280
15281 x_send_scroll_bar_event (window_being_scrolled,
15282 scroll_bar_end_scroll, 0, 0, true);
15283 w = XWINDOW (window_being_scrolled);
15284 if (!NILP (w->horizontal_scroll_bar))
15285 {
15286 bar = XSCROLL_BAR (w->horizontal_scroll_bar);
15287 if (bar->dragging != -1)
15288 {
15289 bar->dragging = -1;
15290
15291 set_horizontal_scroll_bar (w);
15292 }
15293 window_being_scrolled = Qnil;
15294 #if defined (USE_LUCID)
15295 bar->last_seen_part = scroll_bar_nowhere;
15296 #endif
15297
15298 toolkit_scroll_bar_interaction = false;
15299 }
15300 }
15301 }
15302 #endif
15303
15304
15305
15306
15307 static bool
15308 x_protect_window_for_callback (struct x_display_info *dpyinfo,
15309 Lisp_Object window)
15310 {
15311 if (dpyinfo->n_protected_windows + 1
15312 >= dpyinfo->protected_windows_max)
15313 return false;
15314
15315 dpyinfo->protected_windows[dpyinfo->n_protected_windows++]
15316 = window;
15317 return true;
15318 }
15319
15320 static Lisp_Object
15321 x_unprotect_window_for_callback (struct x_display_info *dpyinfo)
15322 {
15323 Lisp_Object window;
15324
15325 if (!dpyinfo->n_protected_windows)
15326 return Qnil;
15327
15328 window = dpyinfo->protected_windows[0];
15329
15330 dpyinfo->n_protected_windows--;
15331
15332 if (dpyinfo->n_protected_windows)
15333 memmove (dpyinfo->protected_windows, &dpyinfo->protected_windows[1],
15334 sizeof (Lisp_Object) * dpyinfo->n_protected_windows);
15335
15336 return window;
15337 }
15338
15339
15340
15341
15342
15343
15344 static void
15345 x_send_scroll_bar_event (Lisp_Object window, enum scroll_bar_part part,
15346 int portion, int whole, bool horizontal)
15347 {
15348 XEvent event;
15349 XClientMessageEvent *ev = &event.xclient;
15350 struct window *w = XWINDOW (window);
15351 struct frame *f = XFRAME (w->frame);
15352 verify (INTPTR_WIDTH <= 64);
15353
15354
15355
15356 if (!x_protect_window_for_callback (FRAME_DISPLAY_INFO (f), window))
15357 return;
15358
15359 block_input ();
15360
15361 ev->type = ClientMessage;
15362 ev->message_type = (horizontal
15363 ? FRAME_DISPLAY_INFO (f)->Xatom_Horizontal_Scrollbar
15364 : FRAME_DISPLAY_INFO (f)->Xatom_Scrollbar);
15365 ev->display = FRAME_X_DISPLAY (f);
15366 ev->window = FRAME_X_WINDOW (f);
15367 ev->format = 32;
15368
15369
15370
15371
15372 ev->data.l[0] = 0;
15373 ev->data.l[1] = 0;
15374 ev->data.l[2] = part;
15375 ev->data.l[3] = portion;
15376 ev->data.l[4] = whole;
15377
15378
15379 #ifdef USE_X_TOOLKIT
15380 toolkit_scroll_bar_interaction = true;
15381 x_activate_timeout_atimer ();
15382 #endif
15383
15384
15385
15386
15387 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False,
15388 NoEventMask, &event);
15389 unblock_input ();
15390 }
15391
15392
15393
15394
15395
15396 static void
15397 x_scroll_bar_to_input_event (struct x_display_info *dpyinfo,
15398 const XEvent *event,
15399 struct input_event *ievent)
15400 {
15401 Lisp_Object window;
15402
15403
15404
15405
15406
15407 window = x_unprotect_window_for_callback (dpyinfo);
15408
15409 if (NILP (window))
15410 {
15411
15412
15413 EVENT_INIT (*ievent);
15414 return;
15415 }
15416
15417 ievent->kind = SCROLL_BAR_CLICK_EVENT;
15418 ievent->frame_or_window = window;
15419 ievent->arg = Qnil;
15420 ievent->timestamp = x_get_last_toolkit_time (dpyinfo);
15421 ievent->code = 0;
15422 ievent->part = event->xclient.data.l[2];
15423 ievent->x = make_fixnum (event->xclient.data.l[3]);
15424 ievent->y = make_fixnum (event->xclient.data.l[4]);
15425 ievent->modifiers = 0;
15426 }
15427
15428
15429
15430
15431 static void
15432 x_horizontal_scroll_bar_to_input_event (struct x_display_info *dpyinfo,
15433 const XEvent *event,
15434 struct input_event *ievent)
15435 {
15436 Lisp_Object window;
15437
15438
15439
15440
15441
15442 window = x_unprotect_window_for_callback (dpyinfo);
15443
15444 if (NILP (window))
15445 {
15446
15447
15448 EVENT_INIT (*ievent);
15449 return;
15450 }
15451
15452 ievent->kind = HORIZONTAL_SCROLL_BAR_CLICK_EVENT;
15453 ievent->frame_or_window = window;
15454 ievent->arg = Qnil;
15455 ievent->timestamp = x_get_last_toolkit_time (dpyinfo);
15456 ievent->code = 0;
15457 ievent->part = event->xclient.data.l[2];
15458 ievent->x = make_fixnum (event->xclient.data.l[3]);
15459 ievent->y = make_fixnum (event->xclient.data.l[4]);
15460 ievent->modifiers = 0;
15461 }
15462
15463
15464 #ifdef USE_MOTIF
15465
15466
15467
15468 #define XM_SB_MAX 10000000
15469
15470
15471
15472
15473
15474 static void
15475 xm_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data)
15476 {
15477 struct scroll_bar *bar = client_data;
15478 XmScrollBarCallbackStruct *cs = call_data;
15479 enum scroll_bar_part part = scroll_bar_nowhere;
15480 bool horizontal = bar->horizontal;
15481 int whole = 0, portion = 0;
15482
15483 switch (cs->reason)
15484 {
15485 case XmCR_DECREMENT:
15486 bar->dragging = -1;
15487 part = horizontal ? scroll_bar_left_arrow : scroll_bar_up_arrow;
15488 break;
15489
15490 case XmCR_INCREMENT:
15491 bar->dragging = -1;
15492 part = horizontal ? scroll_bar_right_arrow : scroll_bar_down_arrow;
15493 break;
15494
15495 case XmCR_PAGE_DECREMENT:
15496 bar->dragging = -1;
15497 part = horizontal ? scroll_bar_before_handle : scroll_bar_above_handle;
15498 break;
15499
15500 case XmCR_PAGE_INCREMENT:
15501 bar->dragging = -1;
15502 part = horizontal ? scroll_bar_after_handle : scroll_bar_below_handle;
15503 break;
15504
15505 case XmCR_TO_TOP:
15506 bar->dragging = -1;
15507 part = horizontal ? scroll_bar_to_leftmost : scroll_bar_to_top;
15508 break;
15509
15510 case XmCR_TO_BOTTOM:
15511 bar->dragging = -1;
15512 part = horizontal ? scroll_bar_to_rightmost : scroll_bar_to_bottom;
15513 break;
15514
15515 case XmCR_DRAG:
15516 {
15517 int slider_size;
15518
15519 block_input ();
15520 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
15521 unblock_input ();
15522
15523 if (horizontal)
15524 {
15525 portion = bar->whole * ((float)cs->value / XM_SB_MAX);
15526 whole = bar->whole * ((float)(XM_SB_MAX - slider_size) / XM_SB_MAX);
15527 portion = min (portion, whole);
15528 part = scroll_bar_horizontal_handle;
15529 }
15530 else
15531 {
15532 whole = XM_SB_MAX - slider_size;
15533 portion = min (cs->value, whole);
15534 part = scroll_bar_handle;
15535 }
15536
15537 bar->dragging = cs->value;
15538 }
15539 break;
15540
15541 case XmCR_VALUE_CHANGED:
15542 break;
15543 };
15544
15545 if (part != scroll_bar_nowhere)
15546 {
15547 window_being_scrolled = bar->window;
15548 x_send_scroll_bar_event (bar->window, part, portion, whole,
15549 bar->horizontal);
15550 }
15551 }
15552
15553 #elif defined USE_GTK
15554
15555
15556
15557
15558 static gboolean
15559 xg_scroll_callback (GtkRange *range, GtkScrollType scroll,
15560 gdouble value, gpointer user_data)
15561 {
15562 int whole, portion;
15563 struct scroll_bar *bar;
15564 enum scroll_bar_part part;
15565 GtkAdjustment *adj;
15566 struct frame *f;
15567 guint32 time;
15568 struct x_display_info *dpyinfo;
15569
15570 if (xg_ignore_gtk_scrollbar) return false;
15571
15572 whole = 0;
15573 portion = 0;
15574 bar = user_data;
15575 part = scroll_bar_nowhere;
15576 adj = GTK_ADJUSTMENT (gtk_range_get_adjustment (range));
15577 f = g_object_get_data (G_OBJECT (range), XG_FRAME_DATA);
15578 time = gtk_get_current_event_time ();
15579 dpyinfo = FRAME_DISPLAY_INFO (f);
15580
15581 if (time != GDK_CURRENT_TIME)
15582 x_display_set_last_user_time (dpyinfo, time, true,
15583 true);
15584
15585 switch (scroll)
15586 {
15587 case GTK_SCROLL_JUMP:
15588
15589 if (FRAME_DISPLAY_INFO (f)->grabbed != 0
15590 && FRAME_DISPLAY_INFO (f)->grabbed < (1 << 4))
15591 {
15592 if (bar->horizontal)
15593 {
15594 part = scroll_bar_horizontal_handle;
15595 whole = (int)(gtk_adjustment_get_upper (adj) -
15596 gtk_adjustment_get_page_size (adj));
15597 portion = min ((int)value, whole);
15598 bar->dragging = portion;
15599 }
15600 else
15601 {
15602 part = scroll_bar_handle;
15603 whole = gtk_adjustment_get_upper (adj) -
15604 gtk_adjustment_get_page_size (adj);
15605 portion = min ((int)value, whole);
15606 bar->dragging = portion;
15607 }
15608 }
15609 break;
15610 case GTK_SCROLL_STEP_BACKWARD:
15611 part = (bar->horizontal
15612 ? scroll_bar_left_arrow : scroll_bar_up_arrow);
15613 bar->dragging = -1;
15614 break;
15615 case GTK_SCROLL_STEP_FORWARD:
15616 part = (bar->horizontal
15617 ? scroll_bar_right_arrow : scroll_bar_down_arrow);
15618 bar->dragging = -1;
15619 break;
15620 case GTK_SCROLL_PAGE_BACKWARD:
15621 part = (bar->horizontal
15622 ? scroll_bar_before_handle : scroll_bar_above_handle);
15623 bar->dragging = -1;
15624 break;
15625 case GTK_SCROLL_PAGE_FORWARD:
15626 part = (bar->horizontal
15627 ? scroll_bar_after_handle : scroll_bar_below_handle);
15628 bar->dragging = -1;
15629 break;
15630 default:
15631 break;
15632 }
15633
15634 if (part != scroll_bar_nowhere)
15635 {
15636 window_being_scrolled = bar->window;
15637 x_send_scroll_bar_event (bar->window, part, portion, whole,
15638 bar->horizontal);
15639 }
15640
15641 return false;
15642 }
15643
15644
15645
15646 static gboolean
15647 xg_end_scroll_callback (GtkWidget *widget,
15648 GdkEventButton *event,
15649 gpointer user_data)
15650 {
15651 struct scroll_bar *bar;
15652
15653 bar = user_data;
15654 bar->dragging = -1;
15655
15656 if (WINDOWP (window_being_scrolled))
15657 {
15658 x_send_scroll_bar_event (window_being_scrolled,
15659 scroll_bar_end_scroll, 0, 0, bar->horizontal);
15660 window_being_scrolled = Qnil;
15661 }
15662
15663 return false;
15664 }
15665
15666
15667 #else
15668
15669
15670
15671
15672
15673
15674 static void
15675 xaw_jump_callback (Widget widget, XtPointer client_data, XtPointer call_data)
15676 {
15677 struct scroll_bar *bar = client_data;
15678 float *top_addr = call_data;
15679 float top = *top_addr;
15680 float shown;
15681 int whole, portion, height, width;
15682 enum scroll_bar_part part;
15683 bool horizontal = bar->horizontal;
15684
15685 if (horizontal)
15686 {
15687
15688 block_input ();
15689 XtVaGetValues (widget, XtNshown, &shown, XtNwidth, &width, NULL);
15690 unblock_input ();
15691
15692 if (shown < 1)
15693 {
15694 whole = bar->whole - (shown * bar->whole);
15695 portion = min (top * bar->whole, whole);
15696 }
15697 else
15698 {
15699 whole = bar->whole;
15700 portion = 0;
15701 }
15702
15703 part = scroll_bar_horizontal_handle;
15704 }
15705 else
15706 {
15707
15708 block_input ();
15709 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
15710 unblock_input ();
15711
15712 whole = 10000000;
15713 portion = shown < 1 ? top * whole : 0;
15714
15715 if (shown < 1 && (eabs (top + shown - 1) < 1.0f / height))
15716
15717
15718
15719
15720
15721 part = scroll_bar_down_arrow;
15722 else
15723 part = scroll_bar_handle;
15724 }
15725
15726 window_being_scrolled = bar->window;
15727 bar->dragging = portion;
15728 bar->last_seen_part = part;
15729 x_send_scroll_bar_event (bar->window, part, portion, whole, bar->horizontal);
15730 }
15731
15732
15733
15734
15735
15736
15737
15738
15739
15740
15741 static void
15742 xaw_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data)
15743 {
15744 struct scroll_bar *bar = client_data;
15745
15746 int position = (intptr_t) call_data;
15747 Dimension height, width;
15748 enum scroll_bar_part part;
15749
15750 if (bar->horizontal)
15751 {
15752
15753 block_input ();
15754 XtVaGetValues (widget, XtNwidth, &width, NULL);
15755 unblock_input ();
15756
15757 if (eabs (position) >= width)
15758 part = (position < 0) ? scroll_bar_before_handle : scroll_bar_after_handle;
15759
15760
15761
15762 else if (xaw3d_arrow_scroll && eabs (position) <= max (5, width / 20))
15763 part = (position < 0) ? scroll_bar_left_arrow : scroll_bar_right_arrow;
15764 else
15765 part = scroll_bar_move_ratio;
15766
15767 window_being_scrolled = bar->window;
15768 bar->dragging = -1;
15769 bar->last_seen_part = part;
15770 x_send_scroll_bar_event (bar->window, part, position, width,
15771 bar->horizontal);
15772 }
15773 else
15774 {
15775
15776
15777 block_input ();
15778 XtVaGetValues (widget, XtNheight, &height, NULL);
15779 unblock_input ();
15780
15781 if (eabs (position) >= height)
15782 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
15783
15784
15785
15786 else if (xaw3d_arrow_scroll && eabs (position) <= max (5, height / 20))
15787 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
15788 else
15789 part = scroll_bar_move_ratio;
15790
15791 window_being_scrolled = bar->window;
15792 bar->dragging = -1;
15793 bar->last_seen_part = part;
15794 x_send_scroll_bar_event (bar->window, part, position, height,
15795 bar->horizontal);
15796 }
15797 }
15798
15799 #endif
15800
15801 #define SCROLL_BAR_NAME "verticalScrollBar"
15802 #define SCROLL_BAR_HORIZONTAL_NAME "horizontalScrollBar"
15803
15804
15805
15806
15807 #ifdef USE_GTK
15808 static void
15809 x_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
15810 {
15811 const char *scroll_bar_name = SCROLL_BAR_NAME;
15812
15813 block_input ();
15814 xg_create_scroll_bar (f, bar, G_CALLBACK (xg_scroll_callback),
15815 G_CALLBACK (xg_end_scroll_callback),
15816 scroll_bar_name);
15817 unblock_input ();
15818 }
15819
15820 static void
15821 x_create_horizontal_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
15822 {
15823 const char *scroll_bar_name = SCROLL_BAR_HORIZONTAL_NAME;
15824
15825 block_input ();
15826 xg_create_horizontal_scroll_bar (f, bar, G_CALLBACK (xg_scroll_callback),
15827 G_CALLBACK (xg_end_scroll_callback),
15828 scroll_bar_name);
15829 unblock_input ();
15830 }
15831
15832 #else
15833
15834 static void
15835 x_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
15836 {
15837 Window xwindow;
15838 Widget widget;
15839 Arg av[20];
15840 int ac = 0;
15841 const char *scroll_bar_name = SCROLL_BAR_NAME;
15842 unsigned long pixel;
15843
15844 block_input ();
15845
15846 #ifdef USE_MOTIF
15847
15848 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
15849 XtSetArg (av[ac], XmNminimum, 0); ++ac;
15850 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
15851 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
15852 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
15853 XtSetArg (av[ac], XmNincrement, 1); ++ac;
15854 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
15855
15856
15857
15858 pixel = f->output_data.x->scroll_bar_foreground_pixel;
15859 if (pixel != -1)
15860 {
15861 XtSetArg (av[ac], XmNbackground, pixel);
15862 ++ac;
15863 }
15864
15865 pixel = f->output_data.x->scroll_bar_background_pixel;
15866 if (pixel != -1)
15867 {
15868 XtSetArg (av[ac], XmNtroughColor, pixel);
15869 ++ac;
15870 }
15871
15872 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
15873 (char *) scroll_bar_name, av, ac);
15874
15875
15876 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
15877 (XtPointer) bar);
15878 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
15879 (XtPointer) bar);
15880 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
15881 (XtPointer) bar);
15882 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
15883 (XtPointer) bar);
15884 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
15885 (XtPointer) bar);
15886 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
15887 (XtPointer) bar);
15888 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
15889 (XtPointer) bar);
15890
15891
15892 XtRealizeWidget (widget);
15893
15894
15895
15896 XDefineCursor (XtDisplay (widget), XtWindow (widget),
15897 f->output_data.x->nontext_cursor);
15898
15899 #ifdef HAVE_XINPUT2
15900
15901
15902 if (FRAME_DISPLAY_INFO (f)->supports_xi2)
15903 xi_select_scroll_bar_events (FRAME_DISPLAY_INFO (f),
15904 XtWindow (widget));
15905 #endif
15906 #else
15907
15908
15909
15910
15911
15912 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
15913 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
15914
15915
15916
15917 pixel = f->output_data.x->scroll_bar_foreground_pixel;
15918 if (pixel != -1)
15919 {
15920 XtSetArg (av[ac], XtNforeground, pixel);
15921 ++ac;
15922 }
15923
15924 pixel = f->output_data.x->scroll_bar_background_pixel;
15925 if (pixel != -1)
15926 {
15927 XtSetArg (av[ac], XtNbackground, pixel);
15928 ++ac;
15929 }
15930
15931
15932
15933
15934 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1)
15935 {
15936 pixel = f->output_data.x->scroll_bar_background_pixel;
15937 if (pixel != -1)
15938 {
15939 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
15940 FRAME_X_COLORMAP (f),
15941 &pixel, 1.2, 0x8000))
15942 pixel = -1;
15943 f->output_data.x->scroll_bar_top_shadow_pixel = pixel;
15944 }
15945 }
15946 if (f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
15947 {
15948 pixel = f->output_data.x->scroll_bar_background_pixel;
15949 if (pixel != -1)
15950 {
15951 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
15952 FRAME_X_COLORMAP (f),
15953 &pixel, 0.6, 0x4000))
15954 pixel = -1;
15955 f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
15956 }
15957 }
15958
15959 #ifdef XtNbeNiceToColormap
15960
15961 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1
15962 || f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
15963
15964
15965
15966
15967 {
15968 XtSetArg (av[ac], (String) XtNbeNiceToColormap,
15969 DefaultDepthOfScreen (FRAME_X_SCREEN (f)) < 16);
15970 ++ac;
15971 }
15972 else
15973
15974
15975
15976 {
15977
15978
15979 XtSetArg (av[ac], (String) XtNbeNiceToColormap, False);
15980 ++ac;
15981
15982
15983 pixel = f->output_data.x->scroll_bar_top_shadow_pixel;
15984 if (pixel != -1)
15985 {
15986 XtSetArg (av[ac], (String) XtNtopShadowPixel, pixel);
15987 ++ac;
15988 }
15989 pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel;
15990 if (pixel != -1)
15991 {
15992 XtSetArg (av[ac], (String) XtNbottomShadowPixel, pixel);
15993 ++ac;
15994 }
15995 }
15996 #endif
15997
15998 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
15999 f->output_data.x->edit_widget, av, ac);
16000
16001 {
16002 char const *initial = "";
16003 char const *val = initial;
16004 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
16005 #ifdef XtNarrowScrollbars
16006 XtNarrowScrollbars, (XtPointer) &xaw3d_arrow_scroll,
16007 #endif
16008 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
16009 if (xaw3d_arrow_scroll || val == initial)
16010 {
16011 xaw3d_arrow_scroll = True;
16012
16013 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
16014 }
16015 }
16016
16017
16018 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
16019 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
16020 (XtPointer) bar);
16021
16022
16023 XtRealizeWidget (widget);
16024
16025 #endif
16026
16027
16028
16029 if (action_hook_id == 0)
16030 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
16031
16032
16033 SET_SCROLL_BAR_X_WIDGET (bar, widget);
16034 xwindow = XtWindow (widget);
16035 bar->x_window = xwindow;
16036 bar->whole = 1;
16037 bar->horizontal = false;
16038
16039 unblock_input ();
16040 }
16041
16042 static void
16043 x_create_horizontal_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
16044 {
16045 Window xwindow;
16046 Widget widget;
16047 Arg av[20];
16048 int ac = 0;
16049 const char *scroll_bar_name = SCROLL_BAR_HORIZONTAL_NAME;
16050 unsigned long pixel;
16051
16052 block_input ();
16053
16054 #ifdef USE_MOTIF
16055
16056 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
16057 XtSetArg (av[ac], XmNminimum, 0); ++ac;
16058 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
16059 XtSetArg (av[ac], XmNorientation, XmHORIZONTAL); ++ac;
16060 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_RIGHT), ++ac;
16061 XtSetArg (av[ac], XmNincrement, 1); ++ac;
16062 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
16063
16064
16065
16066 pixel = f->output_data.x->scroll_bar_foreground_pixel;
16067 if (pixel != -1)
16068 {
16069 XtSetArg (av[ac], XmNbackground, pixel);
16070 ++ac;
16071 }
16072
16073 pixel = f->output_data.x->scroll_bar_background_pixel;
16074 if (pixel != -1)
16075 {
16076 XtSetArg (av[ac], XmNtroughColor, pixel);
16077 ++ac;
16078 }
16079
16080 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
16081 (char *) scroll_bar_name, av, ac);
16082
16083
16084 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
16085 (XtPointer) bar);
16086 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
16087 (XtPointer) bar);
16088 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
16089 (XtPointer) bar);
16090 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
16091 (XtPointer) bar);
16092 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
16093 (XtPointer) bar);
16094 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
16095 (XtPointer) bar);
16096 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
16097 (XtPointer) bar);
16098
16099
16100 XtRealizeWidget (widget);
16101
16102
16103
16104 XDefineCursor (XtDisplay (widget), XtWindow (widget),
16105 f->output_data.x->nontext_cursor);
16106
16107 #ifdef HAVE_XINPUT2
16108
16109
16110 if (FRAME_DISPLAY_INFO (f)->supports_xi2)
16111 xi_select_scroll_bar_events (FRAME_DISPLAY_INFO (f),
16112 XtWindow (widget));
16113 #endif
16114 #else
16115
16116
16117
16118
16119
16120 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
16121 XtSetArg (av[ac], XtNorientation, XtorientHorizontal); ++ac;
16122
16123
16124
16125 pixel = f->output_data.x->scroll_bar_foreground_pixel;
16126 if (pixel != -1)
16127 {
16128 XtSetArg (av[ac], XtNforeground, pixel);
16129 ++ac;
16130 }
16131
16132 pixel = f->output_data.x->scroll_bar_background_pixel;
16133 if (pixel != -1)
16134 {
16135 XtSetArg (av[ac], XtNbackground, pixel);
16136 ++ac;
16137 }
16138
16139
16140
16141
16142 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1)
16143 {
16144 pixel = f->output_data.x->scroll_bar_background_pixel;
16145 if (pixel != -1)
16146 {
16147 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
16148 FRAME_X_COLORMAP (f),
16149 &pixel, 1.2, 0x8000))
16150 pixel = -1;
16151 f->output_data.x->scroll_bar_top_shadow_pixel = pixel;
16152 }
16153 }
16154 if (f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
16155 {
16156 pixel = f->output_data.x->scroll_bar_background_pixel;
16157 if (pixel != -1)
16158 {
16159 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
16160 FRAME_X_COLORMAP (f),
16161 &pixel, 0.6, 0x4000))
16162 pixel = -1;
16163 f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
16164 }
16165 }
16166
16167 #ifdef XtNbeNiceToColormap
16168
16169 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1
16170 || f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
16171
16172
16173
16174
16175 {
16176 XtSetArg (av[ac], (String) XtNbeNiceToColormap,
16177 DefaultDepthOfScreen (FRAME_X_SCREEN (f)) < 16);
16178 ++ac;
16179 }
16180 else
16181
16182
16183
16184 {
16185
16186
16187 XtSetArg (av[ac], (String) XtNbeNiceToColormap, False);
16188 ++ac;
16189
16190
16191 pixel = f->output_data.x->scroll_bar_top_shadow_pixel;
16192 if (pixel != -1)
16193 {
16194 XtSetArg (av[ac], (String) XtNtopShadowPixel, pixel);
16195 ++ac;
16196 }
16197 pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel;
16198 if (pixel != -1)
16199 {
16200 XtSetArg (av[ac], (String) XtNbottomShadowPixel, pixel);
16201 ++ac;
16202 }
16203 }
16204 #endif
16205
16206 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
16207 f->output_data.x->edit_widget, av, ac);
16208
16209 {
16210 char const *initial = "";
16211 char const *val = initial;
16212 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
16213 #ifdef XtNarrowScrollbars
16214 XtNarrowScrollbars, (XtPointer) &xaw3d_arrow_scroll,
16215 #endif
16216 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
16217 if (xaw3d_arrow_scroll || val == initial)
16218 {
16219 xaw3d_arrow_scroll = True;
16220
16221 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
16222 }
16223 }
16224
16225
16226 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
16227 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
16228 (XtPointer) bar);
16229
16230
16231 XtRealizeWidget (widget);
16232
16233 #endif
16234
16235
16236
16237 if (horizontal_action_hook_id == 0)
16238 horizontal_action_hook_id
16239 = XtAppAddActionHook (Xt_app_con, xt_horizontal_action_hook, 0);
16240
16241
16242 SET_SCROLL_BAR_X_WIDGET (bar, widget);
16243 xwindow = XtWindow (widget);
16244 bar->x_window = xwindow;
16245 bar->whole = 1;
16246 bar->horizontal = true;
16247
16248 unblock_input ();
16249 }
16250 #endif
16251
16252
16253
16254
16255
16256 #ifdef USE_GTK
16257 static void
16258 x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position, int whole)
16259 {
16260 xg_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
16261 }
16262
16263 static void
16264 x_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position, int whole)
16265 {
16266 xg_set_toolkit_horizontal_scroll_bar_thumb (bar, portion, position, whole);
16267 }
16268
16269 #else
16270 static void
16271 x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position,
16272 int whole)
16273 {
16274 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
16275 Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
16276 float top, shown;
16277
16278 block_input ();
16279
16280 #ifdef USE_MOTIF
16281
16282 if (scroll_bar_adjust_thumb_portion_p)
16283 {
16284
16285
16286
16287
16288
16289
16290
16291
16292
16293
16294
16295 portion = WINDOW_TOTAL_LINES (XWINDOW (bar->window)) * 30;
16296
16297
16298 whole += portion;
16299 }
16300
16301 if (whole <= 0)
16302 top = 0, shown = 1;
16303 else
16304 {
16305 top = (float) position / whole;
16306 shown = (float) portion / whole;
16307 }
16308
16309 if (bar->dragging == -1)
16310 {
16311 int size, value;
16312
16313
16314
16315
16316 size = clip_to_bounds (1, shown * XM_SB_MAX, XM_SB_MAX);
16317
16318
16319 value = top * XM_SB_MAX;
16320 value = min (value, XM_SB_MAX - size);
16321
16322 XmScrollBarSetValues (widget, value, size, 0, 0, False);
16323 }
16324 #else
16325
16326 if (whole == 0)
16327 top = 0, shown = 1;
16328 else
16329 {
16330 top = (float) position / whole;
16331 shown = (float) portion / whole;
16332 }
16333
16334 {
16335 float old_top, old_shown;
16336 Dimension height;
16337 XtVaGetValues (widget,
16338 XtNtopOfThumb, &old_top,
16339 XtNshown, &old_shown,
16340 XtNheight, &height,
16341 NULL);
16342
16343
16344 if (bar->dragging == -1 || bar->last_seen_part == scroll_bar_down_arrow)
16345 top = max (0, min (1, top));
16346 else
16347 top = old_top;
16348 #if ! defined (HAVE_XAW3D)
16349
16350
16351 top = min (top, 0.99f);
16352 #endif
16353
16354 shown = max (0, min (1 - top - (2.0f / height), shown));
16355 #if ! defined (HAVE_XAW3D)
16356
16357 shown = max (shown, 0.01f);
16358 #endif
16359
16360
16361
16362
16363 if (top != old_top || shown != old_shown)
16364 {
16365 if (bar->dragging == -1)
16366 XawScrollbarSetThumb (widget, top, shown);
16367 else
16368 {
16369
16370 if (!xaw3d_pick_top)
16371 shown = min (shown, old_shown);
16372
16373 XawScrollbarSetThumb (widget, top, shown);
16374 }
16375 }
16376 }
16377 #endif
16378
16379 unblock_input ();
16380 }
16381
16382 static void
16383 x_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position,
16384 int whole)
16385 {
16386 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
16387 Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
16388 float top, shown;
16389
16390 block_input ();
16391
16392 #ifdef USE_MOTIF
16393 bar->whole = whole;
16394 shown = (float) portion / whole;
16395 top = (float) position / (whole - portion);
16396 {
16397 int size = clip_to_bounds (1, shown * XM_SB_MAX, XM_SB_MAX);
16398 int value = clip_to_bounds (0, top * (XM_SB_MAX - size), XM_SB_MAX - size);
16399
16400 XmScrollBarSetValues (widget, value, size, 0, 0, False);
16401 }
16402 #else
16403 bar->whole = whole;
16404 if (whole == 0)
16405 top = 0, shown = 1;
16406 else
16407 {
16408 top = (float) position / whole;
16409 shown = (float) portion / whole;
16410 }
16411
16412 {
16413 float old_top, old_shown;
16414 Dimension height;
16415 XtVaGetValues (widget,
16416 XtNtopOfThumb, &old_top,
16417 XtNshown, &old_shown,
16418 XtNheight, &height,
16419 NULL);
16420
16421 #if false
16422
16423 if (bar->dragging == -1 || bar->last_seen_part == scroll_bar_down_arrow)
16424 top = max (0, min (1, top));
16425 else
16426 top = old_top;
16427 #if ! defined (HAVE_XAW3D)
16428
16429
16430 top = min (top, 0.99f);
16431 #endif
16432
16433 shown = max (0, min (1 - top - (2.0f / height), shown));
16434 #if ! defined (HAVE_XAW3D)
16435
16436 shown = max (shown, 0.01f);
16437 #endif
16438 #endif
16439
16440
16441
16442
16443 XawScrollbarSetThumb (widget, top, shown);
16444 #if false
16445 if (top != old_top || shown != old_shown)
16446 {
16447 if (bar->dragging == -1)
16448 XawScrollbarSetThumb (widget, top, shown);
16449 else
16450 {
16451
16452 if (!xaw3d_pick_top)
16453 shown = min (shown, old_shown);
16454
16455 XawScrollbarSetThumb (widget, top, shown);
16456 }
16457 }
16458 #endif
16459 }
16460 #endif
16461
16462 unblock_input ();
16463 }
16464 #endif
16465
16466 #endif
16467
16468
16469
16470
16471
16472
16473
16474
16475
16476
16477
16478
16479 static struct scroll_bar *
16480 x_scroll_bar_create (struct window *w, int top, int left,
16481 int width, int height, bool horizontal)
16482 {
16483 struct frame *f = XFRAME (w->frame);
16484 struct scroll_bar *bar = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, prev,
16485 PVEC_OTHER);
16486 Lisp_Object barobj;
16487
16488 block_input ();
16489
16490 #ifdef USE_TOOLKIT_SCROLL_BARS
16491 if (horizontal)
16492 x_create_horizontal_toolkit_scroll_bar (f, bar);
16493 else
16494 x_create_toolkit_scroll_bar (f, bar);
16495 #else
16496 {
16497 XSetWindowAttributes a;
16498 unsigned long mask;
16499 Window window;
16500
16501 a.event_mask = (ButtonPressMask | ButtonReleaseMask
16502 | ButtonMotionMask | PointerMotionHintMask);
16503 a.cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
16504
16505 mask = (CWEventMask | CWCursor);
16506
16507
16508
16509
16510 if (width > 0 && window_box_height (w) > 0)
16511 x_clear_area (f, left, top, width, window_box_height (w));
16512
16513
16514
16515
16516 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
16517
16518 left, top, width, height,
16519
16520 0,
16521
16522 CopyFromParent,
16523
16524 InputOnly,
16525
16526 CopyFromParent,
16527
16528 mask, &a);
16529
16530 #ifdef HAVE_XINPUT2
16531
16532
16533 if (FRAME_DISPLAY_INFO (f)->supports_xi2)
16534 xi_select_scroll_bar_events (FRAME_DISPLAY_INFO (f),
16535 window);
16536 #endif
16537
16538 bar->x_window = window;
16539 }
16540 #endif
16541
16542 XSETWINDOW (bar->window, w);
16543 bar->top = top;
16544 bar->left = left;
16545 bar->width = width;
16546 bar->height = height;
16547 bar->start = 0;
16548 bar->end = 0;
16549 bar->dragging = -1;
16550 bar->horizontal = horizontal;
16551 #if defined (USE_TOOLKIT_SCROLL_BARS) && defined (USE_LUCID)
16552 bar->last_seen_part = scroll_bar_nowhere;
16553 #endif
16554
16555
16556 bar->next = FRAME_SCROLL_BARS (f);
16557 bar->prev = Qnil;
16558 XSETVECTOR (barobj, bar);
16559 fset_scroll_bars (f, barobj);
16560 if (!NILP (bar->next))
16561 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
16562
16563
16564 #ifdef USE_TOOLKIT_SCROLL_BARS
16565 {
16566 #ifdef USE_GTK
16567 if (horizontal)
16568 xg_update_horizontal_scrollbar_pos (f, bar->x_window, top,
16569 left, width, max (height, 1));
16570 else
16571 xg_update_scrollbar_pos (f, bar->x_window, top,
16572 left, width, max (height, 1));
16573 #else
16574 Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
16575 XtConfigureWidget (scroll_bar, left, top, width, max (height, 1), 0);
16576 XtMapWidget (scroll_bar);
16577
16578 XLowerWindow (FRAME_X_DISPLAY (f), bar->x_window);
16579 #endif
16580 }
16581 #else
16582 XMapWindow (FRAME_X_DISPLAY (f), bar->x_window);
16583
16584 XLowerWindow (FRAME_X_DISPLAY (f), bar->x_window);
16585 #endif
16586
16587 unblock_input ();
16588 return bar;
16589 }
16590
16591
16592 #ifndef USE_TOOLKIT_SCROLL_BARS
16593
16594
16595
16596
16597
16598
16599
16600
16601
16602
16603
16604
16605
16606
16607 static void
16608 x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end,
16609 bool rebuild)
16610 {
16611 bool dragging;
16612 struct frame *f;
16613 Drawable w;
16614 GC gc;
16615 int inside_width, inside_height, top_range, length;
16616
16617
16618 if (! rebuild
16619 && start == bar->start
16620 && end == bar->end)
16621 return;
16622
16623 f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
16624 dragging = bar->dragging != -1;
16625 gc = f->output_data.x->normal_gc;
16626 w = FRAME_X_DRAWABLE (f);
16627
16628 block_input ();
16629
16630 inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, bar->width);
16631 inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, bar->height);
16632 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
16633
16634
16635
16636 length = end - start;
16637
16638 if (start < 0)
16639 start = 0;
16640 else if (start > top_range)
16641 start = top_range;
16642 end = start + length;
16643
16644 if (end < start)
16645 end = start;
16646 else if (end > top_range && ! dragging)
16647 end = top_range;
16648
16649
16650 bar->start = start;
16651 bar->end = end;
16652
16653
16654 if (end > top_range)
16655 end = top_range;
16656
16657
16658
16659
16660 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
16661
16662
16663
16664 if ((inside_width > 0) && (start > 0))
16665 {
16666 if (f->output_data.x->scroll_bar_background_pixel != -1)
16667 XSetForeground (FRAME_X_DISPLAY (f), gc,
16668 f->output_data.x->scroll_bar_background_pixel);
16669 else
16670 XSetForeground (FRAME_X_DISPLAY (f), gc,
16671 FRAME_BACKGROUND_PIXEL (f));
16672
16673 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
16674 bar->left + VERTICAL_SCROLL_BAR_LEFT_BORDER,
16675 bar->top + VERTICAL_SCROLL_BAR_TOP_BORDER,
16676 inside_width, start);
16677
16678 XSetForeground (FRAME_X_DISPLAY (f), gc,
16679 FRAME_FOREGROUND_PIXEL (f));
16680 }
16681
16682
16683 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
16684 XSetForeground (FRAME_X_DISPLAY (f), gc,
16685 f->output_data.x->scroll_bar_foreground_pixel);
16686
16687
16688 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
16689
16690 bar->left + VERTICAL_SCROLL_BAR_LEFT_BORDER,
16691 bar->top + VERTICAL_SCROLL_BAR_TOP_BORDER + start,
16692 inside_width, end - start);
16693
16694
16695
16696
16697 if ((inside_width > 0) && (end < inside_height))
16698 {
16699 if (f->output_data.x->scroll_bar_background_pixel != -1)
16700 XSetForeground (FRAME_X_DISPLAY (f), gc,
16701 f->output_data.x->scroll_bar_background_pixel);
16702 else
16703 XSetForeground (FRAME_X_DISPLAY (f), gc,
16704 FRAME_BACKGROUND_PIXEL (f));
16705
16706 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
16707 bar->left + VERTICAL_SCROLL_BAR_LEFT_BORDER,
16708 bar->top + VERTICAL_SCROLL_BAR_TOP_BORDER + end,
16709 inside_width, inside_height - end);
16710
16711 XSetForeground (FRAME_X_DISPLAY (f), gc,
16712 FRAME_FOREGROUND_PIXEL (f));
16713 }
16714
16715
16716 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
16717 XSetForeground (FRAME_X_DISPLAY (f), gc,
16718 FRAME_FOREGROUND_PIXEL (f));
16719
16720 unblock_input ();
16721 }
16722
16723 #endif
16724
16725
16726
16727
16728 static void
16729 x_scroll_bar_remove (struct scroll_bar *bar)
16730 {
16731 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
16732 block_input ();
16733
16734 #ifdef USE_TOOLKIT_SCROLL_BARS
16735 #ifdef USE_GTK
16736 xg_remove_scroll_bar (f, bar->x_window);
16737 #else
16738 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));
16739 #endif
16740 #else
16741 XDestroyWindow (FRAME_X_DISPLAY (f), bar->x_window);
16742 #endif
16743
16744
16745 if (bar->horizontal)
16746 wset_horizontal_scroll_bar (XWINDOW (bar->window), Qnil);
16747 else
16748 wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil);
16749
16750 unblock_input ();
16751 }
16752
16753
16754
16755
16756
16757
16758
16759 static void
16760 XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int position)
16761 {
16762 struct frame *f = XFRAME (w->frame);
16763 Lisp_Object barobj;
16764 struct scroll_bar *bar;
16765 int top, height, left, width;
16766 int window_y, window_height;
16767
16768
16769 window_box (w, ANY_AREA, 0, &window_y, 0, &window_height);
16770 top = window_y;
16771 height = window_height;
16772 left = WINDOW_SCROLL_BAR_AREA_X (w);
16773 width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
16774
16775
16776 if (NILP (w->vertical_scroll_bar))
16777 {
16778 if (width > 0 && height > 0)
16779 {
16780 block_input ();
16781 x_clear_area (f, left, top, width, height);
16782 unblock_input ();
16783 }
16784
16785 bar = x_scroll_bar_create (w, top, left, width, max (height, 1), false);
16786 #ifndef USE_TOOLKIT_SCROLL_BARS
16787
16788
16789
16790 x_scroll_bar_redraw (bar);
16791 #endif
16792 }
16793 else
16794 {
16795
16796 unsigned int mask = 0;
16797
16798 bar = XSCROLL_BAR (w->vertical_scroll_bar);
16799
16800 block_input ();
16801
16802 if (left != bar->left)
16803 mask |= CWX;
16804 if (top != bar->top)
16805 mask |= CWY;
16806 if (width != bar->width)
16807 mask |= CWWidth;
16808 if (height != bar->height)
16809 mask |= CWHeight;
16810
16811 #ifdef USE_TOOLKIT_SCROLL_BARS
16812
16813
16814 if (mask)
16815 {
16816
16817
16818 if (width > 0 && height > 0)
16819 x_clear_area (f, left, top, width, height);
16820 #ifdef USE_GTK
16821 xg_update_scrollbar_pos (f, bar->x_window, top,
16822 left, width, max (height, 1));
16823 #else
16824 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
16825 left, top, width, max (height, 1), 0);
16826 #endif
16827 }
16828 #else
16829
16830
16831 if (mask)
16832 {
16833 XWindowChanges wc;
16834
16835 wc.x = left;
16836 wc.y = top;
16837 wc.width = width;
16838 wc.height = height;
16839 XConfigureWindow (FRAME_X_DISPLAY (f), bar->x_window,
16840 mask, &wc);
16841 }
16842
16843 #endif
16844
16845
16846 bar->left = left;
16847 bar->top = top;
16848 bar->width = width;
16849 bar->height = height;
16850
16851 #ifndef USE_TOOLKIT_SCROLL_BARS
16852
16853 x_scroll_bar_redraw (bar);
16854 #endif
16855
16856 unblock_input ();
16857 }
16858
16859 #ifdef USE_TOOLKIT_SCROLL_BARS
16860 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
16861 #else
16862
16863
16864 if (bar->dragging == -1)
16865 {
16866 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
16867
16868 if (whole == 0)
16869 x_scroll_bar_set_handle (bar, 0, top_range, false);
16870 else
16871 {
16872 int start = ((double) position * top_range) / whole;
16873 int end = ((double) (position + portion) * top_range) / whole;
16874 x_scroll_bar_set_handle (bar, start, end, false);
16875 }
16876 }
16877 #endif
16878
16879 XSETVECTOR (barobj, bar);
16880 wset_vertical_scroll_bar (w, barobj);
16881 }
16882
16883
16884 static void
16885 XTset_horizontal_scroll_bar (struct window *w, int portion, int whole, int position)
16886 {
16887 struct frame *f = XFRAME (w->frame);
16888 Lisp_Object barobj;
16889 struct scroll_bar *bar;
16890 int top, height, left, width;
16891 int window_x, window_width;
16892 int pixel_width = WINDOW_PIXEL_WIDTH (w);
16893
16894
16895 window_box (w, ANY_AREA, &window_x, 0, &window_width, 0);
16896 left = window_x;
16897 width = window_width;
16898 top = WINDOW_SCROLL_BAR_AREA_Y (w);
16899 height = WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
16900
16901
16902 if (NILP (w->horizontal_scroll_bar))
16903 {
16904 if (width > 0 && height > 0)
16905 {
16906 block_input ();
16907
16908
16909
16910 x_clear_area (f, left, top, pixel_width, height);
16911 unblock_input ();
16912 }
16913
16914 bar = x_scroll_bar_create (w, top, left, width, height, true);
16915 }
16916 else
16917 {
16918
16919 unsigned int mask = 0;
16920
16921 bar = XSCROLL_BAR (w->horizontal_scroll_bar);
16922
16923 block_input ();
16924
16925 if (left != bar->left)
16926 mask |= CWX;
16927 if (top != bar->top)
16928 mask |= CWY;
16929 if (width != bar->width)
16930 mask |= CWWidth;
16931 if (height != bar->height)
16932 mask |= CWHeight;
16933
16934 #ifdef USE_TOOLKIT_SCROLL_BARS
16935
16936 if (mask)
16937 {
16938
16939
16940 if (width > 0 && height > 0)
16941 x_clear_area (f,
16942 WINDOW_LEFT_EDGE_X (w), top,
16943 pixel_width - WINDOW_RIGHT_DIVIDER_WIDTH (w), height);
16944 #ifdef USE_GTK
16945 xg_update_horizontal_scrollbar_pos (f, bar->x_window, top, left,
16946 width, height);
16947 #else
16948 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
16949 left, top, width, height, 0);
16950 #endif
16951 }
16952 #else
16953
16954
16955
16956
16957
16958 {
16959 int area_height = WINDOW_CONFIG_SCROLL_BAR_HEIGHT (w);
16960 int rest = area_height - height;
16961 if (rest > 0 && width > 0)
16962 x_clear_area (f, left, top, width, rest);
16963 }
16964
16965
16966 if (mask)
16967 {
16968 XWindowChanges wc;
16969
16970 wc.x = left;
16971 wc.y = top;
16972 wc.width = width;
16973 wc.height = height;
16974 XConfigureWindow (FRAME_X_DISPLAY (f), bar->x_window,
16975 mask, &wc);
16976 }
16977
16978 #endif
16979
16980
16981 bar->left = left;
16982 bar->top = top;
16983 bar->width = width;
16984 bar->height = height;
16985
16986 unblock_input ();
16987 }
16988
16989 #ifdef USE_TOOLKIT_SCROLL_BARS
16990 x_set_toolkit_horizontal_scroll_bar_thumb (bar, portion, position, whole);
16991 #else
16992
16993
16994 if (bar->dragging == -1)
16995 {
16996 int left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, width);
16997
16998 if (whole == 0)
16999 x_scroll_bar_set_handle (bar, 0, left_range, false);
17000 else
17001 {
17002 int start = ((double) position * left_range) / whole;
17003 int end = ((double) (position + portion) * left_range) / whole;
17004 x_scroll_bar_set_handle (bar, start, end, false);
17005 }
17006 }
17007 #endif
17008
17009 XSETVECTOR (barobj, bar);
17010 wset_horizontal_scroll_bar (w, barobj);
17011 }
17012
17013
17014
17015
17016
17017
17018
17019
17020
17021
17022
17023
17024
17025
17026 static void
17027 XTcondemn_scroll_bars (struct frame *frame)
17028 {
17029 if (!NILP (FRAME_SCROLL_BARS (frame)))
17030 {
17031 if (!NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
17032 {
17033
17034 Lisp_Object last = FRAME_SCROLL_BARS (frame);
17035
17036 while (!NILP (XSCROLL_BAR (last)->next))
17037 last = XSCROLL_BAR (last)->next;
17038
17039 XSCROLL_BAR (last)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
17040 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = last;
17041 }
17042
17043 fset_condemned_scroll_bars (frame, FRAME_SCROLL_BARS (frame));
17044 fset_scroll_bars (frame, Qnil);
17045 }
17046 }
17047
17048
17049
17050
17051
17052 static void
17053 XTredeem_scroll_bar (struct window *w)
17054 {
17055 struct scroll_bar *bar;
17056 Lisp_Object barobj;
17057 struct frame *f;
17058
17059
17060 if (NILP (w->vertical_scroll_bar) && NILP (w->horizontal_scroll_bar))
17061 emacs_abort ();
17062
17063 if (!NILP (w->vertical_scroll_bar) && WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
17064 {
17065 bar = XSCROLL_BAR (w->vertical_scroll_bar);
17066
17067 f = XFRAME (WINDOW_FRAME (w));
17068 if (NILP (bar->prev))
17069 {
17070
17071
17072 if (EQ (FRAME_SCROLL_BARS (f), w->vertical_scroll_bar))
17073
17074 goto horizontal;
17075 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
17076 w->vertical_scroll_bar))
17077 fset_condemned_scroll_bars (f, bar->next);
17078 else
17079
17080
17081 emacs_abort ();
17082 }
17083 else
17084 XSCROLL_BAR (bar->prev)->next = bar->next;
17085
17086 if (! NILP (bar->next))
17087 XSCROLL_BAR (bar->next)->prev = bar->prev;
17088
17089 bar->next = FRAME_SCROLL_BARS (f);
17090 bar->prev = Qnil;
17091 XSETVECTOR (barobj, bar);
17092 fset_scroll_bars (f, barobj);
17093 if (! NILP (bar->next))
17094 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
17095 }
17096
17097 horizontal:
17098 if (!NILP (w->horizontal_scroll_bar) && WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
17099 {
17100 bar = XSCROLL_BAR (w->horizontal_scroll_bar);
17101
17102 f = XFRAME (WINDOW_FRAME (w));
17103 if (NILP (bar->prev))
17104 {
17105
17106
17107 if (EQ (FRAME_SCROLL_BARS (f), w->horizontal_scroll_bar))
17108
17109 return;
17110 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
17111 w->horizontal_scroll_bar))
17112 fset_condemned_scroll_bars (f, bar->next);
17113 else
17114
17115
17116 emacs_abort ();
17117 }
17118 else
17119 XSCROLL_BAR (bar->prev)->next = bar->next;
17120
17121 if (! NILP (bar->next))
17122 XSCROLL_BAR (bar->next)->prev = bar->prev;
17123
17124 bar->next = FRAME_SCROLL_BARS (f);
17125 bar->prev = Qnil;
17126 XSETVECTOR (barobj, bar);
17127 fset_scroll_bars (f, barobj);
17128 if (! NILP (bar->next))
17129 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
17130 }
17131 }
17132
17133
17134
17135
17136 static void
17137 XTjudge_scroll_bars (struct frame *f)
17138 {
17139 Lisp_Object bar, next;
17140
17141 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
17142
17143
17144
17145 fset_condemned_scroll_bars (f, Qnil);
17146
17147 for (; ! NILP (bar); bar = next)
17148 {
17149 struct scroll_bar *b = XSCROLL_BAR (bar);
17150
17151 x_scroll_bar_remove (b);
17152
17153 next = b->next;
17154 b->next = b->prev = Qnil;
17155 }
17156
17157
17158
17159 }
17160
17161
17162 #ifndef USE_TOOLKIT_SCROLL_BARS
17163
17164
17165
17166 static void
17167 x_scroll_bar_handle_exposure (struct frame *f, XEvent *event)
17168 {
17169 int x, y, width, height;
17170 XRectangle rect, scroll_bar_rect, intersection;
17171 Lisp_Object bar, condemned;
17172 struct scroll_bar *b;
17173
17174 if (event->type == GraphicsExpose)
17175 {
17176 x = event->xgraphicsexpose.x;
17177 y = event->xgraphicsexpose.y;
17178 width = event->xgraphicsexpose.width;
17179 height = event->xgraphicsexpose.height;
17180 }
17181 else
17182 {
17183 x = event->xexpose.x;
17184 y = event->xexpose.y;
17185 width = event->xexpose.width;
17186 height = event->xexpose.height;
17187 }
17188
17189 rect.x = x;
17190 rect.y = y;
17191 rect.width = width;
17192 rect.height = height;
17193
17194
17195
17196 condemned = FRAME_CONDEMNED_SCROLL_BARS (f);
17197 for (bar = FRAME_SCROLL_BARS (f);
17198
17199
17200 !NILP (bar) || (bar = condemned,
17201 condemned = Qnil,
17202 !NILP (bar));
17203 bar = XSCROLL_BAR (bar)->next)
17204 {
17205 b = XSCROLL_BAR (bar);
17206
17207 scroll_bar_rect.x = b->left;
17208 scroll_bar_rect.y = b->top;
17209 scroll_bar_rect.width = b->width;
17210 scroll_bar_rect.height = b->height;
17211
17212 if (gui_intersect_rectangles (&rect,
17213 &scroll_bar_rect,
17214 &intersection))
17215 x_scroll_bar_redraw (b);
17216 }
17217 }
17218
17219
17220
17221
17222
17223 static void
17224 x_scroll_bar_redraw (struct scroll_bar *bar)
17225 {
17226 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
17227 GC gc = f->output_data.x->normal_gc;
17228
17229 if (f->output_data.x->scroll_bar_background_pixel != -1)
17230 XSetForeground (FRAME_X_DISPLAY (f), gc,
17231 f->output_data.x->scroll_bar_background_pixel);
17232 else
17233 XSetForeground (FRAME_X_DISPLAY (f), gc,
17234 FRAME_BACKGROUND_PIXEL (f));
17235
17236 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), gc,
17237 bar->left, bar->top, bar->width, bar->height);
17238
17239 XSetForeground (FRAME_X_DISPLAY (f), gc,
17240 FRAME_FOREGROUND_PIXEL (f));
17241
17242 x_scroll_bar_set_handle (bar, bar->start, bar->end, true);
17243
17244
17245 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
17246 XSetForeground (FRAME_X_DISPLAY (f), gc,
17247 f->output_data.x->scroll_bar_foreground_pixel);
17248
17249
17250 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), gc,
17251 bar->left, bar->top, bar->width - 1, bar->height - 1);
17252
17253
17254 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
17255 XSetForeground (FRAME_X_DISPLAY (f), gc,
17256 FRAME_FOREGROUND_PIXEL (f));
17257 }
17258 #endif
17259
17260
17261
17262
17263
17264
17265
17266
17267 static void
17268 x_scroll_bar_handle_click (struct scroll_bar *bar,
17269 const XEvent *event,
17270 struct input_event *emacs_event,
17271 Lisp_Object device)
17272 {
17273 int left_range, x, top_range, y;
17274 #ifndef USE_TOOLKIT_SCROLL_BARS
17275 int new_start, new_end;
17276 #endif
17277
17278 if (! WINDOWP (bar->window))
17279 emacs_abort ();
17280
17281 emacs_event->kind = (bar->horizontal
17282 ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT
17283 : SCROLL_BAR_CLICK_EVENT);
17284 emacs_event->code = event->xbutton.button - Button1;
17285 emacs_event->modifiers
17286 = (x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO
17287 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
17288 event->xbutton.state)
17289 | (event->type == ButtonRelease
17290 ? up_modifier
17291 : down_modifier));
17292 emacs_event->frame_or_window = bar->window;
17293 emacs_event->arg = Qnil;
17294 emacs_event->timestamp = event->xbutton.time;
17295
17296 if (!NILP (device))
17297 emacs_event->device = device;
17298
17299 if (bar->horizontal)
17300 {
17301
17302 left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width);
17303 x = event->xbutton.x - HORIZONTAL_SCROLL_BAR_LEFT_BORDER;
17304
17305 if (x < 0) x = 0;
17306 if (x > left_range) x = left_range;
17307
17308 if (x < bar->start)
17309 emacs_event->part = scroll_bar_before_handle;
17310 else if (x < bar->end + HORIZONTAL_SCROLL_BAR_MIN_HANDLE)
17311 emacs_event->part = scroll_bar_horizontal_handle;
17312 else
17313 emacs_event->part = scroll_bar_after_handle;
17314
17315 #ifndef USE_TOOLKIT_SCROLL_BARS
17316
17317 if (event->type == ButtonRelease && bar->dragging != -1)
17318 {
17319 new_start = - bar->dragging;
17320 new_end = new_start + bar->end - bar->start;
17321
17322 x_scroll_bar_set_handle (bar, new_start, new_end, false);
17323 bar->dragging = -1;
17324 }
17325 #endif
17326
17327 XSETINT (emacs_event->x, left_range);
17328 XSETINT (emacs_event->y, x);
17329 }
17330 else
17331 {
17332 top_range
17333 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
17334 y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
17335
17336 if (y < 0) y = 0;
17337 if (y > top_range) y = top_range;
17338
17339 if (y < bar->start)
17340 emacs_event->part = scroll_bar_above_handle;
17341 else if (y < bar->end + VERTICAL_SCROLL_BAR_MIN_HANDLE)
17342 emacs_event->part = scroll_bar_handle;
17343 else
17344 emacs_event->part = scroll_bar_below_handle;
17345
17346 #ifndef USE_TOOLKIT_SCROLL_BARS
17347
17348 if (event->type == ButtonRelease && bar->dragging != -1)
17349 {
17350 new_start = y - bar->dragging;
17351 new_end = new_start + bar->end - bar->start;
17352
17353 x_scroll_bar_set_handle (bar, new_start, new_end, false);
17354 bar->dragging = -1;
17355 }
17356 #endif
17357
17358 XSETINT (emacs_event->x, y);
17359 XSETINT (emacs_event->y, top_range);
17360 }
17361 }
17362
17363 #ifndef USE_TOOLKIT_SCROLL_BARS
17364
17365
17366
17367
17368
17369
17370 static void
17371 x_scroll_bar_note_movement (struct scroll_bar *bar,
17372 const XMotionEvent *event)
17373 {
17374 struct frame *f = XFRAME (XWINDOW (bar->window)->frame);
17375 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
17376
17377 dpyinfo->last_mouse_movement_time = event->time;
17378 dpyinfo->last_mouse_movement_time_send_event = event->send_event;
17379 dpyinfo->last_mouse_scroll_bar = bar;
17380 f->mouse_moved = true;
17381
17382
17383 if (bar->dragging != -1)
17384 {
17385
17386 int new_start = event->y - bar->dragging;
17387
17388 if (new_start != bar->start)
17389 {
17390 int new_end = new_start + bar->end - bar->start;
17391
17392 x_scroll_bar_set_handle (bar, new_start, new_end, false);
17393 }
17394 }
17395 }
17396
17397 #endif
17398
17399
17400
17401
17402 static void
17403 x_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
17404 enum scroll_bar_part *part, Lisp_Object *x,
17405 Lisp_Object *y, Time *timestamp)
17406 {
17407 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp);
17408 struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar;
17409 Window w = bar->x_window;
17410 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
17411 int win_x, win_y;
17412 Window dummy_window;
17413 int dummy_coord;
17414 unsigned int dummy_mask;
17415
17416 block_input ();
17417
17418
17419
17420 if (x_query_pointer (FRAME_X_DISPLAY (f), w,
17421
17422
17423 &dummy_window, &dummy_window,
17424 &dummy_coord, &dummy_coord,
17425
17426
17427 &win_x, &win_y,
17428
17429
17430 &dummy_mask))
17431 {
17432 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
17433
17434 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
17435
17436 if (bar->dragging != -1)
17437 win_y -= bar->dragging;
17438
17439 if (win_y < 0)
17440 win_y = 0;
17441 if (win_y > top_range)
17442 win_y = top_range;
17443
17444 *fp = f;
17445 *bar_window = bar->window;
17446
17447 if (bar->dragging != -1)
17448 *part = scroll_bar_handle;
17449 else if (win_y < bar->start)
17450 *part = scroll_bar_above_handle;
17451 else if (win_y < bar->end + VERTICAL_SCROLL_BAR_MIN_HANDLE)
17452 *part = scroll_bar_handle;
17453 else
17454 *part = scroll_bar_below_handle;
17455
17456 XSETINT (*x, win_y);
17457 XSETINT (*y, top_range);
17458
17459 f->mouse_moved = false;
17460 dpyinfo->last_mouse_scroll_bar = NULL;
17461 *timestamp = dpyinfo->last_mouse_movement_time;
17462 }
17463
17464 unblock_input ();
17465 }
17466
17467
17468
17469
17470
17471 static void
17472 x_horizontal_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
17473 enum scroll_bar_part *part, Lisp_Object *x,
17474 Lisp_Object *y, Time *timestamp)
17475 {
17476 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp);
17477 struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar;
17478 Window w = bar->x_window;
17479 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
17480 int win_x, win_y;
17481 Window dummy_window;
17482 int dummy_coord;
17483 unsigned int dummy_mask;
17484
17485 block_input ();
17486
17487
17488
17489 if (x_query_pointer (FRAME_X_DISPLAY (f), w,
17490
17491
17492 &dummy_window, &dummy_window,
17493 &dummy_coord, &dummy_coord,
17494
17495
17496 &win_x, &win_y,
17497
17498
17499 &dummy_mask))
17500 {
17501 int left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width);
17502
17503 win_x -= HORIZONTAL_SCROLL_BAR_LEFT_BORDER;
17504
17505 if (bar->dragging != -1)
17506 win_x -= bar->dragging;
17507
17508 if (win_x < 0)
17509 win_x = 0;
17510 if (win_x > left_range)
17511 win_x = left_range;
17512
17513 *fp = f;
17514 *bar_window = bar->window;
17515
17516 if (bar->dragging != -1)
17517 *part = scroll_bar_horizontal_handle;
17518 else if (win_x < bar->start)
17519 *part = scroll_bar_before_handle;
17520 else if (win_x < bar->end + HORIZONTAL_SCROLL_BAR_MIN_HANDLE)
17521 *part = scroll_bar_handle;
17522 else
17523 *part = scroll_bar_after_handle;
17524
17525 XSETINT (*y, win_x);
17526 XSETINT (*x, left_range);
17527
17528 f->mouse_moved = false;
17529 dpyinfo->last_mouse_scroll_bar = NULL;
17530 *timestamp = dpyinfo->last_mouse_movement_time;
17531 }
17532
17533 unblock_input ();
17534 }
17535
17536
17537
17538
17539
17540
17541 static void
17542 x_scroll_bar_clear (struct frame *f)
17543 {
17544 #ifndef USE_TOOLKIT_SCROLL_BARS
17545 Lisp_Object bar, condemned;
17546 GC gc = f->output_data.x->normal_gc;
17547
17548 if (f->output_data.x->scroll_bar_background_pixel != -1)
17549 XSetForeground (FRAME_X_DISPLAY (f), gc,
17550 f->output_data.x->scroll_bar_background_pixel);
17551 else
17552 XSetForeground (FRAME_X_DISPLAY (f), gc,
17553 FRAME_BACKGROUND_PIXEL (f));
17554
17555
17556
17557
17558 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
17559 {
17560 condemned = FRAME_CONDEMNED_SCROLL_BARS (f);
17561 for (bar = FRAME_SCROLL_BARS (f);
17562
17563
17564 !NILP (bar) || (bar = condemned,
17565 condemned = Qnil,
17566 !NILP (bar));
17567 bar = XSCROLL_BAR (bar)->next)
17568 x_scroll_bar_redraw (XSCROLL_BAR (bar));
17569 }
17570
17571 XSetForeground (FRAME_X_DISPLAY (f), gc,
17572 FRAME_FOREGROUND_PIXEL (f));
17573 #endif
17574 }
17575
17576 #ifdef ENABLE_CHECKING
17577
17578
17579
17580
17581 static int temp_index;
17582 static short temp_buffer[100];
17583
17584 #define STORE_KEYSYM_FOR_DEBUG(keysym) \
17585 if (temp_index == ARRAYELTS (temp_buffer)) \
17586 temp_index = 0; \
17587 temp_buffer[temp_index++] = (keysym)
17588
17589 #else
17590
17591 #define STORE_KEYSYM_FOR_DEBUG(keysym) ((void)0)
17592
17593 #endif
17594
17595
17596
17597
17598 static struct x_display_info *XTread_socket_fake_io_error;
17599
17600
17601
17602
17603
17604
17605 static struct x_display_info *next_noop_dpyinfo;
17606
17607
17608
17609
17610
17611
17612
17613
17614
17615 #ifdef HAVE_X_I18N
17616 static int
17617 x_filter_event (struct x_display_info *dpyinfo, XEvent *event)
17618 {
17619
17620
17621
17622
17623
17624 struct frame *f1;
17625
17626 #if defined HAVE_XINPUT2 && defined USE_GTK
17627 bool xinput_event = false;
17628 if (dpyinfo->supports_xi2
17629 && event->type == GenericEvent
17630 && (event->xgeneric.extension
17631 == dpyinfo->xi2_opcode)
17632 && ((event->xgeneric.evtype
17633 == XI_KeyPress)
17634 || (event->xgeneric.evtype
17635 == XI_KeyRelease)))
17636 {
17637 f1 = x_any_window_to_frame (dpyinfo,
17638 ((XIDeviceEvent *)
17639 event->xcookie.data)->event);
17640 xinput_event = true;
17641 }
17642 else
17643 #endif
17644 f1 = x_any_window_to_frame (dpyinfo,
17645 event->xclient.window);
17646
17647 #ifdef USE_GTK
17648 if (!x_gtk_use_native_input
17649 && !dpyinfo->prefer_native_input)
17650 {
17651 #endif
17652 return XFilterEvent (event, f1 ? FRAME_X_WINDOW (f1) : None);
17653 #ifdef USE_GTK
17654 }
17655 else if (f1 && (event->type == KeyPress
17656 || event->type == KeyRelease
17657 #ifdef HAVE_XINPUT2
17658 || xinput_event
17659 #endif
17660 ))
17661 {
17662 bool result;
17663
17664 block_input ();
17665 result = xg_filter_key (f1, event);
17666 unblock_input ();
17667
17668
17669
17670
17671
17672 if (popup_activated ())
17673 xg_pending_quit_event.kind = NO_EVENT;
17674
17675 if (result && f1)
17676
17677
17678 XNoOp (FRAME_X_DISPLAY (f1));
17679
17680 return result;
17681 }
17682
17683 return 0;
17684 #endif
17685 }
17686 #endif
17687
17688 #ifdef USE_GTK
17689
17690
17691
17692 static GdkFilterReturn
17693 event_handler_gdk (GdkXEvent *gxev, GdkEvent *ev, gpointer data)
17694 {
17695 XEvent *xev = (XEvent *) gxev;
17696
17697 block_input ();
17698 if (current_count >= 0)
17699 {
17700 struct x_display_info *dpyinfo;
17701
17702 dpyinfo = x_display_info_for_display (xev->xany.display);
17703
17704 #ifdef HAVE_X_I18N
17705
17706
17707
17708 if ((xev->type == KeyPress || xev->type == KeyRelease)
17709 && dpyinfo
17710 && x_filter_event (dpyinfo, xev))
17711 {
17712 unblock_input ();
17713 return GDK_FILTER_REMOVE;
17714 }
17715 #elif USE_GTK
17716 if (dpyinfo && (dpyinfo->prefer_native_input
17717 || x_gtk_use_native_input)
17718 && (xev->type == KeyPress
17719 #ifdef HAVE_XINPUT2
17720
17721
17722 || (dpyinfo->supports_xi2
17723 && xev->type == GenericEvent
17724 && (xev->xgeneric.extension
17725 == dpyinfo->xi2_opcode)
17726 && ((xev->xgeneric.evtype
17727 == XI_KeyPress)
17728 || (xev->xgeneric.evtype
17729 == XI_KeyRelease)))
17730 #endif
17731 ))
17732 {
17733 struct frame *f;
17734
17735 #ifdef HAVE_XINPUT2
17736 if (xev->type == GenericEvent)
17737 f = x_any_window_to_frame (dpyinfo,
17738 ((XIDeviceEvent *) xev->xcookie.data)->event);
17739 else
17740 #endif
17741 f = x_any_window_to_frame (dpyinfo, xev->xany.window);
17742
17743 if (f && xg_filter_key (f, xev))
17744 {
17745 unblock_input ();
17746 return GDK_FILTER_REMOVE;
17747 }
17748 }
17749 #endif
17750
17751 if (! dpyinfo)
17752 current_finish = X_EVENT_NORMAL;
17753 else
17754 current_count
17755 += handle_one_xevent (dpyinfo, xev, ¤t_finish,
17756 current_hold_quit);
17757 }
17758 else
17759 current_finish = x_dispatch_event (xev, xev->xany.display);
17760
17761 unblock_input ();
17762
17763 if (current_finish == X_EVENT_GOTO_OUT || current_finish == X_EVENT_DROP)
17764 return GDK_FILTER_REMOVE;
17765
17766 return GDK_FILTER_CONTINUE;
17767 }
17768 #endif
17769
17770
17771 static void xembed_send_message (struct frame *f, Time,
17772 enum xembed_message,
17773 long detail, long data1, long data2);
17774
17775 static void
17776 x_net_wm_state (struct frame *f, Window window)
17777 {
17778 int value = FULLSCREEN_NONE;
17779 Lisp_Object lval = Qnil;
17780 bool sticky = false, shaded = false;
17781
17782 x_get_current_wm_state (f, window, &value, &sticky, &shaded);
17783
17784 switch (value)
17785 {
17786 case FULLSCREEN_WIDTH:
17787 lval = Qfullwidth;
17788 break;
17789 case FULLSCREEN_HEIGHT:
17790 lval = Qfullheight;
17791 break;
17792 case FULLSCREEN_BOTH:
17793 lval = Qfullboth;
17794 break;
17795 case FULLSCREEN_MAXIMIZED:
17796 lval = Qmaximized;
17797 break;
17798 }
17799
17800 store_frame_param (f, Qfullscreen, lval);
17801 store_frame_param (f, Qsticky, sticky ? Qt : Qnil);
17802 store_frame_param (f, Qshaded, shaded ? Qt : Qnil);
17803 }
17804
17805
17806
17807 static void
17808 x_flush_dirty_back_buffer_on (struct frame *f)
17809 {
17810 #ifdef HAVE_XDBE
17811 if (FRAME_GARBAGED_P (f)
17812 || buffer_flipping_blocked_p ()
17813
17814
17815 || !FRAME_X_COMPLETE_P (f)
17816 || !FRAME_X_NEED_BUFFER_FLIP (f))
17817 return;
17818
17819 show_back_buffer (f);
17820 #endif
17821 }
17822
17823 #ifdef HAVE_GTK3
17824 void
17825 x_scroll_bar_configure (GdkEvent *event)
17826 {
17827 XEvent configure;
17828 GdkDisplay *gdpy;
17829 Display *dpy;
17830
17831 configure.xconfigure.type = ConfigureNotify;
17832 configure.xconfigure.serial = 0;
17833 configure.xconfigure.send_event = event->configure.send_event;
17834 configure.xconfigure.x = event->configure.x;
17835 configure.xconfigure.y = event->configure.y;
17836 configure.xconfigure.width = event->configure.width;
17837 configure.xconfigure.height = event->configure.height;
17838 configure.xconfigure.border_width = 0;
17839 configure.xconfigure.event = GDK_WINDOW_XID (event->configure.window);
17840 configure.xconfigure.window = GDK_WINDOW_XID (event->configure.window);
17841 configure.xconfigure.above = None;
17842 configure.xconfigure.override_redirect = False;
17843
17844 gdpy = gdk_window_get_display (event->configure.window);
17845 dpy = gdk_x11_display_get_xdisplay (gdpy);
17846
17847 x_dispatch_event (&configure, dpy);
17848 }
17849 #endif
17850
17851
17852
17853
17854
17855
17856
17857
17858
17859 static struct frame *
17860 mouse_or_wdesc_frame (struct x_display_info *dpyinfo, int wdesc)
17861 {
17862 struct frame *lm_f = (gui_mouse_grabbed (dpyinfo)
17863 ? dpyinfo->last_mouse_frame
17864 : NULL);
17865
17866 if (lm_f && !EQ (track_mouse, Qdropping)
17867 && !EQ (track_mouse, Qdrag_source))
17868 return lm_f;
17869 else
17870 {
17871 struct frame *w_f = x_window_to_frame (dpyinfo, wdesc);
17872
17873
17874 if (!w_f || FRAME_TOOLTIP_P (w_f))
17875 return EQ (track_mouse, Qdropping) ? lm_f : NULL;
17876 else
17877
17878
17879 return w_f;
17880 }
17881 }
17882
17883 static void
17884 x_dnd_compute_tip_xy (int *root_x, int *root_y, Lisp_Object attributes)
17885 {
17886 Lisp_Object monitor, geometry;
17887 int min_x, min_y, max_x, max_y;
17888 int width, height;
17889
17890 width = FRAME_PIXEL_WIDTH (XFRAME (tip_frame));
17891 height = FRAME_PIXEL_HEIGHT (XFRAME (tip_frame));
17892
17893 max_y = -1;
17894
17895
17896
17897 while (CONSP (attributes))
17898 {
17899 monitor = XCAR (attributes);
17900 geometry = assq_no_quit (Qgeometry, monitor);
17901
17902 if (CONSP (geometry))
17903 {
17904 min_x = XFIXNUM (Fnth (make_fixnum (1), geometry));
17905 min_y = XFIXNUM (Fnth (make_fixnum (2), geometry));
17906 max_x = min_x + XFIXNUM (Fnth (make_fixnum (3), geometry));
17907 max_y = min_y + XFIXNUM (Fnth (make_fixnum (4), geometry));
17908
17909 if (min_x <= *root_x && *root_x < max_x
17910 && min_y <= *root_y && *root_y < max_y)
17911 break;
17912
17913 max_y = -1;
17914 }
17915
17916 attributes = XCDR (attributes);
17917 }
17918
17919
17920
17921 if (max_y < 0)
17922 {
17923 min_x = 0;
17924 min_y = 0;
17925 max_x = x_display_pixel_width (FRAME_DISPLAY_INFO (x_dnd_frame));
17926 max_y = x_display_pixel_height (FRAME_DISPLAY_INFO (x_dnd_frame));
17927 }
17928
17929 if (*root_y + XFIXNUM (tip_dy) <= min_y)
17930 *root_y = min_y;
17931 else if (*root_y + XFIXNUM (tip_dy) + height <= max_y)
17932
17933 *root_y += XFIXNUM (tip_dy);
17934 else if (height + XFIXNUM (tip_dy) + min_y <= *root_y)
17935
17936 *root_y -= height + XFIXNUM (tip_dy);
17937 else
17938
17939 *root_y = min_y;
17940
17941 if (*root_x + XFIXNUM (tip_dx) <= min_x)
17942 *root_x = 0;
17943 else if (*root_x + XFIXNUM (tip_dx) + width <= max_x)
17944
17945 *root_x += XFIXNUM (tip_dx);
17946 else if (width + XFIXNUM (tip_dx) + min_x <= *root_x)
17947
17948 *root_x -= width + XFIXNUM (tip_dx);
17949 else
17950
17951 *root_x = min_x;
17952 }
17953
17954 static void
17955 x_dnd_update_tooltip_position (int root_x, int root_y)
17956 {
17957 struct frame *tip_f;
17958
17959 if (!x_dnd_in_progress || !x_dnd_update_tooltip)
17960 return;
17961
17962 if (!FRAMEP (tip_frame))
17963 return;
17964
17965 tip_f = XFRAME (tip_frame);
17966
17967 if (!FRAME_LIVE_P (tip_f)
17968 || !FRAME_VISIBLE_P (tip_f)
17969 || (FRAME_X_DISPLAY (tip_f)
17970 != FRAME_X_DISPLAY (x_dnd_frame)))
17971 return;
17972
17973 if (tip_window != None
17974 && FIXNUMP (tip_dx) && FIXNUMP (tip_dy))
17975 {
17976 x_dnd_compute_tip_xy (&root_x, &root_y,
17977 x_dnd_monitors);
17978
17979 if (x_dnd_last_tooltip_valid
17980 && root_x == x_dnd_last_tooltip_x
17981 && root_y == x_dnd_last_tooltip_y)
17982 return;
17983
17984 x_dnd_last_tooltip_x = root_x;
17985 x_dnd_last_tooltip_y = root_y;
17986 x_dnd_last_tooltip_valid = true;
17987
17988 XMoveWindow (FRAME_X_DISPLAY (x_dnd_frame),
17989 tip_window, root_x, root_y);
17990 }
17991 }
17992
17993 static void
17994 x_dnd_update_tooltip_now (void)
17995 {
17996 int root_x, root_y;
17997 Window root, child;
17998 int win_x, win_y;
17999 unsigned int mask;
18000 Bool rc;
18001 struct x_display_info *dpyinfo;
18002
18003 if (!x_dnd_in_progress || !x_dnd_update_tooltip)
18004 return;
18005
18006 dpyinfo = FRAME_DISPLAY_INFO (x_dnd_frame);
18007
18008 #ifndef HAVE_XINPUT2
18009 rc = XQueryPointer (dpyinfo->display,
18010 dpyinfo->root_window,
18011 &root, &child, &root_x,
18012 &root_y, &win_x, &win_y,
18013 &mask);
18014 #else
18015 rc = x_query_pointer_1 (dpyinfo, x_dnd_pointer_device,
18016 dpyinfo->root_window,
18017 &root, &child, &root_x,
18018 &root_y, &win_x, &win_y,
18019 &mask);
18020 #endif
18021
18022 if (rc)
18023 x_dnd_update_tooltip_position (root_x, root_y);
18024 }
18025
18026
18027
18028 static void
18029 x_dnd_update_state (struct x_display_info *dpyinfo, Time timestamp)
18030 {
18031 int root_x, root_y, dummy_x, dummy_y, target_proto, motif_style;
18032 unsigned int dummy_mask;
18033 Window dummy, dummy_child, target, toplevel;
18034 xm_top_level_leave_message lmsg;
18035 xm_top_level_enter_message emsg;
18036 xm_drag_motion_message dmsg;
18037 xm_drop_start_message dsmsg;
18038 bool was_frame;
18039
18040 if (x_query_pointer_1 (dpyinfo,
18041 #ifdef HAVE_XINPUT2
18042 x_dnd_pointer_device,
18043 #else
18044 -1,
18045 #endif
18046 dpyinfo->root_window,
18047 &dummy, &dummy_child,
18048 &root_x, &root_y,
18049 &dummy_x, &dummy_y,
18050 &dummy_mask))
18051 {
18052 target = x_dnd_get_target_window (dpyinfo, root_x,
18053 root_y, &target_proto,
18054 &motif_style, &toplevel,
18055 &was_frame);
18056
18057 if (toplevel != x_dnd_last_seen_toplevel)
18058 {
18059 if (toplevel != FRAME_OUTER_WINDOW (x_dnd_frame)
18060 && x_dnd_return_frame == 1)
18061 x_dnd_return_frame = 2;
18062
18063 if (x_dnd_return_frame == 2
18064 && x_any_window_to_frame (dpyinfo, toplevel))
18065 {
18066 if (x_dnd_last_seen_window != None
18067 && x_dnd_last_protocol_version != -1
18068 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
18069 x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window,
18070 x_dnd_last_seen_toplevel);
18071 else if (x_dnd_last_seen_window != None
18072 && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
18073 && !x_dnd_disable_motif_drag
18074 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
18075 {
18076 if (!x_dnd_motif_setup_p)
18077 xm_setup_drag_info (dpyinfo, x_dnd_frame);
18078
18079 lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
18080 XM_DRAG_REASON_TOP_LEVEL_LEAVE);
18081 lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
18082 lmsg.zero = 0;
18083 lmsg.timestamp = timestamp;
18084 lmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
18085
18086 if (x_dnd_motif_setup_p)
18087 xm_send_top_level_leave_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
18088 x_dnd_last_seen_window, &lmsg);
18089 }
18090
18091 x_dnd_end_window = x_dnd_last_seen_window;
18092 x_dnd_last_seen_window = None;
18093 x_dnd_last_seen_toplevel = None;
18094 x_dnd_in_progress = false;
18095 x_dnd_return_frame_object
18096 = x_any_window_to_frame (dpyinfo, toplevel);
18097 x_dnd_return_frame = 3;
18098 x_dnd_waiting_for_finish = false;
18099 target = None;
18100 }
18101 }
18102
18103 if (target != x_dnd_last_seen_window)
18104 {
18105 if (x_dnd_last_seen_window != None
18106 && x_dnd_last_protocol_version != -1
18107 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
18108 x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window,
18109 x_dnd_last_seen_toplevel);
18110 else if (x_dnd_last_seen_window != None
18111 && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
18112 && !x_dnd_disable_motif_drag
18113 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
18114 {
18115 if (!x_dnd_motif_setup_p)
18116 xm_setup_drag_info (dpyinfo, x_dnd_frame);
18117
18118 lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
18119 XM_DRAG_REASON_TOP_LEVEL_LEAVE);
18120 lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
18121 lmsg.zero = 0;
18122 lmsg.timestamp = timestamp;
18123 lmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
18124
18125 if (x_dnd_motif_setup_p)
18126 xm_send_top_level_leave_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
18127 x_dnd_last_seen_window, &lmsg);
18128 }
18129
18130 x_dnd_action = None;
18131 x_dnd_last_seen_toplevel = toplevel;
18132 x_dnd_last_seen_window = target;
18133 x_dnd_last_protocol_version = target_proto;
18134 x_dnd_last_motif_style = motif_style;
18135 x_dnd_last_window_is_frame = was_frame;
18136
18137 if (target != None && x_dnd_last_protocol_version != -1)
18138 x_dnd_send_enter (x_dnd_frame, target, x_dnd_last_seen_toplevel,
18139 x_dnd_last_protocol_version);
18140 else if (target != None && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
18141 && !x_dnd_disable_motif_drag)
18142 {
18143 if (!x_dnd_motif_setup_p)
18144 xm_setup_drag_info (dpyinfo, x_dnd_frame);
18145
18146 emsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
18147 XM_DRAG_REASON_TOP_LEVEL_ENTER);
18148 emsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
18149 emsg.zero = 0;
18150 emsg.timestamp = timestamp;
18151 emsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
18152 emsg.index_atom = x_dnd_motif_atom;
18153
18154 if (x_dnd_motif_setup_p)
18155 xm_send_top_level_enter_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
18156 target, &emsg);
18157 }
18158 }
18159 else
18160 x_dnd_last_seen_toplevel = toplevel;
18161
18162 if (x_dnd_last_window_is_frame && target != None)
18163 x_dnd_note_self_position (dpyinfo, target, root_x, root_y);
18164 else if (x_dnd_last_protocol_version != -1 && target != None)
18165 x_dnd_send_position (x_dnd_frame, target,
18166 x_dnd_last_seen_toplevel,
18167 x_dnd_last_protocol_version,
18168 root_x, root_y,
18169 x_dnd_selection_timestamp,
18170 x_dnd_wanted_action, 0,
18171 #ifdef HAVE_XKB
18172 x_dnd_keyboard_state
18173 #else
18174 0
18175 #endif
18176 );
18177 else if (XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) && target != None
18178 && !x_dnd_disable_motif_drag)
18179 {
18180 if (!x_dnd_motif_setup_p)
18181 xm_setup_drag_info (dpyinfo, x_dnd_frame);
18182
18183 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
18184 XM_DRAG_REASON_DRAG_MOTION);
18185 dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
18186 dmsg.side_effects
18187 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
18188 x_dnd_wanted_action),
18189 XM_DROP_SITE_VALID, x_dnd_motif_operations,
18190 (!x_dnd_xm_use_help
18191 ? XM_DROP_ACTION_DROP
18192 : XM_DROP_ACTION_DROP_HELP));
18193 dmsg.timestamp = timestamp;
18194 dmsg.x = root_x;
18195 dmsg.y = root_y;
18196
18197 if (x_dnd_motif_setup_p)
18198 xm_send_drag_motion_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
18199 target, &dmsg);
18200 }
18201
18202 x_dnd_update_tooltip_position (root_x, root_y);
18203 }
18204
18205 else if (x_dnd_last_protocol_version != -1)
18206 {
18207 if (x_dnd_last_seen_window != None
18208 && x_dnd_last_protocol_version != -1)
18209 x_dnd_send_leave (x_dnd_frame,
18210 x_dnd_last_seen_window,
18211 x_dnd_last_seen_toplevel);
18212 else if (x_dnd_last_seen_window != None
18213 && !XM_DRAG_STYLE_IS_DROP_ONLY (x_dnd_last_motif_style)
18214 && x_dnd_last_motif_style != XM_DRAG_STYLE_NONE
18215 && x_dnd_motif_setup_p)
18216 {
18217 dsmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
18218 XM_DRAG_REASON_DROP_START);
18219 dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
18220 dsmsg.timestamp = timestamp;
18221 dsmsg.side_effects
18222 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
18223 x_dnd_wanted_action),
18224 XM_DROP_SITE_VALID, x_dnd_motif_operations,
18225 XM_DROP_ACTION_DROP_CANCEL);
18226 dsmsg.x = 0;
18227 dsmsg.y = 0;
18228 dsmsg.index_atom = x_dnd_motif_atom;
18229 dsmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
18230
18231 x_dnd_send_xm_leave_for_drop (dpyinfo, x_dnd_frame,
18232 x_dnd_last_seen_window, timestamp);
18233 xm_send_drop_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
18234 x_dnd_last_seen_window, &dsmsg);
18235 }
18236
18237 x_dnd_end_window = x_dnd_last_seen_window;
18238 x_dnd_last_seen_window = None;
18239 x_dnd_last_seen_toplevel = None;
18240 x_dnd_in_progress = false;
18241 x_dnd_waiting_for_finish = false;
18242 x_dnd_frame = NULL;
18243 }
18244 }
18245
18246 int
18247 x_display_pixel_height (struct x_display_info *dpyinfo)
18248 {
18249 if (dpyinfo->screen_height)
18250 return dpyinfo->screen_height;
18251
18252 return HeightOfScreen (dpyinfo->screen);
18253 }
18254
18255 int
18256 x_display_pixel_width (struct x_display_info *dpyinfo)
18257 {
18258 if (dpyinfo->screen_width)
18259 return dpyinfo->screen_width;
18260
18261 return WidthOfScreen (dpyinfo->screen);
18262 }
18263
18264
18265
18266 void
18267 x_wait_for_cell_change (Lisp_Object cell, struct timespec timeout)
18268 {
18269 struct x_display_info *dpyinfo;
18270 fd_set fds;
18271 int fd, maxfd;
18272 #ifndef USE_GTK
18273 int finish, rc;
18274 XEvent event;
18275 fd_set rfds;
18276 #endif
18277 struct input_event hold_quit;
18278 struct timespec current, at;
18279
18280 at = timespec_add (current_timespec (), timeout);
18281
18282 #ifndef USE_GTK
18283 FD_ZERO (&rfds);
18284 rc = -1;
18285 #endif
18286
18287 while (true)
18288 {
18289 FD_ZERO (&fds);
18290 maxfd = -1;
18291
18292 for (dpyinfo = x_display_list; dpyinfo;
18293 dpyinfo = dpyinfo->next)
18294 {
18295 fd = ConnectionNumber (dpyinfo->display);
18296
18297 #ifndef USE_GTK
18298 if ((rc < 0 || FD_ISSET (fd, &rfds))
18299
18300
18301 && XPending (dpyinfo->display))
18302 {
18303 while (XPending (dpyinfo->display))
18304 {
18305 EVENT_INIT (hold_quit);
18306
18307 XNextEvent (dpyinfo->display, &event);
18308 handle_one_xevent (dpyinfo, &event,
18309 &finish, &hold_quit);
18310
18311 if (!NILP (XCAR (cell)))
18312 return;
18313
18314 if (finish == X_EVENT_GOTO_OUT)
18315 break;
18316
18317
18318 if (hold_quit.kind != NO_EVENT)
18319 kbd_buffer_store_event (&hold_quit);
18320 }
18321 }
18322 #endif
18323
18324 if (fd > maxfd)
18325 maxfd = fd;
18326
18327 eassert (fd < FD_SETSIZE);
18328 FD_SET (fd, &fds);
18329 }
18330
18331
18332
18333 #ifdef USE_GTK
18334 while (gtk_events_pending ())
18335 {
18336 EVENT_INIT (hold_quit);
18337 current_count = 0;
18338 current_hold_quit = &hold_quit;
18339 current_finish = X_EVENT_NORMAL;
18340
18341 gtk_main_iteration ();
18342
18343 current_count = -1;
18344 current_hold_quit = NULL;
18345
18346
18347 if (hold_quit.kind != NO_EVENT)
18348 kbd_buffer_store_event (&hold_quit);
18349
18350 if (!NILP (XCAR (cell)))
18351 return;
18352
18353 if (current_finish == X_EVENT_GOTO_OUT)
18354 break;
18355 }
18356 #endif
18357
18358 eassert (maxfd >= 0);
18359
18360 current = current_timespec ();
18361
18362 if (timespec_cmp (at, current) < 0
18363 || !NILP (XCAR (cell)))
18364 return;
18365
18366 timeout = timespec_sub (at, current);
18367
18368 #ifndef USE_GTK
18369 rc = pselect (maxfd + 1, &fds, NULL, NULL, &timeout, NULL);
18370
18371 if (rc >= 0)
18372 rfds = fds;
18373 #else
18374 pselect (maxfd + 1, &fds, NULL, NULL, &timeout, NULL);
18375 #endif
18376 }
18377 }
18378
18379
18380
18381
18382
18383 static bool
18384 x_find_monitors_changed_event (struct x_display_info *dpyinfo)
18385 {
18386 union buffered_input_event *event;
18387
18388 event = kbd_fetch_ptr;
18389
18390 while (event != kbd_store_ptr)
18391 {
18392 if (event->ie.kind == MONITORS_CHANGED_EVENT
18393 && XTERMINAL (event->ie.arg) == dpyinfo->terminal)
18394 return true;
18395
18396 event = X_NEXT_KBD_EVENT (event);
18397 }
18398
18399 return false;
18400 }
18401
18402 #ifdef USE_GTK
18403 static void
18404 x_monitors_changed_cb (GdkScreen *gscr, gpointer user_data)
18405 {
18406 struct x_display_info *dpyinfo;
18407 struct input_event ie;
18408 Lisp_Object current_monitors, terminal;
18409 GdkDisplay *gdpy;
18410 Display *dpy;
18411
18412 gdpy = gdk_screen_get_display (gscr);
18413 dpy = gdk_x11_display_get_xdisplay (gdpy);
18414 dpyinfo = x_display_info_for_display (dpy);
18415
18416 if (!dpyinfo)
18417 return;
18418
18419 if (x_find_monitors_changed_event (dpyinfo))
18420 return;
18421
18422 XSETTERMINAL (terminal, dpyinfo->terminal);
18423
18424 current_monitors
18425 = Fx_display_monitor_attributes_list (terminal);
18426
18427 if (NILP (Fequal (current_monitors,
18428 dpyinfo->last_monitor_attributes_list)))
18429 {
18430 EVENT_INIT (ie);
18431 ie.kind = MONITORS_CHANGED_EVENT;
18432 ie.arg = terminal;
18433
18434 kbd_buffer_store_event (&ie);
18435
18436 if (x_dnd_in_progress && x_dnd_update_tooltip)
18437 x_dnd_monitors = current_monitors;
18438
18439 x_dnd_update_tooltip_now ();
18440 }
18441
18442 dpyinfo->last_monitor_attributes_list = current_monitors;
18443 }
18444 #endif
18445
18446
18447
18448
18449 static bool
18450 x_coords_from_dnd_message (struct x_display_info *dpyinfo,
18451 XEvent *event, int *x_out, int *y_out)
18452 {
18453 xm_drag_motion_message dmsg;
18454 xm_drag_motion_reply dreply;
18455 xm_drop_start_message smsg;
18456 xm_drop_start_reply reply;
18457 unsigned long kde_data;
18458
18459 if (event->type != ClientMessage)
18460 return false;
18461
18462 if (event->xclient.message_type == dpyinfo->Xatom_XdndPosition)
18463 {
18464 if (event->xclient.format != 32)
18465 return false;
18466
18467 *x_out = (((unsigned long) event->xclient.data.l[2]) >> 16
18468 & 0xffff);
18469 *y_out = (event->xclient.data.l[2] & 0xffff);
18470
18471 return true;
18472 }
18473
18474 if ((event->xclient.message_type
18475 == dpyinfo->Xatom_MOTIF_DRAG_AND_DROP_MESSAGE)
18476 && event->xclient.format == 8)
18477 {
18478 if (!xm_read_drag_motion_message (event, &dmsg))
18479 {
18480 *x_out = dmsg.x;
18481 *y_out = dmsg.y;
18482
18483 return true;
18484 }
18485 else if (!xm_read_drag_motion_reply (event, &dreply))
18486 {
18487 *x_out = dreply.better_x;
18488 *y_out = dreply.better_y;
18489
18490 return true;
18491 }
18492 else if (!xm_read_drop_start_message (event, &smsg))
18493 {
18494 *x_out = smsg.x;
18495 *y_out = smsg.y;
18496
18497 return true;
18498 }
18499 else if (!xm_read_drop_start_reply (event, &reply))
18500 {
18501 *x_out = reply.better_x;
18502 *y_out = reply.better_y;
18503
18504 return true;
18505 }
18506 }
18507
18508 if (((event->xclient.message_type
18509 == dpyinfo->Xatom_DndProtocol)
18510 || (event->xclient.message_type
18511 == dpyinfo->Xatom_DND_PROTOCOL))
18512 && event->xclient.format == 32
18513
18514
18515 && event->xclient.data.l[4])
18516 {
18517 kde_data = (unsigned long) event->xclient.data.l[3];
18518
18519 *x_out = (kde_data & 0xffff);
18520 *y_out = (kde_data >> 16 & 0xffff);
18521
18522 return true;
18523 }
18524
18525 return false;
18526 }
18527
18528 static void
18529 x_handle_wm_state (struct frame *f, struct input_event *ie)
18530 {
18531 struct x_display_info *dpyinfo;
18532 Atom type;
18533 int format;
18534 unsigned long nitems, bytes_after;
18535 unsigned char *data;
18536 unsigned long *state;
18537
18538 data = NULL;
18539 dpyinfo = FRAME_DISPLAY_INFO (f);
18540
18541 if (XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
18542 dpyinfo->Xatom_wm_state, 0, 2, False,
18543 AnyPropertyType, &type, &format, &nitems,
18544 &bytes_after, &data) != Success)
18545 return;
18546
18547 if (!data || nitems != 2 || format != 32)
18548 {
18549 if (data)
18550 XFree (data);
18551
18552 return;
18553 }
18554
18555 state = (unsigned long *) data;
18556
18557 if (state[0] == NormalState && FRAME_ICONIFIED_P (f))
18558 {
18559
18560
18561 SET_FRAME_VISIBLE (f, 1);
18562 SET_FRAME_ICONIFIED (f, false);
18563 f->output_data.x->has_been_visible = true;
18564
18565 ie->kind = DEICONIFY_EVENT;
18566 XSETFRAME (ie->frame_or_window, f);
18567 }
18568 else if (state[0] == IconicState
18569
18570
18571 && !x_wm_supports (f, dpyinfo->Xatom_net_wm_state_hidden))
18572 {
18573
18574
18575
18576 SET_FRAME_VISIBLE (f, 0);
18577 SET_FRAME_ICONIFIED (f, true);
18578
18579 ie->kind = ICONIFY_EVENT;
18580 XSETFRAME (ie->frame_or_window, f);
18581 }
18582
18583
18584
18585
18586
18587
18588 XFree (data);
18589 }
18590
18591 #ifdef HAVE_XFIXES
18592
18593 static bool
18594 x_handle_selection_monitor_event (struct x_display_info *dpyinfo,
18595 const XEvent *event)
18596 {
18597 XFixesSelectionNotifyEvent *notify;
18598 int i;
18599
18600 notify = (XFixesSelectionNotifyEvent *) event;
18601
18602 if (notify->window != dpyinfo->selection_tracking_window)
18603 return false;
18604
18605 for (i = 0; i < dpyinfo->n_monitored_selections; ++i)
18606 {
18607
18608 if (notify->selection == dpyinfo->monitored_selections[i].name)
18609 dpyinfo->monitored_selections[i].owner = notify->owner;
18610 }
18611
18612 return true;
18613 }
18614
18615 Window
18616 x_find_selection_owner (struct x_display_info *dpyinfo, Atom selection)
18617 {
18618 int i;
18619
18620 for (i = 0; i < dpyinfo->n_monitored_selections; ++i)
18621 {
18622 if (selection == dpyinfo->monitored_selections[i].name)
18623 return dpyinfo->monitored_selections[i].owner;
18624 }
18625
18626 return X_INVALID_WINDOW;
18627 }
18628
18629 #endif
18630
18631
18632
18633
18634
18635
18636
18637
18638
18639
18640 static int
18641 handle_one_xevent (struct x_display_info *dpyinfo,
18642 #ifndef HAVE_XINPUT2
18643 const XEvent *event,
18644 #else
18645 XEvent *event,
18646 #endif
18647 int *finish, struct input_event *hold_quit)
18648 {
18649 union buffered_input_event inev;
18650 int count = 0;
18651 int do_help = 0;
18652 #ifdef HAVE_XINPUT2
18653 struct xi_device_t *gen_help_device;
18654 Time gen_help_time UNINIT;
18655 #endif
18656 ptrdiff_t nbytes = 0;
18657 struct frame *any, *f = NULL, *mouse_frame;
18658 Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
18659
18660
18661
18662
18663 static XComposeStatus compose_status;
18664 XEvent configureEvent;
18665 XEvent next_event;
18666 Lisp_Object coding;
18667 #if defined USE_X_TOOLKIT && defined HAVE_XINPUT2
18668
18669
18670
18671 bool use_copy = false;
18672 XEvent copy;
18673 #elif defined USE_GTK && !defined HAVE_GTK3 && defined HAVE_XINPUT2
18674 GdkEvent *copy = NULL;
18675 GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display);
18676 #endif
18677 int dx, dy;
18678
18679
18680 #if defined HAVE_XINPUT2 || defined HAVE_XKB || defined HAVE_X_I18N
18681 USE_SAFE_ALLOCA;
18682 #endif
18683
18684
18685
18686
18687 if (!input_blocked_p ())
18688 emacs_abort ();
18689
18690 *finish = X_EVENT_NORMAL;
18691
18692 EVENT_INIT (inev.ie);
18693 inev.ie.kind = NO_EVENT;
18694 inev.ie.arg = Qnil;
18695 #ifdef HAVE_XINPUT2
18696 gen_help_device = NULL;
18697 #endif
18698
18699
18700
18701 if (event->type < LASTEvent)
18702 {
18703 #ifdef HAVE_XINPUT2
18704 if (event->type != GenericEvent)
18705 #endif
18706 any = x_any_window_to_frame (dpyinfo, event->xany.window);
18707 #ifdef HAVE_XINPUT2
18708 else
18709 any = NULL;
18710 #endif
18711 }
18712 else
18713 any = NULL;
18714
18715 if (any && any->wait_event_type == event->type)
18716 any->wait_event_type = 0;
18717
18718 switch (event->type)
18719 {
18720 case ClientMessage:
18721 {
18722 int rc;
18723
18724 if (((x_dnd_in_progress
18725 && FRAME_DISPLAY_INFO (x_dnd_frame) == dpyinfo)
18726 || (x_dnd_waiting_for_finish
18727 && FRAME_DISPLAY_INFO (x_dnd_finish_frame) == dpyinfo))
18728 && event->xclient.message_type == dpyinfo->Xatom_XdndStatus)
18729 {
18730 Window target;
18731 unsigned long r1, r2;
18732 int root_x, root_y;
18733 bool button;
18734
18735 target = event->xclient.data.l[0];
18736
18737 if (x_dnd_last_protocol_version != -1
18738 && x_dnd_in_progress
18739 && target == x_dnd_last_seen_toplevel
18740
18741
18742
18743
18744
18745 && !(event->xclient.data.l[1] & 2))
18746 {
18747 r1 = event->xclient.data.l[2];
18748 r2 = event->xclient.data.l[3];
18749
18750 x_dnd_mouse_rect_target = target;
18751 x_dnd_mouse_rect.x = (r1 & 0xffff0000) >> 16;
18752 x_dnd_mouse_rect.y = (r1 & 0xffff);
18753 x_dnd_mouse_rect.width = (r2 & 0xffff0000) >> 16;
18754 x_dnd_mouse_rect.height = (r2 & 0xffff);
18755 }
18756 else
18757 x_dnd_mouse_rect_target = None;
18758
18759 if (x_dnd_last_protocol_version != -1
18760 && (x_dnd_in_progress
18761 && target == x_dnd_last_seen_window))
18762 {
18763 if (event->xclient.data.l[1] & 1)
18764 {
18765 if (x_dnd_last_protocol_version >= 2)
18766 x_dnd_action = event->xclient.data.l[4];
18767 else
18768 x_dnd_action = dpyinfo->Xatom_XdndActionCopy;
18769 }
18770 else
18771 x_dnd_action = None;
18772 }
18773
18774
18775 if (x_dnd_waiting_for_status_window == target)
18776 {
18777 if (x_dnd_pending_send_position.type != 0)
18778 {
18779
18780
18781
18782
18783
18784 root_x = x_dnd_pending_send_position_root_x;
18785 root_y = x_dnd_pending_send_position_root_y;
18786 button = x_dnd_pending_send_position_button;
18787
18788 if (target == x_dnd_mouse_rect_target
18789 && x_dnd_mouse_rect.width
18790 && x_dnd_mouse_rect.height
18791
18792
18793
18794 && !button
18795 && (root_x >= x_dnd_mouse_rect.x
18796 && root_x < (x_dnd_mouse_rect.x
18797 + x_dnd_mouse_rect.width)
18798 && root_y >= x_dnd_mouse_rect.y
18799 && root_y < (x_dnd_mouse_rect.y
18800 + x_dnd_mouse_rect.height)))
18801 x_dnd_waiting_for_status_window = None;
18802 else
18803 {
18804 x_ignore_errors_for_next_request (dpyinfo, 0);
18805 XSendEvent (dpyinfo->display, target,
18806 False, NoEventMask,
18807 &x_dnd_pending_send_position);
18808 x_stop_ignoring_errors (dpyinfo);
18809 x_dnd_pending_send_position.type = 0;
18810
18811
18812
18813
18814
18815 }
18816 }
18817 else
18818 x_dnd_waiting_for_status_window = None;
18819
18820
18821 if (x_dnd_waiting_for_finish && x_dnd_need_send_drop
18822 && x_dnd_waiting_for_status_window == None)
18823 {
18824 if (event->xclient.data.l[1] & 1)
18825 {
18826 if (x_dnd_send_drop_proto >= 2)
18827 x_dnd_action = event->xclient.data.l[4];
18828 else
18829 x_dnd_action = dpyinfo->Xatom_XdndActionCopy;
18830 }
18831 else
18832 x_dnd_action = None;
18833
18834 x_dnd_waiting_for_finish
18835 = x_dnd_send_drop (x_dnd_finish_frame,
18836 target,
18837 x_dnd_last_seen_toplevel,
18838 x_dnd_selection_timestamp,
18839 x_dnd_send_drop_proto);
18840 }
18841 }
18842
18843 goto done;
18844 }
18845
18846 if (event->xclient.message_type == dpyinfo->Xatom_XdndFinished
18847 && (x_dnd_waiting_for_finish && !x_dnd_waiting_for_motif_finish)
18848
18849
18850
18851 && dpyinfo->display == x_dnd_finish_display
18852 && event->xclient.data.l[0] == x_dnd_pending_finish_target)
18853 {
18854 x_dnd_waiting_for_finish = false;
18855
18856 if (x_dnd_waiting_for_finish_proto >= 5)
18857 x_dnd_action = event->xclient.data.l[2];
18858
18859 if (x_dnd_waiting_for_finish_proto >= 5
18860 && !(event->xclient.data.l[1] & 1))
18861 x_dnd_action = None;
18862
18863 goto done;
18864 }
18865
18866 if ((event->xclient.message_type
18867 == dpyinfo->Xatom_MOTIF_DRAG_AND_DROP_MESSAGE)
18868 && x_dnd_waiting_for_finish
18869 && x_dnd_waiting_for_motif_finish == 1
18870 && dpyinfo == x_dnd_waiting_for_motif_finish_display)
18871 {
18872 xm_drop_start_reply reply;
18873 uint16_t operation, status, action;
18874
18875 if (!xm_read_drop_start_reply (event, &reply))
18876 {
18877 operation = XM_DRAG_SIDE_EFFECT_OPERATION (reply.side_effects);
18878 status = XM_DRAG_SIDE_EFFECT_SITE_STATUS (reply.side_effects);
18879 action = XM_DRAG_SIDE_EFFECT_DROP_ACTION (reply.side_effects);
18880
18881 if (operation != XM_DRAG_MOVE
18882 && operation != XM_DRAG_COPY
18883 && XM_DRAG_OPERATION_IS_LINK (operation))
18884 {
18885 x_dnd_waiting_for_finish = false;
18886 goto done;
18887 }
18888
18889 if (status != XM_DROP_SITE_VALID
18890 || (action == XM_DROP_ACTION_DROP_CANCEL
18891 || action == XM_DROP_ACTION_DROP_HELP))
18892 {
18893 x_dnd_waiting_for_finish = false;
18894 goto done;
18895 }
18896
18897 switch (operation)
18898 {
18899 case XM_DRAG_MOVE:
18900 x_dnd_action_symbol = QXdndActionMove;
18901 break;
18902
18903 case XM_DRAG_COPY:
18904 x_dnd_action_symbol = QXdndActionCopy;
18905 break;
18906
18907
18908 default:
18909 x_dnd_action_symbol = QXdndActionLink;
18910 break;
18911 }
18912
18913 x_dnd_waiting_for_motif_finish = 2;
18914 goto done;
18915 }
18916 }
18917
18918 if (event->xclient.message_type == dpyinfo->Xatom_EMACS_TMP
18919 && event->xclient.format == 8)
18920 {
18921
18922
18923
18924 if (any)
18925 FRAME_X_OUTPUT (any)->hourglass_p = event->xclient.data.b[0];
18926 }
18927
18928 if (event->xclient.message_type == dpyinfo->Xatom_wm_protocols
18929 && event->xclient.format == 32)
18930 {
18931 if (event->xclient.data.l[0] == dpyinfo->Xatom_wm_take_focus)
18932 {
18933
18934
18935
18936 f = any;
18937 #ifdef HAVE_X_I18N
18938
18939 if (f && FRAME_XIC (f))
18940 XSetICFocus (FRAME_XIC (f));
18941 #endif
18942 #if false
18943
18944
18945
18946
18947
18948
18949
18950
18951
18952
18953
18954
18955
18956
18957
18958
18959 if (f)
18960 {
18961 Display *d = event->xclient.display;
18962
18963
18964 x_catch_errors (d);
18965 XSetInputFocus (d, event->xclient.window,
18966
18967
18968 RevertToParent,
18969 event->xclient.data.l[1]);
18970 x_uncatch_errors ();
18971 }
18972
18973 #endif
18974
18975
18976
18977
18978
18979
18980
18981 x_display_set_last_user_time (dpyinfo, (event->xclient.data.l[1]
18982 & 0xffffffff),
18983 true, true);
18984 goto done;
18985 }
18986
18987 if (event->xclient.data.l[0] == dpyinfo->Xatom_wm_save_yourself)
18988 {
18989
18990
18991
18992
18993
18994
18995
18996
18997 #ifdef HAVE_X_SM
18998 if (! x_session_have_connection ())
18999 #endif
19000 {
19001 f = x_top_window_to_frame (dpyinfo,
19002 event->xclient.window);
19003
19004
19005 if (f == SELECTED_FRAME ())
19006 XSetCommand (FRAME_X_DISPLAY (f),
19007 event->xclient.window,
19008 initial_argv, initial_argc);
19009 else if (f)
19010 XSetCommand (FRAME_X_DISPLAY (f),
19011 event->xclient.window,
19012 0, 0);
19013 }
19014 goto done;
19015 }
19016
19017 if (event->xclient.data.l[0] == dpyinfo->Xatom_wm_delete_window)
19018 {
19019 f = x_top_window_to_frame (dpyinfo,
19020 event->xclient.window);
19021
19022 if (!f)
19023 goto OTHER;
19024
19025 inev.ie.kind = DELETE_WINDOW_EVENT;
19026 inev.ie.timestamp = event->xclient.data.l[1];
19027 XSETFRAME (inev.ie.frame_or_window, f);
19028 goto done;
19029 }
19030
19031
19032 if (event->xclient.data.l[0] == dpyinfo->Xatom_net_wm_ping
19033
19034
19035
19036
19037
19038
19039
19040 && (!(x_dnd_in_progress
19041 || x_dnd_waiting_for_finish)
19042 || event->xclient.window != dpyinfo->root_window)
19043 && event->xclient.format == 32)
19044 {
19045 XEvent send_event = *event;
19046
19047 send_event.xclient.window = dpyinfo->root_window;
19048 XSendEvent (dpyinfo->display, dpyinfo->root_window, False,
19049 SubstructureRedirectMask | SubstructureNotifyMask,
19050 &send_event);
19051
19052 *finish = X_EVENT_DROP;
19053 goto done;
19054 }
19055
19056 #if defined HAVE_XSYNC
19057 if (event->xclient.data.l[0] == dpyinfo->Xatom_net_wm_sync_request
19058 && event->xclient.format == 32
19059 && dpyinfo->xsync_supported_p)
19060 {
19061 struct frame *f
19062 = x_top_window_to_frame (dpyinfo,
19063 event->xclient.window);
19064 #if defined HAVE_GTK3
19065 GtkWidget *widget;
19066 GdkWindow *window;
19067 GdkFrameClock *frame_clock;
19068 #endif
19069
19070 if (f)
19071 {
19072 #ifndef HAVE_GTK3
19073 if (event->xclient.data.l[4] == 0)
19074 {
19075 XSyncIntsToValue (&FRAME_X_OUTPUT (f)->pending_basic_counter_value,
19076 event->xclient.data.l[2], event->xclient.data.l[3]);
19077 FRAME_X_OUTPUT (f)->sync_end_pending_p = true;
19078 }
19079 else if (event->xclient.data.l[4] == 1)
19080 {
19081 XSyncIntsToValue (&FRAME_X_OUTPUT (f)->resize_counter_value,
19082 event->xclient.data.l[2],
19083 event->xclient.data.l[3]);
19084
19085 FRAME_X_OUTPUT (f)->ext_sync_end_pending_p = true;
19086 }
19087
19088 *finish = X_EVENT_DROP;
19089 #else
19090 widget = FRAME_GTK_OUTER_WIDGET (f);
19091 window = gtk_widget_get_window (widget);
19092 eassert (window);
19093
19094
19095
19096
19097 gdk_x11_window_set_frame_sync_enabled (window, TRUE);
19098
19099 if (widget && !FRAME_X_OUTPUT (f)->xg_sync_end_pending_p)
19100 {
19101 frame_clock = gdk_window_get_frame_clock (window);
19102 eassert (frame_clock);
19103
19104 gdk_frame_clock_request_phase (frame_clock,
19105 GDK_FRAME_CLOCK_PHASE_BEFORE_PAINT);
19106 FRAME_X_OUTPUT (f)->xg_sync_end_pending_p = true;
19107 }
19108 #endif
19109 goto done;
19110 }
19111 }
19112 #endif
19113
19114 goto done;
19115 }
19116
19117 if (event->xclient.message_type == dpyinfo->Xatom_wm_configure_denied)
19118 goto done;
19119
19120 if (event->xclient.message_type == dpyinfo->Xatom_wm_window_moved)
19121 {
19122 int new_x, new_y;
19123 f = x_window_to_frame (dpyinfo, event->xclient.window);
19124
19125 new_x = event->xclient.data.s[0];
19126 new_y = event->xclient.data.s[1];
19127
19128 if (f)
19129 {
19130 f->left_pos = new_x;
19131 f->top_pos = new_y;
19132 }
19133 goto done;
19134 }
19135
19136 #ifdef X_TOOLKIT_EDITRES
19137 if (event->xclient.message_type == dpyinfo->Xatom_editres)
19138 {
19139 f = any;
19140 if (f)
19141 {
19142 _XEditResCheckMessages (f->output_data.x->widget,
19143 NULL, (XEvent *) event, NULL);
19144 goto done;
19145 }
19146
19147 goto OTHER;
19148 }
19149 #endif
19150
19151 if (event->xclient.message_type == dpyinfo->Xatom_DONE
19152 || event->xclient.message_type == dpyinfo->Xatom_PAGE)
19153 {
19154
19155
19156
19157
19158 f = x_window_to_frame (dpyinfo, event->xclient.window);
19159 if (!f)
19160 goto OTHER;
19161 #ifndef USE_CAIRO
19162 Pixmap pixmap = (Pixmap) event->xclient.data.l[1];
19163
19164
19165 x_catch_errors (dpyinfo->display);
19166 x_kill_gs_process (pixmap, f);
19167 x_uncatch_errors ();
19168 expose_frame (f, 0, 0, 0, 0);
19169 #endif
19170 goto done;
19171 }
19172
19173 #ifdef USE_TOOLKIT_SCROLL_BARS
19174
19175
19176 if (event->xclient.message_type == dpyinfo->Xatom_Scrollbar)
19177 {
19178
19179
19180
19181 x_scroll_bar_to_input_event (dpyinfo, event, &inev.ie);
19182
19183 *finish = X_EVENT_GOTO_OUT;
19184 goto done;
19185 }
19186 else if (event->xclient.message_type == dpyinfo->Xatom_Horizontal_Scrollbar)
19187 {
19188
19189
19190
19191 x_horizontal_scroll_bar_to_input_event (dpyinfo, event,
19192 &inev.ie);
19193
19194 *finish = X_EVENT_GOTO_OUT;
19195 goto done;
19196 }
19197 #endif
19198
19199
19200 if (event->xclient.message_type == dpyinfo->Xatom_XEMBED)
19201 {
19202 enum xembed_message msg = event->xclient.data.l[1];
19203 if (msg == XEMBED_FOCUS_IN || msg == XEMBED_FOCUS_OUT)
19204 x_detect_focus_change (dpyinfo, any, event, &inev.ie);
19205
19206 *finish = X_EVENT_GOTO_OUT;
19207 goto done;
19208 }
19209
19210 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
19211
19212
19213 if (event->xclient.message_type
19214 == dpyinfo->Xatom_net_wm_frame_drawn)
19215 {
19216 if (any)
19217 x_sync_handle_frame_drawn (dpyinfo, (XEvent *) event, any);
19218
19219 goto done;
19220 }
19221
19222 if (event->xclient.message_type
19223 == dpyinfo->Xatom_net_wm_frame_timings)
19224 goto done;
19225 #endif
19226
19227 if (xft_settings_event (dpyinfo, event))
19228 goto done;
19229
19230 f = any;
19231
19232 if (!f || FRAME_TOOLTIP_P (f))
19233 goto OTHER;
19234
19235
19236
19237 dx = 0;
19238 dy = 0;
19239
19240 rc = x_coords_from_dnd_message (dpyinfo, (XEvent *) event,
19241 &dx, &dy);
19242
19243 if (x_handle_dnd_message (f, &event->xclient, dpyinfo, &inev.ie,
19244 rc, dx, dy))
19245 *finish = X_EVENT_DROP;
19246 }
19247 break;
19248
19249 case SelectionNotify:
19250 #if defined USE_X_TOOLKIT || defined USE_GTK
19251 if (!x_window_to_frame (dpyinfo, event->xselection.requestor))
19252 goto OTHER;
19253 #endif
19254 #ifdef HAVE_GTK3
19255
19256
19257
19258 *finish = X_EVENT_DROP;
19259 #endif
19260 x_handle_selection_notify (&event->xselection);
19261 break;
19262
19263 case SelectionClear:
19264 #if defined USE_X_TOOLKIT || defined USE_GTK
19265 if (!x_window_to_frame (dpyinfo, event->xselectionclear.window))
19266 goto OTHER;
19267 #endif
19268 #ifdef HAVE_GTK3
19269 *finish = X_EVENT_DROP;
19270 #endif
19271 {
19272 const XSelectionClearEvent *eventp = &event->xselectionclear;
19273
19274 if (eventp->selection == dpyinfo->motif_drag_atom
19275 && (eventp->time == CurrentTime
19276 || dpyinfo->motif_drag_atom_time <= eventp->time))
19277 dpyinfo->motif_drag_atom = None;
19278
19279 inev.sie.kind = SELECTION_CLEAR_EVENT;
19280 SELECTION_EVENT_DPYINFO (&inev.sie) = dpyinfo;
19281 SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
19282 SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
19283
19284 if (x_use_pending_selection_requests)
19285 {
19286 x_push_selection_request (&inev.sie);
19287 EVENT_INIT (inev.ie);
19288 }
19289 }
19290 break;
19291
19292 case SelectionRequest:
19293 #ifdef USE_X_TOOLKIT
19294 if (!x_window_to_frame (dpyinfo, event->xselectionrequest.owner))
19295 goto OTHER;
19296 #endif
19297 #ifdef HAVE_GTK3
19298 *finish = X_EVENT_DROP;
19299 #endif
19300 {
19301 const XSelectionRequestEvent *eventp = &event->xselectionrequest;
19302
19303 inev.sie.kind = SELECTION_REQUEST_EVENT;
19304 SELECTION_EVENT_DPYINFO (&inev.sie) = dpyinfo;
19305 SELECTION_EVENT_REQUESTOR (&inev.sie) = eventp->requestor;
19306 SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
19307 SELECTION_EVENT_TARGET (&inev.sie) = eventp->target;
19308 SELECTION_EVENT_PROPERTY (&inev.sie) = eventp->property;
19309 SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
19310
19311
19312
19313
19314
19315 if (x_use_pending_selection_requests)
19316 {
19317 x_push_selection_request (&inev.sie);
19318 EVENT_INIT (inev.ie);
19319 }
19320
19321 if (x_dnd_waiting_for_finish
19322 && x_dnd_waiting_for_motif_finish == 2
19323 && dpyinfo == x_dnd_waiting_for_motif_finish_display
19324 && eventp->selection == x_dnd_motif_atom
19325 && (eventp->target == dpyinfo->Xatom_XmTRANSFER_SUCCESS
19326 || eventp->target == dpyinfo->Xatom_XmTRANSFER_FAILURE))
19327 {
19328 x_dnd_waiting_for_finish = false;
19329
19330
19331
19332 if (eventp->target == dpyinfo->Xatom_XmTRANSFER_FAILURE)
19333 x_dnd_action = None;
19334 }
19335 }
19336 break;
19337
19338 case PropertyNotify:
19339 if (x_dnd_in_progress && x_dnd_use_toplevels
19340 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame)
19341 && event->xproperty.atom == dpyinfo->Xatom_wm_state)
19342 {
19343 struct x_client_list_window *tem, *last;
19344
19345 for (last = NULL, tem = x_dnd_toplevels; tem;
19346 last = tem, tem = tem->next)
19347 {
19348 if (tem->window == event->xproperty.window)
19349 {
19350 Atom actual_type;
19351 int actual_format, rc;
19352 unsigned long nitems, bytesafter;
19353 unsigned char *data = NULL;
19354
19355 if (event->xproperty.state == PropertyDelete)
19356 {
19357 if (!last)
19358 x_dnd_toplevels = tem->next;
19359 else
19360 last->next = tem->next;
19361
19362 #ifdef HAVE_XSHAPE
19363 if (tem->n_input_rects != -1)
19364 xfree (tem->input_rects);
19365 if (tem->n_bounding_rects != -1)
19366 xfree (tem->bounding_rects);
19367 #endif
19368 xfree (tem);
19369 }
19370 else
19371 {
19372 x_catch_errors (dpyinfo->display);
19373 rc = XGetWindowProperty (dpyinfo->display,
19374 event->xproperty.window,
19375 dpyinfo->Xatom_wm_state,
19376 0, 2, False, AnyPropertyType,
19377 &actual_type, &actual_format,
19378 &nitems, &bytesafter, &data);
19379
19380 if (!x_had_errors_p (dpyinfo->display) && rc == Success && data
19381 && nitems == 2 && actual_format == 32)
19382 tem->wm_state = ((unsigned long *) data)[0];
19383 else
19384 tem->wm_state = WithdrawnState;
19385
19386 if (data)
19387 XFree (data);
19388 x_uncatch_errors_after_check ();
19389 }
19390
19391 x_dnd_update_state (dpyinfo, event->xproperty.time);
19392 break;
19393 }
19394 }
19395 }
19396
19397 f = x_top_window_to_frame (dpyinfo, event->xproperty.window);
19398 if (f && event->xproperty.atom == dpyinfo->Xatom_net_wm_state
19399
19400 && !FRAME_X_EMBEDDED_P (f))
19401 {
19402 bool not_hidden = x_handle_net_wm_state (f, &event->xproperty);
19403
19404 if (not_hidden && FRAME_ICONIFIED_P (f))
19405 {
19406 if (CONSP (frame_size_history))
19407 frame_size_history_plain
19408 (f, build_string ("PropertyNotify, not hidden & iconified"));
19409
19410
19411
19412
19413 SET_FRAME_VISIBLE (f, 1);
19414 SET_FRAME_ICONIFIED (f, false);
19415
19416 f->output_data.x->has_been_visible = true;
19417 inev.ie.kind = DEICONIFY_EVENT;
19418 #if defined USE_GTK && defined HAVE_GTK3
19419
19420
19421 if (f->was_invisible)
19422 {
19423 xg_frame_set_char_size
19424 (f, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f));
19425 f->was_invisible = false;
19426 }
19427 #endif
19428 XSETFRAME (inev.ie.frame_or_window, f);
19429 }
19430 else if (!not_hidden && !FRAME_ICONIFIED_P (f))
19431 {
19432 if (CONSP (frame_size_history))
19433 frame_size_history_plain
19434 (f, build_string ("PropertyNotify, hidden & not iconified"));
19435
19436 SET_FRAME_VISIBLE (f, 0);
19437 SET_FRAME_ICONIFIED (f, true);
19438 inev.ie.kind = ICONIFY_EVENT;
19439 XSETFRAME (inev.ie.frame_or_window, f);
19440 }
19441 }
19442
19443 if (f && event->xproperty.atom == dpyinfo->Xatom_wm_state
19444 && !FRAME_X_EMBEDDED_P (f) && !FRAME_PARENT_FRAME (f))
19445
19446
19447
19448
19449
19450
19451
19452
19453
19454 x_handle_wm_state (f, &inev.ie);
19455
19456 if (f && FRAME_X_OUTPUT (f)->alpha_identical_p
19457 && (event->xproperty.atom
19458 == dpyinfo->Xatom_net_wm_window_opacity))
19459 {
19460 #ifndef USE_XCB
19461 int rc, actual_format;
19462 Atom actual;
19463 unsigned char *tmp_data;
19464 unsigned long n, left, opacity;
19465
19466 tmp_data = NULL;
19467 #else
19468 xcb_get_property_cookie_t opacity_cookie;
19469 xcb_get_property_reply_t *opacity_reply;
19470 xcb_generic_error_t *error;
19471 bool rc;
19472 uint32_t value;
19473 #endif
19474
19475 if (event->xproperty.state == PropertyDelete)
19476 {
19477 f->alpha[0] = 1.0;
19478 f->alpha[1] = 1.0;
19479
19480 store_frame_param (f, Qalpha, Qnil);
19481 }
19482 else
19483 {
19484 #ifndef USE_XCB
19485 rc = XGetWindowProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
19486 dpyinfo->Xatom_net_wm_window_opacity,
19487 0, 1, False, AnyPropertyType, &actual,
19488 &actual_format, &n, &left, &tmp_data);
19489
19490 if (rc == Success && actual_format == 32
19491 && (actual == XA_CARDINAL
19492
19493
19494
19495 || actual == XA_ATOM
19496 || actual == XA_WINDOW) && n)
19497 {
19498 opacity = *(unsigned long *) tmp_data & OPAQUE;
19499 f->alpha[0] = (double) opacity / (double) OPAQUE;
19500 f->alpha[1] = (double) opacity / (double) OPAQUE;
19501
19502 store_frame_param (f, Qalpha, make_float (f->alpha[0]));
19503 }
19504 else
19505 {
19506 f->alpha[0] = 1.0;
19507 f->alpha[1] = 1.0;
19508
19509 store_frame_param (f, Qalpha, Qnil);
19510 }
19511 #else
19512 opacity_cookie
19513 = xcb_get_property (dpyinfo->xcb_connection, 0,
19514 (xcb_window_t) FRAME_OUTER_WINDOW (f),
19515 (xcb_atom_t) dpyinfo->Xatom_net_wm_window_opacity,
19516 XA_CARDINAL, 0, 1);
19517 opacity_reply
19518 = xcb_get_property_reply (dpyinfo->xcb_connection,
19519 opacity_cookie, &error);
19520
19521 if (!opacity_reply)
19522 free (error), rc = false;
19523 else
19524 rc = (opacity_reply->format == 32
19525 && (opacity_reply->type == XA_CARDINAL
19526 || opacity_reply->type == XA_ATOM
19527 || opacity_reply->type == XA_WINDOW)
19528 && (xcb_get_property_value_length (opacity_reply) >= 4));
19529
19530 if (rc)
19531 {
19532 value = *(uint32_t *) xcb_get_property_value (opacity_reply);
19533
19534 f->alpha[0] = (double) value / (double) OPAQUE;
19535 f->alpha[1] = (double) value / (double) OPAQUE;
19536 store_frame_param (f, Qalpha, make_float (f->alpha[0]));
19537 }
19538 else
19539 {
19540 f->alpha[0] = 1.0;
19541 f->alpha[1] = 1.0;
19542
19543 store_frame_param (f, Qalpha, Qnil);
19544 }
19545
19546 if (opacity_reply)
19547 free (opacity_reply);
19548 #endif
19549 }
19550
19551 #ifndef USE_XCB
19552 if (tmp_data)
19553 XFree (tmp_data);
19554 #endif
19555 }
19556
19557 if (event->xproperty.window == dpyinfo->root_window
19558 && (event->xproperty.atom == dpyinfo->Xatom_net_client_list_stacking
19559 || event->xproperty.atom == dpyinfo->Xatom_net_current_desktop)
19560 && x_dnd_in_progress
19561 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
19562 {
19563 if (x_dnd_use_toplevels)
19564 {
19565 x_dnd_free_toplevels (true);
19566
19567 if (x_dnd_compute_toplevels (dpyinfo))
19568 {
19569 x_dnd_free_toplevels (true);
19570 x_dnd_use_toplevels = false;
19571 }
19572 }
19573
19574 x_dnd_update_state (dpyinfo, event->xproperty.time);
19575 }
19576
19577 x_handle_property_notify (&event->xproperty);
19578 xft_settings_event (dpyinfo, event);
19579 goto OTHER;
19580
19581 case ReparentNotify:
19582 f = x_top_window_to_frame (dpyinfo, event->xreparent.window);
19583 if (f)
19584 {
19585 #ifndef USE_GTK
19586 if (FRAME_OUTPUT_DATA (f)->parent_desc
19587 && FRAME_X_EMBEDDED_P (f))
19588 {
19589
19590
19591
19592
19593
19594 FRAME_X_OUTPUT (f)->explicit_parent = false;
19595
19596
19597 XDeleteProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
19598 dpyinfo->Xatom_XEMBED_INFO);
19599 x_make_frame_visible (f);
19600 }
19601 #endif
19602
19603
19604 f->output_data.x->parent_desc = event->xreparent.parent;
19605
19606 if (!FRAME_PARENT_FRAME (f))
19607 {
19608 x_real_positions (f, &f->left_pos, &f->top_pos);
19609
19610
19611 dpyinfo->wm_type = X_WMTYPE_UNKNOWN;
19612 dpyinfo->net_supported_window = 0;
19613
19614 #ifndef USE_GTK
19615
19616
19617
19618
19619
19620
19621 if (FRAME_X_OUTPUT (f)->has_been_visible)
19622 x_update_frame_user_time_window (f);
19623 #endif
19624 }
19625 else
19626 {
19627 Window root;
19628 unsigned int dummy_uint;
19629
19630 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
19631 &root, &f->left_pos, &f->top_pos,
19632 &dummy_uint, &dummy_uint, &dummy_uint, &dummy_uint);
19633 }
19634
19635 x_set_frame_alpha (f);
19636 }
19637 goto OTHER;
19638
19639 case Expose:
19640
19641 #ifdef HAVE_XWIDGETS
19642 {
19643 struct xwidget_view *xv;
19644
19645 xv = xwidget_view_from_window (event->xexpose.window);
19646
19647 if (xv)
19648 {
19649 xwidget_expose (xv);
19650 goto OTHER;
19651 }
19652 }
19653 #endif
19654
19655 f = x_window_to_frame (dpyinfo, event->xexpose.window);
19656 if (f)
19657 {
19658 if (!FRAME_VISIBLE_P (f))
19659 {
19660
19661
19662
19663
19664
19665 if (EQ (x_set_frame_visibility_more_laxly, Qexpose)
19666 || EQ (x_set_frame_visibility_more_laxly, Qt))
19667 {
19668 SET_FRAME_VISIBLE (f, 1);
19669 SET_FRAME_ICONIFIED (f, false);
19670 }
19671
19672 #ifdef HAVE_XDBE
19673 if (FRAME_X_DOUBLE_BUFFERED_P (f))
19674 x_drop_xrender_surfaces (f);
19675 #endif
19676 f->output_data.x->has_been_visible = true;
19677 SET_FRAME_GARBAGED (f);
19678 }
19679 else if (FRAME_GARBAGED_P (f))
19680 {
19681 #ifdef USE_GTK
19682
19683
19684
19685
19686
19687
19688 x_clear_area1 (FRAME_X_DISPLAY (f),
19689 FRAME_X_WINDOW (f),
19690 event->xexpose.x, event->xexpose.y,
19691 event->xexpose.width, event->xexpose.height,
19692 0);
19693 x_clear_under_internal_border (f);
19694 #endif
19695 }
19696
19697 if (!FRAME_GARBAGED_P (f))
19698 {
19699 #if defined USE_X_TOOLKIT && defined USE_TOOLKIT_SCROLL_BARS
19700 if (f->output_data.x->edit_widget)
19701
19702
19703 goto OTHER;
19704 #endif
19705 #ifdef USE_GTK
19706
19707
19708 x_clear_area (f,
19709 event->xexpose.x, event->xexpose.y,
19710 event->xexpose.width, event->xexpose.height);
19711 #endif
19712 expose_frame (f, event->xexpose.x, event->xexpose.y,
19713 event->xexpose.width, event->xexpose.height);
19714 #ifndef USE_TOOLKIT_SCROLL_BARS
19715 x_scroll_bar_handle_exposure (f, (XEvent *) event);
19716 #endif
19717 #ifdef USE_GTK
19718 x_clear_under_internal_border (f);
19719 #endif
19720 }
19721 #ifndef USE_TOOLKIT_SCROLL_BARS
19722 else
19723 x_scroll_bar_handle_exposure (f, (XEvent *) event);
19724 #endif
19725
19726 #ifdef HAVE_XDBE
19727 if (!FRAME_GARBAGED_P (f))
19728 show_back_buffer (f);
19729 #endif
19730 }
19731 else
19732 {
19733 #if defined USE_LUCID
19734
19735
19736
19737 {
19738 Widget widget = x_window_to_menu_bar (event->xexpose.window);
19739 if (widget)
19740 xlwmenu_redisplay (widget);
19741 }
19742 #endif
19743
19744
19745 goto OTHER;
19746 }
19747 break;
19748
19749 case GraphicsExpose:
19750
19751
19752 f = x_window_to_frame (dpyinfo, event->xgraphicsexpose.drawable);
19753 if (f)
19754 {
19755 expose_frame (f, event->xgraphicsexpose.x,
19756 event->xgraphicsexpose.y,
19757 event->xgraphicsexpose.width,
19758 event->xgraphicsexpose.height);
19759 #ifndef USE_TOOLKIT_SCROLL_BARS
19760 x_scroll_bar_handle_exposure (f, (XEvent *) event);
19761 #endif
19762 #ifdef USE_GTK
19763 x_clear_under_internal_border (f);
19764 #endif
19765 #ifdef HAVE_XDBE
19766 show_back_buffer (f);
19767 #endif
19768 }
19769 #ifdef USE_X_TOOLKIT
19770 else
19771 goto OTHER;
19772 #endif
19773 break;
19774
19775 case NoExpose:
19776
19777
19778 #ifdef USE_X_TOOLKIT
19779 *finish = X_EVENT_DROP;
19780 #endif
19781 break;
19782
19783 case UnmapNotify:
19784 if (x_dnd_in_progress && x_dnd_use_toplevels
19785 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
19786 {
19787 for (struct x_client_list_window *tem = x_dnd_toplevels; tem;
19788 tem = tem->next)
19789 {
19790 if (tem->window == event->xunmap.window)
19791 {
19792 tem->mapped_p = false;
19793 break;
19794 }
19795 }
19796 }
19797
19798
19799 if (event->xunmap.window == tip_window)
19800 {
19801 tip_window = None;
19802 gui_redo_mouse_highlight (dpyinfo);
19803 }
19804
19805 f = x_top_window_to_frame (dpyinfo, event->xunmap.window);
19806 if (f)
19807
19808 {
19809 bool visible = FRAME_VISIBLE_P (f);
19810
19811 #ifdef USE_LUCID
19812
19813
19814
19815 if (FRAME_TOOLTIP_P (f) && popup_activated ())
19816 {
19817 Widget w;
19818 Lisp_Object tail, frame;
19819 struct frame *f1;
19820
19821 FOR_EACH_FRAME (tail, frame)
19822 {
19823 if (!FRAME_X_P (XFRAME (frame)))
19824 continue;
19825
19826 f1 = XFRAME (frame);
19827
19828 if (FRAME_LIVE_P (f1))
19829 {
19830 w = FRAME_X_OUTPUT (f1)->menubar_widget;
19831
19832 if (w && !DoesSaveUnders (FRAME_DISPLAY_INFO (f1)->screen))
19833 xlwmenu_redisplay (w);
19834 }
19835 }
19836 }
19837 #endif
19838
19839
19840
19841
19842 SET_FRAME_VISIBLE (f, 0);
19843
19844
19845
19846
19847
19848
19849 if (visible || FRAME_ICONIFIED_P (f))
19850 {
19851 if (CONSP (frame_size_history))
19852 frame_size_history_plain
19853 (f, build_string ("UnmapNotify, visible | iconified"));
19854
19855 SET_FRAME_ICONIFIED (f, true);
19856 inev.ie.kind = ICONIFY_EVENT;
19857 XSETFRAME (inev.ie.frame_or_window, f);
19858 }
19859 else if (CONSP (frame_size_history))
19860 frame_size_history_plain
19861 (f, build_string ("UnmapNotify, not visible & not iconified"));
19862 }
19863 goto OTHER;
19864
19865 case MapNotify:
19866 #if defined HAVE_XINPUT2 && defined HAVE_GTK3
19867 if (xg_is_menu_window (dpyinfo->display, event->xmap.window))
19868 popup_activated_flag = 1;
19869 #endif
19870
19871 if (x_dnd_in_progress
19872
19873
19874
19875
19876 && !x_dnd_use_toplevels
19877 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
19878 x_dnd_update_state (dpyinfo, dpyinfo->last_user_time);
19879
19880 if (x_dnd_in_progress && x_dnd_use_toplevels
19881 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
19882 {
19883 for (struct x_client_list_window *tem = x_dnd_toplevels; tem;
19884 tem = tem->next)
19885 {
19886 if (tem->window == event->xmap.window)
19887 {
19888 tem->mapped_p = true;
19889 break;
19890 }
19891 }
19892 }
19893
19894
19895
19896
19897 f = x_top_window_to_frame (dpyinfo, event->xmap.window);
19898 if (f)
19899 {
19900 bool iconified = FRAME_ICONIFIED_P (f);
19901 int value;
19902 bool sticky, shaded;
19903 bool not_hidden = x_get_current_wm_state (f, event->xmap.window, &value, &sticky,
19904 &shaded);
19905
19906 if (CONSP (frame_size_history))
19907 frame_size_history_extra
19908 (f,
19909 iconified
19910 ? (not_hidden
19911 ? build_string ("MapNotify, not hidden & iconified")
19912 : build_string ("MapNotify, hidden & iconified"))
19913 : (not_hidden
19914 ? build_string ("MapNotify, not hidden & not iconified")
19915 : build_string ("MapNotify, hidden & not iconified")),
19916 FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f),
19917 -1, -1, f->new_width, f->new_height);
19918
19919
19920
19921 if (!f->output_data.x->has_been_visible)
19922 {
19923
19924 x_check_fullscreen (f);
19925 #ifndef USE_GTK
19926
19927
19928 if (FRAME_SKIP_TASKBAR (f))
19929 x_set_skip_taskbar (f, Qt, Qnil);
19930 #endif
19931 }
19932
19933 if (!iconified)
19934 {
19935
19936
19937 if (FRAME_Z_GROUP (f) == z_group_above)
19938 x_set_z_group (f, Qabove, Qnil);
19939 else if (FRAME_Z_GROUP (f) == z_group_below)
19940 x_set_z_group (f, Qbelow, Qnil);
19941 }
19942
19943
19944
19945 if (not_hidden || FRAME_X_EMBEDDED_P (f))
19946 {
19947 SET_FRAME_VISIBLE (f, 1);
19948 SET_FRAME_ICONIFIED (f, false);
19949 #if defined USE_GTK && defined HAVE_GTK3
19950
19951
19952 if (f->was_invisible)
19953 {
19954 xg_frame_set_char_size
19955 (f, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f));
19956 f->was_invisible = false;
19957 }
19958 #endif
19959 f->output_data.x->has_been_visible = true;
19960 }
19961
19962 x_update_opaque_region (f, NULL);
19963
19964 if ((not_hidden || FRAME_X_EMBEDDED_P (f)) && iconified)
19965 {
19966 inev.ie.kind = DEICONIFY_EVENT;
19967 XSETFRAME (inev.ie.frame_or_window, f);
19968 }
19969 }
19970 goto OTHER;
19971
19972 case KeyPress:
19973 x_display_set_last_user_time (dpyinfo, event->xkey.time,
19974 event->xkey.send_event,
19975 true);
19976 ignore_next_mouse_click_timeout = 0;
19977
19978 coding = Qlatin_1;
19979
19980 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
19981
19982 if (popup_activated ())
19983 goto OTHER;
19984 #endif
19985
19986 f = any;
19987
19988 #ifdef USE_GTK
19989 if (f)
19990 x_set_gtk_user_time (f, event->xkey.time);
19991 #endif
19992
19993
19994
19995 if (!hlinfo->mouse_face_hidden && FIXNUMP (Vmouse_highlight)
19996 && (f == 0
19997 #if ! defined (USE_GTK)
19998 || !EQ (f->tool_bar_window, hlinfo->mouse_face_window)
19999 #endif
20000 || !EQ (f->tab_bar_window, hlinfo->mouse_face_window))
20001 )
20002 {
20003 mouse_frame = hlinfo->mouse_face_mouse_frame;
20004
20005 clear_mouse_face (hlinfo);
20006 hlinfo->mouse_face_hidden = true;
20007
20008 if (mouse_frame)
20009 x_flush_dirty_back_buffer_on (mouse_frame);
20010 }
20011
20012 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
20013 if (f == 0)
20014 {
20015
20016
20017 Widget widget = XtWindowToWidget (dpyinfo->display,
20018 event->xkey.window);
20019 if (widget && XmIsScrollBar (widget))
20020 {
20021 widget = XtParent (widget);
20022 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
20023 }
20024 }
20025 #endif
20026
20027 if (f != 0)
20028 {
20029 KeySym keysym, orig_keysym;
20030
20031
20032
20033
20034
20035
20036
20037
20038
20039
20040
20041 unsigned char copy_buffer[513];
20042 unsigned char *copy_bufptr = copy_buffer;
20043 int copy_bufsiz = sizeof (copy_buffer);
20044 int modifiers;
20045 Lisp_Object c;
20046
20047
20048 XKeyEvent xkey = event->xkey;
20049
20050 if (event->xkey.window == FRAME_X_WINDOW (f))
20051
20052
20053 x_compute_root_window_offset (f, event->xkey.x_root,
20054 event->xkey.y_root,
20055 event->xkey.x, event->xkey.y);
20056
20057 #ifdef HAVE_XINPUT2
20058 Time pending_keystroke_time;
20059 struct xi_device_t *source;
20060
20061 pending_keystroke_time = dpyinfo->pending_keystroke_time;
20062
20063 if (event->xkey.time >= pending_keystroke_time)
20064 {
20065 #if defined USE_GTK && !defined HAVE_GTK3
20066 if (!dpyinfo->pending_keystroke_time_special_p)
20067 #endif
20068 dpyinfo->pending_keystroke_time = 0;
20069 #if defined USE_GTK && !defined HAVE_GTK3
20070 else
20071 dpyinfo->pending_keystroke_time_special_p = false;
20072 #endif
20073 }
20074 #endif
20075
20076 #ifdef USE_GTK
20077
20078
20079
20080
20081 *finish = X_EVENT_DROP;
20082 #endif
20083
20084 xkey.state |= x_emacs_to_x_modifiers (dpyinfo,
20085 extra_keyboard_modifiers);
20086 modifiers = xkey.state;
20087
20088
20089
20090
20091
20092 xkey.state &= ~ControlMask;
20093 xkey.state &= ~(dpyinfo->meta_mod_mask
20094 | dpyinfo->super_mod_mask
20095 | dpyinfo->hyper_mod_mask
20096 | dpyinfo->alt_mod_mask);
20097
20098
20099
20100
20101
20102
20103 if (modifiers & dpyinfo->meta_mod_mask)
20104 memset (&compose_status, 0, sizeof (compose_status));
20105
20106 #ifdef HAVE_X_I18N
20107 if (FRAME_XIC (f))
20108 {
20109 Status status_return;
20110
20111 nbytes = XmbLookupString (FRAME_XIC (f),
20112 &xkey, (char *) copy_bufptr,
20113 copy_bufsiz, &keysym,
20114 &status_return);
20115 coding = FRAME_X_XIM_CODING (f);
20116 if (status_return == XBufferOverflow)
20117 {
20118 copy_bufsiz = nbytes + 1;
20119 copy_bufptr = SAFE_ALLOCA (copy_bufsiz);
20120 nbytes = XmbLookupString (FRAME_XIC (f),
20121 &xkey, (char *) copy_bufptr,
20122 copy_bufsiz, &keysym,
20123 &status_return);
20124 }
20125
20126 if (status_return == XLookupNone)
20127 break;
20128 else if (status_return == XLookupChars)
20129 {
20130 keysym = NoSymbol;
20131 modifiers = 0;
20132 }
20133 else if (status_return != XLookupKeySym
20134 && status_return != XLookupBoth)
20135 emacs_abort ();
20136 }
20137 else
20138 #endif
20139 {
20140 #ifdef HAVE_XKB
20141 int overflow;
20142 unsigned int consumed;
20143
20144 if (dpyinfo->xkb_desc)
20145 {
20146 if (!XkbTranslateKeyCode (dpyinfo->xkb_desc,
20147 xkey.keycode, xkey.state,
20148 &consumed, &keysym))
20149 goto done_keysym;
20150
20151 overflow = 0;
20152
20153 nbytes = XkbTranslateKeySym (dpyinfo->display, &keysym,
20154 xkey.state & ~consumed,
20155 (char *) copy_bufptr,
20156 copy_bufsiz, &overflow);
20157
20158 if (overflow)
20159 {
20160 copy_bufptr = SAFE_ALLOCA ((copy_bufsiz += overflow)
20161 * sizeof *copy_bufptr);
20162 overflow = 0;
20163 nbytes = XkbTranslateKeySym (dpyinfo->display, &keysym,
20164 xkey.state & ~consumed,
20165 (char *) copy_bufptr,
20166 copy_bufsiz, &overflow);
20167
20168 if (overflow)
20169 nbytes = 0;
20170 }
20171
20172 if (nbytes)
20173 coding = Qnil;
20174 }
20175 else
20176 #endif
20177 nbytes = XLookupString (&xkey, (char *) copy_bufptr,
20178 copy_bufsiz, &keysym,
20179 &compose_status);
20180 }
20181
20182 #ifdef XK_F1
20183 if (x_dnd_in_progress && keysym == XK_F1)
20184 {
20185 x_dnd_xm_use_help = true;
20186 goto done_keysym;
20187 }
20188 #endif
20189
20190
20191
20192 if (keysym == dpyinfo->quit_keysym
20193 && (xkey.time - dpyinfo->quit_keysym_time
20194 <= 350))
20195 {
20196 Vquit_flag = Qt;
20197 goto done_keysym;
20198 }
20199
20200 if (keysym == dpyinfo->quit_keysym)
20201 {
20202
20203
20204 dpyinfo->quit_keysym_time = xkey.time;
20205 goto done_keysym;
20206 }
20207
20208
20209
20210 if (compose_status.chars_matched > 0 && nbytes == 0)
20211 break;
20212
20213 memset (&compose_status, 0, sizeof (compose_status));
20214 orig_keysym = keysym;
20215
20216
20217 XSETFRAME (inev.ie.frame_or_window, f);
20218 inev.ie.modifiers
20219 = x_x_to_emacs_modifiers (dpyinfo, modifiers);
20220 inev.ie.timestamp = xkey.time;
20221
20222
20223
20224 if (keysym >= 32 && keysym < 128)
20225
20226 {
20227 inev.ie.kind = ASCII_KEYSTROKE_EVENT;
20228 inev.ie.code = keysym;
20229
20230 #ifdef HAVE_XINPUT2
20231 if (event->xkey.time == pending_keystroke_time)
20232 {
20233 source = xi_device_from_id (dpyinfo,
20234 dpyinfo->pending_keystroke_source);
20235
20236 if (source)
20237 inev.ie.device = source->name;
20238 }
20239 #endif
20240
20241 goto done_keysym;
20242 }
20243
20244
20245 if (keysym >= 0x01000000 && keysym <= 0x0110FFFF)
20246 {
20247 if (keysym < 0x01000080)
20248 inev.ie.kind = ASCII_KEYSTROKE_EVENT;
20249 else
20250 inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
20251 inev.ie.code = keysym & 0xFFFFFF;
20252
20253 #ifdef HAVE_XINPUT2
20254 if (event->xkey.time == pending_keystroke_time)
20255 {
20256 source = xi_device_from_id (dpyinfo,
20257 dpyinfo->pending_keystroke_source);
20258
20259 if (source)
20260 inev.ie.device = source->name;
20261 }
20262 #endif
20263
20264 goto done_keysym;
20265 }
20266
20267
20268 if (HASH_TABLE_P (Vx_keysym_table)
20269 && (c = Fgethash (make_fixnum (keysym),
20270 Vx_keysym_table,
20271 Qnil),
20272 FIXNATP (c)))
20273 {
20274 inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFIXNAT (c))
20275 ? ASCII_KEYSTROKE_EVENT
20276 : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
20277 inev.ie.code = XFIXNAT (c);
20278
20279 #ifdef HAVE_XINPUT2
20280 if (event->xkey.time == pending_keystroke_time)
20281 {
20282 source = xi_device_from_id (dpyinfo,
20283 dpyinfo->pending_keystroke_source);
20284
20285 if (source)
20286 inev.ie.device = source->name;
20287 }
20288 #endif
20289
20290 goto done_keysym;
20291 }
20292
20293
20294 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
20295 || keysym == XK_Delete
20296 #ifdef XK_ISO_Left_Tab
20297 || (keysym >= XK_ISO_Left_Tab
20298 && keysym <= XK_ISO_Enter)
20299 #endif
20300 || IsCursorKey (keysym)
20301 || IsMiscFunctionKey (keysym)
20302 #ifdef HPUX
20303
20304
20305
20306
20307 || (XK_Select <= keysym && keysym < XK_KP_Space)
20308 #endif
20309 #ifdef XK_dead_circumflex
20310 || orig_keysym == XK_dead_circumflex
20311 #endif
20312 #ifdef XK_dead_grave
20313 || orig_keysym == XK_dead_grave
20314 #endif
20315 #ifdef XK_dead_tilde
20316 || orig_keysym == XK_dead_tilde
20317 #endif
20318 #ifdef XK_dead_diaeresis
20319 || orig_keysym == XK_dead_diaeresis
20320 #endif
20321 #ifdef XK_dead_macron
20322 || orig_keysym == XK_dead_macron
20323 #endif
20324 #ifdef XK_dead_degree
20325 || orig_keysym == XK_dead_degree
20326 #endif
20327 #ifdef XK_dead_acute
20328 || orig_keysym == XK_dead_acute
20329 #endif
20330 #ifdef XK_dead_cedilla
20331 || orig_keysym == XK_dead_cedilla
20332 #endif
20333 #ifdef XK_dead_breve
20334 || orig_keysym == XK_dead_breve
20335 #endif
20336 #ifdef XK_dead_ogonek
20337 || orig_keysym == XK_dead_ogonek
20338 #endif
20339 #ifdef XK_dead_caron
20340 || orig_keysym == XK_dead_caron
20341 #endif
20342 #ifdef XK_dead_doubleacute
20343 || orig_keysym == XK_dead_doubleacute
20344 #endif
20345 #ifdef XK_dead_abovedot
20346 || orig_keysym == XK_dead_abovedot
20347 #endif
20348 #ifdef XK_dead_abovering
20349 || orig_keysym == XK_dead_abovering
20350 #endif
20351 #ifdef XK_dead_belowdot
20352 || orig_keysym == XK_dead_belowdot
20353 #endif
20354 #ifdef XK_dead_voiced_sound
20355 || orig_keysym == XK_dead_voiced_sound
20356 #endif
20357 #ifdef XK_dead_semivoiced_sound
20358 || orig_keysym == XK_dead_semivoiced_sound
20359 #endif
20360 #ifdef XK_dead_hook
20361 || orig_keysym == XK_dead_hook
20362 #endif
20363 #ifdef XK_dead_horn
20364 || orig_keysym == XK_dead_horn
20365 #endif
20366 #ifdef XK_dead_stroke
20367 || orig_keysym == XK_dead_stroke
20368 #endif
20369 #ifdef XK_dead_abovecomma
20370 || orig_keysym == XK_dead_abovecomma
20371 #endif
20372 || IsKeypadKey (keysym)
20373 || IsFunctionKey (keysym)
20374
20375 || (orig_keysym & (1 << 28))
20376 || (keysym != NoSymbol && nbytes == 0))
20377 && ! (IsModifierKey (orig_keysym)
20378
20379
20380
20381
20382
20383 #if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
20384 || (XK_ISO_Lock <= orig_keysym
20385 && orig_keysym <= XK_ISO_Last_Group_Lock)
20386 #endif
20387 ))
20388 {
20389 STORE_KEYSYM_FOR_DEBUG (keysym);
20390
20391
20392 inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
20393 inev.ie.code = keysym;
20394
20395 #ifdef HAVE_XINPUT2
20396 if (event->xkey.time == pending_keystroke_time)
20397 {
20398 source = xi_device_from_id (dpyinfo,
20399 dpyinfo->pending_keystroke_source);
20400
20401 if (source)
20402 inev.ie.device = source->name;
20403 }
20404 #endif
20405
20406 goto done_keysym;
20407 }
20408
20409 {
20410 ptrdiff_t i;
20411
20412 for (i = 0; i < nbytes; i++)
20413 {
20414 STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]);
20415 }
20416
20417 if (nbytes)
20418 {
20419 inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
20420 inev.ie.arg = make_unibyte_string ((char *) copy_bufptr, nbytes);
20421
20422 Fput_text_property (make_fixnum (0), make_fixnum (nbytes),
20423 Qcoding, coding, inev.ie.arg);
20424
20425 #ifdef HAVE_XINPUT2
20426 if (event->xkey.time == pending_keystroke_time
20427
20428
20429
20430
20431 || (pending_keystroke_time && !event->xkey.time))
20432 {
20433 source = xi_device_from_id (dpyinfo,
20434 dpyinfo->pending_keystroke_source);
20435
20436 if (source)
20437 inev.ie.device = source->name;
20438 }
20439 #endif
20440 }
20441
20442 if (keysym == NoSymbol)
20443 break;
20444 }
20445 }
20446 done_keysym:
20447 #ifdef HAVE_X_I18N
20448 if (f)
20449 {
20450 struct window *w = XWINDOW (f->selected_window);
20451 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
20452
20453 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
20454 xic_set_statusarea (f);
20455 }
20456
20457
20458
20459
20460 break;
20461 #else
20462 goto OTHER;
20463 #endif
20464
20465 case KeyRelease:
20466 #ifdef HAVE_X_I18N
20467
20468
20469
20470 break;
20471 #else
20472 goto OTHER;
20473 #endif
20474
20475 case EnterNotify:
20476 x_display_set_last_user_time (dpyinfo, event->xcrossing.time,
20477 event->xcrossing.send_event,
20478 false);
20479
20480 #ifdef HAVE_XWIDGETS
20481 {
20482 struct xwidget_view *xvw;
20483 Mouse_HLInfo *hlinfo;
20484
20485 xvw = xwidget_view_from_window (event->xcrossing.window);
20486
20487 if (xvw)
20488 {
20489 xwidget_motion_or_crossing (xvw, event);
20490 hlinfo = MOUSE_HL_INFO (xvw->frame);
20491
20492 if (xvw->frame == hlinfo->mouse_face_mouse_frame)
20493 {
20494 clear_mouse_face (hlinfo);
20495 hlinfo->mouse_face_mouse_frame = 0;
20496 x_flush_dirty_back_buffer_on (xvw->frame);
20497 }
20498
20499 if (any_help_event_p)
20500 do_help = -1;
20501
20502 goto OTHER;
20503 }
20504 }
20505 #endif
20506
20507 #ifdef HAVE_XINPUT2
20508
20509
20510
20511
20512
20513
20514
20515 if (dpyinfo->supports_xi2)
20516 goto OTHER;
20517 #endif
20518
20519 if (x_top_window_to_frame (dpyinfo, event->xcrossing.window))
20520 x_detect_focus_change (dpyinfo, any, event, &inev.ie);
20521
20522 f = any;
20523
20524 if (f && event->xcrossing.window == FRAME_X_WINDOW (f))
20525 x_compute_root_window_offset (f, event->xcrossing.x_root,
20526 event->xcrossing.y_root,
20527 event->xcrossing.x,
20528 event->xcrossing.y);
20529
20530
20531
20532
20533
20534 if (f && x_mouse_click_focus_ignore_position)
20535 {
20536 ignore_next_mouse_click_timeout = (event->xmotion.time
20537 + x_mouse_click_focus_ignore_time);
20538 mouse_click_timeout_display = dpyinfo;
20539 }
20540
20541
20542
20543 if (f && !f->output_data.x->hourglass_p)
20544 x_note_mouse_movement (f, &event->xmotion, Qnil);
20545 #ifdef USE_GTK
20546
20547
20548 if (!f && dpyinfo->last_mouse_glyph_frame)
20549 x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &event->xmotion,
20550 Qnil);
20551 #endif
20552 goto OTHER;
20553
20554 case FocusIn:
20555 #if defined HAVE_XINPUT2 \
20556 && (defined HAVE_GTK3 || (!defined USE_GTK && !defined USE_X_TOOLKIT))
20557
20558
20559
20560
20561
20562
20563
20564
20565
20566
20567 if (dpyinfo->supports_xi2)
20568 goto OTHER;
20569 #endif
20570 #ifdef USE_GTK
20571
20572
20573
20574
20575
20576
20577
20578
20579
20580
20581
20582
20583 if (EQ (x_set_frame_visibility_more_laxly, Qfocus_in)
20584 || EQ (x_set_frame_visibility_more_laxly, Qt))
20585 #endif
20586 {
20587 f = any;
20588 if (f && FRAME_ICONIFIED_P (f))
20589 {
20590 SET_FRAME_VISIBLE (f, 1);
20591 SET_FRAME_ICONIFIED (f, false);
20592 f->output_data.x->has_been_visible = true;
20593 inev.ie.kind = DEICONIFY_EVENT;
20594 XSETFRAME (inev.ie.frame_or_window, f);
20595 }
20596 }
20597
20598 x_detect_focus_change (dpyinfo, any, event, &inev.ie);
20599 goto OTHER;
20600
20601 case LeaveNotify:
20602 x_display_set_last_user_time (dpyinfo, event->xcrossing.time,
20603 event->xcrossing.send_event, false);
20604
20605 #ifdef HAVE_XINPUT2
20606
20607
20608
20609
20610
20611
20612
20613 if (dpyinfo->supports_xi2)
20614 {
20615 #if !defined USE_X_TOOLKIT && (!defined USE_GTK || defined HAVE_GTK3)
20616 goto OTHER;
20617 #else
20618
20619
20620
20621
20622
20623
20624
20625 goto just_clear_mouse_face;
20626 #endif
20627 }
20628 #endif
20629
20630 #ifdef HAVE_XWIDGETS
20631 {
20632 struct xwidget_view *xvw;
20633
20634 xvw = xwidget_view_from_window (event->xcrossing.window);
20635
20636 if (xvw)
20637 {
20638 xwidget_motion_or_crossing (xvw, event);
20639 goto OTHER;
20640 }
20641 }
20642 #endif
20643
20644 if (x_top_window_to_frame (dpyinfo, event->xcrossing.window))
20645 x_detect_focus_change (dpyinfo, any, event, &inev.ie);
20646
20647 #if defined HAVE_XINPUT2 \
20648 && (defined USE_X_TOOLKIT || (defined USE_GTK && !defined HAVE_GTK3))
20649 just_clear_mouse_face:
20650 #endif
20651
20652 #if defined USE_X_TOOLKIT
20653
20654
20655 f = x_window_to_frame (dpyinfo, event->xcrossing.window);
20656
20657 if (!f)
20658 f = x_top_window_to_frame (dpyinfo, event->xcrossing.window);
20659 #else
20660 f = x_top_window_to_frame (dpyinfo, event->xcrossing.window);
20661 #endif
20662
20663 if (f)
20664 {
20665
20666
20667
20668
20669
20670 if (f == dpyinfo->last_mouse_motion_frame)
20671 dpyinfo->last_mouse_motion_frame = NULL;
20672
20673
20674
20675 if (f == dpyinfo->last_mouse_glyph_frame)
20676 dpyinfo->last_mouse_glyph_frame = NULL;
20677
20678 if (f == hlinfo->mouse_face_mouse_frame)
20679 {
20680
20681
20682 clear_mouse_face (hlinfo);
20683 hlinfo->mouse_face_mouse_frame = 0;
20684 x_flush_dirty_back_buffer_on (f);
20685 }
20686
20687
20688
20689
20690
20691 if (any_help_event_p
20692
20693
20694
20695 && !((EQ (track_mouse, Qdrag_source)
20696 || EQ (track_mouse, Qdropping))
20697 && gui_mouse_grabbed (dpyinfo)))
20698 do_help = -1;
20699
20700 if (event->xcrossing.window == FRAME_X_WINDOW (f))
20701 x_compute_root_window_offset (f, event->xcrossing.x_root,
20702 event->xcrossing.y_root,
20703 event->xcrossing.x,
20704 event->xcrossing.y);
20705
20706 }
20707 #ifdef USE_GTK
20708
20709 else if (dpyinfo->last_mouse_glyph_frame)
20710 x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame,
20711 &event->xmotion, Qnil);
20712 #endif
20713 goto OTHER;
20714
20715 case FocusOut:
20716 #if defined HAVE_XINPUT2 \
20717 && (defined HAVE_GTK3 || (!defined USE_GTK && !defined USE_X_TOOLKIT))
20718
20719
20720
20721
20722
20723
20724
20725
20726
20727
20728 if (dpyinfo->supports_xi2)
20729 goto OTHER;
20730 #endif
20731 x_detect_focus_change (dpyinfo, any, event, &inev.ie);
20732 goto OTHER;
20733
20734 case MotionNotify:
20735 {
20736 XMotionEvent xmotion = event->xmotion;
20737
20738 previous_help_echo_string = help_echo_string;
20739 help_echo_string = Qnil;
20740
20741 if (hlinfo->mouse_face_hidden)
20742 {
20743 hlinfo->mouse_face_hidden = false;
20744 clear_mouse_face (hlinfo);
20745 }
20746
20747 f = mouse_or_wdesc_frame (dpyinfo, event->xmotion.window);
20748
20749 if (f && event->xmotion.window == FRAME_X_WINDOW (f))
20750
20751
20752 x_compute_root_window_offset (f, event->xmotion.x_root,
20753 event->xmotion.y_root,
20754 event->xmotion.x,
20755 event->xmotion.y);
20756
20757 if (x_dnd_in_progress
20758
20759
20760
20761
20762
20763 && (command_loop_level + minibuf_level
20764 <= x_dnd_recursion_depth)
20765 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
20766 {
20767 Window target, toplevel;
20768 int target_proto, motif_style;
20769 xm_top_level_leave_message lmsg;
20770 xm_top_level_enter_message emsg;
20771 xm_drag_motion_message dmsg;
20772 XRectangle *r;
20773 bool was_frame;
20774
20775
20776 clear_mouse_face (hlinfo);
20777 hlinfo->mouse_face_hidden = true;
20778
20779
20780
20781
20782
20783
20784 if (f)
20785 {
20786 XTtoggle_invisible_pointer (f, false);
20787
20788 r = &dpyinfo->last_mouse_glyph;
20789
20790
20791
20792 if (f != dpyinfo->last_mouse_glyph_frame
20793 || event->xmotion.x < r->x
20794 || event->xmotion.x >= r->x + r->width
20795 || event->xmotion.y < r->y
20796 || event->xmotion.y >= r->y + r->height)
20797 {
20798 f->mouse_moved = true;
20799 f->last_mouse_device = Qnil;
20800 dpyinfo->last_mouse_scroll_bar = NULL;
20801
20802 remember_mouse_glyph (f, event->xmotion.x,
20803 event->xmotion.y, r);
20804 dpyinfo->last_mouse_glyph_frame = f;
20805 }
20806 }
20807
20808 if (event->xmotion.same_screen)
20809 target = x_dnd_get_target_window (dpyinfo,
20810 event->xmotion.x_root,
20811 event->xmotion.y_root,
20812 &target_proto,
20813 &motif_style, &toplevel,
20814 &was_frame);
20815 else
20816 target = x_dnd_fill_empty_target (&target_proto, &motif_style,
20817 &toplevel, &was_frame);
20818
20819 if (toplevel != x_dnd_last_seen_toplevel)
20820 {
20821 if (toplevel != FRAME_OUTER_WINDOW (x_dnd_frame)
20822 && x_dnd_return_frame == 1)
20823 x_dnd_return_frame = 2;
20824
20825 if (x_dnd_return_frame == 2
20826 && x_any_window_to_frame (dpyinfo, toplevel))
20827 {
20828 if (x_dnd_last_seen_window != None
20829 && x_dnd_last_protocol_version != -1
20830 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
20831 x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window,
20832 x_dnd_last_seen_toplevel);
20833 else if (x_dnd_last_seen_window != None
20834 && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
20835 && !x_dnd_disable_motif_drag
20836 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
20837 {
20838 if (!x_dnd_motif_setup_p)
20839 xm_setup_drag_info (dpyinfo, x_dnd_frame);
20840
20841 lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
20842 XM_DRAG_REASON_TOP_LEVEL_LEAVE);
20843 lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
20844 lmsg.zero = 0;
20845 lmsg.timestamp = event->xmotion.time;
20846 lmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
20847
20848 if (x_dnd_motif_setup_p)
20849 xm_send_top_level_leave_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
20850 x_dnd_last_seen_window, &lmsg);
20851 }
20852
20853 x_dnd_end_window = x_dnd_last_seen_window;
20854 x_dnd_last_seen_window = None;
20855 x_dnd_last_seen_toplevel = None;
20856 x_dnd_in_progress = false;
20857 x_dnd_return_frame_object
20858 = x_any_window_to_frame (dpyinfo, toplevel);
20859 x_dnd_return_frame = 3;
20860 x_dnd_waiting_for_finish = false;
20861 target = None;
20862 }
20863 }
20864
20865 if (target != x_dnd_last_seen_window)
20866 {
20867 if (x_dnd_last_seen_window != None
20868 && x_dnd_last_protocol_version != -1
20869 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
20870 x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window,
20871 x_dnd_last_seen_toplevel);
20872 else if (x_dnd_last_seen_window != None
20873 && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
20874 && x_dnd_disable_motif_drag
20875 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
20876 {
20877 if (!x_dnd_motif_setup_p)
20878 xm_setup_drag_info (dpyinfo, x_dnd_frame);
20879
20880
20881
20882
20883
20884
20885
20886 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
20887 XM_DRAG_REASON_DRAG_MOTION);
20888 dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
20889 dmsg.side_effects = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
20890 x_dnd_wanted_action),
20891 XM_DROP_SITE_NONE, x_dnd_motif_operations,
20892 XM_DROP_ACTION_DROP_CANCEL);
20893 dmsg.timestamp = event->xmotion.time;
20894 dmsg.x = event->xmotion.x_root;
20895 dmsg.y = event->xmotion.y_root;
20896
20897 lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
20898 XM_DRAG_REASON_TOP_LEVEL_LEAVE);
20899 lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
20900 lmsg.zero = 0;
20901 lmsg.timestamp = event->xbutton.time;
20902 lmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
20903
20904 if (x_dnd_motif_setup_p)
20905 {
20906 xm_send_drag_motion_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
20907 x_dnd_last_seen_window, &dmsg);
20908 xm_send_top_level_leave_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
20909 x_dnd_last_seen_window, &lmsg);
20910 }
20911 }
20912
20913 x_dnd_action = None;
20914 x_dnd_last_seen_toplevel = toplevel;
20915 x_dnd_last_seen_window = target;
20916 x_dnd_last_protocol_version = target_proto;
20917 x_dnd_last_motif_style = motif_style;
20918 x_dnd_last_window_is_frame = was_frame;
20919
20920 if (target != None && x_dnd_last_protocol_version != -1)
20921 x_dnd_send_enter (x_dnd_frame, target,
20922 x_dnd_last_seen_toplevel,
20923 x_dnd_last_protocol_version);
20924 else if (target != None && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
20925 && !x_dnd_disable_motif_drag)
20926 {
20927 if (!x_dnd_motif_setup_p)
20928 xm_setup_drag_info (dpyinfo, x_dnd_frame);
20929
20930 emsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
20931 XM_DRAG_REASON_TOP_LEVEL_ENTER);
20932 emsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
20933 emsg.zero = 0;
20934 emsg.timestamp = event->xbutton.time;
20935 emsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
20936 emsg.index_atom = x_dnd_motif_atom;
20937
20938 if (x_dnd_motif_setup_p)
20939 xm_send_top_level_enter_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
20940 target, &emsg);
20941 }
20942 }
20943 else
20944 x_dnd_last_seen_toplevel = toplevel;
20945
20946 if (x_dnd_last_window_is_frame && target != None)
20947 x_dnd_note_self_position (dpyinfo, target,
20948 event->xbutton.x_root,
20949 event->xbutton.y_root);
20950 else if (x_dnd_last_protocol_version != -1 && target != None)
20951 x_dnd_send_position (x_dnd_frame, target,
20952 x_dnd_last_seen_toplevel,
20953 x_dnd_last_protocol_version,
20954 event->xmotion.x_root,
20955 event->xmotion.y_root,
20956 x_dnd_selection_timestamp,
20957 x_dnd_wanted_action, 0,
20958 event->xmotion.state);
20959 else if (XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) && target != None
20960 && !x_dnd_disable_motif_drag)
20961 {
20962 if (!x_dnd_motif_setup_p)
20963 xm_setup_drag_info (dpyinfo, x_dnd_frame);
20964
20965 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
20966 XM_DRAG_REASON_DRAG_MOTION);
20967 dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
20968 dmsg.side_effects = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
20969 x_dnd_wanted_action),
20970 XM_DROP_SITE_VALID, x_dnd_motif_operations,
20971 (!x_dnd_xm_use_help
20972 ? XM_DROP_ACTION_DROP
20973 : XM_DROP_ACTION_DROP_HELP));
20974 dmsg.timestamp = event->xbutton.time;
20975 dmsg.x = event->xmotion.x_root;
20976 dmsg.y = event->xmotion.y_root;
20977
20978 if (x_dnd_motif_setup_p)
20979 xm_send_drag_motion_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
20980 target, &dmsg);
20981 }
20982
20983 x_dnd_update_tooltip_position (event->xmotion.x_root,
20984 event->xmotion.y_root);
20985
20986 goto OTHER;
20987 }
20988
20989 #ifdef USE_GTK
20990 if (f && xg_event_is_for_scrollbar (f, event, false))
20991 f = 0;
20992 #endif
20993 #ifdef HAVE_XWIDGETS
20994 struct xwidget_view *xvw;
20995
20996 xvw = xwidget_view_from_window (event->xmotion.window);
20997
20998 if (xvw)
20999 xwidget_motion_or_crossing (xvw, event);
21000 #endif
21001 if (f)
21002 {
21003
21004
21005
21006 if (!NILP (Vmouse_autoselect_window)
21007 && !popup_activated ()
21008
21009
21010
21011
21012
21013 && !MINI_WINDOW_P (XWINDOW (selected_window))
21014
21015
21016 && (f == XFRAME (selected_frame)
21017 || !NILP (focus_follows_mouse)))
21018 {
21019 static Lisp_Object last_mouse_window;
21020
21021 if (xmotion.window != FRAME_X_WINDOW (f))
21022 {
21023 x_translate_coordinates (f, xmotion.x_root, xmotion.y_root,
21024 &xmotion.x, &xmotion.y);
21025 xmotion.window = FRAME_X_WINDOW (f);
21026 }
21027
21028 Lisp_Object window = window_from_coordinates
21029 (f, xmotion.x, xmotion.y, 0, false, false);
21030
21031
21032
21033
21034
21035
21036
21037
21038
21039 if (WINDOWP (window)
21040 && !EQ (window, last_mouse_window)
21041 && !EQ (window, selected_window))
21042 {
21043 inev.ie.kind = SELECT_WINDOW_EVENT;
21044 inev.ie.frame_or_window = window;
21045 }
21046
21047
21048 last_mouse_window = window;
21049 }
21050
21051 if (!x_note_mouse_movement (f, &xmotion, Qnil))
21052 help_echo_string = previous_help_echo_string;
21053 }
21054 else
21055 {
21056 #ifndef USE_TOOLKIT_SCROLL_BARS
21057 struct scroll_bar *bar
21058 = x_window_to_scroll_bar (event->xmotion.display,
21059 event->xmotion.window, 2);
21060
21061 if (bar)
21062 x_scroll_bar_note_movement (bar, &event->xmotion);
21063 #endif
21064
21065
21066
21067 clear_mouse_face (hlinfo);
21068 }
21069
21070
21071
21072 if (!NILP (help_echo_string)
21073 || !NILP (previous_help_echo_string))
21074 do_help = 1;
21075
21076 if (f)
21077 x_flush_dirty_back_buffer_on (f);
21078 goto OTHER;
21079 }
21080
21081 case ConfigureNotify:
21082
21083
21084
21085
21086
21087
21088
21089
21090
21091
21092
21093
21094 configureEvent = *event;
21095 while (XPending (dpyinfo->display))
21096 {
21097 XNextEvent (dpyinfo->display, &next_event);
21098 if (next_event.type != ConfigureNotify
21099 || next_event.xconfigure.window != event->xconfigure.window
21100
21101
21102
21103 || next_event.xconfigure.width != event->xconfigure.width
21104 || next_event.xconfigure.height != event->xconfigure.height)
21105 {
21106 XPutBackEvent (dpyinfo->display, &next_event);
21107 break;
21108 }
21109 else
21110 configureEvent = next_event;
21111 }
21112
21113
21114
21115
21116 if (configureEvent.xconfigure.window == dpyinfo->root_window)
21117 {
21118 #ifdef HAVE_XRANDR
21119
21120
21121 XRRUpdateConfiguration (&configureEvent);
21122 #elif !defined USE_GTK
21123
21124
21125
21126 if (configureEvent.xconfigure.width != dpyinfo->screen_width
21127 || configureEvent.xconfigure.height != dpyinfo->screen_height)
21128 {
21129
21130
21131
21132
21133 if (!x_find_monitors_changed_event (dpyinfo))
21134 {
21135 inev.ie.kind = MONITORS_CHANGED_EVENT;
21136 XSETTERMINAL (inev.ie.arg, dpyinfo->terminal);
21137
21138
21139
21140 kbd_buffer_store_event (&inev.ie);
21141 inev.ie.kind = NO_EVENT;
21142 }
21143
21144
21145
21146 x_dnd_update_tooltip_now ();
21147 }
21148 #endif
21149
21150 dpyinfo->screen_width = configureEvent.xconfigure.width;
21151 dpyinfo->screen_height = configureEvent.xconfigure.height;
21152 }
21153
21154 if (x_dnd_in_progress && x_dnd_use_toplevels
21155 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
21156 {
21157 int rc, dest_x, dest_y;
21158 Window child;
21159 struct x_client_list_window *tem, *last = NULL;
21160
21161 for (tem = x_dnd_toplevels; tem; last = tem, tem = tem->next)
21162 {
21163
21164
21165
21166 if (tem->window == configureEvent.xconfigure.window)
21167 {
21168 x_catch_errors (dpyinfo->display);
21169 rc = (XTranslateCoordinates (dpyinfo->display,
21170 configureEvent.xconfigure.window,
21171 dpyinfo->root_window,
21172 -configureEvent.xconfigure.border_width,
21173 -configureEvent.xconfigure.border_width,
21174 &dest_x, &dest_y, &child)
21175 && !x_had_errors_p (dpyinfo->display));
21176 x_uncatch_errors_after_check ();
21177
21178 if (rc)
21179 {
21180 tem->x = dest_x;
21181 tem->y = dest_y;
21182 tem->width = (configureEvent.xconfigure.width
21183 + configureEvent.xconfigure.border_width);
21184 tem->height = (configureEvent.xconfigure.height
21185 + configureEvent.xconfigure.border_width);
21186 }
21187 else
21188 {
21189
21190
21191
21192 if (!last)
21193 x_dnd_toplevels = tem->next;
21194 else
21195 last->next = tem->next;
21196
21197 #ifdef HAVE_XSHAPE
21198 if (tem->n_input_rects != -1)
21199 xfree (tem->input_rects);
21200 if (tem->n_bounding_rects != -1)
21201 xfree (tem->bounding_rects);
21202 #endif
21203 xfree (tem);
21204 }
21205
21206 break;
21207 }
21208 }
21209 }
21210
21211 #if defined HAVE_GTK3 && defined USE_TOOLKIT_SCROLL_BARS
21212 struct scroll_bar *bar = x_window_to_scroll_bar (dpyinfo->display,
21213 configureEvent.xconfigure.window, 2);
21214
21215
21216
21217 if (bar)
21218 {
21219
21220
21221 while (XPending (dpyinfo->display))
21222 {
21223 XNextEvent (dpyinfo->display, &next_event);
21224 if (next_event.type != ConfigureNotify
21225 || next_event.xconfigure.window != event->xconfigure.window)
21226 {
21227 XPutBackEvent (dpyinfo->display, &next_event);
21228 break;
21229 }
21230 else
21231 configureEvent = next_event;
21232 }
21233
21234 if (configureEvent.xconfigure.width != max (bar->width, 1)
21235 || configureEvent.xconfigure.height != max (bar->height, 1))
21236 {
21237 XResizeWindow (dpyinfo->display, bar->x_window,
21238 max (bar->width, 1), max (bar->height, 1));
21239 x_flush (WINDOW_XFRAME (XWINDOW (bar->window)));
21240 }
21241
21242 #ifdef HAVE_XDBE
21243 if (f && FRAME_X_DOUBLE_BUFFERED_P (f))
21244 x_drop_xrender_surfaces (f);
21245 #endif
21246
21247 goto OTHER;
21248 }
21249 #endif
21250
21251 f = x_top_window_to_frame (dpyinfo, configureEvent.xconfigure.window);
21252
21253
21254
21255 if (any)
21256 FRAME_X_OUTPUT (any)->window_offset_certain_p = false;
21257
21258
21259
21260
21261
21262
21263 #ifdef HAVE_XDBE
21264 if (f && FRAME_X_DOUBLE_BUFFERED_P (f))
21265 x_drop_xrender_surfaces (f);
21266 #endif
21267 #if defined USE_CAIRO && !defined USE_GTK
21268 if (f)
21269 x_cr_update_surface_desired_size (f, configureEvent.xconfigure.width,
21270 configureEvent.xconfigure.height);
21271 else if (any && configureEvent.xconfigure.window == FRAME_X_WINDOW (any))
21272 x_cr_update_surface_desired_size (any,
21273 configureEvent.xconfigure.width,
21274 configureEvent.xconfigure.height);
21275 #endif
21276
21277 #if !defined USE_X_TOOLKIT && !defined USE_GTK
21278
21279
21280
21281
21282
21283
21284
21285
21286 if (f || (any && configureEvent.xconfigure.window
21287 == FRAME_OUTER_WINDOW (any)))
21288 x_update_opaque_region (f ? f : any, &configureEvent);
21289
21290 #endif
21291
21292 #ifdef USE_GTK
21293 if (!f
21294 && (f = any)
21295 && configureEvent.xconfigure.window == FRAME_X_WINDOW (f)
21296 && (FRAME_VISIBLE_P (f)
21297 || !(configureEvent.xconfigure.width <= 1
21298 && configureEvent.xconfigure.height <= 1)))
21299 {
21300
21301 if (CONSP (frame_size_history))
21302 frame_size_history_extra
21303 (f, build_string ("ConfigureNotify"),
21304 FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f),
21305 configureEvent.xconfigure.width,
21306 configureEvent.xconfigure.height,
21307 f->new_width, f->new_height);
21308
21309 #ifdef HAVE_XDBE
21310 if (FRAME_X_DOUBLE_BUFFERED_P (f))
21311 x_drop_xrender_surfaces (f);
21312 #endif
21313 xg_frame_resized (f, configureEvent.xconfigure.width,
21314 configureEvent.xconfigure.height);
21315 #ifdef USE_CAIRO
21316 x_cr_update_surface_desired_size (f, configureEvent.xconfigure.width,
21317 configureEvent.xconfigure.height);
21318 #endif
21319 x_update_opaque_region (f, &configureEvent);
21320 f = 0;
21321 }
21322 #endif
21323 if (f && (FRAME_VISIBLE_P (f)
21324 || !(configureEvent.xconfigure.width <= 1
21325 && configureEvent.xconfigure.height <= 1)))
21326 {
21327 #ifdef USE_GTK
21328
21329
21330 if (configureEvent.xconfigure.window == FRAME_X_WINDOW (f))
21331 #endif
21332 x_net_wm_state (f, configureEvent.xconfigure.window);
21333
21334 #if defined USE_X_TOOLKIT || defined USE_GTK
21335
21336 if (FRAME_TOOLTIP_P (f))
21337 {
21338 if (FRAME_PIXEL_HEIGHT (f) != configureEvent.xconfigure.height
21339 || FRAME_PIXEL_WIDTH (f) != configureEvent.xconfigure.width)
21340 SET_FRAME_GARBAGED (f);
21341
21342 FRAME_PIXEL_HEIGHT (f) = configureEvent.xconfigure.height;
21343 FRAME_PIXEL_WIDTH (f) = configureEvent.xconfigure.width;
21344 }
21345 #endif
21346
21347 #ifndef USE_X_TOOLKIT
21348 #ifndef USE_GTK
21349 int width = configureEvent.xconfigure.width;
21350 int height = configureEvent.xconfigure.height;
21351
21352 if (CONSP (frame_size_history))
21353 frame_size_history_extra
21354 (f, build_string ("ConfigureNotify"),
21355 FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f),
21356 width, height, f->new_width, f->new_height);
21357
21358
21359
21360
21361
21362
21363
21364
21365
21366 if (width != FRAME_PIXEL_WIDTH (f)
21367 || height != FRAME_PIXEL_HEIGHT (f)
21368 || (f->new_size_p
21369 && ((f->new_width >= 0 && width != f->new_width)
21370 || (f->new_height >= 0 && height != f->new_height))))
21371 {
21372 change_frame_size (f, width, height, false, true, false);
21373 x_clear_under_internal_border (f);
21374 SET_FRAME_GARBAGED (f);
21375 cancel_mouse_face (f);
21376 }
21377 #endif
21378 #endif
21379
21380 #ifdef USE_GTK
21381
21382
21383 if (FRAME_GTK_OUTER_WIDGET (f)
21384 && gtk_widget_get_mapped (FRAME_GTK_OUTER_WIDGET (f)))
21385 #endif
21386 {
21387 int old_left = f->left_pos;
21388 int old_top = f->top_pos;
21389 Lisp_Object frame;
21390
21391 XSETFRAME (frame, f);
21392
21393 if (!FRAME_PARENT_FRAME (f))
21394 x_real_positions (f, &f->left_pos, &f->top_pos);
21395 else
21396 {
21397 Window root;
21398 unsigned int dummy_uint;
21399
21400 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
21401 &root, &f->left_pos, &f->top_pos,
21402 &dummy_uint, &dummy_uint, &dummy_uint, &dummy_uint);
21403 }
21404
21405 if (!FRAME_TOOLTIP_P (f)
21406 && (old_left != f->left_pos || old_top != f->top_pos))
21407 {
21408 inev.ie.kind = MOVE_FRAME_EVENT;
21409 XSETFRAME (inev.ie.frame_or_window, f);
21410 }
21411 }
21412
21413
21414 #ifdef HAVE_X_I18N
21415 if (f)
21416 {
21417 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
21418 xic_set_statusarea (f);
21419
21420 struct window *w = XWINDOW (f->selected_window);
21421 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
21422 }
21423 #endif
21424
21425 #ifdef HAVE_XINPUT2
21426 if (f && dpyinfo->supports_xi2)
21427 {
21428 Mouse_HLInfo *hlinfo;
21429
21430
21431
21432
21433
21434
21435
21436
21437 if (dpyinfo->last_mouse_motion_frame == f)
21438 dpyinfo->last_mouse_motion_frame = NULL;
21439
21440 hlinfo = MOUSE_HL_INFO (f);
21441
21442 if (hlinfo->mouse_face_mouse_frame == f)
21443 reset_mouse_highlight (hlinfo);
21444 }
21445 #endif
21446
21447 }
21448
21449 if (x_dnd_in_progress
21450 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
21451 x_dnd_update_state (dpyinfo, dpyinfo->last_user_time);
21452 goto OTHER;
21453
21454 case ButtonRelease:
21455 case ButtonPress:
21456 {
21457 if (event->xbutton.type == ButtonPress)
21458 x_display_set_last_user_time (dpyinfo, event->xbutton.time,
21459 event->xbutton.send_event, true);
21460
21461 #ifdef HAVE_XWIDGETS
21462 struct xwidget_view *xvw;
21463
21464 xvw = xwidget_view_from_window (event->xbutton.window);
21465
21466 if (xvw)
21467 {
21468 xwidget_button (xvw, event->type == ButtonPress,
21469 event->xbutton.x, event->xbutton.y,
21470 event->xbutton.button, event->xbutton.state,
21471 event->xbutton.time);
21472
21473 if (!EQ (selected_window, xvw->w) && (event->xbutton.button < 4))
21474 {
21475 inev.ie.kind = SELECT_WINDOW_EVENT;
21476 inev.ie.frame_or_window = xvw->w;
21477 }
21478
21479 *finish = X_EVENT_DROP;
21480 goto OTHER;
21481 }
21482 #endif
21483
21484
21485 Lisp_Object tab_bar_arg = Qnil;
21486 bool tab_bar_p = false;
21487 bool tool_bar_p = false;
21488 bool dnd_grab = false;
21489
21490 if (x_dnd_in_progress
21491
21492
21493
21494
21495
21496 && (command_loop_level + minibuf_level
21497 <= x_dnd_recursion_depth)
21498 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
21499 {
21500 f = mouse_or_wdesc_frame (dpyinfo, event->xbutton.window);
21501
21502 if (f && event->xbutton.window == FRAME_X_WINDOW (f))
21503
21504
21505 x_compute_root_window_offset (f, event->xbutton.x_root,
21506 event->xbutton.y_root,
21507 event->xbutton.x,
21508 event->xbutton.y);
21509
21510 if (event->type == ButtonPress)
21511 {
21512 x_display_set_last_user_time (dpyinfo, event->xbutton.time,
21513 event->xbutton.send_event, true);
21514
21515 dpyinfo->grabbed |= (1 << event->xbutton.button);
21516 dpyinfo->last_mouse_frame = f;
21517
21518 if (f)
21519 f->last_tab_bar_item = -1;
21520 #if ! defined (USE_GTK)
21521 if (f)
21522 f->last_tool_bar_item = -1;
21523 #endif
21524 }
21525 else
21526 dpyinfo->grabbed &= ~(1 << event->xbutton.button);
21527
21528 if (event->xbutton.type == ButtonPress
21529 && x_dnd_last_seen_window != None)
21530 {
21531 if (x_dnd_last_window_is_frame)
21532 x_dnd_note_self_wheel (dpyinfo,
21533 x_dnd_last_seen_window,
21534 event->xbutton.x_root,
21535 event->xbutton.y_root,
21536 event->xbutton.button,
21537 event->xbutton.state,
21538 event->xbutton.time);
21539 else if (x_dnd_last_protocol_version != -1)
21540 x_dnd_send_position (x_dnd_frame,
21541 x_dnd_last_seen_window,
21542 x_dnd_last_seen_toplevel,
21543 x_dnd_last_protocol_version,
21544 event->xbutton.x_root,
21545 event->xbutton.y_root,
21546 event->xbutton.time,
21547 x_dnd_wanted_action,
21548 event->xbutton.button,
21549 event->xbutton.state);
21550
21551 goto OTHER;
21552 }
21553
21554 if (event->xbutton.type == ButtonRelease)
21555 {
21556 for (int i = 1; i < 8; ++i)
21557 {
21558 if (i != event->xbutton.button
21559 && event->xbutton.state & (Button1Mask << (i - 1)))
21560 dnd_grab = true;
21561 }
21562
21563 if (!dnd_grab)
21564 {
21565 x_dnd_end_window = x_dnd_last_seen_window;
21566 x_dnd_in_progress = false;
21567
21568 if (x_dnd_update_tooltip
21569 && FRAMEP (tip_frame)
21570 && FRAME_LIVE_P (XFRAME (tip_frame))
21571 && (FRAME_X_DISPLAY (XFRAME (tip_frame))
21572 == FRAME_X_DISPLAY (x_dnd_frame)))
21573 Fx_hide_tip ();
21574
21575 x_dnd_finish_frame = x_dnd_frame;
21576
21577 if (x_dnd_last_seen_window != None
21578 && x_dnd_last_window_is_frame)
21579 {
21580 x_dnd_waiting_for_finish = false;
21581 x_dnd_note_self_drop (dpyinfo,
21582 x_dnd_last_seen_window,
21583 event->xbutton.x_root,
21584 event->xbutton.y_root,
21585 event->xbutton.time);
21586 }
21587 else if (x_dnd_last_seen_window != None
21588 && x_dnd_last_protocol_version != -1)
21589 {
21590 x_dnd_pending_finish_target = x_dnd_last_seen_toplevel;
21591 x_dnd_waiting_for_finish_proto = x_dnd_last_protocol_version;
21592
21593 x_dnd_waiting_for_finish
21594 = x_dnd_do_drop (x_dnd_last_seen_window,
21595 x_dnd_last_seen_toplevel,
21596 x_dnd_last_protocol_version);
21597 x_dnd_finish_display = dpyinfo->display;
21598 }
21599 else if (x_dnd_last_seen_window != None)
21600 {
21601 xm_drop_start_message dmsg;
21602 xm_drag_receiver_info drag_receiver_info;
21603
21604 if (!xm_read_drag_receiver_info (dpyinfo, x_dnd_last_seen_window,
21605 &drag_receiver_info)
21606 && !x_dnd_disable_motif_protocol
21607 && drag_receiver_info.protocol_style != XM_DRAG_STYLE_NONE
21608 && (x_dnd_allow_current_frame
21609 || x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame)))
21610 {
21611 if (!x_dnd_motif_setup_p)
21612 xm_setup_drag_info (dpyinfo, x_dnd_frame);
21613
21614 if (x_dnd_motif_setup_p)
21615 {
21616 memset (&dmsg, 0, sizeof dmsg);
21617
21618 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
21619 XM_DRAG_REASON_DROP_START);
21620 dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST;
21621 dmsg.side_effects
21622 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
21623 x_dnd_wanted_action),
21624 XM_DROP_SITE_VALID, x_dnd_motif_operations,
21625 (!x_dnd_xm_use_help
21626 ? XM_DROP_ACTION_DROP
21627 : XM_DROP_ACTION_DROP_HELP));
21628 dmsg.timestamp = event->xbutton.time;
21629 dmsg.x = event->xbutton.x_root;
21630 dmsg.y = event->xbutton.y_root;
21631 dmsg.index_atom = x_dnd_motif_atom;
21632 dmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
21633
21634 if (!XM_DRAG_STYLE_IS_DROP_ONLY (drag_receiver_info.protocol_style))
21635 x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (x_dnd_frame),
21636 x_dnd_frame, x_dnd_last_seen_window,
21637 event->xbutton.time);
21638
21639 xm_send_drop_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
21640 x_dnd_last_seen_window, &dmsg);
21641
21642 x_dnd_waiting_for_finish = true;
21643 x_dnd_waiting_for_motif_finish_display = dpyinfo;
21644 x_dnd_waiting_for_motif_finish = 1;
21645 x_dnd_finish_display = dpyinfo->display;
21646 }
21647 }
21648 else
21649 x_dnd_send_unsupported_drop (dpyinfo, (x_dnd_last_seen_toplevel != None
21650 ? x_dnd_last_seen_toplevel
21651 : x_dnd_last_seen_window),
21652 event->xbutton.x_root, event->xbutton.y_root,
21653 event->xbutton.time);
21654 }
21655 else if (x_dnd_last_seen_toplevel != None)
21656 x_dnd_send_unsupported_drop (dpyinfo, x_dnd_last_seen_toplevel,
21657 event->xbutton.x_root,
21658 event->xbutton.y_root,
21659 event->xbutton.time);
21660
21661
21662 x_dnd_last_protocol_version = -1;
21663 x_dnd_last_motif_style = XM_DRAG_STYLE_NONE;
21664 x_dnd_last_seen_window = None;
21665 x_dnd_last_seen_toplevel = None;
21666 x_dnd_last_window_is_frame = false;
21667 x_dnd_frame = NULL;
21668 }
21669 }
21670
21671 goto OTHER;
21672 }
21673
21674 if (x_dnd_in_progress
21675 && (command_loop_level + minibuf_level
21676 <= x_dnd_recursion_depth))
21677 goto OTHER;
21678
21679 memset (&compose_status, 0, sizeof (compose_status));
21680 dpyinfo->last_mouse_glyph_frame = NULL;
21681
21682 f = mouse_or_wdesc_frame (dpyinfo, event->xbutton.window);
21683
21684 if (f && event->xbutton.window == FRAME_X_WINDOW (f))
21685
21686
21687 x_compute_root_window_offset (f, event->xbutton.x_root,
21688 event->xbutton.y_root,
21689 event->xbutton.x,
21690 event->xbutton.y);
21691
21692 if (f && event->xbutton.type == ButtonPress
21693 && !popup_activated ()
21694 && !x_window_to_scroll_bar (event->xbutton.display,
21695 event->xbutton.window, 2)
21696 && !FRAME_NO_ACCEPT_FOCUS (f))
21697 {
21698
21699
21700
21701
21702 struct frame *hf = dpyinfo->highlight_frame;
21703
21704 if (FRAME_PARENT_FRAME (f) || (hf && frame_ancestor_p (f, hf)))
21705 {
21706 x_ignore_errors_for_next_request (dpyinfo, 0);
21707 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
21708 RevertToParent, event->xbutton.time);
21709 x_stop_ignoring_errors (dpyinfo);
21710
21711 if (FRAME_PARENT_FRAME (f))
21712 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
21713 }
21714 }
21715
21716 #ifdef USE_GTK
21717 if (!f)
21718 {
21719 f = x_any_window_to_frame (dpyinfo, event->xbutton.window);
21720
21721 if (event->xbutton.button > 3
21722 && event->xbutton.button < 8
21723 && f)
21724 {
21725 if (ignore_next_mouse_click_timeout
21726 && dpyinfo == mouse_click_timeout_display)
21727 {
21728 if (event->type == ButtonPress
21729 && event->xbutton.time > ignore_next_mouse_click_timeout)
21730 {
21731 ignore_next_mouse_click_timeout = 0;
21732 x_construct_mouse_click (&inev.ie, &event->xbutton, f);
21733 }
21734 if (event->type == ButtonRelease)
21735 ignore_next_mouse_click_timeout = 0;
21736 }
21737 else
21738 x_construct_mouse_click (&inev.ie, &event->xbutton, f);
21739
21740 *finish = X_EVENT_DROP;
21741 goto OTHER;
21742 }
21743 else
21744 f = NULL;
21745 }
21746
21747 if (f && xg_event_is_for_scrollbar (f, event, false))
21748 f = 0;
21749 #endif
21750 if (f)
21751 {
21752
21753 if (WINDOWP (f->tab_bar_window)
21754 && WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window)))
21755 {
21756 Lisp_Object window;
21757 int x = event->xbutton.x;
21758 int y = event->xbutton.y;
21759
21760 window = window_from_coordinates (f, x, y, 0, true, true);
21761 tab_bar_p = EQ (window, f->tab_bar_window);
21762
21763 if (tab_bar_p)
21764 {
21765 tab_bar_arg = handle_tab_bar_click
21766 (f, x, y, event->xbutton.type == ButtonPress,
21767 x_x_to_emacs_modifiers (dpyinfo, event->xbutton.state));
21768 x_flush_dirty_back_buffer_on (f);
21769 }
21770 }
21771
21772 #if ! defined (USE_GTK)
21773
21774 if (WINDOWP (f->tool_bar_window)
21775 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
21776 {
21777 Lisp_Object window;
21778 int x = event->xbutton.x;
21779 int y = event->xbutton.y;
21780
21781 window = window_from_coordinates (f, x, y, 0, true, true);
21782 tool_bar_p = (EQ (window, f->tool_bar_window)
21783 && (event->xbutton.type != ButtonRelease
21784 || f->last_tool_bar_item != -1));
21785
21786 if (tool_bar_p && event->xbutton.button < 4)
21787 {
21788 handle_tool_bar_click
21789 (f, x, y, event->xbutton.type == ButtonPress,
21790 x_x_to_emacs_modifiers (dpyinfo, event->xbutton.state));
21791 x_flush_dirty_back_buffer_on (f);
21792 }
21793 }
21794 #endif
21795
21796 if (!(tab_bar_p && NILP (tab_bar_arg)) && !tool_bar_p)
21797 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
21798 if (! popup_activated ())
21799 #endif
21800 {
21801 if (ignore_next_mouse_click_timeout
21802 && dpyinfo == mouse_click_timeout_display)
21803 {
21804 if (event->type == ButtonPress
21805 && event->xbutton.time > ignore_next_mouse_click_timeout)
21806 {
21807 ignore_next_mouse_click_timeout = 0;
21808 x_construct_mouse_click (&inev.ie, &event->xbutton, f);
21809 }
21810 if (event->type == ButtonRelease)
21811 ignore_next_mouse_click_timeout = 0;
21812 }
21813 else
21814 x_construct_mouse_click (&inev.ie, &event->xbutton, f);
21815
21816 if (!NILP (tab_bar_arg))
21817 inev.ie.arg = tab_bar_arg;
21818 }
21819
21820 if (FRAME_X_EMBEDDED_P (f)
21821 && !FRAME_NO_ACCEPT_FOCUS (f))
21822 xembed_send_message (f, event->xbutton.time,
21823 XEMBED_REQUEST_FOCUS, 0, 0, 0);
21824 }
21825 else
21826 {
21827 struct scroll_bar *bar
21828 = x_window_to_scroll_bar (event->xbutton.display,
21829 event->xbutton.window, 2);
21830
21831 #ifdef USE_TOOLKIT_SCROLL_BARS
21832
21833
21834 if (bar && event->xbutton.state & ControlMask)
21835 {
21836 x_scroll_bar_handle_click (bar, event, &inev.ie, Qnil);
21837 *finish = X_EVENT_DROP;
21838 }
21839 #else
21840 if (bar)
21841 x_scroll_bar_handle_click (bar, event, &inev.ie, Qnil);
21842 #endif
21843 }
21844
21845 if (event->type == ButtonPress)
21846 {
21847 dpyinfo->grabbed |= (1 << event->xbutton.button);
21848 dpyinfo->last_mouse_frame = f;
21849 if (f && !tab_bar_p)
21850 f->last_tab_bar_item = -1;
21851 #if ! defined (USE_GTK)
21852 if (f && !tool_bar_p)
21853 f->last_tool_bar_item = -1;
21854 #endif
21855 }
21856 else
21857 dpyinfo->grabbed &= ~(1 << event->xbutton.button);
21858
21859
21860
21861
21862 if (f != 0)
21863 f->mouse_moved = false;
21864
21865 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
21866 f = x_menubar_window_to_frame (dpyinfo, event);
21867
21868
21869
21870
21871 if (! popup_activated ()
21872 #ifdef USE_GTK
21873
21874 && event->xbutton.button < 3
21875 #endif
21876 && f && event->type == ButtonPress
21877
21878
21879 && event->xbutton.x >= 0
21880 && event->xbutton.x < FRAME_PIXEL_WIDTH (f)
21881 && event->xbutton.y >= 0
21882 && event->xbutton.y < FRAME_MENUBAR_HEIGHT (f)
21883 && event->xbutton.same_screen)
21884 {
21885 #ifdef USE_MOTIF
21886 Widget widget;
21887
21888 widget = XtWindowToWidget (dpyinfo->display,
21889 event->xbutton.window);
21890
21891 if (widget && XmIsCascadeButton (widget)
21892 && XtIsSensitive (widget))
21893 {
21894 #endif
21895 if (!f->output_data.x->saved_menu_event)
21896 f->output_data.x->saved_menu_event = xmalloc (sizeof *event);
21897 *f->output_data.x->saved_menu_event = *event;
21898 inev.ie.kind = MENU_BAR_ACTIVATE_EVENT;
21899 XSETFRAME (inev.ie.frame_or_window, f);
21900 *finish = X_EVENT_DROP;
21901 #ifdef USE_MOTIF
21902 }
21903 #endif
21904 }
21905 else
21906 goto OTHER;
21907 #endif
21908 }
21909 break;
21910
21911 case CirculateNotify:
21912 if (x_dnd_in_progress
21913
21914
21915
21916
21917 && !x_dnd_use_toplevels
21918 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
21919 x_dnd_update_state (dpyinfo, dpyinfo->last_user_time);
21920 goto OTHER;
21921
21922 case CirculateRequest:
21923 goto OTHER;
21924
21925 case VisibilityNotify:
21926 f = x_top_window_to_frame (dpyinfo, event->xvisibility.window);
21927
21928 if (f)
21929 FRAME_X_OUTPUT (f)->visibility_state = event->xvisibility.state;
21930
21931 goto OTHER;
21932
21933 case MappingNotify:
21934
21935
21936 switch (event->xmapping.request)
21937 {
21938 case MappingModifier:
21939 x_find_modifier_meanings (dpyinfo);
21940 FALLTHROUGH;
21941 case MappingKeyboard:
21942 XRefreshKeyboardMapping ((XMappingEvent *) &event->xmapping);
21943 }
21944 goto OTHER;
21945
21946 case DestroyNotify:
21947 if (event->xdestroywindow.window
21948 == dpyinfo->net_supported_window)
21949 dpyinfo->net_supported_window = None;
21950
21951 if (event->xdestroywindow.window
21952 == dpyinfo->motif_drag_window)
21953
21954
21955
21956
21957
21958 dpyinfo->motif_drag_window = None;
21959
21960 xft_settings_event (dpyinfo, event);
21961 break;
21962
21963 #ifdef HAVE_XINPUT2
21964 case GenericEvent:
21965 {
21966 if (!dpyinfo->supports_xi2)
21967 goto OTHER;
21968
21969 if (event->xgeneric.extension != dpyinfo->xi2_opcode)
21970
21971 goto OTHER;
21972
21973 bool must_free_data = false;
21974 XIEvent *xi_event = (XIEvent *) event->xcookie.data;
21975
21976
21977
21978 if (!xi_event)
21979 {
21980 if (XGetEventData (dpyinfo->display, &event->xcookie))
21981 must_free_data = true;
21982
21983 xi_event = (XIEvent *) event->xcookie.data;
21984 }
21985
21986 XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
21987
21988 if (!xi_event)
21989 {
21990
21991
21992
21993
21994
21995
21996
21997
21998
21999
22000
22001
22002
22003
22004
22005
22006
22007 if (must_free_data)
22008 XFreeEventData (dpyinfo->display, &event->xcookie);
22009 goto OTHER;
22010 }
22011
22012 switch (event->xcookie.evtype)
22013 {
22014 case XI_FocusIn:
22015 {
22016 XIFocusInEvent *focusin;
22017
22018 focusin = (XIFocusInEvent *) xi_event;
22019 any = x_any_window_to_frame (dpyinfo, focusin->event);
22020
22021 #ifdef USE_GTK
22022
22023
22024
22025
22026
22027
22028
22029
22030
22031
22032
22033
22034 if (EQ (x_set_frame_visibility_more_laxly, Qfocus_in)
22035 || EQ (x_set_frame_visibility_more_laxly, Qt))
22036 #endif
22037 {
22038 f = any;
22039 if (f && FRAME_ICONIFIED_P (f))
22040 {
22041 SET_FRAME_VISIBLE (f, 1);
22042 SET_FRAME_ICONIFIED (f, false);
22043 f->output_data.x->has_been_visible = true;
22044 inev.ie.kind = DEICONIFY_EVENT;
22045 XSETFRAME (inev.ie.frame_or_window, f);
22046 }
22047 }
22048
22049 xi_focus_handle_for_device (dpyinfo, any, xi_event);
22050
22051 goto XI_OTHER;
22052 }
22053
22054 case XI_FocusOut:
22055 {
22056 XIFocusOutEvent *focusout;
22057
22058 focusout = (XIFocusOutEvent *) xi_event;
22059 any = x_any_window_to_frame (dpyinfo, focusout->event);
22060 xi_focus_handle_for_device (dpyinfo, any, xi_event);
22061
22062 goto XI_OTHER;
22063 }
22064
22065 case XI_Enter:
22066 {
22067 XIEnterEvent *enter = (XIEnterEvent *) xi_event;
22068 XMotionEvent ev;
22069 struct xi_device_t *source;
22070
22071 any = x_top_window_to_frame (dpyinfo, enter->event);
22072 source = xi_device_from_id (dpyinfo, enter->sourceid);
22073
22074 ev.x = lrint (enter->event_x);
22075 ev.y = lrint (enter->event_y);
22076 ev.window = enter->event;
22077 ev.time = enter->time;
22078 ev.send_event = enter->send_event;
22079
22080 x_display_set_last_user_time (dpyinfo, enter->time,
22081 enter->send_event, false);
22082
22083 #ifdef USE_MOTIF
22084 use_copy = true;
22085
22086 copy.xcrossing.type = EnterNotify;
22087 copy.xcrossing.serial = enter->serial;
22088 copy.xcrossing.send_event = enter->send_event;
22089 copy.xcrossing.display = dpyinfo->display;
22090 copy.xcrossing.window = enter->event;
22091 copy.xcrossing.root = enter->root;
22092 copy.xcrossing.subwindow = enter->child;
22093 copy.xcrossing.time = enter->time;
22094 copy.xcrossing.x = lrint (enter->event_x);
22095 copy.xcrossing.y = lrint (enter->event_y);
22096 copy.xcrossing.x_root = lrint (enter->root_x);
22097 copy.xcrossing.y_root = lrint (enter->root_y);
22098 copy.xcrossing.mode = enter->mode;
22099 copy.xcrossing.detail = enter->detail;
22100 copy.xcrossing.focus = enter->focus;
22101 copy.xcrossing.state = 0;
22102 copy.xcrossing.same_screen = True;
22103 #endif
22104
22105
22106
22107
22108
22109 if (any)
22110 xi_focus_handle_for_device (dpyinfo, any, xi_event);
22111
22112 if (!any)
22113 any = x_any_window_to_frame (dpyinfo, enter->event);
22114
22115 #ifdef HAVE_XINPUT2_1
22116
22117
22118
22119
22120
22121
22122
22123
22124
22125 if (enter->mode != XINotifyUngrab
22126 && enter->mode != XINotifyGrab
22127 && enter->mode != XINotifyPassiveGrab
22128 && enter->mode != XINotifyPassiveUngrab)
22129 xi_reset_scroll_valuators_for_device_id (dpyinfo,
22130 enter->deviceid);
22131 #endif
22132
22133 {
22134 #ifdef HAVE_XWIDGETS
22135 struct xwidget_view *xwidget_view;
22136
22137 xwidget_view = xwidget_view_from_window (enter->event);
22138
22139 if (xwidget_view)
22140 {
22141 xwidget_motion_or_crossing (xwidget_view, event);
22142
22143 goto XI_OTHER;
22144 }
22145 #endif
22146 }
22147
22148 f = any;
22149
22150 if (f && enter->event == FRAME_X_WINDOW (f))
22151 xi_compute_root_window_offset_enter (f, enter);
22152
22153 if (f && x_mouse_click_focus_ignore_position)
22154 {
22155 ignore_next_mouse_click_timeout = (enter->time
22156 + x_mouse_click_focus_ignore_time);
22157 mouse_click_timeout_display = dpyinfo;
22158 }
22159
22160
22161
22162 if (f && !f->output_data.x->hourglass_p)
22163 x_note_mouse_movement (f, &ev, source ? source->name : Qnil);
22164 #ifdef USE_GTK
22165
22166
22167 if (!f && dpyinfo->last_mouse_glyph_frame)
22168 x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &ev,
22169 source ? source->name : Qnil);
22170 #endif
22171 goto XI_OTHER;
22172 }
22173
22174 case XI_Leave:
22175 {
22176 XILeaveEvent *leave;
22177 struct xi_device_t *device;
22178
22179 leave = (XILeaveEvent *) xi_event;
22180 #ifdef USE_GTK
22181 struct xi_device_t *source;
22182 XMotionEvent ev;
22183
22184 ev.x = lrint (leave->event_x);
22185 ev.y = lrint (leave->event_y);
22186 ev.window = leave->event;
22187 ev.time = leave->time;
22188 ev.send_event = leave->send_event;
22189 #endif
22190
22191 any = x_top_window_to_frame (dpyinfo, leave->event);
22192
22193 #ifdef USE_GTK
22194 source = xi_device_from_id (dpyinfo, leave->sourceid);
22195 #endif
22196 device = xi_device_from_id (dpyinfo, leave->deviceid);
22197
22198 if (device)
22199 xi_report_motion_window_clear (device);
22200
22201
22202
22203
22204
22205
22206 #ifdef USE_X_TOOLKIT
22207 if (popup_activated ()
22208 && (leave->mode == XINotifyPassiveUngrab
22209 || leave->mode == XINotifyUngrab))
22210 any = x_any_window_to_frame (dpyinfo, leave->event);
22211 #endif
22212
22213 #ifdef USE_MOTIF
22214 use_copy = true;
22215
22216 copy.xcrossing.type = LeaveNotify;
22217 copy.xcrossing.serial = leave->serial;
22218 copy.xcrossing.send_event = leave->send_event;
22219 copy.xcrossing.display = dpyinfo->display;
22220 copy.xcrossing.window = leave->event;
22221 copy.xcrossing.root = leave->root;
22222 copy.xcrossing.subwindow = leave->child;
22223 copy.xcrossing.time = leave->time;
22224 copy.xcrossing.x = lrint (leave->event_x);
22225 copy.xcrossing.y = lrint (leave->event_y);
22226 copy.xcrossing.x_root = lrint (leave->root_x);
22227 copy.xcrossing.y_root = lrint (leave->root_y);
22228 copy.xcrossing.mode = leave->mode;
22229 copy.xcrossing.detail = leave->detail;
22230 copy.xcrossing.focus = leave->focus;
22231 copy.xcrossing.state = 0;
22232 copy.xcrossing.same_screen = True;
22233 #endif
22234
22235
22236
22237
22238
22239
22240
22241
22242
22243
22244
22245
22246
22247
22248
22249
22250
22251
22252
22253 #ifdef HAVE_XINPUT2_1
22254
22255
22256
22257
22258
22259
22260
22261
22262
22263 if (leave->mode != XINotifyUngrab
22264 && leave->mode != XINotifyGrab
22265 && leave->mode != XINotifyPassiveUngrab
22266 && leave->mode != XINotifyPassiveGrab)
22267 xi_reset_scroll_valuators_for_device_id (dpyinfo,
22268 leave->deviceid);
22269 #endif
22270
22271 x_display_set_last_user_time (dpyinfo, leave->time,
22272 leave->send_event, false);
22273
22274 #ifdef HAVE_XWIDGETS
22275 {
22276 struct xwidget_view *xvw;
22277
22278 xvw = xwidget_view_from_window (leave->event);
22279
22280 if (xvw)
22281 {
22282 *finish = X_EVENT_DROP;
22283 xwidget_motion_or_crossing (xvw, event);
22284
22285 goto XI_OTHER;
22286 }
22287 }
22288 #endif
22289
22290 if (any)
22291 xi_focus_handle_for_device (dpyinfo, any, xi_event);
22292
22293 #ifndef USE_X_TOOLKIT
22294 f = x_top_window_to_frame (dpyinfo, leave->event);
22295 #else
22296
22297
22298 f = x_window_to_frame (dpyinfo, leave->event);
22299
22300 if (!f)
22301 f = x_top_window_to_frame (dpyinfo, leave->event);
22302 #endif
22303
22304 if (f)
22305 {
22306
22307
22308
22309
22310
22311 if (f == dpyinfo->last_mouse_motion_frame)
22312 dpyinfo->last_mouse_motion_frame = NULL;
22313
22314
22315
22316 if (f == dpyinfo->last_mouse_glyph_frame)
22317 dpyinfo->last_mouse_glyph_frame = NULL;
22318
22319 if (f == hlinfo->mouse_face_mouse_frame)
22320 {
22321
22322
22323 clear_mouse_face (hlinfo);
22324 hlinfo->mouse_face_mouse_frame = 0;
22325 x_flush_dirty_back_buffer_on (f);
22326 }
22327
22328
22329
22330
22331
22332 if (any_help_event_p
22333
22334
22335
22336
22337 && !((EQ (track_mouse, Qdrag_source)
22338 || EQ (track_mouse, Qdropping))
22339 && gui_mouse_grabbed (dpyinfo)))
22340 do_help = -1;
22341
22342 if (f && leave->event == FRAME_X_WINDOW (f))
22343 xi_compute_root_window_offset_enter (f, leave);
22344 }
22345 #ifdef USE_GTK
22346
22347 else if (dpyinfo->last_mouse_glyph_frame)
22348 x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &ev,
22349 source ? source->name : Qnil);
22350 #endif
22351 goto XI_OTHER;
22352 }
22353
22354 case XI_Motion:
22355 {
22356 struct xi_device_t *device, *source;
22357 #ifdef HAVE_XINPUT2_1
22358 XIValuatorState *states;
22359 double *values;
22360 bool found_valuator = false;
22361 bool other_valuators_found = false;
22362 #endif
22363
22364 XMotionEvent ev;
22365 xm_top_level_leave_message lmsg;
22366 xm_top_level_enter_message emsg;
22367 xm_drag_motion_message dmsg;
22368 unsigned int dnd_state;
22369
22370 source = xi_device_from_id (dpyinfo, xev->sourceid);
22371
22372 #ifdef HAVE_XINPUT2_1
22373 states = &xev->valuators;
22374 values = states->values;
22375 #endif
22376
22377 device = xi_device_from_id (dpyinfo, xev->deviceid);
22378
22379 if (!device)
22380 goto XI_OTHER;
22381
22382 #ifdef HAVE_XINPUT2_2
22383 if (xev->flags & XIPointerEmulated)
22384 goto XI_OTHER;
22385 #endif
22386
22387 #ifdef HAVE_XINPUT2_1
22388 #ifdef HAVE_XWIDGETS
22389 struct xwidget_view *xv = xwidget_view_from_window (xev->event);
22390 double xv_total_x = 0.0;
22391 double xv_total_y = 0.0;
22392 #endif
22393 double total_x = 0.0;
22394 double total_y = 0.0;
22395
22396 int real_x, real_y;
22397
22398 for (int i = 0; i < states->mask_len * 8; i++)
22399 {
22400 if (XIMaskIsSet (states->mask, i))
22401 {
22402 struct xi_scroll_valuator_t *val;
22403 double delta, scroll_unit;
22404 int scroll_height;
22405 Lisp_Object window;
22406 struct scroll_bar *bar;
22407
22408 bar = NULL;
22409
22410
22411
22412
22413 delta = x_get_scroll_valuator_delta (dpyinfo, device,
22414 i, *values, &val);
22415 values++;
22416
22417 if (!val)
22418 {
22419 other_valuators_found = true;
22420 continue;
22421 }
22422
22423 if (delta != DBL_MAX)
22424 {
22425 if (!f)
22426 {
22427 f = x_any_window_to_frame (dpyinfo, xev->event);
22428
22429 if (!f)
22430 {
22431 #if defined USE_MOTIF || !defined USE_TOOLKIT_SCROLL_BARS
22432 bar = x_window_to_scroll_bar (dpyinfo->display,
22433 xev->event, 2);
22434
22435 if (bar)
22436 f = WINDOW_XFRAME (XWINDOW (bar->window));
22437
22438 if (!f)
22439 #endif
22440 goto XI_OTHER;
22441 }
22442 }
22443
22444 #ifdef USE_GTK
22445 if (f && xg_event_is_for_scrollbar (f, event, true))
22446 *finish = X_EVENT_DROP;
22447 #endif
22448
22449 if (FRAME_X_WINDOW (f) != xev->event)
22450 {
22451 if (!bar)
22452 bar = x_window_to_scroll_bar (dpyinfo->display, xev->event, 2);
22453
22454
22455
22456
22457
22458 if (bar)
22459 {
22460 real_x = lrint (xev->event_x + bar->left);
22461 real_y = lrint (xev->event_y + bar->top);
22462 }
22463 else
22464 x_translate_coordinates (f,
22465 lrint (xev->root_x),
22466 lrint (xev->root_y),
22467 &real_x, &real_y);
22468 }
22469 else
22470 {
22471 real_x = lrint (xev->event_x);
22472 real_y = lrint (xev->event_y);
22473 }
22474
22475 #ifdef HAVE_XWIDGETS
22476 if (xv)
22477 {
22478 if (val->horizontal)
22479 xv_total_x += delta;
22480 else
22481 xv_total_y += delta;
22482
22483 found_valuator = true;
22484 continue;
22485 }
22486 #endif
22487
22488 if (delta == 0.0)
22489 found_valuator = true;
22490
22491 if (signbit (delta) != signbit (val->emacs_value))
22492 val->emacs_value = 0;
22493
22494 val->emacs_value += delta;
22495
22496 if (mwheel_coalesce_scroll_events
22497 && (fabs (val->emacs_value) < 1)
22498 && (fabs (delta) > 0))
22499 continue;
22500
22501 window = window_from_coordinates (f, real_x, real_y, NULL,
22502 false, false);
22503
22504 if (WINDOWP (window))
22505 scroll_height = XWINDOW (window)->pixel_height;
22506 else
22507
22508
22509
22510 scroll_height = FRAME_PIXEL_HEIGHT (f);
22511
22512 scroll_unit = pow (scroll_height, 2.0 / 3.0);
22513
22514 if (NUMBERP (Vx_scroll_event_delta_factor))
22515 scroll_unit *= XFLOATINT (Vx_scroll_event_delta_factor);
22516
22517 if (val->horizontal)
22518 total_x += val->emacs_value * scroll_unit;
22519 else
22520 total_y += val->emacs_value * scroll_unit;
22521
22522 found_valuator = true;
22523 val->emacs_value = 0;
22524 }
22525 }
22526 }
22527
22528 #ifdef HAVE_XWIDGETS
22529 if (xv)
22530 {
22531 unsigned int state;
22532
22533 state = xi_convert_event_state (xev);
22534 x_display_set_last_user_time (dpyinfo, xev->time,
22535 xev->send_event, true);
22536
22537 if (found_valuator)
22538 xwidget_scroll (xv, xev->event_x, xev->event_y,
22539 -xv_total_x, -xv_total_y, state,
22540 xev->time, (xv_total_x == 0.0
22541 && xv_total_y == 0.0));
22542 else
22543 xwidget_motion_notify (xv, xev->event_x, xev->event_y,
22544 xev->root_x, xev->root_y, state,
22545 xev->time);
22546
22547 goto XI_OTHER;
22548 }
22549 else
22550 {
22551 #endif
22552 if (found_valuator)
22553 {
22554 x_display_set_last_user_time (dpyinfo, xev->time,
22555 xev->send_event, true);
22556
22557
22558 #if defined USE_GTK && !defined HAVE_GTK3
22559
22560
22561
22562
22563
22564
22565
22566
22567 if (xev->child != None
22568 && xev->child != FRAME_X_WINDOW (f))
22569 goto XI_OTHER;
22570 #endif
22571
22572
22573
22574
22575 if (x_dnd_in_progress
22576
22577
22578
22579
22580
22581 && xev->deviceid == x_dnd_pointer_device
22582 && (command_loop_level + minibuf_level
22583 <= x_dnd_recursion_depth)
22584 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
22585 goto XI_OTHER;
22586
22587 if (fabs (total_x) > 0 || fabs (total_y) > 0)
22588 {
22589 inev.ie.kind = (fabs (total_y) >= fabs (total_x)
22590 ? WHEEL_EVENT : HORIZ_WHEEL_EVENT);
22591 inev.ie.timestamp = xev->time;
22592
22593 XSETINT (inev.ie.x, lrint (real_x));
22594 XSETINT (inev.ie.y, lrint (real_y));
22595 XSETFRAME (inev.ie.frame_or_window, f);
22596
22597 inev.ie.modifiers = (signbit (fabs (total_y) >= fabs (total_x)
22598 ? total_y : total_x)
22599 ? down_modifier : up_modifier);
22600 inev.ie.modifiers
22601 |= x_x_to_emacs_modifiers (dpyinfo,
22602 xev->mods.effective);
22603 inev.ie.arg = list3 (Qnil,
22604 make_float (total_x),
22605 make_float (total_y));
22606 }
22607 else
22608 {
22609 inev.ie.kind = TOUCH_END_EVENT;
22610 inev.ie.timestamp = xev->time;
22611
22612 XSETINT (inev.ie.x, lrint (real_x));
22613 XSETINT (inev.ie.y, lrint (real_y));
22614 XSETFRAME (inev.ie.frame_or_window, f);
22615 }
22616
22617 if (source && !NILP (source->name))
22618 inev.ie.device = source->name;
22619
22620 if (!other_valuators_found)
22621 goto XI_OTHER;
22622 }
22623 #ifdef HAVE_XWIDGETS
22624 }
22625 #endif
22626 #endif
22627
22628 if (!xi_position_changed (device, xev))
22629 goto XI_OTHER;
22630
22631 ev.x = lrint (xev->event_x);
22632 ev.y = lrint (xev->event_y);
22633 ev.window = xev->event;
22634 ev.time = xev->time;
22635 ev.send_event = xev->send_event;
22636
22637 #ifdef USE_MOTIF
22638 use_copy = true;
22639
22640 copy.xmotion.type = MotionNotify;
22641 copy.xmotion.serial = xev->serial;
22642 copy.xmotion.send_event = xev->send_event;
22643 copy.xmotion.display = dpyinfo->display;
22644 copy.xmotion.window = xev->event;
22645 copy.xmotion.root = xev->root;
22646 copy.xmotion.subwindow = xev->child;
22647 copy.xmotion.time = xev->time;
22648 copy.xmotion.x = lrint (xev->event_x);
22649 copy.xmotion.y = lrint (xev->event_y);
22650 copy.xmotion.x_root = lrint (xev->root_x);
22651 copy.xmotion.y_root = lrint (xev->root_y);
22652 copy.xmotion.state = xi_convert_event_state (xev);
22653
22654 copy.xmotion.is_hint = False;
22655 copy.xmotion.same_screen = True;
22656 #endif
22657
22658 previous_help_echo_string = help_echo_string;
22659 help_echo_string = Qnil;
22660
22661 if (hlinfo->mouse_face_hidden)
22662 {
22663 hlinfo->mouse_face_hidden = false;
22664 clear_mouse_face (hlinfo);
22665 }
22666
22667 f = mouse_or_wdesc_frame (dpyinfo, xev->event);
22668
22669 if (f && xev->event == FRAME_X_WINDOW (f))
22670
22671
22672 xi_compute_root_window_offset (f, xev);
22673
22674 if (x_dnd_in_progress
22675
22676
22677
22678
22679
22680 && (command_loop_level + minibuf_level
22681 <= x_dnd_recursion_depth)
22682 && xev->deviceid == x_dnd_pointer_device
22683 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
22684 {
22685 Window target, toplevel;
22686 int target_proto, motif_style;
22687 XRectangle *r;
22688 bool was_frame;
22689
22690
22691 clear_mouse_face (hlinfo);
22692 hlinfo->mouse_face_hidden = true;
22693
22694
22695
22696
22697
22698
22699 if (f)
22700 {
22701 XTtoggle_invisible_pointer (f, false);
22702
22703 r = &dpyinfo->last_mouse_glyph;
22704
22705
22706
22707 if (f != dpyinfo->last_mouse_glyph_frame
22708 || lrint (xev->event_x) < r->x
22709 || lrint (xev->event_x) >= r->x + r->width
22710 || lrint (xev->event_y) < r->y
22711 || lrint (xev->event_y) >= r->y + r->height)
22712 {
22713 f->mouse_moved = true;
22714 f->last_mouse_device = (source ? source->name
22715 : Qnil);
22716 dpyinfo->last_mouse_scroll_bar = NULL;
22717
22718 remember_mouse_glyph (f, lrint (xev->event_x),
22719 lrint (xev->event_y), r);
22720 dpyinfo->last_mouse_glyph_frame = f;
22721 }
22722 }
22723
22724 if (xev->root == dpyinfo->root_window)
22725 target = x_dnd_get_target_window (dpyinfo,
22726 lrint (xev->root_x),
22727 lrint (xev->root_y),
22728 &target_proto,
22729 &motif_style,
22730 &toplevel,
22731 &was_frame);
22732 else
22733 target = x_dnd_fill_empty_target (&target_proto,
22734 &motif_style,
22735 &toplevel,
22736 &was_frame);
22737
22738 if (toplevel != x_dnd_last_seen_toplevel)
22739 {
22740 if (toplevel != FRAME_OUTER_WINDOW (x_dnd_frame)
22741 && x_dnd_return_frame == 1)
22742 x_dnd_return_frame = 2;
22743
22744 if (x_dnd_return_frame == 2
22745 && x_any_window_to_frame (dpyinfo, toplevel))
22746 {
22747 if (x_dnd_last_seen_window != None
22748 && x_dnd_last_protocol_version != -1
22749 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
22750 x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window,
22751 x_dnd_last_seen_toplevel);
22752 else if (x_dnd_last_seen_window != None
22753 && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
22754 && !x_dnd_disable_motif_drag
22755 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
22756 {
22757 if (!x_dnd_motif_setup_p)
22758 xm_setup_drag_info (dpyinfo, x_dnd_frame);
22759
22760 lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
22761 XM_DRAG_REASON_TOP_LEVEL_LEAVE);
22762 lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
22763 lmsg.zero = 0;
22764 lmsg.timestamp = xev->time;
22765 lmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
22766
22767 if (x_dnd_motif_setup_p)
22768 xm_send_top_level_leave_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
22769 x_dnd_last_seen_window, &lmsg);
22770 }
22771
22772 x_dnd_end_window = x_dnd_last_seen_window;
22773 x_dnd_last_seen_window = None;
22774 x_dnd_last_seen_toplevel = None;
22775 x_dnd_in_progress = false;
22776 x_dnd_return_frame_object
22777 = x_any_window_to_frame (dpyinfo, toplevel);
22778 x_dnd_return_frame = 3;
22779 x_dnd_waiting_for_finish = false;
22780 target = None;
22781 }
22782 }
22783
22784 if (target != x_dnd_last_seen_window)
22785 {
22786 if (x_dnd_last_seen_window != None
22787 && x_dnd_last_protocol_version != -1
22788 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
22789 x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window,
22790 x_dnd_last_seen_toplevel);
22791 else if (x_dnd_last_seen_window != None
22792 && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
22793 && !x_dnd_disable_motif_drag
22794 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
22795 {
22796 if (!x_dnd_motif_setup_p)
22797 xm_setup_drag_info (dpyinfo, x_dnd_frame);
22798
22799
22800
22801
22802
22803
22804
22805
22806 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
22807 XM_DRAG_REASON_DRAG_MOTION);
22808 dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
22809 dmsg.side_effects
22810 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
22811 x_dnd_wanted_action),
22812 XM_DROP_SITE_NONE, x_dnd_motif_operations,
22813 XM_DROP_ACTION_DROP_CANCEL);
22814 dmsg.timestamp = xev->time;
22815 dmsg.x = lrint (xev->root_x);
22816 dmsg.y = lrint (xev->root_y);
22817
22818 lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
22819 XM_DRAG_REASON_TOP_LEVEL_LEAVE);
22820 lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
22821 lmsg.zero = 0;
22822 lmsg.timestamp = xev->time;
22823 lmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
22824
22825 if (x_dnd_motif_setup_p)
22826 {
22827 xm_send_drag_motion_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
22828 x_dnd_last_seen_window, &dmsg);
22829 xm_send_top_level_leave_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
22830 x_dnd_last_seen_window, &lmsg);
22831 }
22832 }
22833
22834 x_dnd_action = None;
22835 x_dnd_last_seen_toplevel = toplevel;
22836 x_dnd_last_seen_window = target;
22837 x_dnd_last_protocol_version = target_proto;
22838 x_dnd_last_motif_style = motif_style;
22839 x_dnd_last_window_is_frame = was_frame;
22840
22841 if (target != None && x_dnd_last_protocol_version != -1)
22842 x_dnd_send_enter (x_dnd_frame, target,
22843 x_dnd_last_seen_toplevel,
22844 x_dnd_last_protocol_version);
22845 else if (target != None && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
22846 && !x_dnd_disable_motif_drag)
22847 {
22848 if (!x_dnd_motif_setup_p)
22849 xm_setup_drag_info (dpyinfo, x_dnd_frame);
22850
22851 emsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
22852 XM_DRAG_REASON_TOP_LEVEL_ENTER);
22853 emsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
22854 emsg.zero = 0;
22855 emsg.timestamp = xev->time;
22856 emsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
22857 emsg.index_atom = x_dnd_motif_atom;
22858
22859 if (x_dnd_motif_setup_p)
22860 xm_send_top_level_enter_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
22861 target, &emsg);
22862 }
22863 }
22864 else
22865 x_dnd_last_seen_toplevel = toplevel;
22866
22867 if (x_dnd_last_window_is_frame && target != None)
22868 x_dnd_note_self_position (dpyinfo, target,
22869 lrint (xev->root_x),
22870 lrint (xev->root_y));
22871 else if (x_dnd_last_protocol_version != -1 && target != None)
22872 {
22873 dnd_state = xi_convert_event_state (xev);
22874
22875 x_dnd_send_position (x_dnd_frame, target,
22876 x_dnd_last_seen_toplevel,
22877 x_dnd_last_protocol_version,
22878 lrint (xev->root_x),
22879 lrint (xev->root_y),
22880 x_dnd_selection_timestamp,
22881 x_dnd_wanted_action, 0,
22882 dnd_state);
22883 }
22884 else if (XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) && target != None
22885 && !x_dnd_disable_motif_drag)
22886 {
22887 if (!x_dnd_motif_setup_p)
22888 xm_setup_drag_info (dpyinfo, x_dnd_frame);
22889
22890 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
22891 XM_DRAG_REASON_DRAG_MOTION);
22892 dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
22893 dmsg.side_effects
22894 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
22895 x_dnd_wanted_action),
22896 XM_DROP_SITE_VALID, x_dnd_motif_operations,
22897 (!x_dnd_xm_use_help
22898 ? XM_DROP_ACTION_DROP
22899 : XM_DROP_ACTION_DROP_HELP));
22900 dmsg.timestamp = xev->time;
22901 dmsg.x = lrint (xev->root_x);
22902 dmsg.y = lrint (xev->root_y);
22903
22904 if (x_dnd_motif_setup_p)
22905 xm_send_drag_motion_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
22906 target, &dmsg);
22907 }
22908
22909 x_dnd_update_tooltip_position (xev->root_x, xev->root_y);
22910
22911 goto XI_OTHER;
22912 }
22913
22914 #ifdef USE_GTK
22915 if (f && xg_event_is_for_scrollbar (f, event, false))
22916 f = 0;
22917 #endif
22918 if (f)
22919 {
22920 if (xev->event != FRAME_X_WINDOW (f))
22921 {
22922 x_translate_coordinates (f, lrint (xev->root_x),
22923 lrint (xev->root_y),
22924 &ev.x, &ev.y);
22925 ev.window = FRAME_X_WINDOW (f);
22926 }
22927
22928
22929
22930
22931 if (!NILP (Vmouse_autoselect_window)
22932 && !popup_activated ()
22933
22934
22935
22936
22937
22938 && !MINI_WINDOW_P (XWINDOW (selected_window))
22939
22940
22941 && (f == XFRAME (selected_frame)
22942 || !NILP (focus_follows_mouse)))
22943 {
22944 static Lisp_Object last_mouse_window;
22945 Lisp_Object window = window_from_coordinates (f, ev.x, ev.y, 0, false, false);
22946
22947
22948
22949
22950
22951
22952
22953
22954
22955 if (WINDOWP (window)
22956 && !EQ (window, last_mouse_window)
22957 && !EQ (window, selected_window))
22958 {
22959 inev.ie.kind = SELECT_WINDOW_EVENT;
22960 inev.ie.frame_or_window = window;
22961
22962 if (source)
22963 inev.ie.device = source->name;
22964 }
22965
22966
22967 last_mouse_window = window;
22968 }
22969
22970 if (!x_note_mouse_movement (f, &ev, source ? source->name : Qnil))
22971 help_echo_string = previous_help_echo_string;
22972 }
22973 else
22974 {
22975 #ifndef USE_TOOLKIT_SCROLL_BARS
22976 struct scroll_bar *bar
22977 = x_window_to_scroll_bar (dpyinfo->display, xev->event, 2);
22978
22979 if (bar)
22980 x_scroll_bar_note_movement (bar, &ev);
22981 #endif
22982
22983
22984
22985 clear_mouse_face (hlinfo);
22986 }
22987
22988
22989
22990 if (!NILP (help_echo_string)
22991 || !NILP (previous_help_echo_string))
22992 {
22993
22994
22995
22996 gen_help_device = device;
22997 gen_help_time = xev->time;
22998
22999 do_help = 1;
23000 }
23001
23002 if (f)
23003 x_flush_dirty_back_buffer_on (f);
23004 goto XI_OTHER;
23005 }
23006
23007 case XI_ButtonRelease:
23008 case XI_ButtonPress:
23009 {
23010
23011
23012 Lisp_Object tab_bar_arg = Qnil;
23013 bool tab_bar_p = false;
23014 bool tool_bar_p = false;
23015 struct xi_device_t *device, *source;
23016 #ifdef HAVE_XWIDGETS
23017 struct xwidget_view *xvw;
23018 #endif
23019
23020 XButtonEvent bv;
23021 bool dnd_grab = false;
23022 int dnd_state;
23023
23024 if (x_dnd_in_progress
23025 && (command_loop_level + minibuf_level
23026 <= x_dnd_recursion_depth)
23027 && xev->deviceid == x_dnd_pointer_device
23028 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
23029 {
23030 f = mouse_or_wdesc_frame (dpyinfo, xev->event);
23031 device = xi_device_from_id (dpyinfo, xev->deviceid);
23032
23033 if (f && xev->event == FRAME_X_WINDOW (f))
23034
23035
23036
23037 xi_compute_root_window_offset (f, xev);
23038
23039
23040
23041
23042 #ifdef XIPointerEmulated
23043 if (!(xev->flags & XIPointerEmulated))
23044 {
23045 #endif
23046 if (xev->evtype == XI_ButtonPress)
23047 {
23048 x_display_set_last_user_time (dpyinfo, xev->time,
23049 xev->send_event, true);
23050
23051 dpyinfo->grabbed |= (1 << xev->detail);
23052 dpyinfo->last_mouse_frame = f;
23053
23054 if (device)
23055 device->grab |= (1 << xev->detail);
23056
23057 if (f)
23058 f->last_tab_bar_item = -1;
23059 #if ! defined (USE_GTK)
23060 if (f)
23061 f->last_tool_bar_item = -1;
23062 #endif
23063 }
23064 else
23065 {
23066 dpyinfo->grabbed &= ~(1 << xev->detail);
23067 if (device)
23068 device->grab &= ~(1 << xev->detail);
23069 }
23070 #ifdef XIPointerEmulated
23071 }
23072 #endif
23073
23074 if (f && device)
23075 xi_handle_interaction (dpyinfo, f, device,
23076 xev->time);
23077
23078 if (xev->evtype == XI_ButtonPress
23079 && x_dnd_last_seen_window != None)
23080 {
23081 dnd_state = xi_convert_event_state (xev);
23082
23083 if (x_dnd_last_window_is_frame)
23084 {
23085 #ifdef XI_PointerEmulated
23086
23087
23088
23089
23090 if (xev->flags & XIPointerEmulated)
23091 x_display_set_last_user_time (dpyinfo, xev->time,
23092 xev->send_event, true);
23093 #endif
23094 x_dnd_note_self_wheel (dpyinfo,
23095 x_dnd_last_seen_window,
23096 lrint (xev->root_x),
23097 lrint (xev->root_y),
23098 xev->detail, dnd_state,
23099 xev->time);
23100 }
23101 else
23102 x_dnd_send_position (x_dnd_frame,
23103 x_dnd_last_seen_window,
23104 x_dnd_last_seen_toplevel,
23105 x_dnd_last_protocol_version,
23106 lrint (xev->root_x),
23107 lrint (xev->root_y),
23108 xev->time, x_dnd_wanted_action,
23109 xev->detail, dnd_state);
23110
23111 goto OTHER;
23112 }
23113
23114 if (xev->evtype == XI_ButtonRelease)
23115 {
23116 for (int i = 0; i < xev->buttons.mask_len * 8; ++i)
23117 {
23118 if (i != xev->detail && XIMaskIsSet (xev->buttons.mask, i))
23119 dnd_grab = true;
23120 }
23121
23122 if (!dnd_grab)
23123 {
23124 x_dnd_end_window = x_dnd_last_seen_window;
23125 x_dnd_in_progress = false;
23126
23127
23128
23129
23130 if (x_dnd_update_tooltip
23131 && FRAMEP (tip_frame)
23132 && FRAME_LIVE_P (XFRAME (tip_frame))
23133 && (FRAME_X_DISPLAY (XFRAME (tip_frame))
23134 == FRAME_X_DISPLAY (x_dnd_frame)))
23135 Fx_hide_tip ();
23136
23137
23138
23139
23140
23141
23142
23143 x_dnd_finish_frame = x_dnd_frame;
23144
23145 if (x_dnd_last_seen_window != None
23146 && x_dnd_last_window_is_frame)
23147 {
23148 x_dnd_waiting_for_finish = false;
23149 x_dnd_note_self_drop (dpyinfo, x_dnd_last_seen_window,
23150 lrint (xev->root_x),
23151 lrint (xev->root_y), xev->time);
23152 }
23153 else if (x_dnd_last_seen_window != None
23154 && x_dnd_last_protocol_version != -1)
23155 {
23156 x_dnd_pending_finish_target = x_dnd_last_seen_toplevel;
23157 x_dnd_waiting_for_finish_proto = x_dnd_last_protocol_version;
23158
23159 x_dnd_waiting_for_finish
23160 = x_dnd_do_drop (x_dnd_last_seen_window,
23161 x_dnd_last_seen_toplevel,
23162 x_dnd_last_protocol_version);
23163 x_dnd_finish_display = dpyinfo->display;
23164 }
23165 else if (x_dnd_last_seen_window != None)
23166 {
23167 xm_drop_start_message dmsg;
23168 xm_drag_receiver_info drag_receiver_info;
23169
23170 if (!xm_read_drag_receiver_info (dpyinfo, x_dnd_last_seen_window,
23171 &drag_receiver_info)
23172 && !x_dnd_disable_motif_protocol
23173 && drag_receiver_info.protocol_style != XM_DRAG_STYLE_NONE
23174 && (x_dnd_allow_current_frame
23175 || x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame)))
23176 {
23177 if (!x_dnd_motif_setup_p)
23178 xm_setup_drag_info (dpyinfo, x_dnd_frame);
23179
23180 if (x_dnd_motif_setup_p)
23181 {
23182 memset (&dmsg, 0, sizeof dmsg);
23183
23184 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
23185 XM_DRAG_REASON_DROP_START);
23186 dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST;
23187 dmsg.side_effects
23188 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
23189 x_dnd_wanted_action),
23190 XM_DROP_SITE_VALID, x_dnd_motif_operations,
23191 (!x_dnd_xm_use_help
23192 ? XM_DROP_ACTION_DROP
23193 : XM_DROP_ACTION_DROP_HELP));
23194 dmsg.timestamp = xev->time;
23195 dmsg.x = lrint (xev->root_x);
23196 dmsg.y = lrint (xev->root_y);
23197
23198
23199
23200
23201
23202
23203
23204
23205
23206 dmsg.index_atom = x_dnd_motif_atom;
23207 dmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
23208
23209 if (!XM_DRAG_STYLE_IS_DROP_ONLY (drag_receiver_info.protocol_style))
23210 x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (x_dnd_frame),
23211 x_dnd_frame, x_dnd_last_seen_window,
23212 xev->time);
23213
23214 xm_send_drop_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
23215 x_dnd_last_seen_window, &dmsg);
23216
23217 x_dnd_waiting_for_finish = true;
23218 x_dnd_waiting_for_motif_finish_display = dpyinfo;
23219 x_dnd_waiting_for_motif_finish = 1;
23220 x_dnd_finish_display = dpyinfo->display;
23221 }
23222 }
23223 else
23224 x_dnd_send_unsupported_drop (dpyinfo, (x_dnd_last_seen_toplevel != None
23225 ? x_dnd_last_seen_toplevel
23226 : x_dnd_last_seen_window),
23227 lrint (xev->root_x),
23228 lrint (xev->root_y), xev->time);
23229 }
23230 else if (x_dnd_last_seen_toplevel != None)
23231 x_dnd_send_unsupported_drop (dpyinfo,
23232 x_dnd_last_seen_toplevel,
23233 lrint (xev->root_x),
23234 lrint (xev->root_y),
23235 xev->time);
23236
23237 x_dnd_last_protocol_version = -1;
23238 x_dnd_last_motif_style = XM_DRAG_STYLE_NONE;
23239 x_dnd_last_seen_window = None;
23240 x_dnd_last_seen_toplevel = None;
23241 x_dnd_last_window_is_frame = false;
23242 x_dnd_frame = NULL;
23243
23244 goto XI_OTHER;
23245 }
23246 }
23247 }
23248
23249 if (x_dnd_in_progress
23250 && (command_loop_level + minibuf_level
23251 <= x_dnd_recursion_depth))
23252 goto XI_OTHER;
23253
23254 #ifdef USE_MOTIF
23255 #ifdef USE_TOOLKIT_SCROLL_BARS
23256 struct scroll_bar *bar
23257 = x_window_to_scroll_bar (dpyinfo->display,
23258 xev->event, 2);
23259 #endif
23260
23261 use_copy = true;
23262 copy.xbutton.type = (xev->evtype == XI_ButtonPress
23263 ? ButtonPress : ButtonRelease);
23264 copy.xbutton.serial = xev->serial;
23265 copy.xbutton.send_event = xev->send_event;
23266 copy.xbutton.display = dpyinfo->display;
23267 copy.xbutton.window = xev->event;
23268 copy.xbutton.root = xev->root;
23269 copy.xbutton.subwindow = xev->child;
23270 copy.xbutton.time = xev->time;
23271 copy.xbutton.x = lrint (xev->event_x);
23272 copy.xbutton.y = lrint (xev->event_y);
23273 copy.xbutton.x_root = lrint (xev->root_x);
23274 copy.xbutton.y_root = lrint (xev->root_y);
23275 copy.xbutton.state = xi_convert_event_state (xev);
23276 copy.xbutton.button = xev->detail;
23277 copy.xbutton.same_screen = True;
23278
23279 #elif defined USE_GTK && !defined HAVE_GTK3
23280 copy = gdk_event_new (xev->evtype == XI_ButtonPress
23281 ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE);
23282
23283 copy->button.window = gdk_x11_window_lookup_for_display (gdpy, xev->event);
23284 copy->button.send_event = xev->send_event;
23285 copy->button.time = xev->time;
23286 copy->button.x = xev->event_x;
23287 copy->button.y = xev->event_y;
23288 copy->button.x_root = xev->root_x;
23289 copy->button.y_root = xev->root_y;
23290 copy->button.state = xi_convert_event_state (xev);
23291 copy->button.button = xev->detail;
23292
23293 if (!copy->button.window)
23294 emacs_abort ();
23295
23296 g_object_ref (copy->button.window);
23297
23298 if (popup_activated ())
23299 {
23300
23301
23302
23303 if (xev->detail > 3)
23304 *finish = X_EVENT_DROP;
23305
23306 if (xev->evtype == XI_ButtonRelease)
23307 goto XI_OTHER;
23308 }
23309 #endif
23310
23311 #ifdef HAVE_XINPUT2_1
23312
23313
23314 if (xev->flags & XIPointerEmulated)
23315 {
23316 #if !defined USE_MOTIF || !defined USE_TOOLKIT_SCROLL_BARS
23317 *finish = X_EVENT_DROP;
23318 #else
23319 if (bar)
23320 *finish = X_EVENT_DROP;
23321 #endif
23322 goto XI_OTHER;
23323 }
23324 #endif
23325
23326 if (xev->evtype == XI_ButtonPress)
23327 x_display_set_last_user_time (dpyinfo, xev->time,
23328 xev->send_event, true);
23329
23330 source = xi_device_from_id (dpyinfo, xev->sourceid);
23331 device = xi_device_from_id (dpyinfo, xev->deviceid);
23332
23333 #ifdef HAVE_XWIDGETS
23334 xvw = xwidget_view_from_window (xev->event);
23335 if (xvw)
23336 {
23337
23338
23339
23340 if (device)
23341 xi_handle_interaction (dpyinfo, xvw->frame,
23342 device, xev->time);
23343
23344 xwidget_button (xvw, xev->evtype == XI_ButtonPress,
23345 lrint (xev->event_x), lrint (xev->event_y),
23346 xev->detail, xi_convert_event_state (xev),
23347 xev->time);
23348
23349 if (!EQ (selected_window, xvw->w) && (xev->detail < 4))
23350 {
23351 inev.ie.kind = SELECT_WINDOW_EVENT;
23352 inev.ie.frame_or_window = xvw->w;
23353
23354 if (source)
23355 inev.ie.device = source->name;
23356 }
23357
23358 *finish = X_EVENT_DROP;
23359 goto XI_OTHER;
23360 }
23361 #endif
23362
23363 if (!device)
23364 goto XI_OTHER;
23365
23366 bv.button = xev->detail;
23367 bv.type = xev->evtype == XI_ButtonPress ? ButtonPress : ButtonRelease;
23368 bv.x = lrint (xev->event_x);
23369 bv.y = lrint (xev->event_y);
23370 bv.x_root = lrint (xev->root_x);
23371 bv.y_root = lrint (xev->root_y);
23372 bv.window = xev->event;
23373 bv.state = xi_convert_event_state (xev);
23374 bv.time = xev->time;
23375
23376 dpyinfo->last_mouse_glyph_frame = NULL;
23377
23378 f = mouse_or_wdesc_frame (dpyinfo, xev->event);
23379
23380 if (f && xev->event == FRAME_X_WINDOW (f))
23381
23382
23383 xi_compute_root_window_offset (f, xev);
23384
23385 if (f && xev->evtype == XI_ButtonPress
23386 && !popup_activated ()
23387 && !x_window_to_scroll_bar (dpyinfo->display, xev->event, 2)
23388 && !FRAME_NO_ACCEPT_FOCUS (f))
23389 {
23390
23391
23392
23393
23394 struct frame *hf = dpyinfo->highlight_frame;
23395
23396 if (FRAME_PARENT_FRAME (f) || (hf && frame_ancestor_p (f, hf)))
23397 {
23398 #if defined HAVE_GTK3 || (!defined USE_GTK && !defined USE_X_TOOLKIT)
23399 if (device)
23400 {
23401
23402
23403
23404 x_ignore_errors_for_next_request (dpyinfo, 0);
23405 XISetFocus (dpyinfo->display, device->attachment,
23406
23407
23408
23409 FRAME_OUTER_WINDOW (f), xev->time);
23410 x_stop_ignoring_errors (dpyinfo);
23411 }
23412 #else
23413
23414
23415
23416
23417 x_ignore_errors_for_next_request (dpyinfo, 0);
23418 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
23419 RevertToParent, xev->time);
23420 x_stop_ignoring_errors (dpyinfo);
23421 #endif
23422 if (FRAME_PARENT_FRAME (f))
23423 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
23424 }
23425 }
23426
23427 if (f)
23428 {
23429
23430
23431
23432 if (device)
23433 xi_handle_interaction (dpyinfo, f, device,
23434 xev->time);
23435 }
23436
23437 #ifdef USE_GTK
23438 if (!f)
23439 {
23440 int real_x = lrint (xev->root_x);
23441 int real_y = lrint (xev->root_y);
23442
23443 f = x_any_window_to_frame (dpyinfo, xev->event);
23444
23445 if (xev->detail > 3 && xev->detail < 8 && f)
23446 {
23447 if (xev->evtype == XI_ButtonRelease)
23448 {
23449 if (FRAME_X_WINDOW (f) != xev->event)
23450 x_translate_coordinates (f, real_x, real_y,
23451 &real_x, &real_y);
23452
23453 if (xev->detail <= 5)
23454 inev.ie.kind = WHEEL_EVENT;
23455 else
23456 inev.ie.kind = HORIZ_WHEEL_EVENT;
23457
23458 if (source)
23459 inev.ie.device = source->name;
23460
23461 inev.ie.timestamp = xev->time;
23462
23463 XSETINT (inev.ie.x, real_x);
23464 XSETINT (inev.ie.y, real_y);
23465 XSETFRAME (inev.ie.frame_or_window, f);
23466
23467 inev.ie.modifiers
23468 |= x_x_to_emacs_modifiers (dpyinfo,
23469 xev->mods.effective);
23470
23471 inev.ie.modifiers |= xev->detail % 2 ? down_modifier : up_modifier;
23472 }
23473
23474 *finish = X_EVENT_DROP;
23475 goto XI_OTHER;
23476 }
23477 else
23478 f = NULL;
23479 }
23480
23481 if (f && xg_event_is_for_scrollbar (f, event, false))
23482 f = 0;
23483 #endif
23484
23485 if (f)
23486 {
23487 if (xev->detail >= 4 && xev->detail < 8)
23488 {
23489 if (xev->evtype == XI_ButtonRelease)
23490 {
23491 if (xev->detail <= 5)
23492 inev.ie.kind = WHEEL_EVENT;
23493 else
23494 inev.ie.kind = HORIZ_WHEEL_EVENT;
23495
23496 if (source)
23497 inev.ie.device = source->name;
23498
23499 inev.ie.timestamp = xev->time;
23500
23501 XSETINT (inev.ie.x, lrint (xev->event_x));
23502 XSETINT (inev.ie.y, lrint (xev->event_y));
23503 XSETFRAME (inev.ie.frame_or_window, f);
23504
23505 inev.ie.modifiers
23506 |= x_x_to_emacs_modifiers (dpyinfo,
23507 xev->mods.effective);
23508
23509 inev.ie.modifiers |= xev->detail % 2 ? down_modifier : up_modifier;
23510 }
23511
23512 goto XI_OTHER;
23513 }
23514
23515
23516 if (WINDOWP (f->tab_bar_window)
23517 && WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window)))
23518 {
23519 Lisp_Object window;
23520 int x = bv.x;
23521 int y = bv.y;
23522
23523 window = window_from_coordinates (f, x, y, 0, true, true);
23524 tab_bar_p = EQ (window, f->tab_bar_window);
23525
23526 if (tab_bar_p)
23527 {
23528 tab_bar_arg = handle_tab_bar_click
23529 (f, x, y, xev->evtype == XI_ButtonPress,
23530 x_x_to_emacs_modifiers (dpyinfo, bv.state));
23531 x_flush_dirty_back_buffer_on (f);
23532 }
23533 }
23534
23535 #if ! defined (USE_GTK)
23536
23537 if (WINDOWP (f->tool_bar_window)
23538 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
23539 {
23540 Lisp_Object window;
23541 int x = bv.x;
23542 int y = bv.y;
23543
23544 window = window_from_coordinates (f, x, y, 0, true, true);
23545
23546
23547
23548
23549
23550
23551
23552 tool_bar_p = (EQ (window, f->tool_bar_window)
23553 && (xev->evtype != XI_ButtonRelease
23554 || f->last_tool_bar_item != -1));
23555
23556 if (tool_bar_p && xev->detail < 4)
23557 {
23558 handle_tool_bar_click_with_device
23559 (f, x, y, xev->evtype == XI_ButtonPress,
23560 x_x_to_emacs_modifiers (dpyinfo, bv.state),
23561 source ? source->name : Qt);
23562 x_flush_dirty_back_buffer_on (f);
23563 }
23564 }
23565 #endif
23566
23567 if (!(tab_bar_p && NILP (tab_bar_arg)) && !tool_bar_p)
23568 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
23569 if (! popup_activated ())
23570 #endif
23571 {
23572 if (ignore_next_mouse_click_timeout)
23573 {
23574 if (xev->evtype == XI_ButtonPress
23575 && xev->time > ignore_next_mouse_click_timeout)
23576 {
23577 ignore_next_mouse_click_timeout = 0;
23578 x_construct_mouse_click (&inev.ie, &bv, f);
23579 }
23580 if (xev->evtype == XI_ButtonRelease)
23581 ignore_next_mouse_click_timeout = 0;
23582 }
23583 else
23584 x_construct_mouse_click (&inev.ie, &bv, f);
23585
23586 if (!NILP (tab_bar_arg))
23587 inev.ie.arg = tab_bar_arg;
23588 }
23589
23590 if (FRAME_X_EMBEDDED_P (f)
23591 && !FRAME_NO_ACCEPT_FOCUS (f))
23592 xembed_send_message (f, xev->time,
23593 XEMBED_REQUEST_FOCUS, 0, 0, 0);
23594 }
23595 else
23596 {
23597 struct scroll_bar *bar
23598 = x_window_to_scroll_bar (dpyinfo->display,
23599 xev->event, 2);
23600
23601 #ifndef USE_TOOLKIT_SCROLL_BARS
23602 if (bar)
23603 x_scroll_bar_handle_click (bar, (XEvent *) &bv, &inev.ie,
23604 source ? source->name : Qnil);
23605 #else
23606
23607
23608 if (bar && xev->mods.effective & ControlMask)
23609 {
23610 x_scroll_bar_handle_click (bar, (XEvent *) &bv, &inev.ie,
23611 source ? source->name : Qnil);
23612 *finish = X_EVENT_DROP;
23613 }
23614 #endif
23615 }
23616
23617 if (xev->evtype == XI_ButtonPress)
23618 {
23619 dpyinfo->grabbed |= (1 << xev->detail);
23620 device->grab |= (1 << xev->detail);
23621 dpyinfo->last_mouse_frame = f;
23622 if (f && !tab_bar_p)
23623 f->last_tab_bar_item = -1;
23624 #if ! defined (USE_GTK)
23625 if (f && !tool_bar_p)
23626 f->last_tool_bar_item = -1;
23627 #endif
23628
23629 }
23630 else
23631 {
23632 dpyinfo->grabbed &= ~(1 << xev->detail);
23633 device->grab &= ~(1 << xev->detail);
23634 }
23635
23636 if (source && inev.ie.kind != NO_EVENT)
23637 inev.ie.device = source->name;
23638
23639 if (f)
23640 f->mouse_moved = false;
23641
23642 #if defined (USE_GTK)
23643
23644
23645 f = x_menubar_window_to_frame (dpyinfo, event);
23646 if (f
23647 && xev->detail < 3)
23648 {
23649
23650
23651 bool was_waiting_for_input = waiting_for_input;
23652
23653
23654
23655 if (waiting_for_input)
23656 waiting_for_input = 0;
23657 set_frame_menubar (f, true);
23658 waiting_for_input = was_waiting_for_input;
23659 }
23660 #endif
23661 goto XI_OTHER;
23662 }
23663
23664 case XI_KeyPress:
23665 {
23666 int state = xev->mods.effective;
23667 Lisp_Object c;
23668 #ifdef HAVE_XKB
23669 unsigned int mods_rtrn;
23670 #endif
23671 int keycode = xev->detail;
23672 KeySym keysym;
23673 char copy_buffer[81];
23674 char *copy_bufptr = copy_buffer;
23675 int copy_bufsiz = sizeof (copy_buffer);
23676 ptrdiff_t i;
23677 unsigned int old_state;
23678 struct xi_device_t *device, *source;
23679
23680 coding = Qlatin_1;
23681
23682 device = xi_device_from_id (dpyinfo, xev->deviceid);
23683 source = xi_device_from_id (dpyinfo, xev->sourceid);
23684
23685 if (!device)
23686 goto XI_OTHER;
23687
23688 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
23689
23690 if (popup_activated ())
23691 {
23692 #ifdef USE_LUCID
23693
23694 use_copy = true;
23695 copy.xkey.type = KeyPress;
23696 copy.xkey.serial = xev->serial;
23697 copy.xkey.send_event = xev->send_event;
23698 copy.xkey.display = dpyinfo->display;
23699 copy.xkey.window = xev->event;
23700 copy.xkey.root = xev->root;
23701 copy.xkey.subwindow = xev->child;
23702 copy.xkey.time = xev->time;
23703 copy.xkey.state = xi_convert_event_keyboard_state (xev);
23704 xi_convert_button_state (&xev->buttons, ©.xkey.state);
23705
23706 copy.xkey.x = lrint (xev->event_x);
23707 copy.xkey.y = lrint (xev->event_y);
23708 copy.xkey.x_root = lrint (xev->root_x);
23709 copy.xkey.y_root = lrint (xev->root_y);
23710 copy.xkey.keycode = xev->detail;
23711 copy.xkey.same_screen = True;
23712 #endif
23713 goto XI_OTHER;
23714 }
23715 #endif
23716
23717 x_display_set_last_user_time (dpyinfo, xev->time,
23718 xev->send_event, true);
23719 ignore_next_mouse_click_timeout = 0;
23720
23721 f = x_any_window_to_frame (dpyinfo, xev->event);
23722
23723 if (f && xev->event == FRAME_X_WINDOW (f))
23724
23725
23726 xi_compute_root_window_offset (f, xev);
23727
23728
23729
23730
23731
23732 #ifdef USE_GTK
23733 if (f)
23734 x_set_gtk_user_time (f, xev->time);
23735 #endif
23736
23737 if (f)
23738 {
23739
23740
23741
23742 if (device)
23743 xi_handle_interaction (dpyinfo, f, device,
23744 xev->time);
23745 }
23746
23747 XKeyPressedEvent xkey;
23748
23749 memset (&xkey, 0, sizeof xkey);
23750
23751 xkey.type = KeyPress;
23752 xkey.serial = xev->serial;
23753 xkey.send_event = xev->send_event;
23754 xkey.display = dpyinfo->display;
23755 xkey.window = xev->event;
23756 xkey.root = xev->root;
23757 xkey.subwindow = xev->child;
23758 xkey.time = xev->time;
23759 xkey.state = xi_convert_event_keyboard_state (xev);
23760
23761 xkey.x = lrint (xev->event_x);
23762 xkey.y = lrint (xev->event_y);
23763 xkey.x_root = lrint (xev->root_x);
23764 xkey.y_root = lrint (xev->root_y);
23765
23766
23767
23768 xi_convert_button_state (&xev->buttons, &xkey.state);
23769
23770 xkey.keycode = xev->detail;
23771 xkey.same_screen = True;
23772
23773 #ifdef HAVE_X_I18N
23774 #ifdef USE_GTK
23775 if ((!x_gtk_use_native_input
23776 && x_filter_event (dpyinfo, (XEvent *) &xkey))
23777 || (x_gtk_use_native_input
23778 && x_filter_event (dpyinfo, event)))
23779 {
23780
23781
23782
23783 dpyinfo->pending_keystroke_time = xev->time;
23784 dpyinfo->pending_keystroke_source = xev->sourceid;
23785
23786 *finish = X_EVENT_DROP;
23787 goto XI_OTHER;
23788 }
23789 #else
23790 if (x_filter_event (dpyinfo, (XEvent *) &xkey))
23791 {
23792
23793
23794
23795 dpyinfo->pending_keystroke_time = xev->time;
23796 dpyinfo->pending_keystroke_source = xev->sourceid;
23797
23798 *finish = X_EVENT_DROP;
23799 goto XI_OTHER;
23800 }
23801 #endif
23802 #elif USE_GTK
23803 if ((x_gtk_use_native_input
23804 || dpyinfo->prefer_native_input)
23805 && xg_filter_key (any, event))
23806 {
23807
23808
23809
23810 dpyinfo->pending_keystroke_time = xev->time;
23811 dpyinfo->pending_keystroke_source = xev->sourceid;
23812
23813 *finish = X_EVENT_DROP;
23814 goto XI_OTHER;
23815 }
23816 #endif
23817
23818 state |= x_emacs_to_x_modifiers (dpyinfo, extra_keyboard_modifiers);
23819
23820 #ifdef HAVE_XKB
23821 if (dpyinfo->xkb_desc)
23822 {
23823 unsigned int xkb_state;
23824
23825 xkb_state = state & ~(1 << 13 | 1 << 14);
23826 xkb_state |= xev->group.effective << 13;
23827
23828 if (!XkbTranslateKeyCode (dpyinfo->xkb_desc, keycode,
23829 xkb_state, &mods_rtrn, &keysym))
23830 goto XI_OTHER;
23831 }
23832 else
23833 {
23834 #endif
23835 int keysyms_per_keycode_return;
23836 KeySym *ksms = XGetKeyboardMapping (dpyinfo->display, keycode, 1,
23837 &keysyms_per_keycode_return);
23838 if (!(keysym = ksms[0]))
23839 {
23840 XFree (ksms);
23841 goto XI_OTHER;
23842 }
23843 XFree (ksms);
23844 #ifdef HAVE_XKB
23845 }
23846 #endif
23847
23848 if (keysym == NoSymbol)
23849 goto XI_OTHER;
23850
23851
23852
23853 if (!hlinfo->mouse_face_hidden && FIXNUMP (Vmouse_highlight)
23854 && (f == 0
23855 #if ! defined (USE_GTK)
23856 || !EQ (f->tool_bar_window, hlinfo->mouse_face_window)
23857 #endif
23858 || !EQ (f->tab_bar_window, hlinfo->mouse_face_window))
23859 )
23860 {
23861 mouse_frame = hlinfo->mouse_face_mouse_frame;
23862
23863 clear_mouse_face (hlinfo);
23864 hlinfo->mouse_face_hidden = true;
23865
23866 if (mouse_frame)
23867 x_flush_dirty_back_buffer_on (mouse_frame);
23868 }
23869
23870 if (f != 0)
23871 {
23872 #ifdef USE_GTK
23873
23874
23875
23876
23877 *finish = X_EVENT_DROP;
23878 #endif
23879
23880 XSETFRAME (inev.ie.frame_or_window, f);
23881 inev.ie.timestamp = xev->time;
23882
23883 #ifdef HAVE_X_I18N
23884 if (FRAME_XIC (f))
23885 {
23886 Status status_return;
23887 nbytes = XmbLookupString (FRAME_XIC (f),
23888 &xkey, (char *) copy_bufptr,
23889 copy_bufsiz, &keysym,
23890 &status_return);
23891 coding = FRAME_X_XIM_CODING (f);
23892
23893 if (status_return == XBufferOverflow)
23894 {
23895 copy_bufsiz = nbytes + 1;
23896 copy_bufptr = SAFE_ALLOCA (copy_bufsiz);
23897 nbytes = XmbLookupString (FRAME_XIC (f),
23898 &xkey, (char *) copy_bufptr,
23899 copy_bufsiz, &keysym,
23900 &status_return);
23901 }
23902
23903 if (status_return == XLookupNone)
23904 goto xi_done_keysym;
23905 else if (status_return == XLookupChars)
23906 {
23907 keysym = NoSymbol;
23908 state = 0;
23909 }
23910 else if (status_return != XLookupKeySym
23911 && status_return != XLookupBoth)
23912 emacs_abort ();
23913 }
23914 else
23915 #endif
23916 {
23917 #ifdef HAVE_XKB
23918 int overflow = 0;
23919 KeySym sym = keysym;
23920
23921 if (dpyinfo->xkb_desc)
23922 {
23923 nbytes = XkbTranslateKeySym (dpyinfo->display, &sym,
23924 state & ~mods_rtrn, copy_bufptr,
23925 copy_bufsiz, &overflow);
23926 if (overflow)
23927 {
23928 copy_bufptr = SAFE_ALLOCA ((copy_bufsiz += overflow)
23929 * sizeof *copy_bufptr);
23930 overflow = 0;
23931 nbytes = XkbTranslateKeySym (dpyinfo->display, &sym,
23932 state & ~mods_rtrn, copy_bufptr,
23933 copy_bufsiz, &overflow);
23934
23935 if (overflow)
23936 nbytes = 0;
23937 }
23938
23939 coding = Qnil;
23940 }
23941 else
23942 #endif
23943 {
23944 old_state = xkey.state;
23945 xkey.state &= ~ControlMask;
23946 xkey.state &= ~(dpyinfo->meta_mod_mask
23947 | dpyinfo->super_mod_mask
23948 | dpyinfo->hyper_mod_mask
23949 | dpyinfo->alt_mod_mask);
23950
23951 nbytes = XLookupString (&xkey, copy_bufptr,
23952 copy_bufsiz, &keysym,
23953 NULL);
23954
23955 xkey.state = old_state;
23956 }
23957 }
23958
23959 inev.ie.modifiers = x_x_to_emacs_modifiers (dpyinfo, state);
23960
23961 #ifdef XK_F1
23962 if (x_dnd_in_progress
23963 && xev->deviceid == x_dnd_keyboard_device
23964 && keysym == XK_F1)
23965 {
23966 x_dnd_xm_use_help = true;
23967 goto xi_done_keysym;
23968 }
23969 #endif
23970
23971
23972
23973 if (keysym == dpyinfo->quit_keysym
23974 && (xev->time - dpyinfo->quit_keysym_time
23975 <= 350))
23976 {
23977 Vquit_flag = Qt;
23978 goto xi_done_keysym;
23979 }
23980
23981 if (keysym == dpyinfo->quit_keysym)
23982 {
23983
23984
23985 dpyinfo->quit_keysym_time = xev->time;
23986 goto xi_done_keysym;
23987 }
23988
23989
23990
23991 if (keysym >= 32 && keysym < 128)
23992
23993 {
23994 inev.ie.kind = ASCII_KEYSTROKE_EVENT;
23995 inev.ie.code = keysym;
23996
23997 if (source)
23998 inev.ie.device = source->name;
23999
24000 goto xi_done_keysym;
24001 }
24002
24003
24004 if (keysym >= 0x01000000 && keysym <= 0x0110FFFF)
24005 {
24006 if (keysym < 0x01000080)
24007 inev.ie.kind = ASCII_KEYSTROKE_EVENT;
24008 else
24009 inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
24010
24011 if (source)
24012 inev.ie.device = source->name;
24013
24014 inev.ie.code = keysym & 0xFFFFFF;
24015 goto xi_done_keysym;
24016 }
24017
24018
24019 if (HASH_TABLE_P (Vx_keysym_table)
24020 && (c = Fgethash (make_fixnum (keysym),
24021 Vx_keysym_table,
24022 Qnil),
24023 FIXNATP (c)))
24024 {
24025 inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFIXNAT (c))
24026 ? ASCII_KEYSTROKE_EVENT
24027 : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
24028 inev.ie.code = XFIXNAT (c);
24029
24030 if (source)
24031 inev.ie.device = source->name;
24032
24033 goto xi_done_keysym;
24034 }
24035
24036
24037 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
24038 || keysym == XK_Delete
24039 #ifdef XK_ISO_Left_Tab
24040 || (keysym >= XK_ISO_Left_Tab
24041 && keysym <= XK_ISO_Enter)
24042 #endif
24043 || IsCursorKey (keysym)
24044 || IsMiscFunctionKey (keysym)
24045 #ifdef HPUX
24046
24047
24048
24049
24050 || (XK_Select <= keysym && keysym < XK_KP_Space)
24051 #endif
24052 #ifdef XK_dead_circumflex
24053 || keysym == XK_dead_circumflex
24054 #endif
24055 #ifdef XK_dead_grave
24056 || keysym == XK_dead_grave
24057 #endif
24058 #ifdef XK_dead_tilde
24059 || keysym == XK_dead_tilde
24060 #endif
24061 #ifdef XK_dead_diaeresis
24062 || keysym == XK_dead_diaeresis
24063 #endif
24064 #ifdef XK_dead_macron
24065 || keysym == XK_dead_macron
24066 #endif
24067 #ifdef XK_dead_degree
24068 || keysym == XK_dead_degree
24069 #endif
24070 #ifdef XK_dead_acute
24071 || keysym == XK_dead_acute
24072 #endif
24073 #ifdef XK_dead_cedilla
24074 || keysym == XK_dead_cedilla
24075 #endif
24076 #ifdef XK_dead_breve
24077 || keysym == XK_dead_breve
24078 #endif
24079 #ifdef XK_dead_ogonek
24080 || keysym == XK_dead_ogonek
24081 #endif
24082 #ifdef XK_dead_caron
24083 || keysym == XK_dead_caron
24084 #endif
24085 #ifdef XK_dead_doubleacute
24086 || keysym == XK_dead_doubleacute
24087 #endif
24088 #ifdef XK_dead_abovedot
24089 || keysym == XK_dead_abovedot
24090 #endif
24091 #ifdef XK_dead_abovering
24092 || keysym == XK_dead_abovering
24093 #endif
24094 #ifdef XK_dead_belowdot
24095 || keysym == XK_dead_belowdot
24096 #endif
24097 #ifdef XK_dead_voiced_sound
24098 || keysym == XK_dead_voiced_sound
24099 #endif
24100 #ifdef XK_dead_semivoiced_sound
24101 || keysym == XK_dead_semivoiced_sound
24102 #endif
24103 #ifdef XK_dead_hook
24104 || keysym == XK_dead_hook
24105 #endif
24106 #ifdef XK_dead_horn
24107 || keysym == XK_dead_horn
24108 #endif
24109 #ifdef XK_dead_stroke
24110 || keysym == XK_dead_stroke
24111 #endif
24112 #ifdef XK_dead_abovecomma
24113 || keysym == XK_dead_abovecomma
24114 #endif
24115 || IsKeypadKey (keysym)
24116 || IsFunctionKey (keysym)
24117
24118 || (keysym & (1 << 28))
24119 || (keysym != NoSymbol && nbytes == 0))
24120 && ! (IsModifierKey (keysym)
24121
24122
24123
24124
24125
24126 #if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
24127 || (XK_ISO_Lock <= keysym
24128 && keysym <= XK_ISO_Last_Group_Lock)
24129 #endif
24130 ))
24131 {
24132 STORE_KEYSYM_FOR_DEBUG (keysym);
24133
24134
24135 inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
24136 inev.ie.code = keysym;
24137
24138 if (source)
24139 inev.ie.device = source->name;
24140
24141 goto xi_done_keysym;
24142 }
24143
24144 for (i = 0; i < nbytes; i++)
24145 {
24146 STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]);
24147 }
24148
24149 if (nbytes)
24150 {
24151 inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
24152 inev.ie.arg = make_unibyte_string (copy_bufptr, nbytes);
24153
24154 Fput_text_property (make_fixnum (0), make_fixnum (nbytes),
24155 Qcoding, coding, inev.ie.arg);
24156
24157 if (source)
24158 inev.ie.device = source->name;
24159 }
24160 goto xi_done_keysym;
24161 }
24162
24163 goto XI_OTHER;
24164 }
24165
24166 #if defined USE_GTK && !defined HAVE_GTK3
24167 case XI_RawKeyPress:
24168 {
24169 XIRawEvent *raw_event = (XIRawEvent *) xi_event;
24170
24171
24172
24173
24174 dpyinfo->pending_keystroke_time = raw_event->time;
24175 dpyinfo->pending_keystroke_source = raw_event->sourceid;
24176 dpyinfo->pending_keystroke_time_special_p = true;
24177 goto XI_OTHER;
24178 }
24179 #endif
24180
24181 case XI_KeyRelease:
24182 #if defined HAVE_X_I18N || defined USE_GTK || defined USE_LUCID
24183 {
24184 XKeyPressedEvent xkey;
24185
24186 memset (&xkey, 0, sizeof xkey);
24187
24188 xkey.type = KeyRelease;
24189 xkey.serial = xev->serial;
24190 xkey.send_event = xev->send_event;
24191 xkey.display = dpyinfo->display;
24192 xkey.window = xev->event;
24193 xkey.root = xev->root;
24194 xkey.subwindow = xev->child;
24195 xkey.time = xev->time;
24196 xkey.state = xi_convert_event_keyboard_state (xev);
24197 xkey.x = lrint (xev->event_x);
24198 xkey.y = lrint (xev->event_y);
24199 xkey.x_root = lrint (xev->root_x);
24200 xkey.y_root = lrint (xev->root_y);
24201
24202
24203
24204 xi_convert_button_state (&xev->buttons, &xkey.state);
24205
24206 xkey.keycode = xev->detail;
24207 xkey.same_screen = True;
24208
24209 #ifdef USE_LUCID
24210 if (!popup_activated ())
24211 {
24212 #endif
24213 #ifdef HAVE_X_I18N
24214 if (x_filter_event (dpyinfo, (XEvent *) &xkey))
24215 *finish = X_EVENT_DROP;
24216 #elif defined USE_GTK
24217 f = x_any_window_to_frame (xkey->event);
24218
24219 if (f && xg_filter_key (f, event))
24220 *finish = X_EVENT_DROP;
24221 #endif
24222 #ifdef USE_LUCID
24223 }
24224 else
24225 {
24226
24227
24228
24229
24230
24231
24232
24233 }
24234 #endif
24235 }
24236 #endif
24237
24238 goto XI_OTHER;
24239
24240 case XI_PropertyEvent:
24241 goto XI_OTHER;
24242
24243 case XI_HierarchyChanged:
24244 {
24245 XIHierarchyEvent *hev;
24246 XIDeviceInfo *info;
24247 int i, ndevices, n_disabled, *disabled;
24248 struct xi_device_t *device;
24249 bool any_changed;
24250
24251 any_changed = false;
24252 hev = (XIHierarchyEvent *) xi_event;
24253 disabled = SAFE_ALLOCA (sizeof *disabled * hev->num_info);
24254 n_disabled = 0;
24255
24256 for (i = 0; i < hev->num_info; ++i)
24257 {
24258 if (hev->info[i].flags & XIDeviceEnabled)
24259 {
24260
24261
24262
24263 if (n_disabled)
24264 {
24265 xi_disable_devices (dpyinfo, disabled, n_disabled);
24266 n_disabled = 0;
24267
24268
24269
24270
24271 any_changed = true;
24272 }
24273
24274
24275
24276
24277
24278
24279
24280 if (!xi_device_from_id (dpyinfo,
24281 hev->info[i].deviceid))
24282 {
24283 x_catch_errors (dpyinfo->display);
24284 info = XIQueryDevice (dpyinfo->display,
24285 hev->info[i].deviceid,
24286 &ndevices);
24287 x_uncatch_errors ();
24288
24289 if (info && info->enabled)
24290 {
24291 dpyinfo->devices
24292 = xrealloc (dpyinfo->devices,
24293 (sizeof *dpyinfo->devices
24294 * ++dpyinfo->num_devices));
24295 memset (dpyinfo->devices + dpyinfo->num_devices - 1,
24296 0, sizeof *dpyinfo->devices);
24297 device = &dpyinfo->devices[dpyinfo->num_devices - 1];
24298 xi_populate_device_from_info (dpyinfo, device, info);
24299 }
24300
24301 if (info)
24302 XIFreeDeviceInfo (info);
24303 }
24304 }
24305 else if (hev->info[i].flags & XIDeviceDisabled)
24306 disabled[n_disabled++] = hev->info[i].deviceid;
24307 else if (hev->info[i].flags & XISlaveDetached
24308 || hev->info[i].flags & XISlaveAttached)
24309 {
24310 device = xi_device_from_id (dpyinfo, hev->info[i].deviceid);
24311 x_catch_errors (dpyinfo->display);
24312 info = XIQueryDevice (dpyinfo->display, hev->info[i].deviceid,
24313 &ndevices);
24314 x_uncatch_errors ();
24315
24316 if (info)
24317 {
24318 if (device)
24319 {
24320 device->use = info->use;
24321 device->attachment = info->attachment;
24322 }
24323
24324
24325
24326
24327
24328
24329 XIFreeDeviceInfo (info);
24330 }
24331 }
24332 }
24333
24334
24335
24336 xi_disable_devices (dpyinfo, disabled, n_disabled);
24337
24338
24339
24340
24341
24342 if (any_changed || n_disabled)
24343 xi_handle_focus_change (dpyinfo);
24344
24345 goto XI_OTHER;
24346 }
24347
24348 case XI_DeviceChanged:
24349 {
24350 XIDeviceChangedEvent *device_changed;
24351 struct xi_device_t *device;
24352
24353 device_changed = (XIDeviceChangedEvent *) xi_event;
24354 device = xi_device_from_id (dpyinfo, device_changed->deviceid);
24355
24356
24357
24358
24359 if (!device)
24360 goto XI_OTHER;
24361
24362
24363
24364 xi_handle_device_changed (dpyinfo, device, device_changed);
24365 goto XI_OTHER;
24366 }
24367
24368 #ifdef HAVE_XINPUT2_2
24369 case XI_TouchBegin:
24370 {
24371 struct xi_device_t *device, *source;
24372 bool menu_bar_p = false, tool_bar_p = false;
24373 #ifdef HAVE_GTK3
24374 GdkRectangle test_rect;
24375 #endif
24376 device = xi_device_from_id (dpyinfo, xev->deviceid);
24377 source = xi_device_from_id (dpyinfo, xev->sourceid);
24378 x_display_set_last_user_time (dpyinfo, xev->time,
24379 xev->send_event, true);
24380
24381
24382
24383
24384
24385
24386
24387 if (!device || device->use == XIMasterPointer)
24388 goto XI_OTHER;
24389
24390 if (xi_find_touch_point (device, xev->detail))
24391 emacs_abort ();
24392
24393 f = x_window_to_frame (dpyinfo, xev->event);
24394
24395 if (f)
24396
24397
24398 xi_compute_root_window_offset (f, xev);
24399
24400 #ifdef HAVE_GTK3
24401 menu_bar_p = (f && FRAME_X_OUTPUT (f)->menubar_widget
24402 && xg_event_is_for_menubar (f, event));
24403 if (f && FRAME_X_OUTPUT (f)->toolbar_widget)
24404 {
24405 int scale = xg_get_scale (f);
24406
24407 test_rect.x = xev->event_x / scale;
24408 test_rect.y = xev->event_y / scale;
24409 test_rect.width = 1;
24410 test_rect.height = 1;
24411
24412 tool_bar_p = gtk_widget_intersect (FRAME_X_OUTPUT (f)->toolbar_widget,
24413 &test_rect, NULL);
24414 }
24415 #endif
24416
24417 #ifndef HAVE_EXT_TOOL_BAR
24418
24419
24420 if (device->direct_p
24421 && WINDOWP (f->tool_bar_window)
24422 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
24423 {
24424 Lisp_Object window;
24425 int x = xev->event_x;
24426 int y = xev->event_y;
24427
24428 window = window_from_coordinates (f, x, y, 0, true, true);
24429
24430
24431
24432
24433
24434
24435
24436 tool_bar_p = EQ (window, f->tool_bar_window);
24437
24438
24439
24440
24441
24442 if (tool_bar_p)
24443 {
24444
24445
24446
24447
24448
24449
24450
24451 if (!NILP (Vmouse_highlight))
24452 {
24453 note_mouse_highlight (f, x, y);
24454
24455
24456
24457
24458 memset (&dpyinfo->last_mouse_glyph, 0,
24459 sizeof dpyinfo->last_mouse_glyph);
24460 dpyinfo->last_mouse_glyph_frame = f;
24461 }
24462
24463 handle_tool_bar_click_with_device (f, x, y, true, 0,
24464 (source
24465 ? source->name : Qt));
24466
24467
24468
24469 x_flush_dirty_back_buffer_on (f);
24470
24471
24472
24473
24474
24475 FRAME_OUTPUT_DATA (f)->tool_bar_touch_device
24476 = device->device_id;
24477 FRAME_OUTPUT_DATA (f)->tool_bar_touch_id = xev->detail;
24478
24479 goto XI_OTHER;
24480 }
24481 }
24482 #endif
24483
24484 if (!menu_bar_p && !tool_bar_p)
24485 {
24486 if (f && device->direct_p)
24487 {
24488 *finish = X_EVENT_DROP;
24489
24490 x_catch_errors (dpyinfo->display);
24491
24492 if (x_input_grab_touch_events)
24493 XIAllowTouchEvents (dpyinfo->display,
24494 xev->deviceid,
24495 xev->detail, xev->event,
24496 XIAcceptTouch);
24497
24498 if (!x_had_errors_p (dpyinfo->display))
24499 {
24500 xi_link_touch_point (device, xev->detail,
24501 xev->event_x,
24502 xev->event_y, f);
24503
24504 inev.ie.kind = TOUCHSCREEN_BEGIN_EVENT;
24505 inev.ie.timestamp = xev->time;
24506 XSETFRAME (inev.ie.frame_or_window, f);
24507 XSETINT (inev.ie.x, lrint (xev->event_x));
24508 XSETINT (inev.ie.y, lrint (xev->event_y));
24509 XSETINT (inev.ie.arg, xev->detail);
24510
24511 if (source)
24512 inev.ie.device = source->name;
24513 }
24514
24515 x_uncatch_errors ();
24516 }
24517 #ifndef HAVE_GTK3
24518 else if (x_input_grab_touch_events)
24519 {
24520 x_ignore_errors_for_next_request (dpyinfo, 0);
24521 XIAllowTouchEvents (dpyinfo->display, xev->deviceid,
24522 xev->detail, xev->event, XIRejectTouch);
24523 x_stop_ignoring_errors (dpyinfo);
24524 }
24525 #endif
24526 }
24527 else
24528 {
24529 #ifdef HAVE_GTK3
24530 bool was_waiting_for_input = waiting_for_input;
24531
24532
24533
24534 if (waiting_for_input)
24535 waiting_for_input = 0;
24536 set_frame_menubar (f, true);
24537 waiting_for_input = was_waiting_for_input;
24538 #endif
24539 }
24540
24541 goto XI_OTHER;
24542 }
24543
24544 case XI_TouchOwnership:
24545 {
24546 struct xi_device_t *device;
24547 struct xi_touch_point_t *touchpoint;
24548 XITouchOwnershipEvent *event;
24549
24550
24551
24552
24553 event = (XITouchOwnershipEvent *) xi_event;
24554 device = xi_device_from_id (dpyinfo, event->deviceid);
24555
24556 if (!device || device->use == XIMasterPointer)
24557 goto XI_OTHER;
24558
24559 touchpoint = xi_find_touch_point (device, event->touchid);
24560
24561 if (!touchpoint)
24562 goto XI_OTHER;
24563
24564
24565
24566 touchpoint->ownership = TOUCH_OWNERSHIP_SELF;
24567
24568 goto XI_OTHER;
24569 }
24570
24571 case XI_TouchUpdate:
24572 {
24573 struct xi_device_t *device, *source;
24574 struct xi_touch_point_t *touchpoint;
24575 Lisp_Object arg = Qnil;
24576
24577
24578
24579
24580
24581
24582
24583
24584
24585 if (xev->flags & XITouchPendingEnd)
24586 goto XI_OTHER;
24587
24588 device = xi_device_from_id (dpyinfo, xev->deviceid);
24589 source = xi_device_from_id (dpyinfo, xev->sourceid);
24590 x_display_set_last_user_time (dpyinfo, xev->time,
24591 xev->send_event, true);
24592
24593
24594
24595
24596
24597
24598
24599 if (!device || device->use == XIMasterPointer)
24600 goto XI_OTHER;
24601
24602 touchpoint = xi_find_touch_point (device, xev->detail);
24603
24604 if (!touchpoint
24605
24606
24607 || (touchpoint->x == lrint (xev->event_x)
24608 && touchpoint->y == lrint (xev->event_y)))
24609 goto XI_OTHER;
24610
24611 touchpoint->x = lrint (xev->event_x);
24612 touchpoint->y = lrint (xev->event_y);
24613
24614 f = x_window_to_frame (dpyinfo, xev->event);
24615
24616 if (f && device->direct_p)
24617 {
24618 inev.ie.kind = TOUCHSCREEN_UPDATE_EVENT;
24619 inev.ie.timestamp = xev->time;
24620 XSETFRAME (inev.ie.frame_or_window, f);
24621
24622 for (touchpoint = device->touchpoints;
24623 touchpoint; touchpoint = touchpoint->next)
24624 {
24625 if (touchpoint->frame == f)
24626 arg = Fcons (list3i (touchpoint->x, touchpoint->y,
24627 lrint (touchpoint->number)),
24628 arg);
24629 }
24630
24631 if (source)
24632 inev.ie.device = source->name;
24633
24634 inev.ie.arg = arg;
24635 }
24636
24637 goto XI_OTHER;
24638 }
24639
24640 case XI_TouchEnd:
24641 {
24642 struct xi_device_t *device, *source;
24643 int state;
24644
24645 device = xi_device_from_id (dpyinfo, xev->deviceid);
24646 source = xi_device_from_id (dpyinfo, xev->sourceid);
24647 x_display_set_last_user_time (dpyinfo, xev->time,
24648 xev->send_event, true);
24649
24650
24651
24652
24653
24654
24655
24656 if (!device || device->use == XIMasterPointer)
24657 goto XI_OTHER;
24658
24659 state = xi_unlink_touch_point (xev->detail, device);
24660
24661 if (state)
24662 {
24663 f = x_window_to_frame (dpyinfo, xev->event);
24664
24665 if (f && device->direct_p)
24666 {
24667 inev.ie.kind = TOUCHSCREEN_END_EVENT;
24668 inev.ie.timestamp = xev->time;
24669 inev.ie.modifiers = state != 2;
24670
24671 XSETFRAME (inev.ie.frame_or_window, f);
24672 XSETINT (inev.ie.x, lrint (xev->event_x));
24673 XSETINT (inev.ie.y, lrint (xev->event_y));
24674 XSETINT (inev.ie.arg, xev->detail);
24675
24676 if (source)
24677 inev.ie.device = source->name;
24678 }
24679 }
24680
24681 #ifndef HAVE_EXT_TOOL_BAR
24682
24683
24684
24685 if (!f)
24686 f = x_window_to_frame (dpyinfo, xev->event);
24687
24688 if (f && (FRAME_OUTPUT_DATA (f)->tool_bar_touch_id
24689 == xev->detail))
24690 {
24691 if (f->last_tool_bar_item != -1)
24692 handle_tool_bar_click_with_device (f, xev->event_x,
24693 xev->event_y,
24694 false, 0,
24695 (source
24696 ? source->name
24697 : Qnil));
24698
24699
24700 note_mouse_highlight (f, -1, -1);
24701 x_flush_dirty_back_buffer_on (f);
24702
24703
24704 FRAME_OUTPUT_DATA (f)->tool_bar_touch_device = 0;
24705 }
24706 #endif
24707
24708 goto XI_OTHER;
24709 }
24710
24711 #endif
24712
24713 #ifdef HAVE_XINPUT2_4
24714 case XI_GesturePinchBegin:
24715 case XI_GesturePinchUpdate:
24716 {
24717 XIGesturePinchEvent *pev = (XIGesturePinchEvent *) xi_event;
24718 struct xi_device_t *device, *source;
24719
24720 device = xi_device_from_id (dpyinfo, pev->deviceid);
24721 source = xi_device_from_id (dpyinfo, pev->sourceid);
24722 x_display_set_last_user_time (dpyinfo, pev->time,
24723 pev->send_event, true);
24724
24725 if (!device || device->use != XIMasterPointer)
24726 goto XI_OTHER;
24727
24728 #ifdef HAVE_XWIDGETS
24729 struct xwidget_view *xvw = xwidget_view_from_window (pev->event);
24730
24731 if (xvw)
24732 {
24733 *finish = X_EVENT_DROP;
24734 xwidget_pinch (xvw, pev);
24735 goto XI_OTHER;
24736 }
24737 #endif
24738
24739 any = x_window_to_frame (dpyinfo, pev->event);
24740
24741 if (any)
24742 {
24743 if (pev->event == FRAME_X_WINDOW (any))
24744 xi_compute_root_window_offset_pinch (any, pev);
24745
24746 inev.ie.kind = PINCH_EVENT;
24747 inev.ie.modifiers
24748 = x_x_to_emacs_modifiers (dpyinfo, pev->mods.effective);
24749
24750 XSETINT (inev.ie.x, lrint (pev->event_x));
24751 XSETINT (inev.ie.y, lrint (pev->event_y));
24752 XSETFRAME (inev.ie.frame_or_window, any);
24753 inev.ie.arg = list4 (make_float (pev->delta_x),
24754 make_float (pev->delta_y),
24755 make_float (pev->scale),
24756 make_float (pev->delta_angle));
24757
24758 if (source)
24759 inev.ie.device = source->name;
24760 }
24761
24762
24763
24764 *finish = X_EVENT_DROP;
24765 goto XI_OTHER;
24766 }
24767
24768 case XI_GesturePinchEnd:
24769 {
24770 #if defined HAVE_XWIDGETS
24771 XIGesturePinchEvent *pev = (XIGesturePinchEvent *) xi_event;
24772 struct xwidget_view *xvw = xwidget_view_from_window (pev->event);
24773
24774 if (xvw)
24775 xwidget_pinch (xvw, pev);
24776 #endif
24777 *finish = X_EVENT_DROP;
24778 goto XI_OTHER;
24779 }
24780 #endif
24781 default:
24782 goto XI_OTHER;
24783 }
24784
24785 xi_done_keysym:
24786 #ifdef HAVE_X_I18N
24787 if (f)
24788 {
24789 struct window *w = XWINDOW (f->selected_window);
24790 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
24791
24792 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
24793 xic_set_statusarea (f);
24794 }
24795 #endif
24796 if (must_free_data)
24797 XFreeEventData (dpyinfo->display, &event->xcookie);
24798 goto done_keysym;
24799
24800 XI_OTHER:
24801 if (must_free_data)
24802 XFreeEventData (dpyinfo->display, &event->xcookie);
24803 goto OTHER;
24804 }
24805 #endif
24806
24807 default:
24808 #ifdef HAVE_XKB
24809 if (dpyinfo->supports_xkb
24810 && event->type == dpyinfo->xkb_event_type)
24811 {
24812 XkbEvent *xkbevent = (XkbEvent *) event;
24813
24814 if (xkbevent->any.xkb_type == XkbNewKeyboardNotify
24815 || xkbevent->any.xkb_type == XkbMapNotify)
24816 {
24817 XkbRefreshKeyboardMapping (&xkbevent->map);
24818
24819 if (dpyinfo->xkb_desc)
24820 {
24821 if (XkbGetUpdatedMap (dpyinfo->display,
24822 (XkbKeySymsMask
24823 | XkbKeyTypesMask
24824 | XkbModifierMapMask
24825 | XkbVirtualModsMask),
24826 dpyinfo->xkb_desc) == Success)
24827 XkbGetNames (dpyinfo->display, XkbAllNamesMask,
24828 dpyinfo->xkb_desc);
24829 else
24830 {
24831 XkbFreeKeyboard (dpyinfo->xkb_desc,
24832 XkbAllComponentsMask, True);
24833 dpyinfo->xkb_desc = NULL;
24834 }
24835 }
24836 else
24837 {
24838 dpyinfo->xkb_desc = XkbGetMap (dpyinfo->display,
24839 (XkbKeySymsMask
24840 | XkbKeyTypesMask
24841 | XkbModifierMapMask
24842 | XkbVirtualModsMask),
24843 XkbUseCoreKbd);
24844
24845 if (dpyinfo->xkb_desc)
24846 XkbGetNames (dpyinfo->display, XkbAllNamesMask,
24847 dpyinfo->xkb_desc);
24848 }
24849
24850 x_find_modifier_meanings (dpyinfo);
24851 }
24852 else if (x_dnd_in_progress
24853 && xkbevent->any.xkb_type == XkbStateNotify)
24854 x_dnd_keyboard_state = (xkbevent->state.mods
24855 | xkbevent->state.ptr_buttons);
24856 }
24857 #endif
24858 #ifdef HAVE_XSHAPE
24859 if (dpyinfo->xshape_supported_p
24860 && event->type == dpyinfo->xshape_event_base + ShapeNotify
24861 && x_dnd_in_progress && x_dnd_use_toplevels
24862 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
24863 {
24864 #ifndef USE_GTK
24865 XEvent xevent;
24866 #endif
24867 XShapeEvent *xse = (XShapeEvent *) event;
24868 #if defined HAVE_XCB_SHAPE && defined HAVE_XCB_SHAPE_INPUT_RECTS
24869 xcb_shape_get_rectangles_cookie_t bounding_rect_cookie;
24870 xcb_shape_get_rectangles_reply_t *bounding_rect_reply;
24871 xcb_rectangle_iterator_t bounding_rect_iterator;
24872
24873 xcb_shape_get_rectangles_cookie_t input_rect_cookie;
24874 xcb_shape_get_rectangles_reply_t *input_rect_reply;
24875 xcb_rectangle_iterator_t input_rect_iterator;
24876
24877 xcb_generic_error_t *error;
24878 #else
24879 XRectangle *rects;
24880 int rc, ordering;
24881 #endif
24882
24883
24884
24885
24886 #ifndef USE_GTK
24887 while (XPending (dpyinfo->display))
24888 {
24889 XNextEvent (dpyinfo->display, &xevent);
24890
24891 if (xevent.type == dpyinfo->xshape_event_base + ShapeNotify
24892 && ((XShapeEvent *) &xevent)->window == xse->window)
24893 xse = (XShapeEvent *) &xevent;
24894 else
24895 {
24896 XPutBackEvent (dpyinfo->display, &xevent);
24897 break;
24898 }
24899 }
24900 #endif
24901
24902 for (struct x_client_list_window *tem = x_dnd_toplevels; tem;
24903 tem = tem->next)
24904 {
24905 if (tem->window == xse->window)
24906 {
24907 if (tem->n_input_rects != -1)
24908 xfree (tem->input_rects);
24909 if (tem->n_bounding_rects != -1)
24910 xfree (tem->bounding_rects);
24911
24912 tem->n_input_rects = -1;
24913 tem->n_bounding_rects = -1;
24914
24915 #if defined HAVE_XCB_SHAPE && defined HAVE_XCB_SHAPE_INPUT_RECTS
24916 bounding_rect_cookie = xcb_shape_get_rectangles (dpyinfo->xcb_connection,
24917 (xcb_window_t) xse->window,
24918 XCB_SHAPE_SK_BOUNDING);
24919 if (dpyinfo->xshape_major > 1
24920 || (dpyinfo->xshape_major == 1
24921 && dpyinfo->xshape_minor >= 1))
24922 input_rect_cookie
24923 = xcb_shape_get_rectangles (dpyinfo->xcb_connection,
24924 (xcb_window_t) xse->window,
24925 XCB_SHAPE_SK_INPUT);
24926
24927 bounding_rect_reply = xcb_shape_get_rectangles_reply (dpyinfo->xcb_connection,
24928 bounding_rect_cookie,
24929 &error);
24930
24931 if (bounding_rect_reply)
24932 {
24933 bounding_rect_iterator
24934 = xcb_shape_get_rectangles_rectangles_iterator (bounding_rect_reply);
24935 tem->n_bounding_rects = bounding_rect_iterator.rem + 1;
24936 tem->bounding_rects = xmalloc (tem->n_bounding_rects
24937 * sizeof *tem->bounding_rects);
24938 tem->n_bounding_rects = 0;
24939
24940 for (; bounding_rect_iterator.rem; xcb_rectangle_next (&bounding_rect_iterator))
24941 {
24942 tem->bounding_rects[tem->n_bounding_rects].x
24943 = bounding_rect_iterator.data->x;
24944 tem->bounding_rects[tem->n_bounding_rects].y
24945 = bounding_rect_iterator.data->y;
24946 tem->bounding_rects[tem->n_bounding_rects].width
24947 = bounding_rect_iterator.data->width;
24948 tem->bounding_rects[tem->n_bounding_rects].height
24949 = bounding_rect_iterator.data->height;
24950
24951 tem->n_bounding_rects++;
24952 }
24953
24954 free (bounding_rect_reply);
24955 }
24956 else
24957 free (error);
24958
24959 if (dpyinfo->xshape_major > 1
24960 || (dpyinfo->xshape_major == 1
24961 && dpyinfo->xshape_minor >= 1))
24962 {
24963 input_rect_reply = xcb_shape_get_rectangles_reply (dpyinfo->xcb_connection,
24964 input_rect_cookie, &error);
24965
24966 if (input_rect_reply)
24967 {
24968 input_rect_iterator
24969 = xcb_shape_get_rectangles_rectangles_iterator (input_rect_reply);
24970 tem->n_input_rects = input_rect_iterator.rem + 1;
24971 tem->input_rects = xmalloc (tem->n_input_rects
24972 * sizeof *tem->input_rects);
24973 tem->n_input_rects = 0;
24974
24975 for (; input_rect_iterator.rem; xcb_rectangle_next (&input_rect_iterator))
24976 {
24977 tem->input_rects[tem->n_input_rects].x
24978 = input_rect_iterator.data->x;
24979 tem->input_rects[tem->n_input_rects].y
24980 = input_rect_iterator.data->y;
24981 tem->input_rects[tem->n_input_rects].width
24982 = input_rect_iterator.data->width;
24983 tem->input_rects[tem->n_input_rects].height
24984 = input_rect_iterator.data->height;
24985
24986 tem->n_input_rects++;
24987 }
24988
24989 free (input_rect_reply);
24990 }
24991 else
24992 free (error);
24993 }
24994 #else
24995 x_catch_errors (dpyinfo->display);
24996 rects = XShapeGetRectangles (dpyinfo->display,
24997 xse->window,
24998 ShapeBounding,
24999 &count, &ordering);
25000 rc = x_had_errors_p (dpyinfo->display);
25001 x_uncatch_errors_after_check ();
25002
25003
25004
25005 if (!rc)
25006 {
25007 tem->n_bounding_rects = count;
25008 tem->bounding_rects
25009 = xmalloc (sizeof *tem->bounding_rects * count);
25010 memcpy (tem->bounding_rects, rects,
25011 sizeof *tem->bounding_rects * count);
25012
25013 XFree (rects);
25014 }
25015
25016 #ifdef ShapeInput
25017 if (dpyinfo->xshape_major > 1
25018 || (dpyinfo->xshape_major == 1
25019 && dpyinfo->xshape_minor >= 1))
25020 {
25021 x_catch_errors (dpyinfo->display);
25022 rects = XShapeGetRectangles (dpyinfo->display,
25023 xse->window, ShapeInput,
25024 &count, &ordering);
25025 rc = x_had_errors_p (dpyinfo->display);
25026 x_uncatch_errors_after_check ();
25027
25028
25029
25030 if (!rc)
25031 {
25032 tem->n_input_rects = count;
25033 tem->input_rects
25034 = xmalloc (sizeof *tem->input_rects * count);
25035 memcpy (tem->input_rects, rects,
25036 sizeof *tem->input_rects * count);
25037
25038 XFree (rects);
25039 }
25040 }
25041 #endif
25042 #endif
25043
25044
25045
25046
25047 if (tem->n_input_rects != -1
25048 && tem->n_bounding_rects == tem->n_input_rects
25049 && !memcmp (tem->bounding_rects, tem->input_rects,
25050 tem->n_input_rects * sizeof *tem->input_rects))
25051 {
25052 xfree (tem->input_rects);
25053 tem->n_input_rects = -1;
25054 }
25055
25056
25057
25058
25059 if (tem->n_input_rects == -1
25060 && tem->n_bounding_rects == 1
25061 && tem->bounding_rects[0].width == tem->width
25062 && tem->bounding_rects[0].height == tem->height
25063 && tem->bounding_rects[0].x == -tem->border_width
25064 && tem->bounding_rects[0].y == -tem->border_width)
25065 {
25066 xfree (tem->bounding_rects);
25067 tem->n_bounding_rects = -1;
25068 }
25069
25070 break;
25071 }
25072 }
25073 }
25074 #endif
25075 #if defined HAVE_XRANDR && !defined USE_GTK
25076 if (dpyinfo->xrandr_supported_p
25077 && (event->type == (dpyinfo->xrandr_event_base
25078 + RRScreenChangeNotify)
25079 || event->type == (dpyinfo->xrandr_event_base
25080 + RRNotify)))
25081 {
25082 Time timestamp;
25083 Lisp_Object current_monitors;
25084 XRRScreenChangeNotifyEvent *notify;
25085
25086 if (event->type == (dpyinfo->xrandr_event_base
25087 + RRScreenChangeNotify))
25088 XRRUpdateConfiguration ((XEvent *) event);
25089
25090 if (event->type == (dpyinfo->xrandr_event_base
25091 + RRScreenChangeNotify))
25092 {
25093 notify = ((XRRScreenChangeNotifyEvent *) event);
25094 timestamp = notify->timestamp;
25095
25096
25097
25098 if (notify->root == dpyinfo->root_window)
25099 {
25100 dpyinfo->screen_width = notify->width;
25101 dpyinfo->screen_height = notify->height;
25102 dpyinfo->screen_mm_width = notify->mwidth;
25103 dpyinfo->screen_mm_height = notify->mheight;
25104 }
25105 }
25106 else
25107 timestamp = 0;
25108
25109 if (x_find_monitors_changed_event (dpyinfo))
25110
25111
25112 goto OTHER;
25113
25114 inev.ie.kind = MONITORS_CHANGED_EVENT;
25115 inev.ie.timestamp = timestamp;
25116 XSETTERMINAL (inev.ie.arg, dpyinfo->terminal);
25117
25118
25119
25120
25121 current_monitors
25122 = Fx_display_monitor_attributes_list (inev.ie.arg);
25123
25124 if (!NILP (Fequal (current_monitors,
25125 dpyinfo->last_monitor_attributes_list)))
25126 inev.ie.kind = NO_EVENT;
25127
25128 dpyinfo->last_monitor_attributes_list = current_monitors;
25129
25130 if (x_dnd_in_progress && x_dnd_update_tooltip)
25131 x_dnd_monitors = current_monitors;
25132
25133 if (inev.ie.kind != NO_EVENT)
25134 x_dnd_update_tooltip_now ();
25135 }
25136 #endif
25137 #ifdef HAVE_XFIXES
25138 if (dpyinfo->xfixes_supported_p
25139 && event->type == (dpyinfo->xfixes_event_base
25140 + XFixesSelectionNotify)
25141 && x_handle_selection_monitor_event (dpyinfo, event))
25142
25143
25144
25145
25146 *finish = X_EVENT_DROP;
25147 #endif
25148 OTHER:
25149 #ifdef USE_X_TOOLKIT
25150 if (*finish != X_EVENT_DROP)
25151 {
25152
25153
25154
25155 if (event->type != ConfigureNotify
25156 || (event->xconfigure.width != 0
25157 && event->xconfigure.height != 0))
25158 {
25159 #if defined USE_X_TOOLKIT && defined HAVE_XINPUT2
25160 XtDispatchEvent (use_copy ? © : (XEvent *) event);
25161 #else
25162 XtDispatchEvent ((XEvent *) event);
25163 #endif
25164 }
25165 }
25166 #endif
25167 #if defined USE_GTK && !defined HAVE_GTK3 && defined HAVE_XINPUT2
25168 if (*finish != X_EVENT_DROP && copy)
25169 {
25170 gtk_main_do_event (copy);
25171 *finish = X_EVENT_DROP;
25172 }
25173
25174 if (copy)
25175 gdk_event_free (copy);
25176 #endif
25177 break;
25178 }
25179
25180 done:
25181 if (inev.ie.kind != NO_EVENT)
25182 {
25183 kbd_buffer_store_buffered_event (&inev, hold_quit);
25184 count++;
25185 }
25186
25187 if (do_help
25188 && !(hold_quit && hold_quit->kind != NO_EVENT))
25189 {
25190 Lisp_Object frame;
25191
25192 if (f)
25193 XSETFRAME (frame, f);
25194 else
25195 frame = Qnil;
25196
25197 if (do_help > 0)
25198 {
25199 any_help_event_p = true;
25200 #ifdef HAVE_XINPUT2
25201 if (gen_help_device)
25202 xi_handle_interaction (dpyinfo, f,
25203 gen_help_device,
25204 gen_help_time);
25205 #endif
25206 gen_help_event (help_echo_string, frame, help_echo_window,
25207 help_echo_object, help_echo_pos);
25208 }
25209 else
25210 {
25211 help_echo_string = Qnil;
25212 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
25213 }
25214 count++;
25215 }
25216
25217 #if defined HAVE_XINPUT2 || defined HAVE_XKB || defined HAVE_X_I18N
25218 SAFE_FREE ();
25219 #endif
25220
25221 return count;
25222 }
25223
25224
25225
25226
25227
25228
25229
25230 #ifdef USE_GTK
25231 static int
25232 #else
25233 int
25234 #endif
25235 x_dispatch_event (XEvent *event, Display *display)
25236 {
25237 struct x_display_info *dpyinfo;
25238 int finish = X_EVENT_NORMAL;
25239
25240 dpyinfo = x_display_info_for_display (display);
25241
25242 if (dpyinfo)
25243 {
25244
25245 block_input ();
25246 handle_one_xevent (dpyinfo, event, &finish, 0);
25247 unblock_input ();
25248 }
25249
25250 return finish;
25251 }
25252
25253
25254
25255
25256
25257
25258
25259
25260
25261 static int
25262 XTread_socket (struct terminal *terminal, struct input_event *hold_quit)
25263 {
25264 int count = 0;
25265 bool event_found = false;
25266 struct x_display_info *dpyinfo = terminal->display_info.x;
25267
25268
25269
25270
25271
25272
25273
25274
25275
25276
25277
25278 if (!x_dnd_unwind_flag
25279 && ((x_dnd_in_progress
25280 && dpyinfo->display == FRAME_X_DISPLAY (x_dnd_frame))
25281 || (x_dnd_waiting_for_finish
25282 && dpyinfo->display == x_dnd_finish_display)))
25283 return 0;
25284
25285 x_clean_failable_requests (dpyinfo);
25286
25287 block_input ();
25288
25289
25290 if (dpyinfo == XTread_socket_fake_io_error)
25291 {
25292 XTread_socket_fake_io_error = 0;
25293 x_io_error_quitter (dpyinfo->display);
25294 }
25295
25296 #ifndef USE_GTK
25297 while (XPending (dpyinfo->display))
25298 {
25299 int finish;
25300 XEvent event;
25301
25302 XNextEvent (dpyinfo->display, &event);
25303
25304 #ifdef HAVE_X_I18N
25305
25306 #ifdef HAVE_XINPUT2
25307 if (event.type != GenericEvent
25308 || !dpyinfo->supports_xi2
25309 || event.xgeneric.extension != dpyinfo->xi2_opcode)
25310 {
25311
25312
25313 #endif
25314 if (x_filter_event (dpyinfo, &event))
25315 continue;
25316 #ifdef HAVE_XINPUT2
25317 }
25318 #endif
25319 #endif
25320 event_found = true;
25321
25322 count += handle_one_xevent (dpyinfo, &event, &finish, hold_quit);
25323
25324 if (finish == X_EVENT_GOTO_OUT)
25325 break;
25326 }
25327
25328 #else
25329
25330
25331
25332
25333
25334
25335
25336
25337
25338 while (gtk_events_pending ())
25339 {
25340 current_count = count;
25341 current_hold_quit = hold_quit;
25342
25343 gtk_main_iteration ();
25344
25345 count = current_count;
25346 current_count = -1;
25347 current_hold_quit = 0;
25348
25349 if (current_finish == X_EVENT_GOTO_OUT)
25350 break;
25351 }
25352
25353
25354 if (xg_pending_quit_event.kind != NO_EVENT)
25355 {
25356
25357
25358 if (FRAME_LIVE_P (XFRAME (xg_pending_quit_event.frame_or_window)))
25359
25360
25361 *hold_quit = xg_pending_quit_event;
25362
25363
25364 xg_pending_quit_event.kind = NO_EVENT;
25365 }
25366 #endif
25367
25368
25369
25370 if (! event_found)
25371 {
25372
25373
25374
25375 x_noop_count++;
25376 if (x_noop_count >= 100)
25377 {
25378 x_noop_count=0;
25379
25380 if (next_noop_dpyinfo == 0)
25381 next_noop_dpyinfo = x_display_list;
25382
25383 XNoOp (next_noop_dpyinfo->display);
25384
25385
25386 next_noop_dpyinfo = next_noop_dpyinfo->next;
25387 }
25388 }
25389
25390
25391
25392 if (dpyinfo->x_pending_autoraise_frame)
25393 {
25394 x_raise_frame (dpyinfo->x_pending_autoraise_frame);
25395 dpyinfo->x_pending_autoraise_frame = NULL;
25396 }
25397
25398 unblock_input ();
25399
25400 return count;
25401 }
25402
25403
25404
25405
25406
25407
25408
25409
25410
25411
25412
25413
25414
25415
25416
25417 static void
25418 x_clip_to_row (struct window *w, struct glyph_row *row,
25419 enum glyph_row_area area, GC gc)
25420 {
25421 struct frame *f = XFRAME (WINDOW_FRAME (w));
25422 XRectangle clip_rect;
25423 int window_x, window_y, window_width;
25424
25425 window_box (w, area, &window_x, &window_y, &window_width, 0);
25426
25427 clip_rect.x = window_x;
25428 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y));
25429 clip_rect.y = max (clip_rect.y, window_y);
25430 clip_rect.width = window_width;
25431 clip_rect.height = row->visible_height;
25432
25433 x_set_clip_rectangles (f, gc, &clip_rect, 1);
25434 }
25435
25436
25437
25438
25439 static void
25440 x_draw_hollow_cursor (struct window *w, struct glyph_row *row)
25441 {
25442 struct frame *f = XFRAME (WINDOW_FRAME (w));
25443 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
25444 Display *dpy = FRAME_X_DISPLAY (f);
25445 int x, y, wd, h;
25446 XGCValues xgcv;
25447 struct glyph *cursor_glyph;
25448 GC gc;
25449
25450
25451
25452 cursor_glyph = get_phys_cursor_glyph (w);
25453 if (cursor_glyph == NULL)
25454 return;
25455
25456
25457 get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h);
25458 wd = w->phys_cursor_width - 1;
25459
25460
25461
25462 xgcv.foreground = f->output_data.x->cursor_pixel;
25463 xgcv.line_width = 1;
25464 if (dpyinfo->scratch_cursor_gc)
25465 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground | GCLineWidth, &xgcv);
25466 else
25467 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_DRAWABLE (f),
25468 GCForeground | GCLineWidth, &xgcv);
25469 gc = dpyinfo->scratch_cursor_gc;
25470
25471
25472
25473
25474 if ((cursor_glyph->resolved_level & 1) != 0
25475 && cursor_glyph->pixel_width > wd)
25476 {
25477 x += cursor_glyph->pixel_width - wd;
25478 if (wd > 0)
25479 wd -= 1;
25480 }
25481
25482 x_clip_to_row (w, row, TEXT_AREA, gc);
25483 x_draw_rectangle (f, gc, x, y, wd, h - 1);
25484 x_reset_clip_rectangles (f, gc);
25485 }
25486
25487
25488
25489
25490
25491
25492
25493
25494
25495 static void
25496 x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text_cursor_kinds kind)
25497 {
25498 struct frame *f = XFRAME (w->frame);
25499 struct glyph *cursor_glyph;
25500
25501
25502
25503
25504 cursor_glyph = get_phys_cursor_glyph (w);
25505 if (cursor_glyph == NULL)
25506 return;
25507
25508
25509 if (cursor_glyph->type == XWIDGET_GLYPH)
25510 return;
25511
25512
25513
25514
25515 if (cursor_glyph->type == IMAGE_GLYPH)
25516 {
25517 struct glyph_row *r;
25518 r = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
25519 draw_phys_cursor_glyph (w, r, DRAW_CURSOR);
25520 }
25521 else
25522 {
25523 Display *dpy = FRAME_X_DISPLAY (f);
25524 Drawable drawable = FRAME_X_DRAWABLE (f);
25525 GC gc = FRAME_DISPLAY_INFO (f)->scratch_cursor_gc;
25526 unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures;
25527 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
25528 XGCValues xgcv;
25529
25530
25531
25532
25533
25534
25535 if (face->background == f->output_data.x->cursor_pixel)
25536 xgcv.background = xgcv.foreground = face->foreground;
25537 else
25538 xgcv.background = xgcv.foreground = f->output_data.x->cursor_pixel;
25539 xgcv.graphics_exposures = False;
25540 xgcv.line_width = 1;
25541
25542 mask |= GCLineWidth;
25543
25544 if (gc)
25545 XChangeGC (dpy, gc, mask, &xgcv);
25546 else
25547 {
25548 gc = XCreateGC (dpy, drawable, mask, &xgcv);
25549 FRAME_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
25550 }
25551
25552 x_clip_to_row (w, row, TEXT_AREA, gc);
25553
25554 if (kind == BAR_CURSOR)
25555 {
25556 int x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
25557
25558 if (width < 0)
25559 width = FRAME_CURSOR_WIDTH (f);
25560 width = min (cursor_glyph->pixel_width, width);
25561
25562 w->phys_cursor_width = width;
25563
25564
25565
25566 if ((cursor_glyph->resolved_level & 1) != 0)
25567 x += cursor_glyph->pixel_width - width;
25568
25569 x_fill_rectangle (f, gc, x,
25570 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
25571 width, row->height, false);
25572 }
25573 else
25574 {
25575 int dummy_x, dummy_y, dummy_h;
25576 int x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
25577
25578 if (width < 0)
25579 width = row->height;
25580
25581 width = min (row->height, width);
25582
25583 get_phys_cursor_geometry (w, row, cursor_glyph, &dummy_x,
25584 &dummy_y, &dummy_h);
25585
25586 if ((cursor_glyph->resolved_level & 1) != 0
25587 && cursor_glyph->pixel_width > w->phys_cursor_width - 1)
25588 x += cursor_glyph->pixel_width - w->phys_cursor_width + 1;
25589 x_fill_rectangle (f, gc, x,
25590 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
25591 row->height - width),
25592 w->phys_cursor_width - 1, width, false);
25593 }
25594
25595 x_reset_clip_rectangles (f, gc);
25596 }
25597 }
25598
25599
25600
25601
25602 static void
25603 x_define_frame_cursor (struct frame *f, Emacs_Cursor cursor)
25604 {
25605 if (!f->pointer_invisible
25606 && f->output_data.x->current_cursor != cursor)
25607 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
25608 f->output_data.x->current_cursor = cursor;
25609 }
25610
25611
25612
25613
25614 static void
25615 x_clear_frame_area (struct frame *f, int x, int y, int width, int height)
25616 {
25617 x_clear_area (f, x, y, width, height);
25618 }
25619
25620
25621
25622
25623 static void
25624 x_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x,
25625 int y, enum text_cursor_kinds cursor_type,
25626 int cursor_width, bool on_p, bool active_p)
25627 {
25628 #ifdef HAVE_X_I18N
25629 struct frame *f = XFRAME (WINDOW_FRAME (w));
25630 #endif
25631
25632 if (on_p)
25633 {
25634 w->phys_cursor_type = cursor_type;
25635 w->phys_cursor_on_p = true;
25636
25637 if (glyph_row->exact_window_width_line_p
25638 && (glyph_row->reversed_p
25639 ? (w->phys_cursor.hpos < 0)
25640 : (w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])))
25641 {
25642 glyph_row->cursor_in_fringe_p = true;
25643 draw_fringe_bitmap (w, glyph_row, glyph_row->reversed_p);
25644 }
25645 else
25646 {
25647 switch (cursor_type)
25648 {
25649 case HOLLOW_BOX_CURSOR:
25650 x_draw_hollow_cursor (w, glyph_row);
25651 break;
25652
25653 case FILLED_BOX_CURSOR:
25654 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
25655 break;
25656
25657 case BAR_CURSOR:
25658 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
25659 break;
25660
25661 case HBAR_CURSOR:
25662 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
25663 break;
25664
25665 case NO_CURSOR:
25666 w->phys_cursor_width = 0;
25667 break;
25668
25669 default:
25670 emacs_abort ();
25671 }
25672 }
25673
25674 #ifdef HAVE_X_I18N
25675 if (w == XWINDOW (f->selected_window))
25676 xic_set_preeditarea (w, x, y);
25677 #endif
25678 }
25679 }
25680
25681
25682
25683
25684
25685
25686 static bool
25687 x_bitmap_icon (struct frame *f, Lisp_Object file)
25688 {
25689 ptrdiff_t bitmap_id;
25690
25691 if (FRAME_X_WINDOW (f) == 0)
25692 return true;
25693
25694
25695 if (f->output_data.x->icon_bitmap > 0)
25696 image_destroy_bitmap (f, f->output_data.x->icon_bitmap);
25697 f->output_data.x->icon_bitmap = 0;
25698
25699 if (STRINGP (file))
25700 {
25701 #ifdef USE_GTK
25702
25703
25704 if (xg_set_icon (f, file))
25705 return false;
25706 #endif
25707 bitmap_id = image_create_bitmap_from_file (f, file);
25708 x_create_bitmap_mask (f, bitmap_id);
25709 }
25710 else
25711 {
25712
25713 if (FRAME_DISPLAY_INFO (f)->icon_bitmap_id < 0)
25714 {
25715 ptrdiff_t rc = -1;
25716
25717 #ifdef USE_GTK
25718
25719 if (xg_set_icon (f, xg_default_icon_file)
25720 || xg_set_icon_from_xpm_data (f, gnu_xpm_bits))
25721 {
25722 FRAME_DISPLAY_INFO (f)->icon_bitmap_id = -2;
25723 return false;
25724 }
25725
25726 #elif defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
25727
25728 if ((FRAME_X_VISUAL_INFO (f)->class == TrueColor
25729 || FRAME_X_VISUAL_INFO (f)->class == StaticColor
25730 || FRAME_X_VISUAL_INFO (f)->class == StaticGray)
25731
25732
25733
25734 || FRAME_X_VISUAL_INFO (f)->colormap_size >= (240 * 4))
25735 {
25736 rc = x_create_bitmap_from_xpm_data (f, gnu_xpm_bits);
25737 if (rc != -1)
25738 FRAME_DISPLAY_INFO (f)->icon_bitmap_id = rc;
25739 }
25740 #endif
25741
25742
25743 if (rc == -1)
25744 {
25745 rc = image_create_bitmap_from_data (f,
25746 (char *) gnu_xbm_bits,
25747 gnu_xbm_width,
25748 gnu_xbm_height);
25749 if (rc == -1)
25750 return true;
25751
25752 FRAME_DISPLAY_INFO (f)->icon_bitmap_id = rc;
25753 x_create_bitmap_mask (f, FRAME_DISPLAY_INFO (f)->icon_bitmap_id);
25754 }
25755 }
25756
25757
25758
25759
25760
25761 image_reference_bitmap (f, FRAME_DISPLAY_INFO (f)->icon_bitmap_id);
25762
25763 bitmap_id = FRAME_DISPLAY_INFO (f)->icon_bitmap_id;
25764 }
25765
25766 x_wm_set_icon_pixmap (f, bitmap_id);
25767 f->output_data.x->icon_bitmap = bitmap_id;
25768
25769 return false;
25770 }
25771
25772
25773
25774
25775
25776 bool
25777 x_text_icon (struct frame *f, const char *icon_name)
25778 {
25779 if (FRAME_X_WINDOW (f) == 0)
25780 return true;
25781
25782 {
25783 XTextProperty text;
25784 text.value = (unsigned char *) icon_name;
25785 text.encoding = XA_STRING;
25786 text.format = 8;
25787 text.nitems = strlen (icon_name);
25788 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text);
25789 }
25790
25791 if (f->output_data.x->icon_bitmap > 0)
25792 image_destroy_bitmap (f, f->output_data.x->icon_bitmap);
25793 f->output_data.x->icon_bitmap = 0;
25794 x_wm_set_icon_pixmap (f, 0);
25795
25796 return false;
25797 }
25798
25799
25800 struct x_error_message_stack
25801 {
25802
25803
25804 char *string;
25805
25806
25807 Display *dpy;
25808
25809
25810 x_special_error_handler handler;
25811
25812
25813 void *handler_data;
25814
25815
25816 struct x_error_message_stack *prev;
25817
25818
25819
25820
25821 unsigned long first_request;
25822 };
25823
25824
25825
25826
25827
25828
25829
25830
25831
25832 static struct x_error_message_stack *x_error_message;
25833
25834
25835 int x_error_message_count;
25836
25837
25838
25839
25840
25841
25842
25843 static bool
25844 x_is_serial_more_than (unsigned int a, unsigned int b)
25845 {
25846 if (a > b)
25847 return true;
25848
25849 return (b - a > X_ULONG_MAX / 2);
25850 }
25851
25852 static bool
25853 x_is_serial_more_than_or_equal_to (unsigned int a, unsigned int b)
25854 {
25855 if (a >= b)
25856 return true;
25857
25858 return (b - a > X_ULONG_MAX / 2);
25859 }
25860
25861 static bool
25862 x_is_serial_less_than (unsigned int a, unsigned int b)
25863 {
25864 if (a < b)
25865 return true;
25866
25867 return (a - b > X_ULONG_MAX / 2);
25868 }
25869
25870 static bool
25871 x_is_serial_less_than_or_equal_to (unsigned int a, unsigned int b)
25872 {
25873 if (a <= b)
25874 return true;
25875
25876 return (a - b > X_ULONG_MAX / 2);
25877 }
25878
25879 static struct x_error_message_stack *
25880 x_find_error_handler (Display *dpy, XErrorEvent *event)
25881 {
25882 struct x_error_message_stack *stack;
25883
25884 stack = x_error_message;
25885
25886 while (stack)
25887 {
25888 if (x_is_serial_more_than_or_equal_to (event->serial,
25889 stack->first_request)
25890 && dpy == stack->dpy)
25891 return stack;
25892
25893 stack = stack->prev;
25894 }
25895
25896 return NULL;
25897 }
25898
25899 void
25900 x_unwind_errors_to (int depth)
25901 {
25902 while (x_error_message_count > depth)
25903
25904
25905 x_uncatch_errors ();
25906 }
25907
25908 #define X_ERROR_MESSAGE_SIZE 200
25909
25910
25911
25912
25913
25914
25915 static void
25916 x_error_catcher (Display *display, XErrorEvent *event,
25917 struct x_error_message_stack *stack)
25918 {
25919 char buf[X_ERROR_MESSAGE_SIZE];
25920
25921 XGetErrorText (display, event->error_code,
25922 buf, X_ERROR_MESSAGE_SIZE);
25923
25924 if (stack->string)
25925 xfree (stack->string);
25926
25927 stack->string = xstrdup (buf);
25928
25929 if (stack->handler)
25930 stack->handler (display, event, stack->string,
25931 stack->handler_data);
25932 }
25933
25934
25935
25936
25937
25938
25939
25940
25941
25942
25943
25944
25945
25946
25947
25948
25949
25950
25951
25952
25953
25954
25955
25956
25957 void
25958 x_catch_errors_with_handler (Display *dpy, x_special_error_handler handler,
25959 void *handler_data)
25960 {
25961 struct x_error_message_stack *data;
25962
25963 data = xzalloc (sizeof *data);
25964 data->dpy = dpy;
25965 data->handler = handler;
25966 data->handler_data = handler_data;
25967 data->prev = x_error_message;
25968 data->first_request = XNextRequest (dpy);
25969 x_error_message = data;
25970
25971 ++x_error_message_count;
25972 }
25973
25974 void
25975 x_catch_errors (Display *dpy)
25976 {
25977 x_catch_errors_with_handler (dpy, NULL, NULL);
25978 }
25979
25980
25981
25982 static struct x_failable_request *
25983 x_request_can_fail (struct x_display_info *dpyinfo,
25984 unsigned long request)
25985 {
25986 struct x_failable_request *failable_requests;
25987
25988 for (failable_requests = dpyinfo->failable_requests;
25989 failable_requests < dpyinfo->next_failable_request;
25990 failable_requests++)
25991 {
25992 if (x_is_serial_more_than_or_equal_to (request,
25993 failable_requests->start)
25994 && (!failable_requests->end
25995 || x_is_serial_less_than_or_equal_to (request,
25996 failable_requests->end)))
25997 return failable_requests;
25998 }
25999
26000 return NULL;
26001 }
26002
26003
26004
26005 static void
26006 x_clean_failable_requests (struct x_display_info *dpyinfo)
26007 {
26008 struct x_failable_request *first, *last;
26009
26010 last = dpyinfo->next_failable_request;
26011
26012 for (first = dpyinfo->failable_requests; first < last; first++)
26013 {
26014 if (x_is_serial_more_than (first->start,
26015 LastKnownRequestProcessed (dpyinfo->display))
26016 || !first->end
26017 || x_is_serial_more_than (first->end,
26018 LastKnownRequestProcessed (dpyinfo->display)))
26019 break;
26020 }
26021
26022 if (first != last)
26023 memmove (&dpyinfo->failable_requests, first,
26024 sizeof *first * (last - first));
26025
26026 dpyinfo->next_failable_request = (dpyinfo->failable_requests
26027 + (last - first));
26028 }
26029
26030
26031
26032
26033
26034
26035
26036
26037
26038
26039
26040
26041
26042
26043
26044
26045
26046
26047
26048 void
26049 x_ignore_errors_for_next_request (struct x_display_info *dpyinfo,
26050 unsigned int selection_serial)
26051 {
26052 struct x_failable_request *request, *max;
26053 unsigned long next_request;
26054 #ifdef HAVE_GTK3
26055 GdkDisplay *gdpy;
26056 #endif
26057
26058
26059
26060 block_input ();
26061
26062 #ifdef HAVE_GTK3
26063
26064
26065
26066
26067
26068 gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display);
26069
26070 if (gdpy)
26071 gdk_x11_display_error_trap_push (gdpy);
26072 #endif
26073
26074 if ((dpyinfo->next_failable_request
26075 != dpyinfo->failable_requests)
26076 && (dpyinfo->next_failable_request - 1)->end == 0)
26077
26078
26079 emacs_abort ();
26080
26081 request = dpyinfo->next_failable_request;
26082 max = dpyinfo->failable_requests + N_FAILABLE_REQUESTS;
26083 next_request = XNextRequest (dpyinfo->display);
26084
26085 if (request >= max)
26086 {
26087
26088
26089 if ((LastKnownRequestProcessed (dpyinfo->display)
26090 != next_request - 1))
26091 XSync (dpyinfo->display, False);
26092
26093 x_clean_failable_requests (dpyinfo);
26094 request = dpyinfo->next_failable_request;
26095 }
26096
26097 if (request >= max)
26098
26099
26100 emacs_abort ();
26101
26102 request->start = next_request;
26103 request->end = 0;
26104 request->selection_serial = selection_serial;
26105
26106 dpyinfo->next_failable_request++;
26107 }
26108
26109 void
26110 x_stop_ignoring_errors (struct x_display_info *dpyinfo)
26111 {
26112 struct x_failable_request *range;
26113 #ifdef HAVE_GTK3
26114 GdkDisplay *gdpy;
26115 #endif
26116
26117 range = dpyinfo->next_failable_request - 1;
26118 range->end = XNextRequest (dpyinfo->display) - 1;
26119
26120
26121
26122
26123 if (x_is_serial_less_than (range->end, range->start))
26124 emacs_abort ();
26125
26126 #ifdef HAVE_GTK3
26127 gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display);
26128
26129 if (gdpy)
26130 gdk_x11_display_error_trap_pop_ignored (gdpy);
26131 #endif
26132
26133 unblock_input ();
26134 }
26135
26136
26137
26138
26139
26140
26141
26142
26143 void
26144 x_uncatch_errors_after_check (void)
26145 {
26146 struct x_error_message_stack *tmp;
26147
26148 block_input ();
26149 tmp = x_error_message;
26150 x_error_message = x_error_message->prev;
26151 --x_error_message_count;
26152 if (tmp->string)
26153 xfree (tmp->string);
26154 xfree (tmp);
26155 unblock_input ();
26156 }
26157
26158
26159
26160 void
26161 x_uncatch_errors (void)
26162 {
26163 struct x_error_message_stack *tmp;
26164 struct x_display_info *dpyinfo;
26165
26166
26167
26168
26169
26170 if (x_error_message == NULL)
26171 return;
26172
26173 block_input ();
26174
26175 dpyinfo = x_display_info_for_display (x_error_message->dpy);
26176
26177
26178
26179 if (dpyinfo != 0
26180
26181
26182 && (LastKnownRequestProcessed (x_error_message->dpy)
26183 != XNextRequest (x_error_message->dpy) - 1)
26184
26185
26186 && (NextRequest (x_error_message->dpy)
26187 > x_error_message->first_request))
26188 {
26189 XSync (x_error_message->dpy, False);
26190 x_clean_failable_requests (dpyinfo);
26191 }
26192
26193 tmp = x_error_message;
26194 x_error_message = x_error_message->prev;
26195 --x_error_message_count;
26196 if (tmp->string)
26197 xfree (tmp->string);
26198 xfree (tmp);
26199 unblock_input ();
26200 }
26201
26202
26203
26204
26205
26206 void
26207 x_check_errors (Display *dpy, const char *format)
26208 {
26209 struct x_display_info *dpyinfo;
26210 char *string;
26211
26212
26213
26214 if (dpy != x_error_message->dpy)
26215 emacs_abort ();
26216
26217
26218
26219 if ((LastKnownRequestProcessed (dpy)
26220 != XNextRequest (dpy) - 1)
26221 && (NextRequest (dpy)
26222 > x_error_message->first_request))
26223 XSync (dpy, False);
26224
26225 dpyinfo = x_display_info_for_display (dpy);
26226
26227
26228 if (dpyinfo)
26229 x_clean_failable_requests (dpyinfo);
26230
26231 if (x_error_message->string)
26232 {
26233 string = alloca (strlen (x_error_message->string) + 1);
26234 strcpy (string, x_error_message->string);
26235
26236 error (format, string);
26237 }
26238 }
26239
26240
26241
26242
26243 bool
26244 x_had_errors_p (Display *dpy)
26245 {
26246 struct x_display_info *dpyinfo;
26247
26248
26249
26250 if (dpy != x_error_message->dpy)
26251 emacs_abort ();
26252
26253
26254 if ((LastKnownRequestProcessed (dpy)
26255 != XNextRequest (dpy) - 1)
26256 && (NextRequest (dpy)
26257 > x_error_message->first_request))
26258 XSync (dpy, False);
26259
26260 dpyinfo = x_display_info_for_display (dpy);
26261
26262
26263 if (dpyinfo)
26264 x_clean_failable_requests (dpyinfo);
26265
26266 return !!x_error_message->string;
26267 }
26268
26269
26270
26271
26272 void
26273 x_clear_errors (Display *dpy)
26274 {
26275
26276
26277 if (dpy != x_error_message->dpy)
26278 emacs_abort ();
26279
26280 xfree (x_error_message->string);
26281 x_error_message->string = NULL;
26282 }
26283
26284 #if false
26285
26286
26287
26288
26289 void
26290 x_fully_uncatch_errors (void)
26291 {
26292 while (x_error_message)
26293 x_uncatch_errors ();
26294 }
26295 #endif
26296
26297 #if false
26298 static unsigned int x_wire_count;
26299
26300 static int
26301 x_trace_wire (Display *dpy)
26302 {
26303 fprintf (stderr, "Lib call: %u\n", ++x_wire_count);
26304 return 0;
26305 }
26306 #endif
26307
26308
26309
26310
26311
26312
26313
26314
26315 static char *error_msg;
26316
26317
26318
26319
26320
26321 static void
26322 x_try_restore_frame (void)
26323 {
26324 Lisp_Object tail, frame;
26325
26326 FOR_EACH_FRAME (tail, frame)
26327 {
26328 if (!NILP (do_switch_frame (frame, 0, 1, Qnil)))
26329 return;
26330 }
26331 }
26332
26333
26334
26335
26336 static void
26337 x_connection_closed (Display *dpy, const char *error_message, bool ioerror)
26338 {
26339 struct x_display_info *dpyinfo;
26340 Lisp_Object frame, tail;
26341 specpdl_ref idx = SPECPDL_INDEX ();
26342 Emacs_XIOErrorHandler io_error_handler;
26343 xm_drop_start_message dmsg;
26344 struct frame *f;
26345 Lisp_Object minibuf_frame, tmp;
26346 struct x_failable_request *failable;
26347 struct x_error_message_stack *stack;
26348 static Display *current_display;
26349
26350
26351
26352
26353 if (current_display == dpy)
26354 return;
26355
26356 current_display = dpy;
26357
26358 dpyinfo = x_display_info_for_display (dpy);
26359 error_msg = alloca (strlen (error_message) + 1);
26360 strcpy (error_msg, error_message);
26361
26362
26363 specbind (Qinhibit_redisplay, Qt);
26364
26365
26366
26367
26368
26369
26370 if (x_dnd_in_progress || x_dnd_waiting_for_finish)
26371 {
26372 if (!ioerror)
26373 {
26374
26375
26376 io_error_handler = XSetIOErrorHandler (x_dnd_io_error_handler);
26377
26378 if (!!sigsetjmp (x_dnd_disconnect_handler, 1)
26379 && x_dnd_in_progress
26380 && dpy == (x_dnd_waiting_for_finish
26381 ? x_dnd_finish_display
26382 : FRAME_X_DISPLAY (x_dnd_frame)))
26383 {
26384
26385
26386 f = x_dnd_frame;
26387
26388 if (x_dnd_last_seen_window != None
26389 && x_dnd_last_protocol_version != -1)
26390 x_dnd_send_leave (x_dnd_frame,
26391 x_dnd_last_seen_window,
26392 x_dnd_last_seen_toplevel);
26393 else if (x_dnd_last_seen_window != None
26394 && !XM_DRAG_STYLE_IS_DROP_ONLY (x_dnd_last_motif_style)
26395 && x_dnd_last_motif_style != XM_DRAG_STYLE_NONE
26396 && x_dnd_motif_setup_p)
26397 {
26398 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
26399 XM_DRAG_REASON_DROP_START);
26400 dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST;
26401 dmsg.timestamp = FRAME_DISPLAY_INFO (f)->last_user_time;
26402 dmsg.side_effects
26403 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f),
26404 x_dnd_wanted_action),
26405 XM_DROP_SITE_VALID, x_dnd_motif_operations,
26406 XM_DROP_ACTION_DROP_CANCEL);
26407 dmsg.x = 0;
26408 dmsg.y = 0;
26409 dmsg.index_atom = x_dnd_motif_atom;
26410 dmsg.source_window = FRAME_X_WINDOW (f);
26411
26412 x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f,
26413 x_dnd_last_seen_window, 0);
26414 xm_send_drop_message (FRAME_DISPLAY_INFO (f), FRAME_X_WINDOW (f),
26415 x_dnd_last_seen_window, &dmsg);
26416 }
26417 }
26418
26419 XSetIOErrorHandler (io_error_handler);
26420 }
26421
26422 dpyinfo = x_display_info_for_display (dpy);
26423
26424 x_dnd_last_seen_window = None;
26425 x_dnd_last_seen_toplevel = None;
26426 x_dnd_in_progress = false;
26427 x_dnd_waiting_for_finish = false;
26428
26429 if (x_dnd_use_toplevels)
26430 x_dnd_free_toplevels (!ioerror);
26431
26432 x_dnd_return_frame_object = NULL;
26433 x_dnd_movement_frame = NULL;
26434 x_dnd_wheel_frame = NULL;
26435 x_dnd_frame = NULL;
26436 }
26437
26438 if (dpyinfo)
26439 {
26440
26441
26442 dpyinfo->reference_count++;
26443 dpyinfo->terminal->reference_count++;
26444 if (ioerror)
26445 dpyinfo->display = 0;
26446 }
26447
26448
26449
26450
26451
26452 block_input ();
26453
26454
26455
26456 FOR_EACH_FRAME (tail, frame)
26457 {
26458
26459
26460 if (FRAME_TOOLTIP_P (XFRAME (frame)))
26461 continue;
26462
26463 minibuf_frame
26464 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
26465
26466 if (FRAME_X_P (XFRAME (frame))
26467 && FRAME_X_P (XFRAME (minibuf_frame))
26468 && ! EQ (frame, minibuf_frame)
26469 && FRAME_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
26470 delete_frame (frame, Qnoelisp);
26471 }
26472
26473
26474
26475
26476 FOR_EACH_FRAME (tail, frame)
26477 if (FRAME_X_P (XFRAME (frame))
26478 && FRAME_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
26479 {
26480
26481
26482 kset_default_minibuffer_frame (FRAME_KBOARD (XFRAME (frame)), Qt);
26483 delete_frame (frame, Qnoelisp);
26484 }
26485
26486
26487
26488 if (dpyinfo)
26489 {
26490
26491
26492
26493 #ifdef USE_GTK
26494
26495
26496
26497
26498 shut_down_emacs (0, Qnil);
26499 fprintf (stderr, "%s\n\
26500 When compiled with GTK, Emacs cannot recover from X disconnects.\n\
26501 This is a GTK bug: https://gitlab.gnome.org/GNOME/gtk/issues/221\n\
26502 For details, see etc/PROBLEMS.\n",
26503 error_msg);
26504 emacs_abort ();
26505 #endif
26506
26507
26508 dpyinfo->display = 0;
26509
26510 dpyinfo->reference_count--;
26511 dpyinfo->terminal->reference_count--;
26512 if (dpyinfo->reference_count != 0)
26513
26514 emacs_abort ();
26515
26516
26517
26518 if (dpyinfo->terminal == terminal_list
26519 && !terminal_list->next_terminal)
26520 {
26521 fprintf (stderr, "%s\n", error_msg);
26522
26523 if (!ioerror && dpyinfo)
26524 {
26525
26526
26527
26528 if ((dpyinfo->failable_requests
26529 != dpyinfo->next_failable_request) || x_error_message)
26530 fprintf (stderr, "X error handlers currently installed:\n");
26531
26532 for (failable = dpyinfo->failable_requests;
26533 failable < dpyinfo->next_failable_request;
26534 ++failable)
26535 {
26536 if (failable->end)
26537 fprintf (stderr, "Ignoring errors between %lu to %lu\n",
26538 failable->start, failable->end);
26539 else
26540 fprintf (stderr, "Ignoring errors from %lu onwards\n",
26541 failable->start);
26542 }
26543
26544 for (stack = x_error_message; stack; stack = stack->prev)
26545 fprintf (stderr, "Trapping errors from %lu\n",
26546 stack->first_request);
26547 }
26548 }
26549
26550 XSETTERMINAL (tmp, dpyinfo->terminal);
26551 Fdelete_terminal (tmp, Qnoelisp);
26552 }
26553
26554
26555
26556 if (NILP (selected_frame))
26557 x_try_restore_frame ();
26558
26559 unblock_input ();
26560
26561
26562
26563
26564
26565 if (terminal_list == 0 || NILP (selected_frame))
26566 Fkill_emacs (make_fixnum (70), Qnil);
26567
26568 totally_unblock_input ();
26569
26570 unbind_to (idx, Qnil);
26571 clear_waiting_for_input ();
26572
26573
26574
26575
26576 current_display = NULL;
26577 error ("%s", error_msg);
26578 }
26579
26580 static void x_error_quitter (Display *, XErrorEvent *);
26581
26582
26583
26584
26585 static int
26586 x_error_handler (Display *display, XErrorEvent *event)
26587 {
26588 struct x_error_message_stack *stack;
26589 struct x_display_info *dpyinfo;
26590 struct x_failable_request *fail, *last;
26591
26592 #if defined USE_GTK && defined HAVE_GTK3
26593 if ((event->error_code == BadMatch
26594 || event->error_code == BadWindow)
26595 && event->request_code == X_SetInputFocus)
26596 return 0;
26597 #endif
26598
26599 dpyinfo = x_display_info_for_display (display);
26600
26601 if (dpyinfo)
26602 {
26603 fail = x_request_can_fail (dpyinfo, event->serial);
26604
26605 if (fail)
26606 {
26607
26608
26609
26610 if (event->serial == fail->end)
26611 {
26612 last = dpyinfo->next_failable_request;
26613 memmove (&dpyinfo->failable_requests, fail,
26614 sizeof *fail * (last - fail));
26615 dpyinfo->next_failable_request = (dpyinfo->failable_requests
26616 + (last - fail));
26617 }
26618
26619
26620
26621
26622 if (fail->selection_serial)
26623 {
26624 x_handle_selection_error (fail->selection_serial,
26625 event);
26626
26627
26628
26629
26630
26631 fail->selection_serial = 0;
26632 }
26633
26634 return 0;
26635 }
26636 }
26637
26638
26639
26640
26641 #ifdef HAVE_XINPUT2
26642
26643
26644 if (dpyinfo && dpyinfo->supports_xi2
26645 && event->request_code == dpyinfo->xi2_opcode
26646 && (event->minor_code == X_XIGrabDevice
26647 || event->minor_code == X_XIUngrabDevice
26648 || event->minor_code == X_XIAllowEvents))
26649 return 0;
26650 #endif
26651
26652 stack = x_find_error_handler (display, event);
26653
26654 if (stack)
26655 x_error_catcher (display, event, stack);
26656 else
26657 x_error_quitter (display, event);
26658 return 0;
26659 }
26660
26661
26662
26663
26664
26665
26666
26667 static void NO_INLINE
26668 x_error_quitter (Display *display, XErrorEvent *event)
26669 {
26670 char buf[256], buf1[800 + INT_STRLEN_BOUND (int)
26671 + INT_STRLEN_BOUND (unsigned long)
26672 + INT_STRLEN_BOUND (XID)
26673 + INT_STRLEN_BOUND (int)];
26674
26675
26676
26677
26678 if (event->error_code == BadName)
26679 return;
26680
26681
26682
26683
26684 XGetErrorText (display, event->error_code, buf, sizeof (buf));
26685 sprintf (buf1, "X protocol error: %s on protocol request %d\n"
26686 "Serial no: %lu\n"
26687 "Failing resource ID (if any): 0x%lx\n"
26688 "Minor code: %d\n"
26689 "This is a bug! Please report this to bug-gnu-emacs@gnu.org!\n",
26690 buf, event->request_code, event->serial, event->resourceid,
26691 event->minor_code);
26692 x_connection_closed (display, buf1, false);
26693 }
26694
26695
26696
26697
26698
26699
26700 static int NO_INLINE
26701 x_io_error_quitter (Display *display)
26702 {
26703 char buf[256];
26704
26705 snprintf (buf, sizeof buf, "Connection lost to X server '%s'",
26706 DisplayString (display));
26707 x_connection_closed (display, buf, true);
26708
26709 return 0;
26710 }
26711
26712
26713
26714
26715
26716
26717
26718
26719
26720 static Lisp_Object
26721 x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
26722 {
26723 struct font *font = XFONT_OBJECT (font_object);
26724 int unit, font_ascent, font_descent;
26725
26726 if (fontset < 0)
26727 fontset = fontset_from_font (font_object);
26728 FRAME_FONTSET (f) = fontset;
26729 if (FRAME_FONT (f) == font)
26730
26731
26732 return font_object;
26733
26734 FRAME_FONT (f) = font;
26735 FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
26736 FRAME_COLUMN_WIDTH (f) = font->average_width;
26737 get_font_ascent_descent (font, &font_ascent, &font_descent);
26738 FRAME_LINE_HEIGHT (f) = font_ascent + font_descent;
26739
26740 #ifndef USE_X_TOOLKIT
26741 FRAME_MENU_BAR_HEIGHT (f) = FRAME_MENU_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
26742 #endif
26743
26744 FRAME_TAB_BAR_HEIGHT (f) = FRAME_TAB_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
26745
26746
26747
26748
26749
26750 unit = FRAME_COLUMN_WIDTH (f);
26751 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
26752 FRAME_CONFIG_SCROLL_BAR_COLS (f)
26753 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + unit - 1) / unit;
26754 else
26755 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit;
26756
26757
26758
26759
26760
26761 if (FRAME_X_WINDOW (f) != 0 && !FRAME_TOOLTIP_P (f))
26762 adjust_frame_size
26763 (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
26764 FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3, false, Qfont);
26765
26766 #ifdef HAVE_X_I18N
26767 if (FRAME_XIC (f)
26768 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
26769 {
26770 block_input ();
26771 xic_set_xfontset (f, SSDATA (fontset_ascii (fontset)));
26772 unblock_input ();
26773 }
26774 #endif
26775
26776 return font_object;
26777 }
26778
26779
26780
26781
26782
26783
26784 #ifdef HAVE_X_I18N
26785
26786 #ifdef HAVE_X11R6
26787
26788
26789
26790
26791
26792
26793
26794 #ifdef HAVE_X11R6_XIM
26795
26796
26797
26798
26799
26800
26801
26802 static void
26803 x_maybe_clear_preedit (struct frame *f)
26804 {
26805 struct x_output *output;
26806 struct input_event ie;
26807
26808 output = FRAME_X_OUTPUT (f);
26809
26810 if (!output->preedit_chars)
26811 return;
26812
26813 EVENT_INIT (ie);
26814 ie.kind = PREEDIT_TEXT_EVENT;
26815 ie.arg = Qnil;
26816 XSETFRAME (ie.frame_or_window, f);
26817 XSETINT (ie.x, 0);
26818 XSETINT (ie.y, 0);
26819 kbd_buffer_store_event (&ie);
26820
26821 xfree (output->preedit_chars);
26822
26823 output->preedit_size = 0;
26824 output->preedit_active = false;
26825 output->preedit_chars = NULL;
26826 output->preedit_caret = 0;
26827 }
26828
26829
26830
26831
26832
26833 static void
26834 xim_destroy_callback (XIM xim, XPointer client_data, XPointer call_data)
26835 {
26836 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
26837 Lisp_Object frame, tail;
26838
26839 block_input ();
26840
26841
26842 FOR_EACH_FRAME (tail, frame)
26843 {
26844 struct frame *f = XFRAME (frame);
26845 if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) == dpyinfo)
26846 {
26847 FRAME_XIC (f) = NULL;
26848 xic_free_xfontset (f);
26849
26850
26851 x_maybe_clear_preedit (f);
26852 }
26853 }
26854
26855
26856 dpyinfo->xim = NULL;
26857
26858
26859
26860 if (dpyinfo->xim_styles)
26861 XFree (dpyinfo->xim_styles);
26862 dpyinfo->xim_styles = NULL;
26863 unblock_input ();
26864 }
26865
26866 #endif
26867
26868 #endif
26869
26870
26871
26872
26873 static void
26874 xim_open_dpy (struct x_display_info *dpyinfo, char *resource_name)
26875 {
26876 #ifdef HAVE_XIM
26877 XIM xim;
26878 const char *locale;
26879
26880 if (dpyinfo->use_xim)
26881 {
26882 if (dpyinfo->xim)
26883 {
26884 XCloseIM (dpyinfo->xim);
26885
26886
26887
26888
26889 if (dpyinfo->xim_styles)
26890 XFree (dpyinfo->xim_styles);
26891 dpyinfo->xim_styles = NULL;
26892 }
26893
26894 xim = XOpenIM (dpyinfo->display, dpyinfo->rdb, resource_name,
26895 emacs_class);
26896 dpyinfo->xim = xim;
26897
26898 if (xim)
26899 {
26900 #ifdef HAVE_X11R6_XIM
26901 XIMCallback destroy;
26902 #endif
26903
26904
26905 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
26906
26907 #ifdef HAVE_X11R6_XIM
26908 destroy.callback = xim_destroy_callback;
26909 destroy.client_data = (XPointer)dpyinfo;
26910 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
26911 #endif
26912
26913 locale = XLocaleOfIM (xim);
26914
26915
26916
26917
26918 dpyinfo->xim_coding = safe_call1 (Vx_input_coding_function,
26919 build_string (locale));
26920 }
26921 }
26922 else
26923 #endif
26924 dpyinfo->xim = NULL;
26925 }
26926
26927
26928 #ifdef HAVE_X11R6_XIM
26929
26930
26931
26932
26933
26934
26935 static void
26936 xim_instantiate_callback (Display *display, XPointer client_data, XPointer call_data)
26937 {
26938 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
26939 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
26940
26941 if (x_dnd_in_progress)
26942 return;
26943
26944
26945 if (dpyinfo->xim)
26946 return;
26947
26948 xim_open_dpy (dpyinfo, xim_inst->resource_name);
26949
26950
26951
26952 if (dpyinfo->xim && dpyinfo->reference_count > 0)
26953 {
26954 Lisp_Object tail, frame;
26955
26956 block_input ();
26957 FOR_EACH_FRAME (tail, frame)
26958 {
26959 struct frame *f = XFRAME (frame);
26960
26961 if (FRAME_X_P (f)
26962 && FRAME_DISPLAY_INFO (f) == xim_inst->dpyinfo)
26963 if (FRAME_XIC (f) == NULL)
26964 {
26965 create_frame_xic (f);
26966 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
26967 xic_set_statusarea (f);
26968 struct window *w = XWINDOW (f->selected_window);
26969 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
26970 }
26971 }
26972
26973 unblock_input ();
26974 }
26975 }
26976
26977 #endif
26978
26979
26980
26981
26982
26983
26984
26985 static void
26986 xim_initialize (struct x_display_info *dpyinfo, char *resource_name)
26987 {
26988 dpyinfo->xim = NULL;
26989 #ifdef HAVE_XIM
26990 if (dpyinfo->use_xim)
26991 {
26992 #ifdef HAVE_X11R6_XIM
26993 struct xim_inst_t *xim_inst = xmalloc (sizeof *xim_inst);
26994 Bool ret;
26995
26996 dpyinfo->xim_callback_data = xim_inst;
26997 xim_inst->dpyinfo = dpyinfo;
26998 xim_inst->resource_name = xstrdup (resource_name);
26999
27000
27001
27002
27003
27004
27005 ret = XRegisterIMInstantiateCallback (dpyinfo->display,
27006 dpyinfo->rdb,
27007 xim_inst->resource_name,
27008 emacs_class,
27009 xim_instantiate_callback,
27010 (void *) xim_inst);
27011 eassert (ret);
27012 #else
27013 xim_open_dpy (dpyinfo, resource_name);
27014 #endif
27015 }
27016 #endif
27017 }
27018
27019
27020
27021
27022
27023
27024
27025 static void
27026 xim_close_dpy (struct x_display_info *dpyinfo)
27027 {
27028 #ifdef HAVE_XIM
27029 #ifdef HAVE_X11R6_XIM
27030 struct xim_inst_t *xim_inst;
27031 Bool rc;
27032
27033
27034
27035
27036
27037 if (dpyinfo->xim_callback_data)
27038 {
27039 xim_inst = dpyinfo->xim_callback_data;
27040
27041 if (dpyinfo->display)
27042 {
27043 rc = XUnregisterIMInstantiateCallback (dpyinfo->display,
27044 dpyinfo->rdb,
27045 xim_inst->resource_name,
27046 emacs_class,
27047 xim_instantiate_callback,
27048 (void *) xim_inst);
27049 eassert (rc);
27050 }
27051
27052 xfree (xim_inst->resource_name);
27053 xfree (xim_inst);
27054 }
27055 #endif
27056
27057
27058
27059
27060
27061 if (dpyinfo->display && dpyinfo->xim)
27062 XCloseIM (dpyinfo->xim);
27063 dpyinfo->xim = NULL;
27064
27065
27066
27067 if (dpyinfo->xim_styles)
27068 XFree (dpyinfo->xim_styles);
27069 dpyinfo->xim_styles = NULL;
27070 #endif
27071 }
27072
27073 #endif
27074
27075
27076
27077
27078
27079
27080 static void
27081 x_calc_absolute_position (struct frame *f)
27082 {
27083 int flags = f->size_hint_flags;
27084 struct frame *p = FRAME_PARENT_FRAME (f);
27085
27086
27087
27088 if (! ((flags & XNegative) || (flags & YNegative)))
27089 return;
27090
27091
27092
27093 if ((flags & XNegative) && (f->left_pos <= 0))
27094 {
27095 int width = FRAME_PIXEL_WIDTH (f);
27096
27097
27098
27099 if (f->output_data.x->has_been_visible && !p)
27100 {
27101 Lisp_Object frame;
27102 Lisp_Object edges = Qnil;
27103
27104 XSETFRAME (frame, f);
27105 edges = Fx_frame_edges (frame, Qouter_edges);
27106 if (!NILP (edges))
27107 width = (XFIXNUM (Fnth (make_fixnum (2), edges))
27108 - XFIXNUM (Fnth (make_fixnum (0), edges)));
27109 }
27110
27111 if (p)
27112 f->left_pos = (FRAME_PIXEL_WIDTH (p) - width - 2 * f->border_width
27113 + f->left_pos);
27114 else
27115 f->left_pos = (x_display_pixel_width (FRAME_DISPLAY_INFO (f))
27116 - width + f->left_pos);
27117
27118 }
27119
27120 if ((flags & YNegative) && (f->top_pos <= 0))
27121 {
27122 int height = FRAME_PIXEL_HEIGHT (f);
27123
27124 #if defined USE_X_TOOLKIT && defined USE_MOTIF
27125
27126
27127
27128
27129
27130
27131
27132
27133
27134
27135
27136
27137 XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
27138 #endif
27139
27140 if (f->output_data.x->has_been_visible && !p)
27141 {
27142 Lisp_Object frame;
27143 Lisp_Object edges = Qnil;
27144
27145 XSETFRAME (frame, f);
27146 if (NILP (edges))
27147 edges = Fx_frame_edges (frame, Qouter_edges);
27148 if (!NILP (edges))
27149 height = (XFIXNUM (Fnth (make_fixnum (3), edges))
27150 - XFIXNUM (Fnth (make_fixnum (1), edges)));
27151 }
27152
27153 if (p)
27154 f->top_pos = (FRAME_PIXEL_HEIGHT (p) - height - 2 * f->border_width
27155 + f->top_pos);
27156 else
27157 f->top_pos = (x_display_pixel_height (FRAME_DISPLAY_INFO (f))
27158 - height + f->top_pos);
27159 }
27160
27161
27162
27163
27164 f->size_hint_flags &= ~ (XNegative | YNegative);
27165 }
27166
27167
27168
27169
27170
27171
27172
27173 static void
27174 x_set_offset (struct frame *f, int xoff, int yoff, int change_gravity)
27175 {
27176 int modified_top, modified_left;
27177 #ifdef USE_GTK
27178 int scale = xg_get_scale (f);
27179 #endif
27180
27181 if (change_gravity > 0)
27182 {
27183 f->top_pos = yoff;
27184 f->left_pos = xoff;
27185 f->size_hint_flags &= ~ (XNegative | YNegative);
27186 if (xoff < 0)
27187 f->size_hint_flags |= XNegative;
27188 if (yoff < 0)
27189 f->size_hint_flags |= YNegative;
27190 f->win_gravity = NorthWestGravity;
27191 }
27192
27193 x_calc_absolute_position (f);
27194
27195 block_input ();
27196 x_wm_set_size_hint (f, 0, false);
27197
27198 #ifdef USE_GTK
27199 if (x_gtk_use_window_move)
27200 {
27201
27202
27203
27204
27205 if (change_gravity != 0 && FRAME_GTK_OUTER_WIDGET (f))
27206 gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
27207 f->left_pos / scale, f->top_pos / scale);
27208 unblock_input ();
27209 return;
27210 }
27211 #endif
27212
27213 modified_left = f->left_pos;
27214 modified_top = f->top_pos;
27215
27216 if (change_gravity != 0 && FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A)
27217 {
27218
27219
27220
27221 modified_left += FRAME_X_OUTPUT (f)->move_offset_left;
27222 modified_top += FRAME_X_OUTPUT (f)->move_offset_top;
27223 }
27224
27225 #ifdef USE_GTK
27226
27227 gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
27228 modified_left / scale, modified_top / scale);
27229 #else
27230 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
27231 modified_left, modified_top);
27232 #endif
27233
27234
27235
27236 if (NILP (Vx_lax_frame_positioning))
27237 {
27238
27239 if (!FRAME_PARENT_FRAME (f)
27240
27241
27242
27243 && NILP (Vx_no_window_manager))
27244 {
27245 x_sync_with_move (f, f->left_pos, f->top_pos,
27246 FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN);
27247
27248
27249
27250
27251
27252
27253
27254
27255
27256
27257
27258 if (change_gravity != 0
27259 && (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
27260 || (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A
27261 && (FRAME_X_OUTPUT (f)->move_offset_left == 0
27262 && FRAME_X_OUTPUT (f)->move_offset_top == 0))))
27263 x_check_expected_move (f, modified_left, modified_top);
27264 }
27265
27266
27267
27268 else
27269 XSync (FRAME_X_DISPLAY (f), False);
27270 }
27271
27272 unblock_input ();
27273 }
27274
27275 static Window
27276 x_get_wm_check_window (struct x_display_info *dpyinfo)
27277 {
27278 Window result;
27279 unsigned char *tmp_data = NULL;
27280 int rc, actual_format;
27281 unsigned long actual_size, bytes_remaining;
27282 Atom actual_type;
27283
27284 rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window,
27285 dpyinfo->Xatom_net_supporting_wm_check,
27286 0, 1, False, XA_WINDOW, &actual_type,
27287 &actual_format, &actual_size,
27288 &bytes_remaining, &tmp_data);
27289
27290 if (rc != Success || actual_type != XA_WINDOW
27291 || actual_format != 32 || actual_size != 1)
27292 {
27293 if (tmp_data)
27294 XFree (tmp_data);
27295
27296 return None;
27297 }
27298
27299 result = *(Window *) tmp_data;
27300 XFree (tmp_data);
27301
27302 return result;
27303 }
27304
27305
27306
27307
27308
27309
27310
27311 bool
27312 x_wm_supports_1 (struct x_display_info *dpyinfo, Atom want_atom)
27313 {
27314 Atom actual_type;
27315 unsigned long actual_size, bytes_remaining;
27316 int i, rc, actual_format;
27317 bool ret;
27318 Window wmcheck_window;
27319 Window target_window = dpyinfo->root_window;
27320 int max_len = 65536;
27321 Display *dpy = dpyinfo->display;
27322 unsigned char *tmp_data = NULL;
27323 Atom target_type = XA_WINDOW;
27324
27325
27326
27327 if (!NILP (Vx_no_window_manager))
27328 return false;
27329
27330
27331
27332
27333 if (dpyinfo->untrusted)
27334 return false;
27335
27336 block_input ();
27337
27338 x_catch_errors (dpy);
27339
27340 wmcheck_window = dpyinfo->net_supported_window;
27341
27342 if (wmcheck_window == None)
27343 wmcheck_window = x_get_wm_check_window (dpyinfo);
27344
27345 if (!x_special_window_exists_p (dpyinfo, wmcheck_window))
27346 {
27347 if (dpyinfo->net_supported_window != None)
27348 {
27349 dpyinfo->net_supported_window = None;
27350 wmcheck_window = x_get_wm_check_window (dpyinfo);
27351
27352 if (!x_special_window_exists_p (dpyinfo, wmcheck_window))
27353 {
27354 x_uncatch_errors ();
27355 unblock_input ();
27356 return false;
27357 }
27358 }
27359 else
27360 {
27361 x_uncatch_errors ();
27362 unblock_input ();
27363 return false;
27364 }
27365 }
27366
27367 if (dpyinfo->net_supported_window != wmcheck_window)
27368 {
27369
27370 if (dpyinfo->net_supported_atoms != NULL)
27371 XFree (dpyinfo->net_supported_atoms);
27372 dpyinfo->net_supported_atoms = NULL;
27373 dpyinfo->nr_net_supported_atoms = 0;
27374 dpyinfo->net_supported_window = 0;
27375
27376 target_type = XA_ATOM;
27377 tmp_data = NULL;
27378 rc = XGetWindowProperty (dpy, target_window,
27379 dpyinfo->Xatom_net_supported,
27380 0, max_len, False, target_type,
27381 &actual_type, &actual_format, &actual_size,
27382 &bytes_remaining, &tmp_data);
27383
27384 if (rc != Success || actual_type != XA_ATOM || x_had_errors_p (dpy))
27385 {
27386 if (tmp_data)
27387 XFree (tmp_data);
27388 x_uncatch_errors ();
27389 unblock_input ();
27390 return false;
27391 }
27392
27393 dpyinfo->net_supported_atoms = (Atom *) tmp_data;
27394 dpyinfo->nr_net_supported_atoms = actual_size;
27395 dpyinfo->net_supported_window = wmcheck_window;
27396 }
27397
27398 ret = false;
27399
27400 for (i = 0; !ret && i < dpyinfo->nr_net_supported_atoms; ++i)
27401 ret = dpyinfo->net_supported_atoms[i] == want_atom;
27402
27403 x_uncatch_errors ();
27404 unblock_input ();
27405
27406 return ret;
27407 }
27408
27409 bool
27410 x_wm_supports (struct frame *f, Atom want_atom)
27411 {
27412 return x_wm_supports_1 (FRAME_DISPLAY_INFO (f),
27413 want_atom);
27414 }
27415
27416 static void
27417 set_wm_state (Lisp_Object frame, bool add, Atom atom, Atom value)
27418 {
27419 struct x_display_info *dpyinfo;
27420 XEvent msg;
27421
27422 dpyinfo = FRAME_DISPLAY_INFO (XFRAME (frame));
27423 msg.xclient.type = ClientMessage;
27424 msg.xclient.window = FRAME_OUTER_WINDOW (XFRAME (frame));
27425 msg.xclient.message_type = dpyinfo->Xatom_net_wm_state;
27426 msg.xclient.format = 32;
27427
27428 msg.xclient.data.l[0] = add ? 1 : 0;
27429 msg.xclient.data.l[1] = atom;
27430 msg.xclient.data.l[2] = value;
27431 msg.xclient.data.l[3] = 1;
27432 msg.xclient.data.l[4] = 0;
27433
27434 block_input ();
27435 XSendEvent (dpyinfo->display, dpyinfo->root_window,
27436 False, (SubstructureRedirectMask
27437 | SubstructureNotifyMask), &msg);
27438 unblock_input ();
27439 }
27440
27441 void
27442 x_set_sticky (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
27443 {
27444 Lisp_Object frame;
27445 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
27446
27447 XSETFRAME (frame, f);
27448
27449 set_wm_state (frame, !NILP (new_value),
27450 dpyinfo->Xatom_net_wm_state_sticky, None);
27451 }
27452
27453 void
27454 x_set_shaded (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
27455 {
27456 Lisp_Object frame;
27457 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
27458
27459 XSETFRAME (frame, f);
27460
27461 set_wm_state (frame, !NILP (new_value),
27462 dpyinfo->Xatom_net_wm_state_shaded, None);
27463 }
27464
27465
27466
27467
27468
27469
27470
27471
27472
27473
27474
27475 void
27476 x_set_skip_taskbar (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
27477 {
27478 if (!EQ (new_value, old_value))
27479 {
27480 #ifdef USE_GTK
27481 xg_set_skip_taskbar (f, new_value);
27482 #else
27483 Lisp_Object frame;
27484 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
27485
27486 XSETFRAME (frame, f);
27487 set_wm_state (frame, !NILP (new_value),
27488 dpyinfo->Xatom_net_wm_state_skip_taskbar, None);
27489 #endif
27490 FRAME_SKIP_TASKBAR (f) = !NILP (new_value);
27491 }
27492 }
27493
27494
27495
27496
27497
27498
27499
27500
27501
27502
27503
27504
27505
27506
27507
27508
27509
27510 void
27511 x_set_z_group (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
27512 {
27513
27514
27515 Lisp_Object frame;
27516 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
27517
27518 XSETFRAME (frame, f);
27519
27520 if (NILP (new_value))
27521 {
27522 set_wm_state (frame, false,
27523 dpyinfo->Xatom_net_wm_state_above, None);
27524 set_wm_state (frame, false,
27525 dpyinfo->Xatom_net_wm_state_below, None);
27526 FRAME_Z_GROUP (f) = z_group_none;
27527 }
27528 else if (EQ (new_value, Qabove))
27529 {
27530 set_wm_state (frame, true,
27531 dpyinfo->Xatom_net_wm_state_above, None);
27532 set_wm_state (frame, false,
27533 dpyinfo->Xatom_net_wm_state_below, None);
27534 FRAME_Z_GROUP (f) = z_group_above;
27535 }
27536 else if (EQ (new_value, Qbelow))
27537 {
27538 set_wm_state (frame, false,
27539 dpyinfo->Xatom_net_wm_state_above, None);
27540 set_wm_state (frame, true,
27541 dpyinfo->Xatom_net_wm_state_below, None);
27542 FRAME_Z_GROUP (f) = z_group_below;
27543 }
27544 else if (EQ (new_value, Qabove_suspended))
27545 {
27546 set_wm_state (frame, false,
27547 dpyinfo->Xatom_net_wm_state_above, None);
27548 FRAME_Z_GROUP (f) = z_group_above_suspended;
27549 }
27550 else
27551 error ("Invalid z-group specification");
27552 }
27553
27554
27555
27556
27557
27558
27559
27560
27561 static bool
27562 x_get_current_wm_state (struct frame *f,
27563 Window window,
27564 int *size_state,
27565 bool *sticky,
27566 bool *shaded)
27567 {
27568 unsigned long actual_size;
27569 int i;
27570 bool is_hidden = false;
27571 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
27572 long max_len = 65536;
27573 Atom target_type = XA_ATOM;
27574
27575 #ifdef USE_XCB
27576 xcb_get_property_cookie_t prop_cookie;
27577 xcb_get_property_reply_t *prop;
27578 typedef xcb_atom_t reply_data_object;
27579 #else
27580 Display *dpy = FRAME_X_DISPLAY (f);
27581 unsigned long bytes_remaining;
27582 int rc, actual_format;
27583 Atom actual_type;
27584 unsigned char *tmp_data = NULL;
27585 typedef Atom reply_data_object;
27586 #endif
27587 reply_data_object *reply_data;
27588 # if defined GCC_LINT || defined lint
27589 reply_data_object reply_data_dummy;
27590 reply_data = &reply_data_dummy;
27591 # endif
27592
27593 *sticky = false;
27594 *size_state = FULLSCREEN_NONE;
27595 *shaded = false;
27596
27597 block_input ();
27598
27599 #ifdef USE_XCB
27600 prop_cookie = xcb_get_property (dpyinfo->xcb_connection, 0, window,
27601 dpyinfo->Xatom_net_wm_state,
27602 target_type, 0, max_len);
27603 prop = xcb_get_property_reply (dpyinfo->xcb_connection, prop_cookie, NULL);
27604 if (prop && prop->type == target_type)
27605 {
27606 int actual_bytes = xcb_get_property_value_length (prop);
27607 eassume (0 <= actual_bytes);
27608 actual_size = actual_bytes / sizeof *reply_data;
27609 reply_data = xcb_get_property_value (prop);
27610 }
27611 else
27612 {
27613 actual_size = 0;
27614 is_hidden = FRAME_ICONIFIED_P (f);
27615 }
27616 #else
27617 x_catch_errors (dpy);
27618 rc = XGetWindowProperty (dpy, window, dpyinfo->Xatom_net_wm_state,
27619 0, max_len, False, target_type,
27620 &actual_type, &actual_format, &actual_size,
27621 &bytes_remaining, &tmp_data);
27622
27623 if (rc == Success && actual_type == target_type && ! x_had_errors_p (dpy))
27624 reply_data = (Atom *) tmp_data;
27625 else
27626 {
27627 actual_size = 0;
27628 is_hidden = FRAME_ICONIFIED_P (f);
27629 }
27630
27631 x_uncatch_errors ();
27632 #endif
27633
27634 for (i = 0; i < actual_size; ++i)
27635 {
27636 Atom a = reply_data[i];
27637 if (a == dpyinfo->Xatom_net_wm_state_hidden)
27638 is_hidden = true;
27639 else if (a == dpyinfo->Xatom_net_wm_state_maximized_horz)
27640 {
27641 if (*size_state == FULLSCREEN_HEIGHT)
27642 *size_state = FULLSCREEN_MAXIMIZED;
27643 else
27644 *size_state = FULLSCREEN_WIDTH;
27645 }
27646 else if (a == dpyinfo->Xatom_net_wm_state_maximized_vert)
27647 {
27648 if (*size_state == FULLSCREEN_WIDTH)
27649 *size_state = FULLSCREEN_MAXIMIZED;
27650 else
27651 *size_state = FULLSCREEN_HEIGHT;
27652 }
27653 else if (a == dpyinfo->Xatom_net_wm_state_fullscreen)
27654 *size_state = FULLSCREEN_BOTH;
27655 else if (a == dpyinfo->Xatom_net_wm_state_sticky)
27656 *sticky = true;
27657 else if (a == dpyinfo->Xatom_net_wm_state_shaded)
27658 *shaded = true;
27659 }
27660
27661 #ifdef USE_XCB
27662 free (prop);
27663 #else
27664 if (tmp_data) XFree (tmp_data);
27665 #endif
27666
27667 unblock_input ();
27668 return ! is_hidden;
27669 }
27670
27671
27672
27673 static bool
27674 do_ewmh_fullscreen (struct frame *f)
27675 {
27676 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
27677 bool have_net_atom = x_wm_supports (f, dpyinfo->Xatom_net_wm_state);
27678 int cur;
27679 bool dummy;
27680
27681 x_get_current_wm_state (f, FRAME_OUTER_WINDOW (f), &cur, &dummy, &dummy);
27682
27683
27684
27685 if (!have_net_atom)
27686 have_net_atom = x_wm_supports (f, dpyinfo->Xatom_net_wm_state_fullscreen);
27687
27688 if (have_net_atom && cur != f->want_fullscreen)
27689 {
27690 Lisp_Object frame;
27691
27692 XSETFRAME (frame, f);
27693
27694
27695
27696
27697 switch (f->want_fullscreen)
27698 {
27699 case FULLSCREEN_BOTH:
27700 if (cur != FULLSCREEN_BOTH)
27701 set_wm_state (frame, true, dpyinfo->Xatom_net_wm_state_fullscreen,
27702 None);
27703 break;
27704 case FULLSCREEN_WIDTH:
27705 if (x_frame_normalize_before_maximize && cur == FULLSCREEN_MAXIMIZED)
27706 {
27707 set_wm_state (frame, false,
27708 dpyinfo->Xatom_net_wm_state_maximized_horz,
27709 dpyinfo->Xatom_net_wm_state_maximized_vert);
27710 set_wm_state (frame, true,
27711 dpyinfo->Xatom_net_wm_state_maximized_horz, None);
27712 }
27713 else
27714 {
27715 if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_HEIGHT
27716 || cur == FULLSCREEN_MAXIMIZED)
27717 set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
27718 dpyinfo->Xatom_net_wm_state_maximized_vert);
27719 if (cur != FULLSCREEN_MAXIMIZED || x_frame_normalize_before_maximize)
27720 set_wm_state (frame, true,
27721 dpyinfo->Xatom_net_wm_state_maximized_horz, None);
27722 }
27723 break;
27724 case FULLSCREEN_HEIGHT:
27725 if (x_frame_normalize_before_maximize && cur == FULLSCREEN_MAXIMIZED)
27726 {
27727 set_wm_state (frame, false,
27728 dpyinfo->Xatom_net_wm_state_maximized_horz,
27729 dpyinfo->Xatom_net_wm_state_maximized_vert);
27730 set_wm_state (frame, true,
27731 dpyinfo->Xatom_net_wm_state_maximized_vert, None);
27732 }
27733 else
27734 {
27735 if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_WIDTH
27736 || cur == FULLSCREEN_MAXIMIZED)
27737 set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
27738 dpyinfo->Xatom_net_wm_state_maximized_horz);
27739 if (cur != FULLSCREEN_MAXIMIZED || x_frame_normalize_before_maximize)
27740 set_wm_state (frame, true,
27741 dpyinfo->Xatom_net_wm_state_maximized_vert, None);
27742 }
27743 break;
27744 case FULLSCREEN_MAXIMIZED:
27745 if (x_frame_normalize_before_maximize && cur == FULLSCREEN_BOTH)
27746 {
27747 set_wm_state (frame, false,
27748 dpyinfo->Xatom_net_wm_state_fullscreen, None);
27749 set_wm_state (frame, true,
27750 dpyinfo->Xatom_net_wm_state_maximized_horz,
27751 dpyinfo->Xatom_net_wm_state_maximized_vert);
27752 }
27753 else if (x_frame_normalize_before_maximize && cur == FULLSCREEN_WIDTH)
27754 {
27755 set_wm_state (frame, false,
27756 dpyinfo->Xatom_net_wm_state_maximized_horz, None);
27757 set_wm_state (frame, true,
27758 dpyinfo->Xatom_net_wm_state_maximized_horz,
27759 dpyinfo->Xatom_net_wm_state_maximized_vert);
27760 }
27761 else if (x_frame_normalize_before_maximize && cur == FULLSCREEN_HEIGHT)
27762 {
27763 set_wm_state (frame, false,
27764 dpyinfo->Xatom_net_wm_state_maximized_vert, None);
27765 set_wm_state (frame, true,
27766 dpyinfo->Xatom_net_wm_state_maximized_horz,
27767 dpyinfo->Xatom_net_wm_state_maximized_vert);
27768 }
27769 else
27770 {
27771 if (cur == FULLSCREEN_BOTH)
27772 set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
27773 None);
27774 else if (cur == FULLSCREEN_HEIGHT)
27775 set_wm_state (frame, true,
27776 dpyinfo->Xatom_net_wm_state_maximized_horz, None);
27777 else if (cur == FULLSCREEN_WIDTH)
27778 set_wm_state (frame, true, None,
27779 dpyinfo->Xatom_net_wm_state_maximized_vert);
27780 else
27781 set_wm_state (frame, true,
27782 dpyinfo->Xatom_net_wm_state_maximized_horz,
27783 dpyinfo->Xatom_net_wm_state_maximized_vert);
27784 }
27785 break;
27786 case FULLSCREEN_NONE:
27787 if (cur == FULLSCREEN_BOTH)
27788 set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
27789 None);
27790 else
27791 set_wm_state (frame, false,
27792 dpyinfo->Xatom_net_wm_state_maximized_horz,
27793 dpyinfo->Xatom_net_wm_state_maximized_vert);
27794 }
27795
27796 f->want_fullscreen = FULLSCREEN_NONE;
27797
27798 }
27799
27800 return have_net_atom;
27801 }
27802
27803 static void
27804 XTfullscreen_hook (struct frame *f)
27805 {
27806 if (!FRAME_VISIBLE_P (f))
27807 return;
27808
27809 block_input ();
27810 x_check_fullscreen (f);
27811 unblock_input ();
27812 }
27813
27814
27815 static bool
27816 x_handle_net_wm_state (struct frame *f, const XPropertyEvent *event)
27817 {
27818 int value = FULLSCREEN_NONE;
27819 Lisp_Object lval;
27820 bool sticky = false, shaded = false;
27821 bool not_hidden = x_get_current_wm_state (f, event->window,
27822 &value, &sticky,
27823 &shaded);
27824
27825 lval = Qnil;
27826 switch (value)
27827 {
27828 case FULLSCREEN_WIDTH:
27829 lval = Qfullwidth;
27830 break;
27831 case FULLSCREEN_HEIGHT:
27832 lval = Qfullheight;
27833 break;
27834 case FULLSCREEN_BOTH:
27835 lval = Qfullboth;
27836 break;
27837 case FULLSCREEN_MAXIMIZED:
27838 lval = Qmaximized;
27839 break;
27840 }
27841
27842 store_frame_param (f, Qfullscreen, lval);
27843 store_frame_param (f, Qsticky, sticky ? Qt : Qnil);
27844 store_frame_param (f, Qshaded, shaded ? Qt : Qnil);
27845
27846 return not_hidden;
27847 }
27848
27849
27850
27851 static void
27852 x_check_fullscreen (struct frame *f)
27853 {
27854 Lisp_Object lval = Qnil;
27855
27856 if (do_ewmh_fullscreen (f))
27857 return;
27858
27859 if (f->output_data.x->parent_desc != FRAME_DISPLAY_INFO (f)->root_window)
27860 return;
27861
27862
27863
27864
27865
27866 if (f->want_fullscreen != FULLSCREEN_NONE)
27867 {
27868 int width = FRAME_PIXEL_WIDTH (f), height = FRAME_PIXEL_HEIGHT (f);
27869 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
27870
27871 switch (f->want_fullscreen)
27872 {
27873
27874 case FULLSCREEN_MAXIMIZED:
27875 lval = Qmaximized;
27876 width = x_display_pixel_width (dpyinfo);
27877 height = x_display_pixel_height (dpyinfo);
27878 break;
27879 case FULLSCREEN_BOTH:
27880 lval = Qfullboth;
27881 width = x_display_pixel_width (dpyinfo);
27882 height = x_display_pixel_height (dpyinfo);
27883 break;
27884 case FULLSCREEN_WIDTH:
27885 lval = Qfullwidth;
27886 width = x_display_pixel_width (dpyinfo);
27887 height = height + FRAME_MENUBAR_HEIGHT (f);
27888 break;
27889 case FULLSCREEN_HEIGHT:
27890 lval = Qfullheight;
27891 height = x_display_pixel_height (dpyinfo);
27892 break;
27893 default:
27894 emacs_abort ();
27895 }
27896
27897 x_wm_set_size_hint (f, 0, false);
27898
27899 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
27900 width, height);
27901
27902 if (FRAME_VISIBLE_P (f))
27903 x_wait_for_event (f, ConfigureNotify);
27904 else
27905 change_frame_size (f, width, height, false, true, false);
27906 }
27907
27908
27909
27910 store_frame_param (f, Qfullscreen, lval);
27911 }
27912
27913
27914
27915
27916
27917
27918
27919
27920
27921 static void
27922 x_check_expected_move (struct frame *f, int expected_left, int expected_top)
27923 {
27924 int current_left = 0, current_top = 0;
27925
27926
27927
27928
27929 x_real_positions (f, ¤t_left, ¤t_top);
27930
27931 if (current_left != expected_left || current_top != expected_top)
27932 {
27933
27934
27935 int adjusted_left;
27936 int adjusted_top;
27937
27938 FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_A;
27939 FRAME_X_OUTPUT (f)->move_offset_left = expected_left - current_left;
27940 FRAME_X_OUTPUT (f)->move_offset_top = expected_top - current_top;
27941
27942
27943
27944 adjusted_left = expected_left + FRAME_X_OUTPUT (f)->move_offset_left;
27945 adjusted_top = expected_top + FRAME_X_OUTPUT (f)->move_offset_top;
27946
27947 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
27948 adjusted_left, adjusted_top);
27949
27950 x_sync_with_move (f, expected_left, expected_top, false);
27951 }
27952 else
27953
27954
27955 FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_B;
27956 }
27957
27958
27959
27960
27961
27962
27963
27964
27965 static void
27966 x_sync_with_move (struct frame *f, int left, int top, bool fuzzy)
27967 {
27968 sigset_t emptyset;
27969 int count, current_left, current_top;
27970 struct timespec fallback;
27971
27972 sigemptyset (&emptyset);
27973 count = 0;
27974
27975 while (count++ < 50)
27976 {
27977 current_left = 0;
27978 current_top = 0;
27979
27980
27981
27982
27983 x_real_positions (f, ¤t_left, ¤t_top);
27984
27985 if (fuzzy)
27986 {
27987
27988
27989
27990 if (eabs (current_left - left) <= 10
27991 && eabs (current_top - top) <= 40)
27992 return;
27993 }
27994 else if (current_left == left && current_top == top)
27995 return;
27996 }
27997
27998
27999
28000
28001 fallback = dtotimespec (0.5);
28002
28003
28004
28005 if (input_blocked_p ())
28006 pselect (0, NULL, NULL, NULL, &fallback, &emptyset);
28007 else
28008 wait_reading_process_output (0, 500000000, 0, false, Qnil, NULL, 0);
28009 }
28010
28011
28012 void
28013 x_wait_for_event (struct frame *f, int eventtype)
28014 {
28015 if (!FLOATP (Vx_wait_for_event_timeout))
28016 return;
28017
28018 int level = interrupt_input_blocked;
28019 fd_set fds;
28020 struct timespec tmo, tmo_at, time_now;
28021 int fd = ConnectionNumber (FRAME_X_DISPLAY (f));
28022
28023 f->wait_event_type = eventtype;
28024
28025
28026 double timeout = XFLOAT_DATA (Vx_wait_for_event_timeout);
28027 time_t timeout_seconds = (time_t) timeout;
28028 tmo = make_timespec
28029 (timeout_seconds, (long int) ((timeout - timeout_seconds)
28030 * 1000 * 1000 * 1000));
28031 tmo_at = timespec_add (current_timespec (), tmo);
28032
28033 while (f->wait_event_type)
28034 {
28035 pending_signals = true;
28036 totally_unblock_input ();
28037
28038 block_input ();
28039 interrupt_input_blocked = level;
28040
28041 FD_ZERO (&fds);
28042 FD_SET (fd, &fds);
28043
28044 time_now = current_timespec ();
28045 if (timespec_cmp (tmo_at, time_now) < 0)
28046 break;
28047
28048 tmo = timespec_sub (tmo_at, time_now);
28049 if (pselect (fd + 1, &fds, NULL, NULL, &tmo, NULL) == 0)
28050 break;
28051 }
28052
28053 f->wait_event_type = 0;
28054 }
28055
28056
28057
28058
28059
28060
28061
28062 static void
28063 x_set_window_size_1 (struct frame *f, bool change_gravity,
28064 int width, int height)
28065 {
28066 if (change_gravity)
28067 f->win_gravity = NorthWestGravity;
28068 x_wm_set_size_hint (f, 0, false);
28069
28070 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
28071 width, height + FRAME_MENUBAR_HEIGHT (f));
28072
28073
28074
28075
28076
28077 SET_FRAME_GARBAGED (f);
28078
28079
28080
28081
28082 if (!NILP (Vx_lax_frame_positioning))
28083 return;
28084
28085
28086
28087
28088
28089
28090
28091
28092
28093
28094
28095
28096
28097
28098
28099
28100
28101
28102 if (FRAME_VISIBLE_P (f))
28103 {
28104 x_wait_for_event (f, ConfigureNotify);
28105
28106 if (CONSP (frame_size_history))
28107 frame_size_history_extra
28108 (f, build_string ("x_set_window_size_1, visible"),
28109 FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), width, height,
28110 f->new_width, f->new_height);
28111 }
28112 else
28113 {
28114 if (CONSP (frame_size_history))
28115 frame_size_history_extra
28116 (f, build_string ("x_set_window_size_1, invisible"),
28117 FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), width, height,
28118 f->new_width, f->new_height);
28119
28120
28121
28122 adjust_frame_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, width),
28123 FRAME_PIXEL_TO_TEXT_HEIGHT (f, height),
28124 5, 0, Qx_set_window_size_1);
28125 }
28126 }
28127
28128
28129
28130
28131
28132
28133
28134 void
28135 x_set_window_size (struct frame *f, bool change_gravity,
28136 int width, int height)
28137 {
28138 block_input ();
28139
28140 #ifdef USE_GTK
28141 if (FRAME_GTK_WIDGET (f))
28142 xg_frame_set_char_size (f, width, height);
28143 else
28144 x_set_window_size_1 (f, change_gravity, width, height);
28145 #else
28146 x_set_window_size_1 (f, change_gravity, width, height);
28147 x_clear_under_internal_border (f);
28148 #endif
28149
28150
28151 mark_window_cursors_off (XWINDOW (f->root_window));
28152
28153
28154
28155
28156
28157 cancel_mouse_face (f);
28158
28159 unblock_input ();
28160
28161 do_pending_window_change (false);
28162 }
28163
28164
28165
28166 void
28167 frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
28168 {
28169 #ifdef HAVE_XINPUT2
28170 int deviceid;
28171
28172 deviceid = FRAME_DISPLAY_INFO (f)->client_pointer_device;
28173
28174 if (FRAME_DISPLAY_INFO (f)->supports_xi2
28175 && deviceid != -1)
28176 {
28177 block_input ();
28178 x_ignore_errors_for_next_request (FRAME_DISPLAY_INFO (f), 0);
28179 XIWarpPointer (FRAME_X_DISPLAY (f), deviceid, None,
28180 FRAME_X_WINDOW (f), 0, 0, 0, 0, pix_x, pix_y);
28181 x_stop_ignoring_errors (FRAME_DISPLAY_INFO (f));
28182 unblock_input ();
28183 }
28184 else
28185 #endif
28186 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
28187 0, 0, 0, 0, pix_x, pix_y);
28188 }
28189
28190
28191
28192 static void
28193 x_raise_frame (struct frame *f)
28194 {
28195 block_input ();
28196
28197 if (FRAME_VISIBLE_P (f))
28198 {
28199 XRaiseWindow (FRAME_X_DISPLAY (f),
28200 FRAME_OUTER_WINDOW (f));
28201 XFlush (FRAME_X_DISPLAY (f));
28202 }
28203
28204 unblock_input ();
28205 }
28206
28207 static void
28208 x_lower_frame_1 (struct frame *f)
28209 {
28210 Window *windows;
28211 Lisp_Object frame, tail;
28212 struct frame *sibling;
28213
28214 windows = alloca (2 * sizeof *windows);
28215
28216
28217
28218
28219
28220 FOR_EACH_FRAME (tail, frame)
28221 {
28222 sibling = XFRAME (frame);
28223
28224 if (sibling == f)
28225 continue;
28226
28227 if (FRAME_PARENT_FRAME (sibling)
28228 != FRAME_PARENT_FRAME (f))
28229 continue;
28230
28231 windows[0] = FRAME_OUTER_WINDOW (sibling);
28232 windows[1] = FRAME_OUTER_WINDOW (f);
28233
28234 XRestackWindows (FRAME_X_DISPLAY (f), windows, 2);
28235 }
28236 }
28237
28238
28239
28240 static void
28241 x_lower_frame (struct frame *f)
28242 {
28243 if (FRAME_PARENT_FRAME (f)
28244 && (FRAME_HAS_VERTICAL_SCROLL_BARS (FRAME_PARENT_FRAME (f))
28245 || FRAME_HAS_HORIZONTAL_SCROLL_BARS (FRAME_PARENT_FRAME (f))))
28246 x_lower_frame_1 (f);
28247 else
28248 XLowerWindow (FRAME_X_DISPLAY (f),
28249 FRAME_OUTER_WINDOW (f));
28250
28251 #ifdef HAVE_XWIDGETS
28252
28253
28254
28255 if (FRAME_PARENT_FRAME (f))
28256 lower_frame_xwidget_views (FRAME_PARENT_FRAME (f));
28257 #endif
28258
28259 XFlush (FRAME_X_DISPLAY (f));
28260 }
28261
28262 static void
28263 XTframe_raise_lower (struct frame *f, bool raise_flag)
28264 {
28265 if (raise_flag)
28266 x_raise_frame (f);
28267 else
28268 x_lower_frame (f);
28269 }
28270
28271
28272
28273 static void
28274 xembed_request_focus (struct frame *f)
28275 {
28276
28277
28278 if (FRAME_VISIBLE_P (f))
28279 xembed_send_message (f, CurrentTime,
28280 XEMBED_REQUEST_FOCUS, 0, 0, 0);
28281 }
28282
28283 static Bool
28284 server_timestamp_predicate (Display *display, XEvent *xevent,
28285 XPointer arg)
28286 {
28287 XID *args = (XID *) arg;
28288
28289 if (xevent->type == PropertyNotify
28290 && xevent->xproperty.window == args[0]
28291 && xevent->xproperty.atom == args[1])
28292 return True;
28293
28294 return False;
28295 }
28296
28297
28298
28299
28300 static Time
28301 x_get_server_time (struct frame *f)
28302 {
28303 Atom property_atom;
28304 XEvent property_dummy;
28305 struct x_display_info *dpyinfo;
28306 XID client_data[2];
28307 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
28308 uint_fast64_t current_monotonic_time;
28309 #endif
28310
28311
28312
28313
28314 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
28315 if (FRAME_DISPLAY_INFO (f)->server_time_monotonic_p)
28316 {
28317 current_monotonic_time = x_sync_current_monotonic_time ();
28318
28319 if (current_monotonic_time)
28320
28321 return (current_monotonic_time / 1000) & X_ULONG_MAX;
28322 }
28323 #endif
28324
28325 dpyinfo = FRAME_DISPLAY_INFO (f);
28326 property_atom = dpyinfo->Xatom_EMACS_SERVER_TIME_PROP;
28327 client_data[0] = FRAME_OUTER_WINDOW (f);
28328 client_data[1] = property_atom;
28329
28330 XChangeProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
28331 property_atom, XA_ATOM, 32,
28332 PropModeReplace,
28333 (unsigned char *) &property_atom, 1);
28334
28335 XIfEvent (dpyinfo->display, &property_dummy,
28336 server_timestamp_predicate, (XPointer) client_data);
28337
28338 return property_dummy.xproperty.time;
28339 }
28340
28341
28342
28343 static void
28344 x_ewmh_activate_frame (struct frame *f)
28345 {
28346 XEvent msg;
28347 struct x_display_info *dpyinfo;
28348 Time time;
28349
28350 dpyinfo = FRAME_DISPLAY_INFO (f);
28351
28352 if (FRAME_VISIBLE_P (f))
28353 {
28354
28355
28356
28357 msg.xclient.type = ClientMessage;
28358 msg.xclient.window = FRAME_OUTER_WINDOW (f);
28359 msg.xclient.message_type = dpyinfo->Xatom_net_active_window;
28360 msg.xclient.format = 32;
28361 msg.xclient.data.l[0] = 1;
28362 msg.xclient.data.l[1] = dpyinfo->last_user_time;
28363 msg.xclient.data.l[2] = (!dpyinfo->x_focus_frame
28364 ? None
28365 : FRAME_OUTER_WINDOW (dpyinfo->x_focus_frame));
28366 msg.xclient.data.l[3] = 0;
28367 msg.xclient.data.l[4] = 0;
28368
28369
28370
28371
28372 if (!dpyinfo->x_focus_frame)
28373 {
28374 if (EQ (Vx_allow_focus_stealing, Qimitate_pager))
28375 msg.xclient.data.l[0] = 2;
28376 else if (EQ (Vx_allow_focus_stealing, Qnewer_time))
28377 {
28378 block_input ();
28379 time = x_get_server_time (f);
28380 #ifdef USE_GTK
28381 x_set_gtk_user_time (f, time);
28382 #endif
28383
28384
28385 dpyinfo->x_focus_frame = f;
28386 x_display_set_last_user_time (dpyinfo, time, true, true);
28387 dpyinfo->x_focus_frame = NULL;
28388 unblock_input ();
28389
28390 msg.xclient.data.l[1] = time;
28391 }
28392 else if (EQ (Vx_allow_focus_stealing, Qraise_and_focus))
28393 {
28394 time = x_get_server_time (f);
28395
28396 x_set_input_focus (FRAME_DISPLAY_INFO (f),
28397 FRAME_OUTER_WINDOW (f),
28398 time);
28399 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
28400
28401 return;
28402 }
28403 }
28404
28405 XSendEvent (dpyinfo->display, dpyinfo->root_window,
28406 False, (SubstructureRedirectMask
28407 | SubstructureNotifyMask), &msg);
28408 }
28409 }
28410
28411 static Lisp_Object
28412 x_get_focus_frame (struct frame *f)
28413 {
28414 Lisp_Object lisp_focus;
28415
28416 struct frame *focus = FRAME_DISPLAY_INFO (f)->x_focus_frame;
28417
28418 if (!focus)
28419 return Qnil;
28420
28421 XSETFRAME (lisp_focus, focus);
28422 return lisp_focus;
28423 }
28424
28425
28426
28427
28428 static struct frame *
28429 x_get_toplevel_parent (struct frame *f)
28430 {
28431 struct frame *parent;
28432
28433 if (!FRAME_PARENT_FRAME (f))
28434 return NULL;
28435
28436 parent = FRAME_PARENT_FRAME (f);
28437
28438 while (FRAME_PARENT_FRAME (parent))
28439 parent = FRAME_PARENT_FRAME (parent);
28440
28441 return parent;
28442 }
28443
28444 static void
28445 x_set_input_focus (struct x_display_info *dpyinfo, Window window,
28446 Time time)
28447 {
28448 #ifdef HAVE_XINPUT2
28449 struct xi_device_t *device;
28450 #endif
28451
28452
28453
28454
28455
28456
28457
28458
28459
28460
28461
28462 #ifdef HAVE_XINPUT2
28463 if (dpyinfo->supports_xi2
28464 && dpyinfo->client_pointer_device != -1)
28465 {
28466 device = xi_device_from_id (dpyinfo, dpyinfo->client_pointer_device);
28467
28468
28469
28470
28471 if (device)
28472 {
28473 eassert (device->use == XIMasterPointer);
28474
28475 x_ignore_errors_for_next_request (dpyinfo, 0);
28476 XISetFocus (dpyinfo->display, device->attachment,
28477
28478
28479
28480 window, time);
28481 x_stop_ignoring_errors (dpyinfo);
28482
28483 return;
28484 }
28485 }
28486 #endif
28487
28488
28489
28490 x_ignore_errors_for_next_request (dpyinfo, 0);
28491 XSetInputFocus (dpyinfo->display, window, RevertToParent, time);
28492 x_stop_ignoring_errors (dpyinfo);
28493 }
28494
28495
28496
28497
28498
28499
28500
28501
28502
28503
28504 static void
28505 x_focus_frame (struct frame *f, bool noactivate)
28506 {
28507 struct x_display_info *dpyinfo;
28508 Time time;
28509
28510 dpyinfo = FRAME_DISPLAY_INFO (f);
28511
28512 if (dpyinfo->untrusted)
28513
28514
28515 return;
28516
28517
28518
28519 block_input ();
28520
28521 if (FRAME_X_EMBEDDED_P (f))
28522
28523
28524
28525 xembed_request_focus (f);
28526 else
28527 {
28528 if (!noactivate
28529
28530
28531
28532 && !FRAME_OVERRIDE_REDIRECT (f)
28533
28534
28535 && !FRAME_PARENT_FRAME (f)
28536
28537
28538 && (!dpyinfo->x_focus_frame
28539 || (x_get_toplevel_parent (dpyinfo->x_focus_frame)
28540 != f))
28541 && x_wm_supports (f, dpyinfo->Xatom_net_active_window))
28542 {
28543
28544
28545
28546
28547
28548 x_ewmh_activate_frame (f);
28549 goto out;
28550 }
28551
28552 if (NILP (Vx_no_window_manager))
28553 {
28554
28555
28556
28557
28558
28559
28560
28561 time = dpyinfo->last_user_time;
28562
28563
28564
28565 if (EQ (Vx_allow_focus_stealing, Qnewer_time)
28566 && !dpyinfo->x_focus_frame)
28567 time = x_get_server_time (f);
28568
28569
28570
28571
28572
28573 x_set_input_focus (FRAME_DISPLAY_INFO (f), FRAME_OUTER_WINDOW (f),
28574 time);
28575 }
28576 else
28577 x_set_input_focus (FRAME_DISPLAY_INFO (f), FRAME_OUTER_WINDOW (f),
28578
28579
28580
28581 CurrentTime);
28582 }
28583
28584 out:
28585 unblock_input ();
28586 }
28587
28588
28589
28590
28591 #if defined USE_X_TOOLKIT || ! defined USE_GTK
28592
28593
28594
28595 #define XEMBED_VERSION 0
28596
28597 static void
28598 xembed_set_info (struct frame *f, enum xembed_info flags)
28599 {
28600 unsigned long data[2];
28601 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
28602
28603 data[0] = XEMBED_VERSION;
28604 data[1] = flags;
28605
28606 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
28607 dpyinfo->Xatom_XEMBED_INFO, dpyinfo->Xatom_XEMBED_INFO,
28608 32, PropModeReplace, (unsigned char *) data, 2);
28609 }
28610 #endif
28611
28612 static void
28613 xembed_send_message (struct frame *f, Time t, enum xembed_message msg,
28614 long int detail, long int data1, long int data2)
28615 {
28616 XEvent event;
28617
28618 event.xclient.type = ClientMessage;
28619 event.xclient.window = FRAME_X_OUTPUT (f)->parent_desc;
28620 event.xclient.message_type = FRAME_DISPLAY_INFO (f)->Xatom_XEMBED;
28621 event.xclient.format = 32;
28622 event.xclient.data.l[0] = t;
28623 event.xclient.data.l[1] = msg;
28624 event.xclient.data.l[2] = detail;
28625 event.xclient.data.l[3] = data1;
28626 event.xclient.data.l[4] = data2;
28627
28628
28629
28630
28631
28632 x_ignore_errors_for_next_request (FRAME_DISPLAY_INFO (f), 0);
28633 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_OUTPUT (f)->parent_desc,
28634 False, NoEventMask, &event);
28635 x_stop_ignoring_errors (FRAME_DISPLAY_INFO (f));
28636 }
28637
28638
28639
28640
28641
28642
28643
28644
28645
28646
28647
28648 void
28649 x_make_frame_visible (struct frame *f)
28650 {
28651 #ifndef USE_GTK
28652 struct x_display_info *dpyinfo;
28653 struct x_output *output;
28654 #endif
28655 bool output_flushed;
28656
28657 if (FRAME_PARENT_FRAME (f))
28658 {
28659 if (!FRAME_VISIBLE_P (f))
28660 {
28661 block_input ();
28662 #ifdef USE_GTK
28663 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
28664 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
28665 f->left_pos, f->top_pos);
28666 #else
28667 XMapRaised (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
28668 #endif
28669 unblock_input ();
28670
28671 SET_FRAME_VISIBLE (f, true);
28672 SET_FRAME_ICONIFIED (f, false);
28673 }
28674 return;
28675 }
28676
28677 block_input ();
28678
28679 gui_set_bitmap_icon (f);
28680
28681 #ifndef USE_GTK
28682 dpyinfo = FRAME_DISPLAY_INFO (f);
28683 #endif
28684
28685 if (! FRAME_VISIBLE_P (f))
28686 {
28687
28688
28689
28690
28691 if (! FRAME_ICONIFIED_P (f)
28692 && ! FRAME_X_EMBEDDED_P (f)
28693 && ! f->output_data.x->asked_for_visible)
28694 x_set_offset (f, f->left_pos, f->top_pos, 0);
28695
28696 #ifndef USE_GTK
28697 output = FRAME_X_OUTPUT (f);
28698 x_update_frame_user_time_window (f);
28699
28700
28701
28702 if (output->user_time_window != None)
28703 {
28704 if (dpyinfo->last_user_time)
28705 XChangeProperty (dpyinfo->display, output->user_time_window,
28706 dpyinfo->Xatom_net_wm_user_time,
28707 XA_CARDINAL, 32, PropModeReplace,
28708 (unsigned char *) &dpyinfo->last_user_time, 1);
28709 else
28710 XDeleteProperty (dpyinfo->display, output->user_time_window,
28711 dpyinfo->Xatom_net_wm_user_time);
28712 }
28713 #endif
28714
28715 f->output_data.x->asked_for_visible = true;
28716
28717 if (! EQ (Vx_no_window_manager, Qt))
28718 x_wm_set_window_state (f, NormalState);
28719 #ifdef USE_X_TOOLKIT
28720 if (FRAME_X_EMBEDDED_P (f))
28721 xembed_set_info (f, XEMBED_MAPPED);
28722 else
28723 {
28724
28725 XtMapWidget (f->output_data.x->widget);
28726 }
28727 #else
28728 #ifdef USE_GTK
28729 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
28730 gtk_window_deiconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
28731 #else
28732 if (FRAME_X_EMBEDDED_P (f))
28733 xembed_set_info (f, XEMBED_MAPPED);
28734 else
28735 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
28736 #endif
28737 #endif
28738
28739 if (FRAME_X_EMBEDDED_P (f))
28740 {
28741 SET_FRAME_VISIBLE (f, true);
28742 SET_FRAME_ICONIFIED (f, false);
28743 }
28744 }
28745
28746
28747
28748
28749 {
28750 Lisp_Object frame;
28751
28752
28753
28754 bool previously_visible = f->output_data.x->has_been_visible;
28755
28756 XSETFRAME (frame, f);
28757
28758 int original_left = f->left_pos;
28759 int original_top = f->top_pos;
28760
28761
28762 unblock_input ();
28763
28764
28765
28766 output_flushed = false;
28767
28768
28769
28770
28771
28772
28773
28774
28775
28776
28777
28778
28779 if (!FRAME_VISIBLE_P (f)
28780 && !FRAME_ICONIFIED_P (f)
28781 && !FRAME_X_EMBEDDED_P (f)
28782 && !FRAME_PARENT_FRAME (f)
28783 && NILP (Vx_lax_frame_positioning)
28784 && f->win_gravity == NorthWestGravity
28785 && previously_visible)
28786 {
28787 Drawable rootw;
28788 int x, y;
28789 unsigned int width, height, border, depth;
28790
28791 block_input ();
28792
28793
28794
28795
28796
28797
28798
28799
28800 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
28801 &rootw, &x, &y, &width, &height, &border, &depth);
28802 output_flushed = true;
28803
28804 if (original_left != x || original_top != y)
28805 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
28806 original_left, original_top);
28807
28808 unblock_input ();
28809 }
28810
28811
28812
28813
28814
28815 #ifdef CYGWIN
28816
28817
28818
28819
28820
28821
28822
28823
28824
28825 int old_poll_suppress_count = poll_suppress_count;
28826 poll_suppress_count = 1;
28827 poll_for_input_1 ();
28828 poll_suppress_count = old_poll_suppress_count;
28829 #endif
28830
28831 if (!FRAME_VISIBLE_P (f)
28832 && NILP (Vx_lax_frame_positioning))
28833 {
28834 if (CONSP (frame_size_history))
28835 frame_size_history_plain
28836 (f, build_string ("x_make_frame_visible"));
28837
28838 x_wait_for_event (f, MapNotify);
28839 output_flushed = true;
28840 }
28841
28842 if (!output_flushed)
28843 x_flush (f);
28844 }
28845 }
28846
28847
28848
28849
28850
28851 void
28852 x_make_frame_invisible (struct frame *f)
28853 {
28854 Window window;
28855
28856
28857 window = FRAME_OUTER_WINDOW (f);
28858
28859
28860 if (FRAME_DISPLAY_INFO (f)->highlight_frame == f)
28861 FRAME_DISPLAY_INFO (f)->highlight_frame = 0;
28862
28863 block_input ();
28864
28865 #ifdef HAVE_XINPUT2_2
28866
28867 xi_unlink_touch_points (f);
28868 #endif
28869
28870
28871
28872
28873
28874
28875 x_wm_set_size_hint (f, 0, true);
28876
28877 #ifdef USE_GTK
28878 if (FRAME_GTK_OUTER_WIDGET (f))
28879 gtk_widget_hide (FRAME_GTK_OUTER_WIDGET (f));
28880 else
28881 #else
28882 if (FRAME_X_EMBEDDED_P (f))
28883 xembed_set_info (f, 0);
28884 else
28885 #endif
28886
28887 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
28888 DefaultScreen (FRAME_X_DISPLAY (f))))
28889 {
28890 unblock_input ();
28891 error ("Can't notify window manager of window withdrawal");
28892 }
28893
28894
28895
28896 if (NILP (Vx_lax_frame_positioning))
28897 XSync (FRAME_X_DISPLAY (f), False);
28898
28899
28900
28901
28902
28903
28904 SET_FRAME_VISIBLE (f, 0);
28905 SET_FRAME_ICONIFIED (f, false);
28906
28907 if (CONSP (frame_size_history))
28908 frame_size_history_plain (f, build_string ("x_make_frame_invisible"));
28909
28910 unblock_input ();
28911 }
28912
28913 static void
28914 x_make_frame_visible_invisible (struct frame *f, bool visible)
28915 {
28916 if (visible)
28917 x_make_frame_visible (f);
28918 else
28919 x_make_frame_invisible (f);
28920 }
28921
28922 Cursor
28923 x_create_font_cursor (struct x_display_info *dpyinfo, int glyph)
28924 {
28925 if (glyph <= 65535)
28926 return XCreateFontCursor (dpyinfo->display, glyph);
28927
28928
28929
28930 return make_invisible_cursor (dpyinfo);
28931 }
28932
28933
28934
28935
28936 void
28937 x_iconify_frame (struct frame *f)
28938 {
28939 #ifdef USE_X_TOOLKIT
28940 int result;
28941 #endif
28942
28943
28944 if (FRAME_DISPLAY_INFO (f)->highlight_frame == f)
28945 FRAME_DISPLAY_INFO (f)->highlight_frame = 0;
28946
28947 if (FRAME_ICONIFIED_P (f))
28948 return;
28949
28950 block_input ();
28951
28952 gui_set_bitmap_icon (f);
28953
28954 #if defined (USE_GTK)
28955 if (FRAME_GTK_OUTER_WIDGET (f))
28956 {
28957 if (! FRAME_VISIBLE_P (f))
28958 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
28959
28960 gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
28961 SET_FRAME_VISIBLE (f, 0);
28962 SET_FRAME_ICONIFIED (f, true);
28963 unblock_input ();
28964 return;
28965 }
28966 #endif
28967
28968 #ifdef USE_X_TOOLKIT
28969
28970 if (! FRAME_VISIBLE_P (f))
28971 {
28972 if (! EQ (Vx_no_window_manager, Qt))
28973 x_wm_set_window_state (f, IconicState);
28974
28975 XtMapWidget (f->output_data.x->widget);
28976
28977
28978
28979 SET_FRAME_VISIBLE (f, 0);
28980 SET_FRAME_ICONIFIED (f, true);
28981 unblock_input ();
28982 return;
28983 }
28984
28985 result = XIconifyWindow (FRAME_X_DISPLAY (f),
28986 XtWindow (f->output_data.x->widget),
28987 DefaultScreen (FRAME_X_DISPLAY (f)));
28988 unblock_input ();
28989
28990 if (!result)
28991 error ("Can't notify window manager of iconification");
28992
28993 SET_FRAME_ICONIFIED (f, true);
28994 SET_FRAME_VISIBLE (f, 0);
28995
28996 block_input ();
28997 XFlush (FRAME_X_DISPLAY (f));
28998 unblock_input ();
28999 #else
29000
29001
29002
29003 if (! FRAME_VISIBLE_P (f)
29004 && ! FRAME_ICONIFIED_P (f)
29005 && ! FRAME_X_EMBEDDED_P (f))
29006 x_set_offset (f, f->left_pos, f->top_pos, 0);
29007
29008
29009
29010
29011
29012
29013 {
29014 XEvent msg;
29015
29016 msg.xclient.window = FRAME_X_WINDOW (f);
29017 msg.xclient.type = ClientMessage;
29018 msg.xclient.message_type = FRAME_DISPLAY_INFO (f)->Xatom_wm_change_state;
29019 msg.xclient.format = 32;
29020 msg.xclient.data.l[0] = IconicState;
29021 msg.xclient.data.l[1] = 0;
29022 msg.xclient.data.l[2] = 0;
29023 msg.xclient.data.l[3] = 0;
29024 msg.xclient.data.l[4] = 0;
29025
29026 if (! XSendEvent (FRAME_X_DISPLAY (f),
29027 FRAME_DISPLAY_INFO (f)->root_window,
29028 False,
29029 SubstructureRedirectMask | SubstructureNotifyMask,
29030 &msg))
29031 {
29032 unblock_input ();
29033 error ("Can't notify window manager of iconification");
29034 }
29035 }
29036
29037
29038
29039 x_wm_set_window_state (f, IconicState);
29040
29041 if (!FRAME_VISIBLE_P (f))
29042 {
29043
29044 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
29045 }
29046
29047 SET_FRAME_ICONIFIED (f, true);
29048 SET_FRAME_VISIBLE (f, 0);
29049
29050 XFlush (FRAME_X_DISPLAY (f));
29051 unblock_input ();
29052 #endif
29053 }
29054
29055
29056
29057
29058 void
29059 x_free_frame_resources (struct frame *f)
29060 {
29061 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
29062 Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
29063 #ifdef USE_X_TOOLKIT
29064 Lisp_Object bar;
29065 struct scroll_bar *b;
29066 #endif
29067
29068 block_input ();
29069
29070 #ifdef HAVE_XINPUT2
29071
29072 xi_handle_delete_frame (dpyinfo, f);
29073 #endif
29074
29075 #ifdef HAVE_XINPUT2_2
29076
29077 xi_unlink_touch_points (f);
29078 #endif
29079
29080
29081
29082 if (dpyinfo->display)
29083 {
29084
29085
29086 if (f->pointer_invisible)
29087 XTtoggle_invisible_pointer (f, 0);
29088
29089
29090
29091
29092 free_frame_faces (f);
29093 tear_down_x_back_buffer (f);
29094
29095 if (f->output_data.x->icon_desc)
29096 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
29097
29098 #ifdef USE_X_TOOLKIT
29099
29100
29101
29102
29103 for (bar = FRAME_SCROLL_BARS (f); !NILP (bar); bar = b->next)
29104 {
29105 b = XSCROLL_BAR (bar);
29106 x_scroll_bar_remove (b);
29107 }
29108 #endif
29109
29110 #ifdef HAVE_X_I18N
29111 if (FRAME_XIC (f))
29112 free_frame_xic (f);
29113 #endif
29114
29115 #ifdef USE_CAIRO
29116 x_cr_destroy_frame_context (f);
29117 #endif
29118 #ifdef USE_X_TOOLKIT
29119 if (f->output_data.x->widget)
29120 {
29121 XtDestroyWidget (f->output_data.x->widget);
29122 f->output_data.x->widget = NULL;
29123 }
29124
29125
29126 else if (FRAME_X_WINDOW (f))
29127 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
29128
29129 free_frame_menubar (f);
29130
29131 if (f->shell_position)
29132 xfree (f->shell_position);
29133 #else
29134
29135 #ifdef HAVE_XWIDGETS
29136 kill_frame_xwidget_views (f);
29137 #endif
29138
29139 #ifdef USE_GTK
29140 xg_free_frame_widgets (f);
29141 #endif
29142
29143 tear_down_x_back_buffer (f);
29144 if (FRAME_X_WINDOW (f))
29145 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
29146 #endif
29147
29148 #ifdef HAVE_XSYNC
29149 if (FRAME_X_BASIC_COUNTER (f) != None)
29150 XSyncDestroyCounter (FRAME_X_DISPLAY (f),
29151 FRAME_X_BASIC_COUNTER (f));
29152
29153 if (FRAME_X_EXTENDED_COUNTER (f) != None)
29154 XSyncDestroyCounter (FRAME_X_DISPLAY (f),
29155 FRAME_X_EXTENDED_COUNTER (f));
29156 #endif
29157
29158 unload_color (f, FRAME_FOREGROUND_PIXEL (f));
29159 unload_color (f, FRAME_BACKGROUND_PIXEL (f));
29160 unload_color (f, f->output_data.x->cursor_pixel);
29161 unload_color (f, f->output_data.x->cursor_foreground_pixel);
29162 unload_color (f, f->output_data.x->border_pixel);
29163 unload_color (f, f->output_data.x->mouse_pixel);
29164
29165 if (f->output_data.x->scroll_bar_background_pixel != -1)
29166 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
29167 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
29168 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
29169 #if defined (USE_LUCID) && defined (USE_TOOLKIT_SCROLL_BARS)
29170
29171 if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
29172 unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
29173 if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
29174 unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
29175 #endif
29176 if (f->output_data.x->white_relief.pixel != -1)
29177 unload_color (f, f->output_data.x->white_relief.pixel);
29178 if (f->output_data.x->black_relief.pixel != -1)
29179 unload_color (f, f->output_data.x->black_relief.pixel);
29180
29181 x_free_gcs (f);
29182
29183
29184 if (f->output_data.x->white_relief.gc)
29185 {
29186 XFreeGC (dpyinfo->display, f->output_data.x->white_relief.gc);
29187 f->output_data.x->white_relief.gc = 0;
29188 }
29189 if (f->output_data.x->black_relief.gc)
29190 {
29191 XFreeGC (dpyinfo->display, f->output_data.x->black_relief.gc);
29192 f->output_data.x->black_relief.gc = 0;
29193 }
29194
29195
29196 if (f->output_data.x->text_cursor != 0)
29197 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->text_cursor);
29198 if (f->output_data.x->nontext_cursor != 0)
29199 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->nontext_cursor);
29200 if (f->output_data.x->modeline_cursor != 0)
29201 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->modeline_cursor);
29202 if (f->output_data.x->hand_cursor != 0)
29203 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->hand_cursor);
29204 if (f->output_data.x->hourglass_cursor != 0)
29205 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->hourglass_cursor);
29206 if (f->output_data.x->horizontal_drag_cursor != 0)
29207 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->horizontal_drag_cursor);
29208 if (f->output_data.x->vertical_drag_cursor != 0)
29209 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->vertical_drag_cursor);
29210 if (f->output_data.x->left_edge_cursor != 0)
29211 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->left_edge_cursor);
29212 if (f->output_data.x->top_left_corner_cursor != 0)
29213 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->top_left_corner_cursor);
29214 if (f->output_data.x->top_edge_cursor != 0)
29215 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->top_edge_cursor);
29216 if (f->output_data.x->top_right_corner_cursor != 0)
29217 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->top_right_corner_cursor);
29218 if (f->output_data.x->right_edge_cursor != 0)
29219 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->right_edge_cursor);
29220 if (f->output_data.x->bottom_right_corner_cursor != 0)
29221 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->bottom_right_corner_cursor);
29222 if (f->output_data.x->bottom_edge_cursor != 0)
29223 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->bottom_edge_cursor);
29224 if (f->output_data.x->bottom_left_corner_cursor != 0)
29225 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->bottom_left_corner_cursor);
29226
29227
29228 #if defined HAVE_XSYNCTRIGGERFENCE && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
29229 x_sync_free_fences (f);
29230 #endif
29231
29232 #ifdef USE_TOOLKIT_SCROLL_BARS
29233
29234
29235
29236 dpyinfo->n_protected_windows = 0;
29237 #endif
29238 }
29239
29240 #ifdef HAVE_GTK3
29241 if (FRAME_OUTPUT_DATA (f)->scrollbar_background_css_provider)
29242 g_object_unref (FRAME_OUTPUT_DATA (f)->scrollbar_background_css_provider);
29243
29244 if (FRAME_OUTPUT_DATA (f)->scrollbar_foreground_css_provider)
29245 g_object_unref (FRAME_OUTPUT_DATA (f)->scrollbar_foreground_css_provider);
29246 #endif
29247
29248 if (f == dpyinfo->motif_drag_atom_owner)
29249 {
29250 dpyinfo->motif_drag_atom_owner = NULL;
29251 dpyinfo->motif_drag_atom = None;
29252 }
29253
29254 if (f == dpyinfo->x_focus_frame)
29255 dpyinfo->x_focus_frame = 0;
29256 if (f == dpyinfo->x_focus_event_frame)
29257 dpyinfo->x_focus_event_frame = 0;
29258 if (f == dpyinfo->highlight_frame)
29259 dpyinfo->highlight_frame = 0;
29260 if (f == hlinfo->mouse_face_mouse_frame)
29261 reset_mouse_highlight (hlinfo);
29262
29263
29264
29265 if (f == dpyinfo->last_mouse_motion_frame)
29266 dpyinfo->last_mouse_motion_frame = NULL;
29267 if (f == dpyinfo->last_mouse_frame)
29268 dpyinfo->last_mouse_frame = NULL;
29269
29270 #ifdef HAVE_XINPUT2
29271
29272
29273
29274
29275
29276 if (dpyinfo->supports_xi2)
29277 xi_handle_focus_change (dpyinfo);
29278 #endif
29279
29280 unblock_input ();
29281 }
29282
29283
29284
29285
29286 static void
29287 x_destroy_window (struct frame *f)
29288 {
29289 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
29290
29291
29292
29293 if (dpyinfo->display != 0)
29294 x_free_frame_resources (f);
29295
29296 xfree (f->output_data.x->saved_menu_event);
29297
29298 #ifdef HAVE_X_I18N
29299 if (f->output_data.x->preedit_chars)
29300 xfree (f->output_data.x->preedit_chars);
29301 #endif
29302
29303 #ifdef HAVE_XINPUT2
29304 #ifdef HAVE_XINPUT2_1
29305 if (f->output_data.x->xi_masks)
29306 XFree (f->output_data.x->xi_masks);
29307 #else
29308
29309
29310 if (f->output_data.x->xi_masks)
29311 xfree (f->output_data.x->xi_masks);
29312 #endif
29313 #endif
29314
29315 xfree (f->output_data.x);
29316 f->output_data.x = NULL;
29317
29318 dpyinfo->reference_count--;
29319 }
29320
29321
29322
29323
29324
29325
29326 Atom
29327 x_intern_cached_atom (struct x_display_info *dpyinfo,
29328 const char *name, bool predefined_only)
29329 {
29330 int i;
29331 char *ptr;
29332 Atom *atom;
29333
29334
29335 char xsettings_atom_name[sizeof "_XSETTINGS_S%d" - 2
29336 + INT_STRLEN_BOUND (int)];
29337 char cm_atom_name[sizeof "_NET_WM_CM_S%d" - 2
29338 + INT_STRLEN_BOUND (int)];
29339
29340 sprintf (xsettings_atom_name, "_XSETTINGS_S%d",
29341 XScreenNumberOfScreen (dpyinfo->screen));
29342 sprintf (cm_atom_name, "_NET_WM_CM_S%d",
29343 XScreenNumberOfScreen (dpyinfo->screen));
29344
29345 if (!strcmp (name, xsettings_atom_name))
29346 return dpyinfo->Xatom_xsettings_sel;
29347
29348 if (!strcmp (name, cm_atom_name))
29349 return dpyinfo->Xatom_NET_WM_CM_Sn;
29350
29351
29352 if (!strcmp (name, "PRIMARY"))
29353 return XA_PRIMARY;
29354
29355 if (!strcmp (name, "SECONDARY"))
29356 return XA_SECONDARY;
29357
29358 if (!strcmp (name, "STRING"))
29359 return XA_STRING;
29360
29361 if (!strcmp (name, "INTEGER"))
29362 return XA_INTEGER;
29363
29364 if (!strcmp (name, "ATOM"))
29365 return XA_ATOM;
29366
29367 if (!strcmp (name, "WINDOW"))
29368 return XA_WINDOW;
29369
29370 if (!strcmp (name, "DRAWABLE"))
29371 return XA_DRAWABLE;
29372
29373 if (!strcmp (name, "BITMAP"))
29374 return XA_BITMAP;
29375
29376 if (!strcmp (name, "CARDINAL"))
29377 return XA_CARDINAL;
29378
29379 if (!strcmp (name, "COLORMAP"))
29380 return XA_COLORMAP;
29381
29382 if (!strcmp (name, "CURSOR"))
29383 return XA_CURSOR;
29384
29385 if (!strcmp (name, "FONT"))
29386 return XA_FONT;
29387
29388 if (dpyinfo->motif_drag_atom != None
29389 && !strcmp (name, dpyinfo->motif_drag_atom_name))
29390 return dpyinfo->motif_drag_atom;
29391
29392 for (i = 0; i < ARRAYELTS (x_atom_refs); ++i)
29393 {
29394 ptr = (char *) dpyinfo;
29395
29396 if (!strcmp (x_atom_refs[i].name, name))
29397 {
29398 atom = (Atom *) (ptr + x_atom_refs[i].offset);
29399
29400 return *atom;
29401 }
29402 }
29403
29404 if (predefined_only)
29405 return None;
29406
29407 return XInternAtom (dpyinfo->display, name, False);
29408 }
29409
29410
29411
29412
29413 char *
29414 x_get_atom_name (struct x_display_info *dpyinfo, Atom atom,
29415 bool *need_sync)
29416 {
29417 char *dpyinfo_pointer, *name, *value, *buffer;
29418 int i;
29419 Atom ref_atom;
29420
29421 dpyinfo_pointer = (char *) dpyinfo;
29422 value = NULL;
29423
29424 if (need_sync)
29425 *need_sync = false;
29426
29427 buffer = alloca (45 + INT_STRLEN_BOUND (int));
29428
29429 switch (atom)
29430 {
29431 case XA_PRIMARY:
29432 return xstrdup ("PRIMARY");
29433
29434 case XA_SECONDARY:
29435 return xstrdup ("SECONDARY");
29436
29437 case XA_INTEGER:
29438 return xstrdup ("INTEGER");
29439
29440 case XA_ATOM:
29441 return xstrdup ("ATOM");
29442
29443 case XA_CARDINAL:
29444 return xstrdup ("CARDINAL");
29445
29446 case XA_WINDOW:
29447 return xstrdup ("WINDOW");
29448
29449 case XA_DRAWABLE:
29450 return xstrdup ("DRAWABLE");
29451
29452 case XA_BITMAP:
29453 return xstrdup ("BITMAP");
29454
29455 case XA_COLORMAP:
29456 return xstrdup ("COLORMAP");
29457
29458 case XA_FONT:
29459 return xstrdup ("FONT");
29460
29461 default:
29462 if (dpyinfo->motif_drag_atom
29463 && atom == dpyinfo->motif_drag_atom)
29464 return xstrdup (dpyinfo->motif_drag_atom_name);
29465
29466 if (atom == dpyinfo->Xatom_xsettings_sel)
29467 {
29468 sprintf (buffer, "_XSETTINGS_S%d",
29469 XScreenNumberOfScreen (dpyinfo->screen));
29470 return xstrdup (buffer);
29471 }
29472
29473 if (atom == dpyinfo->Xatom_NET_WM_CM_Sn)
29474 {
29475 sprintf (buffer, "_NET_WM_CM_S%d",
29476 XScreenNumberOfScreen (dpyinfo->screen));
29477 return xstrdup (buffer);
29478 }
29479
29480 for (i = 0; i < ARRAYELTS (x_atom_refs); ++i)
29481 {
29482 ref_atom = *(Atom *) (dpyinfo_pointer
29483 + x_atom_refs[i].offset);
29484
29485 if (atom == ref_atom)
29486 return xstrdup (x_atom_refs[i].name);
29487 }
29488
29489 name = XGetAtomName (dpyinfo->display, atom);
29490
29491 if (need_sync)
29492 *need_sync = true;
29493
29494 if (name)
29495 {
29496 value = xstrdup (name);
29497 XFree (name);
29498 }
29499
29500 break;
29501 }
29502
29503 return value;
29504 }
29505
29506
29507
29508
29509
29510
29511
29512
29513 void
29514 x_intern_atoms (struct x_display_info *dpyinfo, char **names, int count,
29515 Atom *atoms_return)
29516 {
29517 int i, j, indices[256];
29518 char *new_names[256];
29519 Atom results[256], candidate;
29520
29521 if (count > 256)
29522
29523
29524 XInternAtoms (dpyinfo->display, new_names, count, False, atoms_return);
29525 else
29526 {
29527 for (i = 0, j = 0; i < count; ++i)
29528 {
29529 candidate = x_intern_cached_atom (dpyinfo, names[i],
29530 true);
29531
29532 if (candidate)
29533 atoms_return[i] = candidate;
29534 else
29535 {
29536 indices[j++] = i;
29537 new_names[j - 1] = names[i];
29538 }
29539 }
29540
29541 if (!j)
29542 return;
29543
29544
29545 XInternAtoms (dpyinfo->display, new_names, j, False,
29546 results);
29547
29548 for (i = 0; i < j; ++i)
29549 atoms_return[indices[i]] = results[i];
29550 }
29551 }
29552
29553 #ifndef USE_GTK
29554
29555
29556
29557
29558 bool
29559 x_embed_frame (struct x_display_info *dpyinfo, struct frame *f)
29560 {
29561 bool rc;
29562
29563 x_catch_errors (dpyinfo->display);
29564
29565 XReparentWindow (dpyinfo->display, FRAME_OUTER_WINDOW (f),
29566 FRAME_OUTPUT_DATA (f)->parent_desc, 0, 0);
29567 rc = x_had_errors_p (dpyinfo->display);
29568 x_uncatch_errors_after_check ();
29569
29570 if (rc)
29571 return false;
29572
29573 return true;
29574 }
29575
29576 #endif
29577
29578
29579
29580
29581
29582
29583
29584
29585
29586
29587
29588 void
29589 x_wm_set_size_hint (struct frame *f, long flags, bool user_position)
29590 {
29591 #ifndef USE_GTK
29592 XSizeHints size_hints;
29593 Window window = FRAME_OUTER_WINDOW (f);
29594 #ifdef USE_X_TOOLKIT
29595 WMShellWidget shell;
29596 #ifndef USE_MOTIF
29597 bool hints_changed;
29598 #endif
29599 #endif
29600
29601 if (!window)
29602 return;
29603
29604 #ifdef USE_X_TOOLKIT
29605 if (f->output_data.x->widget)
29606 {
29607
29608
29609
29610 eassert (XtIsWMShell (f->output_data.x->widget));
29611 shell = (WMShellWidget) f->output_data.x->widget;
29612
29613 if (flags)
29614 {
29615 shell->wm.size_hints.flags &= ~(PPosition | USPosition);
29616 shell->wm.size_hints.flags |= flags & (PPosition | USPosition);
29617 }
29618
29619 if (user_position)
29620 {
29621 shell->wm.size_hints.flags &= ~PPosition;
29622 shell->wm.size_hints.flags |= USPosition;
29623 }
29624
29625 #ifndef USE_MOTIF
29626 hints_changed
29627 = widget_update_wm_size_hints (f->output_data.x->widget,
29628 f->output_data.x->edit_widget);
29629 #else
29630 widget_update_wm_size_hints (f->output_data.x->widget,
29631 f->output_data.x->edit_widget);
29632
29633
29634
29635 shell->wm.size_hints.flags &= ~(PPosition | USPosition);
29636 shell->wm.size_hints.flags |= flags & (PPosition | USPosition);
29637
29638 if (user_position)
29639 {
29640 shell->wm.size_hints.flags &= ~PPosition;
29641 shell->wm.size_hints.flags |= USPosition;
29642 }
29643 #endif
29644
29645
29646 size_hints.flags = shell->wm.size_hints.flags;
29647 size_hints.x = shell->wm.size_hints.x;
29648 size_hints.y = shell->wm.size_hints.y;
29649 size_hints.width = shell->wm.size_hints.width;
29650 size_hints.height = shell->wm.size_hints.height;
29651 size_hints.min_width = shell->wm.size_hints.min_width;
29652 size_hints.min_height = shell->wm.size_hints.min_height;
29653 size_hints.max_width = shell->wm.size_hints.max_width;
29654 size_hints.max_height = shell->wm.size_hints.max_height;
29655 size_hints.width_inc = shell->wm.size_hints.width_inc;
29656 size_hints.height_inc = shell->wm.size_hints.height_inc;
29657 size_hints.min_aspect.x = shell->wm.size_hints.min_aspect.x;
29658 size_hints.min_aspect.y = shell->wm.size_hints.min_aspect.y;
29659 size_hints.max_aspect.x = shell->wm.size_hints.max_aspect.x;
29660 size_hints.max_aspect.y = shell->wm.size_hints.max_aspect.y;
29661 size_hints.base_width = shell->wm.base_width;
29662 size_hints.base_height = shell->wm.base_height;
29663 size_hints.win_gravity = shell->wm.win_gravity;
29664
29665 #ifdef USE_MOTIF
29666 XSetWMNormalHints (XtDisplay (f->output_data.x->widget),
29667 XtWindow (f->output_data.x->widget),
29668 &size_hints);
29669 #else
29670
29671
29672
29673
29674 if (!hints_changed)
29675 XSetWMNormalHints (XtDisplay (f->output_data.x->widget),
29676 XtWindow (f->output_data.x->widget),
29677 &size_hints);
29678 #endif
29679
29680 return;
29681 }
29682 #endif
29683
29684
29685 size_hints.flags = PResizeInc | PMinSize ;
29686
29687 size_hints.x = f->left_pos;
29688 size_hints.y = f->top_pos;
29689
29690 size_hints.width = FRAME_PIXEL_WIDTH (f);
29691 size_hints.height = FRAME_PIXEL_HEIGHT (f);
29692
29693 size_hints.width_inc = frame_resize_pixelwise ? 1 : FRAME_COLUMN_WIDTH (f);
29694 size_hints.height_inc = frame_resize_pixelwise ? 1 : FRAME_LINE_HEIGHT (f);
29695
29696 size_hints.max_width = x_display_pixel_width (FRAME_DISPLAY_INFO (f))
29697 - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
29698 size_hints.max_height = x_display_pixel_height (FRAME_DISPLAY_INFO (f))
29699 - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
29700
29701
29702 {
29703 int base_width, base_height;
29704
29705 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
29706 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
29707
29708
29709
29710
29711
29712
29713
29714 size_hints.flags |= PBaseSize;
29715 size_hints.base_width = base_width;
29716 size_hints.base_height = base_height + FRAME_MENUBAR_HEIGHT (f);
29717 size_hints.min_width = base_width;
29718 size_hints.min_height = base_height;
29719 }
29720
29721
29722 if (flags)
29723 {
29724 size_hints.flags |= flags;
29725 goto no_read;
29726 }
29727
29728 {
29729 XSizeHints hints;
29730 long supplied_return;
29731 int value;
29732
29733 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
29734 &supplied_return);
29735
29736 if (flags)
29737 size_hints.flags |= flags;
29738 else
29739 {
29740 if (value == 0)
29741 hints.flags = 0;
29742 if (hints.flags & PSize)
29743 size_hints.flags |= PSize;
29744 if (hints.flags & PPosition)
29745 size_hints.flags |= PPosition;
29746 if (hints.flags & USPosition)
29747 size_hints.flags |= USPosition;
29748 if (hints.flags & USSize)
29749 size_hints.flags |= USSize;
29750 }
29751 }
29752
29753 no_read:
29754
29755 #ifdef PWinGravity
29756 size_hints.win_gravity = f->win_gravity;
29757 size_hints.flags |= PWinGravity;
29758
29759 if (user_position)
29760 {
29761 size_hints.flags &= ~ PPosition;
29762 size_hints.flags |= USPosition;
29763 }
29764 #endif
29765
29766 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
29767 #else
29768 xg_wm_set_size_hint (f, flags, user_position);
29769 #endif
29770 }
29771
29772
29773
29774 static void
29775 x_wm_set_window_state (struct frame *f, int state)
29776 {
29777 #ifdef USE_X_TOOLKIT
29778 Arg al[1];
29779
29780 XtSetArg (al[0], XtNinitialState, state);
29781 XtSetValues (f->output_data.x->widget, al, 1);
29782 #else
29783 Window window = FRAME_X_WINDOW (f);
29784
29785 f->output_data.x->wm_hints.flags |= StateHint;
29786 f->output_data.x->wm_hints.initial_state = state;
29787
29788 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
29789 #endif
29790 }
29791
29792 static void
29793 x_wm_set_icon_pixmap (struct frame *f, ptrdiff_t pixmap_id)
29794 {
29795 Pixmap icon_pixmap, icon_mask;
29796
29797 #if !defined USE_X_TOOLKIT && !defined USE_GTK
29798 Window window = FRAME_OUTER_WINDOW (f);
29799 #endif
29800
29801 if (pixmap_id > 0)
29802 {
29803 icon_pixmap = image_bitmap_pixmap (f, pixmap_id);
29804 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
29805 icon_mask = x_bitmap_mask (f, pixmap_id);
29806 f->output_data.x->wm_hints.icon_mask = icon_mask;
29807 }
29808 else
29809 {
29810
29811
29812 return;
29813 }
29814
29815
29816 #ifdef USE_GTK
29817 {
29818 xg_set_frame_icon (f, icon_pixmap, icon_mask);
29819 return;
29820 }
29821
29822 #elif defined (USE_X_TOOLKIT)
29823
29824 {
29825 Arg al[1];
29826 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
29827 XtSetValues (f->output_data.x->widget, al, 1);
29828 XtSetArg (al[0], XtNiconMask, icon_mask);
29829 XtSetValues (f->output_data.x->widget, al, 1);
29830 }
29831
29832 #else
29833
29834 f->output_data.x->wm_hints.flags |= (IconPixmapHint | IconMaskHint);
29835 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
29836
29837 #endif
29838 }
29839
29840 void
29841 x_wm_set_icon_position (struct frame *f, int icon_x, int icon_y)
29842 {
29843 Window window = FRAME_OUTER_WINDOW (f);
29844
29845 f->output_data.x->wm_hints.flags |= IconPositionHint;
29846 f->output_data.x->wm_hints.icon_x = icon_x;
29847 f->output_data.x->wm_hints.icon_y = icon_y;
29848
29849 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
29850 }
29851
29852
29853
29854
29855
29856
29857 #ifdef GLYPH_DEBUG
29858
29859
29860
29861
29862 static void
29863 x_check_font (struct frame *f, struct font *font)
29864 {
29865 eassert (font != NULL && ! NILP (font->props[FONT_TYPE_INDEX]));
29866 if (font->driver->check)
29867 eassert (font->driver->check (f, font) == 0);
29868 }
29869
29870 #endif
29871
29872
29873
29874
29875
29876
29877 static void
29878 x_free_pixmap (struct frame *f, Emacs_Pixmap pixmap)
29879 {
29880 #ifdef USE_CAIRO
29881 if (pixmap)
29882 {
29883 xfree (pixmap->data);
29884 xfree (pixmap);
29885 }
29886 #else
29887 XFreePixmap (FRAME_X_DISPLAY (f), pixmap);
29888 #endif
29889 }
29890
29891
29892
29893
29894
29895
29896 #ifdef USE_X_TOOLKIT
29897 static XrmOptionDescRec emacs_options[] = {
29898 {(char *) "-geometry", (char *) ".geometry", XrmoptionSepArg, NULL},
29899 {(char *) "-iconic", (char *) ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
29900
29901 {(char *) "-internal-border-width",
29902 (char *) "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
29903 {(char *) "-ib", (char *) "*EmacsScreen.internalBorderWidth",
29904 XrmoptionSepArg, NULL},
29905 {(char *) "-T", (char *) "*EmacsShell.title", XrmoptionSepArg, NULL},
29906 {(char *) "-wn", (char *) "*EmacsShell.title", XrmoptionSepArg, NULL},
29907 {(char *) "-title", (char *) "*EmacsShell.title", XrmoptionSepArg, NULL},
29908 {(char *) "-iconname", (char *) "*EmacsShell.iconName",
29909 XrmoptionSepArg, NULL},
29910 {(char *) "-in", (char *) "*EmacsShell.iconName", XrmoptionSepArg, NULL},
29911 {(char *) "-mc", (char *) "*pointerColor", XrmoptionSepArg, NULL},
29912 {(char *) "-cr", (char *) "*cursorColor", XrmoptionSepArg, NULL}
29913 };
29914
29915
29916
29917 static bool x_timeout_atimer_activated_flag;
29918
29919 #endif
29920
29921 static int x_initialized;
29922
29923
29924
29925 static bool
29926 same_x_server (const char *name1, const char *name2)
29927 {
29928 bool seen_colon = false;
29929 Lisp_Object sysname = Fsystem_name ();
29930 if (! STRINGP (sysname))
29931 sysname = empty_unibyte_string;
29932 const char *system_name = SSDATA (sysname);
29933 ptrdiff_t system_name_length = SBYTES (sysname);
29934 ptrdiff_t length_until_period = 0;
29935
29936 while (system_name[length_until_period] != 0
29937 && system_name[length_until_period] != '.')
29938 length_until_period++;
29939
29940
29941 if (! strncmp (name1, "unix:", 5))
29942 name1 += 4;
29943 if (! strncmp (name2, "unix:", 5))
29944 name2 += 4;
29945
29946 if (! strncmp (name1, system_name, system_name_length)
29947 && name1[system_name_length] == ':')
29948 name1 += system_name_length;
29949 if (! strncmp (name2, system_name, system_name_length)
29950 && name2[system_name_length] == ':')
29951 name2 += system_name_length;
29952
29953 if (! strncmp (name1, system_name, length_until_period)
29954 && name1[length_until_period] == ':')
29955 name1 += length_until_period;
29956 if (! strncmp (name2, system_name, length_until_period)
29957 && name2[length_until_period] == ':')
29958 name2 += length_until_period;
29959
29960 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
29961 {
29962 if (*name1 == ':')
29963 seen_colon = true;
29964 if (seen_colon && *name1 == '.')
29965 return true;
29966 }
29967 return (seen_colon
29968 && (*name1 == '.' || *name1 == '\0')
29969 && (*name2 == '.' || *name2 == '\0'));
29970 }
29971
29972
29973
29974
29975 static void
29976 get_bits_and_offset (unsigned long mask, int *bits, int *offset)
29977 {
29978 int nr = 0;
29979 int off = 0;
29980
29981 while (!(mask & 1))
29982 {
29983 off++;
29984 mask >>= 1;
29985 }
29986
29987 while (mask & 1)
29988 {
29989 nr++;
29990 mask >>= 1;
29991 }
29992
29993 *offset = off;
29994 *bits = nr;
29995 }
29996
29997
29998
29999
30000 bool
30001 x_display_ok (const char *display)
30002 {
30003
30004 unrequest_sigio ();
30005 Display *dpy = XOpenDisplay (display);
30006 request_sigio ();
30007 if (!dpy)
30008 return false;
30009 XCloseDisplay (dpy);
30010 return true;
30011 }
30012
30013 #ifdef USE_GTK
30014 static void
30015 my_log_handler (const gchar *log_domain, GLogLevelFlags log_level,
30016 const gchar *msg, gpointer user_data)
30017 {
30018 if (!strstr (msg, "g_set_prgname"))
30019 fprintf (stderr, "%s-WARNING **: %s\n", log_domain, msg);
30020 }
30021 #endif
30022
30023
30024
30025 static unsigned x_display_id;
30026
30027 #if defined HAVE_XINPUT2 && !defined HAVE_GTK3
30028
30029
30030
30031
30032 static void
30033 xi_select_hierarchy_events (struct x_display_info *dpyinfo)
30034 {
30035 XIEventMask mask;
30036 ptrdiff_t l;
30037 unsigned char *m;
30038
30039 l = XIMaskLen (XI_LASTEVENT);
30040 mask.mask = m = alloca (l);
30041 memset (m, 0, l);
30042 mask.mask_len = l;
30043
30044 mask.deviceid = XIAllDevices;
30045
30046 XISetMask (m, XI_PropertyEvent);
30047 XISetMask (m, XI_HierarchyChanged);
30048 XISetMask (m, XI_DeviceChanged);
30049
30050 XISelectEvents (dpyinfo->display, dpyinfo->root_window,
30051 &mask, 1);
30052 }
30053
30054 #endif
30055
30056 #if defined HAVE_XINPUT2 && defined HAVE_GTK3
30057
30058
30059
30060
30061
30062
30063
30064
30065
30066 static int
30067 xi_check_toolkit (Display *display)
30068 {
30069 GdkDisplay *gdpy;
30070 GdkDeviceManager *manager;
30071
30072 gdpy = gdk_x11_lookup_xdisplay (display);
30073 eassume (gdpy);
30074 manager = gdk_display_get_device_manager (gdpy);
30075
30076 if (!strcmp (G_OBJECT_TYPE_NAME (manager),
30077 "GdkX11DeviceManagerXI2"))
30078 return 1;
30079
30080 if (!strcmp (G_OBJECT_TYPE_NAME (manager),
30081 "GdkX11DeviceManagerCore"))
30082 return 0;
30083
30084
30085
30086
30087 return 2;
30088 }
30089
30090 #endif
30091
30092
30093
30094
30095
30096
30097 struct x_display_info *
30098 x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
30099 {
30100 Display *dpy;
30101 XKeyboardState keyboard_state;
30102 struct terminal *terminal;
30103 struct x_display_info *dpyinfo;
30104 XrmDatabase xrdb;
30105 Lisp_Object tem, quit_keysym;
30106 #ifdef USE_XCB
30107 xcb_connection_t *xcb_conn;
30108 #endif
30109 static char const cm_atom_fmt[] = "_NET_WM_CM_S%d";
30110 char cm_atom_sprintf[sizeof cm_atom_fmt - 2 + INT_STRLEN_BOUND (int)];
30111 #ifdef USE_GTK
30112 GdkDisplay *gdpy;
30113 GdkScreen *gscr;
30114 #endif
30115 #ifdef HAVE_XFIXES
30116 Lisp_Object lisp_name;
30117 int num_fast_selections;
30118 Atom selection_name;
30119 #ifdef USE_XCB
30120 xcb_get_selection_owner_cookie_t *selection_cookies;
30121 xcb_get_selection_owner_reply_t *selection_reply;
30122 xcb_generic_error_t *selection_error;
30123 #endif
30124 #endif
30125 int i;
30126
30127 #if defined HAVE_XFIXES && defined USE_XCB
30128 USE_SAFE_ALLOCA;
30129 #endif
30130
30131 block_input ();
30132
30133 if (!x_initialized)
30134 {
30135 x_initialize ();
30136 ++x_initialized;
30137 }
30138
30139 #if defined USE_X_TOOLKIT || defined USE_GTK
30140
30141 if (!x_display_ok (SSDATA (display_name)))
30142 error ("Display %s can't be opened", SSDATA (display_name));
30143
30144 #endif
30145
30146 #ifdef USE_GTK
30147 {
30148 #define NUM_ARGV 10
30149 int argc;
30150 char *argv[NUM_ARGV];
30151 char **argv2 = argv;
30152 guint id;
30153
30154 if (x_initialized++ > 1)
30155 {
30156 xg_display_open (SSDATA (display_name), &dpy);
30157 }
30158 else
30159 {
30160 static char display_opt[] = "--display";
30161 static char name_opt[] = "--name";
30162
30163 for (argc = 0; argc < NUM_ARGV; ++argc)
30164 argv[argc] = 0;
30165
30166 argc = 0;
30167 argv[argc++] = initial_argv[0];
30168
30169 if (! NILP (display_name))
30170 {
30171 argv[argc++] = display_opt;
30172 argv[argc++] = SSDATA (display_name);
30173 }
30174
30175 argv[argc++] = name_opt;
30176 argv[argc++] = resource_name;
30177
30178 XSetLocaleModifiers ("");
30179
30180
30181
30182 id = g_log_set_handler ("GLib", G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL
30183 | G_LOG_FLAG_RECURSION, my_log_handler, NULL);
30184
30185
30186
30187 gdk_window_add_filter (NULL, event_handler_gdk, NULL);
30188
30189
30190 fixup_locale ();
30191 unrequest_sigio ();
30192 gtk_init (&argc, &argv2);
30193 request_sigio ();
30194
30195 g_log_remove_handler ("GLib", id);
30196
30197 xg_initialize ();
30198
30199
30200
30201
30202 fixup_locale ();
30203
30204 dpy = DEFAULT_GDK_DISPLAY ();
30205
30206 #ifndef HAVE_GTK3
30207
30208 {
30209 const char *file = "~/.emacs.d/gtkrc";
30210 Lisp_Object s, abs_file;
30211
30212 s = build_string (file);
30213 abs_file = Fexpand_file_name (s, Qnil);
30214
30215 if (! NILP (abs_file) && !NILP (Ffile_readable_p (abs_file)))
30216 gtk_rc_parse (SSDATA (abs_file));
30217 }
30218 #endif
30219
30220 XSetErrorHandler (x_error_handler);
30221 XSetIOErrorHandler (x_io_error_quitter);
30222 }
30223 }
30224 #else
30225 #ifdef USE_X_TOOLKIT
30226
30227
30228
30229
30230
30231 #ifdef HAVE_X11XTR6
30232 XtSetLanguageProc (NULL, NULL, NULL);
30233 #endif
30234
30235 {
30236 int argc = 0;
30237 char *argv[3];
30238
30239 argv[0] = (char *) "";
30240 argc = 1;
30241 if (xrm_option)
30242 {
30243 argv[argc++] = (char *) "-xrm";
30244 argv[argc++] = xrm_option;
30245 }
30246 turn_on_atimers (false);
30247 unrequest_sigio ();
30248 dpy = XtOpenDisplay (Xt_app_con, SSDATA (display_name),
30249 resource_name, EMACS_CLASS,
30250 emacs_options, XtNumber (emacs_options),
30251 &argc, argv);
30252 request_sigio ();
30253 turn_on_atimers (true);
30254
30255 #ifdef HAVE_X11XTR6
30256
30257 fixup_locale ();
30258 #endif
30259 }
30260
30261 #else
30262 XSetLocaleModifiers ("");
30263 unrequest_sigio ();
30264 dpy = XOpenDisplay (SSDATA (display_name));
30265 request_sigio ();
30266 #endif
30267 #endif
30268
30269
30270 if (dpy == 0)
30271 {
30272 #if !defined USE_X_TOOLKIT && !defined USE_GTK
30273
30274
30275
30276
30277
30278 error ("Display %s can't be opened", SSDATA (display_name));
30279 #endif
30280
30281 unblock_input ();
30282
30283 #if defined HAVE_XFIXES && defined USE_XCB
30284 SAFE_FREE ();
30285 #endif
30286 return 0;
30287 }
30288
30289 #ifdef USE_XCB
30290 xcb_conn = XGetXCBConnection (dpy);
30291 if (!xcb_conn)
30292 {
30293 #ifdef USE_GTK
30294 xg_display_close (dpy);
30295 #else
30296 #ifdef USE_X_TOOLKIT
30297 XtCloseDisplay (dpy);
30298 #else
30299 XCloseDisplay (dpy);
30300 #endif
30301 #endif
30302
30303 unblock_input ();
30304
30305 #if defined HAVE_XFIXES && defined USE_XCB
30306 SAFE_FREE ();
30307 #endif
30308 return 0;
30309 }
30310 #endif
30311
30312
30313
30314
30315 XSelectInput (dpy, DefaultRootWindow (dpy), StructureNotifyMask);
30316
30317
30318
30319 dpyinfo = xzalloc (sizeof *dpyinfo);
30320 terminal = x_create_terminal (dpyinfo);
30321
30322 if (!NILP (Vx_detect_server_trust))
30323 {
30324
30325
30326
30327 XGrabServer (dpy);
30328 XGetKeyboardControl (dpy, &keyboard_state);
30329
30330 x_catch_errors (dpy);
30331
30332
30333
30334
30335
30336 if (keyboard_state.global_auto_repeat
30337 == AutoRepeatModeOn)
30338 XAutoRepeatOn (dpy);
30339 else
30340 XAutoRepeatOff (dpy);
30341
30342 if (x_had_errors_p (dpy))
30343 dpyinfo->untrusted = true;
30344 x_uncatch_errors_after_check ();
30345 XUngrabServer (dpy);
30346 }
30347
30348 dpyinfo->next_failable_request = dpyinfo->failable_requests;
30349
30350 {
30351 struct x_display_info *share;
30352
30353 for (share = x_display_list; share; share = share->next)
30354 if (same_x_server (SSDATA (XCAR (share->name_list_element)),
30355 SSDATA (display_name)))
30356 break;
30357 if (share)
30358 terminal->kboard = share->terminal->kboard;
30359 else
30360 {
30361 terminal->kboard = allocate_kboard (Qx);
30362
30363 if (!BASE_EQ (XSYMBOL (Qvendor_specific_keysyms)->u.s.function,
30364 Qunbound))
30365 {
30366 char *vendor = ServerVendor (dpy);
30367
30368
30369
30370
30371
30372 terminal_list = terminal->next_terminal;
30373 unblock_input ();
30374 kset_system_key_alist (terminal->kboard,
30375 safe_call1 (Qvendor_specific_keysyms,
30376 (vendor
30377 ? build_string (vendor)
30378 : empty_unibyte_string)));
30379 block_input ();
30380 terminal->next_terminal = terminal_list;
30381 terminal_list = terminal;
30382 }
30383
30384
30385
30386
30387 if (current_kboard == initial_kboard)
30388 current_kboard = terminal->kboard;
30389 }
30390 terminal->kboard->reference_count++;
30391 }
30392
30393
30394
30395 tem = Vx_quit_keysym;
30396 FOR_EACH_TAIL_SAFE (tem)
30397 {
30398 quit_keysym = XCAR (tem);
30399
30400
30401
30402
30403 if (!CONSP (quit_keysym) || !FIXNUMP (XCDR (quit_keysym))
30404 || !STRINGP (XCAR (quit_keysym)))
30405 continue;
30406
30407
30408
30409 if (strcmp (SSDATA (XCAR (quit_keysym)), ServerVendor (dpy)))
30410 continue;
30411
30412 dpyinfo->quit_keysym = XFIXNUM (XCDR (quit_keysym));
30413 }
30414
30415
30416 dpyinfo->next = x_display_list;
30417 x_display_list = dpyinfo;
30418
30419 dpyinfo->name_list_element = Fcons (display_name, Qnil);
30420 dpyinfo->display = dpy;
30421 dpyinfo->connection = ConnectionNumber (dpyinfo->display);
30422 #ifdef USE_XCB
30423 dpyinfo->xcb_connection = xcb_conn;
30424 #endif
30425
30426
30427 dpyinfo->smallest_font_height = 1;
30428 dpyinfo->smallest_char_width = 1;
30429
30430 dpyinfo->color_names_size = 256;
30431 dpyinfo->color_names = xzalloc (dpyinfo->color_names_size
30432 * sizeof *dpyinfo->color_names);
30433 dpyinfo->color_names_length = xzalloc (dpyinfo->color_names_size
30434 * sizeof *dpyinfo->color_names_length);
30435
30436
30437 terminal->name = xlispstrdup (display_name);
30438
30439 #if false
30440 XSetAfterFunction (dpyinfo->display, x_trace_wire);
30441 #endif
30442
30443 Lisp_Object system_name = Fsystem_name ();
30444 static char const title[] = "GNU Emacs";
30445 if (STRINGP (system_name))
30446 {
30447 static char const at[] = " at ";
30448 ptrdiff_t nbytes = sizeof (title) + sizeof (at);
30449 if (ckd_add (&nbytes, nbytes, SBYTES (system_name)))
30450 memory_full (SIZE_MAX);
30451 dpyinfo->x_id_name = xmalloc (nbytes);
30452 sprintf (dpyinfo->x_id_name, "%s%s%s", title, at, SDATA (system_name));
30453 }
30454 else
30455 {
30456 dpyinfo->x_id_name = xmalloc (sizeof (title));
30457 strcpy (dpyinfo->x_id_name, title);
30458 }
30459
30460 dpyinfo->x_id = ++x_display_id;
30461
30462 #ifndef HAVE_XKB
30463
30464 x_find_modifier_meanings (dpyinfo);
30465 #endif
30466
30467
30468 #ifdef USE_GTK
30469
30470 dpyinfo->xg_cursor = xg_create_default_cursor (dpyinfo->display);
30471 #endif
30472
30473 dpyinfo->vertical_scroll_bar_cursor
30474 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
30475
30476 dpyinfo->horizontal_scroll_bar_cursor
30477 = XCreateFontCursor (dpyinfo->display, XC_sb_h_double_arrow);
30478
30479 xrdb = x_load_resources (dpyinfo->display, xrm_option,
30480 resource_name, EMACS_CLASS);
30481 #ifdef HAVE_XRMSETDATABASE
30482 XrmSetDatabase (dpyinfo->display, xrdb);
30483 #else
30484 dpyinfo->display->db = xrdb;
30485 #endif
30486
30487 #ifdef HAVE_XRENDER
30488 int event_base, error_base;
30489 dpyinfo->xrender_supported_p
30490 = XRenderQueryExtension (dpyinfo->display, &event_base, &error_base);
30491
30492 if (dpyinfo->xrender_supported_p)
30493 dpyinfo->xrender_supported_p
30494 = XRenderQueryVersion (dpyinfo->display, &dpyinfo->xrender_major,
30495 &dpyinfo->xrender_minor);
30496 #endif
30497
30498
30499 #ifdef HAVE_XCOMPOSITE
30500 int composite_event_base, composite_error_base;
30501 dpyinfo->composite_supported_p = XCompositeQueryExtension (dpyinfo->display,
30502 &composite_event_base,
30503 &composite_error_base);
30504
30505 if (dpyinfo->composite_supported_p)
30506 dpyinfo->composite_supported_p
30507 = XCompositeQueryVersion (dpyinfo->display,
30508 &dpyinfo->composite_major,
30509 &dpyinfo->composite_minor);
30510 #endif
30511
30512 #ifdef HAVE_XSHAPE
30513 dpyinfo->xshape_supported_p
30514 = XShapeQueryExtension (dpyinfo->display,
30515 &dpyinfo->xshape_event_base,
30516 &dpyinfo->xshape_error_base);
30517
30518 if (dpyinfo->xshape_supported_p)
30519 dpyinfo->xshape_supported_p
30520 = XShapeQueryVersion (dpyinfo->display,
30521 &dpyinfo->xshape_major,
30522 &dpyinfo->xshape_minor);
30523 #endif
30524
30525
30526
30527 dpyinfo->rdb = xrdb;
30528
30529 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
30530 DefaultScreen (dpyinfo->display));
30531 select_visual (dpyinfo);
30532 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
30533 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
30534 dpyinfo->icon_bitmap_id = -1;
30535 dpyinfo->wm_type = X_WMTYPE_UNKNOWN;
30536
30537 reset_mouse_highlight (&dpyinfo->mouse_highlight);
30538
30539 #ifdef HAVE_XRENDER
30540 if (dpyinfo->xrender_supported_p
30541
30542
30543 && !dpyinfo->pict_format)
30544 dpyinfo->pict_format = XRenderFindVisualFormat (dpyinfo->display,
30545 dpyinfo->visual);
30546 #endif
30547
30548 #ifdef HAVE_XSYNC
30549 int xsync_event_base, xsync_error_base;
30550 dpyinfo->xsync_supported_p
30551 = XSyncQueryExtension (dpyinfo->display,
30552 &xsync_event_base,
30553 &xsync_error_base);
30554
30555 if (dpyinfo->xsync_supported_p)
30556 dpyinfo->xsync_supported_p = XSyncInitialize (dpyinfo->display,
30557 &dpyinfo->xsync_major,
30558 &dpyinfo->xsync_minor);
30559
30560 {
30561 AUTO_STRING (synchronizeResize, "synchronizeResize");
30562 AUTO_STRING (SynchronizeResize, "SynchronizeResize");
30563
30564 Lisp_Object value = gui_display_get_resource (dpyinfo,
30565 synchronizeResize,
30566 SynchronizeResize,
30567 Qnil, Qnil);
30568
30569 if (STRINGP (value)
30570 && (!strcmp (SSDATA (value), "false")
30571 || !strcmp (SSDATA (value), "off")))
30572 dpyinfo->xsync_supported_p = false;
30573 }
30574 #endif
30575
30576 #ifdef HAVE_XINERAMA
30577 int xin_event_base, xin_error_base;
30578 dpyinfo->xinerama_supported_p
30579 = XineramaQueryExtension (dpy, &xin_event_base, &xin_error_base);
30580 #endif
30581
30582
30583 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
30584 {
30585 if (dpyinfo->visual_info.class == PseudoColor)
30586 {
30587 AUTO_STRING (privateColormap, "privateColormap");
30588 AUTO_STRING (PrivateColormap, "PrivateColormap");
30589 Lisp_Object value
30590 = gui_display_get_resource (dpyinfo, privateColormap,
30591 PrivateColormap, Qnil, Qnil);
30592 if (STRINGP (value)
30593 && (!strcmp (SSDATA (value), "true")
30594 || !strcmp (SSDATA (value), "on")))
30595 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
30596 }
30597 }
30598 else
30599 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
30600 dpyinfo->visual, AllocNone);
30601
30602
30603 if (dpyinfo->visual_info.class == TrueColor)
30604 {
30605 get_bits_and_offset (dpyinfo->visual_info.red_mask,
30606 &dpyinfo->red_bits, &dpyinfo->red_offset);
30607 get_bits_and_offset (dpyinfo->visual_info.blue_mask,
30608 &dpyinfo->blue_bits, &dpyinfo->blue_offset);
30609 get_bits_and_offset (dpyinfo->visual_info.green_mask,
30610 &dpyinfo->green_bits, &dpyinfo->green_offset);
30611
30612 #ifdef HAVE_XRENDER
30613 if (dpyinfo->pict_format)
30614 {
30615 unsigned long channel_mask
30616 = ((unsigned long) dpyinfo->pict_format->direct.alphaMask
30617 << dpyinfo->pict_format->direct.alpha);
30618
30619 if (channel_mask)
30620 get_bits_and_offset (channel_mask, &dpyinfo->alpha_bits,
30621 &dpyinfo->alpha_offset);
30622 dpyinfo->alpha_mask = channel_mask;
30623 }
30624 else
30625 #endif
30626 {
30627 XColor xc;
30628 unsigned long alpha_mask;
30629 xc.red = 65535;
30630 xc.green = 65535;
30631 xc.blue = 65535;
30632
30633 if (XAllocColor (dpyinfo->display,
30634 dpyinfo->cmap, &xc) != 0)
30635 {
30636 alpha_mask = xc.pixel & ~(dpyinfo->visual_info.red_mask
30637 | dpyinfo->visual_info.blue_mask
30638 | dpyinfo->visual_info.green_mask);
30639
30640 if (alpha_mask)
30641 get_bits_and_offset (alpha_mask, &dpyinfo->alpha_bits,
30642 &dpyinfo->alpha_offset);
30643 dpyinfo->alpha_mask = alpha_mask;
30644 }
30645 }
30646 }
30647
30648 #ifdef HAVE_XDBE
30649 dpyinfo->supports_xdbe = false;
30650 int xdbe_major;
30651 int xdbe_minor;
30652 if (XdbeQueryExtension (dpyinfo->display, &xdbe_major, &xdbe_minor))
30653 dpyinfo->supports_xdbe = true;
30654 #endif
30655
30656 #ifdef USE_XCB
30657 xcb_screen_t *xcb_screen = NULL;
30658 xcb_screen_iterator_t iter;
30659 xcb_visualid_t wanted = { XVisualIDFromVisual (dpyinfo->visual) };
30660 xcb_depth_iterator_t depth_iter;
30661 xcb_visualtype_iterator_t visual_iter;
30662
30663 int screen = DefaultScreen (dpyinfo->display);
30664
30665 iter = xcb_setup_roots_iterator (xcb_get_setup (dpyinfo->xcb_connection));
30666 for (; iter.rem; --screen, xcb_screen_next (&iter))
30667 {
30668 if (!screen)
30669 xcb_screen = iter.data;
30670 }
30671
30672 if (xcb_screen)
30673 {
30674 depth_iter = xcb_screen_allowed_depths_iterator (xcb_screen);
30675 for (; depth_iter.rem; xcb_depth_next (&depth_iter))
30676 {
30677 visual_iter = xcb_depth_visuals_iterator (depth_iter.data);
30678 for (; visual_iter.rem; xcb_visualtype_next (&visual_iter))
30679 {
30680 if (wanted == visual_iter.data->visual_id)
30681 {
30682 dpyinfo->xcb_visual = visual_iter.data;
30683 break;
30684 }
30685 }
30686 }
30687 }
30688 #endif
30689
30690 #ifdef HAVE_XINPUT2
30691 dpyinfo->supports_xi2 = false;
30692 int rc;
30693 int major = 2;
30694 int xi_first_event, xi_first_error;
30695
30696 #ifndef HAVE_GTK3
30697 {
30698 AUTO_STRING (disableInputExtension, "disableInputExtension");
30699 AUTO_STRING (DisableInputExtension, "DisableInputExtension");
30700
30701 Lisp_Object value = gui_display_get_resource (dpyinfo,
30702 disableInputExtension,
30703 DisableInputExtension,
30704 Qnil, Qnil);
30705
30706 if (STRINGP (value)
30707 && (!strcmp (SSDATA (value), "on")
30708 || !strcmp (SSDATA (value), "true")))
30709 goto skip_xi_setup;
30710 }
30711 #endif
30712
30713 #ifdef HAVE_XINPUT2_4
30714 int minor = 4;
30715 #elif defined HAVE_XINPUT2_3
30716 int minor = 3;
30717 #elif defined HAVE_XINPUT2_2
30718 int minor = 2;
30719 #elif defined HAVE_XINPUT2_1
30720 int minor = 1;
30721 #else
30722 int minor = 0;
30723 #endif
30724
30725 dpyinfo->client_pointer_device = -1;
30726
30727 #ifdef HAVE_GTK3
30728
30729
30730
30731
30732 rc = xi_check_toolkit (dpyinfo->display);
30733
30734 if (!rc)
30735 goto skip_xi_setup;
30736 #endif
30737
30738 if (XQueryExtension (dpyinfo->display, "XInputExtension",
30739 &dpyinfo->xi2_opcode, &xi_first_event,
30740 &xi_first_error))
30741 {
30742 #ifdef HAVE_GTK3
30743 bool move_backwards = false;
30744 int original_minor = minor;
30745
30746 query:
30747
30748
30749
30750
30751
30752
30753
30754
30755
30756
30757
30758
30759 #endif
30760
30761 x_catch_errors (dpyinfo->display);
30762
30763 rc = XIQueryVersion (dpyinfo->display, &major, &minor);
30764
30765 #ifdef HAVE_GTK3
30766
30767
30768
30769
30770
30771 if (x_had_errors_p (dpyinfo->display))
30772 {
30773 x_uncatch_errors_after_check ();
30774
30775
30776
30777
30778
30779 if (minor >= 2)
30780 {
30781 move_backwards = true;
30782 minor = original_minor;
30783
30784 if (--minor < 0)
30785 rc = BadRequest;
30786 else
30787 goto query;
30788 }
30789 else
30790 {
30791 if (!move_backwards)
30792 {
30793 minor++;
30794 goto query;
30795 }
30796
30797 if (--minor < 0)
30798 rc = BadRequest;
30799 else
30800 goto query;
30801
30802 }
30803 }
30804 else
30805 x_uncatch_errors_after_check ();
30806
30807
30808
30809
30810
30811 if (minor > original_minor)
30812 minor = original_minor;
30813 #else
30814 if (x_had_errors_p (dpyinfo->display))
30815 rc = BadRequest;
30816
30817 x_uncatch_errors_after_check ();
30818 #endif
30819
30820 if (rc == Success)
30821 {
30822 dpyinfo->supports_xi2 = true;
30823 #ifndef HAVE_GTK3
30824
30825
30826 xi_select_hierarchy_events (dpyinfo);
30827 #endif
30828
30829 dpyinfo->xi2_version = minor;
30830 x_cache_xi_devices (dpyinfo);
30831 }
30832 }
30833 skip_xi_setup:
30834 ;
30835 #endif
30836
30837 #if defined HAVE_XRANDR || defined USE_GTK
30838 Lisp_Object term;
30839
30840 XSETTERMINAL (term, terminal);
30841 #endif
30842
30843 #ifdef HAVE_XRANDR
30844 dpyinfo->xrandr_supported_p
30845 = XRRQueryExtension (dpy, &dpyinfo->xrandr_event_base,
30846 &dpyinfo->xrandr_error_base);
30847
30848 #ifndef USE_GTK
30849 dpyinfo->last_monitor_attributes_list = Qnil;
30850 #endif
30851
30852 if (dpyinfo->xrandr_supported_p)
30853 {
30854 XRRQueryVersion (dpy, &dpyinfo->xrandr_major_version,
30855 &dpyinfo->xrandr_minor_version);
30856
30857 #ifndef USE_GTK
30858 if (dpyinfo->xrandr_major_version == 1
30859 && dpyinfo->xrandr_minor_version >= 2)
30860 {
30861 XRRSelectInput (dpyinfo->display,
30862 dpyinfo->root_window,
30863 (RRScreenChangeNotifyMask
30864 | RRCrtcChangeNotifyMask
30865 | RROutputChangeNotifyMask
30866 #ifdef USE_GTK
30867
30868
30869
30870 | RROutputPropertyNotifyMask
30871 #endif
30872 ));
30873
30874 dpyinfo->last_monitor_attributes_list
30875 = Fx_display_monitor_attributes_list (term);
30876 }
30877 #endif
30878 }
30879 #endif
30880
30881 #ifdef USE_GTK
30882 dpyinfo->last_monitor_attributes_list
30883 = Fx_display_monitor_attributes_list (term);
30884
30885 gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display);
30886 gscr = gdk_display_get_default_screen (gdpy);
30887
30888 g_signal_connect (G_OBJECT (gscr), "monitors-changed",
30889 G_CALLBACK (x_monitors_changed_cb),
30890 NULL);
30891 #endif
30892
30893 #ifdef HAVE_XKB
30894 int xkb_major, xkb_minor, xkb_op, xkb_error_code;
30895 xkb_major = XkbMajorVersion;
30896 xkb_minor = XkbMinorVersion;
30897
30898 if (XkbLibraryVersion (&xkb_major, &xkb_minor)
30899 && XkbQueryExtension (dpyinfo->display, &xkb_op, &dpyinfo->xkb_event_type,
30900 &xkb_error_code, &xkb_major, &xkb_minor))
30901 {
30902 dpyinfo->supports_xkb = true;
30903 dpyinfo->xkb_desc = XkbGetMap (dpyinfo->display,
30904 (XkbKeySymsMask
30905 | XkbKeyTypesMask
30906 | XkbModifierMapMask
30907 | XkbVirtualModsMask),
30908 XkbUseCoreKbd);
30909
30910 if (dpyinfo->xkb_desc)
30911 XkbGetNames (dpyinfo->display, XkbAllNamesMask,
30912 dpyinfo->xkb_desc);
30913
30914 XkbSelectEvents (dpyinfo->display, XkbUseCoreKbd,
30915 XkbNewKeyboardNotifyMask | XkbMapNotifyMask,
30916 XkbNewKeyboardNotifyMask | XkbMapNotifyMask);
30917 }
30918 #endif
30919
30920 #ifdef HAVE_XFIXES
30921 int xfixes_error_base;
30922 dpyinfo->xfixes_supported_p
30923 = XFixesQueryExtension (dpyinfo->display,
30924 &dpyinfo->xfixes_event_base,
30925 &xfixes_error_base);
30926
30927 if (dpyinfo->xfixes_supported_p)
30928 {
30929 if (!XFixesQueryVersion (dpyinfo->display, &dpyinfo->xfixes_major,
30930 &dpyinfo->xfixes_minor))
30931 dpyinfo->xfixes_supported_p = false;
30932 }
30933 #endif
30934
30935 #if defined USE_CAIRO || defined HAVE_XFT
30936 {
30937
30938
30939
30940
30941
30942
30943
30944
30945
30946
30947
30948
30949
30950
30951 char *v = XGetDefault (dpyinfo->display, "Xft", "dpi");
30952 double d;
30953 if (v != NULL && sscanf (v, "%lf", &d) == 1)
30954 dpyinfo->resy = dpyinfo->resx = d;
30955 }
30956 #endif
30957
30958 if (dpyinfo->resy < 1)
30959 {
30960 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
30961 double pixels = DisplayHeight (dpyinfo->display, screen_number);
30962 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
30963
30964 dpyinfo->resy = (mm < 1) ? 100 : pixels * 25.4 / mm;
30965 pixels = DisplayWidth (dpyinfo->display, screen_number);
30966 mm = DisplayWidthMM (dpyinfo->display, screen_number);
30967
30968 dpyinfo->resx = (mm < 1) ? 100 : pixels * 25.4 / mm;
30969 }
30970
30971 sprintf (cm_atom_sprintf, cm_atom_fmt,
30972 XScreenNumberOfScreen (dpyinfo->screen));
30973
30974 {
30975 enum { atom_count = ARRAYELTS (x_atom_refs) };
30976
30977 enum { total_atom_count = 2 + atom_count };
30978 Atom atoms_return[total_atom_count];
30979 char *atom_names[total_atom_count];
30980 static char const xsettings_fmt[] = "_XSETTINGS_S%d";
30981 char xsettings_atom_name[sizeof xsettings_fmt - 2
30982 + INT_STRLEN_BOUND (int)];
30983
30984 for (i = 0; i < atom_count; i++)
30985 atom_names[i] = (char *) x_atom_refs[i].name;
30986
30987
30988 sprintf (xsettings_atom_name, xsettings_fmt,
30989 XScreenNumberOfScreen (dpyinfo->screen));
30990 atom_names[i] = xsettings_atom_name;
30991 atom_names[i + 1] = cm_atom_sprintf;
30992
30993 XInternAtoms (dpyinfo->display, atom_names, total_atom_count,
30994 False, atoms_return);
30995
30996 for (i = 0; i < atom_count; i++)
30997 *(Atom *) ((char *) dpyinfo + x_atom_refs[i].offset) = atoms_return[i];
30998
30999
31000 dpyinfo->Xatom_xsettings_sel = atoms_return[i];
31001 dpyinfo->Xatom_NET_WM_CM_Sn = atoms_return[i + 1];
31002 }
31003
31004 #ifdef HAVE_XKB
31005
31006 x_find_modifier_meanings (dpyinfo);
31007 #endif
31008
31009 dpyinfo->x_dnd_atoms_size = 16;
31010 dpyinfo->x_dnd_atoms = xmalloc (sizeof *dpyinfo->x_dnd_atoms
31011 * dpyinfo->x_dnd_atoms_size);
31012 dpyinfo->gray
31013 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
31014 gray_bits, gray_width, gray_height,
31015 1, 0, 1);
31016
31017 dpyinfo->invisible_cursor = make_invisible_cursor (dpyinfo);
31018 #if defined HAVE_XFIXES && XFIXES_VERSION >= 40000
31019 dpyinfo->fixes_pointer_blanking = (egetenv ("EMACS_XFIXES") != NULL);
31020 #endif
31021
31022 xsettings_initialize (dpyinfo);
31023
31024
31025 if (dpyinfo->connection != 0)
31026 add_keyboard_wait_descriptor (dpyinfo->connection);
31027
31028 #ifdef F_SETOWN
31029 fcntl (dpyinfo->connection, F_SETOWN, getpid ());
31030 #endif
31031
31032 if (interrupt_input)
31033 init_sigio (dpyinfo->connection);
31034
31035 #ifdef USE_LUCID
31036 {
31037 XrmValue d, fr, to;
31038 Font font;
31039 XFontStruct *query_result;
31040
31041 dpy = dpyinfo->display;
31042 d.addr = (XPointer) &dpy;
31043 d.size = sizeof (Display *);
31044 fr.addr = (char *) XtDefaultFont;
31045 fr.size = sizeof (XtDefaultFont);
31046 to.size = sizeof (Font *);
31047 to.addr = (XPointer) &font;
31048 x_catch_errors (dpy);
31049 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
31050 emacs_abort ();
31051 query_result = XQueryFont (dpy, font);
31052
31053
31054
31055 if (x_had_errors_p (dpy) || !font)
31056 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
31057
31058
31059
31060
31061
31062 XFreeFontInfo (NULL, query_result, 1);
31063 x_uncatch_errors ();
31064 }
31065 #endif
31066
31067
31068
31069 {
31070 AUTO_STRING (synchronous, "synchronous");
31071 AUTO_STRING (Synchronous, "Synchronous");
31072 Lisp_Object value = gui_display_get_resource (dpyinfo, synchronous,
31073 Synchronous, Qnil, Qnil);
31074 if (STRINGP (value)
31075 && (!strcmp (SSDATA (value), "true")
31076 || !strcmp (SSDATA (value), "on")))
31077 XSynchronize (dpyinfo->display, True);
31078 }
31079
31080 #ifdef HAVE_X_I18N
31081 {
31082 AUTO_STRING (useXIM, "useXIM");
31083 AUTO_STRING (UseXIM, "UseXIM");
31084 Lisp_Object value = gui_display_get_resource (dpyinfo, useXIM, UseXIM,
31085 Qnil, Qnil);
31086
31087
31088
31089
31090 #ifdef USE_XIM
31091 dpyinfo->use_xim = true;
31092
31093 if (STRINGP (value)
31094 && (!strcmp (SSDATA (value), "false")
31095 || !strcmp (SSDATA (value), "off")))
31096 dpyinfo->use_xim = false;
31097 #else
31098 dpyinfo->use_xim = false;
31099
31100 if (STRINGP (value)
31101 && (!strcmp (SSDATA (value), "true")
31102 || !strcmp (SSDATA (value), "on")))
31103 dpyinfo->use_xim = true;
31104 #endif
31105 }
31106
31107 {
31108 AUTO_STRING (inputStyle, "inputStyle");
31109 AUTO_STRING (InputStyle, "InputStyle");
31110 Lisp_Object value = gui_display_get_resource (dpyinfo, inputStyle, InputStyle,
31111 Qnil, Qnil);
31112
31113 if (STRINGP (value))
31114 {
31115 if (!strcmp (SSDATA (value), "callback"))
31116 dpyinfo->preferred_xim_style = STYLE_CALLBACK;
31117 else if (!strcmp (SSDATA (value), "none"))
31118 dpyinfo->preferred_xim_style = STYLE_NONE;
31119 else if (!strcmp (SSDATA (value), "overthespot"))
31120 dpyinfo->preferred_xim_style = STYLE_OVERTHESPOT;
31121 else if (!strcmp (SSDATA (value), "offthespot"))
31122 dpyinfo->preferred_xim_style = STYLE_OFFTHESPOT;
31123 else if (!strcmp (SSDATA (value), "root"))
31124 dpyinfo->preferred_xim_style = STYLE_ROOT;
31125 #ifdef USE_GTK
31126 else if (!strcmp (SSDATA (value), "native"))
31127 dpyinfo->prefer_native_input = true;
31128 #endif
31129 }
31130 }
31131
31132
31133
31134
31135
31136
31137
31138 if (XSupportsLocale ())
31139 xim_initialize (dpyinfo, resource_name);
31140 #endif
31141
31142 #ifdef HAVE_X_SM
31143
31144
31145
31146 if (!dpyinfo->next && ! IS_DAEMON)
31147 x_session_initialize (dpyinfo);
31148 #endif
31149
31150 #if defined USE_CAIRO || defined HAVE_XRENDER
31151 x_extension_initialize (dpyinfo);
31152 #endif
31153
31154 #ifdef USE_TOOLKIT_SCROLL_BARS
31155 dpyinfo->protected_windows = xmalloc (sizeof (Lisp_Object) * 256);
31156 dpyinfo->n_protected_windows = 0;
31157 dpyinfo->protected_windows_max = 256;
31158 #endif
31159
31160 #ifdef HAVE_XFIXES
31161
31162
31163
31164 if (CONSP (Vx_fast_selection_list)
31165 && dpyinfo->xfixes_supported_p
31166 && dpyinfo->xfixes_major >= 1)
31167 {
31168 num_fast_selections = 0;
31169 tem = Vx_fast_selection_list;
31170
31171 FOR_EACH_TAIL_SAFE (tem)
31172 {
31173 if (!SYMBOLP (XCAR (tem)))
31174 continue;
31175
31176 num_fast_selections++;
31177 }
31178
31179 dpyinfo->n_monitored_selections = num_fast_selections;
31180 dpyinfo->selection_tracking_window
31181 = x_create_special_window (dpyinfo, dpyinfo->root_window);
31182 dpyinfo->monitored_selections
31183 = xmalloc (num_fast_selections
31184 * sizeof *dpyinfo->monitored_selections);
31185
31186 num_fast_selections = 0;
31187 tem = Vx_fast_selection_list;
31188
31189 FOR_EACH_TAIL_SAFE (tem)
31190 {
31191 lisp_name = XCAR (tem);
31192
31193 if (!SYMBOLP (lisp_name))
31194 continue;
31195
31196 selection_name = symbol_to_x_atom (dpyinfo, lisp_name);
31197 dpyinfo->monitored_selections[num_fast_selections++].name
31198 = selection_name;
31199 dpyinfo->monitored_selections[num_fast_selections - 1].owner
31200 = X_INVALID_WINDOW;
31201
31202
31203 XFixesSelectSelectionInput (dpyinfo->display,
31204 dpyinfo->selection_tracking_window,
31205 selection_name,
31206 (XFixesSetSelectionOwnerNotifyMask
31207 | XFixesSetSelectionOwnerNotifyMask
31208 | XFixesSelectionClientCloseNotifyMask));
31209 }
31210
31211 #ifdef USE_XCB
31212 selection_cookies = SAFE_ALLOCA (sizeof *selection_cookies
31213 * num_fast_selections);
31214 #endif
31215
31216
31217 for (i = 0; i < num_fast_selections; ++i)
31218 {
31219 #ifdef USE_XCB
31220 selection_cookies[i]
31221 = xcb_get_selection_owner (dpyinfo->xcb_connection,
31222 dpyinfo->monitored_selections[i].name);
31223 #else
31224 dpyinfo->monitored_selections[i].owner
31225 = XGetSelectionOwner (dpyinfo->display,
31226 dpyinfo->monitored_selections[i].name);
31227 #endif
31228 }
31229
31230 #ifdef USE_XCB
31231 for (i = 0; i < num_fast_selections; ++i)
31232 {
31233 selection_reply
31234 = xcb_get_selection_owner_reply (dpyinfo->xcb_connection,
31235 selection_cookies[i],
31236 &selection_error);
31237
31238 if (selection_reply)
31239 {
31240 dpyinfo->monitored_selections[i].owner
31241 = selection_reply->owner;
31242 free (selection_reply);
31243 }
31244 else if (selection_error)
31245 free (selection_error);
31246 }
31247 #endif
31248 }
31249 #endif
31250
31251 unblock_input ();
31252
31253 #if defined HAVE_XFIXES && defined USE_XCB
31254 SAFE_FREE ();
31255 #endif
31256 return dpyinfo;
31257 }
31258
31259
31260
31261
31262
31263
31264 static void
31265 x_delete_selection_requests (struct x_display_info *dpyinfo)
31266 {
31267 union buffered_input_event *event;
31268 int moved_events;
31269
31270 for (event = kbd_fetch_ptr; event != kbd_store_ptr;
31271 event = X_NEXT_KBD_EVENT (event))
31272 {
31273 if (event->kind == SELECTION_REQUEST_EVENT
31274 || event->kind == SELECTION_CLEAR_EVENT)
31275 {
31276 if (SELECTION_EVENT_DPYINFO (&event->sie) != dpyinfo)
31277 continue;
31278
31279
31280
31281
31282
31283
31284
31285 if (event < kbd_fetch_ptr)
31286 {
31287 memmove (kbd_buffer + 1, kbd_buffer,
31288 (event - kbd_buffer) * sizeof *kbd_buffer);
31289 kbd_buffer[0] = kbd_buffer[KBD_BUFFER_SIZE - 1];
31290 moved_events = kbd_buffer + KBD_BUFFER_SIZE - 1 - kbd_fetch_ptr;
31291 }
31292 else
31293 moved_events = event - kbd_fetch_ptr;
31294
31295 memmove (kbd_fetch_ptr + 1, kbd_fetch_ptr,
31296 moved_events * sizeof *kbd_fetch_ptr);
31297 kbd_fetch_ptr = X_NEXT_KBD_EVENT (kbd_fetch_ptr);
31298
31299
31300
31301 input_pending = false;
31302 }
31303 }
31304 }
31305
31306
31307
31308
31309 static void
31310 x_delete_display (struct x_display_info *dpyinfo)
31311 {
31312 struct terminal *t;
31313 struct color_name_cache_entry *color_entry, *next_color_entry;
31314 int i;
31315 struct x_selection_request_event *ie, *last, *temp;
31316
31317
31318
31319 for (t = terminal_list; t; t = t->next_terminal)
31320 if (t->type == output_x_window && t->display_info.x == dpyinfo)
31321 {
31322 #ifdef HAVE_X_SM
31323
31324 if (t->id == 1 && x_session_have_connection ())
31325 x_session_close ();
31326 #endif
31327 delete_terminal (t);
31328 break;
31329 }
31330
31331
31332
31333
31334 last = NULL;
31335
31336 for (ie = pending_selection_requests; ie; ie = ie->next)
31337 {
31338 again:
31339
31340 if (SELECTION_EVENT_DPYINFO (&ie->se) == dpyinfo)
31341 {
31342 if (last)
31343 last->next = ie->next;
31344
31345 temp = ie;
31346 ie = ie->next;
31347 xfree (temp);
31348
31349 goto again;
31350 }
31351
31352 last = ie;
31353 }
31354
31355
31356
31357 x_delete_selection_requests (dpyinfo);
31358
31359
31360 x_remove_selection_transfers (dpyinfo);
31361
31362 if (next_noop_dpyinfo == dpyinfo)
31363 next_noop_dpyinfo = dpyinfo->next;
31364
31365 if (mouse_click_timeout_display == dpyinfo)
31366 mouse_click_timeout_display = NULL;
31367
31368 if (x_display_list == dpyinfo)
31369 x_display_list = dpyinfo->next;
31370 else
31371 {
31372 struct x_display_info *tail;
31373
31374 for (tail = x_display_list; tail; tail = tail->next)
31375 if (tail->next == dpyinfo)
31376 tail->next = tail->next->next;
31377 }
31378
31379 for (i = 0; i < dpyinfo->color_names_size; ++i)
31380 {
31381 for (color_entry = dpyinfo->color_names[i];
31382 color_entry; color_entry = next_color_entry)
31383 {
31384 next_color_entry = color_entry->next;
31385
31386 xfree (color_entry->name);
31387 xfree (color_entry);
31388 }
31389 }
31390
31391 if (dpyinfo->net_supported_atoms)
31392 XFree (dpyinfo->net_supported_atoms);
31393
31394 xfree (dpyinfo->color_names);
31395 xfree (dpyinfo->color_names_length);
31396 xfree (dpyinfo->x_id_name);
31397 xfree (dpyinfo->x_dnd_atoms);
31398 xfree (dpyinfo->color_cells);
31399 #ifdef HAVE_XFIXES
31400 if (dpyinfo->monitored_selections)
31401 xfree (dpyinfo->monitored_selections);
31402 #endif
31403 #ifdef USE_TOOLKIT_SCROLL_BARS
31404 xfree (dpyinfo->protected_windows);
31405 #endif
31406 #ifdef HAVE_XINPUT2
31407 if (dpyinfo->supports_xi2)
31408 x_free_xi_devices (dpyinfo);
31409 #endif
31410 xfree (dpyinfo);
31411 }
31412
31413 #ifdef USE_X_TOOLKIT
31414
31415
31416
31417
31418
31419
31420 static void
31421 x_process_timeouts (struct atimer *timer)
31422 {
31423 block_input ();
31424 x_timeout_atimer_activated_flag = false;
31425 if (toolkit_scroll_bar_interaction || popup_activated ())
31426 {
31427 while (XtAppPending (Xt_app_con) & XtIMTimer)
31428 XtAppProcessEvent (Xt_app_con, XtIMTimer);
31429
31430 x_activate_timeout_atimer ();
31431 }
31432 unblock_input ();
31433 }
31434
31435
31436
31437
31438
31439
31440
31441
31442
31443 void
31444 x_activate_timeout_atimer (void)
31445 {
31446 block_input ();
31447 if (!x_timeout_atimer_activated_flag)
31448 {
31449 struct timespec interval = make_timespec (0, 100 * 1000 * 1000);
31450 start_atimer (ATIMER_RELATIVE, interval, x_process_timeouts, 0);
31451 x_timeout_atimer_activated_flag = true;
31452 }
31453 unblock_input ();
31454 }
31455
31456 #endif
31457
31458
31459
31460
31461 extern frame_parm_handler x_frame_parm_handlers[];
31462
31463 static struct redisplay_interface x_redisplay_interface =
31464 {
31465 x_frame_parm_handlers,
31466 gui_produce_glyphs,
31467 gui_write_glyphs,
31468 gui_insert_glyphs,
31469 gui_clear_end_of_line,
31470 x_scroll_run,
31471 x_after_update_window_line,
31472 NULL,
31473 NULL,
31474 x_flip_and_flush,
31475 gui_clear_window_mouse_face,
31476 gui_get_glyph_overhangs,
31477 gui_fix_overlapping_area,
31478 x_draw_fringe_bitmap,
31479 #ifdef USE_CAIRO
31480 x_cr_define_fringe_bitmap,
31481 x_cr_destroy_fringe_bitmap,
31482 #else
31483 0,
31484 0,
31485 #endif
31486 x_compute_glyph_string_overhangs,
31487 x_draw_glyph_string,
31488 x_define_frame_cursor,
31489 x_clear_frame_area,
31490 x_clear_under_internal_border,
31491 x_draw_window_cursor,
31492 x_draw_vertical_window_border,
31493 x_draw_window_divider,
31494 x_shift_glyphs_for_insert,
31495 x_show_hourglass,
31496 x_hide_hourglass,
31497 x_default_font_parameter
31498 };
31499
31500
31501
31502 void
31503 x_delete_terminal (struct terminal *terminal)
31504 {
31505 struct x_display_info *dpyinfo;
31506 struct frame *f;
31507 Lisp_Object tail, frame;
31508
31509 dpyinfo = terminal->display_info.x;
31510
31511
31512
31513 if (!terminal->name)
31514 return;
31515
31516 block_input ();
31517
31518
31519
31520
31521 FOR_EACH_FRAME (tail, frame)
31522 {
31523 f = XFRAME (frame);
31524
31525 if (FRAME_LIVE_P (f) && f->terminal == terminal)
31526
31527 delete_frame (frame, Qnoelisp);
31528 }
31529
31530 #ifdef HAVE_X_I18N
31531
31532
31533 xim_close_dpy (dpyinfo);
31534 #endif
31535
31536
31537 image_destroy_all_bitmaps (dpyinfo);
31538
31539
31540 xfree (dpyinfo->bitmaps);
31541
31542
31543 dpyinfo->bitmaps = NULL;
31544 dpyinfo->bitmaps_last = 0;
31545
31546
31547 if (dpyinfo->display)
31548 {
31549 XSetCloseDownMode (dpyinfo->display, DestroyAll);
31550
31551
31552 if (dpyinfo->scratch_cursor_gc)
31553 XFreeGC (dpyinfo->display, dpyinfo->scratch_cursor_gc);
31554
31555
31556
31557 if ((x_dnd_in_progress || x_dnd_waiting_for_finish)
31558 && dpyinfo->display == (x_dnd_waiting_for_finish
31559 ? x_dnd_finish_display
31560 : FRAME_X_DISPLAY (x_dnd_frame)))
31561 {
31562 x_dnd_last_seen_window = None;
31563 x_dnd_last_seen_toplevel = None;
31564 x_dnd_in_progress = false;
31565 x_dnd_waiting_for_finish = false;
31566
31567
31568
31569 if (x_dnd_use_toplevels)
31570 x_dnd_free_toplevels (false);
31571
31572 x_dnd_return_frame_object = NULL;
31573 x_dnd_movement_frame = NULL;
31574 x_dnd_wheel_frame = NULL;
31575 x_dnd_frame = NULL;
31576 }
31577
31578
31579
31580
31581
31582
31583
31584
31585
31586
31587
31588
31589
31590
31591
31592 #if false
31593 #ifdef HAVE_XRMSETDATABASE
31594 XrmSetDatabase (dpyinfo->display, NULL);
31595 #else
31596 dpyinfo->display->db = NULL;
31597 #endif
31598
31599
31600
31601 XrmDestroyDatabase (dpyinfo->rdb);
31602 #endif
31603 #ifdef USE_GTK
31604 xg_display_close (dpyinfo->display);
31605 #else
31606 #ifdef USE_X_TOOLKIT
31607 XtCloseDisplay (dpyinfo->display);
31608 #else
31609 XCloseDisplay (dpyinfo->display);
31610 #endif
31611 #endif
31612
31613
31614 dpyinfo->display = NULL;
31615 }
31616
31617
31618
31619
31620
31621 else if (dpyinfo->connection >= 0)
31622 emacs_close (dpyinfo->connection);
31623
31624
31625
31626
31627
31628 #ifdef HAVE_XKB
31629 if (dpyinfo->xkb_desc)
31630 XkbFreeKeyboard (dpyinfo->xkb_desc, XkbAllComponentsMask, True);
31631 #endif
31632
31633 if (dpyinfo->modmap)
31634 XFreeModifiermap (dpyinfo->modmap);
31635
31636
31637 delete_keyboard_wait_descriptor (dpyinfo->connection);
31638
31639 dpyinfo->connection = -1;
31640
31641 x_delete_display (dpyinfo);
31642 unblock_input ();
31643 }
31644
31645 #ifdef HAVE_XINPUT2
31646 static bool
31647 x_have_any_grab (struct x_display_info *dpyinfo)
31648 {
31649 int i;
31650
31651 if (!dpyinfo->supports_xi2)
31652 return false;
31653
31654 for (i = 0; i < dpyinfo->num_devices; ++i)
31655 {
31656 if (dpyinfo->devices[i].grab)
31657 return true;
31658 }
31659
31660 return false;
31661 }
31662 #endif
31663
31664
31665
31666
31667 static struct terminal *
31668 x_create_terminal (struct x_display_info *dpyinfo)
31669 {
31670 struct terminal *terminal;
31671
31672 terminal = create_terminal (output_x_window, &x_redisplay_interface);
31673
31674 terminal->display_info.x = dpyinfo;
31675 dpyinfo->terminal = terminal;
31676
31677
31678
31679 terminal->clear_frame_hook = x_clear_frame;
31680 terminal->ins_del_lines_hook = x_ins_del_lines;
31681 terminal->delete_glyphs_hook = x_delete_glyphs;
31682 terminal->ring_bell_hook = XTring_bell;
31683 terminal->toggle_invisible_pointer_hook = XTtoggle_invisible_pointer;
31684 terminal->update_begin_hook = x_update_begin;
31685 terminal->update_end_hook = x_update_end;
31686 terminal->read_socket_hook = XTread_socket;
31687 terminal->frame_up_to_date_hook = XTframe_up_to_date;
31688 #ifdef HAVE_XDBE
31689 terminal->buffer_flipping_unblocked_hook = XTbuffer_flipping_unblocked_hook;
31690 #endif
31691 terminal->defined_color_hook = x_defined_color;
31692 terminal->query_frame_background_color = x_query_frame_background_color;
31693 terminal->query_colors = x_query_colors;
31694 terminal->mouse_position_hook = XTmouse_position;
31695 terminal->get_focus_frame = x_get_focus_frame;
31696 terminal->focus_frame_hook = x_focus_frame;
31697 terminal->frame_rehighlight_hook = XTframe_rehighlight;
31698 terminal->frame_raise_lower_hook = XTframe_raise_lower;
31699 terminal->frame_visible_invisible_hook = x_make_frame_visible_invisible;
31700 terminal->fullscreen_hook = XTfullscreen_hook;
31701 terminal->iconify_frame_hook = x_iconify_frame;
31702 terminal->set_window_size_hook = x_set_window_size;
31703 terminal->set_frame_offset_hook = x_set_offset;
31704 terminal->set_frame_alpha_hook = x_set_frame_alpha;
31705 terminal->set_new_font_hook = x_new_font;
31706 terminal->set_bitmap_icon_hook = x_bitmap_icon;
31707 terminal->implicit_set_name_hook = x_implicitly_set_name;
31708 terminal->menu_show_hook = x_menu_show;
31709 #ifdef HAVE_EXT_MENU_BAR
31710 terminal->activate_menubar_hook = x_activate_menubar;
31711 #endif
31712 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
31713 terminal->popup_dialog_hook = xw_popup_dialog;
31714 #endif
31715 terminal->change_tab_bar_height_hook = x_change_tab_bar_height;
31716 #ifndef HAVE_EXT_TOOL_BAR
31717 terminal->change_tool_bar_height_hook = x_change_tool_bar_height;
31718 #endif
31719 terminal->set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
31720 terminal->set_horizontal_scroll_bar_hook = XTset_horizontal_scroll_bar;
31721 terminal->set_scroll_bar_default_width_hook = x_set_scroll_bar_default_width;
31722 terminal->set_scroll_bar_default_height_hook = x_set_scroll_bar_default_height;
31723 terminal->condemn_scroll_bars_hook = XTcondemn_scroll_bars;
31724 terminal->redeem_scroll_bar_hook = XTredeem_scroll_bar;
31725 terminal->judge_scroll_bars_hook = XTjudge_scroll_bars;
31726 terminal->get_string_resource_hook = x_get_string_resource;
31727 terminal->free_pixmap = x_free_pixmap;
31728 terminal->delete_frame_hook = x_destroy_window;
31729 terminal->delete_terminal_hook = x_delete_terminal;
31730 terminal->toolkit_position_hook = x_toolkit_position;
31731 #ifdef HAVE_XINPUT2
31732 terminal->any_grab_hook = x_have_any_grab;
31733 #endif
31734
31735
31736 return terminal;
31737 }
31738
31739 static void
31740 x_initialize (void)
31741 {
31742 baud_rate = 19200;
31743
31744 x_noop_count = 0;
31745 any_help_event_p = false;
31746 ignore_next_mouse_click_timeout = 0;
31747 mouse_click_timeout_display = NULL;
31748
31749 #ifdef USE_GTK
31750 current_count = -1;
31751 #endif
31752
31753
31754 Fset_input_interrupt_mode (Qt);
31755
31756 #if THREADS_ENABLED
31757
31758 if (XInitThreads () == 0)
31759 fputs ("Warning: An error occurred initializing X11 thread support!\n",
31760 stderr);
31761 #endif
31762
31763 #ifdef USE_X_TOOLKIT
31764 XtToolkitInitialize ();
31765
31766 Xt_app_con = XtCreateApplicationContext ();
31767
31768
31769
31770 XtAppSetTypeConverter (Xt_app_con,
31771 XtRString, XtRPixel, cvt_string_to_pixel,
31772 cvt_string_to_pixel_args,
31773 XtNumber (cvt_string_to_pixel_args),
31774 XtCacheByDisplay, cvt_pixel_dtor);
31775
31776 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
31777 #endif
31778
31779 #ifdef USE_TOOLKIT_SCROLL_BARS
31780 #ifndef USE_GTK
31781 xaw3d_arrow_scroll = False;
31782 xaw3d_pick_top = True;
31783 #endif
31784 #endif
31785
31786 #ifdef USE_CAIRO
31787 gui_init_fringe (&x_redisplay_interface);
31788 #endif
31789
31790
31791
31792 XSetErrorHandler (x_error_handler);
31793 XSetIOErrorHandler (x_io_error_quitter);
31794 }
31795
31796 #ifdef HAVE_X_I18N
31797
31798
31799
31800
31801 static void
31802 x_reset_conversion (struct frame *f)
31803 {
31804 char *string;
31805
31806 if (FRAME_XIC (f))
31807 {
31808 string = XmbResetIC (FRAME_XIC (f));
31809
31810
31811
31812
31813 if (string)
31814 XFree (string);
31815 }
31816 }
31817
31818
31819
31820 static struct textconv_interface text_conversion_interface =
31821 {
31822 x_reset_conversion,
31823 };
31824
31825 #endif
31826
31827 void
31828 init_xterm (void)
31829 {
31830 #ifndef HAVE_XINPUT2
31831
31832
31833
31834 #ifndef HAVE_GTK3
31835 xputenv ("GDK_CORE_DEVICE_EVENTS=1");
31836 #else
31837 gdk_disable_multidevice ();
31838 #endif
31839 #endif
31840
31841 #ifdef HAVE_X_I18N
31842 register_textconv_interface (&text_conversion_interface);
31843 #endif
31844 }
31845
31846 void
31847 mark_xterm (void)
31848 {
31849 Lisp_Object val;
31850 #if defined HAVE_XINPUT2 || defined USE_TOOLKIT_SCROLL_BARS \
31851 || defined HAVE_XRANDR || defined USE_GTK || defined HAVE_X_I18N
31852 struct x_display_info *dpyinfo;
31853 #if defined HAVE_XINPUT2 || defined USE_TOOLKIT_SCROLL_BARS
31854 int i;
31855 #endif
31856 #endif
31857
31858 if (x_dnd_return_frame_object)
31859 {
31860 XSETFRAME (val, x_dnd_return_frame_object);
31861 mark_object (val);
31862 }
31863
31864 if (x_dnd_movement_frame)
31865 {
31866 XSETFRAME (val, x_dnd_movement_frame);
31867 mark_object (val);
31868 }
31869
31870 if (x_dnd_wheel_frame)
31871 {
31872 XSETFRAME (val, x_dnd_wheel_frame);
31873 mark_object (val);
31874 }
31875
31876 #if defined HAVE_XINPUT2 || defined USE_TOOLKIT_SCROLL_BARS \
31877 || defined HAVE_XRANDR || defined USE_GTK || defined HAVE_X_I18N
31878 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
31879 {
31880 #ifdef HAVE_XINPUT2
31881 for (i = 0; i < dpyinfo->num_devices; ++i)
31882 mark_object (dpyinfo->devices[i].name);
31883 #endif
31884 #ifdef USE_TOOLKIT_SCROLL_BARS
31885 for (i = 0; i < dpyinfo->n_protected_windows; ++i)
31886 mark_object (dpyinfo->protected_windows[i]);
31887 #endif
31888 #if defined HAVE_XRANDR || defined USE_GTK
31889 mark_object (dpyinfo->last_monitor_attributes_list);
31890 #endif
31891 #if defined HAVE_X_I18N
31892 mark_object (dpyinfo->xim_coding);
31893 #endif
31894 }
31895 #endif
31896 }
31897
31898
31899
31900
31901
31902 void
31903 x_catch_errors_for_lisp (struct x_display_info *dpyinfo)
31904 {
31905 if (!x_fast_protocol_requests)
31906 x_catch_errors (dpyinfo->display);
31907 else
31908 x_ignore_errors_for_next_request (dpyinfo, 0);
31909 }
31910
31911 void
31912 x_check_errors_for_lisp (struct x_display_info *dpyinfo,
31913 const char *format)
31914 {
31915 if (!x_fast_protocol_requests)
31916 x_check_errors (dpyinfo->display, format);
31917 }
31918
31919 void
31920 x_uncatch_errors_for_lisp (struct x_display_info *dpyinfo)
31921 {
31922 if (!x_fast_protocol_requests)
31923 x_uncatch_errors ();
31924 else
31925 x_stop_ignoring_errors (dpyinfo);
31926 }
31927
31928
31929
31930
31931
31932 void
31933 x_preserve_selections (struct x_display_info *dpyinfo, Lisp_Object lost,
31934 Lisp_Object current_owner)
31935 {
31936 Lisp_Object tail, frame, new_owner;
31937 Time timestamp;
31938 Window *owners;
31939 Atom *names;
31940 ptrdiff_t nowners, counter;
31941 struct selection_input_event clear;
31942 #ifdef USE_XCB
31943 xcb_get_selection_owner_cookie_t *cookies;
31944 xcb_generic_error_t *error;
31945 xcb_get_selection_owner_reply_t *reply;
31946 #endif
31947
31948 new_owner = Qnil;
31949
31950 FOR_EACH_FRAME (tail, frame)
31951 {
31952 if (FRAME_X_P (XFRAME (frame))
31953 && !EQ (frame, current_owner)
31954 && FRAME_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
31955 {
31956 new_owner = frame;
31957 break;
31958 }
31959 }
31960
31961 tail = lost;
31962 nowners = 0;
31963
31964 FOR_EACH_TAIL_SAFE (tail)
31965 {
31966 Lisp_Object tem = XCAR (tail);
31967 ++nowners;
31968
31969
31970
31971 if (NILP (new_owner))
31972 CALLN (Frun_hook_with_args, Qx_lost_selection_functions,
31973 XCAR (tem));
31974 else
31975 {
31976 CONS_TO_INTEGER (XCAR (XCDR (XCDR (tem))), Time, timestamp);
31977
31978
31979
31980 x_own_selection (XCAR (tem), XCAR (XCDR (tem)),
31981 new_owner, XCAR (XCDR (XCDR (XCDR (XCDR (tem))))),
31982 timestamp);
31983 }
31984 }
31985
31986 if (!NILP (new_owner))
31987 {
31988 owners = alloca (sizeof *owners * nowners);
31989 names = alloca (sizeof *names * nowners);
31990 #ifdef USE_XCB
31991 cookies = alloca (sizeof *cookies * nowners);
31992 #endif
31993
31994 tail = lost;
31995 nowners = 0;
31996 counter = 0;
31997
31998 FOR_EACH_TAIL_SAFE (tail)
31999 {
32000 Lisp_Object tem = XCAR (tail);
32001
32002
32003
32004 names[counter++] = symbol_to_x_atom (dpyinfo, XCAR (tem));
32005
32006 #ifndef USE_XCB
32007 owners[nowners++] = XGetSelectionOwner (dpyinfo->display,
32008 names[counter - 1]);
32009 #else
32010 cookies[nowners++]
32011 = xcb_get_selection_owner (dpyinfo->xcb_connection,
32012 names[counter - 1]);
32013 }
32014
32015 nowners = 0;
32016 tail = lost;
32017
32018 FOR_EACH_TAIL_SAFE (tail)
32019 {
32020 Lisp_Object tem = XCAR (tail);
32021
32022 reply = xcb_get_selection_owner_reply (dpyinfo->xcb_connection,
32023 cookies[nowners++], &error);
32024 if (reply)
32025 owners[nowners - 1] = reply->owner;
32026 else
32027 owners[nowners - 1] = None;
32028
32029 free (reply ? (void *) reply : (void *) error);
32030 #endif
32031
32032 if (owners[nowners - 1] != FRAME_X_WINDOW (XFRAME (new_owner)))
32033 {
32034
32035
32036 CONS_TO_INTEGER (XCAR (XCDR (XCDR (tem))), Time, timestamp);
32037
32038 clear.kind = SELECTION_CLEAR_EVENT;
32039
32040 SELECTION_EVENT_DPYINFO (&clear) = dpyinfo;
32041 SELECTION_EVENT_SELECTION (&clear) = names[nowners - 1];
32042 SELECTION_EVENT_TIME (&clear) = timestamp;
32043
32044 x_handle_selection_event (&clear);
32045 }
32046 }
32047
32048 tail = lost;
32049 nowners = 0;
32050
32051 FOR_EACH_TAIL_SAFE (tail)
32052 {
32053 Lisp_Object tem = XCAR (tail);
32054
32055
32056
32057 if (owners[nowners++] != FRAME_X_WINDOW (XFRAME (new_owner)))
32058 CALLN (Frun_hook_with_args, Qx_lost_selection_functions,
32059 XCAR (tem));
32060 }
32061 }
32062 }
32063
32064
32065
32066
32067
32068
32069 Lisp_Object
32070 x_get_keyboard_modifiers (struct x_display_info *dpyinfo)
32071 {
32072
32073
32074
32075
32076 #ifdef HAVE_XKB
32077 if (!dpyinfo->xkb_desc && !dpyinfo->modmap)
32078 x_find_modifier_meanings (dpyinfo);
32079 #else
32080 if (!dpyinfo->modmap)
32081 x_find_modifier_meanings (dpyinfo);
32082 #endif
32083
32084 return list5 (make_uint (dpyinfo->hyper_mod_mask),
32085 make_uint (dpyinfo->super_mod_mask),
32086 make_uint (dpyinfo->alt_mod_mask),
32087 make_uint (dpyinfo->shift_lock_mask),
32088 make_uint (dpyinfo->meta_mod_mask));
32089 }
32090
32091 void
32092 syms_of_xterm (void)
32093 {
32094 x_error_message = NULL;
32095 PDUMPER_IGNORE (x_error_message);
32096
32097 x_dnd_monitors = Qnil;
32098 staticpro (&x_dnd_monitors);
32099
32100 x_dnd_action_symbol = Qnil;
32101 staticpro (&x_dnd_action_symbol);
32102
32103 x_dnd_selection_alias_cell = Fcons (Qnil, Qnil);
32104 staticpro (&x_dnd_selection_alias_cell);
32105
32106 x_dnd_unsupported_drop_data = Qnil;
32107 staticpro (&x_dnd_unsupported_drop_data);
32108
32109
32110 DEFSYM (Qconcat, "concat");
32111
32112 DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms");
32113 DEFSYM (Qlatin_1, "latin-1");
32114 DEFSYM (Qnow, "now");
32115 DEFSYM (Qx_dnd_targets_list, "x-dnd-targets-list");
32116 DEFSYM (Qx_auto_preserve_selections, "x-auto-preserve-selections");
32117 DEFSYM (Qexpose, "expose");
32118 DEFSYM (Qdont_save, "dont-save");
32119
32120 #ifdef USE_GTK
32121 xg_default_icon_file = build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg");
32122 staticpro (&xg_default_icon_file);
32123
32124 DEFSYM (Qx_gtk_map_stock, "x-gtk-map-stock");
32125 #endif
32126
32127 DEFVAR_BOOL ("x-use-underline-position-properties",
32128 x_use_underline_position_properties,
32129 doc:
32130
32131
32132
32133 );
32134 x_use_underline_position_properties = true;
32135 DEFSYM (Qx_use_underline_position_properties,
32136 "x-use-underline-position-properties");
32137
32138 DEFVAR_BOOL ("x-underline-at-descent-line",
32139 x_underline_at_descent_line,
32140 doc:
32141
32142
32143
32144
32145 );
32146 x_underline_at_descent_line = false;
32147 DEFSYM (Qx_underline_at_descent_line, "x-underline-at-descent-line");
32148
32149 DEFVAR_BOOL ("x-mouse-click-focus-ignore-position",
32150 x_mouse_click_focus_ignore_position,
32151 doc:
32152
32153
32154
32155
32156
32157
32158
32159
32160
32161 );
32162 x_mouse_click_focus_ignore_position = false;
32163
32164 DEFVAR_INT ("x-mouse-click-focus-ignore-time", x_mouse_click_focus_ignore_time,
32165 doc:
32166
32167
32168 );
32169 x_mouse_click_focus_ignore_time = 200;
32170
32171 DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
32172 doc:
32173
32174
32175
32176
32177
32178 );
32179 #ifdef USE_TOOLKIT_SCROLL_BARS
32180 #ifdef USE_MOTIF
32181 Vx_toolkit_scroll_bars = intern_c_string ("motif");
32182 #elif defined HAVE_XAW3D
32183 Vx_toolkit_scroll_bars = intern_c_string ("xaw3d");
32184 #elif USE_GTK
32185 Vx_toolkit_scroll_bars = intern_c_string ("gtk");
32186 #else
32187 Vx_toolkit_scroll_bars = intern_c_string ("xaw");
32188 #endif
32189 #else
32190 Vx_toolkit_scroll_bars = Qnil;
32191 #endif
32192
32193 DEFSYM (Qmodifier_value, "modifier-value");
32194 DEFSYM (Qctrl, "ctrl");
32195 Fput (Qctrl, Qmodifier_value, make_fixnum (ctrl_modifier));
32196 DEFSYM (Qalt, "alt");
32197 Fput (Qalt, Qmodifier_value, make_fixnum (alt_modifier));
32198 DEFSYM (Qhyper, "hyper");
32199 Fput (Qhyper, Qmodifier_value, make_fixnum (hyper_modifier));
32200 DEFSYM (Qmeta, "meta");
32201 Fput (Qmeta, Qmodifier_value, make_fixnum (meta_modifier));
32202 DEFSYM (Qsuper, "super");
32203 Fput (Qsuper, Qmodifier_value, make_fixnum (super_modifier));
32204 DEFSYM (QXdndSelection, "XdndSelection");
32205 DEFSYM (Qx_selection_alias_alist, "x-selection-alias-alist");
32206 DEFSYM (Qimitate_pager, "imitate-pager");
32207 DEFSYM (Qnewer_time, "newer-time");
32208 DEFSYM (Qraise_and_focus, "raise-and-focus");
32209 DEFSYM (Qreally_fast, "really-fast");
32210
32211 DEFVAR_LISP ("x-ctrl-keysym", Vx_ctrl_keysym,
32212 doc:
32213
32214
32215 );
32216 Vx_ctrl_keysym = Qnil;
32217
32218 DEFVAR_LISP ("x-alt-keysym", Vx_alt_keysym,
32219 doc:
32220
32221
32222 );
32223 Vx_alt_keysym = Qnil;
32224
32225 DEFVAR_LISP ("x-hyper-keysym", Vx_hyper_keysym,
32226 doc:
32227
32228
32229 );
32230 Vx_hyper_keysym = Qnil;
32231
32232 DEFVAR_LISP ("x-meta-keysym", Vx_meta_keysym,
32233 doc:
32234
32235
32236 );
32237 Vx_meta_keysym = Qnil;
32238
32239 DEFVAR_LISP ("x-super-keysym", Vx_super_keysym,
32240 doc:
32241
32242
32243 );
32244 Vx_super_keysym = Qnil;
32245
32246 DEFVAR_LISP ("x-wait-for-event-timeout", Vx_wait_for_event_timeout,
32247 doc:
32248
32249
32250
32251
32252
32253
32254 );
32255 Vx_wait_for_event_timeout = make_float (0.1);
32256
32257 DEFVAR_LISP ("x-keysym-table", Vx_keysym_table,
32258 doc: );
32259 Vx_keysym_table = make_hash_table (hashtest_eql, 900,
32260 DEFAULT_REHASH_SIZE,
32261 DEFAULT_REHASH_THRESHOLD,
32262 Qnil, false);
32263
32264 DEFVAR_BOOL ("x-frame-normalize-before-maximize",
32265 x_frame_normalize_before_maximize,
32266 doc:
32267
32268
32269
32270
32271
32272
32273
32274 );
32275 x_frame_normalize_before_maximize = false;
32276
32277 DEFVAR_BOOL ("x-gtk-use-window-move", x_gtk_use_window_move,
32278 doc:
32279
32280
32281
32282 );
32283 x_gtk_use_window_move = true;
32284
32285 DEFVAR_LISP ("x-scroll-event-delta-factor", Vx_scroll_event_delta_factor,
32286 doc:
32287
32288 );
32289 Vx_scroll_event_delta_factor = make_float (1.0);
32290
32291 DEFVAR_BOOL ("x-gtk-use-native-input", x_gtk_use_native_input,
32292 doc:
32293
32294 );
32295 x_gtk_use_native_input = false;
32296
32297 DEFVAR_LISP ("x-set-frame-visibility-more-laxly",
32298 x_set_frame_visibility_more_laxly,
32299 doc:
32300
32301
32302
32303
32304
32305
32306
32307
32308
32309 );
32310 x_set_frame_visibility_more_laxly = Qnil;
32311
32312 DEFVAR_BOOL ("x-input-grab-touch-events", x_input_grab_touch_events,
32313 doc:
32314
32315
32316
32317
32318
32319 );
32320 x_input_grab_touch_events = true;
32321
32322 DEFVAR_BOOL ("x-dnd-fix-motif-leave", x_dnd_fix_motif_leave,
32323 doc:
32324
32325
32326
32327 );
32328 x_dnd_fix_motif_leave = true;
32329
32330 DEFVAR_BOOL ("x-dnd-disable-motif-drag", x_dnd_disable_motif_drag,
32331 doc:
32332
32333
32334 );
32335 x_dnd_disable_motif_drag = false;
32336
32337 DEFVAR_LISP ("x-dnd-movement-function", Vx_dnd_movement_function,
32338 doc:
32339
32340
32341 );
32342 Vx_dnd_movement_function = Qnil;
32343
32344 DEFVAR_LISP ("x-dnd-wheel-function", Vx_dnd_wheel_function,
32345 doc:
32346
32347
32348
32349
32350 );
32351 Vx_dnd_wheel_function = Qnil;
32352
32353 DEFVAR_LISP ("x-dnd-unsupported-drop-function", Vx_dnd_unsupported_drop_function,
32354 doc:
32355
32356
32357
32358
32359
32360
32361
32362
32363
32364
32365
32366
32367
32368
32369
32370
32371 );
32372 Vx_dnd_unsupported_drop_function = Qnil;
32373
32374 DEFVAR_INT ("x-color-cache-bucket-size", x_color_cache_bucket_size,
32375 doc:
32376 );
32377 x_color_cache_bucket_size = 128;
32378
32379 DEFVAR_LISP ("x-dnd-targets-list", Vx_dnd_targets_list,
32380 doc:
32381
32382
32383 );
32384 Vx_dnd_targets_list = Qnil;
32385
32386 DEFVAR_LISP ("x-dnd-native-test-function", Vx_dnd_native_test_function,
32387 doc:
32388
32389
32390
32391
32392
32393
32394
32395
32396 );
32397 Vx_dnd_native_test_function = Qnil;
32398
32399 DEFVAR_BOOL ("x-dnd-preserve-selection-data", x_dnd_preserve_selection_data,
32400 doc:
32401
32402
32403 );
32404 x_dnd_preserve_selection_data = false;
32405
32406 DEFVAR_BOOL ("x-dnd-disable-motif-protocol", x_dnd_disable_motif_protocol,
32407 doc:
32408
32409 );
32410 x_dnd_disable_motif_protocol = false;
32411
32412 DEFVAR_BOOL ("x-dnd-use-unsupported-drop", x_dnd_use_unsupported_drop,
32413 doc:
32414
32415
32416 );
32417 x_dnd_use_unsupported_drop = true;
32418
32419 DEFVAR_BOOL ("x-fast-protocol-requests", x_fast_protocol_requests,
32420 doc:
32421
32422
32423
32424
32425 );
32426 x_fast_protocol_requests = false;
32427
32428 DEFVAR_LISP ("x-auto-preserve-selections", Vx_auto_preserve_selections,
32429 doc:
32430
32431
32432
32433
32434
32435 );
32436 Vx_auto_preserve_selections = list2 (QCLIPBOARD, QPRIMARY);
32437
32438 DEFVAR_LISP ("x-input-coding-system", Vx_input_coding_system,
32439 doc:
32440
32441
32442 );
32443 Vx_input_coding_system = Qnil;
32444
32445 DEFVAR_LISP ("x-input-coding-function", Vx_input_coding_function,
32446 doc:
32447
32448
32449 );
32450 Vx_input_coding_function = Qnil;
32451
32452 DEFVAR_LISP ("x-fast-selection-list", Vx_fast_selection_list,
32453 doc:
32454
32455
32456
32457
32458
32459
32460 );
32461
32462
32463 Vx_fast_selection_list = list1 (QCLIPBOARD);
32464
32465 DEFVAR_LISP ("x-allow-focus-stealing", Vx_allow_focus_stealing,
32466 doc:
32467
32468
32469
32470
32471
32472
32473
32474
32475
32476
32477
32478
32479
32480
32481
32482
32483
32484
32485
32486
32487
32488 );
32489 Vx_allow_focus_stealing = Qnewer_time;
32490
32491 DEFVAR_LISP ("x-use-fast-mouse-position", Vx_use_fast_mouse_position,
32492 doc:
32493
32494
32495
32496
32497
32498
32499
32500
32501
32502
32503 );
32504 Vx_use_fast_mouse_position = Qnil;
32505
32506 DEFVAR_LISP ("x-detect-server-trust", Vx_detect_server_trust,
32507 doc:
32508
32509
32510
32511
32512
32513 );
32514 Vx_detect_server_trust = Qnil;
32515
32516 DEFVAR_LISP ("x-lax-frame-positioning", Vx_lax_frame_positioning,
32517 doc:
32518
32519
32520
32521
32522
32523
32524
32525 );
32526 Vx_lax_frame_positioning = Qnil;
32527
32528 DEFVAR_LISP ("x-quit-keysym", Vx_quit_keysym,
32529 doc:
32530
32531
32532
32533
32534
32535
32536
32537
32538
32539
32540 );
32541 Vx_quit_keysym
32542 = list2 (Fcons (build_string ("The X.Org Foundation"),
32543 make_int (269025041)),
32544 Fcons (build_string ("The XFree86 Project, Inc."),
32545 make_int (269025041)));
32546 }