Extendamac Frequently Asked Questions

Last Updated on Thursday, August 8, 2002 (8:52 PM)
Maintained By Duane Murphy

  • What is Extendamac?
  • How do I write an OS X System Menu?
  • How do I write an OS X Dockling?
  • How do I get my application to automatically launch at startup without the user having to do it manually with System Preferences.
  • How do I get my application to be in the Dock automatically without the user having to do it manually?
  • Hey, OS X doesn't have traps and there's all this memory protection stuff. How do I get my code to run inside of other applications?
  • I heard about this thing called libPatch. Can I use that to get into other applications?
  • How do I get a window to float over all the other window like DragThing?
  • In OS 9 I used to be able to draw direct to the screen buffer to do things that would cross between windows. How do I do that on OS X?
  • How do I get the list of all the windows in OS X?
  • Private APIs! Isn't that dangerous? What does Apple have to say about this?
  • What about these Accessibility APIs?
  • How do I write a contextual menu that shows up in the Finder?
  • How do I make my application's icon not show up in the dock?
  • How do I catch shortcut keys globally?

  • What is Extendamac?

    See About Extendamac

    "Extendamac is a community of Macintosh developers organized to document and distribute best known practices for extending the Mac OS and improving the Mac OS experience."

    Return to the top

  • How do I write an OS X System Menu?

    ?

    Return to the top

  • How do I write an OS X Dockling?

    Docklings are no longer supported in Mac OS X. However, applications can modify their icon and menu shown in the dock, so a normal application can be made that will fulfill most needs. You only need to get the application launched at startup. See Customizing Your Application Dock Tile [GW]

    If you feel that you really need to write a dockling, then the article Creating docklings on Mac OS X 10.0.4 from StepWise may prove useful. [WF]

    There are a couple of reasons for wanting to a do a dockling over an application. Docklings are loaded automatically at login. You can arrange for your application to do the same, however there are differences. A dockling does not have a Quit and Hide menu item that all applications have. Alas, there is currently no way to disable these menu items.

    Return to the top

  • How do I get my application to automatically launch at startup without the user having to do it manually with System Preferences.

    LoginWindowCheck.c is a procedure for adding and removing an application from the login window's list of startup items. [GLW]

    Return to the top

  • How do I get my application to be in the Dock automatically without the user having to do it manually?

    Here's the "unofficial" code to add an application to the dock's preferences. It won't actually update the dock until the next time it starts up (login?). Note that Apple might change how this preference is stored at any time and that this code may break if they do. Use at your own risk.

    Return to the top

  • Hey, OS X doesn't have traps and there's all this memory protection stuff. How do I get my code to run inside of other applications?

    ?

    Return to the top

  • I heard about this thing called libPatch. Can I use that to get into other applications?

    libPatch was an early effort to allow code to be executed inside of other applications. It is now deprecated and no longer supported. You should use [ application extension? ] instead.

    Return to the top

  • How do I get a window to float over all the other window like DragThing?

    OS X has the utility window class and the overlay window class. There are also window groups and layers. See MacWindows.h for a starting point to learn more.

    Return to the top

  • In OS 9 I was to be able to draw direct to the screen buffer to do things that would cross between windows. How do I do that on OS X?

    In OS X, you can create a transparent window that covers the entire screen. This makes it appear that you are drawing over the entire screen. See overlay windows in MacWindows.h.

    Return to the top

  • How do I get the list of all the windows in OS X?

    There are a couple of answers to this question.

    If you are working in OS X 10.1.x or newer you may have to use some private functions. In 10.2 Apple is introducing Accessibility APIs that may provide more access. You need to use private functions within the CoreGraphics framework. More specifically, these:

    
    typedef UInt32 CGSConnectionRef;
    typedef UInt32 CGSWindowRef;
    
    CG_EXTERN CGError CGSGetConnectionIDForPSN(UInt32 inParam1,
    ProcessSerialNumber* inPSN, CGSConnectionRef* outConnectionRef);
    
    CG_EXTERN CGError CGSGetOnScreenWindowCount(CGSConnectionRef
    inCurrentConnectionRef, CGSConnectionRef inTargetConnectionRef, UInt32*
    outWindowCount);
    
    CG_EXTERN CGError CGSGetOnScreenWindowList(CGSConnectionRef
    inCurrentConnectionRef, CGSConnectionRef inTargetConnectionRef, UInt32
    inMaxWindowRefs, CGSWindowRef* outWindowRefList, UInt32*
    outWindowRefListCount);
    

    Then you'll want to walk the process list and get the list of windows for each process. Code like this will do that:

    CGError err = 0;
    UInt32 count = 0;
    UInt32 connectionID = 0;
    ProcessSerialNumber psn = {kNoProcess, kNoProcess};
    UInt32 myConnectionID = 0;
    ProcessSerialNumber myPSN = {kNoProcess, kNoProcess};
    
    // get our connection id.  From looking at other hacks
    //  I believe you can do this part another way.
    GetCurrentProcess(&myPSN);
    err = CGSGetConnectionIDForPSN(0, &myPSN, &myConnectionID);
    
    // walk the process list
    err = GetNextProcess(&psn);
    
    while( err == noErr ) {
        err = CGSGetConnectionIDForPSN(0, &psn, &connectionID);
    
        if( err == noErr ) {
            err = CGSGetOnScreenWindowCount(
            		myConnectionID, connectionID, &count);
            if( (err == noErr) && (count > 0) ) {
                UInt32* ids = (UInt32*)calloc(count, sizeof(UInt32));
                UInt32 actualIDs = 0;
                UInt32 i = 0;
    
                err = CGSGetOnScreenWindowList(m
                	yConnectionID, connectionID, count, ids, &actualIDs);
    
                for(i = 0; i < actualIDs; i++) {
                    // do something with the actualIDs[I]
                }
                free(ids);
            }
        }
    
        err = GetNextProcess(&psn);
    }
    

    Once you have the window ID you can get information about that window. [AF]

    Return to the top

  • Private APIs! Isn't that dangerous? What does Apple have to say about this?

    Yep, they are dangerous. There is a risk that Apple may change private APIs at any time. This is the risk you take and the users of your application. You must do your best to code defensively to prevent a bad experience for the user; they're the reason we're here, remember.

    Apple's statement on using private APIs is simple. Don'ft do it. They are unsupported and unauthorized. Your application could break at any time.

    It should be made clear that some information presented by extendamac will use unpublished, undocumented, private APIs. Use this information at your own risk. In order to achieve some functionality, using these APIs may be necessary. We will always encourage Apple to provide sanctioned APIs for our needs. When and if that happens, the information on extendamac will be updated.

    Return to the top

  • What about these Accessibility APIs?

    Basically, Mac OS X 10.2 (Jaguar) will provide an Accessibility API which is meant to allow the creation of software to improve the accessibility of the system to users with disabilities. However, there's nothing stopping you from using it either. The API allows you to ask for attributes of accessible objects in the user interface; one such accessible object is the application, and one of its attributes is its list of children. The children of the application are its menubar and its visible windows, so this would give you a way to get all of the visible windows of an application. [ES]

    Return to the top

  • How do I write a contextual menu that shows up in the Finder?

    You want to write a contextual menu plugin. See SampleCMPlugin for sample code. [AF]

    Return to the top

  • How do I make my application's icon not show up in the dock?

    Add LSUIElement = 1 to your Info.plist. With this you can still display UI, but your menu bar and dock icon will not show. [LY]

    There is also an LSBackgroundOnly flag for processes that truly have no UI. It should be noted that the LSBackgroundOnly applications are treated as daemons and are exited using SIG_QUIT (and friends including SIG_KILL) instead of the usual AEQuit method. [LY]

    Return to the top

  • How do I catch shortcut keys globally?

    You want to use the hot keys API found in carbon. See CarbonEvents.h and search for RegisterEventHotKey. [AF]

    Hot key support is undocumented in Cocoa. You can't just use Carbon Event handlers in Cocoa (registering them works, but they're never invoked). However, you can examine events as they get delivered to NSApplication by overriding -[NSApplication sendEvent:]. Sample code can be found in HotKeys.dmg [NR]

    Return to the top

  • Contributors

    The following individuals have contributed to the information contained in this FAQ.

    [AF] Andy Finnell
    [ES] Eric Schlegel
    [GLW] Gary L. Wade
    [GW] George Warner
    [DM] Duane Murphy
    [NR] Nicholas Riley
    [WF] Jonathan 'Wolf' Rentzsch