mirror of
https://github.com/QB64-Phoenix-Edition/QB64pe.git
synced 2024-09-20 03:14:45 +00:00
Add support for _MOUSEWHEEL and _MOUSEMOVEMENTx on macOS
This commit is contained in:
parent
c7e912ace6
commit
787c9579b6
6 changed files with 123 additions and 27 deletions
2
Makefile
2
Makefile
|
@ -155,7 +155,7 @@ ifeq ($(OS),win)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(OS),osx)
|
ifeq ($(OS),osx)
|
||||||
CXXLIBS += -framework OpenGL -framework IOKit -framework GLUT -framework Cocoa
|
CXXLIBS += -framework OpenGL -framework IOKit -framework GLUT -framework Cocoa -framework ApplicationServices
|
||||||
|
|
||||||
# OSX doesn't strip using objcopy, so we're using `-s` instead
|
# OSX doesn't strip using objcopy, so we're using `-s` instead
|
||||||
ifneq ($(STRIP_SYMBOLS),n)
|
ifneq ($(STRIP_SYMBOLS),n)
|
||||||
|
|
|
@ -29582,11 +29582,19 @@ void GLUT_MOUSE_FUNC(int glut_button, int state, int x, int y) {
|
||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is used to save the last mouse position which is then paired with the mouse wheel event on macOS
|
||||||
|
int g_MouseX = 0;
|
||||||
|
int g_MouseY = 0;
|
||||||
|
|
||||||
void GLUT_MOTION_FUNC(int x, int y) {
|
void GLUT_MOTION_FUNC(int x, int y) {
|
||||||
|
|
||||||
int32 i, last_i;
|
int32 i, last_i;
|
||||||
int32 handle;
|
int32 handle;
|
||||||
int32 xrel, yrel;
|
int32 xrel, yrel;
|
||||||
|
|
||||||
|
g_MouseX = x;
|
||||||
|
g_MouseY = y;
|
||||||
|
|
||||||
handle = mouse_message_queue_first;
|
handle = mouse_message_queue_first;
|
||||||
mouse_message_queue_struct *queue = (mouse_message_queue_struct *)list_get(mouse_message_queue_handles, handle);
|
mouse_message_queue_struct *queue = (mouse_message_queue_struct *)list_get(mouse_message_queue_handles, handle);
|
||||||
|
|
||||||
|
@ -29601,12 +29609,14 @@ void GLUT_MOTION_FUNC(int x, int y) {
|
||||||
nextIndex = 0;
|
nextIndex = 0;
|
||||||
queue->current = nextIndex;
|
queue->current = nextIndex;
|
||||||
}
|
}
|
||||||
# ifdef QB64_WINDOWS
|
|
||||||
|
# if defined(QB64_WINDOWS) || defined(QB64_MACOSX)
|
||||||
// Windows calculates relative movement by intercepting WM_INPUT events
|
// Windows calculates relative movement by intercepting WM_INPUT events
|
||||||
// instead
|
// macOS uses the Quartz Event Services to get relative movements
|
||||||
xrel = 0;
|
xrel = 0;
|
||||||
yrel = 0;
|
yrel = 0;
|
||||||
# else
|
# else
|
||||||
|
// TODO: This needs to be correctly implemented on Linux
|
||||||
xrel = x - queue->queue[queue->last].x;
|
xrel = x - queue->queue[queue->last].x;
|
||||||
yrel = y - queue->queue[queue->last].y;
|
yrel = y - queue->queue[queue->last].y;
|
||||||
# endif
|
# endif
|
||||||
|
|
|
@ -34,7 +34,7 @@ libqb-objs-y$(DEP_CONSOLE_ONLY) += $(PATH_LIBQB)/src/glut-msg-queue.o
|
||||||
libqb-objs-$(DEP_CONSOLE_ONLY) += $(PATH_LIBQB)/src/console-only-main-thread.o
|
libqb-objs-$(DEP_CONSOLE_ONLY) += $(PATH_LIBQB)/src/console-only-main-thread.o
|
||||||
|
|
||||||
ifeq ($(OS),osx)
|
ifeq ($(OS),osx)
|
||||||
libqb-objs-y$(DEP_CONSOLE_ONLY) += $(PATH_LIBQB)/src/mac-key-monitor.o
|
libqb-objs-y$(DEP_CONSOLE_ONLY) += $(PATH_LIBQB)/src/mac-key-monitor.o $(PATH_LIBQB)/src/mac-mouse-support.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
$(PATH_LIBQB)/src/%.o: $(PATH_LIBQB)/src/%.cpp
|
$(PATH_LIBQB)/src/%.o: $(PATH_LIBQB)/src/%.cpp
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
|
|
||||||
#include "libqb-common.h"
|
#include "libqb-common.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <GL/glew.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include "GL/glew.h"
|
|
||||||
|
|
||||||
// note: MacOSX uses Apple's GLUT not FreeGLUT
|
// note: MacOSX uses Apple's GLUT not FreeGLUT
|
||||||
#ifdef QB64_MACOSX
|
#ifdef QB64_MACOSX
|
||||||
|
@ -18,12 +18,13 @@
|
||||||
# include <GL/freeglut.h>
|
# include <GL/freeglut.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "mutex.h"
|
|
||||||
#include "thread.h"
|
|
||||||
#include "completion.h"
|
#include "completion.h"
|
||||||
|
#include "glut-thread.h"
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
#include "mac-key-monitor.h"
|
#include "mac-key-monitor.h"
|
||||||
#include "glut-thread.h"
|
#include "mac-mouse-support.h"
|
||||||
|
#include "mutex.h"
|
||||||
|
#include "thread.h"
|
||||||
|
|
||||||
// FIXME: These extern variable and function definitions should probably go
|
// FIXME: These extern variable and function definitions should probably go
|
||||||
// somewhere more global so that they can be referenced by libqb.cpp
|
// somewhere more global so that they can be referenced by libqb.cpp
|
||||||
|
@ -58,20 +59,20 @@ static void glutWarning(const char *fmt, va_list lst) {
|
||||||
|
|
||||||
// Performs all of the FreeGLUT initialization except for calling glutMainLoop()
|
// Performs all of the FreeGLUT initialization except for calling glutMainLoop()
|
||||||
static void initialize_glut(int argc, char **argv) {
|
static void initialize_glut(int argc, char **argv) {
|
||||||
# ifdef CORE_FREEGLUT
|
#ifdef CORE_FREEGLUT
|
||||||
glutInitWarningFunc(glutWarning);
|
glutInitWarningFunc(glutWarning);
|
||||||
glutInitErrorFunc(glutWarning);
|
glutInitErrorFunc(glutWarning);
|
||||||
# endif
|
#endif
|
||||||
|
|
||||||
glutInit(&argc, argv);
|
glutInit(&argc, argv);
|
||||||
|
|
||||||
mac_register_key_handler();
|
mac_register_key_handler();
|
||||||
|
|
||||||
# ifdef QB64_WINDOWS
|
#ifdef QB64_WINDOWS
|
||||||
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE);
|
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE);
|
||||||
# else
|
#else
|
||||||
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
|
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
|
||||||
# endif
|
#endif
|
||||||
|
|
||||||
glutInitWindowSize(640, 400); // cannot be changed unless display_x(etc) are modified
|
glutInitWindowSize(640, 400); // cannot be changed unless display_x(etc) are modified
|
||||||
|
|
||||||
|
@ -96,11 +97,11 @@ static void initialize_glut(int argc, char **argv) {
|
||||||
|
|
||||||
glutDisplayFunc(GLUT_DISPLAY_REQUEST);
|
glutDisplayFunc(GLUT_DISPLAY_REQUEST);
|
||||||
|
|
||||||
# ifdef QB64_WINDOWS
|
#ifdef QB64_WINDOWS
|
||||||
glutTimerFunc(8, GLUT_TIMER_EVENT, 0);
|
glutTimerFunc(8, GLUT_TIMER_EVENT, 0);
|
||||||
# else
|
#else
|
||||||
glutIdleFunc(GLUT_IDLEFUNC);
|
glutIdleFunc(GLUT_IDLEFUNC);
|
||||||
# endif
|
#endif
|
||||||
|
|
||||||
glutKeyboardFunc(GLUT_KEYBOARD_FUNC);
|
glutKeyboardFunc(GLUT_KEYBOARD_FUNC);
|
||||||
glutKeyboardUpFunc(GLUT_KEYBOARDUP_FUNC);
|
glutKeyboardUpFunc(GLUT_KEYBOARDUP_FUNC);
|
||||||
|
@ -111,9 +112,13 @@ static void initialize_glut(int argc, char **argv) {
|
||||||
glutPassiveMotionFunc(GLUT_PASSIVEMOTION_FUNC);
|
glutPassiveMotionFunc(GLUT_PASSIVEMOTION_FUNC);
|
||||||
glutReshapeFunc(GLUT_RESHAPE_FUNC);
|
glutReshapeFunc(GLUT_RESHAPE_FUNC);
|
||||||
|
|
||||||
# ifdef CORE_FREEGLUT
|
#ifdef CORE_FREEGLUT
|
||||||
glutMouseWheelFunc(GLUT_MOUSEWHEEL_FUNC);
|
glutMouseWheelFunc(GLUT_MOUSEWHEEL_FUNC);
|
||||||
# endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef QB64_MACOSX
|
||||||
|
macMouseInit();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool glut_is_started;
|
static bool glut_is_started;
|
||||||
|
@ -136,9 +141,7 @@ void libqb_start_glut_thread() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks whether the GLUT thread is running
|
// Checks whether the GLUT thread is running
|
||||||
bool libqb_is_glut_up() {
|
bool libqb_is_glut_up() { return glut_is_started; }
|
||||||
return glut_is_started;
|
|
||||||
}
|
|
||||||
|
|
||||||
void libqb_glut_presetup(int argc, char **argv) {
|
void libqb_glut_presetup(int argc, char **argv) {
|
||||||
if (!screen_hide) {
|
if (!screen_hide) {
|
||||||
|
@ -178,8 +181,11 @@ void libqb_start_main_thread(int argc, char **argv) {
|
||||||
// from two threads at the same time).
|
// from two threads at the same time).
|
||||||
//
|
//
|
||||||
// This is accomplished by simply queuing a GLUT message that calls exit() for us.
|
// This is accomplished by simply queuing a GLUT message that calls exit() for us.
|
||||||
void libqb_exit(int exitcode)
|
void libqb_exit(int exitcode) {
|
||||||
{
|
#ifdef QB64_MACOSX
|
||||||
|
macMouseDone();
|
||||||
|
#endif
|
||||||
|
|
||||||
// If GLUT isn't running then we're free to do the exit() call from here
|
// If GLUT isn't running then we're free to do the exit() call from here
|
||||||
if (!libqb_is_glut_up())
|
if (!libqb_is_glut_up())
|
||||||
exit(exitcode);
|
exit(exitcode);
|
||||||
|
|
74
internal/c/libqb/src/mac-mouse-support.cpp
Normal file
74
internal/c/libqb/src/mac-mouse-support.cpp
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
// Mouse support functions for macOS
|
||||||
|
// These are required to overcome the limitations of GLUT
|
||||||
|
|
||||||
|
#include "libqb-common.h"
|
||||||
|
|
||||||
|
#include "mac-mouse-support.h"
|
||||||
|
|
||||||
|
#include <ApplicationServices/ApplicationServices.h>
|
||||||
|
#include <GLUT/glut.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#define QB64_EVENT_CLOSE 1
|
||||||
|
#define QB64_EVENT_KEY 2
|
||||||
|
#define QB64_EVENT_RELATIVE_MOUSE_MOVEMENT 3
|
||||||
|
#define QB64_EVENT_FILE_DROP 4
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
static CFMachPortRef g_EventTap = nullptr;
|
||||||
|
static CFRunLoopSourceRef g_RunLoopSource = nullptr;
|
||||||
|
|
||||||
|
static CGEventRef macMouseCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *userInfo) {
|
||||||
|
auto appPID = reinterpret_cast<int64_t>(userInfo);
|
||||||
|
|
||||||
|
if (CGEventGetIntegerValueField(event, kCGEventTargetUnixProcessID) == appPID) {
|
||||||
|
if (type == kCGEventScrollWheel) {
|
||||||
|
auto deltaScroll = CGEventGetIntegerValueField(event, kCGScrollWheelEventPointDeltaAxis1);
|
||||||
|
GLUT_MOUSEWHEEL_FUNC(0, deltaScroll, g_MouseX, g_MouseY);
|
||||||
|
} else {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
void macMouseInit() {
|
||||||
|
if (!g_EventTap) {
|
||||||
|
CGEventMask eventMask = CGEventMaskBit(kCGEventLeftMouseDown) | CGEventMaskBit(kCGEventLeftMouseUp) | CGEventMaskBit(kCGEventRightMouseDown) |
|
||||||
|
CGEventMaskBit(kCGEventRightMouseUp) | CGEventMaskBit(kCGEventMouseMoved) | CGEventMaskBit(kCGEventLeftMouseDragged) |
|
||||||
|
CGEventMaskBit(kCGEventRightMouseDragged) | CGEventMaskBit(kCGEventScrollWheel) | CGEventMaskBit(kCGEventOtherMouseDown) |
|
||||||
|
CGEventMaskBit(kCGEventOtherMouseUp) | CGEventMaskBit(kCGEventOtherMouseDragged);
|
||||||
|
|
||||||
|
g_EventTap = CGEventTapCreate(kCGAnnotatedSessionEventTap, kCGHeadInsertEventTap, kCGEventTapOptionListenOnly, eventMask, macMouseCallback,
|
||||||
|
reinterpret_cast<void *>(getpid()));
|
||||||
|
if (g_EventTap) {
|
||||||
|
g_RunLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, g_EventTap, 0);
|
||||||
|
|
||||||
|
if (g_RunLoopSource) {
|
||||||
|
CFRunLoopAddSource(CFRunLoopGetCurrent(), g_RunLoopSource, kCFRunLoopCommonModes);
|
||||||
|
CGEventTapEnable(g_EventTap, true);
|
||||||
|
} else {
|
||||||
|
CFRelease(g_EventTap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void macMouseDone() {
|
||||||
|
if (g_EventTap) {
|
||||||
|
CGEventTapEnable(g_EventTap, false);
|
||||||
|
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), g_RunLoopSource, kCFRunLoopCommonModes);
|
||||||
|
CFRelease(g_RunLoopSource);
|
||||||
|
CFRelease(g_EventTap);
|
||||||
|
g_RunLoopSource = nullptr;
|
||||||
|
g_EventTap = nullptr;
|
||||||
|
}
|
||||||
|
}
|
6
internal/c/libqb/src/mac-mouse-support.h
Normal file
6
internal/c/libqb/src/mac-mouse-support.h
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef QB64_MACOSX
|
||||||
|
void macMouseInit();
|
||||||
|
void macMouseDone();
|
||||||
|
#endif
|
Loading…
Reference in a new issue