diff --git a/redo/uitask_windows.c b/redo/uitask_windows.c index 9b38aef..3382d41 100644 --- a/redo/uitask_windows.c +++ b/redo/uitask_windows.c @@ -71,6 +71,13 @@ HWND msgwin; #define msgwinclass L"gouimsgwin" +struct modalqueue { + BOOL inmodal; + void **modals; + size_t len; + size_t cap; +}; + static BOOL CALLBACK beginEndModalAll(HWND hwnd, LPARAM lParam) { 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) { 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)) return shared; @@ -93,20 +117,27 @@ static LRESULT CALLBACK msgwinproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM l case msgRequest: // in modal? if (GetWindowLongPtrW(hwnd, GWLP_USERDATA) != 0) { - // post again later - // TODO this chokes the message queue! - issue((void *) lParam); - return 0; + mq->modals[mq->len] = (void *) lParam; + mq->len++; + if (mq->len >= mq->cap) { + 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 doissue((void *) lParam); return 0; case msgBeginModal: - SetWindowLongPtrW(hwnd, GWLP_USERDATA, 1); + mq->inmodal = TRUE; EnumThreadWindows(GetCurrentThreadId(), beginEndModalAll, msgBeginModal); return 0; 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); return 0; default: