Skip to content

Commit f70bf39

Browse files
authored
Merge pull request #444 from lanxiuyun/ctrl+ctrl
Double click the modifer to pop up window
2 parents 4735930 + 7cabbe2 commit f70bf39

File tree

3 files changed

+116
-28
lines changed

3 files changed

+116
-28
lines changed

feature/src/views/settings/index.vue

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -274,12 +274,16 @@ const state = reactive({
274274
custom: {},
275275
});
276276
277+
// 添加lastKeyPressTime变量来跟踪按键时间
278+
const lastKeyPressTime = ref(0);
279+
const DOUBLE_CLICK_THRESHOLD = 300; // 双击时间阈值(毫秒)
280+
277281
const isWindows = window?.rubick?.isWindows();
278282
const tipText = computed(() => {
279283
const optionKeyName = isWindows ? 'Alt' : 'Option、Command';
280284
return t('feature.settings.global.addShortcutKeyTips', {
281285
optionKeyName: optionKeyName,
282-
});
286+
}) + `此外你也可以双击修饰键如(Ctrl+Ctrl)`;
283287
});
284288
285289
const currentSelect = ref(['userInfo']);
@@ -314,33 +318,60 @@ watch(state, setConfig);
314318
315319
const changeShortCut = (e, key) => {
316320
let compose = '';
317-
// 添加是否包含功能键的判断
318-
let incluFuncKeys = false;
321+
const currentTime = Date.now();
322+
const isDoubleClick = currentTime - lastKeyPressTime.value < DOUBLE_CLICK_THRESHOLD;
323+
lastKeyPressTime.value = currentTime;
324+
325+
// 处理 F1-F12 功能键
326+
if (e.keyCode >= 112 && e.keyCode <= 123) {
327+
state.shortCut[key] = keycodes[e.keyCode].toUpperCase();
328+
return;
329+
}
330+
331+
// 处理双击功能键的情况
332+
if (isDoubleClick) {
333+
if (e.keyCode === 17) { // Ctrl
334+
state.shortCut[key] = 'Ctrl+Ctrl';
335+
return;
336+
}
337+
if (e.keyCode === 18) { // Alt
338+
state.shortCut[key] = 'Option+Option';
339+
return;
340+
}
341+
if (e.keyCode === 16) { // Shift
342+
state.shortCut[key] = 'Shift+Shift';
343+
return;
344+
}
345+
if (e.keyCode === 93) { // Command
346+
state.shortCut[key] = 'Command+Command';
347+
return;
348+
}
349+
}
350+
351+
// 处理功能键+普通键的组合
352+
let hasModifierKey = false;
353+
319354
if (e.ctrlKey && e.keyCode !== 17) {
320355
compose += '+Ctrl';
321-
incluFuncKeys = true;
356+
hasModifierKey = true;
322357
}
323358
if (e.shiftKey && e.keyCode !== 16) {
324359
compose += '+Shift';
325-
incluFuncKeys = true;
360+
hasModifierKey = true;
326361
}
327362
if (e.altKey && e.keyCode !== 18) {
328363
compose += '+Option';
329-
incluFuncKeys = true;
364+
hasModifierKey = true;
330365
}
331366
if (e.metaKey && e.keyCode !== 93) {
332367
compose += '+Command';
333-
incluFuncKeys = true;
368+
hasModifierKey = true;
334369
}
335-
compose += '+' + keycodes[e.keyCode].toUpperCase();
336-
compose = compose.substring(1);
337-
if (
338-
incluFuncKeys &&
339-
e.keyCode !== 16 &&
340-
e.keyCode !== 17 &&
341-
e.keyCode !== 18 &&
342-
e.keyCode !== 93
343-
) {
370+
371+
// 只有当有修饰键时才添加普通键
372+
if (hasModifierKey) {
373+
compose += '+' + keycodes[e.keyCode].toUpperCase();
374+
compose = compose.substring(1);
344375
state.shortCut[key] = compose;
345376
} else {
346377
// 不做处理

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
"pouchdb-load": "^1.4.6",
4040
"pouchdb-replication-stream": "^1.2.9",
4141
"simple-plist": "0.2.1",
42+
"uiohook-napi": "^1.5.4",
4243
"vue": "^3.0.0",
4344
"vue-router": "^4.0.0-0",
4445
"vuex": "^4.0.0-0",

src/main/common/registerHotKey.ts

Lines changed: 68 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
import screenCapture from '@/core/screen-capture';
1111
import localConfig from '@/main/common/initLocalConfig';
1212
import winPosition from './getWinPosition';
13+
import { uIOhook, UiohookKey } from 'uiohook-napi';
1314

1415
const registerHotKey = (mainWindow: BrowserWindow): void => {
1516
// 设置开机启动
@@ -57,27 +58,43 @@ const registerHotKey = (mainWindow: BrowserWindow): void => {
5758
}
5859
};
5960

61+
// 显示主窗口
62+
function mainWindowPopUp() {
63+
const currentShow = mainWindow.isVisible() && mainWindow.isFocused();
64+
if (currentShow) return mainWindow.hide();
65+
const { x: wx, y: wy } = winPosition.getPosition();
66+
mainWindow.setAlwaysOnTop(false);
67+
mainWindow.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true });
68+
mainWindow.focus();
69+
mainWindow.setVisibleOnAllWorkspaces(false, {
70+
visibleOnFullScreen: true,
71+
});
72+
mainWindow.setPosition(wx, wy);
73+
mainWindow.show();
74+
}
75+
6076
const init = async () => {
6177
await setAutoLogin();
6278
await setDarkMode();
6379
await setTheme();
6480
const config = await localConfig.getConfig();
6581
globalShortcut.unregisterAll();
82+
6683
// 注册偏好快捷键
67-
globalShortcut.register(config.perf.shortCut.showAndHidden, () => {
68-
const currentShow = mainWindow.isVisible() && mainWindow.isFocused();
69-
if (currentShow) return mainWindow.hide();
70-
const { x: wx, y: wy } = winPosition.getPosition();
71-
mainWindow.setAlwaysOnTop(false);
72-
mainWindow.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true });
73-
mainWindow.focus();
74-
mainWindow.setVisibleOnAllWorkspaces(false, {
75-
visibleOnFullScreen: true,
84+
// 处理显示/隐藏快捷键的注册
85+
const doublePressShortcuts = ['Ctrl+Ctrl', 'Option+Option', 'Shift+Shift', 'Command+Command'];
86+
const isDoublePressShortcut = doublePressShortcuts.includes(config.perf.shortCut.showAndHidden);
87+
88+
if (isDoublePressShortcut) {
89+
// 双击快捷键(如 Ctrl+Ctrl)详见 uIOhookRegister 函数实现
90+
} else {
91+
// 注册普通快捷键(如 Ctrl+Space、F8 等)
92+
globalShortcut.register(config.perf.shortCut.showAndHidden, () => {
93+
mainWindowPopUp();
7694
});
77-
mainWindow.setPosition(wx, wy);
78-
mainWindow.show();
79-
});
95+
}
8096

97+
// 截图快捷键
8198
globalShortcut.register(config.perf.shortCut.capture, () => {
8299
screenCapture(mainWindow, (data) => {
83100
data &&
@@ -107,9 +124,48 @@ const registerHotKey = (mainWindow: BrowserWindow): void => {
107124
});
108125
});
109126
};
127+
128+
uIOhookRegister(mainWindowPopUp);
110129
init();
111130
ipcMain.on('re-register', () => {
112131
init();
113132
});
114133
};
115134
export default registerHotKey;
135+
136+
function uIOhookRegister(callback: () => void) {
137+
let lastModifierPress = Date.now();
138+
uIOhook.on('keydown', async (uio_event) => {
139+
const config = await localConfig.getConfig(); // 此处还有优化空间
140+
141+
if (
142+
![
143+
'Ctrl+Ctrl',
144+
'Option+Option',
145+
'Shift+Shift',
146+
'Command+Command',
147+
].includes(config.perf.shortCut.showAndHidden)
148+
) {
149+
return;
150+
}
151+
152+
// 双击快捷键,如 Ctrl+Ctrl
153+
const modifers = config.perf.shortCut.showAndHidden.split('+');
154+
const showAndHiddenKeyStr = modifers.pop(); // Ctrl
155+
const keyStr2uioKeyCode = {
156+
Ctrl: UiohookKey.Ctrl,
157+
Shift: UiohookKey.Shift,
158+
Option: UiohookKey.Alt,
159+
Command: UiohookKey.Comma,
160+
};
161+
162+
if (uio_event.keycode === keyStr2uioKeyCode[showAndHiddenKeyStr]) {
163+
const currentTime = Date.now();
164+
if (currentTime - lastModifierPress < 300) {
165+
callback(); // 调用 mainWindowPopUp
166+
}
167+
lastModifierPress = currentTime;
168+
}
169+
});
170+
uIOhook.start();
171+
}

0 commit comments

Comments
 (0)