mirror of https://github.com/adamdruppe/arsd.git
popup windows with input grab, and myriad bug fixes
This commit is contained in:
parent
fe1014cb46
commit
42de573c1d
150
simpledisplay.d
150
simpledisplay.d
|
@ -1087,6 +1087,81 @@ class SimpleWindow : CapableOfHandlingNativeEvent {
|
||||||
_suppressDestruction = true; // so it doesn't try to close
|
_suppressDestruction = true; // so it doesn't try to close
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Experimental, do not use yet
|
||||||
|
/++
|
||||||
|
Grabs exclusive input from the user until you release it with
|
||||||
|
[releaseInputGrab].
|
||||||
|
|
||||||
|
|
||||||
|
Note: it is extremely rude to do this without good reason.
|
||||||
|
Reasons may include doing some kind of mouse drag operation
|
||||||
|
or popping up a temporary menu that should get events and will
|
||||||
|
be dismissed at ease by the user clicking away.
|
||||||
|
|
||||||
|
Params:
|
||||||
|
keyboard = do you want to grab keyboard input?
|
||||||
|
mouse = grab mouse input?
|
||||||
|
confine = confine the mouse cursor to inside this window?
|
||||||
|
+/
|
||||||
|
void grabInput(bool keyboard = true, bool mouse = true, bool confine = false) {
|
||||||
|
static if(UsingSimpledisplayX11) {
|
||||||
|
XSync(XDisplayConnection.get, 0);
|
||||||
|
if(keyboard)
|
||||||
|
XSetInputFocus(XDisplayConnection.get, this.impl.window, RevertToParent, CurrentTime);
|
||||||
|
if(mouse)
|
||||||
|
if(auto res = XGrabPointer(XDisplayConnection.get, this.impl.window, false /* owner_events */,
|
||||||
|
EventMask.PointerMotionMask // FIXME: not efficient
|
||||||
|
| EventMask.ButtonPressMask
|
||||||
|
| EventMask.ButtonReleaseMask
|
||||||
|
/* event mask */, GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine ? this.impl.window : None, None, CurrentTime)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
XSync(XDisplayConnection.get, 0);
|
||||||
|
import core.stdc.stdio;
|
||||||
|
printf("Grab input failed %d\n", res);
|
||||||
|
//throw new Exception("Grab input failed");
|
||||||
|
} else {
|
||||||
|
// cool
|
||||||
|
}
|
||||||
|
|
||||||
|
} else version(Windows) {
|
||||||
|
// FIXME: keyboard?
|
||||||
|
SetCapture(impl.hwnd);
|
||||||
|
if(confine) {
|
||||||
|
RECT rcClip;
|
||||||
|
//RECT rcOldClip;
|
||||||
|
//GetClipCursor(&rcOldClip);
|
||||||
|
GetWindowRect(hwnd, &rcClip);
|
||||||
|
ClipCursor(&rcClip);
|
||||||
|
}
|
||||||
|
} else static assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
Releases the grab acquired by [grabInput].
|
||||||
|
+/
|
||||||
|
void releaseInputGrab() {
|
||||||
|
static if(UsingSimpledisplayX11) {
|
||||||
|
XUngrabPointer(XDisplayConnection.get, CurrentTime);
|
||||||
|
} else version(Windows) {
|
||||||
|
ReleaseCapture();
|
||||||
|
ClipCursor(null);
|
||||||
|
} else static assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
Sets the input focus to this window.
|
||||||
|
|
||||||
|
You shouldn't call this very often - please let the user control the input focus.
|
||||||
|
+/
|
||||||
|
void focus() {
|
||||||
|
static if(UsingSimpledisplayX11) {
|
||||||
|
XSetInputFocus(XDisplayConnection.get, this.impl.window, RevertToParent, CurrentTime);
|
||||||
|
} else version(Windows) {
|
||||||
|
SetFocus(this.impl.hwnd);
|
||||||
|
} else static assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
/++
|
/++
|
||||||
Requests attention from the user for this window.
|
Requests attention from the user for this window.
|
||||||
|
|
||||||
|
@ -2563,6 +2638,14 @@ version(X11) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private extern(C) int adrlogger (Display* dpy, XErrorEvent* evt) nothrow @nogc {
|
||||||
|
import core.stdc.stdio;
|
||||||
|
char[265] buffer;
|
||||||
|
XGetErrorText(dpy, evt.error_code, buffer.ptr, cast(int) buffer.length);
|
||||||
|
printf("ERROR: %s\n", buffer.ptr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/++
|
/++
|
||||||
Global hotkey manager. It contains static methods to manage global hotkeys.
|
Global hotkey manager. It contains static methods to manage global hotkeys.
|
||||||
|
|
||||||
|
@ -3118,7 +3201,21 @@ struct MouseEvent {
|
||||||
RootWindow(XDisplayConnection.get, DefaultScreen(XDisplayConnection.get)),
|
RootWindow(XDisplayConnection.get, DefaultScreen(XDisplayConnection.get)),
|
||||||
x, y, &p.x, &p.y, &child);
|
x, y, &p.x, &p.y, &child);
|
||||||
return p;
|
return p;
|
||||||
} else {} // FIXME: windows impl
|
} else version(Windows) {
|
||||||
|
POINT[1] points;
|
||||||
|
points[0].x = x;
|
||||||
|
points[0].y = y;
|
||||||
|
MapWindowPoints(
|
||||||
|
window.impl.hwnd,
|
||||||
|
null,
|
||||||
|
points.ptr,
|
||||||
|
points.length
|
||||||
|
);
|
||||||
|
p.x = points[0].x;
|
||||||
|
p.y = points[0].y;
|
||||||
|
|
||||||
|
return p;
|
||||||
|
} else static assert(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4703,7 +4800,7 @@ version(Windows) {
|
||||||
// Mix this into the SimpleWindow class
|
// Mix this into the SimpleWindow class
|
||||||
mixin template NativeSimpleWindowImplementation() {
|
mixin template NativeSimpleWindowImplementation() {
|
||||||
int curHidden = 0; // counter
|
int curHidden = 0; // counter
|
||||||
bool[string] knownWinClasses;
|
static bool[string] knownWinClasses;
|
||||||
|
|
||||||
void hideCursor () {
|
void hideCursor () {
|
||||||
++curHidden;
|
++curHidden;
|
||||||
|
@ -4743,7 +4840,7 @@ version(Windows) {
|
||||||
RECT rect;
|
RECT rect;
|
||||||
GetWindowRect(hwnd, &rect);
|
GetWindowRect(hwnd, &rect);
|
||||||
// move it while maintaining the same size...
|
// move it while maintaining the same size...
|
||||||
MoveWindow(hwnd, x, y, rect.right - rect.left + x, rect.bottom - rect.top + y, true);
|
MoveWindow(hwnd, x, y, rect.right - rect.left, rect.bottom - rect.top, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void resize(int w, int h) {
|
void resize(int w, int h) {
|
||||||
|
@ -4814,7 +4911,7 @@ version(Windows) {
|
||||||
wc.hIconSm = null;
|
wc.hIconSm = null;
|
||||||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||||
if(!RegisterClassExW(&wc))
|
if(!RegisterClassExW(&wc))
|
||||||
throw new Exception("RegisterClass");
|
throw new Exception("RegisterClass " ~ to!string(GetLastError()));
|
||||||
knownWinClasses[cnamec] = true;
|
knownWinClasses[cnamec] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4833,7 +4930,7 @@ version(Windows) {
|
||||||
break;
|
break;
|
||||||
case WindowTypes.dropdownMenu:
|
case WindowTypes.dropdownMenu:
|
||||||
case WindowTypes.popupMenu:
|
case WindowTypes.popupMenu:
|
||||||
// FIXME
|
style = WS_POPUP | WS_SYSMENU | WS_BORDER;
|
||||||
}
|
}
|
||||||
|
|
||||||
hwnd = CreateWindow(cn.ptr, toWStringz(title), style,
|
hwnd = CreateWindow(cn.ptr, toWStringz(title), style,
|
||||||
|
@ -4896,7 +4993,7 @@ version(Windows) {
|
||||||
ghRC = wglCreateContextAttribsARB(ghDC, null, contextAttribs.ptr);
|
ghRC = wglCreateContextAttribsARB(ghDC, null, contextAttribs.ptr);
|
||||||
if (ghRC is null && sdpyOpenGLContextAllowFallback) {
|
if (ghRC is null && sdpyOpenGLContextAllowFallback) {
|
||||||
// activate fallback mode
|
// activate fallback mode
|
||||||
sdpyOpenGLContextVersion = 0;
|
// sdpyOpenGLContextVeto-type focus management policy leads to race conditions because the window becoming unviewable may coincide with the window manager deciding to move the focus elsrsion = 0;
|
||||||
ghRC = wglCreateContext(ghDC);
|
ghRC = wglCreateContext(ghDC);
|
||||||
}
|
}
|
||||||
if (ghRC is null)
|
if (ghRC is null)
|
||||||
|
@ -4958,8 +5055,7 @@ version(Windows) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns zero if it recognized the event
|
// returns zero if it recognized the event
|
||||||
static int triggerEvents(HWND hwnd, uint msg, WPARAM wParam, LPARAM lParam, int offsetX, int offsetY, SimpleWindow wind) nothrow {
|
static int triggerEvents(HWND hwnd, uint msg, WPARAM wParam, LPARAM lParam, int offsetX, int offsetY, SimpleWindow wind) {
|
||||||
try {
|
|
||||||
MouseEvent mouse;
|
MouseEvent mouse;
|
||||||
|
|
||||||
void mouseEvent() {
|
void mouseEvent() {
|
||||||
|
@ -5103,9 +5199,6 @@ version(Windows) {
|
||||||
default: return 1;
|
default: return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
} catch(Exception e) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HWND hwnd;
|
HWND hwnd;
|
||||||
|
@ -6260,6 +6353,25 @@ version(X11) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(opengl == OpenGlOptions.no) {
|
if(opengl == OpenGlOptions.no) {
|
||||||
|
|
||||||
|
bool overrideRedirect = false;
|
||||||
|
if(windowType == WindowTypes.dropdownMenu || windowType == WindowTypes.popupMenu)
|
||||||
|
overrideRedirect = true;
|
||||||
|
|
||||||
|
XSetWindowAttributes swa;
|
||||||
|
swa.background_pixel = WhitePixel(display, screen);
|
||||||
|
swa.border_pixel = BlackPixel(display, screen);
|
||||||
|
swa.override_redirect = overrideRedirect;
|
||||||
|
auto root = RootWindow(display, screen);
|
||||||
|
swa.colormap = XCreateColormap(display, root, DefaultVisual(display, screen), AllocNone);
|
||||||
|
|
||||||
|
window = XCreateWindow(display, parent is null ? root : parent.impl.window,
|
||||||
|
0, 0, width, height,
|
||||||
|
0, CopyFromParent, 1 /* InputOutput */, cast(Visual*) CopyFromParent, CWColormap | CWBackPixel | CWBorderPixel | CWOverrideRedirect, &swa);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
window = XCreateSimpleWindow(
|
window = XCreateSimpleWindow(
|
||||||
display,
|
display,
|
||||||
parent is null ? RootWindow(display, screen) : parent.impl.window,
|
parent is null ? RootWindow(display, screen) : parent.impl.window,
|
||||||
|
@ -6268,6 +6380,7 @@ version(X11) {
|
||||||
1, // border width
|
1, // border width
|
||||||
BlackPixel(display, screen), // border
|
BlackPixel(display, screen), // border
|
||||||
WhitePixel(display, screen)); // background
|
WhitePixel(display, screen)); // background
|
||||||
|
*/
|
||||||
|
|
||||||
buffer = XCreatePixmap(display, cast(Drawable) window, width, height, 24);
|
buffer = XCreatePixmap(display, cast(Drawable) window, width, height, 24);
|
||||||
|
|
||||||
|
@ -6327,8 +6440,8 @@ version(X11) {
|
||||||
setNetWMWindowType(GetAtom!"_NET_WM_WINDOW_TYPE_NORMAL"(display));
|
setNetWMWindowType(GetAtom!"_NET_WM_WINDOW_TYPE_NORMAL"(display));
|
||||||
break;
|
break;
|
||||||
case WindowTypes.undecorated:
|
case WindowTypes.undecorated:
|
||||||
setNetWMWindowType(GetAtom!"_NET_WM_WINDOW_TYPE_NORMAL"(display));
|
|
||||||
motifHideDecorations();
|
motifHideDecorations();
|
||||||
|
setNetWMWindowType(GetAtom!"_NET_WM_WINDOW_TYPE_NORMAL"(display));
|
||||||
break;
|
break;
|
||||||
case WindowTypes.hidden:
|
case WindowTypes.hidden:
|
||||||
_hidden = true;
|
_hidden = true;
|
||||||
|
@ -6337,13 +6450,13 @@ version(X11) {
|
||||||
//break;
|
//break;
|
||||||
|
|
||||||
case WindowTypes.dropdownMenu:
|
case WindowTypes.dropdownMenu:
|
||||||
setNetWMWindowType(GetAtom!"_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"(display));
|
|
||||||
motifHideDecorations();
|
motifHideDecorations();
|
||||||
|
setNetWMWindowType(GetAtom!"_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"(display));
|
||||||
customizationFlags |= WindowFlags.skipTaskbar | WindowFlags.alwaysOnTop;
|
customizationFlags |= WindowFlags.skipTaskbar | WindowFlags.alwaysOnTop;
|
||||||
break;
|
break;
|
||||||
case WindowTypes.popupMenu:
|
case WindowTypes.popupMenu:
|
||||||
setNetWMWindowType(GetAtom!"_NET_WM_WINDOW_TYPE_POPUP_MENU"(display));
|
|
||||||
motifHideDecorations();
|
motifHideDecorations();
|
||||||
|
setNetWMWindowType(GetAtom!"_NET_WM_WINDOW_TYPE_POPUP_MENU"(display));
|
||||||
customizationFlags |= WindowFlags.skipTaskbar | WindowFlags.alwaysOnTop;
|
customizationFlags |= WindowFlags.skipTaskbar | WindowFlags.alwaysOnTop;
|
||||||
break;
|
break;
|
||||||
/+
|
/+
|
||||||
|
@ -6436,7 +6549,7 @@ version(X11) {
|
||||||
XChangeProperty(
|
XChangeProperty(
|
||||||
display,
|
display,
|
||||||
impl.window,
|
impl.window,
|
||||||
GetAtom!"_NET_WM_PID"(display),
|
GetAtom!("_NET_WM_PID", true)(display),
|
||||||
XA_CARDINAL,
|
XA_CARDINAL,
|
||||||
32 /* bits */,
|
32 /* bits */,
|
||||||
0 /*PropModeReplace*/,
|
0 /*PropModeReplace*/,
|
||||||
|
@ -8706,12 +8819,19 @@ struct Visual
|
||||||
alias XErrorHandler = int function(Display*, XErrorEvent*);
|
alias XErrorHandler = int function(Display*, XErrorEvent*);
|
||||||
XErrorHandler XSetErrorHandler(XErrorHandler);
|
XErrorHandler XSetErrorHandler(XErrorHandler);
|
||||||
|
|
||||||
|
int XGetErrorText(Display*, int, char*, int);
|
||||||
|
|
||||||
/* WARNING, this type not in Xlib spec */
|
/* WARNING, this type not in Xlib spec */
|
||||||
extern(C) alias XIOErrorHandler = int function (Display* display);
|
extern(C) alias XIOErrorHandler = int function (Display* display);
|
||||||
XIOErrorHandler XSetIOErrorHandler (XIOErrorHandler handler);
|
XIOErrorHandler XSetIOErrorHandler (XIOErrorHandler handler);
|
||||||
|
|
||||||
Bool XkbSetDetectableAutoRepeat(Display* dpy, Bool detectable, Bool* supported);
|
Bool XkbSetDetectableAutoRepeat(Display* dpy, Bool detectable, Bool* supported);
|
||||||
|
|
||||||
|
|
||||||
|
int XGrabPointer(Display *display, Window grab_window, Bool owner_events, uint event_mask, int pointer_mode, int keyboard_mode, Window confine_to, Cursor cursor, Time time);
|
||||||
|
int XUngrabPointer(Display *display, Time time);
|
||||||
|
int XChangeActivePointerGrab(Display *display, uint event_mask, Cursor cursor, Time time);
|
||||||
|
|
||||||
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*);
|
||||||
|
|
Loading…
Reference in New Issue