How to show toolbar window when clicking on statusbar in an OSX app? - swift

I am working on an OSX app which is mainly a toolbar app. This app also prowides a status bar. This status bar is mainly to display some data, and has no menu.
Now I want to add the possibility that, when the status bar is clicked, the toolbar window gets to the front. As far as I found out, this is done like:
NSApp.activate(ignoringOtherApps: true)
What I haven't found yet is how I get my statusbar item to perform that. I created a function, and tried it with statusitem.perform, but that doesn't work.
Thanks,
Jack

Related

NSWindow appears inactive but still accepts keyevents

I'm building a status bar app (windowless) on OSX and having trouble with a pesky little UI bug.
The application opens up a preferences window from the status bar menu when a certain menu item is clicked. The bug presents after the following scenario:
A user opens the preference window from the status bar menu
App resigns the active status when the user opens a browser or another app
User clicks the status bar item (to look at some info in the menu) but doesnt click the menuitem to show the preferenceswindow
User closes the other application and clicks on the already opened preferences window again
After this sequence the NSWindow representing the preferences window appears inactive while still accepting key events. By inactive I mean that the close button for the preferences NSWindow is gray unless hovered over, all the textfields don't get a blue focus ring when clicked and buttons with keyEquivalent = "\r" are not blue. The status bar item will also not highlight. It's like some other hidden window is hijacking the visuals of an active window.
This is what the preferences window looks like normally:
This is what it looks like after the scenario I just described:
How do I make it so that when the preferences NSWindow looks active when clicked even if the user has used other apps and clicked the status bar item in the meantime? Note that the window accepts keyevents normally, and the application is active. Even just a step further in how to debug this would be helpful. Ive logged the main/key window and the apps active status in multiple places and everything looks right.
I think I figured it out. Apparently the NSMenu pop up from the statusbar blocks the execution of the application code. Somehow the NSMenu was retaining the focus even if the menu had been closed if the application wasn't active.
Solution was to activate the app if windows are open when clicking on the NSMenu before popUpMenu is called. Note that the popUpMenu must be done slightly later to not block the activation of the app. Something like:
let noWindowsOpen = extraVisibleWindows.count == 0
if (!noWindowsOpen) {
NSApp.activate(ignoringOtherApps: true)
}
Timer.scheduledTimer(withTimeInterval: 0.04, repeats: false) { _ in
self.statusItem.popUp(self.menu)
}
I found the solution on Github for another app that was dealing with similar problems.

How to open app window on toolbar click in safari app extension?

I'd like to open an application/extension Window when user clicks toolbar item in safari. This is not question about extension's Popover feature. The main reason is to close/hide the window on deactivation AND user action (both conditions are required to work).
Safari App Extension (meaning the new preferred/forced way to create extensions for safari by Apple) can open a Popover or call a Command when toolbar item is clicked. But it cannot be hidden programatically (https://forums.developer.apple.com/thread/105817). Per answer by bweinstein it's work in progress by apple devs.
My use case is about Window containing WKWebView with loaded webpage. When user clicks anything in there I want to open a page in Safari's new tab (this part already works for me in Popover mode) and close the window immediately (this doesn't work for me yet)
So my thinking here was to avoid integrated Popover feature. I'd like to show Window instead when Command (override func toolbarItemClicked(in window: SFSafariWindow) {}) is called.
I know this is somehow doable as e.g. agilebits' 1Password extension is doing exactly this: when you click a toolbar item, window is displayed having no close/minimize buttons, no menu etc. It works exactly as I need, but I don't know how to achieve that.
I don't know whether to define the view as part of Safari extension or as part of Storyboard of containing app and how to access it programatically and show it on screen when user clicks the toolbar item.
As I am new to macos development I don't really have a code to share. Important part from my POV:
- Info.plist's NSExtension->SFSafariToolbarItem->Action is set to Command
As pointed above, feature I need to achieve is to open and close a Window programatically when user clicks toolbar item.
Thanks in advance
Could you not call SFSafarWindow.openTab("httxxx://mysite.com", true, ...) in your toolbarItemClicked
You could also call SFSafariApplication.openWindow API and close SFSafariWindow (by calling windowObject.close() ) -

Swift NSWindow fixed position

I am creating an OSX App in Swift.
What I want is: when I press the icon in the mac top bar I want the window to be exactly underneath the icon like most preferences app do.
Thanks,
You can get the position of the mouse when the user clicks the statusbar and then you know where you can put your window:
NSEvent.mouseLocation()

popover view for a status item not responsive to mouse movements

I have been struggling with this and could not find a solution.
I am creating a statusitem app for mac osx using swift. When the item is clicked a popover with a custom view that has a webview in it appears. everything works fine except that after clicking outside and the popover is closed and clicking again on statusitem to show popover this time the view (webview) is not responsive to mouse movement events like mouse hover a link etc.. unless I click inside the popover to activate it. I found a solution by calling NSApp.activateIgnoringOtherApps(true) but this greys out other opened applications like chrome.
Now my question is that, can I make the app active without greying out other apps? dropbox mac app is an example, clicking the item in status bar, opens the popover of dropbox and its responsive to mouse events but other opened apps in the background are not greyed out and they are responsive to mouse movement events, even after clicking inside it doesn't grey out other apps unless a window appear e.g. preferences window or login window. How to achieve this behaviour?
this image shows how webview is not interactive with mouse
the second image show how it is interactive with mouse hover effect on "Advertising Programs" but chrome app is greyed out

iPhone: hide address bar, also if user clicks top of screen or clock/battery bar

I want the address bar to disappear on the iPhone. So far I have used:
window.scrollTo(0, 1);
This hides the address bar when the page is first loaded.
Then I have
document.body.addEventListener('touchmove', function(e){ e.preventDefault(); });
This prevents the user from scrolling back up to the address bar (or anywhere else) while still allowing buttons to be tapped.
But, the address bar still appears when I tap the top of the page. Not sure if this is because I am touching the top of the webpage or because I am touching the bar with the clock and battery.
I'm guessing that the user himself would need to set this option on his phone, although it would be nice if I could control it via the webpage. Is either way possible?
Why? I want to make a web app for a disabled child who has a hard time controlling his movements. I essentially want to turn off any touch actions that aren't related to the web app itself. Otherwise he will accidentally set off lots of unwanted actions. Not sure if this is possible.
I'm afraid you can't hide the status bar. For example in iOS 6 you can, in landscape mode, go full screen, it hides the status bar, but there is a new button at the bottom right of the screen to leave the full screen mode.
What you are asking is not achievable within Safari. But you can develop a simple application full screen (no adress bar, no buttons, no status bar) with a simple UIWebView. This way there will not be any unwanted action.