QB64 Phoenix Edition
Custom MouseMovement Example - Printable Version

+- QB64 Phoenix Edition (https://qb64phoenix.com/forum)
+-- Forum: QB64 Rising (https://qb64phoenix.com/forum/forumdisplay.php?fid=1)
+--- Forum: Prolific Programmers (https://qb64phoenix.com/forum/forumdisplay.php?fid=26)
+---- Forum: SMcNeill (https://qb64phoenix.com/forum/forumdisplay.php?fid=29)
+---- Thread: Custom MouseMovement Example (/showthread.php?tid=2465)

Pages: 1 2


Custom MouseMovement Example - SMcNeill - 02-25-2024

There's been several discussions here recently about _MouseMovementX and _MouseMovementY, and how they don't work 100% as expected in Linux and Mac.  Unfortunately, the problem here is an underlying issue with glut itself not reporting that relative movement back to us.

The only real solution at the moment is for one to write their own routine to handle this type of situation, so I thought I'd take a few minutes and write up a quick example of how to do that for someone:

Code: (Select All)
DIM SHARED AS LONG MouseMoveX, MouseMoveY, MouseX, MouseY

SCREEN _NEWIMAGE(800, 600, 32)
_SCREENMOVE _MIDDLE


DO
    CLS
    Mouse
    TMMX = TMMX + MouseMoveX: TMMY = TMMY + MouseMoveY
    PRINT "Mouse x:"; MouseX
    PRINT "Mouse y:"; MouseY
    PRINT "MouseMoveX:"; MouseMoveX
    PRINT "MouseMoveY:"; MouseMoveY
    PRINT "Total MouseMoveX:"; TMMX
    PRINT "TOtal MouseMoveY:"; TMMY
    _LIMIT 30
    _DISPLAY
LOOP UNTIL _MOUSEBUTTON(2)
SYSTEM



SUB Mouse
    STATIC AS LONG CurrentX, CurrentY
    STATIC AS LONG Pointer 'We need a pointer of some sort for a manual pointer.  Here's a cheesy one by default.
    STATIC AS INTEGER Init

    WHILE _MOUSEINPUT: WEND 'catch up to the current mouse's position so we sync properly
    X = _MOUSEX: Y = _MOUSEY
    MouseMoveX = 0: MouseMoveY = 0

    IF Init = 0 THEN
        Init = -1
        CurrentX = _WIDTH \ 2: CurrentY = _HEIGHT \ 2
        _MOUSEHIDE
        _MOUSEMOVE _WIDTH \ 2, _HEIGHT \ 2
        Pointer = _NEWIMAGE(16, 8, 32)
        COLOR -1, 0
        _PRINTSTRING (0, 0), CHR$(24), Pointer
    ELSE
        IF X <> _WIDTH \ 2 OR Y <> _HEIGHT \ 2 THEN
            MouseMoveX = X - _WIDTH \ 2: MouseMoveY = Y - _HEIGHT \ 2
            CurrentX = CurrentX + MouseMoveX
            CurrentY = CurrentY + MouseMoveY
            IF CurrentX < 0 THEN CurrentX = 0
            IF CurrentX >= _WIDTH THEN CurrentX = _WIDTH - 1
            IF CurrentY < 0 THEN CurrentY = 0
            IF CurrentY >= _HEIGHT THEN CurrentY = _HEIGHT - 1
        END IF
    END IF
    _PUTIMAGE (CurrentX - 8, CurrentY - 8)-STEP(32, 32), Pointer
    _MOUSEMOVE _WIDTH / 2, _HEIGHT / 2
    MouseX = CurrentX: MouseY = CurrentY
END SUB

Test that out and see if it doesn't keep track of the current mouse position, while also allowing for mouse movement to take place regardless of the edge of the screen.

Feel free to ask/add any questions, comments, or insights into the process here, but I'm thinking this should work on all OSes without any issues.  (As long as _MouseHide works on all OSes...  I didn't think to check to see if it does or doesn't, to be honest.)


RE: Custom MouseMovement Example - NakedApe - 02-26-2024

Thanks vm for this, Steve, but it doesn't run on MacOS. I've previously found you've gotta put the MOUSEX and Y polling inside the WHILE _MOUSEINPUT: WEND loop, which I did, but that wasn't enough. For some reason your pointer doesn't show up. The Total MouseMovementX & Y readouts show quickly rising negative numbers while the MOUSEMOVEMENTX & Y get stuck at -400, -300. MouseX & Y show zeros.  Huh  Remming out the _MOUSEHIDE shows the system pointer angrily stuck in the middle of the screen...

What are you trying to pull here, Mr. McNeill?  Wink


RE: Custom MouseMovement Example - SMcNeill - 02-26-2024

It doesn't work on Mac?   

Mac mouse commands must be broken more than I'd ever thought they were!   

What we're doing here is hiding our mouse, while creating an image of one which we track and display manually.  The system mouse is always jumping back to the center of the screen, so we're always reading the relative movement on it...

And that leads to me wondering just WHICH of these commands is glitching out on Mac!

Gah!   One of these days, I'm going to breakdown and buy an old second hand one from somewhere just for testing purposes.  Tongue


RE: Custom MouseMovement Example - SMcNeill - 02-26-2024

Give this version a test run, if you get a chance.   IF you can't see a cursor with _PUTIMAGE, then maybe it's a color -1 issue?  Or something else odd?

Code: (Select All)
DIM SHARED AS LONG MouseMoveX, MouseMoveY, MouseX, MouseY

SCREEN _NEWIMAGE(800, 600, 32)
_SCREENMOVE _MIDDLE


DO
    CLS
    Mouse
    TMMX = TMMX + MouseMoveX: TMMY = TMMY + MouseMoveY
    PRINT "Mouse x:"; MouseX
    PRINT "Mouse y:"; MouseY
    PRINT "MouseMoveX:"; MouseMoveX
    PRINT "MouseMoveY:"; MouseMoveY
    PRINT "Total MouseMoveX:"; TMMX
    PRINT "TOtal MouseMoveY:"; TMMY
    _LIMIT 30
    _PRINTSTRING (MouseX, MouseY), CHR$(24)
    _DISPLAY
LOOP UNTIL _MOUSEBUTTON(2)
SYSTEM



SUB Mouse
    STATIC AS LONG CurrentX, CurrentY
    STATIC AS INTEGER Init
    WHILE _MOUSEINPUT
        Xjunk = _MOUSEX: Yjunk = _MOUSEY
    WEND 'catch up to the current mouse's position so we sync properly
    X = _MOUSEX: Y = _MOUSEY
    MouseMoveX = 0: MouseMoveY = 0

    IF Init = 0 THEN
        Init = -1
        CurrentX = _WIDTH \ 2: CurrentY = _HEIGHT \ 2
        _MOUSEHIDE
        _MOUSEMOVE _WIDTH \ 2, _HEIGHT \ 2
    ELSE
        IF X <> _WIDTH \ 2 OR Y <> _HEIGHT \ 2 THEN
            MouseMoveX = X - _WIDTH \ 2: MouseMoveY = Y - _HEIGHT \ 2
            CurrentX = CurrentX + MouseMoveX
            CurrentY = CurrentY + MouseMoveY
            IF CurrentX < 0 THEN CurrentX = 0
            IF CurrentX >= _WIDTH THEN CurrentX = _WIDTH - 1
            IF CurrentY < 0 THEN CurrentY = 0
            IF CurrentY >= _HEIGHT THEN CurrentY = _HEIGHT - 1
        END IF
    END IF

    _MOUSEMOVE _WIDTH \ 2, _HEIGHT \ 2
    WHILE _MOUSEINPUT
        Xjunk = _MOUSEX: Yjunk = _MOUSEY
    WEND 'clear the manual reset to the center so we don't read it in the next pass
    MouseX = CurrentX: MouseY = CurrentY
END SUB

Even if the values do something odd (which I don't know why they should), you should still be able to see the arrow on the screen and move it around.  In this case, it's only going to be a text sized character of an arrow (CHR$(24)), so you might need to strain your eyes to find it, but it should definitely be there.

Once a cursor is available and moving, then we can sort out what the heck is going on with the return values.  Work on one thing at a time.  Big Grin


RE: Custom MouseMovement Example - NakedApe - 02-26-2024

I gave it a shot. The numbers don't change, though I do see the pointer stuck at 0, 0. You put that junkX/Y = _MOUSEX/Y inside the WHILE/WEND, but no info is transferred from those variables to the rest of your sub as written.  I do get basic mouse x and y values and pointer movement from the below, but nothing from your sub...

Code: (Select All)
DIM SHARED AS LONG MouseX, MouseY
SCREEN _NEWIMAGE(800, 600, 32)
_SCREENMOVE _MIDDLE

DO
    CLS
    Mouse
    TMMX = TMMX + MouseMoveX: TMMY = TMMY + MouseMoveY
    PRINT "Mouse x:"; MouseX
    PRINT "Mouse y:"; MouseY
    PRINT "MouseMoveX:"; MouseMoveX
    PRINT "MouseMoveY:"; MouseMoveY
    PRINT "Total MouseMoveX:"; TMMX
    PRINT "TOtal MouseMoveY:"; TMMY
    _LIMIT 30
    _PRINTSTRING (MouseX, MouseY), CHR$(24)
    _DISPLAY
LOOP UNTIL _MOUSEBUTTON(2)
SYSTEM

SUB Mouse
    WHILE _MOUSEINPUT
        MouseX = _MOUSEX: MouseY = _MOUSEY
    WEND '

    _MOUSEHIDE
END SUB



RE: Custom MouseMovement Example - NakedApe - 02-26-2024

UPDATE: You got me thinking . . .   Your idea here of resetting the mouse to middle of screen works to overcome the _mousemovementX issue pretty darned well! There's a slight pause in mouse control when the mouse position is reset, but that sure beats having to "unwind" the mouse to get more movement out of it. Thanks again, Sir Steve.


RE: Custom MouseMovement Example - SMcNeill - 02-27-2024

@NakedApe The problem on Mac, it turns out, is the glutWarpPointer function that we call to move the mouse.  For whatever reason, once it's called, it invokes a 250ms lockout of all keyboard and mouse events.    

Move the mouse, we stop reading keyboard input and mouse events for a quarter of a second...

The loop is on a _LIMIT 30, so it's ran 7.5 times more often than that...   So the vast majority of mouse movements and keypresses and such just get blocked by the system, by moving the mouse back to the center so often.

https://stackoverflow.com/questions/10196603/using-cgeventsourcesetlocaleventssuppressioninterval-instead-of-the-deprecated  <-- This may have a solution to that issue, as we've did some prelimary digging into it.  All we need now is for our Mac guru's to have some free time so they can see about implementing the fix for us.  Wink


RE: Custom MouseMovement Example - GareBear - 02-27-2024

SMcNeill,

No problem that I can tell on linux. The first on with a big pointer, all numbers shows up no delays in display. The same with the second one with a small pointer. I hope this helps in some way.


RE: Custom MouseMovement Example - SMcNeill - 02-27-2024

Linux and Windows work as expected.  Mac has the issue with glutWarpPointer that I mentioned above.  We'll need to find a fix to it, and then this should work on all platforms in a consistant manner.  Wink


RE: Custom MouseMovement Example - SMcNeill - 02-27-2024

One of our Mac users could test this out, if they'd be so kind, and tell us how it performs for them:

Code: (Select All)
DIM SHARED AS LONG MouseMoveX, MouseMoveY, MouseX, MouseY

SCREEN _NEWIMAGE(800, 600, 32)
_SCREENMOVE _MIDDLE

Pointer = _NEWIMAGE(16, 8, 32)
COLOR -1, 0
_PRINTSTRING (0, 0), CHR$(24), Pointer



DO
    CLS
    Mouse
    TMMX = TMMX + MouseMoveX: TMMY = TMMY + MouseMoveY
    PRINT "Mouse x:"; MouseX
    PRINT "Mouse y:"; MouseY
    PRINT "MouseMoveX:"; MouseMoveX
    PRINT "MouseMoveY:"; MouseMoveY
    PRINT "Total MouseMoveX:"; TMMX
    PRINT "TOtal MouseMoveY:"; TMMY
    _LIMIT 30
    _PUTIMAGE (MouseX - 8, MouseY - 8)-STEP(32, 32), Pointer
    _DISPLAY
LOOP UNTIL _MOUSEBUTTON(2)
SYSTEM



SUB Mouse
    STATIC AS LONG CurrentX, CurrentY
    STATIC AS INTEGER Init, counter
    counter = (counter + 1) MOD 10
    WHILE _MOUSEINPUT: WEND 'catch up to the current mouse's position so we sync properly
    X = _MOUSEX: Y = _MOUSEY
    MouseMoveX = 0: MouseMoveY = 0

    IF Init = 0 THEN
        Init = -1
        CurrentX = _WIDTH \ 2: CurrentY = _HEIGHT \ 2
        _MOUSEHIDE
        _MOUSEMOVE _WIDTH \ 2, _HEIGHT \ 2
    ELSE
        IF X <> _WIDTH \ 2 OR Y <> _HEIGHT \ 2 THEN
            MouseMoveX = X - _WIDTH \ 2: MouseMoveY = Y - _HEIGHT \ 2
            CurrentX = CurrentX + MouseMoveX
            CurrentY = CurrentY + MouseMoveY
            IF CurrentX < 0 THEN CurrentX = 0
            IF CurrentX >= _WIDTH THEN CurrentX = _WIDTH - 1
            IF CurrentY < 0 THEN CurrentY = 0
            IF CurrentY >= _HEIGHT THEN CurrentY = _HEIGHT - 1
        END IF
    END IF
    IF counter = 0 THEN _MOUSEMOVE _WIDTH \ 2, _HEIGHT \ 2
    MouseX = CurrentX: MouseY = CurrentY
END SUB

This seems hyper-sensitive to me on Windows for some reason, but the idea here is that this _MouseMove statement *only* occcurs on every 10th pass.  (1/3rd of a second, while the _mousemove blocks input for 1/4th of a second.)  I'm thinking that with a longer delay than the lock, Mac should still be able to read mouse events and report them for us.  I'm not entriely certain how laggy/skippy it might be, and I wouldn't want to try and implement any actual program on Mac that uses _MouseMove right now.  Have a program move the mouse and lock out keyboard and mouse input??   No thanks!  What the heck type of glitch is that for glut??  And if it's not a glitch, then what the heck is its intended purpose?

This should just give some testable example of this glitch in action.  Lower the mod on the counter to decrease delay between mousemove calls (     counter = (counter + 1) MOD 10); increase it to increase the delay between mousemove calls.  Feel free to change it and see how it performs with various alterations to how fast mousemove is called.

I don't have a Mac for testing, so I'm kind of curious what type of results this will actually generate for us.  My mind is telling me what I'd *expect* to happen.  Now, whether or not that's actually happens, remains up to the OS to decide I guess.  LOL!  In the end, this still might not make any change to things with Mac, though I'd *think* that it should.  Wink