Added uiQueueMain() (basically g_idle_add()) and implemented it on all platforms except Haiku. A test to come. After this we can start rewriting the Go package ui at long last.

This commit is contained in:
Pietro Gagliardi 2015-12-04 23:42:03 -05:00
parent d12974eef1
commit f77955aefb
7 changed files with 56 additions and 0 deletions

View File

@ -105,8 +105,18 @@ void uiMain(void)
[realNSApp() run];
}
// TODO make this delayed
void uiQuit(void)
{
canQuit = YES;
[realNSApp() terminate:realNSApp()];
}
// thanks to mikeash in irc.freenode.net/#macdev for suggesting the use of Grand Central Dispatch for this
// TODO will dispatch_get_main_queue() break after _CFRunLoopSetCurrent()?
void uiQueueMain(void (*f)(void *data), void *data)
{
// dispatch_get_main_queue() is a serial queue so it will not execute multiple uiQueueMain() functions concurrently
// the signature of f matches dispatch_function_t
dispatch_async_f(dispatch_get_main_queue(), data, f);
}

View File

@ -44,3 +44,8 @@ void uiQuit(void)
// TODO see window.cpp for why that alone won't work
app->Quit();
}
void uiQueueMain(void (*f)(void *data), void *data)
{
// TODO
}

3
ui.h
View File

@ -29,6 +29,9 @@ _UI_EXTERN void uiFreeInitError(const char *err);
_UI_EXTERN void uiMain(void);
_UI_EXTERN void uiQuit(void);
// TODO write a test for this after adding multiline entries
_UI_EXTERN void uiQueueMain(void (*f)(void *data), void *data);
_UI_EXTERN void uiOnShouldQuit(int (*f)(void *data), void *data);
_UI_EXTERN void uiFreeText(char *text);

View File

@ -48,3 +48,28 @@ void uiQuit(void)
{
gdk_threads_add_idle(quit, NULL);
}
struct queued {
void (*f)(void *);
void *data;
};
static gboolean doqueued(gpointer data)
{
struct queued *q = (struct queued *) data;
(*(q->f))(q->data);
uiFree(q);
return FALSE;
}
// TODO document that the effect of calling this function after uiQuit() is called (either directly or via a nonzero return to uiShouldQuit()) is undefined
void uiQueueMain(void (*f)(void *data), void *data)
{
struct queued *q;
q = uiNew(struct queued);
q->f = f;
q->data = data;
gdk_threads_add_idle(doqueued, q);
}

View File

@ -41,3 +41,10 @@ void uiQuit(void)
{
PostQuitMessage(0);
}
void uiQueueMain(void (*f)(void *data), void *data)
{
if (PostMessageW(utilWindow, msgQueued, (WPARAM) f, (LPARAM) data) == 0)
// TODO make sure this is safe to call across threads
logLastError("error queueing function to run on main thread in uiQueueMain()");
}

View File

@ -13,6 +13,7 @@ enum {
msgNOTIFY,
msgHSCROLL,
msgConsoleEndSession,
msgQueued,
};
// init.c

View File

@ -18,6 +18,7 @@ HWND utilWindow;
static LRESULT CALLBACK utilWindowWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
void (*qf)(void *);
LRESULT lResult;
if (handleParentMessages(hwnd, uMsg, wParam, lParam, &lResult) != FALSE)
@ -41,6 +42,10 @@ static LRESULT CALLBACK utilWindowWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, L
case WM_WININICHANGE:
issueWM_WININICHANGE(wParam, lParam);
return 0;
case msgQueued:
qf = (void (*)(void *)) wParam;
(*qf)((void *) lParam);
return 0;
}
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
}