fixed issue #13 - at least for win32 platform

This commit is contained in:
Vadim Lopatin 2014-12-10 11:15:54 +03:00
parent 4ee330fb7c
commit 0e3d0db945
3 changed files with 81 additions and 29 deletions

View File

@ -28,6 +28,10 @@ import dlangui.graphics.drawbuf;
private import dlangui.graphics.gldrawbuf; private import dlangui.graphics.gldrawbuf;
private import std.algorithm; private import std.algorithm;
// specify debug=DebugMouseEvents for logging mouse handling
// specify debug=DebugRedraw for logging drawing and layouts handling
// specify debug=DebugKeys for logging of key events
/// window creation flags /// window creation flags
enum WindowFlag : uint { enum WindowFlag : uint {
/// window can be resized /// window can be resized
@ -202,12 +206,14 @@ class Window {
long measureStart = currentTimeMillis; long measureStart = currentTimeMillis;
measure(); measure();
long measureEnd = currentTimeMillis; long measureEnd = currentTimeMillis;
if (measureEnd - measureStart > PERFORMANCE_LOGGING_THRESHOLD_MS) if (measureEnd - measureStart > PERFORMANCE_LOGGING_THRESHOLD_MS) {
Log.d("measure took ", measureEnd - measureStart, " ms"); debug(DebugRedraw) Log.d("measure took ", measureEnd - measureStart, " ms");
}
layout(); layout();
long layoutEnd = currentTimeMillis; long layoutEnd = currentTimeMillis;
if (layoutEnd - measureEnd > PERFORMANCE_LOGGING_THRESHOLD_MS) if (layoutEnd - measureEnd > PERFORMANCE_LOGGING_THRESHOLD_MS) {
Log.d("layout took ", layoutEnd - measureEnd, " ms"); debug(DebugRedraw) Log.d("layout took ", layoutEnd - measureEnd, " ms");
}
//checkUpdateNeeded(needDraw, needLayout, animationActive); //checkUpdateNeeded(needDraw, needLayout, animationActive);
} }
long drawStart = currentTimeMillis; long drawStart = currentTimeMillis;
@ -217,8 +223,10 @@ class Window {
foreach(p; _popups) foreach(p; _popups)
p.onDraw(buf); p.onDraw(buf);
long drawEnd = currentTimeMillis; long drawEnd = currentTimeMillis;
if (drawEnd - drawStart > PERFORMANCE_LOGGING_THRESHOLD_MS) debug(DebugRedraw) {
Log.d("draw took ", drawEnd - drawStart, " ms"); if (drawEnd - drawStart > PERFORMANCE_LOGGING_THRESHOLD_MS)
Log.d("draw took ", drawEnd - drawStart, " ms");
}
if (animationActive) if (animationActive)
scheduleAnimation(); scheduleAnimation();
} }
@ -254,7 +262,7 @@ class Window {
if (newFocus is null || isChild(newFocus)) { if (newFocus is null || isChild(newFocus)) {
if (newFocus !is null) { if (newFocus !is null) {
// when calling, setState(focused), window.focusedWidget is still previously focused widget // when calling, setState(focused), window.focusedWidget is still previously focused widget
Log.d("new focus: ", newFocus.id); debug(DebugFocus) Log.d("new focus: ", newFocus.id);
newFocus.setState(State.Focused); newFocus.setState(State.Focused);
} }
_focusedWidget = newFocus; _focusedWidget = newFocus;
@ -283,7 +291,7 @@ class Window {
if (event.action == KeyAction.KeyDown || event.action == KeyAction.KeyUp) { if (event.action == KeyAction.KeyDown || event.action == KeyAction.KeyUp) {
_keyboardModifiers = event.flags; _keyboardModifiers = event.flags;
if (event.keyCode == KeyCode.ALT || event.keyCode == KeyCode.LALT || event.keyCode == KeyCode.RALT) { if (event.keyCode == KeyCode.ALT || event.keyCode == KeyCode.LALT || event.keyCode == KeyCode.RALT) {
Log.d("ALT key: keyboardModifiers = ", _keyboardModifiers); debug(DebugKeys) Log.d("ALT key: keyboardModifiers = ", _keyboardModifiers);
if (_mainWidget) { if (_mainWidget) {
_mainWidget.invalidate(); _mainWidget.invalidate();
res = true; res = true;
@ -329,9 +337,9 @@ class Window {
} }
// if not processed by children, offer event to root // if not processed by children, offer event to root
if (sendAndCheckOverride(root, event)) { if (sendAndCheckOverride(root, event)) {
debug(mouse) Log.d("MouseEvent is processed"); debug(DebugMouseEvents) Log.d("MouseEvent is processed");
if (event.action == MouseAction.ButtonDown && _mouseCaptureWidget is null && !event.doNotTrackButtonDown) { if (event.action == MouseAction.ButtonDown && _mouseCaptureWidget is null && !event.doNotTrackButtonDown) {
debug(mouse) Log.d("Setting active widget"); debug(DebugMouseEvents) Log.d("Setting active widget");
setCaptureWidget(root, event); setCaptureWidget(root, event);
} else if (event.action == MouseAction.Move) { } else if (event.action == MouseAction.Move) {
addTracking(root); addTracking(root);
@ -393,11 +401,17 @@ class Window {
/// does current capture widget want to receive move events even if pointer left it /// does current capture widget want to receive move events even if pointer left it
protected bool _mouseCaptureFocusedOutTrackMovements; protected bool _mouseCaptureFocusedOutTrackMovements;
protected void clearMouseCapture() {
_mouseCaptureWidget = null;
_mouseCaptureFocusedOut = false;
_mouseCaptureFocusedOutTrackMovements = false;
_mouseCaptureButtons = 0;
}
protected bool dispatchCancel(MouseEvent event) { protected bool dispatchCancel(MouseEvent event) {
event.changeAction(MouseAction.Cancel); event.changeAction(MouseAction.Cancel);
bool res = _mouseCaptureWidget.onMouseEvent(event); bool res = _mouseCaptureWidget.onMouseEvent(event);
_mouseCaptureWidget = null; clearMouseCapture();
_mouseCaptureFocusedOut = false;
return res; return res;
} }
@ -411,6 +425,11 @@ class Window {
return res; return res;
} }
/// returns true if mouse is currently captured
bool isMouseCaptured() {
return (_mouseCaptureWidget !is null && isChild(_mouseCaptureWidget));
}
/// dispatch mouse event to window content widgets /// dispatch mouse event to window content widgets
bool dispatchMouseEvent(MouseEvent event) { bool dispatchMouseEvent(MouseEvent event) {
// ignore events if there is no root // ignore events if there is no root
@ -418,19 +437,23 @@ class Window {
return false; return false;
// check if _mouseCaptureWidget and _mouseTrackingWidget still exist in child of root widget // check if _mouseCaptureWidget and _mouseTrackingWidget still exist in child of root widget
if (_mouseCaptureWidget !is null && !isChild(_mouseCaptureWidget)) if (_mouseCaptureWidget !is null && !isChild(_mouseCaptureWidget)) {
_mouseCaptureWidget = null; clearMouseCapture();
}
//Log.d("dispatchMouseEvent ", event.action, " (", event.x, ",", event.y, ")"); debug(DebugMouseEvents) Log.d("dispatchMouseEvent ", event.action, " (", event.x, ",", event.y, ")");
bool res = false; bool res = false;
ushort currentButtons = event.flags & (MouseFlag.LButton|MouseFlag.RButton|MouseFlag.MButton); ushort currentButtons = event.flags & (MouseFlag.LButton|MouseFlag.RButton|MouseFlag.MButton);
if (_mouseCaptureWidget !is null) { if (_mouseCaptureWidget !is null) {
// try to forward message directly to active widget // try to forward message directly to active widget
if (event.action == MouseAction.Move) { if (event.action == MouseAction.Move) {
debug(DebugMouseEvents) Log.d("dispatchMouseEvent: Move; buttons state=", currentButtons);
if (!_mouseCaptureWidget.isPointInside(event.x, event.y)) { if (!_mouseCaptureWidget.isPointInside(event.x, event.y)) {
if (currentButtons != _mouseCaptureButtons) if (currentButtons != _mouseCaptureButtons) {
debug(DebugMouseEvents) Log.d("dispatchMouseEvent: Move; buttons state changed from ", _mouseCaptureButtons, " to ", currentButtons, " - cancelling capture");
return dispatchCancel(event); return dispatchCancel(event);
}
// point is no more inside of captured widget // point is no more inside of captured widget
if (!_mouseCaptureFocusedOut) { if (!_mouseCaptureFocusedOut) {
// sending FocusOut message // sending FocusOut message
@ -462,15 +485,25 @@ class Window {
_mouseCaptureFocusedOut = true; _mouseCaptureFocusedOut = true;
_mouseCaptureButtons = event.flags & (MouseFlag.LButton|MouseFlag.RButton|MouseFlag.MButton); _mouseCaptureButtons = event.flags & (MouseFlag.LButton|MouseFlag.RButton|MouseFlag.MButton);
return sendAndCheckOverride(_mouseCaptureWidget, event); return sendAndCheckOverride(_mouseCaptureWidget, event);
} else {
debug(DebugMouseEvents) Log.d("dispatchMouseEvent: mouseCaptureFocusedOut + Leave - cancelling capture");
return dispatchCancel(event);
} }
return true; return true;
} else if (event.action == MouseAction.ButtonDown || event.action == MouseAction.ButtonUp) {
if (!_mouseCaptureWidget.isPointInside(event.x, event.y)) {
if (currentButtons != _mouseCaptureButtons) {
debug(DebugMouseEvents) Log.d("dispatchMouseEvent: ButtonUp/ButtonDown; buttons state changed from ", _mouseCaptureButtons, " to ", currentButtons, " - cancelling capture");
return dispatchCancel(event);
}
}
} }
// other messages // other messages
res = sendAndCheckOverride(_mouseCaptureWidget, event); res = sendAndCheckOverride(_mouseCaptureWidget, event);
if (!currentButtons) { if (!currentButtons) {
// usable capturing - no more buttons pressed // usable capturing - no more buttons pressed
debug(mouse) Log.d("unsetting active widget"); debug(DebugMouseEvents) Log.d("unsetting active widget");
_mouseCaptureWidget = null; clearMouseCapture();
} }
return res; return res;
} }

View File

@ -23,6 +23,10 @@ version (USE_OPENGL) {
import dlangui.graphics.glsupport; import dlangui.graphics.glsupport;
} }
// specify debug=DebugMouseEvents for logging mouse handling
// specify debug=DebugRedraw for logging drawing and layouts handling
// specify debug=DebugKeys for logging of key events
pragma(lib, "gdi32.lib"); pragma(lib, "gdi32.lib");
pragma(lib, "user32.lib"); pragma(lib, "user32.lib");
@ -461,7 +465,7 @@ class Win32Window : Window {
private bool _mouseTracking; private bool _mouseTracking;
private bool onMouse(uint message, uint flags, short x, short y) { private bool onMouse(uint message, uint flags, short x, short y) {
//Log.d("Win32 Mouse Message ", message, " flags=", flags, " x=", x, " y=", y); debug(DebugMouseEvents) Log.d("Win32 Mouse Message ", message, " flags=", flags, " x=", x, " y=", y);
MouseButton button = MouseButton.None; MouseButton button = MouseButton.None;
MouseAction action = MouseAction.ButtonDown; MouseAction action = MouseAction.ButtonDown;
ButtonDetails * pbuttonDetails = null; ButtonDetails * pbuttonDetails = null;
@ -501,7 +505,7 @@ class Win32Window : Window {
pbuttonDetails = &_mbutton; pbuttonDetails = &_mbutton;
break; break;
case WM_MOUSELEAVE: case WM_MOUSELEAVE:
Log.d("WM_MOUSELEAVE"); debug(DebugMouseEvents) Log.d("WM_MOUSELEAVE");
action = MouseAction.Leave; action = MouseAction.Leave;
break; break;
case WM_MOUSEWHEEL: case WM_MOUSEWHEEL:
@ -525,15 +529,17 @@ class Win32Window : Window {
} else if (action == MouseAction.ButtonUp) { } else if (action == MouseAction.ButtonUp) {
pbuttonDetails.up(x, y, cast(ushort)flags); pbuttonDetails.up(x, y, cast(ushort)flags);
} }
if (((message == WM_MOUSELEAVE) || (x < 0 || y < 0 || x > _dx || y > _dy)) && _mouseTracking) { if (((message == WM_MOUSELEAVE) || (x < 0 || y < 0 || x >= _dx || y >= _dy)) && _mouseTracking) {
action = MouseAction.Leave; if (!isMouseCaptured() || (!_lbutton.isDown && !_rbutton.isDown && !_mbutton.isDown)) {
Log.d("WM_MOUSELEAVE - releasing capture"); action = MouseAction.Leave;
_mouseTracking = false; debug(DebugMouseEvents) Log.d("Win32Window.onMouse releasing capture");
ReleaseCapture(); _mouseTracking = false;
ReleaseCapture();
}
} }
if (message != WM_MOUSELEAVE && !_mouseTracking) { if (message != WM_MOUSELEAVE && !_mouseTracking) {
if (x >=0 && y >= 0 && x < _dx && y < _dy) { if (x >=0 && y >= 0 && x < _dx && y < _dy) {
Log.d("Setting capture"); debug(DebugMouseEvents) Log.d("Win32Window.onMouse Setting capture");
_mouseTracking = true; _mouseTracking = true;
SetCapture(_hwnd); SetCapture(_hwnd);
} }
@ -544,7 +550,7 @@ class Win32Window : Window {
event.mbutton = _mbutton; event.mbutton = _mbutton;
bool res = dispatchMouseEvent(event); bool res = dispatchMouseEvent(event);
if (res) { if (res) {
Log.d("Calling update() after mouse event"); //Log.v("Calling update() after mouse event");
update(); update();
} }
return res; return res;
@ -587,7 +593,7 @@ class Win32Window : Window {
res = dispatchKeyEvent(event); res = dispatchKeyEvent(event);
} }
if (res) { if (res) {
Log.d("Calling update() after key event"); debug(DebugRedraw) Log.d("Calling update() after key event");
update(); update();
} }
return res; return res;

View File

@ -475,10 +475,16 @@ class ScrollBar : AbstractSlider, OnClickHandler {
return true; return true;
} }
if (event.action == MouseAction.FocusOut && _dragging) { if (event.action == MouseAction.FocusOut && _dragging) {
Log.d("ScrollBar slider dragging - FocusOut");
return true;
}
if (event.action == MouseAction.FocusIn && _dragging) {
Log.d("ScrollBar slider dragging - FocusIn");
return true; return true;
} }
if (event.action == MouseAction.Move && _dragging) { if (event.action == MouseAction.Move && _dragging) {
int delta = _orientation == Orientation.Vertical ? event.y - _dragStart.y : event.x - _dragStart.x; int delta = _orientation == Orientation.Vertical ? event.y - _dragStart.y : event.x - _dragStart.x;
Log.d("ScrollBar slider dragging - Move delta=", delta);
Rect rc = _dragStartRect; Rect rc = _dragStartRect;
int offset; int offset;
int space; int space;
@ -529,11 +535,18 @@ class ScrollBar : AbstractSlider, OnClickHandler {
} }
return true; return true;
} }
if ((event.action == MouseAction.Leave || event.action == MouseAction.Cancel) && trackHover) { if (event.action == MouseAction.Leave && trackHover) {
Log.d("Leave ", id); Log.d("Leave ", id);
resetState(State.Hovered); resetState(State.Hovered);
return true; return true;
} }
if (event.action == MouseAction.Cancel && trackHover) {
Log.d("Cancel ? trackHover", id);
resetState(State.Hovered);
resetState(State.Pressed);
_dragging = false;
return true;
}
if (event.action == MouseAction.Cancel) { if (event.action == MouseAction.Cancel) {
Log.d("SliderButton.onMouseEvent event.action == MouseAction.Cancel"); Log.d("SliderButton.onMouseEvent event.action == MouseAction.Cancel");
resetState(State.Pressed); resetState(State.Pressed);