I have been hitting the wall on this issue for a few days now, and cannot for the life of me figure out what I am doing wrong (or if this is some kind of bug):
I have a custom Mac application (in Java, if it matters). It essentially takes a specific type of document bundle, does some processing on it, and sends the results to a server. I have everything working, except for the one use-case of a user dropping a "file" onto the application's dock icon.
Everything I have read so far seems to indicate that dropping on a Mac Dock icon uses the same Launch Services that the Finder uses. And yet, opening the Applications directory and dropping on the application there works, while dropping on the application icon in the Dock does nothing.
So, some specifics of what I have tried so far:
App handles documents with a *.foo extension, which are Document Bundles (i.e. opt-click gives "Show Package Contents" option)
Document has UTI of org.example.foo, which conforms to the UTIs com.apple.package and public.composite-content (all info copied from owner application Info.plist Exported Type UTIs key)
Info.plist declares this document type in Imported Type UTIs (UTImportedTypeDeclarations key)
Also in Info.plist, the UTI is declared in Document Types (CFBundleDocumentTypes key)
CFBundleTypeExtensions includes "foo"
CFBundleTypeOSTypes set to "****"
Cmd-Opt-drop on the Dock icon (to force the drop) does nothing. Dropping in Finder works exactly as expected. So this appears to be an issue with dropping on the Dock icon specifically.
Any ideas on what to change?
Maz has hit the heart of the issue, I think. The application is set up to run in Mac OS X 10.5 or 10.6, and the Java APIs I am using (com.apple.eawt.*) appear to be deprecated without replacements; which likely explains why it mostly works, but doesn't work in annoying ways.
It seems the actual solution will involve reverse-engineering the JavaApplicationStub executable to work with the newer APIs, and make JNI hooks so that the proper events get passed along to my application.
Related
On Mac it is usual that there is a "hidden" main window.
The usual example is "Text Edit". When you open a file you with you don't see a "main frame". Instead every single file will be opened in its own "Text Edit" instance. This is OSX way of emulating the so-called MDI interface.
However, there is an exception. If you open Xcode and open the project there, you can click on the file and it will be open inside the main Xcode window. And if you double click the file it will be opened in its own independent editor window, keeping the main Xcode window visible.
My question would be: do I need to do anything special in order to make my program behave like an Xcode? Should I use different class for the main frame or maybe react differently on the opening document event?
Any hints/pointers where to look or even to the official Apple documentation would be helpful.
The TextEdit behavior you're describing is much more like “SDI” than “MDI”, and the terms “SDI” and “MDI” weren't even needed until Microsoft invented MDI long after Xerox invented the SDI-type interface of which macOS is a derivative.
Anyway, I think you are misunderstanding Xcode's behavior. You seem to think “its own independent editor window” is a different kind of window than “the main Xcode window”. But in fact the new window is of the same kind as the old window, with some optional parts hidden. You can show those hidden parts and make the new window look exactly like the old window. Demo:
The ability to open multiple windows showing the same document (or, in Xcode's case, project) is a matter of software architecture. If you carefully design your app so that multiple windows can share a single model object graph, and can be notified and redraw themselves when the object graph changes, then you have an app that supports multiple windows showing the same document. If you want multiple kinds of windows showing the same document, nothing about Cocoa stands in your way. As a matter of fact, Xcode does have at least one other kind of window in which it shows some properties of a project:
That project settings sheet is really another window; macOS keeps it attached to the main window, but it is in fact an instance of NSWindow (or a subclass of NSWindow), no doubt with its own custom window controller that references the same project objects as the main window.
If you use the Cocoa NSDocument architecture, then a small amount of multi-window support is built-in: an NSDocument knows about its associated windows (via their window controllers). If you want to use the NSDocument architecture, you should read Document-Based App Programming Guide for Mac.
It is unclear what you are after. The traditional Mac UI has been one window per document - i.e. SDI with a single instance of the app running multiple windows - but there has always been the ability for any app to organise the content of that window as it sees fit, including showing multiple "documents" within one window - i.e MDI type UI.
Apps approach such "MDI" in different ways, e.g. some use panes (views) and others tabs. From macOS Sierra the standard NSWindow supports tabs, this system is (semi)automatic for standard document apps. Read Apple's NSWindow Automatic Window Tabbing section in the Sierra release notes for more details.
If you wish to use multiple panes - e.g. like Xcode - you just use views (NSView) and arrange them how you wish.
HTH
I've implemented a drag-and-drop function in my application. The app let's you open .kext files.
I've used -(void)application:openFiles: as well as having set the Document Types:
All works well, and my app can detect when the kext is dropped. However, when a Kext is dropped, all kexts on my Mac change icon to Folder icon! I guess it has something to do with my app messing with the file associations.
Is there any way around this?
Wow, the answer was simple: Tick the Document is distributed as Bundle box in the Document Types area, and the Icon doesn't change.
My app at launch time prompts the user with a template chooser, this works fine on Snow Leopard but on Lion the window never appears maybe due to restoration behaviour.
My app is NSDocument based and I use NSDocumentController to open the window on newDocument:(id)sender
Now on Lion no application delegate related to "untitiled" is called so I don't understard how to make it working
I think XCode 4 is NSDocument based and it shows the Startup Panel, how it does?
Another smart XCode Startup Panel's behaviour consists to show the panel only when no other windows are restored, again how this is implemented in Lion?
You're right to suspect the new restorable state behavior. The app may never be asked to create a new, empty document when relaunched/resumed. This is stated in the release notes:
As part of the restorable windows feature, the application delegate
may not be asked to create an Untitled window at launch in some
circumstances. This was found to cause crashes in certain apps, so
these apps will maintain 10.6 behavior of more often opening Untitled
windows. When these apps are recompiled on 10.7, they will acquire the
10.7 behavior. For maximum compatibility, do not depend on being asked
to create an Untitled window at launch.
They don't mention an alternative, and the document-based app documentation does not appear to have been updated yet with restorable state information.
As to your approach, you could change so that the template chooser is shown as a sheet on a new, empty doc window (like Pages or Instruments, for example). The document's contents are set when the template sheet is completed. This way, each new document shows its template sheet but this only happens if the user requests a new document, rather than relying on a fresh app launch (which you're no longer meant to do).
I have an app that may get launched with current user's or with root permissions.
In fact, there's the possibility that the app runs twice at the same time - once under the current user and once as root.
I like to inform the user when the app is running under root. Currently, I show this in its window title, but I'd prefer to change the app's name so that it reads "Appname (Root)" where appropriate. That way, the name would appear both in the menu bar and in the Dock with this "root" info, and it would allow the user to tell which of the two app instances in the Dock is the root version.
Does someone know if the app name can be changed by code, i.e. by the app itself, or by its launcher?
If not, my only option appears to be adding a badge to the Dock icon that says "root", but that's my last resort, as it won't work for the menu bar nor for other tools that display the app names (i.e. other app launchers such as DragThing).
…there are at least five application names floating around, at least in concept: (1) the file name the Finder sees, which in the case of an application package is the package (bundle) name; (2) the name of the executable inside the package, (3) the long name used in many places for display purposes only; (4) the short name used as the application menu title and in a few other places where a long name won’t fit for display purposes; and (5) the process name of a running application. They aren’t always the same, especially in Microsoft and Adobe products.
—Bill Cheeseman
From what I can tell, the name in the dock is the name of the application bundle (sans ".app") on the filesystem.
The value under the CFBundleName key in info.plist is what shows up in the menubar.
As far as I know, changing either these at runtime isn't going to work… but what you can do is have two versions of your app, a root and non-root version, inside your user-facing .app bundle. When the user-facing app is launched, it checks if it's running as root or not, and launches the appropriate copy of the real app, which has theCFBundleName and file-name you want.
I wish I knew of a more elegant solution.
That label comes out of your Info.plist and I don't believe it's ever consulted again after it's been launched. If you want to have a parent application that does nothing but launch the real application (possibly from inside its own bundle) after munging its Info.plist, then that might give you the effect you're hoping for. You will get two icons bouncing at launch time, though.
OS X apps do not normally run with multiple instances. Look at any app developed by Apple for example. It would be more common to allow for multiple documents/windows, in this case each window could be either a root or non-root window.
The most common way to allow for root authentication however is to have a padlock icon that can be clicked to switch to root mode with a password prompt, this can be seen in many of the System Preferences panels.
Is it possible to embed Finder functionality in a cocoa app, now that Finder is itself cocoa (assuming the app were to function only in snow leopard)?
What I mean is to have a file browser pane as part of the app, actually browsing the file system itself (to edit in another pane), but without writing all the functionality of the Finder. Thanks!
The Finder itself is just an application. It is not a components library nor a framework. While you cannot "embed" Finder functionality in your application, you can influence Finder functionality and invoke Finder functionality.
First off, you can attach Folder Actions to folders. These will trigger when a user does something to the contents of a folder - for instance, they drop a file into it. You set this up in the Finder. You should to learn a little AppleScript, if interacting with the Finder is something you want to do.
Second, since the Finder supports AppleEvents, you can affect the Finder using AppleScript. Take a look at My First AppleScript and My First AppleScript Part II to see how to do this. Here is much more in-depth information, in AppleScript Overview: Scripting with AppleScript. Here is some More Finder Scripting.
Third, there is also support for developing ways for the Finder to do complex things for the user at the click of a button, using Automator (Mac OS X 10.5). You can also create a Service in Automator, beginning in Mac OS X 10.6 ("Snow Leopard"). Take a look at Automator and Finder Actions in Mac OS X 10.6 for an introduction to this latter technique.
Even though Finder windows themselves are not an embeddable component, if you really want to provide the ability to pen, Print, Delete, Duplicate, etc. Files/Folders, and navigate from Folder to Folder, you can develop a simple Folder browser in your application.
It should not be a huge amount of work to do this so long as you do not set your sites on mimicking the finder or duplicating all of its functionality, just the essential basics I have mentioned.
You would need to know how to program the Macintosh, however - not just use AppleScript. The normal way to do this would be to learn the Objective-C programming language and the Cocoa framework. You would need to get familiar with writing applications using a Model-View-Controller architecture.
You would create a subclass of NSObject named something like MyFile, and a subclass of a collection class named something like MyFolder. When the application creates the browsing Windows, and each time the application activates (becomes the frontmost application), you8 would refresh the contents of the browsing menu.
You could put a menu in your menu bar with commands in it: Open, Print, Delete, Duplicate. When the user does one of those commands, your application performs the appropriate actions itself or sends the request to the Finder. After the action has been completely carried out, then you refresh the browsing window for currently displayed Folder, or newly displayed Folder if the user navigated to a different Folder.
If you are familiar with design patterns, object-oriented programming, and frameworks in general - reading up on Cocoa Design Patterns will speed your learning curve immensely.
These are various techniques you can use to harness some of the power of the Finder. As you look these over, I suggest getting very clear in your mind just what benefit this brings to the user of your application. Writing down what the overall objective of this feature is, and what commands you wish to support, will make it easier to choose the path you take in developing it.
The user can always click on a Finder folder window at the click of a button, since Finder is always running. So avoid simply duplicating that functionality for its own sake. Focus on the benefit you are providing the user. Make sure that you do handle the situations where the user updates the Folder you are showing the contents of from another application and then switches back to your application.
No, they have not made Finder simply a host for a framework, like Preview. You still have to write this yourself.