mirror of https://github.com/buggins/dlangui.git
X11 timers support
This commit is contained in:
parent
1c5ca7757a
commit
c3cd93fa51
|
@ -167,6 +167,9 @@ class X11Window : DWindow {
|
|||
}
|
||||
|
||||
~this() {
|
||||
if (timer) {
|
||||
timer.stop();
|
||||
}
|
||||
if (_gc)
|
||||
XFreeGC(x11display, _gc);
|
||||
if (_win)
|
||||
|
@ -203,6 +206,7 @@ class X11Window : DWindow {
|
|||
ev.type = Expose;
|
||||
ev.xexpose.window = _win;
|
||||
XSendEvent(x11display, _win, false, ExposureMask, &ev);
|
||||
XFlush(x11display);
|
||||
}
|
||||
|
||||
/// close window
|
||||
|
@ -662,15 +666,32 @@ class X11Window : DWindow {
|
|||
return res;
|
||||
}
|
||||
|
||||
TimerThread timer;
|
||||
private long _nextExpectedTimerTs;
|
||||
|
||||
XEvent ev;
|
||||
|
||||
/// schedule timer for interval in milliseconds - call window.onTimer when finished
|
||||
override protected void scheduleSystemTimer(long intervalMillis) {
|
||||
if (!timer) {
|
||||
timer = new TimerThread(delegate() {
|
||||
core.stdc.string.memset(&ev, 0, ev.sizeof);
|
||||
//ev.xclient = XClientMessageEvent.init;
|
||||
ev.xclient.type = ClientMessage;
|
||||
ev.xclient.window = _win;
|
||||
ev.xclient.display = x11display;
|
||||
ev.xclient.format = TIMER_EVENT;
|
||||
Log.d("Sending timer event");
|
||||
XSendEvent(x11display, _win, false, StructureNotifyMask, &ev);
|
||||
});
|
||||
}
|
||||
if (intervalMillis < 10)
|
||||
intervalMillis = 10;
|
||||
long nextts = currentTimeMillis + intervalMillis;
|
||||
if (!_nextExpectedTimerTs || _nextExpectedTimerTs > nextts)
|
||||
if (_nextExpectedTimerTs == 0 || _nextExpectedTimerTs > nextts) {
|
||||
_nextExpectedTimerTs = nextts;
|
||||
timer.set(nextts);
|
||||
}
|
||||
}
|
||||
|
||||
bool handleTimer() {
|
||||
|
@ -689,7 +710,7 @@ class X11Window : DWindow {
|
|||
override void postEvent(CustomEvent event) {
|
||||
super.postEvent(event);
|
||||
XEvent ev;
|
||||
ev.type = ClientMessage;
|
||||
ev.xclient.type = ClientMessage;
|
||||
ev.xclient.window = _win;
|
||||
ev.xclient.format = CUSTOM_EVENT;
|
||||
ev.xclient.data.l[0] = event.uniqueId;
|
||||
|
@ -709,6 +730,7 @@ class X11Window : DWindow {
|
|||
}
|
||||
|
||||
private immutable int CUSTOM_EVENT = 32;
|
||||
private immutable int TIMER_EVENT = 8;
|
||||
|
||||
class X11Platform : Platform {
|
||||
|
||||
|
@ -781,11 +803,12 @@ class X11Platform : Platform {
|
|||
/* get the next event and stuff it into our event variable.
|
||||
Note: only events we set the mask for are detected!
|
||||
*/
|
||||
handleTimers();
|
||||
if (!XPending(x11display)) {
|
||||
Thread.sleep(dur!("msecs")(10));
|
||||
continue;
|
||||
}
|
||||
//bool timersHandled = handleTimers();
|
||||
//if (timersHandled)
|
||||
// XFlush(x11display);
|
||||
while (XEventsQueued(x11display, QueuedAfterFlush)) {//QueuedAfterFlush
|
||||
//Thread.sleep(dur!("msecs")(10));
|
||||
//continue;
|
||||
XNextEvent(x11display, &event);
|
||||
|
||||
switch (event.type) {
|
||||
|
@ -976,6 +999,8 @@ class X11Platform : Platform {
|
|||
if (w) {
|
||||
if (event.xclient.format == CUSTOM_EVENT) {
|
||||
w.handlePostedEvent(cast(uint)event.xclient.data.l[0]);
|
||||
} else if (event.xclient.format == TIMER_EVENT) {
|
||||
w.handleTimer();
|
||||
}
|
||||
} else {
|
||||
Log.e("Window not found");
|
||||
|
@ -985,6 +1010,9 @@ class X11Platform : Platform {
|
|||
break;
|
||||
}
|
||||
}
|
||||
//Thread.sleep(dur!("msecs")(10));
|
||||
//XFlush(x11display);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1008,6 +1036,79 @@ class X11Platform : Platform {
|
|||
}
|
||||
}
|
||||
|
||||
import core.thread;
|
||||
import core.sync.mutex;
|
||||
import core.sync.condition;
|
||||
class TimerThread : Thread {
|
||||
Mutex mutex;
|
||||
Condition condition;
|
||||
bool stopped;
|
||||
long nextEventTs;
|
||||
void delegate() callback;
|
||||
|
||||
this(void delegate() timerCallback) {
|
||||
callback = timerCallback;
|
||||
mutex = new Mutex();
|
||||
condition = new Condition(mutex);
|
||||
super(&run);
|
||||
start();
|
||||
}
|
||||
|
||||
~this() {
|
||||
stop();
|
||||
destroy(condition);
|
||||
destroy(mutex);
|
||||
}
|
||||
|
||||
void set(long nextTs) {
|
||||
mutex.lock();
|
||||
if (nextEventTs == 0 || nextEventTs > nextTs) {
|
||||
nextEventTs = nextTs;
|
||||
condition.notify();
|
||||
}
|
||||
mutex.unlock();
|
||||
}
|
||||
void run() {
|
||||
|
||||
while (!stopped) {
|
||||
bool expired = false;
|
||||
|
||||
mutex.lock();
|
||||
|
||||
long ts = currentTimeMillis;
|
||||
long timeToWait = nextEventTs == 0 ? 1000 : nextEventTs - ts;
|
||||
if (timeToWait < 10)
|
||||
timeToWait = 10;
|
||||
|
||||
condition.wait(dur!"msecs"(timeToWait));
|
||||
|
||||
if (stopped) {
|
||||
mutex.unlock();
|
||||
break;
|
||||
}
|
||||
ts = currentTimeMillis;
|
||||
if (nextEventTs && nextEventTs < ts && !stopped) {
|
||||
expired = true;
|
||||
nextEventTs = 0;
|
||||
}
|
||||
|
||||
mutex.unlock();
|
||||
|
||||
if (expired)
|
||||
callback();
|
||||
}
|
||||
}
|
||||
void stop() {
|
||||
if (stopped)
|
||||
return;
|
||||
stopped = true;
|
||||
mutex.lock();
|
||||
condition.notify();
|
||||
mutex.unlock();
|
||||
join();
|
||||
}
|
||||
}
|
||||
|
||||
enum {
|
||||
XC_X_cursor=0,
|
||||
XC_arrow=2,
|
||||
|
@ -1104,6 +1205,8 @@ extern(C) int DLANGUImain(string[] args)
|
|||
|
||||
currentTheme = createDefaultTheme();
|
||||
|
||||
XInitThreads();
|
||||
|
||||
/* use the information from the environment variable DISPLAY
|
||||
to create the X connection:
|
||||
*/
|
||||
|
@ -1141,6 +1244,8 @@ extern(C) int DLANGUImain(string[] args)
|
|||
|
||||
Log.d("X11 display=", x11display, " screen=", x11screen);
|
||||
|
||||
|
||||
|
||||
X11Platform x11platform = new X11Platform();
|
||||
|
||||
Platform.setInstance(x11platform);
|
||||
|
|
Loading…
Reference in New Issue