First draft of context menu handling on Windows
This commit is contained in:
parent
567c35eb0e
commit
65f9811db3
186
Cargo.lock
generated
186
Cargo.lock
generated
|
@ -1,5 +1,15 @@
|
||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
|
[[package]]
|
||||||
|
name = "anyhow"
|
||||||
|
version = "1.0.38"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.66"
|
version = "1.0.66"
|
||||||
|
@ -10,6 +20,18 @@ name = "cfg-if"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chrono"
|
||||||
|
version = "0.4.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"libc 0.2.84 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-integer 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-traits 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"time 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "enum-as-inner"
|
name = "enum-as-inner"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
|
@ -28,6 +50,7 @@ dependencies = [
|
||||||
"espanso-detect 0.1.0",
|
"espanso-detect 0.1.0",
|
||||||
"espanso-ui 0.1.0",
|
"espanso-ui 0.1.0",
|
||||||
"maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"simplelog 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -45,9 +68,13 @@ dependencies = [
|
||||||
name = "espanso-ui"
|
name = "espanso-ui"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anyhow 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cc 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cc 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lazycell 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazycell 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde 1.0.123 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde_json 1.0.61 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"thiserror 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"widestring 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"widestring 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -59,11 +86,21 @@ dependencies = [
|
||||||
"unicode-segmentation 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicode-segmentation 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "0.4.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazycell"
|
name = "lazycell"
|
||||||
version = "1.3.0"
|
version = "1.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.84"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.14"
|
version = "0.4.14"
|
||||||
|
@ -77,6 +114,23 @@ name = "maplit"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-integer"
|
||||||
|
version = "0.1.44"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-traits 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.24"
|
version = "1.0.24"
|
||||||
|
@ -93,6 +147,49 @@ dependencies = [
|
||||||
"proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
"proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ryu"
|
||||||
|
version = "1.0.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.123"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive 1.0.123 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.123"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syn 1.0.60 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.61"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"itoa 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"ryu 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde 1.0.123 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "simplelog"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"chrono 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"log 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"termcolor 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.60"
|
version = "1.0.60"
|
||||||
|
@ -103,6 +200,42 @@ dependencies = [
|
||||||
"unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "termcolor"
|
||||||
|
version = "1.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "1.0.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "1.0.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syn 1.0.60 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time"
|
||||||
|
version = "0.1.44"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"libc 0.2.84 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"wasi 0.10.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-segmentation"
|
name = "unicode-segmentation"
|
||||||
version = "1.7.1"
|
version = "1.7.1"
|
||||||
|
@ -113,22 +246,75 @@ name = "unicode-xid"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.10.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "widestring"
|
name = "widestring"
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-util"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
|
"checksum anyhow 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1"
|
||||||
|
"checksum autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||||
"checksum cc 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)" = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
|
"checksum cc 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)" = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
|
||||||
"checksum cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
"checksum cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
"checksum chrono 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)" = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
|
||||||
"checksum enum-as-inner 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7c5f0096a91d210159eceb2ff5e1c4da18388a170e1e3ce948aac9c8fdbbf595"
|
"checksum enum-as-inner 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7c5f0096a91d210159eceb2ff5e1c4da18388a170e1e3ce948aac9c8fdbbf595"
|
||||||
"checksum heck 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac"
|
"checksum heck 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac"
|
||||||
|
"checksum itoa 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
|
||||||
"checksum lazycell 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
"checksum lazycell 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
||||||
|
"checksum libc 0.2.84 (registry+https://github.com/rust-lang/crates.io-index)" = "1cca32fa0182e8c0989459524dc356b8f2b5c10f1b9eb521b7d182c03cf8c5ff"
|
||||||
"checksum log 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
"checksum log 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
||||||
"checksum maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
|
"checksum maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
|
||||||
|
"checksum num-integer 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
|
||||||
|
"checksum num-traits 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
||||||
"checksum proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
|
"checksum proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
|
||||||
"checksum quote 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df"
|
"checksum quote 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df"
|
||||||
|
"checksum ryu 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
|
||||||
|
"checksum serde 1.0.123 (registry+https://github.com/rust-lang/crates.io-index)" = "92d5161132722baa40d802cc70b15262b98258453e85e5d1d365c757c73869ae"
|
||||||
|
"checksum serde_derive 1.0.123 (registry+https://github.com/rust-lang/crates.io-index)" = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31"
|
||||||
|
"checksum serde_json 1.0.61 (registry+https://github.com/rust-lang/crates.io-index)" = "4fceb2595057b6891a4ee808f70054bd2d12f0e97f1cbb78689b59f676df325a"
|
||||||
|
"checksum simplelog 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4bc0ffd69814a9b251d43afcabf96dad1b29f5028378056257be9e3fecc9f720"
|
||||||
"checksum syn 1.0.60 (registry+https://github.com/rust-lang/crates.io-index)" = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081"
|
"checksum syn 1.0.60 (registry+https://github.com/rust-lang/crates.io-index)" = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081"
|
||||||
|
"checksum termcolor 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
|
||||||
|
"checksum thiserror 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)" = "76cc616c6abf8c8928e2fdcc0dbfab37175edd8fb49a4641066ad1364fdab146"
|
||||||
|
"checksum thiserror-impl 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9be73a2caec27583d0046ef3796c3794f868a5bc813db689eed00c7631275cd1"
|
||||||
|
"checksum time 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
|
||||||
"checksum unicode-segmentation 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
|
"checksum unicode-segmentation 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
|
||||||
"checksum unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
|
"checksum unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
|
||||||
|
"checksum wasi 0.10.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
||||||
"checksum widestring 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c"
|
"checksum widestring 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c"
|
||||||
|
"checksum winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||||
|
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
"checksum winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||||
|
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
|
@ -7,6 +7,10 @@ build="build.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
|
serde_json = "1.0.61"
|
||||||
|
serde = { version = "1.0.123", features = ["derive"] }
|
||||||
|
anyhow = "1.0.38"
|
||||||
|
thiserror = "1.0.23"
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
widestring = "0.4.3"
|
widestring = "0.4.3"
|
||||||
|
|
|
@ -25,6 +25,7 @@ fn cc_config() {
|
||||||
.cpp(true)
|
.cpp(true)
|
||||||
.include("src/win32/native.h")
|
.include("src/win32/native.h")
|
||||||
.include("src/win32/WinToast/wintoastlib.h")
|
.include("src/win32/WinToast/wintoastlib.h")
|
||||||
|
.include("src/win32/json/json.hpp")
|
||||||
.file("src/win32/native.cpp")
|
.file("src/win32/native.cpp")
|
||||||
.file("src/win32/WinToast/wintoastlib.cpp")
|
.file("src/win32/WinToast/wintoastlib.cpp")
|
||||||
.compile("espansoui");
|
.compile("espansoui");
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
pub mod menu;
|
||||||
pub mod event;
|
pub mod event;
|
||||||
pub mod icons;
|
pub mod icons;
|
||||||
|
|
||||||
|
|
203
espanso-ui/src/menu.rs
Normal file
203
espanso-ui/src/menu.rs
Normal file
|
@ -0,0 +1,203 @@
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Menu {
|
||||||
|
items: Vec<MenuItem>,
|
||||||
|
|
||||||
|
// Mapping between the raw numeric ids and string ids
|
||||||
|
raw_ids: HashMap<u32, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Menu {
|
||||||
|
pub fn from(mut items: Vec<MenuItem>) -> Result<Self> {
|
||||||
|
// Generate the raw ids, also checking for duplicate ids
|
||||||
|
let mut raw_ids: HashMap<u32, String> = HashMap::new();
|
||||||
|
let mut ids: HashSet<String> = HashSet::new();
|
||||||
|
let mut current = 0;
|
||||||
|
for item in items.iter_mut() {
|
||||||
|
Self::generate_raw_id(&mut raw_ids, &mut ids, &mut current, item)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Self { items, raw_ids })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_json(&self) -> Result<String> {
|
||||||
|
Ok(serde_json::to_string(&self.items)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_item_id(&self, raw_id: u32) -> Option<String> {
|
||||||
|
self.raw_ids.get(&raw_id).cloned()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_raw_id(raw_ids: &mut HashMap<u32, String>, ids: &mut HashSet<String>, current: &mut u32, item: &mut MenuItem) -> Result<()> {
|
||||||
|
match item {
|
||||||
|
MenuItem::Simple(simple_item) => {
|
||||||
|
if ids.contains::<str>(&simple_item.id) { // Duplicate id, throw error
|
||||||
|
Err(MenuError::DuplicateMenuId(simple_item.id.to_string()).into())
|
||||||
|
} else {
|
||||||
|
ids.insert(simple_item.id.to_string());
|
||||||
|
raw_ids.insert(*current, simple_item.id.to_string());
|
||||||
|
simple_item.raw_id = Some(*current);
|
||||||
|
*current += 1;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MenuItem::Sub(SubMenuItem { items, ..}) => {
|
||||||
|
for sub_item in items.iter_mut() {
|
||||||
|
Self::generate_raw_id(raw_ids, ids, current, sub_item)?
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
MenuItem::Separator => Ok(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
pub enum MenuError {
|
||||||
|
#[error("json serialization error")]
|
||||||
|
Serialization(#[from] serde_json::Error),
|
||||||
|
|
||||||
|
#[error("two or more menu items share the same id")]
|
||||||
|
DuplicateMenuId(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
#[serde(tag = "type")]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub enum MenuItem {
|
||||||
|
Simple(SimpleMenuItem),
|
||||||
|
Sub(SubMenuItem),
|
||||||
|
Separator,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct SimpleMenuItem {
|
||||||
|
id: String,
|
||||||
|
label: String,
|
||||||
|
raw_id: Option<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SimpleMenuItem {
|
||||||
|
pub fn new(id: &str, label: &str) -> Self {
|
||||||
|
Self {
|
||||||
|
id: id.to_string(),
|
||||||
|
label: label.to_string(),
|
||||||
|
raw_id: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct SubMenuItem {
|
||||||
|
label: String,
|
||||||
|
items: Vec<MenuItem>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SubMenuItem {
|
||||||
|
pub fn new(label: &str, items: Vec<MenuItem>) -> Self {
|
||||||
|
Self {
|
||||||
|
label: label.to_string(),
|
||||||
|
items,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_context_menu_serializes_correctly() {
|
||||||
|
let menu = Menu::from(vec![
|
||||||
|
MenuItem::Simple(SimpleMenuItem::new(
|
||||||
|
"open",
|
||||||
|
"Open",
|
||||||
|
)),
|
||||||
|
MenuItem::Separator,
|
||||||
|
MenuItem::Sub(SubMenuItem::new(
|
||||||
|
"Sub",
|
||||||
|
vec![
|
||||||
|
MenuItem::Simple(SimpleMenuItem::new(
|
||||||
|
"sub1",
|
||||||
|
"Sub 1",
|
||||||
|
)),
|
||||||
|
MenuItem::Simple(SimpleMenuItem::new(
|
||||||
|
"sub2",
|
||||||
|
"Sub 2",
|
||||||
|
)),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
]).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
menu.to_json().unwrap(),
|
||||||
|
r#"[{"type":"simple","id":"open","label":"Open","raw_id":0},{"type":"separator"},{"type":"sub","label":"Sub","items":[{"type":"simple","id":"sub1","label":"Sub 1","raw_id":1},{"type":"simple","id":"sub2","label":"Sub 2","raw_id":2}]}]"#
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_context_menu_raw_ids_work_correctly() {
|
||||||
|
let menu = Menu::from(vec![
|
||||||
|
MenuItem::Simple(SimpleMenuItem::new(
|
||||||
|
"open",
|
||||||
|
"Open",
|
||||||
|
)),
|
||||||
|
MenuItem::Separator,
|
||||||
|
MenuItem::Sub(SubMenuItem::new(
|
||||||
|
"Sub",
|
||||||
|
vec![
|
||||||
|
MenuItem::Simple(SimpleMenuItem::new(
|
||||||
|
"sub1",
|
||||||
|
"Sub 1",
|
||||||
|
)),
|
||||||
|
MenuItem::Simple(SimpleMenuItem::new(
|
||||||
|
"sub2",
|
||||||
|
"Sub 2",
|
||||||
|
)),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
]).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
menu.get_item_id(0).unwrap(),
|
||||||
|
"open"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
menu.get_item_id(1).unwrap(),
|
||||||
|
"sub1"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
menu.get_item_id(2).unwrap(),
|
||||||
|
"sub2"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_context_menu_detects_duplicate_ids() {
|
||||||
|
let menu = Menu::from(vec![
|
||||||
|
MenuItem::Simple(SimpleMenuItem::new(
|
||||||
|
"open",
|
||||||
|
"Open",
|
||||||
|
)),
|
||||||
|
MenuItem::Separator,
|
||||||
|
MenuItem::Sub(SubMenuItem::new(
|
||||||
|
"Sub",
|
||||||
|
vec![
|
||||||
|
MenuItem::Simple(SimpleMenuItem::new(
|
||||||
|
"open",
|
||||||
|
"Sub 1",
|
||||||
|
)),
|
||||||
|
MenuItem::Simple(SimpleMenuItem::new(
|
||||||
|
"sub2",
|
||||||
|
"Sub 2",
|
||||||
|
)),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
assert!(matches!(menu.unwrap_err().downcast::<MenuError>().unwrap(),
|
||||||
|
MenuError::DuplicateMenuId(id) if id == "open"));
|
||||||
|
}
|
||||||
|
}
|
25447
espanso-ui/src/win32/json/json.hpp
Normal file
25447
espanso-ui/src/win32/json/json.hpp
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -17,16 +17,23 @@
|
||||||
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use std::{cmp::min, collections::HashMap, ffi::c_void, sync::{
|
use std::{
|
||||||
|
cmp::min,
|
||||||
|
collections::HashMap,
|
||||||
|
ffi::{c_void, CString},
|
||||||
|
os::raw::c_char,
|
||||||
|
sync::{
|
||||||
atomic::{AtomicPtr, Ordering},
|
atomic::{AtomicPtr, Ordering},
|
||||||
Arc,
|
Arc,
|
||||||
}, thread::ThreadId};
|
},
|
||||||
|
thread::ThreadId,
|
||||||
|
};
|
||||||
|
|
||||||
use lazycell::LazyCell;
|
use lazycell::LazyCell;
|
||||||
use log::{error, trace};
|
use log::{error, trace};
|
||||||
use widestring::{WideCString};
|
use widestring::WideCString;
|
||||||
|
|
||||||
use crate::{event::UIEvent, icons::TrayIcon};
|
use crate::{event::UIEvent, icons::TrayIcon, menu::Menu};
|
||||||
|
|
||||||
// IMPORTANT: if you change these, also edit the native.h file.
|
// IMPORTANT: if you change these, also edit the native.h file.
|
||||||
const MAX_FILE_PATH: usize = 260;
|
const MAX_FILE_PATH: usize = 260;
|
||||||
|
@ -66,6 +73,7 @@ extern "C" {
|
||||||
pub fn ui_destroy(window_handle: *const c_void) -> i32;
|
pub fn ui_destroy(window_handle: *const c_void) -> i32;
|
||||||
pub fn ui_update_tray_icon(window_handle: *const c_void, index: i32);
|
pub fn ui_update_tray_icon(window_handle: *const c_void, index: i32);
|
||||||
pub fn ui_show_notification(window_handle: *const c_void, message: *const u16);
|
pub fn ui_show_notification(window_handle: *const c_void, message: *const u16);
|
||||||
|
pub fn ui_show_context_menu(window_handle: *const c_void, payload: *const c_char);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Win32UIOptions<'a> {
|
pub struct Win32UIOptions<'a> {
|
||||||
|
@ -142,14 +150,16 @@ impl Win32EventLoop {
|
||||||
let mut icon_paths: [[u16; MAX_FILE_PATH]; MAX_ICON_COUNT] =
|
let mut icon_paths: [[u16; MAX_FILE_PATH]; MAX_ICON_COUNT] =
|
||||||
[[0; MAX_FILE_PATH]; MAX_ICON_COUNT];
|
[[0; MAX_FILE_PATH]; MAX_ICON_COUNT];
|
||||||
for (i, icon_path) in icon_paths.iter_mut().enumerate().take(self.icons.len()) {
|
for (i, icon_path) in icon_paths.iter_mut().enumerate().take(self.icons.len()) {
|
||||||
let wide_path = WideCString::from_str(&self.icons[i]).expect("Error while converting icon to wide string");
|
let wide_path =
|
||||||
|
WideCString::from_str(&self.icons[i]).expect("Error while converting icon to wide string");
|
||||||
let len = min(wide_path.len(), MAX_FILE_PATH - 1);
|
let len = min(wide_path.len(), MAX_FILE_PATH - 1);
|
||||||
icon_path[0..len].clone_from_slice(&wide_path.as_slice()[..len]);
|
icon_path[0..len].clone_from_slice(&wide_path.as_slice()[..len]);
|
||||||
// TODO: test overflow, correct case
|
// TODO: test overflow, correct case
|
||||||
}
|
}
|
||||||
|
|
||||||
let wide_notification_icon_path =
|
let wide_notification_icon_path =
|
||||||
widestring::WideCString::from_str(&self.notification_icon_path).expect("Error while converting notification icon to wide string");
|
widestring::WideCString::from_str(&self.notification_icon_path)
|
||||||
|
.expect("Error while converting notification icon to wide string");
|
||||||
let mut wide_notification_icon_path_buffer: [u16; MAX_FILE_PATH] = [0; MAX_FILE_PATH];
|
let mut wide_notification_icon_path_buffer: [u16; MAX_FILE_PATH] = [0; MAX_FILE_PATH];
|
||||||
wide_notification_icon_path_buffer[..wide_notification_icon_path.as_slice().len()]
|
wide_notification_icon_path_buffer[..wide_notification_icon_path.as_slice().len()]
|
||||||
.clone_from_slice(wide_notification_icon_path.as_slice());
|
.clone_from_slice(wide_notification_icon_path.as_slice());
|
||||||
|
@ -279,7 +289,34 @@ impl Win32Remote {
|
||||||
match wide_message {
|
match wide_message {
|
||||||
Ok(wide_message) => unsafe { ui_show_notification(handle, wide_message.as_ptr()) },
|
Ok(wide_message) => unsafe { ui_show_notification(handle, wide_message.as_ptr()) },
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
error!("Unable to show notification, invalid message encoding {}", error);
|
error!(
|
||||||
|
"Unable to show notification, invalid message encoding {}",
|
||||||
|
error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn show_context_menu(&self, menu: &Menu) {
|
||||||
|
let handle = self.handle.load(Ordering::Acquire);
|
||||||
|
if handle.is_null() {
|
||||||
|
error!("Unable to show context menu, pointer is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
match menu.to_json() {
|
||||||
|
Ok(payload) => {
|
||||||
|
let c_string = CString::new(payload);
|
||||||
|
match c_string {
|
||||||
|
Ok(c_string) => unsafe { ui_show_context_menu(handle, c_string.as_ptr()) },
|
||||||
|
Err(error) => error!(
|
||||||
|
"Unable to show context menu, impossible to convert payload to c_string: {}",
|
||||||
|
error
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(error) => {
|
||||||
|
error!("Unable to show context menu, {}", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,9 @@
|
||||||
#include "WinToast/wintoastlib.h"
|
#include "WinToast/wintoastlib.h"
|
||||||
using namespace WinToastLib;
|
using namespace WinToastLib;
|
||||||
|
|
||||||
|
#include "json/json.hpp"
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
#define APPWM_ICON_CLICK (WM_APP + 1)
|
#define APPWM_ICON_CLICK (WM_APP + 1)
|
||||||
#define APPWM_SHOW_CONTEXT_MENU (WM_APP + 2)
|
#define APPWM_SHOW_CONTEXT_MENU (WM_APP + 2)
|
||||||
#define APPWM_UPDATE_TRAY_ICON (WM_APP + 3)
|
#define APPWM_UPDATE_TRAY_ICON (WM_APP + 3)
|
||||||
|
@ -111,6 +114,7 @@ LRESULT CALLBACK ui_window_procedure(HWND window, unsigned int msg, WPARAM wp, L
|
||||||
if (flags == 0)
|
if (flags == 0)
|
||||||
{
|
{
|
||||||
std::cout << "click menu" << std::flush;
|
std::cout << "click menu" << std::flush;
|
||||||
|
// TODO: click
|
||||||
//context_menu_click_callback(manager_instance, (int32_t)idItem);
|
//context_menu_click_callback(manager_instance, (int32_t)idItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,27 +122,12 @@ LRESULT CALLBACK ui_window_procedure(HWND window, unsigned int msg, WPARAM wp, L
|
||||||
}
|
}
|
||||||
case APPWM_SHOW_CONTEXT_MENU: // Request to show context menu
|
case APPWM_SHOW_CONTEXT_MENU: // Request to show context menu
|
||||||
{
|
{
|
||||||
HMENU hPopupMenu = CreatePopupMenu();
|
HMENU menu = (HMENU)lp;
|
||||||
|
POINT pt;
|
||||||
|
GetCursorPos(&pt);
|
||||||
|
SetForegroundWindow(window);
|
||||||
|
TrackPopupMenu(menu, TPM_BOTTOMALIGN | TPM_LEFTALIGN, pt.x, pt.y, 0, window, NULL);
|
||||||
|
|
||||||
// Create the menu
|
|
||||||
|
|
||||||
/*
|
|
||||||
int32_t count = static_cast<int32_t>(lp);
|
|
||||||
std::unique_ptr<MenuItem[]> items(reinterpret_cast<MenuItem*>(wp));
|
|
||||||
|
|
||||||
for (int i = 0; i<count; i++) {
|
|
||||||
if (items[i].type == 1) {
|
|
||||||
InsertMenu(hPopupMenu, i, MF_BYPOSITION | MF_STRING, items[i].id, items[i].name);
|
|
||||||
}else{
|
|
||||||
InsertMenu(hPopupMenu, i, MF_BYPOSITION | MF_SEPARATOR, items[i].id, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
POINT pt;
|
|
||||||
GetCursorPos(&pt);
|
|
||||||
SetForegroundWindow(nw);
|
|
||||||
TrackPopupMenu(hPopupMenu, TPM_BOTTOMALIGN | TPM_LEFTALIGN, pt.x, pt.y, 0, nw, NULL);
|
|
||||||
*/
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case APPWM_UPDATE_TRAY_ICON: // Request to update the tray icon
|
case APPWM_UPDATE_TRAY_ICON: // Request to update the tray icon
|
||||||
|
@ -288,7 +277,7 @@ void *ui_initialize(void *_self, UIOptions _options, int32_t *error_code)
|
||||||
|
|
||||||
// Initialize the notification handler
|
// Initialize the notification handler
|
||||||
WinToast::instance()->setAppName(L"Espanso");
|
WinToast::instance()->setAppName(L"Espanso");
|
||||||
const auto aumi = WinToast::configureAUMI(L"federico.terzi", L"Espanso", L"Espanso", L"1.0.0");
|
const auto aumi = WinToast::configureAUMI(L"federico.terzi", L"Espanso", L"Core", L"1.0.0");
|
||||||
WinToast::instance()->setAppUserModelId(aumi);
|
WinToast::instance()->setAppUserModelId(aumi);
|
||||||
if (!WinToast::instance()->initialize())
|
if (!WinToast::instance()->initialize())
|
||||||
{
|
{
|
||||||
|
@ -342,3 +331,68 @@ int32_t ui_show_notification(void *window, wchar_t *message)
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Menu related methods
|
||||||
|
|
||||||
|
void _insert_separator_menu(HMENU parent)
|
||||||
|
{
|
||||||
|
InsertMenu(parent, -1, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _insert_single_menu(HMENU parent, json item)
|
||||||
|
{
|
||||||
|
if (!item["label"].is_string() || !item["raw_id"].is_number())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::string label = item["label"];
|
||||||
|
uint32_t raw_id = item["raw_id"];
|
||||||
|
|
||||||
|
// Convert to wide chars
|
||||||
|
std::wstring wide_label(label.length(), L'#');
|
||||||
|
mbstowcs(&wide_label[0], label.c_str(), label.length());
|
||||||
|
|
||||||
|
InsertMenu(parent, -1, MF_BYPOSITION | MF_STRING, raw_id, wide_label.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void _insert_sub_menu(HMENU parent, json items)
|
||||||
|
{
|
||||||
|
for (auto &item : items)
|
||||||
|
{
|
||||||
|
if (item["type"] == "simple")
|
||||||
|
{
|
||||||
|
_insert_single_menu(parent, item);
|
||||||
|
}
|
||||||
|
else if (item["type"] == "separator")
|
||||||
|
{
|
||||||
|
_insert_separator_menu(parent);
|
||||||
|
}
|
||||||
|
else if (item["type"] == "sub")
|
||||||
|
{
|
||||||
|
HMENU subMenu = CreatePopupMenu();
|
||||||
|
std::string label = item["label"];
|
||||||
|
|
||||||
|
// Convert to wide chars
|
||||||
|
std::wstring wide_label(label.length(), L'#');
|
||||||
|
mbstowcs(&wide_label[0], label.c_str(), label.length());
|
||||||
|
|
||||||
|
InsertMenu(parent, -1, MF_BYPOSITION | MF_POPUP, (UINT_PTR)subMenu, wide_label.c_str());
|
||||||
|
_insert_sub_menu(subMenu, item["items"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t ui_show_context_menu(void *window, char *payload)
|
||||||
|
{
|
||||||
|
if (window)
|
||||||
|
{
|
||||||
|
auto j_menu = json::parse(payload);
|
||||||
|
// Generate the menu from the JSON payload
|
||||||
|
HMENU parentMenu = CreatePopupMenu();
|
||||||
|
_insert_sub_menu(parentMenu, j_menu);
|
||||||
|
|
||||||
|
PostMessage((HWND)window, APPWM_SHOW_CONTEXT_MENU, 0, (LPARAM)parentMenu);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
|
@ -60,4 +60,9 @@ extern "C" void ui_update_tray_icon(void * window, int32_t index);
|
||||||
// Show a native Windows 10 notification
|
// Show a native Windows 10 notification
|
||||||
extern "C" int32_t ui_show_notification(void * window, wchar_t * message);
|
extern "C" int32_t ui_show_notification(void * window, wchar_t * message);
|
||||||
|
|
||||||
|
// Display the context menu on the tray icon.
|
||||||
|
// Payload is passed as JSON as given the complex structure, parsing
|
||||||
|
// this manually would have been complex.
|
||||||
|
extern "C" int32_t ui_show_context_menu(void * window, char * payload);
|
||||||
|
|
||||||
#endif //ESPANSO_UI_H
|
#endif //ESPANSO_UI_H
|
|
@ -12,3 +12,4 @@ edition = "2018"
|
||||||
espanso-detect = { path = "../espanso-detect" }
|
espanso-detect = { path = "../espanso-detect" }
|
||||||
espanso-ui = { path = "../espanso-ui" }
|
espanso-ui = { path = "../espanso-ui" }
|
||||||
maplit = "1.0.2"
|
maplit = "1.0.2"
|
||||||
|
simplelog = "0.9.0"
|
|
@ -1,7 +1,18 @@
|
||||||
use espanso_detect::event::{InputEvent, Status};
|
use espanso_detect::event::{InputEvent, Status};
|
||||||
|
use espanso_ui::menu::*;
|
||||||
|
use simplelog::{CombinedLogger, Config, LevelFilter, TermLogger, TerminalMode};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("Hello, world!z");
|
println!("Hello, world!z");
|
||||||
|
CombinedLogger::init(vec![
|
||||||
|
TermLogger::new(LevelFilter::Debug, Config::default(), TerminalMode::Mixed),
|
||||||
|
// WriteLogger::new(
|
||||||
|
// LevelFilter::Info,
|
||||||
|
// Config::default(),
|
||||||
|
// File::create("my_rust_binary.log").unwrap(),
|
||||||
|
// ),
|
||||||
|
])
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let icon_paths = vec![
|
let icon_paths = vec![
|
||||||
(
|
(
|
||||||
|
@ -17,7 +28,8 @@ fn main() {
|
||||||
let (remote, mut eventloop) = espanso_ui::win32::create(espanso_ui::win32::Win32UIOptions {
|
let (remote, mut eventloop) = espanso_ui::win32::create(espanso_ui::win32::Win32UIOptions {
|
||||||
show_icon: true,
|
show_icon: true,
|
||||||
icon_paths: &icon_paths,
|
icon_paths: &icon_paths,
|
||||||
notification_icon_path: r"C:\Users\Freddy\Insync\Development\Espanso\Images\icongreensmall.png".to_string(),
|
notification_icon_path: r"C:\Users\Freddy\Insync\Development\Espanso\Images\icongreensmall.png"
|
||||||
|
.to_string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
|
@ -30,7 +42,7 @@ fn main() {
|
||||||
InputEvent::Keyboard(evt) => {
|
InputEvent::Keyboard(evt) => {
|
||||||
if evt.key == espanso_detect::event::Key::Shift && evt.status == Status::Pressed {
|
if evt.key == espanso_detect::event::Key::Shift && evt.status == Status::Pressed {
|
||||||
//remote.update_tray_icon(espanso_ui::icons::TrayIcon::Disabled);
|
//remote.update_tray_icon(espanso_ui::icons::TrayIcon::Disabled);
|
||||||
remote.show_notification("Espanso is running!");
|
//remote.show_notification("Espanso is running!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +50,20 @@ fn main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
eventloop.initialize();
|
eventloop.initialize();
|
||||||
eventloop.run(Box::new(|event| {
|
eventloop.run(Box::new(move |event| {
|
||||||
println!("ui {:?}", event);
|
println!("ui {:?}", event);
|
||||||
|
let menu = Menu::from(vec![
|
||||||
|
MenuItem::Simple(SimpleMenuItem::new("open", "Open")),
|
||||||
|
MenuItem::Separator,
|
||||||
|
MenuItem::Sub(SubMenuItem::new(
|
||||||
|
"Sub",
|
||||||
|
vec![
|
||||||
|
MenuItem::Simple(SimpleMenuItem::new("sub1", "Sub 1")),
|
||||||
|
MenuItem::Simple(SimpleMenuItem::new("sub2", "Sub 2")),
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
])
|
||||||
|
.unwrap();
|
||||||
|
remote.show_context_menu(&menu);
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user