当在GTK#app

时间:2015-09-21 14:21:58

标签: macos mono gtk monomac

我正在尝试使用MonoMac公开的API来改进运行在Mac OS上的GTK#应用程序,并使用 NSMenuItem NSMenu 构建本机Mac菜单类。

到目前为止,一切看起来都不错,我能够将一些键盘加速器(KeyEquivalent)设置到菜单,但问题是他们不会对键盘做出反应。键组合在菜单中正确显示,但按键不执行任何操作。使用鼠标选择菜单项可以正常工作。

以下是我用来初始化环境的一些代码:

NSApplication.InitDrawingBridge ();
NSApplication.Init ();

NSMenuItem super = new NSMenuItem (DataHelper.ProductName);
super.Submenu = new NSMenu (DataHelper.ProductName);

NSMenu mainMenu = new NSMenu ();
mainMenu.AddItem (super);

NSApplication.SharedApplication.MainMenu = mainMenu;

< menu initialization comes here >

NSApplication.SharedApplication.Delegate = new AppDelegate ();
NSApplication.SharedApplication.ActivateIgnoringOtherApps (true);

为了让键盘事件传递到菜单,我还有什么需要做的吗?

我查看了MonoDevelop的代码参考,找不到任何可以产生差异的东西。我使用了一些代码来设置KeyEquivalent值。

1 个答案:

答案 0 :(得分:0)

事实证明,如果未经处理,GTK不会自动将KeyPress事件发送到菜单。我所做的是在GTK中最外面的容器上捕获事件并手动将其发送到Mac菜单:

  

注意:下面的大部分代码都是从Monodevelop借来的,并且是MIT / X11许可的

private void frmMain_KeyPressEvent (object o, KeyPressEventArgs args)
{
    Gdk.ModifierType state;
    state = GtkWorkarounds.FixMacModifiers (args.Event.State, args.Event.Group);

    string keyEquivalent;
    NSEventModifierMask mask;
    GetKeyEquivalentForGdkKey (args.Event.Key, state, out keyEquivalent, out mask);
    if (keyEquivalent.Length == 0)
        return false;

    var nsEvent = NSEvent.KeyEvent (
        NSEventType.KeyDown, PointF.Empty, mask, 0, 0,
        NSGraphicsContext.CurrentContext, keyEquivalent, keyEquivalent, false, 0);

    if (NSApplication.SharedApplication.MainMenu.PerformKeyEquivalent (nsEvent)) {
        args.RetVal = true;
        return true;
    }
    return false;
}

public static void GetKeyEquivalentForGdkKey (Gdk.Key key, ModifierType modifierType, out string keyEquivalent, out NSEventModifierMask mask)
{
    keyEquivalent = GetKeyEquivalent (key);
    mask = 0;

    if (keyEquivalent.Length == 0)
        return;

    if ((modifierType & Gdk.ModifierType.Mod1Mask) != 0) {
        mask |= NSEventModifierMask.AlternateKeyMask;
        modifierType ^= Gdk.ModifierType.Mod1Mask;
    }
    if ((modifierType & Gdk.ModifierType.ShiftMask) != 0) {
        mask |= NSEventModifierMask.ShiftKeyMask;
        modifierType ^= Gdk.ModifierType.ShiftMask;
    }
    if ((modifierType & Gdk.ModifierType.ControlMask) != 0) {
        mask |= NSEventModifierMask.ControlKeyMask;
        modifierType ^= Gdk.ModifierType.ControlMask;
    }
    if ((modifierType & Gdk.ModifierType.MetaMask) != 0) {
        mask |= NSEventModifierMask.CommandKeyMask;
        modifierType ^= Gdk.ModifierType.MetaMask;
    }
}

static string GetKeyEquivalent (Gdk.Key key)
{
    char c = (char) Gdk.Keyval.ToUnicode ((uint) key);
    if (c != 0)
        return c.ToString ();

    var fk = GetFunctionKey (key);
    if (fk != 0)
        return ((char) fk).ToString ();

    return "";
}

static FunctionKey GetFunctionKey (Gdk.Key key)
{
    switch (key) {
        case Gdk.Key.Return:
            return (FunctionKey) (uint) '\n';
        case Gdk.Key.BackSpace:
            return (FunctionKey) 0x08;
        // NSBackspaceCharacter
        case Gdk.Key.KP_Delete:
        case Gdk.Key.Delete:
            return (FunctionKey) 0x7F;
        // NSDeleteCharacter
        case Gdk.Key.KP_Up:
        case Gdk.Key.Up:
            return FunctionKey.UpArrow;
        case Gdk.Key.KP_Down:
        case Gdk.Key.Down:
            return FunctionKey.DownArrow;
        case Gdk.Key.KP_Left:
        case Gdk.Key.Left:
            return FunctionKey.LeftArrow;
        case Gdk.Key.KP_Right:
        case Gdk.Key.Right:
            return FunctionKey.RightArrow;
        case Gdk.Key.F1:
            return FunctionKey.F1;
        case Gdk.Key.F2:
            return FunctionKey.F2;
        case Gdk.Key.F3:
            return FunctionKey.F3;
        case Gdk.Key.F4:
            return FunctionKey.F4;
        case Gdk.Key.F5:
            return FunctionKey.F5;
        case Gdk.Key.F6:
            return FunctionKey.F6;
        case Gdk.Key.F7:
            return FunctionKey.F7;
        case Gdk.Key.F8:
            return FunctionKey.F8;
        case Gdk.Key.F9:
            return FunctionKey.F9;
        case Gdk.Key.F10:
            return FunctionKey.F10;
        case Gdk.Key.F11:
            return FunctionKey.F11;
        case Gdk.Key.F12:
            return FunctionKey.F12;
        case Gdk.Key.F13:
            return FunctionKey.F13;
        case Gdk.Key.F14:
            return FunctionKey.F14;
        case Gdk.Key.F15:
            return FunctionKey.F15;
        case Gdk.Key.F16:
            return FunctionKey.F16;
        case Gdk.Key.F17:
            return FunctionKey.F17;
        case Gdk.Key.F18:
            return FunctionKey.F18;
        case Gdk.Key.F19:
            return FunctionKey.F19;
        case Gdk.Key.F20:
            return FunctionKey.F20;
        case Gdk.Key.F21:
            return FunctionKey.F21;
        case Gdk.Key.F22:
            return FunctionKey.F22;
        case Gdk.Key.F23:
            return FunctionKey.F23;
        case Gdk.Key.F24:
            return FunctionKey.F24;
        case Gdk.Key.F25:
            return FunctionKey.F25;
        case Gdk.Key.F26:
            return FunctionKey.F26;
        case Gdk.Key.F27:
            return FunctionKey.F27;
        case Gdk.Key.F28:
            return FunctionKey.F28;
        case Gdk.Key.F29:
            return FunctionKey.F29;
        case Gdk.Key.F30:
            return FunctionKey.F30;
        case Gdk.Key.F31:
            return FunctionKey.F31;
        case Gdk.Key.F32:
            return FunctionKey.F32;
        case Gdk.Key.F33:
            return FunctionKey.F33;
        case Gdk.Key.F34:
            return FunctionKey.F34;
        case Gdk.Key.F35:
            return FunctionKey.F35;
        case Gdk.Key.KP_Insert:
        case Gdk.Key.Insert:
            return FunctionKey.Insert;
        case Gdk.Key.KP_Home:
        case Gdk.Key.Home:
            return FunctionKey.Home;
        case Gdk.Key.Begin:
            return FunctionKey.Begin;
        case Gdk.Key.KP_End:
        case Gdk.Key.End:
            return FunctionKey.End;
        case Gdk.Key.KP_Page_Up:
        case Gdk.Key.Page_Up:
            return FunctionKey.PageUp;
        case Gdk.Key.KP_Page_Down:
        case Gdk.Key.Page_Down:
            return FunctionKey.PageDown;
        case Gdk.Key.Key_3270_PrintScreen:
            return FunctionKey.PrintScreen;
        case Gdk.Key.Scroll_Lock:
            return FunctionKey.ScrollLock;
        case Gdk.Key.Pause:
            return FunctionKey.Pause;
        case Gdk.Key.Sys_Req:
            return FunctionKey.SysReq;
        case Gdk.Key.Break:
            return FunctionKey.Break;
        case Gdk.Key.Key_3270_Reset:
            return FunctionKey.Reset;
        case Gdk.Key.Menu:
            return FunctionKey.Menu;
        case Gdk.Key.Print:
            return FunctionKey.Print;
        case Gdk.Key.Help:
            return FunctionKey.Help;
        case Gdk.Key.Find:
            return FunctionKey.Find;
        case Gdk.Key.Undo:
            return FunctionKey.Undo;
        case Gdk.Key.Redo:
            return FunctionKey.Redo;
        case Gdk.Key.Execute:
            return FunctionKey.Execute;
        /*
        return FunctionKey.Stop;
        return FunctionKey.User;
        return FunctionKey.System;
        return FunctionKey.ClearLine;
        return FunctionKey.ClearDisplay;
        return FunctionKey.InsertLine;
        return FunctionKey.DeleteLine;
        return FunctionKey.InsertChar;
        return FunctionKey.DeleteChar;
        return FunctionKey.Next;
        return FunctionKey.Prev;
        return FunctionKey.Select;
        return FunctionKey.ModeSwitch;
        */
    }

    return 0;
}

