From 704684d79efbfe9b223231f67be30a35c9fce528 Mon Sep 17 00:00:00 2001 From: frankboehkeenlab Date: Mon, 15 Jun 2026 14:08:32 +0200 Subject: [PATCH] Recognise IB Gateway 1037+ login controls (hyphenated forms) IB Gateway 10.37 renamed several UI controls to use hyphens in place of spaces, which prevents IBC from auto-logging in. Affected controls: * Window title: 'IBKR-Gateway' (was 'IBKR Gateway') * Login button: 'Paper-Login' (was 'Paper Log In') * Mode toggles: 'Live-Trading' / 'Paper-Trading' (was 'Live Trading' / 'Paper Trading') * API toggle: 'FIX-CTCI' (was 'FIX CTCI') Without these, GatewayLoginFrameHandler.recogniseWindow() returns false, the login handler never fires, and IBC exits 1112 (LOGIN_DIALOG_DISPLAY_ TIMED_OUT) after its 60s wait, with the IBC log showing only the 'IBKR-Gateway frame Opened' event followed by silence. Behaviour confirmed by enabling LogComponents=open and dumping the live Swing component tree: the new names are emitted verbatim by Gateway 1037. Older Gateway/TWS versions remain matched by the existing space-separated strings (the change is purely additive, no removals). End-to-end verified on Gateway 10.37.1q (Windows, paper trading): fully automated login completes in ~10s and the Gateway API port (4002) stays listening continuously. --- src/ibcalpha/ibc/AbstractLoginHandler.java | 14 ++++++++++---- src/ibcalpha/ibc/GatewayLoginFrameHandler.java | 7 +++++-- ...nectDataOrAccountConfirmationDialogHandler.java | 8 +++++--- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/ibcalpha/ibc/AbstractLoginHandler.java b/src/ibcalpha/ibc/AbstractLoginHandler.java index 4da2e6b5..27b54dea 100644 --- a/src/ibcalpha/ibc/AbstractLoginHandler.java +++ b/src/ibcalpha/ibc/AbstractLoginHandler.java @@ -25,6 +25,7 @@ import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; +import javax.swing.JToggleButton; public abstract class AbstractLoginHandler implements WindowHandler { @@ -157,6 +158,7 @@ private JButton findLoginButton(final Window window) { JButton b = SwingUtils.findButton(window, "Login"); if (b == null) b = SwingUtils.findButton(window, "Log In"); if (b == null) b = SwingUtils.findButton(window, "Paper Log In"); + if (b == null) b = SwingUtils.findButton(window, "Paper-Login"); // Gateway 1037+ (hyphenated) return b; } @@ -174,14 +176,18 @@ protected final void setCredential(final Window window, protected final boolean setTradingMode(final Window window) { String tradingMode = TradingModeManager.tradingModeManager().getTradingMode(); - if (SwingUtils.findToggleButton(window, "Live Trading") != null && - SwingUtils.findToggleButton(window, "Paper Trading") != null) { + // Gateway 1037+ uses hyphenated names; older Gateway/TWS uses space-separated. + JToggleButton liveBtn = SwingUtils.findToggleButton(window, "Live Trading"); + if (liveBtn == null) liveBtn = SwingUtils.findToggleButton(window, "Live-Trading"); + JToggleButton paperBtn = SwingUtils.findToggleButton(window, "Paper Trading"); + if (paperBtn == null) paperBtn = SwingUtils.findToggleButton(window, "Paper-Trading"); + if (liveBtn != null && paperBtn != null) { // TWS 974 onwards uses toggle buttons rather than a combo box Utils.logToConsole("Setting Trading mode = " + tradingMode); if (tradingMode.equalsIgnoreCase(TradingModeManager.TRADING_MODE_LIVE)) { - SwingUtils.findToggleButton(window, "Live Trading").doClick(); + liveBtn.doClick(); } else { - SwingUtils.findToggleButton(window, "Paper Trading").doClick(); + paperBtn.doClick(); } return true; } else { diff --git a/src/ibcalpha/ibc/GatewayLoginFrameHandler.java b/src/ibcalpha/ibc/GatewayLoginFrameHandler.java index d1829730..9ca27931 100644 --- a/src/ibcalpha/ibc/GatewayLoginFrameHandler.java +++ b/src/ibcalpha/ibc/GatewayLoginFrameHandler.java @@ -30,11 +30,13 @@ public boolean recogniseWindow(Window window) { if (! (window instanceof JFrame)) return false; return ((SwingUtils.titleContains(window, "IBKR Gateway") || - SwingUtils.titleContains(window, "IB Gateway") || + SwingUtils.titleContains(window, "IBKR-Gateway") || // Gateway 1037+ + SwingUtils.titleContains(window, "IB Gateway") || SwingUtils.titleContains(window, "Interactive Brokers Gateway")) && (SwingUtils.findButton(window, "Login") != null || SwingUtils.findButton(window, "Log In") != null || // TWS 974+ - SwingUtils.findButton(window, "Paper Log In") != null)); // TWS 974+ + SwingUtils.findButton(window, "Paper Log In") != null || // TWS 974+ + SwingUtils.findButton(window, "Paper-Login") != null)); // Gateway 1037+ (hyphenated) } @Override @@ -119,6 +121,7 @@ private void selectGatewayMode(Window window) throws IbcException { private void switchToFIX(Window window) throws IbcException { JToggleButton button = SwingUtils.findToggleButton(window, "FIX CTCI"); + if (button == null) button = SwingUtils.findToggleButton(window, "FIX-CTCI"); // Gateway 1037+ if (button == null) throw new IbcException("FIX CTCI selector"); if (! button.isSelected()) { diff --git a/src/ibcalpha/ibc/ReconnectDataOrAccountConfirmationDialogHandler.java b/src/ibcalpha/ibc/ReconnectDataOrAccountConfirmationDialogHandler.java index cd1a3345..b4b5acf4 100644 --- a/src/ibcalpha/ibc/ReconnectDataOrAccountConfirmationDialogHandler.java +++ b/src/ibcalpha/ibc/ReconnectDataOrAccountConfirmationDialogHandler.java @@ -46,10 +46,12 @@ public void handleWindow(Window window, int eventID) { public boolean recogniseWindow(Window window) { if (! (window instanceof JDialog)) return false; - return ((SwingUtils.titleContains(window, "IBKR Trader Workstation") + return ((SwingUtils.titleContains(window, "IBKR Trader Workstation") || - SwingUtils.titleContains(window, "IBKR Gateway")) - && + SwingUtils.titleContains(window, "IBKR Gateway") + || + SwingUtils.titleContains(window, "IBKR-Gateway")) // Gateway 1037+ + && (SwingUtils.findLabel(window, "Are you sure you want to execute \"simulate") != null) ); }