Conversation
| w->update(); | ||
| w->applyLayout(); | ||
| } | ||
| SystemApi::dispatchMouseReevaluate(*implTrieRoot(this)); |
There was a problem hiding this comment.
Calling to reevaluate whole tree, inside Widget::setGeometry just like so, can be huge performance issue - better not touch for now.
| } | ||
|
|
||
| void EventDispatcher::implSetMouseOver(const std::shared_ptr<Widget::Ref> &wptr,MouseEvent& orig) { | ||
| void EventDispatcher::implSetMouseOver(const std::shared_ptr<Widget::Ref> &wptr,MouseEvent& orig,bool force) { |
| break; | ||
| } | ||
| case EnterNotify: { | ||
| SystemApi::dispatchMouseReevaluate(cb,Point(xev.xcrossing.x,xev.xcrossing.y)); |
There was a problem hiding this comment.
I think it's good call to monitor EnterWindowMask, but then it suppose to be something like SystemAPI::dispatchMouseEnter/SystemAPI::dispatchMouseLeave
| if(astate.disable>0) | ||
| implDisableSum(w,astate.disable); | ||
| lay->applyLayout(); | ||
| SystemApi::dispatchMouseReevaluate(*implTrieRoot(this)); |
There was a problem hiding this comment.
same problem as in setGeometry: construction of complex UI will hammer such reevaluation
| dispatchMouseReevaluate(wnd,mousePosition); | ||
| } | ||
|
|
||
| void EventDispatcher::dispatchMouseReevaluate(Widget& wnd, Point pos) { |
There was a problem hiding this comment.
so far it look like hallucinated move-event... lets focus on EnterNotify first.
|
Just an observation: |
|
Fix X11 cursor visibility when entering a window with an already-idle pointer. On X11,
Thank you for the feedback, I have tried to do it in a less performance expensive way and follow your suggestion where (and if) I understood it. The mouse reevaluation mechanism from widget creation, geometry, and visibility changes from earlier where therefore removed again. So it avoids repeatedly reevaluating the complete widget tree.
I honestly do not know how to do it better, please suggest a good way if force is not an option.
I tried to follow the suggestion by adding
I think with your comment now it does make sense to keep the fix locally on the X11 event path, which I tried in this attempt. |
659f8e1 to
270e884
Compare
If I've understood you right, this is a system-side bug, isn't it? Basically you have the |
| break; | ||
| } | ||
| case EnterNotify: { | ||
| SystemApi::dispatchMouseEnter(cb,Point(xev.xcrossing.x,xev.xcrossing.y)); |
There was a problem hiding this comment.
There is not a literal one-to-one X11 message called WM_ACTIVATE. The X11 focus events that come close would be:
FocusIn = WM_ACTIVATE(WA_ACTIVE)
FocusOut =WM_ACTIVATE(WA_INACTIVE)
By contrast, EnterNotify / LeaveNotify are pointer events, not focus events.
So I agree with you, same as WM_ACTIVATE means it would probably be better to change it to FocusIn, not EnterNotify. I could test that soon and report back.
Sort of, poking fixes the problem. X11 behaves according to the documentation, I would probably not call it a system-side bug - but it is definitely a behaviour Windows does not have. Tempest does not currently reapply the logical cursor state when activation changes while |
|
Current attempt: keep
unrelated, consistency nitpick: |
|
Cross checking withwindows: Here one thing windows-build is bit buggy, as it "restores" cursor, only according to one relevant to the window, not to whole UI tree. This can be fixed by storing resolved cursor at
If we have store of cursor state at Probably no need in dedicated
You don't have to, but consistency is nice :) |
|
Cursor state is now restored from the stored resolved cursor state rather than by forcing a new hover calculation.
test limitation: tested on Linux. Cannot test on Windows currently, please help with verification. |
| ~Window() override; | ||
|
|
||
| void setWindowTitle(const char* utf8); | ||
| CursorShape implResolvedCursor() const { return resolvedCursor; } |
| } | ||
| focusLast.reset(); | ||
|
|
||
| if(auto w = mouseOver.lock()) { |
There was a problem hiding this comment.
Why this code needed?
In windows you calling one-line:
SetCursor(cb->implResolvedCursor());
OK
On X11 you not doing it, but instead:
case EnterNotify: {
...
SystemApi::dispatchMouseMove(cb,e);
break;
}
Why not using same approach on both systems?
case WM_ACTIVATE / EnterNotify: {
...
SystemApi::dispatchMouseMove(cb,e);
SetCursor(cb->implResolvedCursor());
break;
}
And why all of this code in EventDispatcher::dispatchFocus ? What use-case it covers?
Drop the cursor block from EventDispatcher::dispatchFocus - it was a second writer of cursor state next to implExcMouseOver, and it handled pointer state inside a keyboard-focus path. Both backends now do the same two steps at their activation event: dispatch a mouse move to recompute mouseOver, then re-apply the resolved shape. Window::implResolvedCursor is private; backends reach it through a protected SystemApi::cursorShape accessor, since friendship is not inherited by WindowsApi/X11Api.
Agree, private now. In the previous version it was the poor attempt to compensate friendship not being inherited and
It simply duplicated
OK
If we make both steps on both OS backends for the same behaviour it can be made symmetrical. Two steps at the activation event: Rationale: note on X11, Step2 really is a no-op due to tests pass on linux, please assist with Windows verification once this solution becomes acceptable. |
|
@Abendlied PR looks good; I've pushed a few alignment commits: to make sure, that engine works the same on Window/Mac. |
Fix for Linux on X11.
The native mouse cursor remained visible in-game even though
CursorShape::Hiddenwas requested during game startup.The initial PR https://github.com/Try/Tempest/pull/98/changes is flawed. It adressed the symptom but violated the framework cursor management model completely.
Now in the new approach I try to follow the recommendation.
EventDispatcherdid not know the mouse position until after receiving aMotionNotify. When the mouse was already over the game window, and no mouse movement received, the cursor state was not updated. This happened every time due to fullscreen.The new implementation now gets the initial pointer position from
EnterNotifyand reevaluates the hovered widget when the window receives focus. The hover state is also reevaluated with widget geometry change.Window::setCursorShape()stays how it is, cursor management is now inEventDispatcher.Tested on Linux with X11:
Cursor is hidden immediately on startup of the game and remains hidden as long as OpenGothic has focus. Cursor becomes visible when losing focus, e.g. alt-tabbing. Cursor is hidden again when focus comes back to OpenGothic for hovering.