Mac-specific: Implement scanning in Safari (issue #129)

This commit is contained in:
Abs62 2013-04-11 17:35:59 +04:00
parent 4199ea20a8
commit dd0a4fc896

View file

@ -130,6 +130,7 @@ void MacMouseOver::handlePosition()
QString strToTranslate; QString strToTranslate;
CGPoint pt = carbonScreenPointFromCocoaScreenPoint( [NSEvent mouseLocation] ); CGPoint pt = carbonScreenPointFromCocoaScreenPoint( [NSEvent mouseLocation] );
CFArrayRef names = 0;
AXUIElementRef elem = 0; AXUIElementRef elem = 0;
AXError err = AXUIElementCopyElementAtPosition( elementSystemWide, pt.x, pt.y, &elem ); AXError err = AXUIElementCopyElementAtPosition( elementSystemWide, pt.x, pt.y, &elem );
@ -141,63 +142,100 @@ void MacMouseOver::handlePosition()
{ {
CFTypeRef parameter = AXValueCreate( kAXValueCGPointType, &pt ); CFTypeRef parameter = AXValueCreate( kAXValueCGPointType, &pt );
CFTypeRef rangeValue; CFTypeRef rangeValue;
err = AXUIElementCopyParameterizedAttributeValue( elem, kAXRangeForPositionParameterizedAttribute, err = AXUIElementCopyParameterizedAttributeNames( elem, &names );
parameter, &rangeValue );
CFRelease( parameter );
if( err != kAXErrorSuccess ) if( err != kAXErrorSuccess )
break; break;
CFStringRef stringValue; int numOfAttributes = CFArrayGetCount( names );
if( CFArrayContainsValue( names, CFRangeMake( 0, numOfAttributes ), CFSTR( "AXRangeForPosition" ) ) )
CFRange decodedRange = CFRangeMake( 0, 0 );
bool b = AXValueGetValue( (AXValueRef)rangeValue, kAXValueCFRangeType, &decodedRange );
CFRelease( rangeValue );
if( b )
{ {
int fromPos = decodedRange.location - 127; // Standard interface
if( fromPos < 0 ) err = AXUIElementCopyParameterizedAttributeValue( elem, kAXRangeForPositionParameterizedAttribute,
fromPos = 0; parameter, ( CFTypeRef * )&rangeValue );
int wordPos = decodedRange.location - fromPos; // Cursor position in result string
CFRange range = CFRangeMake( fromPos, wordPos + 1 );
parameter = AXValueCreate( kAXValueCFRangeType, &range );
err = AXUIElementCopyParameterizedAttributeValue( elem, kAXStringForRangeParameterizedAttribute,
parameter, (CFTypeRef *)&stringValue );
CFRelease( parameter ); CFRelease( parameter );
if( err != kAXErrorSuccess ) if( err != kAXErrorSuccess )
break; break;
strToTranslate = CFStringRefToQString( stringValue ); CFStringRef stringValue;
CFRelease( stringValue );
// Read string further CFRange decodedRange = CFRangeMake( 0, 0 );
for( int i = 1; i < 128; i++ ) bool b = AXValueGetValue( (AXValueRef)rangeValue, kAXValueCFRangeType, &decodedRange );
CFRelease( rangeValue );
if( b )
{ {
range = CFRangeMake( decodedRange.location + i, 1 ); int fromPos = decodedRange.location - 127;
if( fromPos < 0 )
fromPos = 0;
int wordPos = decodedRange.location - fromPos; // Cursor position in result string
CFRange range = CFRangeMake( fromPos, wordPos + 1 );
parameter = AXValueCreate( kAXValueCFRangeType, &range ); parameter = AXValueCreate( kAXValueCFRangeType, &range );
err = AXUIElementCopyParameterizedAttributeValue( elem, kAXStringForRangeParameterizedAttribute, err = AXUIElementCopyParameterizedAttributeValue( elem, kAXStringForRangeParameterizedAttribute,
parameter, (CFTypeRef *)&stringValue ); parameter, (CFTypeRef *)&stringValue );
CFRelease( parameter ); CFRelease( parameter );
if( err != kAXErrorSuccess ) if( err != kAXErrorSuccess )
break; break;
QString s = CFStringRefToQString( stringValue ); strToTranslate = CFStringRefToQString( stringValue );
CFRelease( stringValue ); CFRelease( stringValue );
if( s[ 0 ].isLetterOrNumber() || s[ 0 ] == '-' ) // Read string further
strToTranslate += s; for( int i = 1; i < 128; i++ )
else {
break; range = CFRangeMake( decodedRange.location + i, 1 );
parameter = AXValueCreate( kAXValueCFRangeType, &range );
err = AXUIElementCopyParameterizedAttributeValue( elem, kAXStringForRangeParameterizedAttribute,
parameter, (CFTypeRef *)&stringValue );
CFRelease( parameter );
if( err != kAXErrorSuccess )
break;
QString s = CFStringRefToQString( stringValue );
CFRelease( stringValue );
if( s[ 0 ].isLetterOrNumber() || s[ 0 ] == '-' )
strToTranslate += s;
else
break;
}
handleRetrievedString( strToTranslate, wordPos );
} }
handleRetrievedString( strToTranslate, wordPos );
} }
else if( CFArrayContainsValue( names, CFRangeMake( 0, numOfAttributes ), CFSTR( "AXTextMarkerForPosition" ) ) )
{
// Safari interface
CFTypeRef marker, range;
CFStringRef str;
err = AXUIElementCopyParameterizedAttributeValue( elem, CFSTR( "AXTextMarkerForPosition" ),
parameter, ( CFTypeRef * )&marker );
CFRelease( parameter );
if( err != kAXErrorSuccess )
break;
err = AXUIElementCopyParameterizedAttributeValue( elem, CFSTR( "AXLeftWordTextMarkerRangeForTextMarker" ),
marker, ( CFTypeRef * )&range );
CFRelease( marker );
if( err != kAXErrorSuccess )
break;
err = AXUIElementCopyParameterizedAttributeValue( elem, CFSTR( "AXStringForTextMarkerRange" ),
range, ( CFTypeRef * )&str );
CFRelease( range );
if( err == kAXErrorSuccess )
{
strToTranslate = CFStringRefToQString( str );
CFRelease( str );
handleRetrievedString( strToTranslate, 0 );
}
}
break; break;
} }
if( elem ) if( elem )
CFRelease( elem ); CFRelease( elem );
if( names )
CFRelease( names );
} }
void MacMouseOver::handleRetrievedString( QString & wordSeq, int wordSeqPos ) void MacMouseOver::handleRetrievedString( QString & wordSeq, int wordSeqPos )