• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: AppleScriptObjC oddity
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: AppleScriptObjC oddity


  • Subject: Re: AppleScriptObjC oddity
  • From: Chris Page <email@hidden>
  • Date: Sun, 12 Jul 2015 19:48:26 -0700


On Jun 23, 2015, at 2:40 PM, Steve Mills <email@hidden> wrote:

If I run the script from ScriptDebugger, from the system script menu, or from LaunchBar, it works as expected. But if I run it via a global key equiv I've set on a DragThing item, it works wrong. It appears that different apps are returning different values for NSScreen's frame. Could this be because DragThing still appears to be a Carbon app?

use scripting additions
use framework "AppKit" -- for NSScreen

set ss to current application's NSScreen's screens()
set leftScreenBox to (ss's objectAtIndex:1)'s frame()

Do you have more than one display? AppleScript indexes are one-based, but Objective-C's are zero-based. So, "objectAtIndex:1" is asking for the second screen, not the first one. There are two potential problems:

1. If you only have one display, "objectAtIndex:1" will return an error and your script will stop executing.

2. As far as I am aware, except for the first screen (index zero, which always refers to the "default" screen) the screens aren't in any particular order in the array; therefore, even if it succeeds, the exact screen selected with index one may vary from process to process.

If you want the first screen, you can use Objective-C's "indexAtObject:0" or "firstObject". AppleScript's "item 1" or "first item" will also work with NSArrays.

While I'm at it, I'd like to make some other comments about the code:

1. Since the script doesn't use scripting additions, there's no reason to 'use scripting additions'. One of the goals of "use" is to add more structure and explicitness to the otherwise very dynamic AppleScript language, and part of this is being concise and not "use"ing things unless you actually need them. (I understand if this is an excerpt from a larger script that does use additions, but I thought this was a good opportunity to mention this.)

2. "screens" and "frame" are properties, not functions, so you shouldn't use "()" with them. Although it may currently work, it is superfluous and the exact meaning of using parenthesis after a property name may change in the future. (e.g., it should probably mean instead "get the property, whose value is a function, then call that function", just as it does when sending the message to an AppleScript object that has a property whose value is a handler.)

Since I'm new to AppleScriptObjC, is there some way to have "current application" be the app that is being targeted by the script, so I can ensure it's working with a Cocoa app that will return the correct values? Like:

tell app "Safari"
    set ss to current application's NSScreen's screens()
end tell

From my tests, "current application" always seems to be the app that executed the script.

No, you cannot send Objective-C messages to another process, in AppleScript or Objective-C†. That's the reason why looking up Objective-C identifiers in AppleScript requires the "current application" prefix, to ensure you're trying to interact with the Objective-C runtime (in the current process) and not sending a message to some other application process.

Hypothetically, there could be a scriptable application that explicitly supports getting the screen layout, but I don't know of one offhand, and you can't send arbitrary events (either Objective-C messages or AppleScript events) to arbitrary programs.

I'd like to stress that "current application" always means the current application. Its primary purpose is to allow you to target the current application when inside a "tell" block, by ignoring the current target ("it"). If you want to send a message to the current target explicitly, use "it" instead:

tell application "Safari"
name -- implicitly sent to "it", which means it is sent to Safari
its name -- explicitly sent to "it", which means it is sent to Safari
current application's name -- explicitly sent to the current application instead of "it"
my name -- explicitly sent to "me", the current script, instead of "it"
end tell

In Script Editor, the following equivalent script

tell application "Safari" to {name, its name, current application's name, my name}

returns

{"Safari", "Safari", "Script Editor", "Untitled 3"}

† For the pedantic, Objective-C has a feature called Distributed Objects that allows sending messages to objects in another process, but it's something that an application has to support, and it doesn't give you the ability to send arbitrary messages to arbitrary objects.

-- 
Chris Page
The other, other AppleScript Chris

 _______________________________________________
Do not post admin requests to the list. They will be ignored.
AppleScript-Users mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
Archives: http://lists.apple.com/archives/applescript-users

This email sent to email@hidden

  • Follow-Ups:
    • Re: AppleScriptObjC oddity
      • From: Shane Stanley <email@hidden>
    • Re: AppleScriptObjC oddity
      • From: Steve Mills <email@hidden>
    • Re: AppleScriptObjC oddity
      • From: Shane Stanley <email@hidden>
  • Prev by Date: Using frameworks explicitly (was Re: AppleScriptObjC oddity solved - kinda)
  • Next by Date: Re: AppleScriptObjC oddity
  • Previous by thread: Using frameworks explicitly (was Re: AppleScriptObjC oddity solved - kinda)
  • Next by thread: Re: AppleScriptObjC oddity
  • Index(es):
    • Date
    • Thread