diff options
Diffstat (limited to 'numlib')
-rw-r--r-- | numlib/numsup.c | 304 | ||||
-rw-r--r-- | numlib/numsup.h | 85 | ||||
-rw-r--r-- | numlib/ui.c | 205 | ||||
-rw-r--r-- | numlib/ui.h | 13 |
4 files changed, 542 insertions, 65 deletions
diff --git a/numlib/numsup.c b/numlib/numsup.c index c08ed99..39011ae 100644 --- a/numlib/numsup.c +++ b/numlib/numsup.c @@ -51,6 +51,7 @@ char *exe_path = "\000"; /* Directory executable resides in ('/' dir separator //char *error_program = "Unknown"; /* Name to report as responsible for an error */ static int g_log_init = 0; /* Initialised ? */ +static int g_deb_init = 0; /* Debug output Initialised ? */ extern a1log default_log; extern a1log *g_log; @@ -247,9 +248,11 @@ typedef struct { BYTE wReserved; } osversioninfoexw; -#define VER_NT_DOMAIN_CONTROLLER 0x0000002 -#define VER_NT_SERVER 0x0000003 -#define VER_NT_WORKSTATION 0x0000001 +#ifndef VER_NT_DOMAIN_CONTROLLER +# define VER_NT_DOMAIN_CONTROLLER 0x0000002 +# define VER_NT_SERVER 0x0000003 +# define VER_NT_WORKSTATION 0x0000001 +#endif static char *get_sys_info() { static char sysinfo[100] = { "Unknown" }; @@ -328,14 +331,17 @@ static char *get_sys_info() { } -# define A1LOG_LOCK(log) \ +# define A1LOG_LOCK(log, deb) \ if (g_log_init == 0) { \ InitializeCriticalSection(&log->lock); \ EnterCriticalSection(&log->lock); \ g_log_init = 1; \ - va_loge(log, "Argyll 'V%s' Build '%s' System '%s'\n",ARGYLL_VERSION_STR,ARGYLL_BUILD_STR, get_sys_info()); \ } else { \ EnterCriticalSection(&log->lock); \ + } \ + if (deb && !g_deb_init) { \ + va_loge(log, "Argyll 'V%s' Build '%s' System '%s'\n",ARGYLL_VERSION_STR,ARGYLL_BUILD_STR, get_sys_info()); \ + g_deb_init = 1; \ } # define A1LOG_UNLOCK(log) LeaveCriticalSection(&log->lock) #endif @@ -350,14 +356,17 @@ static char *get_sys_info() { return sysinfo; } -# define A1LOG_LOCK(log) \ +# define A1LOG_LOCK(log, deb) \ if (g_log_init == 0) { \ pthread_mutex_init(&log->lock, NULL); \ pthread_mutex_lock(&log->lock); \ g_log_init = 1; \ - va_loge(log, "Argyll 'V%s' Build '%s' System '%s'\n",ARGYLL_VERSION_STR,ARGYLL_BUILD_STR, get_sys_info()); \ } else { \ pthread_mutex_lock(&log->lock); \ + } \ + if (deb && !g_deb_init) { \ + va_loge(log, "Argyll 'V%s' Build '%s' System '%s'\n",ARGYLL_VERSION_STR,ARGYLL_BUILD_STR, get_sys_info()); \ + g_deb_init = 1; \ } # define A1LOG_UNLOCK(log) pthread_mutex_unlock(&log->lock) #endif @@ -485,7 +494,7 @@ void a1logv(a1log *log, int level, char *fmt, ...) { if (log->verb >= level) { va_list args; - A1LOG_LOCK(log); + A1LOG_LOCK(log, 0); va_start(args, fmt); log->logv(log->cntx, log, fmt, args); va_end(args); @@ -500,7 +509,7 @@ void a1logd(a1log *log, int level, char *fmt, ...) { if (log->debug >= level) { va_list args; - A1LOG_LOCK(log); + A1LOG_LOCK(log, 1); va_start(args, fmt); log->loge(log->cntx, log, fmt, args); va_end(args); @@ -515,20 +524,20 @@ void a1logw(a1log *log, char *fmt, ...) { va_list args; /* log to all the outputs, but only log once */ - A1LOG_LOCK(log); + A1LOG_LOCK(log, 0); va_start(args, fmt); log->loge(log->cntx, log, fmt, args); va_end(args); A1LOG_UNLOCK(log); if (log->logd != log->loge) { - A1LOG_LOCK(log); + A1LOG_LOCK(log, 1); va_start(args, fmt); log->logd(log->cntx, log, fmt, args); va_end(args); A1LOG_UNLOCK(log); } if (log->logv != log->loge && log->logv != log->logd) { - A1LOG_LOCK(log); + A1LOG_LOCK(log, 0); va_start(args, fmt); log->logv(log->cntx, log, fmt, args); va_end(args); @@ -545,7 +554,7 @@ void a1loge(a1log *log, int ecode, char *fmt, ...) { va_list args; if (log->errc == 0) { - A1LOG_LOCK(log); + A1LOG_LOCK(log, 0); log->errc = ecode; va_start(args, fmt); vsnprintf(log->errm, A1_LOG_BUFSIZE, fmt, args); @@ -554,20 +563,20 @@ void a1loge(a1log *log, int ecode, char *fmt, ...) { } va_start(args, fmt); /* log to all the outputs, but only log once */ - A1LOG_LOCK(log); + A1LOG_LOCK(log, 0); va_start(args, fmt); log->loge(log->cntx, log, fmt, args); va_end(args); A1LOG_UNLOCK(log); if (log->logd != log->loge) { - A1LOG_LOCK(log); + A1LOG_LOCK(log, 1); va_start(args, fmt); log->logd(log->cntx, log, fmt, args); va_end(args); A1LOG_UNLOCK(log); } if (log->logv != log->loge && log->logv != log->logd) { - A1LOG_LOCK(log); + A1LOG_LOCK(log, 0); va_start(args, fmt); log->logv(log->cntx, log, fmt, args); va_end(args); @@ -640,7 +649,7 @@ verbose(int level, char *fmt, ...) { if (g_log->verb >= level) { va_list args; - A1LOG_LOCK(g_log); + A1LOG_LOCK(g_log, 0); g_logv("%s: ",g_log->tag); va_start(args, fmt); g_log->logv(g_log->cntx, g_log, fmt, args); @@ -654,7 +663,7 @@ void warning(char *fmt, ...) { va_list args; - A1LOG_LOCK(g_log); + A1LOG_LOCK(g_log, 0); g_loge("%s: Warning - ",g_log->tag); va_start(args, fmt); g_log->loge(g_log->cntx, g_log, fmt, args); @@ -667,7 +676,7 @@ ATTRIBUTE_NORETURN void error(char *fmt, ...) { va_list args; - A1LOG_LOCK(g_log); + A1LOG_LOCK(g_log, 0); g_loge("%s: Error - ",g_log->tag); va_start(args, fmt); g_log->loge(g_log->cntx, g_log, fmt, args); @@ -789,7 +798,7 @@ void osx_userinitiated_start() { Class pic; /* Process info class */ SEL pis; /* Process info selector */ SEL bawo; /* Begin Activity With Options selector */ - id pi; /* Process info */ + id pi; /* Process info */ id str; if (osx_userinitiated_cnt++ != 0) @@ -797,7 +806,8 @@ void osx_userinitiated_start() { a1logd(g_log, 7, "OS X - User Initiated Activity start\n"); - /* We have to be conservative to avoid triggering an exception when run on older OS X */ + /* We have to be conservative to avoid triggering an exception when run on older OS X, */ + /* since beginActivityWithOptions is only available in >= 10.9 */ if ((pic = (Class)objc_getClass("NSProcessInfo")) == nil) { return; } @@ -2200,3 +2210,255 @@ void write_INR64_le(ORD8 *p, INR64 d) { p[7] = (ORD8)(d >> 56); } +/*******************************/ +/* System independent timing */ + +#ifdef NT + +/* Sleep for the given number of msec */ +void msec_sleep(unsigned int msec) { + Sleep(msec); +} + +/* Return the current time in msec since */ +/* the first invokation of msec_time() */ +/* (Is this based on timeGetTime() ? ) */ +unsigned int msec_time() { + unsigned int rv; + static unsigned int startup = 0; + + rv = GetTickCount(); + if (startup == 0) + startup = rv; + + return rv - startup; +} + +/* Return the current time in usec */ +/* since the first invokation of usec_time() */ +/* Return -1.0 if not available */ +double usec_time() { + double rv; + LARGE_INTEGER val; + static double scale = 0.0; + static LARGE_INTEGER startup; + + if (scale == 0.0) { + if (QueryPerformanceFrequency(&val) == 0) + return -1.0; + scale = 1000000.0/val.QuadPart; + QueryPerformanceCounter(&val); + startup.QuadPart = val.QuadPart; + + } else { + QueryPerformanceCounter(&val); + } + val.QuadPart -= startup.QuadPart; + + rv = val.QuadPart * scale; + + return rv; +} + +#endif /* NT */ + +#if defined(UNIX) + +/* Sleep for the given number of msec */ +/* (Note that OS X 10.9+ App Nap can wreck this, unless */ +/* it is turned off.) */ +void msec_sleep(unsigned int msec) { +#ifdef NEVER + if (msec > 1000) { + unsigned int secs; + secs = msec / 1000; + msec = msec % 1000; + sleep(secs); + } + usleep(msec * 1000); +#else + struct timespec ts; + + ts.tv_sec = msec / 1000; + ts.tv_nsec = (msec % 1000) * 1000000; + nanosleep(&ts, NULL); +#endif +} + + +#if defined(__APPLE__) && !defined(CLOCK_MONOTONIC) + +#include <mach/mach_time.h> + +unsigned int msec_time() { + mach_timebase_info_data_t timebase; + static uint64_t startup = 0; + uint64_t time; + double msec; + + time = mach_absolute_time(); + if (startup == 0) + startup = time; + + mach_timebase_info(&timebase); + time -= startup; + msec = ((double)time * (double)timebase.numer)/((double)timebase.denom * 1e6); + + return (unsigned int)floor(msec + 0.5); +} + +/* Return the current time in usec */ +/* since the first invokation of usec_time() */ +double usec_time() { + mach_timebase_info_data_t timebase; + static uint64_t startup = 0; + uint64_t time; + double usec; + + time = mach_absolute_time(); + if (startup == 0) + startup = time; + + mach_timebase_info(&timebase); + time -= startup; + usec = ((double)time * (double)timebase.numer)/((double)timebase.denom * 1e3); + + return usec; +} + +#else + +/* Return the current time in msec */ +/* since the first invokation of msec_time() */ +unsigned int msec_time() { + unsigned int rv; + static struct timespec startup = { 0, 0 }; + struct timespec cv; + + clock_gettime(CLOCK_MONOTONIC, &cv); + + /* Set time to 0 on first invocation */ + if (startup.tv_sec == 0 && startup.tv_nsec == 0) + startup = cv; + + /* Subtract, taking care of carry */ + cv.tv_sec -= startup.tv_sec; + if (startup.tv_nsec > cv.tv_nsec) { + cv.tv_sec--; + cv.tv_nsec += 1000000000; + } + cv.tv_nsec -= startup.tv_nsec; + + /* Convert nsec to msec */ + rv = cv.tv_sec * 1000 + cv.tv_nsec / 1000000; + + return rv; +} + +/* Return the current time in usec */ +/* since the first invokation of usec_time() */ +double usec_time() { + double rv; + static struct timespec startup = { 0, 0 }; + struct timespec cv; + + clock_gettime(CLOCK_MONOTONIC, &cv); + + /* Set time to 0 on first invocation */ + if (startup.tv_sec == 0 && startup.tv_nsec == 0) + startup = cv; + + /* Subtract, taking care of carry */ + cv.tv_sec -= startup.tv_sec; + if (startup.tv_nsec > cv.tv_nsec) { + cv.tv_sec--; + cv.tv_nsec += 1000000000; + } + cv.tv_nsec -= startup.tv_nsec; + + /* Convert to usec */ + rv = cv.tv_sec * 1000000.0 + cv.tv_nsec/1000; + + return rv; +} + +#endif + +#endif /* UNIX */ + +/*******************************/ +/* Debug convenience functions */ +/*******************************/ + +#define DEB_MAX_CHAN 15 + +/* Print an int vector to a string. */ +/* Returned static buffer is re-used every 5 calls. */ +char *debPiv(int di, int *p) { + static char buf[5][DEB_MAX_CHAN * 16]; + static int ix = 0; + int e; + char *bp; + + if (++ix >= 5) + ix = 0; + bp = buf[ix]; + + if (di > DEB_MAX_CHAN) + di = DEB_MAX_CHAN; /* Make sure that buf isn't overrun */ + + for (e = 0; e < di; e++) { + if (e > 0) + *bp++ = ' '; + sprintf(bp, "%d", p[e]); bp += strlen(bp); + } + return buf[ix]; +} + +/* Print a double color vector to a string. */ +/* Returned static buffer is re-used every 5 calls. */ +char *debPdv(int di, double *p) { + static char buf[5][DEB_MAX_CHAN * 16]; + static int ix = 0; + int e; + char *bp; + + if (++ix >= 5) + ix = 0; + bp = buf[ix]; + + if (di > DEB_MAX_CHAN) + di = DEB_MAX_CHAN; /* Make sure that buf isn't overrun */ + + for (e = 0; e < di; e++) { + if (e > 0) + *bp++ = ' '; + sprintf(bp, "%.8f", p[e]); bp += strlen(bp); + } + return buf[ix]; +} + +/* Print a float color vector to a string. */ +/* Returned static buffer is re-used every 5 calls. */ +char *debPfv(int di, float *p) { + static char buf[5][DEB_MAX_CHAN * 16]; + static int ix = 0; + int e; + char *bp; + + if (++ix >= 5) + ix = 0; + bp = buf[ix]; + + if (di > DEB_MAX_CHAN) + di = DEB_MAX_CHAN; /* Make sure that buf isn't overrun */ + + for (e = 0; e < di; e++) { + if (e > 0) + *bp++ = ' '; + sprintf(bp, "%.8f", p[e]); bp += strlen(bp); + } + return buf[ix]; +} + +#undef DEB_MAX_CHAN diff --git a/numlib/numsup.h b/numlib/numsup.h index 366763d..9d55daf 100644 --- a/numlib/numsup.h +++ b/numlib/numsup.h @@ -43,9 +43,9 @@ /* so long shouldn't really be used in any code.... */ /* (duplicated in icc.h) */ -/* Use __LP64__ as cross platform 64 bit pointer #define */ -#if !defined(__LP64__) && defined(_WIN64) -# define __LP64__ 1 +/* Use __P64__ as cross platform 64 bit pointer #define */ +#if defined(__LP64__) || defined(__ILP64__) || defined(__LLP64__) || defined(_WIN64) +# define __P64__ 1 #endif #ifndef ORD32 @@ -59,17 +59,25 @@ #define INR8 int8_t /* 8 bit signed */ #define INR16 int16_t /* 16 bit signed */ #define INR32 int32_t /* 32 bit signed */ -#define INR64 int64_t /* 64 bit signed - not used in icclib */ +#define INR64 int64_t /* 64 bit signed */ #define ORD8 uint8_t /* 8 bit unsigned */ #define ORD16 uint16_t /* 16 bit unsigned */ #define ORD32 uint32_t /* 32 bit unsigned */ -#define ORD64 uint64_t /* 64 bit unsigned - not used in icclib */ +#define ORD64 uint64_t /* 64 bit unsigned */ #define PNTR intptr_t #define PF64PREC "ll" /* printf format precision specifier */ #define CF64PREC "LL" /* Constant precision specifier */ +#ifndef ATTRIBUTE_NORETURN +# ifdef _MSC_VER +# define ATTRIBUTE_NORETURN __declspec(noreturn) +# else +# define ATTRIBUTE_NORETURN __attribute__((noreturn)) +# endif +#endif + #else /* !__STDC_VERSION__ */ #ifdef _MSC_VER @@ -77,17 +85,21 @@ #define INR8 __int8 /* 8 bit signed */ #define INR16 __int16 /* 16 bit signed */ #define INR32 __int32 /* 32 bit signed */ -#define INR64 __int64 /* 64 bit signed - not used in icclib */ +#define INR64 __int64 /* 64 bit signed */ #define ORD8 unsigned __int8 /* 8 bit unsigned */ #define ORD16 unsigned __int16 /* 16 bit unsigned */ #define ORD32 unsigned __int32 /* 32 bit unsigned */ -#define ORD64 unsigned __int64 /* 64 bit unsigned - not used in icclib */ +#define ORD64 unsigned __int64 /* 64 bit unsigned */ #define PNTR UINT_PTR #define PF64PREC "I64" /* printf format precision specifier */ #define CF64PREC "LL" /* Constant precision specifier */ +#ifndef ATTRIBUTE_NORETURN +# define ATTRIBUTE_NORETURN __declspec(noreturn) +#endif + #else /* !_MSC_VER */ /* The following works on a lot of modern systems, including */ @@ -101,29 +113,28 @@ #define ORD32 unsigned int /* 32 bit unsigned */ #ifdef __GNUC__ -# define INR64 long long /* 64 bit signed - not used in icclib */ -# define ORD64 unsigned long long /* 64 bit unsigned - not used in icclib */ -# define PF64PREC "ll" /* printf format precision specifier */ -# define CF64PREC "LL" /* Constant precision specifier */ +# ifdef __LP64__ /* long long could be 128 bit ? */ +# define INR64 long /* 64 bit signed */ +# define ORD64 unsigned long /* 64 bit unsigned */ +# define PF64PREC "l" /* printf format precision specifier */ +# define CF64PREC "L" /* Constant precision specifier */ +# else +# define INR64 long long /* 64 bit signed */ +# define ORD64 unsigned long long /* 64 bit unsigned */ +# define PF64PREC "ll" /* printf format precision specifier */ +# define CF64PREC "LL" /* Constant precision specifier */ +# endif /* !__LP64__ */ #endif /* __GNUC__ */ #define PNTR unsigned long -#endif /* !_MSC_VER */ -#endif /* !__STDC_VERSION__ */ -#endif /* !ORD32 */ - -#ifdef _MSC_VER -#ifndef ATTRIBUTE_NORETURN -# define ATTRIBUTE_NORETURN __declspec(noreturn) -#endif -#endif - -#ifdef __GNUC__ #ifndef ATTRIBUTE_NORETURN # define ATTRIBUTE_NORETURN __attribute__((noreturn)) #endif -#endif + +#endif /* !_MSC_VER */ +#endif /* !__STDC_VERSION__ */ +#endif /* !ORD32 */ /* =========================================================== */ /* System compatibility #defines */ @@ -517,6 +528,34 @@ void write_INR64_be(ORD8 *p, INR64 d); void write_INR64_le(ORD8 *p, INR64 d); /*******************************************/ + +/* Sleep for the given number of msec */ +void msec_sleep(unsigned int msec); + +/* Return the current time in msec since */ +/* the first invokation of msec_time() */ +unsigned int msec_time(); + +/* Return the current time in usec */ +/* (The first invokation of usec_time() returns zero) */ +double usec_time(); + +/*******************************************/ +/* Debug convenience functions (duplicated in icc) */ + +/* Print an int vector to a string. */ +/* Returned static buffer is re-used every 5 calls. */ +char *debPiv(int di, int *p); + +/* Print a double color vector to a string. */ +/* Returned static buffer is re-used every 5 calls. */ +char *debPdv(int di, double *p); + +/* Print a float color vector to a string. */ +/* Returned static buffer is re-used every 5 calls. */ +char *debPfv(int di, float *p); + +/*******************************************/ /* Numerical diagnostics */ #ifndef isNan diff --git a/numlib/ui.c b/numlib/ui.c index a3cdbe8..390a332 100644 --- a/numlib/ui.c +++ b/numlib/ui.c @@ -32,6 +32,8 @@ main thread, spawn a secondary thread to run the application main(), and then do nothing but service the events in the main thread. + We can also pass functions back to be run in the main thread, + and wait for events in the main thread to be processed. Note though that Cocoa has poor thread safety :- ie. NSRunLoop can't be used to access events - use CFRunLoop @@ -45,6 +47,7 @@ # include <stdio.h> # include <stdlib.h> # include <pthread.h> +# include "ui.h" # include <Foundation/Foundation.h> # include <AppKit/AppKit.h> @@ -66,6 +69,10 @@ static char **g_argv; pthread_t ui_thid = 0; /* Thread ID of main thread running io run loop */ pthread_t ui_main_thid = 0; /* Thread ID of thread running application main() */ +static pthread_mutex_t ui_lock1, ui_lock2; /* Protect wait code */ +static pthread_cond_t ui_cond1, ui_cond2; /* Signal to waiting thread */ +static int ui_event1 = 0, ui_event2 = 0; /* Sync event was received */ + extern int uimain(int argc, char *argv[]); /* Thread that calls the real application main() */ @@ -79,12 +86,21 @@ static void *callMain(void *p) { /* Turn App Nap off */ osx_userinitiated_start(); + /* Should we catch and report exceptions ? */ + rv = uimain(g_argc, g_argv); + /* Restore App Nap state */ osx_userinitiated_end(); [tpool release]; + /* Cleanup, since main thread won't return */ + pthread_cond_destroy(&ui_cond1); + pthread_cond_destroy(&ui_cond2); + pthread_mutex_destroy(&ui_lock1); + pthread_mutex_destroy(&ui_lock2); + exit(rv); } @@ -101,37 +117,24 @@ static void *callMain(void *p) { int main(int argc, char ** argv) { + pthread_mutex_init(&ui_lock1, NULL); + pthread_mutex_init(&ui_lock2, NULL); + pthread_cond_init(&ui_cond1, NULL); + pthread_cond_init(&ui_cond2, NULL); + ui_thid = pthread_self(); /* Create an NSApp */ static NSAutoreleasePool *pool = nil; - ProcessSerialNumber psn = { 0, 0 }; - - /* Transform the process so that the desktop interacts with it properly. */ - /* We don't need resources or a bundle if we do this. */ - if (GetCurrentProcess(&psn) == noErr) { - OSStatus stat; - if (psn.lowLongOfPSN != 0 && (stat = TransformProcessType(&psn, - kProcessTransformToForegroundApplication)) != noErr) { -// fprintf(stderr,"TransformProcess failed with code %d\n",stat); - } else { -// fprintf(stderr,"TransformProcess suceeded\n"); - } -// if ((stat = SetFrontProcess(&psn)) != noErr) { -// fprintf(stderr,"SetFrontProcess returned error %d\n",stat); -// } - } pool = [NSAutoreleasePool new]; [NSApplication sharedApplication]; /* Creates NSApp */ - [NSApp finishLaunching]; - /* We seem to need this, because otherwise we don't get focus automatically */ - [NSApp activateIgnoringOtherApps: YES]; + [NSApp finishLaunching]; /* We need to create at least one NSThread to tell Cocoa that we are using */ - /* threads, and to protect Cococa objects. */ + /* threads, and to protect Cococa objects. (We don't actually have to start the thread.) */ [NSThread detachNewThreadSelector:@selector(dummyfunc:) toTarget:[MainClass class] withObject:nil]; /* Call the real main() in another thread */ @@ -156,13 +159,163 @@ int main(int argc, char ** argv) { } /* Service the run queue */ - [NSApp run]; + { + NSEvent *event; + NSDate *to; + + /* Process events, looking for application events. */ + for (;;) { + /* Hmm. Assume to is autorelease */ + to = [NSDate dateWithTimeIntervalSinceNow:1.0]; + /* Hmm. Assume event is autorelease */ + if ((event = [NSApp nextEventMatchingMask:NSAnyEventMask + untilDate:to inMode:NSDefaultRunLoopMode dequeue:YES]) != nil) { + + /* call function message */ + if ([event type] == NSApplicationDefined + && [event subtype] == 1) { + void *cntx = (void *)[event data1]; + void (*function)(void *cntx) = (void (*)(void *)) [event data2]; + + function(cntx); + + pthread_mutex_lock(&ui_lock1); + ui_event1 = 1; + pthread_cond_signal(&ui_cond1); + pthread_mutex_unlock(&ui_lock1); + [event release]; + + /* event flush message */ + } else if ([event type] == NSApplicationDefined + && [event subtype] == 2) { + pthread_mutex_lock(&ui_lock2); + ui_event2 = 1; + pthread_cond_signal(&ui_cond2); + pthread_mutex_unlock(&ui_lock2); + [event release]; + + /* Everything else */ + } else { + [NSApp sendEvent:event]; + } + } + } + } /* Note that we don't actually clean this up on exit - */ /* possibly we can't. */ // [NSApp terminate: nil]; } +/* Call this if we decide we are actually going to display something in the GUI. */ +/* We switch to "interact with the Dock" mode. */ +void ui_UsingGUI() { + static int attached = 0; + ProcessSerialNumber psn = { 0, 0 }; + + if (!attached) { +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 + /* Make the application appear in the Dock, and interact with the desktop properly. */ + /* (Unbundled applications default to NSApplicationActivationPolicyProhibited) */ + [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; + +#else +# if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 + /* Make the application appear in the Dock, and interact with the desktop properly. */ + /* We don't need resources or a bundle if we do this. */ + if (GetCurrentProcess(&psn) == noErr) { + OSStatus stat; + if (psn.lowLongOfPSN != 0 && (stat = TransformProcessType(&psn, + kProcessTransformToForegroundApplication)) != noErr) { + fprintf(stderr,"TransformProcess failed with code %d\n",stat); + + /* An older trick uses an undocumented API: + CPSEnableForegroundOperation(&processSerialNum, 0, 0, 0, 0); + */ + } else { + // fprintf(stderr,"TransformProcess suceeded\n"); + } + } +# endif /* OS X 10.3 */ +#endif /* !OS X 10.6 */ + + /* We seem to need this, because otherwise we don't get focus automatically */ + [NSApp activateIgnoringOtherApps: YES]; + + attached = 1; + } +} + +/* Run a function in the main thread and return when it is complete. */ +/* (It's up to the function to record it's result status in its context) */ +void ui_runInMainThreadAndWait(void *cntx, void (*function)(void *cntx)) { + + NSEvent *event; + NSPoint point = { 0.0, 0.0 }; + int rv; + + pthread_mutex_lock(&ui_lock1); + ui_event1 = 0; + + event = [NSEvent otherEventWithType:NSApplicationDefined + location:point + modifierFlags:0 + timestamp:0.0 + windowNumber:0 + context:nil + subtype:1 + data1:(long)cntx /* long same size as * */ + data2:(long)function]; + [NSApp postEvent:event atStart:NO]; + + // unlock and wait for signal + for (;;) { /* Ignore spurious wakeups */ + if ((rv = pthread_cond_wait(&ui_cond1, &ui_lock1)) != 0) { + break; // Hmm. + } + if (ui_event1) /* Got what we were waiting for */ + break; + } + pthread_mutex_unlock(&ui_lock1); +} + + +/* We are about to change the UI */ +void ui_aboutToWait() { + + pthread_mutex_lock(&ui_lock2); + ui_event2 = 0; +} + +/* Wait until we are sure our UI change is complete, */ +/* because our event has trickled through. */ +void ui_waitForEvents() { + NSEvent *event; + NSPoint point = { 0.0, 0.0 }; + int rv; + + event = [NSEvent otherEventWithType:NSApplicationDefined + location:point + modifierFlags:0 + timestamp:0.0 + windowNumber:0 + context:nil + subtype:2 + data1:0 + data2:0]; + [NSApp postEvent:event atStart:NO]; + + // unlock and wait for signal + for (;;) { /* Ignore spurious wakeups */ + if ((rv = pthread_cond_wait(&ui_cond2, &ui_lock2)) != 0) { + break; // Hmm. + } + if (ui_event2) /* Got what we were waiting for */ + break; + } + pthread_mutex_unlock(&ui_lock2); +} + #else /* !APPLE */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - */ @@ -171,6 +324,11 @@ int main(int argc, char ** argv) { /* This is a mechanism to force libui to link */ int ui_initialized = 1; /* Nothing needs initializing */ +/* Call this if we decide we are actually going to display */ +/* something in the GUI */ +void ui_UsingGUI() { +} + #endif /* !APPLE */ #endif /* UNIX */ @@ -262,4 +420,9 @@ int ui_initialized = 1; /* Nothing needs initializing */ #endif /* !NEVER */ +/* Call this if we decide we are actually going to display */ +/* something in the GUI */ +void ui_UsingGUI() { +} + #endif /* NT */ diff --git a/numlib/ui.h b/numlib/ui.h index e1d7a58..a282c26 100644 --- a/numlib/ui.h +++ b/numlib/ui.h @@ -21,12 +21,25 @@ extern int ui_initialized; static int *pui_initialized = &ui_initialized; +/* Call this if we decide we are actually going to display */ +/* something in the GUI */ +void ui_UsingGUI(); + #ifdef UNIX # ifdef __APPLE__ extern pthread_t ui_thid; /* Thread ID of main thread running io run loop */ extern pthread_t ui_main_thid; /* Thread ID of thread running application main() */ +/* Run a function in the main thread and return when it is complete */ +void ui_runInMainThreadAndWait(void *cntx, void (*function)(void *context)); + +/* We are about to change the UI */ +void ui_aboutToWait(); + +/* Wait until we are sure our UI change is complete */ +void ui_waitForEvents(); + #ifndef __UI_C__ # define main uimain #endif |