-
-
Notifications
You must be signed in to change notification settings - Fork 674
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
Systray support ? #97
Comments
You're correct that it isn't currently supported - we're still trying to get a basic spread of widgets working. But this is absolutely on the roadmap. |
Does this fit as a widget of some kind? Or do we need a different category for "support" features - tray icons, notifications, progress indicators (see https://msdn.microsoft.com/en-us/library/windows/desktop/dd378460(v=vs.85).aspx) It's going to be a little bit of a pain to implement in Windows due to the changes from Win7 -> Win10. |
I don't think this is a "widget" - it's more of a feature of the app itself. In the same way an app has a main_window, it may also have a system tray representation (and, in some cases, it may have a sys tray but not a main window, or vice versa) For macOS and Linux, it makes sense that it's a "menu attached to an icon"; iOS and Android will be a menu as well, with different activation modes (possibly with a slide out tray on iOS, and a toolbar menu on Android). I'm guessing the same would be true of Win7; not sure what the interpretation on Win10 would be. Any suggestions on API are welcome. If you want to take this on as a mini project, it would be a great addition. |
I'm not confident enough on the API design yet but I'll keep it in mind. |
But can this be incorporated into the project? I get confused at organizing this in the "core", systray on the smartphone would be status bar icons. Maybe it's more a matter of name and organizing in the project. |
Looks like I created a duplicate of this issue I've lined out somewhat of a spec for this and how it might be implemented on Android/IOS as the system tray icon doesn't exactly fit. Since most of the time it's to know an application is running and provide quick access / info without having to have the main window open. So the Android and IOS might be a couple of items to accomplish the same behaviors. |
Tray Icon ProposalTray Icons are usually used to show an application is running but not display a window. Sometimes the window is visible with the TrayIcon as well. The Icon also usually allows for a context menu to select some actions. Proposed Properties
Resources
|
how about integrating with pystray - https://pystray.readthedocs.io/en/latest/usage.html |
@gaozhidf That's a nice idea, but the problem is that their macOS support is provided with PyObjC, which overlaps responsibilities with the Rubicon ObjC library that Toga uses. It may be worth examining their API design for ideas, though. Looking at their API, there's also some possible overlap with #907. |
Design discussion: #2108 |
I did an initial pass of adding status icons with #2238; this revealed the need for a bunch of other structural changes around app lifecycle. Those changes became #2244, which then landed as a series of separate PRs - most notably (for the purposes of this PR) #2651. So - we're now in a position to return to adding status icons. The implementation in #2238 will need to be massively reworked to accomodate these changes, and revealed some gaps in the proposed API, but it did allow me to work out the internal details of how status icons are implemented on each (desktop) platform.
The question we're now faced is the design of the public API for creating status icons. There are essentially 3 use cases for status icons that I can see:
I propose that we introduce a base class to represent status icons, with subclasses for each of these use cases. We also add a Usage would look something like:
If you want an "icon only" status icon, you register a If you want a menu-based status icon, you register a
Creating the status icon creates the icon representation; the menus are created (and modified) as part of the existing menu item handling. The only difference to the existing code is that we need to account for a new type of root menu (when the group is a MenuStatusIcon). We might not implement This structure provides a clear API point where we could add any status icon-specific APIs (like show/hide, or modifying the icon in response to status changes). Again, we might not implement any of these APIs in the first pass, but it's fairly clear where the functionality would live if we chose to add it. There's one other major design decision - the handling of "default" menu items. In all the options described above, there's no guarantee that, as a user, you have registered an "Exit" menu item. This could lead to "unquittable apps". Unlike menus, there's no strong UX conventions around what happens with status-icon-only apps, so it's not immediately obvious to me what approach we should take. The easy option is to nothing. If the user doesn't define EXIT, then their app is unquittable. Sucks to be them :-) However, we could take a similar approach with apps, and guarantee registration of some commands - this would be EXIT at a minimum; you could probably make the argument for ABOUT and PREFERENCES as well (once we have default preferences handling). If we do this, I'd argue these commands are added to the end of the first status item, after a separator. It's not clear what we'd do if the only status item is "widget-based" or "icon only". A variation of this would be to only install the defaults if the app My preference here is the latter - to guarantee basic commands on the first status item if the main window is BACKGROUND. This still leaves the user with an unquittable app if they don't define at least one menu status icon, but that's better than nothing. FWIW, I've got a prototype implementation of this API for macOS to prove out the edge cases. However, I'd be interested in other opinions (or alternative API suggestions). |
Thanks, I'll look over this on Tuesday. |
Overall this design looks good. Just a few comments:
So is the proposal that we simply wouldn't support them on GTK? Based on that page and the other pages it links to, it looks like they're hidden in the default configuration, so it wouldn't be worth the effort for us to support them.
I agree, let's wait and see if there's any demand for it.
I understand that logic, but I think it's still easier for each icon to have its own CommandSet, as proposed for per-window commands in #2210:
If each status icon had its own CommandSet, then making it a subclass of Group would be redundant. Instead, we could require that all status icon commands have a top-level group of
I think keeping track of all these conditions is needless work both for us and for the app developer. What if we simply say that ALL MenuStatusIcons get the default menu items, regardless of whether they're the first icon or what the value of |
The problem is that GTK != GNOME. If you're a Mint user, for example, you can have status icons, because the Cinnamon desktop is GTK, but not GNOME. FWIW, I've got a working implementation on GTK - the implementation has some interesting bugs (which are all GTK's problem, AFAICT), but it works. So, IMHO we might as well include an implementation - but it will need some hefty platform notes for GTK users.
I'll have a play with this and see what falls out. I did do some experiments with having a single "status icons" commandset, but I don't think I tried a command set per status icon. I agree there's some nice symmetry with #2210; and being able to clear one icon's commands is also potentially useful. The complication will come around top-level group handling/validation, and adding commands to both the app and the status icon.
In this vein, I guess there's another option: make "include default menu commands" an argument on the MenuStatusIcon constructor. That way the commands are easy to get if you need them, and easy to opt out of if you don't. I guess the only question then would be whether the default value for that argument is On or Off. My argument would be to default to it being On, so that icons "do the right thing" by default, but if you have more than one (or have a status icon in an app that also has windows), you can easily opt out of those default menu items. |
I agree including the standard commands by default is better, because this feature will most often be used in situations where there's one status icon and no visible windows.
We don't have such an argument on the App class, and there's no need for one as long as the default commands can be removed with a simple call to In fact, that's another argument for each status icon having its own CommandSet – it allows the standard commands to be accessed via their standard IDs, because they'd be unique within that CommandSet. |
In the case of App, I'd argue the use case for removing the standard commands is extremely niche, if it exists at all. Apps should have an exit command (et al), and the corresponding menu item(s). Not having the standard commands is very much the exception, not the rule. If a status bar-only app manifests as 2 icons, one of them needs to have the standard commands, but the other one doesn't. And if a window-based app also has status icons, then it doesn't need any standard commands in the status menus. While this could be accommodated with "a clear the defaults before adding your own commands" pattern, it strikes me as such a predictable usage pattern that it makes sense to promote to a first-class API.
Agreed it's a good argument in favor of isolated CommandSets. |
OK, fair enough. |
We talked the other day about what the Group of a status icon command should be, and mentioned 3 options:
In all cases, the icon would require that every command in its CommandSet was directly or indirectly contained within the expected group. I'm still leaning towards the COMMANDS group. It may seem arbitrary, but it has one big advantage: it's the default in the |
In the process of implementing #2768, I came up with a potential hybrid option - make MenuStatusIcon a group, but make it sort equivalent to COMMANDS. That way, you don't have to register a command as having a specific group (falling back to the COMMANDS default). Then, when the menu is created, the top-level groups (ie., any group with parent=None) is ignored rather than being turned into an explicit menu item. That technically means any group could be used as the parent for submenu purposes - the only difference will be ordering (FILE will order before COMMANDS). This also allows you to register any standard command with the status icon, and it will be rendered in an order that is consistent with how they'd appear in main menus... just without the top level labels (so "File > Open" would appear as "Open" if it were added to a status icon). The only downside I see is that technically, you could register a subgroup with a parent of We avoid that inconsistency if we don't make MenuStatusIcon a group, but at the cost of it not being entirely clear why FWIW, the difference between the hybrid I've implemented in #2768, and a COMMANDS/aliased COMMANDS approach is fairly minimal - a one word change in the example app, some minor simplification after removing Group as a base class of MenuStatusIcon, and optionally a new alias for COMMANDS. |
Just now we agreed the following:
Compared to each icon having its own CommandSet, this would lose the ability to clear a single icon's menu with a single method call, or to have multiple commands with the same ID in different icons, although there are workarounds for both of these. It also loses some clarity in that a MenuStatusIcon's menu is no longer contained within the MenuStatusIcon object, but instead has to be managed elsewhere. What I don't remember is, what do we gain in exchange for these losses? What does this design have over each icon having its own CommandSet, which requires all of its commands to be contained within COMMANDS? It may not be immediately clear to the developer why it has to be COMMANDS, but the answer is just "it has to be something, and that was already the default in the Command constructor". As long as we state this rule in the documentation, and give a clear error message when it's broken, it shouldn't be any more confusing than either of the alternatives above. |
To my mind, there's several benefits: Firstly, if each icon has its own commands, then we have to take either the "top level group is ignored" interpretation, or the "top level must be one specific group" interpretation, because every command must have a group. It also means that when you're setting up a submenu of the status icon menu, the group you use must have a parent, so you can't avoid the "parent is COMMANDS" situation - except that it literally doesn't matter which parent you use, because the top level parent is ignored. This can be explained, but the fact that it needs to be explained at all is a mild red flag. However, for me, the biggest argument is that it's more consistent with main menus. You don't "add a File menu" then "add commands to the file menu's command set" - you have a single collection of commands; those commands are grouped, and the top-level grouping determines what menus exist. To my mind, that's a really close analog with having a single commandset for all menu-based status icons, with the top level grouping determining which icons are in use. The only special case that needs to be explained here is how top-level groups that aren't registered as status icons are handled - but that's a special case based on "a thing that doesn't exist", rather than "a thing that exists we're going to ignore", which is much less of a special case. We also have to deal with non-menu status icons; but that doesn't really change the core mechanic - it's just an oddity that you have to deal with in iteration. |
OK, that makes sense. Just a couple of questions:
Do we really want a MenuStatusIcon to disappear when it doesn't have any commands? I think that would be confusing. Unlike a regular Group with no commands, it can still convey information by changing its icon.
I see you've already specified this in #2768, so I'll post there. |
Most desktop-managers have some sort of system tray where to keep icons for long-running programs and notifications. This doesn't seem to be supported in Toga at the moment.
The text was updated successfully, but these errors were encountered: