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

Kanata native Windows GUI tray app #990

Merged
merged 154 commits into from
May 7, 2024
Merged

Conversation

eugenesvk
Copy link
Contributor

@eugenesvk eugenesvk commented Apr 28, 2024

Describe your changes. Use imperative present tense.

Add a gui feature allowing compiling kanata as a native tray-only Windows GUI application. This greatly simplifies launching the app on startup instead of resorting to hacks like this, gets rid of the console window and also allows UIAccess to work in elevated apps.
There is a kanata-tray project which helps with the former, but doesn't allow UIAccess issue

It also supports custom icon indicator per config and per layer within the same config, as well as (re)loading configs. Other configs are passed as cli args in the .lnk file

It also supports being launched from a console as a regular cli app, so it's possible to replace the main kanata.exe with this or let it be some separate kanata-tray.exe file

It also opens an avenue to more interesting ideas, but will add those in a separate issue #991

Checklist

  • Add documentation to docs/config.adoc
    • Yes or N/A
  • Add example and basic docs to cfg_samples/kanata.kbd
    • N/A
  • Update error messages
    • Yes or N/A
  • Added tests, or did manual testing
    • Yes, manual

Copy link
Owner

@jtroo jtroo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR 🙂

Cargo.toml Outdated Show resolved Hide resolved
docs/config.adoc Outdated Show resolved Hide resolved
src/kanata/mod.rs Outdated Show resolved Hide resolved
src/kanata/windows/llhook.rs Outdated Show resolved Hide resolved
src/kanata/windows/llhook.rs Outdated Show resolved Hide resolved
EnableUIAccess/EnableUIAccess_launch.ahk Outdated Show resolved Hide resolved
parser/src/cfg/defcfg.rs Outdated Show resolved Hide resolved
parser/src/cfg/defcfg.rs Outdated Show resolved Hide resolved
assets/kanata.ico Outdated Show resolved Hide resolved
src/m_gui_win.rs Outdated Show resolved Hide resolved
@eugenesvk eugenesvk force-pushed the win_tray_icon branch 2 times, most recently from f0d809c to e8d5c6e Compare April 30, 2024 08:44
@eugenesvk
Copy link
Contributor Author

