mirror of https://github.com/buggins/dlangui.git
Merge pull request #477 from FreeSlave/x11_refactor_eventloop
Avoid code duplication when processing x11 events. Add redraw events …
This commit is contained in:
commit
7da6b5482e
|
@ -101,6 +101,7 @@ private __gshared
|
|||
Atom atom_DLANGUI_TASK_EVENT;
|
||||
Atom atom_DLANGUI_CLOSE_WINDOW_EVENT;
|
||||
Atom atom_DLANGUI_CLIPBOARD_BUFFER;
|
||||
Atom atom_DLANGUI_REDRAW_EVENT;
|
||||
}
|
||||
|
||||
static void setupX11Atoms()
|
||||
|
@ -127,6 +128,7 @@ static void setupX11Atoms()
|
|||
atom_DLANGUI_TASK_EVENT = XInternAtom(x11display, "DLANGUI_TASK_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_REDRAW_EVENT = XInternAtom(x11display, "DLANGUI_REDRAW_EVENT", False);
|
||||
}
|
||||
|
||||
// Cursor font constants
|
||||
|
@ -254,7 +256,6 @@ class X11Window : DWindow {
|
|||
X11Window[] _children;
|
||||
X11Window _parent;
|
||||
|
||||
bool _needRedraw;
|
||||
int _cachedWidth, _cachedHeight;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
uint _lastRedrawEventCode;
|
||||
/// request window redraw
|
||||
override void invalidate() {
|
||||
if (!_needRedraw) {
|
||||
debug(x11) Log.d("Window.invalidate()");
|
||||
_needRedraw = true;
|
||||
}
|
||||
XEvent ev;
|
||||
ev.xclient.type = ClientMessage;
|
||||
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
|
||||
|
@ -738,7 +745,7 @@ class X11Window : DWindow {
|
|||
}
|
||||
|
||||
void redraw() {
|
||||
_needRedraw = false;
|
||||
_lastRedrawEventCode = 0;
|
||||
//Use values cached by ConfigureNotify to avoid XGetWindowAttributes call.
|
||||
//XWindowAttributes window_attributes_return;
|
||||
//XGetWindowAttributes(x11display, _win, &window_attributes_return);
|
||||
|
@ -1335,7 +1342,7 @@ class X11Platform : Platform {
|
|||
return _windowMap.length == 0;
|
||||
}
|
||||
|
||||
protected int numberOfPendingEvents()
|
||||
protected int numberOfPendingEvents(int msecs = 10)
|
||||
{
|
||||
import core.sys.posix.sys.select;
|
||||
int x11displayFd = ConnectionNumber(x11display);
|
||||
|
@ -1349,13 +1356,14 @@ class X11Platform : Platform {
|
|||
import core.stdc.errno;
|
||||
int selectResult;
|
||||
do {
|
||||
timeval zeroTime;
|
||||
selectResult = select(x11displayFd + 1, &fdSet, null, null, &zeroTime);
|
||||
timeval timeout;
|
||||
timeout.tv_usec = msecs;
|
||||
selectResult = select(x11displayFd + 1, &fdSet, null, null, &timeout);
|
||||
} while(selectResult == -1 && errno == EINTR);
|
||||
if (selectResult < 0) {
|
||||
Log.e("X11: display fd select error");
|
||||
} else if (selectResult == 1) {
|
||||
Log.d("X11: XPending");
|
||||
//Log.d("X11: XPending");
|
||||
eventsInQueue = XPending(x11display);
|
||||
}
|
||||
}
|
||||
|
@ -1531,7 +1539,9 @@ class X11Platform : Platform {
|
|||
case EnterNotify:
|
||||
Log.d("X11: EnterNotify event");
|
||||
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");
|
||||
}
|
||||
break;
|
||||
|
@ -1639,6 +1649,9 @@ class X11Platform : Platform {
|
|||
w.handlePostedEvent(cast(uint)event.xclient.data.l[0]);
|
||||
} else if (event.xclient.message_type == atom_DLANGUI_TIMER_EVENT) {
|
||||
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) {
|
||||
Log.d("Handling WM_PROTOCOLS");
|
||||
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.
|
||||
*
|
||||
* When returned from this method, application is shutting down.
|
||||
*/
|
||||
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()");
|
||||
|
||||
while(!allWindowsClosed()) {
|
||||
// Note: only events we set the mask for are detected!
|
||||
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);
|
||||
}
|
||||
pumpEvents();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1733,18 +1735,7 @@ class X11Platform : Platform {
|
|||
Log.e("Waiting for clipboard contents timeout");
|
||||
return ""d;
|
||||
}
|
||||
XFlush(x11display);
|
||||
int eventsInQueue = numberOfPendingEvents();
|
||||
foreach(eventIndex; 0..eventsInQueue)
|
||||
{
|
||||
if (allWindowsClosed())
|
||||
break;
|
||||
if (!numberOfPendingEvents())
|
||||
break;
|
||||
XEvent event;
|
||||
XNextEvent(x11display, &event);
|
||||
processXEvent(event);
|
||||
}
|
||||
pumpEvents();
|
||||
}
|
||||
Atom selectionTarget;
|
||||
int selectionFormat;
|
||||
|
|
Loading…
Reference in New Issue