3 #if defined(__unix__) || defined(__APPLE__)
4 #define property _property
9 #define Window X11Window
10 #define Cursor X11Cursor
12 #define Display X11Display
14 #define KeyCode X11KeyCode
15 #define Picture X11Picture
17 #include <X11/Xutil.h>
34 #if !defined(ECERE_VANILLA) && !defined(ECERE_NONET)
35 #if defined(__WIN32__)
37 #define WIN32_LEAN_AND_MEAN
39 static WSADATA wsaData;
41 #elif defined(__unix__) || defined(__APPLE__)
48 #include <netinet/in.h>
50 #include <sys/socket.h>
52 #include <sys/types.h>
54 #include <arpa/inet.h>
59 typedef struct hostent HOSTENT;
60 typedef struct sockaddr SOCKADDR;
61 typedef struct sockaddr_in SOCKADDR_IN;
62 typedef struct in_addr IN_ADDR;
63 #define closesocket(s) close(s)
70 #if defined(__APPLE__)
71 import "CocoaInterface"
72 #elif defined(__unix__)
78 GuiApplication guiApp;
81 enum GuiErrorCode : ErrorCode
83 driverNotSupported = ErrorCode { VeryFatal, 1 },
84 windowCreationFailed = ErrorCode { VeryFatal, 2 },
85 graphicsLoadingFailed = ErrorCode { VeryFatal, 3 },
86 modeSwitchFailed = ErrorCode { VeryFatal, 4 }
89 static Array<String> errorMessages
92 $"Graphics driver not supported by any user interface system",
93 $"Window creation failed",
94 $"Window graphics loading failed",
95 $"Driver/Mode switch failed"
98 public class GuiApplication : Application
107 subclass(Interface) interfaceDriver;
108 subclass(Skin) currentSkin;
115 bool fullScreenMode; // Needs to start at true for the desktop to resize
118 Resolution resolution;
119 PixelFormat pixelFormat;
122 char * defaultDisplayDriver;
124 Cursor systemCursors[SystemCursor];
128 OldList customCursors;
131 OldList windowTimers;
134 Window prevWindow; // Used for OnMouseLeave
135 Window windowCaptured;
137 // Mouse based moving & resizing
139 Point windowMovingStart;
140 Point windowMovingBefore;
141 Size windowResizingBefore;
143 bool windowIsResizing;
144 bool resizeX, resizeEndX;
145 bool resizeY, resizeEndY;
147 // Mouse based scrolling
148 Window windowScrolling;
149 Point windowScrollingBefore, windowScrollingStart;
152 Bitmap cursorBackground { };
153 int cursorBackgroundX, cursorBackgroundY;
154 int cursorBackgroundW, cursorBackgroundH;
160 Window acquiredWindow;
161 int acquiredMouseX, acquiredMouseY;
163 Cursor currentCursor;
165 uint errorLevel, lastErrorCode;
173 Window interimWindow;
177 uint timerResolution;
180 Point virtualScreenPos;
188 mainThread = GetCurrentThreadID();
192 strcpy(appName, $"ECERE Application");
197 // customCursors.offset = OFFSET(Cursor, prev);
198 windowTimers.offset = (uint)&((Timer)0).prev;
200 for(c = 0; c<SystemCursor::enumSize; c++)
201 systemCursors[c] = Cursor { systemCursor = c; };
203 globalSystem.eventSemaphore = Semaphore { };
204 globalSystem.fileMonitorMutex = Mutex { };
205 globalSystem.fileMonitors.offset = (uint)&((FileMonitor)0).prev;
216 customCursors.Clear();
218 #if defined(__unix__)
220 XUnlockDisplay(xGlobalDisplay);
227 interfaceDriver.Terminate();
230 // interfaceDrivers.Free(null);
236 for(c = 0; c<SystemCursor::enumSize; c++)
237 delete systemCursors[c];
239 #if !defined(ECERE_VANILLA) && !defined(ECERE_NONET)
243 delete globalSystem.eventSemaphore;
244 delete globalSystem.fileMonitorMutex;
245 delete globalSystem.fileMonitorThread;
247 UnapplySkin(class(Window));
253 Time time = GetTime();
256 for(timer = windowTimers.first; timer; timer = timer.next)
257 timer.dispatched = false;
260 for(timer = windowTimers.first; timer; timer = timer.next)
262 if(!timer.dispatched)
264 if((timer.delay - (Seconds)(time - timer.lastTime)) < Seconds { 0.00001 })
267 timer.lastTime = time;
268 if(timer.DelayExpired(timer.window))
270 timer.dispatched = true;
272 eInstance_DecRef(timer);
282 // --- Mouse-based window movement ---
283 void SetCurrentCursor(Cursor cursor)
285 currentCursor = cursor;
288 if(fullScreenMode && cursor.bitmap)
289 interfaceDriver.SetMouseCursor((SystemCursor)-1);
292 interfaceDriver.SetMouseCursor(cursor.systemCursor);
293 cursorBackground.Free();
299 void PreserveAndDrawCursor()
302 if(!acquiredWindow && cursorUpdate && currentCursor && currentCursor->bitmap)
306 Box against = {0,0, desktop.w-1,desktop.h-1};
307 Box box = {0, 0, currentCursor->bitmap->width,currentCursor->bitmap->height};
309 interfaceDriver->GetMousePosition(&mouseX, &mouseY);
311 mouseX -= currentCursor->hotSpotX;
312 mouseY -= currentCursor->hotSpotY;
314 // Preserve Background
315 if(!(eDisplay_GetFlags(desktop.display) & DISPLAY_FLIPPING))
317 cursorBackgroundX = mouseX;
318 cursorBackgroundY = mouseY;
319 cursorBackgroundW = currentCursor->bitmap->width;
320 cursorBackgroundH = currentCursor->bitmap->height;
321 eDisplay_Grab(desktop.display, cursorBackground,
322 mouseX, mouseY, cursorBackgroundW, cursorBackgroundH);
325 eBox_ClipOffset(&box, &against, mouseX, mouseY);
327 if(!(eDisplay_GetFlags(desktop.display) & DISPLAY_FLIPPING))
328 eDisplay_StartUpdate(desktop.display);
330 surface = eDisplay_GetSurface(desktop.display, mouseX, mouseY, &box);
333 eSurface_SetForeground(surface, WHITE);
334 eSurface_Blit(surface, currentCursor->bitmap, 0,0, 0,0,
335 currentCursor->bitmap->width,currentCursor->bitmap->height);
336 eInstance_Delete(surface);
338 if(!(eDisplay_GetFlags(desktop.display) & DISPLAY_FLIPPING))
343 box.bottom += mouseY;
344 eDisplay_Update(desktop.display, &box);
347 if(!(eDisplay_GetFlags(desktop.display) & DISPLAY_FLIPPING))
348 eDisplay_EndUpdate(desktop.display);
353 void RestoreCursorBackground()
356 // Restore Cursor Background
357 if(cursorBackground && desktop.active)
359 Box box = {0, 0, cursorBackgroundW-1,cursorBackgroundH-1};
360 Box against = {0,0, desktop.w-1,desktop.h-1};
363 eBox_ClipOffset(&box, &against, cursorBackgroundX, cursorBackgroundY);
364 if((surface = eDisplay_GetSurface(desktop.display, cursorBackgroundX,cursorBackgroundY, &box)))
366 eSurface_Blit(surface, cursorBackground, 0, 0, 0,0, cursorBackgroundW,cursorBackgroundH);
367 eInstance_Delete(surface);
373 bool IsModeSwitching()
375 return modeSwitching;
378 public bool SetDesktopPosition(int x, int y, int w, int h, bool moveChildren)
381 bool windowResized = desktop.size.w != w || desktop.size.h != h;
382 bool windowMoved = desktop.clientStart.x != x || desktop.clientStart.y != y;
384 if((windowResized || windowMoved) && moveChildren)
387 desktop.Position(x, y, w, h, true, true, true, true, false, false);
389 // Maximized native decorations windows suffer when we drag the dock around, so remaximize them
390 // It's a little jumpy, but oh well.
391 for(child = desktop.children.first; child; child = child.next)
393 if(child.nativeDecorations && child.rootWindow == child && child.state == maximized)
395 child.state = normal;
396 child.state = maximized;
399 /*for(child = desktop.children.first; child; child = child.next)
401 if(!child.systemParent)
406 child.ComputeAnchors(
407 child.ax, child.ay, child.aw, child.ah,
409 child.Position(x, y, w, h, true, true, true, true, false);
411 if(child.state == Maximized)
415 child.ComputeAnchors(,
416 A_LEFT,A_LEFT,A_OFFSET,A_OFFSET,
418 child.Position(, x, y, w, h, false, true, true, true, false);
424 desktop.display.Lock(true);
427 if(!desktop.display.Resize(desktop.size.w, desktop.size.h))
430 desktop.dirty = true;
431 if(!desktop.display.flags.flipping)
432 desktop.Update(null);
434 // When does the desktop have a display in not fullscreen mode?
435 if(!fullScreenMode && !modeSwitching)
436 desktop.UpdateDisplay();
437 desktop.display.Unlock();
441 desktop.SetPosition(x, y, w, h, false, false, false);
445 void SetAppFocus(bool state)
447 // Shouldn't be property here
448 desktop.active = state;
451 bool SelectSkin(char * skinName)
457 for(link = class(Skin).derivatives.first; link; link = link.next)
460 if(skin.name && !strcmp(skin.name, skinName))
463 if(!link) skin = null;
467 if(skin != currentSkin || !currentSkin)
469 // Try finding a driver to support this mode
470 if(skin.textMode != textMode)
476 bool needReload = false;
478 if(!modeSwitching && currentSkin)
480 modeSwitching = true;
481 desktop.UnloadGraphics(true);
485 UnapplySkin(class(Window));
489 ApplySkin(class(Window), skin.name, null);
493 if(desktop.SetupDisplay())
494 if(desktop.LoadGraphics(false, true))
496 modeSwitching = false;
508 void Initialize(bool switchMode)
510 static bool initialized = false;
513 // if(!initialized && eClass_IsDerived(__ecereModule->app->module.inst.class, guiApplicationClass))
516 char * defaultDriver = null;
517 #if defined(ECERE_VANILLA) || defined(ECERE_ONEDRIVER)
518 char * driver = null;
521 // char * driver = getenv("ECERE_DRIVER");
522 char * driver = null;
523 static char driverStorage[1024];
524 GetEnvironment("ECERE_DRIVER", driverStorage, sizeof(driverStorage));
525 if(driverStorage[0]) driver = driverStorage;
529 fullScreenMode = true; // Needs to start at true for the desktop to resize
530 // Set this to true earlier so we can override it!
536 #if defined(__unix__)
538 XLockDisplay(xGlobalDisplay);
544 desktop = Window { nativeDecorations = false };
547 desktop.childrenOrder.circ = true;
548 desktop.childrenCycle.circ = true;
549 desktop.background = blue;
550 desktop.rootWindow = desktop;
551 desktop.cursor = GetCursor(arrow);
552 desktop.caption = appName;
553 *&desktop.visible = true;
554 desktop.position = Point { };
555 desktop.mutex = Mutex { };
556 desktop.created = true;
559 #if defined(__WIN32__)
562 defaultDriver = driver;
563 else if(this.isGUIApp && !textMode)
564 defaultDriver = "GDI";
566 defaultDriver = "Win32Console";
568 #elif defined(__APPLE__)
571 defaultDriver = driver;
573 defaultDriver = "CocoaOpenGL";
577 if(this.isGUIApp && !textMode)
579 char * display = getenv("DISPLAY");
581 if(!display || !display[0] || !SwitchMode(false, "X", 0, 0, 0, null, true))
582 defaultDriver = "NCurses";
583 // SwitchMode(true, "NCurses", 0, PixelFormatText, 0, null, true);
587 defaultDriver = driver;
590 defaultDriver = "NCurses";
595 SwitchMode(false, defaultDriver, 0, 0, 0, null, true);
599 #if defined(__WIN32__)
600 SwitchMode(true, "Win32Console", 0, PixelFormatText, 0, null, true);
605 SwitchMode(true, "SVGA", Res640x480, PixelFormat8, 0, null, true);
608 #if defined(__APPLE__)
609 SwitchMode(true, "CocoaOpenGL", 0, 0, 0, null, true);
612 #if defined(__unix__)
613 #if defined(ECERE_MINIGLX)
614 SwitchMode(true, "OpenGL", 0, 0, 0, null, true);
622 defaultDisplayDriver = defaultDriver;
627 virtual bool Init(void);
628 virtual bool Cycle(bool idle);
629 virtual void Terminate(void);
639 // better solution when designing tab order/activated window etc, why do windows move in the list?
642 for(window = desktop.children.first; window; window = window.next)
644 if(window.autoCreate && !window.created)
658 while(desktop && interfaceDriver)
662 if(terminateX != terminated)
664 terminated = terminateX;
670 //printf("Resetting terminate X to 0\n");
674 for(child = desktop.children.first; child; child = child.next)
675 if(child.created && child.visible)
679 for(window = desktop.children.first; window; window = window.next)
680 if(window.mutex) window.mutex.Wait();
682 for(window = desktop.children.first; window; window = window.next)
683 if(window.mutex) window.mutex.Release();
684 wait = !ProcessInput(true);
686 if(lockMutex.owningThread != GetCurrentThreadID())
687 PrintLn("WARNING: ProcessInput returned unlocked GUI!");
696 #if defined(__unix__)
698 XUnlockDisplay(xGlobalDisplay);
704 #if defined(__unix__)
706 XLockDisplay(xGlobalDisplay);
710 eInstance_DecRef(desktop);
718 #if defined(__unix__)
720 XUnlockDisplay(xGlobalDisplay);
728 interfaceDriver.Wait();
734 #if defined(__unix__)
736 XLockDisplay(xGlobalDisplay);
740 bool ProcessInput(bool useProcessAll)
746 #if !defined(ECERE_VANILLA) && !defined(ECERE_NONET)
747 ProcessNetworkEvents();
751 result = interfaceDriver.ProcessInput(useProcessAll && processAll);
752 if(!desktop || !interfaceDriver) return;
756 for(child = app.desktop.children.first; child; child = child.next)
757 if(child.created && child.visible)
759 if(!child) return result;
762 result |= UpdateTimers();
763 result |= ProcessFileNotifications();
766 result |= ProcessFileNotifications();
767 result |= UpdateTimers();
768 result |= interfaceDriver.ProcessInput(useProcessAll && processAll);
775 void UpdateDisplay(void)
777 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
778 if(Desktop3DUpdateDisplay()) return;
783 if(fullScreenMode && desktop.display)
785 desktop.mutex.Wait();
788 desktop.display.Lock(true);
790 if(desktop.dirty || cursorUpdate)
792 if(desktop.display.flags.flipping)
793 desktop.Update(null);
794 desktop.UpdateDisplay();
797 if(cursorUpdate || desktop.dirty)
799 PreserveAndDrawCursor();
800 cursorUpdate = false;
801 desktop.dirty = false;
802 RestoreCursorBackground();
805 desktop.display.Unlock();
807 desktop.mutex.Release();
813 for(window = desktop.children.first; window; window = window.next)
815 if(window.mutex) window.mutex.Wait();
816 if(window.visible && window.dirty)
818 // Logf("Updating %s\n", window.name);
819 interfaceDriver.Lock(window);
822 if(window.display.current)
826 window.display.Lock(true);
827 window.UpdateDisplay();
828 window.display.Unlock();
831 window.dirty = false;
832 interfaceDriver.Unlock(window);
834 Log("--------------\n");
838 if(window.mutex) window.mutex.Release();
846 globalSystem.eventSemaphore.Wait();
849 #if !defined(ECERE_VANILLA) && !defined(ECERE_NONET)
850 bool ProcessNetworkEvents()
852 bool gotEvent = false;
853 #if defined(__WIN32__) || defined(__unix__) || defined(__APPLE__)
854 if(network.networkInitialized)
858 struct timeval tv = {0, 0};
863 PauseNetworkEvents();
864 network.mutex.Wait();
867 if(network.connectEvent || network.networkEvent)
868 Log("[P] [NProcess]\n");
870 rs = network.readSet;
871 ws = network.writeSet;
872 es = network.exceptSet;
874 if((network.ns && select(network.ns, &rs, &ws, &es, &tv)) || network.leftOverBytes)
876 network.leftOverBytes = false;
878 // Danger here? Why looping with a next and not unlocking anything?
879 for(socket = network.connectSockets.first; socket; socket = next)
882 if(!socket.processAlone && FD_ISSET(socket.s, &ws))
884 network.mutex.Release();
885 socket.connectThread.Wait();
886 network.mutex.Wait();
889 for(socket = network.sockets.first; socket; socket = next)
892 if(!socket.processAlone)
894 network.mutex.Release();
895 gotEvent |= socket.ProcessSocket(&rs, &ws, &es);
896 network.mutex.Wait();
900 for(service = network.services.first; service; service = nextService)
902 nextService = service.next;
903 if(!service.processAlone)
905 if(FD_ISSET(service.s, &rs))
908 Logf("[P] Accepting connection (%x)\n", service.s);
910 service.accepted = false;
912 if(!service.accepted)
916 int addrLen = sizeof(a);
917 s = accept(service.s,(SOCKADDR *)&a,&addrLen);
923 Log("[P] Connection accepted\n");
927 for(socket = service.sockets.first; socket; socket = next)
930 if(!socket.processAlone)
932 network.mutex.Release();
933 gotEvent |= socket.ProcessSocket(&rs, &ws, &es);
934 network.mutex.Wait();
939 if(network.connectEvent)
945 for(socket = network.connectSockets.first; socket; socket = next)
948 if(socket._connected && socket._connected != -2)
950 network.connectSockets.Remove(socket);
951 delete socket.connectThread;
953 // printf("%s is connected = %d\n", socket._class.name, socket._connected);
954 if(socket._connected == -1)
957 Logf("[P] Processing disconnected connect (%x)\n", socket.s);
960 if(socket.disconnectCode == ResolveFailed)
961 Logf("Error resolving address %s\n", socket.address);
963 if(socket.s == network.ns - 1)
964 Network_DetermineMaxSocket();
969 else if(socket._connected == 1)
972 Log("[P] Processing connected connect\n");
974 FD_CLR(socket.s, &network.writeSet);
975 FD_SET(socket.s, &network.readSet);
976 FD_SET(socket.s, &network.exceptSet);
977 network.mutex.Release();
979 // printf("Calling OnConnect on %s\n", socket._class.name);
981 network.mutex.Wait();
982 network.sockets.Add(socket);
990 network.connectEvent = false;
992 if(network.networkEvent)
994 network.networkEvent = false;
995 network.selectSemaphore.Release();
1000 for(semPtr = network.mtSemaphores.first; semPtr; semPtr = semPtr.next)
1002 ((Semaphore)semPtr.data).Release();
1006 network.mutex.Release();
1007 ResumeNetworkEvents();
1013 void WaitNetworkEvent()
1015 if(network.networkInitialized)
1017 if(GetCurrentThreadID() == network.mainThreadID)
1023 Semaphore semaphore { };
1024 OldLink semPtr { data = semaphore };
1025 network.mutex.Wait();
1026 network.mtSemaphores.Add(semPtr);
1027 network.mutex.Release();
1029 ResumeNetworkEvents();
1031 PauseNetworkEvents();
1032 network.mutex.Wait();
1033 network.mtSemaphores.Delete(semPtr);
1034 network.mutex.Release();
1040 void PauseNetworkEvents()
1042 if(network.networkInitialized)
1044 network.processMutex.Wait();
1048 void ResumeNetworkEvents()
1050 if(network.networkInitialized)
1052 network.processMutex.Release();
1057 void SignalEvent(void)
1059 globalSystem.eventSemaphore.Release();
1062 // TODO: Might want to make this private with simpler public version?
1063 bool SwitchMode(bool fullScreen, char * driverName, Resolution resolution, PixelFormat colorDepth, int refreshRate, char * skinName, bool fallBack)
1065 bool result = false;
1068 bool fbFullScreen = 0;
1069 Resolution fbResolution = 0;
1070 PixelFormat fbColorDepth = 0;
1071 int fbRefreshRate = 0;
1072 subclass(Interface) inter;
1073 subclass(Skin) skin = null;
1079 for(link = class(Skin).derivatives.first; link; link = link.next)
1082 if(skin.name && !strcmp(skin.name, skinName))
1085 if(!link) skin = null;
1090 fbDriver = defaultDisplayDriver;
1091 inter = interfaceDriver;
1094 interfaceDriver.GetCurrentMode(&fbFullScreen, &fbResolution, &fbColorDepth, &fbRefreshRate);
1096 if(!driverName && !interfaceDriver)
1097 driverName = defaultDisplayDriver;
1099 if(driverName || (skin && skin.textMode != textMode))
1101 for(link = class(Interface).derivatives.first; link; link = link.next)
1103 bool foundDriver = false;
1105 char ** graphicsDrivers;
1108 graphicsDrivers = inter.GraphicsDrivers(&numDrivers);
1110 for(c=0; c<numDrivers; c++)
1111 if(!driverName || !strcmp(driverName, graphicsDrivers[c]))
1113 if(!skin || skin.textMode == IsDriverTextMode(graphicsDrivers[c]))
1115 driverName = graphicsDrivers[c];
1130 #if defined(__WIN32__)
1131 #if !defined(ECERE_VANILLA)
1132 if(!strcmp(driverName, "Win32Console")) inter = (subclass(Interface))class(Win32ConsoleInterface); else
1134 inter = (subclass(Interface))class(Win32Interface);
1136 if(!strcmp(driverName, "X")) inter = (subclass(Interface))class(XInterface);
1137 else inter = (subclass(Interface))class(NCursesInterface);
1142 if(interfaceDriver && (!driverName || (fbDriver && !strcmp(fbDriver, driverName))) &&
1143 fullScreen == fbFullScreen &&
1144 (!resolution || resolution == fbResolution) &&
1145 (!colorDepth || colorDepth == fbColorDepth) &&
1146 (!refreshRate || refreshRate == fbRefreshRate) &&
1147 (currentSkin && (!skinName || !strcmp(currentSkin.name, skinName))))
1151 bool wasFullScreen = fullScreenMode;
1152 subclass(Skin) oldSkin = currentSkin;
1155 modeSwitching = true;
1158 desktop.UnloadGraphics(true);
1160 if(inter != interfaceDriver)
1164 interfaceDriver.Terminate();
1166 result = inter.Initialize();
1174 interfaceDriver = inter;
1175 interfaceDriver.SetTimerResolution(timerResolution);
1176 inter.EnsureFullScreen(&fullScreen);
1177 fullScreenMode = fullScreen;
1179 if((!wasFullScreen && !fullScreen) ||
1180 inter.ScreenMode(fullScreen, resolution, colorDepth, refreshRate, &textMode))
1182 if(!fbDriver || (driverName && strcmp(fbDriver, driverName)))
1183 defaultDisplayDriver = driverName;
1185 if(!skinName || !SelectSkin(skinName))
1187 if(!currentSkin || currentSkin.textMode != textMode ||
1188 !SelectSkin(currentSkin.name))
1191 subclass(Skin) skin = null;
1193 for(link = class(Skin).derivatives.first; link; link = link.next)
1196 if(skin.textMode == textMode)
1199 if(!link) skin = null;
1202 SelectSkin(skin.name);
1206 if(currentSkin && desktop.SetupDisplay())
1208 desktop.active = true;
1212 desktop.display.Lock(false);
1213 desktop.display.Position(0,0);
1214 desktop.display.Unlock();
1217 if(desktop.LoadGraphics(false, oldSkin != currentSkin))
1221 desktop.UpdateDisplay();
1224 this.fullScreen = fullScreen;
1230 modeSwitching = false;
1232 LogErrorCode(modeSwitchFailed, driverName ? driverName : defaultDisplayDriver);
1235 LogErrorCode(driverNotSupported, driverName ? driverName : defaultDisplayDriver);
1237 if(!result && fallBack && fbDriver)
1239 if(!SwitchMode(fbFullScreen, fbDriver, fbResolution, fbColorDepth, fbRefreshRate, null, false))
1240 Log($"Error falling back to previous video mode.\n");
1245 bool ProcessFileNotifications()
1247 bool activity = false;
1248 FileMonitor monitor, next;
1249 static int reentrant = 0;
1251 // Reentrant FileNotification is asking for trouble since each monitor is spawning a Modal() MessageBox
1252 if(reentrant) return false;
1253 // printf("[%d] Waiting in ProcessFileNotifications for fileMonitor Mutex %x...\n", GetCurrentThreadID(), globalSystem.fileMonitorMutex);
1254 globalSystem.fileMonitorMutex.Wait();
1256 for(monitor = globalSystem.fileMonitors.first; monitor; monitor = next)
1260 next = monitor.next;
1265 if(!monitor.reentrant && !monitor.toBeFreed)
1267 monitor.reentrant = true;
1268 while((notify = monitor.fileNotifies.first))
1270 monitor.fileNotifies.Remove(notify);
1274 if(monitor.directory)
1276 if(!monitor.OnDirNotify(monitor.data, notify.action, notify.fileName, notify.param))
1277 monitor.StopMonitoring();
1281 if(!monitor.OnFileNotify(monitor.data, notify.action, notify.param))
1282 monitor.StopMonitoring();
1285 monitor.reentrant = false;
1291 monitor.reentrant = false;
1294 if(next && next._refCount > 1)
1302 for(monitor = globalSystem.fileMonitors.first; monitor; monitor = next)
1304 next = monitor.next;
1305 if(monitor.toBeFreed && !monitor.reentrant)
1306 monitor.FreeMonitor();
1309 // printf("[%d] Releasing in ProcessFileNotifications fileMonitor Mutex %x...\n", GetCurrentThreadID(), globalSystem.fileMonitorMutex);
1310 globalSystem.fileMonitorMutex.Release();
1317 #if defined(__unix__)
1319 XLockDisplay(xGlobalDisplay);
1325 #if defined(__unix__)
1327 XUnlockDisplay(xGlobalDisplay);
1329 lockMutex.Release();
1332 Cursor GetCursor(SystemCursor cursor)
1334 return systemCursors[cursor];
1337 bool GetKeyState(Key key)
1339 return interfaceDriver.GetKeyState(key);
1342 bool GetMouseState(MouseButtons * buttons, int * x, int * y)
1344 return interfaceDriver.GetMouseState(buttons, x, y);
1348 property char * appName
1352 strcpy(appName, value);
1353 if(desktop) desktop.text = appName;
1357 return (char *)(this ? appName : null);
1360 property Semaphore semaphore { get { return globalSystem.eventSemaphore; } };
1361 property bool alwaysEmptyInput{ set { processAll = value; } get { return processAll; } };
1362 property bool fullScreen
1366 SwitchMode(value, defaultDisplayDriver, resolution,
1367 pixelFormat, refreshRate, currentSkin ? currentSkin.name : null, true);
1369 get { return this ? fullScreen : false; }
1371 property char * driver
1375 SwitchMode( fullScreen, value, resolution, pixelFormat, refreshRate,
1376 currentSkin ? currentSkin.name : null, true);
1378 get { return this ? defaultDisplayDriver : null; }
1380 property Resolution resolution
1384 SwitchMode(fullScreen, defaultDisplayDriver, value, pixelFormat, refreshRate,
1385 currentSkin ? currentSkin.name : null, true);
1387 get { return this ? resolution : 0; }
1389 property PixelFormat pixelFormat
1393 SwitchMode(fullScreen, defaultDisplayDriver, resolution,
1394 pixelFormat, refreshRate, currentSkin ? currentSkin.name : null, true);
1396 get { return this ? pixelFormat : 0; }
1398 property int refreshRate
1402 SwitchMode(fullScreen, defaultDisplayDriver, resolution,
1403 pixelFormat, refreshRate, currentSkin ? currentSkin.name : null, true);
1405 get { return this ? refreshRate : 0; }
1407 property char * skin
1409 set { SelectSkin(value); }
1410 get { return (this && currentSkin) ? currentSkin.name : null; }
1412 property bool textMode
1414 set { textMode = value; } // TODO: Implement switching
1415 get { return this ? textMode : false; }
1417 property Window desktop { get { return this ? desktop : null; } };
1418 property char ** drivers { get { return null; } };
1419 property char ** skins { get { return null; } };
1420 property subclass(Skin) currentSkin { get { return this ? currentSkin : null; } };
1421 property int numDrivers { get { return 0; } };
1422 property int numSkins { get { return 0; } };
1423 property uint timerResolution
1425 set { timerResolution = value; if(interfaceDriver) interfaceDriver.SetTimerResolution(value); }