return ms;
}
+// TODO : once the new key/char handling is tested, move all the code to wxWindow
bool wxApp::MacSendKeyDownEvent( wxWindow* focus , long keymessage , long modifiers , long when , short wherex , short wherey , wxChar uniChar )
{
if ( !focus )
return false ;
- short keycode ;
- short keychar ;
- keychar = short(keymessage & charCodeMask);
- keycode = short(keymessage & keyCodeMask) >> 8 ;
-
- if ( modifiers & ( controlKey|shiftKey|optionKey ) )
- {
- // control interferes with some built-in keys like pgdown, return etc. therefore we remove the controlKey modifier
- // and look at the character after
- UInt32 state = 0;
- UInt32 keyInfo = KeyTranslate((Ptr)GetScriptManagerVariable(smKCHRCache), ( modifiers & (~(controlKey|shiftKey|optionKey))) | keycode, &state);
- keychar = short(keyInfo & charCodeMask);
- }
-
- long keyval = wxMacTranslateKey(keychar, keycode) ;
- long realkeyval = keyval ;
- if ( keyval == keychar )
- {
- // we are not on a special character combo -> pass the real os event-value to EVT_CHAR, but not to EVT_KEY (make upper first)
- realkeyval = short(keymessage & charCodeMask) ;
- keyval = wxToupper( keyval ) ;
- }
-
- // Check for NUMPAD keys
- if (keyval >= '0' && keyval <= '9' && keycode >= 82 && keycode <= 92)
- {
- keyval = keyval - '0' + WXK_NUMPAD0;
- }
- else if (keycode >= 67 && keycode <= 81)
- {
- switch (keycode)
- {
- case 76 :
- keyval = WXK_NUMPAD_ENTER;
- break;
-
- case 81:
- keyval = WXK_NUMPAD_EQUAL;
- break;
-
- case 67:
- keyval = WXK_NUMPAD_MULTIPLY;
- break;
-
- case 75:
- keyval = WXK_NUMPAD_DIVIDE;
- break;
-
- case 78:
- keyval = WXK_NUMPAD_SUBTRACT;
- break;
-
- case 69:
- keyval = WXK_NUMPAD_ADD;
- break;
-
- case 65:
- keyval = WXK_NUMPAD_DECIMAL;
- break;
-
- default:
- break;
- } // end switch
- }
-
- wxKeyEvent event(wxEVT_KEY_DOWN);
- bool handled = false ;
- event.m_shiftDown = modifiers & shiftKey;
- event.m_controlDown = modifiers & controlKey;
- event.m_altDown = modifiers & optionKey;
- event.m_metaDown = modifiers & cmdKey;
- event.m_keyCode = keyval ;
-
-#if wxUSE_UNICODE
- event.m_uniChar = uniChar ;
-#endif
-
- event.m_rawCode = keymessage;
- event.m_rawFlags = modifiers;
- event.m_x = wherex;
- event.m_y = wherey;
- event.SetTimestamp(when);
- event.SetEventObject(focus);
+ bool handled;
+ wxKeyEvent event(wxEVT_KEY_DOWN) ;
+ MacCreateKeyEvent( event, focus , keymessage , modifiers , when , wherex , wherey , uniChar ) ;
+
handled = focus->GetEventHandler()->ProcessEvent( event ) ;
if ( handled && event.GetSkipped() )
handled = false ;
}
#endif // wxUSE_ACCEL
- if (!handled)
- {
- wxTopLevelWindowMac *tlw = focus->MacGetTopLevelWindow() ;
+ return handled ;
+}
- if (tlw)
- {
- event.Skip( false ) ;
- event.SetEventType( wxEVT_CHAR_HOOK );
- // raw value again
- event.m_keyCode = realkeyval ;
-
- handled = tlw->GetEventHandler()->ProcessEvent( event );
- if ( handled && event.GetSkipped() )
- handled = false ;
- }
- }
+bool wxApp::MacSendKeyUpEvent( wxWindow* focus , long keymessage , long modifiers , long when , short wherex , short wherey , wxChar uniChar )
+{
+ if ( !focus )
+ return false ;
- if ( !handled )
- {
- event.Skip( false ) ;
- event.SetEventType( wxEVT_CHAR ) ;
+ bool handled;
+ wxKeyEvent event( wxEVT_KEY_UP ) ;
+ MacCreateKeyEvent( event, focus , keymessage , modifiers , when , wherex , wherey , uniChar ) ;
+ handled = focus->GetEventHandler()->ProcessEvent( event ) ;
+
+ return handled ;
+}
- // raw value again
- event.m_keyCode = realkeyval ;
+bool wxApp::MacSendCharEvent( wxWindow* focus , long keymessage , long modifiers , long when , short wherex , short wherey , wxChar uniChar )
+{
+ if ( !focus )
+ return false ;
+
+ wxKeyEvent event(wxEVT_CHAR) ;
+ MacCreateKeyEvent( event, focus , keymessage , modifiers , when , wherex , wherey , uniChar ) ;
+ long keyval = event.m_keyCode ;
+ short realkeyval = short(keymessage & charCodeMask) ;
- handled = focus->GetEventHandler()->ProcessEvent( event ) ;
+ bool handled = false ;
+
+ wxTopLevelWindowMac *tlw = focus->MacGetTopLevelWindow() ;
+
+ if (tlw)
+ {
+ event.SetEventType( wxEVT_CHAR_HOOK );
+ // send original character, not the uppercase version
+ event.m_keyCode = realkeyval ;
+
+ handled = tlw->GetEventHandler()->ProcessEvent( event );
if ( handled && event.GetSkipped() )
handled = false ;
}
+ if ( !handled )
+ {
+ event.SetEventType( wxEVT_CHAR );
+ event.Skip( false ) ;
+ handled = focus->GetEventHandler()->ProcessEvent( event ) ;
+ }
+
if ( !handled && (keyval == WXK_TAB) )
{
wxWindow* iter = focus->GetParent() ;
}
}
}
-
return handled ;
}
-bool wxApp::MacSendKeyUpEvent( wxWindow* focus , long keymessage , long modifiers , long when , short wherex , short wherey , wxChar uniChar )
+// This method handles common code for SendKeyDown, SendKeyUp, and SendChar events.
+void wxApp::MacCreateKeyEvent( wxKeyEvent& event, wxWindow* focus , long keymessage , long modifiers , long when , short wherex , short wherey , wxChar uniChar )
{
- if ( !focus )
- return false ;
-
short keycode, keychar ;
keychar = short(keymessage & charCodeMask);
keycode = short(keymessage & keyCodeMask) >> 8 ;
- if ( modifiers & (controlKey | shiftKey | optionKey) )
+ if ( !(event.GetEventType() == wxEVT_CHAR) && (modifiers & (controlKey | shiftKey | optionKey) ) )
{
// control interferes with some built-in keys like pgdown, return etc. therefore we remove the controlKey modifier
// and look at the character after
}
long keyval = wxMacTranslateKey(keychar, keycode) ;
- if ( keyval == keychar )
+ if ( keyval == keychar && ( event.GetEventType() == wxEVT_KEY_UP || event.GetEventType() == wxEVT_KEY_DOWN ) )
keyval = wxToupper( keyval ) ;
// Check for NUMPAD keys
} // end switch
}
- bool handled = false ;
-
- wxKeyEvent event(wxEVT_KEY_UP);
event.m_shiftDown = modifiers & shiftKey;
event.m_controlDown = modifiers & controlKey;
event.m_altDown = modifiers & optionKey;
event.m_y = wherey;
event.SetTimestamp(when);
event.SetEventObject(focus);
- handled = focus->GetEventHandler()->ProcessEvent( event ) ;
-
- return handled ;
}
{
// TODO: remove control related event like key and mouse (except for WindowLeave events)
#if 1
- { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent } ,
-
{ kEventClassKeyboard, kEventRawKeyDown } ,
{ kEventClassKeyboard, kEventRawKeyRepeat } ,
{ kEventClassKeyboard, kEventRawKeyUp } ,
{ kEventClassMouse , kEventMouseDragged } ,
} ;
-static pascal OSStatus TextInputEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
-{
- OSStatus result = eventNotHandledErr ;
- wxWindow* focus ;
- UInt32 keyCode, modifiers ;
- Point point ;
- EventRef rawEvent ;
- unsigned char charCode ;
-
- GetEventParameter( event, kEventParamTextInputSendKeyboardEvent, typeEventRef, NULL, sizeof(rawEvent), NULL, &rawEvent ) ;
-
- GetEventParameter( rawEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &charCode );
- GetEventParameter( rawEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode );
- GetEventParameter( rawEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers );
- GetEventParameter( rawEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &point );
-
- focus = wxWindow::FindFocus() ;
-
- switch ( GetEventKind( event ) )
- {
- case kEventTextInputUnicodeForKeyEvent :
- {
- // this is only called when no default handler has jumped in, e.g. a wxControl on a floater window does not
- // get its own kEventTextInputUnicodeForKeyEvent, so we reroute the event back to the control
- wxControl* control = wxDynamicCast( focus , wxControl ) ;
- if ( control )
- {
- ControlRef macControl = (ControlRef) control->GetHandle() ;
- if ( macControl )
- {
- ::HandleControlKey( macControl , keyCode , charCode , modifiers ) ;
- result = noErr ;
- }
- }
-
-#if 0
- // this may lead to double events sent to a window in case all handlers have skipped the key down event
- UInt32 when = EventTimeToTicks( GetEventTime( event ) ) ;
- UInt32 message = (keyCode << 8) + charCode;
-
- if ( (focus != NULL) &&
- wxTheApp->MacSendKeyDownEvent( focus , message , modifiers , when , point.h , point.v ) )
- {
- result = noErr ;
- }
-#endif
- }
- break ;
-
- default:
- break ;
- }
-
- return result ;
-}
-
static pascal OSStatus KeyboardEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
{
OSStatus result = eventNotHandledErr ;
result = KeyboardEventHandler( handler, event , data ) ;
break ;
- case kEventClassTextInput :
- result = TextInputEventHandler( handler, event , data ) ;
- break ;
-
case kEventClassWindow :
result = wxMacTopLevelWindowEventHandler( handler, event , data ) ;
break ;
{ kEventClassControl , kEventControlHit } ,
#if TARGET_API_MAC_OSX
+ { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent } ,
+ { kEventClassTextInput, kEventTextInputUpdateActiveInputArea } ,
+
{ kEventClassControl , kEventControlDraw } ,
{ kEventClassControl , kEventControlVisibilityChanged } ,
{ kEventClassControl , kEventControlEnabledStateChanged } ,
return result ;
}
+pascal OSStatus wxMacUnicodeTextEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
+{
+ OSStatus result = eventNotHandledErr ;
+ wxWindowMac* focus = (wxWindowMac*) data ;
+
+ wchar_t* uniChars = NULL ;
+ UInt32 when = EventTimeToTicks( GetEventTime( event ) ) ;
+
+ UniChar* charBuf;
+ UInt32 dataSize = 0 ;
+ int numChars = 0 ;
+ UniChar buf[2] ;
+ if ( GetEventParameter( event, kEventParamTextInputSendText, typeUnicodeText, NULL, 0 , &dataSize, NULL ) == noErr )
+ {
+ numChars = dataSize / sizeof( UniChar) ;
+ charBuf = buf ;
+
+ if ( dataSize > sizeof(buf) )
+ charBuf = new UniChar[ numChars ] ;
+ else
+ charBuf = buf ;
+
+ uniChars = new wchar_t[ numChars ] ;
+ GetEventParameter( event, kEventParamTextInputSendText, typeUnicodeText, NULL, dataSize , NULL , charBuf ) ;
+#if SIZEOF_WCHAR_T == 2
+ uniChars = charBuf ;
+ memcpy( uniChars , charBuf , dataSize ) ;
+#else
+ // the resulting string will never have more chars than the utf16 version, so this is safe
+ wxMBConvUTF16 converter ;
+ numChars = converter.MB2WC( uniChars , (const char*)charBuf , numChars ) ;
+#endif
+ }
+
+ switch ( GetEventKind( event ) )
+ {
+ case kEventTextInputUpdateActiveInputArea :
+ {
+ // An IME input event may return several characters, but we need to send one char at a time to
+ // EVT_CHAR
+ for (int pos=0 ; pos < numChars ; pos++)
+ {
+
+ WXEVENTREF formerEvent = wxTheApp->MacGetCurrentEvent() ;
+ WXEVENTHANDLERCALLREF formerHandler = wxTheApp->MacGetCurrentEventHandlerCallRef() ;
+ wxTheApp->MacSetCurrentEvent( event , handler ) ;
+
+ UInt32 message = (0 << 8) + ((char)uniChars[pos] );
+ if ( wxTheApp->MacSendCharEvent(
+ focus , message , 0 , when , 0 , 0 , uniChars[pos] ) )
+ {
+ result = noErr ;
+ }
+
+ wxTheApp->MacSetCurrentEvent( formerEvent , formerHandler ) ;
+ }
+ }
+ break ;
+ case kEventTextInputUnicodeForKeyEvent :
+ {
+ UInt32 keyCode, modifiers ;
+ Point point ;
+ EventRef rawEvent ;
+ unsigned char charCode ;
+
+ GetEventParameter( event, kEventParamTextInputSendKeyboardEvent, typeEventRef, NULL, sizeof(rawEvent), NULL, &rawEvent ) ;
+ GetEventParameter( rawEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &charCode );
+ GetEventParameter( rawEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode );
+ GetEventParameter( rawEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers );
+ GetEventParameter( rawEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &point );
+
+ UInt32 message = (keyCode << 8) + charCode;
+ // this is only called when no default handler has jumped in, e.g. a wxControl on a floater window does not
+ // get its own kEventTextInputUnicodeForKeyEvent, so we reroute the event back to the control
+
+ // NOTE to Stefan: Is this still needed? Shouldn't we be calling SendToEventTarget rather than
+ // HandleControlKey? (which, IIRC, is not Unicode friendly?) TODO :: MEMORY LEAK IN uniChar etc.
+ /*
+ wxControl* control = wxDynamicCast( focus , wxControl ) ;
+ if ( control )
+ {
+ ControlRef macControl = (ControlRef) control->GetHandle() ;
+ if ( macControl )
+ {
+ ::HandleControlKey( macControl , keyCode , charCode , modifiers ) ;
+ result = noErr ;
+ }
+ }
+ */
+
+ // An IME input event may return several characters, but we need to send one char at a time to
+ // EVT_CHAR
+ for (int pos=0 ; pos < numChars ; pos++)
+ {
+
+ WXEVENTREF formerEvent = wxTheApp->MacGetCurrentEvent() ;
+ WXEVENTHANDLERCALLREF formerHandler = wxTheApp->MacGetCurrentEventHandlerCallRef() ;
+ wxTheApp->MacSetCurrentEvent( event , handler ) ;
+
+ if ( wxTheApp->MacSendCharEvent(
+ focus , message , modifiers , when , point.h , point.v , uniChars[pos] ) )
+ {
+ result = noErr ;
+ }
+
+ wxTheApp->MacSetCurrentEvent( formerEvent , formerHandler ) ;
+ }
+ }
+ break;
+ default:
+ break ;
+ }
+
+ delete[] uniChars ;
+ if ( charBuf != buf )
+ delete[] charBuf ;
+
+ return result ;
+
+}
+
pascal OSStatus wxMacWindowEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
{
EventRef formerEvent = (EventRef) wxTheApp->MacGetCurrentEvent() ;
result = wxMacWindowServiceEventHandler( handler, event , data ) ;
break ;
+ case kEventClassTextInput :
+ result = wxMacUnicodeTextEventHandler( handler , event , data ) ;
+ break ;
default :
break ;
}