Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for _MOUSEWHEEL and _MOUSEMOVEMENTx on macOS #468

Merged
merged 5 commits into from
Mar 24, 2024

Conversation

a740g
Copy link
Contributor

@a740g a740g commented Mar 9, 2024

Fixes #289, #465

This PR fixes some longstanding macOS issues with the mouse.

Key fixes include:

  • Enabling support for _MOUSEWHEEL.
  • Implementing _MOUSEMOVEMENTX and _MOUSEMOVEMENTY accurately.

Previously, these issues stemmed from limitations within the GLUB library on macOS. To work around these limitations, this PR leverages the Quartz Event Services API in a manner that does not disrupt the GLUT input event queue, ensuring smooth and reliable mouse functionality.

@a740g a740g added bug Something isn't working enhancement New feature or request labels Mar 9, 2024
@a740g a740g self-assigned this Mar 9, 2024
@a740g a740g linked an issue Mar 9, 2024 that may be closed by this pull request
extern "C" int qb64_custom_event(int event, int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8, void *p1, void *p2);
void GLUT_MOUSEWHEEL_FUNC(int wheel, int direction, int x, int y);

extern int g_MouseX, g_MouseY;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it'd be cleaner to declare these static in this file and then expose a function for GLUT_MOUSE_FUNC to call that sets them. If/when we pull the basic GLUT stuff out of libqb.cpp that's the kind of change we'll make anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

auto deltaX = CGEventGetIntegerValueField(event, kCGMouseEventDeltaX);
auto deltaY = CGEventGetIntegerValueField(event, kCGMouseEventDeltaY);
if (deltaX || deltaY)
qb64_custom_event(QB64_EVENT_RELATIVE_MOUSE_MOVEMENT, deltaX, deltaY, 0, 0, 0, 0, 0, 0, nullptr, nullptr);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be good to pull the QB64_EVENT_RELATIVE_MOUSE_MOVEMENT code out of qb64_custom_event and place it in a separate function in libqb.cpp. After that both qb64_custom_event() and your own code can call that new function.

qb64_custom_event() was designed so that there's only a single function for the GLUT code to call, but it's pretty nasty to use elsewhere with all the extra parameters and IMO worth avoiding.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cleaned this up as suggested.

static CFMachPortRef g_EventTap = nullptr;
static CFRunLoopSourceRef g_RunLoopSource = nullptr;

static CGEventRef macMouseCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *userInfo) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume the callback gets called from the same main thread that GLUT runs on (since that should be running the event loop)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. None of this stuff depends on GLUT as it bypasses it and goes straight to the OS.

{
void libqb_exit(int exitcode) {
#ifdef QB64_MACOSX
macMouseDone();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this call belongs in here instead. I suspect that you're intended to only call some of those CG* functions from the main thread.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved this to glut_message_exit_program::execute().

@@ -0,0 +1,6 @@
#pragma once

#ifdef QB64_MACOSX
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a small thing in this case, but rather than require the caller to check QB64_MACOSX every time they want to call these functions I think it's better to declare stubs in here that don't do anything on the other OSs. That way callers don't have to check and we don't need to add #ifdefs everywhere. IE:

#ifdef QB64_MACOSX
void macMouseInit();
void macMouseDone();
#else
static inline void macMouseInit() { }
static inline void macMouseDone() { }
#endif

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. This looks a lot cleaner. Done.

@grymmjack
Copy link
Contributor

Tested on my Mac:
gj-Mac-Specs

With this code:

DO
    ' Keyboard handling
    DIM k AS STRING
    DIM AS INTEGER MMX, MMY, MW
    k$ = LCASE$(INKEY$)
    DO WHILE _MOUSEINPUT
        MMX = _MOUSEMOVEMENTX
        MMY = _MOUSEMOVEMENTY
        MW = _MOUSEWHEEL
        IF MMX <> 0 THEN
            LOCATE 1, 1 : PRINT SPACE$(50)
            LOCATE 1, 1 : PRINT "MMX:", MMX
        END IF
        IF MMY <> 0 THEN
            LOCATE 2, 1 : PRINT SPACE$(50)
            LOCATE 2, 1 : PRINT "MMY:", MMY
        END IF
        IF MW <> 0 THEN
            LOCATE 3, 1 : PRINT SPACE$(50)
            LOCATE 3, 1 : PRINT "MW:", MW
        END IF
    LOOP
    IF k$ = CHR$(27) THEN EXIT DO
LOOP
SYSTEM

Worked great!

image

built from the PR branch a740g:macOS-mouse-fixes

@a740g a740g merged commit cae5949 into QB64-Phoenix-Edition:main Mar 24, 2024
4 checks passed
@a740g a740g deleted the macOS-mouse-fixes branch March 24, 2024 16:59
@a740g a740g mentioned this pull request May 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

MOUSEMOVEMENTX/Y does not work properly on MacOS _MOUSEWHEEL does not work on macOS
4 participants