feat: shortcut key prediction (#126)

This commit is contained in:
hstyi
2025-01-24 15:40:14 +08:00
committed by GitHub
parent 96999205a8
commit 3d0ef2a331

View File

@@ -12,9 +12,9 @@ import org.apache.commons.lang3.StringUtils
import org.jdesktop.swingx.action.ActionManager import org.jdesktop.swingx.action.ActionManager
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.awt.KeyEventDispatcher import java.awt.KeyEventDispatcher
import java.awt.KeyEventPostProcessor
import java.awt.KeyboardFocusManager import java.awt.KeyboardFocusManager
import java.awt.event.KeyEvent import java.awt.event.KeyEvent
import javax.swing.JComponent
import javax.swing.JDialog import javax.swing.JDialog
import javax.swing.KeyStroke import javax.swing.KeyStroke
@@ -23,15 +23,13 @@ class KeymapManager private constructor() : Disposable {
companion object { companion object {
private val log = LoggerFactory.getLogger(KeymapManager::class.java) private val log = LoggerFactory.getLogger(KeymapManager::class.java)
const val PROCESS_GLOBAL_KEYMAP = "PROCESS_GLOBAL_KEYMAP"
fun getInstance(): KeymapManager { fun getInstance(): KeymapManager {
return ApplicationScope.forApplicationScope() return ApplicationScope.forApplicationScope()
.getOrCreate(KeymapManager::class) { KeymapManager() } .getOrCreate(KeymapManager::class) { KeymapManager() }
} }
} }
private val myKeyEventPostProcessor = MyKeyEventPostProcessor() private val keymapKeyEventDispatcher = KeymapKeyEventDispatcher()
private val myKeyEventDispatcher = MyKeyEventDispatcher() private val myKeyEventDispatcher = MyKeyEventDispatcher()
private val database get() = Database.getDatabase() private val database get() = Database.getDatabase()
private val keymaps = linkedMapOf<String, Keymap>() private val keymaps = linkedMapOf<String, Keymap>()
@@ -39,7 +37,7 @@ class KeymapManager private constructor() : Disposable {
private val keyboardFocusManager by lazy { KeyboardFocusManager.getCurrentKeyboardFocusManager() } private val keyboardFocusManager by lazy { KeyboardFocusManager.getCurrentKeyboardFocusManager() }
init { init {
keyboardFocusManager.addKeyEventPostProcessor(myKeyEventPostProcessor) keyboardFocusManager.addKeyEventDispatcher(keymapKeyEventDispatcher)
keyboardFocusManager.addKeyEventDispatcher(myKeyEventDispatcher) keyboardFocusManager.addKeyEventDispatcher(myKeyEventDispatcher)
try { try {
@@ -97,36 +95,49 @@ class KeymapManager private constructor() : Disposable {
database.removeKeymap(name) database.removeKeymap(name)
} }
private inner class MyKeyEventPostProcessor : KeyEventPostProcessor { private inner class KeymapKeyEventDispatcher : KeyEventDispatcher {
override fun postProcessKeyEvent(e: KeyEvent): Boolean {
// 只处理 PRESSED 和 带有 modifiers 键的事件 override fun dispatchKeyEvent(e: KeyEvent): Boolean {
if (!e.isConsumed && e.id == KeyEvent.KEY_PRESSED && e.modifiersEx != 0) { if (e.isConsumed || e.id != KeyEvent.KEY_PRESSED || e.modifiersEx == 0) {
val shortcuts = getActiveKeymap() return false
val actionIds = shortcuts.getActionIds(KeyShortcut(KeyStroke.getKeyStrokeForEvent(e))) }
if (actionIds.isEmpty()) {
val keyStroke = KeyStroke.getKeyStrokeForEvent(e)
val component = e.source
if (component is JComponent) {
// 如果这个键已经被组件注册了,那么忽略
if (component.getConditionForKeyStroke(keyStroke) != JComponent.UNDEFINED_CONDITION) {
return false return false
} }
}
val focusedWindow = keyboardFocusManager.focusedWindow
if (focusedWindow is DialogWrapper) { val shortcuts = getActiveKeymap()
if (!focusedWindow.processGlobalKeymap) { val actionIds = shortcuts.getActionIds(KeyShortcut(keyStroke))
return false if (actionIds.isEmpty()) {
} return false
} else if (focusedWindow is JDialog) { }
val focusedWindow = keyboardFocusManager.focusedWindow
if (focusedWindow is DialogWrapper) {
if (!focusedWindow.processGlobalKeymap) {
return false return false
} }
} else if (focusedWindow is JDialog) {
return false
}
val evt = AnActionEvent(e.source, StringUtils.EMPTY, e) val evt = AnActionEvent(e.source, StringUtils.EMPTY, e)
for (actionId in actionIds) { for (actionId in actionIds) {
val action = ActionManager.getInstance().getAction(actionId) ?: continue val action = ActionManager.getInstance().getAction(actionId) ?: continue
if (!action.isEnabled) { if (!action.isEnabled) {
continue continue
} }
action.actionPerformed(evt) action.actionPerformed(evt)
if (evt.isConsumed) { if (evt.isConsumed) {
return true return true
}
} }
} }
@@ -163,7 +174,7 @@ class KeymapManager private constructor() : Disposable {
override fun dispose() { override fun dispose() {
keyboardFocusManager.removeKeyEventPostProcessor(myKeyEventPostProcessor) keyboardFocusManager.removeKeyEventDispatcher(keymapKeyEventDispatcher)
keyboardFocusManager.removeKeyEventDispatcher(myKeyEventDispatcher) keyboardFocusManager.removeKeyEventDispatcher(myKeyEventDispatcher)
} }
} }