wxOSX > Cocoaでのキーボード・テキスト入力のイベント処理の流れ

wxOSX/Cocoaでのキーボード・テキスト入力のイベント処理の流れ

src/osx/cocoa/window.mm:

void wxOSXCocoaClassAddWXMethods(Class c)
{
...
    wxOSX_CLASS_ADD_METHOD(c, @selector(keyDown:), (IMP) wxOSX_keyEvent, "v@:@" )
    wxOSX_CLASS_ADD_METHOD(c, @selector(keyUp:), (IMP) wxOSX_keyEvent, "v@:@" )
    wxOSX_CLASS_ADD_METHOD(c, @selector(flagsChanged:), (IMP) wxOSX_keyEvent, "v@:@" )
 
    wxOSX_CLASS_ADD_METHOD(c, @selector(insertText:), (IMP) wxOSX_insertText, "v@:@" )
...
}
 

void wxOSX_keyEvent(NSView* self, SEL _cmd, NSEvent *event)
{
    wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
    if (impl == NULL)
        return;
 
    impl->keyEvent(event, self, _cmd);
}
 

void wxOSX_insertText(NSView* self, SEL _cmd, NSString* text)
{
    wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
    if (impl == NULL)
        return;
 
    impl->insertText(text, self, _cmd);
}
 

void wxWidgetCocoaImpl::keyEvent(WX_NSEvent event, WXWidget slf, void *_cmd)
{
    if ( [event type] == NSKeyDown )
    {
        // there are key equivalents that are not command-combos and therefore not handled by cocoa automatically, 
        // therefore we call the menubar directly here, exit if the menu is handling the shortcut
        if ( [[[NSApplication sharedApplication] mainMenu] performKeyEquivalent:event] )
            return;
 
        m_lastKeyDownEvent = event;
    }
 
    if ( GetFocusedViewInWindow([slf window]) != slf || m_hasEditor || !DoHandleKeyEvent(event) )
    {
        wxOSX_EventHandlerPtr superimpl = (wxOSX_EventHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
        superimpl(slf, (SEL)_cmd, event);
    }
    m_lastKeyDownEvent = NULL;
}
 

void wxWidgetCocoaImpl::insertText(NSString* text, WXWidget slf, void *_cmd)
{
    if ( m_lastKeyDownEvent==NULL || m_hasEditor || !DoHandleCharEvent(m_lastKeyDownEvent, text) )
    {
        wxOSX_TextEventHandlerPtr superimpl = (wxOSX_TextEventHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
        superimpl(slf, (SEL)_cmd, text);
    }
}
 

bool wxWidgetCocoaImpl::DoHandleCharEvent(NSEvent *event, NSString *text)
{
    wxKeyEvent wxevent(wxEVT_CHAR);
    SetupKeyEvent( wxevent, event, text );
 
    return GetWXPeer()->OSXHandleKeyEvent(wxevent);
}
 

bool wxWidgetCocoaImpl::DoHandleKeyEvent(NSEvent *event)
{
    wxKeyEvent wxevent(wxEVT_KEY_DOWN);
    SetupKeyEvent( wxevent, event );
    bool result = GetWXPeer()->OSXHandleKeyEvent(wxevent);
 
    // this will fire higher level events, like insertText, to help
    // us handle EVT_CHAR, etc.
 
    if ( m_wxPeer->MacIsUserPane() && [event type] == NSKeyDown)
    {
        if ( !result )
        {
            if ( wxevent.GetKeyCode() < WXK_SPACE || wxevent.GetKeyCode() == WXK_DELETE || wxevent.GetKeyCode() >= WXK_START )
            {
                // eventually we could setup a doCommandBySelector catcher and retransform this into the wx key chars
                wxKeyEvent wxevent2(wxevent) ;
                wxevent2.SetEventType(wxEVT_CHAR);
                result = GetWXPeer()->OSXHandleKeyEvent(wxevent2);
            }
            else
            {
                if ( !wxevent.CmdDown() )
                {
                    if ( [m_osxView isKindOfClass:[NSScrollView class] ] )
                        [[(NSScrollView*)m_osxView documentView] interpretKeyEvents:[NSArray arrayWithObject:event]];
                    else
                        [m_osxView interpretKeyEvents:[NSArray arrayWithObject:event]];
                    result = true;
                }
            }
        }
    }
 
    return result;
}
 

src/osx/window_osx.cpp:

bool wxWindowMac::OSXHandleKeyEvent( wxKeyEvent& event )
{
    bool handled = false;
 
    // moved the ordinary key event sending AFTER the accel evaluation
 
#if wxUSE_ACCEL
    if ( !handled && event.GetEventType() == wxEVT_KEY_DOWN)
    {
        wxWindow *ancestor = this;
        while (ancestor)
        {
            int command = ancestor->GetAcceleratorTable()->GetCommand( event );
            if (command != -1)
            {
                wxEvtHandler * const handler = ancestor->GetEventHandler();
 
                wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command );
                handled = handler->ProcessEvent( command_event );
 
                if ( !handled )
                {
                    // accelerators can also be used with buttons, try them too
                    command_event.SetEventType(wxEVT_COMMAND_BUTTON_CLICKED);
                    handled = handler->ProcessEvent( command_event );
                }
 
                break;
            }
 
            if (ancestor->IsTopLevel())
                break;
 
            ancestor = ancestor->GetParent();
        }
    }
#endif // wxUSE_ACCEL
    
    if ( !handled )
    {
        handled = HandleWindowEvent( event ) ;
        if ( handled && event.GetSkipped() )
            handled = false ;
    }
 
    return handled ;
}
 

  • interpretKeyEvents:は呼ばれるみたい
    • ただし、EVT_KEY_DOWNが処理されなかった場合のみ
  • insertText:で複数文字が渡ってきた場合は最初の1文字しか処理されない?

タグ:

+ タグ編集
  • タグ:
最終更新:2011年03月18日 07:54