[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);
}
void setForceRedraw() {
this.needRedraw = true;
}
/**
* set the Icon of the application.
* @param iconFile File name icon (.bmp/.png).
@ -293,16 +297,19 @@ public class GaleApplication {
if (size.x() <= 0 || size.y() <= 0) {
Log.error("Wrong windows size: " + size);
}
Vector2f oldSize = this.windowsSize;
final Vector2f oldSize = this.windowsSize;
this.windowsSize = size;
final GaleContext context = Gale.getContext();
if (context == null) {
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.");
this.windowsSize = oldSize;
}
*/
}
/**

View File

@ -1,7 +1,6 @@
package org.atriasoft.gale.context;
import java.time.Clock;
import java.util.Vector;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@ -9,6 +8,7 @@ import org.atriasoft.etk.Color;
import org.atriasoft.etk.ThreadAbstract;
import org.atriasoft.etk.Uri;
import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.etk.util.AutoUnLock;
import org.atriasoft.gale.Fps;
import org.atriasoft.gale.Gale;
import org.atriasoft.gale.GaleApplication;
@ -48,8 +48,6 @@ public abstract class GaleContext {
GaleContext.globalContext = context;
}
Lock lock = new ReentrantLock();
protected ThreadAbstract periodicThread;
protected GaleApplication application; //!< Application handle
protected ApplicationState applicationState = ApplicationState.UNDEFINED; // state of the application
@ -58,7 +56,10 @@ public abstract class GaleContext {
// simulation area:
private long previousDisplayTime; // this is to limit framerate ... in case...
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 fpsSystemContext = new Fps("SystemContext", this.displayFps);
private final Fps fpsSystem = new Fps("System", this.displayFps);
@ -112,9 +113,9 @@ public abstract class GaleContext {
// }
//cout.setOutputFile(true);
Log.info("GALE v:" + Gale.getVersion());
Log.info("GALE v: {}", Gale.getVersion());
forceOrientation(Orientation.screenAuto);
postAction(context -> {
postActionAsync(context -> {
final GaleApplication appl = context.getApplication();
if (appl == null) {
this.applicationState = ApplicationState.UNDEFINED;
@ -152,7 +153,15 @@ public abstract class GaleContext {
* force the screen orientation (availlable on portable elements ...
* @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
@ -169,16 +178,20 @@ public abstract class GaleContext {
// Called by Consumer
public ActionToDoInAsyncLoop getAction() {
return this.msgSystem.getElementWait();
return this.msgSystemAsync.getElementWait();
}
public GaleApplication getApplication() {
this.lock.lock();
return this.application;
/*
* pb on this lock ...
this.msgSystemAsyncLock.lock();
try {
return this.application;
} finally {
this.lock.unlock();
this.msgSystemAsyncLock.unlock();
}
*/
}
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)
* @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
* @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 ...
*/
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.
*/
public void hide() {
public final void hide() {
postActionToGui(context -> {
context.hideThreadGUI();
});
}
protected void hideThreadGUI() {
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 ...");
}
/**
* display the virtal keyboard (for touch system only)
* display the virtual keyboard (for touch system only)
*/
public void keyboardShow() {
Log.info("keyboardShow: NOT implemented ...");
public final void keyboardShow() {
postActionToGui(context -> {
context.keyboardShowThreadGUI();
});
}
protected void lockContext() {
protected void keyboardShowThreadGUI() {
Log.info("keyboardShow: NOT implemented ...");
}
/**
* Open an URL on an eternal brother.
* @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)
*/
public void operatingSystemBackground() {
// set the current interface :
lockContext();
Log.info("operatingSystemBackground...");
// if (this.windowsCurrent != null) {
// this.windowsCurrent.onStateBackground();
// }
// release the current interface :
unLockContext();
try (AutoUnLock autoUnlock = AutoUnLock.lock(this.msgSystemAsyncLock)) {
Log.info("operatingSystemBackground...");
// if (this.windowsCurrent != null) {
// this.windowsCurrent.onStateBackground();
// }
// release the current interface :
}
}
/**
@ -276,7 +328,7 @@ public abstract class GaleContext {
* @param clipboardID of the clipboard
*/
public void operatingSystemClipBoardArrive(final ClipboardList clipboardID) {
postAction(context -> {
postActionAsync(context -> {
final GaleApplication appl = context.getApplication();
if (appl != null) {
appl.onClipboardEvent(clipboardID);
@ -313,33 +365,32 @@ public abstract class GaleContext {
//! Event management section ...
{
// set the current interface:
lockContext();
/*
Lock the event processing
try (AutoUnLock autoUnlock = AutoUnLock.lock(this.msgSystemAsyncLock)) {
/*
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.applicationState == ApplicationState.RUNNING) {
// Redraw all needed elements
//Log.debug("Regenerate Display");
this.application.onRegenerateDisplay(this);
needRedraw = this.application.isDrawingNeeded();
} else {
needRedraw = true;
*/
if (this.application != null) {
if (this.applicationState == ApplicationState.RUNNING) {
// Redraw all needed elements
//Log.debug("Regenerate Display");
this.application.onRegenerateDisplay(this);
needRedraw = this.application.isDrawingNeeded();
} else {
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;
//! drawing section:
@ -351,9 +402,9 @@ public abstract class GaleContext {
}
if (needRedraw || displayEveryTime) {
//Log.debug(" ==> real Draw");
lockContext();
this.resourceManager.updateContext();
unLockContext();
try (AutoUnLock autoUnlock = AutoUnLock.lock(this.msgSystemAsyncLock)) {
this.resourceManager.updateContext();
}
if (this.displayFps) {
this.fpsSystemContext.incrementCounter();
}
@ -366,16 +417,16 @@ public abstract class GaleContext {
if (needRedraw || displayEveryTime) {
this.fpsSystem.incrementCounter();
// set the current interface :
lockContext();
if (this.applicationState == ApplicationState.RUNNING) {
this.application.onDraw(this);
} else {
OpenGL.setViewPort(new Vector2f(0, 0), this.application.getSize());
final Color bgColor = new Color(0.8f, 0.5f, 0.8f, 1.0f);
OpenGL.clearColor(bgColor);
//Log.info("==> appl clear ==> not created ...");
try (AutoUnLock autoUnlock = AutoUnLock.lock(this.msgSystemAsyncLock)) {
if (this.applicationState == ApplicationState.RUNNING) {
this.application.onDraw(this);
} else {
OpenGL.setViewPort(new Vector2f(0, 0), this.application.getSize());
final Color bgColor = new Color(0.8f, 0.5f, 0.8f, 1.0f);
OpenGL.clearColor(bgColor);
//Log.info("==> appl clear ==> not created ...");
}
}
unLockContext();
hasDisplayDone = true;
}
}
@ -404,17 +455,16 @@ public abstract class GaleContext {
}
{
// set the current interface:
lockContext();
// release open GL Context
OpenGL.lock();
// while The Gui is drawing in OpenGl, we do some not realTime things
this.resourceManager.updateContext();
// release open GL Context
OpenGL.unLock();
// TODO this.objectManager.cleanInternalRemoved();
this.resourceManager.cleanInternalRemoved();
// release the current interface:
unLockContext();
try (AutoUnLock autoUnlock = AutoUnLock.lock(this.msgSystemAsyncLock)) {
// release open GL Context
OpenGL.lock();
// while The Gui is drawing in OpenGl, we do some not realTime things
this.resourceManager.updateContext();
// release open GL Context
OpenGL.unLock();
// TODO this.objectManager.cleanInternalRemoved();
this.resourceManager.cleanInternalRemoved();
}
}
OpenGL.threadHasNoMoreContext();
return hasDisplayDone;
@ -425,21 +475,20 @@ public abstract class GaleContext {
*/
public void operatingSystemForeground() {
// set the current interface :
lockContext();
Log.info("operatingSystemForeground...");
try (AutoUnLock autoUnlock = AutoUnLock.lock(this.msgSystemAsyncLock)) {
Log.info("operatingSystemForeground...");
// if (this.windowsCurrent != null) {
// this.windowsCurrent.onStateForeground();
// }
// release the current interface :
unLockContext();
// if (this.windowsCurrent != null) {
// this.windowsCurrent.onStateForeground();
// }
}
}
/**
* The OS inform that the Windows is now Hidden.
*/
public void operatingSystemHide() {
postAction(context -> {
postActionAsync(context -> {
/*
Application> appl = context.getApplication();
if (appl == null) {
@ -462,8 +511,8 @@ public abstract class GaleContext {
if (this.windowsPos.isEqual(pos)) {
return;
}
postAction(context -> {
Log.debug("Receive MSG : THREADMOVE : " + context.windowsPos + " ==> " + pos);
postActionAsync(context -> {
Log.debug("Receive MSG : THREADMOVE : {} ==> {}", context.windowsPos, pos);
context.windowsPos = pos;
final GaleApplication appl = context.getApplication();
if (appl == null) {
@ -485,14 +534,14 @@ public abstract class GaleContext {
* @param size new size of the windows.
*/
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)) {
return;
}
// TODO Better in the thread ... ==> but generate some init error ...
//gale::Dimension::setPixelWindowsSize(size);
postAction(context -> {
Log.error("Receive MSG : THREAD_RESIZE : " + context.windowsSize + " ==> " + size);
postActionAsync(context -> {
Log.error("Receive MSG : THREAD_RESIZE : {} ==> {}", context.windowsSize, size);
context.windowsSize = size;
//gale::Dimension::setPixelWindowsSize(context.windowsSize);
final GaleApplication tmpAppl = context.getApplication();
@ -509,20 +558,19 @@ public abstract class GaleContext {
*/
public void operatingSystemResume() {
// set the current interface :
lockContext();
Log.info("operatingSystemResume...");
this.previousDisplayTime = System.currentTimeMillis();
// TODO this.objectManager.timeCallResume(this.previousDisplayTime);
// if (this.windowsCurrent != null) {
// this.windowsCurrent.onStateResume();
// }
// release the current interface :
unLockContext();
try (AutoUnLock autoUnlock = AutoUnLock.lock(this.msgSystemAsyncLock)) {
Log.info("operatingSystemResume...");
this.previousDisplayTime = System.currentTimeMillis();
// TODO this.objectManager.timeCallResume(this.previousDisplayTime);
// if (this.windowsCurrent != null) {
// this.windowsCurrent.onStateResume();
// }
}
}
public void operatingSystemSetInput(final KeySpecial special, final KeyType type, final KeyStatus status, final int pointerID, final Vector2f pos) {
Log.verbose("Position motion: " + pos);
postAction(context -> {
postActionAsync(context -> {
final GaleApplication appl = context.getApplication();
if (appl == null) {
return;
@ -548,7 +596,7 @@ public abstract class GaleContext {
}
public void operatingSystemsetKeyboard2(final KeySpecial special, final KeyKeyboard type, final KeyStatus state, final Character charValue) {
postAction(context -> {
postActionAsync(context -> {
final GaleApplication appl = context.getApplication();
if (appl == null) {
return;
@ -561,7 +609,7 @@ public abstract class GaleContext {
* The OS inform that the Windows is now visible.
*/
public void operatingSystemShow() {
postAction(context -> {
postActionAsync(context -> {
/*
Application> appl = context.getApplication();
if (appl == null) {
@ -581,15 +629,14 @@ public abstract class GaleContext {
*/
public void operatingSystemStop() {
// set the current interface :
lockContext();
Log.info("operatingSystemStop...");
if (this.application == null) {
stop();
return;
try (AutoUnLock autoUnlock = AutoUnLock.lock(this.msgSystemAsyncLock)) {
Log.info("operatingSystemStop...");
if (this.application == null) {
stop();
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() {
// set the current interface :
lockContext();
Log.info("operatingSystemSuspend...");
this.previousDisplayTime = 0;
try (AutoUnLock autoUnlock = AutoUnLock.lock(this.msgSystemAsyncLock)) {
Log.info("operatingSystemSuspend...");
this.previousDisplayTime = 0;
// if (this.windowsCurrent != null) {
// this.windowsCurrent.onStateSuspend();
// }
// release the current interface :
unLockContext();
// if (this.windowsCurrent != null) {
// this.windowsCurrent.onStateSuspend();
// }
}
}
private void postAction(final ActionToDoInAsyncLoop data) {
this.msgSystem.addElement(data);
protected void postActionAsync(final ActionToDoInAsyncLoop 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.
}
/**
* Processing all the event arrived ... (commonly called in draw function)
*/
public void processEvents(final Clock clock, final long time) {
if (!this.lock.tryLock()) {
public void processEventsAsync(final Clock clock, final long time) {
if (!this.msgSystemAsyncLock.tryLock()) {
return;
}
try {
int nbEvent = 0;
while (this.msgSystem.getSize() > 0) {
//Log.error(" [" + nbEvent + "] event ...");
while (this.msgSystemAsync.getSize() > 0) {
Log.error(" [" + nbEvent + "] event ...");
nbEvent++;
final ActionToDoInAsyncLoop func = this.msgSystem.getElementWait();
final ActionToDoInAsyncLoop func = this.msgSystemAsync.getElementWait();
if (func == null) {
continue;
}
func.run(this);
}
} catch (Exception e) {
} catch (final Exception e) {
Log.critical("Catch exception in main event Loop ...", e);
} 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() {
postAction(context -> {
postActionAsync(context -> {
//Log.debug("Receive MSG : THREADRESIZE");
context.forceRedrawAll();
});
@ -698,27 +771,56 @@ public abstract class GaleContext {
* set the cursor display type.
* @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.
* @param status status of the fullscreen mode.
*/
public void setFullScreen(final boolean status) {
this.fullscreen = status;
public final void setFullScreen(final boolean 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
* @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.
* @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 ...");
}
@ -726,16 +828,31 @@ public abstract class GaleContext {
* The application request a change of his current size.
* @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 ...");
return false;
}
/**
* set the new title of the windows
* @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 ...");
}
@ -743,12 +860,26 @@ public abstract class GaleContext {
* Enable or Disable the decoration on the Windows (availlable only on Desktop)
* @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.
*/
public void show() {
postActionToGui(context -> {
context.showThreadGUI();
});
}
public void showThreadGUI() {
Log.info("show: NOT implemented ...");
}
@ -758,16 +889,15 @@ public abstract class GaleContext {
*/
public void start2ndThreadProcessing() {
// set the current interface:
lockContext();
this.periodicThread.threadStart();
try {
Thread.sleep(1);
} catch (final InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
try (AutoUnLock autoUnlock = AutoUnLock.lock(this.msgSystemAsyncLock)) {
this.periodicThread.threadStart();
try {
Thread.sleep(1);
} catch (final InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// release the current interface:
unLockContext();
}
/**
@ -777,89 +907,4 @@ public abstract class GaleContext {
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 org.atriasoft.etk.Uri;
import org.atriasoft.etk.math.FMath;
import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.gale.DisplayManagerDraw;
import org.atriasoft.gale.Fps;
@ -125,7 +126,7 @@ public class ContextLWJGLAWT extends GaleContext implements MouseListener, Mouse
}
@Override
public void grabPointerEvents(final boolean status, final Vector2f forcedPosition) {
protected void grabPointerEventsThreadGUI(final boolean status, final Vector2f forcedPosition) {
if (status) {
try {
this.robot = new Robot();
@ -166,13 +167,14 @@ public class ContextLWJGLAWT extends GaleContext implements MouseListener, Mouse
@Override
public void paintGL() {
final long startRender = System.currentTimeMillis();
//Log.warning("Draw ... ");
final int w = getWidth();
final int h = getHeight();
if (ContextLWJGLAWT.this.decoratedWindowsSize.x() != w || ContextLWJGLAWT.this.decoratedWindowsSize.y() != h) {
ContextLWJGLAWT.this.decoratedWindowsSize = new Vector2f(w, h);
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);
}
operatingSystemDraw(true);
@ -180,6 +182,16 @@ public class ContextLWJGLAWT extends GaleContext implements MouseListener, Mouse
if (Logger.isCriticalOccured()) {
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);
this.frame.pack();
@ -590,7 +602,7 @@ public class ContextLWJGLAWT extends GaleContext implements MouseListener, Mouse
}
@Override
public void setFullScreen(final boolean status) {
public void setFullScreenThreadGUI(final boolean status) {
super.setFullScreen(status);
if (status) {
this.frame.setExtendedState(Frame.MAXIMIZED_BOTH);
@ -602,13 +614,13 @@ public class ContextLWJGLAWT extends GaleContext implements MouseListener, Mouse
}
@Override
public void setIcon(final Uri inputFile) {
public void setIconThreadGUI(final Uri inputFile) {
}
/****************************************************************************************/
@Override
public void setTitle(final String title) {
public void setTitleThreadGUI(final String 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;
public class Log {
private static final boolean FORCE_ALL = false;
private static final String LIB_NAME = "gale";
private static final String LIB_NAME_DRAW = Logger.getDrawableName(LIB_NAME);
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_PRINT = Logger.getNeedPrint(LIB_NAME, LogLevel.PRINT);
public static void critical(final String data) {
if (PRINT_CRITICAL) {
Logger.critical(LIB_NAME_DRAW, data);
}
}
public static void critical(final String data, final Exception e) {
public static void critical(final Exception e, final String data) {
e.printStackTrace();
if (PRINT_CRITICAL) {
if (PRINT_CRITICAL || FORCE_ALL) {
Logger.critical(LIB_NAME_DRAW, data + " : " + e.getMessage());
}
}
public static void debug(final String data) {
if (PRINT_DEBUG) {
Logger.debug(LIB_NAME_DRAW, data);
public static void critical(final String data, final Object... objects) {
if (PRINT_CRITICAL || FORCE_ALL) {
Logger.critical(LIB_NAME_DRAW, data, objects);
}
}
public static void error(final String data) {
if (PRINT_ERROR) {
Logger.error(LIB_NAME_DRAW, data);
public static void debug(final String data, final Object... objects) {
if (PRINT_DEBUG || FORCE_ALL) {
Logger.debug(LIB_NAME_DRAW, data, objects);
}
}
public static void info(final String data) {
if (PRINT_INFO) {
Logger.info(LIB_NAME_DRAW, data);
public static void error(final String data, final Object... objects) {
if (PRINT_ERROR || FORCE_ALL) {
Logger.error(LIB_NAME_DRAW, data, objects);
}
}
public static void print(final String data) {
if (PRINT_PRINT) {
Logger.print(LIB_NAME_DRAW, data);
public static void info(final String data, final Object... objects) {
if (PRINT_INFO || FORCE_ALL) {
Logger.info(LIB_NAME_DRAW, data, objects);
}
}
public static void todo(final String data) {
if (PRINT_TODO) {
Logger.todo(LIB_NAME_DRAW, data);
public static void print(final String data, final Object... objects) {
if (PRINT_PRINT || FORCE_ALL) {
Logger.print(LIB_NAME_DRAW, data, objects);
}
}
public static void verbose(final String data) {
if (PRINT_VERBOSE) {
Logger.verbose(LIB_NAME_DRAW, data);
public static void todo(final String data, final Object... objects) {
if (PRINT_TODO || FORCE_ALL) {
Logger.todo(LIB_NAME_DRAW, data, objects);
}
}
public static void warning(final String data) {
if (PRINT_WARNING) {
Logger.warning(LIB_NAME_DRAW, data);
public static void verbose(final String data, final Object... objects) {
if (PRINT_VERBOSE || FORCE_ALL) {
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);
}
}