Saturday, January 23, 2021


Tags

Xojo Mac Apps handling Sym Links & Bookmarks (aliases)

Trying to update an application to process Aliases and ran into all sorts of issues with Xojo prefering to auto-resolve aliases

Saturday, January 23, 2021 - Sam Rowlands

There were a total of 4 issues I ran into, while working on macOS 11.1 and Xojo 2020r1.2.

  1. Unable to read the contents via a binary or text stream.
  2. Aliases being dragged into an app window/control are auto-resolved.
  3. Aliases dropped into the app icon are auto-resolved.
  4. Xojo bug with new folderitem and url paths

There's a bonus item Getting files from the clipboard.

Unable to read the contents

Yesterday, I posted in the Xojo forum about failing to read the contents of an alias. After getting some sleep, talking to other developers and tackling this the following day, the reason was perfectly clear. I CAN read the contents of a Bookmark with a Xojo stream (binary/text), however a "Symbolic Link" (which shows as an Alias in the Finder and Xojo), I cannot.

Solution

I can get the destination of a Sym Link, and that appears to match the "length" of the file, so I think this is as close as I am going to get, to reading the contents.

if UTTypeConformsTo( fileUTI, kUTTypeSymbolicLink ) then Dim e as integer data = NSFileManagerDestinationOfSymbolicLinkAtPath( NSFileManagerDefaultManager, file.nativePath, e ) else // --- Use a stream to read the file contents. end if

First I read the UTI of the file, if it conforms to "public.symlink", then ask use [NSFileManager destinationOfSymbolicLinkAtPath:] to read the destination. The code snippet is missing error handling from the NSFileManager.

Drag & Drop into window/control = auto-resolved aliases

if obj.folderItemAvailable then Dim f as folderitem = obj.folderItem // ---- Do something with the folderitem. end if

The above code always gives the auto-resolved folderitem, never the alias.

Solution

if obj.folderItemAvailable then Dim pb as integer = NSDraggingInfo_draggingPasteboard( obj.handle ) Dim nURL as integer = NSURLWithString( NSURLClass, NSPasteboardItem_stringForType( pb, "public.file-url" ) ) Dim f as folderitem = new folderItem( NSURLPath( nURL ), folderItem.pathModes.native, false ) // ---- Do something with the folderitem. end if

The above code, obtains the NSPasteboard from dragItem, and extracts the "public.file-url" from it. Uusing "New folderitem( <path/>, folderitem.pathmodes.url, false )" returned the resolved file, not the alias (See point 4). Creating a NSURL from the URL, then asking for the file path from the NSURL, which is then used to create a Xojo folderitem, works.

I had to add API to the Ohanaware App Kit to make this work, it will be released in an update shortly.

Aliases dropped into the app icon are auto-resolved

The next challenege was to get the alias from a file drop on to the app icon. This failed miserable, which leads me to beleive that this maybe a design of iOS macOS.

Manually processing the Apple Events, and exaiming the raw data revealled that files dropped onto the app icon, come in as bookmarks.

Examining the bookmarks for dropped aliases, shows that they reference the final destination, not the alias, sadly.

I cannot think of anything else to try at this point, if you have suggestions, then please let me know.

Xojo bug with new folderitem and url paths

It appeared that New folderitem( <path/>, folderitem.pathmodes.url, false ) auto-resolves even when told not to do so.

You can test this by copy/pasting the following code into the open event of a window.

dim rootPath as string = app.executableFile.parent.parent.nativePath dim rpl as integer = len( rootPath ) Dim executableAlias as folderItem = app.executableFile.parent.parent.child( "Frameworks" ).child( "XojoFramework.framework" ).Child( "XojoFramework", false ) Dim urlItem as folderItem = new folderItem( executableAlias.uRLPath, folderItem.pathModes.uRL, false ) Dim nativeItem as folderItem = new folderItem( executableAlias.nativePath, folderItem.pathModes.native, false ) Dim urlPath as string = right( urlItem.nativePath, len( urlItem.nativePath ) - rpl ) Dim nativePath as string = right( nativeItem.nativePath, len( nativeItem.nativePath ) - rpl )

Which will generate the same results as below. The "nativePath" is correct.

nativePath = "/Frameworks/XojoFramework.framework/XojoFramework"
urlPath    = "/Frameworks/XojoFramework.framework/Versions/Current/XojoFramework"

Filed as feedback://showreport?report_id=63416

bonus: Files and Alises from the clipboard

To get files from the clipboard, we can use a similar trick to handling them from the DragItem. Grab the URL and NSURL to translate that into a file path.

Dim c as new clipboard if c.rawDataAvailable( "public.file-url" ) then Dim fURL as string = c.rawdata( "public.file-url" ) Dim nurl as integer = NSURLWithString( NSURLClass, fURL ) Dim f as folderItem = new folderItem( NSURLPath( nurl ), folderItem.pathModes.native, false ) // ---- Do something with the folderitem. end if c.close