Search code examples
javaswingfocusjxbrowser

How to get the focused jxBrowser in java swing


To determine which component owns the focus I usually call KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(), but when a BrowserView is in focus, it returns null. Why is it so? Is there an alternative way for jxBrowser?


Solution

  • By default, JxBrowser uses heavyweight mode. In heavyweight rendering mode the separate process handles rendering and the focus owner is in another BrowserContext. That is why calling the KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() returns null. To resolve the issue, please consider using a lightweight mode. You can find more information about rendering mode in JxBrowser guide: https://jxbrowser.support.teamdev.com/support/solutions/articles/9000013069-lightweight-or-heavyweight


    EDIT: In the heavyweight rendering mode, we embed a native window into your Java application. JavaFX and Swing have different implementations regarding focus transferring. In JavaFX we don't clear the focus owner, so you can obtain it via Scene.focusOwnerProperty(). In Swing we have to clear the global focus owner when the embedded native window receives focus, otherwise, we won't be able to transfer focus to other Swing components later. However, we set the most recent focus owner using an internal Java API. If you have to use the heavyweight rendering mode, you can obtain the most recent focus owner using reflection. I've updated the answer to demonstrate this approach.

    public static Component getMostRecentFocusOwner(Window window) {
        try {
            KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
            Method getMostRecentFocusOwner = KeyboardFocusManager.class.getDeclaredMethod("getMostRecentFocusOwner", Window.class);
            getMostRecentFocusOwner.setAccessible(true);
            return (Component) getMostRecentFocusOwner.invoke(focusManager, window);
        } catch (Exception ignored) {}
        return null;
    }