SDL: strongly improved modal behavior. Window state handled correctly.

This commit is contained in:
and3md 2017-04-29 17:11:21 +02:00
parent 076b2a44e7
commit 14c99be69c
1 changed files with 81 additions and 32 deletions

View File

@ -123,7 +123,7 @@ class SDLWindow : Window {
} }
bool hasModalChild() { private bool hasModalChild() {
foreach (SDLWindow w;_children) { foreach (SDLWindow w;_children) {
if (w.flags & WindowFlag.Modal) if (w.flags & WindowFlag.Modal)
return true; return true;
@ -134,17 +134,21 @@ class SDLWindow : Window {
return false; return false;
} }
void restoreModalChilds() {
private void restoreModalChilds() {
foreach (SDLWindow w;_children) { foreach (SDLWindow w;_children) {
if (w.flags & WindowFlag.Modal) { if (w.flags & WindowFlag.Modal) {
w.show(); if (w._windowState == WindowState.maximized)
w.activateWindow();
else
w.restoreWindow(true);
} }
w.restoreModalChilds(); w.restoreModalChilds();
} }
} }
void minimizeModalChilds() { private void minimizeModalChilds() {
foreach (SDLWindow w;_children) { foreach (SDLWindow w;_children) {
if (w.flags & WindowFlag.Modal) if (w.flags & WindowFlag.Modal)
{ {
@ -156,12 +160,10 @@ class SDLWindow : Window {
} }
void restoreParentWindows() { private void restoreParentWindows() {
SDLWindow[] tempWin; SDLWindow[] tempWin;
if (!_platform) if (!_platform)
return; return;
_platform._parentWindowRestoration = true;
scope(exit) {_platform._parentWindowRestoration = false;}
SDLWindow w = this; SDLWindow w = this;
@ -174,10 +176,28 @@ class SDLWindow : Window {
w = w._parent; w = w._parent;
} }
for (size_t i = tempWin.length ; i-- > 0 ; ) { for (size_t i = tempWin.length ; i-- > 0 ; )
tempWin[i].show(); tempWin[i].restoreWindow(true);
}
private void minimizeParentWindows() {
SDLWindow[] tempWin;
if (!_platform)
return;
SDLWindow w = this;
while (true) {
if (w is null)
break;
tempWin~=w;
w = w._parent;
} }
for (size_t i = tempWin.length ; i-- > 0 ; )
tempWin[i].minimizeWindow();
} }
/// post event to handle in UI thread (this method can be used from background thread) /// post event to handle in UI thread (this method can be used from background thread)
@ -319,7 +339,7 @@ class SDLWindow : Window {
} }
override void show() { override void show() {
Log.d("SDLWindow.show()"); Log.d("SDLWindow.show() - ", windowCaption);
if (_mainWidget && !(_flags & WindowFlag.Resizable)) { if (_mainWidget && !(_flags & WindowFlag.Resizable)) {
_mainWidget.measure(SIZE_UNSPECIFIED, SIZE_UNSPECIFIED); _mainWidget.measure(SIZE_UNSPECIFIED, SIZE_UNSPECIFIED);
SDL_SetWindowSize(_win, _mainWidget.measuredWidth, _mainWidget.measuredHeight); SDL_SetWindowSize(_win, _mainWidget.measuredWidth, _mainWidget.measuredHeight);
@ -347,27 +367,35 @@ class SDLWindow : Window {
return false; return false;
bool res = false; bool res = false;
bool stateChanged = false;
// change state // change state
switch(newState) { switch(newState) {
case WindowState.maximized: case WindowState.maximized:
if (_windowState != WindowState.maximized) if (_windowState != WindowState.maximized) {
SDL_MaximizeWindow(_win); SDL_MaximizeWindow(_win);
stateChanged = true;
}
res = true; res = true;
break; break;
case WindowState.minimized: case WindowState.minimized:
if (_windowState != WindowState.minimized) if (_windowState != WindowState.minimized) {
SDL_MinimizeWindow(_win); SDL_MinimizeWindow(_win);
stateChanged = true;
}
res = true; res = true;
break; break;
case WindowState.hidden: case WindowState.hidden:
if (_windowState != WindowState.hidden) if (_windowState != WindowState.hidden) {
SDL_HideWindow(_win); SDL_HideWindow(_win);
stateChanged = true;
}
res = true; res = true;
break; break;
case WindowState.normal: case WindowState.normal:
if (_windowState != WindowState.normal) { if (_windowState != WindowState.normal) {
SDL_RestoreWindow(_win); SDL_RestoreWindow(_win);
stateChanged = true;
} }
res = true; res = true;
break; break;
@ -375,18 +403,23 @@ class SDLWindow : Window {
break; break;
} }
// change size and/or position // change size and/or position
bool windowRectChanged = false;
if (newWindowRect != RECT_VALUE_IS_NOT_SET && (newState == WindowState.normal || newState == WindowState.unspecified)) { if (newWindowRect != RECT_VALUE_IS_NOT_SET && (newState == WindowState.normal || newState == WindowState.unspecified)) {
// change position // change position
if (newWindowRect.top != int.min && newWindowRect.left != int.min) { if (newWindowRect.top != int.min && newWindowRect.left != int.min) {
SDL_SetWindowPosition(_win, newWindowRect.left, newWindowRect.top); SDL_SetWindowPosition(_win, newWindowRect.left, newWindowRect.top);
res = true; res = true;
windowRectChanged = true;
} }
// change size // change size
if (newWindowRect.bottom != int.min && newWindowRect.right != int.min) { if (newWindowRect.bottom != int.min && newWindowRect.right != int.min) {
SDL_SetWindowSize(_win, newWindowRect.right, newWindowRect.bottom); SDL_SetWindowSize(_win, newWindowRect.right, newWindowRect.bottom);
res = true; res = true;
windowRectChanged = true;
} }
} }
@ -395,6 +428,8 @@ class SDLWindow : Window {
res = true; res = true;
} }
handleWindowStateChange(stateChanged ? newState : WindowState.unspecified, windowRectChanged ? newWindowRect : RECT_VALUE_IS_NOT_SET);
return res; return res;
} }
@ -1147,9 +1182,9 @@ class SDLPlatform : Platform {
// foreach(w; _windowMap) // foreach(w; _windowMap)
// w.redraw(); // w.redraw();
//} //}
private bool _parentWindowRestoration = false;
private bool _windowsMinimized = false;
override int enterMessageLoop() { override int enterMessageLoop() {
Log.i("entering message loop"); Log.i("entering message loop");
SDL_Event event; SDL_Event event;
@ -1212,55 +1247,69 @@ class SDLPlatform : Platform {
} }
break; break;
case SDL_WINDOWEVENT_SHOWN: case SDL_WINDOWEVENT_SHOWN:
debug(DebugSDL) Log.d("SDL_WINDOWEVENT_SHOWN"); debug(DebugSDL) Log.d("SDL_WINDOWEVENT_SHOWN - ", w.windowCaption);
if (w.hasModalChild()) if (!_windowsMinimized && w.hasModalChild())
w.restoreModalChilds(); w.restoreModalChilds();
break; break;
case SDL_WINDOWEVENT_HIDDEN: case SDL_WINDOWEVENT_HIDDEN:
debug(DebugSDL) Log.d("SDL_WINDOWEVENT_HIDDEN"); debug(DebugSDL) Log.d("SDL_WINDOWEVENT_HIDDEN - ", w.windowCaption);
break; break;
case SDL_WINDOWEVENT_EXPOSED: case SDL_WINDOWEVENT_EXPOSED:
debug(DebugSDL) Log.d("SDL_WINDOWEVENT_EXPOSED"); debug(DebugSDL) Log.d("SDL_WINDOWEVENT_EXPOSED - ", w.windowCaption);
if (w.hasModalChild()) if (!_windowsMinimized && w.hasModalChild())
w.restoreModalChilds(); w.restoreModalChilds();
version(linux) { version(linux) {
w.invalidate(); w.invalidate();
} }
break; break;
case SDL_WINDOWEVENT_MOVED: case SDL_WINDOWEVENT_MOVED:
debug(DebugSDL) Log.d("SDL_WINDOWEVENT_MOVED"); debug(DebugSDL) Log.d("SDL_WINDOWEVENT_MOVED- ", w.windowCaption);
if (w.hasModalChild()) if (!_windowsMinimized && w.hasModalChild())
w.restoreModalChilds(); w.restoreModalChilds();
break; break;
case SDL_WINDOWEVENT_MINIMIZED: case SDL_WINDOWEVENT_MINIMIZED:
debug(DebugSDL) Log.d("SDL_WINDOWEVENT_MINIMIZED"); debug(DebugSDL) Log.d("SDL_WINDOWEVENT_MINIMIZED - ", w.windowCaption);
if (w.hasModalChild()) w.handleWindowStateChange(WindowState.minimized);
if (!_windowsMinimized && w.hasModalChild())
w.minimizeModalChilds(); w.minimizeModalChilds();
if (!_windowsMinimized && w.flags & WindowFlag.Modal)
w.minimizeParentWindows();
_windowsMinimized = true;
break; break;
case SDL_WINDOWEVENT_MAXIMIZED: case SDL_WINDOWEVENT_MAXIMIZED:
debug(DebugSDL) Log.d("SDL_WINDOWEVENT_MAXIMIZED"); debug(DebugSDL) Log.d("SDL_WINDOWEVENT_MAXIMIZED - ", w.windowCaption);
w.handleWindowStateChange(WindowState.maximized);
_windowsMinimized = false;
break; break;
case SDL_WINDOWEVENT_RESTORED: case SDL_WINDOWEVENT_RESTORED:
debug(DebugSDL) Log.d("SDL_WINDOWEVENT_RESTORED"); debug(DebugSDL) Log.d("SDL_WINDOWEVENT_RESTORED - ", w.windowCaption);
if (!_parentWindowRestoration && w.flags & WindowFlag.Modal) _windowsMinimized = false;
if (w.flags & WindowFlag.Modal) {
w.restoreParentWindows(); w.restoreParentWindows();
if (!_parentWindowRestoration && w.hasModalChild()) w.restoreWindow(true);
}
w.handleWindowStateChange(WindowState.normal);
if (w.hasModalChild())
w.restoreModalChilds(); w.restoreModalChilds();
version(linux) { //not sure if needed on Windows or OSX. Also need to check on FreeBSD version(linux) { //not sure if needed on Windows or OSX. Also need to check on FreeBSD
w.invalidate(); w.invalidate();
} }
break; break;
case SDL_WINDOWEVENT_ENTER: case SDL_WINDOWEVENT_ENTER:
debug(DebugSDL) Log.d("SDL_WINDOWEVENT_ENTER"); debug(DebugSDL) Log.d("SDL_WINDOWEVENT_ENTER - ", w.windowCaption);
break; break;
case SDL_WINDOWEVENT_LEAVE: case SDL_WINDOWEVENT_LEAVE:
debug(DebugSDL) Log.d("SDL_WINDOWEVENT_LEAVE"); debug(DebugSDL) Log.d("SDL_WINDOWEVENT_LEAVE - ", w.windowCaption);
break; break;
case SDL_WINDOWEVENT_FOCUS_GAINED: case SDL_WINDOWEVENT_FOCUS_GAINED:
debug(DebugSDL) Log.d("SDL_WINDOWEVENT_FOCUS_GAINED"); debug(DebugSDL) Log.d("SDL_WINDOWEVENT_FOCUS_GAINED - ", w.windowCaption);
if (!_windowsMinimized)
w.restoreModalChilds();
break; break;
case SDL_WINDOWEVENT_FOCUS_LOST: case SDL_WINDOWEVENT_FOCUS_LOST:
debug(DebugSDL) Log.d("SDL_WINDOWEVENT_FOCUS_LOST"); debug(DebugSDL) Log.d("SDL_WINDOWEVENT_FOCUS_LOST - ", w.windowCaption);
break; break;
default: default:
break; break;