From 14c99be69cfb5e0056d95050ec66b91afff78467 Mon Sep 17 00:00:00 2001 From: and3md Date: Sat, 29 Apr 2017 17:11:21 +0200 Subject: [PATCH] SDL: strongly improved modal behavior. Window state handled correctly. --- src/dlangui/platforms/sdl/sdlapp.d | 113 +++++++++++++++++++++-------- 1 file changed, 81 insertions(+), 32 deletions(-) diff --git a/src/dlangui/platforms/sdl/sdlapp.d b/src/dlangui/platforms/sdl/sdlapp.d index 9ad1d143..72fed45d 100644 --- a/src/dlangui/platforms/sdl/sdlapp.d +++ b/src/dlangui/platforms/sdl/sdlapp.d @@ -123,7 +123,7 @@ class SDLWindow : Window { } - bool hasModalChild() { + private bool hasModalChild() { foreach (SDLWindow w;_children) { if (w.flags & WindowFlag.Modal) return true; @@ -134,17 +134,21 @@ class SDLWindow : Window { return false; } - void restoreModalChilds() { + + private void restoreModalChilds() { foreach (SDLWindow w;_children) { if (w.flags & WindowFlag.Modal) { - w.show(); + if (w._windowState == WindowState.maximized) + w.activateWindow(); + else + w.restoreWindow(true); } w.restoreModalChilds(); } } - void minimizeModalChilds() { + private void minimizeModalChilds() { foreach (SDLWindow w;_children) { if (w.flags & WindowFlag.Modal) { @@ -156,12 +160,10 @@ class SDLWindow : Window { } - void restoreParentWindows() { + private void restoreParentWindows() { SDLWindow[] tempWin; if (!_platform) return; - _platform._parentWindowRestoration = true; - scope(exit) {_platform._parentWindowRestoration = false;} SDLWindow w = this; @@ -174,10 +176,28 @@ class SDLWindow : Window { w = w._parent; } - for (size_t i = tempWin.length ; i-- > 0 ; ) { - tempWin[i].show(); + for (size_t i = tempWin.length ; i-- > 0 ; ) + 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) @@ -319,7 +339,7 @@ class SDLWindow : Window { } override void show() { - Log.d("SDLWindow.show()"); + Log.d("SDLWindow.show() - ", windowCaption); if (_mainWidget && !(_flags & WindowFlag.Resizable)) { _mainWidget.measure(SIZE_UNSPECIFIED, SIZE_UNSPECIFIED); SDL_SetWindowSize(_win, _mainWidget.measuredWidth, _mainWidget.measuredHeight); @@ -347,27 +367,35 @@ class SDLWindow : Window { return false; bool res = false; + bool stateChanged = false; // change state switch(newState) { case WindowState.maximized: - if (_windowState != WindowState.maximized) + if (_windowState != WindowState.maximized) { SDL_MaximizeWindow(_win); + stateChanged = true; + } res = true; break; case WindowState.minimized: - if (_windowState != WindowState.minimized) + if (_windowState != WindowState.minimized) { SDL_MinimizeWindow(_win); + stateChanged = true; + } res = true; break; case WindowState.hidden: - if (_windowState != WindowState.hidden) + if (_windowState != WindowState.hidden) { SDL_HideWindow(_win); + stateChanged = true; + } res = true; break; case WindowState.normal: if (_windowState != WindowState.normal) { SDL_RestoreWindow(_win); + stateChanged = true; } res = true; break; @@ -375,18 +403,23 @@ class SDLWindow : Window { break; } // change size and/or position + + bool windowRectChanged = 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) { SDL_SetWindowPosition(_win, newWindowRect.left, newWindowRect.top); res = true; + windowRectChanged = true; } // change size if (newWindowRect.bottom != int.min && newWindowRect.right != int.min) { SDL_SetWindowSize(_win, newWindowRect.right, newWindowRect.bottom); res = true; + windowRectChanged = true; } } @@ -395,6 +428,8 @@ class SDLWindow : Window { res = true; } + handleWindowStateChange(stateChanged ? newState : WindowState.unspecified, windowRectChanged ? newWindowRect : RECT_VALUE_IS_NOT_SET); + return res; } @@ -1147,9 +1182,9 @@ class SDLPlatform : Platform { // foreach(w; _windowMap) // w.redraw(); //} - - private bool _parentWindowRestoration = false; + private bool _windowsMinimized = false; + override int enterMessageLoop() { Log.i("entering message loop"); SDL_Event event; @@ -1212,55 +1247,69 @@ class SDLPlatform : Platform { } break; case SDL_WINDOWEVENT_SHOWN: - debug(DebugSDL) Log.d("SDL_WINDOWEVENT_SHOWN"); - if (w.hasModalChild()) + debug(DebugSDL) Log.d("SDL_WINDOWEVENT_SHOWN - ", w.windowCaption); + if (!_windowsMinimized && w.hasModalChild()) w.restoreModalChilds(); break; case SDL_WINDOWEVENT_HIDDEN: - debug(DebugSDL) Log.d("SDL_WINDOWEVENT_HIDDEN"); + debug(DebugSDL) Log.d("SDL_WINDOWEVENT_HIDDEN - ", w.windowCaption); break; case SDL_WINDOWEVENT_EXPOSED: - debug(DebugSDL) Log.d("SDL_WINDOWEVENT_EXPOSED"); - if (w.hasModalChild()) + debug(DebugSDL) Log.d("SDL_WINDOWEVENT_EXPOSED - ", w.windowCaption); + if (!_windowsMinimized && w.hasModalChild()) w.restoreModalChilds(); version(linux) { w.invalidate(); } break; case SDL_WINDOWEVENT_MOVED: - debug(DebugSDL) Log.d("SDL_WINDOWEVENT_MOVED"); - if (w.hasModalChild()) + debug(DebugSDL) Log.d("SDL_WINDOWEVENT_MOVED- ", w.windowCaption); + if (!_windowsMinimized && w.hasModalChild()) w.restoreModalChilds(); break; case SDL_WINDOWEVENT_MINIMIZED: - debug(DebugSDL) Log.d("SDL_WINDOWEVENT_MINIMIZED"); - if (w.hasModalChild()) + debug(DebugSDL) Log.d("SDL_WINDOWEVENT_MINIMIZED - ", w.windowCaption); + w.handleWindowStateChange(WindowState.minimized); + + if (!_windowsMinimized && w.hasModalChild()) w.minimizeModalChilds(); + if (!_windowsMinimized && w.flags & WindowFlag.Modal) + w.minimizeParentWindows(); + + _windowsMinimized = true; break; 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; case SDL_WINDOWEVENT_RESTORED: - debug(DebugSDL) Log.d("SDL_WINDOWEVENT_RESTORED"); - if (!_parentWindowRestoration && w.flags & WindowFlag.Modal) + debug(DebugSDL) Log.d("SDL_WINDOWEVENT_RESTORED - ", w.windowCaption); + _windowsMinimized = false; + if (w.flags & WindowFlag.Modal) { w.restoreParentWindows(); - if (!_parentWindowRestoration && w.hasModalChild()) + w.restoreWindow(true); + } + w.handleWindowStateChange(WindowState.normal); + if (w.hasModalChild()) w.restoreModalChilds(); version(linux) { //not sure if needed on Windows or OSX. Also need to check on FreeBSD w.invalidate(); } break; case SDL_WINDOWEVENT_ENTER: - debug(DebugSDL) Log.d("SDL_WINDOWEVENT_ENTER"); + debug(DebugSDL) Log.d("SDL_WINDOWEVENT_ENTER - ", w.windowCaption); break; case SDL_WINDOWEVENT_LEAVE: - debug(DebugSDL) Log.d("SDL_WINDOWEVENT_LEAVE"); + debug(DebugSDL) Log.d("SDL_WINDOWEVENT_LEAVE - ", w.windowCaption); break; 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; case SDL_WINDOWEVENT_FOCUS_LOST: - debug(DebugSDL) Log.d("SDL_WINDOWEVENT_FOCUS_LOST"); + debug(DebugSDL) Log.d("SDL_WINDOWEVENT_FOCUS_LOST - ", w.windowCaption); break; default: break;