Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some icons not accessible when using an app with many menus and/or narrow screen #111

Closed
gingerbeardman opened this issue Apr 19, 2020 · 29 comments · Fixed by #121
Closed

Comments

@gingerbeardman
Copy link
Contributor

gingerbeardman commented Apr 19, 2020

Problem

  1. Use an app with many menus, eg. Safari
  2. Have a load of menu icons and/or use a narrow screen
  3. Try to access the left most icon

Expected

  • should be able to access all icons

Actual

  • cannot access some icons

Screen shot 2020-04-19 at 18 46 17

Workaround

  • sometimes you can switch to an app with fewer menus, eg. Finder

Screen shot 2020-04-19 at 18 46 28

  • but even then some are unavailable

Screen shot 2020-04-19 at 18 46 41

  • an app with one menu will let me get at them all

Screen shot 2020-04-19 at 18 49 35

Extras

Suggestion

  • Make Dozer show it's own menu in certain circumstances
@decadent
Copy link

decadent commented Jun 3, 2020

Some apps, like Bartender, create a dock icon on-the-fly for this condition, when the user requests all the status icons to be shown. This puts the app in the menu, and it has no menus other than the app name—so the status icons are visible instead.

Bartender also seems to somehow detect dynamically when the current app has too many or too wide menus.

@pr0jectile
Copy link

Also experiencing this issue on a Macbook Pro 15-inch, 2018 model. Is this being looked into?

@gingerbeardman
Copy link
Contributor Author

Any thoughts @Mortennn @aonez ?

@aonez
Copy link
Contributor

aonez commented Jun 17, 2020

@gingerbeardman the suggestion of @decadent seems doable and may work.

Bartender also seems to somehow detect dynamically when the current app has too many or too wide menus.

I don't have a clue how to do this...

@decadent
Copy link

decadent commented Jun 17, 2020

My guess is that, for detection, Bartender just accesses the menus through the standard API (the same that you can use in AppleScript) and then calculates the width in pixels by rendering the text on an internal invisible canvas, adding some fixed values for the padding between menu items.

Properly, with this approach the app should process changes in the focused app's menus—dunno is that's impossible or problematic. Parameters of the menu font should be taken from the system settings.

The values may be easily cached until menus of an app change.

But initially Dozer could take an easier approach of always displaying the dock icon when extra status-menu items are shown =) Though, it might slow down the workings considerably, while currently the speed is Dozer's advantage.

@gingerbeardman
Copy link
Contributor Author

gingerbeardman commented Jul 3, 2020

My workaround for this is a tiny (signed) app I created called Menu.app which shows a minimal menu when you run it, allowing you to hopefully see all your Dozer icons.

Menu.app.zip (21KB zip, 62KB installed)

@gingerbeardman
Copy link
Contributor Author

gingerbeardman commented Jul 3, 2020

One more thought, is that if Dozer is built to have a dock icon LSUIElement=NO then switching to Dozer would show a single menu item and achieve this in a more self-contained way.

So here's a (signed) Dozer 4.2.0 that acts as described above [redacted]

As far as I know there's no way to change LSUIElement dynamically without restarting the app?

@gingerbeardman
Copy link
Contributor Author

gingerbeardman commented Jul 3, 2020

It does seem possible to do it programmatically, see here: https://stackoverflow.com/questions/620841/how-to-hide-the-dock-icon

Will try when I have some time now

@gingerbeardman
Copy link
Contributor Author

gingerbeardman commented Jul 3, 2020

OK, I've done it and it works well!

I also needed to activate the app after showing the dock icon/menu.

Now to tie it to a preference (toggle) or heuristic (left/remove dot position is/are more than half of screen width?)

@decadent
Copy link

decadent commented Jul 3, 2020

IMO for starters it would be alright if Dozer displayed the dock icon when showing the extra status icons, without other conditions. Showing the extra icons isn't supposed to be a frequent operation, I think—so it's fine that something happens in addition, or even if a bit of delay is introduced due to the dock icon.

Regarding the heuristics, measuring just the icons isn't enough since people use different screens, and on my Macbook some apps' menus pretty much encroach on the status icons even when only a few are shown. Properly, width of the menu should be taken into account, but that can be done later. Or, if displaying the dock icon together with the extra status icons works well, then smart heuristics may be omitted altogether.

@decadent
Copy link

decadent commented Jul 3, 2020

BTW, if more info is desired in regard to creating the dock icon, Hammerspoon's code can be consulted: it can show or hide the icon by preference, and also has a Lua api to do that.

@gingerbeardman
Copy link
Contributor Author

gingerbeardman commented Jul 3, 2020

Currently I am storing the x-pos of the leftmost icon in use (remove, or left dot) and if the position of that is more than half a screen, it shows the icon/menu. On my narrow Portrait display, that makes sense for the apps I've been using since adding this feature. But my logic is a little wrong as Dozer menu still appears at times.

