fix(windows): 修复 OpenLess 前台主窗口热键失效#86
Conversation
Reviewer's GuideImplements a Windows-specific path for handling the main window’s own hotkey keyboard events by forwarding keydown/keyup from the frontend to the Rust coordinator, matching them against the configured hotkey trigger, and reusing existing coordinator pressed/released/cancel semantics with de‑duplication, plus optional UI key event logging for debugging. Updated class diagram for Coordinator and hotkey handlingclassDiagram
class Inner {
+Prefs prefs
+Mutex~Option_Recorder~~ recorder
+Mutex~Option_HotkeyMonitor~~ hotkey
+Mutex~HotkeyStatus~ hotkey_status
+Mutex~bool~ window_hotkey_held
}
class Coordinator {
-Arc~Inner~ inner
+new() Coordinator
+handle_window_hotkey_event(event_type: &str, key: &str, code: &str, repeat: bool) Result~(), String~
+repolish(raw_text: String, mode: PolishMode) Result~String, String~
}
class HotkeyTrigger {
<<enum>>
RightControl
LeftControl
RightOption
RightAlt
LeftOption
RightCommand
Fn
}
class CommandsModule {
<<module>>
+is_debug_ui_key_events_enabled() bool
+debug_log_ui_key_event(event_type: String, key: String, code: String, ctrl: bool, alt: bool, shift: bool, meta: bool, repeat: bool) void
+handle_window_hotkey_event(coord: CoordinatorState, event_type: String, key: String, code: String, repeat: bool) Result~(), String~
}
class CoordinatorCoreFunctions {
<<module>>
+handle_window_hotkey_event(inner: &Arc~Inner~, event_type: &str, key: &str, code: &str, repeat: bool) void
+matches_window_hotkey(trigger: HotkeyTrigger, code: &str) bool
+handle_pressed(inner: &Arc~Inner~) void
+handle_released(inner: &Arc~Inner~) void
+cancel_session(inner: &Arc~Inner~) void
}
class App_tsx {
+useEffect_hotkey_debug()
+useEffect_window_hotkey()
}
class Ipc_ts {
+isDebugUiKeyEventsEnabled() Promise~boolean~
+debugLogUiKeyEvent(eventType: string, key: string, code: string, ctrl: boolean, alt: boolean, shift: boolean, meta: boolean, repeat: boolean) Promise~void~
+handleWindowHotkeyEvent(eventType: string, key: string, code: string, repeat: boolean) Promise~void~
}
Coordinator --> Inner
CoordinatorCoreFunctions --> Inner
CoordinatorCoreFunctions --> HotkeyTrigger
CommandsModule --> Coordinator
App_tsx --> Ipc_ts
Ipc_ts --> CommandsModule
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 2 issues
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="openless-all/app/src-tauri/src/commands.rs" line_range="322-303" />
<code_context>
+}
+
+#[tauri::command]
+pub async fn handle_window_hotkey_event(
+ coord: CoordinatorState<'_>,
+ event_type: String,
+ key: String,
+ code: String,
+ repeat: bool,
+) -> Result<(), String> {
+ coord.handle_window_hotkey_event(&event_type, &key, &code, repeat)
</code_context>
<issue_to_address>
**issue (bug_risk):** The Tauri command argument names don't match the keys used in the frontend invoke payload, which will likely break deserialization.
On the TS side, `handleWindowHotkeyEvent` is invoked with `{ eventType, key, code, repeat }`, so Tauri expects arguments with those exact names. The Rust command uses `event_type: String`, which won’t match `eventType`, so deserialization will fail at runtime. Please either align the Rust parameter names with the JS keys, use a struct with `#[serde(rename = "eventType")]` (and similar for others), or update the frontend payload to use snake_case. The same mismatch exists for `debug_log_ui_key_event` (`eventType` vs `event_type`).
</issue_to_address>
### Comment 2
<location path="openless-all/app/src-tauri/src/lib.rs" line_range="182-183" />
<code_context>
- api.prevent_close();
- hide_main_window(app);
+ match event {
+ tauri::WindowEvent::Focused(focused) => {
+ log::info!("[window] main focused={focused}");
+ }
+ tauri::WindowEvent::CloseRequested { api, .. } => {
</code_context>
<issue_to_address>
**issue (bug_risk):** Losing window focus while the hotkey is held can leave `window_hotkey_held` stuck in the "pressed" state.
Because `window_hotkey_held` is only cleared on `keyup`, losing focus while the hotkey is pressed can leave it stuck `true`, making later hotkey presses no-op until restart. Add logic to reset this flag when the main window loses focus (e.g., in a `WindowEvent::Focused(false)` branch).
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| alt: bool, | ||
| shift: bool, | ||
| meta: bool, | ||
| repeat: bool, |
There was a problem hiding this comment.
issue (bug_risk): The Tauri command argument names don't match the keys used in the frontend invoke payload, which will likely break deserialization.
On the TS side, handleWindowHotkeyEvent is invoked with { eventType, key, code, repeat }, so Tauri expects arguments with those exact names. The Rust command uses event_type: String, which won’t match eventType, so deserialization will fail at runtime. Please either align the Rust parameter names with the JS keys, use a struct with #[serde(rename = "eventType")] (and similar for others), or update the frontend payload to use snake_case. The same mismatch exists for debug_log_ui_key_event (eventType vs event_type).
| tauri::WindowEvent::Focused(focused) => { | ||
| log::info!("[window] main focused={focused}"); |
There was a problem hiding this comment.
issue (bug_risk): Losing window focus while the hotkey is held can leave window_hotkey_held stuck in the "pressed" state.
Because window_hotkey_held is only cleared on keyup, losing focus while the hotkey is pressed can leave it stuck true, making later hotkey presses no-op until restart. Add logic to reset this flag when the main window loses focus (e.g., in a WindowEvent::Focused(false) branch).
|
不幸的是,我们似乎进行了相同的工作... #90 |
摘要
修复 Windows 下 OpenLess 主窗口自身处于前台时,默认
rightControl热键不触发的问题。变更
keydown/keyup上报当前键盘事件hotkey.trigger匹配主窗口内的热键事件验证
powershell -ExecutionPolicy Bypass -File .\openless-all\app\scripts\windows-build-gnu.ps1 -CheckOnly -KeepMirror[window-hotkey] pressed trigger=RightControl code=ControlRight repeat=false[coord] hotkey pressed mode=Toggle phase=IdleCloses #85