Window.FloaterProcess Fix for Mac OS X

February 1st, 2008 by Jonathan Johnson

Recently on the NUG, a question came up about making Window.FloaterProcess work correctly on Mac OS X. This property is designed to make it easy to have one of your global floating windows show up only “inside” of another application. After a lack of volunteers, I coded up a generic drop-in fix.

Module FloaterProcessFix
  Private Const kEventAppFrontSwitched = 7
  Private Const kEventClassApplication = 'appl'
 
  Protected Sub CheckOpenWindows()
    declare function GetFrontProcess lib "Carbon" (psn as Ptr) as Integer
    dim psn as new MemoryBlock(8)
    dim err as Integer = GetFrontProcess(psn)
    if err = 0 then
      declare function GetProcessInformation lib "Carbon" (psn as Ptr, _
        info as Ptr) as Integer
      dim info as new MemoryBlock(60)
      err = GetProcessInformation(psn, info)
      if err = 0 then
        dim p as Ptr = info
        dim type as String = p.OSType(20)
        HideShowFloaters(type)
      end if
    end if
  End Sub
 
  Protected Sub Install()
    declare function NewEventHandlerUPP lib "Carbon" (handler as Ptr) _
      as Integer
    declare function InstallEventHandler lib "Carbon" (target as Integer, _
      handler as Integer, itemCount as Integer, typeList as Ptr, _
      userData as Integer, outRef as Integer) as Integer
    declare function GetApplicationEventTarget lib "Carbon" () as Integer
 
    dim handler as Integer = _
      NewEventHandlerUPP(addressOf CarbonEventHandler)
    dim eventTypes as new MemoryBlock(8)
    eventTypes.Int32Value(0) = kEventClassApplication
    eventTypes.Int32Value(4) = kEventAppFrontSwitched
    dim err as Integer
    err = InstallEventHandler(GetApplicationEventTarget, _
      handler, 1, eventTypes, 0, 0)
 
    CheckOpenWindows
  End Sub
 
  Private Function CarbonEventHandler(inHandlerCallRef as Integer, _
      inEvent as Integer, inUserData as Integer) As Integer
    CheckOpenWindows
    return 0
  End Function
 
  Private Sub HideShowFloaters(frontAppCode as String)
    for i as integer = 0 to WindowCount - 1
      if strcomp(Window(i).FloaterProcess, frontAppCode, 0) = 0 then
        Window(i).Show
      elseif Window(i).FloaterProcess <> "" then
        Window(i).Hide
      end if
    next
  End Sub
End Module

How does the code work? There is a Carbon event that fires each time a new application is activated. By installing this handler, we can then find out what the creator code of the frontmost app is, loop over our windows, and hide/show them appropriately. Because Carbon events are fired only when the event happens, the CPU usage is nearly 0, and you can once again use FloaterProcess on OS X.

You can download a full example here.


COMMENTS

10 Responses to “Window.FloaterProcess Fix for Mac OS X”

  1. charles Says:

    Why does this line compile?

    eventTypes.Int32Value(0) = kEventClassApplication

  2. Jonathan Johnson Says:

    Why wouldn’t it? :) A long standing feature of REALbasic is that constants defined in the IDE as ‘four’ char codes in single quotes will be treated as numbers. The real compilation error is if you try to do this:

    Const kEventClassApplication = ‘appl’

    In code. The compiler balks at it. However, the IDE automatically turns the above into an integer when you define it in constant editor.

  3. charles Says:

    It is this “long-standing feature” that I had either forgotten or never knew about.

  4. Jonathan Johnson Says:

    Yeah, it’s fairly obscure. I worked for them and I didn’t even know about it until it wasn’t implemented in RB 2005 yet. Users complained, and someone admitted that it was a hidden feature of the old 5.5 IDE. Thus, it was resurrected.

  5. Norman Says:

    And a damned handy one as well :)
    Beats the hell out of having to figure out what the numeric value of that const is just to use it :)

  6. Jeff Says:

    Heya Jonathan,

    It was really good of you to make this code available.

    I am now using it in my project and it’s working like a charm!!

    Only problem - You need a donation button next to the example project download :-)

    Great work and a big thanks!!

    Cheers

    Jeff

  7. Joe Ranieri Says:

    Why didn’t you use structures to clean this up a bit?

  8. Jonathan Johnson Says:

    If by clean up, you mean make two lines of code read a little more clearly, while adding another 18 line structure declaration, then I have no idea why I didn’t “clean” this up a bit.

    To me, it’s not a big deal, and the huge structure declaration isn’t needed for this code. My aim was simply to solve the problem, and I did it quickly and succinctly.

  9. Ryan Govostes Says:

    Joe - I think it’s better without using structures. You can use it on older versions of REALbasic (pre-2005) by working around the ‘appl’ notation (hint: it’s equal to 1634758764).

  10. Jonathan Johnson Says:

    Actually, as I mentioned in comment 4, this feature lasted back even in 5.5, and probably even earlier.

Leave a Reply