So I think you might be right that I am overcomplicating things, I should just show it all the time. At least then it behaves consistently. Perhaps with a preference to agree that you want this behaviour.

@gingerbeardman
Copy link
Contributor Author

gingerbeardman commented Jul 3, 2020

OK, I've made it so it shows it every time. No preference right now.

Feel free to try what I have so far: [redacted]

@decadent
Copy link

decadent commented Jul 4, 2020

@gingerbeardman It says, “the app is damaged and can't be opened”.

Could you please publish the code in a branch in your fork, for example? No offense but—that would also help with the nagging feeling I get when when my open-source software isn't quite that open.

@gingerbeardman
Copy link
Contributor Author

Sure! I'll do that today on my fork

@gingerbeardman
Copy link
Contributor Author

@gingerbeardman
Copy link
Contributor Author

gingerbeardman commented Jul 4, 2020

My fork/branch now has preferences added, and some small UI tweaks: Dozer.app.zip

I'm thinking about adding a new tab to the app with simple usage instructions.

@gingerbeardman
Copy link
Contributor Author

How are you finding using it @decadent ?

@decadent
Copy link

decadent commented Jul 4, 2020

I wasn't keeping my Xcode setup well-oiled, and building the project is likely to be a bit of a major endeavor on my machine and with my luck—hopefully I'll get around to it later in the weekend. But if the PR happens to be merged before that, I'll probably be pretty happy.

Gotta say though, the option title sounds somewhat convoluted. I'd go with just: “When showing icons, free up the menu bar”, and in the subtitle: “Dozer will display a dock icon so it can replace the running application's menu”. Seeing icons in the menu bar is the main thing, and the dock icon is just a necessary side-effect.

@gingerbeardman
Copy link
Contributor Author

gingerbeardman commented Jul 5, 2020

Yes, good point. I'll redo the text when revising the PR

@gingerbeardman
Copy link
Contributor Author

gingerbeardman commented Jul 5, 2020

What about this:

Use full screen width when showing menu bar icons
Temporarily replaces Application menu and shows Dozer dock icon.

Screen shot 2020-07-05 at 12 51 36

@gingerbeardman
Copy link
Contributor Author

gingerbeardman commented Jul 6, 2020

Tightening up the finer points of how this works, there were a couple of holes in the option-click hide/show.

I would like the app to give up its focus when all icons are hidden so the menu disappears and the app you were using comes back. Trying to figure that out. If anybody knows or has any hints please mention them. Thanks!

@aonez
Copy link
Contributor

aonez commented Jul 6, 2020

This should do:

https://developer.apple.com/documentation/appkit/nsapplication/1428733-hide

 [[NSApplication sharedApplication] hide:self];

@gingerbeardman
Copy link
Contributor Author

Yes, I thought so too.

But it seems the Dozer icon that has been clicked has some sort of focus and it is not hidden/deactivated.

It's an annoying extra click to return to previous app that I'd like to get rid of.

NSApp.deactivate()
NSApp.hide(self)

@gingerbeardman
Copy link
Contributor Author

gingerbeardman commented Jul 9, 2020

NSApp.deactivate() is definitely not what we want, because if this "Show Menu" mode is active and the Dozer icon is clicked whilst the preference window is shown then the preference window no longer allows interactions due to it being deactivated.

NSApp.hide(self) does not have any visible effect.

@decadent
Copy link

decadent commented Jul 9, 2020

I vaguely remember that I was solving pretty much the same problem by forcefully focusing the previously active application. However can't recall where I was doing that: possibly that was some sort of background notification process, which therefore could get the active app before popping up its window. So, I'm not sure if Mac's API provides the previously-active app.

But! Since Dozer is doing sorta the same thing by displaying its own active ‘quasi-window’, I think it might also be able to retrieve the focused application before creating the dock icon. And then pass the focus back to it when it's done. I guess it depends on whether MacOS considers an app ‘active’ when its menu icon is clicked—probably not, for the very reason that the focused window and the menu are from the running app.

There's a detail that the user might (and will) pull the rug from under Dozer in this scenario by switching to another app while Dozer's dock icon is hanging around. So, before activating the previous app, Dozer should check that Dozer's dock icon is still ‘focused’—otherwise just silently remove the icon like it does now.

@gingerbeardman
Copy link
Contributor Author

Too much conjecture! 🤓

We need verified working methods.

@gingerbeardman
Copy link
Contributor Author

gingerbeardman commented Jul 9, 2020

Good news!

  • let previousApp = NSWorkspace.shared.frontmostApplication grabs the active app
  • previousApp.activate() reactivates said app

Logic

  • I only remember previousApp if the active app is not Dozer
  • I only activate previousApp if the active app is Dozer

@gingerbeardman
Copy link
Contributor Author

OK, this is done and in #121 and I found and fixed another bug on the way!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants