2015-04-22 12:53:22 -05:00
|
|
|
// 6 april 2015
|
|
|
|
#include "uipriv_unix.h"
|
|
|
|
|
2018-04-15 14:49:45 -05:00
|
|
|
uiInitOptions uiprivOptions;
|
2015-04-22 12:53:22 -05:00
|
|
|
|
|
|
|
const char *uiInit(uiInitOptions *o)
|
|
|
|
{
|
|
|
|
GError *err = NULL;
|
|
|
|
const char *msg;
|
|
|
|
|
2018-04-15 14:49:45 -05:00
|
|
|
uiprivOptions = *o;
|
2015-04-22 12:53:22 -05:00
|
|
|
if (gtk_init_with_args(NULL, NULL, NULL, NULL, NULL, &err) == FALSE) {
|
|
|
|
msg = g_strdup(err->message);
|
|
|
|
g_error_free(err);
|
|
|
|
return msg;
|
|
|
|
}
|
2018-05-12 11:47:21 -05:00
|
|
|
uiprivInitAlloc();
|
2018-05-12 12:19:35 -05:00
|
|
|
uiprivLoadFutures();
|
2015-04-22 12:53:22 -05:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2015-05-07 21:32:17 -05:00
|
|
|
void uiUninit(void)
|
|
|
|
{
|
2018-05-12 11:47:21 -05:00
|
|
|
uiprivUninitMenus();
|
|
|
|
uiprivUninitAlloc();
|
2015-05-07 21:32:17 -05:00
|
|
|
}
|
|
|
|
|
2015-04-22 12:53:22 -05:00
|
|
|
void uiFreeInitError(const char *err)
|
|
|
|
{
|
|
|
|
g_free((gpointer) err);
|
|
|
|
}
|
|
|
|
|
2016-06-17 08:16:30 -05:00
|
|
|
static gboolean (*iteration)(gboolean) = NULL;
|
|
|
|
|
2015-04-22 12:53:22 -05:00
|
|
|
void uiMain(void)
|
|
|
|
{
|
2016-06-17 08:16:30 -05:00
|
|
|
iteration = gtk_main_iteration_do;
|
2015-04-22 12:53:22 -05:00
|
|
|
gtk_main();
|
|
|
|
}
|
|
|
|
|
2016-06-17 08:16:30 -05:00
|
|
|
static gboolean stepsQuit = FALSE;
|
2016-06-16 12:59:35 -05:00
|
|
|
|
2016-06-17 08:22:31 -05:00
|
|
|
// the only difference is we ignore the return value from gtk_main_iteration_do(), since it will always be TRUE if gtk_main() was never called
|
|
|
|
// gtk_main_iteration_do() will still run the main loop regardless
|
2016-06-17 08:16:30 -05:00
|
|
|
static gboolean stepsIteration(gboolean block)
|
2016-06-16 12:59:35 -05:00
|
|
|
{
|
2016-06-17 08:16:30 -05:00
|
|
|
gtk_main_iteration_do(block);
|
|
|
|
return stepsQuit;
|
2016-06-16 12:59:35 -05:00
|
|
|
}
|
|
|
|
|
2016-06-17 08:22:31 -05:00
|
|
|
void uiMainSteps(void)
|
2016-06-16 12:59:35 -05:00
|
|
|
{
|
2016-06-17 08:16:30 -05:00
|
|
|
iteration = stepsIteration;
|
2016-06-16 12:59:35 -05:00
|
|
|
}
|
|
|
|
|
2016-05-24 21:29:33 -05:00
|
|
|
int uiMainStep(int wait)
|
|
|
|
{
|
|
|
|
gboolean block;
|
|
|
|
|
|
|
|
block = FALSE;
|
|
|
|
if (wait)
|
|
|
|
block = TRUE;
|
2016-06-17 08:16:30 -05:00
|
|
|
return (*iteration)(block) == FALSE;
|
2016-05-24 21:29:33 -05:00
|
|
|
}
|
|
|
|
|
2015-04-22 12:53:22 -05:00
|
|
|
// gtk_main_quit() may run immediately, or it may wait for other pending events; "it depends" (thanks mclasen in irc.gimp.net/#gtk+)
|
|
|
|
// PostQuitMessage() on Windows always waits, so we must do so too
|
|
|
|
// we'll do it by using an idle callback
|
|
|
|
static gboolean quit(gpointer data)
|
|
|
|
{
|
2016-06-17 08:16:30 -05:00
|
|
|
if (iteration == stepsIteration)
|
|
|
|
stepsQuit = TRUE;
|
2016-06-17 08:24:15 -05:00
|
|
|
// TODO run a gtk_main() here just to do the cleanup steps of syncing the clipboard and other stuff gtk_main() does before it returns
|
2016-06-17 08:16:30 -05:00
|
|
|
else
|
|
|
|
gtk_main_quit();
|
2015-04-22 12:53:22 -05:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void uiQuit(void)
|
|
|
|
{
|
|
|
|
gdk_threads_add_idle(quit, NULL);
|
|
|
|
}
|
2015-12-04 22:42:03 -06:00
|
|
|
|
|
|
|
struct queued {
|
|
|
|
void (*f)(void *);
|
|
|
|
void *data;
|
|
|
|
};
|
|
|
|
|
|
|
|
static gboolean doqueued(gpointer data)
|
|
|
|
{
|
|
|
|
struct queued *q = (struct queued *) data;
|
|
|
|
|
|
|
|
(*(q->f))(q->data);
|
2016-10-31 12:38:38 -05:00
|
|
|
g_free(q);
|
2015-12-04 22:42:03 -06:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void uiQueueMain(void (*f)(void *data), void *data)
|
|
|
|
{
|
|
|
|
struct queued *q;
|
|
|
|
|
2018-04-15 15:36:03 -05:00
|
|
|
// we have to use g_new0()/g_free() because uiprivAlloc() is only safe to call on the main thread
|
2016-10-31 12:38:38 -05:00
|
|
|
// for some reason it didn't affect me, but it did affect krakjoe
|
|
|
|
q = g_new0(struct queued, 1);
|
2015-12-04 22:42:03 -06:00
|
|
|
q->f = f;
|
|
|
|
q->data = data;
|
|
|
|
gdk_threads_add_idle(doqueued, q);
|
|
|
|
}
|
2017-08-19 17:32:52 -05:00
|
|
|
|
2017-08-19 17:41:04 -05:00
|
|
|
struct timer {
|
|
|
|
int (*f)(void *);
|
|
|
|
void *data;
|
|
|
|
};
|
|
|
|
|
2018-04-18 20:04:12 -05:00
|
|
|
static gboolean doTimer(gpointer data)
|
2017-08-19 17:41:04 -05:00
|
|
|
{
|
|
|
|
struct timer *t = (struct timer *) data;
|
|
|
|
|
2018-04-18 20:04:12 -05:00
|
|
|
if (!(*(t->f))(t->data)) {
|
|
|
|
uiprivFree(t);
|
2017-08-19 17:41:04 -05:00
|
|
|
return FALSE;
|
|
|
|
}
|
2018-04-18 20:04:12 -05:00
|
|
|
return TRUE;
|
2017-08-19 17:41:04 -05:00
|
|
|
}
|
|
|
|
|
2017-08-19 17:32:52 -05:00
|
|
|
void uiTimer(int milliseconds, int (*f)(void *data), void *data)
|
|
|
|
{
|
2017-08-19 17:41:04 -05:00
|
|
|
struct timer *t;
|
|
|
|
|
2018-04-18 20:04:12 -05:00
|
|
|
t = uiprivNew(struct timer);
|
2017-08-19 17:41:04 -05:00
|
|
|
t->f = f;
|
|
|
|
t->data = data;
|
2018-04-18 20:04:12 -05:00
|
|
|
g_timeout_add(milliseconds, doTimer, t);
|
2017-08-19 17:32:52 -05:00
|
|
|
}
|