mirror of https://github.com/adamdruppe/arsd.git
optional use of arsd.eventloop on X/Linux
This commit is contained in:
parent
ca5ea9d0f7
commit
d1beb29cd4
173
simpledisplay.d
173
simpledisplay.d
|
@ -38,7 +38,8 @@ struct Size {
|
||||||
|
|
||||||
|
|
||||||
struct KeyEvent {
|
struct KeyEvent {
|
||||||
|
uint keycode;
|
||||||
|
bool pressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MouseEvent {
|
struct MouseEvent {
|
||||||
|
@ -902,6 +903,7 @@ version(X11) {
|
||||||
XCopyArea(display, d, destiny, gc, 0, 0, this.window.width, this.window.height, 0, 0);
|
XCopyArea(display, d, destiny, gc, 0, 0, this.window.width, this.window.height, 0, 0);
|
||||||
|
|
||||||
XFreeGC(display, gc);
|
XFreeGC(display, gc);
|
||||||
|
XFlush(display);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool backgroundIsNotTransparent = true;
|
bool backgroundIsNotTransparent = true;
|
||||||
|
@ -1020,14 +1022,38 @@ version(X11) {
|
||||||
class XDisplayConnection {
|
class XDisplayConnection {
|
||||||
private static Display* display;
|
private static Display* display;
|
||||||
|
|
||||||
static Display* get() {
|
static Display* get(SimpleWindow window = null) {
|
||||||
if(display is null)
|
// FIXME: this shouldn't even be necessary
|
||||||
|
version(with_eventloop)
|
||||||
|
if(window !is null)
|
||||||
|
this.window = window;
|
||||||
|
if(display is null) {
|
||||||
display = enforce(XOpenDisplay(null));
|
display = enforce(XOpenDisplay(null));
|
||||||
|
version(with_eventloop) {
|
||||||
|
import arsd.eventloop;
|
||||||
|
addFileEventListeners(display.fd, &eventListener, null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return display;
|
return display;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
version(with_eventloop) {
|
||||||
|
import arsd.eventloop;
|
||||||
|
static void eventListener(OsFileHandle fd) {
|
||||||
|
while(XPending(display))
|
||||||
|
doXNextEvent(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SimpleWindow window;
|
||||||
|
}
|
||||||
|
|
||||||
static void close() {
|
static void close() {
|
||||||
|
version(with_eventloop) {
|
||||||
|
import arsd.eventloop;
|
||||||
|
removeFileEventListeners(display.fd);
|
||||||
|
}
|
||||||
|
|
||||||
XCloseDisplay(display);
|
XCloseDisplay(display);
|
||||||
display = null;
|
display = null;
|
||||||
}
|
}
|
||||||
|
@ -1098,7 +1124,7 @@ version(X11) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void createWindow(int width, int height, string title) {
|
void createWindow(int width, int height, string title) {
|
||||||
display = XDisplayConnection.get();
|
display = XDisplayConnection.get(this);
|
||||||
auto screen = DefaultScreen(display);
|
auto screen = DefaultScreen(display);
|
||||||
|
|
||||||
window = XCreateSimpleWindow(
|
window = XCreateSimpleWindow(
|
||||||
|
@ -1141,11 +1167,14 @@ version(X11) {
|
||||||
| EventMask.ButtonPressMask
|
| EventMask.ButtonPressMask
|
||||||
| EventMask.ButtonReleaseMask
|
| EventMask.ButtonReleaseMask
|
||||||
);
|
);
|
||||||
|
|
||||||
|
XFlush(display);
|
||||||
}
|
}
|
||||||
|
|
||||||
void closeWindow() {
|
void closeWindow() {
|
||||||
XFreePixmap(display, buffer);
|
XFreePixmap(display, buffer);
|
||||||
XDestroyWindow(display, window);
|
XDestroyWindow(display, window);
|
||||||
|
XFlush(display);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
@ -1154,68 +1183,13 @@ version(X11) {
|
||||||
bool destroyed = false;
|
bool destroyed = false;
|
||||||
|
|
||||||
int eventLoop(long pulseTimeout) {
|
int eventLoop(long pulseTimeout) {
|
||||||
XEvent e;
|
|
||||||
bool done = false;
|
bool done = false;
|
||||||
|
|
||||||
while (!done) {
|
while (!done) {
|
||||||
while(!done &&
|
while(!done &&
|
||||||
(pulseTimeout == 0 || (XPending(display) > 0)))
|
(pulseTimeout == 0 || (XPending(display) > 0)))
|
||||||
{
|
{
|
||||||
XNextEvent(display, &e);
|
done = doXNextEvent(this); // FIXME: what about multiple windows? This wasn't originally going to support them but maybe I should
|
||||||
|
|
||||||
switch(e.type) {
|
|
||||||
case EventType.Expose:
|
|
||||||
//if(backingImage !is null)
|
|
||||||
// XPutImage(display, cast(Drawable) window, gc, backingImage.handle, 0, 0, 0, 0, backingImage.width, backingImage.height);
|
|
||||||
XCopyArea(display, cast(Drawable) buffer, cast(Drawable) window, gc, 0, 0, width, height, 0, 0);
|
|
||||||
break;
|
|
||||||
case EventType.ClientMessage: // User clicked the close button
|
|
||||||
case EventType.DestroyNotify:
|
|
||||||
done = true;
|
|
||||||
destroyed = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EventType.MotionNotify:
|
|
||||||
MouseEvent mouse;
|
|
||||||
auto event = e.xmotion;
|
|
||||||
|
|
||||||
mouse.type = 0;
|
|
||||||
mouse.x = event.x;
|
|
||||||
mouse.y = event.y;
|
|
||||||
mouse.buttonFlags = event.state;
|
|
||||||
|
|
||||||
if(handleMouseEvent)
|
|
||||||
handleMouseEvent(mouse);
|
|
||||||
break;
|
|
||||||
case EventType.ButtonPress:
|
|
||||||
case EventType.ButtonRelease:
|
|
||||||
MouseEvent mouse;
|
|
||||||
auto event = e.xbutton;
|
|
||||||
|
|
||||||
mouse.type = e.type == EventType.ButtonPress ? 1 : 2;
|
|
||||||
mouse.x = event.x;
|
|
||||||
mouse.y = event.y;
|
|
||||||
mouse.button = event.button;
|
|
||||||
//mouse.buttonFlags = event.detail;
|
|
||||||
|
|
||||||
if(handleMouseEvent)
|
|
||||||
handleMouseEvent(mouse);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EventType.KeyPress:
|
|
||||||
if(handleCharEvent)
|
|
||||||
handleCharEvent(
|
|
||||||
cast(dchar) XKeycodeToKeysym(
|
|
||||||
XDisplayConnection.get(),
|
|
||||||
e.xkey.keycode,
|
|
||||||
0)); // FIXME: we should check shift, etc. too, so it matches Windows' behavior better
|
|
||||||
goto case;
|
|
||||||
case EventType.KeyRelease:
|
|
||||||
if(handleKeyEvent)
|
|
||||||
handleKeyEvent(e.xkey.keycode, e.type == EventType.ButtonPress);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if(!done && pulseTimeout !=0) {
|
if(!done && pulseTimeout !=0) {
|
||||||
if(handlePulse !is null)
|
if(handlePulse !is null)
|
||||||
|
@ -1229,6 +1203,85 @@ version(X11) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
version(X11) {
|
||||||
|
bool doXNextEvent(SimpleWindow t) {
|
||||||
|
bool done;
|
||||||
|
XEvent e;
|
||||||
|
XNextEvent(t.display, &e);
|
||||||
|
|
||||||
|
version(with_eventloop)
|
||||||
|
import arsd.eventloop;
|
||||||
|
|
||||||
|
switch(e.type) {
|
||||||
|
case EventType.Expose:
|
||||||
|
//if(backingImage !is null)
|
||||||
|
// XPutImage(display, cast(Drawable) window, gc, backingImage.handle, 0, 0, 0, 0, backingImage.width, backingImage.height);
|
||||||
|
XCopyArea(t.display, cast(Drawable) t.buffer, cast(Drawable) t.window, t.gc, 0, 0, t.width, t.height, 0, 0);
|
||||||
|
break;
|
||||||
|
case EventType.ClientMessage: // User clicked the close button
|
||||||
|
case EventType.DestroyNotify:
|
||||||
|
done = true;
|
||||||
|
t.destroyed = true;
|
||||||
|
version(with_eventloop)
|
||||||
|
exit();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EventType.MotionNotify:
|
||||||
|
MouseEvent mouse;
|
||||||
|
auto event = e.xmotion;
|
||||||
|
|
||||||
|
mouse.type = 0;
|
||||||
|
mouse.x = event.x;
|
||||||
|
mouse.y = event.y;
|
||||||
|
mouse.buttonFlags = event.state;
|
||||||
|
|
||||||
|
if(t.handleMouseEvent)
|
||||||
|
t.handleMouseEvent(mouse);
|
||||||
|
version(with_eventloop)
|
||||||
|
send(mouse);
|
||||||
|
break;
|
||||||
|
case EventType.ButtonPress:
|
||||||
|
case EventType.ButtonRelease:
|
||||||
|
MouseEvent mouse;
|
||||||
|
auto event = e.xbutton;
|
||||||
|
|
||||||
|
mouse.type = e.type == EventType.ButtonPress ? 1 : 2;
|
||||||
|
mouse.x = event.x;
|
||||||
|
mouse.y = event.y;
|
||||||
|
mouse.button = event.button;
|
||||||
|
//mouse.buttonFlags = event.detail;
|
||||||
|
|
||||||
|
if(t.handleMouseEvent)
|
||||||
|
t.handleMouseEvent(mouse);
|
||||||
|
version(with_eventloop)
|
||||||
|
send(mouse);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EventType.KeyPress:
|
||||||
|
auto ch = cast(dchar) XKeycodeToKeysym(
|
||||||
|
XDisplayConnection.get(),
|
||||||
|
e.xkey.keycode,
|
||||||
|
0); // FIXME: we should check shift, etc. too, so it matches Windows' behavior better
|
||||||
|
|
||||||
|
if(t.handleCharEvent)
|
||||||
|
t.handleCharEvent(ch);
|
||||||
|
version(with_eventloop)
|
||||||
|
send(ch);
|
||||||
|
goto case;
|
||||||
|
case EventType.KeyRelease:
|
||||||
|
if(t.handleKeyEvent)
|
||||||
|
t.handleKeyEvent(e.xkey.keycode, e.type == EventType.ButtonPress);
|
||||||
|
|
||||||
|
version(with_eventloop)
|
||||||
|
send(KeyEvent(e.xkey.keycode, e.type == EventType.ButtonPress));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
return done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* *************************************** */
|
/* *************************************** */
|
||||||
/* Done with simpledisplay stuff */
|
/* Done with simpledisplay stuff */
|
||||||
/* *************************************** */
|
/* *************************************** */
|
||||||
|
|
Loading…
Reference in New Issue