If I want to add config support for icon names for each layer (instead of duplicating layer names at the top of defcfg to define icons), so do something like
(deflayer navigation (icon "nav.png") 1 2 3 4 5) where (icon "nav.png) is optional

What's the easiest way to update the config parser? I see there is parse_layer_indexes, but that directly removes the ability to add () pairs, so should I try to adjust that and also return "icon" in another hashmap in additon to "index" for each layer name? Or something else?

@eugenesvk
Copy link
Contributor Author

eugenesvk commented May 2, 2024

I've meanwhile added a nice feature of changing icons on layer changes and a config option to allow setting icon per layer instead of per config and a config example with some icon files for illustration

cfg_samples/tray-icon/icons/1symbols.ico Outdated Show resolved Hide resolved
src/lib_main.rs Outdated Show resolved Hide resolved
parser/src/cfg/mod.rs Outdated Show resolved Hide resolved
src/kanata/mod.rs Outdated Show resolved Hide resolved
src/kanata/mod.rs Outdated Show resolved Hide resolved
parser/src/cfg/mod.rs Outdated Show resolved Hide resolved
parser/src/cfg/mod.rs Outdated Show resolved Hide resolved
@eugenesvk
Copy link
Contributor Author

idea: maybe instead of introducing a whole special 3rd item for this, should maybe the name config be converted into a list and support additonal options besides its name?
So

  • (deflayer my-layer-name ...) becomes
  • (deflayer (my-layer-name icon lyr-icon.png)...)
  • and deflayermap is already a list, so it just adds extra options

Might be more flexible in case more per-layer options are needed later?

What do you think?

@jtroo
Copy link
Owner

jtroo commented May 2, 2024

idea: maybe instead of introducing a whole special 3rd item for this, should maybe the name config be converted into a list and support additonal options besides its name? So

* `(deflayer my-layer-name ...)` becomes

* `(deflayer (my-layer-name icon lyr-icon.png)...)`

* and `deflayermap` is already a list, so it just adds extra options

Might be more flexible in case more per-layer options are needed later?

What do you think?

I like the idea. For backwards compatibility let's continue to accept an atom, and also accept a list.

src/kanata/mod.rs Outdated Show resolved Hide resolved
win_dbg_logger/Cargo.toml Outdated Show resolved Hide resolved
src/lib_main.rs Outdated Show resolved Hide resolved
src/kanata/mod.rs Outdated Show resolved Hide resolved
src/kanata/mod.rs Outdated Show resolved Hide resolved
license-tray-icons Outdated Show resolved Hide resolved
Copy link
Owner

@jtroo jtroo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nearly there, just needs some cleanup (and me reviewing AHK+gui code a bit more)

src/gui/win.rs Outdated Show resolved Hide resolved
@jtroo jtroo merged commit a41b473 into jtroo:main May 7, 2024
4 checks passed
@eugenesvk eugenesvk deleted the win_tray_icon branch May 7, 2024 09:28
@riotrah
Copy link

riotrah commented May 11, 2024

Incredible

@gerhard-h
Copy link
Contributor

tried to build the gui feature, but it failed (Windows 10)

$ cargo build  --features interception_driver --features cmd --features gui                  
   Compiling winnow v0.5.40                                                                  
   Compiling serde v1.0.197                                                                  
   Compiling interception-sys v0.1.3                                                         
   Compiling kanata v1.7.0-prerelease (C:\path\kanata)                                       
   Compiling kanata-parser v0.161.0 (C:\path\kanata\parser)                                  
   Compiling toml_edit v0.19.15                                                              
   Compiling proc-macro-crate v1.3.1                                                         
   Compiling serde_json v1.0.114                                                             
   Compiling num_enum_derive v0.6.1                                                          
   Compiling kanata-tcp-protocol v0.161.0 (C:\path\kanata\tcp_protocol)                      
   Compiling num_enum v0.6.1                                                                 
   Compiling kanata-interception v0.2.0                                                      
error[E0061]: this function takes 2 arguments but 3 arguments were supplied                  
   --> src\main_lib\win_gui.rs:161:5                                                         
    |                                                                                        
161 |     Kanata::event_loop(kanata_arc, tx, ui)?;                                           
    |     ^^^^^^^^^^^^^^^^^^               ----                                              
    |                                      | |                                               
    |                                      | unexpected argument of type `SystemTrayUi`      
    |                                      help: remove the extra argument                   
    |                                                                                        
note: associated function defined here                                                       
   --> C:\path\kanata\src\kanata\windows\interception.rs:13:12                               
    |                                                                                        
13  |     pub fn event_loop(kanata: Arc<Mutex<Self>>, tx: Sender<KeyEvent>) -> Result<()> {  
    |            ^^^^^^^^^^                                                                  
                                                                                             
For more information about this error, try `rustc --explain E0061`.                          
error: could not compile `kanata` (bin "kanata") due to 1 previous error   

without interception_driver I can build but it won't run

11:26:02.9849 [INFO] kanata v1.7.0-prerelease starting
11:26:02.9856 [INFO] using LLHOOK+SendInput for keyboard IO
11:26:02.9956 [INFO] delegating transparent keys on other layers to first defined layer
11:26:02.9957 [INFO] process unmapped keys: true
11:26:02.9962 [WARN] DANGER! cmd action is enabled.
11:26:03.0007 [INFO] config file is valid
11:26:03.0008 [INFO] Asking Windows to improve timer precision
11:26:03.0009 [INFO] Asking Windows to increase process priority
11:26:03.0010 [INFO] Sleeping for 2s. Please release all keys and don't press additional ones. Run kanata with --help to see how understand more and how to disable this sleep.
11:26:05.0073 [ERROR] Failed to build UI

@eugenesvk
Copy link
Contributor Author

this fixes the build issue, but won't work anyway since it seems that the interception variant is using its own loop instead of the NWG GUI event loop that llhook was using before I added actual gui app on top of that

So not exactly sure how to marry those two loops.

  • Maybe you could try to move the interception loop to another thread and otherwise replace it with the gui loop for the tray app to handle various windowing events?
  • Or maybe the NWG GUI loop should be copied here and the current keystroke handler should be added in

Don't have interception driver installed due to its unfortunate catastrophic failure mode, so can't test properly

@eugenesvk
Copy link
Contributor Author

eugenesvk commented May 18, 2024

Not sure about the other one, works for me™ from the current main branch also on Win10 with the same command, runs both from the terminal and on double-click (did you try double-click?).

Could you try this #1051, it doesn't paper over the original error, so instead of Failed to build UI you should get a more specific error message of where it failed

jtroo pushed a commit that referenced this pull request May 18, 2024
Previous `.context` was hiding the errors during the gui building stage,
leading to:
#990 (comment)

This fixes it and now it should bubble up the original error

(anyhow's trait isn't implemented for NWG errors, so not sure you can
conveniently chain both)
@gerhard-h
Copy link
Contributor

Thanks for the error message
ERROR] Failed to create a resource: "No module named \"kanata.exe\" in application"
I renamed kanata.exe because I wanted to keep my wintercept version.
after not renaming it works.

@rszyma
I like the gui reload feature. But I miss the pause feature from kanata-tray.exe

@eugenesvk
Copy link
Contributor Author

eugenesvk commented May 19, 2024

Think kanata doesn't support pause, also miss it #991
Here kanata is running directly, so there is no external process to pause it like in the kanata-tray

Exe renaming is fixed in #1052

And wintercept seems to be working when moved to a separate thread

@gerhard-h
Copy link
Contributor

Think kanata doesn't support pause,

kanata-tray.exe also has no pause - it has a start/stop toggel. I just called it pause.
p.s. a start/stop toggle demands for
a) an UI for command line parameters
b) capturinge and reapplying the current command line parameters on (re)start
c) both ?! (what to do if the configured parameters are different from the actual ones)

jtroo pushed a commit that referenced this pull request May 21, 2024
Allow renaming of `kanata.exe` gui app by omitting the name.

Fixes one of
#990 (comment)
jtroo pushed a commit that referenced this pull request May 25, 2024
Add Interception builds of the Windows GUI app

Fixes the other part of
#990 (comment)
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 this pull request may close these issues.

None yet

4 participants