FB II Compiler

PG PRO

Debugging

Memory

System

Mathematics

Resources

Disk I/O

Windows

Controls

Menus

Mouse

Keyboard

Text

Fonts

Drawing

Sound

Clipboard

Printing

Communication

ASM

Made with FB

SYSTEM

Better comprehend Apple Events


I'm trying to get my application to respond to Apple Events other than the 4 required events and I'm sort of stuck.

I've implemented the 4 required events as has been described in the FB manuals and in the articles that appeared in Inside Basic and they seem to work ok as long as the events are sent by the Finder. Lately, I have been trying to use AppleScript to send events to my application and things don't seem to work the same way. If I "tell" my app to "run" from within a script it sits there in the background as an open process but it doesn't do anything until I switch to it (I have Program Switcher installed and it shows up in its list of processes so I can switch to it but it doesn't appear in the Finder menu of processes until I switch to it in this way). Once I switch to it everything goes as expected in that the program "starts" and processes the (apple) events I have sent it from the script.

In addition to the 4 required events I have installed an AppleScript specific event processor for the "activate" event (event class=_"misc", event=_"actv"). I have included the appropriate signature in the _"size" resource and have an _"AETE" resource that defines the 4 required events as well as the "activate" event. In fact, the "activate" event gets to my app and I process it but only after switching to the active but not running app using Program Switcher.

What am I not doing properly?

Charlie Dickman


Sounds like I'm always preaching for the proces manager recently :-) What you could do is check if your app is in the fore when it receives the 'run' command it can pull itself forward and then execute it. Look at the process manager examples with FB.

However, this seems strange, most apps should run in the background, unless their 'running' needs them to be the foremost. Are you by any chance blocking events when your backgrounding?

jonathan


Do you have "Can Background" checked in your resource file's Size resource? If not, you'd get what you're seeing...

Bill


Thanks Bill. This got me "over the hump" but I still can't seem to figure out when to drop my splash screen and dive into the program. Immediately after putting up the splash screen I go into a modal HANDLEEVENTS loop waiting for a mouse click, a RETURN or 3 seconds. Time seems to be suspended when you're in the background.

Jonathan suggested that I invoke the process manager to bring my app to the foreground so I may give this a try. Also, I may forego the splash screen if my app isn't the front one.

Charlie Dickman


<< Immediately after putting up the splash screen I go into a modal HANDLEEVENTS loop waiting for a mouse click, a RETURN or 3 seconds. >>

This is almost certainly the problem. If you are running in a HANDLEEVENTS loop looking only for certain kinds of events, what happens to the other events - such as the incoming AEs? Unless you've executed some rather clever coding, they end up in the bit bucket.

I'd do one of two things with this:

1) Don't use HandleEvents. Use CALL GETKEYS and FN BUTTON to determine whether the mouse or return key is down, and FN TICKCOUNT to see if the time is up. Don't do any event loading until the splash screen has been dismissed. This way your app will launch, the splash screen will display, and THEN it will receive the AEs.

2) Make your splash screen asynchronous. Instead of using a special HANDLEEVENTS loop before the program starts, then falling into your main loop - go directly to your main loop. Whenever you receive a mouse click or return key event, check to see if the topmost window is your splash window. If so, dismiss the window; otherwise, handle the event as normal.

This way your AEs will come in "behind" the splash screen, instead of being eaten.

Mars


Following observations:

1. The aete resource should be lowercase. Try using Script Editor Open Dictionary command and select your application file from the dialog box. If it recognises your application and the aete dictionary then the aete resource is not necessarily incorrectly defined.

2. Is your SIZE resource flags set to Allow High Level events?

3. Are you sure your application is accepting the High Level event? In your ON EVENT part of the event handler, are you able to tell if the Apple Event was received and recognised?

4. Is the custom event set up correctly using the LINE command and AEINSTALLHANDLER (etc) shown in the example for the other four?

5. Note that the activate Apple Event is a finder event and not one you need to handle. Your application handles it by moving to the front from the background and receives it as a multifinder event in the DIALOG statement anyway. Maybe there is a clash?

Deep


Time is not suspended while you are in the background. You should receive events just as you would in the foreground. Post the code and maybe someone can show you what you are doing wrong.

You might want to try doing something like this instead to avoid the extra event loop:

'open dialog

numSecs = 5
start& = FN TICKCOUNT
paused = _zTrue
WHILE paused
  paused = FN TICKCOUNT - start& < (numSecs*60)
  IF paused THEN paused = (FN BUTTON = 0)
'IF paused THEN (do GetKeys here)
WEND

'close dialog

Mars Saxman wrote:

<< This is almost certainly the problem. If you are running in a HANDLEEVENTS loop looking only for certain kinds of events, what happens to the other events - such as the incoming AEs? Unless you've executed some rather clever coding, they end up in the bit bucket. >>

Oops.

I see Mars beat me to it. ;-)

David Blache


I hate to disagree with someone who I consider much more knowledgable about these things but I've been studying Apple Events for months now and I think the following is true...

While it's true that the activate event is not a required event it is not in the Finder suite but is peculiar to AppleScript (according to Danny Goodman's "AppleScript Handbook" and should not be confused with the MultiFinder event that occurs and is processed via DIALOG when your app is brought to the front by the user or some other mechanism. This MultiFinder event predates AppleEvents by many years and OS versions and is quite distinct from the activate event send by AppleScript. So the bottom line is that I don't think there is a conflict between the two. By the way, the reason I am handling the activate event is because I'm practicing to make my app scriptable and this is the first example in "The TAO of AppleScript" by Derrick Schneider. The concensus seems to be that in response to the activate I should bring my app to the front using the Process Manager (thanks Jonathan) so I think I'll give it a try.

Both Mars and David B. indicated some concerns about the way I'm handling events relative to timing my splash screen and processing Apple Events. Let me try to explain why I don't think this is the problem.

I execute ON EVENT FN DoEvent and ON DIALOG FN DoDialog, in that order, before ever entering _any_ HANDLEEVENT loop. In the DoEvent function I have code to process AppleEvents...

theEvent = {EVENT}
LONG IF theEvent = _khighlevelevent
  theError = FN AEPROCESSAPPLEEVENT(EVENT)
.
.
.
END IF

After having established these event processors, and doing some other initialization, I invoke my SplashScreen function which has at the end of it, after bringing up the splash, ...

FLUSHEVENTS
tic& = FN TICKCOUNT
DO
  HANDLEEVENTS
  toc& = FN TICKCOUNT
UNTIL gKey = _CR OR gKey = _EOT OR ((toc& - tic&) > _SplashTicToc)
FN BashSplash

_SplashTicToc ::= 180 and gKey is a global which is set in DoDialog when an _evKey event occurs.

Now, with the placement of CALL DEBUGSTR("<event>;g") where <event> is one of "run", "activate", "splashing" or "done splashing" at the appropriate places I can see that the order in which things occur is...

"splashing" followed by "run" followed by "activate" and then nothing until something causes an app switch. This can be bringing my app to the front via a click in the splash window (long after 3 seconds have elapsed), quitting the Script Editor or using Program Switcher to change apps to _anything else_, eg., the Finder, and then I see "done splashing" but it _never_ occurs spontaneously.

I understand the concern about swallowing the Apple Events but they just don't get eaten... the clear evidence is that they are processed but I can't detect the passage of time. I'm a big fan of relativity and understand that time dilates to infinity at the event horizon of a black hole but I didn't think that being in the background was anything like being in a black hole ;-)

Jonathan and Deep have suggested that I bring my app to the front when I receive the activate event and, in fact, this is what the Scriptable Text Editor does. I can bypass my splash screen when I'm not the frontmost app. and do this - it sounds good to me but I don't understand why my splash screen won't time out using the code above.

Charlie Dickman


Ahhh. Your splash screen is probably a modal window. The Event and Layer managers do funny things when an app's frontmost window is modal. (You can switch in, but you can't switch out, for example.) It's entirely possible that the Event Manager simply stops sending you events while a modal window is up, until the user activates your app manually.

Just to see what happens, try making the splash window non-modal. My guess is that your app will magically begin handling events in the way it was "supposed" to.

Other ideas: If you poke a value at a certain offset from the EVENT function, you can convince HANDLEEVENTS to call WaitNextEvent instead of GetNextEvent. Have you done this? I have a hunch that using WNE instead of GNE might solve the problem.

Aside from that, all I can think of are 1) only open the splash screen if your app is in the foreground or 2) install a Time Manager task which goes off after three seconds and brings your app to the foreground, thus allowing events to continue processing.

Mars