1919
2020namespace cage
2121{
22- namespace privat
23- {
24- struct GraphicsContext ;
25- }
26-
2722 namespace
2823 {
2924 ModifiersFlags getKeyModifiers (int mods)
@@ -45,29 +40,24 @@ namespace cage
4540 return r;
4641 }
4742
48- struct MouseOffset
49- {
50- Vec2 off;
51- };
52-
5343 class WindowImpl : public Window
5444 {
5545 public:
56- Vec2 lastMouseButtonPressPositions[5 ] = {};
57- uint64 lastMouseButtonPressTimes[5 ] = {}; // unused, left, right, unused, middle
58-
5946 Holder<privat::GraphicsContext> graphicsContext;
6047 ConcurrentQueue<GenericInput> eventsQueue;
6148 FlatSet<uint32> stateKeys;
49+ uint64 lastMouseButtonPressTimes[5 ] = {}; // unused, left, right, unused, middle
50+ Vec2 lastMouseButtonPressPositions[5 ] = {};
51+ Vec2 lastRelativePosition;
52+ Vec2 stateMousePosition;
53+ Vec2 stateMouseScale;
6254 MouseButtonsFlags stateButtons = MouseButtonsFlags::None;
6355 ModifiersFlags stateMods = ModifiersFlags::None;
64- Vec2 stateMousePosition;
65- Vec2 lastRelativePosition;
66- Vec2 mouseScale;
6756 GLFWwindow *window = nullptr ;
6857 bool focus = true ;
6958 bool mouseIntendVisible = true ;
7059 bool mouseIntendRelative = false ;
60+ bool mouseAllowRelativeMovement = false ; // prevent mouse jumping shortly after switching from absolute to relative movement
7161
7262#ifdef GCHL_WINDOWS_THREAD
7363 Holder<Thread> windowThread;
@@ -152,23 +142,34 @@ namespace cage
152142
153143 void initializeEvents ();
154144
155- void updateMouseMode ()
145+ bool getRelative () const { return glfwGetInputMode (window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED; }
146+
147+ Vec2 getPosition ()
156148 {
157- int intent = GLFW_CURSOR_NORMAL;
158- if (!mouseIntendVisible)
159- intent = GLFW_CURSOR_HIDDEN;
160- if (mouseIntendRelative)
161- intent = GLFW_CURSOR_DISABLED;
162- glfwSetInputMode (window, GLFW_CURSOR, intent);
149+ Vec2 pos;
150+ double xpos, ypos;
151+ glfwGetCursorPos (window, &xpos, &ypos);
152+ pos[0 ] = xpos;
153+ pos[1 ] = ypos;
154+ return pos * stateMouseScale;
155+ }
163156
164- mouseScale = Vec2 (1 );
165- int fbw = 0 , fbh = 0 , ww = 0 , wh = 0 ;
166- glfwGetFramebufferSize (window, &fbw, &fbh);
167- glfwGetWindowSize (window, &ww, &wh);
168- if (fbw > 0 && fbh > 0 && ww > 0 && wh > 0 )
157+ bool determineMouseDoubleClick (MouseButtonsFlags buttons, Vec2 cp)
158+ {
159+ CAGE_ASSERT ((uint32)buttons < array_size (lastMouseButtonPressTimes));
160+ const uint64 ct = applicationTime ();
161+ uint64 < = lastMouseButtonPressTimes[(uint32)buttons];
162+ Vec2 &lp = lastMouseButtonPressPositions[(uint32)buttons];
163+ if (ct - lt < 300'000 && distance (cp, lp) < 10 )
164+ {
165+ lt = 0 ;
166+ return true ;
167+ }
168+ else
169169 {
170- mouseScale[0 ] = double (fbw) / double (ww);
171- mouseScale[1 ] = double (fbh) / double (wh);
170+ lt = ct;
171+ lp = cp;
172+ return false ;
172173 }
173174 }
174175
@@ -188,6 +189,8 @@ namespace cage
188189 if constexpr (std::is_same_v<T, input::MouseRelativeMove>)
189190 {
190191 CAGE_ASSERT (i.relative );
192+ if (!mouseAllowRelativeMovement)
193+ return ;
191194 const Vec2 n = i.position ;
192195 if (valid (lastRelativePosition))
193196 i.position = n - lastRelativePosition;
@@ -203,35 +206,97 @@ namespace cage
203206 events.dispatch (i);
204207 }
205208
206- bool getRelative () const { return glfwGetInputMode (window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED; }
207-
208- Vec2 getPosition ()
209+ void updateMouseMode ()
209210 {
210- Vec2 pos;
211- double xpos, ypos;
212- glfwGetCursorPos (window, &xpos, &ypos);
213- pos[0 ] = xpos;
214- pos[1 ] = ypos;
215- return pos * mouseScale;
211+ int intent = GLFW_CURSOR_NORMAL;
212+ if (!mouseIntendVisible)
213+ intent = GLFW_CURSOR_HIDDEN;
214+ if (mouseIntendRelative)
215+ intent = GLFW_CURSOR_DISABLED;
216+ glfwSetInputMode (window, GLFW_CURSOR, intent);
217+
218+ stateMouseScale = Vec2 (1 );
219+ int fbw = 0 , fbh = 0 , ww = 0 , wh = 0 ;
220+ glfwGetFramebufferSize (window, &fbw, &fbh);
221+ glfwGetWindowSize (window, &ww, &wh);
222+ if (fbw > 0 && fbh > 0 && ww > 0 && wh > 0 )
223+ {
224+ stateMouseScale[0 ] = double (fbw) / double (ww);
225+ stateMouseScale[1 ] = double (fbh) / double (wh);
226+ }
216227 }
217228
218- bool determineMouseDoubleClick (MouseButtonsFlags buttons, Vec2 cp )
229+ void processEvents ( )
219230 {
220- CAGE_ASSERT ((uint32)buttons < array_size (lastMouseButtonPressTimes));
221- const uint64 ct = applicationTime ();
222- uint64 < = lastMouseButtonPressTimes[(uint32)buttons];
223- Vec2 &lp = lastMouseButtonPressPositions[(uint32)buttons];
224- if (ct - lt < 300'000 && distance (cp, lp) < 5 )
231+ #ifndef GCHL_WINDOWS_THREAD
232+ updateMouseMode ();
225233 {
226- lt = 0 ;
227- return true ;
234+ ScopeLock l ( cageGlfwMutex ()) ;
235+ glfwPollEvents () ;
228236 }
229- else
237+ #endif
238+
239+ GenericInput e;
240+ while (eventsQueue.tryPop (e))
230241 {
231- lt = ct;
232- lp = cp;
233- return false ;
242+ switch (e.typeHash ())
243+ {
244+ case detail::typeHash<input::MouseMove>():
245+ updateMouseStateAndDispatch<input::MouseMove>(e);
246+ break ;
247+ case detail::typeHash<input::MouseRelativeMove>():
248+ updateMouseStateAndDispatch<input::MouseRelativeMove>(e);
249+ break ;
250+ case detail::typeHash<input::MousePress>():
251+ updateMouseStateAndDispatch<input::MousePress>(e);
252+ break ;
253+ case detail::typeHash<input::MouseDoublePress>():
254+ updateMouseStateAndDispatch<input::MouseDoublePress>(e);
255+ break ;
256+ case detail::typeHash<input::MouseRelease>():
257+ updateMouseStateAndDispatch<input::MouseRelease>(e);
258+ break ;
259+ case detail::typeHash<input::MouseWheel>():
260+ updateMouseStateAndDispatch<input::MouseWheel>(e);
261+ break ;
262+ case detail::typeHash<input::KeyPress>():
263+ {
264+ stateKeys.insert (e.get <input::KeyPress>().key );
265+ stateMods = e.get <input::KeyPress>().mods ;
266+ events.dispatch (e);
267+ const input::KeyPress p = e.get <input::KeyPress>();
268+ events.dispatch (input::KeyRepeat{ p.window , p.key , p.mods });
269+ break ;
270+ }
271+ case detail::typeHash<input::KeyRelease>():
272+ stateKeys.erase (e.get <input::KeyRelease>().key );
273+ stateMods = e.get <input::KeyRelease>().mods ;
274+ events.dispatch (e);
275+ break ;
276+ case detail::typeHash<input::KeyRepeat>():
277+ stateKeys.insert (e.get <input::KeyRepeat>().key );
278+ stateMods = e.get <input::KeyRepeat>().mods ;
279+ events.dispatch (e);
280+ break ;
281+ case detail::typeHash<input::Character>():
282+ stateMods = e.get <input::Character>().mods ;
283+ events.dispatch (e);
284+ break ;
285+ case detail::typeHash<input::WindowFocusGain>():
286+ focus = true ;
287+ events.dispatch (e);
288+ break ;
289+ case detail::typeHash<input::WindowFocusLose>():
290+ focus = false ;
291+ events.dispatch (e);
292+ break ;
293+ default :
294+ events.dispatch (e);
295+ break ;
296+ }
234297 }
298+
299+ mouseAllowRelativeMovement = true ;
235300 }
236301 };
237302
@@ -319,7 +384,7 @@ namespace cage
319384 e.mods = getKeyModifiers (w);
320385 e.position [0 ] = xpos;
321386 e.position [1 ] = ypos;
322- e.position *= impl->mouseScale ;
387+ e.position *= impl->stateMouseScale ;
323388 if (glfwGetMouseButton (w, GLFW_MOUSE_BUTTON_LEFT))
324389 e.buttons |= MouseButtonsFlags::Left;
325390 if (glfwGetMouseButton (w, GLFW_MOUSE_BUTTON_RIGHT))
@@ -579,6 +644,7 @@ namespace cage
579644 if (impl->mouseIntendRelative != relative)
580645 impl->lastRelativePosition = Vec2::Nan ();
581646 impl->mouseIntendRelative = relative;
647+ impl->mouseAllowRelativeMovement = false ;
582648 }
583649
584650 Vec2 Window::mousePosition () const
@@ -615,72 +681,7 @@ namespace cage
615681 void Window::processEvents ()
616682 {
617683 WindowImpl *impl = (WindowImpl *)this ;
618- #ifndef GCHL_WINDOWS_THREAD
619- impl->updateMouseMode ();
620- {
621- ScopeLock l (cageGlfwMutex ());
622- glfwPollEvents ();
623- }
624- #endif
625- GenericInput e;
626- while (impl->eventsQueue .tryPop (e))
627- {
628- switch (e.typeHash ())
629- {
630- case detail::typeHash<input::MouseMove>():
631- impl->updateMouseStateAndDispatch <input::MouseMove>(e);
632- break ;
633- case detail::typeHash<input::MouseRelativeMove>():
634- impl->updateMouseStateAndDispatch <input::MouseRelativeMove>(e);
635- break ;
636- case detail::typeHash<input::MousePress>():
637- impl->updateMouseStateAndDispatch <input::MousePress>(e);
638- break ;
639- case detail::typeHash<input::MouseDoublePress>():
640- impl->updateMouseStateAndDispatch <input::MouseDoublePress>(e);
641- break ;
642- case detail::typeHash<input::MouseRelease>():
643- impl->updateMouseStateAndDispatch <input::MouseRelease>(e);
644- break ;
645- case detail::typeHash<input::MouseWheel>():
646- impl->updateMouseStateAndDispatch <input::MouseWheel>(e);
647- break ;
648- case detail::typeHash<input::KeyPress>():
649- {
650- impl->stateKeys .insert (e.get <input::KeyPress>().key );
651- impl->stateMods = e.get <input::KeyPress>().mods ;
652- events.dispatch (e);
653- const input::KeyPress p = e.get <input::KeyPress>();
654- events.dispatch (input::KeyRepeat{ p.window , p.key , p.mods });
655- break ;
656- }
657- case detail::typeHash<input::KeyRelease>():
658- impl->stateKeys .erase (e.get <input::KeyRelease>().key );
659- impl->stateMods = e.get <input::KeyRelease>().mods ;
660- events.dispatch (e);
661- break ;
662- case detail::typeHash<input::KeyRepeat>():
663- impl->stateKeys .insert (e.get <input::KeyRepeat>().key );
664- impl->stateMods = e.get <input::KeyRepeat>().mods ;
665- events.dispatch (e);
666- break ;
667- case detail::typeHash<input::Character>():
668- impl->stateMods = e.get <input::Character>().mods ;
669- events.dispatch (e);
670- break ;
671- case detail::typeHash<input::WindowFocusGain>():
672- impl->focus = true ;
673- events.dispatch (e);
674- break ;
675- case detail::typeHash<input::WindowFocusLose>():
676- impl->focus = false ;
677- events.dispatch (e);
678- break ;
679- default :
680- events.dispatch (e);
681- break ;
682- }
683- }
684+ impl->processEvents ();
684685 }
685686
686687 Vec2i Window::resolution () const
0 commit comments