diff --git a/jadx-gui/src/main/java/jadx/gui/ui/JadxEventQueue.java b/jadx-gui/src/main/java/jadx/gui/ui/JadxEventQueue.java new file mode 100644 index 000000000..c07f08a3b --- /dev/null +++ b/jadx-gui/src/main/java/jadx/gui/ui/JadxEventQueue.java @@ -0,0 +1,54 @@ +package jadx.gui.ui; + +import java.awt.AWTEvent; +import java.awt.EventQueue; +import java.awt.Toolkit; +import java.awt.event.InputEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseWheelEvent; + +import jadx.gui.utils.UiUtils; + +public class JadxEventQueue extends EventQueue { + + private static final boolean IS_X_TOOLKIT = UiUtils.isXToolkit(); + + public static void register() { + if (IS_X_TOOLKIT) { + Toolkit.getDefaultToolkit().getSystemEventQueue().push(new JadxEventQueue()); + } + } + + private JadxEventQueue() { + } + + @Override + protected void dispatchEvent(AWTEvent event) { + AWTEvent mappedEvent = mapEvent(event); + super.dispatchEvent(mappedEvent); + } + + private static AWTEvent mapEvent(AWTEvent event) { + if (IS_X_TOOLKIT && event instanceof MouseEvent && ((MouseEvent) event).getButton() > 3) { + return mapXWindowMouseEvent((MouseEvent) event); + } + return event; + } + + @SuppressWarnings({ "deprecation", "MagicConstant" }) + private static AWTEvent mapXWindowMouseEvent(MouseEvent src) { + if (src.getButton() < 6) { + // buttons 4-5 come from touchpad, they must be converted to horizontal scrolling events + int modifiers = src.getModifiers() | InputEvent.SHIFT_DOWN_MASK; + return new MouseWheelEvent(src.getComponent(), MouseEvent.MOUSE_WHEEL, src.getWhen(), modifiers, + src.getX(), src.getY(), 0, false, MouseWheelEvent.WHEEL_UNIT_SCROLL, + src.getClickCount(), src.getButton() == 4 ? -1 : 1); + } else { + // Here we "shift" events with buttons `6` and `7` to similar events with buttons 4 and 5 + // See `java.awt.InputEvent#BUTTON_DOWN_MASK`, 1<<14 is the 4th physical button, 1<<15 is the 5th. + int modifiers = src.getModifiers() | (1 << (8 + src.getButton())); + return new MouseEvent(src.getComponent(), src.getID(), src.getWhen(), modifiers, + src.getX(), src.getY(), 1, src.isPopupTrigger(), src.getButton() - 2); + } + } +} diff --git a/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java b/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java index ae01e65e2..1dfb87ac6 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java @@ -250,6 +250,7 @@ public class MainWindow extends JFrame { this.cacheManager = new CacheManager(settings); this.shortcutsController = new ShortcutsController(settings); + JadxEventQueue.register(); resetCache(); FontUtils.registerBundledFonts(); setEditorTheme(settings.getEditorThemePath()); diff --git a/jadx-gui/src/main/java/jadx/gui/utils/SystemInfo.java b/jadx-gui/src/main/java/jadx/gui/utils/SystemInfo.java index e7c24e43f..f9dae09be 100644 --- a/jadx-gui/src/main/java/jadx/gui/utils/SystemInfo.java +++ b/jadx-gui/src/main/java/jadx/gui/utils/SystemInfo.java @@ -17,6 +17,7 @@ public class SystemInfo { public static final boolean IS_WINDOWS = LOWER_OS_NAME.startsWith("windows"); public static final boolean IS_MAC = LOWER_OS_NAME.startsWith("mac"); public static final boolean IS_LINUX = LOWER_OS_NAME.startsWith("linux"); + public static final boolean IS_UNIX = !IS_WINDOWS; private SystemInfo() { } diff --git a/jadx-gui/src/main/java/jadx/gui/utils/UiUtils.java b/jadx-gui/src/main/java/jadx/gui/utils/UiUtils.java index f677e7679..398c2211a 100644 --- a/jadx-gui/src/main/java/jadx/gui/utils/UiUtils.java +++ b/jadx-gui/src/main/java/jadx/gui/utils/UiUtils.java @@ -394,6 +394,12 @@ public class UiUtils { } } + public static boolean isXToolkit() { + return SystemInfo.IS_UNIX + && !SystemInfo.IS_MAC + && "sun.awt.X11.XToolkit".equals(Toolkit.getDefaultToolkit().getClass().getName()); + } + @TestOnly public static void debugTimer(int periodInSeconds, Runnable action) { if (!LOG.isDebugEnabled()) {