Delay at least 100ms between individual UI updates
Thanks to @JustasMasiulis for the help!
This commit is contained in:
parent
570aaea06d
commit
f56fa5ce23
|
@ -28,20 +28,188 @@ class BridgeArchitecture : public Architecture
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
Class Members
|
Class Members
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
static const char* msg2str(GUIMSG msg)
|
||||||
|
{
|
||||||
|
switch(msg)
|
||||||
|
{
|
||||||
|
case GUI_UPDATE_REGISTER_VIEW:
|
||||||
|
return "GUI_UPDATE_REGISTER_VIEW";
|
||||||
|
case GUI_UPDATE_DISASSEMBLY_VIEW:
|
||||||
|
return "GUI_UPDATE_DISASSEMBLY_VIEW";
|
||||||
|
case GUI_UPDATE_BREAKPOINTS_VIEW:
|
||||||
|
return "GUI_UPDATE_BREAKPOINTS_VIEW";
|
||||||
|
case GUI_UPDATE_DUMP_VIEW:
|
||||||
|
return "GUI_UPDATE_DUMP_VIEW";
|
||||||
|
case GUI_UPDATE_THREAD_VIEW:
|
||||||
|
return "GUI_UPDATE_THREAD_VIEW";
|
||||||
|
case GUI_UPDATE_MEMORY_VIEW:
|
||||||
|
return "GUI_UPDATE_MEMORY_VIEW";
|
||||||
|
case GUI_UPDATE_SIDEBAR:
|
||||||
|
return "GUI_UPDATE_SIDEBAR";
|
||||||
|
case GUI_REPAINT_TABLE_VIEW:
|
||||||
|
return "GUI_REPAINT_TABLE_VIEW";
|
||||||
|
case GUI_UPDATE_PATCHES:
|
||||||
|
return "GUI_UPDATE_PATCHES";
|
||||||
|
case GUI_UPDATE_CALLSTACK:
|
||||||
|
return "GUI_UPDATE_CALLSTACK";
|
||||||
|
case GUI_UPDATE_SEHCHAIN:
|
||||||
|
return "GUI_UPDATE_SEHCHAIN";
|
||||||
|
case GUI_UPDATE_TIME_WASTED_COUNTER:
|
||||||
|
return "GUI_UPDATE_TIME_WASTED_COUNTER";
|
||||||
|
case GUI_UPDATE_ARGUMENT_VIEW:
|
||||||
|
return "GUI_UPDATE_ARGUMENT_VIEW";
|
||||||
|
case GUI_UPDATE_WATCH_VIEW:
|
||||||
|
return "GUI_UPDATE_WATCH_VIEW";
|
||||||
|
case GUI_UPDATE_GRAPH_VIEW:
|
||||||
|
return "GUI_UPDATE_GRAPH_VIEW";
|
||||||
|
case GUI_UPDATE_TYPE_WIDGET:
|
||||||
|
return "GUI_UPDATE_TYPE_WIDGET";
|
||||||
|
case GUI_UPDATE_TRACE_BROWSER:
|
||||||
|
return "GUI_UPDATE_TRACE_BROWSER";
|
||||||
|
default:
|
||||||
|
return "<unknown message>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bridge::throttleUpdateSlot(GUIMSG msg)
|
||||||
|
{
|
||||||
|
// NOTE: This is running synchronously on the UI thread
|
||||||
|
|
||||||
|
auto lastUpdate = mLastUpdates[msg];
|
||||||
|
auto now = GetTickCount();
|
||||||
|
auto elapsed = now - lastUpdate;
|
||||||
|
const auto interval = 100;
|
||||||
|
if(lastUpdate > 0 && elapsed < interval)
|
||||||
|
{
|
||||||
|
//qDebug() << "Delay update:" << msg2str(msg);
|
||||||
|
QTimer* timer = mUpdateTimers[msg];
|
||||||
|
if(timer == nullptr)
|
||||||
|
{
|
||||||
|
timer = new QTimer(this);
|
||||||
|
timer->setSingleShot(true);
|
||||||
|
connect(timer, &QTimer::timeout, this, [this, msg]
|
||||||
|
{
|
||||||
|
doUpdate(msg);
|
||||||
|
});
|
||||||
|
mUpdateTimers[msg] = timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!timer->isActive())
|
||||||
|
{
|
||||||
|
timer->setInterval(interval - elapsed);
|
||||||
|
timer->start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//qDebug() << "No delay: " << msg2str(msg);
|
||||||
|
doUpdate(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bridge::doUpdate(GUIMSG msg)
|
||||||
|
{
|
||||||
|
auto start = GetTickCount();
|
||||||
|
|
||||||
|
switch(msg)
|
||||||
|
{
|
||||||
|
case GUI_UPDATE_REGISTER_VIEW:
|
||||||
|
updateRegisters();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GUI_UPDATE_DISASSEMBLY_VIEW:
|
||||||
|
updateDisassembly();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GUI_UPDATE_BREAKPOINTS_VIEW:
|
||||||
|
updateBreakpoints();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GUI_UPDATE_DUMP_VIEW:
|
||||||
|
updateDump();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GUI_UPDATE_THREAD_VIEW:
|
||||||
|
updateThreads();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GUI_UPDATE_MEMORY_VIEW:
|
||||||
|
updateMemory();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GUI_UPDATE_SIDEBAR:
|
||||||
|
updateSideBar();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GUI_REPAINT_TABLE_VIEW:
|
||||||
|
repaintTableView();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GUI_UPDATE_PATCHES:
|
||||||
|
updatePatches();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GUI_UPDATE_CALLSTACK:
|
||||||
|
updateCallStack();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GUI_UPDATE_SEHCHAIN:
|
||||||
|
updateSEHChain();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GUI_UPDATE_TIME_WASTED_COUNTER:
|
||||||
|
updateTimeWastedCounter();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GUI_UPDATE_ARGUMENT_VIEW:
|
||||||
|
updateArgumentView();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GUI_UPDATE_WATCH_VIEW:
|
||||||
|
updateWatch();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GUI_UPDATE_GRAPH_VIEW:
|
||||||
|
updateGraph();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GUI_UPDATE_TYPE_WIDGET:
|
||||||
|
typeUpdateWidget();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GUI_UPDATE_TRACE_BROWSER:
|
||||||
|
updateTraceBrowser();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
__debugbreak();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log potentially bottlenecked updates
|
||||||
|
auto now = GetTickCount();
|
||||||
|
auto elapsed = now - start;
|
||||||
|
if(elapsed > 5)
|
||||||
|
qDebug() << msg2str(msg) << elapsed << "ms";
|
||||||
|
|
||||||
|
mLastUpdates[msg] = now;
|
||||||
|
}
|
||||||
|
|
||||||
Bridge::Bridge(QObject* parent) : QObject(parent)
|
Bridge::Bridge(QObject* parent) : QObject(parent)
|
||||||
{
|
{
|
||||||
InitializeCriticalSection(&csBridge);
|
InitializeCriticalSection(&mCsBridge);
|
||||||
for(size_t i = 0; i < BridgeResult::Last; i++)
|
for(size_t i = 0; i < BridgeResult::Last; i++)
|
||||||
resultEvents[i] = CreateEventW(nullptr, true, true, nullptr);
|
mResultEvents[i] = CreateEventW(nullptr, true, true, nullptr);
|
||||||
dwMainThreadId = GetCurrentThreadId();
|
mMainThreadId = GetCurrentThreadId();
|
||||||
|
|
||||||
|
connect(this, &Bridge::throttleUpdate, this, &Bridge::throttleUpdateSlot);
|
||||||
}
|
}
|
||||||
|
|
||||||
Bridge::~Bridge()
|
Bridge::~Bridge()
|
||||||
{
|
{
|
||||||
EnterCriticalSection(&csBridge);
|
EnterCriticalSection(&mCsBridge);
|
||||||
for(size_t i = 0; i < BridgeResult::Last; i++)
|
for(size_t i = 0; i < BridgeResult::Last; i++)
|
||||||
CloseHandle(resultEvents[i]);
|
CloseHandle(mResultEvents[i]);
|
||||||
DeleteCriticalSection(&csBridge);
|
DeleteCriticalSection(&mCsBridge);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bridge::CopyToClipboard(const QString & text)
|
void Bridge::CopyToClipboard(const QString & text)
|
||||||
|
@ -68,8 +236,8 @@ void Bridge::setResult(BridgeResult::Type type, dsint result)
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
OutputDebugStringA(QString().sprintf("[x64dbg] [%u] Bridge::setResult(%d, %p)\n", GetCurrentThreadId(), type, result).toUtf8().constData());
|
OutputDebugStringA(QString().sprintf("[x64dbg] [%u] Bridge::setResult(%d, %p)\n", GetCurrentThreadId(), type, result).toUtf8().constData());
|
||||||
#endif //DEBUG
|
#endif //DEBUG
|
||||||
bridgeResults[type] = result;
|
mBridgeResults[type] = result;
|
||||||
SetEvent(resultEvents[type]);
|
SetEvent(mResultEvents[type]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
|
@ -103,7 +271,7 @@ void Bridge::emitMenuAddToList(QWidget* parent, QMenu* menu, GUIMENUTYPE hMenu,
|
||||||
|
|
||||||
void Bridge::setDbgStopped()
|
void Bridge::setDbgStopped()
|
||||||
{
|
{
|
||||||
dbgStopped = true;
|
mDbgStopped = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
|
@ -112,7 +280,7 @@ void Bridge::setDbgStopped()
|
||||||
|
|
||||||
void* Bridge::processMessage(GUIMSG type, void* param1, void* param2)
|
void* Bridge::processMessage(GUIMSG type, void* param1, void* param2)
|
||||||
{
|
{
|
||||||
if(dbgStopped) //there can be no more messages if the debugger stopped = IGNORE
|
if(mDbgStopped) //there can be no more messages if the debugger stopped = IGNORE
|
||||||
return nullptr;
|
return nullptr;
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
|
@ -160,24 +328,12 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2)
|
||||||
emit redirectLogStop();
|
emit redirectLogStop();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GUI_UPDATE_REGISTER_VIEW:
|
|
||||||
emit updateRegisters();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GUI_UPDATE_DISASSEMBLY_VIEW:
|
|
||||||
emit updateDisassembly();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GUI_UPDATE_BREAKPOINTS_VIEW:
|
|
||||||
emit updateBreakpoints();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GUI_UPDATE_WINDOW_TITLE:
|
case GUI_UPDATE_WINDOW_TITLE:
|
||||||
emit updateWindowTitle(QString((const char*)param1));
|
emit updateWindowTitle(QString((const char*)param1));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GUI_GET_WINDOW_HANDLE:
|
case GUI_GET_WINDOW_HANDLE:
|
||||||
return winId;
|
return mWinId;
|
||||||
|
|
||||||
case GUI_DUMP_AT:
|
case GUI_DUMP_AT:
|
||||||
emit dumpAt((dsint)param1);
|
emit dumpAt((dsint)param1);
|
||||||
|
@ -252,25 +408,25 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GUI_REF_ADDCOLUMN:
|
case GUI_REF_ADDCOLUMN:
|
||||||
if(referenceManager->currentReferenceView())
|
if(mReferenceManager->currentReferenceView())
|
||||||
referenceManager->currentReferenceView()->addColumnAtRef((int)param1, QString((const char*)param2));
|
mReferenceManager->currentReferenceView()->addColumnAtRef((int)param1, QString((const char*)param2));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GUI_REF_SETROWCOUNT:
|
case GUI_REF_SETROWCOUNT:
|
||||||
{
|
{
|
||||||
if(referenceManager->currentReferenceView())
|
if(mReferenceManager->currentReferenceView())
|
||||||
referenceManager->currentReferenceView()->setRowCount((dsint)param1);
|
mReferenceManager->currentReferenceView()->setRowCount((dsint)param1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GUI_REF_GETROWCOUNT:
|
case GUI_REF_GETROWCOUNT:
|
||||||
if(referenceManager->currentReferenceView())
|
if(mReferenceManager->currentReferenceView())
|
||||||
return (void*)referenceManager->currentReferenceView()->stdList()->getRowCount();
|
return (void*)mReferenceManager->currentReferenceView()->stdList()->getRowCount();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case GUI_REF_SEARCH_GETROWCOUNT:
|
case GUI_REF_SEARCH_GETROWCOUNT:
|
||||||
if(referenceManager->currentReferenceView())
|
if(mReferenceManager->currentReferenceView())
|
||||||
return (void*)referenceManager->currentReferenceView()->mCurList->getRowCount();
|
return (void*)mReferenceManager->currentReferenceView()->mCurList->getRowCount();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case GUI_REF_DELETEALLCOLUMNS:
|
case GUI_REF_DELETEALLCOLUMNS:
|
||||||
|
@ -280,16 +436,16 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2)
|
||||||
case GUI_REF_SETCELLCONTENT:
|
case GUI_REF_SETCELLCONTENT:
|
||||||
{
|
{
|
||||||
CELLINFO* info = (CELLINFO*)param1;
|
CELLINFO* info = (CELLINFO*)param1;
|
||||||
if(referenceManager->currentReferenceView())
|
if(mReferenceManager->currentReferenceView())
|
||||||
referenceManager->currentReferenceView()->setCellContent(info->row, info->col, QString(info->str));
|
mReferenceManager->currentReferenceView()->setCellContent(info->row, info->col, QString(info->str));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GUI_REF_GETCELLCONTENT:
|
case GUI_REF_GETCELLCONTENT:
|
||||||
{
|
{
|
||||||
QString content;
|
QString content;
|
||||||
if(referenceManager->currentReferenceView())
|
if(mReferenceManager->currentReferenceView())
|
||||||
content = referenceManager->currentReferenceView()->stdList()->getCellContent((int)param1, (int)param2);
|
content = mReferenceManager->currentReferenceView()->stdList()->getCellContent((int)param1, (int)param2);
|
||||||
auto bytes = content.toUtf8();
|
auto bytes = content.toUtf8();
|
||||||
auto data = BridgeAlloc(bytes.size() + 1);
|
auto data = BridgeAlloc(bytes.size() + 1);
|
||||||
memcpy(data, bytes.constData(), bytes.size());
|
memcpy(data, bytes.constData(), bytes.size());
|
||||||
|
@ -299,8 +455,8 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2)
|
||||||
case GUI_REF_SEARCH_GETCELLCONTENT:
|
case GUI_REF_SEARCH_GETCELLCONTENT:
|
||||||
{
|
{
|
||||||
QString content;
|
QString content;
|
||||||
if(referenceManager->currentReferenceView())
|
if(mReferenceManager->currentReferenceView())
|
||||||
content = referenceManager->currentReferenceView()->mCurList->getCellContent((int)param1, (int)param2);
|
content = mReferenceManager->currentReferenceView()->mCurList->getCellContent((int)param1, (int)param2);
|
||||||
auto bytes = content.toUtf8();
|
auto bytes = content.toUtf8();
|
||||||
auto data = BridgeAlloc(bytes.size() + 1);
|
auto data = BridgeAlloc(bytes.size() + 1);
|
||||||
memcpy(data, bytes.constData(), bytes.size());
|
memcpy(data, bytes.constData(), bytes.size());
|
||||||
|
@ -316,26 +472,26 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GUI_REF_SETPROGRESS:
|
case GUI_REF_SETPROGRESS:
|
||||||
if(referenceManager->currentReferenceView())
|
if(mReferenceManager->currentReferenceView())
|
||||||
{
|
{
|
||||||
auto newProgress = (int)param1;
|
auto newProgress = (int)param1;
|
||||||
if(referenceManager->currentReferenceView()->progress() != newProgress)
|
if(mReferenceManager->currentReferenceView()->progress() != newProgress)
|
||||||
emit referenceSetProgress(newProgress);
|
emit referenceSetProgress(newProgress);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GUI_REF_SETCURRENTTASKPROGRESS:
|
case GUI_REF_SETCURRENTTASKPROGRESS:
|
||||||
if(referenceManager->currentReferenceView())
|
if(mReferenceManager->currentReferenceView())
|
||||||
{
|
{
|
||||||
auto newProgress = (int)param1;
|
auto newProgress = (int)param1;
|
||||||
if(referenceManager->currentReferenceView()->currentTaskProgress() != newProgress)
|
if(mReferenceManager->currentReferenceView()->currentTaskProgress() != newProgress)
|
||||||
emit referenceSetCurrentTaskProgress((int)param1, QString((const char*)param2));
|
emit referenceSetCurrentTaskProgress((int)param1, QString((const char*)param2));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GUI_REF_SETSEARCHSTARTCOL:
|
case GUI_REF_SETSEARCHSTARTCOL:
|
||||||
if(referenceManager->currentReferenceView())
|
if(mReferenceManager->currentReferenceView())
|
||||||
referenceManager->currentReferenceView()->setSearchStartCol((duint)param1);
|
mReferenceManager->currentReferenceView()->setSearchStartCol((duint)param1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GUI_REF_INITIALIZE:
|
case GUI_REF_INITIALIZE:
|
||||||
|
@ -350,18 +506,6 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2)
|
||||||
emit stackDumpAt((duint)param1, (duint)param2);
|
emit stackDumpAt((duint)param1, (duint)param2);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GUI_UPDATE_DUMP_VIEW:
|
|
||||||
emit updateDump();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GUI_UPDATE_THREAD_VIEW:
|
|
||||||
emit updateThreads();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GUI_UPDATE_MEMORY_VIEW:
|
|
||||||
emit updateMemory();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GUI_ADD_RECENT_FILE:
|
case GUI_ADD_RECENT_FILE:
|
||||||
emit addRecentFile(QString((const char*)param1));
|
emit addRecentFile(QString((const char*)param1));
|
||||||
break;
|
break;
|
||||||
|
@ -619,26 +763,6 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2)
|
||||||
emit addMsgToStatusBar(QString((const char*)param1));
|
emit addMsgToStatusBar(QString((const char*)param1));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GUI_UPDATE_SIDEBAR:
|
|
||||||
emit updateSideBar();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GUI_REPAINT_TABLE_VIEW:
|
|
||||||
emit repaintTableView();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GUI_UPDATE_PATCHES:
|
|
||||||
emit updatePatches();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GUI_UPDATE_CALLSTACK:
|
|
||||||
emit updateCallStack();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GUI_UPDATE_SEHCHAIN:
|
|
||||||
emit updateSEHChain();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GUI_SYMBOL_REFRESH_CURRENT:
|
case GUI_SYMBOL_REFRESH_CURRENT:
|
||||||
emit symbolRefreshCurrent();
|
emit symbolRefreshCurrent();
|
||||||
break;
|
break;
|
||||||
|
@ -669,17 +793,13 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2)
|
||||||
|
|
||||||
case GUI_EXECUTE_ON_GUI_THREAD:
|
case GUI_EXECUTE_ON_GUI_THREAD:
|
||||||
{
|
{
|
||||||
if(GetCurrentThreadId() == dwMainThreadId)
|
if(GetCurrentThreadId() == mMainThreadId)
|
||||||
((GUICALLBACKEX)param1)(param2);
|
((GUICALLBACKEX)param1)(param2);
|
||||||
else
|
else
|
||||||
emit executeOnGuiThread(param1, param2);
|
emit executeOnGuiThread(param1, param2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GUI_UPDATE_TIME_WASTED_COUNTER:
|
|
||||||
emit updateTimeWastedCounter();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GUI_SET_GLOBAL_NOTES:
|
case GUI_SET_GLOBAL_NOTES:
|
||||||
{
|
{
|
||||||
QString text = QString((const char*)param1);
|
QString text = QString((const char*)param1);
|
||||||
|
@ -734,10 +854,6 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2)
|
||||||
emit unregisterScriptLang((int)param1);
|
emit unregisterScriptLang((int)param1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GUI_UPDATE_ARGUMENT_VIEW:
|
|
||||||
emit updateArgumentView();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GUI_FOCUS_VIEW:
|
case GUI_FOCUS_VIEW:
|
||||||
{
|
{
|
||||||
int hWindow = int(param1);
|
int hWindow = int(param1);
|
||||||
|
@ -764,10 +880,6 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GUI_UPDATE_WATCH_VIEW:
|
|
||||||
emit updateWatch();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GUI_LOAD_GRAPH:
|
case GUI_LOAD_GRAPH:
|
||||||
{
|
{
|
||||||
BridgeResult result(BridgeResult::LoadGraph);
|
BridgeResult result(BridgeResult::LoadGraph);
|
||||||
|
@ -784,17 +896,13 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GUI_UPDATE_GRAPH_VIEW:
|
|
||||||
emit updateGraph();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GUI_SET_LOG_ENABLED:
|
case GUI_SET_LOG_ENABLED:
|
||||||
loggingEnabled = param1 != 0;
|
mLoggingEnabled = param1 != 0;
|
||||||
emit setLogEnabled(loggingEnabled);
|
emit setLogEnabled(mLoggingEnabled);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GUI_IS_LOG_ENABLED:
|
case GUI_IS_LOG_ENABLED:
|
||||||
return (void*)loggingEnabled;
|
return (void*)mLoggingEnabled;
|
||||||
|
|
||||||
case GUI_ADD_FAVOURITE_TOOL:
|
case GUI_ADD_FAVOURITE_TOOL:
|
||||||
{
|
{
|
||||||
|
@ -883,10 +991,6 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GUI_UPDATE_TYPE_WIDGET:
|
|
||||||
emit typeUpdateWidget();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GUI_CLOSE_APPLICATION:
|
case GUI_CLOSE_APPLICATION:
|
||||||
emit closeApplication();
|
emit closeApplication();
|
||||||
break;
|
break;
|
||||||
|
@ -914,12 +1018,8 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GUI_UPDATE_TRACE_BROWSER:
|
|
||||||
emit updateTraceBrowser();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GUI_INVALIDATE_SYMBOL_SOURCE:
|
case GUI_INVALIDATE_SYMBOL_SOURCE:
|
||||||
symbolView->invalidateSymbolSource(duint(param1));
|
mSymbolView->invalidateSymbolSource(duint(param1));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GUI_GET_CURRENT_GRAPH:
|
case GUI_GET_CURRENT_GRAPH:
|
||||||
|
@ -947,7 +1047,28 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GUI_GET_MAIN_THREAD_ID:
|
case GUI_GET_MAIN_THREAD_ID:
|
||||||
return (void*)dwMainThreadId;
|
return (void*)mMainThreadId;
|
||||||
|
|
||||||
|
case GUI_UPDATE_REGISTER_VIEW:
|
||||||
|
case GUI_UPDATE_DISASSEMBLY_VIEW:
|
||||||
|
case GUI_UPDATE_BREAKPOINTS_VIEW:
|
||||||
|
case GUI_UPDATE_DUMP_VIEW:
|
||||||
|
case GUI_UPDATE_THREAD_VIEW:
|
||||||
|
case GUI_UPDATE_MEMORY_VIEW:
|
||||||
|
case GUI_UPDATE_SIDEBAR:
|
||||||
|
case GUI_REPAINT_TABLE_VIEW:
|
||||||
|
case GUI_UPDATE_PATCHES:
|
||||||
|
case GUI_UPDATE_CALLSTACK:
|
||||||
|
case GUI_UPDATE_SEHCHAIN:
|
||||||
|
case GUI_UPDATE_TIME_WASTED_COUNTER:
|
||||||
|
case GUI_UPDATE_ARGUMENT_VIEW:
|
||||||
|
case GUI_UPDATE_WATCH_VIEW:
|
||||||
|
case GUI_UPDATE_GRAPH_VIEW:
|
||||||
|
case GUI_UPDATE_TYPE_WIDGET:
|
||||||
|
case GUI_UPDATE_TRACE_BROWSER:
|
||||||
|
// NOTE: this can run on any thread.
|
||||||
|
emit throttleUpdate(type);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -26,6 +26,11 @@ class Bridge : public QObject
|
||||||
|
|
||||||
friend class BridgeResult;
|
friend class BridgeResult;
|
||||||
|
|
||||||
|
void doUpdate(GUIMSG msg);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void throttleUpdateSlot(GUIMSG msg);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Bridge(QObject* parent = nullptr);
|
explicit Bridge(QObject* parent = nullptr);
|
||||||
~Bridge();
|
~Bridge();
|
||||||
|
@ -49,12 +54,12 @@ public:
|
||||||
void setDbgStopped();
|
void setDbgStopped();
|
||||||
|
|
||||||
//Public variables
|
//Public variables
|
||||||
void* winId = nullptr;
|
void* mWinId = nullptr;
|
||||||
ReferenceManager* referenceManager = nullptr;
|
ReferenceManager* mReferenceManager = nullptr;
|
||||||
bool mIsRunning = false;
|
bool mIsRunning = false;
|
||||||
duint mLastCip = 0;
|
duint mLastCip = 0;
|
||||||
SymbolView* symbolView = nullptr;
|
SymbolView* mSymbolView = nullptr;
|
||||||
bool loggingEnabled = true;
|
bool mLoggingEnabled = true;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void disassembleAt(duint va, duint eip);
|
void disassembleAt(duint va, duint eip);
|
||||||
|
@ -183,11 +188,14 @@ signals:
|
||||||
void showReferences();
|
void showReferences();
|
||||||
void gotoTraceIndex(duint index);
|
void gotoTraceIndex(duint index);
|
||||||
void showTraceBrowser();
|
void showTraceBrowser();
|
||||||
|
void throttleUpdate(GUIMSG msg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CRITICAL_SECTION csBridge;
|
CRITICAL_SECTION mCsBridge;
|
||||||
HANDLE resultEvents[BridgeResult::Last];
|
HANDLE mResultEvents[BridgeResult::Last];
|
||||||
duint bridgeResults[BridgeResult::Last];
|
duint mBridgeResults[BridgeResult::Last];
|
||||||
DWORD dwMainThreadId = 0;
|
DWORD mMainThreadId = 0;
|
||||||
volatile bool dbgStopped = false;
|
volatile bool mDbgStopped = false;
|
||||||
|
QMap<GUIMSG, DWORD> mLastUpdates;
|
||||||
|
QMap<GUIMSG, QTimer*> mUpdateTimers;
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,11 +6,11 @@ BridgeResult::BridgeResult(Type type)
|
||||||
: mType(type)
|
: mType(type)
|
||||||
{
|
{
|
||||||
Bridge* bridge = Bridge::getBridge();
|
Bridge* bridge = Bridge::getBridge();
|
||||||
EnterCriticalSection(&bridge->csBridge);
|
EnterCriticalSection(&bridge->mCsBridge);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
OutputDebugStringA(QString().sprintf("[x64dbg] [%u] BridgeResult(%d)\n", GetCurrentThreadId(), type).toUtf8().constData());
|
OutputDebugStringA(QString().sprintf("[x64dbg] [%u] BridgeResult(%d)\n", GetCurrentThreadId(), type).toUtf8().constData());
|
||||||
#endif //DEBUG
|
#endif //DEBUG
|
||||||
ResetEvent(bridge->resultEvents[type]);
|
ResetEvent(bridge->mResultEvents[type]);
|
||||||
}
|
}
|
||||||
|
|
||||||
BridgeResult::~BridgeResult()
|
BridgeResult::~BridgeResult()
|
||||||
|
@ -18,7 +18,7 @@ BridgeResult::~BridgeResult()
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
OutputDebugStringA(QString().sprintf("[x64dbg] [%u] ~BridgeResult(%d)\n", GetCurrentThreadId(), mType).toUtf8().constData());
|
OutputDebugStringA(QString().sprintf("[x64dbg] [%u] ~BridgeResult(%d)\n", GetCurrentThreadId(), mType).toUtf8().constData());
|
||||||
#endif //DEBUG
|
#endif //DEBUG
|
||||||
LeaveCriticalSection(&Bridge::getBridge()->csBridge);
|
LeaveCriticalSection(&Bridge::getBridge()->mCsBridge);
|
||||||
}
|
}
|
||||||
|
|
||||||
dsint BridgeResult::Wait()
|
dsint BridgeResult::Wait()
|
||||||
|
@ -27,9 +27,9 @@ dsint BridgeResult::Wait()
|
||||||
OutputDebugStringA(QString().sprintf("[x64dbg] [%u] BridgeResult::Wait(%d)\n", GetCurrentThreadId(), mType).toUtf8().constData());
|
OutputDebugStringA(QString().sprintf("[x64dbg] [%u] BridgeResult::Wait(%d)\n", GetCurrentThreadId(), mType).toUtf8().constData());
|
||||||
#endif //DEBUG
|
#endif //DEBUG
|
||||||
Bridge* bridge = Bridge::getBridge();
|
Bridge* bridge = Bridge::getBridge();
|
||||||
HANDLE hResultEvent = bridge->resultEvents[mType];
|
HANDLE hResultEvent = bridge->mResultEvents[mType];
|
||||||
//Don't freeze when waiting on the main thread (https://github.com/x64dbg/x64dbg/issues/1716)
|
//Don't freeze when waiting on the main thread (https://github.com/x64dbg/x64dbg/issues/1716)
|
||||||
if(GetCurrentThreadId() == bridge->dwMainThreadId)
|
if(GetCurrentThreadId() == bridge->mMainThreadId)
|
||||||
while(WaitForSingleObject(hResultEvent, 10) == WAIT_TIMEOUT)
|
while(WaitForSingleObject(hResultEvent, 10) == WAIT_TIMEOUT)
|
||||||
QCoreApplication::processEvents();
|
QCoreApplication::processEvents();
|
||||||
else
|
else
|
||||||
|
@ -37,5 +37,5 @@ dsint BridgeResult::Wait()
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
OutputDebugStringA(QString().sprintf("[x64dbg] [%u] BridgeResult::~Wait(%d)\n", GetCurrentThreadId(), mType).toUtf8().constData());
|
OutputDebugStringA(QString().sprintf("[x64dbg] [%u] BridgeResult::~Wait(%d)\n", GetCurrentThreadId(), mType).toUtf8().constData());
|
||||||
#endif //DEBUG
|
#endif //DEBUG
|
||||||
return bridge->bridgeResults[mType];
|
return bridge->mBridgeResults[mType];
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,7 +154,7 @@ MainWindow::MainWindow(QWidget* parent)
|
||||||
|
|
||||||
// Symbol view
|
// Symbol view
|
||||||
mSymbolView = new SymbolView();
|
mSymbolView = new SymbolView();
|
||||||
Bridge::getBridge()->symbolView = mSymbolView;
|
Bridge::getBridge()->mSymbolView = mSymbolView;
|
||||||
mSymbolView->setWindowTitle(tr("Symbols"));
|
mSymbolView->setWindowTitle(tr("Symbols"));
|
||||||
mSymbolView->setWindowIcon(DIcon("pdb"));
|
mSymbolView->setWindowIcon(DIcon("pdb"));
|
||||||
mSymbolView->hide();
|
mSymbolView->hide();
|
||||||
|
@ -207,7 +207,7 @@ MainWindow::MainWindow(QWidget* parent)
|
||||||
|
|
||||||
// Reference manager
|
// Reference manager
|
||||||
mReferenceManager = new ReferenceManager(this);
|
mReferenceManager = new ReferenceManager(this);
|
||||||
Bridge::getBridge()->referenceManager = mReferenceManager;
|
Bridge::getBridge()->mReferenceManager = mReferenceManager;
|
||||||
mReferenceManager->setWindowTitle(tr("References"));
|
mReferenceManager->setWindowTitle(tr("References"));
|
||||||
mReferenceManager->setWindowIcon(DIcon("search"));
|
mReferenceManager->setWindowIcon(DIcon("search"));
|
||||||
|
|
||||||
|
|
|
@ -123,7 +123,7 @@ QAction* ThreadView::makeCommandAction(QAction* action, const QString & command)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief ThreadView::ExecCommand execute command slot for menus. Only used by command that reference thread id.
|
* @brief ThreadView::execCommandSlot execute command slot for menus. Only used by command that reference thread id.
|
||||||
*/
|
*/
|
||||||
void ThreadView::execCommandSlot()
|
void ThreadView::execCommandSlot()
|
||||||
{
|
{
|
||||||
|
|
|
@ -190,6 +190,7 @@ int main(int argc, char* argv[])
|
||||||
qRegisterMetaType<duint>("duint");
|
qRegisterMetaType<duint>("duint");
|
||||||
qRegisterMetaType<byte_t>("byte_t");
|
qRegisterMetaType<byte_t>("byte_t");
|
||||||
qRegisterMetaType<DBGSTATE>("DBGSTATE");
|
qRegisterMetaType<DBGSTATE>("DBGSTATE");
|
||||||
|
qRegisterMetaType<GUIMSG>("GUIMSG");
|
||||||
|
|
||||||
// Set QString codec to UTF-8
|
// Set QString codec to UTF-8
|
||||||
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
|
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
|
||||||
|
@ -207,7 +208,7 @@ int main(int argc, char* argv[])
|
||||||
mainWindow->show();
|
mainWindow->show();
|
||||||
|
|
||||||
// Set some data
|
// Set some data
|
||||||
Bridge::getBridge()->winId = (void*)mainWindow->winId();
|
Bridge::getBridge()->mWinId = (void*)mainWindow->winId();
|
||||||
|
|
||||||
// Init debugger
|
// Init debugger
|
||||||
const char* errormsg = DbgInit();
|
const char* errormsg = DbgInit();
|
||||||
|
|
Loading…
Reference in New Issue