/// <summary>
        /// Returns a <see cref="System.String"/> that represents this Gdk key.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <returns>
        /// A <see cref="System.String"/> that represents this instance.
        /// </returns>
        /// <remarks>
        /// This is taken from MonoDevelop's code.
        /// </remarks>
        public static string ToString(Key key)
        {
            // Pull out the unicode value for the key. If we have one, we use
            // that instead.
            var c = (char)Keyval.ToUnicode((uint)key);

            if (c != 0)
            {
                return(c == ' '
                                        ? "Space"
                                        : Char.ToUpper(c).ToString());
            }

            // Some keys do not convert directly because there are multiple
            // values for the enumeration. This is used to normalize the values.
            switch (key)
            {
            case Key.Next:
                return("Page_Down");

            case Key.L1:
                return("F11");

            case Key.L2:
                return("F12");
            }

            // Return the string representation of the key.
            return(key.ToString());
        }
        /// <summary>
        /// Breaks apart an event key into the individual and normalized key and
        /// any modifiers.
        /// </summary>
        /// <param name="evt">The evt.</param>
        /// <param name="key">The key.</param>
        /// <param name="modifiers">The mod.</param>
        public static void DecomposeKeys(
            EventKey evt,
            out Key key,
            out ModifierType modifiers)
        {
            // Use the keymap to decompose various elements of the hardware keys.
            uint keyval;
            int  effectiveGroup,
                 level;
            ModifierType consumedModifiers;

            keymap.TranslateKeyboardState(
                evt.HardwareKeycode,
                evt.State,
                evt.Group,
                out keyval,
                out effectiveGroup,
                out level,
                out consumedModifiers);

            // Break out the identified keys and modifiers.
            key       = (Key)keyval;
            modifiers = evt.State & ~consumedModifiers;

            // Normalize some of the keys that don't make sense.
            if (key == Key.ISO_Left_Tab)
            {
                key        = Key.Tab;
                modifiers |= ModifierType.ShiftMask;
            }

            // Check to see if we are a character and pull out the shift key if
            // it is a capital letter. This is used to normalize so all the
            // keys are uppercase with a shift modifier.
            bool shiftWasConsumed = ((evt.State ^ modifiers) & ModifierType.ShiftMask)
                                    != 0;
            var unicode = (char)Keyval.ToUnicode((uint)key);

            if (shiftWasConsumed && Char.IsUpper(unicode))
            {
                modifiers |= ModifierType.ShiftMask;
            }

            if (Char.IsLetter(unicode) &&
                Char.IsLower(unicode))
            {
                key = (Key)Char.ToUpper(unicode);
            }
        }