From 2676d1e94ec6378c85891ae48e7370fc2ade4050 Mon Sep 17 00:00:00 2001 From: Rejean Loyer Date: Wed, 9 Dec 2015 17:31:28 -0500 Subject: [PATCH] ecere,ecereCOM: support Emscriptem platform. add new Emscripten interface driver. - had to move GetDisplayDriver and GetDisplaySystem to end of Display.ec file due to compiler issue - #if !defined(__EMSCRIPTEN__) out: - dynamic loading - thread/mutex/semaphore and Condition class - file monitoring - png/jpeg/gif - X driver - NCurses driver - dcom - add emscripten_main_loop_callback in GuiApplication.ec - use of glfw and a bit of tweaking in the OpenGL driver --- ecere/ecere.epj | 59 +++++- ecere/ecereCOM.epj | 13 +- ecere/src/com/String.ec | 2 +- ecere/src/com/containers/Array.ec | 1 + ecere/src/com/containers/Map.ec | 2 + ecere/src/com/instance.c | 30 +-- ecere/src/com/instance.ec | 16 +- ecere/src/gfx/Display.ec | 51 +++-- ecere/src/gfx/DisplaySystem.ec | 8 + ecere/src/gfx/bitmaps/GIFFormat.ec | 8 +- ecere/src/gfx/bitmaps/PNGFormat.ec | 4 + ecere/src/gfx/drivers/NCursesDisplayDriver.ec | 2 +- ecere/src/gfx/drivers/XDisplayDriver.ec | 4 +- ecere/src/gui/Desktop3D.ec | 2 + ecere/src/gui/GuiApplication.ec | 96 ++++++++- ecere/src/gui/Window.ec | 36 ++++ ecere/src/gui/drivers/EmscriptenInterface.ec | 287 ++++++++++++++++++++++++++ ecere/src/gui/drivers/NCursesInterface.ec | 2 +- ecere/src/gui/drivers/XInterface.ec | 10 +- ecere/src/gui/skins/WindowsSkin.ec | 4 +- ecere/src/net/dcom.ec | 4 + ecere/src/sys/Condition.ec | 8 + ecere/src/sys/EARArchive.ec | 4 +- ecere/src/sys/FileMonitor.ec | 4 + ecere/src/sys/GlobalAppSettings.ec | 10 + ecere/src/sys/JSON.ec | 1 + ecere/src/sys/Mutex.ec | 16 +- ecere/src/sys/Semaphore.ec | 17 ++ ecere/src/sys/System.ec | 6 + ecere/src/sys/Thread.ec | 17 +- ecere/src/sys/i18n.ec | 3 +- samples/guiAndGfx/HelloForm/helloForm.ec | 2 +- samples/guiAndGfx/HelloForm/helloForm.epj | 23 +++ 33 files changed, 689 insertions(+), 63 deletions(-) create mode 100644 ecere/src/gui/drivers/EmscriptenInterface.ec diff --git a/ecere/ecere.epj b/ecere/ecere.epj index d981c99..819cdfc 100644 --- a/ecere/ecere.epj +++ b/ecere/ecere.epj @@ -474,6 +474,18 @@ if distributed with the Ecere SDK Windows installer. ], "FastMath" : true } + }, + { + "Name" : "Emscripten", + "Options" : { + "Debug" : true, + "PreprocessorDefinitions" : [ + "ECERE_STATIC", + "NOBLENDING" + ], + "TargetType" : "StaticLibrary", + "TargetFileName" : "ecereStatic" + } } ], "Files" : [ @@ -734,6 +746,12 @@ if distributed with the Ecere SDK Windows installer. "Options" : { "ExcludeFromBuild" : true } + }, + { + "Name" : "Emscripten", + "Options" : { + "ExcludeFromBuild" : true + } } ] }, @@ -756,6 +774,12 @@ if distributed with the Ecere SDK Windows installer. } } ] + }, + { + "Name" : "Emscripten", + "Options" : { + "ExcludeFromBuild" : true + } } ] }, @@ -770,7 +794,17 @@ if distributed with the Ecere SDK Windows installer. } ] }, - "PNGFormat.ec", + { + "FileName" : "PNGFormat.ec", + "Configurations" : [ + { + "Name" : "Emscripten", + "Options" : { + "ExcludeFromBuild" : true + } + } + ] + }, { "FileName" : "RGBFormat.ec", "Configurations" : [ @@ -796,6 +830,12 @@ if distributed with the Ecere SDK Windows installer. } } ] + }, + { + "Name" : "Emscripten", + "Options" : { + "ExcludeFromBuild" : true + } } ] } @@ -2226,6 +2266,17 @@ if distributed with the Ecere SDK Windows installer. } } ] + }, + { + "FileName" : "EmscriptenInterface.ec", + "Configurations" : [ + { + "Name" : "Emscripten", + "Options" : { + "ExcludeFromBuild" : false + } + } + ] } ], "Options" : { @@ -2421,6 +2472,12 @@ if distributed with the Ecere SDK Windows installer. } } ] + }, + { + "Name" : "Emscripten", + "Options" : { + "ExcludeFromBuild" : true + } } ] }, diff --git a/ecere/ecereCOM.epj b/ecere/ecereCOM.epj index 587efcf..5166b8c 100644 --- a/ecere/ecereCOM.epj +++ b/ecere/ecereCOM.epj @@ -70,13 +70,24 @@ ], "TargetType" : "StaticLibrary", "TargetFileName" : "ecereCOMStatic", - "TargetDirectory" : "ecereCOMStatic", "ObjectsDirectory" : "ecereCOMStatic", "Libraries" : [ ], "FastMath" : true } + }, + { + "Name" : "Emscripten", + "Options" : { + "Optimization" : "Size", + "PreprocessorDefinitions" : [ + "ECERE_STATIC", + "ECERE_COM_ONLY" + ], + "TargetType" : "StaticLibrary", + "TargetFileName" : "ecereCOMStatic" + } } ], "Files" : [ diff --git a/ecere/src/com/String.ec b/ecere/src/com/String.ec index 4d5b832..2c10ae1 100644 --- a/ecere/src/com/String.ec +++ b/ecere/src/com/String.ec @@ -9,7 +9,7 @@ default: #undef __BLOCKS__ #include #if !defined(ECERE_BOOTSTRAP) // quick fix for now -#if defined(__WIN32__) +#if defined(__WIN32__) && !defined(__EMSCRIPTEN__) #define WIN32_LEAN_AND_MEAN #define String _String #include diff --git a/ecere/src/com/containers/Array.ec b/ecere/src/com/containers/Array.ec index 5bbf4c3..ee65836 100644 --- a/ecere/src/com/containers/Array.ec +++ b/ecere/src/com/containers/Array.ec @@ -1,5 +1,6 @@ namespace com; +import "instance" import "Container" #ifdef _DEBUG diff --git a/ecere/src/com/containers/Map.ec b/ecere/src/com/containers/Map.ec index 3cd9bf4..57c6400 100644 --- a/ecere/src/com/containers/Map.ec +++ b/ecere/src/com/containers/Map.ec @@ -1,6 +1,8 @@ namespace com; +#if !defined(_DEBUG) || defined(MEMINFO) import "instance" // TOFIX: This is required to build Debug on Ubuntu 10.04, GCC 4.4.3 +#endif import "CustomAVLTree" default: diff --git a/ecere/src/com/instance.c b/ecere/src/com/instance.c index a9f3c25..3539e8d 100644 --- a/ecere/src/com/instance.c +++ b/ecere/src/com/instance.c @@ -24,7 +24,7 @@ #undef bool #endif -#if defined(__WIN32__) +#if defined(__WIN32__) && !defined(__EMSCRIPTEN__) #define WIN32_LEAN_AND_MEAN #define UNICODE #include @@ -54,14 +54,14 @@ typedef unsigned long long uint64; __declspec(dllexport) int isblank(int c) { return c == '\t' || c == ' '; } #endif -#if defined(__WIN32__) +#if defined(__WIN32__) && !defined(__EMSCRIPTEN__) intptr_t stdinHandle, stdoutHandle; int osfStdin, osfStdout; FILE * fStdIn, * fStdOut; #endif FILE *eC_stdin(void) { -#if defined(__WIN32__) +#if defined(__WIN32__) && !defined(__EMSCRIPTEN__) if(!fStdIn) { stdinHandle = (intptr_t)GetStdHandle(STD_INPUT_HANDLE); @@ -137,7 +137,7 @@ extern struct __ecereNameSpace__ecere__com__Instance * __thisModule; typedef enum { unknown, win32, tux, apple } Platform; -#if defined(__WIN32__) +#if defined(__WIN32__) && !defined(__EMSCRIPTEN__) Platform runtimePlatform = win32; #elif defined(__APPLE__) Platform runtimePlatform = apple; @@ -190,7 +190,7 @@ static bool DualPipe_GetLine(FILE * p, char *s, int max) bool Instance_LocateModule(const char * name, char * fileName) { -#if defined(__WIN32__) +#if defined(__WIN32__) && !defined(__EMSCRIPTEN__) HMODULE hModule = null; if(name && name[0]) { @@ -248,7 +248,7 @@ bool Instance_LocateModule(const char * name, char * fileName) } #elif defined(__unix__) //File f = FileOpen("/proc/self/maps", read); - FILE * f; + FILE * f = null; char exeName[MAX_FILENAME]; exeName[0] = 0; #if defined(__linux__) @@ -325,7 +325,7 @@ bool Instance_LocateModule(const char * name, char * fileName) } fclose(f); } -#if !defined(ECERE_NOFILE) && !defined(__linux__) +#if !defined(ECERE_NOFILE) && !defined(__linux__) && !defined(__EMSCRIPTEN__) if(name && name[0]) { // Couldn't locate libraries with /proc/curmap/map, attempt with ldd @@ -404,11 +404,11 @@ bool Instance_LocateModule(const char * name, char * fileName) void Instance_COM_Initialize(int argc, char ** argv, char ** parsedCommand, int * argcPtr, const char *** argvPtr) { -#if !defined(__WIN32__) && !defined(ECERE_BOOTSTRAP) +#if !defined(__WIN32__) && !defined(__EMSCRIPTEN__) && !defined(ECERE_BOOTSTRAP) // Disable stdout buffering on Unix setvbuf(stdout, null, _IONBF, 0); #endif -#if defined(__WIN32__) +#if defined(__WIN32__) && !defined(__EMSCRIPTEN__) *parsedCommand = UTF16toUTF8(GetCommandLineW()); *argvPtr = eSystem_New0(sizeof(char *) * 512); *argcPtr = Tokenize(*parsedCommand, 512,(void*)(char **)(*argvPtr), forArgsPassing); @@ -439,7 +439,7 @@ void * Instance_Module_Load(const char * libLocation, const char * name, void ** *Load = null; *Unload = null; -#if defined(__WIN32__) +#if defined(__WIN32__) && !defined(__EMSCRIPTEN__) strcpy(fileName, name); GetExtension(fileName, extension); if(!extension[0]) @@ -476,7 +476,9 @@ void * Instance_Module_Load(const char * libLocation, const char * name, void ** strcat(fileName, ".so"); #endif +#if !defined(__EMSCRIPTEN__) library = dlopen(fileName, RTLD_LAZY); +#endif while(!library && attempts < sizeof(paths)/sizeof(paths[0])) { if(paths[attempts]) @@ -499,15 +501,19 @@ void * Instance_Module_Load(const char * libLocation, const char * name, void ** #else strcat(fileName, ".so"); #endif +#if !defined(__EMSCRIPTEN__) library = dlopen(fileName, RTLD_LAZY); +#endif } if(library) { *Load = dlsym(library, "__ecereDll_Load"); *Unload = dlsym(library, "__ecereDll_Unload"); +#if !defined(__EMSCRIPTEN__) if(!*Load) dlclose(library); +#endif } #elif defined(__APPLE__) if(libLocation || strchr(name, '/')) @@ -550,10 +556,10 @@ void * Instance_Module_Load(const char * libLocation, const char * name, void ** void Instance_Module_Free(void * library) { -#if defined(__WIN32__) +#if defined(__WIN32__) && !defined(__EMSCRIPTEN__) if(library) FreeLibrary(library); -#elif defined(__unix__) || defined(__APPLE__) +#elif (defined(__unix__) || defined(__APPLE__)) && !defined(__EMSCRIPTEN__) if(library) dlclose(library); #endif diff --git a/ecere/src/com/instance.ec b/ecere/src/com/instance.ec index 1a887ee..ae6b6b3 100644 --- a/ecere/src/com/instance.ec +++ b/ecere/src/com/instance.ec @@ -20,9 +20,11 @@ import "dataTypes" #undef __BLOCKS__ +#if !defined(__EMSCRIPTEN__) #if !defined(ECERE_BOOTSTRAP) import "Mutex" #endif +#endif // #define MEMINFO /* @@ -43,7 +45,9 @@ import "Mutex" #endif #ifdef MEMINFO +#if !defined(__EMSCRIPTEN__) import "Thread" +#endif static define MAX_MEMORY_LOC = 40; static define MAX_STACK_FRAMES = 1000; @@ -189,7 +193,9 @@ public dllexport void MemoryGuard_PushLoc(const char * loc) { #ifdef MEMINFO MemStack stack; +#if !defined(__EMSCRIPTEN__) memMutex.Wait(); +#endif stack = (MemStack)memStacks.Find(GetCurrentThreadID()); if(!stack) { @@ -199,22 +205,28 @@ public dllexport void MemoryGuard_PushLoc(const char * loc) } if(stack.pos < MAX_STACK_FRAMES) stack.frames[stack.pos++] = loc; +#if !defined(__EMSCRIPTEN__) memMutex.Release(); #endif +#endif } public dllexport void MemoryGuard_PopLoc() { #ifdef MEMINFO MemStack stack; +#if !defined(__EMSCRIPTEN__) memMutex.Wait(); +#endif stack = (MemStack)memStacks.Find(GetCurrentThreadID()); if(stack && stack.pos > 0) { stack.pos--; } +#if !defined(__EMSCRIPTEN__) memMutex.Release(); #endif +#endif } #ifdef ECERE_STATIC @@ -713,9 +725,11 @@ static uint TOTAL_MEM = 0; static uint OUTSIDE_MEM = 0; #endif +#if !defined(__EMSCRIPTEN__) #if !defined(ECERE_BOOTSTRAP) static Mutex memMutex { }; #endif +#endif private class MemBlock : struct { @@ -5932,7 +5946,7 @@ static int64 GetEnumSize(Class _class) #define strnicmp strncasecmp #endif -#if defined(ECERE_BOOTSTRAP) || (defined(__GNUC__) && !defined(__DJGPP__) && !defined(__WIN32__)) +#if defined(ECERE_BOOTSTRAP) || (defined(__GNUC__) && !defined(__DJGPP__) && !defined(__WIN32__) && !defined(__EMSCRIPTEN__)) #undef strlwr #undef strupr default dllexport char * strlwr(char *string) diff --git a/ecere/src/gfx/Display.ec b/ecere/src/gfx/Display.ec index ed36ecb..d572904 100644 --- a/ecere/src/gfx/Display.ec +++ b/ecere/src/gfx/Display.ec @@ -48,7 +48,9 @@ public class FontFlags __attribute__((unused)) static void DummyFunction() { +#if !defined(__EMSCRIPTEN__) Mutex { }; +#endif } public class DisplayDriver @@ -179,27 +181,6 @@ public: public enum Alignment { left, right, center }; public enum ClearType { colorBuffer, depthBuffer, colorAndDepth }; -subclass(DisplayDriver) GetDisplayDriver(const char * driverName) -{ - if(driverName) - { - OldLink link; - for(link = class(DisplayDriver).derivatives.first; link; link = link.next) - { - subclass(DisplayDriver) displayDriver = link.data; - if(displayDriver && displayDriver.name && !strcmp(displayDriver.name, driverName)) - return displayDriver; - } - } - return null; -} - -DisplaySystem GetDisplaySystem(const char * driverName) -{ - subclass(DisplayDriver) displayDriver = GetDisplayDriver(driverName); - return displayDriver ? displayDriver.displaySystem : null; -} - define textCellW = 8; define textCellH = 16; @@ -549,7 +530,9 @@ public: result = displaySystem && displaySystem.Lock(); if(result && render) { +#if !defined(__EMSCRIPTEN__) mutex.Wait(); +#endif if(!current) result = displaySystem.driver.Lock(this); @@ -575,7 +558,9 @@ public: */ if(!current && displaySystem) displaySystem.driver.Unlock(this); +#if !defined(__EMSCRIPTEN__) mutex.Release(); +#endif } if(displaySystem) displaySystem.Unlock(); @@ -1128,7 +1113,9 @@ private: DisplaySystem displaySystem; void * window; +#if !defined(__EMSCRIPTEN__) Mutex mutex { }; +#endif int current; #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D) @@ -1909,3 +1896,25 @@ public int BestColorMatch(ColorAlpha * palette, int start, int end, Color rgb) } return best; } + +// had to move this here due to compiler ordering issue for "get property" symbol +subclass(DisplayDriver) GetDisplayDriver(const char * driverName) +{ + if(driverName) + { + OldLink link; + for(link = class(DisplayDriver).derivatives.first; link; link = link.next) + { + subclass(DisplayDriver) displayDriver = link.data; + if(displayDriver && displayDriver.name && !strcmp(displayDriver.name, driverName)) + return displayDriver; + } + } + return null; +} + +DisplaySystem GetDisplaySystem(const char * driverName) +{ + subclass(DisplayDriver) displayDriver = GetDisplayDriver(driverName); + return displayDriver ? displayDriver.displaySystem : null; +} diff --git a/ecere/src/gfx/DisplaySystem.ec b/ecere/src/gfx/DisplaySystem.ec index f043da2..7b008eb 100644 --- a/ecere/src/gfx/DisplaySystem.ec +++ b/ecere/src/gfx/DisplaySystem.ec @@ -1,6 +1,8 @@ namespace gfx; +#if !defined(__EMSCRIPTEN__) import "Mutex" +#endif import "Display" const String printingDocumentName; @@ -168,7 +170,9 @@ public: bool Lock() { bool result = false; +#if !defined(__EMSCRIPTEN__) mutex.Wait(); +#endif if(!current) result = driver.LockSystem(this); @@ -184,7 +188,9 @@ public: if(!current) driver.UnlockSystem(this); +#if !defined(__EMSCRIPTEN__) mutex.Release(); +#endif } #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D) // --- Materials List Management --- @@ -329,5 +335,7 @@ private: void * driverData; int current; +#if !defined(__EMSCRIPTEN__) Mutex mutex { }; +#endif }; diff --git a/ecere/src/gfx/bitmaps/GIFFormat.ec b/ecere/src/gfx/bitmaps/GIFFormat.ec index 9d81af9..681692d 100644 --- a/ecere/src/gfx/bitmaps/GIFFormat.ec +++ b/ecere/src/gfx/bitmaps/GIFFormat.ec @@ -1,9 +1,11 @@ namespace gfx::bitmaps; -#include "gif_lib.h" - import "Display" +#if !defined(__EMSCRIPTEN__) + +#include "gif_lib.h" + static int ReadData(GifFileType * gifFile, GifByteType * bytes, int size) { File f = gifFile->UserData; @@ -129,3 +131,5 @@ class GIFFormat : BitmapFormat return result; } } + +#endif // !defined(__EMSCRIPTEN__) diff --git a/ecere/src/gfx/bitmaps/PNGFormat.ec b/ecere/src/gfx/bitmaps/PNGFormat.ec index 22de51a..95e596e 100644 --- a/ecere/src/gfx/bitmaps/PNGFormat.ec +++ b/ecere/src/gfx/bitmaps/PNGFormat.ec @@ -2,6 +2,8 @@ namespace gfx::bitmaps; import "Display" +#if !defined(__EMSCRIPTEN__) + #define uint _uint #include "png.h" #undef uint @@ -307,3 +309,5 @@ class PNGFormat : BitmapFormat return result; } } + +#endif // !defined(__EMSCRIPTEN__) diff --git a/ecere/src/gfx/drivers/NCursesDisplayDriver.ec b/ecere/src/gfx/drivers/NCursesDisplayDriver.ec index 2e7cd19..b15db41 100644 --- a/ecere/src/gfx/drivers/NCursesDisplayDriver.ec +++ b/ecere/src/gfx/drivers/NCursesDisplayDriver.ec @@ -4,7 +4,7 @@ import "instance" #undef __BLOCKS__ -#if (defined(__unix__) || defined(__APPLE__)) && !defined(__DOS__) +#if (defined(__unix__) || defined(__APPLE__)) && !defined(__DOS__) && !defined(__EMSCRIPTEN__) #include diff --git a/ecere/src/gfx/drivers/XDisplayDriver.ec b/ecere/src/gfx/drivers/XDisplayDriver.ec index 01497c9..81a6d8f 100644 --- a/ecere/src/gfx/drivers/XDisplayDriver.ec +++ b/ecere/src/gfx/drivers/XDisplayDriver.ec @@ -2,7 +2,7 @@ namespace gfx::drivers; import "instance" -#if (defined(__unix__) || defined(__APPLE__)) && !defined(ECERE_MINIGLX) +#if (defined(__unix__) || defined(__APPLE__)) && !defined(ECERE_MINIGLX) && !defined(__EMSCRIPTEN__) default: @@ -21,8 +21,10 @@ default: #include #include +#if !defined(__EMSCRIPTEN__) #include #include +#endif #include #include #include diff --git a/ecere/src/gui/Desktop3D.ec b/ecere/src/gui/Desktop3D.ec index d9e273e..45085a8 100644 --- a/ecere/src/gui/Desktop3D.ec +++ b/ecere/src/gui/Desktop3D.ec @@ -54,7 +54,9 @@ static bool Window3D_Setup(Window window, bool positionChildren) window.display.driverData = virtualDesktop.display.driverData; window.display.current = virtualDesktop.display.current; +#if !defined(__EMSCRIPTEN__) window.display.mutex = null; +#endif window.ComputeAnchors(window.stateAnchor, window.stateSizeAnchor, &x,&y,&w,&h); virtualDesktop.display.Lock(false); window.windowHandle = Setup3DWindow(window, w, h); diff --git a/ecere/src/gui/GuiApplication.ec b/ecere/src/gui/GuiApplication.ec index 87fe462..bb7fd95 100644 --- a/ecere/src/gui/GuiApplication.ec +++ b/ecere/src/gui/GuiApplication.ec @@ -1,6 +1,14 @@ namespace gui; -#if (defined(__unix__) || defined(__APPLE__)) && !defined(__ANDROID__) +#ifdef __EMSCRIPTEN__ +#include +#endif + +#ifdef __EMSCRIPTEN__ +#include +#endif + +#if (defined(__unix__) || defined(__APPLE__)) && !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) #define property _property #define new _new #define class _class @@ -77,7 +85,7 @@ import "network" import "CocoaInterface" #endif -#if (defined(__unix__) || defined(__APPLE__)) && !defined(__ANDROID__) +#if (defined(__unix__) || defined(__APPLE__)) && !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) import "XInterface" #endif @@ -160,9 +168,13 @@ public class GuiApplication : Application bool processAll; +#if !defined(__EMSCRIPTEN__) Mutex waitMutex {}; +#endif bool waiting; +#if !defined(__EMSCRIPTEN__) Mutex lockMutex {}; +#endif Window interimWindow; bool caretEnabled; @@ -179,7 +191,9 @@ public class GuiApplication : Application { SystemCursor c; +#if !defined(__EMSCRIPTEN__) mainThread = GetCurrentThreadID(); +#endif if(!guiApp) guiApp = this; @@ -194,9 +208,11 @@ public class GuiApplication : Application for(c = 0; c + +// source file line number printf (sflnprintf) +#define sflnprintf(format,...) printf("%s:% 5d: " format, __FILE__, __LINE__, ##__VA_ARGS__) + +#define property _property +#define uint _uint + +//#include +#include +#include + +#undef property +#undef uint + + +class EmscriptenInterface : Interface +{ + class_property(name) = "Emscripten"; + + + // --- User Interface System --- + + bool ::Initialize() + { + sflnprintf("class(EmscriptenInterface) ::Initialize [STUB!]\n"); + guiApp.desktop.ExternalPosition(0,0, 640, 480); + return true; + } + + void ::Terminate() + { + sflnprintf("class(EmscriptenInterface) ::Terminate [STUB!]\n"); + } + + bool ::ProcessInput(bool processAll) + { + sflnprintf("class(EmscriptenInterface) ::ProcessInput [STUB!]\n"); + return false; + } + + void ::Wait() + { + sflnprintf("class(EmscriptenInterface) ::Wait [STUB!]\n"); + } + + void ::Lock(Window window) + { + sflnprintf("class(EmscriptenInterface) ::Lock [STUB!]\n"); + } + + void ::Unlock(Window window) + { + sflnprintf("class(EmscriptenInterface) ::Unlock [STUB!]\n"); + } + + void ::SetTimerResolution(uint hertz) + { + sflnprintf("class(EmscriptenInterface) ::SetTimerResolution [STUB!] Implement high resolution timer here\n"); + } + + const char ** ::GraphicsDrivers(int * numDrivers) + { + //sflnprintf("class(EmscriptenInterface) ::GraphicsDrivers [STUB!]\n"); + static const char *graphicsDrivers[] = { "OpenGL" }; + *numDrivers = sizeof(graphicsDrivers) / sizeof(char *); + return (const char **)graphicsDrivers; + return null; + } + + void ::EnsureFullScreen(bool * fullScreen) + { + sflnprintf("class(EmscriptenInterface) ::EnsureFullScreen [STUB!]\n"); + *fullScreen = true; + } + + void ::GetCurrentMode(bool * fullScreen, Resolution * resolution, PixelFormat * colorDepth, int * refreshRate) + { + sflnprintf("class(EmscriptenInterface) ::GetCurrentMode [STUB!]\n"); + } + + bool ::ScreenMode(bool fullScreen, Resolution resolution, PixelFormat colorDepth, int refreshRate, bool * textMode) + { + sflnprintf("class(EmscriptenInterface) ::ScreenMode [STUB!]\n"); + return true; + } + + + // --- Window Creation --- + + void * ::CreateRootWindow(Window window) + { + sflnprintf("class(EmscriptenInterface) ::CreateRootWindow [STUB!]\n"); + return null; + } + + void ::DestroyRootWindow(Window window) + { + sflnprintf("class(EmscriptenInterface) ::DestroyRootWindow [STUB!]\n"); + } + + + // --- Window manipulation --- + + void ::SetRootWindowCaption(Window window, const char * name) + { + sflnprintf("class(EmscriptenInterface) ::SetRootWindowCaption [STUB!]\n"); + } + + void ::PositionRootWindow(Window window, int x, int y, int w, int h, bool move, bool resize) + { + sflnprintf("class(EmscriptenInterface) ::Stub [STUB!]\n"); + } + + void ::OffsetWindow(Window window, int * x, int * y) + { + sflnprintf("class(EmscriptenInterface) ::OffsetWindow [STUB!]\n"); + } + + void ::UpdateRootWindow(Window window) + { + sflnprintf("class(EmscriptenInterface) ::UpdateRootWindow [STUB!]\n"); + } + + void ::SetRootWindowState(Window window, WindowState state, bool visible) + { + sflnprintf("class(EmscriptenInterface) ::SetRootWindowState [STUB!]\n"); + } + + void ::ActivateRootWindow(Window window) + { + sflnprintf("class(EmscriptenInterface) ::ActivateRootWindow [STUB!]\n"); + } + + void ::OrderRootWindow(Window window, bool topMost) + { + sflnprintf("class(EmscriptenInterface) ::OrderRootWindow [STUB!]\n"); + } + + void ::SetRootWindowColor(Window window) + { + sflnprintf("class(EmscriptenInterface) ::SetRootWindowColor [STUB!]\n"); + } + + void ::FlashRootWindow(Window window) + { + sflnprintf("class(EmscriptenInterface) ::FlashRootWindow [STUB!]\n"); + } + + + // --- Mouse-based window movement --- + + void ::StartMoving(Window window, int x, int y, bool fromKeyBoard) + { + sflnprintf("class(EmscriptenInterface) ::StartMoving [STUB!]\n"); + } + + void ::StopMoving(Window window) + { + sflnprintf("class(EmscriptenInterface) ::StopMoving [STUB!]\n"); + } + + + // --- Mouse manipulation --- + + void ::GetMousePosition(int *x, int *y) + { + sflnprintf("class(EmscriptenInterface) ::GetMousePosition [STUB!]\n"); + } + + void ::SetMousePosition(int x, int y) + { + sflnprintf("class(EmscriptenInterface) ::SetMousePosition [STUB!]\n"); + } + + void ::SetMouseRange(Window window, Box box) + { + sflnprintf("class(EmscriptenInterface) ::SetMouseRange [STUB!]\n"); + } + + void ::SetMouseCapture(Window window) + { + sflnprintf("class(EmscriptenInterface) ::SetMouseCapture [STUB!]\n"); + } + + + // --- Mouse cursor --- + + void ::SetMouseCursor(Window window, SystemCursor cursor) + { + sflnprintf("class(EmscriptenInterface) ::SetMouseCursor [STUB!]\n"); + } + + + // --- Caret manipulation --- + + void ::SetCaret(int caretX, int caretY, int size) + { + sflnprintf("class(EmscriptenInterface) ::SetCaret [STUB!]\n"); + } + + + // --- Clipboard manipulation --- + + void ::ClearClipboard() + { + sflnprintf("class(EmscriptenInterface) ::ClearClipboard [STUB!]\n"); + } + + bool ::AllocateClipboard(ClipBoard clipBoard, uint size) + { + sflnprintf("class(EmscriptenInterface) ::AllocateClipboard [STUB!]\n"); + return false; + } + + bool ::SaveClipboard(ClipBoard clipBoard) + { + sflnprintf("class(EmscriptenInterface) ::SaveClipboard [STUB!]\n"); + return false; + } + + bool ::LoadClipboard(ClipBoard clipBoard) + { + sflnprintf("class(EmscriptenInterface) ::LoadClipboard [STUB!]\n"); + return false; + } + + void ::UnloadClipboard(ClipBoard clipBoard) + { + sflnprintf("class(EmscriptenInterface) ::UnloadClipboard [STUB!]\n"); + } + + + // --- State based input --- + + bool ::AcquireInput(Window window, bool state) + { + sflnprintf("class(EmscriptenInterface) ::AcquireInput [STUB!]\n"); + return false; + } + + bool ::GetMouseState(MouseButtons * buttons, int * x, int * y) + { + sflnprintf("class(EmscriptenInterface) ::GetMouseState [STUB!]\n"); + return false; + } + + bool ::GetJoystickState(int device, Joystick joystick) + { + sflnprintf("class(EmscriptenInterface) ::GetJoystickState [STUB!]\n"); + return false; + } + + bool ::GetKeyState(Key key) + { + sflnprintf("class(EmscriptenInterface) ::GetKeyState [STUB!]\n"); + return false; + } + + bool ::SetIcon(Window window, BitmapResource icon) + { + sflnprintf("class(EmscriptenInterface) ::SetIcon [STUB!]\n"); + return false; + } + + void ::GetScreenArea(Window window, Box box) + { + sflnprintf("class(EmscriptenInterface) ::GetScreenArea [STUB!]\n"); + } +} + +#endif diff --git a/ecere/src/gui/drivers/NCursesInterface.ec b/ecere/src/gui/drivers/NCursesInterface.ec index 67a2254..a20a7cf 100644 --- a/ecere/src/gui/drivers/NCursesInterface.ec +++ b/ecere/src/gui/drivers/NCursesInterface.ec @@ -2,7 +2,7 @@ namespace gui::drivers; import "instance" -#if (defined(__unix__) || defined(__APPLE__)) && !defined(__DOS__) +#if (defined(__unix__) || defined(__APPLE__)) && !defined(__DOS__) && !defined(__EMSCRIPTEN__) #undef __BLOCKS__ #define DBLCLICK_DELAY 0.3 // seconds diff --git a/ecere/src/gui/drivers/XInterface.ec b/ecere/src/gui/drivers/XInterface.ec index 9570ec4..e40f6a6 100644 --- a/ecere/src/gui/drivers/XInterface.ec +++ b/ecere/src/gui/drivers/XInterface.ec @@ -5,7 +5,7 @@ import "instance" import "OpenGLDisplayDriver" #endif -#if (defined(__unix__) || defined(__APPLE__)) && !defined(ECERE_MINIGLX) +#if (defined(__unix__) || defined(__APPLE__)) && !defined(ECERE_MINIGLX) && !defined(__EMSCRIPTEN__) #undef __BLOCKS__ default: @@ -50,16 +50,24 @@ typedef int X11Bool; #include #include +#if !defined(__EMSCRIPTEN__) #include +#endif #include #include #include #include #include #if !defined(ECERE_NO3D) && !defined(ECERE_NOGL) //&& !defined(__ODROID__) +#if defined(__EMSCRIPTEN__) +#include +#else #include #endif +#endif +#if !defined(__EMSCRIPTEN__) #include +#endif #include #undef Bool diff --git a/ecere/src/gui/skins/WindowsSkin.ec b/ecere/src/gui/skins/WindowsSkin.ec index 4c3c395..eab0746 100644 --- a/ecere/src/gui/skins/WindowsSkin.ec +++ b/ecere/src/gui/skins/WindowsSkin.ec @@ -198,7 +198,7 @@ public class WindowsSkin_Window : Window // PrintLn(_class.name, " is at l = ", rcWindow.left, ", r = ", rcWindow.right); #else Box widths = { 0 }; -#if !defined(__ANDROID__) +#if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) XGetBorderWidths(this, widths); #endif *w += widths.left + widths.right; @@ -285,7 +285,7 @@ public class WindowsSkin_Window : Window *y += client00.y - rcWindow.top; #else Box widths = { 0 }; -#if !defined(__ANDROID__) +#if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) XGetBorderWidths(this, widths); #endif *x += widths.left; diff --git a/ecere/src/net/dcom.ec b/ecere/src/net/dcom.ec index 455b810..3603854 100644 --- a/ecere/src/net/dcom.ec +++ b/ecere/src/net/dcom.ec @@ -38,6 +38,8 @@ typedef struct in_addr IN_ADDR; import "network" import "List" +#if !defined(__EMSCRIPTEN__) + // SERVER static enum DCOMPacketType @@ -812,3 +814,5 @@ public: sendingOut = false; } } + +#endif // !defined(__EMSCRIPTEN__) diff --git a/ecere/src/sys/Condition.ec b/ecere/src/sys/Condition.ec index b9366f2..23a6c8c 100644 --- a/ecere/src/sys/Condition.ec +++ b/ecere/src/sys/Condition.ec @@ -1,8 +1,14 @@ #if defined(BUILDING_ECERE_COM) +#if !defined(__EMSCRIPTEN__) import "Semaphore" #else import "ecere" #endif +#else +import "ecere" +#endif + +#if !defined(__EMSCRIPTEN__) public class Condition : struct { @@ -56,3 +62,5 @@ public: mutex.Wait(); } } + +#endif // !defined(__EMSCRIPTEN__) diff --git a/ecere/src/sys/EARArchive.ec b/ecere/src/sys/EARArchive.ec index 6b59c2e..9e867db 100644 --- a/ecere/src/sys/EARArchive.ec +++ b/ecere/src/sys/EARArchive.ec @@ -1200,7 +1200,7 @@ class EARArchiveDir : ArchiveDir return true; } }; -#endif +#endif // !defined(ECERE_NOARCHIVE) && !defined(ECERE_VANILLA) // Directory Description for file listing class EARDir : struct @@ -1694,7 +1694,7 @@ class EARFileSystem : FileSystem } return result; } -#endif +#endif // !defined(ECERE_NOARCHIVE) && !defined(ECERE_VANILLA) bool ::QuerySize(const char * archive, FileSize * size) { bool result = false; diff --git a/ecere/src/sys/FileMonitor.ec b/ecere/src/sys/FileMonitor.ec index a6dde40..7ea5966 100644 --- a/ecere/src/sys/FileMonitor.ec +++ b/ecere/src/sys/FileMonitor.ec @@ -2,6 +2,8 @@ namespace sys; import "System" +#if !defined(__EMSCRIPTEN__) + public class FileChange { public: @@ -431,3 +433,5 @@ static class MonitorThread : Thread return 0; } } + +#endif // !defined(__EMSCRIPTEN__) diff --git a/ecere/src/sys/GlobalAppSettings.ec b/ecere/src/sys/GlobalAppSettings.ec index 4bb261c..192e836 100644 --- a/ecere/src/sys/GlobalAppSettings.ec +++ b/ecere/src/sys/GlobalAppSettings.ec @@ -146,6 +146,7 @@ private: SettingsLocationType readType; SettingsLocationType writeType; +#if !defined(__EMSCRIPTEN__) FileMonitor settingsMonitor { this, fileChange = { modified = true }; @@ -156,6 +157,7 @@ private: return true; } }; +#endif File f; bool locked; @@ -380,7 +382,9 @@ public: SettingsLocationType type = readType; if(!f) { +#if !defined(__EMSCRIPTEN__) settingsMonitor.StopMonitoring(); +#endif if(settingsFilePath) FileOpenTryRead(type); @@ -475,7 +479,9 @@ public: { locked = false; +#if !defined(__EMSCRIPTEN__) settingsMonitor.StopMonitoring(); +#endif if(settingsFilePath) // Don't auto delete settingsFilePath because only want to try another path if we were using a global path @@ -544,7 +550,9 @@ public: { if(f) { +#if !defined(__EMSCRIPTEN__) settingsMonitor.StopMonitoring(); +#endif f.Unlock(0,0,true); locked = false; delete f; @@ -556,8 +564,10 @@ public: Close(); if(settingsFilePath && OnAskReloadSettings != GlobalSettings::OnAskReloadSettings) { +#if !defined(__EMSCRIPTEN__) settingsMonitor.fileName = settingsFilePath; settingsMonitor.StartMonitoring(); +#endif } } } diff --git a/ecere/src/sys/JSON.ec b/ecere/src/sys/JSON.ec index fa327d6..573b777 100644 --- a/ecere/src/sys/JSON.ec +++ b/ecere/src/sys/JSON.ec @@ -1,5 +1,6 @@ namespace sys; +import "instance" import "System" import "Array" diff --git a/ecere/src/sys/Mutex.ec b/ecere/src/sys/Mutex.ec index ea4606a..ba212df 100644 --- a/ecere/src/sys/Mutex.ec +++ b/ecere/src/sys/Mutex.ec @@ -14,7 +14,7 @@ namespace sys; #define uint _uint #define set _set #define String _String -#if defined(__WIN32__) +#if defined(__WIN32__) && !defined(__EMSCRIPTEN__) #define WIN32_LEAN_AND_MEAN #include #else @@ -38,6 +38,8 @@ public int64 GetCurrentThreadID() public class Mutex : struct { +#if !defined(__EMSCRIPTEN__) + // class_fixed #if defined(__WIN32__) #ifdef _DEBUG @@ -48,6 +50,7 @@ public class Mutex : struct #else pthread_mutex_t mutex; #endif +#endif #ifdef _DEBUG int64 owningThread; @@ -56,6 +59,7 @@ public class Mutex : struct Mutex() { +#if !defined(__EMSCRIPTEN__) #if defined(__WIN32__) #ifdef _DEBUG mutex = CreateMutex(null, FALSE, null); @@ -76,6 +80,8 @@ public class Mutex : struct pthread_mutex_init(&mutex, &attr); pthread_mutexattr_destroy(&attr); #endif +#endif + lockCount = 0; #ifdef _DEBUG owningThread = 0; @@ -85,6 +91,7 @@ public class Mutex : struct ~Mutex() { +#if !defined(__EMSCRIPTEN__) #if defined(__WIN32__) #ifdef _DEBUG CloseHandle(mutex); @@ -94,6 +101,7 @@ public class Mutex : struct #else pthread_mutex_destroy(&mutex); #endif +#endif } public: @@ -101,6 +109,7 @@ public: { if(this) { +#if !defined(__EMSCRIPTEN__) /* if(this == globalSystem.fileMonitorMutex) printf("[%d] Waiting on Mutex %x\n", (int)GetCurrentThreadID(), this); @@ -125,6 +134,8 @@ public: #endif #endif +#endif + #ifdef _DEBUG owningThread = GetCurrentThreadID(); #endif @@ -136,6 +147,7 @@ public: { if(this) { +#if !defined(__EMSCRIPTEN__) /* if(this == globalSystem.fileMonitorMutex) printf("[%d] Releasing Mutex %x\n", (int)GetCurrentThreadID(), this); @@ -169,6 +181,8 @@ public: pthread_mutex_unlock(&mutex); #endif #endif +#endif + #ifdef _DEBUG if(lockCount < 0) PrintLn("WARNING: lockCount < 0"); diff --git a/ecere/src/sys/Semaphore.ec b/ecere/src/sys/Semaphore.ec index 44c692c..b7e5c7c 100644 --- a/ecere/src/sys/Semaphore.ec +++ b/ecere/src/sys/Semaphore.ec @@ -26,6 +26,8 @@ import "System" public class Semaphore : struct { +#if !defined(__EMSCRIPTEN__) + #if defined(__WIN32__) HANDLE handle; #elif defined(__APPLE__) @@ -35,11 +37,13 @@ public class Semaphore : struct #else sem_t semaphore; #endif +#endif int initCount, maxCount; Semaphore() { +#if !defined(__EMSCRIPTEN__) #if defined(__WIN32__) handle = CreateSemaphore(null, 0, 1, null); #elif defined(__APPLE__) @@ -47,12 +51,14 @@ public class Semaphore : struct #else sem_init(&semaphore, 0, 0); #endif +#endif maxCount = 1; initCount = 0; } ~Semaphore() { +#if !defined(__EMSCRIPTEN__) #if defined(__WIN32__) if(handle) CloseHandle(handle); #elif defined(__APPLE__) @@ -60,12 +66,14 @@ public class Semaphore : struct #else sem_destroy(&semaphore); #endif +#endif } public: bool TryWait(void) { bool result; +#if !defined(__EMSCRIPTEN__) #if defined(__WIN32__) result = WaitForSingleObject(handle, 0) != WAIT_TIMEOUT; #elif defined(__APPLE__) @@ -84,11 +92,13 @@ public: #else result = sem_trywait(&semaphore) != EAGAIN; #endif +#endif return result; } void Wait(void) { +#if !defined(__EMSCRIPTEN__) #if defined(__WIN32__) if(WaitForSingleObject(handle, INFINITE /*2000*/) == WAIT_TIMEOUT) PrintLn("Semaphore not released?"); @@ -108,10 +118,12 @@ public: sem_wait(&semaphore); #endif #endif +#endif } void Release(void) { +#if !defined(__EMSCRIPTEN__) #if defined(__WIN32__) ReleaseSemaphore(handle, 1, null); #elif defined(__APPLE__) @@ -125,12 +137,14 @@ public: if(count < maxCount) sem_post(&semaphore); #endif +#endif } property int initCount { set { +#if !defined(__EMSCRIPTEN__) #if defined(__WIN32__) if(handle) CloseHandle(handle); handle = CreateSemaphore(null, initCount, value, null); @@ -142,6 +156,7 @@ public: sem_destroy(&semaphore); sem_init(&semaphore, 0, initCount); #endif +#endif initCount = value; } get { return initCount; } @@ -150,10 +165,12 @@ public: { set { +#if !defined(__EMSCRIPTEN__) #if defined(__WIN32__) if(handle) CloseHandle(handle); handle = CreateSemaphore(null, value, maxCount, null); #endif +#endif maxCount = value; } get { return maxCount; } diff --git a/ecere/src/sys/System.ec b/ecere/src/sys/System.ec index 1f168a0..1b7bcd8 100644 --- a/ecere/src/sys/System.ec +++ b/ecere/src/sys/System.ec @@ -64,10 +64,12 @@ private: #if !defined(ECERE_BOOTSTRAP) import "units" import "Time" +#if !defined(__EMSCRIPTEN__) import "Mutex" import "Semaphore" import "FileMonitor" import "Thread" +#endif import "Archive" import "EARArchive" import "Date" @@ -488,14 +490,18 @@ private struct System ErrorLevel errorLevel; #ifndef ECERE_BOOTSTRAP +#if !defined(__EMSCRIPTEN__) Semaphore eventSemaphore; +#endif //FileSystem fileSystems; // File Monitor OldList fileMonitors; +#if !defined(__EMSCRIPTEN__) Mutex fileMonitorMutex; Thread fileMonitorThread; +#endif bool systemTerminate; #endif }; diff --git a/ecere/src/sys/Thread.ec b/ecere/src/sys/Thread.ec index 2495455..ae2478b 100644 --- a/ecere/src/sys/Thread.ec +++ b/ecere/src/sys/Thread.ec @@ -49,7 +49,7 @@ public class Thread #if defined(__WIN32__) HANDLE handle; uint id; -#else +#elif !defined(__EMSCRIPTEN__) pthread_t id; bool dontDetach; Semaphore sem { }; @@ -58,6 +58,7 @@ public class Thread uint returnCode; bool started; +#if !defined(__EMSCRIPTEN__) #if defined(__WIN32__) uint ThreadCallBack() #else @@ -82,6 +83,7 @@ public class Thread return (void *)(uintptr_t)returnCode; #endif } +#endif public: virtual uint Main(void); @@ -91,11 +93,12 @@ public: incref this; if(!started) { -#if !defined(__WIN32__) +#if !defined(__WIN32__) && !defined(__EMSCRIPTEN__) sem.TryWait(); #endif started = true; // printf("Creating %s thread\n", _class.name); +#if !defined(__EMSCRIPTEN__) #if defined(__WIN32__) if(!handle) { @@ -112,13 +115,15 @@ public: error = pthread_create(&id, null /*&attr*/, ThreadCallBack, this); if(error) printf("Error %d creating a thread\n", error); - } + } +#endif #endif } } void Kill() { +#if !defined(__EMSCRIPTEN__) #if defined(__WIN32__) if(handle) { @@ -129,6 +134,7 @@ public: if(started) pthread_kill(id, SIGQUIT); #endif +#endif if(started) { started = false; @@ -138,6 +144,7 @@ public: void Wait() { +#if !defined(__EMSCRIPTEN__) #if defined(__WIN32__) if(WaitForSingleObject(handle, INFINITE /*2000*/) == WAIT_TIMEOUT) PrintLn("Thread not returning?\n"); @@ -150,10 +157,12 @@ public: if(started) sem.Wait(); #endif +#endif } void SetPriority(ThreadPriority priority) { +#if !defined(__EMSCRIPTEN__) #if defined(__WIN32__) SetThreadPriority(handle, priority); #else @@ -164,7 +173,9 @@ public: pthread_setschedparam(id, policy, ¶m); */ #endif +#endif } property bool created { get { return started; } }; } + diff --git a/ecere/src/sys/i18n.ec b/ecere/src/sys/i18n.ec index 26ad8ff..9df3ac7 100644 --- a/ecere/src/sys/i18n.ec +++ b/ecere/src/sys/i18n.ec @@ -1,3 +1,4 @@ +import "instance" #ifndef ECERE_NOFILE import "File" #endif @@ -23,7 +24,7 @@ static Map> moduleMaps { }; public dllexport void LoadTranslatedStrings(const String moduleName, const char * name) { -#ifndef ECERE_NOFILE +#if !defined(ECERE_NOFILE) && !defined(__EMSCRIPTEN__) File f; char fileName[MAX_LOCATION]; diff --git a/samples/guiAndGfx/HelloForm/helloForm.ec b/samples/guiAndGfx/HelloForm/helloForm.ec index 3f2dbf2..69793fc 100644 --- a/samples/guiAndGfx/HelloForm/helloForm.ec +++ b/samples/guiAndGfx/HelloForm/helloForm.ec @@ -1,4 +1,4 @@ -import "ecere" +import IMPORT_STATIC "ecere" class HelloForm : Window { diff --git a/samples/guiAndGfx/HelloForm/helloForm.epj b/samples/guiAndGfx/HelloForm/helloForm.epj index 07266b4..744b797 100644 --- a/samples/guiAndGfx/HelloForm/helloForm.epj +++ b/samples/guiAndGfx/HelloForm/helloForm.epj @@ -15,6 +15,9 @@ "Name" : "Debug", "Options" : { "Debug" : true, + "PreprocessorDefinitions" : [ + "IMPORT_STATIC=" + ], "FastMath" : false } }, @@ -23,9 +26,29 @@ "Options" : { "Debug" : true, "MemoryGuard" : true, + "PreprocessorDefinitions" : [ + "IMPORT_STATIC=" + ], "Console" : true, "FastMath" : false } + }, + { + "Name" : "Emscripten", + "Options" : { + "Debug" : true, + "PreprocessorDefinitions" : [ + "IMPORT_STATIC=static" + ], + "Libraries" : [ + "ecereStatic", + "freetype", + "z" + ], + "LibraryDirs" : [ + "../../../ecere/obj/emscripten.linux.emscripten.x32" + ] + } } ], "Files" : [ -- 1.8.3.1