diff --git a/src/main/kotlin/com/chylex/intellij/pinundockedtoolwindows/patch/AwtClickListener.kt b/src/main/kotlin/com/chylex/intellij/pinundockedtoolwindows/patch/AwtClickListener.kt new file mode 100644 index 0000000..080539a --- /dev/null +++ b/src/main/kotlin/com/chylex/intellij/pinundockedtoolwindows/patch/AwtClickListener.kt @@ -0,0 +1,25 @@ +package com.chylex.intellij.pinundockedtoolwindows.patch + +import com.intellij.openapi.actionSystem.AnActionHolder +import com.intellij.openapi.application.ApplicationManager +import java.awt.AWTEvent +import java.awt.event.AWTEventListener +import java.awt.event.MouseEvent +import javax.swing.AbstractButton + +object AwtClickListener : AWTEventListener { + var wasPressingButton = false + private set + + override fun eventDispatched(event: AWTEvent?) { + if (event !is MouseEvent || event.id != MouseEvent.MOUSE_RELEASED) { + return + } + + val source = event.source + if (source is AbstractButton || source is AnActionHolder) { + wasPressingButton = true + ApplicationManager.getApplication().invokeLater { wasPressingButton = false } + } + } +} diff --git a/src/main/kotlin/com/chylex/intellij/pinundockedtoolwindows/patch/PatchedAwtFocusListener.kt b/src/main/kotlin/com/chylex/intellij/pinundockedtoolwindows/patch/PatchedAwtFocusListener.kt index f95e7c2..f4e9f0a 100644 --- a/src/main/kotlin/com/chylex/intellij/pinundockedtoolwindows/patch/PatchedAwtFocusListener.kt +++ b/src/main/kotlin/com/chylex/intellij/pinundockedtoolwindows/patch/PatchedAwtFocusListener.kt @@ -22,6 +22,10 @@ class PatchedAwtFocusListener(internal val original: AWTEventListener) : AWTEven } private fun shouldIgnoreFocusLostEvent(currentlyFocused: Component?): Boolean { + if (AwtClickListener.wasPressingButton) { + return false + } + val project = IdeFocusManager.getGlobalInstance().lastFocusedFrame?.project ?: return false if (project.isDisposed || project.isDefault) { return false diff --git a/src/main/kotlin/com/chylex/intellij/pinundockedtoolwindows/patch/ToolWindowPatcher.kt b/src/main/kotlin/com/chylex/intellij/pinundockedtoolwindows/patch/ToolWindowPatcher.kt index a279d4d..527fcb6 100644 --- a/src/main/kotlin/com/chylex/intellij/pinundockedtoolwindows/patch/ToolWindowPatcher.kt +++ b/src/main/kotlin/com/chylex/intellij/pinundockedtoolwindows/patch/ToolWindowPatcher.kt @@ -5,25 +5,34 @@ import java.awt.Toolkit import java.awt.event.AWTEventListenerProxy object ToolWindowPatcher { - private const val EVENT_MASK = AWTEvent.FOCUS_EVENT_MASK or AWTEvent.WINDOW_FOCUS_EVENT_MASK + private data class ActivePatch(val focusListener: PatchedAwtFocusListener, val focusEventMask: Long) { + fun apply() = with(Toolkit.getDefaultToolkit()) { + removeAWTEventListener(focusListener.original) + addAWTEventListener(focusListener, focusEventMask) + addAWTEventListener(AwtClickListener, AWTEvent.MOUSE_EVENT_MASK) + } + + fun revert() = with(Toolkit.getDefaultToolkit()) { + removeAWTEventListener(AwtClickListener) + removeAWTEventListener(focusListener) + addAWTEventListener(focusListener.original, focusEventMask) + } + } private var activePatch: ActivePatch? = null - private data class ActivePatch(val listener: PatchedAwtFocusListener, val eventMask: Long) - fun apply() { if (activePatch != null) { return } val toolkit = Toolkit.getDefaultToolkit() - for (listenerProxy in toolkit.getAWTEventListeners(EVENT_MASK)) { + for (listenerProxy in toolkit.getAWTEventListeners(AWTEvent.FOCUS_EVENT_MASK or AWTEvent.WINDOW_FOCUS_EVENT_MASK)) { if (listenerProxy is AWTEventListenerProxy) { val listener = listenerProxy.listener if (listener.javaClass.name == "com.intellij.openapi.wm.impl.ToolWindowManagerImpl\$ToolWindowManagerAppLevelHelper\$MyListener") { val patch = ActivePatch(PatchedAwtFocusListener(listener), listenerProxy.eventMask) - toolkit.removeAWTEventListener(listener) - toolkit.addAWTEventListener(patch.listener, patch.eventMask) + patch.apply() activePatch = patch return } @@ -34,9 +43,7 @@ object ToolWindowPatcher { fun revert() { val patch = activePatch if (patch != null) { - val toolkit = Toolkit.getDefaultToolkit() - toolkit.removeAWTEventListener(patch.listener) - toolkit.addAWTEventListener(patch.listener.original, patch.eventMask) + patch.revert() activePatch = null } }