[DEV] rework interface thread GUI

This commit is contained in:
Edouard DUPIN 2022-04-01 00:54:26 +02:00
parent 20887460f1
commit 5b3e45405c
6 changed files with 425 additions and 269 deletions

View File

@ -258,6 +258,10 @@ public class GaleApplication {
Gale.getContext().setCursor(this.cursor); Gale.getContext().setCursor(this.cursor);
} }
void setForceRedraw() {
this.needRedraw = true;
}
/** /**
* set the Icon of the application. * set the Icon of the application.
* @param iconFile File name icon (.bmp/.png). * @param iconFile File name icon (.bmp/.png).
@ -293,16 +297,19 @@ public class GaleApplication {
if (size.x() <= 0 || size.y() <= 0) { if (size.x() <= 0 || size.y() <= 0) {
Log.error("Wrong windows size: " + size); Log.error("Wrong windows size: " + size);
} }
Vector2f oldSize = this.windowsSize; final Vector2f oldSize = this.windowsSize;
this.windowsSize = size; this.windowsSize = size;
final GaleContext context = Gale.getContext(); final GaleContext context = Gale.getContext();
if (context == null) { if (context == null) {
return; return;
} }
if (!context.setSize(size)) { context.setSize(size);
/* ==> change API ==> need the GUI notify the Windows that the size has change ????
if (!) {
Log.error("Can not set the size required by the user."); Log.error("Can not set the size required by the user.");
this.windowsSize = oldSize; this.windowsSize = oldSize;
} }
*/
} }
/** /**

View File

@ -1,7 +1,6 @@
package org.atriasoft.gale.context; package org.atriasoft.gale.context;
import java.time.Clock; import java.time.Clock;
import java.util.Vector;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
@ -9,6 +8,7 @@ import org.atriasoft.etk.Color;
import org.atriasoft.etk.ThreadAbstract; import org.atriasoft.etk.ThreadAbstract;
import org.atriasoft.etk.Uri; import org.atriasoft.etk.Uri;
import org.atriasoft.etk.math.Vector2f; import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.etk.util.AutoUnLock;
import org.atriasoft.gale.Fps; import org.atriasoft.gale.Fps;
import org.atriasoft.gale.Gale; import org.atriasoft.gale.Gale;
import org.atriasoft.gale.GaleApplication; import org.atriasoft.gale.GaleApplication;
@ -48,8 +48,6 @@ public abstract class GaleContext {
GaleContext.globalContext = context; GaleContext.globalContext = context;
} }
Lock lock = new ReentrantLock();
protected ThreadAbstract periodicThread; protected ThreadAbstract periodicThread;
protected GaleApplication application; //!< Application handle protected GaleApplication application; //!< Application handle
protected ApplicationState applicationState = ApplicationState.UNDEFINED; // state of the application protected ApplicationState applicationState = ApplicationState.UNDEFINED; // state of the application
@ -58,7 +56,10 @@ public abstract class GaleContext {
// simulation area: // simulation area:
private long previousDisplayTime; // this is to limit framerate ... in case... private long previousDisplayTime; // this is to limit framerate ... in case...
private final boolean displayFps = true; private final boolean displayFps = true;
private final MessageSystem msgSystem = new MessageSystem();
private final Lock msgSystemAsyncLock = new ReentrantLock();
private final MessageSystem msgSystemAsync = new MessageSystem();
private final MessageSystem msgSystemGui = new MessageSystem();
private final Fps fpsSystemEvent = new Fps("SystemEvent", this.displayFps); private final Fps fpsSystemEvent = new Fps("SystemEvent", this.displayFps);
private final Fps fpsSystemContext = new Fps("SystemContext", this.displayFps); private final Fps fpsSystemContext = new Fps("SystemContext", this.displayFps);
private final Fps fpsSystem = new Fps("System", this.displayFps); private final Fps fpsSystem = new Fps("System", this.displayFps);
@ -112,9 +113,9 @@ public abstract class GaleContext {
// } // }
//cout.setOutputFile(true); //cout.setOutputFile(true);
Log.info("GALE v:" + Gale.getVersion()); Log.info("GALE v: {}", Gale.getVersion());
forceOrientation(Orientation.screenAuto); forceOrientation(Orientation.screenAuto);
postAction(context -> { postActionAsync(context -> {
final GaleApplication appl = context.getApplication(); final GaleApplication appl = context.getApplication();
if (appl == null) { if (appl == null) {
this.applicationState = ApplicationState.UNDEFINED; this.applicationState = ApplicationState.UNDEFINED;
@ -152,7 +153,15 @@ public abstract class GaleContext {
* force the screen orientation (availlable on portable elements ... * force the screen orientation (availlable on portable elements ...
* @param orientation Selected orientation. * @param orientation Selected orientation.
*/ */
public void forceOrientation(final Orientation orientation) {} public final void forceOrientation(final Orientation orientation) {
postActionToGui(context -> {
context.forceOrientationThreadGUI(orientation);
});
}
protected void forceOrientationThreadGUI(final Orientation orientation) {
Log.todo("forceOrientation: not implemented");
}
/** /**
* Redraw all the windows * Redraw all the windows
@ -169,16 +178,20 @@ public abstract class GaleContext {
// Called by Consumer // Called by Consumer
public ActionToDoInAsyncLoop getAction() { public ActionToDoInAsyncLoop getAction() {
return this.msgSystem.getElementWait(); return this.msgSystemAsync.getElementWait();
} }
public GaleApplication getApplication() { public GaleApplication getApplication() {
this.lock.lock(); return this.application;
/*
* pb on this lock ...
this.msgSystemAsyncLock.lock();
try { try {
return this.application; return this.application;
} finally { } finally {
this.lock.unlock(); this.msgSystemAsyncLock.unlock();
} }
*/
} }
public CommandLine getCmd() { public CommandLine getCmd() {
@ -213,19 +226,42 @@ public abstract class GaleContext {
* get all Keyboard event from the X system (like many time use of META) * get all Keyboard event from the X system (like many time use of META)
* @param status "true" if all the event will be get, false if we want only ours. * @param status "true" if all the event will be get, false if we want only ours.
*/ */
public void grabKeyboardEvents(final boolean status) {} public final void grabKeyboardEvents(final boolean status) {
postActionToGui(context -> {
context.grabKeyboardEventsThreadGUI(status);
});
}
protected void grabKeyboardEventsThreadGUI(final boolean status) {
Log.info("grabKeyboardEvents: NOT implemented ...");
}
/** /**
* get all Mouse/Touch events from the X system * get all Mouse/Touch events from the X system
* @param status "true" if all the event will be get, false if we want only ours. * @param status "true" if all the event will be get, false if we want only ours.
* @param forcedPosition the position where the mouse might be reset at every events ... * @param forcedPosition the position where the mouse might be reset at every events ...
*/ */
public void grabPointerEvents(final boolean status, final Vector2f forcedPosition) {} public final void grabPointerEvents(final boolean status, final Vector2f forcedPosition) {
postActionToGui(context -> {
context.grabPointerEventsThreadGUI(status, forcedPosition);
});
}
protected void grabPointerEventsThreadGUI(final boolean status, final Vector2f forcedPosition) {
Log.info("grabPointerEvents: NOT implemented ...");
}
/** /**
* The Application request that the Windows will be Hidden. * The Application request that the Windows will be Hidden.
*/ */
public void hide() { public final void hide() {
postActionToGui(context -> {
context.hideThreadGUI();
});
}
protected void hideThreadGUI() {
Log.info("hide: NOT implemented ..."); Log.info("hide: NOT implemented ...");
} }
@ -234,41 +270,57 @@ public abstract class GaleContext {
} }
/** /**
* Hide the virtal keyboard (for touch system only) * Hide the virtual keyboard (for touch system only)
*/ */
public void keyboardHide() { public final void keyboardHide() {
postActionToGui(context -> {
context.keyboardHideThreadGUI();
});
}
protected void keyboardHideThreadGUI() {
Log.info("keyboardHide: NOT implemented ..."); Log.info("keyboardHide: NOT implemented ...");
} }
/** /**
* display the virtal keyboard (for touch system only) * display the virtual keyboard (for touch system only)
*/ */
public void keyboardShow() { public final void keyboardShow() {
Log.info("keyboardShow: NOT implemented ..."); postActionToGui(context -> {
context.keyboardShowThreadGUI();
});
} }
protected void lockContext() { protected void keyboardShowThreadGUI() {
Log.info("keyboardShow: NOT implemented ...");
} }
/** /**
* Open an URL on an eternal brother. * Open an URL on an eternal brother.
* @param url URL to open. * @param url URL to open.
*/ */
public void openURL(final String url) {} public final void openURL(final String url) {
postActionToGui(context -> {
context.openURLThreadGUI(url);
});
}
protected void openURLThreadGUI(final String url) {
Log.info("openURL: NOT implemented ...");
}
/** /**
* The current context is set in background (framerate is slowing down (max fps)/5 # 4fps) * The current context is set in background (framerate is slowing down (max fps)/5 # 4fps)
*/ */
public void operatingSystemBackground() { public void operatingSystemBackground() {
// set the current interface : // set the current interface :
lockContext(); try (AutoUnLock autoUnlock = AutoUnLock.lock(this.msgSystemAsyncLock)) {
Log.info("operatingSystemBackground..."); Log.info("operatingSystemBackground...");
// if (this.windowsCurrent != null) { // if (this.windowsCurrent != null) {
// this.windowsCurrent.onStateBackground(); // this.windowsCurrent.onStateBackground();
// } // }
// release the current interface : // release the current interface :
unLockContext(); }
} }
/** /**
@ -276,7 +328,7 @@ public abstract class GaleContext {
* @param clipboardID of the clipboard * @param clipboardID of the clipboard
*/ */
public void operatingSystemClipBoardArrive(final ClipboardList clipboardID) { public void operatingSystemClipBoardArrive(final ClipboardList clipboardID) {
postAction(context -> { postActionAsync(context -> {
final GaleApplication appl = context.getApplication(); final GaleApplication appl = context.getApplication();
if (appl != null) { if (appl != null) {
appl.onClipboardEvent(clipboardID); appl.onClipboardEvent(clipboardID);
@ -313,33 +365,32 @@ public abstract class GaleContext {
//! Event management section ... //! Event management section ...
{ {
// set the current interface: // set the current interface:
lockContext(); try (AutoUnLock autoUnlock = AutoUnLock.lock(this.msgSystemAsyncLock)) {
/* /*
Lock the event processing Lock the event processing
Wait end of current processing Wait end of current processing
Display ... Display ...
Release the event processing Release the event processing
*/ */
if (this.application != null) { if (this.application != null) {
if (this.applicationState == ApplicationState.RUNNING) { if (this.applicationState == ApplicationState.RUNNING) {
// Redraw all needed elements // Redraw all needed elements
//Log.debug("Regenerate Display"); //Log.debug("Regenerate Display");
this.application.onRegenerateDisplay(this); this.application.onRegenerateDisplay(this);
needRedraw = this.application.isDrawingNeeded(); needRedraw = this.application.isDrawingNeeded();
} else { } else {
needRedraw = true; needRedraw = true;
}
}
if (this.displayFps) {
this.fpsSystemEvent.incrementCounter();
this.fpsSystemEvent.toc();
} }
} }
if (this.displayFps) {
this.fpsSystemEvent.incrementCounter();
this.fpsSystemEvent.toc();
}
// release the current interface :
unLockContext();
} }
boolean hasDisplayDone = false; boolean hasDisplayDone = false;
//! drawing section: //! drawing section:
@ -351,9 +402,9 @@ public abstract class GaleContext {
} }
if (needRedraw || displayEveryTime) { if (needRedraw || displayEveryTime) {
//Log.debug(" ==> real Draw"); //Log.debug(" ==> real Draw");
lockContext(); try (AutoUnLock autoUnlock = AutoUnLock.lock(this.msgSystemAsyncLock)) {
this.resourceManager.updateContext(); this.resourceManager.updateContext();
unLockContext(); }
if (this.displayFps) { if (this.displayFps) {
this.fpsSystemContext.incrementCounter(); this.fpsSystemContext.incrementCounter();
} }
@ -366,16 +417,16 @@ public abstract class GaleContext {
if (needRedraw || displayEveryTime) { if (needRedraw || displayEveryTime) {
this.fpsSystem.incrementCounter(); this.fpsSystem.incrementCounter();
// set the current interface : // set the current interface :
lockContext(); try (AutoUnLock autoUnlock = AutoUnLock.lock(this.msgSystemAsyncLock)) {
if (this.applicationState == ApplicationState.RUNNING) { if (this.applicationState == ApplicationState.RUNNING) {
this.application.onDraw(this); this.application.onDraw(this);
} else { } else {
OpenGL.setViewPort(new Vector2f(0, 0), this.application.getSize()); OpenGL.setViewPort(new Vector2f(0, 0), this.application.getSize());
final Color bgColor = new Color(0.8f, 0.5f, 0.8f, 1.0f); final Color bgColor = new Color(0.8f, 0.5f, 0.8f, 1.0f);
OpenGL.clearColor(bgColor); OpenGL.clearColor(bgColor);
//Log.info("==> appl clear ==> not created ..."); //Log.info("==> appl clear ==> not created ...");
}
} }
unLockContext();
hasDisplayDone = true; hasDisplayDone = true;
} }
} }
@ -404,17 +455,16 @@ public abstract class GaleContext {
} }
{ {
// set the current interface: // set the current interface:
lockContext(); try (AutoUnLock autoUnlock = AutoUnLock.lock(this.msgSystemAsyncLock)) {
// release open GL Context // release open GL Context
OpenGL.lock(); OpenGL.lock();
// while The Gui is drawing in OpenGl, we do some not realTime things // while The Gui is drawing in OpenGl, we do some not realTime things
this.resourceManager.updateContext(); this.resourceManager.updateContext();
// release open GL Context // release open GL Context
OpenGL.unLock(); OpenGL.unLock();
// TODO this.objectManager.cleanInternalRemoved(); // TODO this.objectManager.cleanInternalRemoved();
this.resourceManager.cleanInternalRemoved(); this.resourceManager.cleanInternalRemoved();
// release the current interface: }
unLockContext();
} }
OpenGL.threadHasNoMoreContext(); OpenGL.threadHasNoMoreContext();
return hasDisplayDone; return hasDisplayDone;
@ -425,21 +475,20 @@ public abstract class GaleContext {
*/ */
public void operatingSystemForeground() { public void operatingSystemForeground() {
// set the current interface : // set the current interface :
lockContext(); try (AutoUnLock autoUnlock = AutoUnLock.lock(this.msgSystemAsyncLock)) {
Log.info("operatingSystemForeground..."); Log.info("operatingSystemForeground...");
// if (this.windowsCurrent != null) { // if (this.windowsCurrent != null) {
// this.windowsCurrent.onStateForeground(); // this.windowsCurrent.onStateForeground();
// } // }
// release the current interface : }
unLockContext();
} }
/** /**
* The OS inform that the Windows is now Hidden. * The OS inform that the Windows is now Hidden.
*/ */
public void operatingSystemHide() { public void operatingSystemHide() {
postAction(context -> { postActionAsync(context -> {
/* /*
Application> appl = context.getApplication(); Application> appl = context.getApplication();
if (appl == null) { if (appl == null) {
@ -462,8 +511,8 @@ public abstract class GaleContext {
if (this.windowsPos.isEqual(pos)) { if (this.windowsPos.isEqual(pos)) {
return; return;
} }
postAction(context -> { postActionAsync(context -> {
Log.debug("Receive MSG : THREADMOVE : " + context.windowsPos + " ==> " + pos); Log.debug("Receive MSG : THREADMOVE : {} ==> {}", context.windowsPos, pos);
context.windowsPos = pos; context.windowsPos = pos;
final GaleApplication appl = context.getApplication(); final GaleApplication appl = context.getApplication();
if (appl == null) { if (appl == null) {
@ -485,14 +534,14 @@ public abstract class GaleContext {
* @param size new size of the windows. * @param size new size of the windows.
*/ */
public void operatingSystemResize(final Vector2f size) { public void operatingSystemResize(final Vector2f size) {
Log.warning("Resize request: " + size + " old=" + this.windowsSize); Log.warning("Resize request={} previous={}", size, this.windowsSize);
if (this.windowsSize.equals(size)) { if (this.windowsSize.equals(size)) {
return; return;
} }
// TODO Better in the thread ... ==> but generate some init error ... // TODO Better in the thread ... ==> but generate some init error ...
//gale::Dimension::setPixelWindowsSize(size); //gale::Dimension::setPixelWindowsSize(size);
postAction(context -> { postActionAsync(context -> {
Log.error("Receive MSG : THREAD_RESIZE : " + context.windowsSize + " ==> " + size); Log.error("Receive MSG : THREAD_RESIZE : {} ==> {}", context.windowsSize, size);
context.windowsSize = size; context.windowsSize = size;
//gale::Dimension::setPixelWindowsSize(context.windowsSize); //gale::Dimension::setPixelWindowsSize(context.windowsSize);
final GaleApplication tmpAppl = context.getApplication(); final GaleApplication tmpAppl = context.getApplication();
@ -509,20 +558,19 @@ public abstract class GaleContext {
*/ */
public void operatingSystemResume() { public void operatingSystemResume() {
// set the current interface : // set the current interface :
lockContext(); try (AutoUnLock autoUnlock = AutoUnLock.lock(this.msgSystemAsyncLock)) {
Log.info("operatingSystemResume..."); Log.info("operatingSystemResume...");
this.previousDisplayTime = System.currentTimeMillis(); this.previousDisplayTime = System.currentTimeMillis();
// TODO this.objectManager.timeCallResume(this.previousDisplayTime); // TODO this.objectManager.timeCallResume(this.previousDisplayTime);
// if (this.windowsCurrent != null) { // if (this.windowsCurrent != null) {
// this.windowsCurrent.onStateResume(); // this.windowsCurrent.onStateResume();
// } // }
// release the current interface : }
unLockContext();
} }
public void operatingSystemSetInput(final KeySpecial special, final KeyType type, final KeyStatus status, final int pointerID, final Vector2f pos) { public void operatingSystemSetInput(final KeySpecial special, final KeyType type, final KeyStatus status, final int pointerID, final Vector2f pos) {
Log.verbose("Position motion: " + pos); Log.verbose("Position motion: " + pos);
postAction(context -> { postActionAsync(context -> {
final GaleApplication appl = context.getApplication(); final GaleApplication appl = context.getApplication();
if (appl == null) { if (appl == null) {
return; return;
@ -548,7 +596,7 @@ public abstract class GaleContext {
} }
public void operatingSystemsetKeyboard2(final KeySpecial special, final KeyKeyboard type, final KeyStatus state, final Character charValue) { public void operatingSystemsetKeyboard2(final KeySpecial special, final KeyKeyboard type, final KeyStatus state, final Character charValue) {
postAction(context -> { postActionAsync(context -> {
final GaleApplication appl = context.getApplication(); final GaleApplication appl = context.getApplication();
if (appl == null) { if (appl == null) {
return; return;
@ -561,7 +609,7 @@ public abstract class GaleContext {
* The OS inform that the Windows is now visible. * The OS inform that the Windows is now visible.
*/ */
public void operatingSystemShow() { public void operatingSystemShow() {
postAction(context -> { postActionAsync(context -> {
/* /*
Application> appl = context.getApplication(); Application> appl = context.getApplication();
if (appl == null) { if (appl == null) {
@ -581,15 +629,14 @@ public abstract class GaleContext {
*/ */
public void operatingSystemStop() { public void operatingSystemStop() {
// set the current interface : // set the current interface :
lockContext(); try (AutoUnLock autoUnlock = AutoUnLock.lock(this.msgSystemAsyncLock)) {
Log.info("operatingSystemStop..."); Log.info("operatingSystemStop...");
if (this.application == null) { if (this.application == null) {
stop(); stop();
return; return;
}
this.application.onKillDemand(this);
} }
this.application.onKillDemand(this);
// release the current interface :
unLockContext();
} }
/** /**
@ -597,44 +644,70 @@ public abstract class GaleContext {
*/ */
public void operatingSystemSuspend() { public void operatingSystemSuspend() {
// set the current interface : // set the current interface :
lockContext(); try (AutoUnLock autoUnlock = AutoUnLock.lock(this.msgSystemAsyncLock)) {
Log.info("operatingSystemSuspend..."); Log.info("operatingSystemSuspend...");
this.previousDisplayTime = 0; this.previousDisplayTime = 0;
// if (this.windowsCurrent != null) { // if (this.windowsCurrent != null) {
// this.windowsCurrent.onStateSuspend(); // this.windowsCurrent.onStateSuspend();
// } // }
// release the current interface : }
unLockContext();
} }
private void postAction(final ActionToDoInAsyncLoop data) { protected void postActionAsync(final ActionToDoInAsyncLoop data) {
this.msgSystem.addElement(data); this.msgSystemAsync.addElement(data);
//Later, when the necessary event happens, the thread that is running it calls notify() from a block synchronized on the same object.
}
protected void postActionToGui(final ActionToDoInAsyncLoop data) {
this.msgSystemGui.addElement(data);
//Later, when the necessary event happens, the thread that is running it calls notify() from a block synchronized on the same object. //Later, when the necessary event happens, the thread that is running it calls notify() from a block synchronized on the same object.
} }
/** /**
* Processing all the event arrived ... (commonly called in draw function) * Processing all the event arrived ... (commonly called in draw function)
*/ */
public void processEvents(final Clock clock, final long time) { public void processEventsAsync(final Clock clock, final long time) {
if (!this.lock.tryLock()) { if (!this.msgSystemAsyncLock.tryLock()) {
return; return;
} }
try { try {
int nbEvent = 0; int nbEvent = 0;
while (this.msgSystem.getSize() > 0) { while (this.msgSystemAsync.getSize() > 0) {
//Log.error(" [" + nbEvent + "] event ..."); Log.error(" [" + nbEvent + "] event ...");
nbEvent++; nbEvent++;
final ActionToDoInAsyncLoop func = this.msgSystem.getElementWait(); final ActionToDoInAsyncLoop func = this.msgSystemAsync.getElementWait();
if (func == null) { if (func == null) {
continue; continue;
} }
func.run(this); func.run(this);
} }
} catch (Exception e) { } catch (final Exception e) {
Log.critical("Catch exception in main event Loop ...", e); Log.critical("Catch exception in main event Loop ...", e);
} finally { } finally {
this.lock.unlock(); this.msgSystemAsyncLock.unlock();
}
}
/**
* Process event in the GUI thread ==> prevent dead lock on the global GUI interface
*/
protected void processEventsGui() {
if (!this.msgSystemAsyncLock.tryLock()) {
return;
}
try {
while (this.msgSystemGui.getSize() > 0) {
final ActionToDoInAsyncLoop func = this.msgSystemGui.getElementWait();
if (func == null) {
continue;
}
func.run(this);
}
} catch (final Exception e) {
Log.critical("Catch exception in main event Loop ...", e);
} finally {
this.msgSystemAsyncLock.unlock();
} }
} }
@ -674,7 +747,7 @@ public abstract class GaleContext {
// } // }
// } // }
public void requestUpdateSize() { public void requestUpdateSize() {
postAction(context -> { postActionAsync(context -> {
//Log.debug("Receive MSG : THREADRESIZE"); //Log.debug("Receive MSG : THREADRESIZE");
context.forceRedrawAll(); context.forceRedrawAll();
}); });
@ -698,27 +771,56 @@ public abstract class GaleContext {
* set the cursor display type. * set the cursor display type.
* @param newCursor selected new cursor. * @param newCursor selected new cursor.
*/ */
public void setCursor(final Cursor newCursor) {} public final void setCursor(final Cursor newCursor) {
postActionToGui(context -> {
context.setCursorThreadGUI(newCursor);
});
}
public void setCursorThreadGUI(final Cursor newCursor) {
Log.info("setCursor: NOT implemented ...");
}
/** /**
* The application request a change of his current size force the fullscreen mode. * The application request a change of his current size force the fullscreen mode.
* @param status status of the fullscreen mode. * @param status status of the fullscreen mode.
*/ */
public void setFullScreen(final boolean status) { public final void setFullScreen(final boolean status) {
this.fullscreen = status; postActionToGui(context -> {
this.fullscreen = status;
context.setFullScreenThreadGUI(status);
});
}
protected void setFullScreenThreadGUI(final boolean status) {
Log.info("setFullScreen: NOT implemented ...");
} }
/** /**
* set the Icon of the program * set the Icon of the program
* @param inputFile new filename icon of the current program. * @param inputFile new filename icon of the current program.
*/ */
public void setIcon(final Uri inputFile) {} public final void setIcon(final Uri inputFile) {
postActionToGui(context -> {
context.setIconThreadGUI(inputFile);
});
}
public void setIconThreadGUI(final Uri inputFile) {
Log.info("setIcon: NOT implemented ...");
}
/** /**
* The Application request that the current windows will change his position. * The Application request that the current windows will change his position.
* @param pos New position of the Windows requested. * @param pos New position of the Windows requested.
*/ */
public void setPos(final Vector2f pos) { public final void setPos(final Vector2f pos) {
postActionToGui(context -> {
context.setPosThreadGUI(pos);
});
}
protected void setPosThreadGUI(final Vector2f pos) {
Log.info("setPos: NOT implemented ..."); Log.info("setPos: NOT implemented ...");
} }
@ -726,16 +828,31 @@ public abstract class GaleContext {
* The application request a change of his current size. * The application request a change of his current size.
* @param size new Requested size of the windows. * @param size new Requested size of the windows.
*/ */
public boolean setSize(final Vector2f size) { public final void setSize(final Vector2f size) {
postActionToGui(context -> {
context.setSizeThreadGUI(size);
});
}
protected void setSizeThreadGUI(final Vector2f size) {
Log.info("setSize: NOT implemented ..."); Log.info("setSize: NOT implemented ...");
return false;
} }
/** /**
* set the new title of the windows * set the new title of the windows
* @param title New desired title * @param title New desired title
*/ */
public void setTitle(final String title) { public final void setTitle(final String title) {
postActionToGui(context -> {
context.setTitleThreadGUI(title);
});
}
/**
* set the new title of the windows
* @param title New desired title
*/
protected void setTitleThreadGUI(final String title) {
Log.info("setTitle: NOT implemented ..."); Log.info("setTitle: NOT implemented ...");
} }
@ -743,12 +860,26 @@ public abstract class GaleContext {
* Enable or Disable the decoration on the Windows (availlable only on Desktop) * Enable or Disable the decoration on the Windows (availlable only on Desktop)
* @param status "true" to enable decoration / false otherwise * @param status "true" to enable decoration / false otherwise
*/ */
public void setWindowsDecoration(final boolean status) {} public final void setWindowsDecoration(final boolean status) {
postActionToGui(context -> {
context.setWindowsDecorationThreadGUI(status);
});
}
protected void setWindowsDecorationThreadGUI(final boolean status) {
Log.info("setWindowsDecoration: NOT implemented ...");
}
/** /**
* The Application request that the Windows will be visible. * The Application request that the Windows will be visible.
*/ */
public void show() { public void show() {
postActionToGui(context -> {
context.showThreadGUI();
});
}
public void showThreadGUI() {
Log.info("show: NOT implemented ..."); Log.info("show: NOT implemented ...");
} }
@ -758,16 +889,15 @@ public abstract class GaleContext {
*/ */
public void start2ndThreadProcessing() { public void start2ndThreadProcessing() {
// set the current interface: // set the current interface:
lockContext(); try (AutoUnLock autoUnlock = AutoUnLock.lock(this.msgSystemAsyncLock)) {
this.periodicThread.threadStart(); this.periodicThread.threadStart();
try { try {
Thread.sleep(1); Thread.sleep(1);
} catch (final InterruptedException e) { } catch (final InterruptedException e) {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();
}
} }
// release the current interface:
unLockContext();
} }
/** /**
@ -777,89 +907,4 @@ public abstract class GaleContext {
Log.warning("stop: NOT implemented for this platform..."); Log.warning("stop: NOT implemented for this platform...");
} }
protected void unLockContext() {
}
}
class MessageSystem {
private final Vector<ActionToDoInAsyncLoop> data = new Vector<>();
public synchronized void addElement(final ActionToDoInAsyncLoop data2) {
this.data.addElement(data2);
notifyAll();
}
public synchronized ActionToDoInAsyncLoop getElement() {
//Log.warning("+++++++++++++++++++++++++++++++++ getElement()");
ActionToDoInAsyncLoop message = this.data.firstElement();
this.data.removeElement(message);
//Log.warning("+++++++++++++++++++++++++++++++++ getElement() ===> done " + message);
return message;
}
public synchronized ActionToDoInAsyncLoop getElementWait() {
if (this.data.isEmpty()) {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
if (this.data.isEmpty()) {
return null;
}
return getElement();
}
public synchronized int getSize() {
return this.data.size();
}
}
class PeriodicThread extends ThreadAbstract {
private final GaleContext context;
public PeriodicThread(final GaleContext context) {
super("Galethread 2");
this.context = context;
}
@Override
protected void birth() {
// TODO Auto-generated method stub
}
@Override
protected void death() {
// TODO Auto-generated method stub
}
@Override
protected void runPeriodic() {
Log.verbose("----------------------------- [START] -----------------------------------");
try {
Thread.sleep(10);
} catch (final InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return;
}
// Keep global clock to process events
Clock clock = Clock.systemUTC();
long time = System.nanoTime();
///synchronized (this.context) {
this.context.processEvents(clock, time);
// call all the application for periodic request (the application manage multiple instance )...
final GaleApplication appl = this.context.getApplication();
//Log.verbose("Call application : " + appl);
if (appl != null) {
appl.onPeriod(clock, time);
}
Log.verbose("----------------------------- [ END ] -----------------------------------");
}
} }

View File

@ -26,6 +26,7 @@ import javax.swing.SwingUtilities;
import javax.swing.WindowConstants; import javax.swing.WindowConstants;
import org.atriasoft.etk.Uri; import org.atriasoft.etk.Uri;
import org.atriasoft.etk.math.FMath;
import org.atriasoft.etk.math.Vector2f; import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.gale.DisplayManagerDraw; import org.atriasoft.gale.DisplayManagerDraw;
import org.atriasoft.gale.Fps; import org.atriasoft.gale.Fps;
@ -125,7 +126,7 @@ public class ContextLWJGLAWT extends GaleContext implements MouseListener, Mouse
} }
@Override @Override
public void grabPointerEvents(final boolean status, final Vector2f forcedPosition) { protected void grabPointerEventsThreadGUI(final boolean status, final Vector2f forcedPosition) {
if (status) { if (status) {
try { try {
this.robot = new Robot(); this.robot = new Robot();
@ -166,13 +167,14 @@ public class ContextLWJGLAWT extends GaleContext implements MouseListener, Mouse
@Override @Override
public void paintGL() { public void paintGL() {
final long startRender = System.currentTimeMillis();
//Log.warning("Draw ... "); //Log.warning("Draw ... ");
final int w = getWidth(); final int w = getWidth();
final int h = getHeight(); final int h = getHeight();
if (ContextLWJGLAWT.this.decoratedWindowsSize.x() != w || ContextLWJGLAWT.this.decoratedWindowsSize.y() != h) { if (ContextLWJGLAWT.this.decoratedWindowsSize.x() != w || ContextLWJGLAWT.this.decoratedWindowsSize.y() != h) {
ContextLWJGLAWT.this.decoratedWindowsSize = new Vector2f(w, h); ContextLWJGLAWT.this.decoratedWindowsSize = new Vector2f(w, h);
final Rectangle bounds = ContextLWJGLAWT.this.canvas.getBounds(); final Rectangle bounds = ContextLWJGLAWT.this.canvas.getBounds();
Vector2f tmpWindowsSize = new Vector2f(bounds.width, bounds.height); final Vector2f tmpWindowsSize = new Vector2f(bounds.width, bounds.height);
operatingSystemResize(tmpWindowsSize); operatingSystemResize(tmpWindowsSize);
} }
operatingSystemDraw(true); operatingSystemDraw(true);
@ -180,6 +182,16 @@ public class ContextLWJGLAWT extends GaleContext implements MouseListener, Mouse
if (Logger.isCriticalOccured()) { if (Logger.isCriticalOccured()) {
ContextLWJGLAWT.this.frame.dispose(); ContextLWJGLAWT.this.frame.dispose();
} }
// Process event from the GUI (specific events...
processEventsGui();
final long stopRender = System.currentTimeMillis();
try {
// limit at 60FPS ==> bad to do it here, but it work for now... add a minimum of 10ms to free lock...
Thread.sleep((int) FMath.max((3000.0f / 60.0f) - (stopRender - startRender), 10)); // This permit to limit the FPS (base 602FPS)
} catch (final InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} }
}, BorderLayout.CENTER); }, BorderLayout.CENTER);
this.frame.pack(); this.frame.pack();
@ -590,7 +602,7 @@ public class ContextLWJGLAWT extends GaleContext implements MouseListener, Mouse
} }
@Override @Override
public void setFullScreen(final boolean status) { public void setFullScreenThreadGUI(final boolean status) {
super.setFullScreen(status); super.setFullScreen(status);
if (status) { if (status) {
this.frame.setExtendedState(Frame.MAXIMIZED_BOTH); this.frame.setExtendedState(Frame.MAXIMIZED_BOTH);
@ -602,13 +614,13 @@ public class ContextLWJGLAWT extends GaleContext implements MouseListener, Mouse
} }
@Override @Override
public void setIcon(final Uri inputFile) { public void setIconThreadGUI(final Uri inputFile) {
} }
/****************************************************************************************/ /****************************************************************************************/
@Override @Override
public void setTitle(final String title) { public void setTitleThreadGUI(final String title) {
this.frame.setTitle(title); this.frame.setTitle(title);
} }

View File

@ -0,0 +1,40 @@
package org.atriasoft.gale.context;
import java.util.Vector;
public class MessageSystem {
private final Vector<ActionToDoInAsyncLoop> data = new Vector<>();
public synchronized void addElement(final ActionToDoInAsyncLoop data2) {
this.data.addElement(data2);
notifyAll();
}
public synchronized ActionToDoInAsyncLoop getElement() {
//Log.warning("+++++++++++++++++++++++++++++++++ getElement()");
final ActionToDoInAsyncLoop message = this.data.firstElement();
this.data.removeElement(message);
//Log.warning("+++++++++++++++++++++++++++++++++ getElement() ===> done " + message);
return message;
}
public synchronized ActionToDoInAsyncLoop getElementWait() {
if (this.data.isEmpty()) {
try {
wait();
} catch (final InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
if (this.data.isEmpty()) {
return null;
}
return getElement();
}
public synchronized int getSize() {
return this.data.size();
}
}

View File

@ -0,0 +1,51 @@
package org.atriasoft.gale.context;
import java.time.Clock;
import org.atriasoft.etk.ThreadAbstract;
import org.atriasoft.gale.GaleApplication;
import org.atriasoft.gale.internal.Log;
public class PeriodicThread extends ThreadAbstract {
private final GaleContext context;
public PeriodicThread(final GaleContext context) {
super("GaleAsync");
this.context = context;
}
@Override
protected void birth() {
// TODO Auto-generated method stub
}
@Override
protected void death() {
// TODO Auto-generated method stub
}
@Override
protected void runPeriodic() {
Log.verbose("----------------------------- [START] -----------------------------------");
try {
Thread.sleep(100);
} catch (final InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return;
}
// Keep global clock to process events
final Clock clock = Clock.systemUTC();
final long time = System.nanoTime();
///synchronized (this.context) {
this.context.processEventsAsync(clock, time);
// call all the application for periodic request (the application manage multiple instance )...
final GaleApplication appl = this.context.getApplication();
//Log.verbose("Call application : " + appl);
if (appl != null) {
appl.onPeriod(clock, time);
}
Log.verbose("----------------------------- [ END ] -----------------------------------");
}
}

View File

@ -4,6 +4,7 @@ import io.scenarium.logger.LogLevel;
import io.scenarium.logger.Logger; import io.scenarium.logger.Logger;
public class Log { public class Log {
private static final boolean FORCE_ALL = false;
private static final String LIB_NAME = "gale"; private static final String LIB_NAME = "gale";
private static final String LIB_NAME_DRAW = Logger.getDrawableName(LIB_NAME); private static final String LIB_NAME_DRAW = Logger.getDrawableName(LIB_NAME);
private static final boolean PRINT_CRITICAL = Logger.getNeedPrint(LIB_NAME, LogLevel.CRITICAL); private static final boolean PRINT_CRITICAL = Logger.getNeedPrint(LIB_NAME, LogLevel.CRITICAL);
@ -15,58 +16,58 @@ public class Log {
private static final boolean PRINT_TODO = Logger.getNeedPrint(LIB_NAME, LogLevel.TODO); private static final boolean PRINT_TODO = Logger.getNeedPrint(LIB_NAME, LogLevel.TODO);
private static final boolean PRINT_PRINT = Logger.getNeedPrint(LIB_NAME, LogLevel.PRINT); private static final boolean PRINT_PRINT = Logger.getNeedPrint(LIB_NAME, LogLevel.PRINT);
public static void critical(final String data) { public static void critical(final Exception e, final String data) {
if (PRINT_CRITICAL) {
Logger.critical(LIB_NAME_DRAW, data);
}
}
public static void critical(final String data, final Exception e) {
e.printStackTrace(); e.printStackTrace();
if (PRINT_CRITICAL) { if (PRINT_CRITICAL || FORCE_ALL) {
Logger.critical(LIB_NAME_DRAW, data + " : " + e.getMessage()); Logger.critical(LIB_NAME_DRAW, data + " : " + e.getMessage());
} }
} }
public static void debug(final String data) { public static void critical(final String data, final Object... objects) {
if (PRINT_DEBUG) { if (PRINT_CRITICAL || FORCE_ALL) {
Logger.debug(LIB_NAME_DRAW, data); Logger.critical(LIB_NAME_DRAW, data, objects);
} }
} }
public static void error(final String data) { public static void debug(final String data, final Object... objects) {
if (PRINT_ERROR) { if (PRINT_DEBUG || FORCE_ALL) {
Logger.error(LIB_NAME_DRAW, data); Logger.debug(LIB_NAME_DRAW, data, objects);
} }
} }
public static void info(final String data) { public static void error(final String data, final Object... objects) {
if (PRINT_INFO) { if (PRINT_ERROR || FORCE_ALL) {
Logger.info(LIB_NAME_DRAW, data); Logger.error(LIB_NAME_DRAW, data, objects);
} }
} }
public static void print(final String data) { public static void info(final String data, final Object... objects) {
if (PRINT_PRINT) { if (PRINT_INFO || FORCE_ALL) {
Logger.print(LIB_NAME_DRAW, data); Logger.info(LIB_NAME_DRAW, data, objects);
} }
} }
public static void todo(final String data) { public static void print(final String data, final Object... objects) {
if (PRINT_TODO) { if (PRINT_PRINT || FORCE_ALL) {
Logger.todo(LIB_NAME_DRAW, data); Logger.print(LIB_NAME_DRAW, data, objects);
} }
} }
public static void verbose(final String data) { public static void todo(final String data, final Object... objects) {
if (PRINT_VERBOSE) { if (PRINT_TODO || FORCE_ALL) {
Logger.verbose(LIB_NAME_DRAW, data); Logger.todo(LIB_NAME_DRAW, data, objects);
} }
} }
public static void warning(final String data) { public static void verbose(final String data, final Object... objects) {
if (PRINT_WARNING) { if (PRINT_VERBOSE || FORCE_ALL) {
Logger.warning(LIB_NAME_DRAW, data); Logger.verbose(LIB_NAME_DRAW, data, objects);
}
}
public static void warning(final String data, final Object... objects) {
if (PRINT_WARNING || FORCE_ALL) {
Logger.warning(LIB_NAME_DRAW, data, objects);
} }
} }