@@ -52,6 +52,7 @@ struct _MetaCompositorX11
52
52
53
53
gboolean frame_has_updated_xsurfaces ;
54
54
gboolean have_x11_sync_object ;
55
+ gboolean have_root_window_key_grab ;
55
56
56
57
MetaWindow * unredirected_window ;
57
58
MetaWindow * focus_window ;
@@ -61,8 +62,17 @@ struct _MetaCompositorX11
61
62
int64_t xserver_time_offset_us ;
62
63
};
63
64
65
+ typedef struct
66
+ {
67
+ MetaCompositorX11 * compositor_x11 ;
68
+ Window xwindow ;
69
+ gboolean grab ;
70
+ } KeyGrabData ;
71
+
64
72
G_DEFINE_TYPE (MetaCompositorX11 , meta_compositor_x11 , META_TYPE_COMPOSITOR )
65
73
74
+ static void meta_compositor_x11_grab_root_window_keys (MetaCompositorX11 * compositor_x11 );
75
+
66
76
static void
67
77
process_damage (MetaCompositorX11 * compositor_x11 ,
68
78
XDamageNotifyEvent * damage_xevent ,
@@ -202,6 +212,8 @@ meta_compositor_x11_manage (MetaCompositor *compositor,
202
212
203
213
meta_x11_display_redirect_windows (x11_display , display );
204
214
215
+ meta_compositor_x11_grab_root_window_keys (compositor_x11 );
216
+
205
217
return TRUE;
206
218
}
207
219
@@ -528,6 +540,135 @@ meta_compositor_x11_ungrab_focus_window_button (MetaCompositorX11 *compositor_x1
528
540
META_GRAB_MODE_ASYNC , 0 );
529
541
}
530
542
543
+ static void
544
+ meta_compositor_x11_change_keygrab (MetaCompositorX11 * compositor_x11 ,
545
+ Window xwindow ,
546
+ gboolean grab ,
547
+ MetaResolvedKeyCombo * resolved_combo )
548
+ {
549
+ MetaBackend * backend =
550
+ meta_compositor_get_backend (META_COMPOSITOR (compositor_x11 ));
551
+ MetaBackendX11 * backend_x11 = META_BACKEND_X11 (backend );
552
+ int i ;
553
+
554
+ for (i = 0 ; i < resolved_combo -> len ; i ++ )
555
+ {
556
+ xkb_keycode_t keycode = resolved_combo -> keycodes [i ];
557
+
558
+ meta_topic (META_DEBUG_KEYBINDINGS ,
559
+ "%s keybinding keycode %d mask 0x%x on 0x%lx" ,
560
+ grab ? "Grabbing" : "Ungrabbing" ,
561
+ keycode , resolved_combo -> mask , xwindow );
562
+
563
+ if (grab )
564
+ {
565
+ meta_backend_x11_passive_key_grab (backend_x11 , xwindow ,
566
+ keycode ,
567
+ META_GRAB_MODE_SYNC ,
568
+ resolved_combo -> mask );
569
+ }
570
+ else
571
+ {
572
+ meta_backend_x11_passive_key_ungrab (backend_x11 , xwindow ,
573
+ keycode ,
574
+ resolved_combo -> mask );
575
+ }
576
+ }
577
+ }
578
+
579
+ static void
580
+ passive_key_grab_foreach (MetaDisplay * display ,
581
+ MetaKeyBindingFlags flags ,
582
+ MetaResolvedKeyCombo * resolved_combo ,
583
+ gpointer user_data )
584
+ {
585
+ MetaX11Display * x11_display = display -> x11_display ;
586
+ Window xroot = x11_display -> xroot ;
587
+ KeyGrabData * data = user_data ;
588
+
589
+ /* Ignore the key bindings marked as META_KEY_BINDING_NO_AUTO_GRAB. */
590
+ if ((flags & META_KEY_BINDING_NO_AUTO_GRAB ) != 0 &&
591
+ data -> grab )
592
+ return ;
593
+
594
+ if ((flags & META_KEY_BINDING_PER_WINDOW ) != 0 &&
595
+ data -> xwindow == xroot )
596
+ return ;
597
+
598
+ meta_compositor_x11_change_keygrab (data -> compositor_x11 ,
599
+ data -> xwindow ,
600
+ data -> grab ,
601
+ resolved_combo );
602
+ }
603
+
604
+ static void
605
+ meta_compositor_x11_grab_window_keys (MetaCompositorX11 * compositor_x11 ,
606
+ Window xwindow )
607
+ {
608
+ MetaCompositor * compositor = META_COMPOSITOR (compositor_x11 );
609
+ MetaDisplay * display = meta_compositor_get_display (compositor );
610
+ KeyGrabData data = { compositor_x11 , xwindow , TRUE };
611
+
612
+ meta_display_keybinding_foreach (display ,
613
+ passive_key_grab_foreach ,
614
+ & data );
615
+ }
616
+
617
+ static void
618
+ meta_compositor_x11_ungrab_window_keys (MetaCompositorX11 * compositor_x11 ,
619
+ Window xwindow )
620
+ {
621
+ MetaCompositor * compositor = META_COMPOSITOR (compositor_x11 );
622
+ MetaDisplay * display = meta_compositor_get_display (compositor );
623
+ KeyGrabData data = { compositor_x11 , xwindow , FALSE };
624
+
625
+ meta_display_keybinding_foreach (display ,
626
+ passive_key_grab_foreach ,
627
+ & data );
628
+ }
629
+
630
+ static void
631
+ meta_compositor_x11_grab_root_window_keys (MetaCompositorX11 * compositor_x11 )
632
+ {
633
+ MetaCompositor * compositor = META_COMPOSITOR (compositor_x11 );
634
+ MetaDisplay * display = meta_compositor_get_display (compositor );
635
+ MetaX11Display * x11_display = display -> x11_display ;
636
+ Window xroot = x11_display -> xroot ;
637
+ KeyGrabData data = { compositor_x11 , xroot , TRUE };
638
+
639
+ if (compositor_x11 -> have_root_window_key_grab )
640
+ return ;
641
+
642
+ meta_display_keybinding_foreach (display ,
643
+ passive_key_grab_foreach ,
644
+ & data );
645
+ compositor_x11 -> have_root_window_key_grab = TRUE;
646
+ }
647
+
648
+ static void
649
+ meta_compositor_x11_ungrab_root_window_keys (MetaCompositorX11 * compositor_x11 )
650
+ {
651
+ MetaCompositor * compositor = META_COMPOSITOR (compositor_x11 );
652
+ MetaDisplay * display = meta_compositor_get_display (compositor );
653
+ MetaX11Display * x11_display = display -> x11_display ;
654
+ Window xroot = x11_display -> xroot ;
655
+ KeyGrabData data = { compositor_x11 , xroot , FALSE };
656
+
657
+ if (!compositor_x11 -> have_root_window_key_grab )
658
+ return ;
659
+
660
+ meta_display_keybinding_foreach (display ,
661
+ passive_key_grab_foreach ,
662
+ & data );
663
+ compositor_x11 -> have_root_window_key_grab = FALSE;
664
+ }
665
+
666
+ static gboolean
667
+ should_have_passive_grab (MetaWindow * window )
668
+ {
669
+ return window -> type != META_WINDOW_DOCK && !window -> override_redirect ;
670
+ }
671
+
531
672
static void
532
673
on_focus_window_change (MetaDisplay * display ,
533
674
GParamSpec * pspec ,
@@ -540,7 +681,7 @@ on_focus_window_change (MetaDisplay *display,
540
681
old_focus = compositor_x11 -> focus_window ;
541
682
focus = meta_display_get_focus_window (display );
542
683
543
- if (focus && (focus -> type == META_WINDOW_DOCK || focus -> override_redirect ))
684
+ if (focus && ! should_have_passive_grab (focus ))
544
685
focus = NULL ;
545
686
546
687
if (focus == old_focus )
@@ -579,6 +720,51 @@ on_focus_window_change (MetaDisplay *display,
579
720
compositor_x11 -> focus_window = focus ;
580
721
}
581
722
723
+ static void
724
+ on_window_type_changed (MetaWindow * window ,
725
+ GParamSpec * pspec ,
726
+ MetaCompositorX11 * compositor_x11 )
727
+ {
728
+ Window xwindow ;
729
+
730
+ xwindow = meta_window_x11_get_toplevel_xwindow (window );
731
+
732
+ if (should_have_passive_grab (window ))
733
+ meta_compositor_x11_grab_window_keys (compositor_x11 , xwindow );
734
+ else
735
+ meta_compositor_x11_ungrab_window_keys (compositor_x11 , xwindow );
736
+ }
737
+
738
+ static void
739
+ on_window_decorated_changed (MetaWindow * window ,
740
+ GParamSpec * pspec ,
741
+ MetaCompositorX11 * compositor_x11 )
742
+ {
743
+ Window old_effective_toplevel = None , xwindow ;
744
+
745
+ /* We must clean up the passive grab on the prior effective toplevel */
746
+ if (window -> decorated )
747
+ {
748
+ old_effective_toplevel = meta_window_x11_get_xwindow (window );
749
+ }
750
+ else
751
+ {
752
+ MetaFrame * frame ;
753
+
754
+ frame = meta_window_x11_get_frame (window );
755
+ old_effective_toplevel = meta_frame_get_xwindow (frame );
756
+ }
757
+
758
+ if (old_effective_toplevel != None )
759
+ {
760
+ meta_compositor_x11_ungrab_window_keys (compositor_x11 ,
761
+ old_effective_toplevel );
762
+ }
763
+
764
+ xwindow = meta_window_x11_get_toplevel_xwindow (window );
765
+ meta_compositor_x11_grab_window_keys (compositor_x11 , xwindow );
766
+ }
767
+
582
768
static void
583
769
meta_compositor_x11_before_paint (MetaCompositor * compositor ,
584
770
MetaCompositorView * compositor_view )
@@ -614,9 +800,24 @@ meta_compositor_x11_add_window (MetaCompositor *compositor,
614
800
{
615
801
MetaCompositorX11 * compositor_x11 = META_COMPOSITOR_X11 (compositor );
616
802
MetaCompositorClass * parent_class ;
803
+ Window xwindow ;
617
804
618
- if (window -> type != META_WINDOW_DOCK && !window -> override_redirect )
619
- meta_compositor_x11_grab_focus_window_button (compositor_x11 , window );
805
+ if (should_have_passive_grab (window ))
806
+ {
807
+ xwindow = meta_window_x11_get_toplevel_xwindow (window );
808
+
809
+ meta_compositor_x11_grab_focus_window_button (compositor_x11 , window );
810
+ meta_compositor_x11_grab_window_keys (compositor_x11 , xwindow );
811
+
812
+ g_signal_connect_object (window , "notify::window-type" ,
813
+ G_CALLBACK (on_window_type_changed ),
814
+ compositor ,
815
+ G_CONNECT_DEFAULT );
816
+ g_signal_connect_object (window , "notify::decorated" ,
817
+ G_CALLBACK (on_window_decorated_changed ),
818
+ compositor ,
819
+ G_CONNECT_DEFAULT );
820
+ }
620
821
621
822
parent_class = META_COMPOSITOR_CLASS (meta_compositor_x11_parent_class );
622
823
parent_class -> add_window (compositor , window );
@@ -628,6 +829,7 @@ meta_compositor_x11_remove_window (MetaCompositor *compositor,
628
829
{
629
830
MetaCompositorX11 * compositor_x11 = META_COMPOSITOR_X11 (compositor );
630
831
MetaCompositorClass * parent_class ;
832
+ Window xwindow ;
631
833
632
834
if (compositor_x11 -> unredirected_window == window )
633
835
set_unredirected_window (compositor_x11 , NULL );
@@ -637,11 +839,19 @@ meta_compositor_x11_remove_window (MetaCompositor *compositor,
637
839
meta_compositor_x11_ungrab_window_buttons (compositor_x11 , window );
638
840
compositor_x11 -> focus_window = NULL ;
639
841
}
640
- else if (window -> type != META_WINDOW_DOCK && ! window -> override_redirect )
842
+ else if (should_have_passive_grab ( window ) )
641
843
{
642
844
meta_compositor_x11_ungrab_focus_window_button (compositor_x11 , window );
643
845
}
644
846
847
+ xwindow = meta_window_x11_get_toplevel_xwindow (window );
848
+ meta_compositor_x11_ungrab_window_keys (compositor_x11 , xwindow );
849
+
850
+ g_signal_handlers_disconnect_by_func (window , on_window_type_changed ,
851
+ compositor );
852
+ g_signal_handlers_disconnect_by_func (window , on_window_decorated_changed ,
853
+ compositor );
854
+
645
855
parent_class = META_COMPOSITOR_CLASS (meta_compositor_x11_parent_class );
646
856
parent_class -> remove_window (compositor , window );
647
857
}
@@ -745,7 +955,24 @@ meta_compositor_x11_notify_mapping_change (MetaCompositor *compositor,
745
955
}
746
956
747
957
break ;
748
- default :
958
+ case META_MAPPING_TYPE_KEY :
959
+ windows = meta_display_list_windows (display , META_LIST_DEFAULT );
960
+
961
+ if (grab )
962
+ meta_compositor_x11_grab_root_window_keys (compositor_x11 );
963
+ else
964
+ meta_compositor_x11_ungrab_root_window_keys (compositor_x11 );
965
+
966
+ for (l = windows ; l ; l = l -> next )
967
+ {
968
+ MetaWindow * window = l -> data ;
969
+ Window xwindow = meta_window_x11_get_toplevel_xwindow (window );
970
+
971
+ if (grab )
972
+ meta_compositor_x11_grab_window_keys (compositor_x11 , xwindow );
973
+ else
974
+ meta_compositor_x11_ungrab_window_keys (compositor_x11 , xwindow );
975
+ }
749
976
break ;
750
977
}
751
978
}
@@ -806,6 +1033,8 @@ meta_compositor_x11_dispose (GObject *object)
806
1033
g_clear_signal_handler (& compositor_x11 -> after_update_handler_id , stage );
807
1034
g_clear_signal_handler (& compositor_x11 -> focus_window_handler_id , display );
808
1035
1036
+ meta_compositor_x11_ungrab_root_window_keys (compositor_x11 );
1037
+
809
1038
G_OBJECT_CLASS (meta_compositor_x11_parent_class )-> dispose (object );
810
1039
}
811
1040
0 commit comments