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
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ ifeq ($(OS),win)
endif

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
ifneq ($(STRIP_SYMBOLS),n)
Expand Down
113 changes: 62 additions & 51 deletions internal/c/libqb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@
#include "audio.h"
#include "bitops.h"
#include "cmem.h"
#include "completion.h"
#include "command.h"
#include "completion.h"
#include "compression.h"
#include "datetime.h"
#include "event.h"
#include "error_handle.h"
#include "event.h"
#include "file-fields.h"
#include "filepath.h"
#include "filesystem.h"
#include "file-fields.h"
#include "font.h"
#include "game_controller.h"
#include "gfs.h"
Expand All @@ -32,9 +32,10 @@
#include "http.h"
#include "image.h"
#include "keyhandler.h"
#include "qblist.h"
#include "mac-mouse-support.h"
#include "mem.h"
#include "mutex.h"
#include "qblist.h"
#include "qbs.h"
#include "rounding.h"
#include "shell.h"
Expand Down Expand Up @@ -29587,6 +29588,10 @@ void GLUT_MOTION_FUNC(int x, int y) {
int32 i, last_i;
int32 handle;
int32 xrel, yrel;

// This is used to save the last mouse position which is then paired with the mouse wheel event on macOS
macMouseUpdatePosition(x, y);

handle = mouse_message_queue_first;
mouse_message_queue_struct *queue = (mouse_message_queue_struct *)list_get(mouse_message_queue_handles, handle);

Expand All @@ -29601,12 +29606,14 @@ void GLUT_MOTION_FUNC(int x, int y) {
nextIndex = 0;
queue->current = nextIndex;
}
# ifdef QB64_WINDOWS

# if defined(QB64_WINDOWS) || defined(QB64_MACOSX)
// Windows calculates relative movement by intercepting WM_INPUT events
// instead
// macOS uses the Quartz Event Services to get relative movements
xrel = 0;
yrel = 0;
# else
// TODO: This needs to be correctly implemented on Linux
xrel = x - queue->queue[queue->last].x;
yrel = y - queue->queue[queue->last].y;
# endif
Expand Down Expand Up @@ -29694,7 +29701,7 @@ void GLUT_MOTION_FUNC(int x, int y) {
void GLUT_PASSIVEMOTION_FUNC(int x, int y) { GLUT_MOTION_FUNC(x, y); }

void GLUT_MOUSEWHEEL_FUNC(int wheel, int direction, int x, int y) {
# ifdef QB64_GLUT
#ifdef QB64_GLUT
// Note: freeglut specific, limited documentation existed so the following
// research was done:
// qbs_print(qbs_str(wheel),NULL); <-- was always 0 [could 1 indicate
Expand All @@ -29709,7 +29716,7 @@ void GLUT_MOUSEWHEEL_FUNC(int wheel, int direction, int x, int y) {
GLUT_MouseButton_Down(5, x, y);
GLUT_MouseButton_Up(5, x, y);
}
# endif
#endif
}

#endif
Expand Down Expand Up @@ -32409,67 +32416,71 @@ extern "C" void qb64_os_event_linux(XEvent *event, Display *display, int *qb64_o
}
#endif

void qb64_custom_event_relative_mouse_movement(int deltaX, int deltaY) {
int32_t handle = mouse_message_queue_first;
mouse_message_queue_struct *queue = (mouse_message_queue_struct *)list_get(mouse_message_queue_handles, handle);
// message #1
int32_t i = queue->last + 1;
if (i > queue->lastIndex)
i = 0;
if (i == queue->current) {
int32_t nextIndex = queue->last + 1;
if (nextIndex > queue->lastIndex)
nextIndex = 0;
queue->current = nextIndex;
}
queue->queue[i].x = queue->queue[queue->last].x;
queue->queue[i].y = queue->queue[queue->last].y;
queue->queue[i].movementx = deltaX;
queue->queue[i].movementy = deltaY;
queue->queue[i].buttons = queue->queue[queue->last].buttons;
queue->last = i;
// message #2 (clears movement values to avoid confusion)
i = queue->last + 1;
if (i > queue->lastIndex)
i = 0;
if (i == queue->current) {
int32_t nextIndex = queue->last + 1;
if (nextIndex > queue->lastIndex)
nextIndex = 0;
queue->current = nextIndex;
}
queue->queue[i].x = queue->queue[queue->last].x;
queue->queue[i].y = queue->queue[queue->last].y;
queue->queue[i].movementx = 0;
queue->queue[i].movementy = 0;
queue->queue[i].buttons = queue->queue[queue->last].buttons;
queue->last = i;
}

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) {
if (event == QB64_EVENT_CLOSE) {
exit_value |= 1;
return NULL;
return 0;
} // close

if (event == QB64_EVENT_KEY) {
if (v1 == VK + QBVK_PAUSE) {
if (v2 > 0)
keydown_vk(v1);
else
keyup_vk(v1);
return NULL;
return 0;
}
if (v1 == VK + QBVK_BREAK) {
if (v2 > 0)
keydown_vk(v1);
else
keyup_vk(v1);
return NULL;
return 0;
}
return -1;
} // key

if (event == QB64_EVENT_RELATIVE_MOUSE_MOVEMENT) { // qb64_custom_event(QB64_EVENT_RELATIVE_MOUSE_MOVEMENT,xPosRelative,yPosRelative,0,0,0,0,0,0,NULL,NULL);
static int32 i;
int32 handle;
handle = mouse_message_queue_first;
mouse_message_queue_struct *queue = (mouse_message_queue_struct *)list_get(mouse_message_queue_handles, handle);
// message #1
i = queue->last + 1;
if (i > queue->lastIndex)
i = 0;
if (i == queue->current) {
int32 nextIndex = queue->last + 1;
if (nextIndex > queue->lastIndex)
nextIndex = 0;
queue->current = nextIndex;
}
queue->queue[i].x = queue->queue[queue->last].x;
queue->queue[i].y = queue->queue[queue->last].y;
queue->queue[i].movementx = v1;
queue->queue[i].movementy = v2;
queue->queue[i].buttons = queue->queue[queue->last].buttons;
queue->last = i;
// message #2 (clears movement values to avoid confusion)
i = queue->last + 1;
if (i > queue->lastIndex)
i = 0;
if (i == queue->current) {
int32 nextIndex = queue->last + 1;
if (nextIndex > queue->lastIndex)
nextIndex = 0;
queue->current = nextIndex;
}
queue->queue[i].x = queue->queue[queue->last].x;
queue->queue[i].y = queue->queue[queue->last].y;
queue->queue[i].movementx = 0;
queue->queue[i].movementy = 0;
queue->queue[i].buttons = queue->queue[queue->last].buttons;
queue->last = i;
return NULL;
// qb64_custom_event(QB64_EVENT_RELATIVE_MOUSE_MOVEMENT,xPosRelative,yPosRelative,0,0,0,0,0,0,NULL,NULL);
if (event == QB64_EVENT_RELATIVE_MOUSE_MOVEMENT) {
qb64_custom_event_relative_mouse_movement(v1, v2);
return 0;
} // QB64_EVENT_RELATIVE_MOUSE_MOVEMENT

if (event == QB64_EVENT_FILE_DROP) {
Expand All @@ -32480,11 +32491,11 @@ extern "C" int qb64_custom_event(int event, int v1, int v2, int v3, int v4, int
hdrop = (HDROP)p1;
totalDroppedFiles = DragQueryFile(hdrop, -1, NULL, 0);
#endif
return NULL;
return 0;
}

return -1; // Unknown command (use for debugging purposes only)
} // qb64_custom_event
}

int32 func__capslock() {
#ifdef QB64_WINDOWS
Expand Down
2 changes: 1 addition & 1 deletion internal/c/libqb/build.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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

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

$(PATH_LIBQB)/src/%.o: $(PATH_LIBQB)/src/%.cpp
Expand Down
11 changes: 11 additions & 0 deletions internal/c/libqb/include/mac-mouse-support.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once

#ifdef QB64_MACOSX
void macMouseInit();
void macMouseDone();
void macMouseUpdatePosition(int x, int y);
#else
static inline void macMouseInit() {}
static inline void macMouseDone() {}
static inline void macMouseUpdatePosition(int x, int y) {}
#endif
46 changes: 23 additions & 23 deletions internal/c/libqb/src/glut-main-thread.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@

#include "libqb-common.h"

#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <GL/glew.h>
#include <list>
#include <queue>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <unordered_map>
#include "GL/glew.h"

// note: MacOSX uses Apple's GLUT not FreeGLUT
#ifdef QB64_MACOSX
Expand All @@ -18,12 +18,13 @@
# include <GL/freeglut.h>
#endif

#include "mutex.h"
#include "thread.h"
#include "completion.h"
#include "glut-thread.h"
#include "gui.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
// somewhere more global so that they can be referenced by libqb.cpp
Expand Down Expand Up @@ -58,20 +59,20 @@ static void glutWarning(const char *fmt, va_list lst) {

// Performs all of the FreeGLUT initialization except for calling glutMainLoop()
static void initialize_glut(int argc, char **argv) {
# ifdef CORE_FREEGLUT
#ifdef CORE_FREEGLUT
glutInitWarningFunc(glutWarning);
glutInitErrorFunc(glutWarning);
# endif
#endif

glutInit(&argc, argv);

mac_register_key_handler();

# ifdef QB64_WINDOWS
#ifdef QB64_WINDOWS
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE);
# else
#else
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
# endif
#endif

glutInitWindowSize(640, 400); // cannot be changed unless display_x(etc) are modified

Expand All @@ -96,11 +97,11 @@ static void initialize_glut(int argc, char **argv) {

glutDisplayFunc(GLUT_DISPLAY_REQUEST);

# ifdef QB64_WINDOWS
#ifdef QB64_WINDOWS
glutTimerFunc(8, GLUT_TIMER_EVENT, 0);
# else
#else
glutIdleFunc(GLUT_IDLEFUNC);
# endif
#endif

glutKeyboardFunc(GLUT_KEYBOARD_FUNC);
glutKeyboardUpFunc(GLUT_KEYBOARDUP_FUNC);
Expand All @@ -111,9 +112,11 @@ static void initialize_glut(int argc, char **argv) {
glutPassiveMotionFunc(GLUT_PASSIVEMOTION_FUNC);
glutReshapeFunc(GLUT_RESHAPE_FUNC);

# ifdef CORE_FREEGLUT
#ifdef CORE_FREEGLUT
glutMouseWheelFunc(GLUT_MOUSEWHEEL_FUNC);
# endif
#endif

macMouseInit();
}

static bool glut_is_started;
Expand All @@ -136,9 +139,7 @@ void libqb_start_glut_thread() {
}

// Checks whether the GLUT thread is running
bool libqb_is_glut_up() {
return glut_is_started;
}
bool libqb_is_glut_up() { return glut_is_started; }

void libqb_glut_presetup(int argc, char **argv) {
if (!screen_hide) {
Expand Down Expand Up @@ -178,8 +179,7 @@ void libqb_start_main_thread(int argc, char **argv) {
// from two threads at the same time).
//
// This is accomplished by simply queuing a GLUT message that calls exit() for us.
void libqb_exit(int exitcode)
{
void libqb_exit(int exitcode) {
// If GLUT isn't running then we're free to do the exit() call from here
if (!libqb_is_glut_up())
exit(exitcode);
Expand Down
3 changes: 2 additions & 1 deletion internal/c/libqb/src/glut-message.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#endif

#include "glut-message.h"
#include "mac-mouse-support.h"

void glut_message_set_cursor::execute() {
glutSetCursor(style);
Expand Down Expand Up @@ -49,6 +50,6 @@ void glut_message_set_window_title::execute() {
}

void glut_message_exit_program::execute() {
macMouseDone();
exit(exitCode);
}

Loading