@@ -39,119 +39,148 @@ void cFodder::Mouse_Setup() {
3939}
4040
4141void cFodder::Mouse_Cursor_Handle () {
42- static bool WasClicked = false ;
43-
44- const cPosition WindowPos = mWindow ->GetWindowPosition ();
45- const cDimension ScreenSize = mWindow ->GetScreenSize ();
46- const cDimension WindowSize = mWindow ->GetWindowSize ();
42+ static int32 CaptureBlockFrames = 0 ;
43+ static bool MouseCapturedGlobal = false ;
4744 const cDimension scale = mWindow ->GetScale ();
48- static bool CursorGrabbed = true ;
45+ static bool CursorCaptured = true ;
46+ const int edgePadding = 2 ;
47+ const uint64 recaptureDelayMs = 150 ;
4948
5049 mMouseButtonStatus = mMouse_EventLastButtonsPressed ;
5150
52- if (!mWindow_Focus && CursorGrabbed) {
53- CursorGrabbed = false ;
54- }
51+ auto UpdateInputFromWindowPos = [&]() {
52+ float x = 0 .0f ;
53+ float y = 0 .0f ;
54+ SDL_GetMouseState (&x, &y);
55+ mInputMouseX = (static_cast <int >(x) / scale.getWidth ()) + MOUSE_POSITION_X_ADJUST;
56+ mInputMouseY = (static_cast <int >(y) / scale.getHeight ()) + MOUSE_POSITION_Y_ADJUST;
57+ };
58+
59+ auto ReleaseCursor = [&](bool pWarpToEdge) {
60+ CursorCaptured = false ;
61+ mMouse_LeftWindow = static_cast <uint64>(SDL_GetTicks ());
62+ mWindow ->SetRelativeMouseMode (false );
63+ SDL_GetRelativeMouseState (nullptr , nullptr );
64+ mMouse_EventLastPositionRelative = { 0 , 0 };
65+ SDL_ShowCursor ();
66+ mWindow_MouseInside = false ;
67+
68+ if (MouseCapturedGlobal) {
69+ SDL_CaptureMouse (false );
70+ MouseCapturedGlobal = false ;
71+ }
72+
73+ if (!pWarpToEdge)
74+ return ;
75+
76+ const cDimension windowSize = mWindow ->GetWindowSize ();
77+ int x = (mMouseX - MOUSE_POSITION_X_ADJUST) * scale.getWidth ();
78+ int y = (mMouseY - MOUSE_POSITION_Y_ADJUST) * scale.getHeight ();
79+ if (x < 0 )
80+ x = 0 ;
81+ else if (x >= windowSize.getWidth ())
82+ x = windowSize.getWidth () - 1 ;
83+ if (y < 0 )
84+ y = 0 ;
85+ else if (y >= windowSize.getHeight ())
86+ y = windowSize.getHeight () - 1 ;
87+ mWindow ->SetMousePositionInWindow (static_cast <float >(x), static_cast <float >(y));
88+ };
5589
5690 if (mStartParams ->mMouseAlternative ) {
5791 mInputMouseX = (mMouse_EventLastPosition .mX / scale.getWidth ()) + MOUSE_POSITION_X_ADJUST;
5892 mInputMouseY = (mMouse_EventLastPosition .mY / scale.getHeight ()) + MOUSE_POSITION_Y_ADJUST;
5993 return ;
6094 }
6195
62- // Check if the system mouse is grabbed
63- if (!CursorGrabbed) {
64-
65- if (!mWindow_Focus && mWindow ->isMouseInside ()) {
96+ if (!mWindow_Focus ) {
97+ if (CursorCaptured) {
98+ CursorCaptured = false ;
99+ mWindow ->SetRelativeMouseMode (false );
100+ SDL_GetRelativeMouseState (nullptr , nullptr );
101+ mMouse_EventLastPositionRelative = { 0 , 0 };
102+ SDL_ShowCursor ();
103+ }
104+ mWindow_MouseInside = false ;
105+ if (MouseCapturedGlobal) {
106+ SDL_CaptureMouse (false );
107+ MouseCapturedGlobal = false ;
108+ }
109+ if (mWindow ->isMouseInside ()) {
66110 // Register mouse position even when not focused but cursor on window
67- mInputMouseX = (mMouse_EventLastPosition .mX / scale.getWidth ()) + MOUSE_POSITION_X_ADJUST;
68- mInputMouseY = (mMouse_EventLastPosition .mY / scale.getHeight ()) + MOUSE_POSITION_Y_ADJUST;
111+ UpdateInputFromWindowPos ();
69112 }
70-
71- if (SDL_GetTicks () - mMouse_LeftWindow < 100 )
72- return ;
113+ return ;
114+ }
73115
74- // Check if the system cursor x/y is inside our window
75- // and ensure the mouse button has been released before we focus
76- if (mWindow_Focus && mWindow ->isMouseInside () && !mMouseButtonStatus ) {
77- WasClicked = true ;
78- CursorGrabbed = true ;
79-
80- if (!mWindow ->isFullscreen ()) {
81- // Ensure X not too close to a border
82- if (mInputMouseX <= MOUSE_POSITION_X_ADJUST)
83- mInputMouseX = MOUSE_POSITION_X_ADJUST + 1 ;
84- else if (mInputMouseX >= ScreenSize.getWidth () + MOUSE_POSITION_X_ADJUST - 1 )
85- mInputMouseX = ScreenSize.getWidth () + MOUSE_POSITION_X_ADJUST - 2 ;
86-
87- // Ensure Y not too close to a border
88- if (mInputMouseY <= MOUSE_POSITION_Y_ADJUST)
89- mInputMouseY = MOUSE_POSITION_Y_ADJUST + 1 ;
90- else if (mInputMouseY >= ScreenSize.getHeight () + MOUSE_POSITION_Y_ADJUST - 1 )
91- mInputMouseY = ScreenSize.getHeight () + MOUSE_POSITION_Y_ADJUST - 2 ;
92- }
116+ // Free cursor mode: wait for window mouse enter event to recapture.
117+ if (!CursorCaptured) {
118+ const uint64 now = static_cast <uint64>(SDL_GetTicks ());
119+ const bool canRecapture = (now - mMouse_LeftWindow ) > recaptureDelayMs;
120+ const bool inside = mWindow_MouseInside || mWindow ->isMouseInside ();
121+
122+ if (canRecapture && inside) {
123+ float wx = 0 .0f , wy = 0 .0f ;
124+ SDL_GetMouseState (&wx, &wy);
125+ const cDimension windowSize = mWindow ->GetWindowSize ();
126+ const bool awayFromEdge =
127+ (wx > edgePadding) &&
128+ (wy > edgePadding) &&
129+ (wx < static_cast <float >(windowSize.getWidth () - edgePadding)) &&
130+ (wy < static_cast <float >(windowSize.getHeight () - edgePadding));
131+ if (!awayFromEdge)
132+ return ;
133+
134+ UpdateInputFromWindowPos ();
135+ mMouseX = mInputMouseX ;
136+ mMouseY = mInputMouseY ;
137+
138+ CaptureBlockFrames = 1 ;
139+ CursorCaptured = true ;
93140 mWindow ->SetRelativeMouseMode (true );
141+ SDL_HideCursor ();
142+ SDL_GetRelativeMouseState (nullptr , nullptr );
143+ mMouse_EventLastPositionRelative = { 0 , 0 };
94144 }
95- } else {
96- if (!mWindow ->isFullscreen ()) {
97- if (!mParams ->mMouseLocked ) {
98- cPosition BorderMouse = Mouse_GetOnBorderPosition ();
99-
100- // Cursor leaving window
101- if (BorderMouse.mX || BorderMouse.mY ) {
102- CursorGrabbed = false ;
103- mMouse_LeftWindow = SDL_GetTicks ();
145+ return ;
146+ }
104147
105- mWindow ->SetRelativeMouseMode (false );
106- mWindow ->SetMousePosition (BorderMouse);
107- return ;
108- }
109- }
148+ if (!mParams ->mMouseLocked && !mWindow ->isFullscreen ()) {
149+ if (Mouse_IsOnBorder () && !mMouseButtonStatus ) {
150+ ReleaseCursor (true );
151+ return ;
110152 }
153+ }
111154
112- // hack to avoid moving cursor on window resizing
113- if (mWindow ->isResized ()) {
114- mWindow ->ClearResized ();
155+ // hack to avoid moving cursor on window resizing
156+ if (mWindow ->isResized ()) {
157+ mWindow ->ClearResized ();
115158
159+ } else {
160+ if (CaptureBlockFrames > 0 ) {
161+ --CaptureBlockFrames;
116162 } else {
117- if (WasClicked) {
118- if (!mWindow ->isMouseButtonPressed_Global ())
119- WasClicked = false ;
120- } else {
121- // Calc the distance from the cursor to the centre of the window
122- mInputMouseX = mMouseX + static_cast <int16>(mMouse_EventLastPositionRelative .mX );
123- mInputMouseY = mMouseY + static_cast <int16>(mMouse_EventLastPositionRelative .mY );
124- mMouse_EventLastPositionRelative = { 0 ,0 };
125- }
163+ // Calc the distance from the cursor to the centre of the window
164+ mInputMouseX = mMouseX + static_cast <int16>(mMouse_EventLastPositionRelative .mX );
165+ mInputMouseY = mMouseY + static_cast <int16>(mMouse_EventLastPositionRelative .mY );
166+ mMouse_EventLastPositionRelative = { 0 ,0 };
126167 }
127168 }
128169}
129170
130- cPosition cFodder::Mouse_GetOnBorderPosition () {
131- cPosition BorderMouse;
132- const cPosition WindowPos = mWindow ->GetWindowPosition ();
171+ bool cFodder::Mouse_IsOnBorder () const {
133172 const cDimension ScreenSize = mWindow ->GetScreenSize ();
134- const cDimension WindowSize = mWindow ->GetWindowSize ();
135- const cDimension scale = mWindow ->GetScale ();
136-
137- if ((mMouseX <= MOUSE_POSITION_X_ADJUST && mMouseY <= MOUSE_POSITION_Y_ADJUST) ||
138- (mMouseX >= ScreenSize.getWidth () + MOUSE_POSITION_X_ADJUST - 1 && mMouseY <= MOUSE_POSITION_Y_ADJUST) ||
139- (mMouseX <= MOUSE_POSITION_X_ADJUST && mMouseY >= ScreenSize.getHeight () + MOUSE_POSITION_Y_ADJUST - 1 ) ||
140- (mMouseX >= ScreenSize.getWidth () + MOUSE_POSITION_X_ADJUST - 1 && mMouseY >= ScreenSize.getHeight () + MOUSE_POSITION_Y_ADJUST - 1 )) {
141- BorderMouse.mX = mMouseX <= MOUSE_POSITION_X_ADJUST ? WindowPos.mX - 1 : WindowPos.mX + WindowSize.getWidth () + 1 ;
142- BorderMouse.mY = mMouseY <= MOUSE_POSITION_Y_ADJUST ? WindowPos.mY - 1 : WindowPos.mY + WindowSize.getHeight () + 1 ;
143- }
144- // Need to check if the game cursor is near a border on X axis
145- else if (mMouseX <= MOUSE_POSITION_X_ADJUST || mMouseX >= ScreenSize.getWidth () + MOUSE_POSITION_X_ADJUST - 1 ) {
146- BorderMouse.mX = mMouseX <= MOUSE_POSITION_X_ADJUST ? WindowPos.mX - 1 : WindowPos.mX + WindowSize.getWidth () + 1 ;
147- BorderMouse.mY = WindowPos.mY + (mMouseY - MOUSE_POSITION_Y_ADJUST) * scale.getHeight ();
148- } // Need to check if the game cursor is near a border Y axis
149- else if (mMouseY <= MOUSE_POSITION_Y_ADJUST || mMouseY >= ScreenSize.getHeight () + MOUSE_POSITION_Y_ADJUST - 1 ) {
150- BorderMouse.mX = WindowPos.mX + (mMouseX - MOUSE_POSITION_X_ADJUST) * scale.getWidth ();
151- BorderMouse.mY = mMouseY <= MOUSE_POSITION_Y_ADJUST ? WindowPos.mY - 1 : WindowPos.mY + WindowSize.getHeight () + 1 ;
152- }
153173
154- return BorderMouse;
174+ if (mMouseX <= MOUSE_POSITION_X_ADJUST)
175+ return true ;
176+ if (mMouseX >= ScreenSize.getWidth () + MOUSE_POSITION_X_ADJUST - 1 )
177+ return true ;
178+ if (mMouseY <= MOUSE_POSITION_Y_ADJUST)
179+ return true ;
180+ if (mMouseY >= ScreenSize.getHeight () + MOUSE_POSITION_Y_ADJUST - 1 )
181+ return true ;
182+
183+ return false ;
155184}
156185
157186void cFodder::Mouse_ReadInputs () {
0 commit comments