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:
Roman Chistokhodov 2017-10-07 22:36:44 +03:00
parent 4c6cc85481
commit 5fb0a14945
1 changed files with 40 additions and 49 deletions

View File

@ -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;