mirror of https://github.com/adamdruppe/arsd.git
from ketmar
This commit is contained in:
parent
e96cf886e0
commit
37eea9f26c
284
simpledisplay.d
284
simpledisplay.d
|
@ -766,9 +766,27 @@ class SimpleWindow : CapableOfHandlingNativeEvent {
|
||||||
_suppressDestruction = true; // so it doesn't try to close
|
_suppressDestruction = true; // so it doesn't try to close
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This will be called when WM wants to close your window (i.e. user clicked "close" icon, for example).
|
||||||
|
/// You'll have to call `close()` manually if you set this delegate.
|
||||||
|
version(X11) void delegate () closeQuery;
|
||||||
|
|
||||||
|
/// This will be called when window visibility was changed.
|
||||||
|
void delegate (bool becomesVisible) visibilityChanged;
|
||||||
|
|
||||||
|
/// This will be called when window becomes visible for the first time.
|
||||||
|
/// You can do OpenGL initialization here. Note that in X11 you can't call
|
||||||
|
/// `setAsCurrentOpenGlContext()` right after window creation, or X11 may
|
||||||
|
/// fail to send reparent and map events (hit that with proprietary NVidia drivers).
|
||||||
|
private bool _visibleForTheFirstTimeCalled;
|
||||||
|
void delegate () visibleForTheFirstTime;
|
||||||
|
|
||||||
/// Returns true if the window has been closed.
|
/// Returns true if the window has been closed.
|
||||||
final @property bool closed() { return _closed; }
|
final @property bool closed() { return _closed; }
|
||||||
|
|
||||||
|
private bool _visible;
|
||||||
|
/// Returns true if the window is visible (mapped).
|
||||||
|
final @property bool visible() { return _visible; }
|
||||||
|
|
||||||
/// Closes the window. If there are no more open windows, the event loop will terminate.
|
/// Closes the window. If there are no more open windows, the event loop will terminate.
|
||||||
void close() {
|
void close() {
|
||||||
impl.closeWindow();
|
impl.closeWindow();
|
||||||
|
@ -877,15 +895,34 @@ class SimpleWindow : CapableOfHandlingNativeEvent {
|
||||||
/// Put your code in here that you want to be drawn automatically when your window is uncovered. Set a handler here *before* entering your event loop any time you pass `OpenGlOptions.yes` to the constructor. Ideally, you will set this delegate immediately after constructing the `SimpleWindow`.
|
/// Put your code in here that you want to be drawn automatically when your window is uncovered. Set a handler here *before* entering your event loop any time you pass `OpenGlOptions.yes` to the constructor. Ideally, you will set this delegate immediately after constructing the `SimpleWindow`.
|
||||||
void delegate() redrawOpenGlScene;
|
void delegate() redrawOpenGlScene;
|
||||||
|
|
||||||
|
/// This will allow you to change OpenGL vsync state.
|
||||||
|
final @property void vsync (bool wait) {
|
||||||
|
if (this._closed) return; // window may be closed, but timer is still firing; avoid GLXBadDrawable error
|
||||||
|
version(X11) {
|
||||||
|
setAsCurrentOpenGlContext();
|
||||||
|
glxSetVSync(display, impl.window, wait);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set this to `false` if you don't need to do `glFinish()` after `swapOpenGlBuffers()`.
|
||||||
|
/// Note that at least NVidia proprietary driver may segfault if you will modify texture fast
|
||||||
|
/// enough without waiting 'em to finish their frame bussiness.
|
||||||
|
bool useGLFinish = true;
|
||||||
|
|
||||||
// FIXME: it should schedule it for the end of the current iteration of the event loop...
|
// FIXME: it should schedule it for the end of the current iteration of the event loop...
|
||||||
/// call this to invoke your delegate. It automatically sets up the context and flips the buffer. If you need to redraw the scene in response to an event, call this.
|
/// call this to invoke your delegate. It automatically sets up the context and flips the buffer. If you need to redraw the scene in response to an event, call this.
|
||||||
void redrawOpenGlSceneNow() {
|
void redrawOpenGlSceneNow() {
|
||||||
|
version(X11) if (!this._visible) return; // no need to do this if window is invisible
|
||||||
|
if (this._closed) return; // window may be closed, but timer is still firing; avoid GLXBadDrawable error
|
||||||
|
|
||||||
this.setAsCurrentOpenGlContext();
|
this.setAsCurrentOpenGlContext();
|
||||||
|
|
||||||
if(redrawOpenGlScene !is null)
|
if(redrawOpenGlScene !is null)
|
||||||
redrawOpenGlScene();
|
redrawOpenGlScene();
|
||||||
|
|
||||||
this.swapOpenGlBuffers();
|
this.swapOpenGlBuffers();
|
||||||
|
// at least nvidia proprietary crap segfaults on exit if you won't do this and will call glTexSubImage2D() too fast; no, `glFlush()` won't work.
|
||||||
|
if (useGLFinish) glFinish();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -909,6 +946,8 @@ class SimpleWindow : CapableOfHandlingNativeEvent {
|
||||||
void swapOpenGlBuffers() {
|
void swapOpenGlBuffers() {
|
||||||
assert(openglMode == OpenGlOptions.yes);
|
assert(openglMode == OpenGlOptions.yes);
|
||||||
version(X11) {
|
version(X11) {
|
||||||
|
if (!this._visible) return; // no need to do this if window is invisible
|
||||||
|
if (this._closed) return; // window may be closed, but timer is still firing; avoid GLXBadDrawable error
|
||||||
glXSwapBuffers(XDisplayConnection.get, impl.window);
|
glXSwapBuffers(XDisplayConnection.get, impl.window);
|
||||||
} else version(Windows) {
|
} else version(Windows) {
|
||||||
SwapBuffers(ghDC);
|
SwapBuffers(ghDC);
|
||||||
|
@ -3677,6 +3716,14 @@ version(Windows) {
|
||||||
return cast(typeof(return)) //GetStockObject(NULL_BRUSH);
|
return cast(typeof(return)) //GetStockObject(NULL_BRUSH);
|
||||||
GetSysColorBrush(COLOR_3DFACE);
|
GetSysColorBrush(COLOR_3DFACE);
|
||||||
break;
|
break;
|
||||||
|
case WM_SHOWWINDOW:
|
||||||
|
this._visible = (wParam != 0);
|
||||||
|
if (!this._visibleForTheFirstTimeCalled) {
|
||||||
|
this._visibleForTheFirstTimeCalled = true;
|
||||||
|
if (this.visibleForTheFirstTime !is null) this.visibleForTheFirstTime();
|
||||||
|
}
|
||||||
|
if (this.visibilityChanged !is null) this.visibilityChanged(this._visible);
|
||||||
|
break;
|
||||||
case WM_PAINT: {
|
case WM_PAINT: {
|
||||||
BITMAP bm;
|
BITMAP bm;
|
||||||
PAINTSTRUCT ps;
|
PAINTSTRUCT ps;
|
||||||
|
@ -4180,6 +4227,8 @@ version(X11) {
|
||||||
display = XOpenDisplay(null);
|
display = XOpenDisplay(null);
|
||||||
if(display is null)
|
if(display is null)
|
||||||
throw new Exception("Unable to open X display");
|
throw new Exception("Unable to open X display");
|
||||||
|
Bool sup;
|
||||||
|
XkbSetDetectableAutoRepeat(display, 1, &sup); // so we will not receive KeyRelease until key is really released
|
||||||
version(with_eventloop) {
|
version(with_eventloop) {
|
||||||
import arsd.eventloop;
|
import arsd.eventloop;
|
||||||
addFileEventListeners(display.fd, &eventListener, null, null);
|
addFileEventListeners(display.fd, &eventListener, null, null);
|
||||||
|
@ -4224,7 +4273,7 @@ version(X11) {
|
||||||
if(!xshmQueryCompleted) {
|
if(!xshmQueryCompleted) {
|
||||||
int i1, i2, i3;
|
int i1, i2, i3;
|
||||||
xshmQueryCompleted = true;
|
xshmQueryCompleted = true;
|
||||||
_xshmAvailable = XQueryExtension(XDisplayConnection.get(), "MIT-SHM", &i1, &i2, &i3);
|
_xshmAvailable = XQueryExtension(XDisplayConnection.get(), "MIT-SHM", &i1, &i2, &i3) != 0;
|
||||||
}
|
}
|
||||||
return _xshmAvailable;
|
return _xshmAvailable;
|
||||||
}
|
}
|
||||||
|
@ -4381,7 +4430,7 @@ version(X11) {
|
||||||
0, 0, width, height,
|
0, 0, width, height,
|
||||||
0, vi.depth, 1 /* InputOutput */, vi.visual, CWColormap, &swa);
|
0, vi.depth, 1 /* InputOutput */, vi.visual, CWColormap, &swa);
|
||||||
|
|
||||||
glc = glXCreateContext(display, vi, null, GL_TRUE);
|
glc = glXCreateContext(display, vi, null, /*GL_TRUE*/1);
|
||||||
if(glc is null)
|
if(glc is null)
|
||||||
throw new Exception("glc");
|
throw new Exception("glc");
|
||||||
}
|
}
|
||||||
|
@ -4537,9 +4586,11 @@ version(X11) {
|
||||||
hints.sizeof / 4);
|
hints.sizeof / 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*k8: unused
|
||||||
void createOpenGlContext() {
|
void createOpenGlContext() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
void closeWindow() {
|
void closeWindow() {
|
||||||
if(buffer)
|
if(buffer)
|
||||||
|
@ -4609,6 +4660,7 @@ version(X11) {
|
||||||
{
|
{
|
||||||
// adding Xlib file
|
// adding Xlib file
|
||||||
ep.epoll_event ev = void;
|
ep.epoll_event ev = void;
|
||||||
|
{ import core.stdc.string : memset; memset(&ev, 0, ev.sizeof); } // this makes valgrind happy
|
||||||
ev.events = ep.EPOLLIN;
|
ev.events = ep.EPOLLIN;
|
||||||
ev.data.fd = display.fd;
|
ev.data.fd = display.fd;
|
||||||
//import std.conv;
|
//import std.conv;
|
||||||
|
@ -4632,6 +4684,7 @@ version(X11) {
|
||||||
throw new Exception("couldn't make pulse timer");
|
throw new Exception("couldn't make pulse timer");
|
||||||
|
|
||||||
ep.epoll_event ev = void;
|
ep.epoll_event ev = void;
|
||||||
|
{ import core.stdc.string : memset; memset(&ev, 0, ev.sizeof); } // this makes valgrind happy
|
||||||
ev.events = ep.EPOLLIN;
|
ev.events = ep.EPOLLIN;
|
||||||
ev.data.fd = pulseFd;
|
ev.data.fd = pulseFd;
|
||||||
ep.epoll_ctl(epollFd, ep.EPOLL_CTL_ADD, pulseFd, &ev);
|
ep.epoll_ctl(epollFd, ep.EPOLL_CTL_ADD, pulseFd, &ev);
|
||||||
|
@ -4646,6 +4699,7 @@ version(X11) {
|
||||||
throw new Exception("epoll wait failure");
|
throw new Exception("epoll wait failure");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//version(sdddd) { import std.stdio; writeln("nfds=", nfds, "; [0]=", events[0].data.fd); }
|
||||||
foreach(idx; 0 .. nfds) {
|
foreach(idx; 0 .. nfds) {
|
||||||
if(done) break;
|
if(done) break;
|
||||||
auto fd = events[idx].data.fd;
|
auto fd = events[idx].data.fd;
|
||||||
|
@ -4653,6 +4707,7 @@ version(X11) {
|
||||||
auto flags = events[idx].events;
|
auto flags = events[idx].events;
|
||||||
if(flags & ep.EPOLLIN) {
|
if(flags & ep.EPOLLIN) {
|
||||||
if(fd == display.fd) {
|
if(fd == display.fd) {
|
||||||
|
version(sdddd) { import std.stdio; writeln("X EVENT PENDING!"); }
|
||||||
while(!done && XPending(display))
|
while(!done && XPending(display))
|
||||||
done = doXNextEvent(this.display);
|
done = doXNextEvent(this.display);
|
||||||
} else if(fd == pulseFd) {
|
} else if(fd == pulseFd) {
|
||||||
|
@ -4665,6 +4720,7 @@ version(X11) {
|
||||||
handlePulse();
|
handlePulse();
|
||||||
} else {
|
} else {
|
||||||
// some other timer
|
// some other timer
|
||||||
|
version(sdddd) { import std.stdio; writeln("unknown fd: ", fd); }
|
||||||
|
|
||||||
if(Timer* t = fd in Timer.mapping)
|
if(Timer* t = fd in Timer.mapping)
|
||||||
(*t).trigger();
|
(*t).trigger();
|
||||||
|
@ -4720,6 +4776,7 @@ version(X11) {
|
||||||
bool done;
|
bool done;
|
||||||
XEvent e;
|
XEvent e;
|
||||||
XNextEvent(display, &e);
|
XNextEvent(display, &e);
|
||||||
|
version(sdddd) { import std.stdio, std.conv : to; writeln("event for: ", e.xany.window, "; type is ", to!string(cast(EventType)e.type)); }
|
||||||
|
|
||||||
version(with_eventloop)
|
version(with_eventloop)
|
||||||
import arsd.eventloop;
|
import arsd.eventloop;
|
||||||
|
@ -4788,6 +4845,7 @@ version(X11) {
|
||||||
case EventType.ConfigureNotify:
|
case EventType.ConfigureNotify:
|
||||||
auto event = e.xconfigure;
|
auto event = e.xconfigure;
|
||||||
if(auto win = event.window in SimpleWindow.nativeMapping) {
|
if(auto win = event.window in SimpleWindow.nativeMapping) {
|
||||||
|
//version(sdddd) { import std.stdio; writeln(" w=", event.width, "; h=", event.height); }
|
||||||
if(event.width != win.width || event.height != win.height) {
|
if(event.width != win.width || event.height != win.height) {
|
||||||
auto oldWidth = win.width;
|
auto oldWidth = win.width;
|
||||||
auto oldHeight = win.height;
|
auto oldHeight = win.height;
|
||||||
|
@ -4844,12 +4902,31 @@ version(X11) {
|
||||||
case EventType.ClientMessage:
|
case EventType.ClientMessage:
|
||||||
if(e.xclient.data.l[0] == GetAtom!"WM_DELETE_WINDOW"(e.xany.display)) {
|
if(e.xclient.data.l[0] == GetAtom!"WM_DELETE_WINDOW"(e.xany.display)) {
|
||||||
// user clicked the close button on the window manager
|
// user clicked the close button on the window manager
|
||||||
if(auto win = e.xclient.window in SimpleWindow.nativeMapping)
|
// FIXME: not implemented on Windows
|
||||||
(*win).close();
|
if(auto win = e.xclient.window in SimpleWindow.nativeMapping) {
|
||||||
|
if ((*win).closeQuery !is null) (*win).closeQuery(); else (*win).close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EventType.MapNotify:
|
||||||
|
if(auto win = e.xmap.window in SimpleWindow.nativeMapping) {
|
||||||
|
(*win)._visible = true;
|
||||||
|
if (!(*win)._visibleForTheFirstTimeCalled) {
|
||||||
|
(*win)._visibleForTheFirstTimeCalled = true;
|
||||||
|
if ((*win).visibleForTheFirstTime !is null) (*win).visibleForTheFirstTime();
|
||||||
|
}
|
||||||
|
if ((*win).visibilityChanged !is null) (*win).visibilityChanged(true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EventType.UnmapNotify:
|
||||||
|
if(auto win = e.xunmap.window in SimpleWindow.nativeMapping) {
|
||||||
|
(*win)._visible = false;
|
||||||
|
if ((*win).visibilityChanged !is null) (*win).visibilityChanged(false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EventType.DestroyNotify:
|
case EventType.DestroyNotify:
|
||||||
if(auto win = e.xdestroywindow.window in SimpleWindow.nativeMapping) {
|
if(auto win = e.xdestroywindow.window in SimpleWindow.nativeMapping) {
|
||||||
|
(*win)._closed = true; // just in case
|
||||||
(*win).destroyed = true;
|
(*win).destroyed = true;
|
||||||
SimpleWindow.nativeMapping.remove(e.xdestroywindow.window);
|
SimpleWindow.nativeMapping.remove(e.xdestroywindow.window);
|
||||||
if(SimpleWindow.nativeMapping.keys.length == 0)
|
if(SimpleWindow.nativeMapping.keys.length == 0)
|
||||||
|
@ -5351,6 +5428,94 @@ int XCloseDisplay(Display*);
|
||||||
|
|
||||||
Bool XQueryExtension(Display*, const char*, int*, int*, int*);
|
Bool XQueryExtension(Display*, const char*, int*, int*, int*);
|
||||||
|
|
||||||
|
// XIM and other crap
|
||||||
|
struct _XOM {}
|
||||||
|
struct _XIM {}
|
||||||
|
struct _XIC {}
|
||||||
|
alias XOM = _XOM*;
|
||||||
|
alias XIM = _XIM*;
|
||||||
|
alias XIC = _XIC*;
|
||||||
|
Bool XSupportsLocale();
|
||||||
|
char* XSetLocaleModifiers(const(char)* modifier_list);
|
||||||
|
XOM XOpenOM(Display* display, _XrmHashBucketRec* rdb, const(char)* res_name, const(char)* res_class);
|
||||||
|
Status XCloseOM(XOM om);
|
||||||
|
|
||||||
|
XIM XOpenIM(Display* dpy, _XrmHashBucketRec* rdb, const(char)* res_name, const(char)* res_class);
|
||||||
|
Status XCloseIM(XIM im);
|
||||||
|
|
||||||
|
char* XGetIMValues(XIM im, ...) /*_X_SENTINEL(0)*/;
|
||||||
|
char* XSetIMValues(XIM im, ...) /*_X_SENTINEL(0)*/;
|
||||||
|
Display* XDisplayOfIM(XIM im);
|
||||||
|
char* XLocaleOfIM(XIM im);
|
||||||
|
XIC XCreateIC(XIM im, ...) /*_X_SENTINEL(0)*/;
|
||||||
|
void XDestroyIC(XIC ic);
|
||||||
|
void XSetICFocus(XIC ic);
|
||||||
|
void XUnsetICFocus(XIC ic);
|
||||||
|
//wchar_t* XwcResetIC(XIC ic);
|
||||||
|
char* XmbResetIC(XIC ic);
|
||||||
|
char* Xutf8ResetIC(XIC ic);
|
||||||
|
char* XSetICValues(XIC ic, ...) /*_X_SENTINEL(0)*/;
|
||||||
|
char* XGetICValues(XIC ic, ...) /*_X_SENTINEL(0)*/;
|
||||||
|
XIM XIMOfIC(XIC ic);
|
||||||
|
|
||||||
|
alias XIMStyle = arch_ulong;
|
||||||
|
enum : arch_ulong {
|
||||||
|
XIMPreeditArea = 0x0001,
|
||||||
|
XIMPreeditCallbacks = 0x0002,
|
||||||
|
XIMPreeditPosition = 0x0004,
|
||||||
|
XIMPreeditNothing = 0x0008,
|
||||||
|
XIMPreeditNone = 0x0010,
|
||||||
|
XIMStatusArea = 0x0100,
|
||||||
|
XIMStatusCallbacks = 0x0200,
|
||||||
|
XIMStatusNothing = 0x0400,
|
||||||
|
XIMStatusNone = 0x0800,
|
||||||
|
}
|
||||||
|
|
||||||
|
immutable char* XNVaNestedList = "XNVaNestedList";
|
||||||
|
immutable char* XNQueryInputStyle = "queryInputStyle";
|
||||||
|
immutable char* XNClientWindow = "clientWindow";
|
||||||
|
immutable char* XNInputStyle = "inputStyle";
|
||||||
|
immutable char* XNFocusWindow = "focusWindow";
|
||||||
|
immutable char* XNResourceName = "resourceName";
|
||||||
|
immutable char* XNResourceClass = "resourceClass";
|
||||||
|
immutable char* XNGeometryCallback = "geometryCallback";
|
||||||
|
immutable char* XNDestroyCallback = "destroyCallback";
|
||||||
|
immutable char* XNFilterEvents = "filterEvents";
|
||||||
|
immutable char* XNPreeditStartCallback = "preeditStartCallback";
|
||||||
|
immutable char* XNPreeditDoneCallback = "preeditDoneCallback";
|
||||||
|
immutable char* XNPreeditDrawCallback = "preeditDrawCallback";
|
||||||
|
immutable char* XNPreeditCaretCallback = "preeditCaretCallback";
|
||||||
|
immutable char* XNPreeditStateNotifyCallback = "preeditStateNotifyCallback";
|
||||||
|
immutable char* XNPreeditAttributes = "preeditAttributes";
|
||||||
|
immutable char* XNStatusStartCallback = "statusStartCallback";
|
||||||
|
immutable char* XNStatusDoneCallback = "statusDoneCallback";
|
||||||
|
immutable char* XNStatusDrawCallback = "statusDrawCallback";
|
||||||
|
immutable char* XNStatusAttributes = "statusAttributes";
|
||||||
|
immutable char* XNArea = "area";
|
||||||
|
immutable char* XNAreaNeeded = "areaNeeded";
|
||||||
|
immutable char* XNSpotLocation = "spotLocation";
|
||||||
|
immutable char* XNColormap = "colorMap";
|
||||||
|
immutable char* XNStdColormap = "stdColorMap";
|
||||||
|
immutable char* XNForeground = "foreground";
|
||||||
|
immutable char* XNBackground = "background";
|
||||||
|
immutable char* XNBackgroundPixmap = "backgroundPixmap";
|
||||||
|
immutable char* XNFontSet = "fontSet";
|
||||||
|
immutable char* XNLineSpace = "lineSpace";
|
||||||
|
immutable char* XNCursor = "cursor";
|
||||||
|
|
||||||
|
immutable char* XNQueryIMValuesList = "queryIMValuesList";
|
||||||
|
immutable char* XNQueryICValuesList = "queryICValuesList";
|
||||||
|
immutable char* XNVisiblePosition = "visiblePosition";
|
||||||
|
immutable char* XNR6PreeditCallback = "r6PreeditCallback";
|
||||||
|
immutable char* XNStringConversionCallback = "stringConversionCallback";
|
||||||
|
immutable char* XNStringConversion = "stringConversion";
|
||||||
|
immutable char* XNResetState = "resetState";
|
||||||
|
immutable char* XNHotKey = "hotKey";
|
||||||
|
immutable char* XNHotKeyState = "hotKeyState";
|
||||||
|
immutable char* XNPreeditState = "preeditState";
|
||||||
|
immutable char* XNSeparatorofNestedList = "separatorofNestedList";
|
||||||
|
|
||||||
|
|
||||||
/* X Shared Memory Extension functions */
|
/* X Shared Memory Extension functions */
|
||||||
//pragma(lib, "Xshm");
|
//pragma(lib, "Xshm");
|
||||||
alias arch_ulong ShmSeg;
|
alias arch_ulong ShmSeg;
|
||||||
|
@ -5551,7 +5716,7 @@ enum ColorMapNotification:int
|
||||||
alias XID Pixmap;
|
alias XID Pixmap;
|
||||||
|
|
||||||
alias arch_ulong Atom;
|
alias arch_ulong Atom;
|
||||||
alias bool Bool;
|
alias int Bool;
|
||||||
alias Display XDisplay;
|
alias Display XDisplay;
|
||||||
|
|
||||||
alias int ByteOrder;
|
alias int ByteOrder;
|
||||||
|
@ -6767,6 +6932,12 @@ struct Visual
|
||||||
alias XErrorHandler = int function(Display*, XErrorEvent*);
|
alias XErrorHandler = int function(Display*, XErrorEvent*);
|
||||||
XErrorHandler XSetErrorHandler(XErrorHandler);
|
XErrorHandler XSetErrorHandler(XErrorHandler);
|
||||||
|
|
||||||
|
/* WARNING, this type not in Xlib spec */
|
||||||
|
extern(C) alias XIOErrorHandler = int function (Display* display);
|
||||||
|
XIOErrorHandler XSetIOErrorHandler (XIOErrorHandler handler);
|
||||||
|
|
||||||
|
Bool XkbSetDetectableAutoRepeat(Display* dpy, Bool detectable, Bool* supported);
|
||||||
|
|
||||||
int XCopyPlane(Display*, Drawable, Drawable, GC, int, int, uint, uint, int, int, arch_ulong);
|
int XCopyPlane(Display*, Drawable, Drawable, GC, int, int, uint, uint, int, int, arch_ulong);
|
||||||
|
|
||||||
Status XGetGeometry(Display*, Drawable, Window*, int*, int*, uint*, uint*, uint*, uint*);
|
Status XGetGeometry(Display*, Drawable, Window*, int*, int*, uint*, uint*, uint*, uint*);
|
||||||
|
@ -7631,6 +7802,27 @@ version(html5) {
|
||||||
|
|
||||||
version(without_opengl) {} else
|
version(without_opengl) {} else
|
||||||
extern(System){
|
extern(System){
|
||||||
|
version(X11) {
|
||||||
|
char* glXQueryExtensionsString (Display*, int);
|
||||||
|
void* glXGetProcAddress (const(char)*);
|
||||||
|
// GLX_EXT_swap_control
|
||||||
|
alias glXSwapIntervalEXT = void function (Display* dpy, /*GLXDrawable*/uint drawable, int interval);
|
||||||
|
private __gshared glXSwapIntervalEXT _glx_swapInterval_fn = null;
|
||||||
|
|
||||||
|
void glxSetVSync (Display* dpy, /*GLXDrawable*/uint drawable, bool wait) {
|
||||||
|
if (cast(void*)_glx_swapInterval_fn is cast(void*)1) return;
|
||||||
|
if (_glx_swapInterval_fn is null) {
|
||||||
|
_glx_swapInterval_fn = cast(glXSwapIntervalEXT)glXGetProcAddress("glXSwapIntervalEXT");
|
||||||
|
if (_glx_swapInterval_fn is null) {
|
||||||
|
_glx_swapInterval_fn = cast(glXSwapIntervalEXT)1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
version(sdddd) { import std.stdio; writeln("glXSwapIntervalEXT found!"); }
|
||||||
|
}
|
||||||
|
_glx_swapInterval_fn(dpy, drawable, (wait ? 1 : 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void glGetIntegerv(int, void*);
|
void glGetIntegerv(int, void*);
|
||||||
void glMatrixMode(int);
|
void glMatrixMode(int);
|
||||||
void glPushMatrix();
|
void glPushMatrix();
|
||||||
|
@ -7649,8 +7841,14 @@ extern(System){
|
||||||
void glVertex2f(float, float);
|
void glVertex2f(float, float);
|
||||||
void glVertex3f(float, float, float);
|
void glVertex3f(float, float, float);
|
||||||
void glEnd();
|
void glEnd();
|
||||||
void glColor3b(ubyte, ubyte, ubyte);
|
void glColor3b(byte, byte, byte);
|
||||||
|
void glColor3ub(ubyte, ubyte, ubyte);
|
||||||
|
void glColor4b(byte, byte, byte, byte);
|
||||||
|
void glColor4ub(ubyte, ubyte, ubyte, ubyte);
|
||||||
void glColor3i(int, int, int);
|
void glColor3i(int, int, int);
|
||||||
|
void glColor3ui(uint, uint, uint);
|
||||||
|
void glColor4i(int, int, int, int);
|
||||||
|
void glColor4ui(uint, uint, uint, uint);
|
||||||
void glColor3f(float, float, float);
|
void glColor3f(float, float, float);
|
||||||
void glColor4f(float, float, float, float);
|
void glColor4f(float, float, float, float);
|
||||||
void glTranslatef(float, float, float);
|
void glTranslatef(float, float, float);
|
||||||
|
@ -7675,7 +7873,15 @@ extern(System){
|
||||||
void glGenTextures(uint, uint*);
|
void glGenTextures(uint, uint*);
|
||||||
void glBindTexture(int, int);
|
void glBindTexture(int, int);
|
||||||
void glTexParameteri(uint, uint, int);
|
void glTexParameteri(uint, uint, int);
|
||||||
|
void glTexParameterf(uint/*GLenum*/ target, uint/*GLenum*/ pname, float param);
|
||||||
void glTexImage2D(int, int, int, int, int, int, int, int, in void*);
|
void glTexImage2D(int, int, int, int, int, int, int, int, in void*);
|
||||||
|
void glTexSubImage2D(uint/*GLenum*/ target, int level, int xoffset, int yoffset,
|
||||||
|
/*GLsizei*/int width, /*GLsizei*/int height,
|
||||||
|
uint/*GLenum*/ format, uint/*GLenum*/ type, in void* pixels);
|
||||||
|
void glTextureSubImage2D(uint texture, int level, int xoffset, int yoffset,
|
||||||
|
/*GLsizei*/int width, /*GLsizei*/int height,
|
||||||
|
uint/*GLenum*/ format, uint/*GLenum*/ type, in void* pixels);
|
||||||
|
void glTexEnvf(uint/*GLenum*/ target, uint/*GLenum*/ pname, float param);
|
||||||
|
|
||||||
|
|
||||||
void glTexCoord2f(float, float);
|
void glTexCoord2f(float, float);
|
||||||
|
@ -7689,6 +7895,8 @@ extern(System){
|
||||||
void glReadBuffer(uint);
|
void glReadBuffer(uint);
|
||||||
void glReadPixels(int, int, int, int, int, int, void*);
|
void glReadPixels(int, int, int, int, int, int, void*);
|
||||||
|
|
||||||
|
void glFlush();
|
||||||
|
void glFinish();
|
||||||
|
|
||||||
enum uint GL_FRONT = 0x0404;
|
enum uint GL_FRONT = 0x0404;
|
||||||
|
|
||||||
|
@ -7707,6 +7915,18 @@ extern(System){
|
||||||
enum uint GL_NEAREST = 0x2600;
|
enum uint GL_NEAREST = 0x2600;
|
||||||
enum uint GL_LINEAR = 0x2601;
|
enum uint GL_LINEAR = 0x2601;
|
||||||
enum uint GL_TEXTURE_MAG_FILTER = 0x2800;
|
enum uint GL_TEXTURE_MAG_FILTER = 0x2800;
|
||||||
|
enum uint GL_TEXTURE_WRAP_S = 0x2802;
|
||||||
|
enum uint GL_TEXTURE_WRAP_T = 0x2803;
|
||||||
|
enum uint GL_REPEAT = 0x2901;
|
||||||
|
enum uint GL_CLAMP = 0x2900;
|
||||||
|
enum uint GL_CLAMP_TO_EDGE = 0x812F;
|
||||||
|
enum uint GL_DECAL = 0x2101;
|
||||||
|
enum uint GL_MODULATE = 0x2100;
|
||||||
|
enum uint GL_TEXTURE_ENV = 0x2300;
|
||||||
|
enum uint GL_TEXTURE_ENV_MODE = 0x2200;
|
||||||
|
enum uint GL_REPLACE = 0x1E01;
|
||||||
|
enum uint GL_LIGHTING = 0x0B50;
|
||||||
|
enum uint GL_DITHER = 0x0BD0;
|
||||||
|
|
||||||
enum uint GL_NO_ERROR = 0;
|
enum uint GL_NO_ERROR = 0;
|
||||||
|
|
||||||
|
@ -7743,10 +7963,60 @@ version(linux) {
|
||||||
return; // already initialized, no need to do it again
|
return; // already initialized, no need to do it again
|
||||||
import ep = core.sys.linux.epoll;
|
import ep = core.sys.linux.epoll;
|
||||||
|
|
||||||
epollFd = ep.epoll_create1(0);
|
epollFd = ep.epoll_create1(ep.EPOLL_CLOEXEC);
|
||||||
if(epollFd == -1)
|
if(epollFd == -1)
|
||||||
throw new Exception("epoll create failure");
|
throw new Exception("epoll create failure");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
version(X11) {
|
||||||
|
__gshared bool sdx_isUTF8Locale;
|
||||||
|
version(linux) {
|
||||||
|
pragma(mangle, "strcasestr")
|
||||||
|
private extern(C) const(char)* strcasestr(const(char)* ns, const(char)* nd) nothrow @nogc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This whole crap is used to initialize X11 locale, so that you can use XIM methods later.
|
||||||
|
// Yes, there are people with non-utf locale (it's me, Ketmar!), but XIM (composing) will
|
||||||
|
// not work right if app/X11 locale is not utf. This sux. That's why all that "utf detection"
|
||||||
|
// anal magic is here. I (Ketmar) hope you like it.
|
||||||
|
shared static this () {
|
||||||
|
import core.stdc.locale;
|
||||||
|
|
||||||
|
setlocale(LC_ALL, "");
|
||||||
|
// check if out locale is UTF-8
|
||||||
|
auto lct = setlocale(LC_CTYPE, null);
|
||||||
|
if (lct is null) {
|
||||||
|
sdx_isUTF8Locale = false;
|
||||||
|
} else {
|
||||||
|
version(linux) {
|
||||||
|
sdx_isUTF8Locale = (strcasestr(lct, "utf-8") !is null) || (strcasestr(lct, "utf8") !is null);
|
||||||
|
} else {
|
||||||
|
for (size_t idx = 0; lct[idx] && lct[idx+1] && lct[idx+2]; ++idx) {
|
||||||
|
if ((lct[idx+0] == 'u' || lct[idx+0] == 'U') &&
|
||||||
|
(lct[idx+1] == 't' || lct[idx+1] == 'T') &&
|
||||||
|
(lct[idx+2] == 'f' || lct[idx+2] == 'F'))
|
||||||
|
{
|
||||||
|
sdx_isUTF8Locale = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
import core.stdc.stdlib : free;
|
||||||
|
import core.stdc.string : strdup;
|
||||||
|
auto olocale = strdup(setlocale(LC_ALL, null));
|
||||||
|
if (sdx_isUTF8Locale) {
|
||||||
|
if (!setlocale(LC_ALL, "")) assert(0, "simpledisplay: can't set locale");
|
||||||
|
} else {
|
||||||
|
if (!setlocale(LC_ALL, "en_US.UTF-8")) assert(0, "simpledisplay: can't set UTF locale");
|
||||||
|
}
|
||||||
|
// this will setup XIM, so we can use it later
|
||||||
|
if (XSupportsLocale()) XSetLocaleModifiers("@im=local");
|
||||||
|
setlocale(LC_ALL, olocale);
|
||||||
|
free(olocale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue