Projects

Ticket #655 (closed defect: fixed)

Opened 22 months ago

Last modified 22 months ago

NSInteger received as nil from QuickLook API

Reported by: jakub.suder@… Owned by: lsansonetti@…
Priority: minor Milestone: MacRuby 0.6
Component: MacRuby Keywords:
Cc:

Description

I'm trying to display a QuickLook preview panel inside my MacRuby application. I've implemented a method previewPanel:previewItemAtIndex: from QLPreviewPanelDataSource protocol, and it seems it's being called with nil in the second parameter, while it should be an NSInteger with the index of the file on the list. The same class implemented in ObjC receives this parameter as a proper NSInteger.

Is it a MacRuby bug, or is it just because some bridge support files are missing in Apple's frameworks? Can I do anything about it, other than implementing the class in ObjC?

Also, when I upgraded to the latest nightly version, I started getting such messages in the console when I start the app (this doesn't happen in 0.5):

2010-04-18 13:35:19.848 QuickLookTest[54689:a0f] [QL] image sp_zoomp_handle not found
2010-04-18 13:35:19.851 QuickLookTest[54689:a0f] [QL] image sp_zoomp_track_left not found
2010-04-18 13:35:19.851 QuickLookTest[54689:a0f] [QL] image sp_zoomp_track_center not found
2010-04-18 13:35:19.852 QuickLookTest[54689:a0f] [QL] image sp_zoomp_track_right not found

They don't seem to have any effect on the QuickLook panel display though...

Attaching a sample project that shows the problem with the data source method.

Attachments

QuickLookTest.zip Download (173.1 KB) - added by jakub.suder@… 22 months ago.
QLPreviewPanel.bridgesupport Download (1.5 KB) - added by jakub.suder@… 22 months ago.

Change History

Changed 22 months ago by jakub.suder@…

Changed 22 months ago by lsansonetti@…

  • status changed from new to closed
  • resolution set to wontfix

It looks like the "QLPreviewPanel" class you are using is not a public Apple API, therefore this delegate/datasource method hasn't been annotated in a BridgeSupport file and it's not behaving as expected in MacRuby.

We highly recommend you to not use private APIs (called SPIs), firstly because non-introspectable features will not work in MacRuby or other Objective-C-based languages (because of missing BridgeSupport annotations), and secondly because these APIs are subject to change without any notice in further OS releases.

Changed 22 months ago by jakub.suder@…

  • status changed from closed to reopened
  • resolution wontfix deleted

I completely agree, except it's *not* a private API. See  http://developer.apple.com/mac/library/DOCUMENTATION/Quartz/Reference/QLPreviewPanel_Class/Reference/Reference.html and /System/Library/Frameworks/Quartz.framework/Versions/A/Frameworks/QuickLookUI.framework/Versions/A/Headers/QLPreviewPanel.h on your computer. If it were a private API, it wouldn't have a page in the docs and it's header would be in PrivateFrameworks, is that right?

Changed 22 months ago by lsansonetti@…

Oops, I apologize... I thought this was part of the private QT framework. Let's re-investigate the problem :)

Changed 22 months ago by martinlagardette@…

Laurent: I wonder if the problem could be related to the fact that QuickLookUI doesn't have any BridgeSupport file?

$> cd /System/Library/Frameworks/Quartz.framework/Versions/A/Frameworks
$> l
total 0
drwxr-xr-x  7 root  wheel   238B Mar 17 17:08 ImageKit.framework
drwxr-xr-x  7 root  wheel   238B Mar 17 17:08 PDFKit.framework
drwxr-xr-x  7 root  wheel   238B Mar 17 17:08 QuartzComposer.framework
drwxr-xr-x  7 root  wheel   238B Mar 17 17:08 QuartzFilters.framework
drwxr-xr-x  7 root  wheel   238B Mar 17 17:08 QuickLookUI.framework
$> find . -iname '*.bridgesupport'
./ImageKit.framework/Versions/A/Resources/BridgeSupport/ImageKit.bridgesupport
./ImageKit.framework/Versions/A/Resources/BridgeSupport/ImageKitFull.bridgesupport
./PDFKit.framework/Versions/A/Resources/BridgeSupport/PDFKit.bridgesupport
./PDFKit.framework/Versions/A/Resources/BridgeSupport/PDFKitFull.bridgesupport
./QuartzComposer.framework/Versions/A/Resources/BridgeSupport/QuartzComposer.bridgesupport
./QuartzComposer.framework/Versions/A/Resources/BridgeSupport/QuartzComposerFull.bridgesupport
$>

Changed 22 months ago by jakub.suder@…

Yeah, that's what I was thinking too. I tried to generate it manually and just include it in the project, but it seems the method I'm interested in (previewPanel:previewItemAtIndex:) isn't included in the generated bridgesupport file... Am I doing something wrong?

Changed 22 months ago by martinlagardette@…

When you say generate manually, you mean you wrote the XML by hand, and you yourself used bridgesupport to generate the XML file? If so, what command did you use?

Changed 22 months ago by jakub.suder@…

I went to /System/Library/Frameworks/Quartz.framework/Frameworks/QuickLookUI.framework and called: gen_bridge_metadata -c "-IHeaders" Headers/QLPreviewPanel.h > ~/QLPreviewPanel.bridgesupport

The result was:

<?xml version='1.0'?>
<!DOCTYPE signatures SYSTEM "file://localhost/System/Library/DTDs/BridgeSupport.dtd">
<signatures version='0.9'>
<class name='NSObject'>
<method selector='acceptsPreviewPanelControl:'>
<retval type='B'/>
</method>
<method selector='previewPanel:handleEvent:'>
<retval type='B'/>
</method>
</class>
<class name='QLPreviewPanel'>
<method selector='enterFullScreenMode:withOptions:'>
<retval type='B'/>
</method>
<method selector='isInFullScreenMode'>
<retval type='B'/>
</method>
<method selector='sharedPreviewPanelExists' class_method='true'>
<retval type='B'/>
</method>
</class>
<informal_protocol name='NSWindowDelegate'>
<method type='B16@0:4@8@12' selector='previewPanel:handleEvent:'/>
<method type='{_NSRect={_NSPoint=ff}{_NSSize=ff}}16@0:4@8@12' selector='previewPanel:sourceFrameOnScreenForPreviewItem:'/>
<method type='@20@0:4@8@12^{_NSRect={_NSPoint=ff}{_NSSize=ff}}16' selector='previewPanel:transitionImageForPreviewItem:contentRect:'/>
</informal_protocol>
<informal_protocol name='QLPreviewPanelController'>
<method type='B12@0:4@8' selector='acceptsPreviewPanelControl:'/>
<method type='v12@0:4@8' selector='beginPreviewPanelControl:'/>
<method type='v12@0:4@8' selector='endPreviewPanelControl:'/>
</informal_protocol>
</signatures>

So it looks like this was completely ignored:

@protocol QLPreviewPanelDataSource
@required
- (NSInteger)numberOfPreviewItemsInPreviewPanel:(QLPreviewPanel *)panel;
- (id <QLPreviewItem>)previewPanel:(QLPreviewPanel *)panel previewItemAtIndex:(NSInteger)index;
@end

Changed 22 months ago by lsansonetti@…

So, there are 2 problems here. Problem #1: there is no BridgeSupport file for QuickLookUI. Problem #2: I suspect the metadata generator doesn't know how to parse the new @protocol syntax (with @required).

Unfortunately this isn't something we can fix in MacRuby itself. These bugs need to be reported to Apple so that they can be fixed in a future version of Mac OS X.

However, a workaround could be to write by hand a bridgesupport file that contains the description of these datasource methods.

Changed 22 months ago by jakub.suder@…

Ok, thanks for help, I'll report this to Apple.

Changed 22 months ago by jakub.suder@…

I've temporarily changed the @protocol declarations in that header to categories on NSObject, generated a bridge support file from that, and added it to my project, and it worked, the method is now called correctly.

Do you have any idea what may be causing the other issue (image not found after update to MacRuby 0.6) ?

Changed 22 months ago by martinlagardette@…

Maybe a category was not needed, I think just getting rid of the "@required" keyword would have been enough ;-)

