Merge pull request #477 from FreeSlave/x11_refactor_eventloop

Avoid code duplication when processing x11 events. Add redraw events …
This commit is contained in:
Vadim Lopatin 2017-10-09 09:29:26 +03:00 committed by GitHub
commit 7da6b5482e
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;