diff --git a/ui/uinotification.cpp b/ui/uinotification.cpp index a9ad89bf..e05e4550 100644 --- a/ui/uinotification.cpp +++ b/ui/uinotification.cpp @@ -246,9 +246,38 @@ bool NotificationListener::OnTokenDoubleClicked(UIContext* context, ViewFrame* f // AddressDisplayToken is intentionally left out: those keep navigating in the current view. // NOTE: opening address-valued literals in a new pane is arguably a better default // and should probably become the standard behavior even outside of a debug session. + + // If the target lands inside the function the user is already looking at, they most + // likely want to jump to it in place rather than open a second pane. Fall through to + // the default double-click behavior (in-pane navigation) in that case. + auto func = location.getFunction(); + if (!func) + { + auto funcs = data->GetAnalysisFunctionsContainingAddress(location.getOffset()); + if (!funcs.empty()) + func = funcs[0]; + } + if (func) + { + for (const auto& range : func->GetAddressRanges()) + { + if ((token.addr >= range.start) && (token.addr < range.end)) + return false; + } + } + target = token.addr; haveTarget = true; } + else if (token.type == DataSymbolToken || token.type == StringToken) + { + // A data symbol (e.g. data_100003fa9) or an inline string. The default behavior + // navigates to it in the same view; while debugging we instead open it in another + // pane so the disassembly the user is looking at stays put. The referenced address is + // carried in the token's value (the address field is not populated for these tokens). + target = token.addrValid ? token.addr : token.token.value; + haveTarget = true; + } else if (token.type == RegisterToken) { // A raw register token: navigate to the address currently held in the register.