Beispiel #1
0
        private static void SendString(string str)
        {
            List <VK> modifiers = new List <VK>();
            bool      use_gtk_hack = false, use_office_hack = false;

            const int     len  = 256;
            StringBuilder buf  = new StringBuilder(len);
            var           hwnd = NativeMethods.GetForegroundWindow();

            if (NativeMethods.GetClassName(hwnd, buf, len) > 0)
            {
                string wclass = buf.ToString();

                /* HACK: GTK+ applications behave differently with Unicode, and some
                 * applications such as XChat for Windows rename their own top-level
                 * window, so we parse through the names we know in order to detect
                 * a GTK+ application. */
                if (wclass == "gdkWindowToplevel" || wclass == "xchatWindowToplevel")
                {
                    use_gtk_hack = true;
                }

                /* HACK: in MS Office, some symbol insertions change the text font
                 * without returning to the original font. To avoid this, we output
                 * a space character, then go left, insert our actual symbol, then
                 * go right and backspace. */
                /* These are the actual window class names for Outlook and Word…
                 * TODO: PowerPoint ("PP(7|97|9|10)FrameClass") */
                if (wclass == "rctrl_renwnd32" || wclass == "OpusApp")
                {
                    use_office_hack = true && Settings.InsertZwsp.Value;
                }
            }

            /* Clear keyboard modifiers if we need one of our custom hacks */
            if (use_gtk_hack || use_office_hack)
            {
                VK[] all_modifiers = new VK[]
                {
                    VK.LSHIFT, VK.RSHIFT,
                    VK.LCONTROL, VK.RCONTROL,
                    VK.LMENU, VK.RMENU,
                };

                foreach (VK vk in all_modifiers)
                {
                    if ((NativeMethods.GetKeyState(vk) & 0x80) == 0x80)
                    {
                        modifiers.Add(vk);
                    }
                }

                foreach (VK vk in modifiers)
                {
                    SendKeyUp(vk);
                }
            }

            if (use_gtk_hack)
            {
                /* Wikipedia says Ctrl+Shift+u, release, then type the four hex
                 * digits, and press Enter.
                 * (http://en.wikipedia.org/wiki/Unicode_input). */
                SendKeyDown(VK.LCONTROL);
                SendKeyDown(VK.LSHIFT);
                SendKeyPress((VK)'U');
                SendKeyUp(VK.LSHIFT);
                SendKeyUp(VK.LCONTROL);

                foreach (var ch in str)
                {
                    foreach (var key in String.Format("{0:X04} ", (short)ch))
                    {
                        SendKeyPress((VK)key);
                    }
                }
            }
            else
            {
                InputSequence Seq = new InputSequence();

                if (use_office_hack)
                {
                    Seq.Add((ScanCodeShort)'\u200b');
                    Seq.Add((VirtualKeyShort)VK.LEFT);
                }

                for (int i = 0; i < str.Length; i++)
                {
                    Seq.Add((ScanCodeShort)str[i]);
                }

                if (use_office_hack)
                {
                    Seq.Add((VirtualKeyShort)VK.RIGHT);
                }

                Seq.Send();
            }

            /* Restore keyboard modifiers if we needed one of our custom hacks */
            if (use_gtk_hack || use_office_hack)
            {
                foreach (VK vk in modifiers)
                {
                    SendKeyDown(vk);
                }
            }
        }
Beispiel #2
0
    private static void SendString(string str)
    {
        List<VK> modifiers = new List<VK>();

        /* HACK: GTK+ applications behave differently with Unicode, and some
         * applications such as XChat for Windows rename their own top-level
         * window, so we parse through the names we know in order to detect
         * a GTK+ application. */
        bool use_gtk_hack = m_window_is_gtk;

        /* HACK: in MS Office, some symbol insertions change the text font
         * without returning to the original font. To avoid this, we output
         * a space character, then go left, insert our actual symbol, then
         * go right and backspace. */
        /* These are the actual window class names for Outlook and Word…
         * TODO: PowerPoint ("PP(7|97|9|10)FrameClass") */
        bool use_office_hack = m_window_is_office && Settings.InsertZwsp.Value;

        /* Clear keyboard modifiers if we need one of our custom hacks */
        if (use_gtk_hack || use_office_hack)
        {
            VK[] all_modifiers = new VK[]
            {
                VK.LSHIFT, VK.RSHIFT,
                VK.LCONTROL, VK.RCONTROL,
                VK.LMENU, VK.RMENU,
                /* Needs to be released, too, otherwise Caps Lock + é on
                 * a French keyboard will print garbage if Caps Lock is
                 * not released soon enough. See note below. */
                VK.CAPITAL,
            };

            foreach (VK vk in all_modifiers)
                if ((NativeMethods.GetKeyState(vk) & 0x80) == 0x80)
                    modifiers.Add(vk);

            foreach (VK vk in modifiers)
                SendKeyUp(vk);
        }

        if (use_gtk_hack)
        {
            /* XXX: We need to disable caps lock because GTK’s Shift-Ctrl-U
             * input mode (see below) doesn’t work when Caps Lock is on. */
            bool has_capslock = NativeMethods.GetKeyState(VK.CAPITAL) != 0;
            if (has_capslock)
                SendKeyPress(VK.CAPITAL);

            foreach (var ch in str)
            {
                if (false)
                {
                    /* FIXME: there is a possible optimisation here where we do
                     * not have to send the whole unicode sequence for regular
                     * ASCII characters. However, SendKeyPress() needs a VK, so
                     * we need an ASCII to VK conversion method, together with
                     * the proper keyboard modifiers. Maybe not worth it.
                     * Also, we cannot use KeySequence because GTK+ seems to
                     * ignore SendInput(). */
                    //SendKeyPress((VK)char.ToUpper(ch));
                }
                else
                {
                    /* Wikipedia says Ctrl+Shift+u, release, then type the four
                     * hex digits, and press Enter.
                     * (http://en.wikipedia.org/wiki/Unicode_input). */
                    SendKeyDown(VK.LCONTROL);
                    SendKeyDown(VK.LSHIFT);
                    SendKeyPress((VK)'U');
                    SendKeyUp(VK.LSHIFT);
                    SendKeyUp(VK.LCONTROL);

                    foreach (var key in String.Format("{0:X04} ", (short)ch))
                        SendKeyPress((VK)key);
                }
            }

            if (has_capslock)
                SendKeyPress(VK.CAPITAL);
        }
        else
        {
            InputSequence Seq = new InputSequence();

            if (use_office_hack)
            {
                Seq.AddInput((ScanCodeShort)'\u200b');
                Seq.AddInput((VirtualKeyShort)VK.LEFT);
            }

            foreach (char ch in str)
            {
                Seq.AddInput((ScanCodeShort)ch);
            }

            if (use_office_hack)
            {
                Seq.AddInput((VirtualKeyShort)VK.RIGHT);
            }

            Seq.Send();
        }

        /* Restore keyboard modifiers if we needed one of our custom hacks */
        if (use_gtk_hack || use_office_hack)
        {
            foreach (VK vk in modifiers)
                SendKeyDown(vk);
        }
    }
Beispiel #3
0
        private static void SendString(string str)
        {
            List <VK> modifiers = new List <VK>();

            /* HACK: GTK+ applications behave differently with Unicode, and some
             * applications such as XChat for Windows rename their own top-level
             * window, so we parse through the names we know in order to detect
             * a GTK+ application. */
            bool use_gtk_hack = m_window_is_gtk;

            /* HACK: in MS Office, some symbol insertions change the text font
             * without returning to the original font. To avoid this, we output
             * a space character, then go left, insert our actual symbol, then
             * go right and backspace. */
            /* These are the actual window class names for Outlook and Word…
             * TODO: PowerPoint ("PP(7|97|9|10)FrameClass") */
            bool use_office_hack = m_window_is_office && Settings.InsertZwsp.Value;

            /* Clear keyboard modifiers if we need one of our custom hacks */
            if (use_gtk_hack || use_office_hack)
            {
                VK[] all_modifiers = new VK[]
                {
                    VK.LSHIFT, VK.RSHIFT,
                    VK.LCONTROL, VK.RCONTROL,
                    VK.LMENU, VK.RMENU,

                    /* Needs to be released, too, otherwise Caps Lock + é on
                     * a French keyboard will print garbage if Caps Lock is
                     * not released soon enough. See note below. */
                    VK.CAPITAL,
                };

                foreach (VK vk in all_modifiers)
                {
                    if ((NativeMethods.GetKeyState(vk) & 0x80) == 0x80)
                    {
                        modifiers.Add(vk);
                    }
                }

                foreach (VK vk in modifiers)
                {
                    SendKeyUp(vk);
                }
            }

            if (use_gtk_hack)
            {
                /* XXX: We need to disable caps lock because GTK’s Shift-Ctrl-U
                 * input mode (see below) doesn’t work when Caps Lock is on. */
                bool has_capslock = NativeMethods.GetKeyState(VK.CAPITAL) != 0;
                if (has_capslock)
                {
                    SendKeyPress(VK.CAPITAL);
                }

                foreach (var ch in str)
                {
                    if (false)
                    {
                        /* FIXME: there is a possible optimisation here where we do
                         * not have to send the whole unicode sequence for regular
                         * ASCII characters. However, SendKeyPress() needs a VK, so
                         * we need an ASCII to VK conversion method, together with
                         * the proper keyboard modifiers. Maybe not worth it.
                         * Also, we cannot use KeySequence because GTK+ seems to
                         * ignore SendInput(). */
                        //SendKeyPress((VK)char.ToUpper(ch));
                    }
                    else
                    {
                        /* Wikipedia says Ctrl+Shift+u, release, then type the four
                         * hex digits, and press Enter.
                         * (http://en.wikipedia.org/wiki/Unicode_input). */
                        SendKeyDown(VK.LCONTROL);
                        SendKeyDown(VK.LSHIFT);
                        SendKeyPress((VK)'U');
                        SendKeyUp(VK.LSHIFT);
                        SendKeyUp(VK.LCONTROL);

                        foreach (var key in String.Format("{0:X04} ", (short)ch))
                        {
                            SendKeyPress((VK)key);
                        }
                    }
                }

                if (has_capslock)
                {
                    SendKeyPress(VK.CAPITAL);
                }
            }
            else
            {
                InputSequence Seq = new InputSequence();

                if (use_office_hack)
                {
                    Seq.AddInput((ScanCodeShort)'\u200b');
                    Seq.AddInput((VirtualKeyShort)VK.LEFT);
                }

                foreach (char ch in str)
                {
                    Seq.AddInput((ScanCodeShort)ch);
                }

                if (use_office_hack)
                {
                    Seq.AddInput((VirtualKeyShort)VK.RIGHT);
                }

                Seq.Send();
            }

            /* Restore keyboard modifiers if we needed one of our custom hacks */
            if (use_gtk_hack || use_office_hack)
            {
                foreach (VK vk in modifiers)
                {
                    SendKeyDown(vk);
                }
            }
        }
Beispiel #4
0
    private static void SendString(string str)
    {
        List<VK> modifiers = new List<VK>();
        bool use_gtk_hack = false, use_office_hack = false;

        const int len = 256;
        StringBuilder buf = new StringBuilder(len);
        var hwnd = NativeMethods.GetForegroundWindow();
        if (NativeMethods.GetClassName(hwnd, buf, len) > 0)
        {
            string wclass = buf.ToString();

            /* HACK: GTK+ applications behave differently with Unicode, and some
             * applications such as XChat for Windows rename their own top-level
             * window, so we parse through the names we know in order to detect
             * a GTK+ application. */
            if (wclass == "gdkWindowToplevel" || wclass == "xchatWindowToplevel")
                use_gtk_hack = true;

            /* HACK: in MS Office, some symbol insertions change the text font
             * without returning to the original font. To avoid this, we output
             * a space character, then go left, insert our actual symbol, then
             * go right and backspace. */
            /* These are the actual window class names for Outlook and Word…
             * TODO: PowerPoint ("PP(7|97|9|10)FrameClass") */
            if (wclass == "rctrl_renwnd32" || wclass == "OpusApp")
                use_office_hack = true && Settings.InsertZwsp.Value;
        }

        /* Clear keyboard modifiers if we need one of our custom hacks */
        if (use_gtk_hack || use_office_hack)
        {
            VK[] all_modifiers = new VK[]
            {
                VK.LSHIFT, VK.RSHIFT,
                VK.LCONTROL, VK.RCONTROL,
                VK.LMENU, VK.RMENU,
            };

            foreach (VK vk in all_modifiers)
                if ((NativeMethods.GetKeyState(vk) & 0x80) == 0x80)
                    modifiers.Add(vk);

            foreach (VK vk in modifiers)
                SendKeyUp(vk);
        }

        if (use_gtk_hack)
        {
            foreach (var ch in str)
            {
                if (false)
                {
                    /* FIXME: there is a possible optimisation here where we do
                     * not have to send the whole unicode sequence for regular
                     * ASCII characters. However, SendKeyPress() needs a VK, so
                     * we need an ASCII to VK conversion method, together with
                     * the proper keyboard modifiers. Maybe not worth it.
                     * Also, we cannot use KeySequence because GTK+ seems to
                     * ignore SendInput(). */
                    //SendKeyPress((VK)char.ToUpper(ch));
                }
                else
                {
                    /* Wikipedia says Ctrl+Shift+u, release, then type the four
                     * hex digits, and press Enter.
                     * (http://en.wikipedia.org/wiki/Unicode_input). */
                    SendKeyDown(VK.LCONTROL);
                    SendKeyDown(VK.LSHIFT);
                    SendKeyPress((VK)'U');
                    SendKeyUp(VK.LSHIFT);
                    SendKeyUp(VK.LCONTROL);

                    foreach (var key in String.Format("{0:X04} ", (short)ch))
                        SendKeyPress((VK)key);
                }
            }
        }
        else
        {
            InputSequence Seq = new InputSequence();

            if (use_office_hack)
            {
                Seq.AddInput((ScanCodeShort)'\u200b');
                Seq.AddInput((VirtualKeyShort)VK.LEFT);
            }

            foreach (char ch in str)
            {
                Seq.AddInput((ScanCodeShort)ch);
            }

            if (use_office_hack)
            {
                Seq.AddInput((VirtualKeyShort)VK.RIGHT);
            }

            Seq.Send();
        }

        /* Restore keyboard modifiers if we needed one of our custom hacks */
        if (use_gtk_hack || use_office_hack)
        {
            foreach (VK vk in modifiers)
                SendKeyDown(vk);
        }
    }
