mono-csharp-linux(ubuntu)全局挂钩键盘

本文关键字:键盘 全局 ubuntu mono-csharp-linux | 更新日期: 2023-09-27 18:28:52

我需要在mono-csharp中实现全局钩子,我读了xkeyhook xkeyhookkeybord。。。不工作所有样本(让我思考如何最好地实现。。。。感谢*

    public X11Hotkey(Gdk.Key key, Gdk.ModifierType modifiers)
    {
        this.key = key;
        this.modifiers = modifiers;
        Gdk.Window rootWin = Gdk.Global.DefaultRootWindow;
        IntPtr xDisplay = GetXDisplay(rootWin);
        this.keycode = XKeysymToKeycode(xDisplay, (int)this.key);
        //here ask the filter 
        rootWin.AddFilter(new Gdk.FilterFunc(FilterFunction));
    }
    //function is not executed
    private Gdk.FilterReturn FilterFunction(IntPtr xEvent, Gdk.Event evnt)
    {
        XKeyEvent xKeyEvent = (XKeyEvent)Marshal.PtrToStructure(
            xEvent, 
            typeof(XKeyEvent));
        if (xKeyEvent.type == KeyPress)
        {
            if (xKeyEvent.keycode == this.keycode 
                && xKeyEvent.state == (uint)this.modifiers)
            {
                this.OnPressed(EventArgs.Empty);
            }
        }
        return Gdk.FilterReturn.Continue;
    }

过滤器甚至不返回。。。该怎么办??

mono-csharp-linux(ubuntu)全局挂钩键盘

 public delegate void SpecialKeyPressedHandler(object o, SpecialKey key);
    public enum SpecialKey 
    {
        one = Gdk.Key.exclam,
        two = Gdk.Key.at,
        tree = Gdk.Key.numbersign,
        four = Gdk.Key.dollar,
        five = Gdk.Key.percent,
        six = Gdk.Key.asciicircum,
        seven = Gdk.Key.ampersand,
        eight = Gdk.Key.asterisk,
        nine = Gdk.Key.parenleft,
        nul = Gdk.Key.parenright,
        retu = Gdk.Key.Return
    };
    public class SpecialKeys
    {
        private Hashtable key_map = new Hashtable();
        private Hashtable key_registrations = new Hashtable();
        private IEnumerable keycode_list;
        private TimeSpan raise_delay = new TimeSpan(0);
        private DateTime last_raise = DateTime.MinValue;
        public SpecialKeys()
        {
            Console.WriteLine("init");
            keycode_list = BuildKeyCodeList();
            InitializeKeys();
        }
        public void Dispose()
        {
            UnitializeKeys();
        }
        public void RegisterHandler(SpecialKeyPressedHandler handler, params SpecialKey [] specialKeys)
        {
            foreach(SpecialKey specialKey in specialKeys) {
                if(key_map.Contains(specialKey)) {
                    int key = (int)key_map[specialKey];
                    key_registrations[key] = Delegate.Combine(key_registrations[key] as Delegate, handler);
                }
            }
        }
        public void UnregisterHandler(SpecialKeyPressedHandler handler, params SpecialKey [] specialKeys)
        {
            foreach(SpecialKey specialKey in specialKeys) {
                if(key_map.Contains(specialKey)) {
                    int key = (int)key_map[specialKey];
                    key_registrations[key] = Delegate.Remove(key_registrations[key] as Delegate, handler); 
                }
            }
        }
        private IEnumerable BuildKeyCodeList()
        {
            ArrayList kc_list = new ArrayList();
            foreach(SpecialKey key in Enum.GetValues(typeof(SpecialKey))) {
                IntPtr xdisplay = gdk_x11_get_default_xdisplay();
                if(!xdisplay.Equals(IntPtr.Zero)) {
                    int keycode = XKeysymToKeycode(xdisplay, key);
                    if(keycode != 0) {
                        key_map[keycode] = key;
                        key_map[key] = keycode;
                        kc_list.Add(keycode);
                    }
                }
            }
            return kc_list;
        }
        private void InitializeKeys()
        {
            for(int i = 0; i < Gdk.Display.Default.NScreens; i++) {
                Gdk.Screen screen = Gdk.Display.Default.GetScreen(i);
                foreach(int keycode in keycode_list) {
                    GrabKey(screen.RootWindow, keycode);
                }
                screen.RootWindow.AddFilter(FilterKey);
            }

        }
        private void UnitializeKeys() 
        {
            for(int i = 0; i < Gdk.Display.Default.NScreens; i++) {
                Gdk.Screen screen = Gdk.Display.Default.GetScreen(i);
                foreach(int keycode in keycode_list) {
                    UngrabKey(screen.RootWindow, keycode);
                }
                screen.RootWindow.RemoveFilter(FilterKey);
            }
        }
        private void GrabKey(Gdk.Window root, int keycode)
        {   
            IntPtr xid = gdk_x11_drawable_get_xid(root.Handle);
            IntPtr xdisplay = gdk_x11_get_default_xdisplay();
            gdk_error_trap_push();
            XGrabKey(xdisplay, keycode, XModMask.None, xid, true, XGrabMode.Async, XGrabMode.Async);
            XGrabKey(xdisplay, keycode, XModMask.Mod2, xid, true, XGrabMode.Async, XGrabMode.Async);
            XGrabKey(xdisplay, keycode, XModMask.Mod5, xid, true, XGrabMode.Async, XGrabMode.Async);
            XGrabKey(xdisplay, keycode, XModMask.Lock, xid, true, XGrabMode.Async, XGrabMode.Async);
            XGrabKey(xdisplay, keycode, XModMask.Mod2 | XModMask.Mod5, xid, true, XGrabMode.Async, XGrabMode.Async);
            XGrabKey(xdisplay, keycode, XModMask.Mod2 | XModMask.Lock, xid, true, XGrabMode.Async, XGrabMode.Async);
            XGrabKey(xdisplay, keycode, XModMask.Mod5 | XModMask.Lock, xid, true, XGrabMode.Async, XGrabMode.Async);
            XGrabKey(xdisplay, keycode, XModMask.Mod2 | XModMask.Mod5 | XModMask.Lock, xid, true, 
                XGrabMode.Async, XGrabMode.Async);
            gdk_flush();
            if(gdk_error_trap_pop() != 0) {
                Console.Error.WriteLine(": Could not grab key {0} (maybe another application has grabbed this key)", keycode);
            }
        }
        private void UngrabKey(Gdk.Window root, int keycode)
        {
            IntPtr xid = gdk_x11_drawable_get_xid(root.Handle);
            IntPtr xdisplay = gdk_x11_get_default_xdisplay();
            gdk_error_trap_push();
            XUngrabKey(xdisplay, keycode, XModMask.None, xid);
            XUngrabKey(xdisplay, keycode, XModMask.Mod2, xid);
            XUngrabKey(xdisplay, keycode, XModMask.Mod5, xid);
            XUngrabKey(xdisplay, keycode, XModMask.Lock, xid);
            XUngrabKey(xdisplay, keycode, XModMask.Mod2 | XModMask.Mod5, xid);
            XUngrabKey(xdisplay, keycode, XModMask.Mod2 | XModMask.Lock, xid);
            XUngrabKey(xdisplay, keycode, XModMask.Mod5 | XModMask.Lock, xid);
            XUngrabKey(xdisplay, keycode, XModMask.Mod2 | XModMask.Mod5 | XModMask.Lock,xid);
            gdk_flush();
            if(gdk_error_trap_pop() != 0) {
                Console.Error.WriteLine(": Could not ungrab key {0} (maybe another application has grabbed this key)", keycode);
            }
        }
        private Gdk.FilterReturn FilterKey(IntPtr xeventPtr, Gdk.Event gdkEvent)
        {
            Console.WriteLine("filter "+ gdkEvent.Type);
            if(DateTime.Now - last_raise < raise_delay) {
                return Gdk.FilterReturn.Continue;
            }
            last_raise = DateTime.Now;
            XKeyEvent xevent = (XKeyEvent)Marshal.PtrToStructure(xeventPtr, typeof(XKeyEvent));
            if(xevent.type != XEventName.KeyPress) {
                return Gdk.FilterReturn.Continue;
            }
            int keycode = (int)xevent.keycode;
            object x = key_map[keycode];
            Console.WriteLine("filter "+ keycode);
            if(x == null) {
                return Gdk.FilterReturn.Continue;
            }
            SpecialKey key = (SpecialKey)key_map[keycode];
            if(key_registrations[keycode] != null) {
                x = key_registrations[keycode];
                if(x is SpecialKeyPressedHandler) {
                    ((SpecialKeyPressedHandler)x)(this, key);    
                }
                return Gdk.FilterReturn.Remove;
            }
            return Gdk.FilterReturn.Continue;
        }
        public TimeSpan Delay {
            get {
                return raise_delay;
            }
            set {
                raise_delay = value;
            }
        }
        [StructLayout(LayoutKind.Sequential)]
        private struct XKeyEvent
        {
            public XEventName type;
            public IntPtr serial;
            public bool send_event;
            public IntPtr display;
            public IntPtr window;
            public IntPtr root;
            public IntPtr subwindow;
            public IntPtr time;
            public int x;
            public int y;
            public int x_root;
            public int x_y;
            public uint state;
            public uint keycode;
            public bool same_screen;
        }
        [DllImport("libX11")]
        private static extern int XKeysymToKeycode(IntPtr display, SpecialKey keysym);
        [DllImport("libX11")]
        private static extern void XGrabKey(IntPtr display, int keycode, XModMask modifiers, 
            IntPtr window, bool owner_events, XGrabMode pointer_mode, XGrabMode keyboard_mode);
        [DllImport("libX11")]
        private static extern void XUngrabKey(IntPtr display, int keycode, XModMask modifiers, 
            IntPtr window);
        [DllImport("gdk-x11-2.0")]
        private static extern IntPtr gdk_x11_drawable_get_xid(IntPtr window);
        [DllImport("gdk-x11-2.0")]
        private static extern IntPtr gdk_x11_get_default_xdisplay();
        [DllImport("gdk-x11-2.0")]
        private static extern void gdk_error_trap_push();
        [DllImport("gdk-x11-2.0")]
        private static extern int gdk_error_trap_pop();
        [DllImport("gdk-x11-2.0")]
        private static extern void gdk_flush();
        [Flags]
        private enum XModMask {
            None    = 0,
            Shift   = 1 << 0,
            Lock    = 1 << 1,
            Control = 1 << 2,
            Mod1    = 1 << 3,
            Mod2    = 1 << 4,
            Mod3    = 1 << 5,
            Mod4    = 1 << 6,
            Mod5    = 1 << 7
        }
        private enum XGrabMode {
            Sync  = 0,
            Async = 1
        }
        private enum XEventName {
            KeyPress   = 2,
            KeyRelease = 3,
        }
    }

一切工作!

GDK过滤器不是作为全局挂钩设计的。它们只会为您提供在正常处理之前已经交付给流程的事件。

要安排将特定组合键的键盘事件发送到进程,请在根窗口中使用XGrabKey功能。请注意,有些通常不被视为"修饰符"的东西,如CapsLock,被X11视为修饰符,您需要掌握要忽略的修饰符的所有可能配置。你可能也会发现这个问题很有用。

X在设计时没有考虑到全局键盘或鼠标挂钩。虽然可以将所有事件传递到您的流程,但在不干扰其他流程的情况下,这是不可能的。