I will look at why you get these warnings though :)

Changed 22 months ago by jakub.suder@…

Removing @required doesn't help, I think the script doesn't understand @protocol at all...

And I have a new problem - I was just about to upload a new release of my app, when I noticed that QuickLook doesn't work in the final version. Apparently, once I get through the compile step (macruby_deploy --compile build/Release/my.app), the same problem reappears - previewItemAtIndex: gets called with nil instead of 0... My QLPreviewPanel.bridgesupport file is still included in the bundle, and it gets loaded during startup, but it doesn't seem to have any effect. A moment earlier, before I compile the ruby files, the same app bundle works as intended. Any ideas?...

Changed 22 months ago by jakub.suder@…

Changed 22 months ago by jakub.suder@…

Ok, I've fixed it... in my rb_main.rb, I was loading the bridge support files after the rb/rbo files. I thought I'd try swapping these and see if it would help, and it did.

Changed 22 months ago by martinlagardette@…

Yep that's right. I did check and in fact, protocols are not yet supported.

Otherwise, I don't know where you loaded the bridge support file, but a good place to do it could be:

# Loading the Cocoa framework. If you need to load more frameworks, you can
# do that here too.
framework 'Cocoa'
load_bridge_support_file NSBundle.mainBundle.pathForResource("QLPreviewPanel", ofType:"bridgesupport")

(this assumes you placed the .bridgesupport file in the Resources directory)

Other than that, after investigation, you can safely ignore the warnings, they will not affect your application and should disappear one day :-).

Changed 22 months ago by jakub.suder@…

Yeah, that's more or less what I'm doing - this is my rb_main:

# Loading frameworks
framework 'Cocoa'

# Loading all the Ruby project files
main = File.basename(__FILE__, File.extname(__FILE__))
dir_path = NSBundle.mainBundle.resourcePath.fileSystemRepresentation
Dir.glob(File.join(dir_path, '*.bridgesupport')).uniq.each do |path|
  load_bridge_support_file(path)
end
Dir.glob(File.join(dir_path, '*.{rb,rbo}')).map { |x| File.basename(x, File.extname(x)) }.uniq.each do |path|
  require(path) unless path == main
end

# Starting the Cocoa main loop
NSApplicationMain(0, nil)

Changed 22 months ago by martinlagardette@…

  • status changed from reopened to closed
  • resolution set to fixed
  • milestone set to MacRuby 0.6

Btw, closing the bug, as one issue is bridgesupport (not macruby) and the other one is not really MacRuby either and will not impact anything (and will disappear in the future).

Changed 22 months ago by jakub.suder@…

I'm curious, what exactly is causing the warnings if this is not MacRuby's fault?

Changed 22 months ago by lsansonetti@…

There is a class in the quartz framework whose +initialize method tries to load these images. The images do not exist and the class itself is not used anymore (it's dead code). The warnings do not appear in a pure ObjC app since the class is not used. However, at runtime, MacRuby parses all the classes and it looks like +initialize got triggered for that specific class.

A bug has been filed against the quicklook component internally :-)

Note: See TracTickets for help on using tickets.