mirror of https://github.com/buggins/dlangui.git
Avoid code duplication when processing x11 events. Add redraw events for x11 (similarly to sdl2 redraw events), simplify event loop. Remove sleep and use select timeout instead
This commit is contained in:
parent
4c6cc85481
commit
5fb0a14945
|
@ -101,6 +101,7 @@ private __gshared
|
||||||
Atom atom_DLANGUI_TASK_EVENT;
|
Atom atom_DLANGUI_TASK_EVENT;
|
||||||
Atom atom_DLANGUI_CLOSE_WINDOW_EVENT;
|
Atom atom_DLANGUI_CLOSE_WINDOW_EVENT;
|
||||||
Atom atom_DLANGUI_CLIPBOARD_BUFFER;
|
Atom atom_DLANGUI_CLIPBOARD_BUFFER;
|
||||||
|
Atom atom_DLANGUI_REDRAW_EVENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setupX11Atoms()
|
static void setupX11Atoms()
|
||||||
|
@ -127,6 +128,7 @@ static void setupX11Atoms()
|
||||||
atom_DLANGUI_TASK_EVENT = XInternAtom(x11display, "DLANGUI_TASK_EVENT", False);
|
atom_DLANGUI_TASK_EVENT = XInternAtom(x11display, "DLANGUI_TASK_EVENT", False);
|
||||||
atom_DLANGUI_CLOSE_WINDOW_EVENT = XInternAtom(x11display, "DLANGUI_CLOSE_WINDOW_EVENT", False);
|
atom_DLANGUI_CLOSE_WINDOW_EVENT = XInternAtom(x11display, "DLANGUI_CLOSE_WINDOW_EVENT", False);
|
||||||
atom_DLANGUI_CLIPBOARD_BUFFER = XInternAtom(x11display, "DLANGUI_CLIPBOARD_BUFFER", False);
|
atom_DLANGUI_CLIPBOARD_BUFFER = XInternAtom(x11display, "DLANGUI_CLIPBOARD_BUFFER", False);
|
||||||
|
atom_DLANGUI_REDRAW_EVENT = XInternAtom(x11display, "DLANGUI_REDRAW_EVENT", False);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cursor font constants
|
// Cursor font constants
|
||||||
|
@ -254,7 +256,6 @@ class X11Window : DWindow {
|
||||||
X11Window[] _children;
|
X11Window[] _children;
|
||||||
X11Window _parent;
|
X11Window _parent;
|
||||||
|
|
||||||
bool _needRedraw;
|
|
||||||
int _cachedWidth, _cachedHeight;
|
int _cachedWidth, _cachedHeight;
|
||||||
|
|
||||||
static if (ENABLE_OPENGL) {
|
static if (ENABLE_OPENGL) {
|
||||||
|
@ -661,12 +662,18 @@ class X11Window : DWindow {
|
||||||
XChangeProperty(x11display, _win, atom_NET_WM_ICON, XA_CARDINAL, 32, PropModeReplace, cast(ubyte*)propData.ptr, cast(int)propData.length);
|
XChangeProperty(x11display, _win, atom_NET_WM_ICON, XA_CARDINAL, 32, PropModeReplace, cast(ubyte*)propData.ptr, cast(int)propData.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint _lastRedrawEventCode;
|
||||||
/// request window redraw
|
/// request window redraw
|
||||||
override void invalidate() {
|
override void invalidate() {
|
||||||
if (!_needRedraw) {
|
XEvent ev;
|
||||||
debug(x11) Log.d("Window.invalidate()");
|
ev.xclient.type = ClientMessage;
|
||||||
_needRedraw = true;
|
ev.xclient.message_type = atom_DLANGUI_REDRAW_EVENT;
|
||||||
}
|
ev.xclient.window = _win;
|
||||||
|
ev.xclient.display = x11display;
|
||||||
|
ev.xclient.format = 32;
|
||||||
|
ev.xclient.data.l[0] = ++_lastRedrawEventCode;
|
||||||
|
XSendEvent(x11display, _win, false, StructureNotifyMask, &ev);
|
||||||
|
XFlush(x11display);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// close window
|
/// close window
|
||||||
|
@ -738,7 +745,7 @@ class X11Window : DWindow {
|
||||||
}
|
}
|
||||||
|
|
||||||
void redraw() {
|
void redraw() {
|
||||||
_needRedraw = false;
|
_lastRedrawEventCode = 0;
|
||||||
//Use values cached by ConfigureNotify to avoid XGetWindowAttributes call.
|
//Use values cached by ConfigureNotify to avoid XGetWindowAttributes call.
|
||||||
//XWindowAttributes window_attributes_return;
|
//XWindowAttributes window_attributes_return;
|
||||||
//XGetWindowAttributes(x11display, _win, &window_attributes_return);
|
//XGetWindowAttributes(x11display, _win, &window_attributes_return);
|
||||||
|
@ -1335,7 +1342,7 @@ class X11Platform : Platform {
|
||||||
return _windowMap.length == 0;
|
return _windowMap.length == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int numberOfPendingEvents()
|
protected int numberOfPendingEvents(int msecs = 10)
|
||||||
{
|
{
|
||||||
import core.sys.posix.sys.select;
|
import core.sys.posix.sys.select;
|
||||||
int x11displayFd = ConnectionNumber(x11display);
|
int x11displayFd = ConnectionNumber(x11display);
|
||||||
|
@ -1349,13 +1356,14 @@ class X11Platform : Platform {
|
||||||
import core.stdc.errno;
|
import core.stdc.errno;
|
||||||
int selectResult;
|
int selectResult;
|
||||||
do {
|
do {
|
||||||
timeval zeroTime;
|
timeval timeout;
|
||||||
selectResult = select(x11displayFd + 1, &fdSet, null, null, &zeroTime);
|
timeout.tv_usec = msecs;
|
||||||
|
selectResult = select(x11displayFd + 1, &fdSet, null, null, &timeout);
|
||||||
} while(selectResult == -1 && errno == EINTR);
|
} while(selectResult == -1 && errno == EINTR);
|
||||||
if (selectResult < 0) {
|
if (selectResult < 0) {
|
||||||
Log.e("X11: display fd select error");
|
Log.e("X11: display fd select error");
|
||||||
} else if (selectResult == 1) {
|
} else if (selectResult == 1) {
|
||||||
Log.d("X11: XPending");
|
//Log.d("X11: XPending");
|
||||||
eventsInQueue = XPending(x11display);
|
eventsInQueue = XPending(x11display);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1531,7 +1539,9 @@ class X11Platform : Platform {
|
||||||
case EnterNotify:
|
case EnterNotify:
|
||||||
Log.d("X11: EnterNotify event");
|
Log.d("X11: EnterNotify event");
|
||||||
X11Window w = findWindow(event.xcrossing.window);
|
X11Window w = findWindow(event.xcrossing.window);
|
||||||
if (!w) {
|
if (w) {
|
||||||
|
w.processMouseEvent(MouseAction.Move, 0, event.xmotion.state, event.xcrossing.x, event.xcrossing.y);
|
||||||
|
} else {
|
||||||
Log.e("Window not found");
|
Log.e("Window not found");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1639,6 +1649,9 @@ class X11Platform : Platform {
|
||||||
w.handlePostedEvent(cast(uint)event.xclient.data.l[0]);
|
w.handlePostedEvent(cast(uint)event.xclient.data.l[0]);
|
||||||
} else if (event.xclient.message_type == atom_DLANGUI_TIMER_EVENT) {
|
} else if (event.xclient.message_type == atom_DLANGUI_TIMER_EVENT) {
|
||||||
w.handleTimer();
|
w.handleTimer();
|
||||||
|
} else if (event.xclient.message_type == atom_DLANGUI_REDRAW_EVENT) {
|
||||||
|
if (event.xclient.data.l[0] == w._lastRedrawEventCode)
|
||||||
|
w.redraw();
|
||||||
} else if (event.xclient.message_type == atom_WM_PROTOCOLS) {
|
} else if (event.xclient.message_type == atom_WM_PROTOCOLS) {
|
||||||
Log.d("Handling WM_PROTOCOLS");
|
Log.d("Handling WM_PROTOCOLS");
|
||||||
if ((event.xclient.format == 32) && (event.xclient.data.l[0]) == atom_WM_DELETE_WINDOW) {
|
if ((event.xclient.format == 32) && (event.xclient.data.l[0]) == atom_WM_DELETE_WINDOW) {
|
||||||
|
@ -1659,41 +1672,30 @@ class X11Platform : Platform {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void pumpEvents()
|
||||||
|
{
|
||||||
|
XFlush(x11display);
|
||||||
|
// Note: only events we set the mask for are detected!
|
||||||
|
while(numberOfPendingEvents())
|
||||||
|
{
|
||||||
|
if (allWindowsClosed())
|
||||||
|
break;
|
||||||
|
XEvent event; /* the XEvent declaration !!! */
|
||||||
|
XNextEvent(x11display, &event);
|
||||||
|
processXEvent(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts application message loop.
|
* Starts application message loop.
|
||||||
*
|
*
|
||||||
* When returned from this method, application is shutting down.
|
* When returned from this method, application is shutting down.
|
||||||
*/
|
*/
|
||||||
override int enterMessageLoop() {
|
override int enterMessageLoop() {
|
||||||
import core.thread;
|
|
||||||
XEvent event; /* the XEvent declaration !!! */
|
|
||||||
KeySym key; /* a dealie-bob to handle KeyPress Events */
|
|
||||||
char[255] text; /* a char buffer for KeyPress Events */
|
|
||||||
|
|
||||||
Log.d("enterMessageLoop()");
|
Log.d("enterMessageLoop()");
|
||||||
|
|
||||||
while(!allWindowsClosed()) {
|
while(!allWindowsClosed()) {
|
||||||
// Note: only events we set the mask for are detected!
|
pumpEvents();
|
||||||
foreach(win; _windowMap) {
|
|
||||||
if (win._needRedraw) {
|
|
||||||
win.redraw();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
XFlush(x11display);
|
|
||||||
int eventsInQueue = numberOfPendingEvents();
|
|
||||||
if (!eventsInQueue) {
|
|
||||||
//debug(x11) Log.d("X11: Sleeping");
|
|
||||||
Thread.sleep(dur!("msecs")(10));
|
|
||||||
}
|
|
||||||
foreach(eventIndex; 0..eventsInQueue)
|
|
||||||
{
|
|
||||||
if (allWindowsClosed())
|
|
||||||
break;
|
|
||||||
if (!numberOfPendingEvents())
|
|
||||||
break;
|
|
||||||
XNextEvent(x11display, &event);
|
|
||||||
processXEvent(event);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1733,18 +1735,7 @@ class X11Platform : Platform {
|
||||||
Log.e("Waiting for clipboard contents timeout");
|
Log.e("Waiting for clipboard contents timeout");
|
||||||
return ""d;
|
return ""d;
|
||||||
}
|
}
|
||||||
XFlush(x11display);
|
pumpEvents();
|
||||||
int eventsInQueue = numberOfPendingEvents();
|
|
||||||
foreach(eventIndex; 0..eventsInQueue)
|
|
||||||
{
|
|
||||||
if (allWindowsClosed())
|
|
||||||
break;
|
|
||||||
if (!numberOfPendingEvents())
|
|
||||||
break;
|
|
||||||
XEvent event;
|
|
||||||
XNextEvent(x11display, &event);
|
|
||||||
processXEvent(event);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Atom selectionTarget;
|
Atom selectionTarget;
|
||||||
int selectionFormat;
|
int selectionFormat;
|
||||||
|
|
Loading…
Reference in New Issue