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_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_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_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 #include <config.h>
561 #include <stdlib.h>
562 #include <math.h>
563 #include <signal.h>
564
565 #include "lisp.h"
566 #include "blockinput.h"
567 #include "sysstdio.h"
568
569
570
571 #include "xterm.h"
572 #include <X11/cursorfont.h>
573
574 #ifdef USE_XCB
575 #include <xcb/xproto.h>
576 #include <xcb/xcb.h>
577 #include <xcb/xcb_aux.h>
578 #endif
579
580
581 #ifdef HAVE_XFIXES
582 #include <X11/extensions/Xfixes.h>
583 #endif
584
585 #ifdef HAVE_XDBE
586 #include <X11/extensions/Xdbe.h>
587 #endif
588
589 #ifdef HAVE_XINPUT2
590 #include <X11/extensions/XInput2.h>
591 #endif
592
593 #ifdef HAVE_XRANDR
594 #include <X11/extensions/Xrandr.h>
595 #endif
596
597 #ifdef HAVE_XSYNC
598 #include <X11/extensions/sync.h>
599 #endif
600
601 #ifdef HAVE_XINERAMA
602 #include <X11/extensions/Xinerama.h>
603 #endif
604
605 #ifdef HAVE_XCOMPOSITE
606 #include <X11/extensions/Xcomposite.h>
607 #endif
608
609 #ifdef HAVE_XSHAPE
610 #include <X11/extensions/shape.h>
611 #endif
612
613 #ifdef HAVE_XCB_SHAPE
614 #include <xcb/shape.h>
615 #endif
616
617
618
619 #ifndef makedev
620 #include <sys/types.h>
621 #endif
622
623 #include <sys/ioctl.h>
624
625 #include "systime.h"
626
627 #include <fcntl.h>
628 #include <errno.h>
629 #include <sys/stat.h>
630 #include <flexmember.h>
631 #include <c-ctype.h>
632 #include <byteswap.h>
633
634 #include "character.h"
635 #include "coding.h"
636 #include "composite.h"
637 #include "frame.h"
638 #include "dispextern.h"
639 #include "xwidget.h"
640 #include "fontset.h"
641 #include "termhooks.h"
642 #include "termopts.h"
643 #include "termchar.h"
644 #include "emacs-icon.h"
645 #include "buffer.h"
646 #include "window.h"
647 #include "keyboard.h"
648 #include "atimer.h"
649 #include "font.h"
650 #include "xsettings.h"
651 #include "sysselect.h"
652 #include "menu.h"
653 #include "pdumper.h"
654
655 #ifdef USE_X_TOOLKIT
656 #include <X11/Shell.h>
657 #include <X11/ShellP.h>
658 #endif
659
660 #include <unistd.h>
661
662 #ifdef USE_GTK
663 #include "gtkutil.h"
664 #ifdef HAVE_GTK3
665 #include <X11/Xproto.h>
666 #endif
667 #endif
668
669 #if defined (USE_LUCID) || defined (USE_MOTIF)
670 #include "../lwlib/xlwmenu.h"
671 #endif
672
673 #ifdef HAVE_XWIDGETS
674 #include <cairo-xlib.h>
675 #endif
676
677 #ifdef USE_MOTIF
678 #include <Xm/Xm.h>
679 #include <Xm/CascadeB.h>
680 #endif
681
682 #ifdef USE_X_TOOLKIT
683
684
685 #ifdef USE_TOOLKIT_SCROLL_BARS
686 #if defined USE_MOTIF
687 #include <Xm/ScrollBar.h>
688 #else
689
690 #ifdef HAVE_XAW3D
691 #include <X11/Xaw3d/Simple.h>
692 #include <X11/Xaw3d/Scrollbar.h>
693 #include <X11/Xaw3d/ThreeD.h>
694 #else
695 #include <X11/Xaw/Simple.h>
696 #include <X11/Xaw/Scrollbar.h>
697 #endif
698 #ifndef XtNpickTop
699 #define XtNpickTop "pickTop"
700 #endif
701 #endif
702 #endif
703
704 #endif
705
706 #ifdef USE_X_TOOLKIT
707 #include "widget.h"
708 #ifndef XtNinitialState
709 #define XtNinitialState "initialState"
710 #endif
711 #endif
712
713 #ifdef USE_GTK
714 #include <xgselect.h>
715 #endif
716
717 #include "bitmaps/gray.xbm"
718
719 #ifdef HAVE_XKB
720 #include <X11/XKBlib.h>
721 #endif
722
723
724
725
726 typedef int (*Emacs_XErrorHandler) (Display *, XErrorEvent *);
727 typedef int (*Emacs_XIOErrorHandler) (Display *);
728
729 #if defined USE_XCB && defined USE_CAIRO_XCB
730 #define USE_CAIRO_XCB_SURFACE
731 #endif
732
733
734 #ifdef USE_XIM
735 bool use_xim = true;
736 #else
737 bool use_xim = false;
738 #endif
739
740 #if XCB_SHAPE_MAJOR_VERSION > 1 \
741 || (XCB_SHAPE_MAJOR_VERSION == 1 && \
742 XCB_SHAPE_MINOR_VERSION >= 1)
743 #define HAVE_XCB_SHAPE_INPUT_RECTS
744 #endif
745
746 #ifdef USE_GTK
747
748
749
750
751
752
753
754 struct input_event xg_pending_quit_event = { .kind = NO_EVENT };
755 #endif
756
757
758
759
760 static bool any_help_event_p;
761
762
763
764
765 struct x_display_info *x_display_list;
766
767 #ifdef USE_X_TOOLKIT
768
769
770 XtAppContext Xt_app_con;
771 static String Xt_default_resources[] = {0};
772
773
774 static bool toolkit_scroll_bar_interaction;
775
776 #endif
777
778
779
780
781
782 static Time ignore_next_mouse_click_timeout;
783
784
785
786 static struct x_display_info *mouse_click_timeout_display;
787
788
789
790 static int x_noop_count;
791
792 #ifdef USE_GTK
793
794 static Lisp_Object xg_default_icon_file;
795 #endif
796
797 #ifdef HAVE_X_I18N
798
799 static char emacs_class[] = EMACS_CLASS;
800 #endif
801
802 #ifdef USE_GTK
803 static int current_count;
804 static int current_finish;
805 static struct input_event *current_hold_quit;
806 #endif
807
808 #ifdef HAVE_XINPUT2
809 #ifndef X_XIGrabDevice
810 #define X_XIGrabDevice 51
811 #endif
812
813 #ifndef X_XIUngrabDevice
814 #define X_XIUngrabDevice 52
815 #endif
816
817 #ifndef X_XIAllowEvents
818 #define X_XIAllowEvents 53
819 #endif
820 #endif
821
822
823
824 static int x_use_pending_selection_requests;
825
826
827 #define X_NEXT_KBD_EVENT(ptr) \
828 ((ptr) == kbd_buffer + KBD_BUFFER_SIZE - 1 ? kbd_buffer : (ptr) + 1)
829
830 static void x_push_selection_request (struct selection_input_event *);
831
832
833
834
835
836
837
838 void
839 x_defer_selection_requests (void)
840 {
841 union buffered_input_event *event;
842 bool between;
843
844 between = false;
845
846 block_input ();
847 if (!x_use_pending_selection_requests)
848 {
849 event = kbd_fetch_ptr;
850
851 while (event != kbd_store_ptr)
852 {
853 if (event->ie.kind == SELECTION_REQUEST_EVENT
854 || event->ie.kind == SELECTION_CLEAR_EVENT)
855 {
856 x_push_selection_request (&event->sie);
857
858
859 SELECTION_EVENT_DPYINFO (&event->sie) = NULL;
860
861
862
863
864
865 if (!between)
866 {
867 kbd_fetch_ptr = X_NEXT_KBD_EVENT (event);
868
869
870
871 input_pending = false;
872 }
873 }
874 else
875 between = true;
876
877 event = X_NEXT_KBD_EVENT (event);
878 }
879 }
880
881 x_use_pending_selection_requests++;
882 unblock_input ();
883 }
884
885 static void
886 x_release_selection_requests (void)
887 {
888 x_use_pending_selection_requests--;
889 }
890
891 void
892 x_release_selection_requests_and_flush (void)
893 {
894 x_release_selection_requests ();
895
896 if (!x_use_pending_selection_requests)
897 x_handle_pending_selection_requests ();
898 }
899
900 struct x_selection_request_event
901 {
902
903 struct selection_input_event se;
904
905
906 struct x_selection_request_event *next;
907 };
908
909
910
911
912
913 struct x_selection_request_event *pending_selection_requests;
914
915 struct x_atom_ref
916 {
917
918 const char *name;
919
920
921 int offset;
922 };
923
924
925
926 static const struct x_atom_ref x_atom_refs[] =
927 {
928 #define ATOM_REFS_INIT(string, member) \
929 { string, offsetof (struct x_display_info, member) },
930 ATOM_REFS_INIT ("WM_PROTOCOLS", Xatom_wm_protocols)
931 ATOM_REFS_INIT ("WM_TAKE_FOCUS", Xatom_wm_take_focus)
932 ATOM_REFS_INIT ("WM_SAVE_YOURSELF", Xatom_wm_save_yourself)
933 ATOM_REFS_INIT ("WM_DELETE_WINDOW", Xatom_wm_delete_window)
934 ATOM_REFS_INIT ("WM_CHANGE_STATE", Xatom_wm_change_state)
935 ATOM_REFS_INIT ("WM_STATE", Xatom_wm_state)
936 ATOM_REFS_INIT ("WM_CONFIGURE_DENIED", Xatom_wm_configure_denied)
937 ATOM_REFS_INIT ("WM_MOVED", Xatom_wm_window_moved)
938 ATOM_REFS_INIT ("WM_CLIENT_LEADER", Xatom_wm_client_leader)
939 ATOM_REFS_INIT ("WM_TRANSIENT_FOR", Xatom_wm_transient_for)
940 ATOM_REFS_INIT ("Editres", Xatom_editres)
941 ATOM_REFS_INIT ("CLIPBOARD", Xatom_CLIPBOARD)
942 ATOM_REFS_INIT ("TIMESTAMP", Xatom_TIMESTAMP)
943 ATOM_REFS_INIT ("TEXT", Xatom_TEXT)
944 ATOM_REFS_INIT ("COMPOUND_TEXT", Xatom_COMPOUND_TEXT)
945 ATOM_REFS_INIT ("UTF8_STRING", Xatom_UTF8_STRING)
946 ATOM_REFS_INIT ("DELETE", Xatom_DELETE)
947 ATOM_REFS_INIT ("MULTIPLE", Xatom_MULTIPLE)
948 ATOM_REFS_INIT ("INCR", Xatom_INCR)
949 ATOM_REFS_INIT ("_EMACS_TMP_", Xatom_EMACS_TMP)
950 ATOM_REFS_INIT ("_EMACS_SERVER_TIME_PROP", Xatom_EMACS_SERVER_TIME_PROP)
951 ATOM_REFS_INIT ("TARGETS", Xatom_TARGETS)
952 ATOM_REFS_INIT ("NULL", Xatom_NULL)
953 ATOM_REFS_INIT ("ATOM", Xatom_ATOM)
954 ATOM_REFS_INIT ("ATOM_PAIR", Xatom_ATOM_PAIR)
955 ATOM_REFS_INIT ("CLIPBOARD_MANAGER", Xatom_CLIPBOARD_MANAGER)
956 ATOM_REFS_INIT ("_XEMBED_INFO", Xatom_XEMBED_INFO)
957 ATOM_REFS_INIT ("_MOTIF_WM_HINTS", Xatom_MOTIF_WM_HINTS)
958 ATOM_REFS_INIT ("_EMACS_DRAG_ATOM", Xatom_EMACS_DRAG_ATOM)
959
960 ATOM_REFS_INIT ("PIXEL_SIZE", Xatom_PIXEL_SIZE)
961 ATOM_REFS_INIT ("AVERAGE_WIDTH", Xatom_AVERAGE_WIDTH)
962 ATOM_REFS_INIT ("_MULE_BASELINE_OFFSET", Xatom_MULE_BASELINE_OFFSET)
963 ATOM_REFS_INIT ("_MULE_RELATIVE_COMPOSE", Xatom_MULE_RELATIVE_COMPOSE)
964 ATOM_REFS_INIT ("_MULE_DEFAULT_ASCENT", Xatom_MULE_DEFAULT_ASCENT)
965
966 ATOM_REFS_INIT ("DONE", Xatom_DONE)
967 ATOM_REFS_INIT ("PAGE", Xatom_PAGE)
968 ATOM_REFS_INIT ("_EMACS_SCROLLBAR", Xatom_Scrollbar)
969 ATOM_REFS_INIT ("_EMACS_HORIZONTAL_SCROLLBAR", Xatom_Horizontal_Scrollbar)
970 ATOM_REFS_INIT ("_XEMBED", Xatom_XEMBED)
971
972 ATOM_REFS_INIT ("_NET_WM_STATE", Xatom_net_wm_state)
973 ATOM_REFS_INIT ("_NET_WM_STATE_FULLSCREEN", Xatom_net_wm_state_fullscreen)
974 ATOM_REFS_INIT ("_NET_WM_STATE_MAXIMIZED_HORZ",
975 Xatom_net_wm_state_maximized_horz)
976 ATOM_REFS_INIT ("_NET_WM_STATE_MAXIMIZED_VERT",
977 Xatom_net_wm_state_maximized_vert)
978 ATOM_REFS_INIT ("_NET_WM_STATE_STICKY", Xatom_net_wm_state_sticky)
979 ATOM_REFS_INIT ("_NET_WM_STATE_SHADED", Xatom_net_wm_state_shaded)
980 ATOM_REFS_INIT ("_NET_WM_STATE_HIDDEN", Xatom_net_wm_state_hidden)
981 ATOM_REFS_INIT ("_NET_WM_WINDOW_TYPE", Xatom_net_window_type)
982 ATOM_REFS_INIT ("_NET_WM_WINDOW_TYPE_TOOLTIP",
983 Xatom_net_window_type_tooltip)
984 ATOM_REFS_INIT ("_NET_WM_ICON_NAME", Xatom_net_wm_icon_name)
985 ATOM_REFS_INIT ("_NET_WM_NAME", Xatom_net_wm_name)
986 ATOM_REFS_INIT ("_NET_SUPPORTED", Xatom_net_supported)
987 ATOM_REFS_INIT ("_NET_SUPPORTING_WM_CHECK", Xatom_net_supporting_wm_check)
988 ATOM_REFS_INIT ("_NET_WM_WINDOW_OPACITY", Xatom_net_wm_window_opacity)
989 ATOM_REFS_INIT ("_NET_ACTIVE_WINDOW", Xatom_net_active_window)
990 ATOM_REFS_INIT ("_NET_FRAME_EXTENTS", Xatom_net_frame_extents)
991 ATOM_REFS_INIT ("_NET_CURRENT_DESKTOP", Xatom_net_current_desktop)
992 ATOM_REFS_INIT ("_NET_WORKAREA", Xatom_net_workarea)
993 ATOM_REFS_INIT ("_NET_WM_SYNC_REQUEST", Xatom_net_wm_sync_request)
994 ATOM_REFS_INIT ("_NET_WM_SYNC_REQUEST_COUNTER", Xatom_net_wm_sync_request_counter)
995 ATOM_REFS_INIT ("_NET_WM_SYNC_FENCES", Xatom_net_wm_sync_fences)
996 ATOM_REFS_INIT ("_NET_WM_BYPASS_COMPOSITOR", Xatom_net_wm_bypass_compositor)
997 ATOM_REFS_INIT ("_NET_WM_FRAME_DRAWN", Xatom_net_wm_frame_drawn)
998 ATOM_REFS_INIT ("_NET_WM_FRAME_TIMINGS", Xatom_net_wm_frame_timings)
999 ATOM_REFS_INIT ("_NET_WM_USER_TIME", Xatom_net_wm_user_time)
1000 ATOM_REFS_INIT ("_NET_WM_USER_TIME_WINDOW", Xatom_net_wm_user_time_window)
1001 ATOM_REFS_INIT ("_NET_CLIENT_LIST_STACKING", Xatom_net_client_list_stacking)
1002
1003 ATOM_REFS_INIT ("SM_CLIENT_ID", Xatom_SM_CLIENT_ID)
1004 ATOM_REFS_INIT ("_XSETTINGS_SETTINGS", Xatom_xsettings_prop)
1005 ATOM_REFS_INIT ("MANAGER", Xatom_xsettings_mgr)
1006 ATOM_REFS_INIT ("_NET_WM_STATE_SKIP_TASKBAR", Xatom_net_wm_state_skip_taskbar)
1007 ATOM_REFS_INIT ("_NET_WM_STATE_ABOVE", Xatom_net_wm_state_above)
1008 ATOM_REFS_INIT ("_NET_WM_STATE_BELOW", Xatom_net_wm_state_below)
1009 ATOM_REFS_INIT ("_NET_WM_OPAQUE_REGION", Xatom_net_wm_opaque_region)
1010 ATOM_REFS_INIT ("_NET_WM_PING", Xatom_net_wm_ping)
1011 ATOM_REFS_INIT ("_NET_WM_PID", Xatom_net_wm_pid)
1012 #ifdef HAVE_XKB
1013 ATOM_REFS_INIT ("Meta", Xatom_Meta)
1014 ATOM_REFS_INIT ("Super", Xatom_Super)
1015 ATOM_REFS_INIT ("Hyper", Xatom_Hyper)
1016 ATOM_REFS_INIT ("ShiftLock", Xatom_ShiftLock)
1017 ATOM_REFS_INIT ("Alt", Xatom_Alt)
1018 #endif
1019
1020 ATOM_REFS_INIT ("XdndAware", Xatom_XdndAware)
1021 ATOM_REFS_INIT ("XdndSelection", Xatom_XdndSelection)
1022 ATOM_REFS_INIT ("XdndTypeList", Xatom_XdndTypeList)
1023 ATOM_REFS_INIT ("XdndActionCopy", Xatom_XdndActionCopy)
1024 ATOM_REFS_INIT ("XdndActionMove", Xatom_XdndActionMove)
1025 ATOM_REFS_INIT ("XdndActionLink", Xatom_XdndActionLink)
1026 ATOM_REFS_INIT ("XdndActionAsk", Xatom_XdndActionAsk)
1027 ATOM_REFS_INIT ("XdndActionPrivate", Xatom_XdndActionPrivate)
1028 ATOM_REFS_INIT ("XdndActionList", Xatom_XdndActionList)
1029 ATOM_REFS_INIT ("XdndActionDescription", Xatom_XdndActionDescription)
1030 ATOM_REFS_INIT ("XdndProxy", Xatom_XdndProxy)
1031 ATOM_REFS_INIT ("XdndEnter", Xatom_XdndEnter)
1032 ATOM_REFS_INIT ("XdndPosition", Xatom_XdndPosition)
1033 ATOM_REFS_INIT ("XdndStatus", Xatom_XdndStatus)
1034 ATOM_REFS_INIT ("XdndLeave", Xatom_XdndLeave)
1035 ATOM_REFS_INIT ("XdndDrop", Xatom_XdndDrop)
1036 ATOM_REFS_INIT ("XdndFinished", Xatom_XdndFinished)
1037
1038 ATOM_REFS_INIT ("XdndDirectSave0", Xatom_XdndDirectSave0)
1039 ATOM_REFS_INIT ("XdndActionDirectSave", Xatom_XdndActionDirectSave)
1040 ATOM_REFS_INIT ("text/plain", Xatom_text_plain)
1041
1042 ATOM_REFS_INIT ("_MOTIF_DRAG_WINDOW", Xatom_MOTIF_DRAG_WINDOW)
1043 ATOM_REFS_INIT ("_MOTIF_DRAG_TARGETS", Xatom_MOTIF_DRAG_TARGETS)
1044 ATOM_REFS_INIT ("_MOTIF_DRAG_AND_DROP_MESSAGE",
1045 Xatom_MOTIF_DRAG_AND_DROP_MESSAGE)
1046 ATOM_REFS_INIT ("_MOTIF_DRAG_INITIATOR_INFO",
1047 Xatom_MOTIF_DRAG_INITIATOR_INFO)
1048 ATOM_REFS_INIT ("_MOTIF_DRAG_RECEIVER_INFO",
1049 Xatom_MOTIF_DRAG_RECEIVER_INFO)
1050 ATOM_REFS_INIT ("XmTRANSFER_SUCCESS", Xatom_XmTRANSFER_SUCCESS)
1051 ATOM_REFS_INIT ("XmTRANSFER_FAILURE", Xatom_XmTRANSFER_FAILURE)
1052
1053 ATOM_REFS_INIT ("DndProtocol", Xatom_DndProtocol)
1054 ATOM_REFS_INIT ("_DND_PROTOCOL", Xatom_DND_PROTOCOL)
1055 };
1056
1057 enum
1058 {
1059 X_EVENT_NORMAL,
1060 X_EVENT_GOTO_OUT,
1061 X_EVENT_DROP
1062 };
1063
1064 enum xembed_info
1065 {
1066 XEMBED_MAPPED = 1 << 0
1067 };
1068
1069 enum xembed_message
1070 {
1071 XEMBED_EMBEDDED_NOTIFY = 0,
1072 XEMBED_WINDOW_ACTIVATE = 1,
1073 XEMBED_WINDOW_DEACTIVATE = 2,
1074 XEMBED_REQUEST_FOCUS = 3,
1075 XEMBED_FOCUS_IN = 4,
1076 XEMBED_FOCUS_OUT = 5,
1077 XEMBED_FOCUS_NEXT = 6,
1078 XEMBED_FOCUS_PREV = 7,
1079
1080 XEMBED_MODALITY_ON = 10,
1081 XEMBED_MODALITY_OFF = 11,
1082 XEMBED_REGISTER_ACCELERATOR = 12,
1083 XEMBED_UNREGISTER_ACCELERATOR = 13,
1084 XEMBED_ACTIVATE_ACCELERATOR = 14
1085 };
1086
1087 static bool x_alloc_nearest_color_1 (Display *, Colormap, XColor *);
1088 static void x_raise_frame (struct frame *);
1089 static void x_lower_frame (struct frame *);
1090 static int x_io_error_quitter (Display *);
1091 static struct terminal *x_create_terminal (struct x_display_info *);
1092 static void x_frame_rehighlight (struct x_display_info *);
1093
1094 static void x_clip_to_row (struct window *, struct glyph_row *,
1095 enum glyph_row_area, GC);
1096 static struct scroll_bar *x_window_to_scroll_bar (Display *, Window, int);
1097 static struct frame *x_window_to_frame (struct x_display_info *, int);
1098 static void x_scroll_bar_report_motion (struct frame **, Lisp_Object *,
1099 enum scroll_bar_part *,
1100 Lisp_Object *, Lisp_Object *,
1101 Time *);
1102 static void x_horizontal_scroll_bar_report_motion (struct frame **, Lisp_Object *,
1103 enum scroll_bar_part *,
1104 Lisp_Object *, Lisp_Object *,
1105 Time *);
1106 static bool x_handle_net_wm_state (struct frame *, const XPropertyEvent *);
1107 static void x_check_fullscreen (struct frame *);
1108 static void x_check_expected_move (struct frame *, int, int);
1109 static void x_sync_with_move (struct frame *, int, int, bool);
1110 #ifndef HAVE_XINPUT2
1111 static int handle_one_xevent (struct x_display_info *,
1112 const XEvent *, int *,
1113 struct input_event *);
1114 #else
1115 static int handle_one_xevent (struct x_display_info *,
1116 XEvent *, int *,
1117 struct input_event *);
1118 #endif
1119 #if ! (defined USE_X_TOOLKIT || defined USE_MOTIF) && defined USE_GTK
1120 static int x_dispatch_event (XEvent *, Display *);
1121 #endif
1122 static void x_wm_set_window_state (struct frame *, int);
1123 static void x_wm_set_icon_pixmap (struct frame *, ptrdiff_t);
1124 static void x_initialize (void);
1125
1126 static bool x_get_current_wm_state (struct frame *, Window, int *, bool *, bool *);
1127 static void x_update_opaque_region (struct frame *, XEvent *);
1128
1129 #ifdef HAVE_X_I18N
1130 static int x_filter_event (struct x_display_info *, XEvent *);
1131 #endif
1132 static void x_clean_failable_requests (struct x_display_info *);
1133
1134 static struct frame *x_tooltip_window_to_frame (struct x_display_info *,
1135 Window, bool *);
1136 static Window x_get_window_below (Display *, Window, int, int, int *, int *);
1137 static void x_set_input_focus (struct x_display_info *, Window, Time);
1138
1139 #ifndef USE_TOOLKIT_SCROLL_BARS
1140 static void x_scroll_bar_redraw (struct scroll_bar *);
1141 #endif
1142
1143
1144
1145
1146 bool x_dnd_in_progress;
1147
1148
1149 struct frame *x_dnd_frame;
1150
1151
1152
1153
1154 struct frame *x_dnd_finish_frame;
1155
1156
1157
1158
1159
1160 bool x_dnd_waiting_for_finish;
1161
1162
1163
1164
1165 static bool x_dnd_run_unsupported_drop_function;
1166
1167
1168 static Time x_dnd_unsupported_drop_time;
1169
1170
1171 static Window x_dnd_unsupported_drop_window;
1172
1173
1174 static Lisp_Object x_dnd_unsupported_drop_data;
1175
1176
1177
1178 static bool x_dnd_update_tooltip;
1179
1180
1181 static Lisp_Object x_dnd_monitors;
1182
1183
1184
1185 static Display *x_dnd_finish_display;
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196 static int x_dnd_waiting_for_motif_finish;
1197
1198
1199
1200 struct x_display_info *x_dnd_waiting_for_motif_finish_display;
1201
1202
1203
1204
1205
1206 static bool x_dnd_xm_use_help;
1207
1208
1209 static bool x_dnd_motif_setup_p;
1210
1211
1212 static Atom x_dnd_motif_atom;
1213
1214
1215
1216 static Window x_dnd_pending_finish_target;
1217
1218
1219 static int x_dnd_waiting_for_finish_proto;
1220
1221
1222
1223 static bool x_dnd_allow_current_frame;
1224
1225
1226
1227 static bool x_dnd_init_type_lists;
1228
1229
1230
1231
1232
1233
1234 static int x_dnd_return_frame;
1235
1236
1237
1238 static struct frame *x_dnd_return_frame_object;
1239
1240
1241
1242
1243 static Window x_dnd_last_seen_window;
1244
1245
1246 static Window x_dnd_last_seen_toplevel;
1247
1248
1249
1250 static Window x_dnd_end_window;
1251
1252
1253
1254 static int x_dnd_last_protocol_version;
1255
1256
1257
1258 static bool x_dnd_last_window_is_frame;
1259
1260
1261
1262
1263
1264
1265
1266 static int x_dnd_last_motif_style;
1267
1268
1269
1270 static Time x_dnd_selection_timestamp;
1271
1272
1273 static Window x_dnd_mouse_rect_target;
1274
1275
1276
1277 static XRectangle x_dnd_mouse_rect;
1278
1279
1280
1281 static Window x_dnd_waiting_for_status_window;
1282
1283
1284
1285 static XEvent x_dnd_pending_send_position;
1286
1287
1288 static bool x_dnd_pending_send_position_button;
1289
1290
1291 static int x_dnd_pending_send_position_root_x;
1292
1293
1294 static int x_dnd_pending_send_position_root_y;
1295
1296
1297
1298 static bool x_dnd_need_send_drop;
1299
1300
1301 static int x_dnd_send_drop_proto;
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313 static Atom x_dnd_action;
1314
1315
1316
1317 static Lisp_Object x_dnd_action_symbol;
1318
1319
1320
1321
1322 static Atom x_dnd_wanted_action;
1323
1324
1325
1326 static uint8_t x_dnd_motif_operations;
1327
1328
1329
1330 static uint8_t x_dnd_first_motif_operation;
1331
1332
1333 static Atom *x_dnd_targets;
1334
1335
1336 static int x_dnd_n_targets;
1337
1338
1339
1340
1341
1342 static XWindowAttributes x_dnd_old_window_attrs;
1343
1344
1345
1346 static bool x_dnd_unwind_flag;
1347
1348
1349 static struct frame *x_dnd_movement_frame;
1350
1351
1352
1353 static int x_dnd_movement_x, x_dnd_movement_y;
1354
1355
1356 static struct frame *x_dnd_wheel_frame;
1357
1358
1359 static int x_dnd_wheel_x, x_dnd_wheel_y;
1360
1361
1362 static int x_dnd_wheel_button;
1363
1364
1365 static int x_dnd_wheel_state;
1366
1367
1368 static Time x_dnd_wheel_time;
1369
1370 #ifdef HAVE_XKB
1371
1372 static unsigned int x_dnd_keyboard_state;
1373 #endif
1374
1375
1376
1377 static sigjmp_buf x_dnd_disconnect_handler;
1378
1379
1380
1381 static bool x_dnd_inside_handle_one_xevent;
1382
1383
1384
1385 static int x_dnd_recursion_depth;
1386
1387
1388
1389
1390 static Lisp_Object x_dnd_selection_alias_cell;
1391
1392
1393 static int x_dnd_last_tooltip_x, x_dnd_last_tooltip_y;
1394
1395
1396 static bool x_dnd_last_tooltip_valid;
1397
1398 #ifdef HAVE_XINPUT2
1399
1400
1401 static int x_dnd_pointer_device;
1402
1403
1404 static int x_dnd_keyboard_device;
1405 #endif
1406
1407
1408
1409 struct x_client_list_window
1410 {
1411
1412 Window window;
1413
1414
1415 Display *dpy;
1416
1417
1418 int x, y;
1419
1420
1421 int width, height;
1422
1423
1424
1425
1426 long previous_event_mask;
1427
1428
1429 unsigned long wm_state;
1430
1431
1432 struct x_client_list_window *next;
1433
1434
1435 int frame_extents_left;
1436 int frame_extents_right;
1437 int frame_extents_top;
1438 int frame_extents_bottom;
1439
1440 #ifdef HAVE_XSHAPE
1441
1442 int border_width;
1443
1444
1445 int n_input_rects;
1446
1447
1448 XRectangle *input_rects;
1449
1450
1451 XRectangle *bounding_rects;
1452
1453
1454 int n_bounding_rects;
1455 #endif
1456
1457
1458 uint8_t xm_protocol_style;
1459
1460
1461 bool mapped_p;
1462 };
1463
1464
1465 static struct x_client_list_window *x_dnd_toplevels;
1466
1467
1468
1469 static bool x_dnd_use_toplevels;
1470
1471
1472
1473
1474
1475 static volatile bool *xm_drag_window_error;
1476
1477 typedef enum xm_byte_order
1478 {
1479 XM_BYTE_ORDER_LSB_FIRST = 'l',
1480 XM_BYTE_ORDER_MSB_FIRST = 'B',
1481 #ifndef WORDS_BIGENDIAN
1482 XM_BYTE_ORDER_CUR_FIRST = 'l',
1483 #else
1484 XM_BYTE_ORDER_CUR_FIRST = 'B',
1485 #endif
1486 } xm_byte_order;
1487
1488 #ifdef ENABLE_CHECKING
1489
1490 #define SWAPCARD32(l) \
1491 { \
1492 struct { unsigned t : 32; } bit32; \
1493 char n, *tp = (char *) &bit32; \
1494 bit32.t = l; \
1495 n = tp[0]; tp[0] = tp[3]; tp[3] = n; \
1496 n = tp[1]; tp[1] = tp[2]; tp[2] = n; \
1497 l = bit32.t; \
1498 }
1499
1500 #define SWAPCARD16(s) \
1501 { \
1502 struct { unsigned t : 16; } bit16; \
1503 char n, *tp = (char *) &bit16; \
1504 bit16.t = s; \
1505 n = tp[0]; tp[0] = tp[1]; tp[1] = n; \
1506 s = bit16.t; \
1507 }
1508
1509 #else
1510 #define SWAPCARD32(l) ((l) = bswap_32 (l))
1511 #define SWAPCARD16(l) ((l) = bswap_16 (l))
1512 #endif
1513
1514 typedef struct xm_targets_table_header
1515 {
1516 uint8_t byte_order;
1517 uint8_t protocol;
1518
1519 uint16_t target_list_count;
1520 uint32_t total_data_size;
1521 } xm_targets_table_header;
1522
1523 typedef struct xm_targets_table_rec
1524 {
1525 uint16_t n_targets;
1526 uint32_t targets[FLEXIBLE_ARRAY_MEMBER];
1527 } xm_targets_table_rec;
1528
1529 typedef struct xm_drop_start_message
1530 {
1531 uint8_t reason;
1532 uint8_t byte_order;
1533
1534 uint16_t side_effects;
1535 uint32_t timestamp;
1536 uint16_t x, y;
1537 uint32_t index_atom;
1538 uint32_t source_window;
1539 } xm_drop_start_message;
1540
1541 typedef struct xm_drop_start_reply
1542 {
1543 uint8_t reason;
1544 uint8_t byte_order;
1545
1546 uint16_t side_effects;
1547 uint16_t better_x;
1548 uint16_t better_y;
1549 } xm_drop_start_reply;
1550
1551 typedef struct xm_drag_initiator_info
1552 {
1553 uint8_t byteorder;
1554 uint8_t protocol;
1555
1556 uint16_t table_index;
1557 uint32_t selection;
1558 } xm_drag_initiator_info;
1559
1560 typedef struct xm_drag_receiver_info
1561 {
1562 uint8_t byteorder;
1563 uint8_t protocol;
1564
1565 uint8_t protocol_style;
1566 uint8_t unspecified0;
1567 uint32_t unspecified1;
1568 uint32_t unspecified2;
1569 uint32_t unspecified3;
1570 } xm_drag_receiver_info;
1571
1572 typedef struct xm_top_level_enter_message
1573 {
1574 uint8_t reason;
1575 uint8_t byteorder;
1576
1577 uint16_t zero;
1578 uint32_t timestamp;
1579 uint32_t source_window;
1580 uint32_t index_atom;
1581 } xm_top_level_enter_message;
1582
1583 typedef struct xm_drag_motion_message
1584 {
1585 uint8_t reason;
1586 uint8_t byteorder;
1587
1588 uint16_t side_effects;
1589 uint32_t timestamp;
1590 uint16_t x, y;
1591 } xm_drag_motion_message;
1592
1593 typedef struct xm_drag_motion_reply
1594 {
1595 uint8_t reason;
1596 uint8_t byte_order;
1597
1598 uint16_t side_effects;
1599 uint32_t timestamp;
1600 uint16_t better_x;
1601 uint16_t better_y;
1602 } xm_drag_motion_reply;
1603
1604 typedef struct xm_top_level_leave_message
1605 {
1606 uint8_t reason;
1607 uint8_t byteorder;
1608
1609 uint16_t zero;
1610 uint32_t timestamp;
1611 uint32_t source_window;
1612 } xm_top_level_leave_message;
1613
1614 #define XM_DRAG_SIDE_EFFECT(op, site, ops, act) \
1615 ((op) | ((site) << 4) | ((ops) << 8) | ((act) << 12))
1616
1617
1618
1619 #define XM_DRAG_SIDE_EFFECT_OPERATION(effect) ((effect) & 0xf)
1620 #define XM_DRAG_SIDE_EFFECT_SITE_STATUS(effect) (((effect) & 0xf0) >> 4)
1621
1622 #define XM_DRAG_SIDE_EFFECT_DROP_ACTION(effect) (((effect) & 0xf000) >> 12)
1623
1624 enum xm_drag_operation
1625 {
1626 XM_DRAG_NOOP = 0,
1627 XM_DRAG_MOVE = (1L << 0),
1628 XM_DRAG_COPY = (1L << 1),
1629 XM_DRAG_LINK = (1L << 2),
1630 XM_DRAG_LINK_REC = 3,
1631 };
1632
1633 #define XM_DRAG_OPERATION_IS_LINK(op) ((op) == XM_DRAG_LINK \
1634 || (op) == XM_DRAG_LINK_REC)
1635
1636 enum xm_drag_action
1637 {
1638 XM_DROP_ACTION_DROP = 0,
1639 XM_DROP_ACTION_DROP_HELP = 1,
1640 XM_DROP_ACTION_DROP_CANCEL = 2,
1641 };
1642
1643 #define XM_DRAG_REASON(originator, code) ((code) | ((originator) << 7))
1644 #define XM_DRAG_REASON_ORIGINATOR(reason) (((reason) & 0x80) ? 1 : 0)
1645 #define XM_DRAG_REASON_CODE(reason) ((reason) & 0x7f)
1646
1647 enum xm_drag_reason
1648 {
1649 XM_DRAG_REASON_DROP_START = 5,
1650 XM_DRAG_REASON_TOP_LEVEL_ENTER = 0,
1651 XM_DRAG_REASON_TOP_LEVEL_LEAVE = 1,
1652 XM_DRAG_REASON_DRAG_MOTION = 2,
1653 };
1654
1655 enum xm_drag_originator
1656 {
1657 XM_DRAG_ORIGINATOR_INITIATOR = 0,
1658 XM_DRAG_ORIGINATOR_RECEIVER = 1,
1659 };
1660
1661 enum xm_drag_style
1662 {
1663
1664
1665 XM_DRAG_STYLE_NONE = 0,
1666 XM_DRAG_STYLE_DROP_ONLY = 1,
1667 XM_DRAG_STYLE_DROP_ONLY_REC = 3,
1668 XM_DRAG_STYLE_DYNAMIC = 5,
1669 XM_DRAG_STYLE_DYNAMIC_REC = 2,
1670 XM_DRAG_STYLE_DYNAMIC_REC1 = 4,
1671 };
1672
1673 #define XM_DRAG_STYLE_IS_DROP_ONLY(n) ((n) == XM_DRAG_STYLE_DROP_ONLY \
1674 || (n) == XM_DRAG_STYLE_DROP_ONLY_REC)
1675 #define XM_DRAG_STYLE_IS_DYNAMIC(n) ((n) == XM_DRAG_STYLE_DYNAMIC \
1676 || (n) == XM_DRAG_STYLE_DYNAMIC_REC \
1677 || (n) == XM_DRAG_STYLE_DYNAMIC_REC1)
1678
1679 enum xm_drop_site_status
1680 {
1681 XM_DROP_SITE_VALID = 3,
1682 XM_DROP_SITE_INVALID = 2,
1683 XM_DROP_SITE_NONE = 1,
1684 };
1685
1686
1687
1688 #define XM_DRAG_PROTOCOL_VERSION 0
1689
1690 static uint8_t
1691 xm_side_effect_from_action (struct x_display_info *dpyinfo, Atom action)
1692 {
1693 if (action == dpyinfo->Xatom_XdndActionCopy)
1694 return XM_DRAG_COPY;
1695 else if (action == dpyinfo->Xatom_XdndActionMove)
1696 return XM_DRAG_MOVE;
1697 else if (action == dpyinfo->Xatom_XdndActionLink)
1698 return XM_DRAG_LINK;
1699 else if (action == dpyinfo->Xatom_XdndActionAsk)
1700 return x_dnd_first_motif_operation;
1701
1702 return XM_DRAG_NOOP;
1703 }
1704
1705 static uint8_t
1706 xm_operations_from_actions (struct x_display_info *dpyinfo,
1707 Atom *ask_actions, int n_ask_actions)
1708 {
1709 int i;
1710 uint8_t flags;
1711
1712 flags = 0;
1713
1714 for (i = 0; i < n_ask_actions; ++i)
1715 {
1716 if (ask_actions[i] == dpyinfo->Xatom_XdndActionCopy)
1717 flags |= XM_DRAG_COPY;
1718 else if (ask_actions[i] == dpyinfo->Xatom_XdndActionMove)
1719 flags |= XM_DRAG_MOVE;
1720 else if (ask_actions[i] == dpyinfo->Xatom_XdndActionLink)
1721 flags |= XM_DRAG_LINK;
1722 }
1723
1724 return flags;
1725 }
1726
1727 static int
1728 xm_read_targets_table_header (uint8_t *bytes, ptrdiff_t length,
1729 xm_targets_table_header *header_return,
1730 xm_byte_order *byteorder_return)
1731 {
1732 if (length < 8)
1733 return -1;
1734
1735 header_return->byte_order = *byteorder_return = *(bytes++);
1736 header_return->protocol = *(bytes++);
1737
1738 header_return->target_list_count = *(uint16_t *) bytes;
1739 header_return->total_data_size = *(uint32_t *) (bytes + 2);
1740
1741 if (header_return->byte_order != XM_BYTE_ORDER_CUR_FIRST)
1742 {
1743 SWAPCARD16 (header_return->target_list_count);
1744 SWAPCARD32 (header_return->total_data_size);
1745 }
1746
1747 header_return->byte_order = XM_BYTE_ORDER_CUR_FIRST;
1748
1749 return 8;
1750 }
1751
1752 static xm_targets_table_rec *
1753 xm_read_targets_table_rec (uint8_t *bytes, ptrdiff_t length,
1754 xm_byte_order byteorder)
1755 {
1756 uint16_t nitems, i;
1757 xm_targets_table_rec *rec;
1758
1759 if (length < 2)
1760 return NULL;
1761
1762 nitems = *(uint16_t *) bytes;
1763
1764 if (byteorder != XM_BYTE_ORDER_CUR_FIRST)
1765 SWAPCARD16 (nitems);
1766
1767 if (length < 2 + nitems * 4)
1768 return NULL;
1769
1770 rec = xmalloc (FLEXSIZEOF (struct xm_targets_table_rec,
1771 targets, nitems * 4));
1772 rec->n_targets = nitems;
1773
1774 for (i = 0; i < nitems; ++i)
1775 {
1776 rec->targets[i] = ((uint32_t *) (bytes + 2))[i];
1777
1778 if (byteorder != XM_BYTE_ORDER_CUR_FIRST)
1779 SWAPCARD32 (rec->targets[i]);
1780 }
1781
1782 return rec;
1783 }
1784
1785 static int
1786 xm_find_targets_table_idx (xm_targets_table_header *header,
1787 xm_targets_table_rec **recs,
1788 Atom *sorted_targets, int ntargets)
1789 {
1790 int j;
1791 uint16_t i;
1792 uint32_t *targets;
1793
1794 targets = alloca (sizeof *targets * ntargets);
1795
1796 for (j = 0; j < ntargets; ++j)
1797 targets[j] = sorted_targets[j];
1798
1799 for (i = 0; i < header->target_list_count; ++i)
1800 {
1801 if (recs[i]->n_targets == ntargets
1802 && !memcmp (&recs[i]->targets, targets,
1803 sizeof *targets * ntargets))
1804 return i;
1805 }
1806
1807 return -1;
1808 }
1809
1810 static int
1811 x_atoms_compare (const void *a, const void *b)
1812 {
1813 return *(Atom *) a - *(Atom *) b;
1814 }
1815
1816 static void
1817 xm_write_targets_table (Display *dpy, Window wdesc,
1818 Atom targets_table_atom,
1819 xm_targets_table_header *header,
1820 xm_targets_table_rec **recs)
1821 {
1822 uint8_t *header_buffer, *ptr, *rec_buffer;
1823 ptrdiff_t rec_buffer_size;
1824 uint16_t i, j;
1825
1826 header_buffer = alloca (8);
1827 ptr = header_buffer;
1828
1829 *(header_buffer++) = header->byte_order;
1830 *(header_buffer++) = header->protocol;
1831 *((uint16_t *) header_buffer) = header->target_list_count;
1832 *((uint32_t *) (header_buffer + 2)) = header->total_data_size;
1833
1834 rec_buffer = xmalloc (600);
1835 rec_buffer_size = 600;
1836
1837 XChangeProperty (dpy, wdesc, targets_table_atom,
1838 targets_table_atom, 8, PropModeReplace,
1839 (unsigned char *) ptr, 8);
1840
1841 for (i = 0; i < header->target_list_count; ++i)
1842 {
1843 if (rec_buffer_size < 2 + recs[i]->n_targets * 4)
1844 {
1845 rec_buffer_size = 2 + recs[i]->n_targets * 4;
1846 rec_buffer = xrealloc (rec_buffer, rec_buffer_size);
1847 }
1848
1849 *((uint16_t *) rec_buffer) = recs[i]->n_targets;
1850
1851 for (j = 0; j < recs[i]->n_targets; ++j)
1852 ((uint32_t *) (rec_buffer + 2))[j] = recs[i]->targets[j];
1853
1854 XChangeProperty (dpy, wdesc, targets_table_atom,
1855 targets_table_atom, 8, PropModeAppend,
1856 (unsigned char *) rec_buffer,
1857 2 + recs[i]->n_targets * 4);
1858 }
1859
1860 xfree (rec_buffer);
1861 }
1862
1863 static void
1864 xm_write_drag_initiator_info (Display *dpy, Window wdesc,
1865 Atom prop_name, Atom type_name,
1866 xm_drag_initiator_info *info)
1867 {
1868 uint8_t *buf;
1869
1870 buf = alloca (8);
1871 buf[0] = info->byteorder;
1872 buf[1] = info->protocol;
1873
1874 if (info->byteorder != XM_BYTE_ORDER_CUR_FIRST)
1875 {
1876 SWAPCARD16 (info->table_index);
1877 SWAPCARD16 (info->selection);
1878 }
1879
1880 *((uint16_t *) (buf + 2)) = info->table_index;
1881 *((uint32_t *) (buf + 4)) = info->selection;
1882
1883 XChangeProperty (dpy, wdesc, prop_name, type_name, 8,
1884 PropModeReplace, (unsigned char *) buf, 8);
1885 }
1886
1887 static int
1888 xm_drag_window_error_handler (Display *display, XErrorEvent *event)
1889 {
1890 if (xm_drag_window_error)
1891 *xm_drag_window_error = true;
1892
1893 return 0;
1894 }
1895
1896 static _Noreturn int
1897 xm_drag_window_io_error_handler (Display *dpy)
1898 {
1899
1900
1901 siglongjmp (x_dnd_disconnect_handler, 1);
1902 }
1903
1904
1905
1906 static bool
1907 x_special_window_exists_p (struct x_display_info *dpyinfo,
1908 Window window)
1909 {
1910 bool rc;
1911
1912 x_catch_errors (dpyinfo->display);
1913 XSelectInput (dpyinfo->display, window,
1914 StructureNotifyMask);
1915 rc = !x_had_errors_p (dpyinfo->display);
1916 x_uncatch_errors_after_check ();
1917
1918 return rc;
1919 }
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941 static Window
1942 xm_get_drag_window_1 (struct x_display_info *dpyinfo)
1943 {
1944 Atom actual_type;
1945 int rc, actual_format;
1946 unsigned long nitems, bytes_remaining;
1947 unsigned char *tmp_data = NULL;
1948 Window drag_window;
1949 XSetWindowAttributes attrs;
1950 Display *temp_display;
1951 Emacs_XErrorHandler old_handler;
1952 Emacs_XIOErrorHandler old_io_handler;
1953
1954
1955
1956 volatile bool error;
1957
1958 drag_window = None;
1959 rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window,
1960 dpyinfo->Xatom_MOTIF_DRAG_WINDOW,
1961 0, 1, False, XA_WINDOW, &actual_type,
1962 &actual_format, &nitems, &bytes_remaining,
1963 &tmp_data) == Success;
1964
1965 if (rc && actual_type == XA_WINDOW
1966 && actual_format == 32 && nitems == 1
1967 && tmp_data)
1968 {
1969 drag_window = *(Window *) tmp_data;
1970
1971
1972
1973
1974 rc = x_special_window_exists_p (dpyinfo, drag_window);
1975
1976 if (!rc)
1977 drag_window = None;
1978 }
1979
1980 if (tmp_data)
1981 XFree (tmp_data);
1982
1983 if (drag_window == None)
1984 {
1985 block_input ();
1986 old_io_handler = XSetIOErrorHandler (xm_drag_window_io_error_handler);
1987
1988 if (sigsetjmp (x_dnd_disconnect_handler, 1))
1989 {
1990 XSetIOErrorHandler (old_io_handler);
1991 unblock_input ();
1992
1993 return None;
1994 }
1995
1996 unrequest_sigio ();
1997 temp_display = XOpenDisplay (XDisplayString (dpyinfo->display));
1998 request_sigio ();
1999
2000 if (!temp_display)
2001 {
2002 XSetIOErrorHandler (old_io_handler);
2003 unblock_input ();
2004
2005 return None;
2006 }
2007
2008 error = false;
2009 xm_drag_window_error = &error;
2010
2011 XSetCloseDownMode (temp_display, RetainPermanent);
2012 old_handler = XSetErrorHandler (xm_drag_window_error_handler);
2013
2014 attrs.override_redirect = True;
2015 drag_window = XCreateWindow (temp_display, DefaultRootWindow (temp_display),
2016 -1, -1, 1, 1, 0, CopyFromParent, InputOnly,
2017 CopyFromParent, CWOverrideRedirect, &attrs);
2018
2019
2020 XSync (temp_display, False);
2021
2022
2023
2024 if (error)
2025 {
2026 XSetCloseDownMode (temp_display, DestroyAll);
2027 drag_window = None;
2028 }
2029
2030 xm_drag_window_error = NULL;
2031
2032
2033
2034 unrequest_sigio ();
2035 XCloseDisplay (temp_display);
2036 request_sigio ();
2037
2038 XSetErrorHandler (old_handler);
2039 XSetIOErrorHandler (old_io_handler);
2040
2041
2042
2043
2044 if (!x_special_window_exists_p (dpyinfo, drag_window))
2045 drag_window = None;
2046 unblock_input ();
2047
2048 if (drag_window != None)
2049 {
2050 XGrabServer (dpyinfo->display);
2051
2052 x_catch_errors (dpyinfo->display);
2053 tmp_data = NULL;
2054
2055 rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window,
2056 dpyinfo->Xatom_MOTIF_DRAG_WINDOW,
2057 0, 1, False, XA_WINDOW, &actual_type,
2058 &actual_format, &nitems, &bytes_remaining,
2059 &tmp_data) == Success;
2060
2061 if (rc && actual_type == XA_WINDOW
2062 && actual_format == 32 && nitems == 1
2063 && tmp_data
2064 && x_special_window_exists_p (dpyinfo,
2065 *(Window *) tmp_data))
2066 {
2067
2068
2069 XKillClient (dpyinfo->display, drag_window);
2070 drag_window = *(Window *) tmp_data;
2071 }
2072 else
2073 XChangeProperty (dpyinfo->display, dpyinfo->root_window,
2074 dpyinfo->Xatom_MOTIF_DRAG_WINDOW,
2075 XA_WINDOW, 32, PropModeReplace,
2076 (unsigned char *) &drag_window, 1);
2077
2078 if (tmp_data)
2079 XFree (tmp_data);
2080
2081 if (x_had_errors_p (dpyinfo->display))
2082 drag_window = None;
2083 x_uncatch_errors ();
2084
2085 XUngrabServer (dpyinfo->display);
2086 }
2087 }
2088
2089 return drag_window;
2090 }
2091
2092 static Window
2093 xm_get_drag_window (struct x_display_info *dpyinfo)
2094 {
2095 if (dpyinfo->motif_drag_window != None)
2096 return dpyinfo->motif_drag_window;
2097
2098 dpyinfo->motif_drag_window = xm_get_drag_window_1 (dpyinfo);
2099 return dpyinfo->motif_drag_window;
2100 }
2101
2102 static int
2103 xm_setup_dnd_targets (struct x_display_info *dpyinfo,
2104 Atom *targets, int ntargets)
2105 {
2106 Window drag_window;
2107 Atom *targets_sorted, actual_type;
2108 unsigned char *tmp_data = NULL;
2109 unsigned long nitems, bytes_remaining;
2110 int rc, actual_format, idx;
2111 bool had_errors;
2112 xm_targets_table_header header;
2113 xm_targets_table_rec **recs UNINIT;
2114 xm_byte_order byteorder;
2115 uint8_t *data;
2116 ptrdiff_t total_bytes, total_items, i;
2117 uint32_t size, target_count;
2118
2119 retry_drag_window:
2120
2121 drag_window = xm_get_drag_window (dpyinfo);
2122
2123 if (drag_window == None || ntargets > 64)
2124 return -1;
2125
2126 targets_sorted = xmalloc (sizeof *targets * ntargets);
2127 memcpy (targets_sorted, targets,
2128 sizeof *targets * ntargets);
2129 qsort (targets_sorted, ntargets,
2130 sizeof (Atom), x_atoms_compare);
2131
2132 XGrabServer (dpyinfo->display);
2133
2134 x_catch_errors (dpyinfo->display);
2135 rc = XGetWindowProperty (dpyinfo->display, drag_window,
2136 dpyinfo->Xatom_MOTIF_DRAG_TARGETS,
2137 0L, LONG_MAX, False,
2138 dpyinfo->Xatom_MOTIF_DRAG_TARGETS,
2139 &actual_type, &actual_format, &nitems,
2140 &bytes_remaining, &tmp_data) == Success;
2141 had_errors = x_had_errors_p (dpyinfo->display);
2142 x_uncatch_errors_after_check ();
2143
2144
2145
2146 if (had_errors)
2147 {
2148 dpyinfo->motif_drag_window = None;
2149 XUngrabServer (dpyinfo->display);
2150
2151 goto retry_drag_window;
2152 }
2153
2154 if (rc && tmp_data && !bytes_remaining
2155 && actual_type == dpyinfo->Xatom_MOTIF_DRAG_TARGETS
2156 && actual_format == 8)
2157 {
2158 data = (uint8_t *) tmp_data;
2159 if (xm_read_targets_table_header ((uint8_t *) tmp_data,
2160 nitems, &header,
2161 &byteorder) == 8)
2162 {
2163 data += 8;
2164 nitems -= 8;
2165 total_bytes = 0;
2166 total_items = 0;
2167
2168
2169
2170 recs = xmalloc ((header.target_list_count + 1)
2171 * sizeof *recs);
2172
2173 while (total_items < header.target_list_count)
2174 {
2175 recs[total_items] = xm_read_targets_table_rec (data + total_bytes,
2176 nitems, byteorder);
2177
2178 if (!recs[total_items])
2179 break;
2180
2181 total_bytes += 2 + recs[total_items]->n_targets * 4;
2182 nitems -= 2 + recs[total_items]->n_targets * 4;
2183 total_items++;
2184 }
2185
2186 if (header.target_list_count != total_items
2187 || header.total_data_size != 8 + total_bytes)
2188 {
2189 for (i = 0; i < total_items; ++i)
2190 {
2191 if (recs[i])
2192 xfree (recs[i]);
2193 else
2194 break;
2195 }
2196
2197 xfree (recs);
2198
2199 rc = false;
2200 }
2201 }
2202 else
2203 rc = false;
2204 }
2205 else
2206 rc = false;
2207
2208 if (tmp_data)
2209 XFree (tmp_data);
2210
2211
2212
2213
2214 if (!rc)
2215 {
2216 header.byte_order = XM_BYTE_ORDER_CUR_FIRST;
2217 header.protocol = XM_DRAG_PROTOCOL_VERSION;
2218 header.target_list_count = 1;
2219 header.total_data_size = 8 + 2 + ntargets * 4;
2220
2221 recs = xmalloc (sizeof *recs);
2222 recs[0] = xmalloc (FLEXSIZEOF (struct xm_targets_table_rec,
2223 targets, ntargets * 4));
2224
2225 recs[0]->n_targets = ntargets;
2226
2227 for (i = 0; i < ntargets; ++i)
2228 recs[0]->targets[i] = targets_sorted[i];
2229
2230 idx = 0;
2231 }
2232 else
2233 {
2234 idx = xm_find_targets_table_idx (&header, recs,
2235 targets_sorted,
2236 ntargets);
2237
2238 if (idx == -1)
2239 {
2240 target_count = header.target_list_count;
2241 rc = false;
2242
2243 if (INT_ADD_WRAPV (header.target_list_count, 1,
2244 &header.target_list_count)
2245 || INT_MULTIPLY_WRAPV (ntargets, 4, &size)
2246 || INT_ADD_WRAPV (header.total_data_size, size,
2247 &header.total_data_size)
2248 || INT_ADD_WRAPV (header.total_data_size, 2,
2249 &header.total_data_size))
2250 {
2251
2252
2253
2254
2255
2256 for (i = 0; i < target_count; ++i)
2257 xfree (recs[i]);
2258
2259 xfree (recs);
2260
2261 header.byte_order = XM_BYTE_ORDER_CUR_FIRST;
2262 header.protocol = XM_DRAG_PROTOCOL_VERSION;
2263 header.target_list_count = 1;
2264 header.total_data_size = 8 + 2 + ntargets * 4;
2265
2266 recs = xmalloc (sizeof *recs);
2267 recs[0] = xmalloc (FLEXSIZEOF (struct xm_targets_table_rec,
2268 targets, ntargets * 4));
2269
2270 recs[0]->n_targets = ntargets;
2271
2272 for (i = 0; i < ntargets; ++i)
2273 recs[0]->targets[i] = targets_sorted[i];
2274
2275 idx = 0;
2276 }
2277 else
2278 {
2279 recs[header.target_list_count - 1]
2280 = xmalloc (FLEXSIZEOF (struct xm_targets_table_rec,
2281 targets, ntargets * 4));
2282 recs[header.target_list_count - 1]->n_targets = ntargets;
2283
2284 for (i = 0; i < ntargets; ++i)
2285 recs[header.target_list_count - 1]->targets[i] = targets_sorted[i];
2286
2287 idx = header.target_list_count - 1;
2288 }
2289 }
2290 }
2291
2292 if (!rc)
2293 {
2294
2295
2296
2297
2298
2299 header.protocol = XM_DRAG_PROTOCOL_VERSION;
2300
2301 x_catch_errors (dpyinfo->display);
2302 xm_write_targets_table (dpyinfo->display, drag_window,
2303 dpyinfo->Xatom_MOTIF_DRAG_TARGETS,
2304 &header, recs);
2305
2306
2307 if (x_had_errors_p (dpyinfo->display))
2308 idx = -1;
2309 x_uncatch_errors_after_check ();
2310 }
2311
2312 XUngrabServer (dpyinfo->display);
2313
2314 for (i = 0; i < header.target_list_count; ++i)
2315 xfree (recs[i]);
2316
2317 xfree (recs);
2318 xfree (targets_sorted);
2319
2320 return idx;
2321 }
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332 static Atom
2333 xm_get_drag_atom_1 (struct x_display_info *dpyinfo,
2334 struct frame *source_frame)
2335 {
2336 Atom actual_type, *atoms, atom;
2337 unsigned long nitems, bytes_remaining;
2338 unsigned char *tmp_data;
2339 int rc, actual_format;
2340 unsigned long i;
2341 char *buffer;
2342 Window owner;
2343
2344
2345 XGrabServer (dpyinfo->display);
2346
2347 rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window,
2348 dpyinfo->Xatom_EMACS_DRAG_ATOM,
2349 0, LONG_MAX, False, XA_ATOM, &actual_type,
2350 &actual_format, &nitems, &bytes_remaining,
2351 &tmp_data);
2352 atom = None;
2353
2354
2355 i = 0;
2356
2357 if (rc == Success
2358 && actual_format == 32 && nitems
2359 && actual_type == XA_ATOM)
2360 {
2361 atoms = (Atom *) tmp_data;
2362
2363 x_catch_errors (dpyinfo->display);
2364
2365 for (i = 0; i < nitems; ++i)
2366 {
2367 owner = XGetSelectionOwner (dpyinfo->display, atoms[i]);
2368
2369 if (!x_had_errors_p (dpyinfo->display)
2370 && (owner == None
2371
2372
2373
2374
2375 || x_window_to_frame (dpyinfo, owner)))
2376 {
2377 atom = atoms[i];
2378
2379 break;
2380 }
2381 }
2382
2383 x_uncatch_errors ();
2384 }
2385
2386 if (tmp_data)
2387 XFree (tmp_data);
2388
2389 buffer = dpyinfo->motif_drag_atom_name;
2390
2391 if (atom)
2392 {
2393 sprintf (buffer, "_EMACS_ATOM_%lu", i + 1);
2394 XSetSelectionOwner (dpyinfo->display, atom,
2395 FRAME_X_WINDOW (source_frame),
2396 dpyinfo->last_user_time);
2397
2398
2399
2400 if (XGetSelectionOwner (dpyinfo->display, atom)
2401 != FRAME_X_WINDOW (source_frame))
2402 atom = None;
2403 }
2404
2405 while (!atom)
2406 {
2407 sprintf (buffer, "_EMACS_ATOM_%lu", nitems + 1);
2408 atom = XInternAtom (dpyinfo->display, buffer, False);
2409
2410 XSetSelectionOwner (dpyinfo->display, atom,
2411 FRAME_X_WINDOW (source_frame),
2412 dpyinfo->last_user_time);
2413
2414 XChangeProperty (dpyinfo->display, dpyinfo->root_window,
2415 dpyinfo->Xatom_EMACS_DRAG_ATOM, XA_ATOM, 32,
2416 (rc != Success
2417 || (actual_format != 32
2418 || actual_type != XA_ATOM)
2419 ? PropModeReplace : PropModeAppend),
2420 (unsigned char *) &atom, 1);
2421
2422 actual_format = 32;
2423 actual_type = XA_ATOM;
2424 rc = Success;
2425 nitems += 1;
2426
2427
2428
2429 if (XGetSelectionOwner (dpyinfo->display, atom)
2430 != FRAME_X_WINDOW (source_frame))
2431 atom = None;
2432 }
2433
2434 dpyinfo->motif_drag_atom_time = dpyinfo->last_user_time;
2435 dpyinfo->motif_drag_atom_owner = source_frame;
2436
2437 XUngrabServer (dpyinfo->display);
2438 return atom;
2439 }
2440
2441 static Atom
2442 xm_get_drag_atom (struct x_display_info *dpyinfo)
2443 {
2444 Atom atom;
2445
2446 if (dpyinfo->motif_drag_atom != None)
2447 atom = dpyinfo->motif_drag_atom;
2448 else
2449 atom = xm_get_drag_atom_1 (dpyinfo, x_dnd_frame);
2450
2451 dpyinfo->motif_drag_atom = atom;
2452 return atom;
2453 }
2454
2455 static void
2456 xm_setup_drag_info (struct x_display_info *dpyinfo,
2457 struct frame *source_frame)
2458 {
2459 Atom atom;
2460 xm_drag_initiator_info drag_initiator_info;
2461 int idx;
2462
2463 atom = xm_get_drag_atom (dpyinfo);
2464
2465 if (atom == None)
2466 return;
2467
2468 XSETCAR (x_dnd_selection_alias_cell,
2469 x_atom_to_symbol (dpyinfo, atom));
2470 XSETCDR (x_dnd_selection_alias_cell, QXdndSelection);
2471
2472 idx = xm_setup_dnd_targets (dpyinfo, x_dnd_targets,
2473 x_dnd_n_targets);
2474
2475 if (idx != -1)
2476 {
2477 drag_initiator_info.byteorder = XM_BYTE_ORDER_CUR_FIRST;
2478 drag_initiator_info.protocol = XM_DRAG_PROTOCOL_VERSION;
2479 drag_initiator_info.table_index = idx;
2480 drag_initiator_info.selection = atom;
2481
2482 xm_write_drag_initiator_info (dpyinfo->display,
2483 FRAME_X_WINDOW (source_frame), atom,
2484 dpyinfo->Xatom_MOTIF_DRAG_INITIATOR_INFO,
2485 &drag_initiator_info);
2486
2487 x_dnd_motif_setup_p = true;
2488 x_dnd_motif_atom = atom;
2489 }
2490 }
2491
2492 static void
2493 xm_send_drop_message (struct x_display_info *dpyinfo, Window source,
2494 Window target, xm_drop_start_message *dmsg)
2495 {
2496 XEvent msg;
2497
2498 msg.xclient.type = ClientMessage;
2499 msg.xclient.message_type
2500 = dpyinfo->Xatom_MOTIF_DRAG_AND_DROP_MESSAGE;
2501 msg.xclient.format = 8;
2502 msg.xclient.window = target;
2503 msg.xclient.data.b[0] = dmsg->reason;
2504 msg.xclient.data.b[1] = dmsg->byte_order;
2505 *((uint16_t *) &msg.xclient.data.b[2]) = dmsg->side_effects;
2506 *((uint32_t *) &msg.xclient.data.b[4]) = dmsg->timestamp;
2507 *((uint16_t *) &msg.xclient.data.b[8]) = dmsg->x;
2508 *((uint16_t *) &msg.xclient.data.b[10]) = dmsg->y;
2509 *((uint32_t *) &msg.xclient.data.b[12]) = dmsg->index_atom;
2510 *((uint32_t *) &msg.xclient.data.b[16]) = dmsg->source_window;
2511
2512 x_ignore_errors_for_next_request (dpyinfo);
2513 XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg);
2514 x_stop_ignoring_errors (dpyinfo);
2515 }
2516
2517 static void
2518 xm_send_top_level_enter_message (struct x_display_info *dpyinfo, Window source,
2519 Window target, xm_top_level_enter_message *dmsg)
2520 {
2521 XEvent msg;
2522
2523 msg.xclient.type = ClientMessage;
2524 msg.xclient.message_type
2525 = dpyinfo->Xatom_MOTIF_DRAG_AND_DROP_MESSAGE;
2526 msg.xclient.format = 8;
2527 msg.xclient.window = target;
2528 msg.xclient.data.b[0] = dmsg->reason;
2529 msg.xclient.data.b[1] = dmsg->byteorder;
2530 *((uint16_t *) &msg.xclient.data.b[2]) = dmsg->zero;
2531 *((uint32_t *) &msg.xclient.data.b[4]) = dmsg->timestamp;
2532 *((uint32_t *) &msg.xclient.data.b[8]) = dmsg->source_window;
2533 *((uint32_t *) &msg.xclient.data.b[12]) = dmsg->index_atom;
2534 msg.xclient.data.b[16] = 0;
2535 msg.xclient.data.b[17] = 0;
2536 msg.xclient.data.b[18] = 0;
2537 msg.xclient.data.b[19] = 0;
2538
2539 x_ignore_errors_for_next_request (dpyinfo);
2540 XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg);
2541 x_stop_ignoring_errors (dpyinfo);
2542 }
2543
2544 static void
2545 xm_send_drag_motion_message (struct x_display_info *dpyinfo, Window source,
2546 Window target, xm_drag_motion_message *dmsg)
2547 {
2548 XEvent msg;
2549
2550 msg.xclient.type = ClientMessage;
2551 msg.xclient.message_type
2552 = dpyinfo->Xatom_MOTIF_DRAG_AND_DROP_MESSAGE;
2553 msg.xclient.format = 8;
2554 msg.xclient.window = target;
2555 msg.xclient.data.b[0] = dmsg->reason;
2556 msg.xclient.data.b[1] = dmsg->byteorder;
2557 *((uint16_t *) &msg.xclient.data.b[2]) = dmsg->side_effects;
2558 *((uint32_t *) &msg.xclient.data.b[4]) = dmsg->timestamp;
2559 *((uint16_t *) &msg.xclient.data.b[8]) = dmsg->x;
2560 *((uint16_t *) &msg.xclient.data.b[10]) = dmsg->y;
2561 msg.xclient.data.b[12] = 0;
2562 msg.xclient.data.b[13] = 0;
2563 msg.xclient.data.b[14] = 0;
2564 msg.xclient.data.b[15] = 0;
2565 msg.xclient.data.b[16] = 0;
2566 msg.xclient.data.b[17] = 0;
2567 msg.xclient.data.b[18] = 0;
2568 msg.xclient.data.b[19] = 0;
2569
2570 x_ignore_errors_for_next_request (dpyinfo);
2571 XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg);
2572 x_stop_ignoring_errors (dpyinfo);
2573 }
2574
2575 static void
2576 xm_send_top_level_leave_message (struct x_display_info *dpyinfo, Window source,
2577 Window target, xm_top_level_leave_message *dmsg)
2578 {
2579 XEvent msg;
2580 xm_drag_motion_message mmsg;
2581
2582
2583
2584
2585
2586
2587
2588
2589 if (x_dnd_fix_motif_leave)
2590 {
2591 mmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
2592 XM_DRAG_REASON_DRAG_MOTION);
2593 mmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
2594 mmsg.side_effects = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
2595 x_dnd_wanted_action),
2596 XM_DROP_SITE_NONE, x_dnd_motif_operations,
2597 XM_DROP_ACTION_DROP_CANCEL);
2598 mmsg.timestamp = dmsg->timestamp;
2599
2600
2601
2602
2603
2604 mmsg.x = X_SHRT_MAX;
2605 mmsg.y = X_SHRT_MAX;
2606
2607 xm_send_drag_motion_message (dpyinfo, source, target, &mmsg);
2608 }
2609
2610 msg.xclient.type = ClientMessage;
2611 msg.xclient.message_type
2612 = dpyinfo->Xatom_MOTIF_DRAG_AND_DROP_MESSAGE;
2613 msg.xclient.format = 8;
2614 msg.xclient.window = target;
2615 msg.xclient.data.b[0] = dmsg->reason;
2616 msg.xclient.data.b[1] = dmsg->byteorder;
2617 *((uint16_t *) &msg.xclient.data.b[2]) = dmsg->zero;
2618 *((uint32_t *) &msg.xclient.data.b[4]) = dmsg->timestamp;
2619 *((uint32_t *) &msg.xclient.data.b[8]) = dmsg->source_window;
2620 msg.xclient.data.b[12] = 0;
2621 msg.xclient.data.b[13] = 0;
2622 msg.xclient.data.b[14] = 0;
2623 msg.xclient.data.b[15] = 0;
2624 msg.xclient.data.b[16] = 0;
2625 msg.xclient.data.b[17] = 0;
2626 msg.xclient.data.b[18] = 0;
2627 msg.xclient.data.b[19] = 0;
2628
2629 x_ignore_errors_for_next_request (dpyinfo);
2630 XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg);
2631 x_stop_ignoring_errors (dpyinfo);
2632 }
2633
2634 static int
2635 xm_read_drop_start_reply (const XEvent *msg, xm_drop_start_reply *reply)
2636 {
2637 const uint8_t *data;
2638
2639 data = (const uint8_t *) &msg->xclient.data.b[0];
2640
2641 if ((XM_DRAG_REASON_ORIGINATOR (data[0])
2642 != XM_DRAG_ORIGINATOR_RECEIVER)
2643 || (XM_DRAG_REASON_CODE (data[0])
2644 != XM_DRAG_REASON_DROP_START))
2645 return 1;
2646
2647 reply->reason = *(data++);
2648 reply->byte_order = *(data++);
2649 reply->side_effects = *(uint16_t *) data;
2650 reply->better_x = *(uint16_t *) (data + 2);
2651 reply->better_y = *(uint16_t *) (data + 4);
2652
2653 if (reply->byte_order != XM_BYTE_ORDER_CUR_FIRST)
2654 {
2655 SWAPCARD16 (reply->side_effects);
2656 SWAPCARD16 (reply->better_x);
2657 SWAPCARD16 (reply->better_y);
2658 }
2659
2660 reply->byte_order = XM_BYTE_ORDER_CUR_FIRST;
2661
2662 return 0;
2663 }
2664
2665 static int
2666 xm_read_drop_start_message (const XEvent *msg,
2667 xm_drop_start_message *dmsg)
2668 {
2669 const uint8_t *data;
2670
2671 data = (const uint8_t *) &msg->xclient.data.b[0];
2672
2673 if ((XM_DRAG_REASON_ORIGINATOR (data[0])
2674 != XM_DRAG_ORIGINATOR_INITIATOR)
2675 || (XM_DRAG_REASON_CODE (data[0])
2676 != XM_DRAG_REASON_DROP_START))
2677 return 1;
2678
2679 dmsg->reason = *(data++);
2680 dmsg->byte_order = *(data++);
2681 dmsg->side_effects = *(uint16_t *) data;
2682 dmsg->timestamp = *(uint32_t *) (data + 2);
2683 dmsg->x = *(uint16_t *) (data + 6);
2684 dmsg->y = *(uint16_t *) (data + 8);
2685 dmsg->index_atom = *(uint32_t *) (data + 10);
2686 dmsg->source_window = *(uint32_t *) (data + 14);
2687
2688 if (dmsg->byte_order != XM_BYTE_ORDER_CUR_FIRST)
2689 {
2690 SWAPCARD16 (dmsg->side_effects);
2691 SWAPCARD32 (dmsg->timestamp);
2692 SWAPCARD16 (dmsg->x);
2693 SWAPCARD16 (dmsg->y);
2694 SWAPCARD32 (dmsg->index_atom);
2695 SWAPCARD32 (dmsg->source_window);
2696 }
2697
2698 dmsg->byte_order = XM_BYTE_ORDER_CUR_FIRST;
2699
2700 return 0;
2701 }
2702
2703 static int
2704 xm_read_drag_receiver_info (struct x_display_info *dpyinfo,
2705 Window wdesc, xm_drag_receiver_info *rec)
2706 {
2707 Atom actual_type;
2708 int rc, actual_format;
2709 unsigned long nitems, bytes_remaining;
2710 unsigned char *tmp_data = NULL;
2711 uint8_t *data;
2712
2713 x_catch_errors (dpyinfo->display);
2714 rc = XGetWindowProperty (dpyinfo->display, wdesc,
2715 dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO,
2716 0, 4, False,
2717 dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO,
2718 &actual_type, &actual_format, &nitems,
2719 &bytes_remaining,
2720 &tmp_data) == Success;
2721
2722 if (x_had_errors_p (dpyinfo->display)
2723 || actual_format != 8 || nitems < 16 || !tmp_data
2724 || actual_type != dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO)
2725 rc = 0;
2726 x_uncatch_errors_after_check ();
2727
2728 if (rc)
2729 {
2730 data = (uint8_t *) tmp_data;
2731
2732 if (data[1] > XM_DRAG_PROTOCOL_VERSION)
2733 return 1;
2734
2735 rec->byteorder = data[0];
2736 rec->protocol = data[1];
2737 rec->protocol_style = data[2];
2738 rec->unspecified0 = data[3];
2739 rec->unspecified1 = *(uint32_t *) &data[4];
2740 rec->unspecified2 = *(uint32_t *) &data[8];
2741 rec->unspecified3 = *(uint32_t *) &data[12];
2742
2743 if (rec->byteorder != XM_BYTE_ORDER_CUR_FIRST)
2744 {
2745 SWAPCARD32 (rec->unspecified1);
2746 SWAPCARD32 (rec->unspecified2);
2747 SWAPCARD32 (rec->unspecified3);
2748 }
2749
2750 rec->byteorder = XM_BYTE_ORDER_CUR_FIRST;
2751 }
2752
2753 if (tmp_data)
2754 XFree (tmp_data);
2755
2756 return !rc;
2757 }
2758
2759 static int
2760 xm_read_drag_motion_message (const XEvent *msg,
2761 xm_drag_motion_message *dmsg)
2762 {
2763 const uint8_t *data;
2764
2765 data = (const uint8_t *) &msg->xclient.data.b[0];
2766
2767 if ((XM_DRAG_REASON_CODE (data[0])
2768 != XM_DRAG_REASON_DRAG_MOTION)
2769 || (XM_DRAG_REASON_ORIGINATOR (data[0])
2770 != XM_DRAG_ORIGINATOR_INITIATOR))
2771 return 1;
2772
2773 dmsg->reason = *(data++);
2774 dmsg->byteorder = *(data++);
2775 dmsg->side_effects = *(uint16_t *) data;
2776 dmsg->timestamp = *(uint32_t *) (data + 2);
2777 dmsg->x = *(uint16_t *) (data + 6);
2778 dmsg->y = *(uint16_t *) (data + 8);
2779
2780 if (dmsg->byteorder != XM_BYTE_ORDER_CUR_FIRST)
2781 {
2782 SWAPCARD16 (dmsg->side_effects);
2783 SWAPCARD32 (dmsg->timestamp);
2784 SWAPCARD16 (dmsg->x);
2785 SWAPCARD16 (dmsg->y);
2786 }
2787
2788 dmsg->byteorder = XM_BYTE_ORDER_CUR_FIRST;
2789
2790 return 0;
2791 }
2792
2793 static int
2794 xm_read_drag_motion_reply (const XEvent *msg, xm_drag_motion_reply *reply)
2795 {
2796 const uint8_t *data;
2797
2798 data = (const uint8_t *) &msg->xclient.data.b[0];
2799
2800 if ((XM_DRAG_REASON_CODE (data[0])
2801 != XM_DRAG_REASON_DRAG_MOTION)
2802 || (XM_DRAG_REASON_ORIGINATOR (data[0])
2803 != XM_DRAG_ORIGINATOR_RECEIVER))
2804 return 1;
2805
2806 reply->reason = *(data++);
2807 reply->byte_order = *(data++);
2808 reply->side_effects = *(uint16_t *) data;
2809 reply->timestamp = *(uint32_t *) (data + 2);
2810 reply->better_x = *(uint16_t *) (data + 6);
2811 reply->better_y = *(uint16_t *) (data + 8);
2812
2813 if (reply->byte_order != XM_BYTE_ORDER_CUR_FIRST)
2814 {
2815 SWAPCARD16 (reply->side_effects);
2816 SWAPCARD32 (reply->timestamp);
2817 SWAPCARD16 (reply->better_x);
2818 SWAPCARD16 (reply->better_y);
2819 }
2820
2821 reply->byte_order = XM_BYTE_ORDER_CUR_FIRST;
2822
2823 return 0;
2824 }
2825
2826 static void
2827 x_dnd_send_xm_leave_for_drop (struct x_display_info *dpyinfo,
2828 struct frame *f, Window wdesc,
2829 Time timestamp)
2830 {
2831 xm_top_level_leave_message lmsg;
2832
2833 lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
2834 XM_DRAG_REASON_TOP_LEVEL_LEAVE);
2835 lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
2836 lmsg.zero = 0;
2837 lmsg.timestamp = timestamp;
2838 lmsg.source_window = FRAME_X_WINDOW (f);
2839
2840 if (x_dnd_motif_setup_p)
2841 xm_send_top_level_leave_message (dpyinfo, FRAME_X_WINDOW (f),
2842 wdesc, &lmsg);
2843 }
2844
2845 static void
2846 x_dnd_free_toplevels (bool display_alive)
2847 {
2848 struct x_client_list_window *last;
2849 struct x_client_list_window *tem = x_dnd_toplevels;
2850 ptrdiff_t n_windows, i, buffer_size;
2851 Window *destroy_windows UNINIT;
2852 unsigned long *prev_masks UNINIT;
2853 specpdl_ref count;
2854 Display *dpy UNINIT;
2855 struct x_display_info *dpyinfo;
2856
2857 if (!x_dnd_toplevels)
2858
2859 return;
2860
2861 if (display_alive)
2862 {
2863 buffer_size = 1024;
2864 destroy_windows = xmalloc (sizeof *destroy_windows
2865 * buffer_size);
2866 prev_masks = xmalloc (sizeof *prev_masks *
2867 buffer_size);
2868 n_windows = 0;
2869 }
2870
2871 block_input ();
2872 while (tem)
2873 {
2874 last = tem;
2875 tem = tem->next;
2876
2877 if (display_alive)
2878 {
2879 if (++n_windows >= buffer_size)
2880 {
2881 buffer_size += 1024;
2882 destroy_windows
2883 = xrealloc (destroy_windows, (sizeof *destroy_windows
2884 * buffer_size));
2885 prev_masks
2886 = xrealloc (prev_masks, (sizeof *prev_masks
2887 * buffer_size));
2888 }
2889
2890 dpy = last->dpy;
2891 prev_masks[n_windows - 1] = last->previous_event_mask;
2892 destroy_windows[n_windows - 1] = last->window;
2893 }
2894
2895 #ifdef HAVE_XSHAPE
2896 if (last->n_input_rects != -1)
2897 xfree (last->input_rects);
2898 if (last->n_bounding_rects != -1)
2899 xfree (last->bounding_rects);
2900 #endif
2901
2902 xfree (last);
2903 }
2904
2905 x_dnd_toplevels = NULL;
2906
2907 if (!display_alive)
2908 {
2909 unblock_input ();
2910 return;
2911 }
2912
2913 count = SPECPDL_INDEX ();
2914 record_unwind_protect_ptr (xfree, destroy_windows);
2915 record_unwind_protect_ptr (xfree, prev_masks);
2916
2917 if (display_alive)
2918 {
2919 dpyinfo = x_display_info_for_display (dpy);
2920
2921 if (n_windows)
2922 {
2923 eassume (dpyinfo);
2924 x_ignore_errors_for_next_request (dpyinfo);
2925
2926 for (i = 0; i < n_windows; ++i)
2927 {
2928 XSelectInput (dpy, destroy_windows[i], prev_masks[i]);
2929 #ifdef HAVE_XSHAPE
2930 XShapeSelectInput (dpy, destroy_windows[i], None);
2931 #endif
2932 }
2933
2934 x_stop_ignoring_errors (dpyinfo);
2935 }
2936 }
2937
2938 unbind_to (count, Qnil);
2939 unblock_input ();
2940 }
2941
2942 static int
2943 x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
2944 {
2945 Atom type;
2946 Window *toplevels;
2947 int format, rc;
2948 unsigned long nitems, bytes_after;
2949 unsigned long i, real_nitems;
2950 unsigned char *data = NULL;
2951 int frame_extents[4];
2952
2953 #ifndef USE_XCB
2954 int dest_x, dest_y;
2955 unsigned long *wmstate;
2956 unsigned long wmstate_items, extent_items;
2957 unsigned char *wmstate_data = NULL, *extent_data = NULL;
2958 XWindowAttributes attrs;
2959 Window child;
2960 xm_drag_receiver_info xm_info;
2961 #else
2962 uint32_t *wmstate, *fextents;
2963 uint8_t *xmdata;
2964 xcb_get_window_attributes_cookie_t *window_attribute_cookies;
2965 xcb_translate_coordinates_cookie_t *translate_coordinate_cookies;
2966 xcb_get_property_cookie_t *get_property_cookies;
2967 xcb_get_property_cookie_t *xm_property_cookies;
2968 xcb_get_property_cookie_t *extent_property_cookies;
2969 xcb_get_geometry_cookie_t *get_geometry_cookies;
2970 xcb_get_window_attributes_reply_t attrs, *attrs_reply;
2971 xcb_translate_coordinates_reply_t *coordinates_reply;
2972 xcb_get_property_reply_t *property_reply;
2973 xcb_get_property_reply_t *xm_property_reply;
2974 xcb_get_property_reply_t *extent_property_reply;
2975 xcb_get_geometry_reply_t *geometry_reply;
2976 xcb_generic_error_t *error;
2977 #endif
2978
2979 #ifdef HAVE_XCB_SHAPE
2980 xcb_shape_get_rectangles_cookie_t *bounding_rect_cookies;
2981 xcb_shape_get_rectangles_reply_t *bounding_rect_reply;
2982 xcb_rectangle_iterator_t bounding_rect_iterator;
2983 #endif
2984
2985 #ifdef HAVE_XCB_SHAPE_INPUT_RECTS
2986 xcb_shape_get_rectangles_cookie_t *input_rect_cookies;
2987 xcb_shape_get_rectangles_reply_t *input_rect_reply;
2988 xcb_rectangle_iterator_t input_rect_iterator;
2989 #endif
2990
2991 struct x_client_list_window *tem;
2992 #if defined HAVE_XSHAPE && !defined HAVE_XCB_SHAPE_INPUT_RECTS
2993 int count, ordering;
2994 XRectangle *rects;
2995 #endif
2996
2997 rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window,
2998 dpyinfo->Xatom_net_client_list_stacking,
2999 0, LONG_MAX, False, XA_WINDOW, &type,
3000 &format, &nitems, &bytes_after, &data);
3001
3002 if (rc != Success)
3003 return 1;
3004
3005 if (format != 32 || type != XA_WINDOW)
3006 {
3007 XFree (data);
3008 return 1;
3009 }
3010
3011 toplevels = (Window *) data;
3012
3013 for (i = 0, real_nitems = 0; i < nitems; ++i)
3014 {
3015
3016
3017 if (!x_tooltip_window_to_frame (dpyinfo, toplevels[i], NULL))
3018 toplevels[real_nitems++] = toplevels[i];
3019 }
3020
3021 nitems = real_nitems;
3022
3023 #ifdef USE_XCB
3024 USE_SAFE_ALLOCA;
3025
3026 window_attribute_cookies
3027 = SAFE_ALLOCA (sizeof *window_attribute_cookies * nitems);
3028 translate_coordinate_cookies
3029 = SAFE_ALLOCA (sizeof *translate_coordinate_cookies * nitems);
3030 get_property_cookies
3031 = SAFE_ALLOCA (sizeof *get_property_cookies * nitems);
3032 xm_property_cookies
3033 = SAFE_ALLOCA (sizeof *xm_property_cookies * nitems);
3034 extent_property_cookies
3035 = SAFE_ALLOCA (sizeof *extent_property_cookies * nitems);
3036 get_geometry_cookies
3037 = SAFE_ALLOCA (sizeof *get_geometry_cookies * nitems);
3038
3039 #ifdef HAVE_XCB_SHAPE
3040 bounding_rect_cookies
3041 = SAFE_ALLOCA (sizeof *bounding_rect_cookies * nitems);
3042 #endif
3043
3044 #ifdef HAVE_XCB_SHAPE_INPUT_RECTS
3045 input_rect_cookies
3046 = SAFE_ALLOCA (sizeof *input_rect_cookies * nitems);
3047 #endif
3048
3049 for (i = 0; i < nitems; ++i)
3050 {
3051 window_attribute_cookies[i]
3052 = xcb_get_window_attributes (dpyinfo->xcb_connection,
3053 (xcb_window_t) toplevels[i]);
3054 translate_coordinate_cookies[i]
3055 = xcb_translate_coordinates (dpyinfo->xcb_connection,
3056 (xcb_window_t) toplevels[i],
3057 (xcb_window_t) dpyinfo->root_window,
3058 0, 0);
3059 get_property_cookies[i]
3060 = xcb_get_property (dpyinfo->xcb_connection, 0, (xcb_window_t) toplevels[i],
3061 (xcb_atom_t) dpyinfo->Xatom_wm_state, XCB_ATOM_ANY,
3062 0, 2);
3063 xm_property_cookies[i]
3064 = xcb_get_property (dpyinfo->xcb_connection, 0, (xcb_window_t) toplevels[i],
3065 (xcb_atom_t) dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO,
3066 (xcb_atom_t) dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO,
3067 0, 4);
3068 extent_property_cookies[i]
3069 = xcb_get_property (dpyinfo->xcb_connection, 0,
3070 (xcb_window_t) toplevels[i],
3071 (xcb_atom_t) dpyinfo->Xatom_net_frame_extents,
3072 XCB_ATOM_CARDINAL, 0, 4);
3073 get_geometry_cookies[i]
3074 = xcb_get_geometry (dpyinfo->xcb_connection, (xcb_window_t) toplevels[i]);
3075
3076 #ifdef HAVE_XCB_SHAPE
3077 bounding_rect_cookies[i]
3078 = xcb_shape_get_rectangles (dpyinfo->xcb_connection,
3079 (xcb_window_t) toplevels[i],
3080 XCB_SHAPE_SK_BOUNDING);
3081 #endif
3082
3083 #ifdef HAVE_XCB_SHAPE_INPUT_RECTS
3084 if (dpyinfo->xshape_major > 1
3085 || (dpyinfo->xshape_major == 1
3086 && dpyinfo->xshape_minor >= 1))
3087 input_rect_cookies[i]
3088 = xcb_shape_get_rectangles (dpyinfo->xcb_connection,
3089 (xcb_window_t) toplevels[i],
3090 XCB_SHAPE_SK_INPUT);
3091 #endif
3092 }
3093 #endif
3094
3095
3096
3097 for (i = 0; i < nitems; ++i)
3098 {
3099 frame_extents[0] = 0;
3100 frame_extents[1] = 0;
3101 frame_extents[2] = 0;
3102 frame_extents[3] = 0;
3103
3104 #ifndef USE_XCB
3105 x_catch_errors (dpyinfo->display);
3106 rc = (XGetWindowAttributes (dpyinfo->display,
3107 toplevels[i], &attrs)
3108 && !x_had_errors_p (dpyinfo->display));
3109
3110 if (rc)
3111 rc = (XTranslateCoordinates (dpyinfo->display, toplevels[i],
3112 attrs.root, -attrs.border_width,
3113 -attrs.border_width, &dest_x,
3114 &dest_y, &child)
3115 && !x_had_errors_p (dpyinfo->display));
3116 if (rc)
3117 rc = ((XGetWindowProperty (dpyinfo->display,
3118 toplevels[i],
3119 dpyinfo->Xatom_wm_state,
3120 0, 2, False, AnyPropertyType,
3121 &type, &format, &wmstate_items,
3122 &bytes_after, &wmstate_data)
3123 == Success)
3124 && !x_had_errors_p (dpyinfo->display)
3125 && wmstate_data && wmstate_items == 2 && format == 32);
3126
3127 if (XGetWindowProperty (dpyinfo->display, toplevels[i],
3128 dpyinfo->Xatom_net_frame_extents,
3129 0, 4, False, XA_CARDINAL, &type,
3130 &format, &extent_items, &bytes_after,
3131 &extent_data) == Success
3132 && !x_had_errors_p (dpyinfo->display)
3133 && extent_data && extent_items >= 4 && format == 32)
3134 {
3135 frame_extents[0] = ((unsigned long *) extent_data)[0];
3136 frame_extents[1] = ((unsigned long *) extent_data)[1];
3137 frame_extents[2] = ((unsigned long *) extent_data)[2];
3138 frame_extents[3] = ((unsigned long *) extent_data)[3];
3139 }
3140
3141 if (extent_data)
3142 XFree (extent_data);
3143
3144 x_uncatch_errors ();
3145 #else
3146 rc = true;
3147
3148 attrs_reply
3149 = xcb_get_window_attributes_reply (dpyinfo->xcb_connection,
3150 window_attribute_cookies[i],
3151 &error);
3152
3153 if (!attrs_reply)
3154 {
3155 rc = false;
3156 free (error);
3157 }
3158
3159 coordinates_reply
3160 = xcb_translate_coordinates_reply (dpyinfo->xcb_connection,
3161 translate_coordinate_cookies[i],
3162 &error);
3163
3164 if (!coordinates_reply)
3165 {
3166 rc = false;
3167 free (error);
3168 }
3169
3170 property_reply = xcb_get_property_reply (dpyinfo->xcb_connection,
3171 get_property_cookies[i],
3172 &error);
3173
3174 if (!property_reply)
3175 {
3176 rc = false;
3177 free (error);
3178 }
3179
3180
3181
3182
3183 xm_property_reply = xcb_get_property_reply (dpyinfo->xcb_connection,
3184 xm_property_cookies[i],
3185 &error);
3186
3187 if (!xm_property_reply)
3188 free (error);
3189
3190 extent_property_reply = xcb_get_property_reply (dpyinfo->xcb_connection,
3191 extent_property_cookies[i],
3192 &error);
3193
3194 if (!extent_property_reply)
3195 free (error);
3196 else
3197 {
3198 if (xcb_get_property_value_length (extent_property_reply) == 16
3199 && extent_property_reply->format == 32
3200 && extent_property_reply->type == XCB_ATOM_CARDINAL)
3201 {
3202 fextents = xcb_get_property_value (extent_property_reply);
3203 frame_extents[0] = fextents[0];
3204 frame_extents[1] = fextents[1];
3205 frame_extents[2] = fextents[2];
3206 frame_extents[3] = fextents[3];
3207 }
3208
3209 free (extent_property_reply);
3210 }
3211
3212 if (property_reply
3213 && (xcb_get_property_value_length (property_reply) != 8
3214 || property_reply->format != 32))
3215 rc = false;
3216
3217 geometry_reply = xcb_get_geometry_reply (dpyinfo->xcb_connection,
3218 get_geometry_cookies[i],
3219 &error);
3220
3221 if (!geometry_reply)
3222 {
3223 rc = false;
3224 free (error);
3225 }
3226 #endif
3227
3228 if (rc)
3229 {
3230 #ifdef USE_XCB
3231 wmstate = (uint32_t *) xcb_get_property_value (property_reply);
3232 attrs = *attrs_reply;
3233 #else
3234 wmstate = (unsigned long *) wmstate_data;
3235 #endif
3236
3237 tem = xmalloc (sizeof *tem);
3238 tem->window = toplevels[i];
3239 tem->dpy = dpyinfo->display;
3240 tem->frame_extents_left = frame_extents[0];
3241 tem->frame_extents_right = frame_extents[1];
3242 tem->frame_extents_top = frame_extents[2];
3243 tem->frame_extents_bottom = frame_extents[3];
3244
3245 #ifndef USE_XCB
3246 tem->x = dest_x;
3247 tem->y = dest_y;
3248 tem->width = attrs.width + attrs.border_width;
3249 tem->height = attrs.height + attrs.border_width;
3250 tem->mapped_p = (attrs.map_state != IsUnmapped);
3251 #else
3252 tem->x = (coordinates_reply->dst_x
3253 - geometry_reply->border_width);
3254 tem->y = (coordinates_reply->dst_y
3255 - geometry_reply->border_width);
3256 tem->width = (geometry_reply->width
3257 + geometry_reply->border_width);
3258 tem->height = (geometry_reply->height
3259 + geometry_reply->border_width);
3260 tem->mapped_p = (attrs.map_state != XCB_MAP_STATE_UNMAPPED);
3261 #endif
3262 tem->next = x_dnd_toplevels;
3263 tem->previous_event_mask = attrs.your_event_mask;
3264 tem->wm_state = wmstate[0];
3265 tem->xm_protocol_style = XM_DRAG_STYLE_NONE;
3266
3267 #ifndef USE_XCB
3268 if (!xm_read_drag_receiver_info (dpyinfo, toplevels[i], &xm_info))
3269 tem->xm_protocol_style = xm_info.protocol_style;
3270 #else
3271 if (xm_property_reply
3272 && xm_property_reply->format == 8
3273 && xm_property_reply->type == dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO
3274 && xcb_get_property_value_length (xm_property_reply) >= 4)
3275 {
3276 xmdata = xcb_get_property_value (xm_property_reply);
3277
3278 if (xmdata[1] <= XM_DRAG_PROTOCOL_VERSION)
3279 tem->xm_protocol_style = xmdata[2];
3280 }
3281 #endif
3282
3283 #ifdef HAVE_XSHAPE
3284 #ifndef USE_XCB
3285 tem->border_width = attrs.border_width;
3286 #else
3287 tem->border_width = geometry_reply->border_width;
3288 #endif
3289 tem->n_bounding_rects = -1;
3290 tem->n_input_rects = -1;
3291
3292 if (dpyinfo->xshape_supported_p)
3293 {
3294 x_ignore_errors_for_next_request (dpyinfo);
3295 XShapeSelectInput (dpyinfo->display,
3296 toplevels[i],
3297 ShapeNotifyMask);
3298 x_stop_ignoring_errors (dpyinfo);
3299
3300 #ifndef HAVE_XCB_SHAPE
3301 x_catch_errors (dpyinfo->display);
3302 rects = XShapeGetRectangles (dpyinfo->display,
3303 toplevels[i],
3304 ShapeBounding,
3305 &count, &ordering);
3306 rc = x_had_errors_p (dpyinfo->display);
3307 x_uncatch_errors_after_check ();
3308
3309
3310
3311 if (!rc)
3312 {
3313 tem->n_bounding_rects = count;
3314 tem->bounding_rects
3315 = xmalloc (sizeof *tem->bounding_rects * count);
3316 memcpy (tem->bounding_rects, rects,
3317 sizeof *tem->bounding_rects * count);
3318
3319 XFree (rects);
3320 }
3321 #else
3322 bounding_rect_reply = xcb_shape_get_rectangles_reply (dpyinfo->xcb_connection,
3323 bounding_rect_cookies[i],
3324 &error);
3325
3326 if (bounding_rect_reply)
3327 {
3328 bounding_rect_iterator
3329 = xcb_shape_get_rectangles_rectangles_iterator (bounding_rect_reply);
3330 tem->n_bounding_rects = bounding_rect_iterator.rem + 1;
3331 tem->bounding_rects = xmalloc (tem->n_bounding_rects
3332 * sizeof *tem->bounding_rects);
3333 tem->n_bounding_rects = 0;
3334
3335 for (; bounding_rect_iterator.rem; xcb_rectangle_next (&bounding_rect_iterator))
3336 {
3337 tem->bounding_rects[tem->n_bounding_rects].x
3338 = bounding_rect_iterator.data->x;
3339 tem->bounding_rects[tem->n_bounding_rects].y
3340 = bounding_rect_iterator.data->y;
3341 tem->bounding_rects[tem->n_bounding_rects].width
3342 = bounding_rect_iterator.data->width;
3343 tem->bounding_rects[tem->n_bounding_rects].height
3344 = bounding_rect_iterator.data->height;
3345
3346 tem->n_bounding_rects++;
3347 }
3348
3349 free (bounding_rect_reply);
3350 }
3351 else
3352 free (error);
3353 #endif
3354
3355 #ifdef HAVE_XCB_SHAPE_INPUT_RECTS
3356 if (dpyinfo->xshape_major > 1
3357 || (dpyinfo->xshape_major == 1
3358 && dpyinfo->xshape_minor >= 1))
3359 {
3360 input_rect_reply = xcb_shape_get_rectangles_reply (dpyinfo->xcb_connection,
3361 input_rect_cookies[i],
3362 &error);
3363
3364 if (input_rect_reply)
3365 {
3366 input_rect_iterator
3367 = xcb_shape_get_rectangles_rectangles_iterator (input_rect_reply);
3368 tem->n_input_rects = input_rect_iterator.rem + 1;
3369 tem->input_rects = xmalloc (tem->n_input_rects
3370 * sizeof *tem->input_rects);
3371 tem->n_input_rects = 0;
3372
3373 for (; input_rect_iterator.rem; xcb_rectangle_next (&input_rect_iterator))
3374 {
3375 tem->input_rects[tem->n_input_rects].x
3376 = input_rect_iterator.data->x;
3377 tem->input_rects[tem->n_input_rects].y
3378 = input_rect_iterator.data->y;
3379 tem->input_rects[tem->n_input_rects].width
3380 = input_rect_iterator.data->width;
3381 tem->input_rects[tem->n_input_rects].height
3382 = input_rect_iterator.data->height;
3383
3384 tem->n_input_rects++;
3385 }
3386
3387 free (input_rect_reply);
3388 }
3389 else
3390 free (error);
3391 }
3392 #else
3393 #ifdef ShapeInput
3394 if (dpyinfo->xshape_major > 1
3395 || (dpyinfo->xshape_major == 1
3396 && dpyinfo->xshape_minor >= 1))
3397 {
3398 x_catch_errors (dpyinfo->display);
3399 rects = XShapeGetRectangles (dpyinfo->display,
3400 toplevels[i], ShapeInput,
3401 &count, &ordering);
3402 rc = x_had_errors_p (dpyinfo->display);
3403 x_uncatch_errors_after_check ();
3404
3405
3406
3407 if (!rc)
3408 {
3409 tem->n_input_rects = count;
3410 tem->input_rects
3411 = xmalloc (sizeof *tem->input_rects * count);
3412 memcpy (tem->input_rects, rects,
3413 sizeof *tem->input_rects * count);
3414
3415 XFree (rects);
3416 }
3417 }
3418 #endif
3419 #endif
3420 }
3421
3422
3423
3424
3425 if (tem->n_input_rects != -1
3426 && tem->n_bounding_rects == tem->n_input_rects
3427 && !memcmp (tem->bounding_rects, tem->input_rects,
3428 tem->n_input_rects * sizeof *tem->input_rects))
3429 {
3430 xfree (tem->input_rects);
3431 tem->n_input_rects = -1;
3432 }
3433
3434
3435
3436
3437 if (tem->n_input_rects == -1
3438 && tem->n_bounding_rects == 1
3439 #ifdef USE_XCB
3440 && tem->bounding_rects[0].width == (geometry_reply->width
3441 + geometry_reply->border_width)
3442 && tem->bounding_rects[0].height == (geometry_reply->height
3443 + geometry_reply->border_width)
3444 && tem->bounding_rects[0].x == -geometry_reply->border_width
3445 && tem->bounding_rects[0].y == -geometry_reply->border_width
3446 #else
3447 && tem->bounding_rects[0].width == attrs.width + attrs.border_width
3448 && tem->bounding_rects[0].height == attrs.height + attrs.border_width
3449 && tem->bounding_rects[0].x == -attrs.border_width
3450 && tem->bounding_rects[0].y == -attrs.border_width
3451 #endif
3452 )
3453 {
3454 xfree (tem->bounding_rects);
3455 tem->n_bounding_rects = -1;
3456 }
3457 #endif
3458
3459 x_ignore_errors_for_next_request (dpyinfo);
3460 XSelectInput (dpyinfo->display, toplevels[i],
3461 (attrs.your_event_mask
3462 | StructureNotifyMask
3463 | PropertyChangeMask));
3464 x_stop_ignoring_errors (dpyinfo);
3465
3466 x_dnd_toplevels = tem;
3467 }
3468 else
3469 {
3470 #ifdef HAVE_XCB_SHAPE
3471 if (dpyinfo->xshape_supported_p)
3472 {
3473 bounding_rect_reply = xcb_shape_get_rectangles_reply (dpyinfo->xcb_connection,
3474 bounding_rect_cookies[i],
3475 &error);
3476
3477 if (bounding_rect_reply)
3478 free (bounding_rect_reply);
3479 else
3480 free (error);
3481 }
3482 #endif
3483
3484 #ifdef HAVE_XCB_SHAPE_INPUT_RECTS
3485 if (dpyinfo->xshape_supported_p
3486 && (dpyinfo->xshape_major > 1
3487 || (dpyinfo->xshape_major == 1
3488 && dpyinfo->xshape_minor >= 1)))
3489 {
3490 input_rect_reply = xcb_shape_get_rectangles_reply (dpyinfo->xcb_connection,
3491 input_rect_cookies[i],
3492 &error);
3493
3494 if (input_rect_reply)
3495 free (input_rect_reply);
3496 else
3497 free (error);
3498 }
3499 #endif
3500 }
3501
3502 #ifdef USE_XCB
3503 if (attrs_reply)
3504 free (attrs_reply);
3505
3506 if (coordinates_reply)
3507 free (coordinates_reply);
3508
3509 if (property_reply)
3510 free (property_reply);
3511
3512 if (xm_property_reply)
3513 free (xm_property_reply);
3514
3515 if (geometry_reply)
3516 free (geometry_reply);
3517 #endif
3518
3519 #ifndef USE_XCB
3520 if (wmstate_data)
3521 {
3522 XFree (wmstate_data);
3523 wmstate_data = NULL;
3524 }
3525 #endif
3526 }
3527
3528 #ifdef USE_XCB
3529 SAFE_FREE ();
3530 #endif
3531
3532 if (data)
3533 XFree (data);
3534
3535 return 0;
3536 }
3537
3538 static _Noreturn int
3539 x_dnd_io_error_handler (Display *display)
3540 {
3541 #ifdef USE_GTK
3542 emacs_abort ();
3543 #else
3544 siglongjmp (x_dnd_disconnect_handler, 1);
3545 #endif
3546 }
3547
3548 #define X_DND_SUPPORTED_VERSION 5
3549
3550 static int x_dnd_get_window_proto (struct x_display_info *, Window);
3551 static Window x_dnd_get_window_proxy (struct x_display_info *, Window);
3552 static void x_dnd_update_state (struct x_display_info *, Time);
3553
3554 #ifdef USE_XCB
3555 static void
3556 x_dnd_get_proxy_proto (struct x_display_info *dpyinfo, Window wdesc,
3557 Window *proxy_out, int *proto_out)
3558 {
3559 xcb_get_property_cookie_t xdnd_proto_cookie;
3560 xcb_get_property_cookie_t xdnd_proxy_cookie;
3561 xcb_get_property_reply_t *reply;
3562 xcb_generic_error_t *error;
3563
3564 if (proxy_out)
3565 *proxy_out = None;
3566
3567 if (proto_out)
3568 *proto_out = -1;
3569
3570 if (proxy_out)
3571 xdnd_proxy_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
3572 (xcb_window_t) wdesc,
3573 (xcb_atom_t) dpyinfo->Xatom_XdndProxy,
3574 XCB_ATOM_WINDOW, 0, 1);
3575
3576 if (proto_out)
3577 xdnd_proto_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
3578 (xcb_window_t) wdesc,
3579 (xcb_atom_t) dpyinfo->Xatom_XdndAware,
3580 XCB_ATOM_ATOM, 0, 1);
3581
3582 if (proxy_out)
3583 {
3584 reply = xcb_get_property_reply (dpyinfo->xcb_connection,
3585 xdnd_proxy_cookie, &error);
3586
3587 if (!reply)
3588 free (error);
3589 else
3590 {
3591 if (reply->format == 32
3592 && reply->type == XCB_ATOM_WINDOW
3593 && (xcb_get_property_value_length (reply) >= 4))
3594 *proxy_out = *(xcb_window_t *) xcb_get_property_value (reply);
3595
3596 free (reply);
3597 }
3598 }
3599
3600 if (proto_out)
3601 {
3602 reply = xcb_get_property_reply (dpyinfo->xcb_connection,
3603 xdnd_proto_cookie, &error);
3604
3605 if (!reply)
3606 free (error);
3607 else
3608 {
3609 if (reply->format == 32
3610 && reply->type == XCB_ATOM_ATOM
3611 && (xcb_get_property_value_length (reply) >= 4))
3612 *proto_out = (int) *(xcb_atom_t *) xcb_get_property_value (reply);
3613
3614 free (reply);
3615 }
3616 }
3617 }
3618 #endif
3619
3620 #ifdef HAVE_XSHAPE
3621 static bool
3622 x_dnd_get_target_window_2 (XRectangle *rects, int nrects,
3623 int x, int y)
3624 {
3625 int i;
3626 XRectangle *tem;
3627
3628 for (i = 0; i < nrects; ++i)
3629 {
3630 tem = &rects[i];
3631
3632 if (x >= tem->x && y >= tem->y
3633 && x < tem->x + tem->width
3634 && y < tem->y + tem->height)
3635 return true;
3636 }
3637
3638 return false;
3639 }
3640 #endif
3641
3642 static Window
3643 x_dnd_get_target_window_1 (struct x_display_info *dpyinfo,
3644 int root_x, int root_y, int *motif_out,
3645 bool *extents_p)
3646 {
3647 struct x_client_list_window *tem, *chosen = NULL;
3648
3649
3650
3651
3652 *motif_out = XM_DRAG_STYLE_NONE;
3653
3654 for (tem = x_dnd_toplevels; tem; tem = tem->next)
3655 {
3656 if (!tem->mapped_p || tem->wm_state != NormalState)
3657 continue;
3658
3659
3660
3661
3662 *extents_p = true;
3663 if (root_x > tem->x - tem->frame_extents_left
3664 && root_x < tem->x
3665 && root_y > tem->y - tem->frame_extents_top
3666 && root_y < (tem->y + tem->height - 1
3667 + tem->frame_extents_bottom))
3668 return None;
3669
3670 if (root_x > tem->x + tem->width
3671 && root_x < (tem->x + tem->width - 1
3672 + tem->frame_extents_right)
3673 && root_y > tem->y - tem->frame_extents_top
3674 && root_y < (tem->y + tem->height - 1
3675 + tem->frame_extents_bottom))
3676 return None;
3677
3678 if (root_y > tem->y - tem->frame_extents_top
3679 && root_y < tem->y
3680 && root_x > tem->x - tem->frame_extents_left
3681 && root_x < (tem->x + tem->width - 1
3682 + tem->frame_extents_right))
3683 return None;
3684
3685 if (root_y > tem->y + tem->height
3686 && root_y < (tem->y + tem->height - 1
3687 + tem->frame_extents_bottom)
3688 && root_x >= tem->x - tem->frame_extents_left
3689 && root_x < (tem->x + tem->width - 1
3690 + tem->frame_extents_right))
3691 return None;
3692 *extents_p = false;
3693
3694 if (root_x >= tem->x && root_y >= tem->y
3695 && root_x < tem->x + tem->width
3696 && root_y < tem->y + tem->height)
3697 {
3698 #ifdef HAVE_XSHAPE
3699 if (tem->n_bounding_rects == -1)
3700 #endif
3701 {
3702 chosen = tem;
3703 break;
3704 }
3705
3706 #ifdef HAVE_XSHAPE
3707 if (x_dnd_get_target_window_2 (tem->bounding_rects,
3708 tem->n_bounding_rects,
3709 tem->border_width + root_x - tem->x,
3710 tem->border_width + root_y - tem->y))
3711 {
3712 if (tem->n_input_rects == -1
3713 || x_dnd_get_target_window_2 (tem->input_rects,
3714 tem->n_input_rects,
3715 tem->border_width + root_x - tem->x,
3716 tem->border_width + root_y - tem->y))
3717 {
3718 chosen = tem;
3719 break;
3720 }
3721 }
3722 #endif
3723 }
3724 }
3725
3726 if (chosen)
3727 {
3728 *motif_out = (x_dnd_disable_motif_protocol
3729 ? XM_DRAG_STYLE_NONE
3730 : chosen->xm_protocol_style);
3731 return chosen->window;
3732 }
3733 else
3734 *motif_out = XM_DRAG_STYLE_NONE;
3735
3736 return None;
3737 }
3738
3739 static int
3740 x_dnd_get_wm_state_and_proto (struct x_display_info *dpyinfo,
3741 Window window, int *wmstate_out,
3742 int *proto_out, int *motif_out,
3743 Window *proxy_out)
3744 {
3745 #ifndef USE_XCB
3746 Atom type;
3747 int format;
3748 unsigned long nitems, bytes_after;
3749 unsigned char *data = NULL;
3750 xm_drag_receiver_info xm_info;
3751 #else
3752 xcb_get_property_cookie_t wmstate_cookie;
3753 xcb_get_property_cookie_t xdnd_proto_cookie;
3754 xcb_get_property_cookie_t xdnd_proxy_cookie;
3755 xcb_get_property_cookie_t xm_style_cookie;
3756 xcb_get_property_reply_t *reply;
3757 xcb_generic_error_t *error;
3758 uint8_t *xmdata;
3759 #endif
3760 int rc;
3761
3762 #ifndef USE_XCB
3763 x_catch_errors (dpyinfo->display);
3764 rc = ((XGetWindowProperty (dpyinfo->display, window,
3765 dpyinfo->Xatom_wm_state,
3766 0, 2, False, AnyPropertyType,
3767 &type, &format, &nitems,
3768 &bytes_after, &data)
3769 == Success)
3770 && !x_had_errors_p (dpyinfo->display)
3771 && data && nitems == 2 && format == 32);
3772 x_uncatch_errors ();
3773
3774 if (rc)
3775 *wmstate_out = *(unsigned long *) data;
3776
3777 *proto_out = x_dnd_get_window_proto (dpyinfo, window);
3778
3779 if (!xm_read_drag_receiver_info (dpyinfo, window, &xm_info))
3780 *motif_out = xm_info.protocol_style;
3781 else
3782 *motif_out = XM_DRAG_STYLE_NONE;
3783
3784 *proxy_out = x_dnd_get_window_proxy (dpyinfo, window);
3785
3786 if (data)
3787 XFree (data);
3788 #else
3789 rc = true;
3790
3791 wmstate_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
3792 (xcb_window_t) window,
3793 (xcb_atom_t) dpyinfo->Xatom_wm_state,
3794 XCB_ATOM_ANY, 0, 2);
3795 xdnd_proto_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
3796 (xcb_window_t) window,
3797 (xcb_atom_t) dpyinfo->Xatom_XdndAware,
3798 XCB_ATOM_ATOM, 0, 1);
3799 xdnd_proxy_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
3800 (xcb_window_t) window,
3801 (xcb_atom_t) dpyinfo->Xatom_XdndProxy,
3802 XCB_ATOM_WINDOW, 0, 1);
3803 xm_style_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
3804 (xcb_window_t) window,
3805 (xcb_atom_t) dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO,
3806 (xcb_atom_t) dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO,
3807 0, 4);
3808
3809 reply = xcb_get_property_reply (dpyinfo->xcb_connection,
3810 wmstate_cookie, &error);
3811
3812 if (!reply)
3813 free (error), rc = false;
3814 else
3815 {
3816 if (reply->format != 32
3817 || xcb_get_property_value_length (reply) != 8)
3818 rc = false;
3819 else
3820 *wmstate_out = *(uint32_t *) xcb_get_property_value (reply);
3821
3822 free (reply);
3823 }
3824
3825 reply = xcb_get_property_reply (dpyinfo->xcb_connection,
3826 xdnd_proto_cookie, &error);
3827
3828 *proto_out = -1;
3829 if (!reply)
3830 free (error);
3831 else
3832 {
3833 if (reply->format == 32
3834 && xcb_get_property_value_length (reply) >= 4)
3835 *proto_out = *(uint32_t *) xcb_get_property_value (reply);
3836
3837 free (reply);
3838 }
3839
3840 *proxy_out = None;
3841 reply = xcb_get_property_reply (dpyinfo->xcb_connection,
3842 xdnd_proxy_cookie, &error);
3843
3844 if (!reply)
3845 free (error);
3846 else
3847 {
3848 if (reply->format == 32
3849 && reply->type == XCB_ATOM_WINDOW
3850 && (xcb_get_property_value_length (reply) >= 4))
3851 *proxy_out = *(xcb_window_t *) xcb_get_property_value (reply);
3852
3853 free (reply);
3854 }
3855
3856 *motif_out = XM_DRAG_STYLE_NONE;
3857
3858 reply = xcb_get_property_reply (dpyinfo->xcb_connection,
3859 xm_style_cookie, &error);
3860
3861 if (!reply)
3862 free (error);
3863 else
3864 {
3865 if (reply->format == 8
3866 && reply->type == dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO
3867 && xcb_get_property_value_length (reply) >= 4)
3868 {
3869 xmdata = xcb_get_property_value (reply);
3870 *motif_out = xmdata[2];
3871 }
3872
3873 free (reply);
3874 }
3875 #endif
3876
3877 return rc;
3878 }
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904 void
3905 x_dnd_do_unsupported_drop (struct x_display_info *dpyinfo,
3906 Lisp_Object frame, Lisp_Object value,
3907 Lisp_Object targets, Window target_window,
3908 int root_x, int root_y, Time before)
3909 {
3910 XEvent event;
3911 int dest_x, dest_y;
3912 Window child_return, child, owner;
3913 Lisp_Object current_value;
3914 struct frame *f;
3915
3916 f = decode_window_system_frame (frame);
3917
3918 if (NILP (value))
3919 return;
3920
3921 if (!x_dnd_use_unsupported_drop)
3922 return;
3923
3924 event.xbutton.serial = 0;
3925 event.xbutton.send_event = True;
3926 event.xbutton.display = dpyinfo->display;
3927 event.xbutton.root = dpyinfo->root_window;
3928 event.xbutton.x_root = root_x;
3929 event.xbutton.y_root = root_y;
3930
3931 x_catch_errors (dpyinfo->display);
3932
3933 child = dpyinfo->root_window;
3934 dest_x = root_x;
3935 dest_y = root_y;
3936
3937 while (XTranslateCoordinates (dpyinfo->display, dpyinfo->root_window,
3938 child, root_x, root_y, &dest_x, &dest_y,
3939 &child_return)
3940 && child_return != None)
3941 child = child_return;
3942
3943 x_uncatch_errors ();
3944
3945 if (!CONSP (value))
3946 return;
3947
3948 current_value = assq_no_quit (QPRIMARY,
3949 dpyinfo->terminal->Vselection_alist);
3950
3951 if (!NILP (current_value))
3952 current_value = XCAR (XCDR (current_value));
3953
3954 x_own_selection (QPRIMARY, current_value, frame,
3955 XCAR (XCDR (value)), before);
3956
3957 owner = XGetSelectionOwner (dpyinfo->display, XA_PRIMARY);
3958
3959
3960
3961
3962 if (owner != FRAME_X_WINDOW (f))
3963 return;
3964
3965 event.xbutton.window = child;
3966 event.xbutton.subwindow = None;
3967 event.xbutton.x = dest_x;
3968 event.xbutton.y = dest_y;
3969 event.xbutton.state = 0;
3970 event.xbutton.button = 2;
3971 event.xbutton.same_screen = True;
3972
3973 dpyinfo->pending_dnd_time = before;
3974
3975 event.xbutton.type = ButtonPress;
3976 event.xbutton.time = before + 1;
3977
3978 x_ignore_errors_for_next_request (dpyinfo);
3979 XSendEvent (dpyinfo->display, child,
3980 True, ButtonPressMask, &event);
3981
3982 event.xbutton.type = ButtonRelease;
3983 event.xbutton.time = before + 2;
3984
3985 XSendEvent (dpyinfo->display, child,
3986 True, ButtonReleaseMask, &event);
3987 x_stop_ignoring_errors (dpyinfo);
3988
3989 x_dnd_action_symbol = QXdndActionPrivate;
3990
3991 return;
3992 }
3993
3994 static void
3995 x_dnd_send_unsupported_drop (struct x_display_info *dpyinfo, Window target_window,
3996 int root_x, int root_y, Time before)
3997 {
3998 Lisp_Object targets, arg;
3999 int i;
4000 char **atom_names, *name;
4001
4002 targets = Qnil;
4003 atom_names = alloca (sizeof *atom_names * x_dnd_n_targets);
4004
4005 if (!XGetAtomNames (dpyinfo->display, x_dnd_targets,
4006 x_dnd_n_targets, atom_names))
4007 return;
4008
4009 for (i = x_dnd_n_targets; i > 0; --i)
4010 {
4011 targets = Fcons (build_string (atom_names[i - 1]),
4012 targets);
4013 XFree (atom_names[i - 1]);
4014 }
4015
4016 name = x_get_atom_name (dpyinfo, x_dnd_wanted_action,
4017 NULL);
4018
4019 if (name)
4020 {
4021 arg = intern (name);
4022 xfree (name);
4023 }
4024 else
4025 arg = Qnil;
4026
4027 x_dnd_run_unsupported_drop_function = true;
4028 x_dnd_unsupported_drop_time = before;
4029 x_dnd_unsupported_drop_window = target_window;
4030 x_dnd_unsupported_drop_data
4031 = listn (5, assq_no_quit (QXdndSelection,
4032 dpyinfo->terminal->Vselection_alist),
4033 targets, arg, make_fixnum (root_x),
4034 make_fixnum (root_y));
4035
4036 x_dnd_waiting_for_finish = true;
4037 x_dnd_finish_display = dpyinfo->display;
4038 }
4039
4040 static Window
4041 x_dnd_fill_empty_target (int *proto_out, int *motif_out,
4042 Window *toplevel_out, bool *was_frame)
4043 {
4044 *proto_out = -1;
4045 *motif_out = XM_DRAG_STYLE_NONE;
4046 *toplevel_out = None;
4047 *was_frame = false;
4048
4049 return None;
4050 }
4051
4052 static Window
4053 x_dnd_get_target_window (struct x_display_info *dpyinfo,
4054 int root_x, int root_y, int *proto_out,
4055 int *motif_out, Window *toplevel_out,
4056 bool *was_frame)
4057 {
4058 Window child_return, child, proxy;
4059 int dest_x_return, dest_y_return, rc, proto, motif;
4060 int parent_x, parent_y;
4061 bool extents_p;
4062 #if defined HAVE_XCOMPOSITE && (XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR > 2)
4063 Window overlay_window;
4064 XWindowAttributes attrs;
4065 #endif
4066 int wmstate;
4067 struct frame *tooltip, *f;
4068 bool unrelated;
4069
4070 child_return = dpyinfo->root_window;
4071 dest_x_return = root_x;
4072 dest_y_return = root_y;
4073
4074 proto = -1;
4075 *motif_out = XM_DRAG_STYLE_NONE;
4076 *toplevel_out = None;
4077 *was_frame = false;
4078
4079 if (x_dnd_use_toplevels)
4080 {
4081 extents_p = false;
4082 child = x_dnd_get_target_window_1 (dpyinfo, root_x,
4083 root_y, motif_out,
4084 &extents_p);
4085
4086 if (!x_dnd_allow_current_frame
4087 && FRAME_X_WINDOW (x_dnd_frame) == child)
4088 *motif_out = XM_DRAG_STYLE_NONE;
4089
4090 f = x_top_window_to_frame (dpyinfo, child);
4091
4092 *toplevel_out = child;
4093
4094 if (child != None)
4095 {
4096 if (f)
4097 {
4098 *was_frame = true;
4099 *proto_out = -1;
4100 *motif_out = XM_DRAG_STYLE_NONE;
4101
4102 return child;
4103 }
4104
4105 #ifndef USE_XCB
4106 proxy = x_dnd_get_window_proxy (dpyinfo, child);
4107 #else
4108 x_dnd_get_proxy_proto (dpyinfo, child, &proxy, proto_out);
4109 #endif
4110
4111 if (proxy != None)
4112 {
4113 proto = x_dnd_get_window_proto (dpyinfo, proxy);
4114
4115 if (proto != -1)
4116 {
4117 *proto_out = proto;
4118 return proxy;
4119 }
4120 }
4121
4122 #ifndef USE_XCB
4123 *proto_out = x_dnd_get_window_proto (dpyinfo, child);
4124 #endif
4125 return child;
4126 }
4127
4128 if (extents_p)
4129 {
4130 *proto_out = -1;
4131 *motif_out = XM_DRAG_STYLE_NONE;
4132 *toplevel_out = None;
4133
4134 return None;
4135 }
4136
4137
4138 #if defined HAVE_XCOMPOSITE && (XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR > 2)
4139 if (dpyinfo->composite_supported_p
4140 && (dpyinfo->composite_major > 0
4141 || dpyinfo->composite_minor > 2))
4142 {
4143 if (XGetSelectionOwner (dpyinfo->display,
4144 dpyinfo->Xatom_NET_WM_CM_Sn) != None)
4145 {
4146 x_catch_errors (dpyinfo->display);
4147 XGrabServer (dpyinfo->display);
4148 overlay_window = XCompositeGetOverlayWindow (dpyinfo->display,
4149 dpyinfo->root_window);
4150 XCompositeReleaseOverlayWindow (dpyinfo->display,
4151 dpyinfo->root_window);
4152 XUngrabServer (dpyinfo->display);
4153
4154 if (!x_had_errors_p (dpyinfo->display))
4155 {
4156 XGetWindowAttributes (dpyinfo->display, overlay_window, &attrs);
4157
4158 if (attrs.map_state == IsViewable)
4159 {
4160 proxy = x_dnd_get_window_proxy (dpyinfo, overlay_window);
4161
4162 if (proxy != None)
4163 {
4164 proto = x_dnd_get_window_proto (dpyinfo, proxy);
4165
4166 if (proto != -1)
4167 {
4168 *proto_out = proto;
4169 *toplevel_out = overlay_window;
4170 x_uncatch_errors_after_check ();
4171
4172 return proxy;
4173 }
4174 }
4175 }
4176 }
4177 x_uncatch_errors_after_check ();
4178 }
4179 }
4180 #endif
4181
4182
4183
4184 proxy = x_dnd_get_window_proxy (dpyinfo, dpyinfo->root_window);
4185
4186 if (proxy != None)
4187 {
4188 proto = x_dnd_get_window_proto (dpyinfo, dpyinfo->root_window);
4189
4190 if (proto != -1)
4191 {
4192 *toplevel_out = dpyinfo->root_window;
4193 *proto_out = proto;
4194 return proxy;
4195 }
4196 }
4197
4198
4199
4200 *proto_out = -1;
4201 *toplevel_out = dpyinfo->root_window;
4202 return None;
4203 }
4204
4205
4206 child = dpyinfo->root_window;
4207
4208 while (child_return != None)
4209 {
4210 child = child_return;
4211 parent_x = dest_x_return;
4212 parent_y = dest_y_return;
4213
4214 x_catch_errors (dpyinfo->display);
4215 rc = XTranslateCoordinates (dpyinfo->display, dpyinfo->root_window,
4216 child_return, root_x, root_y, &dest_x_return,
4217 &dest_y_return, &child_return);
4218
4219 if (x_had_errors_p (dpyinfo->display) || !rc)
4220 {
4221 x_uncatch_errors_after_check ();
4222 break;
4223 }
4224
4225 if (child_return)
4226 {
4227
4228
4229
4230 tooltip = x_tooltip_window_to_frame (dpyinfo, child_return,
4231 &unrelated);
4232
4233 if (tooltip || unrelated)
4234 child_return = x_get_window_below (dpyinfo->display, child_return,
4235 parent_x, parent_y, &dest_x_return,
4236 &dest_y_return);
4237
4238 if (!child_return)
4239 {
4240 x_uncatch_errors ();
4241 break;
4242 }
4243
4244 f = x_top_window_to_frame (dpyinfo, child_return);
4245
4246 if (f)
4247 {
4248 *proto_out = -1;
4249 *motif_out = XM_DRAG_STYLE_NONE;
4250 *toplevel_out = child_return;
4251 *was_frame = true;
4252
4253 return child_return;
4254 }
4255
4256 if (x_dnd_get_wm_state_and_proto (dpyinfo, child_return,
4257 &wmstate, &proto, &motif,
4258 &proxy)
4259
4260
4261 || proto != -1 || motif != XM_DRAG_STYLE_NONE)
4262 {
4263 *proto_out = proto;
4264 *motif_out = (x_dnd_disable_motif_protocol
4265 ? XM_DRAG_STYLE_NONE : motif);
4266 *toplevel_out = child_return;
4267 x_uncatch_errors ();
4268
4269 return child_return;
4270 }
4271
4272 if (proxy != None)
4273 {
4274 proto = x_dnd_get_window_proto (dpyinfo, proxy);
4275
4276 if (proto != -1)
4277 {
4278 *proto_out = proto;
4279 *toplevel_out = child_return;
4280
4281 x_uncatch_errors ();
4282 return proxy;
4283 }
4284 }
4285 }
4286
4287 x_uncatch_errors ();
4288 }
4289
4290 #if defined HAVE_XCOMPOSITE && (XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR > 2)
4291 if (child != dpyinfo->root_window)
4292 {
4293 #endif
4294 if (child != None)
4295 {
4296 proxy = x_dnd_get_window_proxy (dpyinfo, child);
4297
4298 if (proxy)
4299 {
4300 proto = x_dnd_get_window_proto (dpyinfo, proxy);
4301
4302 if (proto != -1)
4303 {
4304 *proto_out = proto;
4305 *toplevel_out = child;
4306 return proxy;
4307 }
4308 }
4309 }
4310
4311 *proto_out = x_dnd_get_window_proto (dpyinfo, child);
4312 return child;
4313 #if defined HAVE_XCOMPOSITE && (XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR > 2)
4314 }
4315 else if (dpyinfo->composite_supported_p
4316 && (dpyinfo->composite_major > 0
4317 || dpyinfo->composite_minor > 2))
4318 {
4319
4320 if (XGetSelectionOwner (dpyinfo->display,
4321 dpyinfo->Xatom_NET_WM_CM_Sn) != None)
4322 {
4323 x_catch_errors (dpyinfo->display);
4324 XGrabServer (dpyinfo->display);
4325 overlay_window = XCompositeGetOverlayWindow (dpyinfo->display,
4326 dpyinfo->root_window);
4327 XCompositeReleaseOverlayWindow (dpyinfo->display,
4328 dpyinfo->root_window);
4329 XUngrabServer (dpyinfo->display);
4330
4331 if (!x_had_errors_p (dpyinfo->display))
4332 {
4333 XGetWindowAttributes (dpyinfo->display, overlay_window, &attrs);
4334
4335 if (attrs.map_state == IsViewable)
4336 {
4337 proxy = x_dnd_get_window_proxy (dpyinfo, overlay_window);
4338
4339 if (proxy != None)
4340 {
4341 proto = x_dnd_get_window_proto (dpyinfo, proxy);
4342
4343 if (proto != -1)
4344 {
4345 *proto_out = proto;
4346 *toplevel_out = overlay_window;
4347 x_uncatch_errors_after_check ();
4348
4349 return proxy;
4350 }
4351 }
4352 }
4353 }
4354 x_uncatch_errors_after_check ();
4355 }
4356 }
4357
4358 if (child != None)
4359 {
4360 proxy = x_dnd_get_window_proxy (dpyinfo, child);
4361
4362 if (proxy)
4363 {
4364 proto = x_dnd_get_window_proto (dpyinfo, proxy);
4365
4366 if (proto != -1)
4367 {
4368 *toplevel_out = child;
4369 *proto_out = proto;
4370 return proxy;
4371 }
4372 }
4373 }
4374
4375 *proto_out = x_dnd_get_window_proto (dpyinfo, child);
4376 *toplevel_out = child;
4377 return child;
4378 #endif
4379 }
4380
4381 static Window
4382 x_dnd_get_window_proxy (struct x_display_info *dpyinfo, Window wdesc)
4383 {
4384 int rc, actual_format;
4385 unsigned long actual_size, bytes_remaining;
4386 unsigned char *tmp_data = NULL;
4387 XWindowAttributes attrs;
4388 Atom actual_type;
4389 Window proxy;
4390
4391 proxy = None;
4392 x_catch_errors (dpyinfo->display);
4393 rc = XGetWindowProperty (dpyinfo->display, wdesc,
4394 dpyinfo->Xatom_XdndProxy,
4395 0, 1, False, XA_WINDOW,
4396 &actual_type, &actual_format,
4397 &actual_size, &bytes_remaining,
4398 &tmp_data);
4399
4400 if (!x_had_errors_p (dpyinfo->display)
4401 && rc == Success
4402 && tmp_data
4403 && actual_type == XA_WINDOW
4404 && actual_format == 32
4405 && actual_size == 1)
4406 {
4407 proxy = *(Window *) tmp_data;
4408
4409
4410 XGetWindowAttributes (dpyinfo->display, proxy, &attrs);
4411
4412 if (x_had_errors_p (dpyinfo->display))
4413 proxy = None;
4414 }
4415
4416 if (tmp_data)
4417 XFree (tmp_data);
4418 x_uncatch_errors_after_check ();
4419
4420 return proxy;
4421 }
4422
4423 static int
4424 x_dnd_get_window_proto (struct x_display_info *dpyinfo, Window wdesc)
4425 {
4426 Atom actual, value;
4427 unsigned char *tmp_data = NULL;
4428 int rc, format;
4429 unsigned long n, left;
4430 bool had_errors;
4431
4432 if (wdesc == None || (!x_dnd_allow_current_frame
4433 && wdesc == FRAME_OUTER_WINDOW (x_dnd_frame)))
4434 return -1;
4435
4436 x_catch_errors (dpyinfo->display);
4437 rc = XGetWindowProperty (dpyinfo->display, wdesc, dpyinfo->Xatom_XdndAware,
4438 0, 1, False, XA_ATOM, &actual, &format, &n, &left,
4439 &tmp_data);
4440 had_errors = x_had_errors_p (dpyinfo->display);
4441 x_uncatch_errors_after_check ();
4442
4443 if (had_errors || rc != Success || actual != XA_ATOM || format != 32 || n < 1
4444 || !tmp_data)
4445 {
4446 if (tmp_data)
4447 XFree (tmp_data);
4448 return -1;
4449 }
4450
4451 value = (int) *(Atom *) tmp_data;
4452 XFree (tmp_data);
4453
4454 return min (X_DND_SUPPORTED_VERSION, (int) value);
4455 }
4456
4457 static void
4458 x_dnd_send_enter (struct frame *f, Window target, Window toplevel,
4459 int supported)
4460 {
4461 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
4462 int i;
4463 XEvent msg;
4464
4465 msg.xclient.type = ClientMessage;
4466 msg.xclient.message_type = dpyinfo->Xatom_XdndEnter;
4467 msg.xclient.format = 32;
4468 msg.xclient.window = toplevel;
4469 msg.xclient.data.l[0] = FRAME_X_WINDOW (f);
4470 msg.xclient.data.l[1] = (((unsigned int) min (X_DND_SUPPORTED_VERSION,
4471 supported) << 24)
4472 | (x_dnd_n_targets > 3 ? 1 : 0));
4473 msg.xclient.data.l[2] = 0;
4474 msg.xclient.data.l[3] = 0;
4475 msg.xclient.data.l[4] = 0;
4476
4477 for (i = 0; i < min (3, x_dnd_n_targets); ++i)
4478 msg.xclient.data.l[i + 2] = x_dnd_targets[i];
4479
4480 if (x_dnd_n_targets > 3 && !x_dnd_init_type_lists)
4481 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4482 dpyinfo->Xatom_XdndTypeList, XA_ATOM, 32,
4483 PropModeReplace, (unsigned char *) x_dnd_targets,
4484 x_dnd_n_targets);
4485
4486
4487
4488 x_dnd_init_type_lists = true;
4489
4490 x_ignore_errors_for_next_request (dpyinfo);
4491 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
4492 x_stop_ignoring_errors (dpyinfo);
4493 }
4494
4495 static void
4496 x_dnd_send_position (struct frame *f, Window target, Window toplevel,
4497 int supported, unsigned short root_x,
4498 unsigned short root_y, Time timestamp, Atom action,
4499 int button, unsigned state)
4500 {
4501 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
4502 XEvent msg;
4503
4504 msg.xclient.type = ClientMessage;
4505 msg.xclient.message_type = dpyinfo->Xatom_XdndPosition;
4506 msg.xclient.format = 32;
4507 msg.xclient.window = toplevel;
4508 msg.xclient.data.l[0] = FRAME_X_WINDOW (f);
4509 msg.xclient.data.l[1] = 0;
4510
4511
4512
4513
4514
4515
4516
4517 if (button >= 4 && button <= 7)
4518 {
4519 msg.xclient.data.l[1] |= (1 << 10);
4520 msg.xclient.data.l[1] |= (button - 4) << 8;
4521 }
4522 else if (button)
4523 return;
4524
4525 msg.xclient.data.l[1] |= state & 0xff;
4526
4527 msg.xclient.data.l[2] = (root_x << 16) | root_y;
4528 msg.xclient.data.l[3] = 0;
4529 msg.xclient.data.l[4] = 0;
4530
4531 if (supported >= 3)
4532 msg.xclient.data.l[3] = timestamp;
4533
4534 if (supported >= 4)
4535 msg.xclient.data.l[4] = action;
4536
4537 if (x_dnd_waiting_for_status_window == target)
4538 {
4539 x_dnd_pending_send_position = msg;
4540 x_dnd_pending_send_position_button = button;
4541 x_dnd_pending_send_position_root_x = root_x;
4542 x_dnd_pending_send_position_root_y = root_y;
4543 }
4544 else
4545 {
4546 if (target == x_dnd_mouse_rect_target
4547 && x_dnd_mouse_rect.width
4548 && x_dnd_mouse_rect.height
4549
4550
4551 && !button)
4552 {
4553 if (root_x >= x_dnd_mouse_rect.x
4554 && root_x < (x_dnd_mouse_rect.x
4555 + x_dnd_mouse_rect.width)
4556 && root_y >= x_dnd_mouse_rect.y
4557 && root_y < (x_dnd_mouse_rect.y
4558 + x_dnd_mouse_rect.height))
4559 return;
4560 }
4561
4562 x_ignore_errors_for_next_request (dpyinfo);
4563 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
4564 x_stop_ignoring_errors (dpyinfo);
4565
4566 x_dnd_waiting_for_status_window = target;
4567 }
4568 }
4569
4570 static void
4571 x_dnd_send_leave (struct frame *f, Window target, Window toplevel)
4572 {
4573 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
4574 XEvent msg;
4575
4576 msg.xclient.type = ClientMessage;
4577 msg.xclient.message_type = dpyinfo->Xatom_XdndLeave;
4578 msg.xclient.format = 32;
4579 msg.xclient.window = toplevel;
4580 msg.xclient.data.l[0] = FRAME_X_WINDOW (f);
4581 msg.xclient.data.l[1] = 0;
4582 msg.xclient.data.l[2] = 0;
4583 msg.xclient.data.l[3] = 0;
4584 msg.xclient.data.l[4] = 0;
4585
4586 x_dnd_waiting_for_status_window = None;
4587 x_dnd_pending_send_position.type = 0;
4588
4589 x_ignore_errors_for_next_request (dpyinfo);
4590 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
4591 x_stop_ignoring_errors (dpyinfo);
4592 }
4593
4594 static bool
4595 x_dnd_send_drop (struct frame *f, Window target, Window toplevel,
4596 Time timestamp, int supported)
4597 {
4598 struct x_display_info *dpyinfo;
4599 XEvent msg;
4600
4601 if (x_dnd_action == None)
4602 {
4603 x_dnd_send_leave (f, target, toplevel);
4604 return false;
4605 }
4606
4607 dpyinfo = FRAME_DISPLAY_INFO (f);
4608
4609 msg.xclient.type = ClientMessage;
4610 msg.xclient.message_type = dpyinfo->Xatom_XdndDrop;
4611 msg.xclient.format = 32;
4612 msg.xclient.window = toplevel;
4613 msg.xclient.data.l[0] = FRAME_X_WINDOW (f);
4614 msg.xclient.data.l[1] = 0;
4615 msg.xclient.data.l[2] = 0;
4616 msg.xclient.data.l[3] = 0;
4617 msg.xclient.data.l[4] = 0;
4618
4619 if (supported >= 1)
4620 msg.xclient.data.l[2] = timestamp;
4621
4622 x_ignore_errors_for_next_request (dpyinfo);
4623 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
4624 x_stop_ignoring_errors (dpyinfo);
4625 return true;
4626 }
4627
4628 static bool
4629 x_dnd_do_drop (Window target, Window toplevel, int supported)
4630 {
4631 if (x_dnd_waiting_for_status_window != target)
4632 return x_dnd_send_drop (x_dnd_frame, target, toplevel,
4633 x_dnd_selection_timestamp, supported);
4634
4635 x_dnd_need_send_drop = true;
4636 x_dnd_send_drop_proto = supported;
4637
4638 return true;
4639 }
4640
4641 static void
4642 x_set_dnd_targets (Atom *targets, int ntargets)
4643 {
4644 if (x_dnd_targets)
4645 xfree (x_dnd_targets);
4646
4647 block_input ();
4648 x_dnd_targets = xmalloc (sizeof *targets * ntargets);
4649 x_dnd_n_targets = ntargets;
4650
4651 memcpy (x_dnd_targets, targets,
4652 sizeof *targets * ntargets);
4653 unblock_input ();
4654 }
4655
4656 static void
4657 x_free_dnd_targets (void)
4658 {
4659 if (!x_dnd_targets)
4660 return;
4661
4662 xfree (x_dnd_targets);
4663 x_dnd_targets = NULL;
4664 x_dnd_n_targets = 0;
4665 }
4666
4667
4668
4669
4670 static void
4671 x_clear_dnd_variables (void)
4672 {
4673 x_dnd_monitors = Qnil;
4674 x_dnd_unsupported_drop_data = Qnil;
4675 }
4676
4677 static void
4678 x_free_dnd_toplevels (void)
4679 {
4680 if (!x_dnd_use_toplevels || !x_dnd_toplevels)
4681 return;
4682
4683
4684
4685
4686 x_dnd_free_toplevels (true);
4687 }
4688
4689
4690
4691 static void
4692 x_restore_events_after_dnd (struct frame *f, XWindowAttributes *wa)
4693 {
4694 struct x_display_info *dpyinfo;
4695
4696 dpyinfo = FRAME_DISPLAY_INFO (f);
4697
4698
4699 XSelectInput (dpyinfo->display, dpyinfo->root_window,
4700 wa->your_event_mask);
4701 #ifdef HAVE_XKB
4702 if (dpyinfo->supports_xkb)
4703 XkbSelectEvents (dpyinfo->display, XkbUseCoreKbd,
4704 XkbStateNotifyMask, 0);
4705 #endif
4706
4707 if (x_dnd_motif_setup_p)
4708 XDeleteProperty (dpyinfo->display, FRAME_X_WINDOW (f),
4709 x_dnd_motif_atom);
4710
4711
4712 if (x_dnd_init_type_lists && x_dnd_n_targets > 3)
4713 XDeleteProperty (dpyinfo->display, FRAME_X_WINDOW (f),
4714 dpyinfo->Xatom_XdndTypeList);
4715 }
4716
4717 #ifdef HAVE_XINPUT2
4718
4719
4720
4721
4722
4723
4724 static void
4725 x_dnd_cancel_dnd_early (void)
4726 {
4727 struct frame *f;
4728 xm_drop_start_message dmsg;
4729
4730 eassert (x_dnd_frame && x_dnd_in_progress);
4731
4732 f = x_dnd_frame;
4733
4734 if (x_dnd_last_seen_window != None
4735 && x_dnd_last_protocol_version != -1)
4736 x_dnd_send_leave (x_dnd_frame,
4737 x_dnd_last_seen_window,
4738 x_dnd_last_seen_toplevel);
4739 else if (x_dnd_last_seen_window != None
4740 && !XM_DRAG_STYLE_IS_DROP_ONLY (x_dnd_last_motif_style)
4741 && x_dnd_last_motif_style != XM_DRAG_STYLE_NONE
4742 && x_dnd_motif_setup_p)
4743 {
4744 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
4745 XM_DRAG_REASON_DROP_START);
4746 dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST;
4747 dmsg.timestamp = FRAME_DISPLAY_INFO (f)->last_user_time;
4748 dmsg.side_effects
4749 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f),
4750 x_dnd_wanted_action),
4751 XM_DROP_SITE_VALID, x_dnd_motif_operations,
4752 XM_DROP_ACTION_DROP_CANCEL);
4753 dmsg.x = 0;
4754 dmsg.y = 0;
4755 dmsg.index_atom = x_dnd_motif_atom;
4756 dmsg.source_window = FRAME_X_WINDOW (f);
4757
4758 x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f,
4759 x_dnd_last_seen_window,
4760 FRAME_DISPLAY_INFO (f)->last_user_time);
4761 xm_send_drop_message (FRAME_DISPLAY_INFO (f), FRAME_X_WINDOW (f),
4762 x_dnd_last_seen_window, &dmsg);
4763 }
4764
4765 x_dnd_last_seen_window = None;
4766 x_dnd_last_seen_toplevel = None;
4767 x_dnd_in_progress = false;
4768 x_dnd_waiting_for_finish = false;
4769 x_dnd_return_frame_object = NULL;
4770 x_dnd_movement_frame = NULL;
4771 x_dnd_wheel_frame = NULL;
4772 x_dnd_frame = NULL;
4773 x_dnd_action = None;
4774 x_dnd_action_symbol = Qnil;
4775 }
4776
4777 #endif
4778
4779 static void
4780 x_dnd_cleanup_drag_and_drop (void *frame)
4781 {
4782 struct frame *f = frame;
4783 xm_drop_start_message dmsg;
4784
4785 if (!x_dnd_unwind_flag)
4786 return;
4787
4788 if (x_dnd_in_progress)
4789 {
4790 eassert (x_dnd_frame);
4791
4792 block_input ();
4793 if (x_dnd_last_seen_window != None
4794 && x_dnd_last_protocol_version != -1)
4795 x_dnd_send_leave (x_dnd_frame,
4796 x_dnd_last_seen_window,
4797 x_dnd_last_seen_toplevel);
4798 else if (x_dnd_last_seen_window != None
4799 && !XM_DRAG_STYLE_IS_DROP_ONLY (x_dnd_last_motif_style)
4800 && x_dnd_last_motif_style != XM_DRAG_STYLE_NONE
4801 && x_dnd_motif_setup_p)
4802 {
4803 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
4804 XM_DRAG_REASON_DROP_START);
4805 dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST;
4806 dmsg.timestamp = FRAME_DISPLAY_INFO (f)->last_user_time;
4807 dmsg.side_effects
4808 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f),
4809 x_dnd_wanted_action),
4810 XM_DROP_SITE_VALID, x_dnd_motif_operations,
4811 XM_DROP_ACTION_DROP_CANCEL);
4812 dmsg.x = 0;
4813 dmsg.y = 0;
4814 dmsg.index_atom = x_dnd_motif_atom;
4815 dmsg.source_window = FRAME_X_WINDOW (f);
4816
4817 x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f,
4818 x_dnd_last_seen_window,
4819 FRAME_DISPLAY_INFO (f)->last_user_time);
4820 xm_send_drop_message (FRAME_DISPLAY_INFO (f), FRAME_X_WINDOW (f),
4821 x_dnd_last_seen_window, &dmsg);
4822 }
4823 unblock_input ();
4824
4825 x_dnd_end_window = x_dnd_last_seen_window;
4826 x_dnd_last_seen_window = None;
4827 x_dnd_last_seen_toplevel = None;
4828 x_dnd_in_progress = false;
4829 }
4830
4831 x_dnd_waiting_for_finish = false;
4832
4833 FRAME_DISPLAY_INFO (f)->grabbed = 0;
4834 #ifdef USE_GTK
4835 current_hold_quit = NULL;
4836 #endif
4837 x_dnd_return_frame_object = NULL;
4838 x_dnd_movement_frame = NULL;
4839 x_dnd_wheel_frame = NULL;
4840 x_dnd_frame = NULL;
4841
4842 x_restore_events_after_dnd (f, &x_dnd_old_window_attrs);
4843 }
4844
4845 static void
4846 x_dnd_note_self_position (struct x_display_info *dpyinfo, Window target,
4847 unsigned short root_x, unsigned short root_y)
4848 {
4849 struct frame *f;
4850 int dest_x, dest_y;
4851
4852 f = x_top_window_to_frame (dpyinfo, target);
4853
4854 if (f)
4855 {
4856 x_translate_coordinates (f, root_x, root_y, &dest_x, &dest_y);
4857
4858 x_dnd_movement_frame = f;
4859 x_dnd_movement_x = dest_x;
4860 x_dnd_movement_y = dest_y;
4861
4862 return;
4863 }
4864 }
4865
4866 static void
4867 x_dnd_note_self_wheel (struct x_display_info *dpyinfo, Window target,
4868 unsigned short root_x, unsigned short root_y,
4869 int button, unsigned int state, Time time)
4870 {
4871 struct frame *f;
4872 int dest_x, dest_y;
4873
4874 if (button < 4 || button > 7)
4875 return;
4876
4877 f = x_top_window_to_frame (dpyinfo, target);
4878
4879 if (f)
4880 {
4881 x_translate_coordinates (f, root_x, root_y, &dest_x, &dest_y);
4882
4883 x_dnd_wheel_frame = f;
4884 x_dnd_wheel_x = dest_x;
4885 x_dnd_wheel_y = dest_y;
4886 x_dnd_wheel_button = button;
4887 x_dnd_wheel_state = state;
4888 x_dnd_wheel_time = time;
4889
4890 return;
4891 }
4892 }
4893
4894 static void
4895 x_dnd_note_self_drop (struct x_display_info *dpyinfo, Window target,
4896 unsigned short root_x, unsigned short root_y,
4897 Time timestamp)
4898 {
4899 struct input_event ie;
4900 struct frame *f;
4901 Lisp_Object lval;
4902 char **atom_names;
4903 char *name;
4904 int win_x, win_y, i;
4905
4906 if (!x_dnd_allow_current_frame
4907 && (FRAME_OUTER_WINDOW (x_dnd_frame)
4908 == target))
4909 return;
4910
4911 f = x_top_window_to_frame (dpyinfo, target);
4912
4913 if (!f)
4914 return;
4915
4916 if (NILP (Vx_dnd_native_test_function))
4917 return;
4918
4919 x_translate_coordinates (f, root_x, root_y, &win_x, &win_y);
4920
4921
4922
4923
4924
4925 XSETFRAME (lval, f);
4926 x_dnd_action = None;
4927 x_dnd_action_symbol
4928 = safe_call2 (Vx_dnd_native_test_function,
4929 Fposn_at_x_y (make_fixnum (win_x),
4930 make_fixnum (win_y),
4931 lval, Qnil),
4932 x_atom_to_symbol (dpyinfo,
4933 x_dnd_wanted_action));
4934
4935 if (!SYMBOLP (x_dnd_action_symbol))
4936 return;
4937
4938 EVENT_INIT (ie);
4939
4940 ie.kind = DRAG_N_DROP_EVENT;
4941 XSETFRAME (ie.frame_or_window, f);
4942
4943 lval = Qnil;
4944 atom_names = alloca (x_dnd_n_targets * sizeof *atom_names);
4945 name = x_get_atom_name (dpyinfo, x_dnd_wanted_action, NULL);
4946
4947 if (!XGetAtomNames (dpyinfo->display, x_dnd_targets,
4948 x_dnd_n_targets, atom_names))
4949 {
4950 xfree (name);
4951 return;
4952 }
4953
4954 for (i = x_dnd_n_targets; i != 0; --i)
4955 {
4956 lval = Fcons (intern (atom_names[i - 1]), lval);
4957 XFree (atom_names[i - 1]);
4958 }
4959
4960 lval = Fcons (assq_no_quit (QXdndSelection,
4961 FRAME_TERMINAL (f)->Vselection_alist),
4962 lval);
4963 lval = Fcons (intern (name), lval);
4964 lval = Fcons (QXdndSelection, lval);
4965 ie.arg = lval;
4966 ie.timestamp = timestamp;
4967
4968 XSETINT (ie.x, win_x);
4969 XSETINT (ie.y, win_y);
4970
4971 xfree (name);
4972 kbd_buffer_store_event (&ie);
4973 }
4974
4975
4976
4977 static void
4978 x_flush (struct frame *f)
4979 {
4980 eassert (f && FRAME_X_P (f));
4981
4982
4983 if (!NILP (Vinhibit_redisplay))
4984 return;
4985
4986 block_input ();
4987 XFlush (FRAME_X_DISPLAY (f));
4988 unblock_input ();
4989 }
4990
4991 #ifdef HAVE_XDBE
4992 static void
4993 x_drop_xrender_surfaces (struct frame *f)
4994 {
4995 font_drop_xrender_surfaces (f);
4996
4997 #ifdef HAVE_XRENDER
4998 if (f && FRAME_X_DOUBLE_BUFFERED_P (f)
4999 && FRAME_X_PICTURE (f) != None)
5000 {
5001 XRenderFreePicture (FRAME_X_DISPLAY (f),
5002 FRAME_X_PICTURE (f));
5003 FRAME_X_PICTURE (f) = None;
5004 }
5005 #endif
5006 }
5007 #endif
5008
5009 #ifdef HAVE_XRENDER
5010 void
5011 x_xr_ensure_picture (struct frame *f)
5012 {
5013 if (FRAME_X_PICTURE (f) == None && FRAME_X_PICTURE_FORMAT (f))
5014 {
5015 XRenderPictureAttributes attrs;
5016 attrs.clip_mask = None;
5017 XRenderPictFormat *fmt = FRAME_X_PICTURE_FORMAT (f);
5018
5019 FRAME_X_PICTURE (f) = XRenderCreatePicture (FRAME_X_DISPLAY (f),
5020 FRAME_X_RAW_DRAWABLE (f),
5021 fmt, CPClipMask, &attrs);
5022 }
5023 }
5024 #endif
5025
5026
5027
5028
5029
5030
5031 #if false
5032
5033
5034
5035
5036 struct record
5037 {
5038 char *locus;
5039 int type;
5040 };
5041
5042 struct record event_record[100];
5043
5044 int event_record_index;
5045
5046 void
5047 record_event (char *locus, int type)
5048 {
5049 if (event_record_index == ARRAYELTS (event_record))
5050 event_record_index = 0;
5051
5052 event_record[event_record_index].locus = locus;
5053 event_record[event_record_index].type = type;
5054 event_record_index++;
5055 }
5056
5057 #endif
5058
5059 #ifdef HAVE_XINPUT2
5060 bool
5061 xi_frame_selected_for (struct frame *f, unsigned long event)
5062 {
5063 XIEventMask *masks;
5064 int i;
5065
5066 masks = FRAME_X_OUTPUT (f)->xi_masks;
5067
5068 if (!masks)
5069 return false;
5070
5071 for (i = 0; i < FRAME_X_OUTPUT (f)->num_xi_masks; ++i)
5072 {
5073 if (masks[i].mask_len >= XIMaskLen (event)
5074 && XIMaskIsSet (masks[i].mask, event))
5075 return true;
5076 }
5077
5078 return false;
5079 }
5080 #endif
5081
5082 static void
5083 x_toolkit_position (struct frame *f, int x, int y,
5084 bool *menu_bar_p, bool *tool_bar_p)
5085 {
5086 #ifdef USE_GTK
5087 GdkRectangle test_rect;
5088 int scale;
5089
5090 y += (FRAME_MENUBAR_HEIGHT (f)
5091 + FRAME_TOOLBAR_TOP_HEIGHT (f));
5092 x += FRAME_TOOLBAR_LEFT_WIDTH (f);
5093
5094 if (FRAME_EXTERNAL_MENU_BAR (f))
5095 *menu_bar_p = (x >= 0 && x < FRAME_PIXEL_WIDTH (f)
5096 && y >= 0 && y < FRAME_MENUBAR_HEIGHT (f));
5097
5098 if (FRAME_X_OUTPUT (f)->toolbar_widget)
5099 {
5100 scale = xg_get_scale (f);
5101 test_rect.x = x / scale;
5102 test_rect.y = y / scale;
5103 test_rect.width = 1;
5104 test_rect.height = 1;
5105
5106 *tool_bar_p = gtk_widget_intersect (FRAME_X_OUTPUT (f)->toolbar_widget,
5107 &test_rect, NULL);
5108 }
5109 #elif defined USE_X_TOOLKIT
5110 *menu_bar_p = (x > 0 && x < FRAME_PIXEL_WIDTH (f)
5111 && (y < 0 && y >= -FRAME_MENUBAR_HEIGHT (f)));
5112 #else
5113 *menu_bar_p = (WINDOWP (f->menu_bar_window)
5114 && (x > 0 && x < FRAME_PIXEL_WIDTH (f)
5115 && (y > 0 && y < FRAME_MENU_BAR_HEIGHT (f))));
5116 #endif
5117 }
5118
5119 static void
5120 x_update_opaque_region (struct frame *f, XEvent *configure)
5121 {
5122 unsigned long opaque_region[] = {0, 0,
5123 (configure
5124 ? configure->xconfigure.width
5125 : FRAME_PIXEL_WIDTH (f)),
5126 (configure
5127 ? configure->xconfigure.height
5128 : FRAME_PIXEL_HEIGHT (f))};
5129 #ifdef HAVE_GTK3
5130 GObjectClass *object_class;
5131 GtkWidgetClass *class;
5132 #endif
5133
5134 if (!FRAME_DISPLAY_INFO (f)->alpha_bits)
5135 return;
5136
5137 if (f->alpha_background < 1.0)
5138 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5139 FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region,
5140 XA_CARDINAL, 32, PropModeReplace,
5141 NULL, 0);
5142 #ifndef HAVE_GTK3
5143 else
5144 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5145 FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region,
5146 XA_CARDINAL, 32, PropModeReplace,
5147 (unsigned char *) &opaque_region, 4);
5148 #else
5149 else if (FRAME_TOOLTIP_P (f))
5150 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5151 FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region,
5152 XA_CARDINAL, 32, PropModeReplace,
5153 (unsigned char *) &opaque_region, 4);
5154 else
5155 {
5156
5157
5158 if (!FRAME_PARENT_FRAME (f))
5159 {
5160 object_class = G_OBJECT_GET_CLASS (FRAME_GTK_OUTER_WIDGET (f));
5161 class = GTK_WIDGET_CLASS (object_class);
5162
5163 if (class->style_updated)
5164 class->style_updated (FRAME_GTK_OUTER_WIDGET (f));
5165 }
5166 }
5167 #endif
5168 }
5169
5170
5171 #if defined USE_CAIRO || defined HAVE_XRENDER
5172 static int
5173 x_gc_free_ext_data_private (XExtData *extension)
5174 {
5175 xfree (extension->private_data);
5176
5177 return 0;
5178 }
5179
5180 static struct x_gc_ext_data *
5181 x_gc_get_ext_data (struct frame *f, GC gc, int create_if_not_found_p)
5182 {
5183 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
5184 XEDataObject object;
5185 XExtData **head, *ext_data;
5186
5187 object.gc = gc;
5188 head = XEHeadOfExtensionList (object);
5189 ext_data = XFindOnExtensionList (head, dpyinfo->ext_codes->extension);
5190 if (ext_data == NULL)
5191 {
5192 if (!create_if_not_found_p)
5193 return NULL;
5194 else
5195 {
5196 ext_data = xzalloc (sizeof (*ext_data));
5197 ext_data->number = dpyinfo->ext_codes->extension;
5198 ext_data->private_data = xzalloc (sizeof (struct x_gc_ext_data));
5199 ext_data->free_private = x_gc_free_ext_data_private;
5200 XAddToExtensionList (head, ext_data);
5201 }
5202 }
5203 return (struct x_gc_ext_data *) ext_data->private_data;
5204 }
5205
5206 static void
5207 x_extension_initialize (struct x_display_info *dpyinfo)
5208 {
5209 XExtCodes *ext_codes = XAddExtension (dpyinfo->display);
5210
5211 dpyinfo->ext_codes = ext_codes;
5212 }
5213 #endif
5214
5215 #ifdef USE_CAIRO
5216
5217 #define FRAME_CR_CONTEXT(f) ((f)->output_data.x->cr_context)
5218 #define FRAME_CR_SURFACE_DESIRED_WIDTH(f) \
5219 ((f)->output_data.x->cr_surface_desired_width)
5220 #define FRAME_CR_SURFACE_DESIRED_HEIGHT(f) \
5221 ((f)->output_data.x->cr_surface_desired_height)
5222
5223 #endif
5224
5225 #ifdef HAVE_XINPUT2
5226
5227
5228
5229 static void
5230 xi_convert_button_state (XIButtonState *in, unsigned int *out)
5231 {
5232 int i;
5233
5234 if (in->mask_len)
5235 {
5236 for (i = 1; i <= 8; ++i)
5237 {
5238 if (XIMaskIsSet (in->mask, i))
5239 *out |= (Button1Mask << (i - 1));
5240 }
5241 }
5242 }
5243
5244
5245
5246
5247
5248 #ifdef USE_GTK
5249 static
5250 #endif
5251 unsigned int
5252 xi_convert_event_state (XIDeviceEvent *xev)
5253 {
5254 unsigned int mods, buttons;
5255
5256 mods = xev->mods.effective;
5257 buttons = 0;
5258
5259 xi_convert_button_state (&xev->buttons, &buttons);
5260
5261 return mods | buttons;
5262 }
5263
5264
5265
5266
5267
5268 static unsigned int
5269 xi_convert_event_keyboard_state (XIDeviceEvent *xev)
5270 {
5271 return ((xev->mods.effective & ~(1 << 13 | 1 << 14))
5272 | (xev->group.effective << 13));
5273 }
5274
5275
5276 static void
5277 x_free_xi_devices (struct x_display_info *dpyinfo)
5278 {
5279 #ifdef HAVE_XINPUT2_2
5280 struct xi_touch_point_t *tem, *last;
5281 #endif
5282
5283 block_input ();
5284
5285 if (dpyinfo->num_devices)
5286 {
5287 for (int i = 0; i < dpyinfo->num_devices; ++i)
5288 {
5289 #ifdef HAVE_XINPUT2_1
5290 xfree (dpyinfo->devices[i].valuators);
5291 #endif
5292
5293 #ifdef HAVE_XINPUT2_2
5294 tem = dpyinfo->devices[i].touchpoints;
5295 while (tem)
5296 {
5297 last = tem;
5298 tem = tem->next;
5299 xfree (last);
5300 }
5301 #endif
5302 }
5303
5304 xfree (dpyinfo->devices);
5305 dpyinfo->devices = NULL;
5306 dpyinfo->num_devices = 0;
5307 }
5308
5309 unblock_input ();
5310 }
5311
5312 #ifdef HAVE_XINPUT2_1
5313
5314 struct xi_known_valuator
5315 {
5316
5317 double current_value;
5318
5319
5320 int number;
5321
5322
5323 struct xi_known_valuator *next;
5324 };
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351 static void
5352 xi_populate_scroll_valuator (struct xi_device_t *device,
5353 int index, XIScrollClassInfo *info)
5354 {
5355 struct xi_scroll_valuator_t *valuator;
5356
5357 valuator = &device->valuators[index];
5358 valuator->horizontal
5359 = (info->scroll_type == XIScrollTypeHorizontal);
5360 valuator->invalid_p = true;
5361 valuator->emacs_value = DBL_MIN;
5362 valuator->increment = info->increment;
5363 valuator->number = info->number;
5364 }
5365
5366 #endif
5367
5368 static void
5369 xi_populate_device_from_info (struct x_display_info *dpyinfo,
5370 struct xi_device_t *xi_device,
5371 XIDeviceInfo *device)
5372 {
5373 #ifdef HAVE_XINPUT2_1
5374 struct xi_known_valuator *values, *tem;
5375 int actual_valuator_count, c;
5376 XIScrollClassInfo *info;
5377 XIValuatorClassInfo *valuator_info;
5378 #endif
5379 #ifdef HAVE_XINPUT2_2
5380 XITouchClassInfo *touch_info;
5381 #endif
5382
5383 #ifdef HAVE_XINPUT2_1
5384 USE_SAFE_ALLOCA;
5385 #endif
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
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 xi_device->device_id = device->deviceid;
5430 xi_device->grab = 0;
5431 xi_device->use = device->use;
5432 xi_device->name = build_string (device->name);
5433 xi_device->attachment = device->attachment;
5434
5435
5436
5437
5438 #ifdef HAVE_XINPUT2_2
5439 xi_device->touchpoints = NULL;
5440 xi_device->direct_p = false;
5441 #endif
5442
5443 #ifdef HAVE_XINPUT2_1
5444 if (!dpyinfo->xi2_version)
5445 {
5446
5447
5448 xi_device->valuators = NULL;
5449 xi_device->scroll_valuator_count = 0;
5450
5451 SAFE_FREE ();
5452 return;
5453 }
5454
5455 actual_valuator_count = 0;
5456 xi_device->valuators = xnmalloc (device->num_classes,
5457 sizeof *xi_device->valuators);
5458 values = NULL;
5459
5460
5461
5462
5463
5464
5465
5466
5467 for (c = 0; c < device->num_classes; ++c)
5468 {
5469 switch (device->classes[c]->type)
5470 {
5471 case XIScrollClass:
5472 {
5473 info = (XIScrollClassInfo *) device->classes[c];
5474 xi_populate_scroll_valuator (xi_device, actual_valuator_count++,
5475 info);
5476 break;
5477 }
5478
5479 case XIValuatorClass:
5480 {
5481 valuator_info = (XIValuatorClassInfo *) device->classes[c];
5482 tem = SAFE_ALLOCA (sizeof *tem);
5483
5484
5485
5486
5487
5488
5489
5490
5491 if (valuator_info->value == 0.0
5492 && valuator_info->mode != XIModeAbsolute)
5493 continue;
5494
5495 tem->next = values;
5496 tem->number = valuator_info->number;
5497 tem->current_value = valuator_info->value;
5498
5499 values = tem;
5500 break;
5501 }
5502
5503 #ifdef HAVE_XINPUT2_2
5504 case XITouchClass:
5505 {
5506 touch_info = (XITouchClassInfo *) device->classes[c];
5507 xi_device->direct_p = touch_info->mode == XIDirectTouch;
5508 }
5509 #endif
5510 default:
5511 break;
5512 }
5513 }
5514
5515 xi_device->scroll_valuator_count = actual_valuator_count;
5516
5517
5518
5519
5520
5521 for (tem = values; values; values = values->next)
5522 {
5523 for (c = 0; c < xi_device->scroll_valuator_count; ++c)
5524 {
5525 if (xi_device->valuators[c].number == tem->number)
5526 {
5527 xi_device->valuators[c].invalid_p = false;
5528 xi_device->valuators[c].current_value
5529 = tem->current_value;
5530 xi_device->valuators[c].emacs_value = 0.0;
5531 }
5532 }
5533 }
5534
5535 SAFE_FREE ();
5536 #endif
5537 }
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567 static void
5568 x_cache_xi_devices (struct x_display_info *dpyinfo)
5569 {
5570 int ndevices, actual_devices, i;
5571 XIDeviceInfo *infos;
5572
5573 actual_devices = 0;
5574 block_input ();
5575 x_free_xi_devices (dpyinfo);
5576 infos = XIQueryDevice (dpyinfo->display,
5577 XIAllDevices,
5578 &ndevices);
5579
5580 if (!ndevices)
5581 {
5582 XIFreeDeviceInfo (infos);
5583 unblock_input ();
5584 return;
5585 }
5586
5587 dpyinfo->devices = xzalloc (sizeof *dpyinfo->devices * ndevices);
5588
5589 for (i = 0; i < ndevices; ++i)
5590 {
5591 if (infos[i].enabled)
5592 xi_populate_device_from_info (dpyinfo,
5593 &dpyinfo->devices[actual_devices++],
5594 &infos[i]);
5595 }
5596
5597 dpyinfo->num_devices = actual_devices;
5598 XIFreeDeviceInfo (infos);
5599 unblock_input ();
5600 }
5601
5602 #ifdef HAVE_XINPUT2_1
5603
5604
5605
5606
5607
5608
5609 static double
5610 x_get_scroll_valuator_delta (struct x_display_info *dpyinfo,
5611 struct xi_device_t *device,
5612 int valuator_number, double value,
5613 struct xi_scroll_valuator_t **valuator_return)
5614 {
5615 struct xi_scroll_valuator_t *sv;
5616 double delta;
5617 int i;
5618
5619 for (i = 0; i < device->scroll_valuator_count; ++i)
5620 {
5621 sv = &device->valuators[i];
5622
5623 if (sv->number == valuator_number)
5624 {
5625 *valuator_return = sv;
5626
5627 if (sv->increment == 0)
5628 return DBL_MAX;
5629
5630 if (sv->invalid_p)
5631 {
5632 sv->current_value = value;
5633 sv->invalid_p = false;
5634
5635 return DBL_MAX;
5636 }
5637 else
5638 {
5639 delta = (sv->current_value - value) / sv->increment;
5640 sv->current_value = value;
5641
5642 return delta;
5643 }
5644 }
5645 }
5646
5647 *valuator_return = NULL;
5648 return DBL_MAX;
5649 }
5650
5651 #endif
5652
5653 struct xi_device_t *
5654 xi_device_from_id (struct x_display_info *dpyinfo, int deviceid)
5655 {
5656 for (int i = 0; i < dpyinfo->num_devices; ++i)
5657 {
5658 if (dpyinfo->devices[i].device_id == deviceid)
5659 return &dpyinfo->devices[i];
5660 }
5661
5662 return NULL;
5663 }
5664
5665 #ifdef HAVE_XINPUT2_2
5666
5667 static void
5668 xi_link_touch_point (struct xi_device_t *device,
5669 int detail, double x, double y)
5670 {
5671 struct xi_touch_point_t *touchpoint;
5672
5673 touchpoint = xmalloc (sizeof *touchpoint);
5674 touchpoint->next = device->touchpoints;
5675 touchpoint->x = x;
5676 touchpoint->y = y;
5677 touchpoint->number = detail;
5678
5679 device->touchpoints = touchpoint;
5680 }
5681
5682 static bool
5683 xi_unlink_touch_point (int detail,
5684 struct xi_device_t *device)
5685 {
5686 struct xi_touch_point_t *last, *tem;
5687
5688 for (last = NULL, tem = device->touchpoints; tem;
5689 last = tem, tem = tem->next)
5690 {
5691 if (tem->number == detail)
5692 {
5693 if (!last)
5694 device->touchpoints = tem->next;
5695 else
5696 last->next = tem->next;
5697
5698 xfree (tem);
5699 return true;
5700 }
5701 }
5702
5703 return false;
5704 }
5705
5706 static struct xi_touch_point_t *
5707 xi_find_touch_point (struct xi_device_t *device, int detail)
5708 {
5709 struct xi_touch_point_t *point;
5710
5711 for (point = device->touchpoints; point; point = point->next)
5712 {
5713 if (point->number == detail)
5714 return point;
5715 }
5716
5717 return NULL;
5718 }
5719
5720 #endif
5721
5722 #ifdef HAVE_XINPUT2_1
5723
5724 static void
5725 xi_reset_scroll_valuators_for_device_id (struct x_display_info *dpyinfo,
5726 int id)
5727 {
5728 struct xi_device_t *device;
5729 struct xi_scroll_valuator_t *valuator;
5730 int i;
5731
5732 device = xi_device_from_id (dpyinfo, id);
5733
5734 if (!device)
5735 return;
5736
5737 if (!device->scroll_valuator_count)
5738 return;
5739
5740 for (i = 0; i < device->scroll_valuator_count; ++i)
5741 {
5742 valuator = &device->valuators[i];
5743 valuator->invalid_p = true;
5744 valuator->emacs_value = 0.0;
5745 }
5746
5747 return;
5748 }
5749
5750 #endif
5751
5752 #endif
5753
5754 #ifdef USE_CAIRO
5755
5756 void
5757 x_cr_destroy_frame_context (struct frame *f)
5758 {
5759 if (FRAME_CR_CONTEXT (f))
5760 {
5761 cairo_destroy (FRAME_CR_CONTEXT (f));
5762 FRAME_CR_CONTEXT (f) = NULL;
5763 }
5764 }
5765
5766 void
5767 x_cr_update_surface_desired_size (struct frame *f, int width, int height)
5768 {
5769 if (FRAME_CR_SURFACE_DESIRED_WIDTH (f) != width
5770 || FRAME_CR_SURFACE_DESIRED_HEIGHT (f) != height)
5771 {
5772 x_cr_destroy_frame_context (f);
5773 FRAME_CR_SURFACE_DESIRED_WIDTH (f) = width;
5774 FRAME_CR_SURFACE_DESIRED_HEIGHT (f) = height;
5775 }
5776 }
5777
5778 static void
5779 x_cr_gc_clip (cairo_t *cr, struct frame *f, GC gc)
5780 {
5781 if (gc)
5782 {
5783 struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 0);
5784
5785 if (gc_ext && gc_ext->n_clip_rects)
5786 {
5787 for (int i = 0; i < gc_ext->n_clip_rects; i++)
5788 cairo_rectangle (cr, gc_ext->clip_rects[i].x,
5789 gc_ext->clip_rects[i].y,
5790 gc_ext->clip_rects[i].width,
5791 gc_ext->clip_rects[i].height);
5792 cairo_clip (cr);
5793 }
5794 }
5795 }
5796
5797 cairo_t *
5798 x_begin_cr_clip (struct frame *f, GC gc)
5799 {
5800 cairo_t *cr = FRAME_CR_CONTEXT (f);
5801
5802 if (!cr)
5803 {
5804 int width = FRAME_CR_SURFACE_DESIRED_WIDTH (f);
5805 int height = FRAME_CR_SURFACE_DESIRED_HEIGHT (f);
5806 cairo_surface_t *surface;
5807 #ifdef USE_CAIRO_XCB_SURFACE
5808 if (FRAME_DISPLAY_INFO (f)->xcb_visual)
5809 surface = cairo_xcb_surface_create (FRAME_DISPLAY_INFO (f)->xcb_connection,
5810 (xcb_drawable_t) FRAME_X_RAW_DRAWABLE (f),
5811 FRAME_DISPLAY_INFO (f)->xcb_visual,
5812 width, height);
5813 else
5814 #endif
5815 surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
5816 FRAME_X_RAW_DRAWABLE (f),
5817 FRAME_X_VISUAL (f),
5818 width, height);
5819
5820 cr = FRAME_CR_CONTEXT (f) = cairo_create (surface);
5821 cairo_surface_destroy (surface);
5822 }
5823 cairo_save (cr);
5824 x_cr_gc_clip (cr, f, gc);
5825
5826 return cr;
5827 }
5828
5829 void
5830 x_end_cr_clip (struct frame *f)
5831 {
5832 cairo_restore (FRAME_CR_CONTEXT (f));
5833 #ifdef HAVE_XDBE
5834 if (FRAME_X_DOUBLE_BUFFERED_P (f))
5835 x_mark_frame_dirty (f);
5836 #endif
5837 }
5838
5839 void
5840 x_set_cr_source_with_gc_foreground (struct frame *f, GC gc,
5841 bool respect_alpha_background)
5842 {
5843 XGCValues xgcv;
5844 XColor color;
5845 unsigned int depth;
5846
5847 XGetGCValues (FRAME_X_DISPLAY (f), gc, GCForeground, &xgcv);
5848 color.pixel = xgcv.foreground;
5849 x_query_colors (f, &color, 1);
5850 depth = FRAME_DISPLAY_INFO (f)->n_planes;
5851
5852 if (f->alpha_background < 1.0 && depth == 32
5853 && respect_alpha_background)
5854 {
5855 cairo_set_source_rgba (FRAME_CR_CONTEXT (f), color.red / 65535.0,
5856 color.green / 65535.0, color.blue / 65535.0,
5857 f->alpha_background);
5858
5859 cairo_set_operator (FRAME_CR_CONTEXT (f), CAIRO_OPERATOR_SOURCE);
5860 }
5861 else
5862 {
5863 cairo_set_source_rgb (FRAME_CR_CONTEXT (f), color.red / 65535.0,
5864 color.green / 65535.0, color.blue / 65535.0);
5865 cairo_set_operator (FRAME_CR_CONTEXT (f), CAIRO_OPERATOR_OVER);
5866 }
5867 }
5868
5869 void
5870 x_set_cr_source_with_gc_background (struct frame *f, GC gc,
5871 bool respect_alpha_background)
5872 {
5873 XGCValues xgcv;
5874 XColor color;
5875 unsigned int depth;
5876
5877 XGetGCValues (FRAME_X_DISPLAY (f), gc, GCBackground, &xgcv);
5878 color.pixel = xgcv.background;
5879
5880 x_query_colors (f, &color, 1);
5881
5882 depth = FRAME_DISPLAY_INFO (f)->n_planes;
5883
5884 if (f->alpha_background < 1.0 && depth == 32
5885 && respect_alpha_background)
5886 {
5887 cairo_set_source_rgba (FRAME_CR_CONTEXT (f), color.red / 65535.0,
5888 color.green / 65535.0, color.blue / 65535.0,
5889 f->alpha_background);
5890
5891 cairo_set_operator (FRAME_CR_CONTEXT (f), CAIRO_OPERATOR_SOURCE);
5892 }
5893 else
5894 {
5895 cairo_set_source_rgb (FRAME_CR_CONTEXT (f), color.red / 65535.0,
5896 color.green / 65535.0, color.blue / 65535.0);
5897 cairo_set_operator (FRAME_CR_CONTEXT (f), CAIRO_OPERATOR_OVER);
5898 }
5899 }
5900
5901 static const cairo_user_data_key_t xlib_surface_key, saved_drawable_key;
5902
5903 static void
5904 x_cr_destroy_xlib_surface (cairo_surface_t *xlib_surface)
5905 {
5906 if (xlib_surface)
5907 {
5908 XFreePixmap (cairo_xlib_surface_get_display (xlib_surface),
5909 cairo_xlib_surface_get_drawable (xlib_surface));
5910 cairo_surface_destroy (xlib_surface);
5911 }
5912 }
5913
5914 static bool
5915 x_try_cr_xlib_drawable (struct frame *f, GC gc)
5916 {
5917 cairo_t *cr = FRAME_CR_CONTEXT (f);
5918 if (!cr)
5919 return true;
5920
5921 cairo_surface_t *surface = cairo_get_target (cr);
5922 switch (cairo_surface_get_type (surface))
5923 {
5924 case CAIRO_SURFACE_TYPE_XLIB:
5925 #ifdef USE_CAIRO_XCB_SURFACE
5926 case CAIRO_SURFACE_TYPE_XCB:
5927 #endif
5928 cairo_surface_flush (surface);
5929 return true;
5930
5931 case CAIRO_SURFACE_TYPE_IMAGE:
5932 break;
5933
5934 default:
5935 return false;
5936 }
5937
5938
5939
5940
5941 cairo_surface_t *xlib_surface = cairo_get_user_data (cr, &xlib_surface_key);
5942 int width = FRAME_CR_SURFACE_DESIRED_WIDTH (f);
5943 int height = FRAME_CR_SURFACE_DESIRED_HEIGHT (f);
5944 Pixmap pixmap;
5945 if (xlib_surface
5946 && cairo_xlib_surface_get_width (xlib_surface) == width
5947 && cairo_xlib_surface_get_height (xlib_surface) == height)
5948 pixmap = cairo_xlib_surface_get_drawable (xlib_surface);
5949 else
5950 {
5951 pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_RAW_DRAWABLE (f),
5952 width, height,
5953 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
5954 xlib_surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
5955 pixmap, FRAME_X_VISUAL (f),
5956 width, height);
5957 cairo_set_user_data (cr, &xlib_surface_key, xlib_surface,
5958 (cairo_destroy_func_t) x_cr_destroy_xlib_surface);
5959 }
5960
5961 cairo_t *buf = cairo_create (xlib_surface);
5962 cairo_set_source_surface (buf, surface, 0, 0);
5963 cairo_matrix_t matrix;
5964 cairo_get_matrix (cr, &matrix);
5965 cairo_pattern_set_matrix (cairo_get_source (cr), &matrix);
5966 cairo_set_operator (buf, CAIRO_OPERATOR_SOURCE);
5967 x_cr_gc_clip (buf, f, gc);
5968 cairo_paint (buf);
5969 cairo_destroy (buf);
5970
5971 cairo_set_user_data (cr, &saved_drawable_key,
5972 (void *) (uintptr_t) FRAME_X_RAW_DRAWABLE (f), NULL);
5973 FRAME_X_RAW_DRAWABLE (f) = pixmap;
5974 cairo_surface_flush (xlib_surface);
5975
5976 return true;
5977 }
5978
5979 static void
5980 x_end_cr_xlib_drawable (struct frame *f, GC gc)
5981 {
5982 cairo_t *cr = FRAME_CR_CONTEXT (f);
5983 if (!cr)
5984 return;
5985
5986 Drawable saved_drawable
5987 = (uintptr_t) cairo_get_user_data (cr, &saved_drawable_key);
5988 cairo_surface_t *surface = (saved_drawable
5989 ? cairo_get_user_data (cr, &xlib_surface_key)
5990 : cairo_get_target (cr));
5991 struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 0);
5992 if (gc_ext && gc_ext->n_clip_rects)
5993 for (int i = 0; i < gc_ext->n_clip_rects; i++)
5994 cairo_surface_mark_dirty_rectangle (surface, gc_ext->clip_rects[i].x,
5995 gc_ext->clip_rects[i].y,
5996 gc_ext->clip_rects[i].width,
5997 gc_ext->clip_rects[i].height);
5998 else
5999 cairo_surface_mark_dirty (surface);
6000 if (!saved_drawable)
6001 return;
6002
6003 cairo_save (cr);
6004 cairo_set_source_surface (cr, surface, 0, 0);
6005 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
6006 x_cr_gc_clip (cr, f, gc);
6007 cairo_paint (cr);
6008 cairo_restore (cr);
6009
6010 FRAME_X_RAW_DRAWABLE (f) = saved_drawable;
6011 cairo_set_user_data (cr, &saved_drawable_key, NULL, NULL);
6012 }
6013
6014
6015
6016 static int max_fringe_bmp = 0;
6017 static cairo_pattern_t **fringe_bmp = 0;
6018
6019 static void
6020 x_cr_define_fringe_bitmap (int which, unsigned short *bits, int h, int wd)
6021 {
6022 int i, stride;
6023 cairo_surface_t *surface;
6024 cairo_pattern_t *pattern;
6025 unsigned char *data;
6026
6027 if (which >= max_fringe_bmp)
6028 {
6029 i = max_fringe_bmp;
6030 max_fringe_bmp = which + 20;
6031 fringe_bmp = xrealloc (fringe_bmp, max_fringe_bmp * sizeof (*fringe_bmp));
6032 while (i < max_fringe_bmp)
6033 fringe_bmp[i++] = 0;
6034 }
6035
6036 block_input ();
6037
6038 surface = cairo_image_surface_create (CAIRO_FORMAT_A1, wd, h);
6039 stride = cairo_image_surface_get_stride (surface);
6040 data = cairo_image_surface_get_data (surface);
6041
6042 for (i = 0; i < h; i++)
6043 {
6044 *((unsigned short *) data) = bits[i];
6045 data += stride;
6046 }
6047
6048 cairo_surface_mark_dirty (surface);
6049 pattern = cairo_pattern_create_for_surface (surface);
6050 cairo_surface_destroy (surface);
6051
6052 unblock_input ();
6053
6054 fringe_bmp[which] = pattern;
6055 }
6056
6057 static void
6058 x_cr_destroy_fringe_bitmap (int which)
6059 {
6060 if (which >= max_fringe_bmp)
6061 return;
6062
6063 if (fringe_bmp[which])
6064 {
6065 block_input ();
6066 cairo_pattern_destroy (fringe_bmp[which]);
6067 unblock_input ();
6068 }
6069 fringe_bmp[which] = 0;
6070 }
6071
6072 static void
6073 x_cr_draw_image (struct frame *f, GC gc, cairo_pattern_t *image,
6074 int src_x, int src_y, int width, int height,
6075 int dest_x, int dest_y, bool overlay_p)
6076 {
6077 cairo_t *cr = x_begin_cr_clip (f, gc);
6078
6079 if (overlay_p)
6080 cairo_rectangle (cr, dest_x, dest_y, width, height);
6081 else
6082 {
6083 x_set_cr_source_with_gc_background (f, gc, false);
6084 cairo_rectangle (cr, dest_x, dest_y, width, height);
6085 cairo_fill_preserve (cr);
6086 }
6087
6088 cairo_translate (cr, dest_x - src_x, dest_y - src_y);
6089
6090 cairo_surface_t *surface;
6091 cairo_pattern_get_surface (image, &surface);
6092 cairo_format_t format = cairo_image_surface_get_format (surface);
6093 if (format != CAIRO_FORMAT_A8 && format != CAIRO_FORMAT_A1)
6094 {
6095 cairo_set_source (cr, image);
6096 cairo_fill (cr);
6097 }
6098 else
6099 {
6100 x_set_cr_source_with_gc_foreground (f, gc, false);
6101 cairo_clip (cr);
6102 cairo_mask (cr, image);
6103 }
6104
6105 x_end_cr_clip (f);
6106 }
6107
6108 void
6109 x_cr_draw_frame (cairo_t *cr, struct frame *f)
6110 {
6111 int width, height;
6112
6113 width = FRAME_PIXEL_WIDTH (f);
6114 height = FRAME_PIXEL_HEIGHT (f);
6115
6116 cairo_t *saved_cr = FRAME_CR_CONTEXT (f);
6117 FRAME_CR_CONTEXT (f) = cr;
6118 x_clear_area (f, 0, 0, width, height);
6119 expose_frame (f, 0, 0, width, height);
6120 FRAME_CR_CONTEXT (f) = saved_cr;
6121 }
6122
6123 static cairo_status_t
6124 x_cr_accumulate_data (void *closure, const unsigned char *data,
6125 unsigned int length)
6126 {
6127 Lisp_Object *acc = (Lisp_Object *) closure;
6128
6129 *acc = Fcons (make_unibyte_string ((char const *) data, length), *acc);
6130
6131 return CAIRO_STATUS_SUCCESS;
6132 }
6133
6134 static void
6135 x_cr_destroy (void *cr)
6136 {
6137 block_input ();
6138 cairo_destroy (cr);
6139 unblock_input ();
6140 }
6141
6142 Lisp_Object
6143 x_cr_export_frames (Lisp_Object frames, cairo_surface_type_t surface_type)
6144 {
6145 struct frame *f;
6146 cairo_surface_t *surface;
6147 cairo_t *cr;
6148 int width, height;
6149 void (*surface_set_size_func) (cairo_surface_t *, double, double) = NULL;
6150 Lisp_Object acc = Qnil;
6151 specpdl_ref count = SPECPDL_INDEX ();
6152
6153 specbind (Qredisplay_dont_pause, Qt);
6154 redisplay_preserve_echo_area (31);
6155
6156 f = XFRAME (XCAR (frames));
6157 frames = XCDR (frames);
6158 width = FRAME_PIXEL_WIDTH (f);
6159 height = FRAME_PIXEL_HEIGHT (f);
6160
6161 block_input ();
6162 #ifdef CAIRO_HAS_PDF_SURFACE
6163 if (surface_type == CAIRO_SURFACE_TYPE_PDF)
6164 {
6165 surface = cairo_pdf_surface_create_for_stream (x_cr_accumulate_data, &acc,
6166 width, height);
6167 surface_set_size_func = cairo_pdf_surface_set_size;
6168 }
6169 else
6170 #endif
6171 #ifdef CAIRO_HAS_PNG_FUNCTIONS
6172 if (surface_type == CAIRO_SURFACE_TYPE_IMAGE)
6173 surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height);
6174 else
6175 #endif
6176 #ifdef CAIRO_HAS_PS_SURFACE
6177 if (surface_type == CAIRO_SURFACE_TYPE_PS)
6178 {
6179 surface = cairo_ps_surface_create_for_stream (x_cr_accumulate_data, &acc,
6180 width, height);
6181 surface_set_size_func = cairo_ps_surface_set_size;
6182 }
6183 else
6184 #endif
6185 #ifdef CAIRO_HAS_SVG_SURFACE
6186 if (surface_type == CAIRO_SURFACE_TYPE_SVG)
6187 surface = cairo_svg_surface_create_for_stream (x_cr_accumulate_data, &acc,
6188 width, height);
6189 else
6190 #endif
6191 abort ();
6192
6193 cr = cairo_create (surface);
6194 cairo_surface_destroy (surface);
6195 record_unwind_protect_ptr (x_cr_destroy, cr);
6196
6197 while (1)
6198 {
6199 cairo_t *saved_cr = FRAME_CR_CONTEXT (f);
6200 FRAME_CR_CONTEXT (f) = cr;
6201 x_clear_area (f, 0, 0, width, height);
6202 expose_frame (f, 0, 0, width, height);
6203 FRAME_CR_CONTEXT (f) = saved_cr;
6204
6205 if (NILP (frames))
6206 break;
6207
6208 cairo_surface_show_page (surface);
6209 f = XFRAME (XCAR (frames));
6210 frames = XCDR (frames);
6211 width = FRAME_PIXEL_WIDTH (f);
6212 height = FRAME_PIXEL_HEIGHT (f);
6213 if (surface_set_size_func)
6214 (*surface_set_size_func) (surface, width, height);
6215
6216 unblock_input ();
6217 maybe_quit ();
6218 block_input ();
6219 }
6220
6221 #ifdef CAIRO_HAS_PNG_FUNCTIONS
6222 if (surface_type == CAIRO_SURFACE_TYPE_IMAGE)
6223 {
6224 cairo_surface_flush (surface);
6225 cairo_surface_write_to_png_stream (surface, x_cr_accumulate_data, &acc);
6226 }
6227 #endif
6228 unblock_input ();
6229
6230 unbind_to (count, Qnil);
6231
6232 return CALLN (Fapply, Qconcat, Fnreverse (acc));
6233 }
6234
6235 #endif
6236
6237 #if defined HAVE_XRENDER
6238 void
6239 x_xr_apply_ext_clip (struct frame *f, GC gc)
6240 {
6241 eassert (FRAME_X_PICTURE (f) != None);
6242
6243 struct x_gc_ext_data *data = x_gc_get_ext_data (f, gc, 1);
6244
6245 if (data->n_clip_rects)
6246 XRenderSetPictureClipRectangles (FRAME_X_DISPLAY (f),
6247 FRAME_X_PICTURE (f),
6248 0, 0, data->clip_rects,
6249 data->n_clip_rects);
6250 }
6251
6252 void
6253 x_xr_reset_ext_clip (struct frame *f)
6254 {
6255 XRenderPictureAttributes attrs = { .clip_mask = None };
6256
6257 XRenderChangePicture (FRAME_X_DISPLAY (f),
6258 FRAME_X_PICTURE (f),
6259 CPClipMask, &attrs);
6260 }
6261 #endif
6262
6263 static void
6264 x_set_clip_rectangles (struct frame *f, GC gc, XRectangle *rectangles, int n)
6265 {
6266 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, rectangles, n, Unsorted);
6267 #if defined USE_CAIRO || defined HAVE_XRENDER
6268 eassert (n >= 0 && n <= MAX_CLIP_RECTS);
6269
6270 {
6271 struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 1);
6272
6273 gc_ext->n_clip_rects = n;
6274 memcpy (gc_ext->clip_rects, rectangles, sizeof (XRectangle) * n);
6275 }
6276 #endif
6277 }
6278
6279 static void
6280 x_reset_clip_rectangles (struct frame *f, GC gc)
6281 {
6282 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
6283 #if defined USE_CAIRO || defined HAVE_XRENDER
6284 {
6285 struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 0);
6286
6287 if (gc_ext)
6288 gc_ext->n_clip_rects = 0;
6289 }
6290 #endif
6291 }
6292
6293 #ifdef HAVE_XRENDER
6294 # if !defined USE_CAIRO && (RENDER_MAJOR > 0 || RENDER_MINOR >= 2)
6295 static void
6296 x_xrender_color_from_gc_foreground (struct frame *f, GC gc, XRenderColor *color,
6297 bool apply_alpha_background)
6298 {
6299 XGCValues xgcv;
6300 XColor xc;
6301
6302 XGetGCValues (FRAME_X_DISPLAY (f), gc, GCForeground, &xgcv);
6303 xc.pixel = xgcv.foreground;
6304 x_query_colors (f, &xc, 1);
6305
6306 color->alpha = (apply_alpha_background
6307 ? 65535 * f->alpha_background
6308 : 65535);
6309
6310 if (color->alpha == 65535)
6311 {
6312 color->red = xc.red;
6313 color->blue = xc.blue;
6314 color->green = xc.green;
6315 }
6316 else
6317 {
6318 color->red = (xc.red * color->alpha) / 65535;
6319 color->blue = (xc.blue * color->alpha) / 65535;
6320 color->green = (xc.green * color->alpha) / 65535;
6321 }
6322 }
6323 # endif
6324
6325 void
6326 x_xrender_color_from_gc_background (struct frame *f, GC gc, XRenderColor *color,
6327 bool apply_alpha_background)
6328 {
6329 XGCValues xgcv;
6330 XColor xc;
6331
6332 XGetGCValues (FRAME_X_DISPLAY (f), gc, GCBackground, &xgcv);
6333 xc.pixel = xgcv.background;
6334 x_query_colors (f, &xc, 1);
6335
6336 color->alpha = (apply_alpha_background
6337 ? 65535 * f->alpha_background
6338 : 65535);
6339
6340 if (color->alpha == 65535)
6341 {
6342 color->red = xc.red;
6343 color->blue = xc.blue;
6344 color->green = xc.green;
6345 }
6346 else
6347 {
6348 color->red = (xc.red * color->alpha) / 65535;
6349 color->blue = (xc.blue * color->alpha) / 65535;
6350 color->green = (xc.green * color->alpha) / 65535;
6351 }
6352 }
6353 #endif
6354
6355 static void
6356 x_fill_rectangle (struct frame *f, GC gc, int x, int y, int width, int height,
6357 bool respect_alpha_background)
6358 {
6359 #ifdef USE_CAIRO
6360 Display *dpy = FRAME_X_DISPLAY (f);
6361 cairo_t *cr;
6362 XGCValues xgcv;
6363
6364 cr = x_begin_cr_clip (f, gc);
6365 XGetGCValues (dpy, gc, GCFillStyle | GCStipple, &xgcv);
6366 if (xgcv.fill_style == FillSolid
6367
6368
6369
6370
6371 || (xgcv.stipple & ((Pixmap) 7 << (sizeof (Pixmap) * CHAR_BIT - 3))))
6372 {
6373 x_set_cr_source_with_gc_foreground (f, gc, respect_alpha_background);
6374 cairo_rectangle (cr, x, y, width, height);
6375 cairo_fill (cr);
6376 }
6377 else
6378 {
6379 eassert (xgcv.fill_style == FillOpaqueStippled);
6380 eassert (xgcv.stipple != None);
6381 x_set_cr_source_with_gc_background (f, gc, respect_alpha_background);
6382 cairo_rectangle (cr, x, y, width, height);
6383 cairo_fill_preserve (cr);
6384
6385 cairo_pattern_t *pattern = x_bitmap_stipple (f, xgcv.stipple);
6386 if (pattern)
6387 {
6388 x_set_cr_source_with_gc_foreground (f, gc, respect_alpha_background);
6389 cairo_clip (cr);
6390 cairo_mask (cr, pattern);
6391 }
6392 }
6393 x_end_cr_clip (f);
6394 #else
6395 #if defined HAVE_XRENDER && (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2))
6396 if (respect_alpha_background
6397 && f->alpha_background != 1.0
6398 && FRAME_DISPLAY_INFO (f)->alpha_bits
6399 && FRAME_CHECK_XR_VERSION (f, 0, 2))
6400 {
6401 x_xr_ensure_picture (f);
6402
6403 if (FRAME_X_PICTURE (f) != None)
6404 {
6405 XRenderColor xc;
6406
6407 #if RENDER_MAJOR > 0 || (RENDER_MINOR >= 10)
6408 XGCValues xgcv;
6409 XRenderPictureAttributes attrs;
6410 XRenderColor alpha;
6411 Picture stipple, fill;
6412 #endif
6413
6414 x_xr_apply_ext_clip (f, gc);
6415
6416 #if RENDER_MAJOR > 0 || (RENDER_MINOR >= 10)
6417 XGetGCValues (FRAME_X_DISPLAY (f),
6418 gc, GCFillStyle | GCStipple, &xgcv);
6419
6420 if (xgcv.fill_style == FillOpaqueStippled
6421 && FRAME_CHECK_XR_VERSION (f, 0, 10))
6422 {
6423 x_xrender_color_from_gc_background (f, gc, &alpha, true);
6424 x_xrender_color_from_gc_foreground (f, gc, &xc, true);
6425 attrs.repeat = RepeatNormal;
6426
6427 stipple = XRenderCreatePicture (FRAME_X_DISPLAY (f),
6428 xgcv.stipple,
6429 XRenderFindStandardFormat (FRAME_X_DISPLAY (f),
6430 PictStandardA1),
6431 CPRepeat, &attrs);
6432
6433 XRenderFillRectangle (FRAME_X_DISPLAY (f), PictOpSrc,
6434 FRAME_X_PICTURE (f),
6435 &alpha, x, y, width, height);
6436
6437 fill = XRenderCreateSolidFill (FRAME_X_DISPLAY (f), &xc);
6438
6439 XRenderComposite (FRAME_X_DISPLAY (f), PictOpOver, fill, stipple,
6440 FRAME_X_PICTURE (f), 0, 0, x, y, x, y, width, height);
6441
6442 XRenderFreePicture (FRAME_X_DISPLAY (f), stipple);
6443 XRenderFreePicture (FRAME_X_DISPLAY (f), fill);
6444 }
6445 else
6446 #endif
6447 {
6448 x_xrender_color_from_gc_foreground (f, gc, &xc, true);
6449 XRenderFillRectangle (FRAME_X_DISPLAY (f),
6450 PictOpSrc, FRAME_X_PICTURE (f),
6451 &xc, x, y, width, height);
6452 }
6453 x_xr_reset_ext_clip (f);
6454 x_mark_frame_dirty (f);
6455
6456 return;
6457 }
6458 }
6459 #endif
6460 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
6461 gc, x, y, width, height);
6462 #endif
6463 }
6464
6465
6466 static void
6467 x_clear_rectangle (struct frame *f, GC gc, int x, int y, int width, int height,
6468 bool respect_alpha_background)
6469 {
6470 #ifdef USE_CAIRO
6471 cairo_t *cr;
6472
6473 cr = x_begin_cr_clip (f, gc);
6474 x_set_cr_source_with_gc_background (f, gc, respect_alpha_background);
6475 cairo_rectangle (cr, x, y, width, height);
6476 cairo_fill (cr);
6477 x_end_cr_clip (f);
6478 #else
6479 #if defined HAVE_XRENDER && (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2))
6480 if (respect_alpha_background
6481 && f->alpha_background != 1.0
6482 && FRAME_DISPLAY_INFO (f)->alpha_bits
6483 && FRAME_CHECK_XR_VERSION (f, 0, 2))
6484 {
6485 x_xr_ensure_picture (f);
6486
6487 if (FRAME_X_PICTURE (f) != None)
6488 {
6489 XRenderColor xc;
6490
6491 x_xr_apply_ext_clip (f, gc);
6492 x_xrender_color_from_gc_background (f, gc, &xc, true);
6493 XRenderFillRectangle (FRAME_X_DISPLAY (f),
6494 PictOpSrc, FRAME_X_PICTURE (f),
6495 &xc, x, y, width, height);
6496 x_xr_reset_ext_clip (f);
6497 x_mark_frame_dirty (f);
6498
6499 return;
6500 }
6501 }
6502 #endif
6503
6504 XGCValues xgcv;
6505 Display *dpy = FRAME_X_DISPLAY (f);
6506 XGetGCValues (dpy, gc, GCBackground | GCForeground, &xgcv);
6507 XSetForeground (dpy, gc, xgcv.background);
6508 XFillRectangle (dpy, FRAME_X_DRAWABLE (f),
6509 gc, x, y, width, height);
6510 XSetForeground (dpy, gc, xgcv.foreground);
6511 #endif
6512 }
6513
6514 static void
6515 x_draw_rectangle (struct frame *f, GC gc, int x, int y, int width, int height)
6516 {
6517 #ifdef USE_CAIRO
6518 cairo_t *cr;
6519
6520 cr = x_begin_cr_clip (f, gc);
6521 x_set_cr_source_with_gc_foreground (f, gc, false);
6522 cairo_rectangle (cr, x + 0.5, y + 0.5, width, height);
6523 cairo_set_line_width (cr, 1);
6524 cairo_stroke (cr);
6525 x_end_cr_clip (f);
6526 #else
6527 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
6528 gc, x, y, width, height);
6529 #endif
6530 }
6531
6532 static void
6533 x_clear_window (struct frame *f)
6534 {
6535 #ifdef USE_CAIRO
6536 cairo_t *cr;
6537
6538 cr = x_begin_cr_clip (f, NULL);
6539 x_set_cr_source_with_gc_background (f, f->output_data.x->normal_gc, true);
6540 cairo_paint (cr);
6541 x_end_cr_clip (f);
6542 #else
6543 #ifndef USE_GTK
6544 if (f->alpha_background != 1.0
6545 #ifdef HAVE_XDBE
6546 || FRAME_X_DOUBLE_BUFFERED_P (f)
6547 #endif
6548 )
6549 #endif
6550 x_clear_area (f, 0, 0, FRAME_PIXEL_WIDTH (f),
6551 FRAME_PIXEL_HEIGHT (f));
6552 #ifndef USE_GTK
6553 else
6554 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
6555 #endif
6556 #endif
6557 }
6558
6559 #ifdef USE_CAIRO
6560 static void
6561 x_fill_trapezoid_for_relief (struct frame *f, GC gc, int x, int y,
6562 int width, int height, int top_p)
6563 {
6564 cairo_t *cr;
6565
6566 cr = x_begin_cr_clip (f, gc);
6567 x_set_cr_source_with_gc_foreground (f, gc, false);
6568 cairo_move_to (cr, top_p ? x : x + height, y);
6569 cairo_line_to (cr, x, y + height);
6570 cairo_line_to (cr, top_p ? x + width - height : x + width, y + height);
6571 cairo_line_to (cr, x + width, y);
6572 cairo_fill (cr);
6573 x_end_cr_clip (f);
6574 }
6575
6576 enum corners
6577 {
6578 CORNER_BOTTOM_RIGHT,
6579 CORNER_BOTTOM_LEFT,
6580 CORNER_TOP_LEFT,
6581 CORNER_TOP_RIGHT,
6582 CORNER_LAST
6583 };
6584
6585 static void
6586 x_erase_corners_for_relief (struct frame *f, GC gc, int x, int y,
6587 int width, int height,
6588 double radius, double margin, int corners)
6589 {
6590 cairo_t *cr;
6591 int i;
6592
6593 cr = x_begin_cr_clip (f, gc);
6594 x_set_cr_source_with_gc_background (f, gc, false);
6595 for (i = 0; i < CORNER_LAST; i++)
6596 if (corners & (1 << i))
6597 {
6598 double xm, ym, xc, yc;
6599
6600 if (i == CORNER_TOP_LEFT || i == CORNER_BOTTOM_LEFT)
6601 xm = x - margin, xc = xm + radius;
6602 else
6603 xm = x + width + margin, xc = xm - radius;
6604 if (i == CORNER_TOP_LEFT || i == CORNER_TOP_RIGHT)
6605 ym = y - margin, yc = ym + radius;
6606 else
6607 ym = y + height + margin, yc = ym - radius;
6608
6609 cairo_move_to (cr, xm, ym);
6610 cairo_arc (cr, xc, yc, radius, i * M_PI_2, (i + 1) * M_PI_2);
6611 }
6612 cairo_clip (cr);
6613 cairo_rectangle (cr, x, y, width, height);
6614 cairo_fill (cr);
6615 x_end_cr_clip (f);
6616 }
6617
6618 static void
6619 x_draw_horizontal_wave (struct frame *f, GC gc, int x, int y,
6620 int width, int height, int wave_length)
6621 {
6622 cairo_t *cr;
6623 double dx = wave_length, dy = height - 1;
6624 int xoffset, n;
6625
6626 cr = x_begin_cr_clip (f, gc);
6627 x_set_cr_source_with_gc_foreground (f, gc, false);
6628 cairo_rectangle (cr, x, y, width, height);
6629 cairo_clip (cr);
6630
6631 if (x >= 0)
6632 {
6633 xoffset = x % (wave_length * 2);
6634 if (xoffset == 0)
6635 xoffset = wave_length * 2;
6636 }
6637 else
6638 xoffset = x % (wave_length * 2) + wave_length * 2;
6639 n = (width + xoffset) / wave_length + 1;
6640 if (xoffset > wave_length)
6641 {
6642 xoffset -= wave_length;
6643 --n;
6644 y += height - 1;
6645 dy = -dy;
6646 }
6647
6648 cairo_move_to (cr, x - xoffset + 0.5, y + 0.5);
6649 while (--n >= 0)
6650 {
6651 cairo_rel_line_to (cr, dx, dy);
6652 dy = -dy;
6653 }
6654 cairo_set_line_width (cr, 1);
6655 cairo_stroke (cr);
6656 x_end_cr_clip (f);
6657 }
6658 #endif
6659
6660
6661
6662
6663 struct x_display_info *
6664 x_display_info_for_display (Display *dpy)
6665 {
6666 struct x_display_info *dpyinfo;
6667
6668 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
6669 if (dpyinfo->display == dpy)
6670 return dpyinfo;
6671
6672 return 0;
6673 }
6674
6675 static Window
6676 x_find_topmost_parent (struct frame *f)
6677 {
6678 struct x_output *x = f->output_data.x;
6679 Window win = None, wi = x->parent_desc;
6680 Display *dpy = FRAME_X_DISPLAY (f);
6681
6682 while (wi != FRAME_DISPLAY_INFO (f)->root_window)
6683 {
6684 Window root;
6685 Window *children;
6686 unsigned int nchildren;
6687
6688 win = wi;
6689 if (XQueryTree (dpy, win, &root, &wi, &children, &nchildren))
6690 XFree (children);
6691 else
6692 break;
6693 }
6694
6695 return win;
6696 }
6697
6698 #define OPAQUE 0xffffffff
6699
6700 static void
6701 x_set_frame_alpha (struct frame *f)
6702 {
6703 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
6704 Display *dpy = FRAME_X_DISPLAY (f);
6705 Window win = FRAME_OUTER_WINDOW (f);
6706 double alpha = 1.0;
6707 double alpha_min = 1.0;
6708 unsigned long opac;
6709 Window parent;
6710
6711 if (dpyinfo->highlight_frame == f)
6712 alpha = f->alpha[0];
6713 else
6714 alpha = f->alpha[1];
6715
6716 if (alpha < 0.0)
6717 return;
6718
6719 if (FLOATP (Vframe_alpha_lower_limit))
6720 alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit);
6721 else if (FIXNUMP (Vframe_alpha_lower_limit))
6722 alpha_min = (XFIXNUM (Vframe_alpha_lower_limit)) / 100.0;
6723
6724 if (alpha > 1.0)
6725 alpha = 1.0;
6726 else if (alpha < alpha_min && alpha_min <= 1.0)
6727 alpha = alpha_min;
6728
6729 opac = alpha * OPAQUE;
6730
6731
6732
6733
6734
6735
6736 x_ignore_errors_for_next_request (dpyinfo);
6737
6738 if (!FRAME_PARENT_FRAME (f))
6739 {
6740 parent = x_find_topmost_parent (f);
6741
6742 if (parent != None)
6743 {
6744 XChangeProperty (dpy, parent,
6745 dpyinfo->Xatom_net_wm_window_opacity,
6746 XA_CARDINAL, 32, PropModeReplace,
6747 (unsigned char *) &opac, 1);
6748 }
6749 }
6750
6751 XChangeProperty (dpy, win, dpyinfo->Xatom_net_wm_window_opacity,
6752 XA_CARDINAL, 32, PropModeReplace,
6753 (unsigned char *) &opac, 1);
6754 x_stop_ignoring_errors (dpyinfo);
6755 }
6756
6757
6758
6759
6760
6761 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
6762
6763
6764
6765
6766
6767
6768
6769 static int
6770 x_if_event (Display *dpy, XEvent *event_return,
6771 Bool (*predicate) (Display *, XEvent *, XPointer),
6772 XPointer arg, struct timespec timeout)
6773 {
6774 struct timespec current_time, target;
6775 int fd;
6776 fd_set fds;
6777
6778 fd = ConnectionNumber (dpy);
6779 current_time = current_timespec ();
6780 target = timespec_add (current_time, timeout);
6781
6782
6783
6784 if (XCheckIfEvent (dpy, event_return, predicate, arg))
6785 return 0;
6786
6787 while (true)
6788 {
6789
6790 XSync (dpy, False);
6791
6792
6793 if (XCheckIfEvent (dpy, event_return, predicate, arg))
6794 return 0;
6795
6796
6797 current_time = current_timespec ();
6798 timeout = timespec_sub (target, current_time);
6799
6800
6801
6802 FD_ZERO (&fds);
6803 FD_SET (fd, &fds);
6804
6805
6806
6807 pselect (fd + 1, &fds, NULL, NULL, &timeout, NULL);
6808
6809
6810 current_time = current_timespec ();
6811 if (timespec_cmp (target, current_time) < 0)
6812 return 1;
6813 }
6814 }
6815
6816
6817
6818
6819
6820 static uint_fast64_t
6821 x_sync_get_monotonic_time (struct x_display_info *dpyinfo,
6822 uint_fast64_t timestamp)
6823 {
6824 if (dpyinfo->server_time_monotonic_p)
6825 return timestamp;
6826
6827
6828 if (!dpyinfo->server_time_offset)
6829 return 0;
6830
6831 uint_fast64_t t;
6832 return (INT_SUBTRACT_WRAPV (timestamp, dpyinfo->server_time_offset, &t)
6833 ? 0 : t);
6834 }
6835
6836 # ifndef CLOCK_MONOTONIC
6837 # define CLOCK_MONOTONIC CLOCK_REALTIME
6838 # endif
6839
6840
6841
6842
6843 static uint_fast64_t
6844 x_sync_current_monotonic_time (void)
6845 {
6846 struct timespec time;
6847 uint_fast64_t t;
6848 return (((clock_gettime (CLOCK_MONOTONIC, &time) != 0
6849 && (CLOCK_MONOTONIC == CLOCK_REALTIME
6850 || clock_gettime (CLOCK_REALTIME, &time) != 0))
6851 || INT_MULTIPLY_WRAPV (time.tv_sec, 1000000, &t)
6852 || INT_ADD_WRAPV (t, time.tv_nsec / 1000, &t))
6853 ? 0 : t);
6854 }
6855
6856
6857
6858
6859 static void
6860 x_sync_note_frame_times (struct x_display_info *dpyinfo,
6861 struct frame *f, XEvent *event)
6862 {
6863 uint_fast64_t low, high, time;
6864 struct x_output *output;
6865
6866 low = event->xclient.data.l[2];
6867 high = event->xclient.data.l[3];
6868 output = FRAME_X_OUTPUT (f);
6869
6870 time = x_sync_get_monotonic_time (dpyinfo, low | (high << 32));
6871
6872 if (!time || !output->temp_frame_time
6873 || INT_SUBTRACT_WRAPV (time, output->temp_frame_time,
6874 &output->last_frame_time))
6875 output->last_frame_time = 0;
6876
6877 #ifdef FRAME_DEBUG
6878 uint_fast64_t last_frame_ms = output->last_frame_time / 1000;
6879 fprintf (stderr,
6880 "Drawing the last frame took: %"PRIuFAST64" ms (%"PRIuFAST64")\n",
6881 last_frame_ms, time);
6882 #endif
6883 }
6884
6885 static Bool
6886 x_sync_is_frame_drawn_event (Display *dpy, XEvent *event,
6887 XPointer user_data)
6888 {
6889 struct frame *f;
6890 struct x_display_info *dpyinfo;
6891
6892 f = (struct frame *) user_data;
6893 dpyinfo = FRAME_DISPLAY_INFO (f);
6894
6895 if (event->type == ClientMessage
6896 && (event->xclient.message_type
6897 == dpyinfo->Xatom_net_wm_frame_drawn)
6898 && event->xclient.window == FRAME_OUTER_WINDOW (f))
6899 return True;
6900
6901 return False;
6902 }
6903
6904
6905
6906
6907
6908 static void
6909 x_sync_wait_for_frame_drawn_event (struct frame *f)
6910 {
6911 XEvent event;
6912
6913 if (!FRAME_X_WAITING_FOR_DRAW (f)
6914
6915
6916 || !FRAME_VISIBLE_P (f))
6917 return;
6918
6919
6920 if (x_if_event (FRAME_X_DISPLAY (f), &event,
6921 x_sync_is_frame_drawn_event, (XPointer) f,
6922 make_timespec (1, 0)))
6923 {
6924
6925
6926
6927 if (FRAME_X_DRAW_JUST_HUNG (f))
6928 {
6929 fprintf (stderr, "Warning: compositing manager spent more than 1 "
6930 "second drawing a frame. Frame synchronization has "
6931 "been disabled\n");
6932 FRAME_X_OUTPUT (f)->use_vsync_p = false;
6933
6934
6935
6936 store_frame_param (f, Quse_frame_synchronization, Qnil);
6937 }
6938 else
6939 {
6940 fprintf (stderr, "Warning: compositing manager spent more than 1 "
6941 "second drawing a frame. Frame synchronization will be "
6942 "disabled if this happens again\n");
6943 FRAME_X_DRAW_JUST_HUNG (f) = true;
6944 }
6945 }
6946 else
6947 x_sync_note_frame_times (FRAME_DISPLAY_INFO (f), f, &event);
6948
6949 FRAME_X_WAITING_FOR_DRAW (f) = false;
6950 }
6951
6952
6953
6954
6955 static void
6956 x_sync_update_begin (struct frame *f)
6957 {
6958 XSyncValue value, add;
6959 Bool overflow;
6960
6961 if (FRAME_X_EXTENDED_COUNTER (f) == None)
6962 return;
6963
6964 value = FRAME_X_COUNTER_VALUE (f);
6965
6966 if (FRAME_X_OUTPUT (f)->ext_sync_end_pending_p)
6967 {
6968 FRAME_X_COUNTER_VALUE (f)
6969 = FRAME_X_OUTPUT (f)->resize_counter_value;
6970
6971 value = FRAME_X_COUNTER_VALUE (f);
6972
6973 if (XSyncValueLow32 (value) % 2)
6974 {
6975 XSyncIntToValue (&add, 1);
6976 XSyncValueAdd (&value, value, add, &overflow);
6977
6978 if (overflow)
6979 XSyncIntToValue (&value, 0);
6980 }
6981
6982 FRAME_X_OUTPUT (f)->ext_sync_end_pending_p = false;
6983 }
6984
6985
6986
6987 if (XSyncValueLow32 (value) % 2)
6988 return;
6989
6990
6991 x_sync_wait_for_frame_drawn_event (f);
6992
6993
6994
6995 FRAME_X_OUTPUT (f)->temp_frame_time = x_sync_current_monotonic_time ();
6996
6997
6998
6999 if (XSyncValueLow32 (value) % 4 == 2)
7000 XSyncIntToValue (&add, 3);
7001 else
7002 XSyncIntToValue (&add, 1);
7003
7004 XSyncValueAdd (&FRAME_X_COUNTER_VALUE (f),
7005 value, add, &overflow);
7006
7007 if (overflow)
7008 XSyncIntToValue (&FRAME_X_COUNTER_VALUE (f), 3);
7009
7010 eassert (XSyncValueLow32 (FRAME_X_COUNTER_VALUE (f)) % 4 == 1);
7011
7012 XSyncSetCounter (FRAME_X_DISPLAY (f),
7013 FRAME_X_EXTENDED_COUNTER (f),
7014 FRAME_X_COUNTER_VALUE (f));
7015 }
7016
7017 #ifdef HAVE_XSYNCTRIGGERFENCE
7018
7019
7020
7021
7022 static void
7023 x_sync_trigger_fence (struct frame *f, XSyncValue value)
7024 {
7025 uint_fast64_t n, low, high, idx;
7026
7027
7028 if (FRAME_DISPLAY_INFO (f)->xsync_major < 3
7029 || (FRAME_DISPLAY_INFO (f)->xsync_major == 3
7030 && FRAME_DISPLAY_INFO (f)->xsync_minor < 1))
7031 return;
7032
7033 low = XSyncValueLow32 (value);
7034 high = XSyncValueHigh32 (value);
7035
7036 n = low | (high << 32);
7037 idx = (n / 4) % 2;
7038
7039 #ifdef FRAME_DEBUG
7040 fprintf (stderr, "Triggering synchronization fence: %lu\n", idx);
7041 #endif
7042
7043 XSyncTriggerFence (FRAME_X_DISPLAY (f),
7044 FRAME_X_OUTPUT (f)->sync_fences[idx]);
7045 }
7046
7047
7048
7049 void
7050 x_sync_init_fences (struct frame *f)
7051 {
7052 struct x_output *output;
7053 struct x_display_info *dpyinfo;
7054
7055 output = FRAME_X_OUTPUT (f);
7056 dpyinfo = FRAME_DISPLAY_INFO (f);
7057
7058
7059 if (dpyinfo->xsync_major < 3
7060 || (dpyinfo->xsync_major == 3
7061 && dpyinfo->xsync_minor < 1))
7062 return;
7063
7064 output->sync_fences[0]
7065 = XSyncCreateFence (FRAME_X_DISPLAY (f),
7066
7067
7068
7069 FRAME_X_WINDOW (f),
7070 False);
7071 output->sync_fences[1]
7072 = XSyncCreateFence (FRAME_X_DISPLAY (f),
7073 FRAME_X_WINDOW (f),
7074 False);
7075
7076 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
7077 dpyinfo->Xatom_net_wm_sync_fences, XA_CARDINAL,
7078 32, PropModeReplace,
7079 (unsigned char *) &output->sync_fences, 2);
7080 }
7081
7082 static void
7083 x_sync_free_fences (struct frame *f)
7084 {
7085 if (FRAME_X_OUTPUT (f)->sync_fences[0] != None)
7086 XSyncDestroyFence (FRAME_X_DISPLAY (f),
7087 FRAME_X_OUTPUT (f)->sync_fences[0]);
7088
7089 if (FRAME_X_OUTPUT (f)->sync_fences[1] != None)
7090 XSyncDestroyFence (FRAME_X_DISPLAY (f),
7091 FRAME_X_OUTPUT (f)->sync_fences[1]);
7092 }
7093
7094 #endif
7095
7096
7097
7098
7099 static void
7100 x_sync_update_finish (struct frame *f)
7101 {
7102 XSyncValue value, add;
7103 Bool overflow;
7104
7105 if (FRAME_X_EXTENDED_COUNTER (f) == None)
7106 return;
7107
7108 value = FRAME_X_COUNTER_VALUE (f);
7109
7110 if (!(XSyncValueLow32 (value) % 2))
7111 return;
7112
7113 if ((XSyncValueLow32 (value) % 4) == 1)
7114
7115
7116 XSyncIntToValue (&add, 3);
7117 else
7118
7119
7120 XSyncIntToValue (&add, 1);
7121
7122 XSyncValueAdd (&FRAME_X_COUNTER_VALUE (f),
7123 value, add, &overflow);
7124
7125 if (overflow)
7126 XSyncIntToValue (&FRAME_X_COUNTER_VALUE (f), 0);
7127
7128
7129 #ifdef HAVE_XSYNCTRIGGERFENCE
7130 x_sync_trigger_fence (f, FRAME_X_COUNTER_VALUE (f));
7131 #endif
7132
7133 XSyncSetCounter (FRAME_X_DISPLAY (f),
7134 FRAME_X_EXTENDED_COUNTER (f),
7135 FRAME_X_COUNTER_VALUE (f));
7136
7137 if (FRAME_OUTPUT_DATA (f)->use_vsync_p)
7138 FRAME_X_WAITING_FOR_DRAW (f) = true;
7139 }
7140
7141
7142
7143 static void
7144 x_sync_handle_frame_drawn (struct x_display_info *dpyinfo,
7145 XEvent *message, struct frame *f)
7146 {
7147 XSyncValue value, counter;
7148
7149 if (FRAME_OUTER_WINDOW (f) == message->xclient.window)
7150 {
7151 counter = FRAME_X_COUNTER_VALUE (f);
7152
7153
7154
7155 XSyncIntsToValue (&value,
7156 message->xclient.data.l[0] & 0xffffffff,
7157 message->xclient.data.l[1] & 0xffffffff);
7158
7159 if (XSyncValueEqual (value, counter))
7160 FRAME_X_WAITING_FOR_DRAW (f) = false;
7161
7162
7163
7164
7165 FRAME_X_DRAW_JUST_HUNG (f) = false;
7166 }
7167
7168 x_sync_note_frame_times (dpyinfo, f, message);
7169 }
7170 #endif
7171
7172
7173
7174
7175
7176
7177
7178 static void
7179 x_update_begin (struct frame *f)
7180 {
7181 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
7182
7183
7184 #ifdef HAVE_XDBE
7185 if (!FRAME_X_DOUBLE_BUFFERED_P (f))
7186 #endif
7187 x_sync_update_begin (f);
7188 #else
7189
7190 #endif
7191
7192 #ifdef HAVE_XDBE
7193 if (FRAME_X_DOUBLE_BUFFERED_P (f))
7194
7195
7196 FRAME_X_COMPLETE_P (f) = false;
7197 #endif
7198 }
7199
7200
7201
7202 static void
7203 x_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
7204 {
7205 struct frame *f = XFRAME (WINDOW_FRAME (w));
7206 struct face *face;
7207
7208 face = FACE_FROM_ID_OR_NULL (f, VERTICAL_BORDER_FACE_ID);
7209 if (face)
7210 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
7211 face->foreground);
7212
7213 #ifdef USE_CAIRO
7214 x_fill_rectangle (f, f->output_data.x->normal_gc, x, y0, 1, y1 - y0, false);
7215 #else
7216 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
7217 f->output_data.x->normal_gc, x, y0, x, y1);
7218 #endif
7219 }
7220
7221
7222
7223 static void
7224 x_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
7225 {
7226 struct frame *f = XFRAME (WINDOW_FRAME (w));
7227 struct face *face = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FACE_ID);
7228 struct face *face_first
7229 = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID);
7230 struct face *face_last
7231 = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_LAST_PIXEL_FACE_ID);
7232 unsigned long color = face ? face->foreground : FRAME_FOREGROUND_PIXEL (f);
7233 unsigned long color_first = (face_first
7234 ? face_first->foreground
7235 : FRAME_FOREGROUND_PIXEL (f));
7236 unsigned long color_last = (face_last
7237 ? face_last->foreground
7238 : FRAME_FOREGROUND_PIXEL (f));
7239 Display *display = FRAME_X_DISPLAY (f);
7240
7241 if ((y1 - y0 > x1 - x0) && (x1 - x0 >= 3))
7242
7243
7244 {
7245 XSetForeground (display, f->output_data.x->normal_gc, color_first);
7246 x_fill_rectangle (f, f->output_data.x->normal_gc,
7247 x0, y0, 1, y1 - y0, false);
7248 XSetForeground (display, f->output_data.x->normal_gc, color);
7249 x_fill_rectangle (f, f->output_data.x->normal_gc,
7250 x0 + 1, y0, x1 - x0 - 2, y1 - y0, false);
7251 XSetForeground (display, f->output_data.x->normal_gc, color_last);
7252 x_fill_rectangle (f, f->output_data.x->normal_gc,
7253 x1 - 1, y0, 1, y1 - y0, false);
7254 }
7255 else if ((x1 - x0 > y1 - y0) && (y1 - y0 >= 3))
7256
7257
7258 {
7259 XSetForeground (display, f->output_data.x->normal_gc, color_first);
7260 x_fill_rectangle (f, f->output_data.x->normal_gc,
7261 x0, y0, x1 - x0, 1, false);
7262 XSetForeground (display, f->output_data.x->normal_gc, color);
7263 x_fill_rectangle (f, f->output_data.x->normal_gc,
7264 x0, y0 + 1, x1 - x0, y1 - y0 - 2, false);
7265 XSetForeground (display, f->output_data.x->normal_gc, color_last);
7266 x_fill_rectangle (f, f->output_data.x->normal_gc,
7267 x0, y1 - 1, x1 - x0, 1, false);
7268 }
7269 else
7270 {
7271
7272
7273 XSetForeground (display, f->output_data.x->normal_gc, color);
7274 x_fill_rectangle (f, f->output_data.x->normal_gc,
7275 x0, y0, x1 - x0, y1 - y0, false);
7276 }
7277 }
7278
7279 #ifdef HAVE_XDBE
7280
7281
7282
7283
7284
7285 static void
7286 show_back_buffer (struct frame *f)
7287 {
7288 XdbeSwapInfo swap_info;
7289 #ifdef USE_CAIRO
7290 cairo_t *cr;
7291 #endif
7292
7293 if (FRAME_X_DOUBLE_BUFFERED_P (f))
7294 {
7295 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
7296
7297
7298 x_sync_wait_for_frame_drawn_event (f);
7299
7300
7301 x_sync_update_begin (f);
7302 #endif
7303
7304 #ifdef USE_CAIRO
7305 cr = FRAME_CR_CONTEXT (f);
7306 if (cr)
7307 cairo_surface_flush (cairo_get_target (cr));
7308 #endif
7309 memset (&swap_info, 0, sizeof (swap_info));
7310 swap_info.swap_window = FRAME_X_WINDOW (f);
7311 swap_info.swap_action = XdbeCopied;
7312 XdbeSwapBuffers (FRAME_X_DISPLAY (f), &swap_info, 1);
7313
7314 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
7315
7316 x_sync_update_finish (f);
7317 #endif
7318 }
7319
7320 FRAME_X_NEED_BUFFER_FLIP (f) = false;
7321 }
7322
7323 #endif
7324
7325
7326
7327
7328 static void
7329 x_flip_and_flush (struct frame *f)
7330 {
7331
7332
7333
7334 if (!NILP (Vinhibit_redisplay)
7335
7336
7337 && !FRAME_TOOLTIP_P (f))
7338 return;
7339
7340 block_input ();
7341 #ifdef HAVE_XDBE
7342 if (FRAME_X_NEED_BUFFER_FLIP (f))
7343 show_back_buffer (f);
7344
7345
7346
7347 FRAME_X_COMPLETE_P (f) = true;
7348 #endif
7349 x_flush (f);
7350 unblock_input ();
7351 }
7352
7353
7354
7355
7356 static void
7357 x_update_end (struct frame *f)
7358 {
7359
7360 MOUSE_HL_INFO (f)->mouse_face_defer = false;
7361
7362 #ifdef USE_CAIRO
7363 # ifdef HAVE_XDBE
7364 if (!FRAME_X_DOUBLE_BUFFERED_P (f) && FRAME_CR_CONTEXT (f))
7365 cairo_surface_flush (cairo_get_target (FRAME_CR_CONTEXT (f)));
7366 # endif
7367 #endif
7368
7369
7370
7371
7372 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
7373 #ifdef HAVE_XDBE
7374 if (!FRAME_X_DOUBLE_BUFFERED_P (f))
7375 #endif
7376 x_sync_update_finish (f);
7377 #endif
7378 }
7379
7380
7381
7382
7383 static void
7384 XTframe_up_to_date (struct frame *f)
7385 {
7386 #if defined HAVE_XSYNC && defined HAVE_GTK3
7387 GtkWidget *widget;
7388 GdkWindow *window;
7389 GdkFrameClock *clock;
7390 #endif
7391
7392 eassert (FRAME_X_P (f));
7393 block_input ();
7394 FRAME_MOUSE_UPDATE (f);
7395
7396 #ifdef HAVE_XDBE
7397 if (!buffer_flipping_blocked_p ()
7398 && FRAME_X_NEED_BUFFER_FLIP (f))
7399 show_back_buffer (f);
7400
7401
7402 FRAME_X_COMPLETE_P (f) = true;
7403 #endif
7404
7405 #ifdef HAVE_XSYNC
7406 #ifndef HAVE_GTK3
7407 if (FRAME_X_OUTPUT (f)->sync_end_pending_p
7408 && FRAME_X_BASIC_COUNTER (f) != None)
7409 {
7410 XSyncSetCounter (FRAME_X_DISPLAY (f),
7411 FRAME_X_BASIC_COUNTER (f),
7412 FRAME_X_OUTPUT (f)->pending_basic_counter_value);
7413 FRAME_X_OUTPUT (f)->sync_end_pending_p = false;
7414 }
7415 #else
7416 if (FRAME_X_OUTPUT (f)->xg_sync_end_pending_p)
7417 {
7418 widget = FRAME_GTK_OUTER_WIDGET (f);
7419 window = gtk_widget_get_window (widget);
7420 eassert (window);
7421 clock = gdk_window_get_frame_clock (window);
7422 eassert (clock);
7423
7424 gdk_frame_clock_request_phase (clock,
7425 GDK_FRAME_CLOCK_PHASE_AFTER_PAINT);
7426 FRAME_X_OUTPUT (f)->xg_sync_end_pending_p = false;
7427 }
7428 #endif
7429 #endif
7430 unblock_input ();
7431 }
7432
7433 #ifdef HAVE_XDBE
7434 static void
7435 XTbuffer_flipping_unblocked_hook (struct frame *f)
7436 {
7437 block_input ();
7438
7439 if (FRAME_X_NEED_BUFFER_FLIP (f))
7440 show_back_buffer (f);
7441
7442 unblock_input ();
7443 }
7444 #endif
7445
7446
7447
7448
7449
7450
7451
7452 void
7453 x_clear_under_internal_border (struct frame *f)
7454 {
7455 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0)
7456 {
7457 int border = FRAME_INTERNAL_BORDER_WIDTH (f);
7458 int width = FRAME_PIXEL_WIDTH (f);
7459 int height = FRAME_PIXEL_HEIGHT (f);
7460 int margin = FRAME_TOP_MARGIN_HEIGHT (f);
7461 int face_id =
7462 (FRAME_PARENT_FRAME (f)
7463 ? (!NILP (Vface_remapping_alist)
7464 ? lookup_basic_face (NULL, f, CHILD_FRAME_BORDER_FACE_ID)
7465 : CHILD_FRAME_BORDER_FACE_ID)
7466 : (!NILP (Vface_remapping_alist)
7467 ? lookup_basic_face (NULL, f, INTERNAL_BORDER_FACE_ID)
7468 : INTERNAL_BORDER_FACE_ID));
7469 struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
7470
7471 if (face)
7472 {
7473 unsigned long color = face->background;
7474 Display *display = FRAME_X_DISPLAY (f);
7475 GC gc = f->output_data.x->normal_gc;
7476
7477 XSetForeground (display, gc, color);
7478 x_fill_rectangle (f, gc, 0, margin, width, border, false);
7479 x_fill_rectangle (f, gc, 0, 0, border, height, false);
7480 x_fill_rectangle (f, gc, width - border, 0, border, height, false);
7481 x_fill_rectangle (f, gc, 0, height - border, width, border, false);
7482 XSetForeground (display, gc, FRAME_FOREGROUND_PIXEL (f));
7483 }
7484 else
7485 {
7486 x_clear_area (f, 0, 0, border, height);
7487 x_clear_area (f, 0, margin, width, border);
7488 x_clear_area (f, width - border, 0, border, height);
7489 x_clear_area (f, 0, height - border, width, border);
7490 }
7491 }
7492 }
7493
7494
7495
7496
7497
7498
7499
7500 static void
7501 x_after_update_window_line (struct window *w, struct glyph_row *desired_row)
7502 {
7503 eassert (w);
7504
7505 if (!desired_row->mode_line_p && !w->pseudo_window_p)
7506 desired_row->redraw_fringe_bitmaps_p = true;
7507
7508 #ifdef USE_X_TOOLKIT
7509
7510
7511
7512
7513
7514
7515 {
7516 struct frame *f;
7517 int width, height;
7518
7519 if (windows_or_buffers_changed
7520 && desired_row->full_width_p
7521 && (f = XFRAME (w->frame),
7522 width = FRAME_INTERNAL_BORDER_WIDTH (f),
7523 width != 0)
7524 && (height = desired_row->visible_height,
7525 height > 0))
7526 {
7527 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
7528 int face_id =
7529 (FRAME_PARENT_FRAME (f)
7530 ? (!NILP (Vface_remapping_alist)
7531 ? lookup_basic_face (NULL, f, CHILD_FRAME_BORDER_FACE_ID)
7532 : CHILD_FRAME_BORDER_FACE_ID)
7533 : (!NILP (Vface_remapping_alist)
7534 ? lookup_basic_face (NULL, f, INTERNAL_BORDER_FACE_ID)
7535 : INTERNAL_BORDER_FACE_ID));
7536 struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
7537
7538 if (face)
7539 {
7540 unsigned long color = face->background;
7541 Display *display = FRAME_X_DISPLAY (f);
7542 GC gc = f->output_data.x->normal_gc;
7543
7544 XSetForeground (display, gc, color);
7545 x_fill_rectangle (f, gc, 0, y, width, height, true);
7546 x_fill_rectangle (f, gc, FRAME_PIXEL_WIDTH (f) - width, y,
7547 width, height, true);
7548 XSetForeground (display, gc, FRAME_FOREGROUND_PIXEL (f));
7549 }
7550 else
7551 {
7552 x_clear_area (f, 0, y, width, height);
7553 x_clear_area (f, FRAME_PIXEL_WIDTH (f) - width, y, width, height);
7554 }
7555 }
7556 }
7557 #endif
7558 }
7559
7560 static void
7561 x_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
7562 struct draw_fringe_bitmap_params *p)
7563 {
7564 struct frame *f = XFRAME (WINDOW_FRAME (w));
7565 Display *display = FRAME_X_DISPLAY (f);
7566 GC gc = f->output_data.x->normal_gc;
7567 struct face *face = p->face;
7568
7569
7570 x_clip_to_row (w, row, ANY_AREA, gc);
7571
7572 if (p->bx >= 0 && !p->overlay_p)
7573 {
7574
7575
7576
7577
7578 if (face->stipple)
7579 {
7580 XSetFillStyle (display, face->gc, FillOpaqueStippled);
7581 x_fill_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny,
7582 true);
7583 XSetFillStyle (display, face->gc, FillSolid);
7584
7585 row->stipple_p = true;
7586 }
7587 else
7588 {
7589 XSetBackground (display, face->gc, face->background);
7590 x_clear_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny,
7591 true);
7592 XSetForeground (display, face->gc, face->foreground);
7593 }
7594 }
7595
7596 #ifdef USE_CAIRO
7597 if (p->which
7598 && p->which < max_fringe_bmp
7599 && p->which < max_used_fringe_bitmap)
7600 {
7601 XGCValues gcv;
7602
7603 XGetGCValues (display, gc, GCForeground | GCBackground, &gcv);
7604 XSetForeground (display, gc, (p->cursor_p
7605 ? (p->overlay_p ? face->background
7606 : f->output_data.x->cursor_pixel)
7607 : face->foreground));
7608 XSetBackground (display, gc, face->background);
7609 if (!fringe_bmp[p->which])
7610 {
7611
7612
7613
7614
7615
7616
7617 gui_define_fringe_bitmap (f, p->which);
7618 }
7619 x_cr_draw_image (f, gc, fringe_bmp[p->which], 0, p->dh,
7620 p->wd, p->h, p->x, p->y, p->overlay_p);
7621 XSetForeground (display, gc, gcv.foreground);
7622 XSetBackground (display, gc, gcv.background);
7623 }
7624 #else
7625 if (p->which)
7626 {
7627 Drawable drawable = FRAME_X_DRAWABLE (f);
7628 char *bits;
7629 Pixmap pixmap, clipmask = None;
7630 int depth = FRAME_DISPLAY_INFO (f)->n_planes;
7631 XGCValues gcv;
7632 unsigned long background = face->background;
7633 XColor bg;
7634 #ifdef HAVE_XRENDER
7635 Picture picture = None;
7636 XRenderPictureAttributes attrs;
7637
7638 memset (&attrs, 0, sizeof attrs);
7639 #endif
7640
7641 if (p->wd > 8)
7642 bits = (char *) (p->bits + p->dh);
7643 else
7644 bits = (char *) p->bits + p->dh;
7645
7646 if (FRAME_DISPLAY_INFO (f)->alpha_bits
7647 && f->alpha_background < 1.0)
7648 {
7649 bg.pixel = background;
7650 x_query_colors (f, &bg, 1);
7651 bg.red *= f->alpha_background;
7652 bg.green *= f->alpha_background;
7653 bg.blue *= f->alpha_background;
7654
7655 background = x_make_truecolor_pixel (FRAME_DISPLAY_INFO (f),
7656 bg.red, bg.green, bg.blue);
7657 background &= ~FRAME_DISPLAY_INFO (f)->alpha_mask;
7658 background |= (((unsigned long) (f->alpha_background * 0xffff)
7659 >> (16 - FRAME_DISPLAY_INFO (f)->alpha_bits))
7660 << FRAME_DISPLAY_INFO (f)->alpha_offset);
7661 }
7662
7663
7664
7665 pixmap = XCreatePixmapFromBitmapData (display, drawable, bits, p->wd, p->h,
7666 (p->cursor_p
7667 ? (p->overlay_p ? face->background
7668 : f->output_data.x->cursor_pixel)
7669 : face->foreground),
7670 background, depth);
7671
7672 #ifdef HAVE_XRENDER
7673 if (FRAME_X_PICTURE_FORMAT (f)
7674 && (x_xr_ensure_picture (f), FRAME_X_PICTURE (f)))
7675 picture = XRenderCreatePicture (display, pixmap,
7676 FRAME_X_PICTURE_FORMAT (f),
7677 0, &attrs);
7678 #endif
7679
7680 if (p->overlay_p)
7681 {
7682 clipmask = XCreatePixmapFromBitmapData (display,
7683 FRAME_DISPLAY_INFO (f)->root_window,
7684 bits, p->wd, p->h,
7685 1, 0, 1);
7686
7687 #ifdef HAVE_XRENDER
7688 if (picture != None)
7689 {
7690 attrs.clip_mask = clipmask;
7691 attrs.clip_x_origin = p->x;
7692 attrs.clip_y_origin = p->y;
7693
7694 XRenderChangePicture (display, FRAME_X_PICTURE (f),
7695 CPClipMask | CPClipXOrigin | CPClipYOrigin,
7696 &attrs);
7697 }
7698 else
7699 #endif
7700 {
7701 gcv.clip_mask = clipmask;
7702 gcv.clip_x_origin = p->x;
7703 gcv.clip_y_origin = p->y;
7704 XChangeGC (display, gc, GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv);
7705 }
7706 }
7707
7708 #ifdef HAVE_XRENDER
7709 if (picture != None)
7710 {
7711 x_xr_apply_ext_clip (f, gc);
7712 XRenderComposite (display, PictOpSrc, picture,
7713 None, FRAME_X_PICTURE (f),
7714 0, 0, 0, 0, p->x, p->y, p->wd, p->h);
7715 x_xr_reset_ext_clip (f);
7716
7717 XRenderFreePicture (display, picture);
7718 }
7719 else
7720 #endif
7721 XCopyArea (display, pixmap, drawable, gc, 0, 0,
7722 p->wd, p->h, p->x, p->y);
7723 XFreePixmap (display, pixmap);
7724
7725 if (p->overlay_p)
7726 {
7727 gcv.clip_mask = (Pixmap) 0;
7728 XChangeGC (display, gc, GCClipMask, &gcv);
7729 XFreePixmap (display, clipmask);
7730 }
7731 }
7732 #endif
7733
7734 x_reset_clip_rectangles (f, gc);
7735 }
7736
7737
7738
7739
7740
7741 static bool x_alloc_lighter_color (struct frame *, Display *, Colormap,
7742 unsigned long *, double, int);
7743 static void x_scroll_bar_clear (struct frame *);
7744
7745 #ifdef GLYPH_DEBUG
7746 static void x_check_font (struct frame *, struct font *);
7747 #endif
7748
7749
7750
7751
7752
7753
7754
7755
7756
7757
7758
7759
7760
7761
7762
7763
7764
7765
7766
7767
7768
7769
7770
7771 static void
7772 x_display_set_last_user_time (struct x_display_info *dpyinfo, Time time,
7773 bool send_event, bool set_property)
7774 {
7775 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
7776 uint_fast64_t monotonic_time;
7777 uint_fast64_t monotonic_ms;
7778 int_fast64_t diff_ms;
7779 #endif
7780 #ifndef USE_GTK
7781 struct frame *focus_frame;
7782 Time old_time;
7783
7784 focus_frame = dpyinfo->x_focus_frame;
7785 old_time = dpyinfo->last_user_time;
7786 #endif
7787
7788 #ifdef ENABLE_CHECKING
7789 eassert (time <= X_ULONG_MAX);
7790 #endif
7791
7792 if (!send_event || time > dpyinfo->last_user_time)
7793 dpyinfo->last_user_time = time;
7794
7795 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
7796 if (!send_event)
7797 {
7798
7799
7800 monotonic_time = x_sync_current_monotonic_time ();
7801 monotonic_ms = monotonic_time / 1000;
7802
7803 dpyinfo->server_time_monotonic_p
7804 = (monotonic_time != 0
7805 && !INT_SUBTRACT_WRAPV (time, monotonic_ms, &diff_ms)
7806 && -500 < diff_ms && diff_ms < 500);
7807
7808 if (!dpyinfo->server_time_monotonic_p)
7809 {
7810
7811
7812
7813 if (!monotonic_time
7814 || INT_MULTIPLY_WRAPV (time, 1000, &dpyinfo->server_time_offset)
7815 || INT_SUBTRACT_WRAPV (dpyinfo->server_time_offset,
7816 monotonic_time,
7817 &dpyinfo->server_time_offset))
7818 dpyinfo->server_time_offset = 0;
7819
7820
7821
7822
7823
7824
7825 monotonic_ms = monotonic_ms & 0xffffffff;
7826 if (!INT_SUBTRACT_WRAPV (time, monotonic_ms, &diff_ms)
7827 && -500 < diff_ms && diff_ms < 500)
7828 {
7829
7830
7831
7832 if (INT_SUBTRACT_WRAPV (monotonic_time / 1000, monotonic_ms,
7833 &dpyinfo->server_time_offset)
7834 || INT_MULTIPLY_WRAPV (dpyinfo->server_time_offset,
7835 1000, &dpyinfo->server_time_offset)
7836 || INT_SUBTRACT_WRAPV (0, dpyinfo->server_time_offset,
7837 &dpyinfo->server_time_offset))
7838 dpyinfo->server_time_offset = 0;
7839 }
7840 }
7841 }
7842 #endif
7843
7844 #ifndef USE_GTK
7845
7846 if (focus_frame && old_time != dpyinfo->last_user_time
7847 && set_property)
7848 {
7849 time = dpyinfo->last_user_time;
7850
7851 while (FRAME_PARENT_FRAME (focus_frame))
7852 focus_frame = FRAME_PARENT_FRAME (focus_frame);
7853
7854 if (FRAME_X_OUTPUT (focus_frame)->user_time_window != None)
7855 XChangeProperty (dpyinfo->display,
7856 FRAME_X_OUTPUT (focus_frame)->user_time_window,
7857 dpyinfo->Xatom_net_wm_user_time,
7858 XA_CARDINAL, 32, PropModeReplace,
7859 (unsigned char *) &time, 1);
7860 }
7861 #endif
7862 }
7863
7864 #ifdef USE_GTK
7865
7866 static void
7867 x_set_gtk_user_time (struct frame *f, Time time)
7868 {
7869 GtkWidget *widget;
7870 GdkWindow *window;
7871
7872 widget = FRAME_GTK_OUTER_WIDGET (f);
7873 window = gtk_widget_get_window (widget);
7874
7875
7876 if (!window)
7877 return;
7878
7879 gdk_x11_window_set_user_time (window, time);
7880 }
7881
7882 #endif
7883
7884 #if !defined USE_GTK || defined HAVE_XFIXES
7885
7886
7887
7888
7889
7890
7891 static Window
7892 x_create_special_window (struct x_display_info *dpyinfo,
7893 Window parent_window)
7894 {
7895 XSetWindowAttributes attrs;
7896
7897 attrs.override_redirect = True;
7898
7899 return XCreateWindow (dpyinfo->display, parent_window,
7900 -1, -1, 1, 1, 0, CopyFromParent, InputOnly,
7901 CopyFromParent, CWOverrideRedirect, &attrs);
7902 }
7903
7904 #endif
7905
7906
7907
7908
7909 #ifndef USE_GTK
7910
7911 static void
7912 x_update_frame_user_time_window (struct frame *f)
7913 {
7914 struct x_output *output;
7915 struct x_display_info *dpyinfo;
7916
7917 output = FRAME_X_OUTPUT (f);
7918 dpyinfo = FRAME_DISPLAY_INFO (f);
7919
7920 if (!NILP (Vx_no_window_manager)
7921 || !x_wm_supports (f, dpyinfo->Xatom_net_wm_user_time))
7922 {
7923 if (output->user_time_window != None
7924 && output->user_time_window != FRAME_OUTER_WINDOW (f))
7925 {
7926 XDestroyWindow (dpyinfo->display, output->user_time_window);
7927 XDeleteProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
7928 dpyinfo->Xatom_net_wm_user_time_window);
7929 }
7930 else
7931 XDeleteProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
7932 dpyinfo->Xatom_net_wm_user_time);
7933
7934 output->user_time_window = None;
7935 return;
7936 }
7937
7938 if (!x_wm_supports (f, dpyinfo->Xatom_net_wm_user_time_window))
7939 {
7940 if (output->user_time_window == None)
7941 output->user_time_window = FRAME_OUTER_WINDOW (f);
7942 else if (output->user_time_window != FRAME_OUTER_WINDOW (f))
7943 {
7944 XDestroyWindow (dpyinfo->display,
7945 output->user_time_window);
7946 XDeleteProperty (dpyinfo->display,
7947 FRAME_OUTER_WINDOW (f),
7948 dpyinfo->Xatom_net_wm_user_time_window);
7949 output->user_time_window = FRAME_OUTER_WINDOW (f);
7950 }
7951 }
7952 else
7953 {
7954 if (output->user_time_window == FRAME_OUTER_WINDOW (f)
7955 || output->user_time_window == None)
7956 {
7957
7958
7959
7960
7961
7962
7963
7964
7965 output->user_time_window
7966 = x_create_special_window (dpyinfo, FRAME_X_WINDOW (f));
7967
7968 XDeleteProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
7969 dpyinfo->Xatom_net_wm_user_time);
7970 XChangeProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
7971 dpyinfo->Xatom_net_wm_user_time_window,
7972 XA_WINDOW, 32, PropModeReplace,
7973 (unsigned char *) &output->user_time_window, 1);
7974 }
7975 }
7976 }
7977
7978 #endif
7979
7980 void
7981 x_set_last_user_time_from_lisp (struct x_display_info *dpyinfo,
7982 Time time)
7983 {
7984 x_display_set_last_user_time (dpyinfo, time, true, true);
7985 }
7986
7987
7988
7989
7990
7991 static void
7992 x_set_cursor_gc (struct glyph_string *s)
7993 {
7994 if (s->font == FRAME_FONT (s->f)
7995 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
7996 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
7997 && !s->cmp)
7998 s->gc = s->f->output_data.x->cursor_gc;
7999 else
8000 {
8001
8002 XGCValues xgcv;
8003 unsigned long mask;
8004 Display *display = FRAME_X_DISPLAY (s->f);
8005
8006 xgcv.background = s->f->output_data.x->cursor_pixel;
8007 xgcv.foreground = s->face->background;
8008
8009
8010 if (xgcv.foreground == xgcv.background)
8011 xgcv.foreground = s->face->foreground;
8012 if (xgcv.foreground == xgcv.background)
8013 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
8014 if (xgcv.foreground == xgcv.background)
8015 xgcv.foreground = s->face->foreground;
8016
8017
8018 if (xgcv.background == s->face->background
8019 && xgcv.foreground == s->face->foreground)
8020 {
8021 xgcv.background = s->face->foreground;
8022 xgcv.foreground = s->face->background;
8023 }
8024
8025 IF_DEBUG (x_check_font (s->f, s->font));
8026 xgcv.graphics_exposures = False;
8027 xgcv.line_width = 1;
8028 mask = (GCForeground | GCBackground
8029 | GCGraphicsExposures
8030 | GCLineWidth);
8031
8032 if (FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc)
8033 XChangeGC (display, FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc,
8034 mask, &xgcv);
8035 else
8036 FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc
8037 = XCreateGC (display, FRAME_X_DRAWABLE (s->f), mask, &xgcv);
8038
8039 s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc;
8040 }
8041 }
8042
8043
8044
8045
8046 static void
8047 x_set_mouse_face_gc (struct glyph_string *s)
8048 {
8049 if (s->font == s->face->font)
8050 s->gc = s->face->gc;
8051 else
8052 {
8053
8054
8055 XGCValues xgcv;
8056 unsigned long mask;
8057 Display *display = FRAME_X_DISPLAY (s->f);
8058
8059 xgcv.background = s->face->background;
8060 xgcv.foreground = s->face->foreground;
8061 xgcv.graphics_exposures = False;
8062 xgcv.line_width = 1;
8063
8064 mask = (GCForeground | GCBackground
8065 | GCGraphicsExposures
8066 | GCLineWidth);
8067
8068 if (FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc)
8069 XChangeGC (display, FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc,
8070 mask, &xgcv);
8071 else
8072 FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc
8073 = XCreateGC (display, FRAME_X_DRAWABLE (s->f), mask, &xgcv);
8074
8075 s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc;
8076
8077 }
8078 eassert (s->gc != 0);
8079 }
8080
8081
8082
8083
8084
8085
8086 static void
8087 x_set_mode_line_face_gc (struct glyph_string *s)
8088 {
8089 s->gc = s->face->gc;
8090 }
8091
8092
8093
8094
8095
8096
8097 static void
8098 x_set_glyph_string_gc (struct glyph_string *s)
8099 {
8100 prepare_face_for_display (s->f, s->face);
8101
8102 if (s->hl == DRAW_NORMAL_TEXT)
8103 {
8104 s->gc = s->face->gc;
8105 s->stippled_p = s->face->stipple != 0;
8106 }
8107 else if (s->hl == DRAW_INVERSE_VIDEO)
8108 {
8109 x_set_mode_line_face_gc (s);
8110 s->stippled_p = s->face->stipple != 0;
8111 }
8112 else if (s->hl == DRAW_CURSOR)
8113 {
8114 x_set_cursor_gc (s);
8115 s->stippled_p = false;
8116 }
8117 else if (s->hl == DRAW_MOUSE_FACE)
8118 {
8119 x_set_mouse_face_gc (s);
8120 s->stippled_p = s->face->stipple != 0;
8121 }
8122 else if (s->hl == DRAW_IMAGE_RAISED
8123 || s->hl == DRAW_IMAGE_SUNKEN)
8124 {
8125 s->gc = s->face->gc;
8126 s->stippled_p = s->face->stipple != 0;
8127 }
8128 else
8129 emacs_abort ();
8130
8131
8132 eassert (s->gc != 0);
8133 }
8134
8135
8136
8137
8138
8139 static void
8140 x_set_glyph_string_clipping (struct glyph_string *s)
8141 {
8142 XRectangle *r = s->clip;
8143 int n = get_glyph_string_clip_rects (s, r, 2);
8144
8145 if (n > 0)
8146 x_set_clip_rectangles (s->f, s->gc, r, n);
8147 s->num_clips = n;
8148 }
8149
8150
8151
8152
8153
8154
8155 static void
8156 x_set_glyph_string_clipping_exactly (struct glyph_string *src, struct glyph_string *dst)
8157 {
8158 XRectangle r;
8159
8160 r.x = src->x;
8161 r.width = src->width;
8162 r.y = src->y;
8163 r.height = src->height;
8164 dst->clip[0] = r;
8165 dst->num_clips = 1;
8166 x_set_clip_rectangles (dst->f, dst->gc, &r, 1);
8167 }
8168
8169
8170
8171
8172
8173 static void
8174 x_compute_glyph_string_overhangs (struct glyph_string *s)
8175 {
8176 if (s->cmp == NULL
8177 && (s->first_glyph->type == CHAR_GLYPH
8178 || s->first_glyph->type == COMPOSITE_GLYPH))
8179 {
8180 struct font_metrics metrics;
8181
8182 if (s->first_glyph->type == CHAR_GLYPH)
8183 {
8184 struct font *font = s->font;
8185 font->driver->text_extents (font, s->char2b, s->nchars, &metrics);
8186 }
8187 else
8188 {
8189 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
8190
8191 composition_gstring_width (gstring, s->cmp_from, s->cmp_to, &metrics);
8192 }
8193 s->right_overhang = (metrics.rbearing > metrics.width
8194 ? metrics.rbearing - metrics.width : 0);
8195 s->left_overhang = metrics.lbearing < 0 ? - metrics.lbearing : 0;
8196 }
8197 else if (s->cmp)
8198 {
8199 s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width;
8200 s->left_overhang = - s->cmp->lbearing;
8201 }
8202 }
8203
8204
8205
8206
8207 static void
8208 x_clear_glyph_string_rect (struct glyph_string *s, int x, int y, int w, int h)
8209 {
8210 x_clear_rectangle (s->f, s->gc, x, y, w, h, s->hl != DRAW_CURSOR);
8211 }
8212
8213 #ifndef USE_CAIRO
8214
8215 static void
8216 x_clear_point (struct frame *f, GC gc, int x, int y,
8217 bool respect_alpha_background)
8218 {
8219 XGCValues xgcv;
8220 Display *dpy;
8221
8222 dpy = FRAME_X_DISPLAY (f);
8223
8224 if (f->alpha_background != 1.0
8225 && respect_alpha_background)
8226 {
8227 x_clear_rectangle (f, gc, x, y, 1, 1, true);
8228 return;
8229 }
8230
8231 XGetGCValues (dpy, gc, GCBackground | GCForeground, &xgcv);
8232 XSetForeground (dpy, gc, xgcv.background);
8233 XDrawPoint (dpy, FRAME_X_DRAWABLE (f), gc, x, y);
8234 XSetForeground (dpy, gc, xgcv.foreground);
8235 }
8236
8237 #endif
8238
8239
8240
8241
8242
8243
8244
8245 static void
8246 x_draw_glyph_string_background (struct glyph_string *s, bool force_p)
8247 {
8248
8249
8250 if (!s->background_filled_p)
8251 {
8252 int box_line_width = max (s->face->box_horizontal_line_width, 0);
8253
8254 if (s->stippled_p)
8255 {
8256 Display *display = FRAME_X_DISPLAY (s->f);
8257
8258
8259 XSetFillStyle (display, s->gc, FillOpaqueStippled);
8260 x_fill_rectangle (s->f, s->gc, s->x,
8261 s->y + box_line_width,
8262 s->background_width,
8263 s->height - 2 * box_line_width,
8264 s->hl != DRAW_CURSOR);
8265 XSetFillStyle (display, s->gc, FillSolid);
8266 s->background_filled_p = true;
8267 }
8268 else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
8269
8270
8271
8272
8273 || FONT_TOO_HIGH (s->font)
8274 || s->font_not_found_p
8275 || s->extends_to_end_of_line_p
8276 || force_p)
8277 {
8278 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
8279 s->background_width,
8280 s->height - 2 * box_line_width);
8281 s->background_filled_p = true;
8282 }
8283 }
8284 }
8285
8286
8287
8288
8289 static void
8290 x_draw_glyph_string_foreground (struct glyph_string *s)
8291 {
8292 int i, x;
8293
8294
8295
8296 if (s->face->box != FACE_NO_BOX
8297 && s->first_glyph->left_box_line_p)
8298 x = s->x + max (s->face->box_vertical_line_width, 0);
8299 else
8300 x = s->x;
8301
8302
8303
8304 if (s->font_not_found_p)
8305 {
8306 for (i = 0; i < s->nchars; ++i)
8307 {
8308 struct glyph *g = s->first_glyph + i;
8309 x_draw_rectangle (s->f,
8310 s->gc, x, s->y, g->pixel_width - 1,
8311 s->height - 1);
8312 x += g->pixel_width;
8313 }
8314 }
8315 else
8316 {
8317 struct font *font = s->font;
8318 #ifdef USE_CAIRO
8319 if (!EQ (font->driver->type, Qx)
8320 || x_try_cr_xlib_drawable (s->f, s->gc))
8321 {
8322 #endif
8323 int boff = font->baseline_offset;
8324 int y;
8325
8326 if (font->vertical_centering)
8327 boff = VCENTER_BASELINE_OFFSET (font, s->f) - boff;
8328
8329 y = s->ybase - boff;
8330 if (s->for_overlaps
8331 || (s->background_filled_p && s->hl != DRAW_CURSOR))
8332 font->driver->draw (s, 0, s->nchars, x, y, false);
8333 else
8334 font->driver->draw (s, 0, s->nchars, x, y, true);
8335 if (s->face->overstrike)
8336 font->driver->draw (s, 0, s->nchars, x + 1, y, false);
8337 #ifdef USE_CAIRO
8338 if (EQ (font->driver->type, Qx))
8339 x_end_cr_xlib_drawable (s->f, s->gc);
8340 }
8341 else
8342 {
8343
8344
8345 if (!(s->for_overlaps
8346 || (s->background_filled_p && s->hl != DRAW_CURSOR)))
8347 {
8348 int box_line_width = max (s->face->box_horizontal_line_width, 0);
8349
8350 if (s->stippled_p)
8351 {
8352 Display *display = FRAME_X_DISPLAY (s->f);
8353
8354
8355 XSetFillStyle (display, s->gc, FillOpaqueStippled);
8356 x_fill_rectangle (s->f, s->gc, s->x,
8357 s->y + box_line_width,
8358 s->background_width,
8359 s->height - 2 * box_line_width,
8360 false);
8361 XSetFillStyle (display, s->gc, FillSolid);
8362 }
8363 else
8364 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
8365 s->background_width,
8366 s->height - 2 * box_line_width);
8367 }
8368 for (i = 0; i < s->nchars; ++i)
8369 {
8370 struct glyph *g = s->first_glyph + i;
8371 x_draw_rectangle (s->f,
8372 s->gc, x, s->y, g->pixel_width - 1,
8373 s->height - 1);
8374 x += g->pixel_width;
8375 }
8376 }
8377 #endif
8378 }
8379 }
8380
8381
8382
8383 static void
8384 x_draw_composite_glyph_string_foreground (struct glyph_string *s)
8385 {
8386 int i, j, x;
8387 struct font *font = s->font;
8388
8389
8390
8391 if (s->face && s->face->box != FACE_NO_BOX
8392 && s->first_glyph->left_box_line_p)
8393 x = s->x + max (s->face->box_vertical_line_width, 0);
8394 else
8395 x = s->x;
8396
8397
8398
8399
8400
8401
8402
8403
8404 if (s->font_not_found_p)
8405 {
8406 if (s->cmp_from == 0)
8407 x_draw_rectangle (s->f, s->gc, x, s->y,
8408 s->width - 1, s->height - 1);
8409 }
8410 else
8411 #ifdef USE_CAIRO
8412 if (!EQ (font->driver->type, Qx)
8413 || x_try_cr_xlib_drawable (s->f, s->gc))
8414 {
8415 #endif
8416 if (! s->first_glyph->u.cmp.automatic)
8417 {
8418 int y = s->ybase;
8419
8420 for (i = 0, j = s->cmp_from; i < s->nchars; i++, j++)
8421
8422
8423 if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
8424 {
8425 int xx = x + s->cmp->offsets[j * 2];
8426 int yy = y - s->cmp->offsets[j * 2 + 1];
8427
8428 font->driver->draw (s, j, j + 1, xx, yy, false);
8429 if (s->face->overstrike)
8430 font->driver->draw (s, j, j + 1, xx + 1, yy, false);
8431 }
8432 }
8433 else
8434 {
8435 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
8436 Lisp_Object glyph;
8437 int y = s->ybase;
8438 int width = 0;
8439
8440 for (i = j = s->cmp_from; i < s->cmp_to; i++)
8441 {
8442 glyph = LGSTRING_GLYPH (gstring, i);
8443 if (NILP (LGLYPH_ADJUSTMENT (glyph)))
8444 width += LGLYPH_WIDTH (glyph);
8445 else
8446 {
8447 int xoff, yoff, wadjust;
8448
8449 if (j < i)
8450 {
8451 font->driver->draw (s, j, i, x, y, false);
8452 if (s->face->overstrike)
8453 font->driver->draw (s, j, i, x + 1, y, false);
8454 x += width;
8455 }
8456 xoff = LGLYPH_XOFF (glyph);
8457 yoff = LGLYPH_YOFF (glyph);
8458 wadjust = LGLYPH_WADJUST (glyph);
8459 font->driver->draw (s, i, i + 1, x + xoff, y + yoff, false);
8460 if (s->face->overstrike)
8461 font->driver->draw (s, i, i + 1, x + xoff + 1, y + yoff,
8462 false);
8463 x += wadjust;
8464 j = i + 1;
8465 width = 0;
8466 }
8467 }
8468 if (j < i)
8469 {
8470 font->driver->draw (s, j, i, x, y, false);
8471 if (s->face->overstrike)
8472 font->driver->draw (s, j, i, x + 1, y, false);
8473 }
8474 }
8475 #ifdef USE_CAIRO
8476 if (EQ (font->driver->type, Qx))
8477 x_end_cr_xlib_drawable (s->f, s->gc);
8478 }
8479 else
8480 {
8481
8482
8483 if (s->cmp_from == 0)
8484 x_draw_rectangle (s->f, s->gc, x, s->y,
8485 s->width - 1, s->height - 1);
8486 }
8487 #endif
8488 }
8489
8490
8491
8492
8493 static void
8494 x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
8495 {
8496 struct glyph *glyph = s->first_glyph;
8497 unsigned char2b[8];
8498 int x, i, j;
8499
8500
8501
8502 if (s->face && s->face->box != FACE_NO_BOX
8503 && s->first_glyph->left_box_line_p)
8504 x = s->x + max (s->face->box_vertical_line_width, 0);
8505 else
8506 x = s->x;
8507
8508 s->char2b = char2b;
8509
8510 for (i = 0; i < s->nchars; i++, glyph++)
8511 {
8512 #ifdef GCC_LINT
8513 enum { PACIFY_GCC_BUG_81401 = 1 };
8514 #else
8515 enum { PACIFY_GCC_BUG_81401 = 0 };
8516 #endif
8517 char buf[7 + PACIFY_GCC_BUG_81401];
8518 char *str = NULL;
8519 int len = glyph->u.glyphless.len;
8520
8521 if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM)
8522 {
8523 if (len > 0
8524 && CHAR_TABLE_P (Vglyphless_char_display)
8525 && (CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display))
8526 >= 1))
8527 {
8528 Lisp_Object acronym
8529 = (! glyph->u.glyphless.for_no_font
8530 ? CHAR_TABLE_REF (Vglyphless_char_display,
8531 glyph->u.glyphless.ch)
8532 : XCHAR_TABLE (Vglyphless_char_display)->extras[0]);
8533 if (CONSP (acronym))
8534 acronym = XCAR (acronym);
8535 if (STRINGP (acronym))
8536 str = SSDATA (acronym);
8537 }
8538 }
8539 else if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE)
8540 {
8541 unsigned int ch = glyph->u.glyphless.ch;
8542 eassume (ch <= MAX_CHAR);
8543 sprintf (buf, "%0*X", ch < 0x10000 ? 4 : 6, ch);
8544 str = buf;
8545 }
8546
8547 if (str)
8548 {
8549 int upper_len = (len + 1) / 2;
8550
8551
8552 for (j = 0; j < len; j++)
8553 char2b[j] = s->font->driver->encode_char (s->font, str[j]) & 0xFFFF;
8554 s->font->driver->draw (s, 0, upper_len,
8555 x + glyph->slice.glyphless.upper_xoff,
8556 s->ybase + glyph->slice.glyphless.upper_yoff,
8557 false);
8558 s->font->driver->draw (s, upper_len, len,
8559 x + glyph->slice.glyphless.lower_xoff,
8560 s->ybase + glyph->slice.glyphless.lower_yoff,
8561 false);
8562 }
8563 if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE)
8564 x_draw_rectangle (s->f, s->gc,
8565 x, s->ybase - glyph->ascent,
8566 glyph->pixel_width - 1,
8567 glyph->ascent + glyph->descent - 1);
8568 x += glyph->pixel_width;
8569 }
8570
8571
8572
8573 s->char2b = NULL;
8574 }
8575
8576 #ifdef USE_X_TOOLKIT
8577
8578 #ifdef USE_LUCID
8579
8580
8581
8582
8583 static struct frame *
8584 x_frame_of_widget (Widget widget)
8585 {
8586 struct x_display_info *dpyinfo;
8587 Lisp_Object tail, frame;
8588 struct frame *f;
8589
8590 dpyinfo = x_display_info_for_display (XtDisplay (widget));
8591
8592
8593
8594
8595
8596 while (!XtIsTopLevelShell (widget))
8597 widget = XtParent (widget);
8598
8599
8600
8601 FOR_EACH_FRAME (tail, frame)
8602 {
8603 f = XFRAME (frame);
8604 if (FRAME_X_P (f)
8605 && FRAME_DISPLAY_INFO (f) == dpyinfo
8606 && f->output_data.x->widget == widget)
8607 return f;
8608 }
8609 emacs_abort ();
8610 }
8611
8612
8613
8614
8615
8616
8617
8618
8619 bool
8620 x_alloc_lighter_color_for_widget (Widget widget, Display *display, Colormap cmap,
8621 unsigned long *pixel, double factor, int delta)
8622 {
8623 struct frame *f = x_frame_of_widget (widget);
8624 return x_alloc_lighter_color (f, display, cmap, pixel, factor, delta);
8625 }
8626
8627 #endif
8628
8629
8630
8631
8632
8633 static XtConvertArgRec cvt_string_to_pixel_args[] =
8634 {
8635 {XtWidgetBaseOffset, (XtPointer) offsetof (WidgetRec, core.screen),
8636 sizeof (Screen *)},
8637 {XtWidgetBaseOffset, (XtPointer) offsetof (WidgetRec, core.colormap),
8638 sizeof (Colormap)}
8639 };
8640
8641
8642
8643
8644
8645 static Pixel cvt_string_to_pixel_value;
8646
8647
8648
8649
8650
8651
8652
8653
8654
8655
8656
8657
8658
8659
8660
8661
8662
8663
8664
8665 static Boolean
8666 cvt_string_to_pixel (Display *dpy, XrmValue *args, Cardinal *nargs,
8667 XrmValue *from, XrmValue *to,
8668 XtPointer *closure_ret)
8669 {
8670 Screen *screen;
8671 Colormap cmap;
8672 Pixel pixel;
8673 String color_name;
8674 XColor color;
8675
8676 if (*nargs != 2)
8677 {
8678 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
8679 "wrongParameters", "cvt_string_to_pixel",
8680 "XtToolkitError",
8681 "Screen and colormap args required", NULL, NULL);
8682 return False;
8683 }
8684
8685 screen = *(Screen **) args[0].addr;
8686 cmap = *(Colormap *) args[1].addr;
8687 color_name = (String) from->addr;
8688
8689 if (strcmp (color_name, XtDefaultBackground) == 0)
8690 {
8691 *closure_ret = (XtPointer) False;
8692 pixel = WhitePixelOfScreen (screen);
8693 }
8694 else if (strcmp (color_name, XtDefaultForeground) == 0)
8695 {
8696 *closure_ret = (XtPointer) False;
8697 pixel = BlackPixelOfScreen (screen);
8698 }
8699 else if (XParseColor (dpy, cmap, color_name, &color)
8700 && x_alloc_nearest_color_1 (dpy, cmap, &color))
8701 {
8702 pixel = color.pixel;
8703 *closure_ret = (XtPointer) True;
8704 }
8705 else
8706 {
8707 String params[1];
8708 Cardinal nparams = 1;
8709
8710 params[0] = color_name;
8711 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
8712 "badValue", "cvt_string_to_pixel",
8713 "XtToolkitError", "Invalid color '%s'",
8714 params, &nparams);
8715 return False;
8716 }
8717
8718 if (to->addr != NULL)
8719 {
8720 if (to->size < sizeof (Pixel))
8721 {
8722 to->size = sizeof (Pixel);
8723 return False;
8724 }
8725
8726 *(Pixel *) to->addr = pixel;
8727 }
8728 else
8729 {
8730 cvt_string_to_pixel_value = pixel;
8731 to->addr = (XtPointer) &cvt_string_to_pixel_value;
8732 }
8733
8734 to->size = sizeof (Pixel);
8735 return True;
8736 }
8737
8738
8739
8740
8741
8742
8743
8744
8745
8746
8747
8748
8749
8750
8751 static void
8752 cvt_pixel_dtor (XtAppContext app, XrmValuePtr to, XtPointer closure, XrmValuePtr args,
8753 Cardinal *nargs)
8754 {
8755 if (*nargs != 2)
8756 {
8757 XtAppWarningMsg (app, "wrongParameters", "cvt_pixel_dtor",
8758 "XtToolkitError",
8759 "Screen and colormap arguments required",
8760 NULL, NULL);
8761 }
8762 else if (closure != NULL)
8763 {
8764
8765 Screen *screen = *(Screen **) args[0].addr;
8766 Colormap cmap = *(Colormap *) args[1].addr;
8767 x_free_dpy_colors (DisplayOfScreen (screen), screen, cmap,
8768 (Pixel *) to->addr, 1);
8769 }
8770 }
8771
8772
8773 #endif
8774
8775
8776
8777
8778
8779
8780
8781 static const XColor *
8782 x_color_cells (Display *dpy, int *ncells)
8783 {
8784 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
8785 eassume (dpyinfo);
8786
8787 if (dpyinfo->color_cells == NULL)
8788 {
8789 int ncolor_cells = dpyinfo->visual_info.colormap_size;
8790 int i;
8791
8792 dpyinfo->color_cells = xnmalloc (ncolor_cells,
8793 sizeof *dpyinfo->color_cells);
8794 dpyinfo->ncolor_cells = ncolor_cells;
8795
8796 for (i = 0; i < ncolor_cells; ++i)
8797 dpyinfo->color_cells[i].pixel = i;
8798
8799 XQueryColors (dpy, dpyinfo->cmap,
8800 dpyinfo->color_cells, ncolor_cells);
8801 }
8802
8803 *ncells = dpyinfo->ncolor_cells;
8804 return dpyinfo->color_cells;
8805 }
8806
8807
8808
8809
8810
8811 void
8812 x_query_colors (struct frame *f, XColor *colors, int ncolors)
8813 {
8814 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
8815 int i;
8816
8817 if (dpyinfo->red_bits > 0)
8818 {
8819
8820
8821 unsigned int rmult, gmult, bmult;
8822 unsigned int rmask, gmask, bmask;
8823
8824 rmask = (1 << dpyinfo->red_bits) - 1;
8825 gmask = (1 << dpyinfo->green_bits) - 1;
8826 bmask = (1 << dpyinfo->blue_bits) - 1;
8827
8828
8829
8830
8831
8832
8833
8834
8835
8836
8837
8838
8839
8840 rmult = 0xffffffff / rmask;
8841 gmult = 0xffffffff / gmask;
8842 bmult = 0xffffffff / bmask;
8843
8844 for (i = 0; i < ncolors; ++i)
8845 {
8846 unsigned int r, g, b;
8847 unsigned long pixel = colors[i].pixel;
8848
8849 r = (pixel >> dpyinfo->red_offset) & rmask;
8850 g = (pixel >> dpyinfo->green_offset) & gmask;
8851 b = (pixel >> dpyinfo->blue_offset) & bmask;
8852
8853 colors[i].red = (r * rmult) >> 16;
8854 colors[i].green = (g * gmult) >> 16;
8855 colors[i].blue = (b * bmult) >> 16;
8856 }
8857 return;
8858 }
8859
8860 if (dpyinfo->color_cells)
8861 {
8862 int i;
8863 for (i = 0; i < ncolors; ++i)
8864 {
8865 unsigned long pixel = colors[i].pixel;
8866 eassert (pixel < dpyinfo->ncolor_cells);
8867 eassert (dpyinfo->color_cells[pixel].pixel == pixel);
8868 colors[i] = dpyinfo->color_cells[pixel];
8869 }
8870 return;
8871 }
8872
8873 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
8874 }
8875
8876
8877
8878 static void
8879 x_query_frame_background_color (struct frame *f, XColor *bgcolor)
8880 {
8881 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
8882 #ifndef USE_CAIRO
8883 XColor bg;
8884 #endif
8885
8886 if (FRAME_DISPLAY_INFO (f)->alpha_bits)
8887 {
8888 #ifdef USE_CAIRO
8889 background = (background & ~FRAME_DISPLAY_INFO (f)->alpha_mask);
8890 background |= (((unsigned long) (f->alpha_background * 0xffff)
8891 >> (16 - FRAME_DISPLAY_INFO (f)->alpha_bits))
8892 << FRAME_DISPLAY_INFO (f)->alpha_offset);
8893 #else
8894 if (FRAME_DISPLAY_INFO (f)->alpha_bits
8895 && f->alpha_background < 1.0)
8896 {
8897 bg.pixel = background;
8898 x_query_colors (f, &bg, 1);
8899 bg.red *= f->alpha_background;
8900 bg.green *= f->alpha_background;
8901 bg.blue *= f->alpha_background;
8902
8903 background = x_make_truecolor_pixel (FRAME_DISPLAY_INFO (f),
8904 bg.red, bg.green, bg.blue);
8905 background &= ~FRAME_DISPLAY_INFO (f)->alpha_mask;
8906 background |= (((unsigned long) (f->alpha_background * 0xffff)
8907 >> (16 - FRAME_DISPLAY_INFO (f)->alpha_bits))
8908 << FRAME_DISPLAY_INFO (f)->alpha_offset);
8909 }
8910 #endif
8911 }
8912
8913 bgcolor->pixel = background;
8914
8915 x_query_colors (f, bgcolor, 1);
8916 }
8917
8918 static unsigned int
8919 x_hash_string_ignore_case (const char *string)
8920 {
8921 unsigned int i;
8922
8923 i = 3323198485ul;
8924 for (; *string; ++string)
8925 {
8926 i ^= c_tolower (*string);
8927 i *= 0x5bd1e995;
8928 i ^= i >> 15;
8929 }
8930 return i;
8931 }
8932
8933
8934
8935
8936
8937
8938
8939 Status
8940 x_parse_color (struct frame *f, const char *color_name,
8941 XColor *color)
8942 {
8943 unsigned short r, g, b;
8944 Display *dpy;
8945 Colormap cmap;
8946 struct x_display_info *dpyinfo;
8947 struct color_name_cache_entry *cache_entry, *last;
8948 struct color_name_cache_entry *next, *color_entry;
8949 unsigned int hash, idx;
8950 int rc, i;
8951
8952
8953
8954
8955
8956
8957 if (parse_color_spec (color_name, &r, &g, &b))
8958 {
8959 color->red = r;
8960 color->green = g;
8961 color->blue = b;
8962
8963 return 1;
8964 }
8965
8966
8967 if (!strlen (color_name))
8968 return 0;
8969
8970 cmap = FRAME_X_COLORMAP (f);
8971 dpy = FRAME_X_DISPLAY (f);
8972 dpyinfo = FRAME_DISPLAY_INFO (f);
8973
8974 hash = x_hash_string_ignore_case (color_name);
8975 idx = hash % dpyinfo->color_names_size;
8976
8977 last = NULL;
8978
8979 for (cache_entry = dpyinfo->color_names[idx];
8980 cache_entry; cache_entry = cache_entry->next)
8981 {
8982 if (!xstrcasecmp (cache_entry->name, color_name))
8983 {
8984
8985
8986
8987 if (last)
8988 {
8989 last->next = cache_entry->next;
8990 cache_entry->next = dpyinfo->color_names[idx];
8991
8992 dpyinfo->color_names[idx] = cache_entry;
8993 }
8994
8995 if (cache_entry->valid)
8996 *color = cache_entry->rgb;
8997
8998 return cache_entry->valid;
8999 }
9000
9001 last = cache_entry;
9002 }
9003
9004 block_input ();
9005 rc = XParseColor (dpy, cmap, color_name, color);
9006 unblock_input ();
9007
9008 cache_entry = xzalloc (sizeof *cache_entry);
9009 dpyinfo->color_names_length[idx] += 1;
9010
9011 if (rc)
9012 cache_entry->rgb = *color;
9013
9014 cache_entry->valid = rc;
9015 cache_entry->name = xstrdup (color_name);
9016 cache_entry->next = dpyinfo->color_names[idx];
9017
9018 dpyinfo->color_names[idx] = cache_entry;
9019
9020
9021 if (dpyinfo->color_names_length[idx] > (x_color_cache_bucket_size > 0
9022 ? x_color_cache_bucket_size : 128))
9023 {
9024 i = 0;
9025
9026 for (last = dpyinfo->color_names[idx]; last; last = last->next)
9027 {
9028 if (++i == (x_color_cache_bucket_size > 0
9029 ? x_color_cache_bucket_size : 128))
9030 {
9031 next = last->next;
9032 last->next = NULL;
9033
9034 for (color_entry = next; color_entry; color_entry = last)
9035 {
9036 last = color_entry->next;
9037
9038 xfree (color_entry->name);
9039 xfree (color_entry);
9040
9041 dpyinfo->color_names_length[idx] -= 1;
9042 }
9043
9044 return rc;
9045 }
9046 }
9047 }
9048
9049 return rc;
9050 }
9051
9052
9053
9054
9055
9056
9057
9058 static bool
9059 x_alloc_nearest_color_1 (Display *dpy, Colormap cmap, XColor *color)
9060 {
9061 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
9062 bool rc;
9063
9064 eassume (dpyinfo);
9065 rc = XAllocColor (dpy, cmap, color) != 0;
9066
9067 if (dpyinfo->visual_info.class == DirectColor)
9068 return rc;
9069
9070 if (rc == 0)
9071 {
9072
9073
9074
9075
9076
9077 const XColor *cells;
9078 int no_cells;
9079 int nearest;
9080 long nearest_delta, trial_delta;
9081 int x;
9082 Status status;
9083 bool retry = false;
9084 int ncolor_cells, i;
9085 bool temp_allocated;
9086 XColor temp;
9087
9088 start:
9089 cells = x_color_cells (dpy, &no_cells);
9090 temp_allocated = false;
9091
9092 nearest = 0;
9093
9094 nearest_delta = ((((color->red >> 8) - (cells[0].red >> 8))
9095 * ((color->red >> 8) - (cells[0].red >> 8)))
9096 + (((color->green >> 8) - (cells[0].green >> 8))
9097 * ((color->green >> 8) - (cells[0].green >> 8)))
9098 + (((color->blue >> 8) - (cells[0].blue >> 8))
9099 * ((color->blue >> 8) - (cells[0].blue >> 8))));
9100 for (x = 1; x < no_cells; x++)
9101 {
9102 trial_delta = ((((color->red >> 8) - (cells[x].red >> 8))
9103 * ((color->red >> 8) - (cells[x].red >> 8)))
9104 + (((color->green >> 8) - (cells[x].green >> 8))
9105 * ((color->green >> 8) - (cells[x].green >> 8)))
9106 + (((color->blue >> 8) - (cells[x].blue >> 8))
9107 * ((color->blue >> 8) - (cells[x].blue >> 8))));
9108 if (trial_delta < nearest_delta)
9109 {
9110
9111 if (temp_allocated)
9112 {
9113 XFreeColors (dpy, cmap, &temp.pixel, 1, 0);
9114 temp_allocated = false;
9115 }
9116
9117 temp.red = cells[x].red;
9118 temp.green = cells[x].green;
9119 temp.blue = cells[x].blue;
9120 status = XAllocColor (dpy, cmap, &temp);
9121
9122 if (status)
9123 {
9124 temp_allocated = true;
9125 nearest = x;
9126 nearest_delta = trial_delta;
9127 }
9128 }
9129 }
9130 color->red = cells[nearest].red;
9131 color->green = cells[nearest].green;
9132 color->blue = cells[nearest].blue;
9133
9134 if (!temp_allocated)
9135 status = XAllocColor (dpy, cmap, color);
9136 else
9137 {
9138 *color = temp;
9139 status = 1;
9140 }
9141
9142 if (status == 0 && !retry)
9143 {
9144
9145
9146
9147
9148 retry = true;
9149 xfree (dpyinfo->color_cells);
9150
9151 ncolor_cells = dpyinfo->visual_info.colormap_size;
9152
9153 dpyinfo->color_cells = xnmalloc (ncolor_cells,
9154 sizeof *dpyinfo->color_cells);
9155 dpyinfo->ncolor_cells = ncolor_cells;
9156
9157 for (i = 0; i < ncolor_cells; ++i)
9158 dpyinfo->color_cells[i].pixel = i;
9159
9160 XQueryColors (dpy, dpyinfo->cmap,
9161 dpyinfo->color_cells, ncolor_cells);
9162
9163 goto start;
9164 }
9165
9166 rc = status != 0;
9167 }
9168 else
9169 {
9170
9171
9172
9173 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
9174 eassume (dpyinfo);
9175
9176 if (dpyinfo->color_cells)
9177 {
9178 XColor *cached_color = &dpyinfo->color_cells[color->pixel];
9179 if (cached_color->red != color->red
9180 || cached_color->blue != color->blue
9181 || cached_color->green != color->green)
9182 {
9183 xfree (dpyinfo->color_cells);
9184 dpyinfo->color_cells = NULL;
9185 dpyinfo->ncolor_cells = 0;
9186 }
9187 }
9188 }
9189
9190 #ifdef DEBUG_X_COLORS
9191 if (rc)
9192 register_color (color->pixel);
9193 #endif
9194
9195 return rc;
9196 }
9197
9198
9199
9200
9201
9202
9203
9204 bool
9205 x_alloc_nearest_color (struct frame *f, Colormap cmap, XColor *color)
9206 {
9207 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
9208
9209 gamma_correct (f, color);
9210
9211 if (dpyinfo->red_bits > 0)
9212 {
9213 color->pixel = x_make_truecolor_pixel (dpyinfo,
9214 color->red,
9215 color->green,
9216 color->blue);
9217 return true;
9218 }
9219
9220 return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f), cmap, color);
9221 }
9222
9223
9224
9225
9226
9227
9228 unsigned long
9229 x_copy_color (struct frame *f, unsigned long pixel)
9230 {
9231 XColor color;
9232
9233
9234
9235
9236
9237 if (!x_mutable_colormap (FRAME_X_VISUAL_INFO (f)))
9238 return pixel;
9239
9240 color.pixel = pixel;
9241 block_input ();
9242
9243 x_query_colors (f, &color, 1);
9244 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
9245 unblock_input ();
9246 #ifdef DEBUG_X_COLORS
9247 register_color (pixel);
9248 #endif
9249 return color.pixel;
9250 }
9251
9252
9253
9254
9255
9256
9257
9258
9259
9260
9261
9262
9263
9264 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
9265
9266
9267
9268
9269
9270
9271
9272
9273
9274 static bool
9275 x_alloc_lighter_color (struct frame *f, Display *display, Colormap cmap,
9276 unsigned long *pixel, double factor, int delta)
9277 {
9278 XColor color, new;
9279 long bright;
9280 bool success_p;
9281
9282
9283 color.pixel = *pixel;
9284 x_query_colors (f, &color, 1);
9285
9286
9287 eassert (factor >= 0);
9288 new.red = min (0xffff, factor * color.red);
9289 new.green = min (0xffff, factor * color.green);
9290 new.blue = min (0xffff, factor * color.blue);
9291
9292
9293 bright = (2 * color.red + 3 * color.green + color.blue) / 6;
9294
9295
9296
9297 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
9298
9299
9300 {
9301
9302 double dimness = 1 - (double) bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
9303
9304 int min_delta = delta * dimness * factor / 2;
9305
9306 if (factor < 1)
9307 {
9308 new.red = max (0, new.red - min_delta);
9309 new.green = max (0, new.green - min_delta);
9310 new.blue = max (0, new.blue - min_delta);
9311 }
9312 else
9313 {
9314 new.red = min (0xffff, min_delta + new.red);
9315 new.green = min (0xffff, min_delta + new.green);
9316 new.blue = min (0xffff, min_delta + new.blue);
9317 }
9318 }
9319
9320
9321 success_p = x_alloc_nearest_color (f, cmap, &new);
9322 if (success_p)
9323 {
9324 if (new.pixel == *pixel)
9325 {
9326
9327
9328 x_free_colors (f, &new.pixel, 1);
9329
9330 new.red = min (0xffff, delta + color.red);
9331 new.green = min (0xffff, delta + color.green);
9332 new.blue = min (0xffff, delta + color.blue);
9333 success_p = x_alloc_nearest_color (f, cmap, &new);
9334 }
9335 else
9336 success_p = true;
9337 *pixel = new.pixel;
9338 }
9339
9340 return success_p;
9341 }
9342
9343
9344
9345
9346
9347
9348
9349
9350
9351 static void
9352 x_setup_relief_color (struct frame *f, struct relief *relief, double factor,
9353 int delta, unsigned long default_pixel)
9354 {
9355 XGCValues xgcv;
9356 struct x_output *di = f->output_data.x;
9357 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
9358 unsigned long pixel;
9359 unsigned long background = di->relief_background;
9360 Colormap cmap = FRAME_X_COLORMAP (f);
9361 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
9362 Display *dpy = FRAME_X_DISPLAY (f);
9363
9364 xgcv.graphics_exposures = False;
9365 xgcv.line_width = 1;
9366
9367
9368
9369
9370 if (relief->gc && relief->pixel != -1)
9371 {
9372 x_free_colors (f, &relief->pixel, 1);
9373 relief->pixel = -1;
9374 }
9375
9376
9377 xgcv.foreground = default_pixel;
9378 pixel = background;
9379 if (dpyinfo->n_planes != 1
9380 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
9381 xgcv.foreground = relief->pixel = pixel;
9382
9383 if (relief->gc == 0)
9384 {
9385 xgcv.stipple = dpyinfo->gray;
9386 mask |= GCStipple;
9387 relief->gc = XCreateGC (dpy, FRAME_X_DRAWABLE (f), mask, &xgcv);
9388 }
9389 else
9390 XChangeGC (dpy, relief->gc, mask, &xgcv);
9391 }
9392
9393
9394
9395
9396 static void
9397 x_setup_relief_colors (struct glyph_string *s)
9398 {
9399 struct x_output *di = s->f->output_data.x;
9400 unsigned long color;
9401
9402 if (s->face->use_box_color_for_shadows_p)
9403 color = s->face->box_color;
9404 else if (s->first_glyph->type == IMAGE_GLYPH
9405 && s->img->pixmap
9406 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
9407 color = IMAGE_BACKGROUND (s->img, s->f, 0);
9408 else
9409 {
9410 XGCValues xgcv;
9411
9412
9413 XGetGCValues (FRAME_X_DISPLAY (s->f), s->gc, GCBackground, &xgcv);
9414 color = xgcv.background;
9415 }
9416
9417 if (di->white_relief.gc == 0
9418 || color != di->relief_background)
9419 {
9420 di->relief_background = color;
9421 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
9422 WHITE_PIX_DEFAULT (s->f));
9423 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
9424 BLACK_PIX_DEFAULT (s->f));
9425 }
9426 }
9427
9428 #ifndef USE_CAIRO
9429 static void
9430 x_fill_triangle (struct frame *f, GC gc, XPoint point1,
9431 XPoint point2, XPoint point3)
9432 {
9433 XPoint abc[3];
9434
9435 abc[0] = point1;
9436 abc[1] = point2;
9437 abc[2] = point3;
9438
9439 XFillPolygon (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
9440 gc, abc, 3, Convex, CoordModeOrigin);
9441 }
9442
9443 static XPoint
9444 x_make_point (int x, int y)
9445 {
9446 XPoint pt;
9447
9448 pt.x = x;
9449 pt.y = y;
9450
9451 return pt;
9452 }
9453
9454 static bool
9455 x_inside_rect_p (XRectangle *rects, int nrects, int x, int y)
9456 {
9457 int i;
9458
9459 for (i = 0; i < nrects; ++i)
9460 {
9461 if (x >= rects[i].x && y >= rects[i].y
9462 && x < rects[i].x + rects[i].width
9463 && y < rects[i].y + rects[i].height)
9464 return true;
9465 }
9466
9467 return false;
9468 }
9469 #endif
9470
9471
9472
9473
9474
9475
9476
9477
9478
9479
9480 static void
9481 x_draw_relief_rect (struct frame *f, int left_x, int top_y, int right_x,
9482 int bottom_y, int hwidth, int vwidth, bool raised_p,
9483 bool top_p, bool bot_p, bool left_p, bool right_p,
9484 XRectangle *clip_rect)
9485 {
9486 #ifdef USE_CAIRO
9487 GC top_left_gc, bottom_right_gc;
9488 int corners = 0;
9489
9490 if (raised_p)
9491 {
9492 top_left_gc = f->output_data.x->white_relief.gc;
9493 bottom_right_gc = f->output_data.x->black_relief.gc;
9494 }
9495 else
9496 {
9497 top_left_gc = f->output_data.x->black_relief.gc;
9498 bottom_right_gc = f->output_data.x->white_relief.gc;
9499 }
9500
9501 x_set_clip_rectangles (f, top_left_gc, clip_rect, 1);
9502 x_set_clip_rectangles (f, bottom_right_gc, clip_rect, 1);
9503
9504 if (left_p)
9505 {
9506 x_fill_rectangle (f, top_left_gc, left_x, top_y,
9507 vwidth, bottom_y + 1 - top_y, false);
9508 if (top_p)
9509 corners |= 1 << CORNER_TOP_LEFT;
9510 if (bot_p)
9511 corners |= 1 << CORNER_BOTTOM_LEFT;
9512 }
9513 if (right_p)
9514 {
9515 x_fill_rectangle (f, bottom_right_gc, right_x + 1 - vwidth, top_y,
9516 vwidth, bottom_y + 1 - top_y, false);
9517 if (top_p)
9518 corners |= 1 << CORNER_TOP_RIGHT;
9519 if (bot_p)
9520 corners |= 1 << CORNER_BOTTOM_RIGHT;
9521 }
9522 if (top_p)
9523 {
9524 if (!right_p)
9525 x_fill_rectangle (f, top_left_gc, left_x, top_y,
9526 right_x + 1 - left_x, hwidth, false);
9527 else
9528 x_fill_trapezoid_for_relief (f, top_left_gc, left_x, top_y,
9529 right_x + 1 - left_x, hwidth, 1);
9530 }
9531 if (bot_p)
9532 {
9533 if (!left_p)
9534 x_fill_rectangle (f, bottom_right_gc, left_x, bottom_y + 1 - hwidth,
9535 right_x + 1 - left_x, hwidth, false);
9536 else
9537 x_fill_trapezoid_for_relief (f, bottom_right_gc,
9538 left_x, bottom_y + 1 - hwidth,
9539 right_x + 1 - left_x, hwidth, 0);
9540 }
9541 if (left_p && vwidth > 1)
9542 x_fill_rectangle (f, bottom_right_gc, left_x, top_y,
9543 1, bottom_y + 1 - top_y, false);
9544 if (top_p && hwidth > 1)
9545 x_fill_rectangle (f, bottom_right_gc, left_x, top_y,
9546 right_x + 1 - left_x, 1, false);
9547 if (corners)
9548 {
9549 XSetBackground (FRAME_X_DISPLAY (f), top_left_gc,
9550 FRAME_BACKGROUND_PIXEL (f));
9551 x_erase_corners_for_relief (f, top_left_gc, left_x, top_y,
9552 right_x - left_x + 1, bottom_y - top_y + 1,
9553 6, 1, corners);
9554 }
9555
9556 x_reset_clip_rectangles (f, top_left_gc);
9557 x_reset_clip_rectangles (f, bottom_right_gc);
9558 #else
9559 GC gc, white_gc, black_gc, normal_gc;
9560 Drawable drawable;
9561 Display *dpy;
9562
9563
9564
9565
9566
9567
9568 white_gc = f->output_data.x->white_relief.gc;
9569 black_gc = f->output_data.x->black_relief.gc;
9570 normal_gc = f->output_data.x->normal_gc;
9571
9572 drawable = FRAME_X_DRAWABLE (f);
9573 dpy = FRAME_X_DISPLAY (f);
9574
9575 x_set_clip_rectangles (f, white_gc, clip_rect, 1);
9576 x_set_clip_rectangles (f, black_gc, clip_rect, 1);
9577
9578 if (raised_p)
9579 gc = white_gc;
9580 else
9581 gc = black_gc;
9582
9583
9584
9585 if (top_p)
9586 x_fill_rectangle (f, gc, left_x, top_y,
9587 right_x - left_x + 1, hwidth,
9588 false);
9589
9590 if (left_p)
9591 x_fill_rectangle (f, gc, left_x, top_y, vwidth,
9592 bottom_y - top_y + 1, false);
9593
9594 if (raised_p)
9595 gc = black_gc;
9596 else
9597 gc = white_gc;
9598
9599 if (bot_p)
9600 x_fill_rectangle (f, gc, left_x, bottom_y - hwidth + 1,
9601 right_x - left_x + 1, hwidth, false);
9602
9603 if (right_p)
9604 x_fill_rectangle (f, gc, right_x - vwidth + 1, top_y,
9605 vwidth, bottom_y - top_y + 1, false);
9606
9607
9608
9609 if (bot_p && left_p)
9610 x_fill_triangle (f, raised_p ? white_gc : black_gc,
9611 x_make_point (left_x, bottom_y - hwidth),
9612 x_make_point (left_x + vwidth, bottom_y - hwidth),
9613 x_make_point (left_x, bottom_y));
9614
9615 if (top_p && right_p)
9616 x_fill_triangle (f, raised_p ? white_gc : black_gc,
9617 x_make_point (right_x - vwidth, top_y),
9618 x_make_point (right_x, top_y),
9619 x_make_point (right_x - vwidth, top_y + hwidth));
9620
9621
9622
9623 if (top_p && left_p && bot_p && right_p
9624 && hwidth > 1 && vwidth > 1)
9625 x_draw_rectangle (f, black_gc, left_x, top_y,
9626 right_x - left_x, bottom_y - top_y);
9627 else
9628 {
9629 if (top_p && hwidth > 1)
9630 XDrawLine (dpy, drawable, black_gc, left_x, top_y,
9631 right_x + 1, top_y);
9632
9633 if (bot_p && hwidth > 1)
9634 XDrawLine (dpy, drawable, black_gc, left_x, bottom_y,
9635 right_x + 1, bottom_y);
9636
9637 if (left_p && vwidth > 1)
9638 XDrawLine (dpy, drawable, black_gc, left_x, top_y,
9639 left_x, bottom_y + 1);
9640
9641 if (right_p && vwidth > 1)
9642 XDrawLine (dpy, drawable, black_gc, right_x, top_y,
9643 right_x, bottom_y + 1);
9644 }
9645
9646
9647
9648 if (hwidth > 1 && vwidth > 1)
9649 {
9650 if (left_p && top_p && x_inside_rect_p (clip_rect, 1,
9651 left_x, top_y))
9652
9653
9654 x_clear_point (f, normal_gc, left_x, top_y, true);
9655
9656 if (left_p && bot_p && x_inside_rect_p (clip_rect, 1,
9657 left_x, bottom_y))
9658 x_clear_point (f, normal_gc, left_x, bottom_y, true);
9659
9660 if (right_p && top_p && x_inside_rect_p (clip_rect, 1,
9661 right_x, top_y))
9662 x_clear_point (f, normal_gc, right_x, top_y, true);
9663
9664 if (right_p && bot_p && x_inside_rect_p (clip_rect, 1,
9665 right_x, bottom_y))
9666 x_clear_point (f, normal_gc, right_x, bottom_y, true);
9667 }
9668
9669 x_reset_clip_rectangles (f, white_gc);
9670 x_reset_clip_rectangles (f, black_gc);
9671 #endif
9672 }
9673
9674
9675
9676
9677
9678
9679
9680
9681
9682 static void
9683 x_draw_box_rect (struct glyph_string *s,
9684 int left_x, int top_y, int right_x, int bottom_y, int hwidth,
9685 int vwidth, bool left_p, bool right_p, XRectangle *clip_rect)
9686 {
9687 Display *display = FRAME_X_DISPLAY (s->f);
9688 XGCValues xgcv;
9689
9690 XGetGCValues (display, s->gc, GCForeground, &xgcv);
9691 XSetForeground (display, s->gc, s->face->box_color);
9692 x_set_clip_rectangles (s->f, s->gc, clip_rect, 1);
9693
9694
9695 x_fill_rectangle (s->f, s->gc,
9696 left_x, top_y, right_x - left_x + 1, hwidth,
9697 false);
9698
9699
9700 if (left_p)
9701 x_fill_rectangle (s->f, s->gc,
9702 left_x, top_y, vwidth, bottom_y - top_y + 1,
9703 false);
9704
9705
9706 x_fill_rectangle (s->f, s->gc,
9707 left_x, bottom_y - hwidth + 1, right_x - left_x + 1, hwidth,
9708 false);
9709
9710
9711 if (right_p)
9712 x_fill_rectangle (s->f, s->gc,
9713 right_x - vwidth + 1, top_y, vwidth, bottom_y - top_y + 1,
9714 false);
9715
9716 XSetForeground (display, s->gc, xgcv.foreground);
9717 x_reset_clip_rectangles (s->f, s->gc);
9718 }
9719
9720
9721
9722
9723 static void
9724 x_draw_glyph_string_box (struct glyph_string *s)
9725 {
9726 int hwidth, vwidth, left_x, right_x, top_y, bottom_y, last_x;
9727 bool raised_p, left_p, right_p;
9728 struct glyph *last_glyph;
9729 XRectangle clip_rect;
9730
9731 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
9732 ? WINDOW_RIGHT_EDGE_X (s->w)
9733 : window_box_right (s->w, s->area));
9734
9735
9736
9737
9738 if (s->cmp || s->img)
9739 last_glyph = s->first_glyph;
9740 else if (s->first_glyph->type == COMPOSITE_GLYPH
9741 && s->first_glyph->u.cmp.automatic)
9742 {
9743
9744
9745 struct glyph *end = s->row->glyphs[s->area] + s->row->used[s->area];
9746 struct glyph *g = s->first_glyph;
9747 for (last_glyph = g++;
9748 g < end && g->u.cmp.automatic && g->u.cmp.id == s->cmp_id
9749 && g->slice.cmp.to < s->cmp_to;
9750 last_glyph = g++)
9751 ;
9752 }
9753 else
9754 last_glyph = s->first_glyph + s->nchars - 1;
9755
9756 vwidth = eabs (s->face->box_vertical_line_width);
9757 hwidth = eabs (s->face->box_horizontal_line_width);
9758 raised_p = s->face->box == FACE_RAISED_BOX;
9759 left_x = s->x;
9760 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
9761 ? last_x - 1
9762 : min (last_x, s->x + s->background_width) - 1);
9763 top_y = s->y;
9764 bottom_y = top_y + s->height - 1;
9765
9766 left_p = (s->first_glyph->left_box_line_p
9767 || (s->hl == DRAW_MOUSE_FACE
9768 && (s->prev == NULL
9769 || s->prev->hl != s->hl)));
9770 right_p = (last_glyph->right_box_line_p
9771 || (s->hl == DRAW_MOUSE_FACE
9772 && (s->next == NULL
9773 || s->next->hl != s->hl)));
9774
9775 get_glyph_string_clip_rect (s, &clip_rect);
9776
9777 if (s->face->box == FACE_SIMPLE_BOX)
9778 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, hwidth,
9779 vwidth, left_p, right_p, &clip_rect);
9780 else
9781 {
9782 x_setup_relief_colors (s);
9783 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y, hwidth,
9784 vwidth, raised_p, true, true, left_p, right_p,
9785 &clip_rect);
9786 }
9787 }
9788
9789
9790 #ifndef USE_CAIRO
9791
9792 static void
9793 x_composite_image (struct glyph_string *s, Pixmap dest,
9794 #ifdef HAVE_XRENDER
9795 Picture destination,
9796 #endif
9797 int srcX, int srcY, int dstX, int dstY,
9798 int width, int height)
9799 {
9800 Display *display;
9801 #ifdef HAVE_XRENDER
9802 XRenderPictFormat *default_format;
9803 XRenderPictureAttributes attr UNINIT;
9804 #endif
9805
9806 display = FRAME_X_DISPLAY (s->f);
9807
9808 #ifdef HAVE_XRENDER
9809 if (s->img->picture && FRAME_X_PICTURE_FORMAT (s->f))
9810 {
9811 if (destination == None)
9812 {
9813
9814
9815 default_format = FRAME_X_PICTURE_FORMAT (s->f);
9816 destination = XRenderCreatePicture (display, dest,
9817 default_format, 0, &attr);
9818
9819 XRenderComposite (display, (s->img->mask_picture
9820 ? PictOpOver : PictOpSrc),
9821 s->img->picture, s->img->mask_picture,
9822 destination, srcX, srcY, srcX, srcY,
9823 dstX, dstY, width, height);
9824
9825 XRenderFreePicture (display, destination);
9826 }
9827 else
9828 XRenderComposite (display, (s->img->mask_picture
9829 ? PictOpOver : PictOpSrc),
9830 s->img->picture, s->img->mask_picture,
9831 destination, srcX, srcY, srcX, srcY,
9832 dstX, dstY, width, height);
9833
9834 return;
9835 }
9836 #endif
9837
9838 XCopyArea (display, s->img->pixmap,
9839 dest, s->gc,
9840 srcX, srcY,
9841 width, height, dstX, dstY);
9842 }
9843
9844 #endif
9845
9846
9847
9848
9849 static void
9850 x_draw_image_foreground (struct glyph_string *s)
9851 {
9852 int x = s->x;
9853 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
9854
9855
9856
9857 if (s->face->box != FACE_NO_BOX
9858 && s->first_glyph->left_box_line_p
9859 && s->slice.x == 0)
9860 x += max (s->face->box_vertical_line_width, 0);
9861
9862
9863
9864 if (s->slice.x == 0)
9865 x += s->img->hmargin;
9866 if (s->slice.y == 0)
9867 y += s->img->vmargin;
9868
9869 #ifdef USE_CAIRO
9870 if (s->img->cr_data)
9871 {
9872 x_set_glyph_string_clipping (s);
9873 x_cr_draw_image (s->f, s->gc, s->img->cr_data,
9874 s->slice.x, s->slice.y, s->slice.width, s->slice.height,
9875 x, y, true);
9876 if (!s->img->mask)
9877 {
9878
9879
9880
9881
9882
9883
9884 if (s->hl == DRAW_CURSOR)
9885 {
9886 int relief = eabs (s->img->relief);
9887 x_draw_rectangle (s->f, s->gc, x - relief, y - relief,
9888 s->slice.width + relief*2 - 1,
9889 s->slice.height + relief*2 - 1);
9890 }
9891 }
9892 }
9893 #else
9894 if (s->img->pixmap)
9895 {
9896 if (s->img->mask)
9897 {
9898
9899
9900
9901
9902
9903
9904 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
9905 | GCFunction);
9906 XGCValues xgcv;
9907 XRectangle clip_rect, image_rect, r;
9908
9909 xgcv.clip_mask = s->img->mask;
9910 xgcv.clip_x_origin = x;
9911 xgcv.clip_y_origin = y;
9912 xgcv.function = GXcopy;
9913 XChangeGC (FRAME_X_DISPLAY (s->f), s->gc, mask, &xgcv);
9914
9915 get_glyph_string_clip_rect (s, &clip_rect);
9916 image_rect.x = x;
9917 image_rect.y = y;
9918 image_rect.width = s->slice.width;
9919 image_rect.height = s->slice.height;
9920 if (gui_intersect_rectangles (&clip_rect, &image_rect, &r))
9921 x_composite_image (s, FRAME_X_DRAWABLE (s->f),
9922 #ifdef HAVE_XRENDER
9923 FRAME_X_PICTURE (s->f),
9924 #endif
9925 s->slice.x + r.x - x, s->slice.y + r.y - y,
9926 r.x, r.y, r.width, r.height);
9927 }
9928 else
9929 {
9930 XRectangle clip_rect, image_rect, r;
9931
9932 get_glyph_string_clip_rect (s, &clip_rect);
9933 image_rect.x = x;
9934 image_rect.y = y;
9935 image_rect.width = s->slice.width;
9936 image_rect.height = s->slice.height;
9937 if (gui_intersect_rectangles (&clip_rect, &image_rect, &r))
9938 x_composite_image (s, FRAME_X_DRAWABLE (s->f),
9939 #ifdef HAVE_XRENDER
9940 FRAME_X_PICTURE (s->f),
9941 #endif
9942 s->slice.x + r.x - x,
9943 s->slice.y + r.y - y,
9944 r.x, r.y, r.width, r.height);
9945
9946
9947
9948
9949
9950
9951
9952 if (s->hl == DRAW_CURSOR)
9953 {
9954 int relief = eabs (s->img->relief);
9955 x_draw_rectangle (s->f, s->gc,
9956 x - relief, y - relief,
9957 s->slice.width + relief*2 - 1,
9958 s->slice.height + relief*2 - 1);
9959 }
9960 }
9961 }
9962 #endif
9963 else
9964
9965 x_draw_rectangle (s->f, s->gc, x, y,
9966 s->slice.width - 1, s->slice.height - 1);
9967 }
9968
9969
9970
9971
9972 static void
9973 x_draw_image_relief (struct glyph_string *s)
9974 {
9975 int x1, y1, thick;
9976 bool raised_p, top_p, bot_p, left_p, right_p;
9977 int extra_x, extra_y;
9978 XRectangle r;
9979 int x = s->x;
9980 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
9981
9982
9983
9984 if (s->face->box != FACE_NO_BOX
9985 && s->first_glyph->left_box_line_p
9986 && s->slice.x == 0)
9987 x += max (s->face->box_vertical_line_width, 0);
9988
9989
9990
9991 if (s->slice.x == 0)
9992 x += s->img->hmargin;
9993 if (s->slice.y == 0)
9994 y += s->img->vmargin;
9995
9996 if (s->hl == DRAW_IMAGE_SUNKEN
9997 || s->hl == DRAW_IMAGE_RAISED)
9998 {
9999 if (s->face->id == TAB_BAR_FACE_ID)
10000 thick = (tab_bar_button_relief < 0
10001 ? DEFAULT_TAB_BAR_BUTTON_RELIEF
10002 : min (tab_bar_button_relief, 1000000));
10003 else
10004 thick = (tool_bar_button_relief < 0
10005 ? DEFAULT_TOOL_BAR_BUTTON_RELIEF
10006 : min (tool_bar_button_relief, 1000000));
10007 raised_p = s->hl == DRAW_IMAGE_RAISED;
10008 }
10009 else
10010 {
10011 thick = eabs (s->img->relief);
10012 raised_p = s->img->relief > 0;
10013 }
10014
10015 x1 = x + s->slice.width - 1;
10016 y1 = y + s->slice.height - 1;
10017
10018 extra_x = extra_y = 0;
10019 if (s->face->id == TAB_BAR_FACE_ID)
10020 {
10021 if (CONSP (Vtab_bar_button_margin)
10022 && FIXNUMP (XCAR (Vtab_bar_button_margin))
10023 && FIXNUMP (XCDR (Vtab_bar_button_margin)))
10024 {
10025 extra_x = XFIXNUM (XCAR (Vtab_bar_button_margin)) - thick;
10026 extra_y = XFIXNUM (XCDR (Vtab_bar_button_margin)) - thick;
10027 }
10028 else if (FIXNUMP (Vtab_bar_button_margin))
10029 extra_x = extra_y = XFIXNUM (Vtab_bar_button_margin) - thick;
10030 }
10031
10032 if (s->face->id == TOOL_BAR_FACE_ID)
10033 {
10034 if (CONSP (Vtool_bar_button_margin)
10035 && FIXNUMP (XCAR (Vtool_bar_button_margin))
10036 && FIXNUMP (XCDR (Vtool_bar_button_margin)))
10037 {
10038 extra_x = XFIXNUM (XCAR (Vtool_bar_button_margin));
10039 extra_y = XFIXNUM (XCDR (Vtool_bar_button_margin));
10040 }
10041 else if (FIXNUMP (Vtool_bar_button_margin))
10042 extra_x = extra_y = XFIXNUM (Vtool_bar_button_margin);
10043 }
10044
10045 top_p = bot_p = left_p = right_p = false;
10046
10047 if (s->slice.x == 0)
10048 x -= thick + extra_x, left_p = true;
10049 if (s->slice.y == 0)
10050 y -= thick + extra_y, top_p = true;
10051 if (s->slice.x + s->slice.width == s->img->width)
10052 x1 += thick + extra_x, right_p = true;
10053 if (s->slice.y + s->slice.height == s->img->height)
10054 y1 += thick + extra_y, bot_p = true;
10055
10056 x_setup_relief_colors (s);
10057 get_glyph_string_clip_rect (s, &r);
10058 x_draw_relief_rect (s->f, x, y, x1, y1, thick, thick, raised_p,
10059 top_p, bot_p, left_p, right_p, &r);
10060 }
10061
10062
10063 #ifndef USE_CAIRO
10064
10065
10066 static void
10067 x_draw_image_foreground_1 (struct glyph_string *s, Pixmap pixmap)
10068 {
10069 int x = 0;
10070 int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
10071
10072
10073
10074 if (s->face->box != FACE_NO_BOX
10075 && s->first_glyph->left_box_line_p
10076 && s->slice.x == 0)
10077 x += max (s->face->box_vertical_line_width, 0);
10078
10079
10080
10081 if (s->slice.x == 0)
10082 x += s->img->hmargin;
10083 if (s->slice.y == 0)
10084 y += s->img->vmargin;
10085
10086 if (s->img->pixmap)
10087 {
10088 Display *display = FRAME_X_DISPLAY (s->f);
10089
10090 if (s->img->mask)
10091 {
10092
10093
10094
10095
10096
10097
10098 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
10099 | GCFunction);
10100 XGCValues xgcv;
10101
10102 xgcv.clip_mask = s->img->mask;
10103 xgcv.clip_x_origin = x - s->slice.x;
10104 xgcv.clip_y_origin = y - s->slice.y;
10105 xgcv.function = GXcopy;
10106 XChangeGC (display, s->gc, mask, &xgcv);
10107
10108 x_composite_image (s, pixmap,
10109 #ifdef HAVE_XRENDER
10110 None,
10111 #endif
10112 s->slice.x, s->slice.y, x, y,
10113 s->slice.width, s->slice.height);
10114 XSetClipMask (display, s->gc, None);
10115 }
10116 else
10117 {
10118 XCopyArea (display, s->img->pixmap, pixmap, s->gc,
10119 s->slice.x, s->slice.y,
10120 s->slice.width, s->slice.height, x, y);
10121
10122
10123
10124
10125
10126
10127
10128 if (s->hl == DRAW_CURSOR)
10129 {
10130 int r = eabs (s->img->relief);
10131 x_draw_rectangle (s->f, s->gc, x - r, y - r,
10132 s->slice.width + r*2 - 1,
10133 s->slice.height + r*2 - 1);
10134 }
10135 }
10136 }
10137 else
10138
10139 x_draw_rectangle (s->f, s->gc, x, y,
10140 s->slice.width - 1, s->slice.height - 1);
10141 }
10142 #endif
10143
10144
10145
10146
10147
10148 static void
10149 x_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w, int h)
10150 {
10151 if (s->stippled_p)
10152 {
10153 Display *display = FRAME_X_DISPLAY (s->f);
10154
10155
10156 XSetFillStyle (display, s->gc, FillOpaqueStippled);
10157 x_fill_rectangle (s->f, s->gc, x, y, w, h, true);
10158 XSetFillStyle (display, s->gc, FillSolid);
10159 }
10160 else
10161 x_clear_glyph_string_rect (s, x, y, w, h);
10162 }
10163
10164
10165
10166
10167
10168
10169
10170
10171
10172
10173
10174
10175
10176
10177
10178
10179 static void
10180 x_draw_image_glyph_string (struct glyph_string *s)
10181 {
10182 int box_line_hwidth = max (s->face->box_vertical_line_width, 0);
10183 int box_line_vwidth = max (s->face->box_horizontal_line_width, 0);
10184 int height;
10185 #ifndef USE_CAIRO
10186 Display *display = FRAME_X_DISPLAY (s->f);
10187 Pixmap pixmap = None;
10188 #endif
10189
10190 height = s->height;
10191 if (s->slice.y == 0)
10192 height -= box_line_vwidth;
10193 if (s->slice.y + s->slice.height >= s->img->height)
10194 height -= box_line_vwidth;
10195
10196
10197
10198
10199 s->stippled_p = s->face->stipple != 0;
10200 if (height > s->slice.height
10201 || s->img->hmargin
10202 || s->img->vmargin
10203 || s->img->mask
10204 || s->img->pixmap == 0
10205 || s->width != s->background_width)
10206 {
10207 if (s->stippled_p)
10208 s->row->stipple_p = true;
10209
10210 #ifndef USE_CAIRO
10211 if (s->img->mask)
10212 {
10213
10214
10215
10216 int depth = FRAME_DISPLAY_INFO (s->f)->n_planes;
10217
10218
10219 pixmap = XCreatePixmap (display, FRAME_X_DRAWABLE (s->f),
10220 s->background_width,
10221 s->height, depth);
10222
10223
10224
10225 XSetClipMask (display, s->gc, None);
10226
10227
10228 if (s->stippled_p)
10229 {
10230
10231 XSetFillStyle (display, s->gc, FillOpaqueStippled);
10232 XSetTSOrigin (display, s->gc, - s->x, - s->y);
10233 XFillRectangle (display, pixmap, s->gc,
10234 0, 0, s->background_width, s->height);
10235 XSetFillStyle (display, s->gc, FillSolid);
10236 XSetTSOrigin (display, s->gc, 0, 0);
10237 }
10238 else
10239 {
10240 XGCValues xgcv;
10241 #if defined HAVE_XRENDER && (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2))
10242 if (FRAME_DISPLAY_INFO (s->f)->alpha_bits
10243 && s->f->alpha_background != 1.0
10244 && FRAME_CHECK_XR_VERSION (s->f, 0, 2)
10245 && FRAME_X_PICTURE_FORMAT (s->f))
10246 {
10247 XRenderColor xc;
10248 XRenderPictureAttributes attrs;
10249 Picture pict;
10250 memset (&attrs, 0, sizeof attrs);
10251
10252 pict = XRenderCreatePicture (display, pixmap,
10253 FRAME_X_PICTURE_FORMAT (s->f),
10254 0, &attrs);
10255 x_xrender_color_from_gc_background (s->f, s->gc, &xc, true);
10256 XRenderFillRectangle (FRAME_X_DISPLAY (s->f), PictOpSrc, pict,
10257 &xc, 0, 0, s->background_width, s->height);
10258 XRenderFreePicture (display, pict);
10259 }
10260 else
10261 #endif
10262 {
10263 XGetGCValues (display, s->gc, GCForeground | GCBackground,
10264 &xgcv);
10265 XSetForeground (display, s->gc, xgcv.background);
10266 XFillRectangle (display, pixmap, s->gc,
10267 0, 0, s->background_width, s->height);
10268 XSetForeground (display, s->gc, xgcv.foreground);
10269 }
10270 }
10271 }
10272 else
10273 #endif
10274 {
10275 int x = s->x;
10276 int y = s->y;
10277 int width = s->background_width;
10278
10279 if (s->first_glyph->left_box_line_p
10280 && s->slice.x == 0)
10281 {
10282 x += box_line_hwidth;
10283 width -= box_line_hwidth;
10284 }
10285
10286 if (s->slice.y == 0)
10287 y += box_line_vwidth;
10288
10289 x_draw_glyph_string_bg_rect (s, x, y, width, height);
10290 }
10291
10292 s->background_filled_p = true;
10293 }
10294
10295
10296 #ifndef USE_CAIRO
10297 if (pixmap != None)
10298 {
10299 x_draw_image_foreground_1 (s, pixmap);
10300 x_set_glyph_string_clipping (s);
10301 XCopyArea (display, pixmap, FRAME_X_DRAWABLE (s->f), s->gc,
10302 0, 0, s->background_width, s->height, s->x, s->y);
10303 XFreePixmap (display, pixmap);
10304 }
10305 else
10306 #endif
10307 x_draw_image_foreground (s);
10308
10309
10310 if (s->img->relief
10311 || s->hl == DRAW_IMAGE_RAISED
10312 || s->hl == DRAW_IMAGE_SUNKEN)
10313 x_draw_image_relief (s);
10314 }
10315
10316
10317
10318
10319 static void
10320 x_draw_stretch_glyph_string (struct glyph_string *s)
10321 {
10322 eassert (s->first_glyph->type == STRETCH_GLYPH);
10323
10324 if (s->hl == DRAW_CURSOR
10325 && !x_stretch_cursor_p)
10326 {
10327
10328
10329 int width, background_width = s->background_width;
10330 int x = s->x;
10331
10332 if (!s->row->reversed_p)
10333 {
10334 int left_x = window_box_left_offset (s->w, TEXT_AREA);
10335
10336 if (x < left_x)
10337 {
10338 background_width -= left_x - x;
10339 x = left_x;
10340 }
10341 }
10342 else
10343 {
10344
10345
10346 int right_x = window_box_right (s->w, TEXT_AREA);
10347
10348 if (x + background_width > right_x)
10349 background_width -= x - right_x;
10350 x += background_width;
10351 }
10352 width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
10353 if (s->row->reversed_p)
10354 x -= width;
10355
10356
10357 x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
10358
10359
10360 if (width < background_width)
10361 {
10362 int y = s->y;
10363 int w = background_width - width, h = s->height;
10364 Display *display = FRAME_X_DISPLAY (s->f);
10365 XRectangle r;
10366 GC gc;
10367
10368 if (!s->row->reversed_p)
10369 x += width;
10370 else
10371 x = s->x;
10372 if (s->row->mouse_face_p
10373 && cursor_in_mouse_face_p (s->w))
10374 {
10375 x_set_mouse_face_gc (s);
10376 gc = s->gc;
10377 }
10378 else
10379 gc = s->face->gc;
10380
10381 get_glyph_string_clip_rect (s, &r);
10382 x_set_clip_rectangles (s->f, gc, &r, 1);
10383
10384 if (s->face->stipple)
10385 {
10386
10387 XSetFillStyle (display, gc, FillOpaqueStippled);
10388 x_fill_rectangle (s->f, gc, x, y, w, h, true);
10389 XSetFillStyle (display, gc, FillSolid);
10390
10391 s->row->stipple_p = true;
10392 }
10393 else
10394 {
10395 XGCValues xgcv;
10396 XGetGCValues (display, gc, GCForeground | GCBackground, &xgcv);
10397 XSetForeground (display, gc, xgcv.background);
10398 x_fill_rectangle (s->f, gc, x, y, w, h, true);
10399 XSetForeground (display, gc, xgcv.foreground);
10400 }
10401
10402 x_reset_clip_rectangles (s->f, gc);
10403 }
10404 }
10405 else if (!s->background_filled_p)
10406 {
10407 int background_width = s->background_width;
10408 int x = s->x, text_left_x = window_box_left (s->w, TEXT_AREA);
10409
10410
10411
10412 if (s->area == TEXT_AREA
10413 && x < text_left_x && !s->row->mode_line_p)
10414 {
10415 background_width -= text_left_x - x;
10416 x = text_left_x;
10417 }
10418
10419 if (!s->row->stipple_p)
10420 s->row->stipple_p = s->stippled_p;
10421
10422 if (background_width > 0)
10423 x_draw_glyph_string_bg_rect (s, x, s->y,
10424 background_width, s->height);
10425 }
10426
10427 s->background_filled_p = true;
10428 }
10429
10430 static void
10431 x_get_scale_factor (Display *disp, int *scale_x, int *scale_y)
10432 {
10433 const int base_res = 96;
10434 struct x_display_info * dpyinfo = x_display_info_for_display (disp);
10435
10436 *scale_x = *scale_y = 1;
10437
10438 if (dpyinfo)
10439 {
10440 if (dpyinfo->resx > base_res)
10441 *scale_x = floor (dpyinfo->resx / base_res);
10442 if (dpyinfo->resy > base_res)
10443 *scale_y = floor (dpyinfo->resy / base_res);
10444 }
10445 }
10446
10447
10448
10449
10450
10451
10452
10453
10454
10455
10456
10457 static void
10458 x_draw_underwave (struct glyph_string *s, int decoration_width)
10459 {
10460 Display *display = FRAME_X_DISPLAY (s->f);
10461
10462
10463 int scale_x, scale_y;
10464
10465 x_get_scale_factor (display, &scale_x, &scale_y);
10466
10467 int wave_height = 3 * scale_y, wave_length = 2 * scale_x;
10468
10469 #ifdef USE_CAIRO
10470 x_draw_horizontal_wave (s->f, s->gc, s->x, s->ybase - wave_height + 3,
10471 decoration_width, wave_height, wave_length);
10472 #else
10473 int dx, dy, x0, y0, width, x1, y1, x2, y2, xmax, thickness = scale_y;;
10474 bool odd;
10475 XRectangle wave_clip, string_clip, final_clip;
10476
10477 dx = wave_length;
10478 dy = wave_height - 1;
10479 x0 = s->x;
10480 y0 = s->ybase + wave_height / 2 - scale_y;
10481 width = decoration_width;
10482 xmax = x0 + width;
10483
10484
10485
10486 wave_clip.x = x0;
10487 wave_clip.y = y0;
10488 wave_clip.width = width;
10489 wave_clip.height = wave_height;
10490 get_glyph_string_clip_rect (s, &string_clip);
10491
10492 if (!gui_intersect_rectangles (&wave_clip, &string_clip, &final_clip))
10493 return;
10494
10495 XSetClipRectangles (display, s->gc, 0, 0, &final_clip, 1, Unsorted);
10496
10497
10498
10499 x1 = x0 - (x0 % dx);
10500 x2 = x1 + dx;
10501 odd = (x1 / dx) & 1;
10502 y1 = y2 = y0;
10503
10504 if (odd)
10505 y1 += dy;
10506 else
10507 y2 += dy;
10508
10509 if (INT_MAX - dx < xmax)
10510 emacs_abort ();
10511
10512 while (x1 <= xmax)
10513 {
10514 XSetLineAttributes (display, s->gc, thickness, LineSolid, CapButt,
10515 JoinRound);
10516 XDrawLine (display, FRAME_X_DRAWABLE (s->f), s->gc, x1, y1, x2, y2);
10517 x1 = x2, y1 = y2;
10518 x2 += dx, y2 = y0 + odd*dy;
10519 odd = !odd;
10520 }
10521
10522
10523 XSetClipRectangles (display, s->gc, 0, 0, s->clip, s->num_clips, Unsorted);
10524 #endif
10525 }
10526
10527
10528
10529
10530 static void
10531 x_draw_glyph_string (struct glyph_string *s)
10532 {
10533 bool relief_drawn_p = false;
10534
10535
10536
10537
10538 if (s->next && s->right_overhang && !s->for_overlaps)
10539 {
10540 int width;
10541 struct glyph_string *next;
10542
10543 for (width = 0, next = s->next;
10544 next && width < s->right_overhang;
10545 width += next->width, next = next->next)
10546 if (next->first_glyph->type != IMAGE_GLYPH)
10547 {
10548 x_set_glyph_string_gc (next);
10549 x_set_glyph_string_clipping (next);
10550 if (next->first_glyph->type == STRETCH_GLYPH)
10551 x_draw_stretch_glyph_string (next);
10552 else
10553 x_draw_glyph_string_background (next, true);
10554 next->num_clips = 0;
10555 }
10556 }
10557
10558
10559 x_set_glyph_string_gc (s);
10560
10561
10562
10563 if (!s->for_overlaps
10564 && s->face->box != FACE_NO_BOX
10565 && (s->first_glyph->type == CHAR_GLYPH
10566 || s->first_glyph->type == COMPOSITE_GLYPH))
10567
10568 {
10569 x_set_glyph_string_clipping (s);
10570 x_draw_glyph_string_background (s, true);
10571 x_draw_glyph_string_box (s);
10572 x_set_glyph_string_clipping (s);
10573 relief_drawn_p = true;
10574 }
10575 else if (!s->clip_head
10576 && !s->clip_tail
10577 && ((s->prev && s->prev->hl != s->hl && s->left_overhang)
10578 || (s->next && s->next->hl != s->hl && s->right_overhang)))
10579
10580
10581
10582 x_set_glyph_string_clipping_exactly (s, s);
10583 else
10584 x_set_glyph_string_clipping (s);
10585
10586 switch (s->first_glyph->type)
10587 {
10588 case IMAGE_GLYPH:
10589 x_draw_image_glyph_string (s);
10590 break;
10591
10592 case XWIDGET_GLYPH:
10593 x_draw_xwidget_glyph_string (s);
10594 break;
10595
10596 case STRETCH_GLYPH:
10597 x_draw_stretch_glyph_string (s);
10598 break;
10599
10600 case CHAR_GLYPH:
10601 if (s->for_overlaps)
10602 s->background_filled_p = true;
10603 else
10604 x_draw_glyph_string_background (s, false);
10605 x_draw_glyph_string_foreground (s);
10606 break;
10607
10608 case COMPOSITE_GLYPH:
10609 if (s->for_overlaps || (s->cmp_from > 0
10610 && ! s->first_glyph->u.cmp.automatic))
10611 s->background_filled_p = true;
10612 else
10613 x_draw_glyph_string_background (s, true);
10614 x_draw_composite_glyph_string_foreground (s);
10615 break;
10616
10617 case GLYPHLESS_GLYPH:
10618 if (s->for_overlaps)
10619 s->background_filled_p = true;
10620 else
10621 x_draw_glyph_string_background (s, true);
10622 x_draw_glyphless_glyph_string_foreground (s);
10623 break;
10624
10625 default:
10626 emacs_abort ();
10627 }
10628
10629 if (!s->for_overlaps)
10630 {
10631 int area_x, area_y, area_width, area_height;
10632 int area_max_x, decoration_width;
10633
10634
10635
10636 window_box (s->w, s->area, &area_x, &area_y,
10637 &area_width, &area_height);
10638 area_max_x = area_x + area_width - 1;
10639
10640 decoration_width = s->width;
10641 if (!s->row->mode_line_p
10642 && !s->row->tab_line_p
10643 && area_max_x < (s->x + decoration_width - 1))
10644 decoration_width -= (s->x + decoration_width - 1) - area_max_x;
10645
10646
10647 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
10648 x_draw_glyph_string_box (s);
10649
10650
10651 if (s->face->underline)
10652 {
10653 if (s->face->underline == FACE_UNDER_WAVE)
10654 {
10655 if (s->face->underline_defaulted_p)
10656 x_draw_underwave (s, decoration_width);
10657 else
10658 {
10659 Display *display = FRAME_X_DISPLAY (s->f);
10660 XGCValues xgcv;
10661 XGetGCValues (display, s->gc, GCForeground, &xgcv);
10662 XSetForeground (display, s->gc, s->face->underline_color);
10663 x_draw_underwave (s, decoration_width);
10664 XSetForeground (display, s->gc, xgcv.foreground);
10665 }
10666 }
10667 else if (s->face->underline == FACE_UNDER_LINE)
10668 {
10669 unsigned long thickness, position;
10670 int y;
10671
10672 if (s->prev
10673 && s->prev->face->underline == FACE_UNDER_LINE
10674 && (s->prev->face->underline_at_descent_line_p
10675 == s->face->underline_at_descent_line_p)
10676 && (s->prev->face->underline_pixels_above_descent_line
10677 == s->face->underline_pixels_above_descent_line))
10678 {
10679
10680 thickness = s->prev->underline_thickness;
10681 position = s->prev->underline_position;
10682 }
10683 else
10684 {
10685 struct font *font = font_for_underline_metrics (s);
10686 unsigned long minimum_offset;
10687 bool underline_at_descent_line;
10688 bool use_underline_position_properties;
10689 Lisp_Object val = (WINDOW_BUFFER_LOCAL_VALUE
10690 (Qunderline_minimum_offset, s->w));
10691
10692 if (FIXNUMP (val))
10693 minimum_offset = max (0, XFIXNUM (val));
10694 else
10695 minimum_offset = 1;
10696
10697 val = (WINDOW_BUFFER_LOCAL_VALUE
10698 (Qx_underline_at_descent_line, s->w));
10699 underline_at_descent_line
10700 = (!(NILP (val) || BASE_EQ (val, Qunbound))
10701 || s->face->underline_at_descent_line_p);
10702
10703 val = (WINDOW_BUFFER_LOCAL_VALUE
10704 (Qx_use_underline_position_properties, s->w));
10705 use_underline_position_properties
10706 = !(NILP (val) || BASE_EQ (val, Qunbound));
10707
10708
10709 if (font && font->underline_thickness > 0)
10710 thickness = font->underline_thickness;
10711 else
10712 thickness = 1;
10713 if (underline_at_descent_line)
10714 position = ((s->height - thickness)
10715 - (s->ybase - s->y)
10716 - s->face->underline_pixels_above_descent_line);
10717 else
10718 {
10719
10720
10721
10722
10723
10724
10725
10726
10727
10728 if (use_underline_position_properties
10729 && font && font->underline_position >= 0)
10730 position = font->underline_position;
10731 else if (font)
10732 position = (font->descent + 1) / 2;
10733 else
10734 position = minimum_offset;
10735 }
10736
10737
10738
10739 if (!s->face->underline_pixels_above_descent_line)
10740 position = max (position, minimum_offset);
10741 }
10742
10743
10744 if (s->y + s->height <= s->ybase + position)
10745 position = (s->height - 1) - (s->ybase - s->y);
10746 if (s->y + s->height < s->ybase + position + thickness)
10747 thickness = (s->y + s->height) - (s->ybase + position);
10748 s->underline_thickness = thickness;
10749 s->underline_position = position;
10750 y = s->ybase + position;
10751 if (s->face->underline_defaulted_p)
10752 x_fill_rectangle (s->f, s->gc,
10753 s->x, y, decoration_width, thickness,
10754 false);
10755 else
10756 {
10757 Display *display = FRAME_X_DISPLAY (s->f);
10758 XGCValues xgcv;
10759 XGetGCValues (display, s->gc, GCForeground, &xgcv);
10760 XSetForeground (display, s->gc, s->face->underline_color);
10761 x_fill_rectangle (s->f, s->gc,
10762 s->x, y, decoration_width, thickness,
10763 false);
10764 XSetForeground (display, s->gc, xgcv.foreground);
10765 }
10766 }
10767 }
10768
10769 if (s->face->overline_p)
10770 {
10771 unsigned long dy = 0, h = 1;
10772
10773 if (s->face->overline_color_defaulted_p)
10774 x_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
10775 decoration_width, h, false);
10776 else
10777 {
10778 Display *display = FRAME_X_DISPLAY (s->f);
10779 XGCValues xgcv;
10780 XGetGCValues (display, s->gc, GCForeground, &xgcv);
10781 XSetForeground (display, s->gc, s->face->overline_color);
10782 x_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
10783 decoration_width, h, false);
10784 XSetForeground (display, s->gc, xgcv.foreground);
10785 }
10786 }
10787
10788
10789 if (s->face->strike_through_p)
10790 {
10791
10792
10793
10794
10795
10796 int glyph_y = s->ybase - s->first_glyph->ascent;
10797 int glyph_height = s->first_glyph->ascent + s->first_glyph->descent;
10798
10799
10800 unsigned long h = 1;
10801 unsigned long dy = (glyph_height - h) / 2;
10802
10803 if (s->face->strike_through_color_defaulted_p)
10804 x_fill_rectangle (s->f, s->gc, s->x, glyph_y + dy,
10805 s->width, h, false);
10806 else
10807 {
10808 Display *display = FRAME_X_DISPLAY (s->f);
10809 XGCValues xgcv;
10810 XGetGCValues (display, s->gc, GCForeground, &xgcv);
10811 XSetForeground (display, s->gc, s->face->strike_through_color);
10812 x_fill_rectangle (s->f, s->gc, s->x, glyph_y + dy,
10813 decoration_width, h, false);
10814 XSetForeground (display, s->gc, xgcv.foreground);
10815 }
10816 }
10817
10818 if (s->prev)
10819 {
10820 struct glyph_string *prev;
10821
10822 for (prev = s->prev; prev; prev = prev->prev)
10823 if (prev->hl != s->hl
10824 && prev->x + prev->width + prev->right_overhang > s->x)
10825 {
10826
10827
10828 enum draw_glyphs_face save = prev->hl;
10829
10830 prev->hl = s->hl;
10831 x_set_glyph_string_gc (prev);
10832 x_set_glyph_string_clipping_exactly (s, prev);
10833 if (prev->first_glyph->type == CHAR_GLYPH)
10834 x_draw_glyph_string_foreground (prev);
10835 else
10836 x_draw_composite_glyph_string_foreground (prev);
10837 x_reset_clip_rectangles (prev->f, prev->gc);
10838 prev->hl = save;
10839 prev->num_clips = 0;
10840 }
10841 }
10842
10843 if (s->next)
10844 {
10845 struct glyph_string *next;
10846
10847 for (next = s->next; next; next = next->next)
10848 if (next->hl != s->hl
10849 && next->x - next->left_overhang < s->x + s->width)
10850 {
10851
10852
10853 enum draw_glyphs_face save = next->hl;
10854
10855 next->hl = s->hl;
10856 x_set_glyph_string_gc (next);
10857 x_set_glyph_string_clipping_exactly (s, next);
10858 if (next->first_glyph->type == CHAR_GLYPH)
10859 x_draw_glyph_string_foreground (next);
10860 else
10861 x_draw_composite_glyph_string_foreground (next);
10862 x_reset_clip_rectangles (next->f, next->gc);
10863 next->hl = save;
10864 next->num_clips = 0;
10865 next->clip_head = s->next;
10866 }
10867 }
10868 }
10869
10870
10871 x_reset_clip_rectangles (s->f, s->gc);
10872 s->num_clips = 0;
10873
10874
10875
10876
10877 if (s->first_glyph->type != STRETCH_GLYPH
10878 && s->first_glyph->type != IMAGE_GLYPH
10879 && !s->row->stipple_p)
10880 s->row->stipple_p = s->stippled_p;
10881 }
10882
10883
10884
10885 static void
10886 x_shift_glyphs_for_insert (struct frame *f, int x, int y, int width, int height, int shift_by)
10887 {
10888
10889
10890
10891 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), FRAME_X_DRAWABLE (f),
10892 f->output_data.x->normal_gc,
10893 x, y, width, height,
10894 x + shift_by, y);
10895 }
10896
10897
10898
10899
10900 static void
10901 x_delete_glyphs (struct frame *f, int n)
10902 {
10903 emacs_abort ();
10904 }
10905
10906
10907
10908
10909
10910 #if defined USE_GTK || !defined USE_CAIRO
10911 static void
10912 x_clear_area1 (Display *dpy, Window window,
10913 int x, int y, int width, int height, int exposures)
10914 {
10915 eassert (width > 0 && height > 0);
10916 XClearArea (dpy, window, x, y, width, height, exposures);
10917 }
10918 #endif
10919
10920 void
10921 x_clear_area (struct frame *f, int x, int y, int width, int height)
10922 {
10923 #ifdef USE_CAIRO
10924 cairo_t *cr;
10925
10926 eassert (width > 0 && height > 0);
10927
10928 cr = x_begin_cr_clip (f, NULL);
10929 x_set_cr_source_with_gc_background (f, f->output_data.x->normal_gc,
10930 true);
10931 cairo_rectangle (cr, x, y, width, height);
10932 cairo_fill (cr);
10933 x_end_cr_clip (f);
10934 #else
10935 #ifndef USE_GTK
10936 if (f->alpha_background != 1.0
10937 #ifdef HAVE_XDBE
10938 || FRAME_X_DOUBLE_BUFFERED_P (f)
10939 #endif
10940 )
10941 #endif
10942 {
10943 #if defined HAVE_XRENDER && \
10944 (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2))
10945 x_xr_ensure_picture (f);
10946 if (FRAME_DISPLAY_INFO (f)->alpha_bits
10947 && FRAME_X_PICTURE (f) != None
10948 && f->alpha_background != 1.0
10949 && FRAME_CHECK_XR_VERSION (f, 0, 2))
10950 {
10951 XRenderColor xc;
10952 GC gc = f->output_data.x->normal_gc;
10953
10954 x_xr_apply_ext_clip (f, gc);
10955 x_xrender_color_from_gc_background (f, gc, &xc, true);
10956 XRenderFillRectangle (FRAME_X_DISPLAY (f),
10957 PictOpSrc, FRAME_X_PICTURE (f),
10958 &xc, x, y, width, height);
10959 x_xr_reset_ext_clip (f);
10960 x_mark_frame_dirty (f);
10961 }
10962 else
10963 #endif
10964 XFillRectangle (FRAME_X_DISPLAY (f),
10965 FRAME_X_DRAWABLE (f),
10966 f->output_data.x->reverse_gc,
10967 x, y, width, height);
10968 }
10969 #ifndef USE_GTK
10970 else
10971 x_clear_area1 (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10972 x, y, width, height, False);
10973 #endif
10974 #endif
10975 }
10976
10977
10978
10979
10980 static void
10981 x_clear_frame (struct frame *f)
10982 {
10983
10984
10985 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
10986
10987 block_input ();
10988 font_drop_xrender_surfaces (f);
10989 x_clear_window (f);
10990
10991
10992
10993 x_scroll_bar_clear (f);
10994
10995 unblock_input ();
10996 }
10997
10998
10999
11000 static void
11001 x_show_hourglass (struct frame *f)
11002 {
11003 Display *dpy = FRAME_X_DISPLAY (f);
11004
11005 if (dpy)
11006 {
11007 struct x_output *x = FRAME_X_OUTPUT (f);
11008
11009
11010
11011
11012
11013
11014
11015 if (popup_activated ())
11016 return;
11017
11018 #ifdef USE_X_TOOLKIT
11019 if (x->widget)
11020 #else
11021 if (FRAME_OUTER_WINDOW (f))
11022 #endif
11023 {
11024 x->hourglass_p = true;
11025
11026 if (!x->hourglass_window)
11027 {
11028 #ifndef USE_XCB
11029 unsigned long mask = CWCursor;
11030 XSetWindowAttributes attrs;
11031 #ifdef USE_GTK
11032 Window parent = FRAME_X_WINDOW (f);
11033 #else
11034 Window parent = FRAME_OUTER_WINDOW (f);
11035 #endif
11036 attrs.cursor = x->hourglass_cursor;
11037
11038 x->hourglass_window = XCreateWindow
11039 (dpy, parent, 0, 0, 32000, 32000, 0, 0,
11040 InputOnly, CopyFromParent, mask, &attrs);
11041 #else
11042 uint32_t cursor = (uint32_t) x->hourglass_cursor;
11043 #ifdef USE_GTK
11044 xcb_window_t parent = (xcb_window_t) FRAME_X_WINDOW (f);
11045 #else
11046 xcb_window_t parent = (xcb_window_t) FRAME_OUTER_WINDOW (f);
11047 #endif
11048 x->hourglass_window
11049 = (Window) xcb_generate_id (FRAME_DISPLAY_INFO (f)->xcb_connection);
11050
11051 xcb_create_window (FRAME_DISPLAY_INFO (f)->xcb_connection,
11052 XCB_COPY_FROM_PARENT,
11053 (xcb_window_t) x->hourglass_window,
11054 parent, 0, 0, FRAME_PIXEL_WIDTH (f),
11055 FRAME_PIXEL_HEIGHT (f), 0,
11056 XCB_WINDOW_CLASS_INPUT_ONLY,
11057 XCB_COPY_FROM_PARENT, XCB_CW_CURSOR,
11058 &cursor);
11059 #endif
11060 }
11061
11062 #ifndef USE_XCB
11063 XMapRaised (dpy, x->hourglass_window);
11064
11065 flush_frame (f);
11066 #else
11067 uint32_t value = XCB_STACK_MODE_ABOVE;
11068
11069 xcb_configure_window (FRAME_DISPLAY_INFO (f)->xcb_connection,
11070 (xcb_window_t) x->hourglass_window,
11071 XCB_CONFIG_WINDOW_STACK_MODE, &value);
11072 xcb_map_window (FRAME_DISPLAY_INFO (f)->xcb_connection,
11073 (xcb_window_t) x->hourglass_window);
11074 xcb_flush (FRAME_DISPLAY_INFO (f)->xcb_connection);
11075 #endif
11076 }
11077 }
11078 }
11079
11080
11081
11082 static void
11083 x_hide_hourglass (struct frame *f)
11084 {
11085 struct x_output *x = FRAME_X_OUTPUT (f);
11086
11087
11088 if (x->hourglass_window)
11089 {
11090 #ifndef USE_XCB
11091 XUnmapWindow (FRAME_X_DISPLAY (f), x->hourglass_window);
11092
11093
11094 XSync (FRAME_X_DISPLAY (f), False);
11095 #else
11096 xcb_unmap_window (FRAME_DISPLAY_INFO (f)->xcb_connection,
11097 (xcb_window_t) x->hourglass_window);
11098 xcb_aux_sync (FRAME_DISPLAY_INFO (f)->xcb_connection);
11099 #endif
11100 x->hourglass_p = false;
11101 }
11102 }
11103
11104
11105
11106 static void
11107 XTflash (struct frame *f)
11108 {
11109 GC gc;
11110 XGCValues values;
11111 fd_set fds;
11112 int fd, rc;
11113
11114 block_input ();
11115
11116 if (FRAME_X_VISUAL_INFO (f)->class == TrueColor)
11117 {
11118 values.function = GXxor;
11119 values.foreground = (FRAME_FOREGROUND_PIXEL (f)
11120 ^ FRAME_BACKGROUND_PIXEL (f));
11121
11122 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11123 GCFunction | GCForeground, &values);
11124 }
11125 else
11126 gc = FRAME_X_OUTPUT (f)->normal_gc;
11127
11128
11129
11130 int height = FRAME_PIXEL_HEIGHT (f);
11131
11132 int flash_height = FRAME_LINE_HEIGHT (f);
11133
11134 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
11135 int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
11136 int width = flash_right - flash_left;
11137
11138
11139 if (height > 3 * FRAME_LINE_HEIGHT (f))
11140 {
11141 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
11142 flash_left,
11143 (FRAME_INTERNAL_BORDER_WIDTH (f)
11144 + FRAME_TOP_MARGIN_HEIGHT (f)),
11145 width, flash_height);
11146 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
11147 flash_left,
11148 (height - flash_height
11149 - FRAME_INTERNAL_BORDER_WIDTH (f)),
11150 width, flash_height);
11151
11152 }
11153 else
11154
11155 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
11156 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
11157 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
11158
11159 x_flush (f);
11160
11161 struct timespec delay = make_timespec (0, 150 * 1000 * 1000);
11162 struct timespec wakeup = timespec_add (current_timespec (), delay);
11163 fd = ConnectionNumber (FRAME_X_DISPLAY (f));
11164
11165
11166
11167 while (! detect_input_pending ())
11168 {
11169 struct timespec current = current_timespec ();
11170 struct timespec timeout;
11171
11172
11173 if (timespec_cmp (wakeup, current) <= 0)
11174 break;
11175
11176
11177 timeout = make_timespec (0, 10 * 1000 * 1000);
11178
11179
11180
11181 FD_ZERO (&fds);
11182 FD_SET (fd, &fds);
11183
11184
11185 rc = pselect (fd + 1, &fds, NULL, NULL, &timeout, NULL);
11186
11187
11188 if (rc >= 0 && FD_ISSET (fd, &fds))
11189 break;
11190 }
11191
11192
11193 if (height > 3 * FRAME_LINE_HEIGHT (f))
11194 {
11195 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
11196 flash_left,
11197 (FRAME_INTERNAL_BORDER_WIDTH (f)
11198 + FRAME_TOP_MARGIN_HEIGHT (f)),
11199 width, flash_height);
11200 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
11201 flash_left,
11202 (height - flash_height
11203 - FRAME_INTERNAL_BORDER_WIDTH (f)),
11204 width, flash_height);
11205 }
11206 else
11207
11208 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
11209 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
11210 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
11211
11212 if (FRAME_X_VISUAL_INFO (f)->class == TrueColor)
11213 XFreeGC (FRAME_X_DISPLAY (f), gc);
11214 x_flush (f);
11215
11216 unblock_input ();
11217 }
11218
11219
11220
11221 static void
11222 XTring_bell (struct frame *f)
11223 {
11224 if (FRAME_X_DISPLAY (f))
11225 {
11226 if (visible_bell)
11227 XTflash (f);
11228 else
11229 {
11230 block_input ();
11231 #ifdef HAVE_XKB
11232 XkbBell (FRAME_X_DISPLAY (f), None, 0, None);
11233 #else
11234 XBell (FRAME_X_DISPLAY (f), 0);
11235 #endif
11236 XFlush (FRAME_X_DISPLAY (f));
11237 unblock_input ();
11238 }
11239 }
11240 }
11241
11242
11243
11244
11245
11246
11247
11248
11249 static void
11250 x_ins_del_lines (struct frame *f, int vpos, int n)
11251 {
11252 emacs_abort ();
11253 }
11254
11255
11256
11257
11258 static void
11259 x_scroll_run (struct window *w, struct run *run)
11260 {
11261 struct frame *f = XFRAME (w->frame);
11262 int x, y, width, height, from_y, to_y, bottom_y;
11263
11264
11265
11266
11267 window_box (w, ANY_AREA, &x, &y, &width, &height);
11268
11269 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
11270 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
11271 bottom_y = y + height;
11272
11273 if (to_y < from_y)
11274 {
11275
11276
11277 if (from_y + run->height > bottom_y)
11278 height = bottom_y - from_y;
11279 else
11280 height = run->height;
11281 }
11282 else
11283 {
11284
11285
11286 if (to_y + run->height > bottom_y)
11287 height = bottom_y - to_y;
11288 else
11289 height = run->height;
11290 }
11291
11292 block_input ();
11293
11294
11295 gui_clear_cursor (w);
11296
11297 #ifdef HAVE_XWIDGETS
11298
11299 Display *dpy = FRAME_X_DISPLAY (f);
11300 Window window = FRAME_X_WINDOW (f);
11301
11302 Window root, parent, *children;
11303 unsigned int nchildren;
11304
11305 if (XQueryTree (dpy, window, &root, &parent, &children, &nchildren))
11306 {
11307
11308
11309 for (unsigned int i = 0; i < nchildren; ++i)
11310 {
11311 Window child = children[i];
11312 struct xwidget_view *view = xwidget_view_from_window (child);
11313
11314 if (view && !view->hidden)
11315 {
11316 int window_y = view->y + view->clip_top;
11317 int window_height = view->clip_bottom - view->clip_top;
11318
11319 Emacs_Rectangle r1, r2, result;
11320 r1.x = w->pixel_left;
11321 r1.y = from_y;
11322 r1.width = w->pixel_width;
11323 r1.height = height;
11324 r2 = r1;
11325 r2.y = window_y;
11326 r2.height = window_height;
11327
11328
11329 if (window_height == 0)
11330 {
11331 view->hidden = true;
11332 XUnmapWindow (dpy, child);
11333 continue;
11334 }
11335
11336 bool intersects_p =
11337 gui_intersect_rectangles (&r1, &r2, &result);
11338
11339 if (XWINDOW (view->w) == w && intersects_p)
11340 {
11341 int y = view->y + (to_y - from_y);
11342 int text_area_x, text_area_y, text_area_width, text_area_height;
11343 int clip_top, clip_bottom;
11344
11345 window_box (w, view->area, &text_area_x, &text_area_y,
11346 &text_area_width, &text_area_height);
11347
11348 view->y = y;
11349
11350 clip_top = 0;
11351 clip_bottom = XXWIDGET (view->model)->height;
11352
11353 if (y < text_area_y)
11354 clip_top = text_area_y - y;
11355
11356 if ((y + clip_bottom) > (text_area_y + text_area_height))
11357 {
11358 clip_bottom -= (y + clip_bottom) - (text_area_y + text_area_height);
11359 }
11360
11361 view->clip_top = clip_top;
11362 view->clip_bottom = clip_bottom;
11363
11364
11365
11366 if ((view->clip_bottom - view->clip_top) <= 0)
11367 {
11368 view->hidden = true;
11369 XUnmapWindow (dpy, child);
11370 }
11371 else
11372 {
11373 XMoveResizeWindow (dpy, child, view->x + view->clip_left,
11374 view->y + view->clip_top,
11375 view->clip_right - view->clip_left,
11376 view->clip_bottom - view->clip_top);
11377 cairo_xlib_surface_set_size (view->cr_surface,
11378 view->clip_right - view->clip_left,
11379 view->clip_bottom - view->clip_top);
11380 }
11381 xwidget_expose (view);
11382 }
11383 }
11384 }
11385 XFree (children);
11386 }
11387 #endif
11388
11389 #ifdef USE_CAIRO_XCB_SURFACE
11390
11391
11392
11393 XFlushGC (FRAME_X_DISPLAY (f),
11394 f->output_data.x->normal_gc);
11395 #endif
11396
11397 #ifdef USE_CAIRO
11398 if (FRAME_CR_CONTEXT (f))
11399 {
11400 cairo_surface_t *surface = cairo_get_target (FRAME_CR_CONTEXT (f));
11401 if (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_XLIB)
11402 {
11403 eassert (cairo_xlib_surface_get_display (surface)
11404 == FRAME_X_DISPLAY (f));
11405 eassert (cairo_xlib_surface_get_drawable (surface)
11406 == FRAME_X_RAW_DRAWABLE (f));
11407 cairo_surface_flush (surface);
11408 XCopyArea (FRAME_X_DISPLAY (f),
11409 FRAME_X_DRAWABLE (f), FRAME_X_DRAWABLE (f),
11410 f->output_data.x->normal_gc,
11411 x, from_y,
11412 width, height,
11413 x, to_y);
11414 cairo_surface_mark_dirty_rectangle (surface, x, to_y, width, height);
11415 }
11416 #ifdef USE_CAIRO_XCB_SURFACE
11417 else if (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_XCB)
11418 {
11419 cairo_surface_flush (surface);
11420 xcb_copy_area (FRAME_DISPLAY_INFO (f)->xcb_connection,
11421 (xcb_drawable_t) FRAME_X_DRAWABLE (f),
11422 (xcb_drawable_t) FRAME_X_DRAWABLE (f),
11423 (xcb_gcontext_t) XGContextFromGC (f->output_data.x->normal_gc),
11424 x, from_y, x, to_y, width, height);
11425 cairo_surface_mark_dirty_rectangle (surface, x, to_y, width, height);
11426 }
11427 #endif
11428 else
11429 {
11430 cairo_surface_t *s
11431 = cairo_surface_create_similar (surface,
11432 cairo_surface_get_content (surface),
11433 width, height);
11434 cairo_t *cr = cairo_create (s);
11435 cairo_set_source_surface (cr, surface, -x, -from_y);
11436 cairo_paint (cr);
11437 cairo_destroy (cr);
11438
11439 cr = FRAME_CR_CONTEXT (f);
11440 cairo_save (cr);
11441 cairo_set_source_surface (cr, s, x, to_y);
11442 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
11443 cairo_rectangle (cr, x, to_y, width, height);
11444 cairo_fill (cr);
11445 cairo_restore (cr);
11446 cairo_surface_destroy (s);
11447 }
11448 }
11449 else
11450 #endif
11451 XCopyArea (FRAME_X_DISPLAY (f),
11452 FRAME_X_DRAWABLE (f), FRAME_X_DRAWABLE (f),
11453 f->output_data.x->normal_gc,
11454 x, from_y,
11455 width, height,
11456 x, to_y);
11457
11458 unblock_input ();
11459 }
11460
11461
11462
11463
11464
11465
11466
11467
11468 static void
11469 x_frame_highlight (struct frame *f)
11470 {
11471 struct x_display_info *dpyinfo;
11472
11473 dpyinfo = FRAME_DISPLAY_INFO (f);
11474
11475
11476
11477
11478
11479 block_input ();
11480
11481
11482
11483
11484 x_ignore_errors_for_next_request (dpyinfo);
11485 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11486 f->output_data.x->border_pixel);
11487 x_stop_ignoring_errors (dpyinfo);
11488 unblock_input ();
11489 gui_update_cursor (f, true);
11490 x_set_frame_alpha (f);
11491 }
11492
11493 static void
11494 x_frame_unhighlight (struct frame *f)
11495 {
11496 struct x_display_info *dpyinfo;
11497
11498 dpyinfo = FRAME_DISPLAY_INFO (f);
11499
11500
11501
11502
11503
11504
11505 block_input ();
11506
11507 x_ignore_errors_for_next_request (dpyinfo);
11508 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11509 f->output_data.x->border_tile);
11510 x_stop_ignoring_errors (dpyinfo);
11511 unblock_input ();
11512
11513 gui_update_cursor (f, true);
11514 x_set_frame_alpha (f);
11515 }
11516
11517
11518
11519
11520
11521
11522
11523 static void
11524 x_new_focus_frame (struct x_display_info *dpyinfo, struct frame *frame)
11525 {
11526 struct frame *old_focus = dpyinfo->x_focus_frame;
11527 #if defined USE_GTK && !defined HAVE_GTK3 && defined HAVE_XINPUT2
11528 XIEventMask mask;
11529 ptrdiff_t l;
11530
11531 if (dpyinfo->supports_xi2)
11532 {
11533 l = XIMaskLen (XI_LASTEVENT);
11534 mask.mask = alloca (l);
11535 mask.mask_len = l;
11536 memset (mask.mask, 0, l);
11537
11538 mask.deviceid = XIAllDevices;
11539 }
11540 #endif
11541
11542 if (frame != dpyinfo->x_focus_frame)
11543 {
11544
11545
11546 dpyinfo->x_focus_frame = frame;
11547
11548
11549
11550
11551 #if defined USE_GTK && !defined HAVE_GTK3 && defined HAVE_XINPUT2
11552 if (frame && dpyinfo->supports_xi2)
11553 XISetMask (mask.mask, XI_RawKeyPress);
11554
11555 if (dpyinfo->supports_xi2)
11556 XISelectEvents (dpyinfo->display, dpyinfo->root_window, &mask, 1);
11557 #endif
11558
11559 if (old_focus && old_focus->auto_lower)
11560 x_lower_frame (old_focus);
11561
11562 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
11563 dpyinfo->x_pending_autoraise_frame = dpyinfo->x_focus_frame;
11564 else
11565 dpyinfo->x_pending_autoraise_frame = NULL;
11566 }
11567
11568 x_frame_rehighlight (dpyinfo);
11569 }
11570
11571 #ifdef HAVE_XFIXES
11572
11573
11574
11575
11576 static bool
11577 x_fixes_pointer_blanking_supported (struct x_display_info *dpyinfo)
11578 {
11579 return (dpyinfo->xfixes_supported_p
11580 && dpyinfo->xfixes_major >= 4);
11581 }
11582
11583 #endif
11584
11585
11586
11587 #ifdef HAVE_XFIXES
11588 static void
11589 xfixes_toggle_visible_pointer (struct frame *f, bool invisible)
11590
11591 {
11592 if (invisible)
11593 XFixesHideCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11594 else
11595 XFixesShowCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11596 f->pointer_invisible = invisible;
11597 }
11598 #endif
11599
11600
11601 static Cursor
11602 make_invisible_cursor (struct x_display_info *dpyinfo)
11603 {
11604 Display *dpy = dpyinfo->display;
11605 static char const no_data[] = { 0 };
11606 Pixmap pix;
11607 XColor col;
11608 Cursor c;
11609
11610 c = None;
11611
11612 x_catch_errors (dpy);
11613 pix = XCreateBitmapFromData (dpy, dpyinfo->root_window, no_data, 1, 1);
11614 if (!x_had_errors_p (dpy) && pix != None)
11615 {
11616 Cursor pixc;
11617 col.pixel = 0;
11618 col.red = col.green = col.blue = 0;
11619 col.flags = DoRed | DoGreen | DoBlue;
11620 pixc = XCreatePixmapCursor (dpy, pix, pix, &col, &col, 0, 0);
11621 if (! x_had_errors_p (dpy) && pixc != None)
11622 c = pixc;
11623 XFreePixmap (dpy, pix);
11624 }
11625
11626 x_uncatch_errors ();
11627
11628 return c;
11629 }
11630
11631
11632
11633 static void
11634 x_toggle_visible_pointer (struct frame *f, bool invisible)
11635 {
11636 struct x_display_info *dpyinfo;
11637
11638 dpyinfo = FRAME_DISPLAY_INFO (f);
11639
11640
11641
11642
11643 if (dpyinfo->invisible_cursor == None)
11644 dpyinfo->invisible_cursor = make_invisible_cursor (dpyinfo);
11645
11646 #ifndef HAVE_XFIXES
11647 if (dpyinfo->invisible_cursor == None)
11648 invisible = false;
11649 #else
11650
11651 if (dpyinfo->invisible_cursor == None)
11652 {
11653 if (x_fixes_pointer_blanking_supported (dpyinfo))
11654 {
11655 dpyinfo->fixes_pointer_blanking = true;
11656 xfixes_toggle_visible_pointer (f, invisible);
11657
11658 return;
11659 }
11660 else
11661 invisible = false;
11662 }
11663 #endif
11664
11665 if (invisible)
11666 XDefineCursor (dpyinfo->display, FRAME_X_WINDOW (f),
11667 dpyinfo->invisible_cursor);
11668 else
11669 XDefineCursor (dpyinfo->display, FRAME_X_WINDOW (f),
11670 f->output_data.x->current_cursor);
11671
11672 f->pointer_invisible = invisible;
11673 }
11674
11675 static void
11676 XTtoggle_invisible_pointer (struct frame *f, bool invisible)
11677 {
11678 block_input ();
11679 #ifdef HAVE_XFIXES
11680 if (FRAME_DISPLAY_INFO (f)->fixes_pointer_blanking
11681 && x_fixes_pointer_blanking_supported (FRAME_DISPLAY_INFO (f)))
11682 xfixes_toggle_visible_pointer (f, invisible);
11683 else
11684 #endif
11685 x_toggle_visible_pointer (f, invisible);
11686 unblock_input ();
11687 }
11688
11689
11690
11691
11692
11693
11694
11695
11696 static void
11697 x_focus_changed (int type, int state, struct x_display_info *dpyinfo,
11698 struct frame *frame, struct input_event *bufp)
11699 {
11700 if (type == FocusIn)
11701 {
11702 if (dpyinfo->x_focus_event_frame != frame)
11703 {
11704 x_new_focus_frame (dpyinfo, frame);
11705 dpyinfo->x_focus_event_frame = frame;
11706 bufp->kind = FOCUS_IN_EVENT;
11707 XSETFRAME (bufp->frame_or_window, frame);
11708 }
11709
11710 frame->output_data.x->focus_state |= state;
11711
11712 #ifdef HAVE_X_I18N
11713 if (FRAME_XIC (frame))
11714 XSetICFocus (FRAME_XIC (frame));
11715 #ifdef USE_GTK
11716 GtkWidget *widget;
11717
11718 if (x_gtk_use_native_input)
11719 {
11720 gtk_im_context_focus_in (FRAME_X_OUTPUT (frame)->im_context);
11721 widget = FRAME_GTK_OUTER_WIDGET (frame);
11722 gtk_im_context_set_client_window (FRAME_X_OUTPUT (frame)->im_context,
11723 gtk_widget_get_window (widget));
11724 }
11725 #endif
11726 #endif
11727 }
11728 else if (type == FocusOut)
11729 {
11730 frame->output_data.x->focus_state &= ~state;
11731
11732 if (dpyinfo->x_focus_event_frame == frame)
11733 {
11734 dpyinfo->x_focus_event_frame = 0;
11735 x_new_focus_frame (dpyinfo, 0);
11736
11737 bufp->kind = FOCUS_OUT_EVENT;
11738 XSETFRAME (bufp->frame_or_window, frame);
11739 }
11740
11741 if (!frame->output_data.x->focus_state)
11742 {
11743 #ifdef HAVE_X_I18N
11744 if (FRAME_XIC (frame))
11745 XUnsetICFocus (FRAME_XIC (frame));
11746 #ifdef USE_GTK
11747 if (x_gtk_use_native_input)
11748 {
11749 gtk_im_context_focus_out (FRAME_X_OUTPUT (frame)->im_context);
11750 gtk_im_context_set_client_window (FRAME_X_OUTPUT (frame)->im_context, NULL);
11751 }
11752 #endif
11753 #endif
11754 }
11755
11756 if (frame->pointer_invisible)
11757 XTtoggle_invisible_pointer (frame, false);
11758 }
11759 }
11760
11761
11762
11763
11764
11765 static struct frame *
11766 x_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
11767 {
11768 Lisp_Object tail, frame;
11769 struct frame *f;
11770
11771 if (wdesc == None)
11772 return NULL;
11773
11774 #ifdef HAVE_XWIDGETS
11775 struct xwidget_view *xvw = xwidget_view_from_window (wdesc);
11776
11777 if (xvw && xvw->frame)
11778 return xvw->frame;
11779 #endif
11780
11781 FOR_EACH_FRAME (tail, frame)
11782 {
11783 f = XFRAME (frame);
11784 if (!FRAME_X_P (f) || FRAME_DISPLAY_INFO (f) != dpyinfo)
11785 continue;
11786 if (f->output_data.x->hourglass_window == wdesc)
11787 return f;
11788 #ifdef USE_X_TOOLKIT
11789 if ((f->output_data.x->edit_widget
11790 && XtWindow (f->output_data.x->edit_widget) == wdesc)
11791
11792 || (!f->output_data.x->edit_widget
11793 && FRAME_X_WINDOW (f) == wdesc)
11794 || f->output_data.x->icon_desc == wdesc)
11795 return f;
11796 #else
11797 #ifdef USE_GTK
11798 if (f->output_data.x->edit_widget)
11799 {
11800 GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
11801 struct x_output *x = f->output_data.x;
11802 if (gwdesc != 0 && gwdesc == x->edit_widget)
11803 return f;
11804 }
11805 #endif
11806 if (FRAME_X_WINDOW (f) == wdesc
11807 || f->output_data.x->icon_desc == wdesc)
11808 return f;
11809 #endif
11810 }
11811 return 0;
11812 }
11813
11814
11815
11816
11817
11818 static struct frame *
11819 x_tooltip_window_to_frame (struct x_display_info *dpyinfo,
11820 Window wdesc, bool *unrelated_tooltip_p)
11821 {
11822 Lisp_Object tail, frame;
11823 struct frame *f;
11824 #ifdef USE_GTK
11825 GtkWidget *widget;
11826 GdkWindow *tooltip_window;
11827 #endif
11828
11829 if (unrelated_tooltip_p)
11830 *unrelated_tooltip_p = false;
11831
11832 FOR_EACH_FRAME (tail, frame)
11833 {
11834 f = XFRAME (frame);
11835
11836 if (FRAME_X_P (f) && FRAME_TOOLTIP_P (f)
11837 && FRAME_DISPLAY_INFO (f) == dpyinfo
11838 && FRAME_X_WINDOW (f) == wdesc)
11839 return f;
11840
11841 #ifdef USE_GTK
11842 if (!FRAME_X_P (f))
11843 continue;
11844
11845 if (FRAME_X_OUTPUT (f)->ttip_window)
11846 widget = GTK_WIDGET (FRAME_X_OUTPUT (f)->ttip_window);
11847 else
11848 widget = NULL;
11849
11850 if (widget)
11851 tooltip_window = gtk_widget_get_window (widget);
11852 else
11853 tooltip_window = NULL;
11854
11855 #ifdef HAVE_GTK3
11856 if (tooltip_window
11857 && (gdk_x11_window_get_xid (tooltip_window) == wdesc))
11858 {
11859 if (unrelated_tooltip_p)
11860 *unrelated_tooltip_p = true;
11861 break;
11862 }
11863 #else
11864 if (tooltip_window
11865 && (GDK_WINDOW_XID (tooltip_window) == wdesc))
11866 {
11867 if (unrelated_tooltip_p)
11868 *unrelated_tooltip_p = true;
11869 break;
11870 }
11871 #endif
11872 #endif
11873 }
11874
11875 return NULL;
11876 }
11877
11878 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
11879
11880
11881
11882
11883 static struct frame *
11884 x_any_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
11885 {
11886 Lisp_Object tail, frame;
11887 struct frame *f, *found = NULL;
11888 struct x_output *x;
11889
11890 if (wdesc == None)
11891 return NULL;
11892
11893 #ifdef HAVE_XWIDGETS
11894 struct xwidget_view *xv = xwidget_view_from_window (wdesc);
11895
11896 if (xv)
11897 return xv->frame;
11898 #endif
11899
11900 FOR_EACH_FRAME (tail, frame)
11901 {
11902 if (found)
11903 break;
11904 f = XFRAME (frame);
11905 if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) == dpyinfo)
11906 {
11907
11908 x = f->output_data.x;
11909 if (x->hourglass_window == wdesc)
11910 found = f;
11911 else if (x->widget)
11912 {
11913 #ifdef USE_GTK
11914 GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
11915 if (gwdesc != 0
11916 && gtk_widget_get_toplevel (gwdesc) == x->widget)
11917 found = f;
11918 #else
11919 if (wdesc == XtWindow (x->widget)
11920 || wdesc == XtWindow (x->column_widget)
11921 || wdesc == XtWindow (x->edit_widget))
11922 found = f;
11923
11924 else if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
11925 found = f;
11926 #endif
11927 }
11928 else if (FRAME_X_WINDOW (f) == wdesc)
11929
11930 found = f;
11931 }
11932 }
11933
11934 return found;
11935 }
11936
11937
11938
11939 static struct frame *
11940 x_menubar_window_to_frame (struct x_display_info *dpyinfo,
11941 const XEvent *event)
11942 {
11943 Window wdesc;
11944 #ifdef HAVE_XINPUT2
11945 if (event->type == GenericEvent
11946 && dpyinfo->supports_xi2
11947 && (event->xcookie.evtype == XI_ButtonPress
11948 || event->xcookie.evtype == XI_ButtonRelease))
11949 wdesc = ((XIDeviceEvent *) event->xcookie.data)->event;
11950 else
11951 #endif
11952 wdesc = event->xany.window;
11953 Lisp_Object tail, frame;
11954 struct frame *f;
11955 struct x_output *x;
11956
11957 if (wdesc == None)
11958 return NULL;
11959
11960 FOR_EACH_FRAME (tail, frame)
11961 {
11962 f = XFRAME (frame);
11963 if (!FRAME_X_P (f) || FRAME_DISPLAY_INFO (f) != dpyinfo)
11964 continue;
11965 x = f->output_data.x;
11966 #ifdef USE_GTK
11967 if (x->menubar_widget && xg_event_is_for_menubar (f, event))
11968 return f;
11969 #else
11970
11971 if (x->menubar_widget
11972 && lw_window_is_in_menubar (wdesc, x->menubar_widget))
11973 return f;
11974 #endif
11975 }
11976 return 0;
11977 }
11978
11979
11980
11981
11982 struct frame *
11983 x_top_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
11984 {
11985 Lisp_Object tail, frame;
11986 struct frame *f;
11987 struct x_output *x;
11988
11989 if (wdesc == None)
11990 return NULL;
11991
11992 FOR_EACH_FRAME (tail, frame)
11993 {
11994 f = XFRAME (frame);
11995 if (!FRAME_X_P (f) || FRAME_DISPLAY_INFO (f) != dpyinfo)
11996 continue;
11997 x = f->output_data.x;
11998
11999 if (x->widget)
12000 {
12001
12002 #ifdef USE_GTK
12003 GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
12004 if (gwdesc == x->widget)
12005 return f;
12006 #else
12007 if (wdesc == XtWindow (x->widget))
12008 return f;
12009 #endif
12010 }
12011 else if (FRAME_X_WINDOW (f) == wdesc)
12012
12013 return f;
12014 }
12015 return 0;
12016 }
12017
12018 #else
12019
12020 #define x_any_window_to_frame(d, i) x_window_to_frame (d, i)
12021
12022 struct frame *
12023 x_top_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
12024 {
12025 return x_window_to_frame (dpyinfo, wdesc);
12026 }
12027
12028 static void
12029 x_next_event_from_any_display (XEvent *event)
12030 {
12031 struct x_display_info *dpyinfo;
12032 fd_set fds, rfds;
12033 int fd, maxfd, rc;
12034
12035 rc = -1;
12036 FD_ZERO (&rfds);
12037
12038 while (true)
12039 {
12040 FD_ZERO (&fds);
12041 maxfd = -1;
12042
12043 for (dpyinfo = x_display_list; dpyinfo;
12044 dpyinfo = dpyinfo->next)
12045 {
12046 fd = ConnectionNumber (dpyinfo->display);
12047
12048 if ((rc < 0 || FD_ISSET (fd, &rfds))
12049 && XPending (dpyinfo->display))
12050 {
12051 XNextEvent (dpyinfo->display, event);
12052 return;
12053 }
12054
12055 if (fd > maxfd)
12056 maxfd = fd;
12057
12058 eassert (fd < FD_SETSIZE);
12059 FD_SET (fd, &fds);
12060 }
12061
12062 eassert (maxfd >= 0);
12063
12064
12065
12066
12067 rc = pselect (maxfd + 1, &fds, NULL, NULL, NULL, NULL);
12068
12069 if (rc >= 0)
12070 rfds = fds;
12071 }
12072 }
12073
12074 #endif
12075
12076 static void
12077 x_handle_pending_selection_requests_1 (struct x_selection_request_event *tem)
12078 {
12079 specpdl_ref count;
12080 struct selection_input_event se;
12081
12082 count = SPECPDL_INDEX ();
12083 se = tem->se;
12084
12085 record_unwind_protect_ptr (xfree, tem);
12086 x_handle_selection_event (&se);
12087 unbind_to (count, Qnil);
12088 }
12089
12090
12091
12092 void
12093 x_handle_pending_selection_requests (void)
12094 {
12095 struct x_selection_request_event *tem;
12096
12097 while (pending_selection_requests)
12098 {
12099 tem = pending_selection_requests;
12100 pending_selection_requests = tem->next;
12101
12102 x_handle_pending_selection_requests_1 (tem);
12103 }
12104 }
12105
12106 static void
12107 x_push_selection_request (struct selection_input_event *se)
12108 {
12109 struct x_selection_request_event *tem;
12110
12111 tem = xmalloc (sizeof *tem);
12112 tem->next = pending_selection_requests;
12113 tem->se = *se;
12114 pending_selection_requests = tem;
12115 }
12116
12117 bool
12118 x_detect_pending_selection_requests (void)
12119 {
12120 return !!pending_selection_requests;
12121 }
12122
12123 static void
12124 x_clear_dnd_action (void)
12125 {
12126 x_dnd_action_symbol = Qnil;
12127 }
12128
12129
12130 static void
12131 x_dnd_delete_action_list (Lisp_Object frame)
12132 {
12133 struct frame *f;
12134
12135
12136
12137
12138
12139
12140 f = XFRAME (frame);
12141
12142 if (!FRAME_LIVE_P (f) || !FRAME_DISPLAY_INFO (f)->display)
12143 return;
12144
12145 block_input ();
12146 XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12147 FRAME_DISPLAY_INFO (f)->Xatom_XdndActionList);
12148 XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12149 FRAME_DISPLAY_INFO (f)->Xatom_XdndActionDescription);
12150 unblock_input ();
12151 }
12152
12153 static void
12154 x_dnd_lose_ownership (Lisp_Object timestamp_and_frame)
12155 {
12156 struct frame *f;
12157
12158 f = XFRAME (XCDR (timestamp_and_frame));
12159
12160 if (FRAME_LIVE_P (f))
12161 Fx_disown_selection_internal (QXdndSelection,
12162 XCAR (timestamp_and_frame),
12163 XCDR (timestamp_and_frame));
12164 }
12165
12166
12167
12168
12169 static void
12170 x_dnd_process_quit (struct frame *f, Time timestamp)
12171 {
12172 xm_drop_start_message dmsg;
12173
12174 if (x_dnd_in_progress)
12175 {
12176 if (x_dnd_last_seen_window != None
12177 && x_dnd_last_protocol_version != -1)
12178 x_dnd_send_leave (f, x_dnd_last_seen_window,
12179 x_dnd_last_seen_toplevel);
12180 else if (x_dnd_last_seen_window != None
12181 && !XM_DRAG_STYLE_IS_DROP_ONLY (x_dnd_last_motif_style)
12182 && x_dnd_last_motif_style != XM_DRAG_STYLE_NONE
12183 && x_dnd_motif_setup_p)
12184 {
12185 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
12186 XM_DRAG_REASON_DROP_START);
12187 dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST;
12188 dmsg.timestamp = timestamp;
12189 dmsg.side_effects
12190 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f),
12191 x_dnd_wanted_action),
12192 XM_DROP_SITE_VALID, x_dnd_motif_operations,
12193 XM_DROP_ACTION_DROP_CANCEL);
12194 dmsg.x = 0;
12195 dmsg.y = 0;
12196 dmsg.index_atom = x_dnd_motif_atom;
12197 dmsg.source_window = FRAME_X_WINDOW (f);
12198
12199 x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f,
12200 x_dnd_last_seen_window,
12201 timestamp);
12202 xm_send_drop_message (FRAME_DISPLAY_INFO (f), FRAME_X_WINDOW (f),
12203 x_dnd_last_seen_window, &dmsg);
12204 }
12205
12206 x_dnd_end_window = x_dnd_last_seen_window;
12207 x_dnd_last_seen_window = None;
12208 x_dnd_last_seen_toplevel = None;
12209 x_dnd_in_progress = false;
12210 x_dnd_frame = NULL;
12211 }
12212
12213 x_dnd_waiting_for_finish = false;
12214 x_dnd_return_frame_object = NULL;
12215 x_dnd_movement_frame = NULL;
12216 x_dnd_wheel_frame = NULL;
12217 }
12218
12219
12220
12221
12222
12223
12224
12225
12226
12227
12228
12229
12230
12231
12232
12233
12234
12235
12236 Lisp_Object
12237 x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
12238 Lisp_Object return_frame, Atom *ask_action_list,
12239 const char **ask_action_names, size_t n_ask_actions,
12240 bool allow_current_frame, Atom *target_atoms,
12241 int ntargets, Lisp_Object selection_target_list,
12242 bool follow_tooltip)
12243 {
12244 #ifndef USE_GTK
12245 XEvent next_event;
12246 int finish;
12247 #endif
12248 XWindowAttributes root_window_attrs;
12249 struct input_event hold_quit;
12250 char *atom_name, *ask_actions;
12251 Lisp_Object action, ltimestamp, val;
12252 specpdl_ref ref, count, base;
12253 ptrdiff_t i, end, fill;
12254 XTextProperty prop;
12255 Lisp_Object frame_object, x, y, frame, local_value;
12256 bool signals_were_pending, need_sync;
12257 #ifdef HAVE_XKB
12258 XkbStateRec keyboard_state;
12259 #endif
12260 #ifndef USE_GTK
12261 struct x_display_info *event_display;
12262 #endif
12263 unsigned int additional_mask;
12264 #ifdef HAVE_XINPUT2
12265 struct xi_device_t *device;
12266 #endif
12267
12268 base = SPECPDL_INDEX ();
12269
12270
12271
12272 specbind (Qx_dnd_targets_list, selection_target_list);
12273
12274 if (!FRAME_VISIBLE_P (f))
12275 error ("Frame must be visible");
12276
12277 XSETFRAME (frame, f);
12278 local_value = assq_no_quit (QXdndSelection,
12279 FRAME_TERMINAL (f)->Vselection_alist);
12280
12281 if (x_dnd_in_progress || x_dnd_waiting_for_finish)
12282 error ("A drag-and-drop session is already in progress");
12283
12284 DEFER_SELECTIONS;
12285
12286
12287
12288 if (NILP (local_value))
12289 error ("No local value for XdndSelection");
12290
12291 if (popup_activated ())
12292 error ("Trying to drag-and-drop from within a menu-entry");
12293
12294 x_set_dnd_targets (target_atoms, ntargets);
12295 record_unwind_protect_void (x_free_dnd_targets);
12296 record_unwind_protect_void (x_clear_dnd_action);
12297
12298 ltimestamp = x_timestamp_for_selection (FRAME_DISPLAY_INFO (f),
12299 QXdndSelection);
12300
12301 if (NILP (ltimestamp))
12302 error ("No local value for XdndSelection");
12303
12304 if (BIGNUMP (ltimestamp))
12305 x_dnd_selection_timestamp = bignum_to_intmax (ltimestamp);
12306 else
12307 x_dnd_selection_timestamp = XFIXNUM (ltimestamp);
12308
12309
12310
12311
12312
12313 if (!x_dnd_preserve_selection_data)
12314 record_unwind_protect (x_dnd_lose_ownership,
12315 Fcons (ltimestamp, frame));
12316
12317 x_dnd_motif_operations
12318 = xm_side_effect_from_action (FRAME_DISPLAY_INFO (f), xaction);
12319
12320 x_dnd_first_motif_operation = XM_DRAG_NOOP;
12321
12322 if (n_ask_actions)
12323 {
12324 x_dnd_motif_operations
12325 = xm_operations_from_actions (FRAME_DISPLAY_INFO (f),
12326 ask_action_list,
12327 n_ask_actions);
12328 x_dnd_first_motif_operation
12329 = xm_side_effect_from_action (FRAME_DISPLAY_INFO (f),
12330 ask_action_list[0]);
12331
12332 record_unwind_protect (x_dnd_delete_action_list, frame);
12333
12334 ask_actions = NULL;
12335 end = 0;
12336 count = SPECPDL_INDEX ();
12337
12338 for (i = 0; i < n_ask_actions; ++i)
12339 {
12340 fill = end;
12341 end += strlen (ask_action_names[i]) + 1;
12342
12343 if (ask_actions)
12344 ask_actions = xrealloc (ask_actions, end);
12345 else
12346 ask_actions = xmalloc (end);
12347
12348 strncpy (ask_actions + fill,
12349 ask_action_names[i],
12350 end - fill);
12351 }
12352
12353 prop.value = (unsigned char *) ask_actions;
12354 prop.encoding = XA_STRING;
12355 prop.format = 8;
12356 prop.nitems = end;
12357
12358 record_unwind_protect_ptr (xfree, ask_actions);
12359
12360
12361
12362 block_input ();
12363 x_catch_errors (FRAME_X_DISPLAY (f));
12364 XSetTextProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12365 &prop, FRAME_DISPLAY_INFO (f)->Xatom_XdndActionDescription);
12366
12367 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12368 FRAME_DISPLAY_INFO (f)->Xatom_XdndActionList, XA_ATOM, 32,
12369 PropModeReplace, (unsigned char *) ask_action_list,
12370 n_ask_actions);
12371 x_check_errors (FRAME_X_DISPLAY (f),
12372 "Can't set action descriptions: %s");
12373 x_uncatch_errors_after_check ();
12374 unblock_input ();
12375
12376 unbind_to (count, Qnil);
12377 }
12378
12379 record_unwind_protect_void (x_clear_dnd_variables);
12380
12381 if (follow_tooltip)
12382 {
12383 #if defined HAVE_XRANDR || defined USE_GTK
12384 x_dnd_monitors
12385 = FRAME_DISPLAY_INFO (f)->last_monitor_attributes_list;
12386
12387 if (NILP (x_dnd_monitors))
12388 #endif
12389 x_dnd_monitors
12390 = Fx_display_monitor_attributes_list (frame);
12391 }
12392
12393 x_dnd_update_tooltip = follow_tooltip;
12394
12395
12396 if (x_dnd_toplevels)
12397 x_dnd_free_toplevels (true);
12398
12399 #ifdef USE_GTK
12400
12401
12402 suppress_xg_select ();
12403 record_unwind_protect_void (release_xg_select);
12404 #endif
12405
12406
12407 XSETCAR (x_dnd_selection_alias_cell, QSECONDARY);
12408 XSETCDR (x_dnd_selection_alias_cell, QSECONDARY);
12409
12410
12411
12412 specbind (Qx_selection_alias_alist,
12413 Fcons (x_dnd_selection_alias_cell,
12414 Vx_selection_alias_alist));
12415
12416
12417 x_dnd_in_progress = true;
12418 x_dnd_recursion_depth = command_loop_level + minibuf_level;
12419 x_dnd_frame = f;
12420 x_dnd_last_seen_window = None;
12421 x_dnd_last_seen_toplevel = None;
12422 x_dnd_last_protocol_version = -1;
12423 x_dnd_last_window_is_frame = false;
12424 x_dnd_last_motif_style = XM_DRAG_STYLE_NONE;
12425 x_dnd_mouse_rect_target = None;
12426 x_dnd_action = None;
12427 x_dnd_action_symbol = Qnil;
12428 x_dnd_wanted_action = xaction;
12429 x_dnd_return_frame = 0;
12430 x_dnd_waiting_for_finish = false;
12431 x_dnd_waiting_for_motif_finish = 0;
12432 x_dnd_waiting_for_status_window = None;
12433 x_dnd_pending_send_position.type = 0;
12434 x_dnd_xm_use_help = false;
12435 x_dnd_motif_setup_p = false;
12436 x_dnd_end_window = None;
12437 x_dnd_run_unsupported_drop_function = false;
12438 x_dnd_use_toplevels
12439 = x_wm_supports (f, FRAME_DISPLAY_INFO (f)->Xatom_net_client_list_stacking);
12440 x_dnd_last_tooltip_valid = false;
12441 x_dnd_toplevels = NULL;
12442 x_dnd_allow_current_frame = allow_current_frame;
12443 x_dnd_movement_frame = NULL;
12444 x_dnd_wheel_frame = NULL;
12445 x_dnd_init_type_lists = false;
12446 x_dnd_need_send_drop = false;
12447
12448 #ifdef HAVE_XINPUT2
12449
12450 if (FRAME_DISPLAY_INFO (f)->supports_xi2)
12451 {
12452
12453
12454
12455 if (FRAME_DISPLAY_INFO (f)->client_pointer_device != -1)
12456 x_dnd_pointer_device
12457 = FRAME_DISPLAY_INFO (f)->client_pointer_device;
12458 else
12459
12460 XIGetClientPointer (FRAME_X_DISPLAY (f), None,
12461 &x_dnd_pointer_device);
12462
12463 x_dnd_keyboard_device = -1;
12464
12465 device = xi_device_from_id (FRAME_DISPLAY_INFO (f),
12466 x_dnd_pointer_device);
12467
12468 if (device)
12469 x_dnd_keyboard_device = device->attachment;
12470 }
12471 else
12472 {
12473 x_dnd_pointer_device = -1;
12474 x_dnd_keyboard_device = -1;
12475 }
12476
12477 #endif
12478
12479 #ifdef HAVE_XKB
12480 x_dnd_keyboard_state = 0;
12481
12482 if (FRAME_DISPLAY_INFO (f)->supports_xkb)
12483 {
12484 XkbSelectEvents (FRAME_X_DISPLAY (f), XkbUseCoreKbd,
12485 XkbStateNotifyMask, XkbStateNotifyMask);
12486 XkbGetState (FRAME_X_DISPLAY (f), XkbUseCoreKbd,
12487 &keyboard_state);
12488
12489 x_dnd_keyboard_state = (keyboard_state.mods
12490 | keyboard_state.ptr_buttons);
12491 }
12492 #endif
12493
12494 if (x_dnd_use_toplevels)
12495 {
12496 if (x_dnd_compute_toplevels (FRAME_DISPLAY_INFO (f)))
12497 {
12498 x_dnd_free_toplevels (true);
12499 x_dnd_use_toplevels = false;
12500 }
12501 else
12502 record_unwind_protect_void (x_free_dnd_toplevels);
12503 }
12504
12505 if (!NILP (return_frame))
12506 x_dnd_return_frame = 1;
12507
12508 if (EQ (return_frame, Qnow))
12509 x_dnd_return_frame = 2;
12510
12511
12512
12513
12514
12515 XGetWindowAttributes (FRAME_X_DISPLAY (f),
12516 FRAME_DISPLAY_INFO (f)->root_window,
12517 &root_window_attrs);
12518
12519 additional_mask = SubstructureNotifyMask;
12520
12521 if (x_dnd_use_toplevels)
12522 additional_mask |= PropertyChangeMask;
12523
12524 XSelectInput (FRAME_X_DISPLAY (f),
12525 FRAME_DISPLAY_INFO (f)->root_window,
12526 root_window_attrs.your_event_mask
12527 | additional_mask);
12528
12529 if (EQ (return_frame, Qnow))
12530 x_dnd_update_state (FRAME_DISPLAY_INFO (f), CurrentTime);
12531
12532 while (x_dnd_in_progress || x_dnd_waiting_for_finish)
12533 {
12534 EVENT_INIT (hold_quit);
12535
12536 #ifdef USE_GTK
12537 current_finish = X_EVENT_NORMAL;
12538 current_hold_quit = &hold_quit;
12539 current_count = 0;
12540 xg_pending_quit_event.kind = NO_EVENT;
12541 #endif
12542
12543 block_input ();
12544 x_dnd_inside_handle_one_xevent = true;
12545 #ifdef USE_GTK
12546 gtk_main_iteration ();
12547 #elif defined USE_X_TOOLKIT
12548 XtAppNextEvent (Xt_app_con, &next_event);
12549 #else
12550 x_next_event_from_any_display (&next_event);
12551 #endif
12552
12553 #ifndef USE_GTK
12554 event_display
12555 = x_display_info_for_display (next_event.xany.display);
12556
12557 if (event_display)
12558 {
12559 #ifdef HAVE_X_I18N
12560 #ifdef HAVE_XINPUT2
12561 if (next_event.type != GenericEvent
12562 || !event_display->supports_xi2
12563 || (next_event.xgeneric.extension
12564 != event_display->xi2_opcode))
12565 {
12566 #endif
12567 if (!x_filter_event (event_display, &next_event))
12568 handle_one_xevent (event_display,
12569 &next_event, &finish, &hold_quit);
12570 #ifdef HAVE_XINPUT2
12571 }
12572 else
12573 handle_one_xevent (event_display,
12574 &next_event, &finish, &hold_quit);
12575 #endif
12576 #else
12577 handle_one_xevent (event_display,
12578 &next_event, &finish, &hold_quit);
12579 #endif
12580 }
12581 #else
12582
12583 current_count = -1;
12584 current_hold_quit = NULL;
12585 #endif
12586 x_dnd_inside_handle_one_xevent = false;
12587
12588
12589 x_clean_failable_requests (FRAME_DISPLAY_INFO (f));
12590
12591
12592
12593
12594 signals_were_pending = pending_signals;
12595 unblock_input ();
12596 pending_signals = signals_were_pending;
12597
12598
12599
12600 #ifndef USE_GTK
12601 if (event_display == FRAME_DISPLAY_INFO (f))
12602 {
12603 #endif
12604 if (x_dnd_movement_frame
12605
12606
12607 && (FRAME_X_DISPLAY (x_dnd_movement_frame)
12608 == FRAME_X_DISPLAY (f))
12609
12610
12611
12612
12613 && (x_dnd_in_progress || x_dnd_waiting_for_finish))
12614 {
12615 XSETFRAME (frame_object, x_dnd_movement_frame);
12616 XSETINT (x, x_dnd_movement_x);
12617 XSETINT (y, x_dnd_movement_y);
12618 x_dnd_movement_frame = NULL;
12619
12620 if (!NILP (Vx_dnd_movement_function)
12621 && FRAME_LIVE_P (XFRAME (frame_object))
12622 && !FRAME_TOOLTIP_P (XFRAME (frame_object))
12623 && x_dnd_movement_x >= 0
12624 && x_dnd_movement_y >= 0
12625 && x_dnd_frame
12626 && (XFRAME (frame_object) != x_dnd_frame
12627 || x_dnd_allow_current_frame))
12628 {
12629 x_dnd_old_window_attrs = root_window_attrs;
12630 x_dnd_unwind_flag = true;
12631
12632 ref = SPECPDL_INDEX ();
12633 record_unwind_protect_ptr (x_dnd_cleanup_drag_and_drop, f);
12634 call2 (Vx_dnd_movement_function, frame_object,
12635 Fposn_at_x_y (x, y, frame_object, Qnil));
12636 x_dnd_unwind_flag = false;
12637 unbind_to (ref, Qnil);
12638
12639
12640
12641
12642 redisplay_preserve_echo_area (33);
12643 }
12644 }
12645
12646 if (x_dnd_wheel_frame
12647 && (x_dnd_in_progress || x_dnd_waiting_for_finish))
12648 {
12649 XSETFRAME (frame_object, x_dnd_wheel_frame);
12650 XSETINT (x, x_dnd_wheel_x);
12651 XSETINT (y, x_dnd_wheel_y);
12652 x_dnd_wheel_frame = NULL;
12653
12654 if (!NILP (Vx_dnd_wheel_function)
12655 && FRAME_LIVE_P (XFRAME (frame_object))
12656 && !FRAME_TOOLTIP_P (XFRAME (frame_object))
12657 && x_dnd_movement_x >= 0
12658 && x_dnd_movement_y >= 0
12659 && x_dnd_frame
12660 && (XFRAME (frame_object) != x_dnd_frame
12661 || x_dnd_allow_current_frame))
12662 {
12663 x_dnd_old_window_attrs = root_window_attrs;
12664 x_dnd_unwind_flag = true;
12665
12666 ref = SPECPDL_INDEX ();
12667 record_unwind_protect_ptr (x_dnd_cleanup_drag_and_drop, f);
12668 call4 (Vx_dnd_wheel_function,
12669 Fposn_at_x_y (x, y, frame_object, Qnil),
12670 make_fixnum (x_dnd_wheel_button),
12671 make_uint (x_dnd_wheel_state),
12672 make_uint (x_dnd_wheel_time));
12673 x_dnd_unwind_flag = false;
12674 unbind_to (ref, Qnil);
12675
12676
12677
12678
12679 redisplay_preserve_echo_area (33);
12680 }
12681 }
12682
12683 if (hold_quit.kind != NO_EVENT)
12684 {
12685 x_dnd_process_quit (f, hold_quit.timestamp);
12686 #ifdef USE_GTK
12687 current_hold_quit = NULL;
12688 #endif
12689
12690 x_restore_events_after_dnd (f, &root_window_attrs);
12691
12692
12693
12694
12695 kbd_buffer_store_event (&hold_quit);
12696
12697 quit ();
12698 }
12699
12700 if (pending_selection_requests
12701 && (x_dnd_in_progress || x_dnd_waiting_for_finish))
12702 {
12703 x_dnd_old_window_attrs = root_window_attrs;
12704 x_dnd_unwind_flag = true;
12705
12706 ref = SPECPDL_INDEX ();
12707 record_unwind_protect_ptr (x_dnd_cleanup_drag_and_drop, f);
12708 x_handle_pending_selection_requests ();
12709 x_dnd_unwind_flag = false;
12710 unbind_to (ref, Qnil);
12711 }
12712
12713
12714
12715
12716 if (!NILP (Vquit_flag) && !NILP (Vinhibit_quit))
12717 {
12718 x_dnd_process_quit (f, FRAME_DISPLAY_INFO (f)->last_user_time);
12719 #ifdef USE_GTK
12720 current_hold_quit = NULL;
12721 #endif
12722 x_restore_events_after_dnd (f, &root_window_attrs);
12723 quit ();
12724 }
12725
12726 if (x_dnd_run_unsupported_drop_function
12727 && x_dnd_waiting_for_finish)
12728 {
12729 x_dnd_run_unsupported_drop_function = false;
12730 x_dnd_waiting_for_finish = false;
12731 x_dnd_unwind_flag = true;
12732
12733 ref = SPECPDL_INDEX ();
12734 record_unwind_protect_ptr (x_dnd_cleanup_drag_and_drop, f);
12735
12736 if (!NILP (Vx_dnd_unsupported_drop_function))
12737 val = call8 (Vx_dnd_unsupported_drop_function,
12738 XCAR (XCDR (x_dnd_unsupported_drop_data)),
12739 Fnth (make_fixnum (3), x_dnd_unsupported_drop_data),
12740 Fnth (make_fixnum (4), x_dnd_unsupported_drop_data),
12741 Fnth (make_fixnum (2), x_dnd_unsupported_drop_data),
12742 make_uint (x_dnd_unsupported_drop_window),
12743 frame, make_uint (x_dnd_unsupported_drop_time),
12744 Fcopy_sequence (XCAR (x_dnd_unsupported_drop_data)));
12745 else
12746 val = Qnil;
12747
12748 if (NILP (val))
12749 x_dnd_do_unsupported_drop (FRAME_DISPLAY_INFO (f),
12750 frame, XCAR (x_dnd_unsupported_drop_data),
12751 XCAR (XCDR (x_dnd_unsupported_drop_data)),
12752 x_dnd_unsupported_drop_window,
12753 XFIXNUM (Fnth (make_fixnum (3),
12754 x_dnd_unsupported_drop_data)),
12755 XFIXNUM (Fnth (make_fixnum (4),
12756 x_dnd_unsupported_drop_data)),
12757 x_dnd_unsupported_drop_time);
12758 else if (SYMBOLP (val))
12759 x_dnd_action_symbol = val;
12760
12761 x_dnd_unwind_flag = false;
12762 unbind_to (ref, Qnil);
12763
12764
12765
12766 break;
12767 }
12768
12769 #ifdef USE_GTK
12770 if (xg_pending_quit_event.kind != NO_EVENT)
12771 {
12772 xg_pending_quit_event.kind = NO_EVENT;
12773 current_hold_quit = NULL;
12774
12775 x_dnd_process_quit (f, FRAME_DISPLAY_INFO (f)->last_user_time);
12776 x_restore_events_after_dnd (f, &root_window_attrs);
12777 quit ();
12778 }
12779 #else
12780 }
12781 else
12782 {
12783 if (x_dnd_movement_frame)
12784 x_dnd_movement_frame = NULL;
12785
12786 if (x_dnd_wheel_frame)
12787 x_dnd_wheel_frame = NULL;
12788
12789 if (hold_quit.kind != NO_EVENT)
12790 EVENT_INIT (hold_quit);
12791 }
12792 #endif
12793 }
12794
12795 x_dnd_waiting_for_finish = false;
12796
12797 #ifdef USE_GTK
12798 current_hold_quit = NULL;
12799 #endif
12800 x_dnd_movement_frame = NULL;
12801 x_dnd_wheel_frame = NULL;
12802 x_restore_events_after_dnd (f, &root_window_attrs);
12803
12804 if (x_dnd_return_frame == 3
12805 && FRAME_LIVE_P (x_dnd_return_frame_object))
12806 {
12807
12808
12809
12810 if (x_dnd_return_frame_object != x_dnd_frame)
12811 x_dnd_return_frame_object->last_mouse_device = Qnil;
12812
12813 x_dnd_return_frame_object->mouse_moved = true;
12814
12815 XSETFRAME (action, x_dnd_return_frame_object);
12816 x_dnd_return_frame_object = NULL;
12817
12818 return unbind_to (base, action);
12819 }
12820
12821 x_dnd_return_frame_object = NULL;
12822 FRAME_DISPLAY_INFO (f)->grabbed = 0;
12823
12824 if (!NILP (x_dnd_action_symbol))
12825 return unbind_to (base, x_dnd_action_symbol);
12826
12827 if (x_dnd_action != None)
12828 {
12829 block_input ();
12830 x_catch_errors (FRAME_X_DISPLAY (f));
12831 atom_name = x_get_atom_name (FRAME_DISPLAY_INFO (f),
12832 x_dnd_action, &need_sync);
12833
12834 if (need_sync)
12835 x_uncatch_errors ();
12836 else
12837
12838
12839 x_uncatch_errors_after_check ();
12840
12841 if (atom_name)
12842 {
12843 action = intern (atom_name);
12844 xfree (atom_name);
12845 }
12846 else
12847 action = Qnil;
12848 unblock_input ();
12849
12850 return unbind_to (base, action);
12851 }
12852
12853 return unbind_to (base, Qnil);
12854 }
12855
12856 #ifdef HAVE_XINPUT2
12857
12858
12859
12860
12861
12862
12863
12864
12865
12866
12867
12868 static void
12869 xi_handle_focus_change (struct x_display_info *dpyinfo)
12870 {
12871 struct input_event ie;
12872 struct frame *focus, *new;
12873 struct xi_device_t *device, *source = NULL;
12874 ptrdiff_t i;
12875 Time time;
12876 #ifdef USE_GTK
12877 struct x_output *output;
12878 GtkWidget *widget;
12879 #endif
12880
12881 focus = dpyinfo->x_focus_frame;
12882 new = NULL;
12883 time = 0;
12884
12885 dpyinfo->client_pointer_device = -1;
12886
12887 for (i = 0; i < dpyinfo->num_devices; ++i)
12888 {
12889 device = &dpyinfo->devices[i];
12890
12891 if (device->focus_frame
12892 && device->focus_frame_time > time)
12893 {
12894 new = device->focus_frame;
12895 time = device->focus_frame_time;
12896 source = device;
12897
12898
12899
12900
12901 if (device->use == XIMasterKeyboard)
12902 dpyinfo->client_pointer_device = device->attachment;
12903 else
12904 dpyinfo->client_pointer_device = device->device_id;
12905 }
12906
12907
12908
12909 else if (device->focus_implicit_frame
12910 && device->focus_implicit_time > time)
12911 {
12912 new = device->focus_implicit_frame;
12913 time = device->focus_implicit_time;
12914 source = device;
12915
12916
12917
12918
12919 if (device->use == XIMasterKeyboard)
12920 dpyinfo->client_pointer_device = device->attachment;
12921 else
12922 dpyinfo->client_pointer_device = device->device_id;
12923 }
12924 }
12925
12926 if (new != focus && focus)
12927 {
12928 #ifdef HAVE_X_I18N
12929 if (FRAME_XIC (focus))
12930 XUnsetICFocus (FRAME_XIC (focus));
12931 #endif
12932
12933 #ifdef USE_GTK
12934 output = FRAME_X_OUTPUT (focus);
12935
12936 if (x_gtk_use_native_input)
12937 {
12938 gtk_im_context_focus_out (output->im_context);
12939 gtk_im_context_set_client_window (output->im_context,
12940 NULL);
12941 }
12942 #endif
12943
12944 EVENT_INIT (ie);
12945 ie.kind = FOCUS_OUT_EVENT;
12946 XSETFRAME (ie.frame_or_window, focus);
12947
12948 kbd_buffer_store_event (&ie);
12949 }
12950
12951 if (new != focus && new)
12952 {
12953 #ifdef HAVE_X_I18N
12954 if (FRAME_XIC (new))
12955 XSetICFocus (FRAME_XIC (new));
12956 #endif
12957
12958 #ifdef USE_GTK
12959 output = FRAME_X_OUTPUT (new);
12960
12961 if (x_gtk_use_native_input)
12962 {
12963 widget = FRAME_GTK_OUTER_WIDGET (new);
12964
12965 gtk_im_context_focus_in (output->im_context);
12966 gtk_im_context_set_client_window (output->im_context,
12967 gtk_widget_get_window (widget));
12968 }
12969 #endif
12970
12971 EVENT_INIT (ie);
12972 ie.kind = FOCUS_IN_EVENT;
12973 ie.device = source->name;
12974 XSETFRAME (ie.frame_or_window, new);
12975
12976 kbd_buffer_store_event (&ie);
12977 }
12978
12979 x_new_focus_frame (dpyinfo, new);
12980 }
12981
12982 static void
12983 xi_focus_handle_for_device (struct x_display_info *dpyinfo,
12984 struct frame *mentioned_frame,
12985 XIEvent *base_event)
12986 {
12987 struct xi_device_t *device;
12988 XIEnterEvent *event;
12989
12990
12991
12992 event = (XIEnterEvent *) base_event;
12993 device = xi_device_from_id (dpyinfo, event->deviceid);
12994
12995 if (!device)
12996 return;
12997
12998 switch (event->evtype)
12999 {
13000 case XI_FocusIn:
13001
13002
13003 x_display_set_last_user_time (dpyinfo, event->time,
13004 event->send_event, true);
13005
13006 device->focus_frame = mentioned_frame;
13007 device->focus_frame_time = event->time;
13008 break;
13009
13010 case XI_FocusOut:
13011
13012
13013 x_display_set_last_user_time (dpyinfo, event->time,
13014 event->send_event, false);
13015
13016 device->focus_frame = NULL;
13017
13018
13019
13020
13021
13022
13023
13024
13025
13026
13027
13028
13029
13030
13031
13032
13033
13034
13035 device->focus_implicit_frame = NULL;
13036 break;
13037
13038 case XI_Enter:
13039 if (!event->focus)
13040 break;
13041
13042 if (device->use == XIMasterPointer)
13043 device = xi_device_from_id (dpyinfo, device->attachment);
13044
13045 if (!device)
13046 break;
13047
13048 device->focus_implicit_frame = mentioned_frame;
13049 device->focus_implicit_time = event->time;
13050 break;
13051
13052 case XI_Leave:
13053 if (!event->focus)
13054 break;
13055
13056 if (device->use == XIMasterPointer)
13057 device = xi_device_from_id (dpyinfo, device->attachment);
13058
13059 if (!device)
13060 break;
13061
13062 device->focus_implicit_frame = NULL;
13063 break;
13064 }
13065
13066 xi_handle_focus_change (dpyinfo);
13067 }
13068
13069 static void
13070 xi_handle_delete_frame (struct x_display_info *dpyinfo,
13071 struct frame *f)
13072 {
13073 struct xi_device_t *device;
13074 ptrdiff_t i;
13075
13076 for (i = 0; i < dpyinfo->num_devices; ++i)
13077 {
13078 device = &dpyinfo->devices[i];
13079
13080 if (device->focus_frame == f)
13081 device->focus_frame = NULL;
13082
13083 if (device->focus_implicit_frame == f)
13084 device->focus_implicit_frame = NULL;
13085 }
13086 }
13087
13088
13089
13090
13091
13092 static void
13093 xi_handle_interaction (struct x_display_info *dpyinfo,
13094 struct frame *f, struct xi_device_t *device,
13095 Time time)
13096 {
13097 bool change;
13098
13099
13100 if (device->use == XIMasterPointer)
13101 device = xi_device_from_id (dpyinfo, device->attachment);
13102
13103 if (!device)
13104 return;
13105
13106 change = false;
13107
13108 if (device->focus_frame == f)
13109 {
13110 device->focus_frame_time = time;
13111 change = true;
13112 }
13113
13114 if (device->focus_implicit_frame == f)
13115 {
13116 device->focus_implicit_time = time;
13117 change = true;
13118 }
13119
13120
13121 if (change && f != dpyinfo->x_focus_frame)
13122 xi_handle_focus_change (dpyinfo);
13123 }
13124
13125
13126
13127
13128
13129
13130
13131 static bool
13132 xi_position_changed (struct xi_device_t *device, XIDeviceEvent *xev)
13133 {
13134 bool changed;
13135
13136 changed = true;
13137
13138 if (xev->event != device->last_motion_window)
13139 goto out;
13140
13141 if (lrint (xev->event_x) == device->last_motion_x
13142 && lrint (xev->event_y) == device->last_motion_y)
13143 {
13144 changed = false;
13145 goto out;
13146 }
13147
13148 out:
13149 device->last_motion_x = lrint (xev->event_x);
13150 device->last_motion_y = lrint (xev->event_y);
13151 device->last_motion_window = xev->event;
13152
13153 return changed;
13154 }
13155
13156 static void
13157 xi_report_motion_window_clear (struct xi_device_t *device)
13158 {
13159 device->last_motion_window = None;
13160 }
13161
13162 #ifdef HAVE_XINPUT2_1
13163
13164
13165
13166 static struct xi_scroll_valuator_t *
13167 xi_get_scroll_valuator (struct xi_device_t *device, int number)
13168 {
13169 int i;
13170
13171 for (i = 0; i < device->scroll_valuator_count; ++i)
13172 {
13173 if (device->valuators[i].number == number)
13174 return &device->valuators[i];
13175 }
13176
13177 return NULL;
13178 }
13179
13180
13181
13182
13183 static bool
13184 xi_has_scroll_valuators (XIDeviceChangedEvent *event)
13185 {
13186 int i;
13187
13188 for (i = 0; i < event->num_classes; ++i)
13189 {
13190 if (event->classes[i]->type == XIScrollClass)
13191 return true;
13192 }
13193
13194 return false;
13195 }
13196
13197
13198
13199
13200
13201
13202
13203
13204 static void
13205 xi_handle_new_classes (struct x_display_info *dpyinfo, struct xi_device_t *device,
13206 XIAnyClassInfo **classes, int num_classes)
13207 {
13208 XIScrollClassInfo *scroll;
13209 struct xi_scroll_valuator_t *valuator;
13210 XIValuatorClassInfo *valuator_info;
13211 int i;
13212 #ifdef HAVE_XINPUT2_2
13213 XITouchClassInfo *touch;
13214 #endif
13215
13216 if (dpyinfo->xi2_version < 1)
13217
13218
13219 return;
13220
13221 device->valuators = xnmalloc (num_classes,
13222 sizeof *device->valuators);
13223 device->scroll_valuator_count = 0;
13224 #ifdef HAVE_XINPUT2_2
13225 device->direct_p = false;
13226 #endif
13227
13228 for (i = 0; i < num_classes; ++i)
13229 {
13230 switch (classes[i]->type)
13231 {
13232 case XIScrollClass:
13233 scroll = (XIScrollClassInfo *) classes[i];
13234
13235 xi_populate_scroll_valuator (device,
13236 device->scroll_valuator_count++,
13237 scroll);
13238 break;
13239
13240 #ifdef HAVE_XINPUT2_2
13241 case XITouchClass:
13242 touch = (XITouchClassInfo *) classes[i];
13243
13244 if (touch->mode == XIDirectTouch)
13245 device->direct_p = true;
13246 break;
13247 #endif
13248 }
13249 }
13250
13251
13252
13253
13254 for (i = 0; i < num_classes; ++i)
13255 {
13256 if (classes[i]->type != XIValuatorClass)
13257 continue;
13258
13259 valuator_info = (XIValuatorClassInfo *) classes[i];
13260
13261
13262
13263
13264
13265
13266
13267 if (valuator_info->value == 0.0
13268 && valuator_info->mode != XIModeAbsolute)
13269 continue;
13270
13271 valuator = xi_get_scroll_valuator (device,
13272 valuator_info->number);
13273
13274 if (!valuator)
13275 continue;
13276
13277 valuator->invalid_p = false;
13278 valuator->current_value = valuator_info->value;
13279 valuator->emacs_value = 0;
13280
13281 break;
13282 }
13283 }
13284
13285 #endif
13286
13287
13288
13289
13290 static void
13291 xi_handle_device_changed (struct x_display_info *dpyinfo,
13292 struct xi_device_t *device,
13293 XIDeviceChangedEvent *event)
13294 {
13295 #ifdef HAVE_XINPUT2_1
13296 int ndevices;
13297 XIDeviceInfo *info;
13298 #endif
13299 #ifdef HAVE_XINPUT2_2
13300 struct xi_touch_point_t *tem, *last;
13301 #endif
13302
13303 #ifdef HAVE_XINPUT2_1
13304 if (xi_has_scroll_valuators (event))
13305
13306
13307
13308
13309
13310
13311
13312 xi_handle_new_classes (dpyinfo, device, event->classes,
13313 event->num_classes);
13314 else
13315 {
13316
13317
13318
13319
13320
13321
13322 x_catch_errors (dpyinfo->display);
13323 info = XIQueryDevice (dpyinfo->display, event->deviceid,
13324
13325
13326
13327 &ndevices);
13328 x_uncatch_errors ();
13329
13330 if (!info)
13331 return;
13332
13333
13334
13335 xi_handle_new_classes (dpyinfo, device, info->classes,
13336 info->num_classes);
13337 }
13338 #endif
13339
13340 #ifdef HAVE_XINPUT2_2
13341
13342
13343 if (!device->direct_p)
13344 {
13345 tem = device->touchpoints;
13346
13347 while (tem)
13348 {
13349 last = tem;
13350 tem = tem->next;
13351 xfree (last);
13352 }
13353
13354 device->touchpoints = NULL;
13355 }
13356 #endif
13357 }
13358
13359
13360
13361
13362
13363
13364 static void
13365 xi_disable_devices (struct x_display_info *dpyinfo,
13366 int *to_disable, int n_disabled)
13367 {
13368 struct xi_device_t *devices;
13369 int ndevices, i, j;
13370 #ifdef HAVE_XINPUT2_2
13371 struct xi_touch_point_t *tem, *last;
13372 #endif
13373
13374
13375
13376 if (!n_disabled)
13377 return;
13378
13379 ndevices = 0;
13380 devices = xzalloc (sizeof *devices * dpyinfo->num_devices);
13381
13382
13383
13384
13385
13386 for (i = 0; i < dpyinfo->num_devices; ++i)
13387 {
13388 for (j = 0; j < n_disabled; ++j)
13389 {
13390 if (to_disable[j] == dpyinfo->devices[i].device_id)
13391 {
13392 if (x_dnd_in_progress
13393
13394
13395
13396 && to_disable[j] == x_dnd_pointer_device)
13397 x_dnd_cancel_dnd_early ();
13398
13399
13400
13401 #ifdef HAVE_XINPUT2_1
13402 xfree (dpyinfo->devices[i].valuators);
13403 #endif
13404
13405
13406
13407 #ifdef HAVE_XINPUT2_2
13408 tem = dpyinfo->devices[i].touchpoints;
13409 while (tem)
13410 {
13411 last = tem;
13412 tem = tem->next;
13413 xfree (last);
13414 }
13415 #endif
13416
13417 goto out;
13418 }
13419
13420 devices[ndevices++] = dpyinfo->devices[i];
13421
13422 out:
13423 continue;
13424 }
13425 }
13426
13427
13428 xfree (dpyinfo->devices);
13429
13430 dpyinfo->devices = devices;
13431 dpyinfo->num_devices = ndevices;
13432 }
13433
13434 #endif
13435
13436
13437
13438
13439
13440
13441 static void
13442 x_detect_focus_change (struct x_display_info *dpyinfo, struct frame *frame,
13443 const XEvent *event, struct input_event *bufp)
13444 {
13445 if (!frame)
13446 return;
13447
13448 switch (event->type)
13449 {
13450 case EnterNotify:
13451 case LeaveNotify:
13452 {
13453 struct frame *focus_frame = dpyinfo->x_focus_event_frame;
13454 int focus_state
13455 = focus_frame ? focus_frame->output_data.x->focus_state : 0;
13456
13457 if (event->xcrossing.detail != NotifyInferior
13458 && event->xcrossing.focus
13459 && ! (focus_state & FOCUS_EXPLICIT))
13460 x_focus_changed ((event->type == EnterNotify ? FocusIn : FocusOut),
13461 FOCUS_IMPLICIT,
13462 dpyinfo, frame, bufp);
13463 }
13464 break;
13465
13466 case FocusIn:
13467 case FocusOut:
13468
13469
13470
13471
13472
13473
13474
13475 if (event->xfocus.mode == NotifyGrab
13476 || event->xfocus.mode == NotifyUngrab)
13477 return;
13478 x_focus_changed (event->type,
13479 (event->xfocus.detail == NotifyPointer ?
13480 FOCUS_IMPLICIT : FOCUS_EXPLICIT),
13481 dpyinfo, frame, bufp);
13482 break;
13483
13484 case ClientMessage:
13485 if (event->xclient.message_type == dpyinfo->Xatom_XEMBED)
13486 {
13487 enum xembed_message msg = event->xclient.data.l[1];
13488 x_focus_changed ((msg == XEMBED_FOCUS_IN ? FocusIn : FocusOut),
13489 FOCUS_EXPLICIT, dpyinfo, frame, bufp);
13490 }
13491 break;
13492 }
13493 }
13494
13495
13496 #if (defined USE_LUCID && defined HAVE_XINPUT2) \
13497 || (!defined USE_X_TOOLKIT && !defined USE_GTK)
13498
13499
13500 void
13501 x_mouse_leave (struct x_display_info *dpyinfo)
13502 {
13503 #if defined HAVE_XINPUT2 && !defined USE_X_TOOLKIT
13504 struct xi_device_t *device;
13505 #endif
13506 Mouse_HLInfo *hlinfo;
13507
13508 hlinfo = &dpyinfo->mouse_highlight;
13509
13510 if (hlinfo->mouse_face_mouse_frame)
13511 {
13512 clear_mouse_face (hlinfo);
13513 hlinfo->mouse_face_mouse_frame = NULL;
13514 }
13515
13516 #if defined HAVE_XINPUT2 && !defined USE_X_TOOLKIT
13517 if (!dpyinfo->supports_xi2)
13518
13519
13520
13521
13522
13523
13524 #endif
13525 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
13526 #if defined HAVE_XINPUT2 && !defined USE_X_TOOLKIT
13527 else
13528 {
13529 if (dpyinfo->client_pointer_device == -1)
13530
13531
13532 return;
13533
13534 device = xi_device_from_id (dpyinfo, dpyinfo->client_pointer_device);
13535
13536 if (device && device->focus_implicit_frame)
13537 {
13538 device->focus_implicit_frame = NULL;
13539
13540
13541 xi_handle_focus_change (dpyinfo);
13542 }
13543 }
13544 #endif
13545 }
13546 #endif
13547
13548
13549
13550
13551
13552
13553
13554
13555
13556 static void
13557 XTframe_rehighlight (struct frame *frame)
13558 {
13559 x_frame_rehighlight (FRAME_DISPLAY_INFO (frame));
13560 }
13561
13562 static void
13563 x_frame_rehighlight (struct x_display_info *dpyinfo)
13564 {
13565 struct frame *old_highlight = dpyinfo->highlight_frame;
13566
13567 if (dpyinfo->x_focus_frame)
13568 {
13569 dpyinfo->highlight_frame
13570 = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
13571 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
13572 : dpyinfo->x_focus_frame);
13573 if (! FRAME_LIVE_P (dpyinfo->highlight_frame))
13574 {
13575 fset_focus_frame (dpyinfo->x_focus_frame, Qnil);
13576 dpyinfo->highlight_frame = dpyinfo->x_focus_frame;
13577 }
13578 }
13579 else
13580 dpyinfo->highlight_frame = 0;
13581
13582 if (dpyinfo->highlight_frame != old_highlight)
13583 {
13584 if (old_highlight)
13585 x_frame_unhighlight (old_highlight);
13586 if (dpyinfo->highlight_frame)
13587 x_frame_highlight (dpyinfo->highlight_frame);
13588 }
13589 }
13590
13591
13592
13593
13594
13595
13596 static void
13597 x_find_modifier_meanings (struct x_display_info *dpyinfo)
13598 {
13599 int min_code, max_code;
13600 KeySym *syms;
13601 int syms_per_code;
13602 XModifierKeymap *mods;
13603 #ifdef HAVE_XKB
13604 int i;
13605 int found_meta_p = false;
13606 unsigned int vmodmask;
13607 #endif
13608
13609 dpyinfo->meta_mod_mask = 0;
13610 dpyinfo->shift_lock_mask = 0;
13611 dpyinfo->alt_mod_mask = 0;
13612 dpyinfo->super_mod_mask = 0;
13613 dpyinfo->hyper_mod_mask = 0;
13614
13615 #ifdef HAVE_XKB
13616 if (dpyinfo->xkb_desc
13617 && dpyinfo->xkb_desc->server)
13618 {
13619 for (i = 0; i < XkbNumVirtualMods; i++)
13620 {
13621 vmodmask = dpyinfo->xkb_desc->server->vmods[i];
13622
13623 if (dpyinfo->xkb_desc->names->vmods[i] == dpyinfo->Xatom_Meta)
13624 {
13625 dpyinfo->meta_mod_mask |= vmodmask;
13626
13627 if (vmodmask)
13628 found_meta_p = true;
13629 }
13630 else if (dpyinfo->xkb_desc->names->vmods[i] == dpyinfo->Xatom_Alt)
13631 dpyinfo->alt_mod_mask |= vmodmask;
13632 else if (dpyinfo->xkb_desc->names->vmods[i] == dpyinfo->Xatom_Super)
13633 dpyinfo->super_mod_mask |= vmodmask;
13634 else if (dpyinfo->xkb_desc->names->vmods[i] == dpyinfo->Xatom_Hyper)
13635 dpyinfo->hyper_mod_mask |= vmodmask;
13636 else if (dpyinfo->xkb_desc->names->vmods[i] == dpyinfo->Xatom_ShiftLock)
13637 dpyinfo->shift_lock_mask |= vmodmask;
13638 }
13639
13640 if (!found_meta_p)
13641 {
13642 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
13643 dpyinfo->alt_mod_mask = 0;
13644 }
13645
13646 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
13647 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
13648
13649 if (dpyinfo->hyper_mod_mask & dpyinfo->super_mod_mask)
13650 dpyinfo->hyper_mod_mask &= ~dpyinfo->super_mod_mask;
13651
13652 return;
13653 }
13654 #endif
13655
13656 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
13657
13658 syms = XGetKeyboardMapping (dpyinfo->display,
13659 min_code, max_code - min_code + 1,
13660 &syms_per_code);
13661
13662 if (!syms)
13663 {
13664 dpyinfo->meta_mod_mask = Mod1Mask;
13665 dpyinfo->super_mod_mask = Mod2Mask;
13666 return;
13667 }
13668
13669 mods = XGetModifierMapping (dpyinfo->display);
13670
13671
13672
13673 {
13674 int row, col;
13675 bool found_alt_or_meta;
13676
13677 for (row = 3; row < 8; row++)
13678 {
13679 found_alt_or_meta = false;
13680 for (col = 0; col < mods->max_keypermod; col++)
13681 {
13682 KeyCode code = mods->modifiermap[(row * mods->max_keypermod) + col];
13683
13684
13685 if (code == 0)
13686 continue;
13687
13688
13689 {
13690 int code_col;
13691
13692 for (code_col = 0; code_col < syms_per_code; code_col++)
13693 {
13694 int sym = syms[((code - min_code) * syms_per_code) + code_col];
13695
13696 switch (sym)
13697 {
13698 case XK_Meta_L:
13699 case XK_Meta_R:
13700 found_alt_or_meta = true;
13701 dpyinfo->meta_mod_mask |= (1 << row);
13702 break;
13703
13704 case XK_Alt_L:
13705 case XK_Alt_R:
13706 found_alt_or_meta = true;
13707 dpyinfo->alt_mod_mask |= (1 << row);
13708 break;
13709
13710 case XK_Hyper_L:
13711 case XK_Hyper_R:
13712 if (!found_alt_or_meta)
13713 dpyinfo->hyper_mod_mask |= (1 << row);
13714 code_col = syms_per_code;
13715 col = mods->max_keypermod;
13716 break;
13717
13718 case XK_Super_L:
13719 case XK_Super_R:
13720 if (!found_alt_or_meta)
13721 dpyinfo->super_mod_mask |= (1 << row);
13722 code_col = syms_per_code;
13723 col = mods->max_keypermod;
13724 break;
13725
13726 case XK_Shift_Lock:
13727
13728 if (!found_alt_or_meta && ((1 << row) == LockMask))
13729 dpyinfo->shift_lock_mask = LockMask;
13730 code_col = syms_per_code;
13731 col = mods->max_keypermod;
13732 break;
13733 }
13734 }
13735 }
13736 }
13737 }
13738 }
13739
13740
13741 if (! dpyinfo->meta_mod_mask)
13742 {
13743 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
13744 dpyinfo->alt_mod_mask = 0;
13745 }
13746
13747
13748
13749 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
13750 {
13751 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
13752 }
13753
13754
13755
13756
13757 if (dpyinfo->hyper_mod_mask & dpyinfo->super_mod_mask)
13758 dpyinfo->hyper_mod_mask &= ~dpyinfo->super_mod_mask;
13759
13760 XFree (syms);
13761
13762 if (dpyinfo->modmap)
13763 XFreeModifiermap (dpyinfo->modmap);
13764 dpyinfo->modmap = mods;
13765 }
13766
13767
13768
13769
13770 int
13771 x_x_to_emacs_modifiers (struct x_display_info *dpyinfo, int state)
13772 {
13773 int mod_ctrl = ctrl_modifier;
13774 int mod_meta = meta_modifier;
13775 int mod_alt = alt_modifier;
13776 int mod_hyper = hyper_modifier;
13777 int mod_super = super_modifier;
13778 Lisp_Object tem;
13779
13780 tem = Fget (Vx_ctrl_keysym, Qmodifier_value);
13781 if (FIXNUMP (tem)) mod_ctrl = XFIXNUM (tem) & INT_MAX;
13782 tem = Fget (Vx_alt_keysym, Qmodifier_value);
13783 if (FIXNUMP (tem)) mod_alt = XFIXNUM (tem) & INT_MAX;
13784 tem = Fget (Vx_meta_keysym, Qmodifier_value);
13785 if (FIXNUMP (tem)) mod_meta = XFIXNUM (tem) & INT_MAX;
13786 tem = Fget (Vx_hyper_keysym, Qmodifier_value);
13787 if (FIXNUMP (tem)) mod_hyper = XFIXNUM (tem) & INT_MAX;
13788 tem = Fget (Vx_super_keysym, Qmodifier_value);
13789 if (FIXNUMP (tem)) mod_super = XFIXNUM (tem) & INT_MAX;
13790
13791 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
13792 | ((state & ControlMask) ? mod_ctrl : 0)
13793 | ((state & dpyinfo->meta_mod_mask) ? mod_meta : 0)
13794 | ((state & dpyinfo->alt_mod_mask) ? mod_alt : 0)
13795 | ((state & dpyinfo->super_mod_mask) ? mod_super : 0)
13796 | ((state & dpyinfo->hyper_mod_mask) ? mod_hyper : 0));
13797 }
13798
13799 int
13800 x_emacs_to_x_modifiers (struct x_display_info *dpyinfo, intmax_t state)
13801 {
13802 EMACS_INT mod_ctrl = ctrl_modifier;
13803 EMACS_INT mod_meta = meta_modifier;
13804 EMACS_INT mod_alt = alt_modifier;
13805 EMACS_INT mod_hyper = hyper_modifier;
13806 EMACS_INT mod_super = super_modifier;
13807
13808 Lisp_Object tem;
13809
13810 tem = Fget (Vx_ctrl_keysym, Qmodifier_value);
13811 if (FIXNUMP (tem)) mod_ctrl = XFIXNUM (tem);
13812 tem = Fget (Vx_alt_keysym, Qmodifier_value);
13813 if (FIXNUMP (tem)) mod_alt = XFIXNUM (tem);
13814 tem = Fget (Vx_meta_keysym, Qmodifier_value);
13815 if (FIXNUMP (tem)) mod_meta = XFIXNUM (tem);
13816 tem = Fget (Vx_hyper_keysym, Qmodifier_value);
13817 if (FIXNUMP (tem)) mod_hyper = XFIXNUM (tem);
13818 tem = Fget (Vx_super_keysym, Qmodifier_value);
13819 if (FIXNUMP (tem)) mod_super = XFIXNUM (tem);
13820
13821
13822 return ( ((state & mod_alt) ? dpyinfo->alt_mod_mask : 0)
13823 | ((state & mod_super) ? dpyinfo->super_mod_mask : 0)
13824 | ((state & mod_hyper) ? dpyinfo->hyper_mod_mask : 0)
13825 | ((state & shift_modifier) ? ShiftMask : 0)
13826 | ((state & mod_ctrl) ? ControlMask : 0)
13827 | ((state & mod_meta) ? dpyinfo->meta_mod_mask : 0));
13828 }
13829
13830
13831
13832 char *
13833 get_keysym_name (int keysym)
13834 {
13835 char *value;
13836
13837 block_input ();
13838 value = XKeysymToString (keysym);
13839 unblock_input ();
13840
13841 return value;
13842 }
13843
13844
13845
13846
13847
13848
13849
13850 static void
13851 x_compute_root_window_offset (struct frame *f, int root_x, int root_y,
13852 int event_x, int event_y)
13853 {
13854 FRAME_X_OUTPUT (f)->window_offset_certain_p = true;
13855 FRAME_X_OUTPUT (f)->root_x = root_x - event_x;
13856 FRAME_X_OUTPUT (f)->root_y = root_y - event_y;
13857 }
13858
13859
13860
13861
13862
13863
13864
13865 void
13866 x_translate_coordinates (struct frame *f, int root_x, int root_y,
13867 int *x_out, int *y_out)
13868 {
13869 struct x_output *output;
13870 Window dummy;
13871
13872 output = FRAME_X_OUTPUT (f);
13873
13874 if (output->window_offset_certain_p)
13875 {
13876
13877 *x_out = root_x - output->root_x;
13878 *y_out = root_y - output->root_y;
13879
13880 return;
13881 }
13882
13883
13884
13885 if (!XTranslateCoordinates (FRAME_X_DISPLAY (f),
13886 FRAME_DISPLAY_INFO (f)->root_window,
13887 FRAME_X_WINDOW (f), root_x, root_y,
13888 x_out, y_out, &dummy))
13889
13890
13891 *x_out = 0, *y_out = 0;
13892 else
13893 {
13894
13895 output->window_offset_certain_p = true;
13896 output->root_x = root_x - *x_out;
13897 output->root_y = root_y - *y_out;
13898 }
13899 }
13900
13901
13902
13903
13904
13905 void
13906 x_translate_coordinates_to_root (struct frame *f, int x, int y,
13907 int *x_out, int *y_out)
13908 {
13909 struct x_output *output;
13910 Window dummy;
13911
13912 output = FRAME_X_OUTPUT (f);
13913
13914 if (output->window_offset_certain_p)
13915 {
13916
13917 *x_out = x + output->root_x;
13918 *y_out = y + output->root_y;
13919
13920 return;
13921 }
13922
13923
13924
13925 if (!XTranslateCoordinates (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
13926 FRAME_DISPLAY_INFO (f)->root_window,
13927 x, y, x_out, y_out, &dummy))
13928 *x_out = 0, *y_out = 0;
13929 else
13930 {
13931
13932 output->window_offset_certain_p = true;
13933 output->root_x = *x_out - x;
13934 output->root_y = *y_out - y;
13935 }
13936 }
13937
13938
13939
13940
13941
13942 Lisp_Object
13943 x_handle_translate_coordinates (struct frame *f, Lisp_Object dest_window,
13944 int source_x, int source_y)
13945 {
13946 if (NILP (dest_window))
13947 {
13948
13949
13950
13951
13952 if (!FRAME_X_OUTPUT (f)->window_offset_certain_p)
13953 return Qnil;
13954
13955 return list3 (make_fixnum (source_x + FRAME_X_OUTPUT (f)->root_x),
13956 make_fixnum (source_y + FRAME_X_OUTPUT (f)->root_y),
13957 Qnil);
13958 }
13959
13960 return Qnil;
13961 }
13962
13963
13964
13965 #ifdef HAVE_XINPUT2
13966
13967 static void
13968 xi_compute_root_window_offset (struct frame *f, XIDeviceEvent *xev)
13969 {
13970
13971
13972 x_compute_root_window_offset (f, xev->root_x, xev->root_y,
13973 xev->event_x, xev->event_y);
13974 }
13975
13976 static void
13977 xi_compute_root_window_offset_enter (struct frame *f, XIEnterEvent *enter)
13978 {
13979 x_compute_root_window_offset (f, enter->root_x, enter->root_y,
13980 enter->event_x, enter->event_y);
13981 }
13982
13983 #ifdef HAVE_XINPUT2_4
13984
13985 static void
13986 xi_compute_root_window_offset_pinch (struct frame *f, XIGesturePinchEvent *pev)
13987 {
13988
13989
13990 x_compute_root_window_offset (f, pev->root_x, pev->root_y,
13991 pev->event_x, pev->event_y);
13992 }
13993
13994 #endif
13995
13996 #endif
13997
13998 static Bool
13999 x_query_pointer_1 (struct x_display_info *dpyinfo,
14000 int client_pointer_device, Window w,
14001 Window *root_return, Window *child_return,
14002 int *root_x_return, int *root_y_return,
14003 int *win_x_return, int *win_y_return,
14004 unsigned int *mask_return)
14005 {
14006 Bool rc;
14007 Display *dpy;
14008 #ifdef HAVE_XINPUT2
14009 bool had_errors;
14010 XIModifierState modifiers;
14011 XIButtonState buttons;
14012 XIGroupState group;
14013 double root_x, root_y, win_x, win_y;
14014 unsigned int state;
14015 #endif
14016
14017 dpy = dpyinfo->display;
14018
14019 #ifdef HAVE_XINPUT2
14020 if (client_pointer_device != -1)
14021 {
14022
14023
14024 x_catch_errors (dpy);
14025 rc = XIQueryPointer (dpyinfo->display,
14026 dpyinfo->client_pointer_device,
14027 w, root_return, child_return,
14028 &root_x, &root_y, &win_x, &win_y,
14029 &buttons, &modifiers, &group);
14030 had_errors = x_had_errors_p (dpy);
14031 x_uncatch_errors_after_check ();
14032
14033 if (had_errors)
14034 {
14035
14036
14037
14038
14039
14040 if (client_pointer_device == dpyinfo->client_pointer_device)
14041 dpyinfo->client_pointer_device = -1;
14042
14043 rc = XQueryPointer (dpyinfo->display, w, root_return,
14044 child_return, root_x_return,
14045 root_y_return, win_x_return,
14046 win_y_return, mask_return);
14047 }
14048 else
14049 {
14050 state = 0;
14051
14052 xi_convert_button_state (&buttons, &state);
14053 *mask_return = state | modifiers.effective;
14054
14055 XFree (buttons.mask);
14056
14057 *root_x_return = lrint (root_x);
14058 *root_y_return = lrint (root_y);
14059 *win_x_return = lrint (win_x);
14060 *win_y_return = lrint (win_y);
14061 }
14062 }
14063 else
14064 #endif
14065 rc = XQueryPointer (dpy, w, root_return, child_return,
14066 root_x_return, root_y_return, win_x_return,
14067 win_y_return, mask_return);
14068
14069 return rc;
14070 }
14071
14072 Bool
14073 x_query_pointer (Display *dpy, Window w, Window *root_return,
14074 Window *child_return, int *root_x_return,
14075 int *root_y_return, int *win_x_return,
14076 int *win_y_return, unsigned int *mask_return)
14077 {
14078 struct x_display_info *dpyinfo;
14079
14080 dpyinfo = x_display_info_for_display (dpy);
14081
14082 if (!dpyinfo)
14083 emacs_abort ();
14084
14085 #ifdef HAVE_XINPUT2
14086 return x_query_pointer_1 (dpyinfo, dpyinfo->client_pointer_device,
14087 w, root_return, child_return, root_x_return,
14088 root_y_return, win_x_return, win_y_return,
14089 mask_return);
14090 #else
14091 return x_query_pointer_1 (dpyinfo, -1, w, root_return, child_return,
14092 root_x_return, root_y_return, win_x_return,
14093 win_y_return, mask_return);
14094 #endif
14095 }
14096
14097
14098
14099
14100
14101
14102
14103
14104
14105
14106
14107
14108
14109
14110
14111
14112
14113
14114
14115
14116
14117
14118
14119
14120
14121
14122
14123
14124
14125
14126
14127
14128
14129
14130
14131 static Lisp_Object
14132 x_construct_mouse_click (struct input_event *result,
14133 const XButtonEvent *event,
14134 struct frame *f)
14135 {
14136 int x = event->x;
14137 int y = event->y;
14138
14139
14140
14141 result->kind = MOUSE_CLICK_EVENT;
14142 result->code = event->button - Button1;
14143 result->timestamp = event->time;
14144 result->modifiers = (x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO (f),
14145 event->state)
14146 | (event->type == ButtonRelease
14147 ? up_modifier
14148 : down_modifier));
14149
14150
14151
14152
14153 if (event->window != FRAME_X_WINDOW (f))
14154 x_translate_coordinates (f, event->x_root, event->y_root,
14155 &x, &y);
14156
14157 XSETINT (result->x, x);
14158 XSETINT (result->y, y);
14159 XSETFRAME (result->frame_or_window, f);
14160 result->arg = Qnil;
14161 return Qnil;
14162 }
14163
14164
14165
14166
14167
14168
14169
14170
14171
14172
14173
14174
14175
14176
14177
14178
14179
14180
14181 static bool
14182 x_note_mouse_movement (struct frame *frame, const XMotionEvent *event,
14183 Lisp_Object device)
14184 {
14185 XRectangle *r;
14186 struct x_display_info *dpyinfo;
14187
14188 if (!FRAME_X_OUTPUT (frame))
14189 return false;
14190
14191 dpyinfo = FRAME_DISPLAY_INFO (frame);
14192 dpyinfo->last_mouse_movement_time = event->time;
14193 dpyinfo->last_mouse_movement_time_send_event = event->send_event;
14194 dpyinfo->last_mouse_motion_frame = frame;
14195 dpyinfo->last_mouse_motion_x = event->x;
14196 dpyinfo->last_mouse_motion_y = event->y;
14197
14198 if (event->window != FRAME_X_WINDOW (frame))
14199 {
14200 frame->mouse_moved = true;
14201 frame->last_mouse_device = device;
14202 dpyinfo->last_mouse_scroll_bar = NULL;
14203 note_mouse_highlight (frame, -1, -1);
14204 dpyinfo->last_mouse_glyph_frame = NULL;
14205 return true;
14206 }
14207
14208
14209
14210 r = &dpyinfo->last_mouse_glyph;
14211 if (frame != dpyinfo->last_mouse_glyph_frame
14212 || event->x < r->x || event->x >= r->x + r->width
14213 || event->y < r->y || event->y >= r->y + r->height)
14214 {
14215 frame->mouse_moved = true;
14216 frame->last_mouse_device = device;
14217 dpyinfo->last_mouse_scroll_bar = NULL;
14218 note_mouse_highlight (frame, event->x, event->y);
14219
14220 remember_mouse_glyph (frame, event->x, event->y, r);
14221 dpyinfo->last_mouse_glyph_frame = frame;
14222 return true;
14223 }
14224
14225 return false;
14226 }
14227
14228
14229 static Window
14230 x_get_window_below (Display *dpy, Window window,
14231 int parent_x, int parent_y,
14232 int *inner_x, int *inner_y)
14233 {
14234 int rc, i, cx, cy;
14235 XWindowAttributes attrs;
14236 unsigned int nchildren;
14237 Window root, parent, *children, value;
14238 bool window_seen;
14239
14240
14241
14242 children = NULL;
14243 window_seen = false;
14244 value = None;
14245
14246 rc = XQueryTree (dpy, window, &root, &parent,
14247 &children, &nchildren);
14248
14249 if (rc)
14250 {
14251 if (children)
14252 XFree (children);
14253
14254 rc = XQueryTree (dpy, parent, &root,
14255 &parent, &children, &nchildren);
14256 }
14257
14258 if (rc)
14259 {
14260 for (i = nchildren - 1; i >= 0; --i)
14261 {
14262 if (children[i] == window)
14263 {
14264 window_seen = true;
14265 continue;
14266 }
14267
14268 if (!window_seen)
14269 continue;
14270
14271 rc = XGetWindowAttributes (dpy, children[i], &attrs);
14272
14273 if (rc && attrs.map_state != IsViewable)
14274 continue;
14275
14276 if (rc && parent_x >= attrs.x
14277 && parent_y >= attrs.y
14278 && parent_x < attrs.x + attrs.width
14279 && parent_y < attrs.y + attrs.height)
14280 {
14281 value = children[i];
14282 cx = parent_x - attrs.x;
14283 cy = parent_y - attrs.y;
14284
14285 break;
14286 }
14287 }
14288 }
14289
14290 if (children)
14291 XFree (children);
14292
14293 if (value)
14294 {
14295 *inner_x = cx;
14296 *inner_y = cy;
14297 }
14298
14299 return value;
14300 }
14301
14302
14303
14304 static void
14305 x_fast_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
14306 enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
14307 Time *timestamp)
14308 {
14309 int root_x, root_y, win_x, win_y;
14310 unsigned int mask;
14311 Window dummy;
14312 struct scroll_bar *bar;
14313 struct x_display_info *dpyinfo;
14314 Lisp_Object tail, frame;
14315 struct frame *f1;
14316
14317 dpyinfo = FRAME_DISPLAY_INFO (*fp);
14318
14319 if (dpyinfo->last_mouse_scroll_bar && !insist)
14320 {
14321 bar = dpyinfo->last_mouse_scroll_bar;
14322
14323 if (bar->horizontal)
14324 x_horizontal_scroll_bar_report_motion (fp, bar_window, part,
14325 x, y, timestamp);
14326 else
14327 x_scroll_bar_report_motion (fp, bar_window, part,
14328 x, y, timestamp);
14329
14330 return;
14331 }
14332
14333 if (!EQ (Vx_use_fast_mouse_position, Qreally_fast))
14334 {
14335
14336
14337
14338
14339
14340
14341 FOR_EACH_FRAME (tail, frame)
14342 {
14343 if (FRAME_X_P (XFRAME (frame))
14344 && (FRAME_DISPLAY_INFO (XFRAME (frame))
14345 == dpyinfo))
14346 XFRAME (frame)->mouse_moved = false;
14347 }
14348
14349 if (gui_mouse_grabbed (dpyinfo)
14350 && !EQ (track_mouse, Qdropping)
14351 && !EQ (track_mouse, Qdrag_source))
14352
14353 f1 = dpyinfo->last_mouse_frame;
14354 else
14355
14356 f1 = dpyinfo->last_mouse_motion_frame;
14357
14358 if (!f1 && (FRAME_X_P (SELECTED_FRAME ())
14359 && (FRAME_DISPLAY_INFO (SELECTED_FRAME ())
14360 == dpyinfo)))
14361 f1 = SELECTED_FRAME ();
14362
14363 if (!f1 || (!FRAME_X_P (f1) && (insist > 0)))
14364 FOR_EACH_FRAME (tail, frame)
14365 if (FRAME_X_P (XFRAME (frame))
14366 && (FRAME_DISPLAY_INFO (XFRAME (frame))
14367 == dpyinfo)
14368 && !FRAME_TOOLTIP_P (XFRAME (frame)))
14369 f1 = XFRAME (frame);
14370
14371 if (f1 && FRAME_TOOLTIP_P (f1))
14372 f1 = NULL;
14373
14374 if (f1 && FRAME_X_P (f1) && FRAME_X_WINDOW (f1))
14375 {
14376 if (!x_query_pointer (dpyinfo->display, FRAME_X_WINDOW (f1),
14377 &dummy, &dummy, &root_x, &root_y,
14378 &win_x, &win_y, &mask))
14379
14380 return;
14381
14382 remember_mouse_glyph (f1, win_x, win_y,
14383 &dpyinfo->last_mouse_glyph);
14384 dpyinfo->last_mouse_glyph_frame = f1;
14385
14386 *bar_window = Qnil;
14387 *part = scroll_bar_nowhere;
14388
14389
14390
14391
14392 if (EQ (track_mouse, Qdrag_source)
14393 && (win_x < 0 || win_y < 0
14394 || win_x >= FRAME_PIXEL_WIDTH (f1)
14395 || win_y >= FRAME_PIXEL_HEIGHT (f1)))
14396 *fp = NULL;
14397 else
14398 *fp = f1;
14399
14400 *timestamp = dpyinfo->last_mouse_movement_time;
14401 XSETINT (*x, win_x);
14402 XSETINT (*y, win_y);
14403 }
14404 }
14405 else
14406 {
14407
14408
14409
14410 if (dpyinfo->last_mouse_motion_frame)
14411 {
14412 *fp = dpyinfo->last_mouse_motion_frame;
14413 *timestamp = dpyinfo->last_mouse_movement_time;
14414 *x = make_fixnum (dpyinfo->last_mouse_motion_x);
14415 *y = make_fixnum (dpyinfo->last_mouse_motion_y);
14416 *bar_window = Qnil;
14417 *part = scroll_bar_nowhere;
14418
14419 FOR_EACH_FRAME (tail, frame)
14420 {
14421 if (FRAME_X_P (XFRAME (frame))
14422 && (FRAME_DISPLAY_INFO (XFRAME (frame))
14423 == dpyinfo))
14424 XFRAME (frame)->mouse_moved = false;
14425 }
14426
14427 dpyinfo->last_mouse_motion_frame->mouse_moved = false;
14428 }
14429 }
14430 }
14431
14432
14433
14434
14435
14436
14437
14438
14439
14440
14441
14442
14443
14444
14445
14446
14447
14448
14449
14450
14451
14452 static void
14453 XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
14454 enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
14455 Time *timestamp)
14456 {
14457 struct frame *f1, *maybe_tooltip;
14458 struct x_display_info *dpyinfo;
14459 bool unrelated_tooltip;
14460
14461 dpyinfo = FRAME_DISPLAY_INFO (*fp);
14462
14463 if (!NILP (Vx_use_fast_mouse_position))
14464 {
14465
14466
14467
14468
14469
14470
14471
14472
14473
14474 x_fast_mouse_position (fp, insist, bar_window, part, x,
14475 y, timestamp);
14476 return;
14477 }
14478
14479 block_input ();
14480
14481 if (dpyinfo->last_mouse_scroll_bar && insist == 0)
14482 {
14483 struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar;
14484
14485 if (bar->horizontal)
14486 x_horizontal_scroll_bar_report_motion (fp, bar_window, part, x, y, timestamp);
14487 else
14488 x_scroll_bar_report_motion (fp, bar_window, part, x, y, timestamp);
14489 }
14490 else
14491 {
14492 Window root;
14493 int root_x, root_y;
14494
14495 Window dummy_window;
14496 int dummy;
14497
14498 Lisp_Object frame, tail;
14499
14500
14501 FOR_EACH_FRAME (tail, frame)
14502 if (FRAME_X_P (XFRAME (frame))
14503 && FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
14504 XFRAME (frame)->mouse_moved = false;
14505
14506 dpyinfo->last_mouse_scroll_bar = NULL;
14507
14508
14509 x_query_pointer (FRAME_X_DISPLAY (*fp),
14510 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
14511
14512 &root,
14513
14514
14515 &dummy_window,
14516
14517 &root_x, &root_y,
14518
14519 &dummy, &dummy,
14520
14521
14522 (unsigned int *) &dummy);
14523
14524
14525
14526 {
14527 Window win, child;
14528 #ifdef USE_GTK
14529 Window first_win = 0;
14530 #endif
14531 int win_x, win_y;
14532 int parent_x, parent_y;
14533
14534 win = root;
14535 parent_x = root_x;
14536 parent_y = root_y;
14537
14538
14539
14540
14541
14542 x_catch_errors (FRAME_X_DISPLAY (*fp));
14543
14544 if (gui_mouse_grabbed (dpyinfo) && !EQ (track_mouse, Qdropping)
14545 && !EQ (track_mouse, Qdrag_source))
14546 {
14547
14548
14549 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
14550
14551 root,
14552
14553 FRAME_X_WINDOW (dpyinfo->last_mouse_frame),
14554
14555 root_x, root_y, &win_x, &win_y,
14556
14557 &child);
14558 f1 = dpyinfo->last_mouse_frame;
14559 }
14560 else
14561 {
14562 while (true)
14563 {
14564 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
14565
14566 root, win,
14567
14568 root_x, root_y, &win_x, &win_y,
14569
14570 &child);
14571
14572
14573
14574 if (child != None
14575 && (EQ (track_mouse, Qdrag_source)
14576 || EQ (track_mouse, Qdropping)))
14577 {
14578 maybe_tooltip = x_tooltip_window_to_frame (dpyinfo, child,
14579 &unrelated_tooltip);
14580
14581 if (maybe_tooltip || unrelated_tooltip)
14582 child = x_get_window_below (dpyinfo->display, child,
14583 parent_x, parent_y, &win_x,
14584 &win_y);
14585 }
14586
14587 if (child == None || child == win)
14588 {
14589 #ifdef USE_GTK
14590
14591
14592 struct frame *f = x_window_to_frame (dpyinfo, win);
14593
14594 if (f && FRAME_PARENT_FRAME (f))
14595 first_win = win;
14596 #endif
14597 break;
14598 }
14599 #ifdef USE_GTK
14600
14601
14602
14603
14604 if (x_window_to_frame (dpyinfo, win))
14605
14606
14607 first_win = win;
14608 #endif
14609 win = child;
14610 parent_x = win_x;
14611 parent_y = win_y;
14612 }
14613
14614 #ifdef USE_GTK
14615 if (first_win)
14616 win = first_win;
14617 #endif
14618
14619
14620
14621
14622
14623
14624
14625
14626
14627
14628
14629
14630 #ifdef USE_GTK
14631
14632
14633 f1 = x_window_to_frame (dpyinfo, win);
14634 #else
14635
14636 f1 = x_any_window_to_frame (dpyinfo, win);
14637 #endif
14638
14639 #ifdef USE_X_TOOLKIT
14640
14641
14642 if (f1 != NULL
14643 && f1->output_data.x->menubar_widget
14644 && win == XtWindow (f1->output_data.x->menubar_widget))
14645 f1 = NULL;
14646 #endif
14647 }
14648
14649
14650
14651
14652 if ((EQ (track_mouse, Qdrag_source)
14653 || EQ (track_mouse, Qdropping))
14654 && (dpyinfo->last_user_time
14655 < dpyinfo->last_mouse_movement_time))
14656 x_display_set_last_user_time (dpyinfo,
14657 dpyinfo->last_mouse_movement_time,
14658 dpyinfo->last_mouse_movement_time_send_event,
14659 true);
14660
14661 if ((!f1 || FRAME_TOOLTIP_P (f1))
14662 && (EQ (track_mouse, Qdropping)
14663 || EQ (track_mouse, Qdrag_source))
14664 && gui_mouse_grabbed (dpyinfo))
14665 {
14666
14667
14668
14669
14670 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
14671
14672 root,
14673
14674 FRAME_X_WINDOW (dpyinfo->last_mouse_frame),
14675
14676 root_x, root_y, &win_x, &win_y,
14677
14678 &child);
14679
14680 if (!EQ (track_mouse, Qdrag_source)
14681
14682 || (f1 && FRAME_TOOLTIP_P (f1)))
14683 f1 = dpyinfo->last_mouse_frame;
14684 else
14685 {
14686
14687
14688
14689 *bar_window = Qnil;
14690 *part = 0;
14691 *fp = NULL;
14692 XSETINT (*x, win_x);
14693 XSETINT (*y, win_y);
14694 *timestamp = dpyinfo->last_mouse_movement_time;
14695 }
14696 }
14697 else if (f1 && FRAME_TOOLTIP_P (f1))
14698 f1 = NULL;
14699
14700 if (x_had_errors_p (dpyinfo->display))
14701 f1 = NULL;
14702
14703 x_uncatch_errors_after_check ();
14704
14705
14706 if (!f1)
14707 {
14708 struct scroll_bar *bar;
14709
14710 bar = x_window_to_scroll_bar (dpyinfo->display, win, 2);
14711
14712 if (bar)
14713 {
14714 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
14715 win_x = parent_x;
14716 win_y = parent_y;
14717 }
14718 }
14719
14720 if (!f1 && insist > 0)
14721 f1 = SELECTED_FRAME ();
14722
14723 if (f1 && FRAME_X_P (f1))
14724 {
14725
14726
14727
14728
14729
14730
14731
14732
14733 dpyinfo = FRAME_DISPLAY_INFO (f1);
14734 remember_mouse_glyph (f1, win_x, win_y, &dpyinfo->last_mouse_glyph);
14735 dpyinfo->last_mouse_glyph_frame = f1;
14736
14737 *bar_window = Qnil;
14738 *part = 0;
14739 *fp = f1;
14740 XSETINT (*x, win_x);
14741 XSETINT (*y, win_y);
14742 *timestamp = dpyinfo->last_mouse_movement_time;
14743 }
14744 }
14745 }
14746
14747 unblock_input ();
14748 }
14749
14750
14751
14752
14753
14754
14755
14756
14757
14758 #if defined HAVE_XINPUT2
14759
14760
14761
14762
14763
14764 MAYBE_UNUSED static void
14765 xi_select_scroll_bar_events (struct x_display_info *dpyinfo,
14766 Window scroll_bar)
14767 {
14768 XIEventMask mask;
14769 unsigned char *m;
14770 ptrdiff_t length;
14771
14772 length = XIMaskLen (XI_LASTEVENT);
14773 mask.mask = m = alloca (length);
14774 memset (m, 0, length);
14775 mask.mask_len = length;
14776
14777 mask.deviceid = XIAllMasterDevices;
14778 XISetMask (m, XI_ButtonPress);
14779 XISetMask (m, XI_ButtonRelease);
14780 XISetMask (m, XI_Motion);
14781 XISetMask (m, XI_Enter);
14782 XISetMask (m, XI_Leave);
14783
14784 XISelectEvents (dpyinfo->display, scroll_bar, &mask, 1);
14785 }
14786
14787 #endif
14788
14789
14790
14791
14792
14793
14794 static struct scroll_bar *
14795 x_window_to_scroll_bar (Display *display, Window window_id, int type)
14796 {
14797 Lisp_Object tail, frame;
14798
14799 #if defined (USE_GTK) && !defined (HAVE_GTK3) && defined (USE_TOOLKIT_SCROLL_BARS)
14800 window_id = (Window) xg_get_scroll_id_for_window (display, window_id);
14801 #endif
14802
14803 FOR_EACH_FRAME (tail, frame)
14804 {
14805 Lisp_Object bar, condemned;
14806
14807 if (! FRAME_X_P (XFRAME (frame)))
14808 continue;
14809
14810
14811
14812 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
14813 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
14814
14815
14816 ! NILP (bar) || (bar = condemned,
14817 condemned = Qnil,
14818 ! NILP (bar));
14819 bar = XSCROLL_BAR (bar)->next)
14820 if (XSCROLL_BAR (bar)->x_window == window_id
14821 && FRAME_X_DISPLAY (XFRAME (frame)) == display
14822 && (type == 2
14823 || (type == 1 && XSCROLL_BAR (bar)->horizontal)
14824 || (type == 0 && !XSCROLL_BAR (bar)->horizontal)))
14825 return XSCROLL_BAR (bar);
14826 }
14827
14828 return NULL;
14829 }
14830
14831
14832 #if defined USE_LUCID
14833
14834
14835
14836
14837 static Widget
14838 x_window_to_menu_bar (Window window)
14839 {
14840 Lisp_Object tail, frame;
14841
14842 FOR_EACH_FRAME (tail, frame)
14843 if (FRAME_X_P (XFRAME (frame)))
14844 {
14845 Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
14846
14847 if (menu_bar && xlwmenu_window_p (menu_bar, window))
14848 return menu_bar;
14849 }
14850 return NULL;
14851 }
14852
14853 #endif
14854
14855
14856
14857
14858
14859
14860 #ifdef USE_TOOLKIT_SCROLL_BARS
14861
14862 static void x_send_scroll_bar_event (Lisp_Object, enum scroll_bar_part,
14863 int, int, bool);
14864
14865
14866
14867
14868 static Lisp_Object window_being_scrolled;
14869
14870 static Time
14871 x_get_last_toolkit_time (struct x_display_info *dpyinfo)
14872 {
14873 #ifdef USE_X_TOOLKIT
14874 return XtLastTimestampProcessed (dpyinfo->display);
14875 #else
14876 return dpyinfo->last_user_time;
14877 #endif
14878 }
14879
14880 #ifndef USE_GTK
14881
14882
14883
14884 static XtActionHookId action_hook_id;
14885 static XtActionHookId horizontal_action_hook_id;
14886
14887
14888
14889
14890 static Boolean xaw3d_arrow_scroll;
14891
14892
14893
14894
14895
14896 static Boolean xaw3d_pick_top;
14897
14898
14899
14900
14901
14902
14903 static void
14904 xt_action_hook (Widget widget, XtPointer client_data, String action_name,
14905 XEvent *event, String *params, Cardinal *num_params)
14906 {
14907 bool scroll_bar_p;
14908 const char *end_action;
14909
14910 #ifdef USE_MOTIF
14911 scroll_bar_p = XmIsScrollBar (widget);
14912 end_action = "Release";
14913 #else
14914 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
14915 end_action = "EndScroll";
14916 #endif
14917
14918 if (scroll_bar_p
14919 && strcmp (action_name, end_action) == 0
14920 && WINDOWP (window_being_scrolled))
14921 {
14922 struct window *w;
14923 struct scroll_bar *bar;
14924
14925 x_send_scroll_bar_event (window_being_scrolled,
14926 scroll_bar_end_scroll, 0, 0, false);
14927 w = XWINDOW (window_being_scrolled);
14928 bar = XSCROLL_BAR (w->vertical_scroll_bar);
14929
14930 if (bar->dragging != -1)
14931 {
14932 bar->dragging = -1;
14933
14934 set_vertical_scroll_bar (w);
14935 }
14936 window_being_scrolled = Qnil;
14937 #if defined (USE_LUCID)
14938 bar->last_seen_part = scroll_bar_nowhere;
14939 #endif
14940
14941 toolkit_scroll_bar_interaction = false;
14942 }
14943 }
14944
14945
14946 static void
14947 xt_horizontal_action_hook (Widget widget, XtPointer client_data, String action_name,
14948 XEvent *event, String *params, Cardinal *num_params)
14949 {
14950 bool scroll_bar_p;
14951 const char *end_action;
14952
14953 #ifdef USE_MOTIF
14954 scroll_bar_p = XmIsScrollBar (widget);
14955 end_action = "Release";
14956 #else
14957 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
14958 end_action = "EndScroll";
14959 #endif
14960
14961 if (scroll_bar_p
14962 && strcmp (action_name, end_action) == 0
14963 && WINDOWP (window_being_scrolled))
14964 {
14965 struct window *w;
14966 struct scroll_bar *bar;
14967
14968 x_send_scroll_bar_event (window_being_scrolled,
14969 scroll_bar_end_scroll, 0, 0, true);
14970 w = XWINDOW (window_being_scrolled);
14971 if (!NILP (w->horizontal_scroll_bar))
14972 {
14973 bar = XSCROLL_BAR (w->horizontal_scroll_bar);
14974 if (bar->dragging != -1)
14975 {
14976 bar->dragging = -1;
14977
14978 set_horizontal_scroll_bar (w);
14979 }
14980 window_being_scrolled = Qnil;
14981 #if defined (USE_LUCID)
14982 bar->last_seen_part = scroll_bar_nowhere;
14983 #endif
14984
14985 toolkit_scroll_bar_interaction = false;
14986 }
14987 }
14988 }
14989 #endif
14990
14991
14992
14993
14994 static bool
14995 x_protect_window_for_callback (struct x_display_info *dpyinfo,
14996 Lisp_Object window)
14997 {
14998 if (dpyinfo->n_protected_windows + 1
14999 >= dpyinfo->protected_windows_max)
15000 return false;
15001
15002 dpyinfo->protected_windows[dpyinfo->n_protected_windows++]
15003 = window;
15004 return true;
15005 }
15006
15007 static Lisp_Object
15008 x_unprotect_window_for_callback (struct x_display_info *dpyinfo)
15009 {
15010 Lisp_Object window;
15011
15012 if (!dpyinfo->n_protected_windows)
15013 return Qnil;
15014
15015 window = dpyinfo->protected_windows[0];
15016
15017 dpyinfo->n_protected_windows--;
15018
15019 if (dpyinfo->n_protected_windows)
15020 memmove (dpyinfo->protected_windows, &dpyinfo->protected_windows[1],
15021 sizeof (Lisp_Object) * dpyinfo->n_protected_windows);
15022
15023 return window;
15024 }
15025
15026
15027
15028
15029
15030
15031 static void
15032 x_send_scroll_bar_event (Lisp_Object window, enum scroll_bar_part part,
15033 int portion, int whole, bool horizontal)
15034 {
15035 XEvent event;
15036 XClientMessageEvent *ev = &event.xclient;
15037 struct window *w = XWINDOW (window);
15038 struct frame *f = XFRAME (w->frame);
15039 intptr_t iw = (intptr_t) w;
15040 verify (INTPTR_WIDTH <= 64);
15041 int sign_shift = INTPTR_WIDTH - 32;
15042
15043
15044
15045 if (!x_protect_window_for_callback (FRAME_DISPLAY_INFO (f), window))
15046 return;
15047
15048 block_input ();
15049
15050 ev->type = ClientMessage;
15051 ev->message_type = (horizontal
15052 ? FRAME_DISPLAY_INFO (f)->Xatom_Horizontal_Scrollbar
15053 : FRAME_DISPLAY_INFO (f)->Xatom_Scrollbar);
15054 ev->display = FRAME_X_DISPLAY (f);
15055 ev->window = FRAME_X_WINDOW (f);
15056 ev->format = 32;
15057
15058
15059
15060
15061
15062
15063
15064
15065 ev->data.l[0] = iw >> 31 >> 1;
15066 ev->data.l[1] = sign_shift <= 0 ? iw : iw << sign_shift >> sign_shift;
15067 ev->data.l[2] = part;
15068 ev->data.l[3] = portion;
15069 ev->data.l[4] = whole;
15070
15071
15072 #ifdef USE_X_TOOLKIT
15073 toolkit_scroll_bar_interaction = true;
15074 x_activate_timeout_atimer ();
15075 #endif
15076
15077
15078
15079
15080 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False,
15081 NoEventMask, &event);
15082 unblock_input ();
15083 }
15084
15085
15086
15087
15088
15089 static void
15090 x_scroll_bar_to_input_event (struct x_display_info *dpyinfo,
15091 const XEvent *event,
15092 struct input_event *ievent)
15093 {
15094 Lisp_Object window;
15095
15096
15097
15098
15099
15100 window = x_unprotect_window_for_callback (dpyinfo);
15101
15102 if (NILP (window))
15103 {
15104
15105
15106 EVENT_INIT (*ievent);
15107 return;
15108 }
15109
15110 ievent->kind = SCROLL_BAR_CLICK_EVENT;
15111 ievent->frame_or_window = window;
15112 ievent->arg = Qnil;
15113 ievent->timestamp = x_get_last_toolkit_time (dpyinfo);
15114 ievent->code = 0;
15115 ievent->part = event->xclient.data.l[2];
15116 ievent->x = make_fixnum (event->xclient.data.l[3]);
15117 ievent->y = make_fixnum (event->xclient.data.l[4]);
15118 ievent->modifiers = 0;
15119 }
15120
15121
15122
15123
15124 static void
15125 x_horizontal_scroll_bar_to_input_event (struct x_display_info *dpyinfo,
15126 const XEvent *event,
15127 struct input_event *ievent)
15128 {
15129 Lisp_Object window;
15130
15131
15132
15133
15134
15135 window = x_unprotect_window_for_callback (dpyinfo);
15136
15137 if (NILP (window))
15138 {
15139
15140
15141 EVENT_INIT (*ievent);
15142 return;
15143 }
15144
15145 ievent->kind = HORIZONTAL_SCROLL_BAR_CLICK_EVENT;
15146 ievent->frame_or_window = window;
15147 ievent->arg = Qnil;
15148 ievent->timestamp = x_get_last_toolkit_time (dpyinfo);
15149 ievent->code = 0;
15150 ievent->part = event->xclient.data.l[2];
15151 ievent->x = make_fixnum (event->xclient.data.l[3]);
15152 ievent->y = make_fixnum (event->xclient.data.l[4]);
15153 ievent->modifiers = 0;
15154 }
15155
15156
15157 #ifdef USE_MOTIF
15158
15159
15160
15161 #define XM_SB_MAX 10000000
15162
15163
15164
15165
15166
15167 static void
15168 xm_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data)
15169 {
15170 struct scroll_bar *bar = client_data;
15171 XmScrollBarCallbackStruct *cs = call_data;
15172 enum scroll_bar_part part = scroll_bar_nowhere;
15173 bool horizontal = bar->horizontal;
15174 int whole = 0, portion = 0;
15175
15176 switch (cs->reason)
15177 {
15178 case XmCR_DECREMENT:
15179 bar->dragging = -1;
15180 part = horizontal ? scroll_bar_left_arrow : scroll_bar_up_arrow;
15181 break;
15182
15183 case XmCR_INCREMENT:
15184 bar->dragging = -1;
15185 part = horizontal ? scroll_bar_right_arrow : scroll_bar_down_arrow;
15186 break;
15187
15188 case XmCR_PAGE_DECREMENT:
15189 bar->dragging = -1;
15190 part = horizontal ? scroll_bar_before_handle : scroll_bar_above_handle;
15191 break;
15192
15193 case XmCR_PAGE_INCREMENT:
15194 bar->dragging = -1;
15195 part = horizontal ? scroll_bar_after_handle : scroll_bar_below_handle;
15196 break;
15197
15198 case XmCR_TO_TOP:
15199 bar->dragging = -1;
15200 part = horizontal ? scroll_bar_to_leftmost : scroll_bar_to_top;
15201 break;
15202
15203 case XmCR_TO_BOTTOM:
15204 bar->dragging = -1;
15205 part = horizontal ? scroll_bar_to_rightmost : scroll_bar_to_bottom;
15206 break;
15207
15208 case XmCR_DRAG:
15209 {
15210 int slider_size;
15211
15212 block_input ();
15213 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
15214 unblock_input ();
15215
15216 if (horizontal)
15217 {
15218 portion = bar->whole * ((float)cs->value / XM_SB_MAX);
15219 whole = bar->whole * ((float)(XM_SB_MAX - slider_size) / XM_SB_MAX);
15220 portion = min (portion, whole);
15221 part = scroll_bar_horizontal_handle;
15222 }
15223 else
15224 {
15225 whole = XM_SB_MAX - slider_size;
15226 portion = min (cs->value, whole);
15227 part = scroll_bar_handle;
15228 }
15229
15230 bar->dragging = cs->value;
15231 }
15232 break;
15233
15234 case XmCR_VALUE_CHANGED:
15235 break;
15236 };
15237
15238 if (part != scroll_bar_nowhere)
15239 {
15240 window_being_scrolled = bar->window;
15241 x_send_scroll_bar_event (bar->window, part, portion, whole,
15242 bar->horizontal);
15243 }
15244 }
15245
15246 #elif defined USE_GTK
15247
15248
15249
15250
15251 static gboolean
15252 xg_scroll_callback (GtkRange *range, GtkScrollType scroll,
15253 gdouble value, gpointer user_data)
15254 {
15255 int whole, portion;
15256 struct scroll_bar *bar;
15257 enum scroll_bar_part part;
15258 GtkAdjustment *adj;
15259 struct frame *f;
15260 guint32 time;
15261 struct x_display_info *dpyinfo;
15262
15263 if (xg_ignore_gtk_scrollbar) return false;
15264
15265 whole = 0;
15266 portion = 0;
15267 bar = user_data;
15268 part = scroll_bar_nowhere;
15269 adj = GTK_ADJUSTMENT (gtk_range_get_adjustment (range));
15270 f = g_object_get_data (G_OBJECT (range), XG_FRAME_DATA);
15271 time = gtk_get_current_event_time ();
15272 dpyinfo = FRAME_DISPLAY_INFO (f);
15273
15274 if (time != GDK_CURRENT_TIME)
15275 x_display_set_last_user_time (dpyinfo, time, true,
15276 true);
15277
15278 switch (scroll)
15279 {
15280 case GTK_SCROLL_JUMP:
15281
15282 if (FRAME_DISPLAY_INFO (f)->grabbed != 0
15283 && FRAME_DISPLAY_INFO (f)->grabbed < (1 << 4))
15284 {
15285 if (bar->horizontal)
15286 {
15287 part = scroll_bar_horizontal_handle;
15288 whole = (int)(gtk_adjustment_get_upper (adj) -
15289 gtk_adjustment_get_page_size (adj));
15290 portion = min ((int)value, whole);
15291 bar->dragging = portion;
15292 }
15293 else
15294 {
15295 part = scroll_bar_handle;
15296 whole = gtk_adjustment_get_upper (adj) -
15297 gtk_adjustment_get_page_size (adj);
15298 portion = min ((int)value, whole);
15299 bar->dragging = portion;
15300 }
15301 }
15302 break;
15303 case GTK_SCROLL_STEP_BACKWARD:
15304 part = (bar->horizontal
15305 ? scroll_bar_left_arrow : scroll_bar_up_arrow);
15306 bar->dragging = -1;
15307 break;
15308 case GTK_SCROLL_STEP_FORWARD:
15309 part = (bar->horizontal
15310 ? scroll_bar_right_arrow : scroll_bar_down_arrow);
15311 bar->dragging = -1;
15312 break;
15313 case GTK_SCROLL_PAGE_BACKWARD:
15314 part = (bar->horizontal
15315 ? scroll_bar_before_handle : scroll_bar_above_handle);
15316 bar->dragging = -1;
15317 break;
15318 case GTK_SCROLL_PAGE_FORWARD:
15319 part = (bar->horizontal
15320 ? scroll_bar_after_handle : scroll_bar_below_handle);
15321 bar->dragging = -1;
15322 break;
15323 default:
15324 break;
15325 }
15326
15327 if (part != scroll_bar_nowhere)
15328 {
15329 window_being_scrolled = bar->window;
15330 x_send_scroll_bar_event (bar->window, part, portion, whole,
15331 bar->horizontal);
15332 }
15333
15334 return false;
15335 }
15336
15337
15338
15339 static gboolean
15340 xg_end_scroll_callback (GtkWidget *widget,
15341 GdkEventButton *event,
15342 gpointer user_data)
15343 {
15344 struct scroll_bar *bar;
15345
15346 bar = user_data;
15347 bar->dragging = -1;
15348
15349 if (WINDOWP (window_being_scrolled))
15350 {
15351 x_send_scroll_bar_event (window_being_scrolled,
15352 scroll_bar_end_scroll, 0, 0, bar->horizontal);
15353 window_being_scrolled = Qnil;
15354 }
15355
15356 return false;
15357 }
15358
15359
15360 #else
15361
15362
15363
15364
15365
15366
15367 static void
15368 xaw_jump_callback (Widget widget, XtPointer client_data, XtPointer call_data)
15369 {
15370 struct scroll_bar *bar = client_data;
15371 float *top_addr = call_data;
15372 float top = *top_addr;
15373 float shown;
15374 int whole, portion, height, width;
15375 enum scroll_bar_part part;
15376 bool horizontal = bar->horizontal;
15377
15378 if (horizontal)
15379 {
15380
15381 block_input ();
15382 XtVaGetValues (widget, XtNshown, &shown, XtNwidth, &width, NULL);
15383 unblock_input ();
15384
15385 if (shown < 1)
15386 {
15387 whole = bar->whole - (shown * bar->whole);
15388 portion = min (top * bar->whole, whole);
15389 }
15390 else
15391 {
15392 whole = bar->whole;
15393 portion = 0;
15394 }
15395
15396 part = scroll_bar_horizontal_handle;
15397 }
15398 else
15399 {
15400
15401 block_input ();
15402 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
15403 unblock_input ();
15404
15405 whole = 10000000;
15406 portion = shown < 1 ? top * whole : 0;
15407
15408 if (shown < 1 && (eabs (top + shown - 1) < 1.0f / height))
15409
15410
15411
15412
15413
15414 part = scroll_bar_down_arrow;
15415 else
15416 part = scroll_bar_handle;
15417 }
15418
15419 window_being_scrolled = bar->window;
15420 bar->dragging = portion;
15421 bar->last_seen_part = part;
15422 x_send_scroll_bar_event (bar->window, part, portion, whole, bar->horizontal);
15423 }
15424
15425
15426
15427
15428
15429
15430
15431
15432
15433
15434 static void
15435 xaw_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data)
15436 {
15437 struct scroll_bar *bar = client_data;
15438
15439 int position = (intptr_t) call_data;
15440 Dimension height, width;
15441 enum scroll_bar_part part;
15442
15443 if (bar->horizontal)
15444 {
15445
15446 block_input ();
15447 XtVaGetValues (widget, XtNwidth, &width, NULL);
15448 unblock_input ();
15449
15450 if (eabs (position) >= width)
15451 part = (position < 0) ? scroll_bar_before_handle : scroll_bar_after_handle;
15452
15453
15454
15455 else if (xaw3d_arrow_scroll && eabs (position) <= max (5, width / 20))
15456 part = (position < 0) ? scroll_bar_left_arrow : scroll_bar_right_arrow;
15457 else
15458 part = scroll_bar_move_ratio;
15459
15460 window_being_scrolled = bar->window;
15461 bar->dragging = -1;
15462 bar->last_seen_part = part;
15463 x_send_scroll_bar_event (bar->window, part, position, width,
15464 bar->horizontal);
15465 }
15466 else
15467 {
15468
15469
15470 block_input ();
15471 XtVaGetValues (widget, XtNheight, &height, NULL);
15472 unblock_input ();
15473
15474 if (eabs (position) >= height)
15475 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
15476
15477
15478
15479 else if (xaw3d_arrow_scroll && eabs (position) <= max (5, height / 20))
15480 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
15481 else
15482 part = scroll_bar_move_ratio;
15483
15484 window_being_scrolled = bar->window;
15485 bar->dragging = -1;
15486 bar->last_seen_part = part;
15487 x_send_scroll_bar_event (bar->window, part, position, height,
15488 bar->horizontal);
15489 }
15490 }
15491
15492 #endif
15493
15494 #define SCROLL_BAR_NAME "verticalScrollBar"
15495 #define SCROLL_BAR_HORIZONTAL_NAME "horizontalScrollBar"
15496
15497
15498
15499
15500 #ifdef USE_GTK
15501 static void
15502 x_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
15503 {
15504 const char *scroll_bar_name = SCROLL_BAR_NAME;
15505
15506 block_input ();
15507 xg_create_scroll_bar (f, bar, G_CALLBACK (xg_scroll_callback),
15508 G_CALLBACK (xg_end_scroll_callback),
15509 scroll_bar_name);
15510 unblock_input ();
15511 }
15512
15513 static void
15514 x_create_horizontal_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
15515 {
15516 const char *scroll_bar_name = SCROLL_BAR_HORIZONTAL_NAME;
15517
15518 block_input ();
15519 xg_create_horizontal_scroll_bar (f, bar, G_CALLBACK (xg_scroll_callback),
15520 G_CALLBACK (xg_end_scroll_callback),
15521 scroll_bar_name);
15522 unblock_input ();
15523 }
15524
15525 #else
15526
15527 static void
15528 x_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
15529 {
15530 Window xwindow;
15531 Widget widget;
15532 Arg av[20];
15533 int ac = 0;
15534 const char *scroll_bar_name = SCROLL_BAR_NAME;
15535 unsigned long pixel;
15536
15537 block_input ();
15538
15539 #ifdef USE_MOTIF
15540
15541 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
15542 XtSetArg (av[ac], XmNminimum, 0); ++ac;
15543 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
15544 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
15545 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
15546 XtSetArg (av[ac], XmNincrement, 1); ++ac;
15547 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
15548
15549
15550
15551 pixel = f->output_data.x->scroll_bar_foreground_pixel;
15552 if (pixel != -1)
15553 {
15554 XtSetArg (av[ac], XmNbackground, pixel);
15555 ++ac;
15556 }
15557
15558 pixel = f->output_data.x->scroll_bar_background_pixel;
15559 if (pixel != -1)
15560 {
15561 XtSetArg (av[ac], XmNtroughColor, pixel);
15562 ++ac;
15563 }
15564
15565 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
15566 (char *) scroll_bar_name, av, ac);
15567
15568
15569 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
15570 (XtPointer) bar);
15571 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
15572 (XtPointer) bar);
15573 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
15574 (XtPointer) bar);
15575 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
15576 (XtPointer) bar);
15577 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
15578 (XtPointer) bar);
15579 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
15580 (XtPointer) bar);
15581 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
15582 (XtPointer) bar);
15583
15584
15585 XtRealizeWidget (widget);
15586
15587
15588
15589 XDefineCursor (XtDisplay (widget), XtWindow (widget),
15590 f->output_data.x->nontext_cursor);
15591
15592 #ifdef HAVE_XINPUT2
15593
15594
15595 if (FRAME_DISPLAY_INFO (f)->supports_xi2)
15596 xi_select_scroll_bar_events (FRAME_DISPLAY_INFO (f),
15597 XtWindow (widget));
15598 #endif
15599 #else
15600
15601
15602
15603
15604
15605 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
15606 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
15607
15608
15609
15610 pixel = f->output_data.x->scroll_bar_foreground_pixel;
15611 if (pixel != -1)
15612 {
15613 XtSetArg (av[ac], XtNforeground, pixel);
15614 ++ac;
15615 }
15616
15617 pixel = f->output_data.x->scroll_bar_background_pixel;
15618 if (pixel != -1)
15619 {
15620 XtSetArg (av[ac], XtNbackground, pixel);
15621 ++ac;
15622 }
15623
15624
15625
15626
15627 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1)
15628 {
15629 pixel = f->output_data.x->scroll_bar_background_pixel;
15630 if (pixel != -1)
15631 {
15632 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
15633 FRAME_X_COLORMAP (f),
15634 &pixel, 1.2, 0x8000))
15635 pixel = -1;
15636 f->output_data.x->scroll_bar_top_shadow_pixel = pixel;
15637 }
15638 }
15639 if (f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
15640 {
15641 pixel = f->output_data.x->scroll_bar_background_pixel;
15642 if (pixel != -1)
15643 {
15644 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
15645 FRAME_X_COLORMAP (f),
15646 &pixel, 0.6, 0x4000))
15647 pixel = -1;
15648 f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
15649 }
15650 }
15651
15652 #ifdef XtNbeNiceToColormap
15653
15654 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1
15655 || f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
15656
15657
15658
15659
15660 {
15661 XtSetArg (av[ac], (String) XtNbeNiceToColormap,
15662 DefaultDepthOfScreen (FRAME_X_SCREEN (f)) < 16);
15663 ++ac;
15664 }
15665 else
15666
15667
15668
15669 {
15670
15671
15672 XtSetArg (av[ac], (String) XtNbeNiceToColormap, False);
15673 ++ac;
15674
15675
15676 pixel = f->output_data.x->scroll_bar_top_shadow_pixel;
15677 if (pixel != -1)
15678 {
15679 XtSetArg (av[ac], (String) XtNtopShadowPixel, pixel);
15680 ++ac;
15681 }
15682 pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel;
15683 if (pixel != -1)
15684 {
15685 XtSetArg (av[ac], (String) XtNbottomShadowPixel, pixel);
15686 ++ac;
15687 }
15688 }
15689 #endif
15690
15691 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
15692 f->output_data.x->edit_widget, av, ac);
15693
15694 {
15695 char const *initial = "";
15696 char const *val = initial;
15697 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
15698 #ifdef XtNarrowScrollbars
15699 XtNarrowScrollbars, (XtPointer) &xaw3d_arrow_scroll,
15700 #endif
15701 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
15702 if (xaw3d_arrow_scroll || val == initial)
15703 {
15704 xaw3d_arrow_scroll = True;
15705
15706 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
15707 }
15708 }
15709
15710
15711 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
15712 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
15713 (XtPointer) bar);
15714
15715
15716 XtRealizeWidget (widget);
15717
15718 #endif
15719
15720
15721
15722 if (action_hook_id == 0)
15723 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
15724
15725
15726 SET_SCROLL_BAR_X_WIDGET (bar, widget);
15727 xwindow = XtWindow (widget);
15728 bar->x_window = xwindow;
15729 bar->whole = 1;
15730 bar->horizontal = false;
15731
15732 unblock_input ();
15733 }
15734
15735 static void
15736 x_create_horizontal_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
15737 {
15738 Window xwindow;
15739 Widget widget;
15740 Arg av[20];
15741 int ac = 0;
15742 const char *scroll_bar_name = SCROLL_BAR_HORIZONTAL_NAME;
15743 unsigned long pixel;
15744
15745 block_input ();
15746
15747 #ifdef USE_MOTIF
15748
15749 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
15750 XtSetArg (av[ac], XmNminimum, 0); ++ac;
15751 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
15752 XtSetArg (av[ac], XmNorientation, XmHORIZONTAL); ++ac;
15753 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_RIGHT), ++ac;
15754 XtSetArg (av[ac], XmNincrement, 1); ++ac;
15755 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
15756
15757
15758
15759 pixel = f->output_data.x->scroll_bar_foreground_pixel;
15760 if (pixel != -1)
15761 {
15762 XtSetArg (av[ac], XmNbackground, pixel);
15763 ++ac;
15764 }
15765
15766 pixel = f->output_data.x->scroll_bar_background_pixel;
15767 if (pixel != -1)
15768 {
15769 XtSetArg (av[ac], XmNtroughColor, pixel);
15770 ++ac;
15771 }
15772
15773 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
15774 (char *) scroll_bar_name, av, ac);
15775
15776
15777 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
15778 (XtPointer) bar);
15779 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
15780 (XtPointer) bar);
15781 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
15782 (XtPointer) bar);
15783 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
15784 (XtPointer) bar);
15785 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
15786 (XtPointer) bar);
15787 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
15788 (XtPointer) bar);
15789 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
15790 (XtPointer) bar);
15791
15792
15793 XtRealizeWidget (widget);
15794
15795
15796
15797 XDefineCursor (XtDisplay (widget), XtWindow (widget),
15798 f->output_data.x->nontext_cursor);
15799
15800 #ifdef HAVE_XINPUT2
15801
15802
15803 if (FRAME_DISPLAY_INFO (f)->supports_xi2)
15804 xi_select_scroll_bar_events (FRAME_DISPLAY_INFO (f),
15805 XtWindow (widget));
15806 #endif
15807 #else
15808
15809
15810
15811
15812
15813 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
15814 XtSetArg (av[ac], XtNorientation, XtorientHorizontal); ++ac;
15815
15816
15817
15818 pixel = f->output_data.x->scroll_bar_foreground_pixel;
15819 if (pixel != -1)
15820 {
15821 XtSetArg (av[ac], XtNforeground, pixel);
15822 ++ac;
15823 }
15824
15825 pixel = f->output_data.x->scroll_bar_background_pixel;
15826 if (pixel != -1)
15827 {
15828 XtSetArg (av[ac], XtNbackground, pixel);
15829 ++ac;
15830 }
15831
15832
15833
15834
15835 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1)
15836 {
15837 pixel = f->output_data.x->scroll_bar_background_pixel;
15838 if (pixel != -1)
15839 {
15840 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
15841 FRAME_X_COLORMAP (f),
15842 &pixel, 1.2, 0x8000))
15843 pixel = -1;
15844 f->output_data.x->scroll_bar_top_shadow_pixel = pixel;
15845 }
15846 }
15847 if (f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
15848 {
15849 pixel = f->output_data.x->scroll_bar_background_pixel;
15850 if (pixel != -1)
15851 {
15852 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
15853 FRAME_X_COLORMAP (f),
15854 &pixel, 0.6, 0x4000))
15855 pixel = -1;
15856 f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
15857 }
15858 }
15859
15860 #ifdef XtNbeNiceToColormap
15861
15862 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1
15863 || f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
15864
15865
15866
15867
15868 {
15869 XtSetArg (av[ac], (String) XtNbeNiceToColormap,
15870 DefaultDepthOfScreen (FRAME_X_SCREEN (f)) < 16);
15871 ++ac;
15872 }
15873 else
15874
15875
15876
15877 {
15878
15879
15880 XtSetArg (av[ac], (String) XtNbeNiceToColormap, False);
15881 ++ac;
15882
15883
15884 pixel = f->output_data.x->scroll_bar_top_shadow_pixel;
15885 if (pixel != -1)
15886 {
15887 XtSetArg (av[ac], (String) XtNtopShadowPixel, pixel);
15888 ++ac;
15889 }
15890 pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel;
15891 if (pixel != -1)
15892 {
15893 XtSetArg (av[ac], (String) XtNbottomShadowPixel, pixel);
15894 ++ac;
15895 }
15896 }
15897 #endif
15898
15899 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
15900 f->output_data.x->edit_widget, av, ac);
15901
15902 {
15903 char const *initial = "";
15904 char const *val = initial;
15905 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
15906 #ifdef XtNarrowScrollbars
15907 XtNarrowScrollbars, (XtPointer) &xaw3d_arrow_scroll,
15908 #endif
15909 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
15910 if (xaw3d_arrow_scroll || val == initial)
15911 {
15912 xaw3d_arrow_scroll = True;
15913
15914 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
15915 }
15916 }
15917
15918
15919 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
15920 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
15921 (XtPointer) bar);
15922
15923
15924 XtRealizeWidget (widget);
15925
15926 #endif
15927
15928
15929
15930 if (horizontal_action_hook_id == 0)
15931 horizontal_action_hook_id
15932 = XtAppAddActionHook (Xt_app_con, xt_horizontal_action_hook, 0);
15933
15934
15935 SET_SCROLL_BAR_X_WIDGET (bar, widget);
15936 xwindow = XtWindow (widget);
15937 bar->x_window = xwindow;
15938 bar->whole = 1;
15939 bar->horizontal = true;
15940
15941 unblock_input ();
15942 }
15943 #endif
15944
15945
15946
15947
15948
15949 #ifdef USE_GTK
15950 static void
15951 x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position, int whole)
15952 {
15953 xg_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
15954 }
15955
15956 static void
15957 x_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position, int whole)
15958 {
15959 xg_set_toolkit_horizontal_scroll_bar_thumb (bar, portion, position, whole);
15960 }
15961
15962 #else
15963 static void
15964 x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position,
15965 int whole)
15966 {
15967 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
15968 Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
15969 float top, shown;
15970
15971 block_input ();
15972
15973 #ifdef USE_MOTIF
15974
15975 if (scroll_bar_adjust_thumb_portion_p)
15976 {
15977
15978
15979
15980
15981
15982
15983
15984
15985
15986
15987
15988 portion = WINDOW_TOTAL_LINES (XWINDOW (bar->window)) * 30;
15989
15990
15991 whole += portion;
15992 }
15993
15994 if (whole <= 0)
15995 top = 0, shown = 1;
15996 else
15997 {
15998 top = (float) position / whole;
15999 shown = (float) portion / whole;
16000 }
16001
16002 if (bar->dragging == -1)
16003 {
16004 int size, value;
16005
16006
16007
16008
16009 size = clip_to_bounds (1, shown * XM_SB_MAX, XM_SB_MAX);
16010
16011
16012 value = top * XM_SB_MAX;
16013 value = min (value, XM_SB_MAX - size);
16014
16015 XmScrollBarSetValues (widget, value, size, 0, 0, False);
16016 }
16017 #else
16018
16019 if (whole == 0)
16020 top = 0, shown = 1;
16021 else
16022 {
16023 top = (float) position / whole;
16024 shown = (float) portion / whole;
16025 }
16026
16027 {
16028 float old_top, old_shown;
16029 Dimension height;
16030 XtVaGetValues (widget,
16031 XtNtopOfThumb, &old_top,
16032 XtNshown, &old_shown,
16033 XtNheight, &height,
16034 NULL);
16035
16036
16037 if (bar->dragging == -1 || bar->last_seen_part == scroll_bar_down_arrow)
16038 top = max (0, min (1, top));
16039 else
16040 top = old_top;
16041 #if ! defined (HAVE_XAW3D)
16042
16043
16044 top = min (top, 0.99f);
16045 #endif
16046
16047 shown = max (0, min (1 - top - (2.0f / height), shown));
16048 #if ! defined (HAVE_XAW3D)
16049
16050 shown = max (shown, 0.01f);
16051 #endif
16052
16053
16054
16055
16056 if (top != old_top || shown != old_shown)
16057 {
16058 if (bar->dragging == -1)
16059 XawScrollbarSetThumb (widget, top, shown);
16060 else
16061 {
16062
16063 if (!xaw3d_pick_top)
16064 shown = min (shown, old_shown);
16065
16066 XawScrollbarSetThumb (widget, top, shown);
16067 }
16068 }
16069 }
16070 #endif
16071
16072 unblock_input ();
16073 }
16074
16075 static void
16076 x_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position,
16077 int whole)
16078 {
16079 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
16080 Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
16081 float top, shown;
16082
16083 block_input ();
16084
16085 #ifdef USE_MOTIF
16086 bar->whole = whole;
16087 shown = (float) portion / whole;
16088 top = (float) position / (whole - portion);
16089 {
16090 int size = clip_to_bounds (1, shown * XM_SB_MAX, XM_SB_MAX);
16091 int value = clip_to_bounds (0, top * (XM_SB_MAX - size), XM_SB_MAX - size);
16092
16093 XmScrollBarSetValues (widget, value, size, 0, 0, False);
16094 }
16095 #else
16096 bar->whole = whole;
16097 if (whole == 0)
16098 top = 0, shown = 1;
16099 else
16100 {
16101 top = (float) position / whole;
16102 shown = (float) portion / whole;
16103 }
16104
16105 {
16106 float old_top, old_shown;
16107 Dimension height;
16108 XtVaGetValues (widget,
16109 XtNtopOfThumb, &old_top,
16110 XtNshown, &old_shown,
16111 XtNheight, &height,
16112 NULL);
16113
16114 #if false
16115
16116 if (bar->dragging == -1 || bar->last_seen_part == scroll_bar_down_arrow)
16117 top = max (0, min (1, top));
16118 else
16119 top = old_top;
16120 #if ! defined (HAVE_XAW3D)
16121
16122
16123 top = min (top, 0.99f);
16124 #endif
16125
16126 shown = max (0, min (1 - top - (2.0f / height), shown));
16127 #if ! defined (HAVE_XAW3D)
16128
16129 shown = max (shown, 0.01f);
16130 #endif
16131 #endif
16132
16133
16134
16135
16136 XawScrollbarSetThumb (widget, top, shown);
16137 #if false
16138 if (top != old_top || shown != old_shown)
16139 {
16140 if (bar->dragging == -1)
16141 XawScrollbarSetThumb (widget, top, shown);
16142 else
16143 {
16144
16145 if (!xaw3d_pick_top)
16146 shown = min (shown, old_shown);
16147
16148 XawScrollbarSetThumb (widget, top, shown);
16149 }
16150 }
16151 #endif
16152 }
16153 #endif
16154
16155 unblock_input ();
16156 }
16157 #endif
16158
16159 #endif
16160
16161
16162
16163
16164
16165
16166
16167
16168
16169
16170
16171
16172 static struct scroll_bar *
16173 x_scroll_bar_create (struct window *w, int top, int left,
16174 int width, int height, bool horizontal)
16175 {
16176 struct frame *f = XFRAME (w->frame);
16177 struct scroll_bar *bar = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, prev,
16178 PVEC_OTHER);
16179 Lisp_Object barobj;
16180
16181 block_input ();
16182
16183 #ifdef USE_TOOLKIT_SCROLL_BARS
16184 if (horizontal)
16185 x_create_horizontal_toolkit_scroll_bar (f, bar);
16186 else
16187 x_create_toolkit_scroll_bar (f, bar);
16188 #else
16189 {
16190 XSetWindowAttributes a;
16191 unsigned long mask;
16192 Window window;
16193
16194 a.event_mask = (ButtonPressMask | ButtonReleaseMask
16195 | ButtonMotionMask | PointerMotionHintMask);
16196 a.cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
16197
16198 mask = (CWEventMask | CWCursor);
16199
16200
16201
16202
16203 if (width > 0 && window_box_height (w) > 0)
16204 x_clear_area (f, left, top, width, window_box_height (w));
16205
16206
16207
16208
16209 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
16210
16211 left, top, width, height,
16212
16213 0,
16214
16215 CopyFromParent,
16216
16217 InputOnly,
16218
16219 CopyFromParent,
16220
16221 mask, &a);
16222
16223 #ifdef HAVE_XINPUT2
16224
16225
16226 if (FRAME_DISPLAY_INFO (f)->supports_xi2)
16227 xi_select_scroll_bar_events (FRAME_DISPLAY_INFO (f),
16228 window);
16229 #endif
16230
16231 bar->x_window = window;
16232 }
16233 #endif
16234
16235 XSETWINDOW (bar->window, w);
16236 bar->top = top;
16237 bar->left = left;
16238 bar->width = width;
16239 bar->height = height;
16240 bar->start = 0;
16241 bar->end = 0;
16242 bar->dragging = -1;
16243 bar->horizontal = horizontal;
16244 #if defined (USE_TOOLKIT_SCROLL_BARS) && defined (USE_LUCID)
16245 bar->last_seen_part = scroll_bar_nowhere;
16246 #endif
16247
16248
16249 bar->next = FRAME_SCROLL_BARS (f);
16250 bar->prev = Qnil;
16251 XSETVECTOR (barobj, bar);
16252 fset_scroll_bars (f, barobj);
16253 if (!NILP (bar->next))
16254 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
16255
16256
16257 #ifdef USE_TOOLKIT_SCROLL_BARS
16258 {
16259 #ifdef USE_GTK
16260 if (horizontal)
16261 xg_update_horizontal_scrollbar_pos (f, bar->x_window, top,
16262 left, width, max (height, 1));
16263 else
16264 xg_update_scrollbar_pos (f, bar->x_window, top,
16265 left, width, max (height, 1));
16266 #else
16267 Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
16268 XtConfigureWidget (scroll_bar, left, top, width, max (height, 1), 0);
16269 XtMapWidget (scroll_bar);
16270
16271 XLowerWindow (FRAME_X_DISPLAY (f), bar->x_window);
16272 #endif
16273 }
16274 #else
16275 XMapWindow (FRAME_X_DISPLAY (f), bar->x_window);
16276
16277 XLowerWindow (FRAME_X_DISPLAY (f), bar->x_window);
16278 #endif
16279
16280 unblock_input ();
16281 return bar;
16282 }
16283
16284
16285 #ifndef USE_TOOLKIT_SCROLL_BARS
16286
16287
16288
16289
16290
16291
16292
16293
16294
16295
16296
16297
16298
16299
16300 static void
16301 x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end,
16302 bool rebuild)
16303 {
16304 bool dragging;
16305 struct frame *f;
16306 Drawable w;
16307 GC gc;
16308 int inside_width, inside_height, top_range, length;
16309
16310
16311 if (! rebuild
16312 && start == bar->start
16313 && end == bar->end)
16314 return;
16315
16316 f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
16317 dragging = bar->dragging != -1;
16318 gc = f->output_data.x->normal_gc;
16319 w = FRAME_X_DRAWABLE (f);
16320
16321 block_input ();
16322
16323 inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, bar->width);
16324 inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, bar->height);
16325 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
16326
16327
16328
16329 length = end - start;
16330
16331 if (start < 0)
16332 start = 0;
16333 else if (start > top_range)
16334 start = top_range;
16335 end = start + length;
16336
16337 if (end < start)
16338 end = start;
16339 else if (end > top_range && ! dragging)
16340 end = top_range;
16341
16342
16343 bar->start = start;
16344 bar->end = end;
16345
16346
16347 if (end > top_range)
16348 end = top_range;
16349
16350
16351
16352
16353 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
16354
16355
16356
16357 if ((inside_width > 0) && (start > 0))
16358 {
16359 if (f->output_data.x->scroll_bar_background_pixel != -1)
16360 XSetForeground (FRAME_X_DISPLAY (f), gc,
16361 f->output_data.x->scroll_bar_background_pixel);
16362 else
16363 XSetForeground (FRAME_X_DISPLAY (f), gc,
16364 FRAME_BACKGROUND_PIXEL (f));
16365
16366 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
16367 bar->left + VERTICAL_SCROLL_BAR_LEFT_BORDER,
16368 bar->top + VERTICAL_SCROLL_BAR_TOP_BORDER,
16369 inside_width, start);
16370
16371 XSetForeground (FRAME_X_DISPLAY (f), gc,
16372 FRAME_FOREGROUND_PIXEL (f));
16373 }
16374
16375
16376 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
16377 XSetForeground (FRAME_X_DISPLAY (f), gc,
16378 f->output_data.x->scroll_bar_foreground_pixel);
16379
16380
16381 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
16382
16383 bar->left + VERTICAL_SCROLL_BAR_LEFT_BORDER,
16384 bar->top + VERTICAL_SCROLL_BAR_TOP_BORDER + start,
16385 inside_width, end - start);
16386
16387
16388
16389
16390 if ((inside_width > 0) && (end < inside_height))
16391 {
16392 if (f->output_data.x->scroll_bar_background_pixel != -1)
16393 XSetForeground (FRAME_X_DISPLAY (f), gc,
16394 f->output_data.x->scroll_bar_background_pixel);
16395 else
16396 XSetForeground (FRAME_X_DISPLAY (f), gc,
16397 FRAME_BACKGROUND_PIXEL (f));
16398
16399 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
16400 bar->left + VERTICAL_SCROLL_BAR_LEFT_BORDER,
16401 bar->top + VERTICAL_SCROLL_BAR_TOP_BORDER + end,
16402 inside_width, inside_height - end);
16403
16404 XSetForeground (FRAME_X_DISPLAY (f), gc,
16405 FRAME_FOREGROUND_PIXEL (f));
16406 }
16407
16408
16409 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
16410 XSetForeground (FRAME_X_DISPLAY (f), gc,
16411 FRAME_FOREGROUND_PIXEL (f));
16412
16413 unblock_input ();
16414 }
16415
16416 #endif
16417
16418
16419
16420
16421 static void
16422 x_scroll_bar_remove (struct scroll_bar *bar)
16423 {
16424 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
16425 block_input ();
16426
16427 #ifdef USE_TOOLKIT_SCROLL_BARS
16428 #ifdef USE_GTK
16429 xg_remove_scroll_bar (f, bar->x_window);
16430 #else
16431 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));
16432 #endif
16433 #else
16434 XDestroyWindow (FRAME_X_DISPLAY (f), bar->x_window);
16435 #endif
16436
16437
16438 if (bar->horizontal)
16439 wset_horizontal_scroll_bar (XWINDOW (bar->window), Qnil);
16440 else
16441 wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil);
16442
16443 unblock_input ();
16444 }
16445
16446
16447
16448
16449
16450
16451
16452 static void
16453 XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int position)
16454 {
16455 struct frame *f = XFRAME (w->frame);
16456 Lisp_Object barobj;
16457 struct scroll_bar *bar;
16458 int top, height, left, width;
16459 int window_y, window_height;
16460
16461
16462 window_box (w, ANY_AREA, 0, &window_y, 0, &window_height);
16463 top = window_y;
16464 height = window_height;
16465 left = WINDOW_SCROLL_BAR_AREA_X (w);
16466 width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
16467
16468
16469 if (NILP (w->vertical_scroll_bar))
16470 {
16471 if (width > 0 && height > 0)
16472 {
16473 block_input ();
16474 x_clear_area (f, left, top, width, height);
16475 unblock_input ();
16476 }
16477
16478 bar = x_scroll_bar_create (w, top, left, width, max (height, 1), false);
16479 #ifndef USE_TOOLKIT_SCROLL_BARS
16480
16481
16482
16483 x_scroll_bar_redraw (bar);
16484 #endif
16485 }
16486 else
16487 {
16488
16489 unsigned int mask = 0;
16490
16491 bar = XSCROLL_BAR (w->vertical_scroll_bar);
16492
16493 block_input ();
16494
16495 if (left != bar->left)
16496 mask |= CWX;
16497 if (top != bar->top)
16498 mask |= CWY;
16499 if (width != bar->width)
16500 mask |= CWWidth;
16501 if (height != bar->height)
16502 mask |= CWHeight;
16503
16504 #ifdef USE_TOOLKIT_SCROLL_BARS
16505
16506
16507 if (mask)
16508 {
16509
16510
16511 if (width > 0 && height > 0)
16512 x_clear_area (f, left, top, width, height);
16513 #ifdef USE_GTK
16514 xg_update_scrollbar_pos (f, bar->x_window, top,
16515 left, width, max (height, 1));
16516 #else
16517 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
16518 left, top, width, max (height, 1), 0);
16519 #endif
16520 }
16521 #else
16522
16523
16524 if (mask)
16525 {
16526 XWindowChanges wc;
16527
16528 wc.x = left;
16529 wc.y = top;
16530 wc.width = width;
16531 wc.height = height;
16532 XConfigureWindow (FRAME_X_DISPLAY (f), bar->x_window,
16533 mask, &wc);
16534 }
16535
16536 #endif
16537
16538
16539 bar->left = left;
16540 bar->top = top;
16541 bar->width = width;
16542 bar->height = height;
16543
16544 #ifndef USE_TOOLKIT_SCROLL_BARS
16545
16546 x_scroll_bar_redraw (bar);
16547 #endif
16548
16549 unblock_input ();
16550 }
16551
16552 #ifdef USE_TOOLKIT_SCROLL_BARS
16553 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
16554 #else
16555
16556
16557 if (bar->dragging == -1)
16558 {
16559 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
16560
16561 if (whole == 0)
16562 x_scroll_bar_set_handle (bar, 0, top_range, false);
16563 else
16564 {
16565 int start = ((double) position * top_range) / whole;
16566 int end = ((double) (position + portion) * top_range) / whole;
16567 x_scroll_bar_set_handle (bar, start, end, false);
16568 }
16569 }
16570 #endif
16571
16572 XSETVECTOR (barobj, bar);
16573 wset_vertical_scroll_bar (w, barobj);
16574 }
16575
16576
16577 static void
16578 XTset_horizontal_scroll_bar (struct window *w, int portion, int whole, int position)
16579 {
16580 struct frame *f = XFRAME (w->frame);
16581 Lisp_Object barobj;
16582 struct scroll_bar *bar;
16583 int top, height, left, width;
16584 int window_x, window_width;
16585 int pixel_width = WINDOW_PIXEL_WIDTH (w);
16586
16587
16588 window_box (w, ANY_AREA, &window_x, 0, &window_width, 0);
16589 left = window_x;
16590 width = window_width;
16591 top = WINDOW_SCROLL_BAR_AREA_Y (w);
16592 height = WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
16593
16594
16595 if (NILP (w->horizontal_scroll_bar))
16596 {
16597 if (width > 0 && height > 0)
16598 {
16599 block_input ();
16600
16601
16602
16603 x_clear_area (f, left, top, pixel_width, height);
16604 unblock_input ();
16605 }
16606
16607 bar = x_scroll_bar_create (w, top, left, width, height, true);
16608 }
16609 else
16610 {
16611
16612 unsigned int mask = 0;
16613
16614 bar = XSCROLL_BAR (w->horizontal_scroll_bar);
16615
16616 block_input ();
16617
16618 if (left != bar->left)
16619 mask |= CWX;
16620 if (top != bar->top)
16621 mask |= CWY;
16622 if (width != bar->width)
16623 mask |= CWWidth;
16624 if (height != bar->height)
16625 mask |= CWHeight;
16626
16627 #ifdef USE_TOOLKIT_SCROLL_BARS
16628
16629 if (mask)
16630 {
16631
16632
16633 if (width > 0 && height > 0)
16634 x_clear_area (f,
16635 WINDOW_LEFT_EDGE_X (w), top,
16636 pixel_width - WINDOW_RIGHT_DIVIDER_WIDTH (w), height);
16637 #ifdef USE_GTK
16638 xg_update_horizontal_scrollbar_pos (f, bar->x_window, top, left,
16639 width, height);
16640 #else
16641 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
16642 left, top, width, height, 0);
16643 #endif
16644 }
16645 #else
16646
16647
16648
16649
16650
16651 {
16652 int area_height = WINDOW_CONFIG_SCROLL_BAR_HEIGHT (w);
16653 int rest = area_height - height;
16654 if (rest > 0 && width > 0)
16655 x_clear_area (f, left, top, width, rest);
16656 }
16657
16658
16659 if (mask)
16660 {
16661 XWindowChanges wc;
16662
16663 wc.x = left;
16664 wc.y = top;
16665 wc.width = width;
16666 wc.height = height;
16667 XConfigureWindow (FRAME_X_DISPLAY (f), bar->x_window,
16668 mask, &wc);
16669 }
16670
16671 #endif
16672
16673
16674 bar->left = left;
16675 bar->top = top;
16676 bar->width = width;
16677 bar->height = height;
16678
16679 unblock_input ();
16680 }
16681
16682 #ifdef USE_TOOLKIT_SCROLL_BARS
16683 x_set_toolkit_horizontal_scroll_bar_thumb (bar, portion, position, whole);
16684 #else
16685
16686
16687 if (bar->dragging == -1)
16688 {
16689 int left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, width);
16690
16691 if (whole == 0)
16692 x_scroll_bar_set_handle (bar, 0, left_range, false);
16693 else
16694 {
16695 int start = ((double) position * left_range) / whole;
16696 int end = ((double) (position + portion) * left_range) / whole;
16697 x_scroll_bar_set_handle (bar, start, end, false);
16698 }
16699 }
16700 #endif
16701
16702 XSETVECTOR (barobj, bar);
16703 wset_horizontal_scroll_bar (w, barobj);
16704 }
16705
16706
16707
16708
16709
16710
16711
16712
16713
16714
16715
16716
16717
16718
16719 static void
16720 XTcondemn_scroll_bars (struct frame *frame)
16721 {
16722 if (!NILP (FRAME_SCROLL_BARS (frame)))
16723 {
16724 if (!NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
16725 {
16726
16727 Lisp_Object last = FRAME_SCROLL_BARS (frame);
16728
16729 while (!NILP (XSCROLL_BAR (last)->next))
16730 last = XSCROLL_BAR (last)->next;
16731
16732 XSCROLL_BAR (last)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
16733 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = last;
16734 }
16735
16736 fset_condemned_scroll_bars (frame, FRAME_SCROLL_BARS (frame));
16737 fset_scroll_bars (frame, Qnil);
16738 }
16739 }
16740
16741
16742
16743
16744
16745 static void
16746 XTredeem_scroll_bar (struct window *w)
16747 {
16748 struct scroll_bar *bar;
16749 Lisp_Object barobj;
16750 struct frame *f;
16751
16752
16753 if (NILP (w->vertical_scroll_bar) && NILP (w->horizontal_scroll_bar))
16754 emacs_abort ();
16755
16756 if (!NILP (w->vertical_scroll_bar) && WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
16757 {
16758 bar = XSCROLL_BAR (w->vertical_scroll_bar);
16759
16760 f = XFRAME (WINDOW_FRAME (w));
16761 if (NILP (bar->prev))
16762 {
16763
16764
16765 if (EQ (FRAME_SCROLL_BARS (f), w->vertical_scroll_bar))
16766
16767 goto horizontal;
16768 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
16769 w->vertical_scroll_bar))
16770 fset_condemned_scroll_bars (f, bar->next);
16771 else
16772
16773
16774 emacs_abort ();
16775 }
16776 else
16777 XSCROLL_BAR (bar->prev)->next = bar->next;
16778
16779 if (! NILP (bar->next))
16780 XSCROLL_BAR (bar->next)->prev = bar->prev;
16781
16782 bar->next = FRAME_SCROLL_BARS (f);
16783 bar->prev = Qnil;
16784 XSETVECTOR (barobj, bar);
16785 fset_scroll_bars (f, barobj);
16786 if (! NILP (bar->next))
16787 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
16788 }
16789
16790 horizontal:
16791 if (!NILP (w->horizontal_scroll_bar) && WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
16792 {
16793 bar = XSCROLL_BAR (w->horizontal_scroll_bar);
16794
16795 f = XFRAME (WINDOW_FRAME (w));
16796 if (NILP (bar->prev))
16797 {
16798
16799
16800 if (EQ (FRAME_SCROLL_BARS (f), w->horizontal_scroll_bar))
16801
16802 return;
16803 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
16804 w->horizontal_scroll_bar))
16805 fset_condemned_scroll_bars (f, bar->next);
16806 else
16807
16808
16809 emacs_abort ();
16810 }
16811 else
16812 XSCROLL_BAR (bar->prev)->next = bar->next;
16813
16814 if (! NILP (bar->next))
16815 XSCROLL_BAR (bar->next)->prev = bar->prev;
16816
16817 bar->next = FRAME_SCROLL_BARS (f);
16818 bar->prev = Qnil;
16819 XSETVECTOR (barobj, bar);
16820 fset_scroll_bars (f, barobj);
16821 if (! NILP (bar->next))
16822 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
16823 }
16824 }
16825
16826
16827
16828
16829 static void
16830 XTjudge_scroll_bars (struct frame *f)
16831 {
16832 Lisp_Object bar, next;
16833
16834 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
16835
16836
16837
16838 fset_condemned_scroll_bars (f, Qnil);
16839
16840 for (; ! NILP (bar); bar = next)
16841 {
16842 struct scroll_bar *b = XSCROLL_BAR (bar);
16843
16844 x_scroll_bar_remove (b);
16845
16846 next = b->next;
16847 b->next = b->prev = Qnil;
16848 }
16849
16850
16851
16852 }
16853
16854
16855 #ifndef USE_TOOLKIT_SCROLL_BARS
16856
16857
16858
16859 static void
16860 x_scroll_bar_handle_exposure (struct frame *f, XEvent *event)
16861 {
16862 int x, y, width, height;
16863 XRectangle rect, scroll_bar_rect, intersection;
16864 Lisp_Object bar, condemned;
16865 struct scroll_bar *b;
16866
16867 if (event->type == GraphicsExpose)
16868 {
16869 x = event->xgraphicsexpose.x;
16870 y = event->xgraphicsexpose.y;
16871 width = event->xgraphicsexpose.width;
16872 height = event->xgraphicsexpose.height;
16873 }
16874 else
16875 {
16876 x = event->xexpose.x;
16877 y = event->xexpose.y;
16878 width = event->xexpose.width;
16879 height = event->xexpose.height;
16880 }
16881
16882 rect.x = x;
16883 rect.y = y;
16884 rect.width = width;
16885 rect.height = height;
16886
16887
16888
16889 condemned = FRAME_CONDEMNED_SCROLL_BARS (f);
16890 for (bar = FRAME_SCROLL_BARS (f);
16891
16892
16893 !NILP (bar) || (bar = condemned,
16894 condemned = Qnil,
16895 !NILP (bar));
16896 bar = XSCROLL_BAR (bar)->next)
16897 {
16898 b = XSCROLL_BAR (bar);
16899
16900 scroll_bar_rect.x = b->left;
16901 scroll_bar_rect.y = b->top;
16902 scroll_bar_rect.width = b->width;
16903 scroll_bar_rect.height = b->height;
16904
16905 if (gui_intersect_rectangles (&rect,
16906 &scroll_bar_rect,
16907 &intersection))
16908 x_scroll_bar_redraw (b);
16909 }
16910 }
16911
16912
16913
16914
16915
16916 static void
16917 x_scroll_bar_redraw (struct scroll_bar *bar)
16918 {
16919 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
16920 GC gc = f->output_data.x->normal_gc;
16921
16922 if (f->output_data.x->scroll_bar_background_pixel != -1)
16923 XSetForeground (FRAME_X_DISPLAY (f), gc,
16924 f->output_data.x->scroll_bar_background_pixel);
16925 else
16926 XSetForeground (FRAME_X_DISPLAY (f), gc,
16927 FRAME_BACKGROUND_PIXEL (f));
16928
16929 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), gc,
16930 bar->left, bar->top, bar->width, bar->height);
16931
16932 XSetForeground (FRAME_X_DISPLAY (f), gc,
16933 FRAME_FOREGROUND_PIXEL (f));
16934
16935 x_scroll_bar_set_handle (bar, bar->start, bar->end, true);
16936
16937
16938 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
16939 XSetForeground (FRAME_X_DISPLAY (f), gc,
16940 f->output_data.x->scroll_bar_foreground_pixel);
16941
16942
16943 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), gc,
16944 bar->left, bar->top, bar->width - 1, bar->height - 1);
16945
16946
16947 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
16948 XSetForeground (FRAME_X_DISPLAY (f), gc,
16949 FRAME_FOREGROUND_PIXEL (f));
16950 }
16951 #endif
16952
16953
16954
16955
16956
16957
16958
16959
16960 static void
16961 x_scroll_bar_handle_click (struct scroll_bar *bar,
16962 const XEvent *event,
16963 struct input_event *emacs_event,
16964 Lisp_Object device)
16965 {
16966 int left_range, x, top_range, y;
16967 #ifndef USE_TOOLKIT_SCROLL_BARS
16968 int new_start, new_end;
16969 #endif
16970
16971 if (! WINDOWP (bar->window))
16972 emacs_abort ();
16973
16974 emacs_event->kind = (bar->horizontal
16975 ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT
16976 : SCROLL_BAR_CLICK_EVENT);
16977 emacs_event->code = event->xbutton.button - Button1;
16978 emacs_event->modifiers
16979 = (x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO
16980 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
16981 event->xbutton.state)
16982 | (event->type == ButtonRelease
16983 ? up_modifier
16984 : down_modifier));
16985 emacs_event->frame_or_window = bar->window;
16986 emacs_event->arg = Qnil;
16987 emacs_event->timestamp = event->xbutton.time;
16988
16989 if (!NILP (device))
16990 emacs_event->device = device;
16991
16992 if (bar->horizontal)
16993 {
16994
16995 left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width);
16996 x = event->xbutton.x - HORIZONTAL_SCROLL_BAR_LEFT_BORDER;
16997
16998 if (x < 0) x = 0;
16999 if (x > left_range) x = left_range;
17000
17001 if (x < bar->start)
17002 emacs_event->part = scroll_bar_before_handle;
17003 else if (x < bar->end + HORIZONTAL_SCROLL_BAR_MIN_HANDLE)
17004 emacs_event->part = scroll_bar_horizontal_handle;
17005 else
17006 emacs_event->part = scroll_bar_after_handle;
17007
17008 #ifndef USE_TOOLKIT_SCROLL_BARS
17009
17010 if (event->type == ButtonRelease && bar->dragging != -1)
17011 {
17012 new_start = - bar->dragging;
17013 new_end = new_start + bar->end - bar->start;
17014
17015 x_scroll_bar_set_handle (bar, new_start, new_end, false);
17016 bar->dragging = -1;
17017 }
17018 #endif
17019
17020 XSETINT (emacs_event->x, left_range);
17021 XSETINT (emacs_event->y, x);
17022 }
17023 else
17024 {
17025 top_range
17026 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
17027 y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
17028
17029 if (y < 0) y = 0;
17030 if (y > top_range) y = top_range;
17031
17032 if (y < bar->start)
17033 emacs_event->part = scroll_bar_above_handle;
17034 else if (y < bar->end + VERTICAL_SCROLL_BAR_MIN_HANDLE)
17035 emacs_event->part = scroll_bar_handle;
17036 else
17037 emacs_event->part = scroll_bar_below_handle;
17038
17039 #ifndef USE_TOOLKIT_SCROLL_BARS
17040
17041 if (event->type == ButtonRelease && bar->dragging != -1)
17042 {
17043 new_start = y - bar->dragging;
17044 new_end = new_start + bar->end - bar->start;
17045
17046 x_scroll_bar_set_handle (bar, new_start, new_end, false);
17047 bar->dragging = -1;
17048 }
17049 #endif
17050
17051 XSETINT (emacs_event->x, y);
17052 XSETINT (emacs_event->y, top_range);
17053 }
17054 }
17055
17056 #ifndef USE_TOOLKIT_SCROLL_BARS
17057
17058
17059
17060
17061
17062
17063 static void
17064 x_scroll_bar_note_movement (struct scroll_bar *bar,
17065 const XMotionEvent *event)
17066 {
17067 struct frame *f = XFRAME (XWINDOW (bar->window)->frame);
17068 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
17069
17070 dpyinfo->last_mouse_movement_time = event->time;
17071 dpyinfo->last_mouse_movement_time_send_event = event->send_event;
17072 dpyinfo->last_mouse_scroll_bar = bar;
17073 f->mouse_moved = true;
17074
17075
17076 if (bar->dragging != -1)
17077 {
17078
17079 int new_start = event->y - bar->dragging;
17080
17081 if (new_start != bar->start)
17082 {
17083 int new_end = new_start + bar->end - bar->start;
17084
17085 x_scroll_bar_set_handle (bar, new_start, new_end, false);
17086 }
17087 }
17088 }
17089
17090 #endif
17091
17092
17093
17094
17095 static void
17096 x_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
17097 enum scroll_bar_part *part, Lisp_Object *x,
17098 Lisp_Object *y, Time *timestamp)
17099 {
17100 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp);
17101 struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar;
17102 Window w = bar->x_window;
17103 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
17104 int win_x, win_y;
17105 Window dummy_window;
17106 int dummy_coord;
17107 unsigned int dummy_mask;
17108
17109 block_input ();
17110
17111
17112
17113 if (x_query_pointer (FRAME_X_DISPLAY (f), w,
17114
17115
17116 &dummy_window, &dummy_window,
17117 &dummy_coord, &dummy_coord,
17118
17119
17120 &win_x, &win_y,
17121
17122
17123 &dummy_mask))
17124 {
17125 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
17126
17127 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
17128
17129 if (bar->dragging != -1)
17130 win_y -= bar->dragging;
17131
17132 if (win_y < 0)
17133 win_y = 0;
17134 if (win_y > top_range)
17135 win_y = top_range;
17136
17137 *fp = f;
17138 *bar_window = bar->window;
17139
17140 if (bar->dragging != -1)
17141 *part = scroll_bar_handle;
17142 else if (win_y < bar->start)
17143 *part = scroll_bar_above_handle;
17144 else if (win_y < bar->end + VERTICAL_SCROLL_BAR_MIN_HANDLE)
17145 *part = scroll_bar_handle;
17146 else
17147 *part = scroll_bar_below_handle;
17148
17149 XSETINT (*x, win_y);
17150 XSETINT (*y, top_range);
17151
17152 f->mouse_moved = false;
17153 dpyinfo->last_mouse_scroll_bar = NULL;
17154 *timestamp = dpyinfo->last_mouse_movement_time;
17155 }
17156
17157 unblock_input ();
17158 }
17159
17160
17161
17162
17163
17164 static void
17165 x_horizontal_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
17166 enum scroll_bar_part *part, Lisp_Object *x,
17167 Lisp_Object *y, Time *timestamp)
17168 {
17169 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp);
17170 struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar;
17171 Window w = bar->x_window;
17172 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
17173 int win_x, win_y;
17174 Window dummy_window;
17175 int dummy_coord;
17176 unsigned int dummy_mask;
17177
17178 block_input ();
17179
17180
17181
17182 if (x_query_pointer (FRAME_X_DISPLAY (f), w,
17183
17184
17185 &dummy_window, &dummy_window,
17186 &dummy_coord, &dummy_coord,
17187
17188
17189 &win_x, &win_y,
17190
17191
17192 &dummy_mask))
17193 {
17194 int left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width);
17195
17196 win_x -= HORIZONTAL_SCROLL_BAR_LEFT_BORDER;
17197
17198 if (bar->dragging != -1)
17199 win_x -= bar->dragging;
17200
17201 if (win_x < 0)
17202 win_x = 0;
17203 if (win_x > left_range)
17204 win_x = left_range;
17205
17206 *fp = f;
17207 *bar_window = bar->window;
17208
17209 if (bar->dragging != -1)
17210 *part = scroll_bar_horizontal_handle;
17211 else if (win_x < bar->start)
17212 *part = scroll_bar_before_handle;
17213 else if (win_x < bar->end + HORIZONTAL_SCROLL_BAR_MIN_HANDLE)
17214 *part = scroll_bar_handle;
17215 else
17216 *part = scroll_bar_after_handle;
17217
17218 XSETINT (*y, win_x);
17219 XSETINT (*x, left_range);
17220
17221 f->mouse_moved = false;
17222 dpyinfo->last_mouse_scroll_bar = NULL;
17223 *timestamp = dpyinfo->last_mouse_movement_time;
17224 }
17225
17226 unblock_input ();
17227 }
17228
17229
17230
17231
17232
17233
17234 static void
17235 x_scroll_bar_clear (struct frame *f)
17236 {
17237 #ifndef USE_TOOLKIT_SCROLL_BARS
17238 Lisp_Object bar, condemned;
17239 GC gc = f->output_data.x->normal_gc;
17240
17241 if (f->output_data.x->scroll_bar_background_pixel != -1)
17242 XSetForeground (FRAME_X_DISPLAY (f), gc,
17243 f->output_data.x->scroll_bar_background_pixel);
17244 else
17245 XSetForeground (FRAME_X_DISPLAY (f), gc,
17246 FRAME_BACKGROUND_PIXEL (f));
17247
17248
17249
17250
17251 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
17252 {
17253 condemned = FRAME_CONDEMNED_SCROLL_BARS (f);
17254 for (bar = FRAME_SCROLL_BARS (f);
17255
17256
17257 !NILP (bar) || (bar = condemned,
17258 condemned = Qnil,
17259 !NILP (bar));
17260 bar = XSCROLL_BAR (bar)->next)
17261 x_scroll_bar_redraw (XSCROLL_BAR (bar));
17262 }
17263
17264 XSetForeground (FRAME_X_DISPLAY (f), gc,
17265 FRAME_FOREGROUND_PIXEL (f));
17266 #endif
17267 }
17268
17269 #ifdef ENABLE_CHECKING
17270
17271
17272
17273
17274 static int temp_index;
17275 static short temp_buffer[100];
17276
17277 #define STORE_KEYSYM_FOR_DEBUG(keysym) \
17278 if (temp_index == ARRAYELTS (temp_buffer)) \
17279 temp_index = 0; \
17280 temp_buffer[temp_index++] = (keysym)
17281
17282 #else
17283
17284 #define STORE_KEYSYM_FOR_DEBUG(keysym) ((void)0)
17285
17286 #endif
17287
17288
17289
17290
17291 static struct x_display_info *XTread_socket_fake_io_error;
17292
17293
17294
17295
17296
17297
17298 static struct x_display_info *next_noop_dpyinfo;
17299
17300
17301
17302
17303
17304
17305
17306
17307
17308 #ifdef HAVE_X_I18N
17309 static int
17310 x_filter_event (struct x_display_info *dpyinfo, XEvent *event)
17311 {
17312
17313
17314
17315
17316
17317 struct frame *f1;
17318
17319 #if defined HAVE_XINPUT2 && defined USE_GTK
17320 bool xinput_event = false;
17321 if (dpyinfo->supports_xi2
17322 && event->type == GenericEvent
17323 && (event->xgeneric.extension
17324 == dpyinfo->xi2_opcode)
17325 && ((event->xgeneric.evtype
17326 == XI_KeyPress)
17327 || (event->xgeneric.evtype
17328 == XI_KeyRelease)))
17329 {
17330 f1 = x_any_window_to_frame (dpyinfo,
17331 ((XIDeviceEvent *)
17332 event->xcookie.data)->event);
17333 xinput_event = true;
17334 }
17335 else
17336 #endif
17337 f1 = x_any_window_to_frame (dpyinfo,
17338 event->xclient.window);
17339
17340 #ifdef USE_GTK
17341 if (!x_gtk_use_native_input
17342 && !dpyinfo->prefer_native_input)
17343 {
17344 #endif
17345 return XFilterEvent (event, f1 ? FRAME_X_WINDOW (f1) : None);
17346 #ifdef USE_GTK
17347 }
17348 else if (f1 && (event->type == KeyPress
17349 || event->type == KeyRelease
17350 #ifdef HAVE_XINPUT2
17351 || xinput_event
17352 #endif
17353 ))
17354 {
17355 bool result;
17356
17357 block_input ();
17358 result = xg_filter_key (f1, event);
17359 unblock_input ();
17360
17361
17362
17363
17364
17365 if (popup_activated ())
17366 xg_pending_quit_event.kind = NO_EVENT;
17367
17368 if (result && f1)
17369
17370
17371 XNoOp (FRAME_X_DISPLAY (f1));
17372
17373 return result;
17374 }
17375
17376 return 0;
17377 #endif
17378 }
17379 #endif
17380
17381 #ifdef USE_GTK
17382
17383
17384
17385 static GdkFilterReturn
17386 event_handler_gdk (GdkXEvent *gxev, GdkEvent *ev, gpointer data)
17387 {
17388 XEvent *xev = (XEvent *) gxev;
17389
17390 block_input ();
17391 if (current_count >= 0)
17392 {
17393 struct x_display_info *dpyinfo;
17394
17395 dpyinfo = x_display_info_for_display (xev->xany.display);
17396
17397 #ifdef HAVE_X_I18N
17398
17399
17400
17401 if ((xev->type == KeyPress || xev->type == KeyRelease)
17402 && dpyinfo
17403 && x_filter_event (dpyinfo, xev))
17404 {
17405 unblock_input ();
17406 return GDK_FILTER_REMOVE;
17407 }
17408 #elif USE_GTK
17409 if (dpyinfo && (dpyinfo->prefer_native_input
17410 || x_gtk_use_native_input)
17411 && (xev->type == KeyPress
17412 #ifdef HAVE_XINPUT2
17413
17414
17415 || (dpyinfo->supports_xi2
17416 && xev->type == GenericEvent
17417 && (xev->xgeneric.extension
17418 == dpyinfo->xi2_opcode)
17419 && ((xev->xgeneric.evtype
17420 == XI_KeyPress)
17421 || (xev->xgeneric.evtype
17422 == XI_KeyRelease)))
17423 #endif
17424 ))
17425 {
17426 struct frame *f;
17427
17428 #ifdef HAVE_XINPUT2
17429 if (xev->type == GenericEvent)
17430 f = x_any_window_to_frame (dpyinfo,
17431 ((XIDeviceEvent *) xev->xcookie.data)->event);
17432 else
17433 #endif
17434 f = x_any_window_to_frame (dpyinfo, xev->xany.window);
17435
17436 if (f && xg_filter_key (f, xev))
17437 {
17438 unblock_input ();
17439 return GDK_FILTER_REMOVE;
17440 }
17441 }
17442 #endif
17443
17444 if (! dpyinfo)
17445 current_finish = X_EVENT_NORMAL;
17446 else
17447 current_count
17448 += handle_one_xevent (dpyinfo, xev, ¤t_finish,
17449 current_hold_quit);
17450 }
17451 else
17452 current_finish = x_dispatch_event (xev, xev->xany.display);
17453
17454 unblock_input ();
17455
17456 if (current_finish == X_EVENT_GOTO_OUT || current_finish == X_EVENT_DROP)
17457 return GDK_FILTER_REMOVE;
17458
17459 return GDK_FILTER_CONTINUE;
17460 }
17461 #endif
17462
17463
17464 static void xembed_send_message (struct frame *f, Time,
17465 enum xembed_message,
17466 long detail, long data1, long data2);
17467
17468 static void
17469 x_net_wm_state (struct frame *f, Window window)
17470 {
17471 int value = FULLSCREEN_NONE;
17472 Lisp_Object lval = Qnil;
17473 bool sticky = false, shaded = false;
17474
17475 x_get_current_wm_state (f, window, &value, &sticky, &shaded);
17476
17477 switch (value)
17478 {
17479 case FULLSCREEN_WIDTH:
17480 lval = Qfullwidth;
17481 break;
17482 case FULLSCREEN_HEIGHT:
17483 lval = Qfullheight;
17484 break;
17485 case FULLSCREEN_BOTH:
17486 lval = Qfullboth;
17487 break;
17488 case FULLSCREEN_MAXIMIZED:
17489 lval = Qmaximized;
17490 break;
17491 }
17492
17493 store_frame_param (f, Qfullscreen, lval);
17494 store_frame_param (f, Qsticky, sticky ? Qt : Qnil);
17495 store_frame_param (f, Qshaded, shaded ? Qt : Qnil);
17496 }
17497
17498
17499
17500 static void
17501 x_flush_dirty_back_buffer_on (struct frame *f)
17502 {
17503 #ifdef HAVE_XDBE
17504 if (FRAME_GARBAGED_P (f)
17505 || buffer_flipping_blocked_p ()
17506
17507
17508 || !FRAME_X_COMPLETE_P (f)
17509 || !FRAME_X_NEED_BUFFER_FLIP (f))
17510 return;
17511
17512 show_back_buffer (f);
17513 #endif
17514 }
17515
17516 #ifdef HAVE_GTK3
17517 void
17518 x_scroll_bar_configure (GdkEvent *event)
17519 {
17520 XEvent configure;
17521 GdkDisplay *gdpy;
17522 Display *dpy;
17523
17524 configure.xconfigure.type = ConfigureNotify;
17525 configure.xconfigure.serial = 0;
17526 configure.xconfigure.send_event = event->configure.send_event;
17527 configure.xconfigure.x = event->configure.x;
17528 configure.xconfigure.y = event->configure.y;
17529 configure.xconfigure.width = event->configure.width;
17530 configure.xconfigure.height = event->configure.height;
17531 configure.xconfigure.border_width = 0;
17532 configure.xconfigure.event = GDK_WINDOW_XID (event->configure.window);
17533 configure.xconfigure.window = GDK_WINDOW_XID (event->configure.window);
17534 configure.xconfigure.above = None;
17535 configure.xconfigure.override_redirect = False;
17536
17537 gdpy = gdk_window_get_display (event->configure.window);
17538 dpy = gdk_x11_display_get_xdisplay (gdpy);
17539
17540 x_dispatch_event (&configure, dpy);
17541 }
17542 #endif
17543
17544
17545
17546
17547
17548
17549
17550
17551
17552 static struct frame *
17553 mouse_or_wdesc_frame (struct x_display_info *dpyinfo, int wdesc)
17554 {
17555 struct frame *lm_f = (gui_mouse_grabbed (dpyinfo)
17556 ? dpyinfo->last_mouse_frame
17557 : NULL);
17558
17559 if (lm_f && !EQ (track_mouse, Qdropping)
17560 && !EQ (track_mouse, Qdrag_source))
17561 return lm_f;
17562 else
17563 {
17564 struct frame *w_f = x_window_to_frame (dpyinfo, wdesc);
17565
17566
17567 if (!w_f || FRAME_TOOLTIP_P (w_f))
17568 return EQ (track_mouse, Qdropping) ? lm_f : NULL;
17569 else
17570
17571
17572 return w_f;
17573 }
17574 }
17575
17576 static void
17577 x_dnd_compute_tip_xy (int *root_x, int *root_y, Lisp_Object attributes)
17578 {
17579 Lisp_Object monitor, geometry;
17580 int min_x, min_y, max_x, max_y;
17581 int width, height;
17582
17583 width = FRAME_PIXEL_WIDTH (XFRAME (tip_frame));
17584 height = FRAME_PIXEL_HEIGHT (XFRAME (tip_frame));
17585
17586 max_y = -1;
17587
17588
17589
17590 while (CONSP (attributes))
17591 {
17592 monitor = XCAR (attributes);
17593 geometry = assq_no_quit (Qgeometry, monitor);
17594
17595 if (CONSP (geometry))
17596 {
17597 min_x = XFIXNUM (Fnth (make_fixnum (1), geometry));
17598 min_y = XFIXNUM (Fnth (make_fixnum (2), geometry));
17599 max_x = min_x + XFIXNUM (Fnth (make_fixnum (3), geometry));
17600 max_y = min_y + XFIXNUM (Fnth (make_fixnum (4), geometry));
17601
17602 if (min_x <= *root_x && *root_x < max_x
17603 && min_y <= *root_y && *root_y < max_y)
17604 break;
17605
17606 max_y = -1;
17607 }
17608
17609 attributes = XCDR (attributes);
17610 }
17611
17612
17613
17614 if (max_y < 0)
17615 {
17616 min_x = 0;
17617 min_y = 0;
17618 max_x = x_display_pixel_width (FRAME_DISPLAY_INFO (x_dnd_frame));
17619 max_y = x_display_pixel_height (FRAME_DISPLAY_INFO (x_dnd_frame));
17620 }
17621
17622 if (*root_y + XFIXNUM (tip_dy) <= min_y)
17623 *root_y = min_y;
17624 else if (*root_y + XFIXNUM (tip_dy) + height <= max_y)
17625
17626 *root_y += XFIXNUM (tip_dy);
17627 else if (height + XFIXNUM (tip_dy) + min_y <= *root_y)
17628
17629 *root_y -= height + XFIXNUM (tip_dy);
17630 else
17631
17632 *root_y = min_y;
17633
17634 if (*root_x + XFIXNUM (tip_dx) <= min_x)
17635 *root_x = 0;
17636 else if (*root_x + XFIXNUM (tip_dx) + width <= max_x)
17637
17638 *root_x += XFIXNUM (tip_dx);
17639 else if (width + XFIXNUM (tip_dx) + min_x <= *root_x)
17640
17641 *root_x -= width + XFIXNUM (tip_dx);
17642 else
17643
17644 *root_x = min_x;
17645 }
17646
17647 static void
17648 x_dnd_update_tooltip_position (int root_x, int root_y)
17649 {
17650 struct frame *tip_f;
17651
17652 if (!x_dnd_in_progress || !x_dnd_update_tooltip)
17653 return;
17654
17655 if (!FRAMEP (tip_frame))
17656 return;
17657
17658 tip_f = XFRAME (tip_frame);
17659
17660 if (!FRAME_LIVE_P (tip_f)
17661 || !FRAME_VISIBLE_P (tip_f)
17662 || (FRAME_X_DISPLAY (tip_f)
17663 != FRAME_X_DISPLAY (x_dnd_frame)))
17664 return;
17665
17666 if (tip_window != None
17667 && FIXNUMP (tip_dx) && FIXNUMP (tip_dy))
17668 {
17669 x_dnd_compute_tip_xy (&root_x, &root_y,
17670 x_dnd_monitors);
17671
17672 if (x_dnd_last_tooltip_valid
17673 && root_x == x_dnd_last_tooltip_x
17674 && root_y == x_dnd_last_tooltip_y)
17675 return;
17676
17677 x_dnd_last_tooltip_x = root_x;
17678 x_dnd_last_tooltip_y = root_y;
17679 x_dnd_last_tooltip_valid = true;
17680
17681 XMoveWindow (FRAME_X_DISPLAY (x_dnd_frame),
17682 tip_window, root_x, root_y);
17683 }
17684 }
17685
17686 static void
17687 x_dnd_update_tooltip_now (void)
17688 {
17689 int root_x, root_y;
17690 Window root, child;
17691 int win_x, win_y;
17692 unsigned int mask;
17693 Bool rc;
17694 struct x_display_info *dpyinfo;
17695
17696 if (!x_dnd_in_progress || !x_dnd_update_tooltip)
17697 return;
17698
17699 dpyinfo = FRAME_DISPLAY_INFO (x_dnd_frame);
17700
17701 #ifndef HAVE_XINPUT2
17702 rc = XQueryPointer (dpyinfo->display,
17703 dpyinfo->root_window,
17704 &root, &child, &root_x,
17705 &root_y, &win_x, &win_y,
17706 &mask);
17707 #else
17708 rc = x_query_pointer_1 (dpyinfo, x_dnd_pointer_device,
17709 dpyinfo->root_window,
17710 &root, &child, &root_x,
17711 &root_y, &win_x, &win_y,
17712 &mask);
17713 #endif
17714
17715 if (rc)
17716 x_dnd_update_tooltip_position (root_x, root_y);
17717 }
17718
17719
17720
17721 static void
17722 x_dnd_update_state (struct x_display_info *dpyinfo, Time timestamp)
17723 {
17724 int root_x, root_y, dummy_x, dummy_y, target_proto, motif_style;
17725 unsigned int dummy_mask;
17726 Window dummy, dummy_child, target, toplevel;
17727 xm_top_level_leave_message lmsg;
17728 xm_top_level_enter_message emsg;
17729 xm_drag_motion_message dmsg;
17730 xm_drop_start_message dsmsg;
17731 bool was_frame;
17732
17733 if (x_query_pointer_1 (dpyinfo,
17734 #ifdef HAVE_XINPUT2
17735 x_dnd_pointer_device,
17736 #else
17737 -1,
17738 #endif
17739 dpyinfo->root_window,
17740 &dummy, &dummy_child,
17741 &root_x, &root_y,
17742 &dummy_x, &dummy_y,
17743 &dummy_mask))
17744 {
17745 target = x_dnd_get_target_window (dpyinfo, root_x,
17746 root_y, &target_proto,
17747 &motif_style, &toplevel,
17748 &was_frame);
17749
17750 if (toplevel != x_dnd_last_seen_toplevel)
17751 {
17752 if (toplevel != FRAME_OUTER_WINDOW (x_dnd_frame)
17753 && x_dnd_return_frame == 1)
17754 x_dnd_return_frame = 2;
17755
17756 if (x_dnd_return_frame == 2
17757 && x_any_window_to_frame (dpyinfo, toplevel))
17758 {
17759 if (x_dnd_last_seen_window != None
17760 && x_dnd_last_protocol_version != -1
17761 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
17762 x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window,
17763 x_dnd_last_seen_toplevel);
17764 else if (x_dnd_last_seen_window != None
17765 && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
17766 && !x_dnd_disable_motif_drag
17767 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
17768 {
17769 if (!x_dnd_motif_setup_p)
17770 xm_setup_drag_info (dpyinfo, x_dnd_frame);
17771
17772 lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
17773 XM_DRAG_REASON_TOP_LEVEL_LEAVE);
17774 lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
17775 lmsg.zero = 0;
17776 lmsg.timestamp = timestamp;
17777 lmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
17778
17779 if (x_dnd_motif_setup_p)
17780 xm_send_top_level_leave_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
17781 x_dnd_last_seen_window, &lmsg);
17782 }
17783
17784 x_dnd_end_window = x_dnd_last_seen_window;
17785 x_dnd_last_seen_window = None;
17786 x_dnd_last_seen_toplevel = None;
17787 x_dnd_in_progress = false;
17788 x_dnd_return_frame_object
17789 = x_any_window_to_frame (dpyinfo, toplevel);
17790 x_dnd_return_frame = 3;
17791 x_dnd_waiting_for_finish = false;
17792 target = None;
17793 }
17794 }
17795
17796 if (target != x_dnd_last_seen_window)
17797 {
17798 if (x_dnd_last_seen_window != None
17799 && x_dnd_last_protocol_version != -1
17800 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
17801 x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window,
17802 x_dnd_last_seen_toplevel);
17803 else if (x_dnd_last_seen_window != None
17804 && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
17805 && !x_dnd_disable_motif_drag
17806 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
17807 {
17808 if (!x_dnd_motif_setup_p)
17809 xm_setup_drag_info (dpyinfo, x_dnd_frame);
17810
17811 lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
17812 XM_DRAG_REASON_TOP_LEVEL_LEAVE);
17813 lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
17814 lmsg.zero = 0;
17815 lmsg.timestamp = timestamp;
17816 lmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
17817
17818 if (x_dnd_motif_setup_p)
17819 xm_send_top_level_leave_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
17820 x_dnd_last_seen_window, &lmsg);
17821 }
17822
17823 x_dnd_action = None;
17824 x_dnd_last_seen_toplevel = toplevel;
17825 x_dnd_last_seen_window = target;
17826 x_dnd_last_protocol_version = target_proto;
17827 x_dnd_last_motif_style = motif_style;
17828 x_dnd_last_window_is_frame = was_frame;
17829
17830 if (target != None && x_dnd_last_protocol_version != -1)
17831 x_dnd_send_enter (x_dnd_frame, target, x_dnd_last_seen_toplevel,
17832 x_dnd_last_protocol_version);
17833 else if (target != None && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
17834 && !x_dnd_disable_motif_drag)
17835 {
17836 if (!x_dnd_motif_setup_p)
17837 xm_setup_drag_info (dpyinfo, x_dnd_frame);
17838
17839 emsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
17840 XM_DRAG_REASON_TOP_LEVEL_ENTER);
17841 emsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
17842 emsg.zero = 0;
17843 emsg.timestamp = timestamp;
17844 emsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
17845 emsg.index_atom = x_dnd_motif_atom;
17846
17847 if (x_dnd_motif_setup_p)
17848 xm_send_top_level_enter_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
17849 target, &emsg);
17850 }
17851 }
17852 else
17853 x_dnd_last_seen_toplevel = toplevel;
17854
17855 if (x_dnd_last_window_is_frame && target != None)
17856 x_dnd_note_self_position (dpyinfo, target, root_x, root_y);
17857 else if (x_dnd_last_protocol_version != -1 && target != None)
17858 x_dnd_send_position (x_dnd_frame, target,
17859 x_dnd_last_seen_toplevel,
17860 x_dnd_last_protocol_version,
17861 root_x, root_y,
17862 x_dnd_selection_timestamp,
17863 x_dnd_wanted_action, 0,
17864 #ifdef HAVE_XKB
17865 x_dnd_keyboard_state
17866 #else
17867 0
17868 #endif
17869 );
17870 else if (XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) && target != None
17871 && !x_dnd_disable_motif_drag)
17872 {
17873 if (!x_dnd_motif_setup_p)
17874 xm_setup_drag_info (dpyinfo, x_dnd_frame);
17875
17876 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
17877 XM_DRAG_REASON_DRAG_MOTION);
17878 dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
17879 dmsg.side_effects
17880 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
17881 x_dnd_wanted_action),
17882 XM_DROP_SITE_VALID, x_dnd_motif_operations,
17883 (!x_dnd_xm_use_help
17884 ? XM_DROP_ACTION_DROP
17885 : XM_DROP_ACTION_DROP_HELP));
17886 dmsg.timestamp = timestamp;
17887 dmsg.x = root_x;
17888 dmsg.y = root_y;
17889
17890 if (x_dnd_motif_setup_p)
17891 xm_send_drag_motion_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
17892 target, &dmsg);
17893 }
17894
17895 x_dnd_update_tooltip_position (root_x, root_y);
17896 }
17897
17898 else if (x_dnd_last_protocol_version != -1)
17899 {
17900 if (x_dnd_last_seen_window != None
17901 && x_dnd_last_protocol_version != -1)
17902 x_dnd_send_leave (x_dnd_frame,
17903 x_dnd_last_seen_window,
17904 x_dnd_last_seen_toplevel);
17905 else if (x_dnd_last_seen_window != None
17906 && !XM_DRAG_STYLE_IS_DROP_ONLY (x_dnd_last_motif_style)
17907 && x_dnd_last_motif_style != XM_DRAG_STYLE_NONE
17908 && x_dnd_motif_setup_p)
17909 {
17910 dsmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
17911 XM_DRAG_REASON_DROP_START);
17912 dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
17913 dsmsg.timestamp = timestamp;
17914 dsmsg.side_effects
17915 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
17916 x_dnd_wanted_action),
17917 XM_DROP_SITE_VALID, x_dnd_motif_operations,
17918 XM_DROP_ACTION_DROP_CANCEL);
17919 dsmsg.x = 0;
17920 dsmsg.y = 0;
17921 dsmsg.index_atom = x_dnd_motif_atom;
17922 dsmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
17923
17924 x_dnd_send_xm_leave_for_drop (dpyinfo, x_dnd_frame,
17925 x_dnd_last_seen_window, timestamp);
17926 xm_send_drop_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
17927 x_dnd_last_seen_window, &dsmsg);
17928 }
17929
17930 x_dnd_end_window = x_dnd_last_seen_window;
17931 x_dnd_last_seen_window = None;
17932 x_dnd_last_seen_toplevel = None;
17933 x_dnd_in_progress = false;
17934 x_dnd_waiting_for_finish = false;
17935 x_dnd_frame = NULL;
17936 }
17937 }
17938
17939 int
17940 x_display_pixel_height (struct x_display_info *dpyinfo)
17941 {
17942 if (dpyinfo->screen_height)
17943 return dpyinfo->screen_height;
17944
17945 return HeightOfScreen (dpyinfo->screen);
17946 }
17947
17948 int
17949 x_display_pixel_width (struct x_display_info *dpyinfo)
17950 {
17951 if (dpyinfo->screen_width)
17952 return dpyinfo->screen_width;
17953
17954 return WidthOfScreen (dpyinfo->screen);
17955 }
17956
17957
17958
17959 void
17960 x_wait_for_cell_change (Lisp_Object cell, struct timespec timeout)
17961 {
17962 struct x_display_info *dpyinfo;
17963 fd_set fds;
17964 int fd, maxfd;
17965 #ifndef USE_GTK
17966 int finish, rc;
17967 XEvent event;
17968 fd_set rfds;
17969 #endif
17970 struct input_event hold_quit;
17971 struct timespec current, at;
17972
17973 at = timespec_add (current_timespec (), timeout);
17974
17975 #ifndef USE_GTK
17976 FD_ZERO (&rfds);
17977 rc = -1;
17978 #endif
17979
17980 while (true)
17981 {
17982 FD_ZERO (&fds);
17983 maxfd = -1;
17984
17985 for (dpyinfo = x_display_list; dpyinfo;
17986 dpyinfo = dpyinfo->next)
17987 {
17988 fd = ConnectionNumber (dpyinfo->display);
17989
17990 #ifndef USE_GTK
17991 if ((rc < 0 || FD_ISSET (fd, &rfds))
17992
17993
17994 && XPending (dpyinfo->display))
17995 {
17996 while (XPending (dpyinfo->display))
17997 {
17998 EVENT_INIT (hold_quit);
17999
18000 XNextEvent (dpyinfo->display, &event);
18001 handle_one_xevent (dpyinfo, &event,
18002 &finish, &hold_quit);
18003
18004 if (!NILP (XCAR (cell)))
18005 return;
18006
18007 if (finish == X_EVENT_GOTO_OUT)
18008 break;
18009
18010
18011 if (hold_quit.kind != NO_EVENT)
18012 kbd_buffer_store_event (&hold_quit);
18013 }
18014 }
18015 #endif
18016
18017 if (fd > maxfd)
18018 maxfd = fd;
18019
18020 eassert (fd < FD_SETSIZE);
18021 FD_SET (fd, &fds);
18022 }
18023
18024
18025
18026 #ifdef USE_GTK
18027 while (gtk_events_pending ())
18028 {
18029 EVENT_INIT (hold_quit);
18030 current_count = 0;
18031 current_hold_quit = &hold_quit;
18032 current_finish = X_EVENT_NORMAL;
18033
18034 gtk_main_iteration ();
18035
18036 current_count = -1;
18037 current_hold_quit = NULL;
18038
18039
18040 if (hold_quit.kind != NO_EVENT)
18041 kbd_buffer_store_event (&hold_quit);
18042
18043 if (!NILP (XCAR (cell)))
18044 return;
18045
18046 if (current_finish == X_EVENT_GOTO_OUT)
18047 break;
18048 }
18049 #endif
18050
18051 eassert (maxfd >= 0);
18052
18053 current = current_timespec ();
18054
18055 if (timespec_cmp (at, current) < 0
18056 || !NILP (XCAR (cell)))
18057 return;
18058
18059 timeout = timespec_sub (at, current);
18060
18061 #ifndef USE_GTK
18062 rc = pselect (maxfd + 1, &fds, NULL, NULL, &timeout, NULL);
18063
18064 if (rc >= 0)
18065 rfds = fds;
18066 #else
18067 pselect (maxfd + 1, &fds, NULL, NULL, &timeout, NULL);
18068 #endif
18069 }
18070 }
18071
18072
18073
18074
18075
18076 static bool
18077 x_find_monitors_changed_event (struct x_display_info *dpyinfo)
18078 {
18079 union buffered_input_event *event;
18080
18081 event = kbd_fetch_ptr;
18082
18083 while (event != kbd_store_ptr)
18084 {
18085 if (event->ie.kind == MONITORS_CHANGED_EVENT
18086 && XTERMINAL (event->ie.arg) == dpyinfo->terminal)
18087 return true;
18088
18089 event = X_NEXT_KBD_EVENT (event);
18090 }
18091
18092 return false;
18093 }
18094
18095 #ifdef USE_GTK
18096 static void
18097 x_monitors_changed_cb (GdkScreen *gscr, gpointer user_data)
18098 {
18099 struct x_display_info *dpyinfo;
18100 struct input_event ie;
18101 Lisp_Object current_monitors, terminal;
18102 GdkDisplay *gdpy;
18103 Display *dpy;
18104
18105 gdpy = gdk_screen_get_display (gscr);
18106 dpy = gdk_x11_display_get_xdisplay (gdpy);
18107 dpyinfo = x_display_info_for_display (dpy);
18108
18109 if (!dpyinfo)
18110 return;
18111
18112 if (x_find_monitors_changed_event (dpyinfo))
18113 return;
18114
18115 XSETTERMINAL (terminal, dpyinfo->terminal);
18116
18117 current_monitors
18118 = Fx_display_monitor_attributes_list (terminal);
18119
18120 if (NILP (Fequal (current_monitors,
18121 dpyinfo->last_monitor_attributes_list)))
18122 {
18123 EVENT_INIT (ie);
18124 ie.kind = MONITORS_CHANGED_EVENT;
18125 ie.arg = terminal;
18126
18127 kbd_buffer_store_event (&ie);
18128
18129 if (x_dnd_in_progress && x_dnd_update_tooltip)
18130 x_dnd_monitors = current_monitors;
18131
18132 x_dnd_update_tooltip_now ();
18133 }
18134
18135 dpyinfo->last_monitor_attributes_list = current_monitors;
18136 }
18137 #endif
18138
18139
18140
18141
18142 static bool
18143 x_coords_from_dnd_message (struct x_display_info *dpyinfo,
18144 XEvent *event, int *x_out, int *y_out)
18145 {
18146 xm_drag_motion_message dmsg;
18147 xm_drag_motion_reply dreply;
18148 xm_drop_start_message smsg;
18149 xm_drop_start_reply reply;
18150 unsigned long kde_data;
18151
18152 if (event->type != ClientMessage)
18153 return false;
18154
18155 if (event->xclient.message_type == dpyinfo->Xatom_XdndPosition)
18156 {
18157 if (event->xclient.format != 32)
18158 return false;
18159
18160 *x_out = (((unsigned long) event->xclient.data.l[2]) >> 16
18161 & 0xffff);
18162 *y_out = (event->xclient.data.l[2] & 0xffff);
18163
18164 return true;
18165 }
18166
18167 if ((event->xclient.message_type
18168 == dpyinfo->Xatom_MOTIF_DRAG_AND_DROP_MESSAGE)
18169 && event->xclient.format == 8)
18170 {
18171 if (!xm_read_drag_motion_message (event, &dmsg))
18172 {
18173 *x_out = dmsg.x;
18174 *y_out = dmsg.y;
18175
18176 return true;
18177 }
18178 else if (!xm_read_drag_motion_reply (event, &dreply))
18179 {
18180 *x_out = dreply.better_x;
18181 *y_out = dreply.better_y;
18182
18183 return true;
18184 }
18185 else if (!xm_read_drop_start_message (event, &smsg))
18186 {
18187 *x_out = smsg.x;
18188 *y_out = smsg.y;
18189
18190 return true;
18191 }
18192 else if (!xm_read_drop_start_reply (event, &reply))
18193 {
18194 *x_out = reply.better_x;
18195 *y_out = reply.better_y;
18196
18197 return true;
18198 }
18199 }
18200
18201 if (((event->xclient.message_type
18202 == dpyinfo->Xatom_DndProtocol)
18203 || (event->xclient.message_type
18204 == dpyinfo->Xatom_DND_PROTOCOL))
18205 && event->xclient.format == 32
18206
18207
18208 && event->xclient.data.l[4])
18209 {
18210 kde_data = (unsigned long) event->xclient.data.l[3];
18211
18212 *x_out = (kde_data & 0xffff);
18213 *y_out = (kde_data >> 16 & 0xffff);
18214
18215 return true;
18216 }
18217
18218 return false;
18219 }
18220
18221 static void
18222 x_handle_wm_state (struct frame *f, struct input_event *ie)
18223 {
18224 struct x_display_info *dpyinfo;
18225 Atom type;
18226 int format;
18227 unsigned long nitems, bytes_after;
18228 unsigned char *data;
18229 unsigned long *state;
18230
18231 data = NULL;
18232 dpyinfo = FRAME_DISPLAY_INFO (f);
18233
18234 if (XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
18235 dpyinfo->Xatom_wm_state, 0, 2, False,
18236 AnyPropertyType, &type, &format, &nitems,
18237 &bytes_after, &data) != Success)
18238 return;
18239
18240 if (!data || nitems != 2 || format != 32)
18241 {
18242 if (data)
18243 XFree (data);
18244
18245 return;
18246 }
18247
18248 state = (unsigned long *) data;
18249
18250 if (state[0] == NormalState && FRAME_ICONIFIED_P (f))
18251 {
18252
18253
18254 SET_FRAME_VISIBLE (f, 1);
18255 SET_FRAME_ICONIFIED (f, false);
18256 f->output_data.x->has_been_visible = true;
18257
18258 ie->kind = DEICONIFY_EVENT;
18259 XSETFRAME (ie->frame_or_window, f);
18260 }
18261 else if (state[0] == IconicState
18262
18263
18264 && !x_wm_supports (f, dpyinfo->Xatom_net_wm_state_hidden))
18265 {
18266
18267
18268
18269 SET_FRAME_VISIBLE (f, 0);
18270 SET_FRAME_ICONIFIED (f, true);
18271
18272 ie->kind = ICONIFY_EVENT;
18273 XSETFRAME (ie->frame_or_window, f);
18274 }
18275
18276
18277
18278
18279
18280
18281 XFree (data);
18282 }
18283
18284 #ifdef HAVE_XFIXES
18285
18286 static bool
18287 x_handle_selection_monitor_event (struct x_display_info *dpyinfo,
18288 const XEvent *event)
18289 {
18290 XFixesSelectionNotifyEvent *notify;
18291 int i;
18292
18293 notify = (XFixesSelectionNotifyEvent *) event;
18294
18295 if (notify->window != dpyinfo->selection_tracking_window)
18296 return false;
18297
18298 for (i = 0; i < dpyinfo->n_monitored_selections; ++i)
18299 {
18300
18301 if (notify->selection == dpyinfo->monitored_selections[i].name)
18302 dpyinfo->monitored_selections[i].owner = notify->owner;
18303 }
18304
18305 return true;
18306 }
18307
18308 Window
18309 x_find_selection_owner (struct x_display_info *dpyinfo, Atom selection)
18310 {
18311 int i;
18312
18313 for (i = 0; i < dpyinfo->n_monitored_selections; ++i)
18314 {
18315 if (selection == dpyinfo->monitored_selections[i].name)
18316 return dpyinfo->monitored_selections[i].owner;
18317 }
18318
18319 return X_INVALID_WINDOW;
18320 }
18321
18322 #endif
18323
18324
18325
18326
18327
18328
18329
18330
18331
18332
18333 static int
18334 handle_one_xevent (struct x_display_info *dpyinfo,
18335 #ifndef HAVE_XINPUT2
18336 const XEvent *event,
18337 #else
18338 XEvent *event,
18339 #endif
18340 int *finish, struct input_event *hold_quit)
18341 {
18342 union buffered_input_event inev;
18343 int count = 0;
18344 int do_help = 0;
18345 #ifdef HAVE_XINPUT2
18346 struct xi_device_t *gen_help_device;
18347 Time gen_help_time UNINIT;
18348 #endif
18349 ptrdiff_t nbytes = 0;
18350 struct frame *any, *f = NULL, *mouse_frame;
18351 Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
18352
18353
18354
18355
18356 static XComposeStatus compose_status;
18357 XEvent configureEvent;
18358 XEvent next_event;
18359 Lisp_Object coding;
18360 #if defined USE_X_TOOLKIT && defined HAVE_XINPUT2
18361
18362
18363
18364 bool use_copy = false;
18365 XEvent copy;
18366 #elif defined USE_GTK && !defined HAVE_GTK3 && defined HAVE_XINPUT2
18367 GdkEvent *copy = NULL;
18368 GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display);
18369 #endif
18370 int dx, dy;
18371
18372
18373 #if defined HAVE_XINPUT2 || defined HAVE_XKB || defined HAVE_X_I18N
18374 USE_SAFE_ALLOCA;
18375 #endif
18376
18377
18378
18379
18380 if (!input_blocked_p ())
18381 emacs_abort ();
18382
18383 *finish = X_EVENT_NORMAL;
18384
18385 EVENT_INIT (inev.ie);
18386 inev.ie.kind = NO_EVENT;
18387 inev.ie.arg = Qnil;
18388 #ifdef HAVE_XINPUT2
18389 gen_help_device = NULL;
18390 #endif
18391
18392
18393
18394 if (event->type < LASTEvent)
18395 {
18396 #ifdef HAVE_XINPUT2
18397 if (event->type != GenericEvent)
18398 #endif
18399 any = x_any_window_to_frame (dpyinfo, event->xany.window);
18400 #ifdef HAVE_XINPUT2
18401 else
18402 any = NULL;
18403 #endif
18404 }
18405 else
18406 any = NULL;
18407
18408 if (any && any->wait_event_type == event->type)
18409 any->wait_event_type = 0;
18410
18411 switch (event->type)
18412 {
18413 case ClientMessage:
18414 {
18415 int rc;
18416
18417 if (((x_dnd_in_progress
18418 && FRAME_DISPLAY_INFO (x_dnd_frame) == dpyinfo)
18419 || (x_dnd_waiting_for_finish
18420 && FRAME_DISPLAY_INFO (x_dnd_finish_frame) == dpyinfo))
18421 && event->xclient.message_type == dpyinfo->Xatom_XdndStatus)
18422 {
18423 Window target;
18424 unsigned long r1, r2;
18425 int root_x, root_y;
18426 bool button;
18427
18428 target = event->xclient.data.l[0];
18429
18430 if (x_dnd_last_protocol_version != -1
18431 && x_dnd_in_progress
18432 && target == x_dnd_last_seen_toplevel
18433
18434
18435
18436
18437
18438 && !(event->xclient.data.l[1] & 2))
18439 {
18440 r1 = event->xclient.data.l[2];
18441 r2 = event->xclient.data.l[3];
18442
18443 x_dnd_mouse_rect_target = target;
18444 x_dnd_mouse_rect.x = (r1 & 0xffff0000) >> 16;
18445 x_dnd_mouse_rect.y = (r1 & 0xffff);
18446 x_dnd_mouse_rect.width = (r2 & 0xffff0000) >> 16;
18447 x_dnd_mouse_rect.height = (r2 & 0xffff);
18448 }
18449 else
18450 x_dnd_mouse_rect_target = None;
18451
18452 if (x_dnd_last_protocol_version != -1
18453 && (x_dnd_in_progress
18454 && target == x_dnd_last_seen_window))
18455 {
18456 if (event->xclient.data.l[1] & 1)
18457 {
18458 if (x_dnd_last_protocol_version >= 2)
18459 x_dnd_action = event->xclient.data.l[4];
18460 else
18461 x_dnd_action = dpyinfo->Xatom_XdndActionCopy;
18462 }
18463 else
18464 x_dnd_action = None;
18465 }
18466
18467
18468 if (x_dnd_waiting_for_status_window == target)
18469 {
18470 if (x_dnd_pending_send_position.type != 0)
18471 {
18472
18473
18474
18475
18476
18477 root_x = x_dnd_pending_send_position_root_x;
18478 root_y = x_dnd_pending_send_position_root_y;
18479 button = x_dnd_pending_send_position_button;
18480
18481 if (target == x_dnd_mouse_rect_target
18482 && x_dnd_mouse_rect.width
18483 && x_dnd_mouse_rect.height
18484
18485
18486
18487 && !button
18488 && (root_x >= x_dnd_mouse_rect.x
18489 && root_x < (x_dnd_mouse_rect.x
18490 + x_dnd_mouse_rect.width)
18491 && root_y >= x_dnd_mouse_rect.y
18492 && root_y < (x_dnd_mouse_rect.y
18493 + x_dnd_mouse_rect.height)))
18494 x_dnd_waiting_for_status_window = None;
18495 else
18496 {
18497 x_ignore_errors_for_next_request (dpyinfo);
18498 XSendEvent (dpyinfo->display, target,
18499 False, NoEventMask,
18500 &x_dnd_pending_send_position);
18501 x_stop_ignoring_errors (dpyinfo);
18502 x_dnd_pending_send_position.type = 0;
18503
18504
18505
18506
18507
18508 }
18509 }
18510 else
18511 x_dnd_waiting_for_status_window = None;
18512
18513
18514 if (x_dnd_waiting_for_finish && x_dnd_need_send_drop
18515 && x_dnd_waiting_for_status_window == None)
18516 {
18517 if (event->xclient.data.l[1] & 1)
18518 {
18519 if (x_dnd_send_drop_proto >= 2)
18520 x_dnd_action = event->xclient.data.l[4];
18521 else
18522 x_dnd_action = dpyinfo->Xatom_XdndActionCopy;
18523 }
18524 else
18525 x_dnd_action = None;
18526
18527 x_dnd_waiting_for_finish
18528 = x_dnd_send_drop (x_dnd_finish_frame,
18529 target,
18530 x_dnd_last_seen_toplevel,
18531 x_dnd_selection_timestamp,
18532 x_dnd_send_drop_proto);
18533 }
18534 }
18535
18536 goto done;
18537 }
18538
18539 if (event->xclient.message_type == dpyinfo->Xatom_XdndFinished
18540 && (x_dnd_waiting_for_finish && !x_dnd_waiting_for_motif_finish)
18541
18542
18543
18544 && dpyinfo->display == x_dnd_finish_display
18545 && event->xclient.data.l[0] == x_dnd_pending_finish_target)
18546 {
18547 x_dnd_waiting_for_finish = false;
18548
18549 if (x_dnd_waiting_for_finish_proto >= 5)
18550 x_dnd_action = event->xclient.data.l[2];
18551
18552 if (x_dnd_waiting_for_finish_proto >= 5
18553 && !(event->xclient.data.l[1] & 1))
18554 x_dnd_action = None;
18555
18556 goto done;
18557 }
18558
18559 if ((event->xclient.message_type
18560 == dpyinfo->Xatom_MOTIF_DRAG_AND_DROP_MESSAGE)
18561 && x_dnd_waiting_for_finish
18562 && x_dnd_waiting_for_motif_finish == 1
18563 && dpyinfo == x_dnd_waiting_for_motif_finish_display)
18564 {
18565 xm_drop_start_reply reply;
18566 uint16_t operation, status, action;
18567
18568 if (!xm_read_drop_start_reply (event, &reply))
18569 {
18570 operation = XM_DRAG_SIDE_EFFECT_OPERATION (reply.side_effects);
18571 status = XM_DRAG_SIDE_EFFECT_SITE_STATUS (reply.side_effects);
18572 action = XM_DRAG_SIDE_EFFECT_DROP_ACTION (reply.side_effects);
18573
18574 if (operation != XM_DRAG_MOVE
18575 && operation != XM_DRAG_COPY
18576 && XM_DRAG_OPERATION_IS_LINK (operation))
18577 {
18578 x_dnd_waiting_for_finish = false;
18579 goto done;
18580 }
18581
18582 if (status != XM_DROP_SITE_VALID
18583 || (action == XM_DROP_ACTION_DROP_CANCEL
18584 || action == XM_DROP_ACTION_DROP_HELP))
18585 {
18586 x_dnd_waiting_for_finish = false;
18587 goto done;
18588 }
18589
18590 switch (operation)
18591 {
18592 case XM_DRAG_MOVE:
18593 x_dnd_action_symbol = QXdndActionMove;
18594 break;
18595
18596 case XM_DRAG_COPY:
18597 x_dnd_action_symbol = QXdndActionCopy;
18598 break;
18599
18600
18601 default:
18602 x_dnd_action_symbol = QXdndActionLink;
18603 break;
18604 }
18605
18606 x_dnd_waiting_for_motif_finish = 2;
18607 goto done;
18608 }
18609 }
18610
18611 if (event->xclient.message_type == dpyinfo->Xatom_wm_protocols
18612 && event->xclient.format == 32)
18613 {
18614 if (event->xclient.data.l[0] == dpyinfo->Xatom_wm_take_focus)
18615 {
18616
18617
18618
18619 f = any;
18620 #ifdef HAVE_X_I18N
18621
18622 if (f && FRAME_XIC (f))
18623 XSetICFocus (FRAME_XIC (f));
18624 #endif
18625 #if false
18626
18627
18628
18629
18630
18631
18632
18633
18634
18635
18636
18637
18638
18639
18640
18641
18642 if (f)
18643 {
18644 Display *d = event->xclient.display;
18645
18646
18647 x_catch_errors (d);
18648 XSetInputFocus (d, event->xclient.window,
18649
18650
18651 RevertToParent,
18652 event->xclient.data.l[1]);
18653 x_uncatch_errors ();
18654 }
18655
18656 #endif
18657
18658
18659
18660
18661
18662
18663
18664 x_display_set_last_user_time (dpyinfo, (event->xclient.data.l[1]
18665 & 0xffffffff),
18666 true, true);
18667 goto done;
18668 }
18669
18670 if (event->xclient.data.l[0] == dpyinfo->Xatom_wm_save_yourself)
18671 {
18672
18673
18674
18675
18676
18677
18678
18679
18680 #ifdef HAVE_X_SM
18681 if (! x_session_have_connection ())
18682 #endif
18683 {
18684 f = x_top_window_to_frame (dpyinfo,
18685 event->xclient.window);
18686
18687
18688 if (f == SELECTED_FRAME ())
18689 XSetCommand (FRAME_X_DISPLAY (f),
18690 event->xclient.window,
18691 initial_argv, initial_argc);
18692 else if (f)
18693 XSetCommand (FRAME_X_DISPLAY (f),
18694 event->xclient.window,
18695 0, 0);
18696 }
18697 goto done;
18698 }
18699
18700 if (event->xclient.data.l[0] == dpyinfo->Xatom_wm_delete_window)
18701 {
18702 f = x_top_window_to_frame (dpyinfo,
18703 event->xclient.window);
18704
18705 if (!f)
18706 goto OTHER;
18707
18708 inev.ie.kind = DELETE_WINDOW_EVENT;
18709 inev.ie.timestamp = event->xclient.data.l[1];
18710 XSETFRAME (inev.ie.frame_or_window, f);
18711 goto done;
18712 }
18713
18714
18715 if (event->xclient.data.l[0] == dpyinfo->Xatom_net_wm_ping
18716
18717
18718
18719
18720
18721
18722
18723 && (!(x_dnd_in_progress
18724 || x_dnd_waiting_for_finish)
18725 || event->xclient.window != dpyinfo->root_window)
18726 && event->xclient.format == 32)
18727 {
18728 XEvent send_event = *event;
18729
18730 send_event.xclient.window = dpyinfo->root_window;
18731 XSendEvent (dpyinfo->display, dpyinfo->root_window, False,
18732 SubstructureRedirectMask | SubstructureNotifyMask,
18733 &send_event);
18734
18735 *finish = X_EVENT_DROP;
18736 goto done;
18737 }
18738
18739 #if defined HAVE_XSYNC
18740 if (event->xclient.data.l[0] == dpyinfo->Xatom_net_wm_sync_request
18741 && event->xclient.format == 32
18742 && dpyinfo->xsync_supported_p)
18743 {
18744 struct frame *f
18745 = x_top_window_to_frame (dpyinfo,
18746 event->xclient.window);
18747 #if defined HAVE_GTK3
18748 GtkWidget *widget;
18749 GdkWindow *window;
18750 GdkFrameClock *frame_clock;
18751 #endif
18752
18753 if (f)
18754 {
18755 #ifndef HAVE_GTK3
18756 if (event->xclient.data.l[4] == 0)
18757 {
18758 XSyncIntsToValue (&FRAME_X_OUTPUT (f)->pending_basic_counter_value,
18759 event->xclient.data.l[2], event->xclient.data.l[3]);
18760 FRAME_X_OUTPUT (f)->sync_end_pending_p = true;
18761 }
18762 else if (event->xclient.data.l[4] == 1)
18763 {
18764 XSyncIntsToValue (&FRAME_X_OUTPUT (f)->resize_counter_value,
18765 event->xclient.data.l[2],
18766 event->xclient.data.l[3]);
18767
18768 FRAME_X_OUTPUT (f)->ext_sync_end_pending_p = true;
18769 }
18770
18771 *finish = X_EVENT_DROP;
18772 #else
18773 widget = FRAME_GTK_OUTER_WIDGET (f);
18774 window = gtk_widget_get_window (widget);
18775 eassert (window);
18776
18777
18778
18779
18780 gdk_x11_window_set_frame_sync_enabled (window, TRUE);
18781
18782 if (widget && !FRAME_X_OUTPUT (f)->xg_sync_end_pending_p)
18783 {
18784 frame_clock = gdk_window_get_frame_clock (window);
18785 eassert (frame_clock);
18786
18787 gdk_frame_clock_request_phase (frame_clock,
18788 GDK_FRAME_CLOCK_PHASE_BEFORE_PAINT);
18789 FRAME_X_OUTPUT (f)->xg_sync_end_pending_p = true;
18790 }
18791 #endif
18792 goto done;
18793 }
18794 }
18795 #endif
18796
18797 goto done;
18798 }
18799
18800 if (event->xclient.message_type == dpyinfo->Xatom_wm_configure_denied)
18801 goto done;
18802
18803 if (event->xclient.message_type == dpyinfo->Xatom_wm_window_moved)
18804 {
18805 int new_x, new_y;
18806 f = x_window_to_frame (dpyinfo, event->xclient.window);
18807
18808 new_x = event->xclient.data.s[0];
18809 new_y = event->xclient.data.s[1];
18810
18811 if (f)
18812 {
18813 f->left_pos = new_x;
18814 f->top_pos = new_y;
18815 }
18816 goto done;
18817 }
18818
18819 #ifdef X_TOOLKIT_EDITRES
18820 if (event->xclient.message_type == dpyinfo->Xatom_editres)
18821 {
18822 f = any;
18823 if (f)
18824 {
18825 _XEditResCheckMessages (f->output_data.x->widget,
18826 NULL, (XEvent *) event, NULL);
18827 goto done;
18828 }
18829
18830 goto OTHER;
18831 }
18832 #endif
18833
18834 if (event->xclient.message_type == dpyinfo->Xatom_DONE
18835 || event->xclient.message_type == dpyinfo->Xatom_PAGE)
18836 {
18837
18838
18839
18840
18841 f = x_window_to_frame (dpyinfo, event->xclient.window);
18842 if (!f)
18843 goto OTHER;
18844 #ifndef USE_CAIRO
18845 Pixmap pixmap = (Pixmap) event->xclient.data.l[1];
18846
18847
18848 x_catch_errors (dpyinfo->display);
18849 x_kill_gs_process (pixmap, f);
18850 x_uncatch_errors ();
18851 expose_frame (f, 0, 0, 0, 0);
18852 #endif
18853 goto done;
18854 }
18855
18856 #ifdef USE_TOOLKIT_SCROLL_BARS
18857
18858
18859 if (event->xclient.message_type == dpyinfo->Xatom_Scrollbar)
18860 {
18861
18862
18863
18864 x_scroll_bar_to_input_event (dpyinfo, event, &inev.ie);
18865
18866 *finish = X_EVENT_GOTO_OUT;
18867 goto done;
18868 }
18869 else if (event->xclient.message_type == dpyinfo->Xatom_Horizontal_Scrollbar)
18870 {
18871
18872
18873
18874 x_horizontal_scroll_bar_to_input_event (dpyinfo, event,
18875 &inev.ie);
18876
18877 *finish = X_EVENT_GOTO_OUT;
18878 goto done;
18879 }
18880 #endif
18881
18882
18883 if (event->xclient.message_type == dpyinfo->Xatom_XEMBED)
18884 {
18885 enum xembed_message msg = event->xclient.data.l[1];
18886 if (msg == XEMBED_FOCUS_IN || msg == XEMBED_FOCUS_OUT)
18887 x_detect_focus_change (dpyinfo, any, event, &inev.ie);
18888
18889 *finish = X_EVENT_GOTO_OUT;
18890 goto done;
18891 }
18892
18893 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
18894
18895
18896 if (event->xclient.message_type
18897 == dpyinfo->Xatom_net_wm_frame_drawn)
18898 {
18899 if (any)
18900 x_sync_handle_frame_drawn (dpyinfo, (XEvent *) event, any);
18901
18902 goto done;
18903 }
18904
18905 if (event->xclient.message_type
18906 == dpyinfo->Xatom_net_wm_frame_timings)
18907 goto done;
18908 #endif
18909
18910 if (xft_settings_event (dpyinfo, event))
18911 goto done;
18912
18913 f = any;
18914
18915 if (!f || FRAME_TOOLTIP_P (f))
18916 goto OTHER;
18917
18918
18919
18920 dx = 0;
18921 dy = 0;
18922
18923 rc = x_coords_from_dnd_message (dpyinfo, (XEvent *) event,
18924 &dx, &dy);
18925
18926 if (x_handle_dnd_message (f, &event->xclient, dpyinfo, &inev.ie,
18927 rc, dx, dy))
18928 *finish = X_EVENT_DROP;
18929 }
18930 break;
18931
18932 case SelectionNotify:
18933 #if defined USE_X_TOOLKIT || defined USE_GTK
18934 if (!x_window_to_frame (dpyinfo, event->xselection.requestor))
18935 goto OTHER;
18936 #endif
18937 #ifdef HAVE_GTK3
18938
18939
18940
18941 *finish = X_EVENT_DROP;
18942 #endif
18943 x_handle_selection_notify (&event->xselection);
18944 break;
18945
18946 case SelectionClear:
18947 #if defined USE_X_TOOLKIT || defined USE_GTK
18948 if (!x_window_to_frame (dpyinfo, event->xselectionclear.window))
18949 goto OTHER;
18950 #endif
18951 #ifdef HAVE_GTK3
18952 *finish = X_EVENT_DROP;
18953 #endif
18954 {
18955 const XSelectionClearEvent *eventp = &event->xselectionclear;
18956
18957 if (eventp->selection == dpyinfo->motif_drag_atom
18958 && (eventp->time == CurrentTime
18959 || dpyinfo->motif_drag_atom_time <= eventp->time))
18960 dpyinfo->motif_drag_atom = None;
18961
18962 inev.sie.kind = SELECTION_CLEAR_EVENT;
18963 SELECTION_EVENT_DPYINFO (&inev.sie) = dpyinfo;
18964 SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
18965 SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
18966
18967 if (x_use_pending_selection_requests)
18968 {
18969 x_push_selection_request (&inev.sie);
18970 EVENT_INIT (inev.ie);
18971 }
18972 }
18973 break;
18974
18975 case SelectionRequest:
18976 #ifdef USE_X_TOOLKIT
18977 if (!x_window_to_frame (dpyinfo, event->xselectionrequest.owner))
18978 goto OTHER;
18979 #endif
18980 #ifdef HAVE_GTK3
18981 *finish = X_EVENT_DROP;
18982 #endif
18983 {
18984 const XSelectionRequestEvent *eventp = &event->xselectionrequest;
18985
18986 inev.sie.kind = SELECTION_REQUEST_EVENT;
18987 SELECTION_EVENT_DPYINFO (&inev.sie) = dpyinfo;
18988 SELECTION_EVENT_REQUESTOR (&inev.sie) = eventp->requestor;
18989 SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
18990 SELECTION_EVENT_TARGET (&inev.sie) = eventp->target;
18991 SELECTION_EVENT_PROPERTY (&inev.sie) = eventp->property;
18992 SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
18993
18994
18995
18996
18997
18998 if (x_use_pending_selection_requests)
18999 {
19000 x_push_selection_request (&inev.sie);
19001 EVENT_INIT (inev.ie);
19002 }
19003
19004 if (x_dnd_waiting_for_finish
19005 && x_dnd_waiting_for_motif_finish == 2
19006 && dpyinfo == x_dnd_waiting_for_motif_finish_display
19007 && eventp->selection == x_dnd_motif_atom
19008 && (eventp->target == dpyinfo->Xatom_XmTRANSFER_SUCCESS
19009 || eventp->target == dpyinfo->Xatom_XmTRANSFER_FAILURE))
19010 {
19011 x_dnd_waiting_for_finish = false;
19012
19013
19014
19015 if (eventp->target == dpyinfo->Xatom_XmTRANSFER_FAILURE)
19016 x_dnd_action = None;
19017 }
19018 }
19019 break;
19020
19021 case PropertyNotify:
19022 if (x_dnd_in_progress && x_dnd_use_toplevels
19023 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame)
19024 && event->xproperty.atom == dpyinfo->Xatom_wm_state)
19025 {
19026 struct x_client_list_window *tem, *last;
19027
19028 for (last = NULL, tem = x_dnd_toplevels; tem;
19029 last = tem, tem = tem->next)
19030 {
19031 if (tem->window == event->xproperty.window)
19032 {
19033 Atom actual_type;
19034 int actual_format, rc;
19035 unsigned long nitems, bytesafter;
19036 unsigned char *data = NULL;
19037
19038 if (event->xproperty.state == PropertyDelete)
19039 {
19040 if (!last)
19041 x_dnd_toplevels = tem->next;
19042 else
19043 last->next = tem->next;
19044
19045 #ifdef HAVE_XSHAPE
19046 if (tem->n_input_rects != -1)
19047 xfree (tem->input_rects);
19048 if (tem->n_bounding_rects != -1)
19049 xfree (tem->bounding_rects);
19050 #endif
19051 xfree (tem);
19052 }
19053 else
19054 {
19055 x_catch_errors (dpyinfo->display);
19056 rc = XGetWindowProperty (dpyinfo->display,
19057 event->xproperty.window,
19058 dpyinfo->Xatom_wm_state,
19059 0, 2, False, AnyPropertyType,
19060 &actual_type, &actual_format,
19061 &nitems, &bytesafter, &data);
19062
19063 if (!x_had_errors_p (dpyinfo->display) && rc == Success && data
19064 && nitems == 2 && actual_format == 32)
19065 tem->wm_state = ((unsigned long *) data)[0];
19066 else
19067 tem->wm_state = WithdrawnState;
19068
19069 if (data)
19070 XFree (data);
19071 x_uncatch_errors_after_check ();
19072 }
19073
19074 x_dnd_update_state (dpyinfo, event->xproperty.time);
19075 break;
19076 }
19077 }
19078 }
19079
19080 f = x_top_window_to_frame (dpyinfo, event->xproperty.window);
19081 if (f && event->xproperty.atom == dpyinfo->Xatom_net_wm_state
19082
19083 && !FRAME_X_EMBEDDED_P (f))
19084 {
19085 bool not_hidden = x_handle_net_wm_state (f, &event->xproperty);
19086
19087 if (not_hidden && FRAME_ICONIFIED_P (f))
19088 {
19089 if (CONSP (frame_size_history))
19090 frame_size_history_plain
19091 (f, build_string ("PropertyNotify, not hidden & iconified"));
19092
19093
19094
19095
19096 SET_FRAME_VISIBLE (f, 1);
19097 SET_FRAME_ICONIFIED (f, false);
19098
19099 f->output_data.x->has_been_visible = true;
19100 inev.ie.kind = DEICONIFY_EVENT;
19101 #if defined USE_GTK && defined HAVE_GTK3
19102
19103
19104 if (f->was_invisible)
19105 {
19106 xg_frame_set_char_size
19107 (f, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f));
19108 f->was_invisible = false;
19109 }
19110 #endif
19111 XSETFRAME (inev.ie.frame_or_window, f);
19112 }
19113 else if (!not_hidden && !FRAME_ICONIFIED_P (f))
19114 {
19115 if (CONSP (frame_size_history))
19116 frame_size_history_plain
19117 (f, build_string ("PropertyNotify, hidden & not iconified"));
19118
19119 SET_FRAME_VISIBLE (f, 0);
19120 SET_FRAME_ICONIFIED (f, true);
19121 inev.ie.kind = ICONIFY_EVENT;
19122 XSETFRAME (inev.ie.frame_or_window, f);
19123 }
19124 }
19125
19126 if (f && event->xproperty.atom == dpyinfo->Xatom_wm_state
19127 && !FRAME_X_EMBEDDED_P (f) && !FRAME_PARENT_FRAME (f))
19128
19129
19130
19131
19132
19133
19134
19135
19136
19137 x_handle_wm_state (f, &inev.ie);
19138
19139 if (f && FRAME_X_OUTPUT (f)->alpha_identical_p
19140 && (event->xproperty.atom
19141 == dpyinfo->Xatom_net_wm_window_opacity))
19142 {
19143 #ifndef USE_XCB
19144 int rc, actual_format;
19145 Atom actual;
19146 unsigned char *tmp_data;
19147 unsigned long n, left, opacity;
19148
19149 tmp_data = NULL;
19150 #else
19151 xcb_get_property_cookie_t opacity_cookie;
19152 xcb_get_property_reply_t *opacity_reply;
19153 xcb_generic_error_t *error;
19154 bool rc;
19155 uint32_t value;
19156 #endif
19157
19158 if (event->xproperty.state == PropertyDelete)
19159 {
19160 f->alpha[0] = 1.0;
19161 f->alpha[1] = 1.0;
19162
19163 store_frame_param (f, Qalpha, Qnil);
19164 }
19165 else
19166 {
19167 #ifndef USE_XCB
19168 rc = XGetWindowProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
19169 dpyinfo->Xatom_net_wm_window_opacity,
19170 0, 1, False, AnyPropertyType, &actual,
19171 &actual_format, &n, &left, &tmp_data);
19172
19173 if (rc == Success && actual_format == 32
19174 && (actual == XA_CARDINAL
19175
19176
19177
19178 || actual == XA_ATOM
19179 || actual == XA_WINDOW) && n)
19180 {
19181 opacity = *(unsigned long *) tmp_data & OPAQUE;
19182 f->alpha[0] = (double) opacity / (double) OPAQUE;
19183 f->alpha[1] = (double) opacity / (double) OPAQUE;
19184
19185 store_frame_param (f, Qalpha, make_float (f->alpha[0]));
19186 }
19187 else
19188 {
19189 f->alpha[0] = 1.0;
19190 f->alpha[1] = 1.0;
19191
19192 store_frame_param (f, Qalpha, Qnil);
19193 }
19194 #else
19195 opacity_cookie
19196 = xcb_get_property (dpyinfo->xcb_connection, 0,
19197 (xcb_window_t) FRAME_OUTER_WINDOW (f),
19198 (xcb_atom_t) dpyinfo->Xatom_net_wm_window_opacity,
19199 XCB_ATOM_CARDINAL, 0, 1);
19200 opacity_reply
19201 = xcb_get_property_reply (dpyinfo->xcb_connection,
19202 opacity_cookie, &error);
19203
19204 if (!opacity_reply)
19205 free (error), rc = false;
19206 else
19207 rc = (opacity_reply->format == 32
19208 && (opacity_reply->type == XCB_ATOM_CARDINAL
19209 || opacity_reply->type == XCB_ATOM_ATOM
19210 || opacity_reply->type == XCB_ATOM_WINDOW)
19211 && (xcb_get_property_value_length (opacity_reply) >= 4));
19212
19213 if (rc)
19214 {
19215 value = *(uint32_t *) xcb_get_property_value (opacity_reply);
19216
19217 f->alpha[0] = (double) value / (double) OPAQUE;
19218 f->alpha[1] = (double) value / (double) OPAQUE;
19219 store_frame_param (f, Qalpha, make_float (f->alpha[0]));
19220 }
19221 else
19222 {
19223 f->alpha[0] = 1.0;
19224 f->alpha[1] = 1.0;
19225
19226 store_frame_param (f, Qalpha, Qnil);
19227 }
19228
19229 if (opacity_reply)
19230 free (opacity_reply);
19231 #endif
19232 }
19233
19234 #ifndef USE_XCB
19235 if (tmp_data)
19236 XFree (tmp_data);
19237 #endif
19238 }
19239
19240 if (event->xproperty.window == dpyinfo->root_window
19241 && (event->xproperty.atom == dpyinfo->Xatom_net_client_list_stacking
19242 || event->xproperty.atom == dpyinfo->Xatom_net_current_desktop)
19243 && x_dnd_in_progress
19244 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
19245 {
19246 if (x_dnd_use_toplevels)
19247 {
19248 x_dnd_free_toplevels (true);
19249
19250 if (x_dnd_compute_toplevels (dpyinfo))
19251 {
19252 x_dnd_free_toplevels (true);
19253 x_dnd_use_toplevels = false;
19254 }
19255 }
19256
19257 x_dnd_update_state (dpyinfo, event->xproperty.time);
19258 }
19259
19260 x_handle_property_notify (&event->xproperty);
19261 xft_settings_event (dpyinfo, event);
19262 goto OTHER;
19263
19264 case ReparentNotify:
19265 f = x_top_window_to_frame (dpyinfo, event->xreparent.window);
19266 if (f)
19267 {
19268 #ifndef USE_GTK
19269 if (FRAME_OUTPUT_DATA (f)->parent_desc
19270 && FRAME_X_EMBEDDED_P (f))
19271 {
19272
19273
19274
19275
19276
19277 FRAME_X_OUTPUT (f)->explicit_parent = false;
19278
19279
19280 XDeleteProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
19281 dpyinfo->Xatom_XEMBED_INFO);
19282 x_make_frame_visible (f);
19283 }
19284 #endif
19285
19286
19287 f->output_data.x->parent_desc = event->xreparent.parent;
19288
19289 if (!FRAME_PARENT_FRAME (f))
19290 {
19291 x_real_positions (f, &f->left_pos, &f->top_pos);
19292
19293
19294 dpyinfo->wm_type = X_WMTYPE_UNKNOWN;
19295 dpyinfo->net_supported_window = 0;
19296
19297 #ifndef USE_GTK
19298
19299
19300
19301
19302
19303
19304 if (FRAME_X_OUTPUT (f)->has_been_visible)
19305 x_update_frame_user_time_window (f);
19306 #endif
19307 }
19308 else
19309 {
19310 Window root;
19311 unsigned int dummy_uint;
19312
19313 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
19314 &root, &f->left_pos, &f->top_pos,
19315 &dummy_uint, &dummy_uint, &dummy_uint, &dummy_uint);
19316 }
19317
19318 x_set_frame_alpha (f);
19319 }
19320 goto OTHER;
19321
19322 case Expose:
19323
19324 #ifdef HAVE_XWIDGETS
19325 {
19326 struct xwidget_view *xv;
19327
19328 xv = xwidget_view_from_window (event->xexpose.window);
19329
19330 if (xv)
19331 {
19332 xwidget_expose (xv);
19333 goto OTHER;
19334 }
19335 }
19336 #endif
19337
19338 f = x_window_to_frame (dpyinfo, event->xexpose.window);
19339 if (f)
19340 {
19341 if (!FRAME_VISIBLE_P (f))
19342 {
19343
19344
19345
19346
19347
19348 if (EQ (x_set_frame_visibility_more_laxly, Qexpose)
19349 || EQ (x_set_frame_visibility_more_laxly, Qt))
19350 {
19351 SET_FRAME_VISIBLE (f, 1);
19352 SET_FRAME_ICONIFIED (f, false);
19353 }
19354
19355 #ifdef HAVE_XDBE
19356 if (FRAME_X_DOUBLE_BUFFERED_P (f))
19357 x_drop_xrender_surfaces (f);
19358 #endif
19359 f->output_data.x->has_been_visible = true;
19360 SET_FRAME_GARBAGED (f);
19361 }
19362 else if (FRAME_GARBAGED_P (f))
19363 {
19364 #ifdef USE_GTK
19365
19366
19367
19368
19369
19370
19371 x_clear_area1 (FRAME_X_DISPLAY (f),
19372 FRAME_X_WINDOW (f),
19373 event->xexpose.x, event->xexpose.y,
19374 event->xexpose.width, event->xexpose.height,
19375 0);
19376 x_clear_under_internal_border (f);
19377 #endif
19378 }
19379
19380 if (!FRAME_GARBAGED_P (f))
19381 {
19382 #if defined USE_X_TOOLKIT && defined USE_TOOLKIT_SCROLL_BARS
19383 if (f->output_data.x->edit_widget)
19384
19385
19386 goto OTHER;
19387 #endif
19388 #ifdef USE_GTK
19389
19390
19391 x_clear_area (f,
19392 event->xexpose.x, event->xexpose.y,
19393 event->xexpose.width, event->xexpose.height);
19394 #endif
19395 expose_frame (f, event->xexpose.x, event->xexpose.y,
19396 event->xexpose.width, event->xexpose.height);
19397 #ifndef USE_TOOLKIT_SCROLL_BARS
19398 x_scroll_bar_handle_exposure (f, (XEvent *) event);
19399 #endif
19400 #ifdef USE_GTK
19401 x_clear_under_internal_border (f);
19402 #endif
19403 }
19404 #ifndef USE_TOOLKIT_SCROLL_BARS
19405 else
19406 x_scroll_bar_handle_exposure (f, (XEvent *) event);
19407 #endif
19408
19409 #ifdef HAVE_XDBE
19410 if (!FRAME_GARBAGED_P (f))
19411 show_back_buffer (f);
19412 #endif
19413 }
19414 else
19415 {
19416 #if defined USE_LUCID
19417
19418
19419
19420 {
19421 Widget widget = x_window_to_menu_bar (event->xexpose.window);
19422 if (widget)
19423 xlwmenu_redisplay (widget);
19424 }
19425 #endif
19426
19427
19428 goto OTHER;
19429 }
19430 break;
19431
19432 case GraphicsExpose:
19433
19434
19435 f = x_window_to_frame (dpyinfo, event->xgraphicsexpose.drawable);
19436 if (f)
19437 {
19438 expose_frame (f, event->xgraphicsexpose.x,
19439 event->xgraphicsexpose.y,
19440 event->xgraphicsexpose.width,
19441 event->xgraphicsexpose.height);
19442 #ifndef USE_TOOLKIT_SCROLL_BARS
19443 x_scroll_bar_handle_exposure (f, (XEvent *) event);
19444 #endif
19445 #ifdef USE_GTK
19446 x_clear_under_internal_border (f);
19447 #endif
19448 #ifdef HAVE_XDBE
19449 show_back_buffer (f);
19450 #endif
19451 }
19452 #ifdef USE_X_TOOLKIT
19453 else
19454 goto OTHER;
19455 #endif
19456 break;
19457
19458 case NoExpose:
19459
19460
19461 #ifdef USE_X_TOOLKIT
19462 *finish = X_EVENT_DROP;
19463 #endif
19464 break;
19465
19466 case UnmapNotify:
19467 if (x_dnd_in_progress && x_dnd_use_toplevels
19468 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
19469 {
19470 for (struct x_client_list_window *tem = x_dnd_toplevels; tem;
19471 tem = tem->next)
19472 {
19473 if (tem->window == event->xunmap.window)
19474 {
19475 tem->mapped_p = false;
19476 break;
19477 }
19478 }
19479 }
19480
19481
19482 if (event->xunmap.window == tip_window)
19483 {
19484 tip_window = None;
19485 gui_redo_mouse_highlight (dpyinfo);
19486 }
19487
19488 f = x_top_window_to_frame (dpyinfo, event->xunmap.window);
19489 if (f)
19490
19491 {
19492 bool visible = FRAME_VISIBLE_P (f);
19493
19494 #ifdef USE_LUCID
19495
19496
19497
19498 if (FRAME_TOOLTIP_P (f) && popup_activated ())
19499 {
19500 Widget w;
19501 Lisp_Object tail, frame;
19502 struct frame *f1;
19503
19504 FOR_EACH_FRAME (tail, frame)
19505 {
19506 if (!FRAME_X_P (XFRAME (frame)))
19507 continue;
19508
19509 f1 = XFRAME (frame);
19510
19511 if (FRAME_LIVE_P (f1))
19512 {
19513 w = FRAME_X_OUTPUT (f1)->menubar_widget;
19514
19515 if (w && !DoesSaveUnders (FRAME_DISPLAY_INFO (f1)->screen))
19516 xlwmenu_redisplay (w);
19517 }
19518 }
19519 }
19520 #endif
19521
19522
19523
19524
19525 SET_FRAME_VISIBLE (f, 0);
19526
19527
19528
19529
19530
19531
19532 if (visible || FRAME_ICONIFIED_P (f))
19533 {
19534 if (CONSP (frame_size_history))
19535 frame_size_history_plain
19536 (f, build_string ("UnmapNotify, visible | iconified"));
19537
19538 SET_FRAME_ICONIFIED (f, true);
19539 inev.ie.kind = ICONIFY_EVENT;
19540 XSETFRAME (inev.ie.frame_or_window, f);
19541 }
19542 else if (CONSP (frame_size_history))
19543 frame_size_history_plain
19544 (f, build_string ("UnmapNotify, not visible & not iconified"));
19545 }
19546 goto OTHER;
19547
19548 case MapNotify:
19549 #if defined HAVE_XINPUT2 && defined HAVE_GTK3
19550 if (xg_is_menu_window (dpyinfo->display, event->xmap.window))
19551 popup_activated_flag = 1;
19552 #endif
19553
19554 if (x_dnd_in_progress
19555
19556
19557
19558
19559 && !x_dnd_use_toplevels
19560 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
19561 x_dnd_update_state (dpyinfo, dpyinfo->last_user_time);
19562
19563 if (x_dnd_in_progress && x_dnd_use_toplevels
19564 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
19565 {
19566 for (struct x_client_list_window *tem = x_dnd_toplevels; tem;
19567 tem = tem->next)
19568 {
19569 if (tem->window == event->xmap.window)
19570 {
19571 tem->mapped_p = true;
19572 break;
19573 }
19574 }
19575 }
19576
19577
19578
19579
19580 f = x_top_window_to_frame (dpyinfo, event->xmap.window);
19581 if (f)
19582 {
19583 bool iconified = FRAME_ICONIFIED_P (f);
19584 int value;
19585 bool sticky, shaded;
19586 bool not_hidden = x_get_current_wm_state (f, event->xmap.window, &value, &sticky,
19587 &shaded);
19588
19589 if (CONSP (frame_size_history))
19590 frame_size_history_extra
19591 (f,
19592 iconified
19593 ? (not_hidden
19594 ? build_string ("MapNotify, not hidden & iconified")
19595 : build_string ("MapNotify, hidden & iconified"))
19596 : (not_hidden
19597 ? build_string ("MapNotify, not hidden & not iconified")
19598 : build_string ("MapNotify, hidden & not iconified")),
19599 FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f),
19600 -1, -1, f->new_width, f->new_height);
19601
19602
19603
19604 if (!f->output_data.x->has_been_visible)
19605 {
19606
19607 x_check_fullscreen (f);
19608 #ifndef USE_GTK
19609
19610
19611 if (FRAME_SKIP_TASKBAR (f))
19612 x_set_skip_taskbar (f, Qt, Qnil);
19613 #endif
19614 }
19615
19616 if (!iconified)
19617 {
19618
19619
19620 if (FRAME_Z_GROUP (f) == z_group_above)
19621 x_set_z_group (f, Qabove, Qnil);
19622 else if (FRAME_Z_GROUP (f) == z_group_below)
19623 x_set_z_group (f, Qbelow, Qnil);
19624 }
19625
19626
19627
19628 if (not_hidden || FRAME_X_EMBEDDED_P (f))
19629 {
19630 SET_FRAME_VISIBLE (f, 1);
19631 SET_FRAME_ICONIFIED (f, false);
19632 #if defined USE_GTK && defined HAVE_GTK3
19633
19634
19635 if (f->was_invisible)
19636 {
19637 xg_frame_set_char_size
19638 (f, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f));
19639 f->was_invisible = false;
19640 }
19641 #endif
19642 f->output_data.x->has_been_visible = true;
19643 }
19644
19645 x_update_opaque_region (f, NULL);
19646
19647 if ((not_hidden || FRAME_X_EMBEDDED_P (f)) && iconified)
19648 {
19649 inev.ie.kind = DEICONIFY_EVENT;
19650 XSETFRAME (inev.ie.frame_or_window, f);
19651 }
19652 }
19653 goto OTHER;
19654
19655 case KeyPress:
19656 x_display_set_last_user_time (dpyinfo, event->xkey.time,
19657 event->xkey.send_event,
19658 true);
19659 ignore_next_mouse_click_timeout = 0;
19660
19661 coding = Qlatin_1;
19662
19663 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
19664
19665 if (popup_activated ())
19666 goto OTHER;
19667 #endif
19668
19669 f = any;
19670
19671 #ifdef USE_GTK
19672 if (f)
19673 x_set_gtk_user_time (f, event->xkey.time);
19674 #endif
19675
19676
19677
19678 if (!hlinfo->mouse_face_hidden && FIXNUMP (Vmouse_highlight)
19679 && (f == 0
19680 #if ! defined (USE_GTK)
19681 || !EQ (f->tool_bar_window, hlinfo->mouse_face_window)
19682 #endif
19683 || !EQ (f->tab_bar_window, hlinfo->mouse_face_window))
19684 )
19685 {
19686 mouse_frame = hlinfo->mouse_face_mouse_frame;
19687
19688 clear_mouse_face (hlinfo);
19689 hlinfo->mouse_face_hidden = true;
19690
19691 if (mouse_frame)
19692 x_flush_dirty_back_buffer_on (mouse_frame);
19693 }
19694
19695 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
19696 if (f == 0)
19697 {
19698
19699
19700 Widget widget = XtWindowToWidget (dpyinfo->display,
19701 event->xkey.window);
19702 if (widget && XmIsScrollBar (widget))
19703 {
19704 widget = XtParent (widget);
19705 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
19706 }
19707 }
19708 #endif
19709
19710 if (f != 0)
19711 {
19712 KeySym keysym, orig_keysym;
19713
19714
19715
19716
19717
19718
19719
19720
19721
19722
19723
19724 unsigned char copy_buffer[513];
19725 unsigned char *copy_bufptr = copy_buffer;
19726 int copy_bufsiz = sizeof (copy_buffer);
19727 int modifiers;
19728 Lisp_Object c;
19729
19730
19731 XKeyEvent xkey = event->xkey;
19732
19733 if (event->xkey.window == FRAME_X_WINDOW (f))
19734
19735
19736 x_compute_root_window_offset (f, event->xkey.x_root,
19737 event->xkey.y_root,
19738 event->xkey.x, event->xkey.y);
19739
19740 #ifdef HAVE_XINPUT2
19741 Time pending_keystroke_time;
19742 struct xi_device_t *source;
19743
19744 pending_keystroke_time = dpyinfo->pending_keystroke_time;
19745
19746 if (event->xkey.time >= pending_keystroke_time)
19747 {
19748 #if defined USE_GTK && !defined HAVE_GTK3
19749 if (!dpyinfo->pending_keystroke_time_special_p)
19750 #endif
19751 dpyinfo->pending_keystroke_time = 0;
19752 #if defined USE_GTK && !defined HAVE_GTK3
19753 else
19754 dpyinfo->pending_keystroke_time_special_p = false;
19755 #endif
19756 }
19757 #endif
19758
19759 #ifdef USE_GTK
19760
19761
19762
19763
19764 *finish = X_EVENT_DROP;
19765 #endif
19766
19767 xkey.state |= x_emacs_to_x_modifiers (dpyinfo,
19768 extra_keyboard_modifiers);
19769 modifiers = xkey.state;
19770
19771
19772
19773
19774
19775 xkey.state &= ~ControlMask;
19776 xkey.state &= ~(dpyinfo->meta_mod_mask
19777 | dpyinfo->super_mod_mask
19778 | dpyinfo->hyper_mod_mask
19779 | dpyinfo->alt_mod_mask);
19780
19781
19782
19783
19784
19785
19786 if (modifiers & dpyinfo->meta_mod_mask)
19787 memset (&compose_status, 0, sizeof (compose_status));
19788
19789 #ifdef HAVE_X_I18N
19790 if (FRAME_XIC (f))
19791 {
19792 Status status_return;
19793
19794 nbytes = XmbLookupString (FRAME_XIC (f),
19795 &xkey, (char *) copy_bufptr,
19796 copy_bufsiz, &keysym,
19797 &status_return);
19798 coding = FRAME_X_XIM_CODING (f);
19799 if (status_return == XBufferOverflow)
19800 {
19801 copy_bufsiz = nbytes + 1;
19802 copy_bufptr = SAFE_ALLOCA (copy_bufsiz);
19803 nbytes = XmbLookupString (FRAME_XIC (f),
19804 &xkey, (char *) copy_bufptr,
19805 copy_bufsiz, &keysym,
19806 &status_return);
19807 }
19808
19809 if (status_return == XLookupNone)
19810 break;
19811 else if (status_return == XLookupChars)
19812 {
19813 keysym = NoSymbol;
19814 modifiers = 0;
19815 }
19816 else if (status_return != XLookupKeySym
19817 && status_return != XLookupBoth)
19818 emacs_abort ();
19819 }
19820 else
19821 #endif
19822 {
19823 #ifdef HAVE_XKB
19824 int overflow;
19825 unsigned int consumed;
19826
19827 if (dpyinfo->xkb_desc)
19828 {
19829 if (!XkbTranslateKeyCode (dpyinfo->xkb_desc,
19830 xkey.keycode, xkey.state,
19831 &consumed, &keysym))
19832 goto done_keysym;
19833
19834 overflow = 0;
19835
19836 nbytes = XkbTranslateKeySym (dpyinfo->display, &keysym,
19837 xkey.state & ~consumed,
19838 (char *) copy_bufptr,
19839 copy_bufsiz, &overflow);
19840
19841 if (overflow)
19842 {
19843 copy_bufptr = SAFE_ALLOCA ((copy_bufsiz += overflow)
19844 * sizeof *copy_bufptr);
19845 overflow = 0;
19846 nbytes = XkbTranslateKeySym (dpyinfo->display, &keysym,
19847 xkey.state & ~consumed,
19848 (char *) copy_bufptr,
19849 copy_bufsiz, &overflow);
19850
19851 if (overflow)
19852 nbytes = 0;
19853 }
19854
19855 if (nbytes)
19856 coding = Qnil;
19857 }
19858 else
19859 #endif
19860 nbytes = XLookupString (&xkey, (char *) copy_bufptr,
19861 copy_bufsiz, &keysym,
19862 &compose_status);
19863 }
19864
19865 #ifdef XK_F1
19866 if (x_dnd_in_progress && keysym == XK_F1)
19867 {
19868 x_dnd_xm_use_help = true;
19869 goto done_keysym;
19870 }
19871 #endif
19872
19873
19874
19875 if (compose_status.chars_matched > 0 && nbytes == 0)
19876 break;
19877
19878 memset (&compose_status, 0, sizeof (compose_status));
19879 orig_keysym = keysym;
19880
19881
19882 XSETFRAME (inev.ie.frame_or_window, f);
19883 inev.ie.modifiers
19884 = x_x_to_emacs_modifiers (dpyinfo, modifiers);
19885 inev.ie.timestamp = xkey.time;
19886
19887
19888
19889 if (keysym >= 32 && keysym < 128)
19890
19891 {
19892 inev.ie.kind = ASCII_KEYSTROKE_EVENT;
19893 inev.ie.code = keysym;
19894
19895 #ifdef HAVE_XINPUT2
19896 if (event->xkey.time == pending_keystroke_time)
19897 {
19898 source = xi_device_from_id (dpyinfo,
19899 dpyinfo->pending_keystroke_source);
19900
19901 if (source)
19902 inev.ie.device = source->name;
19903 }
19904 #endif
19905
19906 goto done_keysym;
19907 }
19908
19909
19910 if (keysym >= 0x01000000 && keysym <= 0x0110FFFF)
19911 {
19912 if (keysym < 0x01000080)
19913 inev.ie.kind = ASCII_KEYSTROKE_EVENT;
19914 else
19915 inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
19916 inev.ie.code = keysym & 0xFFFFFF;
19917
19918 #ifdef HAVE_XINPUT2
19919 if (event->xkey.time == pending_keystroke_time)
19920 {
19921 source = xi_device_from_id (dpyinfo,
19922 dpyinfo->pending_keystroke_source);
19923
19924 if (source)
19925 inev.ie.device = source->name;
19926 }
19927 #endif
19928
19929 goto done_keysym;
19930 }
19931
19932
19933 if (HASH_TABLE_P (Vx_keysym_table)
19934 && (c = Fgethash (make_fixnum (keysym),
19935 Vx_keysym_table,
19936 Qnil),
19937 FIXNATP (c)))
19938 {
19939 inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFIXNAT (c))
19940 ? ASCII_KEYSTROKE_EVENT
19941 : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
19942 inev.ie.code = XFIXNAT (c);
19943
19944 #ifdef HAVE_XINPUT2
19945 if (event->xkey.time == pending_keystroke_time)
19946 {
19947 source = xi_device_from_id (dpyinfo,
19948 dpyinfo->pending_keystroke_source);
19949
19950 if (source)
19951 inev.ie.device = source->name;
19952 }
19953 #endif
19954
19955 goto done_keysym;
19956 }
19957
19958
19959 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
19960 || keysym == XK_Delete
19961 #ifdef XK_ISO_Left_Tab
19962 || (keysym >= XK_ISO_Left_Tab
19963 && keysym <= XK_ISO_Enter)
19964 #endif
19965 || IsCursorKey (keysym)
19966 || IsMiscFunctionKey (keysym)
19967 #ifdef HPUX
19968
19969
19970
19971
19972 || (XK_Select <= keysym && keysym < XK_KP_Space)
19973 #endif
19974 #ifdef XK_dead_circumflex
19975 || orig_keysym == XK_dead_circumflex
19976 #endif
19977 #ifdef XK_dead_grave
19978 || orig_keysym == XK_dead_grave
19979 #endif
19980 #ifdef XK_dead_tilde
19981 || orig_keysym == XK_dead_tilde
19982 #endif
19983 #ifdef XK_dead_diaeresis
19984 || orig_keysym == XK_dead_diaeresis
19985 #endif
19986 #ifdef XK_dead_macron
19987 || orig_keysym == XK_dead_macron
19988 #endif
19989 #ifdef XK_dead_degree
19990 || orig_keysym == XK_dead_degree
19991 #endif
19992 #ifdef XK_dead_acute
19993 || orig_keysym == XK_dead_acute
19994 #endif
19995 #ifdef XK_dead_cedilla
19996 || orig_keysym == XK_dead_cedilla
19997 #endif
19998 #ifdef XK_dead_breve
19999 || orig_keysym == XK_dead_breve
20000 #endif
20001 #ifdef XK_dead_ogonek
20002 || orig_keysym == XK_dead_ogonek
20003 #endif
20004 #ifdef XK_dead_caron
20005 || orig_keysym == XK_dead_caron
20006 #endif
20007 #ifdef XK_dead_doubleacute
20008 || orig_keysym == XK_dead_doubleacute
20009 #endif
20010 #ifdef XK_dead_abovedot
20011 || orig_keysym == XK_dead_abovedot
20012 #endif
20013 #ifdef XK_dead_abovering
20014 || orig_keysym == XK_dead_abovering
20015 #endif
20016 #ifdef XK_dead_belowdot
20017 || orig_keysym == XK_dead_belowdot
20018 #endif
20019 #ifdef XK_dead_voiced_sound
20020 || orig_keysym == XK_dead_voiced_sound
20021 #endif
20022 #ifdef XK_dead_semivoiced_sound
20023 || orig_keysym == XK_dead_semivoiced_sound
20024 #endif
20025 #ifdef XK_dead_hook
20026 || orig_keysym == XK_dead_hook
20027 #endif
20028 #ifdef XK_dead_horn
20029 || orig_keysym == XK_dead_horn
20030 #endif
20031 #ifdef XK_dead_stroke
20032 || orig_keysym == XK_dead_stroke
20033 #endif
20034 #ifdef XK_dead_abovecomma
20035 || orig_keysym == XK_dead_abovecomma
20036 #endif
20037 || IsKeypadKey (keysym)
20038 || IsFunctionKey (keysym)
20039
20040 || (orig_keysym & (1 << 28))
20041 || (keysym != NoSymbol && nbytes == 0))
20042 && ! (IsModifierKey (orig_keysym)
20043
20044
20045
20046
20047
20048 #if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
20049 || (XK_ISO_Lock <= orig_keysym
20050 && orig_keysym <= XK_ISO_Last_Group_Lock)
20051 #endif
20052 ))
20053 {
20054 STORE_KEYSYM_FOR_DEBUG (keysym);
20055
20056
20057 inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
20058 inev.ie.code = keysym;
20059
20060 #ifdef HAVE_XINPUT2
20061 if (event->xkey.time == pending_keystroke_time)
20062 {
20063 source = xi_device_from_id (dpyinfo,
20064 dpyinfo->pending_keystroke_source);
20065
20066 if (source)
20067 inev.ie.device = source->name;
20068 }
20069 #endif
20070
20071 goto done_keysym;
20072 }
20073
20074 {
20075 ptrdiff_t i;
20076
20077 for (i = 0; i < nbytes; i++)
20078 {
20079 STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]);
20080 }
20081
20082 if (nbytes)
20083 {
20084 inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
20085 inev.ie.arg = make_unibyte_string ((char *) copy_bufptr, nbytes);
20086
20087 Fput_text_property (make_fixnum (0), make_fixnum (nbytes),
20088 Qcoding, coding, inev.ie.arg);
20089
20090 #ifdef HAVE_XINPUT2
20091 if (event->xkey.time == pending_keystroke_time
20092
20093
20094
20095
20096 || (pending_keystroke_time && !event->xkey.time))
20097 {
20098 source = xi_device_from_id (dpyinfo,
20099 dpyinfo->pending_keystroke_source);
20100
20101 if (source)
20102 inev.ie.device = source->name;
20103 }
20104 #endif
20105 }
20106
20107 if (keysym == NoSymbol)
20108 break;
20109 }
20110 }
20111 done_keysym:
20112 #ifdef HAVE_X_I18N
20113 if (f)
20114 {
20115 struct window *w = XWINDOW (f->selected_window);
20116 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
20117
20118 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
20119 xic_set_statusarea (f);
20120 }
20121
20122
20123
20124
20125 break;
20126 #else
20127 goto OTHER;
20128 #endif
20129
20130 case KeyRelease:
20131 #ifdef HAVE_X_I18N
20132
20133
20134
20135 break;
20136 #else
20137 goto OTHER;
20138 #endif
20139
20140 case EnterNotify:
20141 x_display_set_last_user_time (dpyinfo, event->xcrossing.time,
20142 event->xcrossing.send_event,
20143 false);
20144
20145 #ifdef HAVE_XWIDGETS
20146 {
20147 struct xwidget_view *xvw;
20148 Mouse_HLInfo *hlinfo;
20149
20150 xvw = xwidget_view_from_window (event->xcrossing.window);
20151
20152 if (xvw)
20153 {
20154 xwidget_motion_or_crossing (xvw, event);
20155 hlinfo = MOUSE_HL_INFO (xvw->frame);
20156
20157 if (xvw->frame == hlinfo->mouse_face_mouse_frame)
20158 {
20159 clear_mouse_face (hlinfo);
20160 hlinfo->mouse_face_mouse_frame = 0;
20161 x_flush_dirty_back_buffer_on (xvw->frame);
20162 }
20163
20164 if (any_help_event_p)
20165 do_help = -1;
20166
20167 goto OTHER;
20168 }
20169 }
20170 #endif
20171
20172 #ifdef HAVE_XINPUT2
20173
20174
20175
20176
20177
20178
20179
20180 if (dpyinfo->supports_xi2)
20181 goto OTHER;
20182 #endif
20183
20184 if (x_top_window_to_frame (dpyinfo, event->xcrossing.window))
20185 x_detect_focus_change (dpyinfo, any, event, &inev.ie);
20186
20187 f = any;
20188
20189 if (f && event->xcrossing.window == FRAME_X_WINDOW (f))
20190 x_compute_root_window_offset (f, event->xcrossing.x_root,
20191 event->xcrossing.y_root,
20192 event->xcrossing.x,
20193 event->xcrossing.y);
20194
20195
20196
20197
20198
20199 if (f && x_mouse_click_focus_ignore_position)
20200 {
20201 ignore_next_mouse_click_timeout = (event->xmotion.time
20202 + x_mouse_click_focus_ignore_time);
20203 mouse_click_timeout_display = dpyinfo;
20204 }
20205
20206
20207
20208 if (f && !f->output_data.x->hourglass_p)
20209 x_note_mouse_movement (f, &event->xmotion, Qnil);
20210 #ifdef USE_GTK
20211
20212
20213 if (!f && dpyinfo->last_mouse_glyph_frame)
20214 x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &event->xmotion,
20215 Qnil);
20216 #endif
20217 goto OTHER;
20218
20219 case FocusIn:
20220 #if defined HAVE_XINPUT2 \
20221 && (defined HAVE_GTK3 || (!defined USE_GTK && !defined USE_X_TOOLKIT))
20222
20223
20224
20225
20226
20227
20228
20229
20230
20231
20232 if (dpyinfo->supports_xi2)
20233 goto OTHER;
20234 #endif
20235 #ifdef USE_GTK
20236
20237
20238
20239
20240
20241
20242
20243
20244
20245
20246
20247
20248 if (EQ (x_set_frame_visibility_more_laxly, Qfocus_in)
20249 || EQ (x_set_frame_visibility_more_laxly, Qt))
20250 #endif
20251 {
20252 f = any;
20253 if (f && FRAME_ICONIFIED_P (f))
20254 {
20255 SET_FRAME_VISIBLE (f, 1);
20256 SET_FRAME_ICONIFIED (f, false);
20257 f->output_data.x->has_been_visible = true;
20258 inev.ie.kind = DEICONIFY_EVENT;
20259 XSETFRAME (inev.ie.frame_or_window, f);
20260 }
20261 }
20262
20263 x_detect_focus_change (dpyinfo, any, event, &inev.ie);
20264 goto OTHER;
20265
20266 case LeaveNotify:
20267 x_display_set_last_user_time (dpyinfo, event->xcrossing.time,
20268 event->xcrossing.send_event, false);
20269
20270 #ifdef HAVE_XINPUT2
20271
20272
20273
20274
20275
20276
20277
20278 if (dpyinfo->supports_xi2)
20279 {
20280 #if !defined USE_X_TOOLKIT && (!defined USE_GTK || defined HAVE_GTK3)
20281 goto OTHER;
20282 #else
20283
20284
20285
20286
20287
20288
20289
20290 goto just_clear_mouse_face;
20291 #endif
20292 }
20293 #endif
20294
20295 #ifdef HAVE_XWIDGETS
20296 {
20297 struct xwidget_view *xvw;
20298
20299 xvw = xwidget_view_from_window (event->xcrossing.window);
20300
20301 if (xvw)
20302 {
20303 xwidget_motion_or_crossing (xvw, event);
20304 goto OTHER;
20305 }
20306 }
20307 #endif
20308
20309 if (x_top_window_to_frame (dpyinfo, event->xcrossing.window))
20310 x_detect_focus_change (dpyinfo, any, event, &inev.ie);
20311
20312 #if defined HAVE_XINPUT2 \
20313 && (defined USE_X_TOOLKIT || (defined USE_GTK && !defined HAVE_GTK3))
20314 just_clear_mouse_face:
20315 #endif
20316
20317 #if defined USE_X_TOOLKIT
20318
20319
20320 f = x_window_to_frame (dpyinfo, event->xcrossing.window);
20321
20322 if (!f)
20323 f = x_top_window_to_frame (dpyinfo, event->xcrossing.window);
20324 #else
20325 f = x_top_window_to_frame (dpyinfo, event->xcrossing.window);
20326 #endif
20327
20328 if (f)
20329 {
20330
20331
20332
20333
20334
20335 if (f == dpyinfo->last_mouse_motion_frame)
20336 dpyinfo->last_mouse_motion_frame = NULL;
20337
20338
20339
20340 if (f == dpyinfo->last_mouse_glyph_frame)
20341 dpyinfo->last_mouse_glyph_frame = NULL;
20342
20343 if (f == hlinfo->mouse_face_mouse_frame)
20344 {
20345
20346
20347 clear_mouse_face (hlinfo);
20348 hlinfo->mouse_face_mouse_frame = 0;
20349 x_flush_dirty_back_buffer_on (f);
20350 }
20351
20352
20353
20354
20355
20356 if (any_help_event_p
20357
20358
20359
20360 && !((EQ (track_mouse, Qdrag_source)
20361 || EQ (track_mouse, Qdropping))
20362 && gui_mouse_grabbed (dpyinfo)))
20363 do_help = -1;
20364
20365 if (event->xcrossing.window == FRAME_X_WINDOW (f))
20366 x_compute_root_window_offset (f, event->xcrossing.x_root,
20367 event->xcrossing.y_root,
20368 event->xcrossing.x,
20369 event->xcrossing.y);
20370
20371 }
20372 #ifdef USE_GTK
20373
20374 else if (dpyinfo->last_mouse_glyph_frame)
20375 x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame,
20376 &event->xmotion, Qnil);
20377 #endif
20378 goto OTHER;
20379
20380 case FocusOut:
20381 #if defined HAVE_XINPUT2 \
20382 && (defined HAVE_GTK3 || (!defined USE_GTK && !defined USE_X_TOOLKIT))
20383
20384
20385
20386
20387
20388
20389
20390
20391
20392
20393 if (dpyinfo->supports_xi2)
20394 goto OTHER;
20395 #endif
20396 x_detect_focus_change (dpyinfo, any, event, &inev.ie);
20397 goto OTHER;
20398
20399 case MotionNotify:
20400 {
20401 XMotionEvent xmotion = event->xmotion;
20402
20403 previous_help_echo_string = help_echo_string;
20404 help_echo_string = Qnil;
20405
20406 if (hlinfo->mouse_face_hidden)
20407 {
20408 hlinfo->mouse_face_hidden = false;
20409 clear_mouse_face (hlinfo);
20410 }
20411
20412 f = mouse_or_wdesc_frame (dpyinfo, event->xmotion.window);
20413
20414 if (f && event->xmotion.window == FRAME_X_WINDOW (f))
20415
20416
20417 x_compute_root_window_offset (f, event->xmotion.x_root,
20418 event->xmotion.y_root,
20419 event->xmotion.x,
20420 event->xmotion.y);
20421
20422 if (x_dnd_in_progress
20423
20424
20425
20426
20427
20428 && (command_loop_level + minibuf_level
20429 <= x_dnd_recursion_depth)
20430 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
20431 {
20432 Window target, toplevel;
20433 int target_proto, motif_style;
20434 xm_top_level_leave_message lmsg;
20435 xm_top_level_enter_message emsg;
20436 xm_drag_motion_message dmsg;
20437 XRectangle *r;
20438 bool was_frame;
20439
20440
20441 clear_mouse_face (hlinfo);
20442 hlinfo->mouse_face_hidden = true;
20443
20444
20445
20446
20447
20448
20449 if (f)
20450 {
20451 XTtoggle_invisible_pointer (f, false);
20452
20453 r = &dpyinfo->last_mouse_glyph;
20454
20455
20456
20457 if (f != dpyinfo->last_mouse_glyph_frame
20458 || event->xmotion.x < r->x
20459 || event->xmotion.x >= r->x + r->width
20460 || event->xmotion.y < r->y
20461 || event->xmotion.y >= r->y + r->height)
20462 {
20463 f->mouse_moved = true;
20464 f->last_mouse_device = Qnil;
20465 dpyinfo->last_mouse_scroll_bar = NULL;
20466
20467 remember_mouse_glyph (f, event->xmotion.x,
20468 event->xmotion.y, r);
20469 dpyinfo->last_mouse_glyph_frame = f;
20470 }
20471 }
20472
20473 if (event->xmotion.same_screen)
20474 target = x_dnd_get_target_window (dpyinfo,
20475 event->xmotion.x_root,
20476 event->xmotion.y_root,
20477 &target_proto,
20478 &motif_style, &toplevel,
20479 &was_frame);
20480 else
20481 target = x_dnd_fill_empty_target (&target_proto, &motif_style,
20482 &toplevel, &was_frame);
20483
20484 if (toplevel != x_dnd_last_seen_toplevel)
20485 {
20486 if (toplevel != FRAME_OUTER_WINDOW (x_dnd_frame)
20487 && x_dnd_return_frame == 1)
20488 x_dnd_return_frame = 2;
20489
20490 if (x_dnd_return_frame == 2
20491 && x_any_window_to_frame (dpyinfo, toplevel))
20492 {
20493 if (x_dnd_last_seen_window != None
20494 && x_dnd_last_protocol_version != -1
20495 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
20496 x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window,
20497 x_dnd_last_seen_toplevel);
20498 else if (x_dnd_last_seen_window != None
20499 && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
20500 && !x_dnd_disable_motif_drag
20501 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
20502 {
20503 if (!x_dnd_motif_setup_p)
20504 xm_setup_drag_info (dpyinfo, x_dnd_frame);
20505
20506 lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
20507 XM_DRAG_REASON_TOP_LEVEL_LEAVE);
20508 lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
20509 lmsg.zero = 0;
20510 lmsg.timestamp = event->xmotion.time;
20511 lmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
20512
20513 if (x_dnd_motif_setup_p)
20514 xm_send_top_level_leave_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
20515 x_dnd_last_seen_window, &lmsg);
20516 }
20517
20518 x_dnd_end_window = x_dnd_last_seen_window;
20519 x_dnd_last_seen_window = None;
20520 x_dnd_last_seen_toplevel = None;
20521 x_dnd_in_progress = false;
20522 x_dnd_return_frame_object
20523 = x_any_window_to_frame (dpyinfo, toplevel);
20524 x_dnd_return_frame = 3;
20525 x_dnd_waiting_for_finish = false;
20526 target = None;
20527 }
20528 }
20529
20530 if (target != x_dnd_last_seen_window)
20531 {
20532 if (x_dnd_last_seen_window != None
20533 && x_dnd_last_protocol_version != -1
20534 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
20535 x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window,
20536 x_dnd_last_seen_toplevel);
20537 else if (x_dnd_last_seen_window != None
20538 && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
20539 && x_dnd_disable_motif_drag
20540 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
20541 {
20542 if (!x_dnd_motif_setup_p)
20543 xm_setup_drag_info (dpyinfo, x_dnd_frame);
20544
20545
20546
20547
20548
20549
20550
20551 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
20552 XM_DRAG_REASON_DRAG_MOTION);
20553 dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
20554 dmsg.side_effects = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
20555 x_dnd_wanted_action),
20556 XM_DROP_SITE_NONE, x_dnd_motif_operations,
20557 XM_DROP_ACTION_DROP_CANCEL);
20558 dmsg.timestamp = event->xmotion.time;
20559 dmsg.x = event->xmotion.x_root;
20560 dmsg.y = event->xmotion.y_root;
20561
20562 lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
20563 XM_DRAG_REASON_TOP_LEVEL_LEAVE);
20564 lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
20565 lmsg.zero = 0;
20566 lmsg.timestamp = event->xbutton.time;
20567 lmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
20568
20569 if (x_dnd_motif_setup_p)
20570 {
20571 xm_send_drag_motion_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
20572 x_dnd_last_seen_window, &dmsg);
20573 xm_send_top_level_leave_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
20574 x_dnd_last_seen_window, &lmsg);
20575 }
20576 }
20577
20578 x_dnd_action = None;
20579 x_dnd_last_seen_toplevel = toplevel;
20580 x_dnd_last_seen_window = target;
20581 x_dnd_last_protocol_version = target_proto;
20582 x_dnd_last_motif_style = motif_style;
20583 x_dnd_last_window_is_frame = was_frame;
20584
20585 if (target != None && x_dnd_last_protocol_version != -1)
20586 x_dnd_send_enter (x_dnd_frame, target,
20587 x_dnd_last_seen_toplevel,
20588 x_dnd_last_protocol_version);
20589 else if (target != None && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
20590 && !x_dnd_disable_motif_drag)
20591 {
20592 if (!x_dnd_motif_setup_p)
20593 xm_setup_drag_info (dpyinfo, x_dnd_frame);
20594
20595 emsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
20596 XM_DRAG_REASON_TOP_LEVEL_ENTER);
20597 emsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
20598 emsg.zero = 0;
20599 emsg.timestamp = event->xbutton.time;
20600 emsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
20601 emsg.index_atom = x_dnd_motif_atom;
20602
20603 if (x_dnd_motif_setup_p)
20604 xm_send_top_level_enter_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
20605 target, &emsg);
20606 }
20607 }
20608 else
20609 x_dnd_last_seen_toplevel = toplevel;
20610
20611 if (x_dnd_last_window_is_frame && target != None)
20612 x_dnd_note_self_position (dpyinfo, target,
20613 event->xbutton.x_root,
20614 event->xbutton.y_root);
20615 else if (x_dnd_last_protocol_version != -1 && target != None)
20616 x_dnd_send_position (x_dnd_frame, target,
20617 x_dnd_last_seen_toplevel,
20618 x_dnd_last_protocol_version,
20619 event->xmotion.x_root,
20620 event->xmotion.y_root,
20621 x_dnd_selection_timestamp,
20622 x_dnd_wanted_action, 0,
20623 event->xmotion.state);
20624 else if (XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) && target != None
20625 && !x_dnd_disable_motif_drag)
20626 {
20627 if (!x_dnd_motif_setup_p)
20628 xm_setup_drag_info (dpyinfo, x_dnd_frame);
20629
20630 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
20631 XM_DRAG_REASON_DRAG_MOTION);
20632 dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
20633 dmsg.side_effects = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
20634 x_dnd_wanted_action),
20635 XM_DROP_SITE_VALID, x_dnd_motif_operations,
20636 (!x_dnd_xm_use_help
20637 ? XM_DROP_ACTION_DROP
20638 : XM_DROP_ACTION_DROP_HELP));
20639 dmsg.timestamp = event->xbutton.time;
20640 dmsg.x = event->xmotion.x_root;
20641 dmsg.y = event->xmotion.y_root;
20642
20643 if (x_dnd_motif_setup_p)
20644 xm_send_drag_motion_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
20645 target, &dmsg);
20646 }
20647
20648 x_dnd_update_tooltip_position (event->xmotion.x_root,
20649 event->xmotion.y_root);
20650
20651 goto OTHER;
20652 }
20653
20654 #ifdef USE_GTK
20655 if (f && xg_event_is_for_scrollbar (f, event, false))
20656 f = 0;
20657 #endif
20658 #ifdef HAVE_XWIDGETS
20659 struct xwidget_view *xvw;
20660
20661 xvw = xwidget_view_from_window (event->xmotion.window);
20662
20663 if (xvw)
20664 xwidget_motion_or_crossing (xvw, event);
20665 #endif
20666 if (f)
20667 {
20668
20669
20670
20671 if (!NILP (Vmouse_autoselect_window)
20672 && !popup_activated ()
20673
20674
20675
20676
20677
20678 && !MINI_WINDOW_P (XWINDOW (selected_window))
20679
20680
20681 && (f == XFRAME (selected_frame)
20682 || !NILP (focus_follows_mouse)))
20683 {
20684 static Lisp_Object last_mouse_window;
20685
20686 if (xmotion.window != FRAME_X_WINDOW (f))
20687 {
20688 x_translate_coordinates (f, xmotion.x_root, xmotion.y_root,
20689 &xmotion.x, &xmotion.y);
20690 xmotion.window = FRAME_X_WINDOW (f);
20691 }
20692
20693 Lisp_Object window = window_from_coordinates
20694 (f, xmotion.x, xmotion.y, 0, false, false);
20695
20696
20697
20698
20699
20700
20701
20702
20703
20704 if (WINDOWP (window)
20705 && !EQ (window, last_mouse_window)
20706 && !EQ (window, selected_window))
20707 {
20708 inev.ie.kind = SELECT_WINDOW_EVENT;
20709 inev.ie.frame_or_window = window;
20710 }
20711
20712
20713 last_mouse_window = window;
20714 }
20715
20716 if (!x_note_mouse_movement (f, &xmotion, Qnil))
20717 help_echo_string = previous_help_echo_string;
20718 }
20719 else
20720 {
20721 #ifndef USE_TOOLKIT_SCROLL_BARS
20722 struct scroll_bar *bar
20723 = x_window_to_scroll_bar (event->xmotion.display,
20724 event->xmotion.window, 2);
20725
20726 if (bar)
20727 x_scroll_bar_note_movement (bar, &event->xmotion);
20728 #endif
20729
20730
20731
20732 clear_mouse_face (hlinfo);
20733 }
20734
20735
20736
20737 if (!NILP (help_echo_string)
20738 || !NILP (previous_help_echo_string))
20739 do_help = 1;
20740
20741 if (f)
20742 x_flush_dirty_back_buffer_on (f);
20743 goto OTHER;
20744 }
20745
20746 case ConfigureNotify:
20747
20748
20749
20750
20751
20752
20753
20754
20755
20756
20757
20758
20759 configureEvent = *event;
20760 while (XPending (dpyinfo->display))
20761 {
20762 XNextEvent (dpyinfo->display, &next_event);
20763 if (next_event.type != ConfigureNotify
20764 || next_event.xconfigure.window != event->xconfigure.window
20765
20766
20767
20768 || next_event.xconfigure.width != event->xconfigure.width
20769 || next_event.xconfigure.height != event->xconfigure.height)
20770 {
20771 XPutBackEvent (dpyinfo->display, &next_event);
20772 break;
20773 }
20774 else
20775 configureEvent = next_event;
20776 }
20777
20778
20779
20780
20781 if (configureEvent.xconfigure.window == dpyinfo->root_window)
20782 {
20783 #ifdef HAVE_XRANDR
20784
20785
20786 XRRUpdateConfiguration (&configureEvent);
20787 #elif !defined USE_GTK
20788
20789
20790
20791 if (configureEvent.xconfigure.width != dpyinfo->screen_width
20792 || configureEvent.xconfigure.height != dpyinfo->screen_height)
20793 {
20794
20795
20796
20797
20798 if (!x_find_monitors_changed_event (dpyinfo))
20799 {
20800 inev.ie.kind = MONITORS_CHANGED_EVENT;
20801 XSETTERMINAL (inev.ie.arg, dpyinfo->terminal);
20802
20803
20804
20805 kbd_buffer_store_event (&inev.ie);
20806 inev.ie.kind = NO_EVENT;
20807 }
20808
20809
20810
20811 x_dnd_update_tooltip_now ();
20812 }
20813 #endif
20814
20815 dpyinfo->screen_width = configureEvent.xconfigure.width;
20816 dpyinfo->screen_height = configureEvent.xconfigure.height;
20817 }
20818
20819 if (x_dnd_in_progress && x_dnd_use_toplevels
20820 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
20821 {
20822 int rc, dest_x, dest_y;
20823 Window child;
20824 struct x_client_list_window *tem, *last = NULL;
20825
20826 for (tem = x_dnd_toplevels; tem; last = tem, tem = tem->next)
20827 {
20828
20829
20830
20831 if (tem->window == configureEvent.xconfigure.window)
20832 {
20833 x_catch_errors (dpyinfo->display);
20834 rc = (XTranslateCoordinates (dpyinfo->display,
20835 configureEvent.xconfigure.window,
20836 dpyinfo->root_window,
20837 -configureEvent.xconfigure.border_width,
20838 -configureEvent.xconfigure.border_width,
20839 &dest_x, &dest_y, &child)
20840 && !x_had_errors_p (dpyinfo->display));
20841 x_uncatch_errors_after_check ();
20842
20843 if (rc)
20844 {
20845 tem->x = dest_x;
20846 tem->y = dest_y;
20847 tem->width = (configureEvent.xconfigure.width
20848 + configureEvent.xconfigure.border_width);
20849 tem->height = (configureEvent.xconfigure.height
20850 + configureEvent.xconfigure.border_width);
20851 }
20852 else
20853 {
20854
20855
20856
20857 if (!last)
20858 x_dnd_toplevels = tem->next;
20859 else
20860 last->next = tem->next;
20861
20862 #ifdef HAVE_XSHAPE
20863 if (tem->n_input_rects != -1)
20864 xfree (tem->input_rects);
20865 if (tem->n_bounding_rects != -1)
20866 xfree (tem->bounding_rects);
20867 #endif
20868 xfree (tem);
20869 }
20870
20871 break;
20872 }
20873 }
20874 }
20875
20876 #if defined HAVE_GTK3 && defined USE_TOOLKIT_SCROLL_BARS
20877 struct scroll_bar *bar = x_window_to_scroll_bar (dpyinfo->display,
20878 configureEvent.xconfigure.window, 2);
20879
20880
20881
20882 if (bar)
20883 {
20884
20885
20886 while (XPending (dpyinfo->display))
20887 {
20888 XNextEvent (dpyinfo->display, &next_event);
20889 if (next_event.type != ConfigureNotify
20890 || next_event.xconfigure.window != event->xconfigure.window)
20891 {
20892 XPutBackEvent (dpyinfo->display, &next_event);
20893 break;
20894 }
20895 else
20896 configureEvent = next_event;
20897 }
20898
20899 if (configureEvent.xconfigure.width != max (bar->width, 1)
20900 || configureEvent.xconfigure.height != max (bar->height, 1))
20901 {
20902 XResizeWindow (dpyinfo->display, bar->x_window,
20903 max (bar->width, 1), max (bar->height, 1));
20904 x_flush (WINDOW_XFRAME (XWINDOW (bar->window)));
20905 }
20906
20907 #ifdef HAVE_XDBE
20908 if (f && FRAME_X_DOUBLE_BUFFERED_P (f))
20909 x_drop_xrender_surfaces (f);
20910 #endif
20911
20912 goto OTHER;
20913 }
20914 #endif
20915
20916 f = x_top_window_to_frame (dpyinfo, configureEvent.xconfigure.window);
20917
20918
20919
20920 if (any)
20921 FRAME_X_OUTPUT (any)->window_offset_certain_p = false;
20922
20923
20924
20925
20926
20927
20928 #ifdef HAVE_XDBE
20929 if (f && FRAME_X_DOUBLE_BUFFERED_P (f))
20930 x_drop_xrender_surfaces (f);
20931 #endif
20932 #if defined USE_CAIRO && !defined USE_GTK
20933 if (f)
20934 x_cr_update_surface_desired_size (f, configureEvent.xconfigure.width,
20935 configureEvent.xconfigure.height);
20936 else if (any && configureEvent.xconfigure.window == FRAME_X_WINDOW (any))
20937 x_cr_update_surface_desired_size (any,
20938 configureEvent.xconfigure.width,
20939 configureEvent.xconfigure.height);
20940 if (f || (any && configureEvent.xconfigure.window == FRAME_X_WINDOW (any)))
20941 x_update_opaque_region (f ? f : any, &configureEvent);
20942 #endif
20943 #ifdef USE_GTK
20944 if (!f
20945 && (f = any)
20946 && configureEvent.xconfigure.window == FRAME_X_WINDOW (f)
20947 && (FRAME_VISIBLE_P(f)
20948 || !(configureEvent.xconfigure.width <= 1
20949 && configureEvent.xconfigure.height <= 1)))
20950 {
20951
20952 if (CONSP (frame_size_history))
20953 frame_size_history_extra
20954 (f, build_string ("ConfigureNotify"),
20955 FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f),
20956 configureEvent.xconfigure.width,
20957 configureEvent.xconfigure.height,
20958 f->new_width, f->new_height);
20959
20960 #ifdef HAVE_XDBE
20961 if (FRAME_X_DOUBLE_BUFFERED_P (f))
20962 x_drop_xrender_surfaces (f);
20963 #endif
20964 xg_frame_resized (f, configureEvent.xconfigure.width,
20965 configureEvent.xconfigure.height);
20966 #ifdef USE_CAIRO
20967 x_cr_update_surface_desired_size (f, configureEvent.xconfigure.width,
20968 configureEvent.xconfigure.height);
20969 #endif
20970 x_update_opaque_region (f, &configureEvent);
20971 f = 0;
20972 }
20973 #endif
20974 if (f
20975 && (FRAME_VISIBLE_P(f)
20976 || !(configureEvent.xconfigure.width <= 1
20977 && configureEvent.xconfigure.height <= 1)))
20978 {
20979 #ifdef USE_GTK
20980
20981
20982 if (configureEvent.xconfigure.window == FRAME_X_WINDOW (f))
20983 #endif
20984 x_net_wm_state (f, configureEvent.xconfigure.window);
20985
20986 #if defined USE_X_TOOLKIT || defined USE_GTK
20987
20988 if (FRAME_TOOLTIP_P (f))
20989 {
20990 if (FRAME_PIXEL_HEIGHT (f) != configureEvent.xconfigure.height
20991 || FRAME_PIXEL_WIDTH (f) != configureEvent.xconfigure.width)
20992 SET_FRAME_GARBAGED (f);
20993
20994 FRAME_PIXEL_HEIGHT (f) = configureEvent.xconfigure.height;
20995 FRAME_PIXEL_WIDTH (f) = configureEvent.xconfigure.width;
20996 }
20997 #endif
20998
20999 #ifndef USE_X_TOOLKIT
21000 #ifndef USE_GTK
21001 int width = configureEvent.xconfigure.width;
21002 int height = configureEvent.xconfigure.height;
21003
21004 if (CONSP (frame_size_history))
21005 frame_size_history_extra
21006 (f, build_string ("ConfigureNotify"),
21007 FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f),
21008 width, height, f->new_width, f->new_height);
21009
21010
21011
21012
21013
21014
21015
21016
21017
21018 if (width != FRAME_PIXEL_WIDTH (f)
21019 || height != FRAME_PIXEL_HEIGHT (f)
21020 || (f->new_size_p
21021 && ((f->new_width >= 0 && width != f->new_width)
21022 || (f->new_height >= 0 && height != f->new_height))))
21023 {
21024 change_frame_size (f, width, height, false, true, false);
21025 x_clear_under_internal_border (f);
21026 SET_FRAME_GARBAGED (f);
21027 cancel_mouse_face (f);
21028 }
21029 #endif
21030 #endif
21031
21032 #ifdef USE_GTK
21033
21034
21035 if (FRAME_GTK_OUTER_WIDGET (f)
21036 && gtk_widget_get_mapped (FRAME_GTK_OUTER_WIDGET (f)))
21037 #endif
21038 {
21039 int old_left = f->left_pos;
21040 int old_top = f->top_pos;
21041 Lisp_Object frame;
21042
21043 XSETFRAME (frame, f);
21044
21045 if (!FRAME_PARENT_FRAME (f))
21046 x_real_positions (f, &f->left_pos, &f->top_pos);
21047 else
21048 {
21049 Window root;
21050 unsigned int dummy_uint;
21051
21052 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
21053 &root, &f->left_pos, &f->top_pos,
21054 &dummy_uint, &dummy_uint, &dummy_uint, &dummy_uint);
21055 }
21056
21057 if (!FRAME_TOOLTIP_P (f)
21058 && (old_left != f->left_pos || old_top != f->top_pos))
21059 {
21060 inev.ie.kind = MOVE_FRAME_EVENT;
21061 XSETFRAME (inev.ie.frame_or_window, f);
21062 }
21063 }
21064
21065
21066 #ifdef HAVE_X_I18N
21067 if (f)
21068 {
21069 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
21070 xic_set_statusarea (f);
21071
21072 struct window *w = XWINDOW (f->selected_window);
21073 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
21074 }
21075 #endif
21076
21077 #ifdef HAVE_XINPUT2
21078 if (f && dpyinfo->supports_xi2)
21079 {
21080 Mouse_HLInfo *hlinfo;
21081
21082
21083
21084
21085
21086
21087
21088
21089 if (dpyinfo->last_mouse_motion_frame == f)
21090 dpyinfo->last_mouse_motion_frame = NULL;
21091
21092 hlinfo = MOUSE_HL_INFO (f);
21093
21094 if (hlinfo->mouse_face_mouse_frame == f)
21095 reset_mouse_highlight (hlinfo);
21096 }
21097 #endif
21098
21099 }
21100
21101 if (x_dnd_in_progress
21102 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
21103 x_dnd_update_state (dpyinfo, dpyinfo->last_user_time);
21104 goto OTHER;
21105
21106 case ButtonRelease:
21107 case ButtonPress:
21108 {
21109 if (event->xbutton.type == ButtonPress)
21110 x_display_set_last_user_time (dpyinfo, event->xbutton.time,
21111 event->xbutton.send_event, true);
21112
21113 #ifdef HAVE_XWIDGETS
21114 struct xwidget_view *xvw;
21115
21116 xvw = xwidget_view_from_window (event->xbutton.window);
21117
21118 if (xvw)
21119 {
21120 xwidget_button (xvw, event->type == ButtonPress,
21121 event->xbutton.x, event->xbutton.y,
21122 event->xbutton.button, event->xbutton.state,
21123 event->xbutton.time);
21124
21125 if (!EQ (selected_window, xvw->w) && (event->xbutton.button < 4))
21126 {
21127 inev.ie.kind = SELECT_WINDOW_EVENT;
21128 inev.ie.frame_or_window = xvw->w;
21129 }
21130
21131 *finish = X_EVENT_DROP;
21132 goto OTHER;
21133 }
21134 #endif
21135
21136
21137 Lisp_Object tab_bar_arg = Qnil;
21138 bool tab_bar_p = false;
21139 bool tool_bar_p = false;
21140 bool dnd_grab = false;
21141
21142 if (x_dnd_in_progress
21143
21144
21145
21146
21147
21148 && (command_loop_level + minibuf_level
21149 <= x_dnd_recursion_depth)
21150 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
21151 {
21152 f = mouse_or_wdesc_frame (dpyinfo, event->xbutton.window);
21153
21154 if (f && event->xbutton.window == FRAME_X_WINDOW (f))
21155
21156
21157 x_compute_root_window_offset (f, event->xbutton.x_root,
21158 event->xbutton.y_root,
21159 event->xbutton.x,
21160 event->xbutton.y);
21161
21162 if (event->type == ButtonPress)
21163 {
21164 x_display_set_last_user_time (dpyinfo, event->xbutton.time,
21165 event->xbutton.send_event, true);
21166
21167 dpyinfo->grabbed |= (1 << event->xbutton.button);
21168 dpyinfo->last_mouse_frame = f;
21169
21170 if (f)
21171 f->last_tab_bar_item = -1;
21172 #if ! defined (USE_GTK)
21173 if (f)
21174 f->last_tool_bar_item = -1;
21175 #endif
21176 }
21177 else
21178 dpyinfo->grabbed &= ~(1 << event->xbutton.button);
21179
21180 if (event->xbutton.type == ButtonPress
21181 && x_dnd_last_seen_window != None)
21182 {
21183 if (x_dnd_last_window_is_frame)
21184 x_dnd_note_self_wheel (dpyinfo,
21185 x_dnd_last_seen_window,
21186 event->xbutton.x_root,
21187 event->xbutton.y_root,
21188 event->xbutton.button,
21189 event->xbutton.state,
21190 event->xbutton.time);
21191 else if (x_dnd_last_protocol_version != -1)
21192 x_dnd_send_position (x_dnd_frame,
21193 x_dnd_last_seen_window,
21194 x_dnd_last_seen_toplevel,
21195 x_dnd_last_protocol_version,
21196 event->xbutton.x_root,
21197 event->xbutton.y_root,
21198 event->xbutton.time,
21199 x_dnd_wanted_action,
21200 event->xbutton.button,
21201 event->xbutton.state);
21202
21203 goto OTHER;
21204 }
21205
21206 if (event->xbutton.type == ButtonRelease)
21207 {
21208 for (int i = 1; i < 8; ++i)
21209 {
21210 if (i != event->xbutton.button
21211 && event->xbutton.state & (Button1Mask << (i - 1)))
21212 dnd_grab = true;
21213 }
21214
21215 if (!dnd_grab)
21216 {
21217 x_dnd_end_window = x_dnd_last_seen_window;
21218 x_dnd_in_progress = false;
21219
21220 if (x_dnd_update_tooltip
21221 && FRAMEP (tip_frame)
21222 && FRAME_LIVE_P (XFRAME (tip_frame))
21223 && (FRAME_X_DISPLAY (XFRAME (tip_frame))
21224 == FRAME_X_DISPLAY (x_dnd_frame)))
21225 Fx_hide_tip ();
21226
21227 x_dnd_finish_frame = x_dnd_frame;
21228
21229 if (x_dnd_last_seen_window != None
21230 && x_dnd_last_window_is_frame)
21231 {
21232 x_dnd_waiting_for_finish = false;
21233 x_dnd_note_self_drop (dpyinfo,
21234 x_dnd_last_seen_window,
21235 event->xbutton.x_root,
21236 event->xbutton.y_root,
21237 event->xbutton.time);
21238 }
21239 else if (x_dnd_last_seen_window != None
21240 && x_dnd_last_protocol_version != -1)
21241 {
21242 x_dnd_pending_finish_target = x_dnd_last_seen_toplevel;
21243 x_dnd_waiting_for_finish_proto = x_dnd_last_protocol_version;
21244
21245 x_dnd_waiting_for_finish
21246 = x_dnd_do_drop (x_dnd_last_seen_window,
21247 x_dnd_last_seen_toplevel,
21248 x_dnd_last_protocol_version);
21249 x_dnd_finish_display = dpyinfo->display;
21250 }
21251 else if (x_dnd_last_seen_window != None)
21252 {
21253 xm_drop_start_message dmsg;
21254 xm_drag_receiver_info drag_receiver_info;
21255
21256 if (!xm_read_drag_receiver_info (dpyinfo, x_dnd_last_seen_window,
21257 &drag_receiver_info)
21258 && !x_dnd_disable_motif_protocol
21259 && drag_receiver_info.protocol_style != XM_DRAG_STYLE_NONE
21260 && (x_dnd_allow_current_frame
21261 || x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame)))
21262 {
21263 if (!x_dnd_motif_setup_p)
21264 xm_setup_drag_info (dpyinfo, x_dnd_frame);
21265
21266 if (x_dnd_motif_setup_p)
21267 {
21268 memset (&dmsg, 0, sizeof dmsg);
21269
21270 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
21271 XM_DRAG_REASON_DROP_START);
21272 dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST;
21273 dmsg.side_effects
21274 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
21275 x_dnd_wanted_action),
21276 XM_DROP_SITE_VALID, x_dnd_motif_operations,
21277 (!x_dnd_xm_use_help
21278 ? XM_DROP_ACTION_DROP
21279 : XM_DROP_ACTION_DROP_HELP));
21280 dmsg.timestamp = event->xbutton.time;
21281 dmsg.x = event->xbutton.x_root;
21282 dmsg.y = event->xbutton.y_root;
21283 dmsg.index_atom = x_dnd_motif_atom;
21284 dmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
21285
21286 if (!XM_DRAG_STYLE_IS_DROP_ONLY (drag_receiver_info.protocol_style))
21287 x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (x_dnd_frame),
21288 x_dnd_frame, x_dnd_last_seen_window,
21289 event->xbutton.time);
21290
21291 xm_send_drop_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
21292 x_dnd_last_seen_window, &dmsg);
21293
21294 x_dnd_waiting_for_finish = true;
21295 x_dnd_waiting_for_motif_finish_display = dpyinfo;
21296 x_dnd_waiting_for_motif_finish = 1;
21297 x_dnd_finish_display = dpyinfo->display;
21298 }
21299 }
21300 else
21301 x_dnd_send_unsupported_drop (dpyinfo, (x_dnd_last_seen_toplevel != None
21302 ? x_dnd_last_seen_toplevel
21303 : x_dnd_last_seen_window),
21304 event->xbutton.x_root, event->xbutton.y_root,
21305 event->xbutton.time);
21306 }
21307 else if (x_dnd_last_seen_toplevel != None)
21308 x_dnd_send_unsupported_drop (dpyinfo, x_dnd_last_seen_toplevel,
21309 event->xbutton.x_root,
21310 event->xbutton.y_root,
21311 event->xbutton.time);
21312
21313
21314 x_dnd_last_protocol_version = -1;
21315 x_dnd_last_motif_style = XM_DRAG_STYLE_NONE;
21316 x_dnd_last_seen_window = None;
21317 x_dnd_last_seen_toplevel = None;
21318 x_dnd_last_window_is_frame = false;
21319 x_dnd_frame = NULL;
21320 }
21321 }
21322
21323 goto OTHER;
21324 }
21325
21326 if (x_dnd_in_progress
21327 && (command_loop_level + minibuf_level
21328 <= x_dnd_recursion_depth))
21329 goto OTHER;
21330
21331 memset (&compose_status, 0, sizeof (compose_status));
21332 dpyinfo->last_mouse_glyph_frame = NULL;
21333
21334 f = mouse_or_wdesc_frame (dpyinfo, event->xbutton.window);
21335
21336 if (f && event->xbutton.window == FRAME_X_WINDOW (f))
21337
21338
21339 x_compute_root_window_offset (f, event->xbutton.x_root,
21340 event->xbutton.y_root,
21341 event->xbutton.x,
21342 event->xbutton.y);
21343
21344 if (f && event->xbutton.type == ButtonPress
21345 && !popup_activated ()
21346 && !x_window_to_scroll_bar (event->xbutton.display,
21347 event->xbutton.window, 2)
21348 && !FRAME_NO_ACCEPT_FOCUS (f))
21349 {
21350
21351
21352
21353
21354 struct frame *hf = dpyinfo->highlight_frame;
21355
21356 if (FRAME_PARENT_FRAME (f) || (hf && frame_ancestor_p (f, hf)))
21357 {
21358 x_ignore_errors_for_next_request (dpyinfo);
21359 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
21360 RevertToParent, event->xbutton.time);
21361 x_stop_ignoring_errors (dpyinfo);
21362
21363 if (FRAME_PARENT_FRAME (f))
21364 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
21365 }
21366 }
21367
21368 #ifdef USE_GTK
21369 if (!f)
21370 {
21371 f = x_any_window_to_frame (dpyinfo, event->xbutton.window);
21372
21373 if (event->xbutton.button > 3
21374 && event->xbutton.button < 8
21375 && f)
21376 {
21377 if (ignore_next_mouse_click_timeout
21378 && dpyinfo == mouse_click_timeout_display)
21379 {
21380 if (event->type == ButtonPress
21381 && event->xbutton.time > ignore_next_mouse_click_timeout)
21382 {
21383 ignore_next_mouse_click_timeout = 0;
21384 x_construct_mouse_click (&inev.ie, &event->xbutton, f);
21385 }
21386 if (event->type == ButtonRelease)
21387 ignore_next_mouse_click_timeout = 0;
21388 }
21389 else
21390 x_construct_mouse_click (&inev.ie, &event->xbutton, f);
21391
21392 *finish = X_EVENT_DROP;
21393 goto OTHER;
21394 }
21395 else
21396 f = NULL;
21397 }
21398
21399 if (f && xg_event_is_for_scrollbar (f, event, false))
21400 f = 0;
21401 #endif
21402 if (f)
21403 {
21404
21405 if (WINDOWP (f->tab_bar_window)
21406 && WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window)))
21407 {
21408 Lisp_Object window;
21409 int x = event->xbutton.x;
21410 int y = event->xbutton.y;
21411
21412 window = window_from_coordinates (f, x, y, 0, true, true);
21413 tab_bar_p = EQ (window, f->tab_bar_window);
21414
21415 if (tab_bar_p)
21416 {
21417 tab_bar_arg = handle_tab_bar_click
21418 (f, x, y, event->xbutton.type == ButtonPress,
21419 x_x_to_emacs_modifiers (dpyinfo, event->xbutton.state));
21420 x_flush_dirty_back_buffer_on (f);
21421 }
21422 }
21423
21424 #if ! defined (USE_GTK)
21425
21426 if (WINDOWP (f->tool_bar_window)
21427 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
21428 {
21429 Lisp_Object window;
21430 int x = event->xbutton.x;
21431 int y = event->xbutton.y;
21432
21433 window = window_from_coordinates (f, x, y, 0, true, true);
21434 tool_bar_p = (EQ (window, f->tool_bar_window)
21435 && (event->xbutton.type != ButtonRelease
21436 || f->last_tool_bar_item != -1));
21437
21438 if (tool_bar_p && event->xbutton.button < 4)
21439 {
21440 handle_tool_bar_click
21441 (f, x, y, event->xbutton.type == ButtonPress,
21442 x_x_to_emacs_modifiers (dpyinfo, event->xbutton.state));
21443 x_flush_dirty_back_buffer_on (f);
21444 }
21445 }
21446 #endif
21447
21448 if (!(tab_bar_p && NILP (tab_bar_arg)) && !tool_bar_p)
21449 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
21450 if (! popup_activated ())
21451 #endif
21452 {
21453 if (ignore_next_mouse_click_timeout
21454 && dpyinfo == mouse_click_timeout_display)
21455 {
21456 if (event->type == ButtonPress
21457 && event->xbutton.time > ignore_next_mouse_click_timeout)
21458 {
21459 ignore_next_mouse_click_timeout = 0;
21460 x_construct_mouse_click (&inev.ie, &event->xbutton, f);
21461 }
21462 if (event->type == ButtonRelease)
21463 ignore_next_mouse_click_timeout = 0;
21464 }
21465 else
21466 x_construct_mouse_click (&inev.ie, &event->xbutton, f);
21467
21468 if (!NILP (tab_bar_arg))
21469 inev.ie.arg = tab_bar_arg;
21470 }
21471
21472 if (FRAME_X_EMBEDDED_P (f)
21473 && !FRAME_NO_ACCEPT_FOCUS (f))
21474 xembed_send_message (f, event->xbutton.time,
21475 XEMBED_REQUEST_FOCUS, 0, 0, 0);
21476 }
21477 else
21478 {
21479 struct scroll_bar *bar
21480 = x_window_to_scroll_bar (event->xbutton.display,
21481 event->xbutton.window, 2);
21482
21483 #ifdef USE_TOOLKIT_SCROLL_BARS
21484
21485
21486 if (bar && event->xbutton.state & ControlMask)
21487 {
21488 x_scroll_bar_handle_click (bar, event, &inev.ie, Qnil);
21489 *finish = X_EVENT_DROP;
21490 }
21491 #else
21492 if (bar)
21493 x_scroll_bar_handle_click (bar, event, &inev.ie, Qnil);
21494 #endif
21495 }
21496
21497 if (event->type == ButtonPress)
21498 {
21499 dpyinfo->grabbed |= (1 << event->xbutton.button);
21500 dpyinfo->last_mouse_frame = f;
21501 if (f && !tab_bar_p)
21502 f->last_tab_bar_item = -1;
21503 #if ! defined (USE_GTK)
21504 if (f && !tool_bar_p)
21505 f->last_tool_bar_item = -1;
21506 #endif
21507 }
21508 else
21509 dpyinfo->grabbed &= ~(1 << event->xbutton.button);
21510
21511
21512
21513
21514 if (f != 0)
21515 f->mouse_moved = false;
21516
21517 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
21518 f = x_menubar_window_to_frame (dpyinfo, event);
21519
21520
21521
21522
21523 if (! popup_activated ()
21524 #ifdef USE_GTK
21525
21526 && event->xbutton.button < 3
21527 #endif
21528 && f && event->type == ButtonPress
21529
21530
21531 && event->xbutton.x >= 0
21532 && event->xbutton.x < FRAME_PIXEL_WIDTH (f)
21533 && event->xbutton.y >= 0
21534 && event->xbutton.y < FRAME_MENUBAR_HEIGHT (f)
21535 && event->xbutton.same_screen)
21536 {
21537 #ifdef USE_MOTIF
21538 Widget widget;
21539
21540 widget = XtWindowToWidget (dpyinfo->display,
21541 event->xbutton.window);
21542
21543 if (widget && XmIsCascadeButton (widget)
21544 && XtIsSensitive (widget))
21545 {
21546 #endif
21547 if (!f->output_data.x->saved_menu_event)
21548 f->output_data.x->saved_menu_event = xmalloc (sizeof *event);
21549 *f->output_data.x->saved_menu_event = *event;
21550 inev.ie.kind = MENU_BAR_ACTIVATE_EVENT;
21551 XSETFRAME (inev.ie.frame_or_window, f);
21552 *finish = X_EVENT_DROP;
21553 #ifdef USE_MOTIF
21554 }
21555 #endif
21556 }
21557 else
21558 goto OTHER;
21559 #endif
21560 }
21561 break;
21562
21563 case CirculateNotify:
21564 if (x_dnd_in_progress
21565
21566
21567
21568
21569 && !x_dnd_use_toplevels
21570 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
21571 x_dnd_update_state (dpyinfo, dpyinfo->last_user_time);
21572 goto OTHER;
21573
21574 case CirculateRequest:
21575 goto OTHER;
21576
21577 case VisibilityNotify:
21578 f = x_top_window_to_frame (dpyinfo, event->xvisibility.window);
21579 if (f && (event->xvisibility.state == VisibilityUnobscured
21580 || event->xvisibility.state == VisibilityPartiallyObscured))
21581 SET_FRAME_VISIBLE (f, 1);
21582
21583 goto OTHER;
21584
21585 case MappingNotify:
21586
21587
21588 switch (event->xmapping.request)
21589 {
21590 case MappingModifier:
21591 x_find_modifier_meanings (dpyinfo);
21592 FALLTHROUGH;
21593 case MappingKeyboard:
21594 XRefreshKeyboardMapping ((XMappingEvent *) &event->xmapping);
21595 }
21596 goto OTHER;
21597
21598 case DestroyNotify:
21599 if (event->xdestroywindow.window
21600 == dpyinfo->net_supported_window)
21601 dpyinfo->net_supported_window = None;
21602
21603 if (event->xdestroywindow.window
21604 == dpyinfo->motif_drag_window)
21605
21606
21607
21608
21609
21610 dpyinfo->motif_drag_window = None;
21611
21612 xft_settings_event (dpyinfo, event);
21613 break;
21614
21615 #ifdef HAVE_XINPUT2
21616 case GenericEvent:
21617 {
21618 if (!dpyinfo->supports_xi2)
21619 goto OTHER;
21620
21621 if (event->xgeneric.extension != dpyinfo->xi2_opcode)
21622
21623 goto OTHER;
21624
21625 bool must_free_data = false;
21626 XIEvent *xi_event = (XIEvent *) event->xcookie.data;
21627
21628
21629
21630 if (!xi_event)
21631 {
21632 if (XGetEventData (dpyinfo->display, &event->xcookie))
21633 must_free_data = true;
21634
21635 xi_event = (XIEvent *) event->xcookie.data;
21636 }
21637
21638 XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
21639
21640 if (!xi_event)
21641 {
21642
21643
21644
21645
21646
21647
21648
21649
21650
21651
21652
21653
21654
21655
21656
21657
21658
21659 if (must_free_data)
21660 XFreeEventData (dpyinfo->display, &event->xcookie);
21661 goto OTHER;
21662 }
21663
21664 switch (event->xcookie.evtype)
21665 {
21666 case XI_FocusIn:
21667 {
21668 XIFocusInEvent *focusin;
21669
21670 focusin = (XIFocusInEvent *) xi_event;
21671 any = x_any_window_to_frame (dpyinfo, focusin->event);
21672
21673 #ifdef USE_GTK
21674
21675
21676
21677
21678
21679
21680
21681
21682
21683
21684
21685
21686 if (EQ (x_set_frame_visibility_more_laxly, Qfocus_in)
21687 || EQ (x_set_frame_visibility_more_laxly, Qt))
21688 #endif
21689 {
21690 f = any;
21691 if (f && FRAME_ICONIFIED_P (f))
21692 {
21693 SET_FRAME_VISIBLE (f, 1);
21694 SET_FRAME_ICONIFIED (f, false);
21695 f->output_data.x->has_been_visible = true;
21696 inev.ie.kind = DEICONIFY_EVENT;
21697 XSETFRAME (inev.ie.frame_or_window, f);
21698 }
21699 }
21700
21701 xi_focus_handle_for_device (dpyinfo, any, xi_event);
21702
21703 goto XI_OTHER;
21704 }
21705
21706 case XI_FocusOut:
21707 {
21708 XIFocusOutEvent *focusout;
21709
21710 focusout = (XIFocusOutEvent *) xi_event;
21711 any = x_any_window_to_frame (dpyinfo, focusout->event);
21712 xi_focus_handle_for_device (dpyinfo, any, xi_event);
21713
21714 goto XI_OTHER;
21715 }
21716
21717 case XI_Enter:
21718 {
21719 XIEnterEvent *enter = (XIEnterEvent *) xi_event;
21720 XMotionEvent ev;
21721 struct xi_device_t *source;
21722
21723 any = x_top_window_to_frame (dpyinfo, enter->event);
21724 source = xi_device_from_id (dpyinfo, enter->sourceid);
21725
21726 ev.x = lrint (enter->event_x);
21727 ev.y = lrint (enter->event_y);
21728 ev.window = enter->event;
21729 ev.time = enter->time;
21730 ev.send_event = enter->send_event;
21731
21732 x_display_set_last_user_time (dpyinfo, enter->time,
21733 enter->send_event, false);
21734
21735 #ifdef USE_MOTIF
21736 use_copy = true;
21737
21738 copy.xcrossing.type = EnterNotify;
21739 copy.xcrossing.serial = enter->serial;
21740 copy.xcrossing.send_event = enter->send_event;
21741 copy.xcrossing.display = dpyinfo->display;
21742 copy.xcrossing.window = enter->event;
21743 copy.xcrossing.root = enter->root;
21744 copy.xcrossing.subwindow = enter->child;
21745 copy.xcrossing.time = enter->time;
21746 copy.xcrossing.x = lrint (enter->event_x);
21747 copy.xcrossing.y = lrint (enter->event_y);
21748 copy.xcrossing.x_root = lrint (enter->root_x);
21749 copy.xcrossing.y_root = lrint (enter->root_y);
21750 copy.xcrossing.mode = enter->mode;
21751 copy.xcrossing.detail = enter->detail;
21752 copy.xcrossing.focus = enter->focus;
21753 copy.xcrossing.state = 0;
21754 copy.xcrossing.same_screen = True;
21755 #endif
21756
21757
21758
21759
21760
21761 if (any)
21762 xi_focus_handle_for_device (dpyinfo, any, xi_event);
21763
21764 if (!any)
21765 any = x_any_window_to_frame (dpyinfo, enter->event);
21766
21767 #ifdef HAVE_XINPUT2_1
21768
21769
21770
21771
21772
21773
21774
21775
21776
21777 if (enter->mode != XINotifyUngrab
21778 && enter->mode != XINotifyGrab
21779 && enter->mode != XINotifyPassiveGrab
21780 && enter->mode != XINotifyPassiveUngrab)
21781 xi_reset_scroll_valuators_for_device_id (dpyinfo,
21782 enter->deviceid);
21783 #endif
21784
21785 {
21786 #ifdef HAVE_XWIDGETS
21787 struct xwidget_view *xwidget_view;
21788
21789 xwidget_view = xwidget_view_from_window (enter->event);
21790
21791 if (xwidget_view)
21792 {
21793 xwidget_motion_or_crossing (xwidget_view, event);
21794
21795 goto XI_OTHER;
21796 }
21797 #endif
21798 }
21799
21800 f = any;
21801
21802 if (f && enter->event == FRAME_X_WINDOW (f))
21803 xi_compute_root_window_offset_enter (f, enter);
21804
21805 if (f && x_mouse_click_focus_ignore_position)
21806 {
21807 ignore_next_mouse_click_timeout = (enter->time
21808 + x_mouse_click_focus_ignore_time);
21809 mouse_click_timeout_display = dpyinfo;
21810 }
21811
21812
21813
21814 if (f && !f->output_data.x->hourglass_p)
21815 x_note_mouse_movement (f, &ev, source ? source->name : Qnil);
21816 #ifdef USE_GTK
21817
21818
21819 if (!f && dpyinfo->last_mouse_glyph_frame)
21820 x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &ev,
21821 source ? source->name : Qnil);
21822 #endif
21823 goto XI_OTHER;
21824 }
21825
21826 case XI_Leave:
21827 {
21828 XILeaveEvent *leave;
21829 struct xi_device_t *device;
21830
21831 leave = (XILeaveEvent *) xi_event;
21832 #ifdef USE_GTK
21833 struct xi_device_t *source;
21834 XMotionEvent ev;
21835
21836 ev.x = lrint (leave->event_x);
21837 ev.y = lrint (leave->event_y);
21838 ev.window = leave->event;
21839 ev.time = leave->time;
21840 ev.send_event = leave->send_event;
21841 #endif
21842
21843 any = x_top_window_to_frame (dpyinfo, leave->event);
21844
21845 #ifdef USE_GTK
21846 source = xi_device_from_id (dpyinfo, leave->sourceid);
21847 #endif
21848 device = xi_device_from_id (dpyinfo, leave->deviceid);
21849
21850 if (device)
21851 xi_report_motion_window_clear (device);
21852
21853
21854
21855
21856
21857
21858 #ifdef USE_X_TOOLKIT
21859 if (popup_activated ()
21860 && (leave->mode == XINotifyPassiveUngrab
21861 || leave->mode == XINotifyUngrab))
21862 any = x_any_window_to_frame (dpyinfo, leave->event);
21863 #endif
21864
21865 #ifdef USE_MOTIF
21866 use_copy = true;
21867
21868 copy.xcrossing.type = LeaveNotify;
21869 copy.xcrossing.serial = leave->serial;
21870 copy.xcrossing.send_event = leave->send_event;
21871 copy.xcrossing.display = dpyinfo->display;
21872 copy.xcrossing.window = leave->event;
21873 copy.xcrossing.root = leave->root;
21874 copy.xcrossing.subwindow = leave->child;
21875 copy.xcrossing.time = leave->time;
21876 copy.xcrossing.x = lrint (leave->event_x);
21877 copy.xcrossing.y = lrint (leave->event_y);
21878 copy.xcrossing.x_root = lrint (leave->root_x);
21879 copy.xcrossing.y_root = lrint (leave->root_y);
21880 copy.xcrossing.mode = leave->mode;
21881 copy.xcrossing.detail = leave->detail;
21882 copy.xcrossing.focus = leave->focus;
21883 copy.xcrossing.state = 0;
21884 copy.xcrossing.same_screen = True;
21885 #endif
21886
21887
21888
21889
21890
21891
21892
21893
21894
21895
21896
21897
21898
21899
21900
21901
21902
21903
21904
21905 #ifdef HAVE_XINPUT2_1
21906
21907
21908
21909
21910
21911
21912
21913
21914
21915 if (leave->mode != XINotifyUngrab
21916 && leave->mode != XINotifyGrab
21917 && leave->mode != XINotifyPassiveUngrab
21918 && leave->mode != XINotifyPassiveGrab)
21919 xi_reset_scroll_valuators_for_device_id (dpyinfo,
21920 leave->deviceid);
21921 #endif
21922
21923 x_display_set_last_user_time (dpyinfo, leave->time,
21924 leave->send_event, false);
21925
21926 #ifdef HAVE_XWIDGETS
21927 {
21928 struct xwidget_view *xvw;
21929
21930 xvw = xwidget_view_from_window (leave->event);
21931
21932 if (xvw)
21933 {
21934 *finish = X_EVENT_DROP;
21935 xwidget_motion_or_crossing (xvw, event);
21936
21937 goto XI_OTHER;
21938 }
21939 }
21940 #endif
21941
21942 if (any)
21943 xi_focus_handle_for_device (dpyinfo, any, xi_event);
21944
21945 #ifndef USE_X_TOOLKIT
21946 f = x_top_window_to_frame (dpyinfo, leave->event);
21947 #else
21948
21949
21950 f = x_window_to_frame (dpyinfo, leave->event);
21951
21952 if (!f)
21953 f = x_top_window_to_frame (dpyinfo, leave->event);
21954 #endif
21955
21956 if (f)
21957 {
21958
21959
21960
21961
21962
21963 if (f == dpyinfo->last_mouse_motion_frame)
21964 dpyinfo->last_mouse_motion_frame = NULL;
21965
21966
21967
21968 if (f == dpyinfo->last_mouse_glyph_frame)
21969 dpyinfo->last_mouse_glyph_frame = NULL;
21970
21971 if (f == hlinfo->mouse_face_mouse_frame)
21972 {
21973
21974
21975 clear_mouse_face (hlinfo);
21976 hlinfo->mouse_face_mouse_frame = 0;
21977 x_flush_dirty_back_buffer_on (f);
21978 }
21979
21980
21981
21982
21983
21984 if (any_help_event_p
21985
21986
21987
21988
21989 && !((EQ (track_mouse, Qdrag_source)
21990 || EQ (track_mouse, Qdropping))
21991 && gui_mouse_grabbed (dpyinfo)))
21992 do_help = -1;
21993
21994 if (f && leave->event == FRAME_X_WINDOW (f))
21995 xi_compute_root_window_offset_enter (f, leave);
21996 }
21997 #ifdef USE_GTK
21998
21999 else if (dpyinfo->last_mouse_glyph_frame)
22000 x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &ev,
22001 source ? source->name : Qnil);
22002 #endif
22003 goto XI_OTHER;
22004 }
22005
22006 case XI_Motion:
22007 {
22008 struct xi_device_t *device, *source;
22009 #ifdef HAVE_XINPUT2_1
22010 XIValuatorState *states;
22011 double *values;
22012 bool found_valuator = false;
22013 bool other_valuators_found = false;
22014 #endif
22015
22016 XMotionEvent ev;
22017 xm_top_level_leave_message lmsg;
22018 xm_top_level_enter_message emsg;
22019 xm_drag_motion_message dmsg;
22020 unsigned int dnd_state;
22021
22022 source = xi_device_from_id (dpyinfo, xev->sourceid);
22023
22024 #ifdef HAVE_XINPUT2_1
22025 states = &xev->valuators;
22026 values = states->values;
22027 #endif
22028
22029 device = xi_device_from_id (dpyinfo, xev->deviceid);
22030
22031 if (!device)
22032 goto XI_OTHER;
22033
22034 #ifdef HAVE_XINPUT2_2
22035 if (xev->flags & XIPointerEmulated)
22036 goto XI_OTHER;
22037 #endif
22038
22039 #ifdef HAVE_XINPUT2_1
22040 #ifdef HAVE_XWIDGETS
22041 struct xwidget_view *xv = xwidget_view_from_window (xev->event);
22042 double xv_total_x = 0.0;
22043 double xv_total_y = 0.0;
22044 #endif
22045 double total_x = 0.0;
22046 double total_y = 0.0;
22047
22048 int real_x, real_y;
22049
22050 for (int i = 0; i < states->mask_len * 8; i++)
22051 {
22052 if (XIMaskIsSet (states->mask, i))
22053 {
22054 struct xi_scroll_valuator_t *val;
22055 double delta, scroll_unit;
22056 int scroll_height;
22057 Lisp_Object window;
22058 struct scroll_bar *bar;
22059
22060 bar = NULL;
22061
22062
22063
22064
22065 delta = x_get_scroll_valuator_delta (dpyinfo, device,
22066 i, *values, &val);
22067 values++;
22068
22069 if (!val)
22070 {
22071 other_valuators_found = true;
22072 continue;
22073 }
22074
22075 if (delta != DBL_MAX)
22076 {
22077 if (!f)
22078 {
22079 f = x_any_window_to_frame (dpyinfo, xev->event);
22080
22081 if (!f)
22082 {
22083 #if defined USE_MOTIF || !defined USE_TOOLKIT_SCROLL_BARS
22084 bar = x_window_to_scroll_bar (dpyinfo->display,
22085 xev->event, 2);
22086
22087 if (bar)
22088 f = WINDOW_XFRAME (XWINDOW (bar->window));
22089
22090 if (!f)
22091 #endif
22092 goto XI_OTHER;
22093 }
22094 }
22095
22096 #ifdef USE_GTK
22097 if (f && xg_event_is_for_scrollbar (f, event, true))
22098 *finish = X_EVENT_DROP;
22099 #endif
22100
22101 if (FRAME_X_WINDOW (f) != xev->event)
22102 {
22103 if (!bar)
22104 bar = x_window_to_scroll_bar (dpyinfo->display, xev->event, 2);
22105
22106
22107
22108
22109
22110 if (bar)
22111 {
22112 real_x = lrint (xev->event_x + bar->left);
22113 real_y = lrint (xev->event_y + bar->top);
22114 }
22115 else
22116 x_translate_coordinates (f,
22117 lrint (xev->root_x),
22118 lrint (xev->root_y),
22119 &real_x, &real_y);
22120 }
22121 else
22122 {
22123 real_x = lrint (xev->event_x);
22124 real_y = lrint (xev->event_y);
22125 }
22126
22127 #ifdef HAVE_XWIDGETS
22128 if (xv)
22129 {
22130 if (val->horizontal)
22131 xv_total_x += delta;
22132 else
22133 xv_total_y += delta;
22134
22135 found_valuator = true;
22136 continue;
22137 }
22138 #endif
22139
22140 if (delta == 0.0)
22141 found_valuator = true;
22142
22143 if (signbit (delta) != signbit (val->emacs_value))
22144 val->emacs_value = 0;
22145
22146 val->emacs_value += delta;
22147
22148 if (mwheel_coalesce_scroll_events
22149 && (fabs (val->emacs_value) < 1)
22150 && (fabs (delta) > 0))
22151 continue;
22152
22153 window = window_from_coordinates (f, real_x, real_y, NULL,
22154 false, false);
22155
22156 if (WINDOWP (window))
22157 scroll_height = XWINDOW (window)->pixel_height;
22158 else
22159
22160
22161
22162 scroll_height = FRAME_PIXEL_HEIGHT (f);
22163
22164 scroll_unit = pow (scroll_height, 2.0 / 3.0);
22165
22166 if (NUMBERP (Vx_scroll_event_delta_factor))
22167 scroll_unit *= XFLOATINT (Vx_scroll_event_delta_factor);
22168
22169 if (val->horizontal)
22170 total_x += val->emacs_value * scroll_unit;
22171 else
22172 total_y += val->emacs_value * scroll_unit;
22173
22174 found_valuator = true;
22175 val->emacs_value = 0;
22176 }
22177 }
22178 }
22179
22180 #ifdef HAVE_XWIDGETS
22181 if (xv)
22182 {
22183 unsigned int state;
22184
22185 state = xi_convert_event_state (xev);
22186 x_display_set_last_user_time (dpyinfo, xev->time,
22187 xev->send_event, true);
22188
22189 if (found_valuator)
22190 xwidget_scroll (xv, xev->event_x, xev->event_y,
22191 -xv_total_x, -xv_total_y, state,
22192 xev->time, (xv_total_x == 0.0
22193 && xv_total_y == 0.0));
22194 else
22195 xwidget_motion_notify (xv, xev->event_x, xev->event_y,
22196 xev->root_x, xev->root_y, state,
22197 xev->time);
22198
22199 goto XI_OTHER;
22200 }
22201 else
22202 {
22203 #endif
22204 if (found_valuator)
22205 {
22206 x_display_set_last_user_time (dpyinfo, xev->time,
22207 xev->send_event, true);
22208
22209
22210 #if defined USE_GTK && !defined HAVE_GTK3
22211
22212
22213
22214
22215
22216
22217
22218
22219 if (xev->child != None
22220 && xev->child != FRAME_X_WINDOW (f))
22221 goto XI_OTHER;
22222 #endif
22223
22224
22225
22226
22227 if (x_dnd_in_progress
22228
22229
22230
22231
22232
22233 && xev->deviceid == x_dnd_pointer_device
22234 && (command_loop_level + minibuf_level
22235 <= x_dnd_recursion_depth)
22236 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
22237 goto XI_OTHER;
22238
22239 if (fabs (total_x) > 0 || fabs (total_y) > 0)
22240 {
22241 inev.ie.kind = (fabs (total_y) >= fabs (total_x)
22242 ? WHEEL_EVENT : HORIZ_WHEEL_EVENT);
22243 inev.ie.timestamp = xev->time;
22244
22245 XSETINT (inev.ie.x, lrint (real_x));
22246 XSETINT (inev.ie.y, lrint (real_y));
22247 XSETFRAME (inev.ie.frame_or_window, f);
22248
22249 inev.ie.modifiers = (signbit (fabs (total_y) >= fabs (total_x)
22250 ? total_y : total_x)
22251 ? down_modifier : up_modifier);
22252 inev.ie.modifiers
22253 |= x_x_to_emacs_modifiers (dpyinfo,
22254 xev->mods.effective);
22255 inev.ie.arg = list3 (Qnil,
22256 make_float (total_x),
22257 make_float (total_y));
22258 }
22259 else
22260 {
22261 inev.ie.kind = TOUCH_END_EVENT;
22262 inev.ie.timestamp = xev->time;
22263
22264 XSETINT (inev.ie.x, lrint (real_x));
22265 XSETINT (inev.ie.y, lrint (real_y));
22266 XSETFRAME (inev.ie.frame_or_window, f);
22267 }
22268
22269 if (source && !NILP (source->name))
22270 inev.ie.device = source->name;
22271
22272 if (!other_valuators_found)
22273 goto XI_OTHER;
22274 }
22275 #ifdef HAVE_XWIDGETS
22276 }
22277 #endif
22278 #endif
22279
22280 if (!xi_position_changed (device, xev))
22281 goto XI_OTHER;
22282
22283 ev.x = lrint (xev->event_x);
22284 ev.y = lrint (xev->event_y);
22285 ev.window = xev->event;
22286 ev.time = xev->time;
22287 ev.send_event = xev->send_event;
22288
22289 #ifdef USE_MOTIF
22290 use_copy = true;
22291
22292 copy.xmotion.type = MotionNotify;
22293 copy.xmotion.serial = xev->serial;
22294 copy.xmotion.send_event = xev->send_event;
22295 copy.xmotion.display = dpyinfo->display;
22296 copy.xmotion.window = xev->event;
22297 copy.xmotion.root = xev->root;
22298 copy.xmotion.subwindow = xev->child;
22299 copy.xmotion.time = xev->time;
22300 copy.xmotion.x = lrint (xev->event_x);
22301 copy.xmotion.y = lrint (xev->event_y);
22302 copy.xmotion.x_root = lrint (xev->root_x);
22303 copy.xmotion.y_root = lrint (xev->root_y);
22304 copy.xmotion.state = xi_convert_event_state (xev);
22305
22306 copy.xmotion.is_hint = False;
22307 copy.xmotion.same_screen = True;
22308 #endif
22309
22310 previous_help_echo_string = help_echo_string;
22311 help_echo_string = Qnil;
22312
22313 if (hlinfo->mouse_face_hidden)
22314 {
22315 hlinfo->mouse_face_hidden = false;
22316 clear_mouse_face (hlinfo);
22317 }
22318
22319 f = mouse_or_wdesc_frame (dpyinfo, xev->event);
22320
22321 if (f && xev->event == FRAME_X_WINDOW (f))
22322
22323
22324 xi_compute_root_window_offset (f, xev);
22325
22326 if (x_dnd_in_progress
22327
22328
22329
22330
22331
22332 && (command_loop_level + minibuf_level
22333 <= x_dnd_recursion_depth)
22334 && xev->deviceid == x_dnd_pointer_device
22335 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
22336 {
22337 Window target, toplevel;
22338 int target_proto, motif_style;
22339 XRectangle *r;
22340 bool was_frame;
22341
22342
22343 clear_mouse_face (hlinfo);
22344 hlinfo->mouse_face_hidden = true;
22345
22346
22347
22348
22349
22350
22351 if (f)
22352 {
22353 XTtoggle_invisible_pointer (f, false);
22354
22355 r = &dpyinfo->last_mouse_glyph;
22356
22357
22358
22359 if (f != dpyinfo->last_mouse_glyph_frame
22360 || lrint (xev->event_x) < r->x
22361 || lrint (xev->event_x) >= r->x + r->width
22362 || lrint (xev->event_y) < r->y
22363 || lrint (xev->event_y) >= r->y + r->height)
22364 {
22365 f->mouse_moved = true;
22366 f->last_mouse_device = (source ? source->name
22367 : Qnil);
22368 dpyinfo->last_mouse_scroll_bar = NULL;
22369
22370 remember_mouse_glyph (f, lrint (xev->event_x),
22371 lrint (xev->event_y), r);
22372 dpyinfo->last_mouse_glyph_frame = f;
22373 }
22374 }
22375
22376 if (xev->root == dpyinfo->root_window)
22377 target = x_dnd_get_target_window (dpyinfo,
22378 lrint (xev->root_x),
22379 lrint (xev->root_y),
22380 &target_proto,
22381 &motif_style,
22382 &toplevel,
22383 &was_frame);
22384 else
22385 target = x_dnd_fill_empty_target (&target_proto,
22386 &motif_style,
22387 &toplevel,
22388 &was_frame);
22389
22390 if (toplevel != x_dnd_last_seen_toplevel)
22391 {
22392 if (toplevel != FRAME_OUTER_WINDOW (x_dnd_frame)
22393 && x_dnd_return_frame == 1)
22394 x_dnd_return_frame = 2;
22395
22396 if (x_dnd_return_frame == 2
22397 && x_any_window_to_frame (dpyinfo, toplevel))
22398 {
22399 if (x_dnd_last_seen_window != None
22400 && x_dnd_last_protocol_version != -1
22401 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
22402 x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window,
22403 x_dnd_last_seen_toplevel);
22404 else if (x_dnd_last_seen_window != None
22405 && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
22406 && !x_dnd_disable_motif_drag
22407 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
22408 {
22409 if (!x_dnd_motif_setup_p)
22410 xm_setup_drag_info (dpyinfo, x_dnd_frame);
22411
22412 lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
22413 XM_DRAG_REASON_TOP_LEVEL_LEAVE);
22414 lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
22415 lmsg.zero = 0;
22416 lmsg.timestamp = xev->time;
22417 lmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
22418
22419 if (x_dnd_motif_setup_p)
22420 xm_send_top_level_leave_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
22421 x_dnd_last_seen_window, &lmsg);
22422 }
22423
22424 x_dnd_end_window = x_dnd_last_seen_window;
22425 x_dnd_last_seen_window = None;
22426 x_dnd_last_seen_toplevel = None;
22427 x_dnd_in_progress = false;
22428 x_dnd_return_frame_object
22429 = x_any_window_to_frame (dpyinfo, toplevel);
22430 x_dnd_return_frame = 3;
22431 x_dnd_waiting_for_finish = false;
22432 target = None;
22433 }
22434 }
22435
22436 if (target != x_dnd_last_seen_window)
22437 {
22438 if (x_dnd_last_seen_window != None
22439 && x_dnd_last_protocol_version != -1
22440 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
22441 x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window,
22442 x_dnd_last_seen_toplevel);
22443 else if (x_dnd_last_seen_window != None
22444 && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
22445 && !x_dnd_disable_motif_drag
22446 && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
22447 {
22448 if (!x_dnd_motif_setup_p)
22449 xm_setup_drag_info (dpyinfo, x_dnd_frame);
22450
22451
22452
22453
22454
22455
22456
22457
22458 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
22459 XM_DRAG_REASON_DRAG_MOTION);
22460 dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
22461 dmsg.side_effects
22462 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
22463 x_dnd_wanted_action),
22464 XM_DROP_SITE_NONE, x_dnd_motif_operations,
22465 XM_DROP_ACTION_DROP_CANCEL);
22466 dmsg.timestamp = xev->time;
22467 dmsg.x = lrint (xev->root_x);
22468 dmsg.y = lrint (xev->root_y);
22469
22470 lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
22471 XM_DRAG_REASON_TOP_LEVEL_LEAVE);
22472 lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
22473 lmsg.zero = 0;
22474 lmsg.timestamp = xev->time;
22475 lmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
22476
22477 if (x_dnd_motif_setup_p)
22478 {
22479 xm_send_drag_motion_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
22480 x_dnd_last_seen_window, &dmsg);
22481 xm_send_top_level_leave_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
22482 x_dnd_last_seen_window, &lmsg);
22483 }
22484 }
22485
22486 x_dnd_action = None;
22487 x_dnd_last_seen_toplevel = toplevel;
22488 x_dnd_last_seen_window = target;
22489 x_dnd_last_protocol_version = target_proto;
22490 x_dnd_last_motif_style = motif_style;
22491 x_dnd_last_window_is_frame = was_frame;
22492
22493 if (target != None && x_dnd_last_protocol_version != -1)
22494 x_dnd_send_enter (x_dnd_frame, target,
22495 x_dnd_last_seen_toplevel,
22496 x_dnd_last_protocol_version);
22497 else if (target != None && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
22498 && !x_dnd_disable_motif_drag)
22499 {
22500 if (!x_dnd_motif_setup_p)
22501 xm_setup_drag_info (dpyinfo, x_dnd_frame);
22502
22503 emsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
22504 XM_DRAG_REASON_TOP_LEVEL_ENTER);
22505 emsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
22506 emsg.zero = 0;
22507 emsg.timestamp = xev->time;
22508 emsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
22509 emsg.index_atom = x_dnd_motif_atom;
22510
22511 if (x_dnd_motif_setup_p)
22512 xm_send_top_level_enter_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
22513 target, &emsg);
22514 }
22515 }
22516 else
22517 x_dnd_last_seen_toplevel = toplevel;
22518
22519 if (x_dnd_last_window_is_frame && target != None)
22520 x_dnd_note_self_position (dpyinfo, target,
22521 lrint (xev->root_x),
22522 lrint (xev->root_y));
22523 else if (x_dnd_last_protocol_version != -1 && target != None)
22524 {
22525 dnd_state = xi_convert_event_state (xev);
22526
22527 x_dnd_send_position (x_dnd_frame, target,
22528 x_dnd_last_seen_toplevel,
22529 x_dnd_last_protocol_version,
22530 lrint (xev->root_x),
22531 lrint (xev->root_y),
22532 x_dnd_selection_timestamp,
22533 x_dnd_wanted_action, 0,
22534 dnd_state);
22535 }
22536 else if (XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) && target != None
22537 && !x_dnd_disable_motif_drag)
22538 {
22539 if (!x_dnd_motif_setup_p)
22540 xm_setup_drag_info (dpyinfo, x_dnd_frame);
22541
22542 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
22543 XM_DRAG_REASON_DRAG_MOTION);
22544 dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
22545 dmsg.side_effects
22546 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
22547 x_dnd_wanted_action),
22548 XM_DROP_SITE_VALID, x_dnd_motif_operations,
22549 (!x_dnd_xm_use_help
22550 ? XM_DROP_ACTION_DROP
22551 : XM_DROP_ACTION_DROP_HELP));
22552 dmsg.timestamp = xev->time;
22553 dmsg.x = lrint (xev->root_x);
22554 dmsg.y = lrint (xev->root_y);
22555
22556 if (x_dnd_motif_setup_p)
22557 xm_send_drag_motion_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
22558 target, &dmsg);
22559 }
22560
22561 x_dnd_update_tooltip_position (xev->root_x, xev->root_y);
22562
22563 goto XI_OTHER;
22564 }
22565
22566 #ifdef USE_GTK
22567 if (f && xg_event_is_for_scrollbar (f, event, false))
22568 f = 0;
22569 #endif
22570 if (f)
22571 {
22572 if (xev->event != FRAME_X_WINDOW (f))
22573 {
22574 x_translate_coordinates (f, lrint (xev->root_x),
22575 lrint (xev->root_y),
22576 &ev.x, &ev.y);
22577 ev.window = FRAME_X_WINDOW (f);
22578 }
22579
22580
22581
22582
22583 if (!NILP (Vmouse_autoselect_window)
22584 && !popup_activated ()
22585
22586
22587
22588
22589
22590 && !MINI_WINDOW_P (XWINDOW (selected_window))
22591
22592
22593 && (f == XFRAME (selected_frame)
22594 || !NILP (focus_follows_mouse)))
22595 {
22596 static Lisp_Object last_mouse_window;
22597 Lisp_Object window = window_from_coordinates (f, ev.x, ev.y, 0, false, false);
22598
22599
22600
22601
22602
22603
22604
22605
22606
22607 if (WINDOWP (window)
22608 && !EQ (window, last_mouse_window)
22609 && !EQ (window, selected_window))
22610 {
22611 inev.ie.kind = SELECT_WINDOW_EVENT;
22612 inev.ie.frame_or_window = window;
22613
22614 if (source)
22615 inev.ie.device = source->name;
22616 }
22617
22618
22619 last_mouse_window = window;
22620 }
22621
22622 if (!x_note_mouse_movement (f, &ev, source ? source->name : Qnil))
22623 help_echo_string = previous_help_echo_string;
22624 }
22625 else
22626 {
22627 #ifndef USE_TOOLKIT_SCROLL_BARS
22628 struct scroll_bar *bar
22629 = x_window_to_scroll_bar (dpyinfo->display, xev->event, 2);
22630
22631 if (bar)
22632 x_scroll_bar_note_movement (bar, &ev);
22633 #endif
22634
22635
22636
22637 clear_mouse_face (hlinfo);
22638 }
22639
22640
22641
22642 if (!NILP (help_echo_string)
22643 || !NILP (previous_help_echo_string))
22644 {
22645
22646
22647
22648 gen_help_device = device;
22649 gen_help_time = xev->time;
22650
22651 do_help = 1;
22652 }
22653
22654 if (f)
22655 x_flush_dirty_back_buffer_on (f);
22656 goto XI_OTHER;
22657 }
22658
22659 case XI_ButtonRelease:
22660 case XI_ButtonPress:
22661 {
22662
22663
22664 Lisp_Object tab_bar_arg = Qnil;
22665 bool tab_bar_p = false;
22666 bool tool_bar_p = false;
22667 struct xi_device_t *device, *source;
22668 #ifdef HAVE_XWIDGETS
22669 struct xwidget_view *xvw;
22670 #endif
22671
22672 XButtonEvent bv;
22673 bool dnd_grab = false;
22674 int dnd_state;
22675
22676 if (x_dnd_in_progress
22677 && (command_loop_level + minibuf_level
22678 <= x_dnd_recursion_depth)
22679 && xev->deviceid == x_dnd_pointer_device
22680 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
22681 {
22682 f = mouse_or_wdesc_frame (dpyinfo, xev->event);
22683 device = xi_device_from_id (dpyinfo, xev->deviceid);
22684
22685 if (f && xev->event == FRAME_X_WINDOW (f))
22686
22687
22688
22689 xi_compute_root_window_offset (f, xev);
22690
22691
22692
22693
22694 #ifdef XIPointerEmulated
22695 if (!(xev->flags & XIPointerEmulated))
22696 {
22697 #endif
22698 if (xev->evtype == XI_ButtonPress)
22699 {
22700 x_display_set_last_user_time (dpyinfo, xev->time,
22701 xev->send_event, true);
22702
22703 dpyinfo->grabbed |= (1 << xev->detail);
22704 dpyinfo->last_mouse_frame = f;
22705
22706 if (device)
22707 device->grab |= (1 << xev->detail);
22708
22709 if (f)
22710 f->last_tab_bar_item = -1;
22711 #if ! defined (USE_GTK)
22712 if (f)
22713 f->last_tool_bar_item = -1;
22714 #endif
22715 }
22716 else
22717 {
22718 dpyinfo->grabbed &= ~(1 << xev->detail);
22719 if (device)
22720 device->grab &= ~(1 << xev->detail);
22721 }
22722 #ifdef XIPointerEmulated
22723 }
22724 #endif
22725
22726 if (f && device)
22727 xi_handle_interaction (dpyinfo, f, device,
22728 xev->time);
22729
22730 if (xev->evtype == XI_ButtonPress
22731 && x_dnd_last_seen_window != None)
22732 {
22733 dnd_state = xi_convert_event_state (xev);
22734
22735 if (x_dnd_last_window_is_frame)
22736 {
22737 #ifdef XI_PointerEmulated
22738
22739
22740
22741
22742 if (xev->flags & XIPointerEmulated)
22743 x_display_set_last_user_time (dpyinfo, xev->time,
22744 xev->send_event, true);
22745 #endif
22746 x_dnd_note_self_wheel (dpyinfo,
22747 x_dnd_last_seen_window,
22748 lrint (xev->root_x),
22749 lrint (xev->root_y),
22750 xev->detail, dnd_state,
22751 xev->time);
22752 }
22753 else
22754 x_dnd_send_position (x_dnd_frame,
22755 x_dnd_last_seen_window,
22756 x_dnd_last_seen_toplevel,
22757 x_dnd_last_protocol_version,
22758 lrint (xev->root_x),
22759 lrint (xev->root_y),
22760 xev->time, x_dnd_wanted_action,
22761 xev->detail, dnd_state);
22762
22763 goto OTHER;
22764 }
22765
22766 if (xev->evtype == XI_ButtonRelease)
22767 {
22768 for (int i = 0; i < xev->buttons.mask_len * 8; ++i)
22769 {
22770 if (i != xev->detail && XIMaskIsSet (xev->buttons.mask, i))
22771 dnd_grab = true;
22772 }
22773
22774 if (!dnd_grab)
22775 {
22776 x_dnd_end_window = x_dnd_last_seen_window;
22777 x_dnd_in_progress = false;
22778
22779
22780
22781
22782 if (x_dnd_update_tooltip
22783 && FRAMEP (tip_frame)
22784 && FRAME_LIVE_P (XFRAME (tip_frame))
22785 && (FRAME_X_DISPLAY (XFRAME (tip_frame))
22786 == FRAME_X_DISPLAY (x_dnd_frame)))
22787 Fx_hide_tip ();
22788
22789
22790
22791
22792
22793
22794
22795 x_dnd_finish_frame = x_dnd_frame;
22796
22797 if (x_dnd_last_seen_window != None
22798 && x_dnd_last_window_is_frame)
22799 {
22800 x_dnd_waiting_for_finish = false;
22801 x_dnd_note_self_drop (dpyinfo, x_dnd_last_seen_window,
22802 lrint (xev->root_x),
22803 lrint (xev->root_y), xev->time);
22804 }
22805 else if (x_dnd_last_seen_window != None
22806 && x_dnd_last_protocol_version != -1)
22807 {
22808 x_dnd_pending_finish_target = x_dnd_last_seen_toplevel;
22809 x_dnd_waiting_for_finish_proto = x_dnd_last_protocol_version;
22810
22811 x_dnd_waiting_for_finish
22812 = x_dnd_do_drop (x_dnd_last_seen_window,
22813 x_dnd_last_seen_toplevel,
22814 x_dnd_last_protocol_version);
22815 x_dnd_finish_display = dpyinfo->display;
22816 }
22817 else if (x_dnd_last_seen_window != None)
22818 {
22819 xm_drop_start_message dmsg;
22820 xm_drag_receiver_info drag_receiver_info;
22821
22822 if (!xm_read_drag_receiver_info (dpyinfo, x_dnd_last_seen_window,
22823 &drag_receiver_info)
22824 && !x_dnd_disable_motif_protocol
22825 && drag_receiver_info.protocol_style != XM_DRAG_STYLE_NONE
22826 && (x_dnd_allow_current_frame
22827 || x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame)))
22828 {
22829 if (!x_dnd_motif_setup_p)
22830 xm_setup_drag_info (dpyinfo, x_dnd_frame);
22831
22832 if (x_dnd_motif_setup_p)
22833 {
22834 memset (&dmsg, 0, sizeof dmsg);
22835
22836 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
22837 XM_DRAG_REASON_DROP_START);
22838 dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST;
22839 dmsg.side_effects
22840 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
22841 x_dnd_wanted_action),
22842 XM_DROP_SITE_VALID, x_dnd_motif_operations,
22843 (!x_dnd_xm_use_help
22844 ? XM_DROP_ACTION_DROP
22845 : XM_DROP_ACTION_DROP_HELP));
22846 dmsg.timestamp = xev->time;
22847 dmsg.x = lrint (xev->root_x);
22848 dmsg.y = lrint (xev->root_y);
22849
22850
22851
22852
22853
22854
22855
22856
22857
22858 dmsg.index_atom = x_dnd_motif_atom;
22859 dmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
22860
22861 if (!XM_DRAG_STYLE_IS_DROP_ONLY (drag_receiver_info.protocol_style))
22862 x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (x_dnd_frame),
22863 x_dnd_frame, x_dnd_last_seen_window,
22864 xev->time);
22865
22866 xm_send_drop_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
22867 x_dnd_last_seen_window, &dmsg);
22868
22869 x_dnd_waiting_for_finish = true;
22870 x_dnd_waiting_for_motif_finish_display = dpyinfo;
22871 x_dnd_waiting_for_motif_finish = 1;
22872 x_dnd_finish_display = dpyinfo->display;
22873 }
22874 }
22875 else
22876 x_dnd_send_unsupported_drop (dpyinfo, (x_dnd_last_seen_toplevel != None
22877 ? x_dnd_last_seen_toplevel
22878 : x_dnd_last_seen_window),
22879 lrint (xev->root_x),
22880 lrint (xev->root_y), xev->time);
22881 }
22882 else if (x_dnd_last_seen_toplevel != None)
22883 x_dnd_send_unsupported_drop (dpyinfo,
22884 x_dnd_last_seen_toplevel,
22885 lrint (xev->root_x),
22886 lrint (xev->root_y),
22887 xev->time);
22888
22889 x_dnd_last_protocol_version = -1;
22890 x_dnd_last_motif_style = XM_DRAG_STYLE_NONE;
22891 x_dnd_last_seen_window = None;
22892 x_dnd_last_seen_toplevel = None;
22893 x_dnd_last_window_is_frame = false;
22894 x_dnd_frame = NULL;
22895
22896 goto XI_OTHER;
22897 }
22898 }
22899 }
22900
22901 if (x_dnd_in_progress
22902 && (command_loop_level + minibuf_level
22903 <= x_dnd_recursion_depth))
22904 goto XI_OTHER;
22905
22906 #ifdef USE_MOTIF
22907 #ifdef USE_TOOLKIT_SCROLL_BARS
22908 struct scroll_bar *bar
22909 = x_window_to_scroll_bar (dpyinfo->display,
22910 xev->event, 2);
22911 #endif
22912
22913 use_copy = true;
22914 copy.xbutton.type = (xev->evtype == XI_ButtonPress
22915 ? ButtonPress : ButtonRelease);
22916 copy.xbutton.serial = xev->serial;
22917 copy.xbutton.send_event = xev->send_event;
22918 copy.xbutton.display = dpyinfo->display;
22919 copy.xbutton.window = xev->event;
22920 copy.xbutton.root = xev->root;
22921 copy.xbutton.subwindow = xev->child;
22922 copy.xbutton.time = xev->time;
22923 copy.xbutton.x = lrint (xev->event_x);
22924 copy.xbutton.y = lrint (xev->event_y);
22925 copy.xbutton.x_root = lrint (xev->root_x);
22926 copy.xbutton.y_root = lrint (xev->root_y);
22927 copy.xbutton.state = xi_convert_event_state (xev);
22928 copy.xbutton.button = xev->detail;
22929 copy.xbutton.same_screen = True;
22930
22931 #elif defined USE_GTK && !defined HAVE_GTK3
22932 copy = gdk_event_new (xev->evtype == XI_ButtonPress
22933 ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE);
22934
22935 copy->button.window = gdk_x11_window_lookup_for_display (gdpy, xev->event);
22936 copy->button.send_event = xev->send_event;
22937 copy->button.time = xev->time;
22938 copy->button.x = xev->event_x;
22939 copy->button.y = xev->event_y;
22940 copy->button.x_root = xev->root_x;
22941 copy->button.y_root = xev->root_y;
22942 copy->button.state = xi_convert_event_state (xev);
22943 copy->button.button = xev->detail;
22944
22945 if (!copy->button.window)
22946 emacs_abort ();
22947
22948 g_object_ref (copy->button.window);
22949
22950 if (popup_activated ())
22951 {
22952
22953
22954
22955 if (xev->detail > 3)
22956 *finish = X_EVENT_DROP;
22957
22958 if (xev->evtype == XI_ButtonRelease)
22959 goto XI_OTHER;
22960 }
22961 #endif
22962
22963 #ifdef HAVE_XINPUT2_1
22964
22965
22966 if (xev->flags & XIPointerEmulated)
22967 {
22968 #if !defined USE_MOTIF || !defined USE_TOOLKIT_SCROLL_BARS
22969 *finish = X_EVENT_DROP;
22970 #else
22971 if (bar)
22972 *finish = X_EVENT_DROP;
22973 #endif
22974 goto XI_OTHER;
22975 }
22976 #endif
22977
22978 if (xev->evtype == XI_ButtonPress)
22979 x_display_set_last_user_time (dpyinfo, xev->time,
22980 xev->send_event, true);
22981
22982 source = xi_device_from_id (dpyinfo, xev->sourceid);
22983 device = xi_device_from_id (dpyinfo, xev->deviceid);
22984
22985 #ifdef HAVE_XWIDGETS
22986 xvw = xwidget_view_from_window (xev->event);
22987 if (xvw)
22988 {
22989
22990
22991
22992 if (device)
22993 xi_handle_interaction (dpyinfo, xvw->frame,
22994 device, xev->time);
22995
22996 xwidget_button (xvw, xev->evtype == XI_ButtonPress,
22997 lrint (xev->event_x), lrint (xev->event_y),
22998 xev->detail, xi_convert_event_state (xev),
22999 xev->time);
23000
23001 if (!EQ (selected_window, xvw->w) && (xev->detail < 4))
23002 {
23003 inev.ie.kind = SELECT_WINDOW_EVENT;
23004 inev.ie.frame_or_window = xvw->w;
23005
23006 if (source)
23007 inev.ie.device = source->name;
23008 }
23009
23010 *finish = X_EVENT_DROP;
23011 goto XI_OTHER;
23012 }
23013 #endif
23014
23015 if (!device)
23016 goto XI_OTHER;
23017
23018 bv.button = xev->detail;
23019 bv.type = xev->evtype == XI_ButtonPress ? ButtonPress : ButtonRelease;
23020 bv.x = lrint (xev->event_x);
23021 bv.y = lrint (xev->event_y);
23022 bv.x_root = lrint (xev->root_x);
23023 bv.y_root = lrint (xev->root_y);
23024 bv.window = xev->event;
23025 bv.state = xi_convert_event_state (xev);
23026 bv.time = xev->time;
23027
23028 dpyinfo->last_mouse_glyph_frame = NULL;
23029
23030 f = mouse_or_wdesc_frame (dpyinfo, xev->event);
23031
23032 if (f && xev->event == FRAME_X_WINDOW (f))
23033
23034
23035 xi_compute_root_window_offset (f, xev);
23036
23037 if (f && xev->evtype == XI_ButtonPress
23038 && !popup_activated ()
23039 && !x_window_to_scroll_bar (dpyinfo->display, xev->event, 2)
23040 && !FRAME_NO_ACCEPT_FOCUS (f))
23041 {
23042
23043
23044
23045
23046 struct frame *hf = dpyinfo->highlight_frame;
23047
23048 if (FRAME_PARENT_FRAME (f) || (hf && frame_ancestor_p (f, hf)))
23049 {
23050 #if defined HAVE_GTK3 || (!defined USE_GTK && !defined USE_X_TOOLKIT)
23051 if (device)
23052 {
23053
23054
23055
23056 x_ignore_errors_for_next_request (dpyinfo);
23057 XISetFocus (dpyinfo->display, device->attachment,
23058
23059
23060
23061 FRAME_OUTER_WINDOW (f), xev->time);
23062 x_stop_ignoring_errors (dpyinfo);
23063 }
23064 #else
23065
23066
23067
23068
23069 x_ignore_errors_for_next_request (dpyinfo);
23070 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
23071 RevertToParent, xev->time);
23072 x_stop_ignoring_errors (dpyinfo);
23073 #endif
23074 if (FRAME_PARENT_FRAME (f))
23075 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
23076 }
23077 }
23078
23079 if (f)
23080 {
23081
23082
23083
23084 if (device)
23085 xi_handle_interaction (dpyinfo, f, device,
23086 xev->time);
23087 }
23088
23089 #ifdef USE_GTK
23090 if (!f)
23091 {
23092 int real_x = lrint (xev->root_x);
23093 int real_y = lrint (xev->root_y);
23094
23095 f = x_any_window_to_frame (dpyinfo, xev->event);
23096
23097 if (xev->detail > 3 && xev->detail < 8 && f)
23098 {
23099 if (xev->evtype == XI_ButtonRelease)
23100 {
23101 if (FRAME_X_WINDOW (f) != xev->event)
23102 x_translate_coordinates (f, real_x, real_y,
23103 &real_x, &real_y);
23104
23105 if (xev->detail <= 5)
23106 inev.ie.kind = WHEEL_EVENT;
23107 else
23108 inev.ie.kind = HORIZ_WHEEL_EVENT;
23109
23110 if (source)
23111 inev.ie.device = source->name;
23112
23113 inev.ie.timestamp = xev->time;
23114
23115 XSETINT (inev.ie.x, real_x);
23116 XSETINT (inev.ie.y, real_y);
23117 XSETFRAME (inev.ie.frame_or_window, f);
23118
23119 inev.ie.modifiers
23120 |= x_x_to_emacs_modifiers (dpyinfo,
23121 xev->mods.effective);
23122
23123 inev.ie.modifiers |= xev->detail % 2 ? down_modifier : up_modifier;
23124 }
23125
23126 *finish = X_EVENT_DROP;
23127 goto XI_OTHER;
23128 }
23129 else
23130 f = NULL;
23131 }
23132
23133 if (f && xg_event_is_for_scrollbar (f, event, false))
23134 f = 0;
23135 #endif
23136
23137 if (f)
23138 {
23139 if (xev->detail >= 4 && xev->detail < 8)
23140 {
23141 if (xev->evtype == XI_ButtonRelease)
23142 {
23143 if (xev->detail <= 5)
23144 inev.ie.kind = WHEEL_EVENT;
23145 else
23146 inev.ie.kind = HORIZ_WHEEL_EVENT;
23147
23148 if (source)
23149 inev.ie.device = source->name;
23150
23151 inev.ie.timestamp = xev->time;
23152
23153 XSETINT (inev.ie.x, lrint (xev->event_x));
23154 XSETINT (inev.ie.y, lrint (xev->event_y));
23155 XSETFRAME (inev.ie.frame_or_window, f);
23156
23157 inev.ie.modifiers
23158 |= x_x_to_emacs_modifiers (dpyinfo,
23159 xev->mods.effective);
23160
23161 inev.ie.modifiers |= xev->detail % 2 ? down_modifier : up_modifier;
23162 }
23163
23164 goto XI_OTHER;
23165 }
23166
23167
23168 if (WINDOWP (f->tab_bar_window)
23169 && WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window)))
23170 {
23171 Lisp_Object window;
23172 int x = bv.x;
23173 int y = bv.y;
23174
23175 window = window_from_coordinates (f, x, y, 0, true, true);
23176 tab_bar_p = EQ (window, f->tab_bar_window);
23177
23178 if (tab_bar_p)
23179 {
23180 tab_bar_arg = handle_tab_bar_click
23181 (f, x, y, xev->evtype == XI_ButtonPress,
23182 x_x_to_emacs_modifiers (dpyinfo, bv.state));
23183 x_flush_dirty_back_buffer_on (f);
23184 }
23185 }
23186
23187 #if ! defined (USE_GTK)
23188
23189 if (WINDOWP (f->tool_bar_window)
23190 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
23191 {
23192 Lisp_Object window;
23193 int x = bv.x;
23194 int y = bv.y;
23195
23196 window = window_from_coordinates (f, x, y, 0, true, true);
23197
23198
23199
23200
23201
23202
23203
23204 tool_bar_p = (EQ (window, f->tool_bar_window)
23205 && (xev->evtype != XI_ButtonRelease
23206 || f->last_tool_bar_item != -1));
23207
23208 if (tool_bar_p && xev->detail < 4)
23209 {
23210 handle_tool_bar_click_with_device
23211 (f, x, y, xev->evtype == XI_ButtonPress,
23212 x_x_to_emacs_modifiers (dpyinfo, bv.state),
23213 source ? source->name : Qt);
23214 x_flush_dirty_back_buffer_on (f);
23215 }
23216 }
23217 #endif
23218
23219 if (!(tab_bar_p && NILP (tab_bar_arg)) && !tool_bar_p)
23220 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
23221 if (! popup_activated ())
23222 #endif
23223 {
23224 if (ignore_next_mouse_click_timeout)
23225 {
23226 if (xev->evtype == XI_ButtonPress
23227 && xev->time > ignore_next_mouse_click_timeout)
23228 {
23229 ignore_next_mouse_click_timeout = 0;
23230 x_construct_mouse_click (&inev.ie, &bv, f);
23231 }
23232 if (xev->evtype == XI_ButtonRelease)
23233 ignore_next_mouse_click_timeout = 0;
23234 }
23235 else
23236 x_construct_mouse_click (&inev.ie, &bv, f);
23237
23238 if (!NILP (tab_bar_arg))
23239 inev.ie.arg = tab_bar_arg;
23240 }
23241
23242 if (FRAME_X_EMBEDDED_P (f)
23243 && !FRAME_NO_ACCEPT_FOCUS (f))
23244 xembed_send_message (f, xev->time,
23245 XEMBED_REQUEST_FOCUS, 0, 0, 0);
23246 }
23247 else
23248 {
23249 struct scroll_bar *bar
23250 = x_window_to_scroll_bar (dpyinfo->display,
23251 xev->event, 2);
23252
23253 #ifndef USE_TOOLKIT_SCROLL_BARS
23254 if (bar)
23255 x_scroll_bar_handle_click (bar, (XEvent *) &bv, &inev.ie,
23256 source ? source->name : Qnil);
23257 #else
23258
23259
23260 if (bar && xev->mods.effective & ControlMask)
23261 {
23262 x_scroll_bar_handle_click (bar, (XEvent *) &bv, &inev.ie,
23263 source ? source->name : Qnil);
23264 *finish = X_EVENT_DROP;
23265 }
23266 #endif
23267 }
23268
23269 if (xev->evtype == XI_ButtonPress)
23270 {
23271 dpyinfo->grabbed |= (1 << xev->detail);
23272 device->grab |= (1 << xev->detail);
23273 dpyinfo->last_mouse_frame = f;
23274 if (f && !tab_bar_p)
23275 f->last_tab_bar_item = -1;
23276 #if ! defined (USE_GTK)
23277 if (f && !tool_bar_p)
23278 f->last_tool_bar_item = -1;
23279 #endif
23280
23281 }
23282 else
23283 {
23284 dpyinfo->grabbed &= ~(1 << xev->detail);
23285 device->grab &= ~(1 << xev->detail);
23286 }
23287
23288 if (source && inev.ie.kind != NO_EVENT)
23289 inev.ie.device = source->name;
23290
23291 if (f)
23292 f->mouse_moved = false;
23293
23294 #if defined (USE_GTK)
23295
23296
23297 f = x_menubar_window_to_frame (dpyinfo, event);
23298 if (f
23299 && xev->detail < 3)
23300 {
23301
23302
23303 bool was_waiting_for_input = waiting_for_input;
23304
23305
23306
23307 if (waiting_for_input)
23308 waiting_for_input = 0;
23309 set_frame_menubar (f, true);
23310 waiting_for_input = was_waiting_for_input;
23311 }
23312 #endif
23313 goto XI_OTHER;
23314 }
23315
23316 case XI_KeyPress:
23317 {
23318 int state = xev->mods.effective;
23319 Lisp_Object c;
23320 #ifdef HAVE_XKB
23321 unsigned int mods_rtrn;
23322 #endif
23323 int keycode = xev->detail;
23324 KeySym keysym;
23325 char copy_buffer[81];
23326 char *copy_bufptr = copy_buffer;
23327 int copy_bufsiz = sizeof (copy_buffer);
23328 ptrdiff_t i;
23329 unsigned int old_state;
23330 struct xi_device_t *device, *source;
23331
23332 coding = Qlatin_1;
23333
23334 device = xi_device_from_id (dpyinfo, xev->deviceid);
23335 source = xi_device_from_id (dpyinfo, xev->sourceid);
23336
23337 if (!device)
23338 goto XI_OTHER;
23339
23340 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
23341
23342 if (popup_activated ())
23343 {
23344 #ifdef USE_LUCID
23345
23346 use_copy = true;
23347 copy.xkey.type = KeyPress;
23348 copy.xkey.serial = xev->serial;
23349 copy.xkey.send_event = xev->send_event;
23350 copy.xkey.display = dpyinfo->display;
23351 copy.xkey.window = xev->event;
23352 copy.xkey.root = xev->root;
23353 copy.xkey.subwindow = xev->child;
23354 copy.xkey.time = xev->time;
23355 copy.xkey.state = xi_convert_event_keyboard_state (xev);
23356 xi_convert_button_state (&xev->buttons, ©.xkey.state);
23357
23358 copy.xkey.x = lrint (xev->event_x);
23359 copy.xkey.y = lrint (xev->event_y);
23360 copy.xkey.x_root = lrint (xev->root_x);
23361 copy.xkey.y_root = lrint (xev->root_y);
23362 copy.xkey.keycode = xev->detail;
23363 copy.xkey.same_screen = True;
23364 #endif
23365 goto XI_OTHER;
23366 }
23367 #endif
23368
23369 x_display_set_last_user_time (dpyinfo, xev->time,
23370 xev->send_event, true);
23371 ignore_next_mouse_click_timeout = 0;
23372
23373 f = x_any_window_to_frame (dpyinfo, xev->event);
23374
23375 if (f && xev->event == FRAME_X_WINDOW (f))
23376
23377
23378 xi_compute_root_window_offset (f, xev);
23379
23380
23381
23382
23383
23384 #ifdef USE_GTK
23385 if (f)
23386 x_set_gtk_user_time (f, xev->time);
23387 #endif
23388
23389 if (f)
23390 {
23391
23392
23393
23394 if (device)
23395 xi_handle_interaction (dpyinfo, f, device,
23396 xev->time);
23397 }
23398
23399 XKeyPressedEvent xkey;
23400
23401 memset (&xkey, 0, sizeof xkey);
23402
23403 xkey.type = KeyPress;
23404 xkey.serial = xev->serial;
23405 xkey.send_event = xev->send_event;
23406 xkey.display = dpyinfo->display;
23407 xkey.window = xev->event;
23408 xkey.root = xev->root;
23409 xkey.subwindow = xev->child;
23410 xkey.time = xev->time;
23411 xkey.state = xi_convert_event_keyboard_state (xev);
23412
23413 xkey.x = lrint (xev->event_x);
23414 xkey.y = lrint (xev->event_y);
23415 xkey.x_root = lrint (xev->root_x);
23416 xkey.y_root = lrint (xev->root_y);
23417
23418
23419
23420 xi_convert_button_state (&xev->buttons, &xkey.state);
23421
23422 xkey.keycode = xev->detail;
23423 xkey.same_screen = True;
23424
23425 #ifdef HAVE_X_I18N
23426 #ifdef USE_GTK
23427 if ((!x_gtk_use_native_input
23428 && x_filter_event (dpyinfo, (XEvent *) &xkey))
23429 || (x_gtk_use_native_input
23430 && x_filter_event (dpyinfo, event)))
23431 {
23432
23433
23434
23435 dpyinfo->pending_keystroke_time = xev->time;
23436 dpyinfo->pending_keystroke_source = xev->sourceid;
23437
23438 *finish = X_EVENT_DROP;
23439 goto XI_OTHER;
23440 }
23441 #else
23442 if (x_filter_event (dpyinfo, (XEvent *) &xkey))
23443 {
23444
23445
23446
23447 dpyinfo->pending_keystroke_time = xev->time;
23448 dpyinfo->pending_keystroke_source = xev->sourceid;
23449
23450 *finish = X_EVENT_DROP;
23451 goto XI_OTHER;
23452 }
23453 #endif
23454 #elif USE_GTK
23455 if ((x_gtk_use_native_input
23456 || dpyinfo->prefer_native_input)
23457 && xg_filter_key (any, event))
23458 {
23459
23460
23461
23462 dpyinfo->pending_keystroke_time = xev->time;
23463 dpyinfo->pending_keystroke_source = xev->sourceid;
23464
23465 *finish = X_EVENT_DROP;
23466 goto XI_OTHER;
23467 }
23468 #endif
23469
23470 state |= x_emacs_to_x_modifiers (dpyinfo, extra_keyboard_modifiers);
23471
23472 #ifdef HAVE_XKB
23473 if (dpyinfo->xkb_desc)
23474 {
23475 unsigned int xkb_state;
23476
23477 xkb_state = state & ~(1 << 13 | 1 << 14);
23478 xkb_state |= xev->group.effective << 13;
23479
23480 if (!XkbTranslateKeyCode (dpyinfo->xkb_desc, keycode,
23481 xkb_state, &mods_rtrn, &keysym))
23482 goto XI_OTHER;
23483 }
23484 else
23485 {
23486 #endif
23487 int keysyms_per_keycode_return;
23488 KeySym *ksms = XGetKeyboardMapping (dpyinfo->display, keycode, 1,
23489 &keysyms_per_keycode_return);
23490 if (!(keysym = ksms[0]))
23491 {
23492 XFree (ksms);
23493 goto XI_OTHER;
23494 }
23495 XFree (ksms);
23496 #ifdef HAVE_XKB
23497 }
23498 #endif
23499
23500 if (keysym == NoSymbol)
23501 goto XI_OTHER;
23502
23503
23504
23505 if (!hlinfo->mouse_face_hidden && FIXNUMP (Vmouse_highlight)
23506 && (f == 0
23507 #if ! defined (USE_GTK)
23508 || !EQ (f->tool_bar_window, hlinfo->mouse_face_window)
23509 #endif
23510 || !EQ (f->tab_bar_window, hlinfo->mouse_face_window))
23511 )
23512 {
23513 mouse_frame = hlinfo->mouse_face_mouse_frame;
23514
23515 clear_mouse_face (hlinfo);
23516 hlinfo->mouse_face_hidden = true;
23517
23518 if (mouse_frame)
23519 x_flush_dirty_back_buffer_on (mouse_frame);
23520 }
23521
23522 if (f != 0)
23523 {
23524 #ifdef USE_GTK
23525
23526
23527
23528
23529 *finish = X_EVENT_DROP;
23530 #endif
23531
23532 XSETFRAME (inev.ie.frame_or_window, f);
23533 inev.ie.timestamp = xev->time;
23534
23535 #ifdef HAVE_X_I18N
23536 if (FRAME_XIC (f))
23537 {
23538 Status status_return;
23539 nbytes = XmbLookupString (FRAME_XIC (f),
23540 &xkey, (char *) copy_bufptr,
23541 copy_bufsiz, &keysym,
23542 &status_return);
23543 coding = FRAME_X_XIM_CODING (f);
23544
23545 if (status_return == XBufferOverflow)
23546 {
23547 copy_bufsiz = nbytes + 1;
23548 copy_bufptr = SAFE_ALLOCA (copy_bufsiz);
23549 nbytes = XmbLookupString (FRAME_XIC (f),
23550 &xkey, (char *) copy_bufptr,
23551 copy_bufsiz, &keysym,
23552 &status_return);
23553 }
23554
23555 if (status_return == XLookupNone)
23556 goto xi_done_keysym;
23557 else if (status_return == XLookupChars)
23558 {
23559 keysym = NoSymbol;
23560 state = 0;
23561 }
23562 else if (status_return != XLookupKeySym
23563 && status_return != XLookupBoth)
23564 emacs_abort ();
23565 }
23566 else
23567 #endif
23568 {
23569 #ifdef HAVE_XKB
23570 int overflow = 0;
23571 KeySym sym = keysym;
23572
23573 if (dpyinfo->xkb_desc)
23574 {
23575 nbytes = XkbTranslateKeySym (dpyinfo->display, &sym,
23576 state & ~mods_rtrn, copy_bufptr,
23577 copy_bufsiz, &overflow);
23578 if (overflow)
23579 {
23580 copy_bufptr = SAFE_ALLOCA ((copy_bufsiz += overflow)
23581 * sizeof *copy_bufptr);
23582 overflow = 0;
23583 nbytes = XkbTranslateKeySym (dpyinfo->display, &sym,
23584 state & ~mods_rtrn, copy_bufptr,
23585 copy_bufsiz, &overflow);
23586
23587 if (overflow)
23588 nbytes = 0;
23589 }
23590
23591 coding = Qnil;
23592 }
23593 else
23594 #endif
23595 {
23596 old_state = xkey.state;
23597 xkey.state &= ~ControlMask;
23598 xkey.state &= ~(dpyinfo->meta_mod_mask
23599 | dpyinfo->super_mod_mask
23600 | dpyinfo->hyper_mod_mask
23601 | dpyinfo->alt_mod_mask);
23602
23603 nbytes = XLookupString (&xkey, copy_bufptr,
23604 copy_bufsiz, &keysym,
23605 NULL);
23606
23607 xkey.state = old_state;
23608 }
23609 }
23610
23611 inev.ie.modifiers = x_x_to_emacs_modifiers (dpyinfo, state);
23612
23613 #ifdef XK_F1
23614 if (x_dnd_in_progress
23615 && xev->deviceid == x_dnd_keyboard_device
23616 && keysym == XK_F1)
23617 {
23618 x_dnd_xm_use_help = true;
23619 goto xi_done_keysym;
23620 }
23621 #endif
23622
23623
23624
23625 if (keysym >= 32 && keysym < 128)
23626
23627 {
23628 inev.ie.kind = ASCII_KEYSTROKE_EVENT;
23629 inev.ie.code = keysym;
23630
23631 if (source)
23632 inev.ie.device = source->name;
23633
23634 goto xi_done_keysym;
23635 }
23636
23637
23638 if (keysym >= 0x01000000 && keysym <= 0x0110FFFF)
23639 {
23640 if (keysym < 0x01000080)
23641 inev.ie.kind = ASCII_KEYSTROKE_EVENT;
23642 else
23643 inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
23644
23645 if (source)
23646 inev.ie.device = source->name;
23647
23648 inev.ie.code = keysym & 0xFFFFFF;
23649 goto xi_done_keysym;
23650 }
23651
23652
23653 if (HASH_TABLE_P (Vx_keysym_table)
23654 && (c = Fgethash (make_fixnum (keysym),
23655 Vx_keysym_table,
23656 Qnil),
23657 FIXNATP (c)))
23658 {
23659 inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFIXNAT (c))
23660 ? ASCII_KEYSTROKE_EVENT
23661 : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
23662 inev.ie.code = XFIXNAT (c);
23663
23664 if (source)
23665 inev.ie.device = source->name;
23666
23667 goto xi_done_keysym;
23668 }
23669
23670
23671 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
23672 || keysym == XK_Delete
23673 #ifdef XK_ISO_Left_Tab
23674 || (keysym >= XK_ISO_Left_Tab
23675 && keysym <= XK_ISO_Enter)
23676 #endif
23677 || IsCursorKey (keysym)
23678 || IsMiscFunctionKey (keysym)
23679 #ifdef HPUX
23680
23681
23682
23683
23684 || (XK_Select <= keysym && keysym < XK_KP_Space)
23685 #endif
23686 #ifdef XK_dead_circumflex
23687 || keysym == XK_dead_circumflex
23688 #endif
23689 #ifdef XK_dead_grave
23690 || keysym == XK_dead_grave
23691 #endif
23692 #ifdef XK_dead_tilde
23693 || keysym == XK_dead_tilde
23694 #endif
23695 #ifdef XK_dead_diaeresis
23696 || keysym == XK_dead_diaeresis
23697 #endif
23698 #ifdef XK_dead_macron
23699 || keysym == XK_dead_macron
23700 #endif
23701 #ifdef XK_dead_degree
23702 || keysym == XK_dead_degree
23703 #endif
23704 #ifdef XK_dead_acute
23705 || keysym == XK_dead_acute
23706 #endif
23707 #ifdef XK_dead_cedilla
23708 || keysym == XK_dead_cedilla
23709 #endif
23710 #ifdef XK_dead_breve
23711 || keysym == XK_dead_breve
23712 #endif
23713 #ifdef XK_dead_ogonek
23714 || keysym == XK_dead_ogonek
23715 #endif
23716 #ifdef XK_dead_caron
23717 || keysym == XK_dead_caron
23718 #endif
23719 #ifdef XK_dead_doubleacute
23720 || keysym == XK_dead_doubleacute
23721 #endif
23722 #ifdef XK_dead_abovedot
23723 || keysym == XK_dead_abovedot
23724 #endif
23725 #ifdef XK_dead_abovering
23726 || keysym == XK_dead_abovering
23727 #endif
23728 #ifdef XK_dead_belowdot
23729 || keysym == XK_dead_belowdot
23730 #endif
23731 #ifdef XK_dead_voiced_sound
23732 || keysym == XK_dead_voiced_sound
23733 #endif
23734 #ifdef XK_dead_semivoiced_sound
23735 || keysym == XK_dead_semivoiced_sound
23736 #endif
23737 #ifdef XK_dead_hook
23738 || keysym == XK_dead_hook
23739 #endif
23740 #ifdef XK_dead_horn
23741 || keysym == XK_dead_horn
23742 #endif
23743 #ifdef XK_dead_stroke
23744 || keysym == XK_dead_stroke
23745 #endif
23746 #ifdef XK_dead_abovecomma
23747 || keysym == XK_dead_abovecomma
23748 #endif
23749 || IsKeypadKey (keysym)
23750 || IsFunctionKey (keysym)
23751
23752 || (keysym & (1 << 28))
23753 || (keysym != NoSymbol && nbytes == 0))
23754 && ! (IsModifierKey (keysym)
23755
23756
23757
23758
23759
23760 #if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
23761 || (XK_ISO_Lock <= keysym
23762 && keysym <= XK_ISO_Last_Group_Lock)
23763 #endif
23764 ))
23765 {
23766 STORE_KEYSYM_FOR_DEBUG (keysym);
23767
23768
23769 inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
23770 inev.ie.code = keysym;
23771
23772 if (source)
23773 inev.ie.device = source->name;
23774
23775 goto xi_done_keysym;
23776 }
23777
23778 for (i = 0; i < nbytes; i++)
23779 {
23780 STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]);
23781 }
23782
23783 if (nbytes)
23784 {
23785 inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
23786 inev.ie.arg = make_unibyte_string (copy_bufptr, nbytes);
23787
23788 Fput_text_property (make_fixnum (0), make_fixnum (nbytes),
23789 Qcoding, coding, inev.ie.arg);
23790
23791 if (source)
23792 inev.ie.device = source->name;
23793 }
23794 goto xi_done_keysym;
23795 }
23796
23797 goto XI_OTHER;
23798 }
23799
23800 #if defined USE_GTK && !defined HAVE_GTK3
23801 case XI_RawKeyPress:
23802 {
23803 XIRawEvent *raw_event = (XIRawEvent *) xi_event;
23804
23805
23806
23807
23808 dpyinfo->pending_keystroke_time = raw_event->time;
23809 dpyinfo->pending_keystroke_source = raw_event->sourceid;
23810 dpyinfo->pending_keystroke_time_special_p = true;
23811 goto XI_OTHER;
23812 }
23813 #endif
23814
23815 case XI_KeyRelease:
23816 #if defined HAVE_X_I18N || defined USE_GTK || defined USE_LUCID
23817 {
23818 XKeyPressedEvent xkey;
23819
23820 memset (&xkey, 0, sizeof xkey);
23821
23822 xkey.type = KeyRelease;
23823 xkey.serial = xev->serial;
23824 xkey.send_event = xev->send_event;
23825 xkey.display = dpyinfo->display;
23826 xkey.window = xev->event;
23827 xkey.root = xev->root;
23828 xkey.subwindow = xev->child;
23829 xkey.time = xev->time;
23830 xkey.state = xi_convert_event_keyboard_state (xev);
23831 xkey.x = lrint (xev->event_x);
23832 xkey.y = lrint (xev->event_y);
23833 xkey.x_root = lrint (xev->root_x);
23834 xkey.y_root = lrint (xev->root_y);
23835
23836
23837
23838 xi_convert_button_state (&xev->buttons, &xkey.state);
23839
23840 xkey.keycode = xev->detail;
23841 xkey.same_screen = True;
23842
23843 #ifdef USE_LUCID
23844 if (!popup_activated ())
23845 {
23846 #endif
23847 #ifdef HAVE_X_I18N
23848 if (x_filter_event (dpyinfo, (XEvent *) &xkey))
23849 *finish = X_EVENT_DROP;
23850 #elif defined USE_GTK
23851 f = x_any_window_to_frame (xkey->event);
23852
23853 if (f && xg_filter_key (f, event))
23854 *finish = X_EVENT_DROP;
23855 #endif
23856 #ifdef USE_LUCID
23857 }
23858 else
23859 {
23860
23861
23862
23863
23864
23865
23866
23867 }
23868 #endif
23869 }
23870 #endif
23871
23872 goto XI_OTHER;
23873
23874 case XI_PropertyEvent:
23875 goto XI_OTHER;
23876
23877 case XI_HierarchyChanged:
23878 {
23879 XIHierarchyEvent *hev;
23880 XIDeviceInfo *info;
23881 int i, ndevices, n_disabled, *disabled;
23882 struct xi_device_t *device;
23883 bool any_changed;
23884
23885 any_changed = false;
23886 hev = (XIHierarchyEvent *) xi_event;
23887 disabled = SAFE_ALLOCA (sizeof *disabled * hev->num_info);
23888 n_disabled = 0;
23889
23890 for (i = 0; i < hev->num_info; ++i)
23891 {
23892 if (hev->info[i].flags & XIDeviceEnabled)
23893 {
23894
23895
23896
23897 if (n_disabled)
23898 {
23899 xi_disable_devices (dpyinfo, disabled, n_disabled);
23900 n_disabled = 0;
23901
23902
23903
23904
23905 any_changed = true;
23906 }
23907
23908
23909
23910
23911
23912
23913
23914 if (!xi_device_from_id (dpyinfo,
23915 hev->info[i].deviceid))
23916 {
23917 x_catch_errors (dpyinfo->display);
23918 info = XIQueryDevice (dpyinfo->display,
23919 hev->info[i].deviceid,
23920 &ndevices);
23921 x_uncatch_errors ();
23922
23923 if (info && info->enabled)
23924 {
23925 dpyinfo->devices
23926 = xrealloc (dpyinfo->devices,
23927 (sizeof *dpyinfo->devices
23928 * ++dpyinfo->num_devices));
23929 memset (dpyinfo->devices + dpyinfo->num_devices - 1,
23930 0, sizeof *dpyinfo->devices);
23931 device = &dpyinfo->devices[dpyinfo->num_devices - 1];
23932 xi_populate_device_from_info (dpyinfo, device, info);
23933 }
23934
23935 if (info)
23936 XIFreeDeviceInfo (info);
23937 }
23938 }
23939 else if (hev->info[i].flags & XIDeviceDisabled)
23940 disabled[n_disabled++] = hev->info[i].deviceid;
23941 else if (hev->info[i].flags & XISlaveDetached
23942 || hev->info[i].flags & XISlaveAttached)
23943 {
23944 device = xi_device_from_id (dpyinfo, hev->info[i].deviceid);
23945 x_catch_errors (dpyinfo->display);
23946 info = XIQueryDevice (dpyinfo->display, hev->info[i].deviceid,
23947 &ndevices);
23948 x_uncatch_errors ();
23949
23950 if (info)
23951 {
23952 if (device)
23953 {
23954 device->use = info->use;
23955 device->attachment = info->attachment;
23956 }
23957
23958
23959
23960
23961
23962
23963 XIFreeDeviceInfo (info);
23964 }
23965 }
23966 }
23967
23968
23969
23970 xi_disable_devices (dpyinfo, disabled, n_disabled);
23971
23972
23973
23974
23975
23976 if (any_changed || n_disabled)
23977 xi_handle_focus_change (dpyinfo);
23978
23979 goto XI_OTHER;
23980 }
23981
23982 case XI_DeviceChanged:
23983 {
23984 XIDeviceChangedEvent *device_changed;
23985 struct xi_device_t *device;
23986
23987 device_changed = (XIDeviceChangedEvent *) xi_event;
23988 device = xi_device_from_id (dpyinfo, device_changed->deviceid);
23989
23990
23991
23992
23993 if (!device)
23994 goto XI_OTHER;
23995
23996
23997
23998 xi_handle_device_changed (dpyinfo, device, device_changed);
23999 goto XI_OTHER;
24000 }
24001
24002 #ifdef HAVE_XINPUT2_2
24003 case XI_TouchBegin:
24004 {
24005 struct xi_device_t *device, *source;
24006 bool menu_bar_p = false, tool_bar_p = false;
24007 #ifdef HAVE_GTK3
24008 GdkRectangle test_rect;
24009 #endif
24010 device = xi_device_from_id (dpyinfo, xev->deviceid);
24011 source = xi_device_from_id (dpyinfo, xev->sourceid);
24012 x_display_set_last_user_time (dpyinfo, xev->time,
24013 xev->send_event, true);
24014
24015 if (!device)
24016 goto XI_OTHER;
24017
24018 if (xi_find_touch_point (device, xev->detail))
24019 emacs_abort ();
24020
24021 f = x_window_to_frame (dpyinfo, xev->event);
24022
24023 if (f)
24024
24025
24026 xi_compute_root_window_offset (f, xev);
24027
24028 #ifdef HAVE_GTK3
24029 menu_bar_p = (f && FRAME_X_OUTPUT (f)->menubar_widget
24030 && xg_event_is_for_menubar (f, event));
24031 if (f && FRAME_X_OUTPUT (f)->toolbar_widget)
24032 {
24033 int scale = xg_get_scale (f);
24034
24035 test_rect.x = xev->event_x / scale;
24036 test_rect.y = xev->event_y / scale;
24037 test_rect.width = 1;
24038 test_rect.height = 1;
24039
24040 tool_bar_p = gtk_widget_intersect (FRAME_X_OUTPUT (f)->toolbar_widget,
24041 &test_rect, NULL);
24042 }
24043 #endif
24044
24045 if (!menu_bar_p && !tool_bar_p)
24046 {
24047 if (f && device->direct_p)
24048 {
24049 *finish = X_EVENT_DROP;
24050
24051 x_catch_errors (dpyinfo->display);
24052
24053 if (x_input_grab_touch_events)
24054 XIAllowTouchEvents (dpyinfo->display, xev->deviceid,
24055 xev->detail, xev->event, XIAcceptTouch);
24056
24057 if (!x_had_errors_p (dpyinfo->display))
24058 {
24059 xi_link_touch_point (device, xev->detail, xev->event_x,
24060 xev->event_y);
24061
24062 inev.ie.kind = TOUCHSCREEN_BEGIN_EVENT;
24063 inev.ie.timestamp = xev->time;
24064 XSETFRAME (inev.ie.frame_or_window, f);
24065 XSETINT (inev.ie.x, lrint (xev->event_x));
24066 XSETINT (inev.ie.y, lrint (xev->event_y));
24067 XSETINT (inev.ie.arg, xev->detail);
24068
24069 if (source)
24070 inev.ie.device = source->name;
24071 }
24072
24073 x_uncatch_errors ();
24074 }
24075 #ifndef HAVE_GTK3
24076 else if (x_input_grab_touch_events)
24077 {
24078 x_ignore_errors_for_next_request (dpyinfo);
24079 XIAllowTouchEvents (dpyinfo->display, xev->deviceid,
24080 xev->detail, xev->event, XIRejectTouch);
24081 x_stop_ignoring_errors (dpyinfo);
24082 }
24083 #endif
24084 }
24085 else
24086 {
24087 #ifdef HAVE_GTK3
24088 bool was_waiting_for_input = waiting_for_input;
24089
24090
24091
24092 if (waiting_for_input)
24093 waiting_for_input = 0;
24094 set_frame_menubar (f, true);
24095 waiting_for_input = was_waiting_for_input;
24096 #endif
24097 }
24098
24099 goto XI_OTHER;
24100 }
24101
24102 case XI_TouchUpdate:
24103 {
24104 struct xi_device_t *device, *source;
24105 struct xi_touch_point_t *touchpoint;
24106 Lisp_Object arg = Qnil;
24107
24108 device = xi_device_from_id (dpyinfo, xev->deviceid);
24109 source = xi_device_from_id (dpyinfo, xev->sourceid);
24110 x_display_set_last_user_time (dpyinfo, xev->time,
24111 xev->send_event, true);
24112
24113 if (!device)
24114 goto XI_OTHER;
24115
24116 touchpoint = xi_find_touch_point (device, xev->detail);
24117
24118 if (!touchpoint)
24119 goto XI_OTHER;
24120
24121 touchpoint->x = xev->event_x;
24122 touchpoint->y = xev->event_y;
24123
24124 f = x_window_to_frame (dpyinfo, xev->event);
24125
24126 if (f && device->direct_p)
24127 {
24128 inev.ie.kind = TOUCHSCREEN_UPDATE_EVENT;
24129 inev.ie.timestamp = xev->time;
24130 XSETFRAME (inev.ie.frame_or_window, f);
24131
24132 for (touchpoint = device->touchpoints;
24133 touchpoint; touchpoint = touchpoint->next)
24134 {
24135 arg = Fcons (list3i (lrint (touchpoint->x),
24136 lrint (touchpoint->y),
24137 lrint (touchpoint->number)),
24138 arg);
24139 }
24140
24141 if (source)
24142 inev.ie.device = source->name;
24143
24144 inev.ie.arg = arg;
24145 }
24146
24147 goto XI_OTHER;
24148 }
24149
24150 case XI_TouchEnd:
24151 {
24152 struct xi_device_t *device, *source;
24153 bool unlinked_p;
24154
24155 device = xi_device_from_id (dpyinfo, xev->deviceid);
24156 source = xi_device_from_id (dpyinfo, xev->sourceid);
24157 x_display_set_last_user_time (dpyinfo, xev->time,
24158 xev->send_event, true);
24159
24160 if (!device)
24161 goto XI_OTHER;
24162
24163 unlinked_p = xi_unlink_touch_point (xev->detail, device);
24164
24165 if (unlinked_p)
24166 {
24167 f = x_window_to_frame (dpyinfo, xev->event);
24168
24169 if (f && device->direct_p)
24170 {
24171 inev.ie.kind = TOUCHSCREEN_END_EVENT;
24172 inev.ie.timestamp = xev->time;
24173
24174 XSETFRAME (inev.ie.frame_or_window, f);
24175 XSETINT (inev.ie.x, lrint (xev->event_x));
24176 XSETINT (inev.ie.y, lrint (xev->event_y));
24177 XSETINT (inev.ie.arg, xev->detail);
24178
24179 if (source)
24180 inev.ie.device = source->name;
24181 }
24182 }
24183
24184 goto XI_OTHER;
24185 }
24186
24187 #endif
24188
24189 #ifdef HAVE_XINPUT2_4
24190 case XI_GesturePinchBegin:
24191 case XI_GesturePinchUpdate:
24192 {
24193 XIGesturePinchEvent *pev = (XIGesturePinchEvent *) xi_event;
24194 struct xi_device_t *device, *source;
24195
24196 device = xi_device_from_id (dpyinfo, pev->deviceid);
24197 source = xi_device_from_id (dpyinfo, pev->sourceid);
24198 x_display_set_last_user_time (dpyinfo, pev->time,
24199 pev->send_event, true);
24200
24201 if (!device)
24202 goto XI_OTHER;
24203
24204 #ifdef HAVE_XWIDGETS
24205 struct xwidget_view *xvw = xwidget_view_from_window (pev->event);
24206
24207 if (xvw)
24208 {
24209 *finish = X_EVENT_DROP;
24210 xwidget_pinch (xvw, pev);
24211 goto XI_OTHER;
24212 }
24213 #endif
24214
24215 any = x_window_to_frame (dpyinfo, pev->event);
24216
24217 if (any)
24218 {
24219 if (pev->event == FRAME_X_WINDOW (any))
24220 xi_compute_root_window_offset_pinch (any, pev);
24221
24222 inev.ie.kind = PINCH_EVENT;
24223 inev.ie.modifiers
24224 = x_x_to_emacs_modifiers (dpyinfo, pev->mods.effective);
24225
24226 XSETINT (inev.ie.x, lrint (pev->event_x));
24227 XSETINT (inev.ie.y, lrint (pev->event_y));
24228 XSETFRAME (inev.ie.frame_or_window, any);
24229 inev.ie.arg = list4 (make_float (pev->delta_x),
24230 make_float (pev->delta_y),
24231 make_float (pev->scale),
24232 make_float (pev->delta_angle));
24233
24234 if (source)
24235 inev.ie.device = source->name;
24236 }
24237
24238
24239
24240 *finish = X_EVENT_DROP;
24241 goto XI_OTHER;
24242 }
24243
24244 case XI_GesturePinchEnd:
24245 {
24246 #if defined HAVE_XWIDGETS
24247 XIGesturePinchEvent *pev = (XIGesturePinchEvent *) xi_event;
24248 struct xwidget_view *xvw = xwidget_view_from_window (pev->event);
24249
24250 if (xvw)
24251 xwidget_pinch (xvw, pev);
24252 #endif
24253 *finish = X_EVENT_DROP;
24254 goto XI_OTHER;
24255 }
24256 #endif
24257 default:
24258 goto XI_OTHER;
24259 }
24260
24261 xi_done_keysym:
24262 #ifdef HAVE_X_I18N
24263 if (f)
24264 {
24265 struct window *w = XWINDOW (f->selected_window);
24266 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
24267
24268 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
24269 xic_set_statusarea (f);
24270 }
24271 #endif
24272 if (must_free_data)
24273 XFreeEventData (dpyinfo->display, &event->xcookie);
24274 goto done_keysym;
24275
24276 XI_OTHER:
24277 if (must_free_data)
24278 XFreeEventData (dpyinfo->display, &event->xcookie);
24279 goto OTHER;
24280 }
24281 #endif
24282
24283 default:
24284 #ifdef HAVE_XKB
24285 if (dpyinfo->supports_xkb
24286 && event->type == dpyinfo->xkb_event_type)
24287 {
24288 XkbEvent *xkbevent = (XkbEvent *) event;
24289
24290 if (xkbevent->any.xkb_type == XkbNewKeyboardNotify
24291 || xkbevent->any.xkb_type == XkbMapNotify)
24292 {
24293 XkbRefreshKeyboardMapping (&xkbevent->map);
24294
24295 if (dpyinfo->xkb_desc)
24296 {
24297 if (XkbGetUpdatedMap (dpyinfo->display,
24298 (XkbKeySymsMask
24299 | XkbKeyTypesMask
24300 | XkbModifierMapMask
24301 | XkbVirtualModsMask),
24302 dpyinfo->xkb_desc) == Success)
24303 XkbGetNames (dpyinfo->display, XkbAllNamesMask,
24304 dpyinfo->xkb_desc);
24305 else
24306 {
24307 XkbFreeKeyboard (dpyinfo->xkb_desc,
24308 XkbAllComponentsMask, True);
24309 dpyinfo->xkb_desc = NULL;
24310 }
24311 }
24312 else
24313 {
24314 dpyinfo->xkb_desc = XkbGetMap (dpyinfo->display,
24315 (XkbKeySymsMask
24316 | XkbKeyTypesMask
24317 | XkbModifierMapMask
24318 | XkbVirtualModsMask),
24319 XkbUseCoreKbd);
24320
24321 if (dpyinfo->xkb_desc)
24322 XkbGetNames (dpyinfo->display, XkbAllNamesMask,
24323 dpyinfo->xkb_desc);
24324 }
24325
24326 x_find_modifier_meanings (dpyinfo);
24327 }
24328 else if (x_dnd_in_progress
24329 && xkbevent->any.xkb_type == XkbStateNotify)
24330 x_dnd_keyboard_state = (xkbevent->state.mods
24331 | xkbevent->state.ptr_buttons);
24332 }
24333 #endif
24334 #ifdef HAVE_XSHAPE
24335 if (dpyinfo->xshape_supported_p
24336 && event->type == dpyinfo->xshape_event_base + ShapeNotify
24337 && x_dnd_in_progress && x_dnd_use_toplevels
24338 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
24339 {
24340 #ifndef USE_GTK
24341 XEvent xevent;
24342 #endif
24343 XShapeEvent *xse = (XShapeEvent *) event;
24344 #if defined HAVE_XCB_SHAPE && defined HAVE_XCB_SHAPE_INPUT_RECTS
24345 xcb_shape_get_rectangles_cookie_t bounding_rect_cookie;
24346 xcb_shape_get_rectangles_reply_t *bounding_rect_reply;
24347 xcb_rectangle_iterator_t bounding_rect_iterator;
24348
24349 xcb_shape_get_rectangles_cookie_t input_rect_cookie;
24350 xcb_shape_get_rectangles_reply_t *input_rect_reply;
24351 xcb_rectangle_iterator_t input_rect_iterator;
24352
24353 xcb_generic_error_t *error;
24354 #else
24355 XRectangle *rects;
24356 int rc, ordering;
24357 #endif
24358
24359
24360
24361
24362 #ifndef USE_GTK
24363 while (XPending (dpyinfo->display))
24364 {
24365 XNextEvent (dpyinfo->display, &xevent);
24366
24367 if (xevent.type == dpyinfo->xshape_event_base + ShapeNotify
24368 && ((XShapeEvent *) &xevent)->window == xse->window)
24369 xse = (XShapeEvent *) &xevent;
24370 else
24371 {
24372 XPutBackEvent (dpyinfo->display, &xevent);
24373 break;
24374 }
24375 }
24376 #endif
24377
24378 for (struct x_client_list_window *tem = x_dnd_toplevels; tem;
24379 tem = tem->next)
24380 {
24381 if (tem->window == xse->window)
24382 {
24383 if (tem->n_input_rects != -1)
24384 xfree (tem->input_rects);
24385 if (tem->n_bounding_rects != -1)
24386 xfree (tem->bounding_rects);
24387
24388 tem->n_input_rects = -1;
24389 tem->n_bounding_rects = -1;
24390
24391 #if defined HAVE_XCB_SHAPE && defined HAVE_XCB_SHAPE_INPUT_RECTS
24392 bounding_rect_cookie = xcb_shape_get_rectangles (dpyinfo->xcb_connection,
24393 (xcb_window_t) xse->window,
24394 XCB_SHAPE_SK_BOUNDING);
24395 if (dpyinfo->xshape_major > 1
24396 || (dpyinfo->xshape_major == 1
24397 && dpyinfo->xshape_minor >= 1))
24398 input_rect_cookie
24399 = xcb_shape_get_rectangles (dpyinfo->xcb_connection,
24400 (xcb_window_t) xse->window,
24401 XCB_SHAPE_SK_INPUT);
24402
24403 bounding_rect_reply = xcb_shape_get_rectangles_reply (dpyinfo->xcb_connection,
24404 bounding_rect_cookie,
24405 &error);
24406
24407 if (bounding_rect_reply)
24408 {
24409 bounding_rect_iterator
24410 = xcb_shape_get_rectangles_rectangles_iterator (bounding_rect_reply);
24411 tem->n_bounding_rects = bounding_rect_iterator.rem + 1;
24412 tem->bounding_rects = xmalloc (tem->n_bounding_rects
24413 * sizeof *tem->bounding_rects);
24414 tem->n_bounding_rects = 0;
24415
24416 for (; bounding_rect_iterator.rem; xcb_rectangle_next (&bounding_rect_iterator))
24417 {
24418 tem->bounding_rects[tem->n_bounding_rects].x
24419 = bounding_rect_iterator.data->x;
24420 tem->bounding_rects[tem->n_bounding_rects].y
24421 = bounding_rect_iterator.data->y;
24422 tem->bounding_rects[tem->n_bounding_rects].width
24423 = bounding_rect_iterator.data->width;
24424 tem->bounding_rects[tem->n_bounding_rects].height
24425 = bounding_rect_iterator.data->height;
24426
24427 tem->n_bounding_rects++;
24428 }
24429
24430 free (bounding_rect_reply);
24431 }
24432 else
24433 free (error);
24434
24435 if (dpyinfo->xshape_major > 1
24436 || (dpyinfo->xshape_major == 1
24437 && dpyinfo->xshape_minor >= 1))
24438 {
24439 input_rect_reply = xcb_shape_get_rectangles_reply (dpyinfo->xcb_connection,
24440 input_rect_cookie, &error);
24441
24442 if (input_rect_reply)
24443 {
24444 input_rect_iterator
24445 = xcb_shape_get_rectangles_rectangles_iterator (input_rect_reply);
24446 tem->n_input_rects = input_rect_iterator.rem + 1;
24447 tem->input_rects = xmalloc (tem->n_input_rects
24448 * sizeof *tem->input_rects);
24449 tem->n_input_rects = 0;
24450
24451 for (; input_rect_iterator.rem; xcb_rectangle_next (&input_rect_iterator))
24452 {
24453 tem->input_rects[tem->n_input_rects].x
24454 = input_rect_iterator.data->x;
24455 tem->input_rects[tem->n_input_rects].y
24456 = input_rect_iterator.data->y;
24457 tem->input_rects[tem->n_input_rects].width
24458 = input_rect_iterator.data->width;
24459 tem->input_rects[tem->n_input_rects].height
24460 = input_rect_iterator.data->height;
24461
24462 tem->n_input_rects++;
24463 }
24464
24465 free (input_rect_reply);
24466 }
24467 else
24468 free (error);
24469 }
24470 #else
24471 x_catch_errors (dpyinfo->display);
24472 rects = XShapeGetRectangles (dpyinfo->display,
24473 xse->window,
24474 ShapeBounding,
24475 &count, &ordering);
24476 rc = x_had_errors_p (dpyinfo->display);
24477 x_uncatch_errors_after_check ();
24478
24479
24480
24481 if (!rc)
24482 {
24483 tem->n_bounding_rects = count;
24484 tem->bounding_rects
24485 = xmalloc (sizeof *tem->bounding_rects * count);
24486 memcpy (tem->bounding_rects, rects,
24487 sizeof *tem->bounding_rects * count);
24488
24489 XFree (rects);
24490 }
24491
24492 #ifdef ShapeInput
24493 if (dpyinfo->xshape_major > 1
24494 || (dpyinfo->xshape_major == 1
24495 && dpyinfo->xshape_minor >= 1))
24496 {
24497 x_catch_errors (dpyinfo->display);
24498 rects = XShapeGetRectangles (dpyinfo->display,
24499 xse->window, ShapeInput,
24500 &count, &ordering);
24501 rc = x_had_errors_p (dpyinfo->display);
24502 x_uncatch_errors_after_check ();
24503
24504
24505
24506 if (!rc)
24507 {
24508 tem->n_input_rects = count;
24509 tem->input_rects
24510 = xmalloc (sizeof *tem->input_rects * count);
24511 memcpy (tem->input_rects, rects,
24512 sizeof *tem->input_rects * count);
24513
24514 XFree (rects);
24515 }
24516 }
24517 #endif
24518 #endif
24519
24520
24521
24522
24523 if (tem->n_input_rects != -1
24524 && tem->n_bounding_rects == tem->n_input_rects
24525 && !memcmp (tem->bounding_rects, tem->input_rects,
24526 tem->n_input_rects * sizeof *tem->input_rects))
24527 {
24528 xfree (tem->input_rects);
24529 tem->n_input_rects = -1;
24530 }
24531
24532
24533
24534
24535 if (tem->n_input_rects == -1
24536 && tem->n_bounding_rects == 1
24537 && tem->bounding_rects[0].width == tem->width
24538 && tem->bounding_rects[0].height == tem->height
24539 && tem->bounding_rects[0].x == -tem->border_width
24540 && tem->bounding_rects[0].y == -tem->border_width)
24541 {
24542 xfree (tem->bounding_rects);
24543 tem->n_bounding_rects = -1;
24544 }
24545
24546 break;
24547 }
24548 }
24549 }
24550 #endif
24551 #if defined HAVE_XRANDR && !defined USE_GTK
24552 if (dpyinfo->xrandr_supported_p
24553 && (event->type == (dpyinfo->xrandr_event_base
24554 + RRScreenChangeNotify)
24555 || event->type == (dpyinfo->xrandr_event_base
24556 + RRNotify)))
24557 {
24558 Time timestamp;
24559 Lisp_Object current_monitors;
24560 XRRScreenChangeNotifyEvent *notify;
24561
24562 if (event->type == (dpyinfo->xrandr_event_base
24563 + RRScreenChangeNotify))
24564 XRRUpdateConfiguration ((XEvent *) event);
24565
24566 if (event->type == (dpyinfo->xrandr_event_base
24567 + RRScreenChangeNotify))
24568 {
24569 notify = ((XRRScreenChangeNotifyEvent *) event);
24570 timestamp = notify->timestamp;
24571
24572
24573
24574 if (notify->root == dpyinfo->root_window)
24575 {
24576 dpyinfo->screen_width = notify->width;
24577 dpyinfo->screen_height = notify->height;
24578 dpyinfo->screen_mm_width = notify->mwidth;
24579 dpyinfo->screen_mm_height = notify->mheight;
24580 }
24581 }
24582 else
24583 timestamp = 0;
24584
24585 if (x_find_monitors_changed_event (dpyinfo))
24586
24587
24588 goto OTHER;
24589
24590 inev.ie.kind = MONITORS_CHANGED_EVENT;
24591 inev.ie.timestamp = timestamp;
24592 XSETTERMINAL (inev.ie.arg, dpyinfo->terminal);
24593
24594
24595
24596
24597 current_monitors
24598 = Fx_display_monitor_attributes_list (inev.ie.arg);
24599
24600 if (!NILP (Fequal (current_monitors,
24601 dpyinfo->last_monitor_attributes_list)))
24602 inev.ie.kind = NO_EVENT;
24603
24604 dpyinfo->last_monitor_attributes_list = current_monitors;
24605
24606 if (x_dnd_in_progress && x_dnd_update_tooltip)
24607 x_dnd_monitors = current_monitors;
24608
24609 if (inev.ie.kind != NO_EVENT)
24610 x_dnd_update_tooltip_now ();
24611 }
24612 #endif
24613 #ifdef HAVE_XFIXES
24614 if (dpyinfo->xfixes_supported_p
24615 && event->type == (dpyinfo->xfixes_event_base
24616 + XFixesSelectionNotify)
24617 && x_handle_selection_monitor_event (dpyinfo, event))
24618
24619
24620
24621
24622 *finish = X_EVENT_DROP;
24623 #endif
24624 OTHER:
24625 #ifdef USE_X_TOOLKIT
24626 if (*finish != X_EVENT_DROP)
24627 {
24628
24629
24630
24631 if (event->type != ConfigureNotify
24632 || (event->xconfigure.width != 0
24633 && event->xconfigure.height != 0))
24634 {
24635 #if defined USE_X_TOOLKIT && defined HAVE_XINPUT2
24636 XtDispatchEvent (use_copy ? © : (XEvent *) event);
24637 #else
24638 XtDispatchEvent ((XEvent *) event);
24639 #endif
24640 }
24641 }
24642 #endif
24643 #if defined USE_GTK && !defined HAVE_GTK3 && defined HAVE_XINPUT2
24644 if (*finish != X_EVENT_DROP && copy)
24645 {
24646 gtk_main_do_event (copy);
24647 *finish = X_EVENT_DROP;
24648 }
24649
24650 if (copy)
24651 gdk_event_free (copy);
24652 #endif
24653 break;
24654 }
24655
24656 done:
24657 if (inev.ie.kind != NO_EVENT)
24658 {
24659 kbd_buffer_store_buffered_event (&inev, hold_quit);
24660 count++;
24661 }
24662
24663 if (do_help
24664 && !(hold_quit && hold_quit->kind != NO_EVENT))
24665 {
24666 Lisp_Object frame;
24667
24668 if (f)
24669 XSETFRAME (frame, f);
24670 else
24671 frame = Qnil;
24672
24673 if (do_help > 0)
24674 {
24675 any_help_event_p = true;
24676 #ifdef HAVE_XINPUT2
24677 if (gen_help_device)
24678 xi_handle_interaction (dpyinfo, f,
24679 gen_help_device,
24680 gen_help_time);
24681 #endif
24682 gen_help_event (help_echo_string, frame, help_echo_window,
24683 help_echo_object, help_echo_pos);
24684 }
24685 else
24686 {
24687 help_echo_string = Qnil;
24688 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
24689 }
24690 count++;
24691 }
24692
24693 #if defined HAVE_XINPUT2 || defined HAVE_XKB || defined HAVE_X_I18N
24694 SAFE_FREE ();
24695 #endif
24696
24697 return count;
24698 }
24699
24700
24701
24702
24703
24704
24705
24706 #ifdef USE_GTK
24707 static int
24708 #else
24709 int
24710 #endif
24711 x_dispatch_event (XEvent *event, Display *display)
24712 {
24713 struct x_display_info *dpyinfo;
24714 int finish = X_EVENT_NORMAL;
24715
24716 dpyinfo = x_display_info_for_display (display);
24717
24718 if (dpyinfo)
24719 {
24720
24721 block_input ();
24722 handle_one_xevent (dpyinfo, event, &finish, 0);
24723 unblock_input ();
24724 }
24725
24726 return finish;
24727 }
24728
24729
24730
24731
24732
24733
24734
24735
24736
24737 static int
24738 XTread_socket (struct terminal *terminal, struct input_event *hold_quit)
24739 {
24740 int count = 0;
24741 bool event_found = false;
24742 struct x_display_info *dpyinfo = terminal->display_info.x;
24743
24744
24745
24746
24747
24748
24749
24750
24751
24752
24753
24754 if (!x_dnd_unwind_flag
24755 && ((x_dnd_in_progress
24756 && dpyinfo->display == FRAME_X_DISPLAY (x_dnd_frame))
24757 || (x_dnd_waiting_for_finish
24758 && dpyinfo->display == x_dnd_finish_display)))
24759 return 0;
24760
24761 x_clean_failable_requests (dpyinfo);
24762
24763 block_input ();
24764
24765
24766 if (dpyinfo == XTread_socket_fake_io_error)
24767 {
24768 XTread_socket_fake_io_error = 0;
24769 x_io_error_quitter (dpyinfo->display);
24770 }
24771
24772 #ifndef USE_GTK
24773 while (XPending (dpyinfo->display))
24774 {
24775 int finish;
24776 XEvent event;
24777
24778 XNextEvent (dpyinfo->display, &event);
24779
24780 #ifdef HAVE_X_I18N
24781
24782 #ifdef HAVE_XINPUT2
24783 if (event.type != GenericEvent
24784 || !dpyinfo->supports_xi2
24785 || event.xgeneric.extension != dpyinfo->xi2_opcode)
24786 {
24787
24788
24789 #endif
24790 if (x_filter_event (dpyinfo, &event))
24791 continue;
24792 #ifdef HAVE_XINPUT2
24793 }
24794 #endif
24795 #endif
24796 event_found = true;
24797
24798 count += handle_one_xevent (dpyinfo, &event, &finish, hold_quit);
24799
24800 if (finish == X_EVENT_GOTO_OUT)
24801 break;
24802 }
24803
24804 #else
24805
24806
24807
24808
24809
24810
24811
24812
24813
24814 while (gtk_events_pending ())
24815 {
24816 current_count = count;
24817 current_hold_quit = hold_quit;
24818
24819 gtk_main_iteration ();
24820
24821 count = current_count;
24822 current_count = -1;
24823 current_hold_quit = 0;
24824
24825 if (current_finish == X_EVENT_GOTO_OUT)
24826 break;
24827 }
24828
24829
24830 if (xg_pending_quit_event.kind != NO_EVENT)
24831 {
24832
24833
24834 if (FRAME_LIVE_P (XFRAME (xg_pending_quit_event.frame_or_window)))
24835
24836
24837 *hold_quit = xg_pending_quit_event;
24838
24839
24840 xg_pending_quit_event.kind = NO_EVENT;
24841 }
24842 #endif
24843
24844
24845
24846 if (! event_found)
24847 {
24848
24849
24850
24851 x_noop_count++;
24852 if (x_noop_count >= 100)
24853 {
24854 x_noop_count=0;
24855
24856 if (next_noop_dpyinfo == 0)
24857 next_noop_dpyinfo = x_display_list;
24858
24859 XNoOp (next_noop_dpyinfo->display);
24860
24861
24862 next_noop_dpyinfo = next_noop_dpyinfo->next;
24863 }
24864 }
24865
24866
24867
24868 if (dpyinfo->x_pending_autoraise_frame)
24869 {
24870 x_raise_frame (dpyinfo->x_pending_autoraise_frame);
24871 dpyinfo->x_pending_autoraise_frame = NULL;
24872 }
24873
24874 unblock_input ();
24875
24876 return count;
24877 }
24878
24879
24880
24881
24882
24883
24884
24885
24886
24887
24888
24889
24890
24891
24892
24893 static void
24894 x_clip_to_row (struct window *w, struct glyph_row *row,
24895 enum glyph_row_area area, GC gc)
24896 {
24897 struct frame *f = XFRAME (WINDOW_FRAME (w));
24898 XRectangle clip_rect;
24899 int window_x, window_y, window_width;
24900
24901 window_box (w, area, &window_x, &window_y, &window_width, 0);
24902
24903 clip_rect.x = window_x;
24904 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y));
24905 clip_rect.y = max (clip_rect.y, window_y);
24906 clip_rect.width = window_width;
24907 clip_rect.height = row->visible_height;
24908
24909 x_set_clip_rectangles (f, gc, &clip_rect, 1);
24910 }
24911
24912
24913
24914
24915 static void
24916 x_draw_hollow_cursor (struct window *w, struct glyph_row *row)
24917 {
24918 struct frame *f = XFRAME (WINDOW_FRAME (w));
24919 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
24920 Display *dpy = FRAME_X_DISPLAY (f);
24921 int x, y, wd, h;
24922 XGCValues xgcv;
24923 struct glyph *cursor_glyph;
24924 GC gc;
24925
24926
24927
24928 cursor_glyph = get_phys_cursor_glyph (w);
24929 if (cursor_glyph == NULL)
24930 return;
24931
24932
24933 get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h);
24934 wd = w->phys_cursor_width - 1;
24935
24936
24937
24938 xgcv.foreground = f->output_data.x->cursor_pixel;
24939 xgcv.line_width = 1;
24940 if (dpyinfo->scratch_cursor_gc)
24941 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground | GCLineWidth, &xgcv);
24942 else
24943 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_DRAWABLE (f),
24944 GCForeground | GCLineWidth, &xgcv);
24945 gc = dpyinfo->scratch_cursor_gc;
24946
24947
24948
24949
24950 if ((cursor_glyph->resolved_level & 1) != 0
24951 && cursor_glyph->pixel_width > wd)
24952 {
24953 x += cursor_glyph->pixel_width - wd;
24954 if (wd > 0)
24955 wd -= 1;
24956 }
24957
24958 x_clip_to_row (w, row, TEXT_AREA, gc);
24959 x_draw_rectangle (f, gc, x, y, wd, h - 1);
24960 x_reset_clip_rectangles (f, gc);
24961 }
24962
24963
24964
24965
24966
24967
24968
24969
24970
24971 static void
24972 x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text_cursor_kinds kind)
24973 {
24974 struct frame *f = XFRAME (w->frame);
24975 struct glyph *cursor_glyph;
24976
24977
24978
24979
24980 cursor_glyph = get_phys_cursor_glyph (w);
24981 if (cursor_glyph == NULL)
24982 return;
24983
24984
24985 if (cursor_glyph->type == XWIDGET_GLYPH)
24986 return;
24987
24988
24989
24990
24991 if (cursor_glyph->type == IMAGE_GLYPH)
24992 {
24993 struct glyph_row *r;
24994 r = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
24995 draw_phys_cursor_glyph (w, r, DRAW_CURSOR);
24996 }
24997 else
24998 {
24999 Display *dpy = FRAME_X_DISPLAY (f);
25000 Drawable drawable = FRAME_X_DRAWABLE (f);
25001 GC gc = FRAME_DISPLAY_INFO (f)->scratch_cursor_gc;
25002 unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures;
25003 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
25004 XGCValues xgcv;
25005
25006
25007
25008
25009
25010
25011 if (face->background == f->output_data.x->cursor_pixel)
25012 xgcv.background = xgcv.foreground = face->foreground;
25013 else
25014 xgcv.background = xgcv.foreground = f->output_data.x->cursor_pixel;
25015 xgcv.graphics_exposures = False;
25016 xgcv.line_width = 1;
25017
25018 mask |= GCLineWidth;
25019
25020 if (gc)
25021 XChangeGC (dpy, gc, mask, &xgcv);
25022 else
25023 {
25024 gc = XCreateGC (dpy, drawable, mask, &xgcv);
25025 FRAME_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
25026 }
25027
25028 x_clip_to_row (w, row, TEXT_AREA, gc);
25029
25030 if (kind == BAR_CURSOR)
25031 {
25032 int x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
25033
25034 if (width < 0)
25035 width = FRAME_CURSOR_WIDTH (f);
25036 width = min (cursor_glyph->pixel_width, width);
25037
25038 w->phys_cursor_width = width;
25039
25040
25041
25042 if ((cursor_glyph->resolved_level & 1) != 0)
25043 x += cursor_glyph->pixel_width - width;
25044
25045 x_fill_rectangle (f, gc, x,
25046 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
25047 width, row->height, false);
25048 }
25049 else
25050 {
25051 int dummy_x, dummy_y, dummy_h;
25052 int x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
25053
25054 if (width < 0)
25055 width = row->height;
25056
25057 width = min (row->height, width);
25058
25059 get_phys_cursor_geometry (w, row, cursor_glyph, &dummy_x,
25060 &dummy_y, &dummy_h);
25061
25062 if ((cursor_glyph->resolved_level & 1) != 0
25063 && cursor_glyph->pixel_width > w->phys_cursor_width - 1)
25064 x += cursor_glyph->pixel_width - w->phys_cursor_width + 1;
25065 x_fill_rectangle (f, gc, x,
25066 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
25067 row->height - width),
25068 w->phys_cursor_width - 1, width, false);
25069 }
25070
25071 x_reset_clip_rectangles (f, gc);
25072 }
25073 }
25074
25075
25076
25077
25078 static void
25079 x_define_frame_cursor (struct frame *f, Emacs_Cursor cursor)
25080 {
25081 if (!f->pointer_invisible
25082 && f->output_data.x->current_cursor != cursor)
25083 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
25084 f->output_data.x->current_cursor = cursor;
25085 }
25086
25087
25088
25089
25090 static void
25091 x_clear_frame_area (struct frame *f, int x, int y, int width, int height)
25092 {
25093 x_clear_area (f, x, y, width, height);
25094 }
25095
25096
25097
25098
25099 static void
25100 x_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x,
25101 int y, enum text_cursor_kinds cursor_type,
25102 int cursor_width, bool on_p, bool active_p)
25103 {
25104 #ifdef HAVE_X_I18N
25105 struct frame *f = XFRAME (WINDOW_FRAME (w));
25106 #endif
25107
25108 if (on_p)
25109 {
25110 w->phys_cursor_type = cursor_type;
25111 w->phys_cursor_on_p = true;
25112
25113 if (glyph_row->exact_window_width_line_p
25114 && (glyph_row->reversed_p
25115 ? (w->phys_cursor.hpos < 0)
25116 : (w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])))
25117 {
25118 glyph_row->cursor_in_fringe_p = true;
25119 draw_fringe_bitmap (w, glyph_row, glyph_row->reversed_p);
25120 }
25121 else
25122 {
25123 switch (cursor_type)
25124 {
25125 case HOLLOW_BOX_CURSOR:
25126 x_draw_hollow_cursor (w, glyph_row);
25127 break;
25128
25129 case FILLED_BOX_CURSOR:
25130 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
25131 break;
25132
25133 case BAR_CURSOR:
25134 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
25135 break;
25136
25137 case HBAR_CURSOR:
25138 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
25139 break;
25140
25141 case NO_CURSOR:
25142 w->phys_cursor_width = 0;
25143 break;
25144
25145 default:
25146 emacs_abort ();
25147 }
25148 }
25149
25150 #ifdef HAVE_X_I18N
25151 if (w == XWINDOW (f->selected_window))
25152 xic_set_preeditarea (w, x, y);
25153 #endif
25154 }
25155 }
25156
25157
25158
25159
25160
25161
25162 static bool
25163 x_bitmap_icon (struct frame *f, Lisp_Object file)
25164 {
25165 ptrdiff_t bitmap_id;
25166
25167 if (FRAME_X_WINDOW (f) == 0)
25168 return true;
25169
25170
25171 if (f->output_data.x->icon_bitmap > 0)
25172 image_destroy_bitmap (f, f->output_data.x->icon_bitmap);
25173 f->output_data.x->icon_bitmap = 0;
25174
25175 if (STRINGP (file))
25176 {
25177 #ifdef USE_GTK
25178
25179
25180 if (xg_set_icon (f, file))
25181 return false;
25182 #endif
25183 bitmap_id = image_create_bitmap_from_file (f, file);
25184 x_create_bitmap_mask (f, bitmap_id);
25185 }
25186 else
25187 {
25188
25189 if (FRAME_DISPLAY_INFO (f)->icon_bitmap_id < 0)
25190 {
25191 ptrdiff_t rc = -1;
25192
25193 #ifdef USE_GTK
25194
25195 if (xg_set_icon (f, xg_default_icon_file)
25196 || xg_set_icon_from_xpm_data (f, gnu_xpm_bits))
25197 {
25198 FRAME_DISPLAY_INFO (f)->icon_bitmap_id = -2;
25199 return false;
25200 }
25201
25202 #elif defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
25203
25204 if ((FRAME_X_VISUAL_INFO (f)->class == TrueColor
25205 || FRAME_X_VISUAL_INFO (f)->class == StaticColor
25206 || FRAME_X_VISUAL_INFO (f)->class == StaticGray)
25207
25208
25209
25210 || FRAME_X_VISUAL_INFO (f)->colormap_size >= (240 * 4))
25211 {
25212 rc = x_create_bitmap_from_xpm_data (f, gnu_xpm_bits);
25213 if (rc != -1)
25214 FRAME_DISPLAY_INFO (f)->icon_bitmap_id = rc;
25215 }
25216 #endif
25217
25218
25219 if (rc == -1)
25220 {
25221 rc = image_create_bitmap_from_data (f,
25222 (char *) gnu_xbm_bits,
25223 gnu_xbm_width,
25224 gnu_xbm_height);
25225 if (rc == -1)
25226 return true;
25227
25228 FRAME_DISPLAY_INFO (f)->icon_bitmap_id = rc;
25229 x_create_bitmap_mask (f, FRAME_DISPLAY_INFO (f)->icon_bitmap_id);
25230 }
25231 }
25232
25233
25234
25235
25236
25237 image_reference_bitmap (f, FRAME_DISPLAY_INFO (f)->icon_bitmap_id);
25238
25239 bitmap_id = FRAME_DISPLAY_INFO (f)->icon_bitmap_id;
25240 }
25241
25242 x_wm_set_icon_pixmap (f, bitmap_id);
25243 f->output_data.x->icon_bitmap = bitmap_id;
25244
25245 return false;
25246 }
25247
25248
25249
25250
25251
25252 bool
25253 x_text_icon (struct frame *f, const char *icon_name)
25254 {
25255 if (FRAME_X_WINDOW (f) == 0)
25256 return true;
25257
25258 {
25259 XTextProperty text;
25260 text.value = (unsigned char *) icon_name;
25261 text.encoding = XA_STRING;
25262 text.format = 8;
25263 text.nitems = strlen (icon_name);
25264 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text);
25265 }
25266
25267 if (f->output_data.x->icon_bitmap > 0)
25268 image_destroy_bitmap (f, f->output_data.x->icon_bitmap);
25269 f->output_data.x->icon_bitmap = 0;
25270 x_wm_set_icon_pixmap (f, 0);
25271
25272 return false;
25273 }
25274
25275
25276 struct x_error_message_stack
25277 {
25278
25279
25280 char *string;
25281
25282
25283 Display *dpy;
25284
25285
25286 x_special_error_handler handler;
25287
25288
25289 void *handler_data;
25290
25291
25292 struct x_error_message_stack *prev;
25293
25294
25295
25296
25297 unsigned long first_request;
25298 };
25299
25300
25301
25302
25303
25304
25305
25306
25307
25308 static struct x_error_message_stack *x_error_message;
25309
25310
25311 int x_error_message_count;
25312
25313
25314
25315
25316
25317
25318
25319 static bool
25320 x_is_serial_more_than (unsigned int a, unsigned int b)
25321 {
25322 if (a > b)
25323 return true;
25324
25325 return (b - a > X_ULONG_MAX / 2);
25326 }
25327
25328 static bool
25329 x_is_serial_more_than_or_equal_to (unsigned int a, unsigned int b)
25330 {
25331 if (a >= b)
25332 return true;
25333
25334 return (b - a > X_ULONG_MAX / 2);
25335 }
25336
25337 static bool
25338 x_is_serial_less_than (unsigned int a, unsigned int b)
25339 {
25340 if (a < b)
25341 return true;
25342
25343 return (a - b > X_ULONG_MAX / 2);
25344 }
25345
25346 static bool
25347 x_is_serial_less_than_or_equal_to (unsigned int a, unsigned int b)
25348 {
25349 if (a <= b)
25350 return true;
25351
25352 return (a - b > X_ULONG_MAX / 2);
25353 }
25354
25355 static struct x_error_message_stack *
25356 x_find_error_handler (Display *dpy, XErrorEvent *event)
25357 {
25358 struct x_error_message_stack *stack;
25359
25360 stack = x_error_message;
25361
25362 while (stack)
25363 {
25364 if (x_is_serial_more_than_or_equal_to (event->serial,
25365 stack->first_request)
25366 && dpy == stack->dpy)
25367 return stack;
25368
25369 stack = stack->prev;
25370 }
25371
25372 return NULL;
25373 }
25374
25375 void
25376 x_unwind_errors_to (int depth)
25377 {
25378 while (x_error_message_count > depth)
25379
25380
25381 x_uncatch_errors ();
25382 }
25383
25384 #define X_ERROR_MESSAGE_SIZE 200
25385
25386
25387
25388
25389
25390
25391 static void
25392 x_error_catcher (Display *display, XErrorEvent *event,
25393 struct x_error_message_stack *stack)
25394 {
25395 char buf[X_ERROR_MESSAGE_SIZE];
25396
25397 XGetErrorText (display, event->error_code,
25398 buf, X_ERROR_MESSAGE_SIZE);
25399
25400 if (stack->string)
25401 xfree (stack->string);
25402
25403 stack->string = xstrdup (buf);
25404
25405 if (stack->handler)
25406 stack->handler (display, event, stack->string,
25407 stack->handler_data);
25408 }
25409
25410
25411
25412
25413
25414
25415
25416
25417
25418
25419
25420
25421
25422
25423
25424
25425
25426
25427
25428
25429
25430
25431
25432
25433 void
25434 x_catch_errors_with_handler (Display *dpy, x_special_error_handler handler,
25435 void *handler_data)
25436 {
25437 struct x_error_message_stack *data;
25438
25439 data = xzalloc (sizeof *data);
25440 data->dpy = dpy;
25441 data->handler = handler;
25442 data->handler_data = handler_data;
25443 data->prev = x_error_message;
25444 data->first_request = XNextRequest (dpy);
25445 x_error_message = data;
25446
25447 ++x_error_message_count;
25448 }
25449
25450 void
25451 x_catch_errors (Display *dpy)
25452 {
25453 x_catch_errors_with_handler (dpy, NULL, NULL);
25454 }
25455
25456
25457
25458 static struct x_failable_request *
25459 x_request_can_fail (struct x_display_info *dpyinfo,
25460 unsigned long request)
25461 {
25462 struct x_failable_request *failable_requests;
25463
25464 for (failable_requests = dpyinfo->failable_requests;
25465 failable_requests < dpyinfo->next_failable_request;
25466 failable_requests++)
25467 {
25468 if (x_is_serial_more_than_or_equal_to (request,
25469 failable_requests->start)
25470 && (!failable_requests->end
25471 || x_is_serial_less_than_or_equal_to (request,
25472 failable_requests->end)))
25473 return failable_requests;
25474 }
25475
25476 return NULL;
25477 }
25478
25479
25480
25481 static void
25482 x_clean_failable_requests (struct x_display_info *dpyinfo)
25483 {
25484 struct x_failable_request *first, *last;
25485
25486 last = dpyinfo->next_failable_request;
25487
25488 for (first = dpyinfo->failable_requests; first < last; first++)
25489 {
25490 if (x_is_serial_more_than (first->start,
25491 LastKnownRequestProcessed (dpyinfo->display))
25492 || !first->end
25493 || x_is_serial_more_than (first->end,
25494 LastKnownRequestProcessed (dpyinfo->display)))
25495 break;
25496 }
25497
25498 if (first != last)
25499 memmove (&dpyinfo->failable_requests, first,
25500 sizeof *first * (last - first));
25501
25502 dpyinfo->next_failable_request = (dpyinfo->failable_requests
25503 + (last - first));
25504 }
25505
25506
25507
25508
25509
25510
25511
25512
25513
25514
25515
25516
25517 void
25518 x_ignore_errors_for_next_request (struct x_display_info *dpyinfo)
25519 {
25520 struct x_failable_request *request, *max;
25521 unsigned long next_request;
25522 #ifdef HAVE_GTK3
25523 GdkDisplay *gdpy;
25524 #endif
25525
25526
25527
25528 block_input ();
25529
25530 #ifdef HAVE_GTK3
25531
25532
25533
25534
25535
25536 gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display);
25537
25538 if (gdpy)
25539 gdk_x11_display_error_trap_push (gdpy);
25540 #endif
25541
25542 if ((dpyinfo->next_failable_request
25543 != dpyinfo->failable_requests)
25544 && (dpyinfo->next_failable_request - 1)->end == 0)
25545
25546
25547 emacs_abort ();
25548
25549 request = dpyinfo->next_failable_request;
25550 max = dpyinfo->failable_requests + N_FAILABLE_REQUESTS;
25551 next_request = XNextRequest (dpyinfo->display);
25552
25553 if (request >= max)
25554 {
25555
25556
25557 if ((LastKnownRequestProcessed (dpyinfo->display)
25558 != next_request - 1))
25559 XSync (dpyinfo->display, False);
25560
25561 x_clean_failable_requests (dpyinfo);
25562 request = dpyinfo->next_failable_request;
25563 }
25564
25565 if (request >= max)
25566
25567
25568 emacs_abort ();
25569
25570 request->start = next_request;
25571 request->end = 0;
25572
25573 dpyinfo->next_failable_request++;
25574 }
25575
25576 void
25577 x_stop_ignoring_errors (struct x_display_info *dpyinfo)
25578 {
25579 struct x_failable_request *range;
25580 #ifdef HAVE_GTK3
25581 GdkDisplay *gdpy;
25582 #endif
25583
25584 range = dpyinfo->next_failable_request - 1;
25585 range->end = XNextRequest (dpyinfo->display) - 1;
25586
25587
25588
25589
25590 if (x_is_serial_less_than (range->end, range->start))
25591 emacs_abort ();
25592
25593 #ifdef HAVE_GTK3
25594 gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display);
25595
25596 if (gdpy)
25597 gdk_x11_display_error_trap_pop_ignored (gdpy);
25598 #endif
25599
25600 unblock_input ();
25601 }
25602
25603
25604
25605
25606
25607
25608
25609
25610 void
25611 x_uncatch_errors_after_check (void)
25612 {
25613 struct x_error_message_stack *tmp;
25614
25615 block_input ();
25616 tmp = x_error_message;
25617 x_error_message = x_error_message->prev;
25618 --x_error_message_count;
25619 if (tmp->string)
25620 xfree (tmp->string);
25621 xfree (tmp);
25622 unblock_input ();
25623 }
25624
25625
25626
25627 void
25628 x_uncatch_errors (void)
25629 {
25630 struct x_error_message_stack *tmp;
25631 struct x_display_info *dpyinfo;
25632
25633
25634
25635
25636
25637 if (x_error_message == NULL)
25638 return;
25639
25640 block_input ();
25641
25642 dpyinfo = x_display_info_for_display (x_error_message->dpy);
25643
25644
25645
25646 if (dpyinfo != 0
25647
25648
25649 && (LastKnownRequestProcessed (x_error_message->dpy)
25650 != XNextRequest (x_error_message->dpy) - 1)
25651
25652
25653 && (NextRequest (x_error_message->dpy)
25654 > x_error_message->first_request))
25655 {
25656 XSync (x_error_message->dpy, False);
25657 x_clean_failable_requests (dpyinfo);
25658 }
25659
25660 tmp = x_error_message;
25661 x_error_message = x_error_message->prev;
25662 --x_error_message_count;
25663 if (tmp->string)
25664 xfree (tmp->string);
25665 xfree (tmp);
25666 unblock_input ();
25667 }
25668
25669
25670
25671
25672
25673 void
25674 x_check_errors (Display *dpy, const char *format)
25675 {
25676 struct x_display_info *dpyinfo;
25677 char *string;
25678
25679
25680
25681 if (dpy != x_error_message->dpy)
25682 emacs_abort ();
25683
25684
25685
25686 if ((LastKnownRequestProcessed (dpy)
25687 != XNextRequest (dpy) - 1)
25688 && (NextRequest (dpy)
25689 > x_error_message->first_request))
25690 XSync (dpy, False);
25691
25692 dpyinfo = x_display_info_for_display (dpy);
25693
25694
25695 if (dpyinfo)
25696 x_clean_failable_requests (dpyinfo);
25697
25698 if (x_error_message->string)
25699 {
25700 string = alloca (strlen (x_error_message->string) + 1);
25701 strcpy (string, x_error_message->string);
25702
25703 error (format, string);
25704 }
25705 }
25706
25707
25708
25709
25710 bool
25711 x_had_errors_p (Display *dpy)
25712 {
25713 struct x_display_info *dpyinfo;
25714
25715
25716
25717 if (dpy != x_error_message->dpy)
25718 emacs_abort ();
25719
25720
25721 if ((LastKnownRequestProcessed (dpy)
25722 != XNextRequest (dpy) - 1)
25723 && (NextRequest (dpy)
25724 > x_error_message->first_request))
25725 XSync (dpy, False);
25726
25727 dpyinfo = x_display_info_for_display (dpy);
25728
25729
25730 if (dpyinfo)
25731 x_clean_failable_requests (dpyinfo);
25732
25733 return !!x_error_message->string;
25734 }
25735
25736
25737
25738
25739 void
25740 x_clear_errors (Display *dpy)
25741 {
25742
25743
25744 if (dpy != x_error_message->dpy)
25745 emacs_abort ();
25746
25747 xfree (x_error_message->string);
25748 x_error_message->string = NULL;
25749 }
25750
25751 #if false
25752
25753
25754
25755
25756 void
25757 x_fully_uncatch_errors (void)
25758 {
25759 while (x_error_message)
25760 x_uncatch_errors ();
25761 }
25762 #endif
25763
25764 #if false
25765 static unsigned int x_wire_count;
25766
25767 static int
25768 x_trace_wire (Display *dpy)
25769 {
25770 fprintf (stderr, "Lib call: %u\n", ++x_wire_count);
25771 return 0;
25772 }
25773 #endif
25774
25775
25776
25777
25778
25779
25780
25781
25782 static char *error_msg;
25783
25784
25785
25786
25787
25788 static void
25789 x_try_restore_frame (void)
25790 {
25791 Lisp_Object tail, frame;
25792
25793 FOR_EACH_FRAME (tail, frame)
25794 {
25795 if (!NILP (do_switch_frame (frame, 0, 1, Qnil)))
25796 return;
25797 }
25798 }
25799
25800
25801
25802
25803 static void
25804 x_connection_closed (Display *dpy, const char *error_message, bool ioerror)
25805 {
25806 struct x_display_info *dpyinfo;
25807 Lisp_Object frame, tail;
25808 specpdl_ref idx = SPECPDL_INDEX ();
25809 Emacs_XIOErrorHandler io_error_handler;
25810 xm_drop_start_message dmsg;
25811 struct frame *f;
25812 Lisp_Object minibuf_frame, tmp;
25813 struct x_failable_request *failable;
25814 struct x_error_message_stack *stack;
25815 static Display *current_display;
25816
25817
25818
25819
25820 if (current_display == dpy)
25821 return;
25822
25823 current_display = dpy;
25824
25825 dpyinfo = x_display_info_for_display (dpy);
25826 error_msg = alloca (strlen (error_message) + 1);
25827 strcpy (error_msg, error_message);
25828
25829
25830 specbind (Qinhibit_redisplay, Qt);
25831
25832
25833
25834
25835
25836
25837 if (x_dnd_in_progress || x_dnd_waiting_for_finish)
25838 {
25839 if (!ioerror)
25840 {
25841
25842
25843 io_error_handler = XSetIOErrorHandler (x_dnd_io_error_handler);
25844
25845 if (!!sigsetjmp (x_dnd_disconnect_handler, 1)
25846 && x_dnd_in_progress
25847 && dpy == (x_dnd_waiting_for_finish
25848 ? x_dnd_finish_display
25849 : FRAME_X_DISPLAY (x_dnd_frame)))
25850 {
25851
25852
25853 f = x_dnd_frame;
25854
25855 if (x_dnd_last_seen_window != None
25856 && x_dnd_last_protocol_version != -1)
25857 x_dnd_send_leave (x_dnd_frame,
25858 x_dnd_last_seen_window,
25859 x_dnd_last_seen_toplevel);
25860 else if (x_dnd_last_seen_window != None
25861 && !XM_DRAG_STYLE_IS_DROP_ONLY (x_dnd_last_motif_style)
25862 && x_dnd_last_motif_style != XM_DRAG_STYLE_NONE
25863 && x_dnd_motif_setup_p)
25864 {
25865 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
25866 XM_DRAG_REASON_DROP_START);
25867 dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST;
25868 dmsg.timestamp = FRAME_DISPLAY_INFO (f)->last_user_time;
25869 dmsg.side_effects
25870 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f),
25871 x_dnd_wanted_action),
25872 XM_DROP_SITE_VALID, x_dnd_motif_operations,
25873 XM_DROP_ACTION_DROP_CANCEL);
25874 dmsg.x = 0;
25875 dmsg.y = 0;
25876 dmsg.index_atom = x_dnd_motif_atom;
25877 dmsg.source_window = FRAME_X_WINDOW (f);
25878
25879 x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f,
25880 x_dnd_last_seen_window, 0);
25881 xm_send_drop_message (FRAME_DISPLAY_INFO (f), FRAME_X_WINDOW (f),
25882 x_dnd_last_seen_window, &dmsg);
25883 }
25884 }
25885
25886 XSetIOErrorHandler (io_error_handler);
25887 }
25888
25889 dpyinfo = x_display_info_for_display (dpy);
25890
25891 x_dnd_last_seen_window = None;
25892 x_dnd_last_seen_toplevel = None;
25893 x_dnd_in_progress = false;
25894 x_dnd_waiting_for_finish = false;
25895
25896 if (x_dnd_use_toplevels)
25897 x_dnd_free_toplevels (!ioerror);
25898
25899 x_dnd_return_frame_object = NULL;
25900 x_dnd_movement_frame = NULL;
25901 x_dnd_wheel_frame = NULL;
25902 x_dnd_frame = NULL;
25903 }
25904
25905 if (dpyinfo)
25906 {
25907
25908
25909 dpyinfo->reference_count++;
25910 dpyinfo->terminal->reference_count++;
25911 if (ioerror)
25912 dpyinfo->display = 0;
25913 }
25914
25915
25916
25917
25918
25919 block_input ();
25920
25921
25922
25923 FOR_EACH_FRAME (tail, frame)
25924 {
25925
25926
25927 if (FRAME_TOOLTIP_P (XFRAME (frame)))
25928 continue;
25929
25930 minibuf_frame
25931 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
25932
25933 if (FRAME_X_P (XFRAME (frame))
25934 && FRAME_X_P (XFRAME (minibuf_frame))
25935 && ! EQ (frame, minibuf_frame)
25936 && FRAME_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
25937 delete_frame (frame, Qnoelisp);
25938 }
25939
25940
25941
25942
25943 FOR_EACH_FRAME (tail, frame)
25944 if (FRAME_X_P (XFRAME (frame))
25945 && FRAME_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
25946 {
25947
25948
25949 kset_default_minibuffer_frame (FRAME_KBOARD (XFRAME (frame)), Qt);
25950 delete_frame (frame, Qnoelisp);
25951 }
25952
25953
25954
25955 if (dpyinfo)
25956 {
25957
25958
25959
25960 #ifdef USE_GTK
25961
25962
25963
25964
25965 shut_down_emacs (0, Qnil);
25966 fprintf (stderr, "%s\n\
25967 When compiled with GTK, Emacs cannot recover from X disconnects.\n\
25968 This is a GTK bug: https://gitlab.gnome.org/GNOME/gtk/issues/221\n\
25969 For details, see etc/PROBLEMS.\n",
25970 error_msg);
25971 emacs_abort ();
25972 #endif
25973
25974
25975 dpyinfo->display = 0;
25976
25977 dpyinfo->reference_count--;
25978 dpyinfo->terminal->reference_count--;
25979 if (dpyinfo->reference_count != 0)
25980
25981 emacs_abort ();
25982
25983
25984
25985 if (dpyinfo->terminal == terminal_list
25986 && !terminal_list->next_terminal)
25987 {
25988 fprintf (stderr, "%s\n", error_msg);
25989
25990 if (!ioerror && dpyinfo)
25991 {
25992
25993
25994
25995 fprintf (stderr, "X error handlers currently installed:\n");
25996
25997 for (failable = dpyinfo->failable_requests;
25998 failable < dpyinfo->next_failable_request;
25999 ++failable)
26000 {
26001 if (failable->end)
26002 fprintf (stderr, "Ignoring errors between %lu to %lu\n",
26003 failable->start, failable->end);
26004 else
26005 fprintf (stderr, "Ignoring errors from %lu onwards\n",
26006 failable->start);
26007 }
26008
26009 for (stack = x_error_message; stack; stack = stack->prev)
26010 fprintf (stderr, "Trapping errors from %lu\n",
26011 stack->first_request);
26012 }
26013 }
26014
26015 XSETTERMINAL (tmp, dpyinfo->terminal);
26016 Fdelete_terminal (tmp, Qnoelisp);
26017 }
26018
26019
26020
26021 if (NILP (selected_frame))
26022 x_try_restore_frame ();
26023
26024 unblock_input ();
26025
26026
26027
26028
26029
26030 if (terminal_list == 0 || NILP (selected_frame))
26031 Fkill_emacs (make_fixnum (70), Qnil);
26032
26033 totally_unblock_input ();
26034
26035 unbind_to (idx, Qnil);
26036 clear_waiting_for_input ();
26037
26038
26039
26040
26041 current_display = NULL;
26042 error ("%s", error_msg);
26043 }
26044
26045 static void x_error_quitter (Display *, XErrorEvent *);
26046
26047
26048
26049
26050 static int
26051 x_error_handler (Display *display, XErrorEvent *event)
26052 {
26053 struct x_error_message_stack *stack;
26054 struct x_display_info *dpyinfo;
26055 struct x_failable_request *fail, *last;
26056
26057 #if defined USE_GTK && defined HAVE_GTK3
26058 if ((event->error_code == BadMatch
26059 || event->error_code == BadWindow)
26060 && event->request_code == X_SetInputFocus)
26061 return 0;
26062 #endif
26063
26064 dpyinfo = x_display_info_for_display (display);
26065
26066 if (dpyinfo)
26067 {
26068 fail = x_request_can_fail (dpyinfo, event->serial);
26069
26070 if (fail)
26071 {
26072
26073
26074
26075 if (event->serial == fail->end)
26076 {
26077 last = dpyinfo->next_failable_request;
26078 memmove (&dpyinfo->failable_requests, fail,
26079 sizeof *fail * (last - fail));
26080 dpyinfo->next_failable_request = (dpyinfo->failable_requests
26081 + (last - fail));
26082 }
26083
26084 return 0;
26085 }
26086 }
26087
26088
26089
26090
26091 #ifdef HAVE_XINPUT2
26092
26093
26094 if (dpyinfo && dpyinfo->supports_xi2
26095 && event->request_code == dpyinfo->xi2_opcode
26096 && (event->minor_code == X_XIGrabDevice
26097 || event->minor_code == X_XIUngrabDevice
26098 || event->minor_code == X_XIAllowEvents))
26099 return 0;
26100 #endif
26101
26102 stack = x_find_error_handler (display, event);
26103
26104 if (stack)
26105 x_error_catcher (display, event, stack);
26106 else
26107 x_error_quitter (display, event);
26108 return 0;
26109 }
26110
26111
26112
26113
26114
26115
26116
26117 static void NO_INLINE
26118 x_error_quitter (Display *display, XErrorEvent *event)
26119 {
26120 char buf[256], buf1[400 + INT_STRLEN_BOUND (int)
26121 + INT_STRLEN_BOUND (unsigned long)];
26122
26123
26124
26125
26126 if (event->error_code == BadName)
26127 return;
26128
26129
26130
26131
26132 XGetErrorText (display, event->error_code, buf, sizeof (buf));
26133 sprintf (buf1, "X protocol error: %s on protocol request %d\n"
26134 "Serial no: %lu\n", buf, event->request_code,
26135 event->serial);
26136 x_connection_closed (display, buf1, false);
26137 }
26138
26139
26140
26141
26142
26143
26144 static int NO_INLINE
26145 x_io_error_quitter (Display *display)
26146 {
26147 char buf[256];
26148
26149 snprintf (buf, sizeof buf, "Connection lost to X server '%s'",
26150 DisplayString (display));
26151 x_connection_closed (display, buf, true);
26152
26153 return 0;
26154 }
26155
26156
26157
26158
26159
26160
26161
26162
26163
26164 static Lisp_Object
26165 x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
26166 {
26167 struct font *font = XFONT_OBJECT (font_object);
26168 int unit, font_ascent, font_descent;
26169
26170 if (fontset < 0)
26171 fontset = fontset_from_font (font_object);
26172 FRAME_FONTSET (f) = fontset;
26173 if (FRAME_FONT (f) == font)
26174
26175
26176 return font_object;
26177
26178 FRAME_FONT (f) = font;
26179 FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
26180 FRAME_COLUMN_WIDTH (f) = font->average_width;
26181 get_font_ascent_descent (font, &font_ascent, &font_descent);
26182 FRAME_LINE_HEIGHT (f) = font_ascent + font_descent;
26183
26184 #ifndef USE_X_TOOLKIT
26185 FRAME_MENU_BAR_HEIGHT (f) = FRAME_MENU_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
26186 #endif
26187
26188 FRAME_TAB_BAR_HEIGHT (f) = FRAME_TAB_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
26189
26190
26191
26192
26193
26194 unit = FRAME_COLUMN_WIDTH (f);
26195 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
26196 FRAME_CONFIG_SCROLL_BAR_COLS (f)
26197 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + unit - 1) / unit;
26198 else
26199 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit;
26200
26201
26202
26203
26204
26205 if (FRAME_X_WINDOW (f) != 0 && !FRAME_TOOLTIP_P (f))
26206 adjust_frame_size
26207 (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
26208 FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3, false, Qfont);
26209
26210 #ifdef HAVE_X_I18N
26211 if (FRAME_XIC (f)
26212 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
26213 {
26214 block_input ();
26215 xic_set_xfontset (f, SSDATA (fontset_ascii (fontset)));
26216 unblock_input ();
26217 }
26218 #endif
26219
26220 return font_object;
26221 }
26222
26223
26224
26225
26226
26227
26228 #ifdef HAVE_X_I18N
26229
26230 #ifdef HAVE_X11R6
26231
26232
26233
26234
26235
26236
26237
26238 #ifdef HAVE_X11R6_XIM
26239
26240
26241
26242
26243
26244
26245
26246 static void
26247 x_maybe_clear_preedit (struct frame *f)
26248 {
26249 struct x_output *output;
26250 struct input_event ie;
26251
26252 output = FRAME_X_OUTPUT (f);
26253
26254 if (!output->preedit_chars)
26255 return;
26256
26257 EVENT_INIT (ie);
26258 ie.kind = PREEDIT_TEXT_EVENT;
26259 ie.arg = Qnil;
26260 XSETFRAME (ie.frame_or_window, f);
26261 XSETINT (ie.x, 0);
26262 XSETINT (ie.y, 0);
26263 kbd_buffer_store_event (&ie);
26264
26265 xfree (output->preedit_chars);
26266
26267 output->preedit_size = 0;
26268 output->preedit_active = false;
26269 output->preedit_chars = NULL;
26270 output->preedit_caret = 0;
26271 }
26272
26273
26274
26275
26276
26277 static void
26278 xim_destroy_callback (XIM xim, XPointer client_data, XPointer call_data)
26279 {
26280 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
26281 Lisp_Object frame, tail;
26282
26283 block_input ();
26284
26285
26286 FOR_EACH_FRAME (tail, frame)
26287 {
26288 struct frame *f = XFRAME (frame);
26289 if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) == dpyinfo)
26290 {
26291 FRAME_XIC (f) = NULL;
26292 xic_free_xfontset (f);
26293
26294
26295 x_maybe_clear_preedit (f);
26296 }
26297 }
26298
26299
26300 dpyinfo->xim = NULL;
26301 XFree (dpyinfo->xim_styles);
26302 unblock_input ();
26303 }
26304
26305 #endif
26306
26307 #endif
26308
26309
26310
26311
26312 static void
26313 xim_open_dpy (struct x_display_info *dpyinfo, char *resource_name)
26314 {
26315 #ifdef HAVE_XIM
26316 XIM xim;
26317 const char *locale;
26318
26319 if (use_xim)
26320 {
26321 if (dpyinfo->xim)
26322 XCloseIM (dpyinfo->xim);
26323 xim = XOpenIM (dpyinfo->display, dpyinfo->rdb, resource_name,
26324 emacs_class);
26325 dpyinfo->xim = xim;
26326
26327 if (xim)
26328 {
26329 #ifdef HAVE_X11R6_XIM
26330 XIMCallback destroy;
26331 #endif
26332
26333
26334 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
26335
26336 #ifdef HAVE_X11R6_XIM
26337 destroy.callback = xim_destroy_callback;
26338 destroy.client_data = (XPointer)dpyinfo;
26339 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
26340 #endif
26341
26342 locale = XLocaleOfIM (xim);
26343
26344
26345
26346
26347 dpyinfo->xim_coding = safe_call1 (Vx_input_coding_function,
26348 build_string (locale));
26349 }
26350 }
26351
26352 else
26353 #endif
26354 dpyinfo->xim = NULL;
26355 }
26356
26357
26358 #ifdef HAVE_X11R6_XIM
26359
26360
26361
26362
26363
26364
26365 static void
26366 xim_instantiate_callback (Display *display, XPointer client_data, XPointer call_data)
26367 {
26368 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
26369 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
26370
26371 if (x_dnd_in_progress)
26372 return;
26373
26374
26375 if (dpyinfo->xim)
26376 return;
26377
26378 xim_open_dpy (dpyinfo, xim_inst->resource_name);
26379
26380
26381
26382 if (dpyinfo->xim && dpyinfo->reference_count > 0)
26383 {
26384 Lisp_Object tail, frame;
26385
26386 block_input ();
26387 FOR_EACH_FRAME (tail, frame)
26388 {
26389 struct frame *f = XFRAME (frame);
26390
26391 if (FRAME_X_P (f)
26392 && FRAME_DISPLAY_INFO (f) == xim_inst->dpyinfo)
26393 if (FRAME_XIC (f) == NULL)
26394 {
26395 create_frame_xic (f);
26396 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
26397 xic_set_statusarea (f);
26398 struct window *w = XWINDOW (f->selected_window);
26399 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
26400 }
26401 }
26402
26403 unblock_input ();
26404 }
26405 }
26406
26407 #endif
26408
26409
26410
26411
26412
26413
26414
26415 static void
26416 xim_initialize (struct x_display_info *dpyinfo, char *resource_name)
26417 {
26418 dpyinfo->xim = NULL;
26419 #ifdef HAVE_XIM
26420 if (use_xim)
26421 {
26422 #ifdef HAVE_X11R6_XIM
26423 struct xim_inst_t *xim_inst = xmalloc (sizeof *xim_inst);
26424 Bool ret;
26425
26426 dpyinfo->xim_callback_data = xim_inst;
26427 xim_inst->dpyinfo = dpyinfo;
26428 xim_inst->resource_name = xstrdup (resource_name);
26429 ret = XRegisterIMInstantiateCallback
26430 (dpyinfo->display, dpyinfo->rdb, xim_inst->resource_name,
26431 emacs_class, xim_instantiate_callback,
26432
26433
26434
26435
26436 (void *) xim_inst);
26437 eassert (ret == True);
26438 #else
26439 xim_open_dpy (dpyinfo, resource_name);
26440 #endif
26441 }
26442 #endif
26443 }
26444
26445
26446
26447
26448 static void
26449 xim_close_dpy (struct x_display_info *dpyinfo)
26450 {
26451 #ifdef HAVE_XIM
26452 if (use_xim)
26453 {
26454 #ifdef HAVE_X11R6_XIM
26455 struct xim_inst_t *xim_inst = dpyinfo->xim_callback_data;
26456
26457 if (dpyinfo->display)
26458 {
26459 Bool ret = XUnregisterIMInstantiateCallback
26460 (dpyinfo->display, dpyinfo->rdb, xim_inst->resource_name,
26461 emacs_class, xim_instantiate_callback, (void *) xim_inst);
26462 eassert (ret == True);
26463 }
26464 xfree (xim_inst->resource_name);
26465 xfree (xim_inst);
26466 #endif
26467 if (dpyinfo->display)
26468 XCloseIM (dpyinfo->xim);
26469 dpyinfo->xim = NULL;
26470 XFree (dpyinfo->xim_styles);
26471 }
26472 #endif
26473 }
26474
26475 #endif
26476
26477
26478
26479
26480
26481
26482 static void
26483 x_calc_absolute_position (struct frame *f)
26484 {
26485 int flags = f->size_hint_flags;
26486 struct frame *p = FRAME_PARENT_FRAME (f);
26487
26488
26489
26490 if (! ((flags & XNegative) || (flags & YNegative)))
26491 return;
26492
26493
26494
26495 if ((flags & XNegative) && (f->left_pos <= 0))
26496 {
26497 int width = FRAME_PIXEL_WIDTH (f);
26498
26499
26500
26501 if (f->output_data.x->has_been_visible && !p)
26502 {
26503 Lisp_Object frame;
26504 Lisp_Object edges = Qnil;
26505
26506 XSETFRAME (frame, f);
26507 edges = Fx_frame_edges (frame, Qouter_edges);
26508 if (!NILP (edges))
26509 width = (XFIXNUM (Fnth (make_fixnum (2), edges))
26510 - XFIXNUM (Fnth (make_fixnum (0), edges)));
26511 }
26512
26513 if (p)
26514 f->left_pos = (FRAME_PIXEL_WIDTH (p) - width - 2 * f->border_width
26515 + f->left_pos);
26516 else
26517 f->left_pos = (x_display_pixel_width (FRAME_DISPLAY_INFO (f))
26518 - width + f->left_pos);
26519
26520 }
26521
26522 if ((flags & YNegative) && (f->top_pos <= 0))
26523 {
26524 int height = FRAME_PIXEL_HEIGHT (f);
26525
26526 #if defined USE_X_TOOLKIT && defined USE_MOTIF
26527
26528
26529
26530
26531
26532
26533
26534
26535
26536
26537
26538
26539 XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
26540 #endif
26541
26542 if (f->output_data.x->has_been_visible && !p)
26543 {
26544 Lisp_Object frame;
26545 Lisp_Object edges = Qnil;
26546
26547 XSETFRAME (frame, f);
26548 if (NILP (edges))
26549 edges = Fx_frame_edges (frame, Qouter_edges);
26550 if (!NILP (edges))
26551 height = (XFIXNUM (Fnth (make_fixnum (3), edges))
26552 - XFIXNUM (Fnth (make_fixnum (1), edges)));
26553 }
26554
26555 if (p)
26556 f->top_pos = (FRAME_PIXEL_HEIGHT (p) - height - 2 * f->border_width
26557 + f->top_pos);
26558 else
26559 f->top_pos = (x_display_pixel_height (FRAME_DISPLAY_INFO (f))
26560 - height + f->top_pos);
26561 }
26562
26563
26564
26565
26566 f->size_hint_flags &= ~ (XNegative | YNegative);
26567 }
26568
26569
26570
26571
26572
26573
26574
26575 static void
26576 x_set_offset (struct frame *f, int xoff, int yoff, int change_gravity)
26577 {
26578 int modified_top, modified_left;
26579 #ifdef USE_GTK
26580 int scale = xg_get_scale (f);
26581 #endif
26582
26583 if (change_gravity > 0)
26584 {
26585 f->top_pos = yoff;
26586 f->left_pos = xoff;
26587 f->size_hint_flags &= ~ (XNegative | YNegative);
26588 if (xoff < 0)
26589 f->size_hint_flags |= XNegative;
26590 if (yoff < 0)
26591 f->size_hint_flags |= YNegative;
26592 f->win_gravity = NorthWestGravity;
26593 }
26594
26595 x_calc_absolute_position (f);
26596
26597 block_input ();
26598 x_wm_set_size_hint (f, 0, false);
26599
26600 #ifdef USE_GTK
26601 if (x_gtk_use_window_move)
26602 {
26603
26604
26605
26606
26607 if (change_gravity != 0 && FRAME_GTK_OUTER_WIDGET (f))
26608 gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
26609 f->left_pos / scale, f->top_pos / scale);
26610 unblock_input ();
26611 return;
26612 }
26613 #endif
26614
26615 modified_left = f->left_pos;
26616 modified_top = f->top_pos;
26617
26618 if (change_gravity != 0 && FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A)
26619 {
26620
26621
26622
26623 modified_left += FRAME_X_OUTPUT (f)->move_offset_left;
26624 modified_top += FRAME_X_OUTPUT (f)->move_offset_top;
26625 }
26626
26627 #ifdef USE_GTK
26628
26629 gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
26630 modified_left / scale, modified_top / scale);
26631 #else
26632 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
26633 modified_left, modified_top);
26634 #endif
26635
26636
26637 if (!FRAME_PARENT_FRAME (f)
26638
26639
26640
26641 && NILP (Vx_no_window_manager))
26642 {
26643 x_sync_with_move (f, f->left_pos, f->top_pos,
26644 FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN);
26645
26646
26647
26648
26649
26650
26651
26652
26653
26654
26655
26656 if (change_gravity != 0
26657 && (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
26658 || (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A
26659 && (FRAME_X_OUTPUT (f)->move_offset_left == 0
26660 && FRAME_X_OUTPUT (f)->move_offset_top == 0))))
26661 x_check_expected_move (f, modified_left, modified_top);
26662 }
26663
26664
26665
26666 else
26667 XSync (FRAME_X_DISPLAY (f), False);
26668
26669 unblock_input ();
26670 }
26671
26672 static Window
26673 x_get_wm_check_window (struct x_display_info *dpyinfo)
26674 {
26675 Window result;
26676 unsigned char *tmp_data = NULL;
26677 int rc, actual_format;
26678 unsigned long actual_size, bytes_remaining;
26679 Atom actual_type;
26680
26681 rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window,
26682 dpyinfo->Xatom_net_supporting_wm_check,
26683 0, 1, False, XA_WINDOW, &actual_type,
26684 &actual_format, &actual_size,
26685 &bytes_remaining, &tmp_data);
26686
26687 if (rc != Success || actual_type != XA_WINDOW
26688 || actual_format != 32 || actual_size != 1)
26689 {
26690 if (tmp_data)
26691 XFree (tmp_data);
26692
26693 return None;
26694 }
26695
26696 result = *(Window *) tmp_data;
26697 XFree (tmp_data);
26698
26699 return result;
26700 }
26701
26702
26703
26704
26705
26706
26707
26708 bool
26709 x_wm_supports_1 (struct x_display_info *dpyinfo, Atom want_atom)
26710 {
26711 Atom actual_type;
26712 unsigned long actual_size, bytes_remaining;
26713 int i, rc, actual_format;
26714 bool ret;
26715 Window wmcheck_window;
26716 Window target_window = dpyinfo->root_window;
26717 int max_len = 65536;
26718 Display *dpy = dpyinfo->display;
26719 unsigned char *tmp_data = NULL;
26720 Atom target_type = XA_WINDOW;
26721
26722
26723
26724 if (!NILP (Vx_no_window_manager))
26725 return false;
26726
26727 block_input ();
26728
26729 x_catch_errors (dpy);
26730
26731 wmcheck_window = dpyinfo->net_supported_window;
26732
26733 if (wmcheck_window == None)
26734 wmcheck_window = x_get_wm_check_window (dpyinfo);
26735
26736 if (!x_special_window_exists_p (dpyinfo, wmcheck_window))
26737 {
26738 if (dpyinfo->net_supported_window != None)
26739 {
26740 dpyinfo->net_supported_window = None;
26741 wmcheck_window = x_get_wm_check_window (dpyinfo);
26742
26743 if (!x_special_window_exists_p (dpyinfo, wmcheck_window))
26744 {
26745 x_uncatch_errors ();
26746 unblock_input ();
26747 return false;
26748 }
26749 }
26750 else
26751 {
26752 x_uncatch_errors ();
26753 unblock_input ();
26754 return false;
26755 }
26756 }
26757
26758 if (dpyinfo->net_supported_window != wmcheck_window)
26759 {
26760
26761 if (dpyinfo->net_supported_atoms != NULL)
26762 XFree (dpyinfo->net_supported_atoms);
26763 dpyinfo->net_supported_atoms = NULL;
26764 dpyinfo->nr_net_supported_atoms = 0;
26765 dpyinfo->net_supported_window = 0;
26766
26767 target_type = XA_ATOM;
26768 tmp_data = NULL;
26769 rc = XGetWindowProperty (dpy, target_window,
26770 dpyinfo->Xatom_net_supported,
26771 0, max_len, False, target_type,
26772 &actual_type, &actual_format, &actual_size,
26773 &bytes_remaining, &tmp_data);
26774
26775 if (rc != Success || actual_type != XA_ATOM || x_had_errors_p (dpy))
26776 {
26777 if (tmp_data)
26778 XFree (tmp_data);
26779 x_uncatch_errors ();
26780 unblock_input ();
26781 return false;
26782 }
26783
26784 dpyinfo->net_supported_atoms = (Atom *) tmp_data;
26785 dpyinfo->nr_net_supported_atoms = actual_size;
26786 dpyinfo->net_supported_window = wmcheck_window;
26787 }
26788
26789 ret = false;
26790
26791 for (i = 0; !ret && i < dpyinfo->nr_net_supported_atoms; ++i)
26792 ret = dpyinfo->net_supported_atoms[i] == want_atom;
26793
26794 x_uncatch_errors ();
26795 unblock_input ();
26796
26797 return ret;
26798 }
26799
26800 bool
26801 x_wm_supports (struct frame *f, Atom want_atom)
26802 {
26803 return x_wm_supports_1 (FRAME_DISPLAY_INFO (f),
26804 want_atom);
26805 }
26806
26807 static void
26808 set_wm_state (Lisp_Object frame, bool add, Atom atom, Atom value)
26809 {
26810 struct x_display_info *dpyinfo;
26811 XEvent msg;
26812
26813 dpyinfo = FRAME_DISPLAY_INFO (XFRAME (frame));
26814 msg.xclient.type = ClientMessage;
26815 msg.xclient.window = FRAME_OUTER_WINDOW (XFRAME (frame));
26816 msg.xclient.message_type = dpyinfo->Xatom_net_wm_state;
26817 msg.xclient.format = 32;
26818
26819 msg.xclient.data.l[0] = add ? 1 : 0;
26820 msg.xclient.data.l[1] = atom;
26821 msg.xclient.data.l[2] = value;
26822 msg.xclient.data.l[3] = 1;
26823 msg.xclient.data.l[4] = 0;
26824
26825 block_input ();
26826 XSendEvent (dpyinfo->display, dpyinfo->root_window,
26827 False, (SubstructureRedirectMask
26828 | SubstructureNotifyMask), &msg);
26829 unblock_input ();
26830 }
26831
26832 void
26833 x_set_sticky (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
26834 {
26835 Lisp_Object frame;
26836 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
26837
26838 XSETFRAME (frame, f);
26839
26840 set_wm_state (frame, !NILP (new_value),
26841 dpyinfo->Xatom_net_wm_state_sticky, None);
26842 }
26843
26844 void
26845 x_set_shaded (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
26846 {
26847 Lisp_Object frame;
26848 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
26849
26850 XSETFRAME (frame, f);
26851
26852 set_wm_state (frame, !NILP (new_value),
26853 dpyinfo->Xatom_net_wm_state_shaded, None);
26854 }
26855
26856
26857
26858
26859
26860
26861
26862
26863
26864
26865
26866 void
26867 x_set_skip_taskbar (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
26868 {
26869 if (!EQ (new_value, old_value))
26870 {
26871 #ifdef USE_GTK
26872 xg_set_skip_taskbar (f, new_value);
26873 #else
26874 Lisp_Object frame;
26875 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
26876
26877 XSETFRAME (frame, f);
26878 set_wm_state (frame, !NILP (new_value),
26879 dpyinfo->Xatom_net_wm_state_skip_taskbar, None);
26880 #endif
26881 FRAME_SKIP_TASKBAR (f) = !NILP (new_value);
26882 }
26883 }
26884
26885
26886
26887
26888
26889
26890
26891
26892
26893
26894
26895
26896
26897
26898
26899
26900
26901 void
26902 x_set_z_group (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
26903 {
26904
26905
26906 Lisp_Object frame;
26907 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
26908
26909 XSETFRAME (frame, f);
26910
26911 if (NILP (new_value))
26912 {
26913 set_wm_state (frame, false,
26914 dpyinfo->Xatom_net_wm_state_above, None);
26915 set_wm_state (frame, false,
26916 dpyinfo->Xatom_net_wm_state_below, None);
26917 FRAME_Z_GROUP (f) = z_group_none;
26918 }
26919 else if (EQ (new_value, Qabove))
26920 {
26921 set_wm_state (frame, true,
26922 dpyinfo->Xatom_net_wm_state_above, None);
26923 set_wm_state (frame, false,
26924 dpyinfo->Xatom_net_wm_state_below, None);
26925 FRAME_Z_GROUP (f) = z_group_above;
26926 }
26927 else if (EQ (new_value, Qbelow))
26928 {
26929 set_wm_state (frame, false,
26930 dpyinfo->Xatom_net_wm_state_above, None);
26931 set_wm_state (frame, true,
26932 dpyinfo->Xatom_net_wm_state_below, None);
26933 FRAME_Z_GROUP (f) = z_group_below;
26934 }
26935 else if (EQ (new_value, Qabove_suspended))
26936 {
26937 set_wm_state (frame, false,
26938 dpyinfo->Xatom_net_wm_state_above, None);
26939 FRAME_Z_GROUP (f) = z_group_above_suspended;
26940 }
26941 else
26942 error ("Invalid z-group specification");
26943 }
26944
26945
26946
26947
26948
26949
26950
26951
26952 static bool
26953 x_get_current_wm_state (struct frame *f,
26954 Window window,
26955 int *size_state,
26956 bool *sticky,
26957 bool *shaded)
26958 {
26959 unsigned long actual_size;
26960 int i;
26961 bool is_hidden = false;
26962 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
26963 long max_len = 65536;
26964 Atom target_type = XA_ATOM;
26965
26966 #ifdef USE_XCB
26967 xcb_get_property_cookie_t prop_cookie;
26968 xcb_get_property_reply_t *prop;
26969 typedef xcb_atom_t reply_data_object;
26970 #else
26971 Display *dpy = FRAME_X_DISPLAY (f);
26972 unsigned long bytes_remaining;
26973 int rc, actual_format;
26974 Atom actual_type;
26975 unsigned char *tmp_data = NULL;
26976 typedef Atom reply_data_object;
26977 #endif
26978 reply_data_object *reply_data;
26979 # if defined GCC_LINT || defined lint
26980 reply_data_object reply_data_dummy;
26981 reply_data = &reply_data_dummy;
26982 # endif
26983
26984 *sticky = false;
26985 *size_state = FULLSCREEN_NONE;
26986 *shaded = false;
26987
26988 block_input ();
26989
26990 #ifdef USE_XCB
26991 prop_cookie = xcb_get_property (dpyinfo->xcb_connection, 0, window,
26992 dpyinfo->Xatom_net_wm_state,
26993 target_type, 0, max_len);
26994 prop = xcb_get_property_reply (dpyinfo->xcb_connection, prop_cookie, NULL);
26995 if (prop && prop->type == target_type)
26996 {
26997 int actual_bytes = xcb_get_property_value_length (prop);
26998 eassume (0 <= actual_bytes);
26999 actual_size = actual_bytes / sizeof *reply_data;
27000 reply_data = xcb_get_property_value (prop);
27001 }
27002 else
27003 {
27004 actual_size = 0;
27005 is_hidden = FRAME_ICONIFIED_P (f);
27006 }
27007 #else
27008 x_catch_errors (dpy);
27009 rc = XGetWindowProperty (dpy, window, dpyinfo->Xatom_net_wm_state,
27010 0, max_len, False, target_type,
27011 &actual_type, &actual_format, &actual_size,
27012 &bytes_remaining, &tmp_data);
27013
27014 if (rc == Success && actual_type == target_type && ! x_had_errors_p (dpy))
27015 reply_data = (Atom *) tmp_data;
27016 else
27017 {
27018 actual_size = 0;
27019 is_hidden = FRAME_ICONIFIED_P (f);
27020 }
27021
27022 x_uncatch_errors ();
27023 #endif
27024
27025 for (i = 0; i < actual_size; ++i)
27026 {
27027 Atom a = reply_data[i];
27028 if (a == dpyinfo->Xatom_net_wm_state_hidden)
27029 is_hidden = true;
27030 else if (a == dpyinfo->Xatom_net_wm_state_maximized_horz)
27031 {
27032 if (*size_state == FULLSCREEN_HEIGHT)
27033 *size_state = FULLSCREEN_MAXIMIZED;
27034 else
27035 *size_state = FULLSCREEN_WIDTH;
27036 }
27037 else if (a == dpyinfo->Xatom_net_wm_state_maximized_vert)
27038 {
27039 if (*size_state == FULLSCREEN_WIDTH)
27040 *size_state = FULLSCREEN_MAXIMIZED;
27041 else
27042 *size_state = FULLSCREEN_HEIGHT;
27043 }
27044 else if (a == dpyinfo->Xatom_net_wm_state_fullscreen)
27045 *size_state = FULLSCREEN_BOTH;
27046 else if (a == dpyinfo->Xatom_net_wm_state_sticky)
27047 *sticky = true;
27048 else if (a == dpyinfo->Xatom_net_wm_state_shaded)
27049 *shaded = true;
27050 }
27051
27052 #ifdef USE_XCB
27053 free (prop);
27054 #else
27055 if (tmp_data) XFree (tmp_data);
27056 #endif
27057
27058 unblock_input ();
27059 return ! is_hidden;
27060 }
27061
27062
27063
27064 static bool
27065 do_ewmh_fullscreen (struct frame *f)
27066 {
27067 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
27068 bool have_net_atom = x_wm_supports (f, dpyinfo->Xatom_net_wm_state);
27069 int cur;
27070 bool dummy;
27071
27072 x_get_current_wm_state (f, FRAME_OUTER_WINDOW (f), &cur, &dummy, &dummy);
27073
27074
27075
27076 if (!have_net_atom)
27077 have_net_atom = x_wm_supports (f, dpyinfo->Xatom_net_wm_state_fullscreen);
27078
27079 if (have_net_atom && cur != f->want_fullscreen)
27080 {
27081 Lisp_Object frame;
27082
27083 XSETFRAME (frame, f);
27084
27085
27086
27087
27088 switch (f->want_fullscreen)
27089 {
27090 case FULLSCREEN_BOTH:
27091 if (cur != FULLSCREEN_BOTH)
27092 set_wm_state (frame, true, dpyinfo->Xatom_net_wm_state_fullscreen,
27093 None);
27094 break;
27095 case FULLSCREEN_WIDTH:
27096 if (x_frame_normalize_before_maximize && cur == FULLSCREEN_MAXIMIZED)
27097 {
27098 set_wm_state (frame, false,
27099 dpyinfo->Xatom_net_wm_state_maximized_horz,
27100 dpyinfo->Xatom_net_wm_state_maximized_vert);
27101 set_wm_state (frame, true,
27102 dpyinfo->Xatom_net_wm_state_maximized_horz, None);
27103 }
27104 else
27105 {
27106 if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_HEIGHT
27107 || cur == FULLSCREEN_MAXIMIZED)
27108 set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
27109 dpyinfo->Xatom_net_wm_state_maximized_vert);
27110 if (cur != FULLSCREEN_MAXIMIZED || x_frame_normalize_before_maximize)
27111 set_wm_state (frame, true,
27112 dpyinfo->Xatom_net_wm_state_maximized_horz, None);
27113 }
27114 break;
27115 case FULLSCREEN_HEIGHT:
27116 if (x_frame_normalize_before_maximize && cur == FULLSCREEN_MAXIMIZED)
27117 {
27118 set_wm_state (frame, false,
27119 dpyinfo->Xatom_net_wm_state_maximized_horz,
27120 dpyinfo->Xatom_net_wm_state_maximized_vert);
27121 set_wm_state (frame, true,
27122 dpyinfo->Xatom_net_wm_state_maximized_vert, None);
27123 }
27124 else
27125 {
27126 if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_WIDTH
27127 || cur == FULLSCREEN_MAXIMIZED)
27128 set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
27129 dpyinfo->Xatom_net_wm_state_maximized_horz);
27130 if (cur != FULLSCREEN_MAXIMIZED || x_frame_normalize_before_maximize)
27131 set_wm_state (frame, true,
27132 dpyinfo->Xatom_net_wm_state_maximized_vert, None);
27133 }
27134 break;
27135 case FULLSCREEN_MAXIMIZED:
27136 if (x_frame_normalize_before_maximize && cur == FULLSCREEN_BOTH)
27137 {
27138 set_wm_state (frame, false,
27139 dpyinfo->Xatom_net_wm_state_fullscreen, None);
27140 set_wm_state (frame, true,
27141 dpyinfo->Xatom_net_wm_state_maximized_horz,
27142 dpyinfo->Xatom_net_wm_state_maximized_vert);
27143 }
27144 else if (x_frame_normalize_before_maximize && cur == FULLSCREEN_WIDTH)
27145 {
27146 set_wm_state (frame, false,
27147 dpyinfo->Xatom_net_wm_state_maximized_horz, None);
27148 set_wm_state (frame, true,
27149 dpyinfo->Xatom_net_wm_state_maximized_horz,
27150 dpyinfo->Xatom_net_wm_state_maximized_vert);
27151 }
27152 else if (x_frame_normalize_before_maximize && cur == FULLSCREEN_HEIGHT)
27153 {
27154 set_wm_state (frame, false,
27155 dpyinfo->Xatom_net_wm_state_maximized_vert, None);
27156 set_wm_state (frame, true,
27157 dpyinfo->Xatom_net_wm_state_maximized_horz,
27158 dpyinfo->Xatom_net_wm_state_maximized_vert);
27159 }
27160 else
27161 {
27162 if (cur == FULLSCREEN_BOTH)
27163 set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
27164 None);
27165 else if (cur == FULLSCREEN_HEIGHT)
27166 set_wm_state (frame, true,
27167 dpyinfo->Xatom_net_wm_state_maximized_horz, None);
27168 else if (cur == FULLSCREEN_WIDTH)
27169 set_wm_state (frame, true, None,
27170 dpyinfo->Xatom_net_wm_state_maximized_vert);
27171 else
27172 set_wm_state (frame, true,
27173 dpyinfo->Xatom_net_wm_state_maximized_horz,
27174 dpyinfo->Xatom_net_wm_state_maximized_vert);
27175 }
27176 break;
27177 case FULLSCREEN_NONE:
27178 if (cur == FULLSCREEN_BOTH)
27179 set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
27180 None);
27181 else
27182 set_wm_state (frame, false,
27183 dpyinfo->Xatom_net_wm_state_maximized_horz,
27184 dpyinfo->Xatom_net_wm_state_maximized_vert);
27185 }
27186
27187 f->want_fullscreen = FULLSCREEN_NONE;
27188
27189 }
27190
27191 return have_net_atom;
27192 }
27193
27194 static void
27195 XTfullscreen_hook (struct frame *f)
27196 {
27197 if (FRAME_VISIBLE_P (f))
27198 {
27199 block_input ();
27200 x_check_fullscreen (f);
27201 x_sync (f);
27202 unblock_input ();
27203 }
27204 }
27205
27206
27207 static bool
27208 x_handle_net_wm_state (struct frame *f, const XPropertyEvent *event)
27209 {
27210 int value = FULLSCREEN_NONE;
27211 Lisp_Object lval;
27212 bool sticky = false, shaded = false;
27213 bool not_hidden = x_get_current_wm_state (f, event->window,
27214 &value, &sticky,
27215 &shaded);
27216
27217 lval = Qnil;
27218 switch (value)
27219 {
27220 case FULLSCREEN_WIDTH:
27221 lval = Qfullwidth;
27222 break;
27223 case FULLSCREEN_HEIGHT:
27224 lval = Qfullheight;
27225 break;
27226 case FULLSCREEN_BOTH:
27227 lval = Qfullboth;
27228 break;
27229 case FULLSCREEN_MAXIMIZED:
27230 lval = Qmaximized;
27231 break;
27232 }
27233
27234 store_frame_param (f, Qfullscreen, lval);
27235 store_frame_param (f, Qsticky, sticky ? Qt : Qnil);
27236 store_frame_param (f, Qshaded, shaded ? Qt : Qnil);
27237
27238 return not_hidden;
27239 }
27240
27241
27242
27243 static void
27244 x_check_fullscreen (struct frame *f)
27245 {
27246 Lisp_Object lval = Qnil;
27247
27248 if (do_ewmh_fullscreen (f))
27249 return;
27250
27251 if (f->output_data.x->parent_desc != FRAME_DISPLAY_INFO (f)->root_window)
27252 return;
27253
27254
27255
27256
27257
27258 if (f->want_fullscreen != FULLSCREEN_NONE)
27259 {
27260 int width = FRAME_PIXEL_WIDTH (f), height = FRAME_PIXEL_HEIGHT (f);
27261 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
27262
27263 switch (f->want_fullscreen)
27264 {
27265
27266 case FULLSCREEN_MAXIMIZED:
27267 lval = Qmaximized;
27268 width = x_display_pixel_width (dpyinfo);
27269 height = x_display_pixel_height (dpyinfo);
27270 break;
27271 case FULLSCREEN_BOTH:
27272 lval = Qfullboth;
27273 width = x_display_pixel_width (dpyinfo);
27274 height = x_display_pixel_height (dpyinfo);
27275 break;
27276 case FULLSCREEN_WIDTH:
27277 lval = Qfullwidth;
27278 width = x_display_pixel_width (dpyinfo);
27279 height = height + FRAME_MENUBAR_HEIGHT (f);
27280 break;
27281 case FULLSCREEN_HEIGHT:
27282 lval = Qfullheight;
27283 height = x_display_pixel_height (dpyinfo);
27284 break;
27285 default:
27286 emacs_abort ();
27287 }
27288
27289 x_wm_set_size_hint (f, 0, false);
27290
27291 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
27292 width, height);
27293
27294 if (FRAME_VISIBLE_P (f))
27295 x_wait_for_event (f, ConfigureNotify);
27296 else
27297 {
27298 change_frame_size (f, width, height, false, true, false);
27299 x_sync (f);
27300 }
27301 }
27302
27303
27304
27305 store_frame_param (f, Qfullscreen, lval);
27306 }
27307
27308
27309
27310
27311
27312
27313
27314
27315
27316 static void
27317 x_check_expected_move (struct frame *f, int expected_left, int expected_top)
27318 {
27319 int current_left = 0, current_top = 0;
27320
27321
27322
27323
27324 x_real_positions (f, ¤t_left, ¤t_top);
27325
27326 if (current_left != expected_left || current_top != expected_top)
27327 {
27328
27329
27330 int adjusted_left;
27331 int adjusted_top;
27332
27333 FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_A;
27334 FRAME_X_OUTPUT (f)->move_offset_left = expected_left - current_left;
27335 FRAME_X_OUTPUT (f)->move_offset_top = expected_top - current_top;
27336
27337
27338
27339 adjusted_left = expected_left + FRAME_X_OUTPUT (f)->move_offset_left;
27340 adjusted_top = expected_top + FRAME_X_OUTPUT (f)->move_offset_top;
27341
27342 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
27343 adjusted_left, adjusted_top);
27344
27345 x_sync_with_move (f, expected_left, expected_top, false);
27346 }
27347 else
27348
27349
27350 FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_B;
27351 }
27352
27353
27354
27355
27356
27357
27358
27359
27360 static void
27361 x_sync_with_move (struct frame *f, int left, int top, bool fuzzy)
27362 {
27363 sigset_t emptyset;
27364 int count, current_left, current_top;
27365 struct timespec fallback;
27366
27367 sigemptyset (&emptyset);
27368 count = 0;
27369
27370 while (count++ < 50)
27371 {
27372 current_left = 0;
27373 current_top = 0;
27374
27375
27376
27377
27378 x_real_positions (f, ¤t_left, ¤t_top);
27379
27380 if (fuzzy)
27381 {
27382
27383
27384
27385 if (eabs (current_left - left) <= 10
27386 && eabs (current_top - top) <= 40)
27387 return;
27388 }
27389 else if (current_left == left && current_top == top)
27390 return;
27391 }
27392
27393
27394
27395
27396 fallback = dtotimespec (0.5);
27397
27398
27399
27400 if (input_blocked_p ())
27401 pselect (0, NULL, NULL, NULL, &fallback, &emptyset);
27402 else
27403 wait_reading_process_output (0, 500000000, 0, false, Qnil, NULL, 0);
27404 }
27405
27406
27407 void
27408 x_wait_for_event (struct frame *f, int eventtype)
27409 {
27410 if (!FLOATP (Vx_wait_for_event_timeout))
27411 return;
27412
27413 int level = interrupt_input_blocked;
27414 fd_set fds;
27415 struct timespec tmo, tmo_at, time_now;
27416 int fd = ConnectionNumber (FRAME_X_DISPLAY (f));
27417
27418 f->wait_event_type = eventtype;
27419
27420
27421 double timeout = XFLOAT_DATA (Vx_wait_for_event_timeout);
27422 time_t timeout_seconds = (time_t) timeout;
27423 tmo = make_timespec
27424 (timeout_seconds, (long int) ((timeout - timeout_seconds)
27425 * 1000 * 1000 * 1000));
27426 tmo_at = timespec_add (current_timespec (), tmo);
27427
27428 while (f->wait_event_type)
27429 {
27430 pending_signals = true;
27431 totally_unblock_input ();
27432
27433 block_input ();
27434 interrupt_input_blocked = level;
27435
27436 FD_ZERO (&fds);
27437 FD_SET (fd, &fds);
27438
27439 time_now = current_timespec ();
27440 if (timespec_cmp (tmo_at, time_now) < 0)
27441 break;
27442
27443 tmo = timespec_sub (tmo_at, time_now);
27444 if (pselect (fd + 1, &fds, NULL, NULL, &tmo, NULL) == 0)
27445 break;
27446 }
27447
27448 f->wait_event_type = 0;
27449 }
27450
27451
27452
27453
27454
27455
27456
27457 static void
27458 x_set_window_size_1 (struct frame *f, bool change_gravity,
27459 int width, int height)
27460 {
27461 if (change_gravity)
27462 f->win_gravity = NorthWestGravity;
27463 x_wm_set_size_hint (f, 0, false);
27464
27465 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
27466 width, height + FRAME_MENUBAR_HEIGHT (f));
27467
27468
27469
27470
27471
27472 SET_FRAME_GARBAGED (f);
27473
27474
27475
27476
27477
27478
27479
27480
27481
27482
27483
27484
27485
27486
27487
27488
27489
27490
27491 if (FRAME_VISIBLE_P (f))
27492 {
27493 x_wait_for_event (f, ConfigureNotify);
27494
27495 if (CONSP (frame_size_history))
27496 frame_size_history_extra
27497 (f, build_string ("x_set_window_size_1, visible"),
27498 FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), width, height,
27499 f->new_width, f->new_height);
27500 }
27501 else
27502 {
27503 if (CONSP (frame_size_history))
27504 frame_size_history_extra
27505 (f, build_string ("x_set_window_size_1, invisible"),
27506 FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f), width, height,
27507 f->new_width, f->new_height);
27508
27509
27510
27511 adjust_frame_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, width),
27512 FRAME_PIXEL_TO_TEXT_HEIGHT (f, height),
27513 5, 0, Qx_set_window_size_1);
27514
27515 x_sync (f);
27516 }
27517 }
27518
27519
27520
27521
27522
27523
27524
27525 void
27526 x_set_window_size (struct frame *f, bool change_gravity,
27527 int width, int height)
27528 {
27529 block_input ();
27530
27531 #ifdef USE_GTK
27532 if (FRAME_GTK_WIDGET (f))
27533 xg_frame_set_char_size (f, width, height);
27534 else
27535 x_set_window_size_1 (f, change_gravity, width, height);
27536 #else
27537 x_set_window_size_1 (f, change_gravity, width, height);
27538 x_clear_under_internal_border (f);
27539 #endif
27540
27541
27542 mark_window_cursors_off (XWINDOW (f->root_window));
27543
27544
27545
27546
27547
27548 cancel_mouse_face (f);
27549
27550 unblock_input ();
27551
27552 do_pending_window_change (false);
27553 }
27554
27555
27556
27557 void
27558 frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
27559 {
27560 #ifdef HAVE_XINPUT2
27561 int deviceid;
27562
27563 deviceid = FRAME_DISPLAY_INFO (f)->client_pointer_device;
27564
27565 if (FRAME_DISPLAY_INFO (f)->supports_xi2
27566 && deviceid != -1)
27567 {
27568 block_input ();
27569 x_ignore_errors_for_next_request (FRAME_DISPLAY_INFO (f));
27570 XIWarpPointer (FRAME_X_DISPLAY (f), deviceid, None,
27571 FRAME_X_WINDOW (f), 0, 0, 0, 0, pix_x, pix_y);
27572 x_stop_ignoring_errors (FRAME_DISPLAY_INFO (f));
27573 unblock_input ();
27574 }
27575 else
27576 #endif
27577 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
27578 0, 0, 0, 0, pix_x, pix_y);
27579 }
27580
27581
27582
27583 static void
27584 x_raise_frame (struct frame *f)
27585 {
27586 block_input ();
27587
27588 if (FRAME_VISIBLE_P (f))
27589 {
27590 XRaiseWindow (FRAME_X_DISPLAY (f),
27591 FRAME_OUTER_WINDOW (f));
27592 XFlush (FRAME_X_DISPLAY (f));
27593 }
27594
27595 unblock_input ();
27596 }
27597
27598 static void
27599 x_lower_frame_1 (struct frame *f)
27600 {
27601 Window *windows;
27602 Lisp_Object frame, tail;
27603 struct frame *sibling;
27604
27605 windows = alloca (2 * sizeof *windows);
27606
27607
27608
27609
27610
27611 FOR_EACH_FRAME (tail, frame)
27612 {
27613 sibling = XFRAME (frame);
27614
27615 if (sibling == f)
27616 continue;
27617
27618 if (FRAME_PARENT_FRAME (sibling)
27619 != FRAME_PARENT_FRAME (f))
27620 continue;
27621
27622 windows[0] = FRAME_OUTER_WINDOW (sibling);
27623 windows[1] = FRAME_OUTER_WINDOW (f);
27624
27625 XRestackWindows (FRAME_X_DISPLAY (f), windows, 2);
27626 }
27627 }
27628
27629
27630
27631 static void
27632 x_lower_frame (struct frame *f)
27633 {
27634 if (FRAME_PARENT_FRAME (f)
27635 && (FRAME_HAS_VERTICAL_SCROLL_BARS (FRAME_PARENT_FRAME (f))
27636 || FRAME_HAS_HORIZONTAL_SCROLL_BARS (FRAME_PARENT_FRAME (f))))
27637 x_lower_frame_1 (f);
27638 else
27639 XLowerWindow (FRAME_X_DISPLAY (f),
27640 FRAME_OUTER_WINDOW (f));
27641
27642 #ifdef HAVE_XWIDGETS
27643
27644
27645
27646 if (FRAME_PARENT_FRAME (f))
27647 lower_frame_xwidget_views (FRAME_PARENT_FRAME (f));
27648 #endif
27649
27650 XFlush (FRAME_X_DISPLAY (f));
27651 }
27652
27653 static void
27654 XTframe_raise_lower (struct frame *f, bool raise_flag)
27655 {
27656 if (raise_flag)
27657 x_raise_frame (f);
27658 else
27659 x_lower_frame (f);
27660 }
27661
27662
27663
27664 static void
27665 xembed_request_focus (struct frame *f)
27666 {
27667
27668
27669 if (FRAME_VISIBLE_P (f))
27670 xembed_send_message (f, CurrentTime,
27671 XEMBED_REQUEST_FOCUS, 0, 0, 0);
27672 }
27673
27674 static Bool
27675 server_timestamp_predicate (Display *display, XEvent *xevent,
27676 XPointer arg)
27677 {
27678 XID *args = (XID *) arg;
27679
27680 if (xevent->type == PropertyNotify
27681 && xevent->xproperty.window == args[0]
27682 && xevent->xproperty.atom == args[1])
27683 return True;
27684
27685 return False;
27686 }
27687
27688
27689
27690
27691 static Time
27692 x_get_server_time (struct frame *f)
27693 {
27694 Atom property_atom;
27695 XEvent property_dummy;
27696 struct x_display_info *dpyinfo;
27697 XID client_data[2];
27698 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
27699 uint_fast64_t current_monotonic_time;
27700 #endif
27701
27702
27703
27704
27705 #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
27706 if (FRAME_DISPLAY_INFO (f)->server_time_monotonic_p)
27707 {
27708 current_monotonic_time = x_sync_current_monotonic_time ();
27709
27710 if (current_monotonic_time)
27711
27712 return (current_monotonic_time / 1000) & X_ULONG_MAX;
27713 }
27714 #endif
27715
27716 dpyinfo = FRAME_DISPLAY_INFO (f);
27717 property_atom = dpyinfo->Xatom_EMACS_SERVER_TIME_PROP;
27718 client_data[0] = FRAME_OUTER_WINDOW (f);
27719 client_data[1] = property_atom;
27720
27721 XChangeProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
27722 property_atom, XA_ATOM, 32,
27723 PropModeReplace,
27724 (unsigned char *) &property_atom, 1);
27725
27726 XIfEvent (dpyinfo->display, &property_dummy,
27727 server_timestamp_predicate, (XPointer) client_data);
27728
27729 return property_dummy.xproperty.time;
27730 }
27731
27732
27733
27734 static void
27735 x_ewmh_activate_frame (struct frame *f)
27736 {
27737 XEvent msg;
27738 struct x_display_info *dpyinfo;
27739 Time time;
27740
27741 dpyinfo = FRAME_DISPLAY_INFO (f);
27742
27743 if (FRAME_VISIBLE_P (f))
27744 {
27745
27746
27747
27748 msg.xclient.type = ClientMessage;
27749 msg.xclient.window = FRAME_OUTER_WINDOW (f);
27750 msg.xclient.message_type = dpyinfo->Xatom_net_active_window;
27751 msg.xclient.format = 32;
27752 msg.xclient.data.l[0] = 1;
27753 msg.xclient.data.l[1] = dpyinfo->last_user_time;
27754 msg.xclient.data.l[2] = (!dpyinfo->x_focus_frame
27755 ? None
27756 : FRAME_OUTER_WINDOW (dpyinfo->x_focus_frame));
27757 msg.xclient.data.l[3] = 0;
27758 msg.xclient.data.l[4] = 0;
27759
27760
27761
27762
27763 if (!dpyinfo->x_focus_frame)
27764 {
27765 if (EQ (Vx_allow_focus_stealing, Qimitate_pager))
27766 msg.xclient.data.l[0] = 2;
27767 else if (EQ (Vx_allow_focus_stealing, Qnewer_time))
27768 {
27769 block_input ();
27770 time = x_get_server_time (f);
27771 #ifdef USE_GTK
27772 x_set_gtk_user_time (f, time);
27773 #endif
27774
27775
27776 dpyinfo->x_focus_frame = f;
27777 x_display_set_last_user_time (dpyinfo, time, true, true);
27778 dpyinfo->x_focus_frame = NULL;
27779 unblock_input ();
27780
27781 msg.xclient.data.l[1] = time;
27782 }
27783 else if (EQ (Vx_allow_focus_stealing, Qraise_and_focus))
27784 {
27785 time = x_get_server_time (f);
27786
27787 x_set_input_focus (FRAME_DISPLAY_INFO (f),
27788 FRAME_OUTER_WINDOW (f),
27789 time);
27790 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
27791
27792 return;
27793 }
27794 }
27795
27796 XSendEvent (dpyinfo->display, dpyinfo->root_window,
27797 False, (SubstructureRedirectMask
27798 | SubstructureNotifyMask), &msg);
27799 }
27800 }
27801
27802 static Lisp_Object
27803 x_get_focus_frame (struct frame *f)
27804 {
27805 Lisp_Object lisp_focus;
27806
27807 struct frame *focus = FRAME_DISPLAY_INFO (f)->x_focus_frame;
27808
27809 if (!focus)
27810 return Qnil;
27811
27812 XSETFRAME (lisp_focus, focus);
27813 return lisp_focus;
27814 }
27815
27816
27817
27818
27819 static struct frame *
27820 x_get_toplevel_parent (struct frame *f)
27821 {
27822 struct frame *parent;
27823
27824 if (!FRAME_PARENT_FRAME (f))
27825 return NULL;
27826
27827 parent = FRAME_PARENT_FRAME (f);
27828
27829 while (FRAME_PARENT_FRAME (parent))
27830 parent = FRAME_PARENT_FRAME (parent);
27831
27832 return parent;
27833 }
27834
27835 static void
27836 x_set_input_focus (struct x_display_info *dpyinfo, Window window,
27837 Time time)
27838 {
27839 #ifdef HAVE_XINPUT2
27840 struct xi_device_t *device;
27841 #endif
27842
27843
27844
27845
27846
27847
27848
27849
27850
27851
27852
27853 #ifdef HAVE_XINPUT2
27854 if (dpyinfo->supports_xi2
27855 && dpyinfo->client_pointer_device != -1)
27856 {
27857 device = xi_device_from_id (dpyinfo, dpyinfo->client_pointer_device);
27858
27859
27860
27861
27862 if (device)
27863 {
27864 eassert (device->use == XIMasterPointer);
27865
27866 x_ignore_errors_for_next_request (dpyinfo);
27867 XISetFocus (dpyinfo->display, device->attachment,
27868
27869
27870
27871 window, time);
27872 x_stop_ignoring_errors (dpyinfo);
27873
27874 return;
27875 }
27876 }
27877 #endif
27878
27879
27880
27881 x_ignore_errors_for_next_request (dpyinfo);
27882 XSetInputFocus (dpyinfo->display, window, RevertToParent, time);
27883 x_stop_ignoring_errors (dpyinfo);
27884 }
27885
27886
27887
27888
27889
27890
27891
27892
27893
27894
27895 static void
27896 x_focus_frame (struct frame *f, bool noactivate)
27897 {
27898 struct x_display_info *dpyinfo;
27899 Time time;
27900
27901
27902
27903 block_input ();
27904
27905 dpyinfo = FRAME_DISPLAY_INFO (f);
27906
27907 if (FRAME_X_EMBEDDED_P (f))
27908
27909
27910
27911 xembed_request_focus (f);
27912 else
27913 {
27914 if (!noactivate
27915
27916
27917
27918 && !FRAME_OVERRIDE_REDIRECT (f)
27919
27920
27921 && !FRAME_PARENT_FRAME (f)
27922
27923
27924 && (!dpyinfo->x_focus_frame
27925 || (x_get_toplevel_parent (dpyinfo->x_focus_frame)
27926 != f))
27927 && x_wm_supports (f, dpyinfo->Xatom_net_active_window))
27928 {
27929
27930
27931
27932
27933
27934 x_ewmh_activate_frame (f);
27935 goto out;
27936 }
27937
27938 if (NILP (Vx_no_window_manager))
27939 {
27940
27941
27942
27943
27944
27945
27946
27947 time = dpyinfo->last_user_time;
27948
27949
27950
27951 if (EQ (Vx_allow_focus_stealing, Qnewer_time)
27952 && !dpyinfo->x_focus_frame)
27953 time = x_get_server_time (f);
27954
27955
27956
27957
27958
27959 x_set_input_focus (FRAME_DISPLAY_INFO (f), FRAME_OUTER_WINDOW (f),
27960 time);
27961 }
27962 else
27963 x_set_input_focus (FRAME_DISPLAY_INFO (f), FRAME_OUTER_WINDOW (f),
27964
27965
27966
27967 CurrentTime);
27968 }
27969
27970 out:
27971 unblock_input ();
27972 }
27973
27974
27975
27976
27977 #if defined USE_X_TOOLKIT || ! defined USE_GTK
27978
27979
27980
27981 #define XEMBED_VERSION 0
27982
27983 static void
27984 xembed_set_info (struct frame *f, enum xembed_info flags)
27985 {
27986 unsigned long data[2];
27987 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
27988
27989 data[0] = XEMBED_VERSION;
27990 data[1] = flags;
27991
27992 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
27993 dpyinfo->Xatom_XEMBED_INFO, dpyinfo->Xatom_XEMBED_INFO,
27994 32, PropModeReplace, (unsigned char *) data, 2);
27995 }
27996 #endif
27997
27998 static void
27999 xembed_send_message (struct frame *f, Time t, enum xembed_message msg,
28000 long int detail, long int data1, long int data2)
28001 {
28002 XEvent event;
28003
28004 event.xclient.type = ClientMessage;
28005 event.xclient.window = FRAME_X_OUTPUT (f)->parent_desc;
28006 event.xclient.message_type = FRAME_DISPLAY_INFO (f)->Xatom_XEMBED;
28007 event.xclient.format = 32;
28008 event.xclient.data.l[0] = t;
28009 event.xclient.data.l[1] = msg;
28010 event.xclient.data.l[2] = detail;
28011 event.xclient.data.l[3] = data1;
28012 event.xclient.data.l[4] = data2;
28013
28014
28015
28016
28017
28018 x_ignore_errors_for_next_request (FRAME_DISPLAY_INFO (f));
28019 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_OUTPUT (f)->parent_desc,
28020 False, NoEventMask, &event);
28021 x_stop_ignoring_errors (FRAME_DISPLAY_INFO (f));
28022 }
28023
28024
28025
28026
28027
28028
28029
28030
28031
28032
28033
28034 void
28035 x_make_frame_visible (struct frame *f)
28036 {
28037 #ifndef USE_GTK
28038 struct x_display_info *dpyinfo;
28039 struct x_output *output;
28040 #endif
28041 bool output_flushed;
28042
28043 if (FRAME_PARENT_FRAME (f))
28044 {
28045 if (!FRAME_VISIBLE_P (f))
28046 {
28047 block_input ();
28048 #ifdef USE_GTK
28049 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
28050 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
28051 f->left_pos, f->top_pos);
28052 #else
28053 XMapRaised (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
28054 #endif
28055 unblock_input ();
28056
28057 SET_FRAME_VISIBLE (f, true);
28058 SET_FRAME_ICONIFIED (f, false);
28059 }
28060 return;
28061 }
28062
28063 block_input ();
28064
28065 gui_set_bitmap_icon (f);
28066
28067 #ifndef USE_GTK
28068 dpyinfo = FRAME_DISPLAY_INFO (f);
28069 #endif
28070
28071 if (! FRAME_VISIBLE_P (f))
28072 {
28073
28074
28075
28076
28077 if (! FRAME_ICONIFIED_P (f)
28078 && ! FRAME_X_EMBEDDED_P (f)
28079 && ! f->output_data.x->asked_for_visible)
28080 x_set_offset (f, f->left_pos, f->top_pos, 0);
28081
28082 #ifndef USE_GTK
28083 output = FRAME_X_OUTPUT (f);
28084 x_update_frame_user_time_window (f);
28085
28086
28087
28088 if (output->user_time_window != None)
28089 {
28090 if (dpyinfo->last_user_time)
28091 XChangeProperty (dpyinfo->display, output->user_time_window,
28092 dpyinfo->Xatom_net_wm_user_time,
28093 XA_CARDINAL, 32, PropModeReplace,
28094 (unsigned char *) &dpyinfo->last_user_time, 1);
28095 else
28096 XDeleteProperty (dpyinfo->display, output->user_time_window,
28097 dpyinfo->Xatom_net_wm_user_time);
28098 }
28099 #endif
28100
28101 f->output_data.x->asked_for_visible = true;
28102
28103 if (! EQ (Vx_no_window_manager, Qt))
28104 x_wm_set_window_state (f, NormalState);
28105 #ifdef USE_X_TOOLKIT
28106 if (FRAME_X_EMBEDDED_P (f))
28107 xembed_set_info (f, XEMBED_MAPPED);
28108 else
28109 {
28110
28111 XtMapWidget (f->output_data.x->widget);
28112 }
28113 #else
28114 #ifdef USE_GTK
28115 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
28116 gtk_window_deiconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
28117 #else
28118 if (FRAME_X_EMBEDDED_P (f))
28119 xembed_set_info (f, XEMBED_MAPPED);
28120 else
28121 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
28122 #endif
28123 #endif
28124
28125 if (FRAME_X_EMBEDDED_P (f))
28126 {
28127 SET_FRAME_VISIBLE (f, true);
28128 SET_FRAME_ICONIFIED (f, false);
28129 }
28130 }
28131
28132
28133
28134
28135 {
28136 Lisp_Object frame;
28137
28138
28139
28140 bool previously_visible = f->output_data.x->has_been_visible;
28141
28142 XSETFRAME (frame, f);
28143
28144 int original_left = f->left_pos;
28145 int original_top = f->top_pos;
28146
28147
28148 unblock_input ();
28149
28150
28151
28152 output_flushed = false;
28153
28154
28155
28156
28157
28158
28159
28160
28161
28162
28163
28164
28165 if (!FRAME_VISIBLE_P (f)
28166 && !FRAME_ICONIFIED_P (f)
28167 && !FRAME_X_EMBEDDED_P (f)
28168 && !FRAME_PARENT_FRAME (f)
28169 && f->win_gravity == NorthWestGravity
28170 && previously_visible)
28171 {
28172 Drawable rootw;
28173 int x, y;
28174 unsigned int width, height, border, depth;
28175
28176 block_input ();
28177
28178
28179
28180
28181
28182
28183
28184
28185 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
28186 &rootw, &x, &y, &width, &height, &border, &depth);
28187 output_flushed = true;
28188
28189 if (original_left != x || original_top != y)
28190 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
28191 original_left, original_top);
28192
28193 unblock_input ();
28194 }
28195
28196
28197
28198
28199 #ifdef CYGWIN
28200
28201
28202
28203
28204
28205
28206
28207
28208
28209 int old_poll_suppress_count = poll_suppress_count;
28210 poll_suppress_count = 1;
28211 poll_for_input_1 ();
28212 poll_suppress_count = old_poll_suppress_count;
28213 #endif
28214
28215 if (!FRAME_VISIBLE_P (f))
28216 {
28217 if (CONSP (frame_size_history))
28218 frame_size_history_plain
28219 (f, build_string ("x_make_frame_visible"));
28220
28221 x_wait_for_event (f, MapNotify);
28222 output_flushed = true;
28223 }
28224
28225 if (!output_flushed)
28226 x_flush (f);
28227 }
28228 }
28229
28230
28231
28232
28233
28234 void
28235 x_make_frame_invisible (struct frame *f)
28236 {
28237 Window window;
28238
28239
28240 window = FRAME_OUTER_WINDOW (f);
28241
28242
28243 if (FRAME_DISPLAY_INFO (f)->highlight_frame == f)
28244 FRAME_DISPLAY_INFO (f)->highlight_frame = 0;
28245
28246 block_input ();
28247
28248
28249
28250
28251
28252
28253 x_wm_set_size_hint (f, 0, true);
28254
28255 #ifdef USE_GTK
28256 if (FRAME_GTK_OUTER_WIDGET (f))
28257 gtk_widget_hide (FRAME_GTK_OUTER_WIDGET (f));
28258 else
28259 #else
28260 if (FRAME_X_EMBEDDED_P (f))
28261 xembed_set_info (f, 0);
28262 else
28263 #endif
28264
28265 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
28266 DefaultScreen (FRAME_X_DISPLAY (f))))
28267 {
28268 unblock_input ();
28269 error ("Can't notify window manager of window withdrawal");
28270 }
28271
28272 x_sync (f);
28273
28274
28275
28276
28277
28278
28279 SET_FRAME_VISIBLE (f, 0);
28280 SET_FRAME_ICONIFIED (f, false);
28281
28282 if (CONSP (frame_size_history))
28283 frame_size_history_plain
28284 (f, build_string ("x_make_frame_invisible"));
28285
28286 unblock_input ();
28287 }
28288
28289 static void
28290 x_make_frame_visible_invisible (struct frame *f, bool visible)
28291 {
28292 if (visible)
28293 x_make_frame_visible (f);
28294 else
28295 x_make_frame_invisible (f);
28296 }
28297
28298 Cursor
28299 x_create_font_cursor (struct x_display_info *dpyinfo, int glyph)
28300 {
28301 if (glyph <= 65535)
28302 return XCreateFontCursor (dpyinfo->display, glyph);
28303
28304
28305
28306 return make_invisible_cursor (dpyinfo);
28307 }
28308
28309
28310
28311
28312 void
28313 x_iconify_frame (struct frame *f)
28314 {
28315 #ifdef USE_X_TOOLKIT
28316 int result;
28317 #endif
28318
28319
28320 if (FRAME_DISPLAY_INFO (f)->highlight_frame == f)
28321 FRAME_DISPLAY_INFO (f)->highlight_frame = 0;
28322
28323 if (FRAME_ICONIFIED_P (f))
28324 return;
28325
28326 block_input ();
28327
28328 gui_set_bitmap_icon (f);
28329
28330 #if defined (USE_GTK)
28331 if (FRAME_GTK_OUTER_WIDGET (f))
28332 {
28333 if (! FRAME_VISIBLE_P (f))
28334 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
28335
28336 gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
28337 SET_FRAME_VISIBLE (f, 0);
28338 SET_FRAME_ICONIFIED (f, true);
28339 unblock_input ();
28340 return;
28341 }
28342 #endif
28343
28344 #ifdef USE_X_TOOLKIT
28345
28346 if (! FRAME_VISIBLE_P (f))
28347 {
28348 if (! EQ (Vx_no_window_manager, Qt))
28349 x_wm_set_window_state (f, IconicState);
28350
28351 XtMapWidget (f->output_data.x->widget);
28352
28353
28354
28355 SET_FRAME_VISIBLE (f, 0);
28356 SET_FRAME_ICONIFIED (f, true);
28357 unblock_input ();
28358 return;
28359 }
28360
28361 result = XIconifyWindow (FRAME_X_DISPLAY (f),
28362 XtWindow (f->output_data.x->widget),
28363 DefaultScreen (FRAME_X_DISPLAY (f)));
28364 unblock_input ();
28365
28366 if (!result)
28367 error ("Can't notify window manager of iconification");
28368
28369 SET_FRAME_ICONIFIED (f, true);
28370 SET_FRAME_VISIBLE (f, 0);
28371
28372 block_input ();
28373 XFlush (FRAME_X_DISPLAY (f));
28374 unblock_input ();
28375 #else
28376
28377
28378
28379 if (! FRAME_VISIBLE_P (f)
28380 && ! FRAME_ICONIFIED_P (f)
28381 && ! FRAME_X_EMBEDDED_P (f))
28382 x_set_offset (f, f->left_pos, f->top_pos, 0);
28383
28384
28385
28386
28387
28388
28389 {
28390 XEvent msg;
28391
28392 msg.xclient.window = FRAME_X_WINDOW (f);
28393 msg.xclient.type = ClientMessage;
28394 msg.xclient.message_type = FRAME_DISPLAY_INFO (f)->Xatom_wm_change_state;
28395 msg.xclient.format = 32;
28396 msg.xclient.data.l[0] = IconicState;
28397 msg.xclient.data.l[1] = 0;
28398 msg.xclient.data.l[2] = 0;
28399 msg.xclient.data.l[3] = 0;
28400 msg.xclient.data.l[4] = 0;
28401
28402 if (! XSendEvent (FRAME_X_DISPLAY (f),
28403 FRAME_DISPLAY_INFO (f)->root_window,
28404 False,
28405 SubstructureRedirectMask | SubstructureNotifyMask,
28406 &msg))
28407 {
28408 unblock_input ();
28409 error ("Can't notify window manager of iconification");
28410 }
28411 }
28412
28413
28414
28415 x_wm_set_window_state (f, IconicState);
28416
28417 if (!FRAME_VISIBLE_P (f))
28418 {
28419
28420 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
28421 }
28422
28423 SET_FRAME_ICONIFIED (f, true);
28424 SET_FRAME_VISIBLE (f, 0);
28425
28426 XFlush (FRAME_X_DISPLAY (f));
28427 unblock_input ();
28428 #endif
28429 }
28430
28431
28432
28433
28434 void
28435 x_free_frame_resources (struct frame *f)
28436 {
28437 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
28438 Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
28439 #ifdef USE_X_TOOLKIT
28440 Lisp_Object bar;
28441 struct scroll_bar *b;
28442 #endif
28443
28444 block_input ();
28445
28446 #ifdef HAVE_XINPUT2
28447
28448 xi_handle_delete_frame (dpyinfo, f);
28449 #endif
28450
28451
28452
28453 if (dpyinfo->display)
28454 {
28455
28456
28457 if (f->pointer_invisible)
28458 XTtoggle_invisible_pointer (f, 0);
28459
28460
28461
28462
28463 free_frame_faces (f);
28464 tear_down_x_back_buffer (f);
28465
28466 if (f->output_data.x->icon_desc)
28467 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
28468
28469 #ifdef USE_X_TOOLKIT
28470
28471
28472
28473
28474 for (bar = FRAME_SCROLL_BARS (f); !NILP (bar); bar = b->next)
28475 {
28476 b = XSCROLL_BAR (bar);
28477 x_scroll_bar_remove (b);
28478 }
28479 #endif
28480
28481 #ifdef HAVE_X_I18N
28482 if (FRAME_XIC (f))
28483 free_frame_xic (f);
28484 #endif
28485
28486 #ifdef USE_CAIRO
28487 x_cr_destroy_frame_context (f);
28488 #endif
28489 #ifdef USE_X_TOOLKIT
28490 if (f->output_data.x->widget)
28491 {
28492 XtDestroyWidget (f->output_data.x->widget);
28493 f->output_data.x->widget = NULL;
28494 }
28495
28496
28497 else if (FRAME_X_WINDOW (f))
28498 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
28499
28500 free_frame_menubar (f);
28501
28502 if (f->shell_position)
28503 xfree (f->shell_position);
28504 #else
28505
28506 #ifdef HAVE_XWIDGETS
28507 kill_frame_xwidget_views (f);
28508 #endif
28509
28510 #ifdef USE_GTK
28511 xg_free_frame_widgets (f);
28512 #endif
28513
28514 tear_down_x_back_buffer (f);
28515 if (FRAME_X_WINDOW (f))
28516 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
28517 #endif
28518
28519 #ifdef HAVE_XSYNC
28520 if (FRAME_X_BASIC_COUNTER (f) != None)
28521 XSyncDestroyCounter (FRAME_X_DISPLAY (f),
28522 FRAME_X_BASIC_COUNTER (f));
28523
28524 if (FRAME_X_EXTENDED_COUNTER (f) != None)
28525 XSyncDestroyCounter (FRAME_X_DISPLAY (f),
28526 FRAME_X_EXTENDED_COUNTER (f));
28527 #endif
28528
28529 unload_color (f, FRAME_FOREGROUND_PIXEL (f));
28530 unload_color (f, FRAME_BACKGROUND_PIXEL (f));
28531 unload_color (f, f->output_data.x->cursor_pixel);
28532 unload_color (f, f->output_data.x->cursor_foreground_pixel);
28533 unload_color (f, f->output_data.x->border_pixel);
28534 unload_color (f, f->output_data.x->mouse_pixel);
28535
28536 if (f->output_data.x->scroll_bar_background_pixel != -1)
28537 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
28538 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
28539 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
28540 #if defined (USE_LUCID) && defined (USE_TOOLKIT_SCROLL_BARS)
28541
28542 if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
28543 unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
28544 if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
28545 unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
28546 #endif
28547 if (f->output_data.x->white_relief.pixel != -1)
28548 unload_color (f, f->output_data.x->white_relief.pixel);
28549 if (f->output_data.x->black_relief.pixel != -1)
28550 unload_color (f, f->output_data.x->black_relief.pixel);
28551
28552 x_free_gcs (f);
28553
28554
28555 if (f->output_data.x->white_relief.gc)
28556 {
28557 XFreeGC (dpyinfo->display, f->output_data.x->white_relief.gc);
28558 f->output_data.x->white_relief.gc = 0;
28559 }
28560 if (f->output_data.x->black_relief.gc)
28561 {
28562 XFreeGC (dpyinfo->display, f->output_data.x->black_relief.gc);
28563 f->output_data.x->black_relief.gc = 0;
28564 }
28565
28566
28567 if (f->output_data.x->text_cursor != 0)
28568 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->text_cursor);
28569 if (f->output_data.x->nontext_cursor != 0)
28570 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->nontext_cursor);
28571 if (f->output_data.x->modeline_cursor != 0)
28572 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->modeline_cursor);
28573 if (f->output_data.x->hand_cursor != 0)
28574 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->hand_cursor);
28575 if (f->output_data.x->hourglass_cursor != 0)
28576 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->hourglass_cursor);
28577 if (f->output_data.x->horizontal_drag_cursor != 0)
28578 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->horizontal_drag_cursor);
28579 if (f->output_data.x->vertical_drag_cursor != 0)
28580 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->vertical_drag_cursor);
28581 if (f->output_data.x->left_edge_cursor != 0)
28582 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->left_edge_cursor);
28583 if (f->output_data.x->top_left_corner_cursor != 0)
28584 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->top_left_corner_cursor);
28585 if (f->output_data.x->top_edge_cursor != 0)
28586 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->top_edge_cursor);
28587 if (f->output_data.x->top_right_corner_cursor != 0)
28588 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->top_right_corner_cursor);
28589 if (f->output_data.x->right_edge_cursor != 0)
28590 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->right_edge_cursor);
28591 if (f->output_data.x->bottom_right_corner_cursor != 0)
28592 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->bottom_right_corner_cursor);
28593 if (f->output_data.x->bottom_edge_cursor != 0)
28594 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->bottom_edge_cursor);
28595 if (f->output_data.x->bottom_left_corner_cursor != 0)
28596 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->bottom_left_corner_cursor);
28597
28598
28599 #if defined HAVE_XSYNCTRIGGERFENCE && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
28600 x_sync_free_fences (f);
28601 #endif
28602
28603 #ifdef USE_TOOLKIT_SCROLL_BARS
28604
28605
28606
28607 dpyinfo->n_protected_windows = 0;
28608 #endif
28609 }
28610
28611 #ifdef HAVE_GTK3
28612 if (FRAME_OUTPUT_DATA (f)->scrollbar_background_css_provider)
28613 g_object_unref (FRAME_OUTPUT_DATA (f)->scrollbar_background_css_provider);
28614
28615 if (FRAME_OUTPUT_DATA (f)->scrollbar_foreground_css_provider)
28616 g_object_unref (FRAME_OUTPUT_DATA (f)->scrollbar_foreground_css_provider);
28617 #endif
28618
28619 if (f == dpyinfo->motif_drag_atom_owner)
28620 {
28621 dpyinfo->motif_drag_atom_owner = NULL;
28622 dpyinfo->motif_drag_atom = None;
28623 }
28624
28625 if (f == dpyinfo->x_focus_frame)
28626 dpyinfo->x_focus_frame = 0;
28627 if (f == dpyinfo->x_focus_event_frame)
28628 dpyinfo->x_focus_event_frame = 0;
28629 if (f == dpyinfo->highlight_frame)
28630 dpyinfo->highlight_frame = 0;
28631 if (f == hlinfo->mouse_face_mouse_frame)
28632 reset_mouse_highlight (hlinfo);
28633
28634 #ifdef HAVE_XINPUT2
28635
28636
28637
28638
28639
28640 if (dpyinfo->supports_xi2)
28641 xi_handle_focus_change (dpyinfo);
28642 #endif
28643
28644 unblock_input ();
28645 }
28646
28647
28648
28649
28650 static void
28651 x_destroy_window (struct frame *f)
28652 {
28653 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
28654
28655
28656
28657 if (dpyinfo->display != 0)
28658 x_free_frame_resources (f);
28659
28660 xfree (f->output_data.x->saved_menu_event);
28661
28662 #ifdef HAVE_X_I18N
28663 if (f->output_data.x->preedit_chars)
28664 xfree (f->output_data.x->preedit_chars);
28665 #endif
28666
28667 #ifdef HAVE_XINPUT2
28668 #ifdef HAVE_XINPUT2_1
28669 if (f->output_data.x->xi_masks)
28670 XFree (f->output_data.x->xi_masks);
28671 #else
28672
28673
28674 if (f->output_data.x->xi_masks)
28675 xfree (f->output_data.x->xi_masks);
28676 #endif
28677 #endif
28678
28679 xfree (f->output_data.x);
28680 f->output_data.x = NULL;
28681
28682 dpyinfo->reference_count--;
28683 }
28684
28685
28686
28687
28688
28689
28690 Atom
28691 x_intern_cached_atom (struct x_display_info *dpyinfo,
28692 const char *name, bool predefined_only)
28693 {
28694 int i;
28695 char *ptr;
28696 Atom *atom;
28697
28698
28699 char xsettings_atom_name[sizeof "_XSETTINGS_S%d" - 2
28700 + INT_STRLEN_BOUND (int)];
28701 char cm_atom_name[sizeof "_NET_WM_CM_S%d" - 2
28702 + INT_STRLEN_BOUND (int)];
28703
28704 sprintf (xsettings_atom_name, "_XSETTINGS_S%d",
28705 XScreenNumberOfScreen (dpyinfo->screen));
28706 sprintf (cm_atom_name, "_NET_WM_CM_S%d",
28707 XScreenNumberOfScreen (dpyinfo->screen));
28708
28709 if (!strcmp (name, xsettings_atom_name))
28710 return dpyinfo->Xatom_xsettings_sel;
28711
28712 if (!strcmp (name, cm_atom_name))
28713 return dpyinfo->Xatom_NET_WM_CM_Sn;
28714
28715
28716 if (!strcmp (name, "PRIMARY"))
28717 return XA_PRIMARY;
28718
28719 if (!strcmp (name, "SECONDARY"))
28720 return XA_SECONDARY;
28721
28722 if (!strcmp (name, "STRING"))
28723 return XA_STRING;
28724
28725 if (!strcmp (name, "INTEGER"))
28726 return XA_INTEGER;
28727
28728 if (!strcmp (name, "ATOM"))
28729 return XA_ATOM;
28730
28731 if (!strcmp (name, "WINDOW"))
28732 return XA_WINDOW;
28733
28734 if (!strcmp (name, "DRAWABLE"))
28735 return XA_DRAWABLE;
28736
28737 if (!strcmp (name, "BITMAP"))
28738 return XA_BITMAP;
28739
28740 if (!strcmp (name, "CARDINAL"))
28741 return XA_CARDINAL;
28742
28743 if (!strcmp (name, "COLORMAP"))
28744 return XA_COLORMAP;
28745
28746 if (!strcmp (name, "CURSOR"))
28747 return XA_CURSOR;
28748
28749 if (!strcmp (name, "FONT"))
28750 return XA_FONT;
28751
28752 if (dpyinfo->motif_drag_atom != None
28753 && !strcmp (name, dpyinfo->motif_drag_atom_name))
28754 return dpyinfo->motif_drag_atom;
28755
28756 for (i = 0; i < ARRAYELTS (x_atom_refs); ++i)
28757 {
28758 ptr = (char *) dpyinfo;
28759
28760 if (!strcmp (x_atom_refs[i].name, name))
28761 {
28762 atom = (Atom *) (ptr + x_atom_refs[i].offset);
28763
28764 return *atom;
28765 }
28766 }
28767
28768 if (predefined_only)
28769 return None;
28770
28771 return XInternAtom (dpyinfo->display, name, False);
28772 }
28773
28774
28775
28776
28777 char *
28778 x_get_atom_name (struct x_display_info *dpyinfo, Atom atom,
28779 bool *need_sync)
28780 {
28781 char *dpyinfo_pointer, *name, *value, *buffer;
28782 int i;
28783 Atom ref_atom;
28784
28785 dpyinfo_pointer = (char *) dpyinfo;
28786 value = NULL;
28787
28788 if (need_sync)
28789 *need_sync = false;
28790
28791 buffer = alloca (45 + INT_STRLEN_BOUND (int));
28792
28793 switch (atom)
28794 {
28795 case XA_PRIMARY:
28796 return xstrdup ("PRIMARY");
28797
28798 case XA_SECONDARY:
28799 return xstrdup ("SECONDARY");
28800
28801 case XA_INTEGER:
28802 return xstrdup ("INTEGER");
28803
28804 case XA_ATOM:
28805 return xstrdup ("ATOM");
28806
28807 case XA_CARDINAL:
28808 return xstrdup ("CARDINAL");
28809
28810 case XA_WINDOW:
28811 return xstrdup ("WINDOW");
28812
28813 case XA_DRAWABLE:
28814 return xstrdup ("DRAWABLE");
28815
28816 case XA_BITMAP:
28817 return xstrdup ("BITMAP");
28818
28819 case XA_COLORMAP:
28820 return xstrdup ("COLORMAP");
28821
28822 case XA_FONT:
28823 return xstrdup ("FONT");
28824
28825 default:
28826 if (dpyinfo->motif_drag_atom
28827 && atom == dpyinfo->motif_drag_atom)
28828 return xstrdup (dpyinfo->motif_drag_atom_name);
28829
28830 if (atom == dpyinfo->Xatom_xsettings_sel)
28831 {
28832 sprintf (buffer, "_XSETTINGS_S%d",
28833 XScreenNumberOfScreen (dpyinfo->screen));
28834 return xstrdup (buffer);
28835 }
28836
28837 if (atom == dpyinfo->Xatom_NET_WM_CM_Sn)
28838 {
28839 sprintf (buffer, "_NET_WM_CM_S%d",
28840 XScreenNumberOfScreen (dpyinfo->screen));
28841 return xstrdup (buffer);
28842 }
28843
28844 for (i = 0; i < ARRAYELTS (x_atom_refs); ++i)
28845 {
28846 ref_atom = *(Atom *) (dpyinfo_pointer
28847 + x_atom_refs[i].offset);
28848
28849 if (atom == ref_atom)
28850 return xstrdup (x_atom_refs[i].name);
28851 }
28852
28853 name = XGetAtomName (dpyinfo->display, atom);
28854
28855 if (need_sync)
28856 *need_sync = true;
28857
28858 if (name)
28859 {
28860 value = xstrdup (name);
28861 XFree (name);
28862 }
28863
28864 break;
28865 }
28866
28867 return value;
28868 }
28869
28870 #ifndef USE_GTK
28871
28872
28873
28874
28875 bool
28876 x_embed_frame (struct x_display_info *dpyinfo, struct frame *f)
28877 {
28878 bool rc;
28879
28880 x_catch_errors (dpyinfo->display);
28881
28882 XReparentWindow (dpyinfo->display, FRAME_OUTER_WINDOW (f),
28883 FRAME_OUTPUT_DATA (f)->parent_desc, 0, 0);
28884 rc = x_had_errors_p (dpyinfo->display);
28885 x_uncatch_errors_after_check ();
28886
28887 if (rc)
28888 return false;
28889
28890 return true;
28891 }
28892
28893 #endif
28894
28895
28896
28897
28898
28899
28900
28901
28902
28903
28904
28905 void
28906 x_wm_set_size_hint (struct frame *f, long flags, bool user_position)
28907 {
28908 #ifndef USE_GTK
28909 XSizeHints size_hints;
28910 Window window = FRAME_OUTER_WINDOW (f);
28911 #ifdef USE_X_TOOLKIT
28912 WMShellWidget shell;
28913 #ifndef USE_MOTIF
28914 bool hints_changed;
28915 #endif
28916 #endif
28917
28918 if (!window)
28919 return;
28920
28921 #ifdef USE_X_TOOLKIT
28922 if (f->output_data.x->widget)
28923 {
28924
28925
28926
28927 eassert (XtIsWMShell (f->output_data.x->widget));
28928 shell = (WMShellWidget) f->output_data.x->widget;
28929
28930 if (flags)
28931 {
28932 shell->wm.size_hints.flags &= ~(PPosition | USPosition);
28933 shell->wm.size_hints.flags |= flags & (PPosition | USPosition);
28934 }
28935
28936 if (user_position)
28937 {
28938 shell->wm.size_hints.flags &= ~PPosition;
28939 shell->wm.size_hints.flags |= USPosition;
28940 }
28941
28942 #ifndef USE_MOTIF
28943 hints_changed
28944 = widget_update_wm_size_hints (f->output_data.x->widget,
28945 f->output_data.x->edit_widget);
28946 #else
28947 widget_update_wm_size_hints (f->output_data.x->widget,
28948 f->output_data.x->edit_widget);
28949
28950
28951
28952 shell->wm.size_hints.flags &= ~(PPosition | USPosition);
28953 shell->wm.size_hints.flags |= flags & (PPosition | USPosition);
28954
28955 if (user_position)
28956 {
28957 shell->wm.size_hints.flags &= ~PPosition;
28958 shell->wm.size_hints.flags |= USPosition;
28959 }
28960 #endif
28961
28962
28963 size_hints.flags = shell->wm.size_hints.flags;
28964 size_hints.x = shell->wm.size_hints.x;
28965 size_hints.y = shell->wm.size_hints.y;
28966 size_hints.width = shell->wm.size_hints.width;
28967 size_hints.height = shell->wm.size_hints.height;
28968 size_hints.min_width = shell->wm.size_hints.min_width;
28969 size_hints.min_height = shell->wm.size_hints.min_height;
28970 size_hints.max_width = shell->wm.size_hints.max_width;
28971 size_hints.max_height = shell->wm.size_hints.max_height;
28972 size_hints.width_inc = shell->wm.size_hints.width_inc;
28973 size_hints.height_inc = shell->wm.size_hints.height_inc;
28974 size_hints.min_aspect.x = shell->wm.size_hints.min_aspect.x;
28975 size_hints.min_aspect.y = shell->wm.size_hints.min_aspect.y;
28976 size_hints.max_aspect.x = shell->wm.size_hints.max_aspect.x;
28977 size_hints.max_aspect.y = shell->wm.size_hints.max_aspect.y;
28978 size_hints.base_width = shell->wm.base_width;
28979 size_hints.base_height = shell->wm.base_height;
28980 size_hints.win_gravity = shell->wm.win_gravity;
28981
28982 #ifdef USE_MOTIF
28983 XSetWMNormalHints (XtDisplay (f->output_data.x->widget),
28984 XtWindow (f->output_data.x->widget),
28985 &size_hints);
28986 #else
28987
28988
28989
28990
28991 if (!hints_changed)
28992 XSetWMNormalHints (XtDisplay (f->output_data.x->widget),
28993 XtWindow (f->output_data.x->widget),
28994 &size_hints);
28995 #endif
28996
28997 return;
28998 }
28999 #endif
29000
29001
29002 size_hints.flags = PResizeInc | PMinSize ;
29003
29004 size_hints.x = f->left_pos;
29005 size_hints.y = f->top_pos;
29006
29007 size_hints.width = FRAME_PIXEL_WIDTH (f);
29008 size_hints.height = FRAME_PIXEL_HEIGHT (f);
29009
29010 size_hints.width_inc = frame_resize_pixelwise ? 1 : FRAME_COLUMN_WIDTH (f);
29011 size_hints.height_inc = frame_resize_pixelwise ? 1 : FRAME_LINE_HEIGHT (f);
29012
29013 size_hints.max_width = x_display_pixel_width (FRAME_DISPLAY_INFO (f))
29014 - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
29015 size_hints.max_height = x_display_pixel_height (FRAME_DISPLAY_INFO (f))
29016 - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
29017
29018
29019 {
29020 int base_width, base_height;
29021
29022 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
29023 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
29024
29025
29026
29027
29028
29029
29030
29031 size_hints.flags |= PBaseSize;
29032 size_hints.base_width = base_width;
29033 size_hints.base_height = base_height + FRAME_MENUBAR_HEIGHT (f);
29034 size_hints.min_width = base_width;
29035 size_hints.min_height = base_height;
29036 }
29037
29038
29039 if (flags)
29040 {
29041 size_hints.flags |= flags;
29042 goto no_read;
29043 }
29044
29045 {
29046 XSizeHints hints;
29047 long supplied_return;
29048 int value;
29049
29050 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
29051 &supplied_return);
29052
29053 if (flags)
29054 size_hints.flags |= flags;
29055 else
29056 {
29057 if (value == 0)
29058 hints.flags = 0;
29059 if (hints.flags & PSize)
29060 size_hints.flags |= PSize;
29061 if (hints.flags & PPosition)
29062 size_hints.flags |= PPosition;
29063 if (hints.flags & USPosition)
29064 size_hints.flags |= USPosition;
29065 if (hints.flags & USSize)
29066 size_hints.flags |= USSize;
29067 }
29068 }
29069
29070 no_read:
29071
29072 #ifdef PWinGravity
29073 size_hints.win_gravity = f->win_gravity;
29074 size_hints.flags |= PWinGravity;
29075
29076 if (user_position)
29077 {
29078 size_hints.flags &= ~ PPosition;
29079 size_hints.flags |= USPosition;
29080 }
29081 #endif
29082
29083 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
29084 #else
29085 xg_wm_set_size_hint (f, flags, user_position);
29086 #endif
29087 }
29088
29089
29090
29091 static void
29092 x_wm_set_window_state (struct frame *f, int state)
29093 {
29094 #ifdef USE_X_TOOLKIT
29095 Arg al[1];
29096
29097 XtSetArg (al[0], XtNinitialState, state);
29098 XtSetValues (f->output_data.x->widget, al, 1);
29099 #else
29100 Window window = FRAME_X_WINDOW (f);
29101
29102 f->output_data.x->wm_hints.flags |= StateHint;
29103 f->output_data.x->wm_hints.initial_state = state;
29104
29105 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
29106 #endif
29107 }
29108
29109 static void
29110 x_wm_set_icon_pixmap (struct frame *f, ptrdiff_t pixmap_id)
29111 {
29112 Pixmap icon_pixmap, icon_mask;
29113
29114 #if !defined USE_X_TOOLKIT && !defined USE_GTK
29115 Window window = FRAME_OUTER_WINDOW (f);
29116 #endif
29117
29118 if (pixmap_id > 0)
29119 {
29120 icon_pixmap = image_bitmap_pixmap (f, pixmap_id);
29121 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
29122 icon_mask = x_bitmap_mask (f, pixmap_id);
29123 f->output_data.x->wm_hints.icon_mask = icon_mask;
29124 }
29125 else
29126 {
29127
29128
29129 return;
29130 }
29131
29132
29133 #ifdef USE_GTK
29134 {
29135 xg_set_frame_icon (f, icon_pixmap, icon_mask);
29136 return;
29137 }
29138
29139 #elif defined (USE_X_TOOLKIT)
29140
29141 {
29142 Arg al[1];
29143 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
29144 XtSetValues (f->output_data.x->widget, al, 1);
29145 XtSetArg (al[0], XtNiconMask, icon_mask);
29146 XtSetValues (f->output_data.x->widget, al, 1);
29147 }
29148
29149 #else
29150
29151 f->output_data.x->wm_hints.flags |= (IconPixmapHint | IconMaskHint);
29152 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
29153
29154 #endif
29155 }
29156
29157 void
29158 x_wm_set_icon_position (struct frame *f, int icon_x, int icon_y)
29159 {
29160 Window window = FRAME_OUTER_WINDOW (f);
29161
29162 f->output_data.x->wm_hints.flags |= IconPositionHint;
29163 f->output_data.x->wm_hints.icon_x = icon_x;
29164 f->output_data.x->wm_hints.icon_y = icon_y;
29165
29166 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
29167 }
29168
29169
29170
29171
29172
29173
29174 #ifdef GLYPH_DEBUG
29175
29176
29177
29178
29179 static void
29180 x_check_font (struct frame *f, struct font *font)
29181 {
29182 eassert (font != NULL && ! NILP (font->props[FONT_TYPE_INDEX]));
29183 if (font->driver->check)
29184 eassert (font->driver->check (f, font) == 0);
29185 }
29186
29187 #endif
29188
29189
29190
29191
29192
29193
29194 static void
29195 x_free_pixmap (struct frame *f, Emacs_Pixmap pixmap)
29196 {
29197 #ifdef USE_CAIRO
29198 if (pixmap)
29199 {
29200 xfree (pixmap->data);
29201 xfree (pixmap);
29202 }
29203 #else
29204 XFreePixmap (FRAME_X_DISPLAY (f), pixmap);
29205 #endif
29206 }
29207
29208
29209
29210
29211
29212
29213 #ifdef USE_X_TOOLKIT
29214 static XrmOptionDescRec emacs_options[] = {
29215 {(char *) "-geometry", (char *) ".geometry", XrmoptionSepArg, NULL},
29216 {(char *) "-iconic", (char *) ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
29217
29218 {(char *) "-internal-border-width",
29219 (char *) "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
29220 {(char *) "-ib", (char *) "*EmacsScreen.internalBorderWidth",
29221 XrmoptionSepArg, NULL},
29222 {(char *) "-T", (char *) "*EmacsShell.title", XrmoptionSepArg, NULL},
29223 {(char *) "-wn", (char *) "*EmacsShell.title", XrmoptionSepArg, NULL},
29224 {(char *) "-title", (char *) "*EmacsShell.title", XrmoptionSepArg, NULL},
29225 {(char *) "-iconname", (char *) "*EmacsShell.iconName",
29226 XrmoptionSepArg, NULL},
29227 {(char *) "-in", (char *) "*EmacsShell.iconName", XrmoptionSepArg, NULL},
29228 {(char *) "-mc", (char *) "*pointerColor", XrmoptionSepArg, NULL},
29229 {(char *) "-cr", (char *) "*cursorColor", XrmoptionSepArg, NULL}
29230 };
29231
29232
29233
29234 static bool x_timeout_atimer_activated_flag;
29235
29236 #endif
29237
29238 static int x_initialized;
29239
29240
29241
29242 static bool
29243 same_x_server (const char *name1, const char *name2)
29244 {
29245 bool seen_colon = false;
29246 Lisp_Object sysname = Fsystem_name ();
29247 if (! STRINGP (sysname))
29248 sysname = empty_unibyte_string;
29249 const char *system_name = SSDATA (sysname);
29250 ptrdiff_t system_name_length = SBYTES (sysname);
29251 ptrdiff_t length_until_period = 0;
29252
29253 while (system_name[length_until_period] != 0
29254 && system_name[length_until_period] != '.')
29255 length_until_period++;
29256
29257
29258 if (! strncmp (name1, "unix:", 5))
29259 name1 += 4;
29260 if (! strncmp (name2, "unix:", 5))
29261 name2 += 4;
29262
29263 if (! strncmp (name1, system_name, system_name_length)
29264 && name1[system_name_length] == ':')
29265 name1 += system_name_length;
29266 if (! strncmp (name2, system_name, system_name_length)
29267 && name2[system_name_length] == ':')
29268 name2 += system_name_length;
29269
29270 if (! strncmp (name1, system_name, length_until_period)
29271 && name1[length_until_period] == ':')
29272 name1 += length_until_period;
29273 if (! strncmp (name2, system_name, length_until_period)
29274 && name2[length_until_period] == ':')
29275 name2 += length_until_period;
29276
29277 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
29278 {
29279 if (*name1 == ':')
29280 seen_colon = true;
29281 if (seen_colon && *name1 == '.')
29282 return true;
29283 }
29284 return (seen_colon
29285 && (*name1 == '.' || *name1 == '\0')
29286 && (*name2 == '.' || *name2 == '\0'));
29287 }
29288
29289
29290
29291
29292 static void
29293 get_bits_and_offset (unsigned long mask, int *bits, int *offset)
29294 {
29295 int nr = 0;
29296 int off = 0;
29297
29298 while (!(mask & 1))
29299 {
29300 off++;
29301 mask >>= 1;
29302 }
29303
29304 while (mask & 1)
29305 {
29306 nr++;
29307 mask >>= 1;
29308 }
29309
29310 *offset = off;
29311 *bits = nr;
29312 }
29313
29314
29315
29316
29317 bool
29318 x_display_ok (const char *display)
29319 {
29320
29321 unrequest_sigio ();
29322 Display *dpy = XOpenDisplay (display);
29323 request_sigio ();
29324 if (!dpy)
29325 return false;
29326 XCloseDisplay (dpy);
29327 return true;
29328 }
29329
29330 #ifdef USE_GTK
29331 static void
29332 my_log_handler (const gchar *log_domain, GLogLevelFlags log_level,
29333 const gchar *msg, gpointer user_data)
29334 {
29335 if (!strstr (msg, "g_set_prgname"))
29336 fprintf (stderr, "%s-WARNING **: %s\n", log_domain, msg);
29337 }
29338 #endif
29339
29340
29341
29342 static unsigned x_display_id;
29343
29344 #if defined HAVE_XINPUT2 && !defined HAVE_GTK3
29345
29346
29347
29348
29349 static void
29350 xi_select_hierarchy_events (struct x_display_info *dpyinfo)
29351 {
29352 XIEventMask mask;
29353 ptrdiff_t l;
29354 unsigned char *m;
29355
29356 l = XIMaskLen (XI_LASTEVENT);
29357 mask.mask = m = alloca (l);
29358 memset (m, 0, l);
29359 mask.mask_len = l;
29360
29361 mask.deviceid = XIAllDevices;
29362
29363 XISetMask (m, XI_PropertyEvent);
29364 XISetMask (m, XI_HierarchyChanged);
29365 XISetMask (m, XI_DeviceChanged);
29366
29367 XISelectEvents (dpyinfo->display, dpyinfo->root_window,
29368 &mask, 1);
29369 }
29370
29371 #endif
29372
29373 #if defined HAVE_XINPUT2 && defined HAVE_GTK3
29374
29375
29376
29377
29378
29379
29380
29381
29382
29383 static int
29384 xi_check_toolkit (Display *display)
29385 {
29386 GdkDisplay *gdpy;
29387 GdkDeviceManager *manager;
29388
29389 gdpy = gdk_x11_lookup_xdisplay (display);
29390 eassume (gdpy);
29391 manager = gdk_display_get_device_manager (gdpy);
29392
29393 if (!strcmp (G_OBJECT_TYPE_NAME (manager),
29394 "GdkX11DeviceManagerXI2"))
29395 return 1;
29396
29397 if (!strcmp (G_OBJECT_TYPE_NAME (manager),
29398 "GdkX11DeviceManagerCore"))
29399 return 0;
29400
29401
29402
29403
29404 return 2;
29405 }
29406
29407 #endif
29408
29409
29410
29411
29412
29413
29414 struct x_display_info *
29415 x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
29416 {
29417 Display *dpy;
29418 struct terminal *terminal;
29419 struct x_display_info *dpyinfo;
29420 XrmDatabase xrdb;
29421 #ifdef USE_XCB
29422 xcb_connection_t *xcb_conn;
29423 #endif
29424 static char const cm_atom_fmt[] = "_NET_WM_CM_S%d";
29425 char cm_atom_sprintf[sizeof cm_atom_fmt - 2 + INT_STRLEN_BOUND (int)];
29426 #ifdef USE_GTK
29427 GdkDisplay *gdpy;
29428 GdkScreen *gscr;
29429 #endif
29430 #ifdef HAVE_XFIXES
29431 Lisp_Object tem, lisp_name;
29432 int num_fast_selections;
29433 Atom selection_name;
29434 #ifdef USE_XCB
29435 xcb_get_selection_owner_cookie_t *selection_cookies;
29436 xcb_get_selection_owner_reply_t *selection_reply;
29437 xcb_generic_error_t *selection_error;
29438 #endif
29439 #endif
29440 int i;
29441
29442 #if defined HAVE_XFIXES && defined USE_XCB
29443 USE_SAFE_ALLOCA;
29444 #endif
29445
29446 block_input ();
29447
29448 if (!x_initialized)
29449 {
29450 x_initialize ();
29451 ++x_initialized;
29452 }
29453
29454 #if defined USE_X_TOOLKIT || defined USE_GTK
29455
29456 if (!x_display_ok (SSDATA (display_name)))
29457 error ("Display %s can't be opened", SSDATA (display_name));
29458
29459 #endif
29460
29461 #ifdef USE_GTK
29462 {
29463 #define NUM_ARGV 10
29464 int argc;
29465 char *argv[NUM_ARGV];
29466 char **argv2 = argv;
29467 guint id;
29468
29469 if (x_initialized++ > 1)
29470 {
29471 xg_display_open (SSDATA (display_name), &dpy);
29472 }
29473 else
29474 {
29475 static char display_opt[] = "--display";
29476 static char name_opt[] = "--name";
29477
29478 for (argc = 0; argc < NUM_ARGV; ++argc)
29479 argv[argc] = 0;
29480
29481 argc = 0;
29482 argv[argc++] = initial_argv[0];
29483
29484 if (! NILP (display_name))
29485 {
29486 argv[argc++] = display_opt;
29487 argv[argc++] = SSDATA (display_name);
29488 }
29489
29490 argv[argc++] = name_opt;
29491 argv[argc++] = resource_name;
29492
29493 XSetLocaleModifiers ("");
29494
29495
29496
29497 id = g_log_set_handler ("GLib", G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL
29498 | G_LOG_FLAG_RECURSION, my_log_handler, NULL);
29499
29500
29501
29502 gdk_window_add_filter (NULL, event_handler_gdk, NULL);
29503
29504
29505 fixup_locale ();
29506 unrequest_sigio ();
29507 gtk_init (&argc, &argv2);
29508 request_sigio ();
29509
29510 g_log_remove_handler ("GLib", id);
29511
29512 xg_initialize ();
29513
29514
29515
29516
29517 fixup_locale ();
29518
29519 dpy = DEFAULT_GDK_DISPLAY ();
29520
29521 #ifndef HAVE_GTK3
29522
29523 {
29524 const char *file = "~/.emacs.d/gtkrc";
29525 Lisp_Object s, abs_file;
29526
29527 s = build_string (file);
29528 abs_file = Fexpand_file_name (s, Qnil);
29529
29530 if (! NILP (abs_file) && !NILP (Ffile_readable_p (abs_file)))
29531 gtk_rc_parse (SSDATA (abs_file));
29532 }
29533 #endif
29534
29535 XSetErrorHandler (x_error_handler);
29536 XSetIOErrorHandler (x_io_error_quitter);
29537 }
29538 }
29539 #else
29540 #ifdef USE_X_TOOLKIT
29541
29542
29543
29544
29545
29546 #ifdef HAVE_X11XTR6
29547 XtSetLanguageProc (NULL, NULL, NULL);
29548 #endif
29549
29550 {
29551 int argc = 0;
29552 char *argv[3];
29553
29554 argv[0] = (char *) "";
29555 argc = 1;
29556 if (xrm_option)
29557 {
29558 argv[argc++] = (char *) "-xrm";
29559 argv[argc++] = xrm_option;
29560 }
29561 turn_on_atimers (false);
29562 unrequest_sigio ();
29563 dpy = XtOpenDisplay (Xt_app_con, SSDATA (display_name),
29564 resource_name, EMACS_CLASS,
29565 emacs_options, XtNumber (emacs_options),
29566 &argc, argv);
29567 request_sigio ();
29568 turn_on_atimers (true);
29569
29570 #ifdef HAVE_X11XTR6
29571
29572 fixup_locale ();
29573 #endif
29574 }
29575
29576 #else
29577 XSetLocaleModifiers ("");
29578 unrequest_sigio ();
29579 dpy = XOpenDisplay (SSDATA (display_name));
29580 request_sigio ();
29581 #endif
29582 #endif
29583
29584
29585 if (dpy == 0)
29586 {
29587 #if !defined USE_X_TOOLKIT && !defined USE_GTK
29588
29589
29590
29591
29592
29593 error ("Display %s can't be opened", SSDATA (display_name));
29594 #endif
29595
29596 unblock_input ();
29597
29598 #if defined HAVE_XFIXES && defined USE_XCB
29599 SAFE_FREE ();
29600 #endif
29601 return 0;
29602 }
29603
29604 #ifdef USE_XCB
29605 xcb_conn = XGetXCBConnection (dpy);
29606 if (!xcb_conn)
29607 {
29608 #ifdef USE_GTK
29609 xg_display_close (dpy);
29610 #else
29611 #ifdef USE_X_TOOLKIT
29612 XtCloseDisplay (dpy);
29613 #else
29614 XCloseDisplay (dpy);
29615 #endif
29616 #endif
29617
29618 unblock_input ();
29619
29620 #if defined HAVE_XFIXES && defined USE_XCB
29621 SAFE_FREE ();
29622 #endif
29623 return 0;
29624 }
29625 #endif
29626
29627
29628
29629
29630 XSelectInput (dpy, DefaultRootWindow (dpy), StructureNotifyMask);
29631
29632
29633
29634 dpyinfo = xzalloc (sizeof *dpyinfo);
29635 terminal = x_create_terminal (dpyinfo);
29636
29637 dpyinfo->next_failable_request = dpyinfo->failable_requests;
29638
29639 {
29640 struct x_display_info *share;
29641
29642 for (share = x_display_list; share; share = share->next)
29643 if (same_x_server (SSDATA (XCAR (share->name_list_element)),
29644 SSDATA (display_name)))
29645 break;
29646 if (share)
29647 terminal->kboard = share->terminal->kboard;
29648 else
29649 {
29650 terminal->kboard = allocate_kboard (Qx);
29651
29652 if (!BASE_EQ (XSYMBOL (Qvendor_specific_keysyms)->u.s.function,
29653 Qunbound))
29654 {
29655 char *vendor = ServerVendor (dpy);
29656
29657
29658 terminal_list = terminal->next_terminal;
29659 unblock_input ();
29660 kset_system_key_alist
29661 (terminal->kboard,
29662 call1 (Qvendor_specific_keysyms,
29663 vendor ? build_string (vendor) : empty_unibyte_string));
29664 block_input ();
29665 terminal->next_terminal = terminal_list;
29666 terminal_list = terminal;
29667 }
29668
29669
29670
29671
29672 if (current_kboard == initial_kboard)
29673 current_kboard = terminal->kboard;
29674 }
29675 terminal->kboard->reference_count++;
29676 }
29677
29678
29679 dpyinfo->next = x_display_list;
29680 x_display_list = dpyinfo;
29681
29682 dpyinfo->name_list_element = Fcons (display_name, Qnil);
29683 dpyinfo->display = dpy;
29684 dpyinfo->connection = ConnectionNumber (dpyinfo->display);
29685 #ifdef USE_XCB
29686 dpyinfo->xcb_connection = xcb_conn;
29687 #endif
29688
29689
29690 dpyinfo->smallest_font_height = 1;
29691 dpyinfo->smallest_char_width = 1;
29692
29693 dpyinfo->color_names_size = 256;
29694 dpyinfo->color_names = xzalloc (dpyinfo->color_names_size
29695 * sizeof *dpyinfo->color_names);
29696 dpyinfo->color_names_length = xzalloc (dpyinfo->color_names_size
29697 * sizeof *dpyinfo->color_names_length);
29698
29699
29700 terminal->name = xlispstrdup (display_name);
29701
29702 #if false
29703 XSetAfterFunction (dpyinfo->display, x_trace_wire);
29704 #endif
29705
29706 Lisp_Object system_name = Fsystem_name ();
29707 static char const title[] = "GNU Emacs";
29708 if (STRINGP (system_name))
29709 {
29710 static char const at[] = " at ";
29711 ptrdiff_t nbytes = sizeof (title) + sizeof (at);
29712 if (INT_ADD_WRAPV (nbytes, SBYTES (system_name), &nbytes))
29713 memory_full (SIZE_MAX);
29714 dpyinfo->x_id_name = xmalloc (nbytes);
29715 sprintf (dpyinfo->x_id_name, "%s%s%s", title, at, SDATA (system_name));
29716 }
29717 else
29718 {
29719 dpyinfo->x_id_name = xmalloc (sizeof (title));
29720 strcpy (dpyinfo->x_id_name, title);
29721 }
29722
29723 dpyinfo->x_id = ++x_display_id;
29724
29725 #ifndef HAVE_XKB
29726
29727 x_find_modifier_meanings (dpyinfo);
29728 #endif
29729
29730
29731 #ifdef USE_GTK
29732
29733 dpyinfo->xg_cursor = xg_create_default_cursor (dpyinfo->display);
29734 #endif
29735
29736 dpyinfo->vertical_scroll_bar_cursor
29737 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
29738
29739 dpyinfo->horizontal_scroll_bar_cursor
29740 = XCreateFontCursor (dpyinfo->display, XC_sb_h_double_arrow);
29741
29742 xrdb = x_load_resources (dpyinfo->display, xrm_option,
29743 resource_name, EMACS_CLASS);
29744 #ifdef HAVE_XRMSETDATABASE
29745 XrmSetDatabase (dpyinfo->display, xrdb);
29746 #else
29747 dpyinfo->display->db = xrdb;
29748 #endif
29749
29750 #ifdef HAVE_XRENDER
29751 int event_base, error_base;
29752 dpyinfo->xrender_supported_p
29753 = XRenderQueryExtension (dpyinfo->display, &event_base, &error_base);
29754
29755 if (dpyinfo->xrender_supported_p)
29756 dpyinfo->xrender_supported_p
29757 = XRenderQueryVersion (dpyinfo->display, &dpyinfo->xrender_major,
29758 &dpyinfo->xrender_minor);
29759 #endif
29760
29761
29762 #ifdef HAVE_XCOMPOSITE
29763 int composite_event_base, composite_error_base;
29764 dpyinfo->composite_supported_p = XCompositeQueryExtension (dpyinfo->display,
29765 &composite_event_base,
29766 &composite_error_base);
29767
29768 if (dpyinfo->composite_supported_p)
29769 dpyinfo->composite_supported_p
29770 = XCompositeQueryVersion (dpyinfo->display,
29771 &dpyinfo->composite_major,
29772 &dpyinfo->composite_minor);
29773 #endif
29774
29775 #ifdef HAVE_XSHAPE
29776 dpyinfo->xshape_supported_p
29777 = XShapeQueryExtension (dpyinfo->display,
29778 &dpyinfo->xshape_event_base,
29779 &dpyinfo->xshape_error_base);
29780
29781 if (dpyinfo->xshape_supported_p)
29782 dpyinfo->xshape_supported_p
29783 = XShapeQueryVersion (dpyinfo->display,
29784 &dpyinfo->xshape_major,
29785 &dpyinfo->xshape_minor);
29786 #endif
29787
29788
29789
29790 dpyinfo->rdb = xrdb;
29791
29792 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
29793 DefaultScreen (dpyinfo->display));
29794 select_visual (dpyinfo);
29795 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
29796 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
29797 dpyinfo->icon_bitmap_id = -1;
29798 dpyinfo->wm_type = X_WMTYPE_UNKNOWN;
29799
29800 reset_mouse_highlight (&dpyinfo->mouse_highlight);
29801
29802 #ifdef HAVE_XRENDER
29803 if (dpyinfo->xrender_supported_p
29804
29805
29806 && !dpyinfo->pict_format)
29807 dpyinfo->pict_format = XRenderFindVisualFormat (dpyinfo->display,
29808 dpyinfo->visual);
29809 #endif
29810
29811 #ifdef HAVE_XSYNC
29812 int xsync_event_base, xsync_error_base;
29813 dpyinfo->xsync_supported_p
29814 = XSyncQueryExtension (dpyinfo->display,
29815 &xsync_event_base,
29816 &xsync_error_base);
29817
29818 if (dpyinfo->xsync_supported_p)
29819 dpyinfo->xsync_supported_p = XSyncInitialize (dpyinfo->display,
29820 &dpyinfo->xsync_major,
29821 &dpyinfo->xsync_minor);
29822
29823 {
29824 AUTO_STRING (synchronizeResize, "synchronizeResize");
29825 AUTO_STRING (SynchronizeResize, "SynchronizeResize");
29826
29827 Lisp_Object value = gui_display_get_resource (dpyinfo,
29828 synchronizeResize,
29829 SynchronizeResize,
29830 Qnil, Qnil);
29831
29832 if (STRINGP (value)
29833 && (!strcmp (SSDATA (value), "false")
29834 || !strcmp (SSDATA (value), "off")))
29835 dpyinfo->xsync_supported_p = false;
29836 }
29837 #endif
29838
29839 #ifdef HAVE_XINERAMA
29840 int xin_event_base, xin_error_base;
29841 dpyinfo->xinerama_supported_p
29842 = XineramaQueryExtension (dpy, &xin_event_base, &xin_error_base);
29843 #endif
29844
29845
29846 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
29847 {
29848 if (dpyinfo->visual_info.class == PseudoColor)
29849 {
29850 AUTO_STRING (privateColormap, "privateColormap");
29851 AUTO_STRING (PrivateColormap, "PrivateColormap");
29852 Lisp_Object value
29853 = gui_display_get_resource (dpyinfo, privateColormap,
29854 PrivateColormap, Qnil, Qnil);
29855 if (STRINGP (value)
29856 && (!strcmp (SSDATA (value), "true")
29857 || !strcmp (SSDATA (value), "on")))
29858 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
29859 }
29860 }
29861 else
29862 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
29863 dpyinfo->visual, AllocNone);
29864
29865
29866 if (dpyinfo->visual_info.class == TrueColor)
29867 {
29868 get_bits_and_offset (dpyinfo->visual_info.red_mask,
29869 &dpyinfo->red_bits, &dpyinfo->red_offset);
29870 get_bits_and_offset (dpyinfo->visual_info.blue_mask,
29871 &dpyinfo->blue_bits, &dpyinfo->blue_offset);
29872 get_bits_and_offset (dpyinfo->visual_info.green_mask,
29873 &dpyinfo->green_bits, &dpyinfo->green_offset);
29874
29875 #ifdef HAVE_XRENDER
29876 if (dpyinfo->pict_format)
29877 {
29878 unsigned long channel_mask
29879 = ((unsigned long) dpyinfo->pict_format->direct.alphaMask
29880 << dpyinfo->pict_format->direct.alpha);
29881
29882 if (channel_mask)
29883 get_bits_and_offset (channel_mask, &dpyinfo->alpha_bits,
29884 &dpyinfo->alpha_offset);
29885 dpyinfo->alpha_mask = channel_mask;
29886 }
29887 else
29888 #endif
29889 {
29890 XColor xc;
29891 unsigned long alpha_mask;
29892 xc.red = 65535;
29893 xc.green = 65535;
29894 xc.blue = 65535;
29895
29896 if (XAllocColor (dpyinfo->display,
29897 dpyinfo->cmap, &xc) != 0)
29898 {
29899 alpha_mask = xc.pixel & ~(dpyinfo->visual_info.red_mask
29900 | dpyinfo->visual_info.blue_mask
29901 | dpyinfo->visual_info.green_mask);
29902
29903 if (alpha_mask)
29904 get_bits_and_offset (alpha_mask, &dpyinfo->alpha_bits,
29905 &dpyinfo->alpha_offset);
29906 dpyinfo->alpha_mask = alpha_mask;
29907 }
29908 }
29909 }
29910
29911 #ifdef HAVE_XDBE
29912 dpyinfo->supports_xdbe = false;
29913 int xdbe_major;
29914 int xdbe_minor;
29915 if (XdbeQueryExtension (dpyinfo->display, &xdbe_major, &xdbe_minor))
29916 dpyinfo->supports_xdbe = true;
29917 #endif
29918
29919 #ifdef USE_XCB
29920 xcb_screen_t *xcb_screen = NULL;
29921 xcb_screen_iterator_t iter;
29922 xcb_visualid_t wanted = { XVisualIDFromVisual (dpyinfo->visual) };
29923 xcb_depth_iterator_t depth_iter;
29924 xcb_visualtype_iterator_t visual_iter;
29925
29926 int screen = DefaultScreen (dpyinfo->display);
29927
29928 iter = xcb_setup_roots_iterator (xcb_get_setup (dpyinfo->xcb_connection));
29929 for (; iter.rem; --screen, xcb_screen_next (&iter))
29930 {
29931 if (!screen)
29932 xcb_screen = iter.data;
29933 }
29934
29935 if (xcb_screen)
29936 {
29937 depth_iter = xcb_screen_allowed_depths_iterator (xcb_screen);
29938 for (; depth_iter.rem; xcb_depth_next (&depth_iter))
29939 {
29940 visual_iter = xcb_depth_visuals_iterator (depth_iter.data);
29941 for (; visual_iter.rem; xcb_visualtype_next (&visual_iter))
29942 {
29943 if (wanted == visual_iter.data->visual_id)
29944 {
29945 dpyinfo->xcb_visual = visual_iter.data;
29946 break;
29947 }
29948 }
29949 }
29950 }
29951 #endif
29952
29953 #ifdef HAVE_XINPUT2
29954 dpyinfo->supports_xi2 = false;
29955 int rc;
29956 int major = 2;
29957 int xi_first_event, xi_first_error;
29958
29959 #ifndef HAVE_GTK3
29960 {
29961 AUTO_STRING (disableInputExtension, "disableInputExtension");
29962 AUTO_STRING (DisableInputExtension, "DisableInputExtension");
29963
29964 Lisp_Object value = gui_display_get_resource (dpyinfo,
29965 disableInputExtension,
29966 DisableInputExtension,
29967 Qnil, Qnil);
29968
29969 if (STRINGP (value)
29970 && (!strcmp (SSDATA (value), "on")
29971 || !strcmp (SSDATA (value), "true")))
29972 goto skip_xi_setup;
29973 }
29974 #endif
29975
29976 #ifdef HAVE_XINPUT2_4
29977 int minor = 4;
29978 #elif defined HAVE_XINPUT2_3
29979 int minor = 3;
29980 #elif defined HAVE_XINPUT2_2
29981 int minor = 2;
29982 #elif defined HAVE_XINPUT2_1
29983 int minor = 1;
29984 #else
29985 int minor = 0;
29986 #endif
29987
29988 dpyinfo->client_pointer_device = -1;
29989
29990 #ifdef HAVE_GTK3
29991
29992
29993
29994
29995 rc = xi_check_toolkit (dpyinfo->display);
29996
29997 if (!rc)
29998 goto skip_xi_setup;
29999 #endif
30000
30001 if (XQueryExtension (dpyinfo->display, "XInputExtension",
30002 &dpyinfo->xi2_opcode, &xi_first_event,
30003 &xi_first_error))
30004 {
30005 #ifdef HAVE_GTK3
30006 bool move_backwards = false;
30007 int original_minor = minor;
30008
30009 query:
30010
30011
30012
30013
30014
30015
30016
30017
30018
30019
30020
30021
30022 #endif
30023
30024 x_catch_errors (dpyinfo->display);
30025
30026 rc = XIQueryVersion (dpyinfo->display, &major, &minor);
30027
30028 #ifdef HAVE_GTK3
30029
30030
30031
30032
30033
30034 if (x_had_errors_p (dpyinfo->display))
30035 {
30036 x_uncatch_errors_after_check ();
30037
30038
30039
30040
30041
30042 if (minor >= 2)
30043 {
30044 move_backwards = true;
30045 minor = original_minor;
30046
30047 if (--minor < 0)
30048 rc = BadRequest;
30049 else
30050 goto query;
30051 }
30052 else
30053 {
30054 if (!move_backwards)
30055 {
30056 minor++;
30057 goto query;
30058 }
30059
30060 if (--minor < 0)
30061 rc = BadRequest;
30062 else
30063 goto query;
30064
30065 }
30066 }
30067 else
30068 x_uncatch_errors_after_check ();
30069
30070
30071
30072
30073
30074 if (minor > original_minor)
30075 minor = original_minor;
30076 #else
30077 if (x_had_errors_p (dpyinfo->display))
30078 rc = BadRequest;
30079
30080 x_uncatch_errors_after_check ();
30081 #endif
30082
30083 if (rc == Success)
30084 {
30085 dpyinfo->supports_xi2 = true;
30086 #ifndef HAVE_GTK3
30087
30088
30089 xi_select_hierarchy_events (dpyinfo);
30090 #endif
30091
30092 dpyinfo->xi2_version = minor;
30093 x_cache_xi_devices (dpyinfo);
30094 }
30095 }
30096 skip_xi_setup:
30097 ;
30098 #endif
30099
30100 #if defined HAVE_XRANDR || defined USE_GTK
30101 Lisp_Object term;
30102
30103 XSETTERMINAL (term, terminal);
30104 #endif
30105
30106 #ifdef HAVE_XRANDR
30107 dpyinfo->xrandr_supported_p
30108 = XRRQueryExtension (dpy, &dpyinfo->xrandr_event_base,
30109 &dpyinfo->xrandr_error_base);
30110
30111 #ifndef USE_GTK
30112 dpyinfo->last_monitor_attributes_list = Qnil;
30113 #endif
30114
30115 if (dpyinfo->xrandr_supported_p)
30116 {
30117 XRRQueryVersion (dpy, &dpyinfo->xrandr_major_version,
30118 &dpyinfo->xrandr_minor_version);
30119
30120 #ifndef USE_GTK
30121 if (dpyinfo->xrandr_major_version == 1
30122 && dpyinfo->xrandr_minor_version >= 2)
30123 {
30124 XRRSelectInput (dpyinfo->display,
30125 dpyinfo->root_window,
30126 (RRScreenChangeNotifyMask
30127 | RRCrtcChangeNotifyMask
30128 | RROutputChangeNotifyMask
30129 #ifdef USE_GTK
30130
30131
30132
30133 | RROutputPropertyNotifyMask
30134 #endif
30135 ));
30136
30137 dpyinfo->last_monitor_attributes_list
30138 = Fx_display_monitor_attributes_list (term);
30139 }
30140 #endif
30141 }
30142 #endif
30143
30144 #ifdef USE_GTK
30145 dpyinfo->last_monitor_attributes_list
30146 = Fx_display_monitor_attributes_list (term);
30147
30148 gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display);
30149 gscr = gdk_display_get_default_screen (gdpy);
30150
30151 g_signal_connect (G_OBJECT (gscr), "monitors-changed",
30152 G_CALLBACK (x_monitors_changed_cb),
30153 NULL);
30154 #endif
30155
30156 #ifdef HAVE_XKB
30157 int xkb_major, xkb_minor, xkb_op, xkb_error_code;
30158 xkb_major = XkbMajorVersion;
30159 xkb_minor = XkbMinorVersion;
30160
30161 if (XkbLibraryVersion (&xkb_major, &xkb_minor)
30162 && XkbQueryExtension (dpyinfo->display, &xkb_op, &dpyinfo->xkb_event_type,
30163 &xkb_error_code, &xkb_major, &xkb_minor))
30164 {
30165 dpyinfo->supports_xkb = true;
30166 dpyinfo->xkb_desc = XkbGetMap (dpyinfo->display,
30167 (XkbKeySymsMask
30168 | XkbKeyTypesMask
30169 | XkbModifierMapMask
30170 | XkbVirtualModsMask),
30171 XkbUseCoreKbd);
30172
30173 if (dpyinfo->xkb_desc)
30174 XkbGetNames (dpyinfo->display, XkbAllNamesMask,
30175 dpyinfo->xkb_desc);
30176
30177 XkbSelectEvents (dpyinfo->display, XkbUseCoreKbd,
30178 XkbNewKeyboardNotifyMask | XkbMapNotifyMask,
30179 XkbNewKeyboardNotifyMask | XkbMapNotifyMask);
30180 }
30181 #endif
30182
30183 #ifdef HAVE_XFIXES
30184 int xfixes_error_base;
30185 dpyinfo->xfixes_supported_p
30186 = XFixesQueryExtension (dpyinfo->display,
30187 &dpyinfo->xfixes_event_base,
30188 &xfixes_error_base);
30189
30190 if (dpyinfo->xfixes_supported_p)
30191 {
30192 if (!XFixesQueryVersion (dpyinfo->display, &dpyinfo->xfixes_major,
30193 &dpyinfo->xfixes_minor))
30194 dpyinfo->xfixes_supported_p = false;
30195 }
30196 #endif
30197
30198 #if defined USE_CAIRO || defined HAVE_XFT
30199 {
30200
30201
30202
30203
30204
30205
30206
30207
30208
30209
30210
30211
30212
30213
30214 char *v = XGetDefault (dpyinfo->display, "Xft", "dpi");
30215 double d;
30216 if (v != NULL && sscanf (v, "%lf", &d) == 1)
30217 dpyinfo->resy = dpyinfo->resx = d;
30218 }
30219 #endif
30220
30221 if (dpyinfo->resy < 1)
30222 {
30223 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
30224 double pixels = DisplayHeight (dpyinfo->display, screen_number);
30225 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
30226
30227 dpyinfo->resy = (mm < 1) ? 100 : pixels * 25.4 / mm;
30228 pixels = DisplayWidth (dpyinfo->display, screen_number);
30229 mm = DisplayWidthMM (dpyinfo->display, screen_number);
30230
30231 dpyinfo->resx = (mm < 1) ? 100 : pixels * 25.4 / mm;
30232 }
30233
30234 sprintf (cm_atom_sprintf, cm_atom_fmt,
30235 XScreenNumberOfScreen (dpyinfo->screen));
30236
30237 {
30238 enum { atom_count = ARRAYELTS (x_atom_refs) };
30239
30240 enum { total_atom_count = 2 + atom_count };
30241 Atom atoms_return[total_atom_count];
30242 char *atom_names[total_atom_count];
30243 static char const xsettings_fmt[] = "_XSETTINGS_S%d";
30244 char xsettings_atom_name[sizeof xsettings_fmt - 2
30245 + INT_STRLEN_BOUND (int)];
30246
30247 for (i = 0; i < atom_count; i++)
30248 atom_names[i] = (char *) x_atom_refs[i].name;
30249
30250
30251 sprintf (xsettings_atom_name, xsettings_fmt,
30252 XScreenNumberOfScreen (dpyinfo->screen));
30253 atom_names[i] = xsettings_atom_name;
30254 atom_names[i + 1] = cm_atom_sprintf;
30255
30256 XInternAtoms (dpyinfo->display, atom_names, total_atom_count,
30257 False, atoms_return);
30258
30259 for (i = 0; i < atom_count; i++)
30260 *(Atom *) ((char *) dpyinfo + x_atom_refs[i].offset) = atoms_return[i];
30261
30262
30263 dpyinfo->Xatom_xsettings_sel = atoms_return[i];
30264 dpyinfo->Xatom_NET_WM_CM_Sn = atoms_return[i + 1];
30265 }
30266
30267 #ifdef HAVE_XKB
30268
30269 x_find_modifier_meanings (dpyinfo);
30270 #endif
30271
30272 dpyinfo->x_dnd_atoms_size = 16;
30273 dpyinfo->x_dnd_atoms = xmalloc (sizeof *dpyinfo->x_dnd_atoms
30274 * dpyinfo->x_dnd_atoms_size);
30275 dpyinfo->gray
30276 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
30277 gray_bits, gray_width, gray_height,
30278 1, 0, 1);
30279
30280 dpyinfo->invisible_cursor = make_invisible_cursor (dpyinfo);
30281 #ifdef HAVE_XFIXES
30282 dpyinfo->fixes_pointer_blanking = egetenv ("EMACS_XFIXES");
30283 #endif
30284
30285 #ifdef HAVE_X_I18N
30286
30287
30288
30289 if (XSupportsLocale ())
30290 xim_initialize (dpyinfo, resource_name);
30291 #endif
30292
30293 xsettings_initialize (dpyinfo);
30294
30295
30296 if (dpyinfo->connection != 0)
30297 add_keyboard_wait_descriptor (dpyinfo->connection);
30298
30299 #ifdef F_SETOWN
30300 fcntl (dpyinfo->connection, F_SETOWN, getpid ());
30301 #endif
30302
30303 if (interrupt_input)
30304 init_sigio (dpyinfo->connection);
30305
30306 #ifdef USE_LUCID
30307 {
30308 XrmValue d, fr, to;
30309 Font font;
30310 XFontStruct *query_result;
30311
30312 dpy = dpyinfo->display;
30313 d.addr = (XPointer) &dpy;
30314 d.size = sizeof (Display *);
30315 fr.addr = (char *) XtDefaultFont;
30316 fr.size = sizeof (XtDefaultFont);
30317 to.size = sizeof (Font *);
30318 to.addr = (XPointer) &font;
30319 x_catch_errors (dpy);
30320 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
30321 emacs_abort ();
30322 query_result = XQueryFont (dpy, font);
30323
30324
30325
30326 if (x_had_errors_p (dpy) || !font)
30327 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
30328
30329
30330
30331
30332
30333 XFreeFontInfo (NULL, query_result, 1);
30334 x_uncatch_errors ();
30335 }
30336 #endif
30337
30338
30339
30340 {
30341 AUTO_STRING (synchronous, "synchronous");
30342 AUTO_STRING (Synchronous, "Synchronous");
30343 Lisp_Object value = gui_display_get_resource (dpyinfo, synchronous,
30344 Synchronous, Qnil, Qnil);
30345 if (STRINGP (value)
30346 && (!strcmp (SSDATA (value), "true")
30347 || !strcmp (SSDATA (value), "on")))
30348 XSynchronize (dpyinfo->display, True);
30349 }
30350
30351 {
30352 AUTO_STRING (useXIM, "useXIM");
30353 AUTO_STRING (UseXIM, "UseXIM");
30354 Lisp_Object value = gui_display_get_resource (dpyinfo, useXIM, UseXIM,
30355 Qnil, Qnil);
30356 #ifdef USE_XIM
30357 if (STRINGP (value)
30358 && (!strcmp (SSDATA (value), "false")
30359 || !strcmp (SSDATA (value), "off")))
30360 use_xim = false;
30361 #else
30362 if (STRINGP (value)
30363 && (!strcmp (SSDATA (value), "true")
30364 || !strcmp (SSDATA (value), "on")))
30365 use_xim = true;
30366 #endif
30367 }
30368
30369 #ifdef HAVE_X_I18N
30370 {
30371 AUTO_STRING (inputStyle, "inputStyle");
30372 AUTO_STRING (InputStyle, "InputStyle");
30373 Lisp_Object value = gui_display_get_resource (dpyinfo, inputStyle, InputStyle,
30374 Qnil, Qnil);
30375
30376 if (STRINGP (value))
30377 {
30378 if (!strcmp (SSDATA (value), "callback"))
30379 dpyinfo->preferred_xim_style = STYLE_CALLBACK;
30380 else if (!strcmp (SSDATA (value), "none"))
30381 dpyinfo->preferred_xim_style = STYLE_NONE;
30382 else if (!strcmp (SSDATA (value), "overthespot"))
30383 dpyinfo->preferred_xim_style = STYLE_OVERTHESPOT;
30384 else if (!strcmp (SSDATA (value), "offthespot"))
30385 dpyinfo->preferred_xim_style = STYLE_OFFTHESPOT;
30386 else if (!strcmp (SSDATA (value), "root"))
30387 dpyinfo->preferred_xim_style = STYLE_ROOT;
30388 #ifdef USE_GTK
30389 else if (!strcmp (SSDATA (value), "native"))
30390 dpyinfo->prefer_native_input = true;
30391 #endif
30392 }
30393 }
30394 #endif
30395
30396 #ifdef HAVE_X_SM
30397
30398
30399
30400 if (!dpyinfo->next && ! IS_DAEMON)
30401 x_session_initialize (dpyinfo);
30402 #endif
30403
30404 #if defined USE_CAIRO || defined HAVE_XRENDER
30405 x_extension_initialize (dpyinfo);
30406 #endif
30407
30408 #ifdef USE_TOOLKIT_SCROLL_BARS
30409 dpyinfo->protected_windows = xmalloc (sizeof (Lisp_Object) * 256);
30410 dpyinfo->n_protected_windows = 0;
30411 dpyinfo->protected_windows_max = 256;
30412 #endif
30413
30414 #ifdef HAVE_XFIXES
30415
30416
30417
30418 if (CONSP (Vx_fast_selection_list)
30419 && dpyinfo->xfixes_supported_p
30420 && dpyinfo->xfixes_major >= 1)
30421 {
30422 num_fast_selections = 0;
30423 tem = Vx_fast_selection_list;
30424
30425 FOR_EACH_TAIL_SAFE (tem)
30426 {
30427 if (!SYMBOLP (XCAR (tem)))
30428 continue;
30429
30430 num_fast_selections++;
30431 }
30432
30433 dpyinfo->n_monitored_selections = num_fast_selections;
30434 dpyinfo->selection_tracking_window
30435 = x_create_special_window (dpyinfo, dpyinfo->root_window);
30436 dpyinfo->monitored_selections
30437 = xmalloc (num_fast_selections
30438 * sizeof *dpyinfo->monitored_selections);
30439
30440 num_fast_selections = 0;
30441 tem = Vx_fast_selection_list;
30442
30443 FOR_EACH_TAIL_SAFE (tem)
30444 {
30445 lisp_name = XCAR (tem);
30446
30447 if (!SYMBOLP (lisp_name))
30448 continue;
30449
30450 selection_name = symbol_to_x_atom (dpyinfo, lisp_name);
30451 dpyinfo->monitored_selections[num_fast_selections++].name
30452 = selection_name;
30453 dpyinfo->monitored_selections[num_fast_selections - 1].owner
30454 = X_INVALID_WINDOW;
30455
30456
30457 XFixesSelectSelectionInput (dpyinfo->display,
30458 dpyinfo->selection_tracking_window,
30459 selection_name,
30460 (XFixesSetSelectionOwnerNotifyMask
30461 | XFixesSetSelectionOwnerNotifyMask
30462 | XFixesSelectionClientCloseNotifyMask));
30463 }
30464
30465 #ifdef USE_XCB
30466 selection_cookies = SAFE_ALLOCA (sizeof *selection_cookies
30467 * num_fast_selections);
30468 #endif
30469
30470
30471 for (i = 0; i < num_fast_selections; ++i)
30472 {
30473 #ifdef USE_XCB
30474 selection_cookies[i]
30475 = xcb_get_selection_owner (dpyinfo->xcb_connection,
30476 dpyinfo->monitored_selections[i].name);
30477 #else
30478 dpyinfo->monitored_selections[i].owner
30479 = XGetSelectionOwner (dpyinfo->display,
30480 dpyinfo->monitored_selections[i].name);
30481 #endif
30482 }
30483
30484 #ifdef USE_XCB
30485 for (i = 0; i < num_fast_selections; ++i)
30486 {
30487 selection_reply
30488 = xcb_get_selection_owner_reply (dpyinfo->xcb_connection,
30489 selection_cookies[i],
30490 &selection_error);
30491
30492 if (selection_reply)
30493 {
30494 dpyinfo->monitored_selections[i].owner
30495 = selection_reply->owner;
30496 free (selection_reply);
30497 }
30498 else if (selection_error)
30499 free (selection_error);
30500 }
30501 #endif
30502 }
30503 #endif
30504
30505 unblock_input ();
30506
30507 #if defined HAVE_XFIXES && defined USE_XCB
30508 SAFE_FREE ();
30509 #endif
30510 return dpyinfo;
30511 }
30512
30513
30514
30515
30516
30517
30518 static void
30519 x_delete_selection_requests (struct x_display_info *dpyinfo)
30520 {
30521 union buffered_input_event *event;
30522 int moved_events;
30523
30524 for (event = kbd_fetch_ptr; event != kbd_store_ptr;
30525 event = X_NEXT_KBD_EVENT (event))
30526 {
30527 if (event->kind == SELECTION_REQUEST_EVENT
30528 || event->kind == SELECTION_CLEAR_EVENT)
30529 {
30530 if (SELECTION_EVENT_DPYINFO (&event->sie) != dpyinfo)
30531 continue;
30532
30533
30534
30535
30536
30537
30538
30539 if (event < kbd_fetch_ptr)
30540 {
30541 memmove (kbd_buffer + 1, kbd_buffer,
30542 (event - kbd_buffer) * sizeof *kbd_buffer);
30543 kbd_buffer[0] = kbd_buffer[KBD_BUFFER_SIZE - 1];
30544 moved_events = kbd_buffer + KBD_BUFFER_SIZE - 1 - kbd_fetch_ptr;
30545 }
30546 else
30547 moved_events = event - kbd_fetch_ptr;
30548
30549 memmove (kbd_fetch_ptr + 1, kbd_fetch_ptr,
30550 moved_events * sizeof *kbd_fetch_ptr);
30551 kbd_fetch_ptr = X_NEXT_KBD_EVENT (kbd_fetch_ptr);
30552
30553
30554
30555 input_pending = false;
30556 }
30557 }
30558 }
30559
30560
30561
30562
30563 static void
30564 x_delete_display (struct x_display_info *dpyinfo)
30565 {
30566 struct terminal *t;
30567 struct color_name_cache_entry *color_entry, *next_color_entry;
30568 int i;
30569 struct x_selection_request_event *ie, *last, *temp;
30570
30571
30572
30573 for (t = terminal_list; t; t = t->next_terminal)
30574 if (t->type == output_x_window && t->display_info.x == dpyinfo)
30575 {
30576 #ifdef HAVE_X_SM
30577
30578 if (t->id == 1 && x_session_have_connection ())
30579 x_session_close ();
30580 #endif
30581 delete_terminal (t);
30582 break;
30583 }
30584
30585
30586
30587
30588 last = NULL;
30589
30590 for (ie = pending_selection_requests; ie; ie = ie->next)
30591 {
30592 again:
30593
30594 if (SELECTION_EVENT_DPYINFO (&ie->se) == dpyinfo)
30595 {
30596 if (last)
30597 last->next = ie->next;
30598
30599 temp = ie;
30600 ie = ie->next;
30601 xfree (temp);
30602
30603 goto again;
30604 }
30605
30606 last = ie;
30607 }
30608
30609 x_delete_selection_requests (dpyinfo);
30610
30611 if (next_noop_dpyinfo == dpyinfo)
30612 next_noop_dpyinfo = dpyinfo->next;
30613
30614 if (mouse_click_timeout_display == dpyinfo)
30615 mouse_click_timeout_display = NULL;
30616
30617 if (x_display_list == dpyinfo)
30618 x_display_list = dpyinfo->next;
30619 else
30620 {
30621 struct x_display_info *tail;
30622
30623 for (tail = x_display_list; tail; tail = tail->next)
30624 if (tail->next == dpyinfo)
30625 tail->next = tail->next->next;
30626 }
30627
30628 for (i = 0; i < dpyinfo->color_names_size; ++i)
30629 {
30630 for (color_entry = dpyinfo->color_names[i];
30631 color_entry; color_entry = next_color_entry)
30632 {
30633 next_color_entry = color_entry->next;
30634
30635 xfree (color_entry->name);
30636 xfree (color_entry);
30637 }
30638 }
30639
30640 if (dpyinfo->net_supported_atoms)
30641 XFree (dpyinfo->net_supported_atoms);
30642
30643 xfree (dpyinfo->color_names);
30644 xfree (dpyinfo->color_names_length);
30645 xfree (dpyinfo->x_id_name);
30646 xfree (dpyinfo->x_dnd_atoms);
30647 xfree (dpyinfo->color_cells);
30648 #ifdef HAVE_XFIXES
30649 if (dpyinfo->monitored_selections)
30650 xfree (dpyinfo->monitored_selections);
30651 #endif
30652 #ifdef USE_TOOLKIT_SCROLL_BARS
30653 xfree (dpyinfo->protected_windows);
30654 #endif
30655 #ifdef HAVE_XINPUT2
30656 if (dpyinfo->supports_xi2)
30657 x_free_xi_devices (dpyinfo);
30658 #endif
30659 xfree (dpyinfo);
30660 }
30661
30662 #ifdef USE_X_TOOLKIT
30663
30664
30665
30666
30667
30668
30669 static void
30670 x_process_timeouts (struct atimer *timer)
30671 {
30672 block_input ();
30673 x_timeout_atimer_activated_flag = false;
30674 if (toolkit_scroll_bar_interaction || popup_activated ())
30675 {
30676 while (XtAppPending (Xt_app_con) & XtIMTimer)
30677 XtAppProcessEvent (Xt_app_con, XtIMTimer);
30678
30679 x_activate_timeout_atimer ();
30680 }
30681 unblock_input ();
30682 }
30683
30684
30685
30686
30687
30688
30689
30690
30691
30692 void
30693 x_activate_timeout_atimer (void)
30694 {
30695 block_input ();
30696 if (!x_timeout_atimer_activated_flag)
30697 {
30698 struct timespec interval = make_timespec (0, 100 * 1000 * 1000);
30699 start_atimer (ATIMER_RELATIVE, interval, x_process_timeouts, 0);
30700 x_timeout_atimer_activated_flag = true;
30701 }
30702 unblock_input ();
30703 }
30704
30705 #endif
30706
30707
30708
30709
30710 extern frame_parm_handler x_frame_parm_handlers[];
30711
30712 static struct redisplay_interface x_redisplay_interface =
30713 {
30714 x_frame_parm_handlers,
30715 gui_produce_glyphs,
30716 gui_write_glyphs,
30717 gui_insert_glyphs,
30718 gui_clear_end_of_line,
30719 x_scroll_run,
30720 x_after_update_window_line,
30721 NULL,
30722 NULL,
30723 x_flip_and_flush,
30724 gui_clear_window_mouse_face,
30725 gui_get_glyph_overhangs,
30726 gui_fix_overlapping_area,
30727 x_draw_fringe_bitmap,
30728 #ifdef USE_CAIRO
30729 x_cr_define_fringe_bitmap,
30730 x_cr_destroy_fringe_bitmap,
30731 #else
30732 0,
30733 0,
30734 #endif
30735 x_compute_glyph_string_overhangs,
30736 x_draw_glyph_string,
30737 x_define_frame_cursor,
30738 x_clear_frame_area,
30739 x_clear_under_internal_border,
30740 x_draw_window_cursor,
30741 x_draw_vertical_window_border,
30742 x_draw_window_divider,
30743 x_shift_glyphs_for_insert,
30744 x_show_hourglass,
30745 x_hide_hourglass,
30746 x_default_font_parameter
30747 };
30748
30749
30750
30751 void
30752 x_delete_terminal (struct terminal *terminal)
30753 {
30754 struct x_display_info *dpyinfo;
30755 struct frame *f;
30756 Lisp_Object tail, frame;
30757
30758 dpyinfo = terminal->display_info.x;
30759
30760
30761
30762 if (!terminal->name)
30763 return;
30764
30765 block_input ();
30766
30767
30768
30769
30770 FOR_EACH_FRAME (tail, frame)
30771 {
30772 f = XFRAME (frame);
30773
30774 if (FRAME_LIVE_P (f) && f->terminal == terminal)
30775
30776 delete_frame (frame, Qnoelisp);
30777 }
30778
30779 #ifdef HAVE_X_I18N
30780
30781
30782 if (dpyinfo->xim)
30783 xim_close_dpy (dpyinfo);
30784 #endif
30785
30786
30787 if (dpyinfo->display)
30788 {
30789 image_destroy_all_bitmaps (dpyinfo);
30790 XSetCloseDownMode (dpyinfo->display, DestroyAll);
30791
30792
30793 if (dpyinfo->scratch_cursor_gc)
30794 XFreeGC (dpyinfo->display, dpyinfo->scratch_cursor_gc);
30795
30796
30797
30798 if ((x_dnd_in_progress || x_dnd_waiting_for_finish)
30799 && dpyinfo->display == (x_dnd_waiting_for_finish
30800 ? x_dnd_finish_display
30801 : FRAME_X_DISPLAY (x_dnd_frame)))
30802 {
30803 x_dnd_last_seen_window = None;
30804 x_dnd_last_seen_toplevel = None;
30805 x_dnd_in_progress = false;
30806 x_dnd_waiting_for_finish = false;
30807
30808
30809
30810 if (x_dnd_use_toplevels)
30811 x_dnd_free_toplevels (false);
30812
30813 x_dnd_return_frame_object = NULL;
30814 x_dnd_movement_frame = NULL;
30815 x_dnd_wheel_frame = NULL;
30816 x_dnd_frame = NULL;
30817 }
30818
30819
30820
30821
30822
30823
30824
30825
30826
30827
30828
30829
30830
30831
30832
30833 #if false
30834 #ifdef HAVE_XRMSETDATABASE
30835 XrmSetDatabase (dpyinfo->display, NULL);
30836 #else
30837 dpyinfo->display->db = NULL;
30838 #endif
30839
30840
30841
30842 XrmDestroyDatabase (dpyinfo->rdb);
30843 #endif
30844 #ifdef USE_GTK
30845 xg_display_close (dpyinfo->display);
30846 #else
30847 #ifdef USE_X_TOOLKIT
30848 XtCloseDisplay (dpyinfo->display);
30849 #else
30850 XCloseDisplay (dpyinfo->display);
30851 #endif
30852 #endif
30853
30854
30855 dpyinfo->display = NULL;
30856 }
30857
30858
30859
30860
30861
30862 else if (dpyinfo->connection >= 0)
30863 emacs_close (dpyinfo->connection);
30864
30865
30866
30867
30868
30869 #ifdef HAVE_XKB
30870 if (dpyinfo->xkb_desc)
30871 XkbFreeKeyboard (dpyinfo->xkb_desc, XkbAllComponentsMask, True);
30872 #endif
30873
30874 if (dpyinfo->modmap)
30875 XFreeModifiermap (dpyinfo->modmap);
30876
30877
30878 delete_keyboard_wait_descriptor (dpyinfo->connection);
30879
30880 dpyinfo->connection = -1;
30881
30882 x_delete_display (dpyinfo);
30883 unblock_input ();
30884 }
30885
30886 #ifdef HAVE_XINPUT2
30887 static bool
30888 x_have_any_grab (struct x_display_info *dpyinfo)
30889 {
30890 int i;
30891
30892 if (!dpyinfo->supports_xi2)
30893 return false;
30894
30895 for (i = 0; i < dpyinfo->num_devices; ++i)
30896 {
30897 if (dpyinfo->devices[i].grab)
30898 return true;
30899 }
30900
30901 return false;
30902 }
30903 #endif
30904
30905
30906
30907
30908 static struct terminal *
30909 x_create_terminal (struct x_display_info *dpyinfo)
30910 {
30911 struct terminal *terminal;
30912
30913 terminal = create_terminal (output_x_window, &x_redisplay_interface);
30914
30915 terminal->display_info.x = dpyinfo;
30916 dpyinfo->terminal = terminal;
30917
30918
30919
30920 terminal->clear_frame_hook = x_clear_frame;
30921 terminal->ins_del_lines_hook = x_ins_del_lines;
30922 terminal->delete_glyphs_hook = x_delete_glyphs;
30923 terminal->ring_bell_hook = XTring_bell;
30924 terminal->toggle_invisible_pointer_hook = XTtoggle_invisible_pointer;
30925 terminal->update_begin_hook = x_update_begin;
30926 terminal->update_end_hook = x_update_end;
30927 terminal->read_socket_hook = XTread_socket;
30928 terminal->frame_up_to_date_hook = XTframe_up_to_date;
30929 #ifdef HAVE_XDBE
30930 terminal->buffer_flipping_unblocked_hook = XTbuffer_flipping_unblocked_hook;
30931 #endif
30932 terminal->defined_color_hook = x_defined_color;
30933 terminal->query_frame_background_color = x_query_frame_background_color;
30934 terminal->query_colors = x_query_colors;
30935 terminal->mouse_position_hook = XTmouse_position;
30936 terminal->get_focus_frame = x_get_focus_frame;
30937 terminal->focus_frame_hook = x_focus_frame;
30938 terminal->frame_rehighlight_hook = XTframe_rehighlight;
30939 terminal->frame_raise_lower_hook = XTframe_raise_lower;
30940 terminal->frame_visible_invisible_hook = x_make_frame_visible_invisible;
30941 terminal->fullscreen_hook = XTfullscreen_hook;
30942 terminal->iconify_frame_hook = x_iconify_frame;
30943 terminal->set_window_size_hook = x_set_window_size;
30944 terminal->set_frame_offset_hook = x_set_offset;
30945 terminal->set_frame_alpha_hook = x_set_frame_alpha;
30946 terminal->set_new_font_hook = x_new_font;
30947 terminal->set_bitmap_icon_hook = x_bitmap_icon;
30948 terminal->implicit_set_name_hook = x_implicitly_set_name;
30949 terminal->menu_show_hook = x_menu_show;
30950 #ifdef HAVE_EXT_MENU_BAR
30951 terminal->activate_menubar_hook = x_activate_menubar;
30952 #endif
30953 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
30954 terminal->popup_dialog_hook = xw_popup_dialog;
30955 #endif
30956 terminal->change_tab_bar_height_hook = x_change_tab_bar_height;
30957 #ifndef HAVE_EXT_TOOL_BAR
30958 terminal->change_tool_bar_height_hook = x_change_tool_bar_height;
30959 #endif
30960 terminal->set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
30961 terminal->set_horizontal_scroll_bar_hook = XTset_horizontal_scroll_bar;
30962 terminal->set_scroll_bar_default_width_hook = x_set_scroll_bar_default_width;
30963 terminal->set_scroll_bar_default_height_hook = x_set_scroll_bar_default_height;
30964 terminal->condemn_scroll_bars_hook = XTcondemn_scroll_bars;
30965 terminal->redeem_scroll_bar_hook = XTredeem_scroll_bar;
30966 terminal->judge_scroll_bars_hook = XTjudge_scroll_bars;
30967 terminal->get_string_resource_hook = x_get_string_resource;
30968 terminal->free_pixmap = x_free_pixmap;
30969 terminal->delete_frame_hook = x_destroy_window;
30970 terminal->delete_terminal_hook = x_delete_terminal;
30971 terminal->toolkit_position_hook = x_toolkit_position;
30972 #ifdef HAVE_XINPUT2
30973 terminal->any_grab_hook = x_have_any_grab;
30974 #endif
30975
30976
30977 return terminal;
30978 }
30979
30980 static void
30981 x_initialize (void)
30982 {
30983 baud_rate = 19200;
30984
30985 x_noop_count = 0;
30986 any_help_event_p = false;
30987 ignore_next_mouse_click_timeout = 0;
30988 mouse_click_timeout_display = NULL;
30989
30990 #ifdef USE_GTK
30991 current_count = -1;
30992 #endif
30993
30994
30995 Fset_input_interrupt_mode (Qt);
30996
30997 #if THREADS_ENABLED
30998
30999 if (XInitThreads () == 0)
31000 fputs ("Warning: An error occurred initializing X11 thread support!\n",
31001 stderr);
31002 #endif
31003
31004 #ifdef USE_X_TOOLKIT
31005 XtToolkitInitialize ();
31006
31007 Xt_app_con = XtCreateApplicationContext ();
31008
31009
31010
31011 XtAppSetTypeConverter (Xt_app_con,
31012 XtRString, XtRPixel, cvt_string_to_pixel,
31013 cvt_string_to_pixel_args,
31014 XtNumber (cvt_string_to_pixel_args),
31015 XtCacheByDisplay, cvt_pixel_dtor);
31016
31017 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
31018 #endif
31019
31020 #ifdef USE_TOOLKIT_SCROLL_BARS
31021 #ifndef USE_GTK
31022 xaw3d_arrow_scroll = False;
31023 xaw3d_pick_top = True;
31024 #endif
31025 #endif
31026
31027 #ifdef USE_CAIRO
31028 gui_init_fringe (&x_redisplay_interface);
31029 #endif
31030
31031
31032
31033 XSetErrorHandler (x_error_handler);
31034 XSetIOErrorHandler (x_io_error_quitter);
31035 }
31036
31037 #ifdef USE_GTK
31038 void
31039 init_xterm (void)
31040 {
31041 #ifndef HAVE_XINPUT2
31042
31043
31044
31045 #ifndef HAVE_GTK3
31046 xputenv ("GDK_CORE_DEVICE_EVENTS=1");
31047 #else
31048 gdk_disable_multidevice ();
31049 #endif
31050 #endif
31051 }
31052 #endif
31053
31054 void
31055 mark_xterm (void)
31056 {
31057 Lisp_Object val;
31058 #if defined HAVE_XINPUT2 || defined USE_TOOLKIT_SCROLL_BARS \
31059 || defined HAVE_XRANDR || defined USE_GTK || defined HAVE_X_I18N
31060 struct x_display_info *dpyinfo;
31061 #if defined HAVE_XINPUT2 || defined USE_TOOLKIT_SCROLL_BARS
31062 int i;
31063 #endif
31064 #endif
31065
31066 if (x_dnd_return_frame_object)
31067 {
31068 XSETFRAME (val, x_dnd_return_frame_object);
31069 mark_object (val);
31070 }
31071
31072 if (x_dnd_movement_frame)
31073 {
31074 XSETFRAME (val, x_dnd_movement_frame);
31075 mark_object (val);
31076 }
31077
31078 if (x_dnd_wheel_frame)
31079 {
31080 XSETFRAME (val, x_dnd_wheel_frame);
31081 mark_object (val);
31082 }
31083
31084 #if defined HAVE_XINPUT2 || defined USE_TOOLKIT_SCROLL_BARS \
31085 || defined HAVE_XRANDR || defined USE_GTK || defined HAVE_X_I18N
31086 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
31087 {
31088 #ifdef HAVE_XINPUT2
31089 for (i = 0; i < dpyinfo->num_devices; ++i)
31090 mark_object (dpyinfo->devices[i].name);
31091 #endif
31092 #ifdef USE_TOOLKIT_SCROLL_BARS
31093 for (i = 0; i < dpyinfo->n_protected_windows; ++i)
31094 mark_object (dpyinfo->protected_windows[i]);
31095 #endif
31096 #if defined HAVE_XRANDR || defined USE_GTK
31097 mark_object (dpyinfo->last_monitor_attributes_list);
31098 #endif
31099 #if defined HAVE_X_I18N
31100 mark_object (dpyinfo->xim_coding);
31101 #endif
31102 }
31103 #endif
31104 }
31105
31106
31107
31108
31109
31110 void
31111 x_catch_errors_for_lisp (struct x_display_info *dpyinfo)
31112 {
31113 if (!x_fast_protocol_requests)
31114 x_catch_errors (dpyinfo->display);
31115 else
31116 x_ignore_errors_for_next_request (dpyinfo);
31117 }
31118
31119 void
31120 x_check_errors_for_lisp (struct x_display_info *dpyinfo,
31121 const char *format)
31122 {
31123 if (!x_fast_protocol_requests)
31124 x_check_errors (dpyinfo->display, format);
31125 }
31126
31127 void
31128 x_uncatch_errors_for_lisp (struct x_display_info *dpyinfo)
31129 {
31130 if (!x_fast_protocol_requests)
31131 x_uncatch_errors ();
31132 else
31133 x_stop_ignoring_errors (dpyinfo);
31134 }
31135
31136
31137
31138
31139
31140 void
31141 x_preserve_selections (struct x_display_info *dpyinfo, Lisp_Object lost,
31142 Lisp_Object current_owner)
31143 {
31144 Lisp_Object tail, frame, new_owner;
31145 Time timestamp;
31146 Window *owners;
31147 Atom *names;
31148 ptrdiff_t nowners, counter;
31149 struct selection_input_event clear;
31150 #ifdef USE_XCB
31151 xcb_get_selection_owner_cookie_t *cookies;
31152 xcb_generic_error_t *error;
31153 xcb_get_selection_owner_reply_t *reply;
31154 #endif
31155
31156 new_owner = Qnil;
31157
31158 FOR_EACH_FRAME (tail, frame)
31159 {
31160 if (FRAME_X_P (XFRAME (frame))
31161 && !EQ (frame, current_owner)
31162 && FRAME_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
31163 {
31164 new_owner = frame;
31165 break;
31166 }
31167 }
31168
31169 tail = lost;
31170 nowners = 0;
31171
31172 FOR_EACH_TAIL_SAFE (tail)
31173 {
31174 Lisp_Object tem = XCAR (tail);
31175 ++nowners;
31176
31177
31178
31179 if (NILP (new_owner))
31180 CALLN (Frun_hook_with_args, Qx_lost_selection_functions,
31181 XCAR (tem));
31182 else
31183 {
31184 CONS_TO_INTEGER (XCAR (XCDR (XCDR (tem))), Time, timestamp);
31185
31186
31187
31188 x_own_selection (XCAR (tem), XCAR (XCDR (tem)),
31189 new_owner, XCAR (XCDR (XCDR (XCDR (XCDR (tem))))),
31190 timestamp);
31191 }
31192 }
31193
31194 if (!NILP (new_owner))
31195 {
31196 owners = alloca (sizeof *owners * nowners);
31197 names = alloca (sizeof *names * nowners);
31198 #ifdef USE_XCB
31199 cookies = alloca (sizeof *cookies * nowners);
31200 #endif
31201
31202 tail = lost;
31203 nowners = 0;
31204 counter = 0;
31205
31206 FOR_EACH_TAIL_SAFE (tail)
31207 {
31208 Lisp_Object tem = XCAR (tail);
31209
31210
31211
31212 names[counter++] = symbol_to_x_atom (dpyinfo, XCAR (tem));
31213
31214 #ifndef USE_XCB
31215 owners[nowners++] = XGetSelectionOwner (dpyinfo->display,
31216 names[counter - 1]);
31217 #else
31218 cookies[nowners++]
31219 = xcb_get_selection_owner (dpyinfo->xcb_connection,
31220 names[counter - 1]);
31221 }
31222
31223 nowners = 0;
31224 tail = lost;
31225
31226 FOR_EACH_TAIL_SAFE (tail)
31227 {
31228 Lisp_Object tem = XCAR (tail);
31229
31230 reply = xcb_get_selection_owner_reply (dpyinfo->xcb_connection,
31231 cookies[nowners++], &error);
31232 if (reply)
31233 owners[nowners - 1] = reply->owner;
31234 else
31235 owners[nowners - 1] = None;
31236
31237 free (reply ? (void *) reply : (void *) error);
31238 #endif
31239
31240 if (owners[nowners - 1] != FRAME_X_WINDOW (XFRAME (new_owner)))
31241 {
31242
31243
31244 CONS_TO_INTEGER (XCAR (XCDR (XCDR (tem))), Time, timestamp);
31245
31246 clear.kind = SELECTION_CLEAR_EVENT;
31247
31248 SELECTION_EVENT_DPYINFO (&clear) = dpyinfo;
31249 SELECTION_EVENT_SELECTION (&clear) = names[nowners - 1];
31250 SELECTION_EVENT_TIME (&clear) = timestamp;
31251
31252 x_handle_selection_event (&clear);
31253 }
31254 }
31255
31256 tail = lost;
31257 nowners = 0;
31258
31259 FOR_EACH_TAIL_SAFE (tail)
31260 {
31261 Lisp_Object tem = XCAR (tail);
31262
31263
31264
31265 if (owners[nowners++] != FRAME_X_WINDOW (XFRAME (new_owner)))
31266 CALLN (Frun_hook_with_args, Qx_lost_selection_functions,
31267 XCAR (tem));
31268 }
31269 }
31270 }
31271
31272
31273
31274
31275
31276
31277 Lisp_Object
31278 x_get_keyboard_modifiers (struct x_display_info *dpyinfo)
31279 {
31280
31281
31282
31283
31284 #ifdef HAVE_XKB
31285 if (!dpyinfo->xkb_desc && !dpyinfo->modmap)
31286 x_find_modifier_meanings (dpyinfo);
31287 #else
31288 if (!dpyinfo->modmap)
31289 x_find_modifier_meanings (dpyinfo);
31290 #endif
31291
31292 return list5 (make_uint (dpyinfo->hyper_mod_mask),
31293 make_uint (dpyinfo->super_mod_mask),
31294 make_uint (dpyinfo->alt_mod_mask),
31295 make_uint (dpyinfo->shift_lock_mask),
31296 make_uint (dpyinfo->meta_mod_mask));
31297 }
31298
31299 void
31300 syms_of_xterm (void)
31301 {
31302 x_error_message = NULL;
31303 PDUMPER_IGNORE (x_error_message);
31304
31305 x_dnd_monitors = Qnil;
31306 staticpro (&x_dnd_monitors);
31307
31308 x_dnd_action_symbol = Qnil;
31309 staticpro (&x_dnd_action_symbol);
31310
31311 x_dnd_selection_alias_cell = Fcons (Qnil, Qnil);
31312 staticpro (&x_dnd_selection_alias_cell);
31313
31314 x_dnd_unsupported_drop_data = Qnil;
31315 staticpro (&x_dnd_unsupported_drop_data);
31316
31317
31318 DEFSYM (Qconcat, "concat");
31319
31320 DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms");
31321 DEFSYM (Qlatin_1, "latin-1");
31322 DEFSYM (Qnow, "now");
31323 DEFSYM (Qx_dnd_targets_list, "x-dnd-targets-list");
31324 DEFSYM (Qx_auto_preserve_selections, "x-auto-preserve-selections");
31325
31326 #ifdef USE_GTK
31327 xg_default_icon_file = build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg");
31328 staticpro (&xg_default_icon_file);
31329
31330 DEFSYM (Qx_gtk_map_stock, "x-gtk-map-stock");
31331 #endif
31332
31333 DEFVAR_BOOL ("x-use-underline-position-properties",
31334 x_use_underline_position_properties,
31335 doc:
31336
31337
31338
31339 );
31340 x_use_underline_position_properties = true;
31341 DEFSYM (Qx_use_underline_position_properties,
31342 "x-use-underline-position-properties");
31343
31344 DEFVAR_BOOL ("x-underline-at-descent-line",
31345 x_underline_at_descent_line,
31346 doc:
31347
31348
31349
31350
31351 );
31352 x_underline_at_descent_line = false;
31353 DEFSYM (Qx_underline_at_descent_line, "x-underline-at-descent-line");
31354
31355 DEFVAR_BOOL ("x-mouse-click-focus-ignore-position",
31356 x_mouse_click_focus_ignore_position,
31357 doc:
31358
31359
31360
31361
31362
31363
31364
31365
31366
31367 );
31368 x_mouse_click_focus_ignore_position = false;
31369
31370 DEFVAR_INT ("x-mouse-click-focus-ignore-time", x_mouse_click_focus_ignore_time,
31371 doc:
31372
31373
31374 );
31375 x_mouse_click_focus_ignore_time = 200;
31376
31377 DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
31378 doc:
31379
31380
31381
31382 );
31383 #ifdef USE_TOOLKIT_SCROLL_BARS
31384 #ifdef USE_MOTIF
31385 Vx_toolkit_scroll_bars = intern_c_string ("motif");
31386 #elif defined HAVE_XAW3D
31387 Vx_toolkit_scroll_bars = intern_c_string ("xaw3d");
31388 #elif USE_GTK
31389 Vx_toolkit_scroll_bars = intern_c_string ("gtk");
31390 #else
31391 Vx_toolkit_scroll_bars = intern_c_string ("xaw");
31392 #endif
31393 #else
31394 Vx_toolkit_scroll_bars = Qnil;
31395 #endif
31396
31397 DEFSYM (Qmodifier_value, "modifier-value");
31398 DEFSYM (Qctrl, "ctrl");
31399 Fput (Qctrl, Qmodifier_value, make_fixnum (ctrl_modifier));
31400 DEFSYM (Qalt, "alt");
31401 Fput (Qalt, Qmodifier_value, make_fixnum (alt_modifier));
31402 DEFSYM (Qhyper, "hyper");
31403 Fput (Qhyper, Qmodifier_value, make_fixnum (hyper_modifier));
31404 DEFSYM (Qmeta, "meta");
31405 Fput (Qmeta, Qmodifier_value, make_fixnum (meta_modifier));
31406 DEFSYM (Qsuper, "super");
31407 Fput (Qsuper, Qmodifier_value, make_fixnum (super_modifier));
31408 DEFSYM (QXdndSelection, "XdndSelection");
31409 DEFSYM (Qx_selection_alias_alist, "x-selection-alias-alist");
31410 DEFSYM (Qimitate_pager, "imitate-pager");
31411 DEFSYM (Qnewer_time, "newer-time");
31412 DEFSYM (Qraise_and_focus, "raise-and-focus");
31413 DEFSYM (Qreally_fast, "really-fast");
31414
31415 DEFVAR_LISP ("x-ctrl-keysym", Vx_ctrl_keysym,
31416 doc:
31417
31418
31419 );
31420 Vx_ctrl_keysym = Qnil;
31421
31422 DEFVAR_LISP ("x-alt-keysym", Vx_alt_keysym,
31423 doc:
31424
31425
31426 );
31427 Vx_alt_keysym = Qnil;
31428
31429 DEFVAR_LISP ("x-hyper-keysym", Vx_hyper_keysym,
31430 doc:
31431
31432
31433 );
31434 Vx_hyper_keysym = Qnil;
31435
31436 DEFVAR_LISP ("x-meta-keysym", Vx_meta_keysym,
31437 doc:
31438
31439
31440 );
31441 Vx_meta_keysym = Qnil;
31442
31443 DEFVAR_LISP ("x-super-keysym", Vx_super_keysym,
31444 doc:
31445
31446
31447 );
31448 Vx_super_keysym = Qnil;
31449
31450 DEFVAR_LISP ("x-wait-for-event-timeout", Vx_wait_for_event_timeout,
31451 doc:
31452
31453
31454
31455
31456
31457
31458 );
31459 Vx_wait_for_event_timeout = make_float (0.1);
31460
31461 DEFVAR_LISP ("x-keysym-table", Vx_keysym_table,
31462 doc: );
31463 Vx_keysym_table = make_hash_table (hashtest_eql, 900,
31464 DEFAULT_REHASH_SIZE,
31465 DEFAULT_REHASH_THRESHOLD,
31466 Qnil, false);
31467
31468 DEFVAR_BOOL ("x-frame-normalize-before-maximize",
31469 x_frame_normalize_before_maximize,
31470 doc:
31471
31472
31473
31474
31475
31476
31477
31478 );
31479 x_frame_normalize_before_maximize = false;
31480
31481 DEFVAR_BOOL ("x-gtk-use-window-move", x_gtk_use_window_move,
31482 doc:
31483
31484
31485
31486 );
31487 x_gtk_use_window_move = true;
31488
31489 DEFVAR_LISP ("x-scroll-event-delta-factor", Vx_scroll_event_delta_factor,
31490 doc:
31491
31492 );
31493 Vx_scroll_event_delta_factor = make_float (1.0);
31494 DEFSYM (Qexpose, "expose");
31495
31496 DEFVAR_BOOL ("x-gtk-use-native-input", x_gtk_use_native_input,
31497 doc:
31498
31499 );
31500 x_gtk_use_native_input = false;
31501
31502 DEFVAR_LISP ("x-set-frame-visibility-more-laxly",
31503 x_set_frame_visibility_more_laxly,
31504 doc:
31505
31506
31507
31508
31509
31510
31511
31512
31513
31514 );
31515 x_set_frame_visibility_more_laxly = Qnil;
31516
31517 DEFVAR_BOOL ("x-input-grab-touch-events", x_input_grab_touch_events,
31518 doc:
31519
31520
31521
31522 );
31523 x_input_grab_touch_events = true;
31524
31525 DEFVAR_BOOL ("x-dnd-fix-motif-leave", x_dnd_fix_motif_leave,
31526 doc:
31527
31528
31529
31530 );
31531 x_dnd_fix_motif_leave = true;
31532
31533 DEFVAR_BOOL ("x-dnd-disable-motif-drag", x_dnd_disable_motif_drag,
31534 doc:
31535
31536
31537 );
31538 x_dnd_disable_motif_drag = false;
31539
31540 DEFVAR_LISP ("x-dnd-movement-function", Vx_dnd_movement_function,
31541 doc:
31542
31543
31544 );
31545 Vx_dnd_movement_function = Qnil;
31546
31547 DEFVAR_LISP ("x-dnd-wheel-function", Vx_dnd_wheel_function,
31548 doc:
31549
31550
31551
31552
31553 );
31554 Vx_dnd_wheel_function = Qnil;
31555
31556 DEFVAR_LISP ("x-dnd-unsupported-drop-function", Vx_dnd_unsupported_drop_function,
31557 doc:
31558
31559
31560
31561
31562
31563
31564
31565
31566
31567
31568
31569
31570
31571
31572
31573
31574 );
31575 Vx_dnd_unsupported_drop_function = Qnil;
31576
31577 DEFVAR_INT ("x-color-cache-bucket-size", x_color_cache_bucket_size,
31578 doc:
31579 );
31580 x_color_cache_bucket_size = 128;
31581
31582 DEFVAR_LISP ("x-dnd-targets-list", Vx_dnd_targets_list,
31583 doc:
31584
31585
31586 );
31587 Vx_dnd_targets_list = Qnil;
31588
31589 DEFVAR_LISP ("x-dnd-native-test-function", Vx_dnd_native_test_function,
31590 doc:
31591
31592
31593
31594
31595
31596
31597
31598
31599 );
31600 Vx_dnd_native_test_function = Qnil;
31601
31602 DEFVAR_BOOL ("x-dnd-preserve-selection-data", x_dnd_preserve_selection_data,
31603 doc:
31604
31605
31606 );
31607 x_dnd_preserve_selection_data = false;
31608
31609 DEFVAR_BOOL ("x-dnd-disable-motif-protocol", x_dnd_disable_motif_protocol,
31610 doc:
31611
31612 );
31613 x_dnd_disable_motif_protocol = false;
31614
31615 DEFVAR_BOOL ("x-dnd-use-unsupported-drop", x_dnd_use_unsupported_drop,
31616 doc:
31617
31618
31619 );
31620 x_dnd_use_unsupported_drop = true;
31621
31622 DEFVAR_BOOL ("x-fast-protocol-requests", x_fast_protocol_requests,
31623 doc:
31624
31625
31626
31627
31628 );
31629 x_fast_protocol_requests = false;
31630
31631 DEFVAR_LISP ("x-auto-preserve-selections", Vx_auto_preserve_selections,
31632 doc:
31633
31634
31635
31636
31637
31638 );
31639 Vx_auto_preserve_selections = list2 (QCLIPBOARD, QPRIMARY);
31640
31641 DEFVAR_LISP ("x-input-coding-system", Vx_input_coding_system,
31642 doc:
31643
31644
31645 );
31646 Vx_input_coding_system = Qnil;
31647
31648 DEFVAR_LISP ("x-input-coding-function", Vx_input_coding_function,
31649 doc:
31650
31651
31652 );
31653 Vx_input_coding_function = Qnil;
31654
31655 DEFVAR_LISP ("x-fast-selection-list", Vx_fast_selection_list,
31656 doc:
31657
31658
31659
31660
31661
31662
31663 );
31664
31665
31666 Vx_fast_selection_list = list1 (QCLIPBOARD);
31667
31668 DEFVAR_LISP ("x-allow-focus-stealing", Vx_allow_focus_stealing,
31669 doc:
31670
31671
31672
31673
31674
31675
31676
31677
31678
31679
31680
31681
31682
31683
31684
31685
31686
31687
31688
31689
31690
31691 );
31692 Vx_allow_focus_stealing = Qnewer_time;
31693
31694 DEFVAR_LISP ("x-use-fast-mouse-position", Vx_use_fast_mouse_position,
31695 doc:
31696
31697
31698
31699
31700
31701
31702
31703
31704
31705
31706 );
31707 Vx_use_fast_mouse_position = Qnil;
31708 }