Full windowState support for X11.

This commit is contained in:
and3md 2017-08-04 21:33:05 +02:00
parent 1b6714b22b
commit 2cfbc27956
1 changed files with 107 additions and 8 deletions

View File

@ -266,7 +266,7 @@ class X11Window : DWindow {
swa.background_pixel = white; swa.background_pixel = white;
swa.event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | swa.event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
EnterWindowMask | LeaveWindowMask | PointerMotionMask | ButtonMotionMask | ExposureMask | VisibilityChangeMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | ButtonMotionMask | ExposureMask | VisibilityChangeMask |
FocusChangeMask | KeymapStateMask | StructureNotifyMask; FocusChangeMask | KeymapStateMask | StructureNotifyMask | PropertyChangeMask;
Visual * visual = DefaultVisual(x11display, x11screen); Visual * visual = DefaultVisual(x11display, x11screen);
int depth = DefaultDepth(x11display, x11screen); int depth = DefaultDepth(x11display, x11screen);
static if (ENABLE_OPENGL) { static if (ENABLE_OPENGL) {
@ -312,6 +312,7 @@ class X11Window : DWindow {
} }
windowCaption = caption; windowCaption = caption;
XSetWMProtocols(x11display, _win, &atom_WM_DELETE_WINDOW, 1); XSetWMProtocols(x11display, _win, &atom_WM_DELETE_WINDOW, 1);
_windowState = WindowState.hidden;
_children.reserve(20); _children.reserve(20);
_parent = cast(X11Window) parent; _parent = cast(X11Window) parent;
@ -370,6 +371,8 @@ class X11Window : DWindow {
/* clear the window and bring it on top of the other windows */ /* clear the window and bring it on top of the other windows */
//XClearWindow(x11display, _win); //XClearWindow(x11display, _win);
//XFlush(x11display); //XFlush(x11display);
handleWindowStateChange(WindowState.unspecified, Rect(0, 0, _dx, _dy));
} }
~this() { ~this() {
@ -432,9 +435,11 @@ class X11Window : DWindow {
_mainWidget.measure(SIZE_UNSPECIFIED, SIZE_UNSPECIFIED); _mainWidget.measure(SIZE_UNSPECIFIED, SIZE_UNSPECIFIED);
if (flags & WindowFlag.MeasureSize) if (flags & WindowFlag.MeasureSize)
resizeWindow(Point(_mainWidget.measuredWidth, _mainWidget.measuredHeight)); resizeWindow(Point(_mainWidget.measuredWidth, _mainWidget.measuredHeight));
_windowRect.right = _dx;// hack to set windowRect, remove when _windowRect will be full supported on X11 else
_windowRect.bottom = _dy; adjustWindowOrContentSize(_mainWidget.measuredWidth, _mainWidget.measuredHeight);
adjustWindowOrContentSize(_mainWidget.measuredWidth, _mainWidget.measuredHeight);
adjustPositionDuringShow();
_mainWidget.setFocus(); _mainWidget.setFocus();
} }
} }
@ -504,11 +509,51 @@ class X11Window : DWindow {
default: default:
break; break;
} }
// change size and/or position
bool rectChanged = false;
if (newWindowRect != RECT_VALUE_IS_NOT_SET && (newState == WindowState.normal || newState == WindowState.unspecified)) {
// change position
if (newWindowRect.top != int.min && newWindowRect.left != int.min) {
XMoveWindow(x11display, _win, newWindowRect.left, newWindowRect.top);
rectChanged = true;
result = true;
}
// change size
if (newWindowRect.bottom != int.min && newWindowRect.right != int.min) {
if (!(flags & WindowFlag.Resizable)) {
XSizeHints sizeHints;
sizeHints.min_width = newWindowRect.right;
sizeHints.min_height = newWindowRect.bottom;
sizeHints.max_width = newWindowRect.right;
sizeHints.max_height = newWindowRect.bottom;
sizeHints.flags = PMaxSize | PMinSize;
XSetWMNormalHints(x11display, _win, &sizeHints);
}
XResizeWindow(x11display, _win, newWindowRect.right, newWindowRect.bottom);
rectChanged = true;
result = true;
}
}
if (activate) { if (activate) {
XMapRaised(x11display, _win); XMapRaised(x11display, _win);
result = true; result = true;
} }
XFlush(x11display); XFlush(x11display);
//needed here to make _windowRect and _windowState valid
//example: change size by resizeWindow() and make some calculations using windowRect
if (rectChanged) {
handleWindowStateChange(newState, Rect(newWindowRect.left == int.min ? _windowRect.left : newWindowRect.left,
newWindowRect.top == int.min ? _windowRect.top : newWindowRect.top, newWindowRect.right == int.min ? _windowRect.right : newWindowRect.right,
newWindowRect.bottom == int.min ? _windowRect.bottom : newWindowRect.bottom));
}
else
handleWindowStateChange(newState, RECT_VALUE_IS_NOT_SET);
return result; return result;
} }
@ -573,6 +618,10 @@ class X11Window : DWindow {
_platform.closeWindow(this); _platform.closeWindow(this);
} }
override protected void handleWindowStateChange(WindowState newState, Rect newWindowRect = RECT_VALUE_IS_NOT_SET) {
super.handleWindowStateChange(newState, newWindowRect);
}
ColorDrawBuf _drawbuf; ColorDrawBuf _drawbuf;
protected void drawUsingBitmap() { protected void drawUsingBitmap() {
if (_dx > 0 && _dy > 0) { if (_dx > 0 && _dy > 0) {
@ -1073,7 +1122,7 @@ class X11Window : DWindow {
ev.xclient.window = _win; ev.xclient.window = _win;
ev.xclient.display = x11display2; ev.xclient.display = x11display2;
ev.xclient.format = 32; ev.xclient.format = 32;
Log.d("Sending timer event"); //Log.d("Sending timer event");
XLockDisplay(x11display2); XLockDisplay(x11display2);
XSendEvent(x11display2, _win, false, StructureNotifyMask, &ev); XSendEvent(x11display2, _win, false, StructureNotifyMask, &ev);
XFlush(x11display2); XFlush(x11display2);
@ -1264,10 +1313,62 @@ class X11Platform : Platform {
if (w) { if (w) {
w._cachedWidth = event.xconfigure.width; w._cachedWidth = event.xconfigure.width;
w._cachedHeight = event.xconfigure.height; w._cachedHeight = event.xconfigure.height;
w.handleWindowStateChange(WindowState.unspecified, Rect(event.xconfigure.x, event.xconfigure.y, event.xconfigure.width, event.xconfigure.height));
} else { } else {
Log.e("ConfigureNotify: Window not found"); Log.e("ConfigureNotify: Window not found");
} }
break; break;
case PropertyNotify:
if (event.xproperty.atom == atom_NET_WM_STATE && event.xproperty.state == PropertyNewValue) {
X11Window w = findWindow(event.xproperty.window);
if (w) {
Atom type;
int format;
ubyte* properties;
c_ulong dataLength, overflow;
if (XGetWindowProperty(x11display, event.xproperty.window, atom_NET_WM_STATE,
0, int.max/4, False, AnyPropertyType, &type, &format, &dataLength, &overflow, &properties) == 0) {
scope(exit) XFree(properties);
// check for minimized
bool minimized = false;
for (int i=0; i < dataLength ; i++) {
if (((cast(c_ulong*)properties)[i]) == atom_NET_WM_STATE_HIDDEN) {
w.handleWindowStateChange(WindowState.minimized);
minimized = true;
}
}
if (!minimized) {
bool maximizedH = false;
bool maximizedV = false;
for (int i=0; i < dataLength ; i++) {
if (((cast(c_ulong*)properties)[i]) == atom_NET_WM_STATE_MAXIMIZED_VERT)
maximizedV = true;
if (((cast(c_ulong*)properties)[i]) == atom_NET_WM_STATE_MAXIMIZED_HORZ)
maximizedH = true;
}
if (maximizedV && maximizedH)
w.handleWindowStateChange(WindowState.maximized);
else
w.handleWindowStateChange(WindowState.normal);
}
}
}
}
break;
case MapNotify:
X11Window w = findWindow(event.xmap.window);
if (w) {
w.handleWindowStateChange(WindowState.normal);
}
break;
case UnmapNotify:
X11Window w = findWindow(event.xunmap.window);
if (w) {
w.handleWindowStateChange(WindowState.hidden);
}
break;
case Expose: case Expose:
if (event.xexpose.count == 0) { if (event.xexpose.count == 0) {
X11Window w = findWindow(event.xexpose.window); X11Window w = findWindow(event.xexpose.window);
@ -1372,9 +1473,7 @@ 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.FocusIn, 0, event.xcrossing.state, event.xcrossing.x, event.xcrossing.y);
} else {
Log.e("Window not found"); Log.e("Window not found");
} }
break; break;