- <NOTE> 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
],
"FastMath" : true
}
+ },
+ {
+ "Name" : "Emscripten",
+ "Options" : {
+ "Debug" : true,
+ "PreprocessorDefinitions" : [
+ "ECERE_STATIC",
+ "NOBLENDING"
+ ],
+ "TargetType" : "StaticLibrary",
+ "TargetFileName" : "ecereStatic"
+ }
}
],
"Files" : [
"Options" : {
"ExcludeFromBuild" : true
}
+ },
+ {
+ "Name" : "Emscripten",
+ "Options" : {
+ "ExcludeFromBuild" : true
+ }
}
]
},
}
}
]
+ },
+ {
+ "Name" : "Emscripten",
+ "Options" : {
+ "ExcludeFromBuild" : true
+ }
}
]
},
}
]
},
- "PNGFormat.ec",
+ {
+ "FileName" : "PNGFormat.ec",
+ "Configurations" : [
+ {
+ "Name" : "Emscripten",
+ "Options" : {
+ "ExcludeFromBuild" : true
+ }
+ }
+ ]
+ },
{
"FileName" : "RGBFormat.ec",
"Configurations" : [
}
}
]
+ },
+ {
+ "Name" : "Emscripten",
+ "Options" : {
+ "ExcludeFromBuild" : true
+ }
}
]
}
}
}
]
+ },
+ {
+ "FileName" : "EmscriptenInterface.ec",
+ "Configurations" : [
+ {
+ "Name" : "Emscripten",
+ "Options" : {
+ "ExcludeFromBuild" : false
+ }
+ }
+ ]
}
],
"Options" : {
}
}
]
+ },
+ {
+ "Name" : "Emscripten",
+ "Options" : {
+ "ExcludeFromBuild" : true
+ }
}
]
},
],
"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" : [
#include <stdlib.h>
#include <stdarg.h>
#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 <windows.h>
namespace com;
+import "instance"
import "Container"
#ifdef _DEBUG
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:
#undef bool
#endif
-#if defined(__WIN32__)
+#if defined(__WIN32__) && !defined(__EMSCRIPTEN__)
#define WIN32_LEAN_AND_MEAN
#define UNICODE
#include <windows.h>
__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);
typedef enum { unknown, win32, tux, apple } Platform;
-#if defined(__WIN32__)
+#if defined(__WIN32__) && !defined(__EMSCRIPTEN__)
Platform runtimePlatform = win32;
#elif defined(__APPLE__)
Platform runtimePlatform = apple;
bool Instance_LocateModule(const char * name, char * fileName)
{
-#if defined(__WIN32__)
+#if defined(__WIN32__) && !defined(__EMSCRIPTEN__)
HMODULE hModule = null;
if(name && name[0])
{
}
#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__)
}
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
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);
*Load = null;
*Unload = null;
-#if defined(__WIN32__)
+#if defined(__WIN32__) && !defined(__EMSCRIPTEN__)
strcpy(fileName, name);
GetExtension(fileName, extension);
if(!extension[0])
strcat(fileName, ".so");
#endif
+#if !defined(__EMSCRIPTEN__)
library = dlopen(fileName, RTLD_LAZY);
+#endif
while(!library && attempts < sizeof(paths)/sizeof(paths[0]))
{
if(paths[attempts])
#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, '/'))
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
#undef __BLOCKS__
+#if !defined(__EMSCRIPTEN__)
#if !defined(ECERE_BOOTSTRAP)
import "Mutex"
#endif
+#endif
// #define MEMINFO
/*
#endif
#ifdef MEMINFO
+#if !defined(__EMSCRIPTEN__)
import "Thread"
+#endif
static define MAX_MEMORY_LOC = 40;
static define MAX_STACK_FRAMES = 1000;
{
#ifdef MEMINFO
MemStack stack;
+#if !defined(__EMSCRIPTEN__)
memMutex.Wait();
+#endif
stack = (MemStack)memStacks.Find(GetCurrentThreadID());
if(!stack)
{
}
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
static uint OUTSIDE_MEM = 0;
#endif
+#if !defined(__EMSCRIPTEN__)
#if !defined(ECERE_BOOTSTRAP)
static Mutex memMutex { };
#endif
+#endif
private class MemBlock : struct
{
#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)
__attribute__((unused)) static void DummyFunction()
{
+#if !defined(__EMSCRIPTEN__)
Mutex { };
+#endif
}
public class DisplayDriver
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;
result = displaySystem && displaySystem.Lock();
if(result && render)
{
+#if !defined(__EMSCRIPTEN__)
mutex.Wait();
+#endif
if(!current)
result = displaySystem.driver.Lock(this);
*/
if(!current && displaySystem)
displaySystem.driver.Unlock(this);
+#if !defined(__EMSCRIPTEN__)
mutex.Release();
+#endif
}
if(displaySystem)
displaySystem.Unlock();
DisplaySystem displaySystem;
void * window;
+#if !defined(__EMSCRIPTEN__)
Mutex mutex { };
+#endif
int current;
#if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
}
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;
+}
namespace gfx;
+#if !defined(__EMSCRIPTEN__)
import "Mutex"
+#endif
import "Display"
const String printingDocumentName;
bool Lock()
{
bool result = false;
+#if !defined(__EMSCRIPTEN__)
mutex.Wait();
+#endif
if(!current)
result = driver.LockSystem(this);
if(!current)
driver.UnlockSystem(this);
+#if !defined(__EMSCRIPTEN__)
mutex.Release();
+#endif
}
#if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
// --- Materials List Management ---
void * driverData;
int current;
+#if !defined(__EMSCRIPTEN__)
Mutex mutex { };
+#endif
};
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;
return result;
}
}
+
+#endif // !defined(__EMSCRIPTEN__)
import "Display"
+#if !defined(__EMSCRIPTEN__)
+
#define uint _uint
#include "png.h"
#undef uint
return result;
}
}
+
+#endif // !defined(__EMSCRIPTEN__)
#undef __BLOCKS__
-#if (defined(__unix__) || defined(__APPLE__)) && !defined(__DOS__)
+#if (defined(__unix__) || defined(__APPLE__)) && !defined(__DOS__) && !defined(__EMSCRIPTEN__)
#include <curses.h>
import "instance"
-#if (defined(__unix__) || defined(__APPLE__)) && !defined(ECERE_MINIGLX)
+#if (defined(__unix__) || defined(__APPLE__)) && !defined(ECERE_MINIGLX) && !defined(__EMSCRIPTEN__)
default:
#include <X11/Xlib.h>
#include <X11/Xutil.h>
+#if !defined(__EMSCRIPTEN__)
#include <X11/extensions/shape.h>
#include <X11/extensions/Xrender.h>
+#endif
#include <X11/extensions/XShm.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define ECERE_NOTRUETYPE
#endif
+#define _Noreturn
+
#undef __BLOCKS__
#define uint _uint
#define strlen _strlen
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);
namespace gui;
-#if (defined(__unix__) || defined(__APPLE__)) && !defined(__ANDROID__)
+#ifdef __EMSCRIPTEN__
+#include <emscripten.h>
+#endif
+
+#ifdef __EMSCRIPTEN__
+#include <emscripten.h>
+#endif
+
+#if (defined(__unix__) || defined(__APPLE__)) && !defined(__ANDROID__) && !defined(__EMSCRIPTEN__)
#define property _property
#define new _new
#define class _class
import "CocoaInterface"
#endif
-#if (defined(__unix__) || defined(__APPLE__)) && !defined(__ANDROID__)
+#if (defined(__unix__) || defined(__APPLE__)) && !defined(__ANDROID__) && !defined(__EMSCRIPTEN__)
import "XInterface"
#endif
bool processAll;
+#if !defined(__EMSCRIPTEN__)
Mutex waitMutex {};
+#endif
bool waiting;
+#if !defined(__EMSCRIPTEN__)
Mutex lockMutex {};
+#endif
Window interimWindow;
bool caretEnabled;
{
SystemCursor c;
+#if !defined(__EMSCRIPTEN__)
mainThread = GetCurrentThreadID();
+#endif
if(!guiApp)
guiApp = this;
for(c = 0; c<SystemCursor::enumSize; c++)
systemCursors[c] = Cursor { systemCursor = c; };
+#if !defined(__EMSCRIPTEN__)
globalSystem.eventSemaphore = Semaphore { };
globalSystem.fileMonitorMutex = Mutex { };
globalSystem.fileMonitors.offset = (uint)(uintptr)&((FileMonitor)0).prev;
+#endif
return true;
}
delete desktop;
customCursors.Clear();
-#if (defined(__unix__) || defined(__APPLE__)) && !defined(__ANDROID__)
+#if (defined(__unix__) || defined(__APPLE__)) && !defined(__ANDROID__) && !defined(__EMSCRIPTEN__)
if(xGlobalDisplay)
XUnlockDisplay(xGlobalDisplay);
#endif
-#if !defined(__ANDROID__)
+#if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__)
// Because destruction of app won't be from main thread
if(guiApplicationInitialized)
lockMutex.Release();
Network_Terminate();
#endif
+#if !defined(__EMSCRIPTEN__)
delete globalSystem.eventSemaphore;
delete globalSystem.fileMonitorMutex;
delete globalSystem.fileMonitorThread;
+#endif
UnapplySkin(class(Window));
errorLevel = 2;
+#if !defined(__EMSCRIPTEN__)
lockMutex.Wait();
+#endif
/*#if (defined(__unix__) || defined(__APPLE__)) && !defined(__ANDROID__)
if(xGlobalDisplay)
XLockDisplay(xGlobalDisplay);
desktop.caption = appName;
*&desktop.visible = true;
desktop.position = Point { };
+#if !defined(__EMSCRIPTEN__)
desktop.mutex = Mutex { };
+#endif
desktop.created = true;
}
else
defaultDriver = "OpenGL";
}
+ #elif defined(__EMSCRIPTEN__)
+ {
+ if(driver)
+ defaultDriver = driver;
+ else
+ defaultDriver = "OpenGL";
+ }
#else
if((this.isGUIApp & 1) && !textMode)
{
}
}
+#ifdef __EMSCRIPTEN__
+ emscripten_set_main_loop(emscripten_main_loop_callback, 1/*60*/, 1);
+#endif
+
if(desktop)
{
int terminated = 0;
break;
if(!child) break;
+#if !defined(__EMSCRIPTEN__)
for(window = desktop.children.first; window; window = window.next)
if(window.mutex) window.mutex.Wait();
+#endif
UpdateDisplay();
+#if !defined(__EMSCRIPTEN__)
for(window = desktop.children.first; window; window = window.next)
if(window.mutex) window.mutex.Release();
+#endif
wait = !ProcessInput(true);
+#if !defined(__EMSCRIPTEN__)
#ifdef _DEBUG
if(lockMutex.owningThread != GetCurrentThreadID())
PrintLn("WARNING: ProcessInput returned unlocked GUI!");
#endif
+#endif
if(!Cycle(wait))
wait = false;
Wait();
else
{
-#if (defined(__unix__) || defined(__APPLE__)) && !defined(__ANDROID__)
+#if (defined(__unix__) || defined(__APPLE__)) && !defined(__ANDROID__) && !defined(__EMSCRIPTEN__)
if(xGlobalDisplay)
XUnlockDisplay(xGlobalDisplay);
#endif
+#if !defined(__EMSCRIPTEN__)
lockMutex.Release();
lockMutex.Wait();
+#endif
-#if (defined(__unix__) || defined(__APPLE__)) && !defined(__ANDROID__)
+#if (defined(__unix__) || defined(__APPLE__)) && !defined(__ANDROID__) && !defined(__EMSCRIPTEN__)
if(xGlobalDisplay)
XLockDisplay(xGlobalDisplay);
#endif
void Wait(void)
{
-#if (defined(__unix__) || defined(__APPLE__)) && !defined(__ANDROID__)
+#if (defined(__unix__) || defined(__APPLE__)) && !defined(__ANDROID__) && !defined(__EMSCRIPTEN__)
if(xGlobalDisplay)
XUnlockDisplay(xGlobalDisplay);
#endif
+#if !defined(__EMSCRIPTEN__)
lockMutex.Release();
waitMutex.Wait();
+#endif
waiting = true;
if(interfaceDriver)
interfaceDriver.Wait();
waiting = false;
+#if !defined(__EMSCRIPTEN__)
waitMutex.Release();
lockMutex.Wait();
+#endif
-#if (defined(__unix__) || defined(__APPLE__)) && !defined(__ANDROID__)
+#if (defined(__unix__) || defined(__APPLE__)) && !defined(__ANDROID__) && !defined(__EMSCRIPTEN__)
if(xGlobalDisplay)
XLockDisplay(xGlobalDisplay);
#endif
{
if(fullScreenMode && desktop.display)
{
+#if !defined(__EMSCRIPTEN__)
desktop.mutex.Wait();
+#endif
if(desktop.active)
{
desktop.display.Lock(true);
desktop.display.Unlock();
}
+#if !defined(__EMSCRIPTEN__)
desktop.mutex.Release();
+#endif
}
else
{
for(window = desktop.children.first; window; window = window.next)
{
+#if !defined(__EMSCRIPTEN__)
if(window.mutex) window.mutex.Wait();
+#endif
if(window.visible && window.dirty)
{
// Logf("Updating %s\n", window.name);
usleep(1000000);
*/
}
+#if !defined(__EMSCRIPTEN__)
if(window.mutex) window.mutex.Release();
+#endif
}
}
}
void WaitEvent(void)
{
+#if !defined(__EMSCRIPTEN__)
globalSystem.eventSemaphore.Wait();
+#endif
}
#if !defined(ECERE_VANILLA) && !defined(ECERE_NONET)
void SignalEvent(void)
{
+#if !defined(__EMSCRIPTEN__)
globalSystem.eventSemaphore.Release();
+#endif
}
// TODO: Might want to make this private with simpler public version?
bool ProcessFileNotifications()
{
+#if !defined(__EMSCRIPTEN__)
bool activity = false;
FileMonitor monitor, next;
static int reentrant = 0;
// printf("[%d] Releasing in ProcessFileNotifications fileMonitor Mutex %x...\n", (int)GetCurrentThreadID(), globalSystem.fileMonitorMutex);
globalSystem.fileMonitorMutex.Release();
return activity;
+#else
+ return false;
+#endif
}
void Lock(void)
{
+#if !defined(__EMSCRIPTEN__)
lockMutex.Wait();
-#if (defined(__unix__) || defined(__APPLE__)) && !defined(__ANDROID__)
+#if (defined(__unix__) || defined(__APPLE__)) && !defined(__ANDROID__) && !defined(__EMSCRIPTEN__)
if(xGlobalDisplay)
XLockDisplay(xGlobalDisplay);
#endif
+#endif
}
void Unlock(void)
{
-#if (defined(__unix__) || defined(__APPLE__)) && !defined(__ANDROID__)
+#if !defined(__EMSCRIPTEN__)
+#if (defined(__unix__) || defined(__APPLE__)) && !defined(__ANDROID__) && !defined(__EMSCRIPTEN__)
if(xGlobalDisplay)
XUnlockDisplay(xGlobalDisplay);
#endif
lockMutex.Release();
+#endif
}
Cursor GetCursor(SystemCursor cursor)
return (const char *)(this ? appName : null);
}
};
+#if !defined(__EMSCRIPTEN__)
property Semaphore semaphore { get { return globalSystem.eventSemaphore; } };
+#endif
property bool alwaysEmptyInput{ set { processAll = value; } get { return processAll; } };
property bool fullScreen
{
set { timerResolution = value; if(interfaceDriver) interfaceDriver.SetTimerResolution(value); }
};
};
+
+#ifdef __EMSCRIPTEN__
+private void emscripten_main_loop_callback()
+{
+ guiApp.ProcessInput(false);
+ guiApp.Cycle(false);
+ guiApp.UpdateDisplay();
+}
+#endif
OldLink slave;
ResPtr ptr;
+#if !defined(__EMSCRIPTEN__)
if(fileMonitor)
{
int i, lockCount = guiApp.lockMutex.lockCount;
for(i = 0; i < lockCount; i++)
guiApp.lockMutex.Wait();
}
+#endif
if(parent)
{
delete statusBar;
OnDestroyed();
+#if !defined(__EMSCRIPTEN__)
delete mutex;
+#endif
delete icon;
if(((subclass(Window))_class).pureVTbl)
child.display.width = display.width;
child.display.height = display.height;
child.display.driverData = display.driverData;
+#if !defined(__EMSCRIPTEN__)
child.display.mutex = null;
+#endif
}
}
}
{
if(guiApp.fullScreenMode && guiApp.desktop.display)
{
+#if !defined(__EMSCRIPTEN__)
guiApp.desktop.mutex.Wait();
+#endif
guiApp.desktop.display.Lock(true);
Update(extent);
}
guiApp.desktop.display.Unlock();
+#if !defined(__EMSCRIPTEN__)
guiApp.desktop.mutex.Release();
+#endif
}
else
{
Window rootWindow = this.rootWindow;
+#if !defined(__EMSCRIPTEN__)
rootWindow.mutex.Wait();
+#endif
display.Lock(true);
Update(extent);
guiApp.SignalEvent();
else
{
+#if !defined(__EMSCRIPTEN__)
guiApp.waitMutex.Wait();
+#endif
guiApp.interfaceDriver.Lock(rootWindow);
if(!rootWindow.style.hidden && rootWindow.dirty)
{
rootWindow.dirty = false;
}
guiApp.interfaceDriver.Unlock(rootWindow);
+#if !defined(__EMSCRIPTEN__)
guiApp.waitMutex.Release();
+#endif
}
display.Unlock();
+#if !defined(__EMSCRIPTEN__)
rootWindow.mutex.Release();
+#endif
}
}
}
void SetupFileMonitor()
{
+#if !defined(__EMSCRIPTEN__)
if(!fileMonitor)
{
fileMonitor = FileMonitor
};
incref fileMonitor;
}
+#endif
}
public:
}
}
+#if !defined(__EMSCRIPTEN__)
if(parent == guiApp.desktop && !mutex)
mutex = Mutex {};
+#endif
if(style.isDocument)
{
SetupFileMonitor();
if(fileName)
{
+#if !defined(__EMSCRIPTEN__)
fileMonitor.fileName = null;
+#endif
saving = true;
if(OnSaveFile(fileName))
//if(OnFileModified != Window::OnFileModified)
{
saving = false;
+#if !defined(__EMSCRIPTEN__)
fileMonitor.fileName = fileName;
+#endif
}
return true;
}
sprintf(filePath, "Untitled %d", documentID);
fileDialog.filePath = filePath;
}
+#if !defined(__EMSCRIPTEN__)
fileMonitor.fileName = null;
+#endif
fileDialog.type = save;
fileDialog.text = $"Save As";
break;
}
}
+#if !defined(__EMSCRIPTEN__)
//if(OnFileModified != Window::OnFileModified && fileName)
{
if(fileName)
fileMonitor.fileName = fileName;
}
+#endif
delete fileDialog;
}
return (bool)result; // Actually returning result from Yes/NoCancel message box
UpdateCaption();
// if(style.isDocument)
+#if !defined(__EMSCRIPTEN__)
if(!saving)
fileMonitor.fileName = value;
+#endif
}
get { return fileName; }
};
int numIcons;
int positionID;
+#if !defined(__EMSCRIPTEN__)
Mutex mutex;
+#endif
WindowState lastState;
+#if !defined(__EMSCRIPTEN__)
FileMonitor fileMonitor;
+#endif
FontResource setFont, systemFont;
FontResource usedFont;
--- /dev/null
+namespace gui::drivers;
+
+#ifdef BUILDING_ECERE_COM
+import "Window"
+import "Interface"
+#else
+#ifdef ECERE_STATIC
+public import static "ecere"
+#else
+public import "ecere"
+#endif
+#endif
+
+#ifdef __EMSCRIPTEN__
+
+#include <stdio.h>
+
+// source file line number printf (sflnprintf)
+#define sflnprintf(format,...) printf("%s:% 5d: " format, __FILE__, __LINE__, ##__VA_ARGS__)
+
+#define property _property
+#define uint _uint
+
+//#include <GLES2/gl2.h>
+#include <GL/glfw.h>
+#include <emscripten/emscripten.h>
+
+#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
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
import "OpenGLDisplayDriver"
#endif
-#if (defined(__unix__) || defined(__APPLE__)) && !defined(ECERE_MINIGLX)
+#if (defined(__unix__) || defined(__APPLE__)) && !defined(ECERE_MINIGLX) && !defined(__EMSCRIPTEN__)
#undef __BLOCKS__
default:
#include <X11/Xatom.h>
#include <X11/Xlib.h>
+#if !defined(__EMSCRIPTEN__)
#include <X11/Xresource.h>
+#endif
#include <X11/Xutil.h>
#include <X11/XKBlib.h>
#include <X11/keysym.h>
#include <X11/cursorfont.h>
#include <fcntl.h>
#if !defined(ECERE_NO3D) && !defined(ECERE_NOGL) //&& !defined(__ODROID__)
+#if defined(__EMSCRIPTEN__)
+#include <GL/glfw.h>
+#else
#include <GL/glx.h>
#endif
+#endif
+#if !defined(__EMSCRIPTEN__)
#include <X11/extensions/Xrender.h>
+#endif
#include <X11/extensions/XShm.h>
#undef Bool
// 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;
*y += client00.y - rcWindow.top;
#else
Box widths = { 0 };
-#if !defined(__ANDROID__)
+#if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__)
XGetBorderWidths(this, widths);
#endif
*x += widths.left;
import "network"
import "List"
+#if !defined(__EMSCRIPTEN__)
+
// SERVER
static enum DCOMPacketType
sendingOut = false;
}
}
+
+#endif // !defined(__EMSCRIPTEN__)
#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
{
mutex.Wait();
}
}
+
+#endif // !defined(__EMSCRIPTEN__)
return true;
}
};
-#endif
+#endif // !defined(ECERE_NOARCHIVE) && !defined(ECERE_VANILLA)
// Directory Description for file listing
class EARDir : struct
}
return result;
}
-#endif
+#endif // !defined(ECERE_NOARCHIVE) && !defined(ECERE_VANILLA)
bool ::QuerySize(const char * archive, FileSize * size)
{
bool result = false;
import "System"
+#if !defined(__EMSCRIPTEN__)
+
public class FileChange
{
public:
return 0;
}
}
+
+#endif // !defined(__EMSCRIPTEN__)
SettingsLocationType readType;
SettingsLocationType writeType;
+#if !defined(__EMSCRIPTEN__)
FileMonitor settingsMonitor
{
this, fileChange = { modified = true };
return true;
}
};
+#endif
File f;
bool locked;
SettingsLocationType type = readType;
if(!f)
{
+#if !defined(__EMSCRIPTEN__)
settingsMonitor.StopMonitoring();
+#endif
if(settingsFilePath)
FileOpenTryRead(type);
{
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
{
if(f)
{
+#if !defined(__EMSCRIPTEN__)
settingsMonitor.StopMonitoring();
+#endif
f.Unlock(0,0,true);
locked = false;
delete f;
Close();
if(settingsFilePath && OnAskReloadSettings != GlobalSettings::OnAskReloadSettings)
{
+#if !defined(__EMSCRIPTEN__)
settingsMonitor.fileName = settingsFilePath;
settingsMonitor.StartMonitoring();
+#endif
}
}
}
namespace sys;
+import "instance"
import "System"
import "Array"
#define uint _uint
#define set _set
#define String _String
-#if defined(__WIN32__)
+#if defined(__WIN32__) && !defined(__EMSCRIPTEN__)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#else
public class Mutex : struct
{
+#if !defined(__EMSCRIPTEN__)
+
// class_fixed
#if defined(__WIN32__)
#ifdef _DEBUG
#else
pthread_mutex_t mutex;
#endif
+#endif
#ifdef _DEBUG
int64 owningThread;
Mutex()
{
+#if !defined(__EMSCRIPTEN__)
#if defined(__WIN32__)
#ifdef _DEBUG
mutex = CreateMutex(null, FALSE, null);
pthread_mutex_init(&mutex, &attr);
pthread_mutexattr_destroy(&attr);
#endif
+#endif
+
lockCount = 0;
#ifdef _DEBUG
owningThread = 0;
~Mutex()
{
+#if !defined(__EMSCRIPTEN__)
#if defined(__WIN32__)
#ifdef _DEBUG
CloseHandle(mutex);
#else
pthread_mutex_destroy(&mutex);
#endif
+#endif
}
public:
{
if(this)
{
+#if !defined(__EMSCRIPTEN__)
/*
if(this == globalSystem.fileMonitorMutex)
printf("[%d] Waiting on Mutex %x\n", (int)GetCurrentThreadID(), this);
#endif
#endif
+#endif
+
#ifdef _DEBUG
owningThread = GetCurrentThreadID();
#endif
{
if(this)
{
+#if !defined(__EMSCRIPTEN__)
/*
if(this == globalSystem.fileMonitorMutex)
printf("[%d] Releasing Mutex %x\n", (int)GetCurrentThreadID(), this);
pthread_mutex_unlock(&mutex);
#endif
#endif
+#endif
+
#ifdef _DEBUG
if(lockCount < 0)
PrintLn("WARNING: lockCount < 0");
public class Semaphore : struct
{
+#if !defined(__EMSCRIPTEN__)
+
#if defined(__WIN32__)
HANDLE handle;
#elif defined(__APPLE__)
#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__)
#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__)
#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__)
#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?");
sem_wait(&semaphore);
#endif
#endif
+#endif
}
void Release(void)
{
+#if !defined(__EMSCRIPTEN__)
#if defined(__WIN32__)
ReleaseSemaphore(handle, 1, null);
#elif defined(__APPLE__)
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);
sem_destroy(&semaphore);
sem_init(&semaphore, 0, initCount);
#endif
+#endif
initCount = value;
}
get { return initCount; }
{
set
{
+#if !defined(__EMSCRIPTEN__)
#if defined(__WIN32__)
if(handle) CloseHandle(handle);
handle = CreateSemaphore(null, value, maxCount, null);
#endif
+#endif
maxCount = value;
}
get { return maxCount; }
#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"
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
};
#if defined(__WIN32__)
HANDLE handle;
uint id;
-#else
+#elif !defined(__EMSCRIPTEN__)
pthread_t id;
bool dontDetach;
Semaphore sem { };
uint returnCode;
bool started;
+#if !defined(__EMSCRIPTEN__)
#if defined(__WIN32__)
uint ThreadCallBack()
#else
return (void *)(uintptr_t)returnCode;
#endif
}
+#endif
public:
virtual uint Main(void);
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)
{
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)
{
if(started)
pthread_kill(id, SIGQUIT);
#endif
+#endif
if(started)
{
started = false;
void Wait()
{
+#if !defined(__EMSCRIPTEN__)
#if defined(__WIN32__)
if(WaitForSingleObject(handle, INFINITE /*2000*/) == WAIT_TIMEOUT)
PrintLn("Thread not returning?\n");
if(started)
sem.Wait();
#endif
+#endif
}
void SetPriority(ThreadPriority priority)
{
+#if !defined(__EMSCRIPTEN__)
#if defined(__WIN32__)
SetThreadPriority(handle, priority);
#else
pthread_setschedparam(id, policy, ¶m);
*/
#endif
+#endif
}
property bool created { get { return started; } };
}
+
+import "instance"
#ifndef ECERE_NOFILE
import "File"
#endif
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];
-import "ecere"
+import IMPORT_STATIC "ecere"
class HelloForm : Window
{
"Name" : "Debug",
"Options" : {
"Debug" : true,
+ "PreprocessorDefinitions" : [
+ "IMPORT_STATIC="
+ ],
"FastMath" : false
}
},
"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" : [