Fixed message queue overload in Windows modality code.

This commit is contained in:
Pietro Gagliardi 2014-08-19 03:56:04 -04:00
parent b6a5735f89
commit 751180ba20
1 changed files with 37 additions and 6 deletions

View File

@ -71,6 +71,13 @@ HWND msgwin;
#define msgwinclass L"gouimsgwin" #define msgwinclass L"gouimsgwin"
struct modalqueue {
BOOL inmodal;
void **modals;
size_t len;
size_t cap;
};
static BOOL CALLBACK beginEndModalAll(HWND hwnd, LPARAM lParam) static BOOL CALLBACK beginEndModalAll(HWND hwnd, LPARAM lParam)
{ {
if (hwnd != msgwin) if (hwnd != msgwin)
@ -81,6 +88,23 @@ static BOOL CALLBACK beginEndModalAll(HWND hwnd, LPARAM lParam)
static LRESULT CALLBACK msgwinproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) static LRESULT CALLBACK msgwinproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{ {
LRESULT shared; LRESULT shared;
struct modalqueue *mq;
size_t i;
mq = (struct modalqueue *) GetWindowLongPtrW(hwnd, GWLP_USERDATA);
if (mq == NULL) {
mq = (struct modalqueue *) malloc(sizeof (struct modalqueue));
if (mq == NULL)
xpanic("error allocating modal queue structure", GetLastError());
ZeroMemory(mq, sizeof (struct modalqueue));
mq->inmodal = FALSE;
mq->len = 0;
mq->cap = 128;
mq->modals = (void **) malloc(mq->cap * sizeof (void *));
if (mq->modals == NULL)
xpanic("error allocating modal quque", GetLastError());
SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR) mq);
}
if (sharedWndProc(hwnd, uMsg, wParam, lParam, &shared)) if (sharedWndProc(hwnd, uMsg, wParam, lParam, &shared))
return shared; return shared;
@ -93,20 +117,27 @@ static LRESULT CALLBACK msgwinproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM l
case msgRequest: case msgRequest:
// in modal? // in modal?
if (GetWindowLongPtrW(hwnd, GWLP_USERDATA) != 0) { if (GetWindowLongPtrW(hwnd, GWLP_USERDATA) != 0) {
// post again later mq->modals[mq->len] = (void *) lParam;
// TODO this chokes the message queue! mq->len++;
issue((void *) lParam); if (mq->len >= mq->cap) {
return 0; mq->cap *= 2;
mq->modals = (void **) realloc(mq->modals, mq->cap * sizeof (void *));
if (mq->modals == NULL)
xpanic("error growing modal queue", GetLastError());
}
} }
// nope, we can run now // nope, we can run now
doissue((void *) lParam); doissue((void *) lParam);
return 0; return 0;
case msgBeginModal: case msgBeginModal:
SetWindowLongPtrW(hwnd, GWLP_USERDATA, 1); mq->inmodal = TRUE;
EnumThreadWindows(GetCurrentThreadId(), beginEndModalAll, msgBeginModal); EnumThreadWindows(GetCurrentThreadId(), beginEndModalAll, msgBeginModal);
return 0; return 0;
case msgEndModal: case msgEndModal:
SetWindowLongPtrW(hwnd, GWLP_USERDATA, 0); mq->inmodal = FALSE;
for (i = 0; i < mq->len; i++)
doissue(mq->modals[i]);
mq->len = 0;
EnumThreadWindows(GetCurrentThreadId(), beginEndModalAll, msgEndModal); EnumThreadWindows(GetCurrentThreadId(), beginEndModalAll, msgEndModal);
return 0; return 0;
default: default: