keepassxreboot / keepassxc

KeePassXC is a cross-platform community-driven port of the Windows application “Keepass Password Safe”.
https://keepassxc.org/
Other
20.81k stars 1.44k forks source link

Allow background GUI process without system tray icon #5547

Closed etosan closed 1 year ago

etosan commented 3 years ago

Overview

Like old winamp, keepass should support two distinct actions for getting rid of it's main window:

It seems currently only "minimize" is implemented. Unfortunately this command has no meaning in tiling window managers because windows are usually stacked in tiling frames and cannot readily minimize. However even on tilers, applications should be able to close it's own windows and pop them up when needed (especially unobtrusive helper apps like keepass). This would allow app to be used in such situations (tiling but also others) without permanently occupying single tiler frame or entire desktop (even in background) for itself.

This would allow user to more precisely control keepass hiding behaviour. In my recent brief time on windows I used original keepass in "always close to systray" mode, recalling the window only when needed, having it autoclose immediately on "ctrl+c" pwd entry copy - this was least intrusive usage pattern.

Combined with WM/DE shortcuts feature and #5546 suggested feature, this would allow such keyboard heavy usage for keepassxc too. It would be also be infinitely more configurable, then having global shortcut engine implemented within keepassxc with all it's shenanigans, as it's GUI would be invoked externally from reliable global keyboard grabbing source like WM or DE is (or perhaps rofi).

While talking about it, once window closing works - ESC key to close window from keyboard should probably added to finalize support for keyboard heavy users. This would allow to bring up GUI with #5546 and have it close quickly after some work done.

DB locking state should remembered even for closed windo too, some users would probably want keepassxc to lock immediatly after closing/esc - while other might want it to reach locking timeout configured as if minimized.