Beispiel #5
0
        private static void SendString(string str)
        {
            List <VK> modifiers = new List <VK>();

            /* HACK: GTK+ applications behave differently with Unicode, and some
             * applications such as XChat for Windows rename their own top-level
             * window, so we parse through the names we know in order to detect
             * a GTK+ application. */
            bool use_gtk_hack = KeyboardLayout.Window.IsGtk;

            /* HACK: Notepad++ and LibreOffice are unable to output high plane
             * Unicode characters, so we rely on clipboard hacking when the
             * composed string contains such characters. */
            bool use_clipboard_hack = KeyboardLayout.Window.IsNPPOrLO &&
                                      HasSurrogates(str);

            /* HACK: in MS Office, some symbol insertions change the text font
             * without returning to the original font. To avoid this, we output
             * a space character, then go left, insert our actual symbol, then
             * go right and backspace. */
            /* These are the actual window class names for Outlook and Word…
             * TODO: PowerPoint ("PP(7|97|9|10)FrameClass") */
            bool use_office_hack = KeyboardLayout.Window.IsOffice &&
                                   Settings.InsertZwsp.Value;

            /* Clear keyboard modifiers if we need one of our custom hacks */
            if (use_gtk_hack || use_office_hack)
            {
                VK[] all_modifiers =
                {
                    VK.LSHIFT,   VK.RSHIFT,
                    VK.LCONTROL, VK.RCONTROL,
                    VK.LMENU,    VK.RMENU,

                    /* Needs to be released, too, otherwise Caps Lock + é on
                     * a French keyboard will print garbage if Caps Lock is
                     * not released soon enough. See note below. */
                    VK.CAPITAL,
                };

                foreach (VK vk in all_modifiers)
                {
                    if ((NativeMethods.GetKeyState(vk) & 0x80) == 0x80)
                    {
                        modifiers.Add(vk);
                    }
                }

                foreach (VK vk in modifiers)
                {
                    SendKeyUp(vk);
                }
            }

            if (use_gtk_hack)
            {
                /* XXX: We need to disable caps lock because GTK’s Shift-Ctrl-U
                 * input mode (see below) doesn’t work when Caps Lock is on. */
                bool has_capslock = NativeMethods.GetKeyState(VK.CAPITAL) != 0;
                if (has_capslock)
                {
                    SendKeyPress(VK.CAPITAL);
                }

                foreach (var ch in str)
                {
                    if (false)
                    {
                        /* FIXME: there is a possible optimisation here where we do
                         * not have to send the whole unicode sequence for regular
                         * ASCII characters. However, SendKeyPress() needs a VK, so
                         * we need an ASCII to VK conversion method, together with
                         * the proper keyboard modifiers. Maybe not worth it.
                         * Also, we cannot use KeySequence because GTK+ seems to
                         * ignore SendInput(). */
                        //SendKeyPress((VK)char.ToUpper(ch));
                    }
                    else
                    {
                        /* Wikipedia says Ctrl+Shift+u, release, then type the four
                         * hex digits, and press Enter.
                         * (http://en.wikipedia.org/wiki/Unicode_input). */
                        SendKeyDown(VK.LCONTROL);
                        SendKeyDown(VK.LSHIFT);
                        SendKeyPress((VK)'U');
                        SendKeyUp(VK.LSHIFT);
                        SendKeyUp(VK.LCONTROL);

                        foreach (var key in $"{(short)ch:X04} ")
                        {
                            SendKeyPress((VK)key);
                        }
                    }
                }

                if (has_capslock)
                {
                    SendKeyPress(VK.CAPITAL);
                }
            }
            else if (use_clipboard_hack)
            {
                // We do not use Clipboard.GetDataObject because I have been
                // unable to restore the clipboard properly. This is reasonable
                // and has been tested with several clipboard content types.
                var backup_text  = Clipboard.GetText();
                var backup_image = Clipboard.GetImage();
                var backup_audio = Clipboard.GetAudioStream();
                var backup_files = Clipboard.GetFileDropList();

                // Use Shift+Insert instead of Ctrl-V because Ctrl-V will misbehave
                // if a Shift key is held down. Using Shift+Insert even works if the
                // compose key is Insert.
                Clipboard.SetText(str);
                SendKeyDown(VK.SHIFT);
                SendKeyPress(VK.INSERT);
                SendKeyUp(VK.SHIFT);
                Clipboard.Clear();

                if (!string.IsNullOrEmpty(backup_text))
                {
                    Clipboard.SetText(backup_text);
                }
                if (backup_image != null)
                {
                    Clipboard.SetImage(backup_image);
                }
                if (backup_audio != null)
                {
                    Clipboard.SetAudio(backup_audio);
                }
                if (backup_files != null && backup_files.Count > 0)
                {
                    Clipboard.SetFileDropList(backup_files);
                }
            }
            else
            {
                InputSequence Seq = new InputSequence();

                if (use_office_hack)
                {
                    Seq.AddInput((ScanCodeShort)'\u200b');
                    Seq.AddInput((VirtualKeyShort)VK.LEFT);
                }

                foreach (char ch in str)
                {
                    Seq.AddInput((ScanCodeShort)ch);
                }

                if (use_office_hack)
                {
                    Seq.AddInput((VirtualKeyShort)VK.RIGHT);
                }

                Seq.Send();
            }

            /* Restore keyboard modifiers if we needed one of our custom hacks */
            if (use_gtk_hack || use_office_hack)
            {
                foreach (VK vk in modifiers)
                {
                    SendKeyDown(vk);
                }
            }
        }
Beispiel #6
0
        private static void SendString(string str)
        {
            List <VK> modifiers = new List <VK>();

            // HACK: GTK+ applications will crash when receiving surrogate pairs through VK.PACKET,
            // so we use the Ctrl-Shift-u special sequence.
            bool use_gtk_hack = KeyboardLayout.Window.IsGtk &&
                                str.Any(x => char.IsSurrogate(x));

            // HACK: in MS Office, some symbol insertions change the text font
            // without returning to the original font. To avoid this, we output
            // a space character, then go left, insert our actual symbol, then
            // go right and backspace.
            // These are the actual window class names for Outlook and Word…
            // TODO: PowerPoint ("PP(7|97|9|10)FrameClass")
            bool use_office_hack = KeyboardLayout.Window.IsOffice &&
                                   Settings.InsertZwsp.Value;

            InputSequence seq = new InputSequence();

            // Clear keyboard modifiers if we need one of our custom hacks
            if (use_gtk_hack || use_office_hack)
            {
                VK[] all_modifiers =
                {
                    VK.LSHIFT,   VK.RSHIFT,
                    VK.LCONTROL, VK.RCONTROL,
                    VK.LMENU,    VK.RMENU,
                    // Needs to be released, too, otherwise Caps Lock + é on
                    // a French keyboard will print garbage if Caps Lock is
                    // not released soon enough. See note below.
                    VK.CAPITAL,
                };

                modifiers = all_modifiers.Where(x => (NativeMethods.GetKeyState(x) & 0x80) == 0x80)
                            .ToList();
                modifiers.ForEach(vk => seq.AddKeyEvent(EventType.KeyUp, vk));
            }

            if (use_office_hack)
            {
                seq.AddUnicodeInput('\u200b');
                seq.AddKeyEvent(EventType.KeyUpDown, VK.LEFT);
            }

            for (int i = 0; i < str.Length; ++i)
            {
                char ch = str[i];

                if (ch == '\n' || ch == '\r')
                {
                    // On some applications (e.g. Chrome or PowerPoint), \n cannot be injected
                    // through its scancode, so we send the virtual key instead.
                    seq.AddKeyEvent(EventType.KeyUpDown, VK.RETURN);
                }
                else if (use_gtk_hack && char.IsSurrogate(ch))
                {
                    // Sanity check
                    if (i + 1 >= str.Length || !char.IsHighSurrogate(ch) || !char.IsLowSurrogate(str, i + 1))
                    {
                        continue;
                    }

                    var codepoint = char.ConvertToUtf32(ch, str[++i]);

                    // GTK+ hack:
                    //  - We need to disable Caps Lock
                    //  - Wikipedia says Ctrl+Shift+u, release, then type the four hex digits,
                    //    and press Enter (http://en.wikipedia.org/wiki/Unicode_input).
                    //  - The Gimp accepts either Enter or Space but stops immediately in both
                    //    cases.
                    //  - Inkscape stops after Enter, but allows to chain sequences using Space.
                    bool has_capslock = NativeMethods.GetKeyState(VK.CAPITAL) != 0;
                    if (has_capslock)
                    {
                        seq.AddKeyEvent(EventType.KeyUpDown, VK.CAPITAL);
                    }

                    seq.AddKeyEvent(EventType.KeyDown, VK.LCONTROL);
                    seq.AddKeyEvent(EventType.KeyDown, VK.LSHIFT);
                    seq.AddKeyEvent(EventType.KeyUpDown, VK.U);
                    seq.AddKeyEvent(EventType.KeyUp, VK.LSHIFT);
                    seq.AddKeyEvent(EventType.KeyUp, VK.LCONTROL);
                    foreach (var key in $"{codepoint:X04}")
                    {
                        seq.AddKeyEvent(EventType.KeyUpDown, (VK)key);
                    }
                    seq.AddKeyEvent(EventType.KeyUpDown, VK.RETURN);

                    if (has_capslock)
                    {
                        seq.AddKeyEvent(EventType.KeyUpDown, VK.CAPITAL);
                    }
                }
                else
                {
                    seq.AddUnicodeInput(ch);
                }
            }

            if (use_office_hack)
            {
                seq.AddKeyEvent(EventType.KeyUpDown, VK.RIGHT);
            }

            // Restore keyboard modifier state if we needed one of our custom hacks
            modifiers.ForEach(vk => seq.AddKeyEvent(EventType.KeyDown, vk));

            // Send the whole keyboard sequence
            seq.Send();
        }