views:

275

answers:

1

I will soon be working on an application which needs to get the currently selected text in the frontmost application window, be it Safari, Pages, TextEdit, Word, etc., and do something with that text.

My goal is to find a solution that works with as much applications as possible. So far I thought about using AppleScript, but that would limit the amount of applications which could be used with my service. At least these common applications must be supported: Safari, Firefox (no AppleScript?), Word, Pages, Excel, TextEdit, ...

I also thought about keeping the clipboard's content in a temporary variable then simulating a text copy operation (Cmd-C), getting the text and then put the original content back in. This would probably highlight the Edit menu item when the copy operation is simulated and seems a bit hacky to me. IMO this solution doesn't seem good enough for a commercial product.

I am also looking to get more than the selection (i.e: the complete contents of the page in Safari or Word, etc.) to add some additional features in the future.

Any ideas/details on how to implement this behavior?

Thanks in advance for any hints!

N.B: I need to support at least 10.4 and up, but ideally older than 10.4 too.

UPDATE:

The solution I've opted for: Using the "Chain of Responsibility" design pattern (GOF) to combine 3 different input methods (Pasteboard, AppleScript and Accessibility), using the best available input source automatically.

Note that when using NSAppleScript's executeAndReturnError: method which returns an NSAppleEventDescriptor (let's say a "descriptor" instance), for the [descriptor stringValue] method to return something, in your AppleScript you must use "return someString" OUTSIDE of a "tell" block else nothing will be returned.

+1  A: 

Accessibility will work, but only if access for assistive devices is on.

You'll need to get the current application, then get its focused UI element, then get its selected text ranges and its value (whole text) and selected text ranges. You could just get its selected text, but that would either concatenate or ignore multiple selections.

Be prepared for any of those steps to fail: The app may not have any windows up, there may be no UI element with focus, the focused UI element may have no text, and the focused UI element may have only an empty selected text range.

Peter Hosey
The accessibility features seem interesting, but using Accessibility Inspector (from the Dev. Tools) in Firefox and Word yields no interesting values, although there are loads of information when using it in Safari. Does that mean Accessibility features could not be used at all in those applications, or is there still a "generic" way to get the selected text like you described? Do you have a code sample or a link to some examples?
Form
Accessibility works on any accessible application. Some applications aren't accessible. The worst examples, including those two, aren't likely to support any other generic way of inspecting their UIs, either—if you want to support them, you'll have to special-case them with AppleScript.
Peter Hosey
As for examples: No, there don't appear to be any anymore. That said, if you can understand and use a Core-Foundation-based API, you can figure out what you need to do from the function names in the Accessibility headers. (The framework you need, BTW, is ApplicationServices.)
Peter Hosey
Thanks, I'll be using your advice. Since there seems to be no perfect solution, what I'm going to do is create a few "input " classes for each input method (Pasteboard, AppleScript, Accessibility) and use another class for abstraction which will choose the best input method depending on the active application or input gathering results.
Form