Skip to content

[global-shortcut][v2] How to register a shortcut using tauri_plugin_global_shortcut #965

Closed

Description

@MystiPanda

During the migration process, I found that the register function in the tauri_plugin_global_shortcut plug-in does not accept the handler parameter. How can I register a shortcut key?

Thanks and looking forward to your reply:)

Activity

  1. added a commit that references this issue on Feb 19, 2024
    696af68
  2. amrbashir commented on Feb 19, 2024

    @amrbashir
    Member
  3. MystiPanda commented on Feb 19, 2024

    @MystiPanda
    Author

    emm, with all due respect, this design seems a bit counter-intuitive. Is this part of the api likely to change in the future?

  4. jasonterando commented on Feb 19, 2024

    @jasonterando

    Hi, I'm on v2.0, beta 0 for@tauri-apps/plugin-global-shortcut. When running an application with the below main(), I do see the "Setting up global shortcut" message printed, but I do not see the "Shortcut" println coming up on every hotkey-ish type of key press, and I do not (nor do I see the Ctrl-N println for that matter).

    I'm running a NextJS/React app, if that is relevant. JavaScript registrations using register still work, so I could fall back to that if necessary.

    What am I missing? Is there an additional init() like there is for other plugins?

    Thanks!

     fn main() {
        tauri::Builder::default()
            .invoke_handler(tauri::generate_handler![open_workbook, save_workbook, run_request, cancel_request, clear_cached_authorization])
            .plugin(tauri_plugin_fs::init())
            .plugin(tauri_plugin_dialog::init())
            .setup(|app| {
                #[cfg(desktop)]
                {
                  println!("Setting up global shortcut");
                  use tauri_plugin_global_shortcut::{Shortcut, Code, Modifiers};
                  let ctrl_n_shortcut = Shortcut::new(Some(Modifiers::CONTROL), Code::KeyN);
                  app.handle().plugin(
                    tauri_plugin_global_shortcut::Builder::with_handler(move |app, shortcut| {
                        println!("{:?}", shortcut);
                        if shortcut == &ctrl_n_shortcut {
                            println!("Ctrl-N Detected!");
                            app.emit_to(EventTarget::any(), "NEW",  "").unwrap()
                        }
                    })
                    .build()
                  )?;
                }
                Ok(())            
            })
            .run(tauri::generate_context!())
            .expect("error running app");
    }
    
  5. FabianLars commented on Feb 19, 2024

    @FabianLars
    Member

    emm, with all due respect, this design seems a bit counter-intuitive. Is this part of the api likely to change in the future?

    Anything specific that triggers you? Or even better, any ideas how to improve it? Afaik we don't really have any changes planned, but we still can do it while it's still in beta.

  6. amrbashir commented on Feb 19, 2024

    @amrbashir
    Member

    @jasonterando I have updated the example, I forgot to add the registering code

     fn main() {
        tauri::Builder::default()
            .invoke_handler(tauri::generate_handler![open_workbook, save_workbook, run_request, cancel_request, clear_cached_authorization])
            .plugin(tauri_plugin_fs::init())
            .plugin(tauri_plugin_dialog::init())
            .setup(|app| {
                #[cfg(desktop)]
                {
                  println!("Setting up global shortcut");
    -             use tauri_plugin_global_shortcut::{Shortcut, Code, Modifiers};
    +             use tauri_plugin_global_shortcut::{Shortcut, Code, Modifiers, GlobalShortcutExt};
                  let ctrl_n_shortcut = Shortcut::new(Some(Modifiers::CONTROL), Code::KeyN);
                  app.handle().plugin(
                    tauri_plugin_global_shortcut::Builder::with_handler(move |app, shortcut| {
                        println!("{:?}", shortcut);
                        if shortcut == &ctrl_n_shortcut {
                            println!("Ctrl-N Detected!");
                            app.emit_to(EventTarget::any(), "NEW",  "").unwrap()
                        }
                    })
                    .build()
                  )?;
    +             app.global_shorcut().register(ctrl_n_shortcut )?;
                }
                Ok(())            
            })
            .run(tauri::generate_context!())
            .expect("error running app");
    }
  7. amrbashir commented on Feb 19, 2024

    @amrbashir
    Member

    emm, with all due respect, this design seems a bit counter-intuitive. Is this part of the api likely to change in the future?

    As fabian said, we are open to suggestions and nothing is set to stone just yet

  8. MystiPanda commented on Feb 19, 2024

    @MystiPanda
    Author

    @FabianLars @amrbashir Sorry, I just saw your reply, Thank you for your replies. What I am building now is an application that can run in the background, that is, it will still run in the background after closing the last window. This application allows users to customize a series of global shortcut keys that need to be bound. A rust function to perform some system-level operations, such as opening/closing the system proxy, so I cannot complete the shortcut key binding operation in the js code. However, based on the current interface design, I want to implement this in rust It seems to be very difficult to customize the shortcut key function. In my opinion, it would be great if the rust api of the shortcut key plug-in can be as concise and easy to use as the js api, just like the v1 version, at least js and rust can look at the code logic. It is a unified way of use.

    The use cases I am talking about should be more common usage in desktop software, not special cases of individual software, so I hope you can take its application scenarios into consideration when designing the API.

  9. amrbashir commented on Feb 19, 2024

    @amrbashir
    Member

    I think we can do something like this (while keeping the current API as well)

    app.global_shortcut().register_with_handler(shortcut, |app| {
      // shortcut triggered
    });
  10. MystiPanda commented on Feb 19, 2024

    @MystiPanda
    Author

    I noticed that there is still an exposed register function, but it does not accept the handler parameter. I am confused about what this function is used for now.

  11. MystiPanda commented on Feb 19, 2024

    @MystiPanda
    Author

    I think we can do something like this (while keeping the current API as well)

    app.global_shortcut().register_with_handler(shortcut, |app| {
      // shortcut triggered
    });

    This looks good for me.

  12. amrbashir commented on Feb 19, 2024

    @amrbashir
    Member

    I noticed that there is still an exposed register function, but it does not accept the handler parameter. I am confused about what this function is used for now.

    The function is used to register a shortcut that will be catched by the handler passed to tauri_plugin_global_shortcut::Builder::with_handler

  13. MystiPanda commented on Feb 19, 2024

    @MystiPanda
    Author

    I noticed that there is still an exposed register function, but it does not accept the handler parameter. I am confused about what this function is used for now.

    The function is used to register a shortcut that will be catched by the handler passed to tauri_plugin_global_shortcut::Builder::with_handler

    So did you forget to call the register function in your example?

  14. amrbashir commented on Feb 19, 2024

    @amrbashir
    Member

    yeah, I updated the example.

  15. MystiPanda commented on Feb 19, 2024

    @MystiPanda
    Author

    Oh, I just saw your reply above. I have no other questions. The regiater_with_handler proposal you mentioned is great.

    Thank you for your patience, and thank you for your hard work:)

  16. jasonterando commented on Feb 19, 2024

    @jasonterando

    Thanks @amrbashir - getting closer :) If I try doing a doing an app.emit or app.emit_to from within the "with_handler", I get the following error, which is hitting the boundary of my meager (but growing) Rust knowledge. Can you give me an idea of what I'm doing wrong? Thanks!

            .setup(|app| {
                #[cfg(desktop)]
                {
                    use tauri_plugin_global_shortcut::{Code, GlobalShortcutExt, Modifiers, Shortcut};
    
                    let ctrl_n_shortcut = Shortcut::new(Some(Modifiers::CONTROL), Code::KeyN);
                    app.handle().plugin(
                        tauri_plugin_global_shortcut::Builder::with_handler(move |_app, shortcut| {
                            println!("{:?}", shortcut);
                            if shortcut == &ctrl_n_shortcut {
                                println!("Ctrl-N Detected!");
                                app.emit("new", "").unwrap()
                                // app.emit_to(EventTarget::any(), "new",  "").unwrap()
                            }
                        })
                        .build(),
                    )?;
    
                    app.global_shortcut().register(ctrl_n_shortcut)?;
                }
    `(dyn for<'a> FnOnce(&'a mut tauri::App) -> Result<(), Box<(dyn std::error::Error + 'static)>> + Send + 'static)` cannot be shared between threads safely
    the trait `Sync` is not implemented for `(dyn for<'a> FnOnce(&'a mut tauri::App) -> Result<(), Box<(dyn std::error::Error + 'static)>> + Send + 'static)`
    required for `Unique<(dyn for<'a> FnOnce(&'a mut tauri::App) -> Result<(), Box<(dyn std::error::Error + 'static)>> + Send + 'static)>` to implement `Sync`
    required because it appears within the type `&mut App`
    
  17. amrbashir commented on Feb 19, 2024

    @amrbashir
    Member

    App is not Send or Sync and you need to get a handle to it instead

       .setup(|app| {
                #[cfg(desktop)]
                {
                    use tauri_plugin_global_shortcut::{Code, GlobalShortcutExt, Modifiers, Shortcut};
    
                    let ctrl_n_shortcut = Shortcut::new(Some(Modifiers::CONTROL), Code::KeyN);
    +               let handle = app.handle().clone();
                    app.handle().plugin(
                        tauri_plugin_global_shortcut::Builder::with_handler(move |_app, shortcut| {
                            println!("{:?}", shortcut);
                            if shortcut == &ctrl_n_shortcut {
                                println!("Ctrl-N Detected!");
    -                           app.emit("new", "").unwrap()
    +                           handle.emit("new", "").unwrap()
                                // app.emit_to(EventTarget::any(), "new",  "").unwrap()
                            }
                        })
                        .build(),
                    )?;
    
                    app.global_shortcut().register(ctrl_n_shortcut)?;
                }
  18. amrbashir commented on Feb 19, 2024

    @amrbashir
    Member

    PR for the new API #969

  19. jasonterando commented on Feb 19, 2024

    @jasonterando

    @amrbashir - My Hero, thanks! I imagine doing an "emit" from the handler would be a pretty common use case, it may be worthwhile including that in the updated example, if you haven't already.

  20. amrbashir commented on Feb 19, 2024

    @amrbashir
    Member

    will do

  21. added a commit that references this issue on Feb 20, 2024
    4cdb34d
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions