I'm in the process of building a help book for my application, mainly using apple's documentation here, however it appears to be a little dated. In Yosemite OS X 10.10, apple's own apps have a collapsable side bar that displays the table of contents for the help bundle
Although, the side bar button is present on my own app I have no idea how to access it. Does anyone know how to access this sidebar? and provide content for our own apps?
I've just come up against the same problem, and I had to dig around in Apple Mail's help files to find out what they were using. Basically they have constructed their sidebar in HTML/CSS, and its not a part of the help viewer.
To enable the "Table of Contents" button in the help viewer, you need to use the javascript function:
window.HelpViewer.showTOCButton(bool, function, function);
For a more explicit example, the following code snippet will enable the "Table of Contents" button in Apple's help viewer, and link it to the function "toggleNavigation".
if ("HelpViewer" in window && "showTOCButton" in window.HelpViewer) {
window.setTimeout(function () {
window.HelpViewer.showTOCButton(true, toggleNavigation, toggleNavigation);
window.HelpViewer.setTOCButton(true);
}, 100);
}
The toggleNavigation function will contain code to open your sidebar.
function toggleNavigation() {
// YOUR CODE HERE
}
I found that using window.onload doesn't seem to work, but setting a timeout for 100ms did. In Mail, Apple used their equivalent of the "toggleNavigation" function, for both of the function parameters, as per the example. The third parameter is called when you press the "Table of Contents" button, but I've not worked out what the second one is for.
Related
By clicking on a certain command in my code, I get the information not available and available within my project. I do not understand how this is possible, and informs me that you can use the navigation bar to switch context, but I do not know how to do that. The attached figure shows the message. My questions are:
How can something be available and not avilable in the same project?
What is the navigation bar and how do I use it to change the context?
This is the message I received:
Usage:
Dim r as list (of Streaming) = Await StartAsync(...)
MSGEM – Available
MSGEM – Not Available
You can use the navigation bar to wsitch context.
This could be be down to two front-end files sharing the same back-end codefile. In such a situation, the code file will reference a front end control which is in only one of the front end files and not both.
If you do not use such a coding technique, it can easily happen accidently when making a backup of a front end code file by copying it to a different filename but forgetting to add the .exclude extension.
See this answer for more details:
You can use the navigation bar to switch contex
Question
How to use these private functions on other windows? It would be nice to have this knowledge back in the wild. I am specifically trying to get CGSOrderWindow and CGSSetWindowLevel to work.
I was trying in the direction of:
temporarily register as the dock and then register the dock as the dock again immediately afterwards
or
code injection into the Dock process per this comment:
Also, the author of the above project seems determined to make all core functionality available as a framework. It seems to be implemented as code injection into the Dock process.
Reason I know this is possible
I have been doing work on trying to setLevel on window of another app, and focus window of another app if focused. I am posting this again with the info I learned because from my searching online, I know this was done in the past, its just the knowledge is not publicly out there anymore. The sourceforge pages are no longer there. So I was wondering if you could help me make this information public again.
This is the topic I read that gave me this information - http://cocoadev.com/HowtoControlOtherAppsWindows
Here you see comments like:
You cannot control an another app's windows from a user-level process, unfortunately.
SlavaKarpenko
You can, Slava, you just need to register as the Dock. It might be possible to temporarily register as the dock and then register the dock as the dock again immediately afterwards, not sure. I think the call you'd be wanting to investigate as CoreDockRegisterDockOwner in HIServices.framework.
FinlayDobbie
You could also use APE or similar to do control the windows, or (as mentioned above) register as the Dock (look for the private APIs with Universal Connection in their name). Has anyone found a polite way of getting the Dock to give up its universal connection? The only way I can find is to force quit the Dock and grab the universal connection when it's not looking (which prevents the dock reloading).
SamTaylor
There's an open source project up on sourceforge.net that looks much more like the window managers I've used on Unix boxes than Space.app (or Space.dock): http://wsmanager.sourceforge.net/
SteveCook
Verifying things work
This is what I learned, from the sources at bottom of this post, we see all these functions work with CGWindowIds, so how do I get that, this is how:
Get all windows with CGWindowListCopyWindowInfo. Then access each element from that array with CFArrayGetValueAtIndex and then get the CGWindowId with objectForKey:, kCGWindowNumber, and then integerValue.
Now if I try to focus or set level of a window that is OWNED by the app running the code, it works fantastic. For instance:
MY_TARGET_CGWINDOW_ID = 179;
rez_CGError = CGSOrderWindow(_CGSDefaultConnection, MY_TARGET_CGWINDOW_ID, kCGSOrderAbove, 0);
Will focus it, rez_CGError is 0. Even if the window is minimized, it is unminimized, without animation, and shown.
Now however, if I try this on a window of a different app we get some errors:
MY_TARGET_CGWINDOW_ID_of_other_app = 40;
rez_CGError = CGSOrderWindow(_CGSDefaultConnection, MY_TARGET_CGWINDOW_ID_of_other_app, kCGSOrderAbove, 0);
This fails and rez_CGError is 1000, which I suspect means "cid (CGSConnection) used does not have permission to modify target window". The same happens if I first do [app activateWithOptions: (NSApplicationActivateIgnoringOtherApps | NSApplicationActivateAllWindows)] before making the call above.
So I first get the cid of that owning window like this:
var rez_CGError = CGSGetWindowOwner(_CGSDefaultConnection, MY_TARGET_CGWINDOW_ID_of_other_app, &ownerCid);
This works good and I get ownerCid is set to a value. Then I do the focus command with this new connection:
rez_CGError = CGSOrderWindow(ownerCid, MY_TARGET_CGWINDOW_ID_of_other_app, kCGSOrderAbove, 0);
However this gives rez_CGError of 268435459, which I suspect means "current app does not have permission to use this ConnectionId (cid)". (Same happens if I call activateWithOptions first.
My Sources for the Private Functions
Here is the sources for some private functions I found - https://code.google.com/p/undocumented-goodness/source/browse/trunk/CoreGraphics/CGSPrivate.h
This one source here contains a function that is not in the above link - CGSGetConnectionIDForPSN - i test it and it exists - from - https://github.com/mnutt/libqxt/blob/767498816dfa1742a6f3aee787281745afec11b8/src/gui/qxtwindowsystem_mac.h#L80
How to show Quick Help for the methods which we wrote ...?
Like for inbuilt function when we right click on it & Click Quick Help then we get all info about that method like that I want to do for user defined methods so that any one come to know that method takes which parameter and each parameter for which purpose?
For more explanation, see these two images:
Here is a solution for that. Also check apple documentation. You might have to create document set and install it in Xcode.
Edit: Here is another similar post, How do you populate the Xcode 4 "Option+Click" popover?
There is an open source tool called appledoc which helps with this. You can provide your own documentation in the header files and then run the appledoc script which will (depending on your settings) generate the docsets, install them into Xcode, create a HTML for the documentation as well as rss feeds so that changes to the documentation can be published.
I'm developing a cross-platform browser extension, and have based all my code on the Chrome-way of doing this. I have counted on that the background page will be accessible from the options page, which in Safari extensions turns out to be not possible (since there is no such thing as an options-page). You can only access safari.extension.globalPage.contentWindow from within the extension popup, and the background page itself.
Now, I have an options page, which is an html-page within the extension bundle, and so far I haven't found a way for Safari to give it extension "rights". The closest I have come is adding a content script that's only added on the options page. This seems a bit silly, since the html page itself is in the extension bundle?!
Others have suggested using asynchronous ping-pong style message event handlers, and even the canLoad-mechanism (which is "only" able to run in a beforeload-event). I have been able to hack the canLoad-mechanism for synchronous messaging by forging the BeforeLoadEvent:
// Content script (run from anywhere)
var result = safari.self.tab.canLoad(new BeforeLoadEvent, "data")
-> "return value"
// Background page
safari.application.addEventListener('message', function(e) {
if ( e.name === "canLoad" )
e.message = "return value";
}, true);
It's a hack, but it works. However, I am crippled by the message transport serialization, since I need to be able access methods and data on my objects from the background page. Is there anyway around this?
Possible ways that might work but I don't know if possible:
Access options-page window-object from backgrounds page. Is that possible?
Message passing, need to bypass message serialization
Any shared/global object that I can attach objects to and fetch from the options page?
Make Safari run the options.html page from outside the content-script sandbox? It works in Chrome since they are both within the extension-bundle. It's quite annoying that safari doesn't do this too.
Run the options-page from within the popup. This is promising, but it crashes safari (which is very promising!). However, from the looks of it it's just something to do with a CSS animation in my options.html page. The biggest issue is that it has to be able to open an OAuth2 popup, but thanks to being able to programmatically open the popover, it might be a non-issue. However, this option is the most realistic, but I would rather have it open in a new tab.
Any suggestions and hackish workarounds would really help.
I'm currently working on an Extension for Safari 5 and I want to run a listener function whenever Settings changes are made. Apple provides an example for that, but it doesn't work for me. I currently have this listener function in my global html file:
function numberChanged()
{
if(event.key == "number")
alert("Number has changed!");
}
safari.self.addEventListener("change", numberChanged, false);
I hope somebody can help me. Does somebody know what I'm doing wrong?
I believe that you need to include ‘event’ as a parameter in your function so it looks like this:
function numberChanged(event)
{
if(event.key == "number")
alert("Number has changed!");
}
however, that said, it’s not working properly for me either (with or without the param), so I might be wrong. Interestingly, every time I change a field or click a button on this stackoverflow form, my alert (similar to yours) IS firing, even though I did not change my setting. totally weird.
update: I got it working, finally. The example that apple provides is just wrong. So there are two parts to the answer. I gave the first part above — you do need to add ‘event’ as a parameter to your function. the second part is that the addeventlistener has to be done on the settings object and not, as apple shows you, using ‘self’ from the global.html page. so the working call would look like this for you:
safari.extension.settings.addEventListener("change",numberChanged,false);