// "Function-Key Unicodes" from NSEvent reference
enum FunctionKey : ushort
{
    UpArrow = 0xF700,
    DownArrow = 0xF701,
    LeftArrow = 0xF702,
    RightArrow = 0xF703,
    F1 = 0xF704,
    F2 = 0xF705,
    F3 = 0xF706,
    F4 = 0xF707,
    F5 = 0xF708,
    F6 = 0xF709,
    F7 = 0xF70A,
    F8 = 0xF70B,
    F9 = 0xF70C,
    F10 = 0xF70D,
    F11 = 0xF70E,
    F12 = 0xF70F,
    F13 = 0xF710,
    F14 = 0xF711,
    F15 = 0xF712,
    F16 = 0xF713,
    F17 = 0xF714,
    F18 = 0xF715,
    F19 = 0xF716,
    F20 = 0xF717,
    F21 = 0xF718,
    F22 = 0xF719,
    F23 = 0xF71A,
    F24 = 0xF71B,
    F25 = 0xF71C,
    F26 = 0xF71D,
    F27 = 0xF71E,
    F28 = 0xF71F,
    F29 = 0xF720,
    F30 = 0xF721,
    F31 = 0xF722,
    F32 = 0xF723,
    F33 = 0xF724,
    F34 = 0xF725,
    F35 = 0xF726,
    Insert = 0xF727,
    Delete = 0xF728,
    Home = 0xF729,
    Begin = 0xF72A,
    End = 0xF72B,
    PageUp = 0xF72C,
    PageDown = 0xF72D,
    PrintScreen = 0xF72E,
    ScrollLock = 0xF72F,
    Pause = 0xF730,
    SysReq = 0xF731,
    Break = 0xF732,
    Reset = 0xF733,
    Stop = 0xF734,
    Menu = 0xF735,
    User = 0xF736,
    System = 0xF737,
    Print = 0xF738,
    ClearLine = 0xF739,
    ClearDisplay = 0xF73A,
    InsertLine = 0xF73B,
    DeleteLine = 0xF73C,
    InsertChar = 0xF73D,
    DeleteChar = 0xF73E,
    Prev = 0xF73F,
    Next = 0xF740,
    Select = 0xF741,
    Execute = 0xF742,
    Undo = 0xF743,
    Redo = 0xF744,
    Find = 0xF745,
    Help = 0xF746,
    ModeSwitch = 0xF747
}