NSWindow appears inactive but still accepts keyevents - swift

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.

Related

How to make sure that dragging into my app's window doesn't cause the other app's window to lose focus?

I am working on a MacOS app using Swift/Appkit. I have an NSPanel that is always visible and is a dock replacement. It can receive a drag and drop from any other app, but I don't want it to become the key window and get focus when something is dragged into it. I tried setting canBecomeKey as follows:
override var canBecomeKey: Bool { false }
And this is making sure the window doesn't get focus either when clicked, or when something is dragged into it. But when the mouse is dragged into it, then hovered for a bit, the other app's window from which the drag started is losing focus. Is there any way that I stop this from happening? I don't want the other app's window to lose focus.
Set the styleMask of the app's panel or window to .nonactivatingPanel, and the NSApplication's activationPolicy to .prohibited

Catching window state change by custom system buttons

I'm developing custom system buttons - minimize, maximize and close window. It's working OK, but also I want to catch changing window state for Maximize / Restore down button. For example, when user double click on window title, window maximized and corresponding button should automatically repaint for "Restore down" state.
As I know, there is WM_SYSCOMMAND message for Form which notify for window state change. And we can get parent form for button (by GetParentForm()). So how to tie it all together? Or maybe you suggests something else?
Button inherits by TCustomControl.

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() ) -

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

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

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