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