fix window closing and input events handling if there is modal window above - fix #251 under windows

This commit is contained in:
Vadim Lopatin 2016-05-18 12:33:48 +03:00
parent b728a32b80
commit 9d983dcf52
3 changed files with 51 additions and 2 deletions

View File

@ -166,7 +166,9 @@ class Window : CustomEventTarget {
protected uint _backgroundColor;
protected Widget _mainWidget;
protected EventList _eventList;
protected uint _flags;
@property uint flags() { return _flags; }
@property uint backgroundColor() const { return _backgroundColor; }
@property void backgroundColor(uint color) { _backgroundColor = color; }
@property int width() const { return _dx; }
@ -304,8 +306,15 @@ class Window : CustomEventTarget {
/// set handler for closing of window
@property Window onClose(void delegate() handler) { _onClose = handler; return this; }
/// returns true if there is some modal window opened above this window, and this window should not process mouse/key input and should not allow closing
bool hasModalWindowsAbove() {
return platform.hasModalWindowsAbove(this);
}
/// calls onCanClose handler if set to check if system may close window
bool handleCanClose() {
if (hasModalWindowsAbove())
return false;
if (!_onCanClose)
return true;
bool res = _onCanClose();
@ -446,7 +455,10 @@ class Window : CustomEventTarget {
static immutable int PERFORMANCE_LOGGING_THRESHOLD_MS = 20;
/// set when first draw is called: don't handle mouse/key input until draw (layout) is called
protected bool _firstDrawCalled = false;
void onDraw(DrawBuf buf) {
_firstDrawCalled = true;
static import std.datetime;
try {
bool needDraw = false;
@ -569,6 +581,8 @@ class Window : CustomEventTarget {
/// dispatch keyboard event
bool dispatchKeyEvent(KeyEvent event) {
if (hasModalWindowsAbove() || !_firstDrawCalled)
return false;
bool res = false;
hideTooltip();
PopupWidget modal = modalPopup();
@ -874,6 +888,8 @@ class Window : CustomEventTarget {
private int _lastMouseY;
/// dispatch mouse event to window content widgets
bool dispatchMouseEvent(MouseEvent event) {
if (hasModalWindowsAbove() || !_firstDrawCalled)
return false;
// ignore events if there is no root
if (_mainWidget is null)
return false;
@ -1308,6 +1324,13 @@ class Platform {
/// calls request layout for all windows
abstract void requestLayout();
/// returns true if there is some modal window opened above this window, and this window should not process mouse/key input and should not allow closing
bool hasModalWindowsAbove(Window w) {
// override in platform specific class
return false;
}
protected string _uiLanguage;
/// returns currently selected UI language code
@property string uiLanguage() {

View File

@ -137,7 +137,6 @@ class SDLWindow : Window {
}
}
protected uint _flags;
bool create(uint flags) {
if (!_dx)
_dx = 600;

View File

@ -237,7 +237,6 @@ class Win32Window : Window {
dstring _caption;
Win32ColorDrawBuf _drawbuf;
bool useOpengl;
uint _flags;
this(Win32Platform platform, dstring windowCaption, Window parent, uint flags, uint width = 0, uint height = 0) {
Win32Window w32parent = cast(Win32Window)parent;
HWND parenthwnd = w32parent ? w32parent._hwnd : null;
@ -833,11 +832,15 @@ class Win32Platform : Platform {
}
return cast(int)msg.wParam;
}
private Win32Window[ulong] _windowMap;
private Win32Window[] _windowList;
/// add window to window map
void onWindowCreated(HWND hwnd, Win32Window window) {
Log.v("created window, adding to map");
_windowMap[cast(ulong)hwnd] = window;
_windowList ~= window;
}
/// remove window from window map, returns true if there are some more windows left in map
bool onWindowDestroyed(HWND hwnd, Win32Window window) {
@ -848,6 +851,15 @@ class Win32Platform : Platform {
_windowsToDestroy ~= window;
//destroy(window);
}
for (uint i = 0; i < _windowList.length; i++) {
if (window is _windowList[i]) {
for (uint j = i; j + 1 < _windowList.length; j++)
_windowList[j] = _windowList[j + 1];
_windowList[$ - 1] = null;
_windowList.length--;
break;
}
}
return _windowMap.length > 0;
}
/// returns number of currently active windows
@ -878,6 +890,21 @@ class Win32Platform : Platform {
}
}
/// returns true if there is some modal window opened above this window, and this window should not process mouse/key input and should not allow closing
override bool hasModalWindowsAbove(Window w) {
// override in platform specific class
for (uint i = 0; i + 1 < _windowList.length; i++) {
if (_windowList[i] is w) {
for (uint j = i + 1; j < _windowList.length; j++) {
if (_windowList[j].flags & WindowFlag.Modal)
return true;
}
return false;
}
}
return false;
}
/// handle theme change: e.g. reload some themed resources
override void onThemeChanged() {
foreach(w; _windowMap)