未验证 提交 912c4315 编写于 作者: S Skylot

fix(debugger): process UI updates in correct thread (#1796)

上级 5d6b8272
......@@ -14,12 +14,10 @@ import java.util.concurrent.Executors;
import javax.swing.JOptionPane;
import javax.swing.tree.DefaultMutableTreeNode;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.reactivex.annotations.NonNull;
import io.reactivex.annotations.Nullable;
import jadx.core.dex.info.FieldInfo;
import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.nodes.ClassNode;
......@@ -42,6 +40,7 @@ import jadx.gui.ui.panel.JDebuggerPanel;
import jadx.gui.ui.panel.JDebuggerPanel.IListElement;
import jadx.gui.ui.panel.JDebuggerPanel.ValueTreeNode;
import jadx.gui.utils.NLS;
import jadx.gui.utils.UiUtils;
public final class DebugController implements SmaliDebugger.SuspendListener, IDebugController {
......@@ -78,7 +77,7 @@ public final class DebugController implements SmaliDebugger.SuspendListener, IDe
initTypeMap();
}
this.debuggerPanel = debuggerPanel;
debuggerPanel.resetUI();
UiUtils.uiRunAndWait(debuggerPanel::resetUI);
try {
debugger = SmaliDebugger.attach(adbHost, adbPort, this);
} catch (SmaliDebuggerException e) {
......@@ -251,7 +250,6 @@ public final class DebugController implements SmaliDebugger.SuspendListener, IDe
throw new JadxRuntimeException("Unexpected type: " + type);
}
@NonNull
protected static RuntimeType castType(String type) {
RuntimeType rt = null;
if (!StringUtils.isEmpty(type)) {
......@@ -663,22 +661,22 @@ public final class DebugController implements SmaliDebugger.SuspendListener, IDe
}
private void updateAllRegisters(FrameNode frame) {
if (buildRegTreeNodes(frame).size() > 0) {
fetchAllRegisters(frame);
}
UiUtils.uiRun(() -> {
if (!buildRegTreeNodes(frame).isEmpty()) {
fetchAllRegisters(frame);
}
});
}
private void fetchAllRegisters(FrameNode frame) {
List<SmaliRegister> regs = cur.regAdapter.getInitializedList(frame.getCodeOffset());
for (SmaliRegister reg : regs) {
lazyQueue.execute(() -> {
Entry<String, String> info = cur.regAdapter.getInfo(reg.getRuntimeRegNum(), frame.getCodeOffset());
RegTreeNode regNode = frame.getRegNodes().get(reg.getRegNum());
if (info != null) {
applyDbgInfo(regNode, info);
}
updateRegister(regNode, null, true);
});
Entry<String, String> info = cur.regAdapter.getInfo(reg.getRuntimeRegNum(), frame.getCodeOffset());
RegTreeNode regNode = frame.getRegNodes().get(reg.getRegNum());
if (info != null) {
applyDbgInfo(regNode, info);
}
updateRegister(regNode, null, true);
}
}
......
......@@ -475,28 +475,28 @@ public class ADBDialog extends JDialog implements ADB.DeviceStateListener, ADB.J
LOG.error("Failed to find device", e);
return;
}
node.tNode.removeAllChildren();
DefaultMutableTreeNode tempNode = null;
for (String s : procList) {
DefaultMutableTreeNode pnode = new DefaultMutableTreeNode(s);
node.tNode.add(pnode);
if (!debugSetter.expectPkg.isEmpty() && s.endsWith(debugSetter.expectPkg)) {
if (debugSetter.autoAttachPkg && debugSetter.device.equals(node.device)) {
debugSetter.set(node.device, debugSetter.ver, getPid(s), s);
if (attachProcess(mainWindow)) {
dispose();
return;
SwingUtilities.invokeLater(() -> {
node.tNode.removeAllChildren();
DefaultMutableTreeNode foundNode = null;
for (String procStr : procList) {
DefaultMutableTreeNode pnode = new DefaultMutableTreeNode(procStr);
node.tNode.add(pnode);
if (!debugSetter.expectPkg.isEmpty() && procStr.endsWith(debugSetter.expectPkg)) {
if (debugSetter.autoAttachPkg && debugSetter.device.equals(node.device)) {
debugSetter.set(node.device, debugSetter.ver, getPid(procStr), procStr);
if (attachProcess(mainWindow)) {
dispose();
return;
}
}
foundNode = pnode;
}
tempNode = pnode;
}
}
DefaultMutableTreeNode theNode = tempNode;
SwingUtilities.invokeLater(() -> {
procTreeModel.reload(node.tNode);
procTree.expandPath(new TreePath(node.tNode.getPath()));
if (theNode != null) {
TreePath thePath = new TreePath(theNode.getPath());
if (foundNode != null) {
TreePath thePath = new TreePath(foundNode.getPath());
procTree.scrollPathToVisible(thePath);
procTree.setSelectionPath(thePath);
}
......
......@@ -88,6 +88,7 @@ public class JDebuggerPanel extends JPanel {
private transient KeyEventDispatcher controllerShortCutDispatcher;
public JDebuggerPanel(MainWindow mainWindow) {
UiUtils.uiThreadGuard();
this.mainWindow = mainWindow;
controller = new DebugController();
this.setLayout(new BorderLayout());
......@@ -287,24 +288,26 @@ public class JDebuggerPanel extends JPanel {
@Override
public void onStateChanged(boolean suspended, boolean stopped) {
if (!stopped) {
if (isGray) {
stop.putValue(Action.SMALL_ICON, ICON_STOP);
UiUtils.uiRun(() -> {
if (!stopped) {
if (isGray) {
stop.putValue(Action.SMALL_ICON, ICON_STOP);
}
} else {
stop.putValue(Action.SMALL_ICON, ICON_STOP_GRAY);
run.putValue(Action.SMALL_ICON, ICON_RUN);
run.putValue(Action.SHORT_DESCRIPTION, NLS.str("debugger.run"));
isGray = true;
return;
}
} else {
stop.putValue(Action.SMALL_ICON, ICON_STOP_GRAY);
run.putValue(Action.SMALL_ICON, ICON_RUN);
run.putValue(Action.SHORT_DESCRIPTION, NLS.str("debugger.run"));
isGray = true;
return;
}
if (suspended) {
run.putValue(Action.SMALL_ICON, ICON_RUN);
run.putValue(Action.SHORT_DESCRIPTION, NLS.str("debugger.run"));
} else {
run.putValue(Action.SMALL_ICON, ICON_PAUSE);
run.putValue(Action.SHORT_DESCRIPTION, NLS.str("debugger.pause"));
}
if (suspended) {
run.putValue(Action.SMALL_ICON, ICON_RUN);
run.putValue(Action.SHORT_DESCRIPTION, NLS.str("debugger.run"));
} else {
run.putValue(Action.SMALL_ICON, ICON_PAUSE);
run.putValue(Action.SHORT_DESCRIPTION, NLS.str("debugger.pause"));
}
});
}
});
......@@ -387,16 +390,18 @@ public class JDebuggerPanel extends JPanel {
public boolean showDebugger(String procName, String host, int port, int androidVer, ADBDevice device, String pid) {
boolean ok = controller.startDebugger(this, host, port, androidVer);
if (ok) {
log(String.format("Attached %s %s:%d", procName, host, port));
try {
logcatPanel.init(device, pid);
} catch (Exception e) {
log(NLS.str("logcat.error_fail_start"));
LOG.error("Logcat failed to start", e);
}
leftSplitter.setDividerLocation(mainWindow.getSettings().getDebuggerStackFrameSplitterLoc());
rightSplitter.setDividerLocation(mainWindow.getSettings().getDebuggerVarTreeSplitterLoc());
mainWindow.showDebuggerPanel();
UiUtils.uiRun(() -> {
log(String.format("Attached %s %s:%d", procName, host, port));
try {
logcatPanel.init(device, pid);
} catch (Exception e) {
log(NLS.str("logcat.error_fail_start"));
LOG.error("Logcat failed to start", e);
}
leftSplitter.setDividerLocation(mainWindow.getSettings().getDebuggerStackFrameSplitterLoc());
rightSplitter.setDividerLocation(mainWindow.getSettings().getDebuggerVarTreeSplitterLoc());
mainWindow.showDebuggerPanel();
});
}
return ok;
}
......@@ -414,6 +419,8 @@ public class JDebuggerPanel extends JPanel {
}
public void loadSettings() {
UiUtils.uiThreadGuard();
Font font = mainWindow.getSettings().getFont();
variableTree.setFont(font.deriveFont(font.getSize() + 1.f));
variableTree.setRowHeight(-1);
......@@ -423,6 +430,8 @@ public class JDebuggerPanel extends JPanel {
}
public void resetUI() {
UiUtils.uiThreadGuard();
thisTreeNode.removeAllChildren();
regTreeNode.removeAllChildren();
......@@ -464,12 +473,11 @@ public class JDebuggerPanel extends JPanel {
}
public void refreshThreadBox(List<? extends IListElement> elements) {
if (elements.size() > 0) {
DefaultComboBoxModel<IListElement> model =
(DefaultComboBoxModel<IListElement>) threadBox.getModel();
elements.forEach(model::addElement);
}
SwingUtilities.invokeLater(() -> {
UiUtils.uiRun(() -> {
if (!elements.isEmpty()) {
DefaultComboBoxModel<IListElement> model = (DefaultComboBoxModel<IListElement>) threadBox.getModel();
elements.forEach(model::addElement);
}
threadBox.updateUI();
stackFrameList.setFont(mainWindow.getSettings().getFont());
});
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册