Finally these mechanics should work even if no systray applet is running on X (because even if systray does not work, one could still easily use #5546 to bring keeepass UI back, even without systray).

droidmonkey commented 3 years ago

We support trayed "closing"

ozls commented 3 years ago

I don't think it's closed at all. I just started using KeePassXC, and I have the same issue. Right now I have a choice between:

I also use a tiling window manager, and I would like the following behaviour:

Could you please not dismiss out of hand the very thorough bug description @etosan took the time to write ? I really would like a fix for this in the future.

droidmonkey commented 3 years ago

You cannot have your behavior, how do you recall the window again? Perhaps with a global shortcut, but that is not usual behavior for a gui application.

droidmonkey commented 3 years ago

I'll reopen the request... what is the aversion to a system tray icon?

ozls commented 3 years ago

By reopening the app from an application launcher or menu. In any case, I typically need the GUI only when decrypting my database and this is prompted by my autofill plugin.

My aversion to tray icons is that I try to maintain a minimal desktop, and to only show the information I need all the time in my bar. Any computer is running a number of background processes at any given moment: I don't need to track them all by their mismatched icons if I know precisely what they are.

etosan commented 3 years ago

@droidmonkey as it seems that you reconsidered your position I will go on to clarify: it's not aversion, really.

It's just side effect of the fact, that most lightweight bars, that are used (if even) together with tilers, are really just that: lightweight.

To "normal" user they would seem spartan even. Some tiler users don't even use bars.

Many tiling wm users pick such wms up because of perceived efficiency (at least I do), so missing systray is not seen as much of a problem as is waste of screen space, and systray often wastes precious screen space (even if collapsible).

More over, many of these light bars are pixel high only just enough, to fit window title/"buttons" of custom texts, so there is not even space for systray. Even if there was space for systray, source code wise, LOC count of many of these bars, is microscopic. Like they are under 1k LOC small, so they are really really tiny.

From research I did so far, it seems systray implementation under X is relatively complex and that often means it's way over code size budget of most of these lightweight tiler friendly bars.

Other very important factor is, that tiler users often have extremely powerful and often fully scriptable keybinding engines at their disposal. Either one that is embedded right into their WM or through separate, companion shortcut handling daemon.

I was studying ksnip for a while, because it seems to be working pretty well for me (there are some edges but so far it works quite well alongside a tiler). It somehow is able to close window yet remain running with tabs and all the other state preserved. When run from terminal, one can see that process does not exit when the window is closed, and this makes it possible to have ksnip supervised as user service even (and this is tangentially related to this issue too). Thus in my environment I spawn ksnip from my service supervisor (you can think of it as service manager), and since then it's running, invisible, ready to handle screenshotting requests.

Now here comes the question of activation. At first I just used ksnip's buit-in shortcuts, but later I found out that I can tell it an action I want it to perform using command line options. So I unbound all internal shortcuts in ksnip and bound them as cli commands to my wm instead. Then I instructed ksnip to not capture screenshot and to not spawn window on normal startup (this makes it capture screenshots only on specific requests: like with -r option (capture rectangle)). Single example is worth more than thousand words:

: hc list_keybinds  | ag ksnip
Mod4+Print spawn    ksnip -r   # starts rectangle selection screenshot
Mod4+Shift+Print spawn ksnip   # just respawns window, reactivating "closed" UI

Ksnip seems to be using single instance feature of QT somehow, and when invoked second time(!) alongside of already running instance(!), it will "reactivate" this instance instead. Even if main editing window was closed in the mean time, when wm's spawn command is executed, it will pop back-in into the frame.

This makes it possible to use it even without systray. Systray is not needed because of combination of two factors: external invocations using wm keybinds and, in my case, of service supervision. This works as supervisor software always makes sure that ksnip is running.

Not all users might be using supervision software like I do, but almost all users have systemd user instance service manager, their DE builtin "autorun" mangers, or plethora of other tools at their disposal. In the worst case of startx/.xinitrc users adding these lines in .xinitrc would achieve the same:

: cat .xinitrc
...
ksnip &
keepassxc &
...
exec start-my-de-session

Hope this answers majority of your questions about usage without systray and expected reasonable behaviour.

EDIT:

Since I asked ksnip author how he does the hiding, here is the relevant code in ksnip that he linked: https://github.com/ksnip/ksnip/blob/master/src/gui/widgetHider/WidgetHider.cpp

As minimize action is ignored in my wm of choice, I guess opacity "trick" paired with setWindowState(Qt::WindowActive); is achieving the observed behaviour. Maybe it might prove helpful for keepass too, should you decide to implement it as well.

etosan commented 3 years ago

Recently my tiling window manager grew up a proper support for minimization but I haven't had time to update it yet right away.

This weekend I updated and after switching the radiobutton to 'Minimize' under checkbox with label 'Minimize when copying to clipboard window' and checkbox with label 'Minimize instead of app exit', I am able to minimize it successfully in all cases I care about.

Now, I can also bring GUI back to front by running keepassxc executable from window manager bound keyboard shortcut again, but when inspecting session logs, this form of invocation still causes this warning to log:

Another instance of KeePassXC is already running.

In #5546 I asked about CLI variant having GUI reactivation support. It was said CLI variant won't ever communicate with GUI variant (for reasons I don't understand, but I am okay with the decision) and it was pointed out that #99 already covers the issue.

Now I got lost reading #99, but it seems to me, that while single instance mode was definitely implementeted and running keepassxc binary second time indeed reactivates the already running instance and brings it to foregound, do I understand correctly, that command line switch to actually tell second (invoking) instance to just bring-u[/reactivate first instance was never really implemented, and activation of first instance by second instance is just default and hardcoded action?

I tried several switches mentioned in #99, but none of those seem to exist (any such invocation stills brings first minimized keepass instance to front):

keepassxc --toggle-window
KeePassXC: Unknown option 'toggle-window'.

Please I would like to ask for implementation of this (or similar) switch to be able to get rid of message Another instance of KeePassXC is already running. every time I reactivate keepasxc instance this way from my logs.

If this request is problematic due to weak interproces communication on all keepassxc supported platforms (I am explicitly against this switch depending on DBus' presence), I am perfectly okay with just addition of --quiet switch that would keep current single instance behaviour as it is already, but would still mute the warning from second, invoking, instance.

Actually thinking about it, this would probably be probably my preferred solution, given the code changes should be least invasive.

Thank you for consideration.

etosan commented 3 years ago

Since my WM has minimization capabilities now, and is fully scriptable, I solved the issue by remembering keepassxc window ID and minimizing it and maximizing it with a hotkey. So on my side I solved this issue.

I still believe that message Another instance of KeePassXC is already running. should be muteable so I leave this issue open for now.

droidmonkey commented 1 year ago

We won't be implementing this feature request, thank you.

Doosty commented 5 months ago

I dont use a system tray and consequently cant use KeepassXC even though i'd like to. It would be amazing if we could run keepassxc in cli daemon mode in a systemd service or something, to allow the browser extension to communicate with it.

etosan commented 3 months ago

@Doosty, you can get quite far but what is currently there.

Because keepassxc team implemented window hiding I mentioned before, keepassxc GUI part can run in "daemon mode" by spawning as Type=simple service type with systemd under user session (or any other supervisor of your choice for that matter (I use s6)), given your Xorg or wayland, DE X-session manager runs before it.

You just need to check these settings in the application: image

image

image

This will start keepassxc in background and make it go to background every time you copy data from it. Method of minimisation depends on your WM /DE setup.

You can then bring the window forward by window manager scripting abilities on keystroke.


The problem that I suggested solving later in the issue is, that in some setups, singleton/single-instance detection won't work in some environment because it relies on lot of modern crap (probably dbus/windowing related stuff).

Ie. once you spawn keepassxc in a way described above, and if instance detection is broken (which is for me), the second invocation of keepasxc command spawns a new application instance instead of bringing current window forward, ie you have to use WM scripting to bring it into focus. My WM has ability to be scripted this way, but under X you can use other helpers like xdotool and wmctrl to achieve the same.

Then keepassxc package also provides keepassxc-cli tool that is able to manipulate the DB directly, unfortunately as far I know, this tool works yet again as standalone keepassxc process instance. With this tool you can script a lot of work to access passwords, but there is potential race condition when accessing DB alongside with the GUI program, as these are two distinct processes.

Finally I noticed, that for some time keepassxc provides keepassxc-proxy process which probably does part of what is wanted (it seems to hold DB open for other processes to access over socket - but I am just assuming I haven't had time for OSS last few years due to work), but might not be there either. Thus same access race conditions might apply.

All those above mentioned issues could be solved if keepassxc was split into more flexible "daemon like" architecture:

The little bit infuriating part is, that most of the groundwork is probably already done within the project (my guesstimate would be somewhere around like 60% here and there), but this would require a big refocus and some perspective and vision change to deliver.

Project supports many platforms, has lots of users and so on, and I guess it was never designed which such advanced use in mind. All that makes very complicated endeavor, especially if core team is not on board with it. Bringing it to polished 100% functionality with this advanced design, might prove really hard to justify, effectively impossible.