diff --git a/.ci/build.sh b/.ci/build.sh index 590119cc4..5442a512f 100644 --- a/.ci/build.sh +++ b/.ci/build.sh @@ -568,59 +568,64 @@ then fi else cwd_root=$(pwd) + cache_dir="$HOME/86box-build-cache" + [ ! -d "$cache_dir" ] && mkdir -p "$cache_dir" if grep -q "OPENAL:BOOL=ON" build/CMakeCache.txt then # Build openal-soft 1.21.1 manually to fix audio issues. This is a temporary # workaround until a newer version of openal-soft trickles down to Debian repos. - if [ -d "openal-soft-1.21.1" ] + prefix="$cache_dir/openal-soft-1.21.1" + if [ -d "$prefix" ] then - rm -rf openal-soft-1.21.1/build + rm -rf "$prefix/build" else - wget -qO - https://github.com/kcat/openal-soft/archive/refs/tags/1.21.1.tar.gz | tar zxf - + wget -qO - https://github.com/kcat/openal-soft/archive/refs/tags/1.21.1.tar.gz | tar zxf - -C "$cache_dir" || rm -rf "$prefix" fi - cmake -G Ninja -D "CMAKE_TOOLCHAIN_FILE=$cwd_root/toolchain.cmake" -D "CMAKE_INSTALL_PREFIX=$cwd_root/archive_tmp/usr" -S openal-soft-1.21.1 -B openal-soft-1.21.1/build || exit 99 - cmake --build openal-soft-1.21.1/build -j$(nproc) || exit 99 - cmake --install openal-soft-1.21.1/build || exit 99 + cmake -G Ninja -D "CMAKE_TOOLCHAIN_FILE=$cwd_root/toolchain.cmake" -D "CMAKE_INSTALL_PREFIX=$cwd_root/archive_tmp/usr" -S "$prefix" -B "$prefix/build" || exit 99 + cmake --build "$prefix/build" -j$(nproc) || exit 99 + cmake --install "$prefix/build" || exit 99 # Build SDL2 without sound systems. sdl_ss=OFF else # Build FAudio 22.03 manually to remove the dependency on GStreamer. This is a temporary # workaround until a newer version of FAudio trickles down to Debian repos. - if [ -d "FAudio-22.03" ] + prefix="$cache_dir/FAudio-22.03" + if [ -d "$prefix" ] then - rm -rf FAudio-22.03/build + rm -rf "$prefix/build" else - wget -qO - https://github.com/FNA-XNA/FAudio/archive/refs/tags/22.03.tar.gz | tar zxf - + wget -qO - https://github.com/FNA-XNA/FAudio/archive/refs/tags/22.03.tar.gz | tar zxf - -C "$cache_dir" || rm -rf "$prefix" fi - cmake -G Ninja -D "CMAKE_TOOLCHAIN_FILE=$cwd_root/toolchain.cmake" -D "CMAKE_INSTALL_PREFIX=$cwd_root/archive_tmp/usr" -S FAudio-22.03 -B FAudio-22.03/build || exit 99 - cmake --build FAudio-22.03/build -j$(nproc) || exit 99 - cmake --install FAudio-22.03/build || exit 99 + cmake -G Ninja -D "CMAKE_TOOLCHAIN_FILE=$cwd_root/toolchain.cmake" -D "CMAKE_INSTALL_PREFIX=$cwd_root/archive_tmp/usr" -S "$prefix" -B "$prefix/build" || exit 99 + cmake --build "$prefix/build" -j$(nproc) || exit 99 + cmake --install "$prefix/build" || exit 99 # Build SDL2 with sound systems. sdl_ss=ON fi # Build rtmidi without JACK support to remove the dependency on libjack. - if [ -d "rtmidi-4.0.0" ] + prefix="$cache_dir/rtmidi-4.0.0" + if [ -d "$prefix" ] then - rm -rf rtmidi-4.0.0/build + rm -rf "$prefix/build" else - wget -qO - http://www.music.mcgill.ca/~gary/rtmidi/release/rtmidi-4.0.0.tar.gz | tar zxf - + wget -qO - https://github.com/thestk/rtmidi/archive/refs/tags/4.0.0.tar.gz | tar zxf - -C "$cache_dir" || rm -rf "$prefix" fi - cmake -G Ninja -D RTMIDI_API_JACK=OFF -D "CMAKE_TOOLCHAIN_FILE=$cwd_root/toolchain.cmake" -D "CMAKE_INSTALL_PREFIX=$cwd_root/archive_tmp/usr" -S rtmidi-4.0.0 -B rtmidi-4.0.0/build || exit 99 - cmake --build rtmidi-4.0.0/build -j$(nproc) || exit 99 - cmake --install rtmidi-4.0.0/build || exit 99 + cmake -G Ninja -D RTMIDI_API_JACK=OFF -D "CMAKE_TOOLCHAIN_FILE=$cwd_root/toolchain.cmake" -D "CMAKE_INSTALL_PREFIX=$cwd_root/archive_tmp/usr" -S "$prefix" -B "$prefix/build" || exit 99 + cmake --build "$prefix/build" -j$(nproc) || exit 99 + cmake --install "$prefix/build" || exit 99 # Build SDL2 for joystick and FAudio support, with most components # disabled to remove the dependencies on PulseAudio and libdrm. - if [ ! -d "SDL2-2.0.20" ] + prefix="$cache_dir/SDL2-2.0.20" + if [ ! -d "$prefix" ] then - wget -qO - https://www.libsdl.org/release/SDL2-2.0.20.tar.gz | tar zxf - + wget -qO - https://www.libsdl.org/release/SDL2-2.0.20.tar.gz | tar zxf - -C "$cache_dir" || rm -rf "$prefix" fi - rm -rf sdlbuild - mkdir sdlbuild + rm -rf "$cache_dir/sdlbuild" cmake -G Ninja -D SDL_DISKAUDIO=OFF -D SDL_DIRECTFB_SHARED=OFF -D SDL_OPENGL=OFF -D SDL_OPENGLES=OFF -D SDL_OSS=OFF -D SDL_ALSA=$sdl_ss \ -D SDL_ALSA_SHARED=$sdl_ss -D SDL_JACK=$sdl_ss -D SDL_JACK_SHARED=$sdl_ss -D SDL_ESD=OFF -D SDL_ESD_SHARED=OFF -D SDL_PIPEWIRE=$sdl_ss \ -D SDL_PIPEWIRE_SHARED=$sdl_ss -D SDL_PULSEAUDIO=$sdl_ss -D SDL_PULSEAUDIO_SHARED=$sdl_ss -D SDL_ARTS=OFF -D SDL_ARTS_SHARED=OFF \ @@ -628,10 +633,10 @@ else -D SDL_FUSIONSOUND_SHARED=OFF -D SDL_LIBSAMPLERATE=$sdl_ss -D SDL_LIBSAMPLERATE_SHARED=$sdl_ss -D SDL_X11=OFF -D SDL_X11_SHARED=OFF \ -D SDL_WAYLAND=OFF -D SDL_WAYLAND_SHARED=OFF -D SDL_WAYLAND_LIBDECOR=OFF -D SDL_WAYLAND_LIBDECOR_SHARED=OFF -D SDL_WAYLAND_QT_TOUCH=OFF \ -D SDL_RPI=OFF -D SDL_VIVANTE=OFF -D SDL_VULKAN=OFF -D SDL_KMSDRM=OFF -D SDL_KMSDRM_SHARED=OFF -D SDL_OFFSCREEN=OFF \ - -D SDL_HIDAPI_JOYSTICK=ON -D SDL_VIRTUAL_JOYSTICK=ON -D SDL_SHARED=ON -D SDL_STATIC=OFF -S SDL2-2.0.20 -B sdlbuild \ + -D SDL_HIDAPI_JOYSTICK=ON -D SDL_VIRTUAL_JOYSTICK=ON -D SDL_SHARED=ON -D SDL_STATIC=OFF -S "$prefix" -B "$cache_dir/sdlbuild" \ -D "CMAKE_TOOLCHAIN_FILE=$cwd_root/toolchain.cmake" -D "CMAKE_INSTALL_PREFIX=$cwd_root/archive_tmp/usr" || exit 99 - cmake --build sdlbuild -j$(nproc) || exit 99 - cmake --install sdlbuild || exit 99 + cmake --build "$cache_dir/sdlbuild" -j$(nproc) || exit 99 + cmake --install "$cache_dir/sdlbuild" || exit 99 # Archive Discord Game SDK library. 7z e -y -o"archive_tmp/usr/lib" discord_game_sdk.zip "lib/$arch_discord/discord_game_sdk.so" diff --git a/CMakeLists.txt b/CMakeLists.txt index 294f5b55d..85920bc10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,7 +35,7 @@ if(MUNT_EXTERNAL) endif() project(86Box - VERSION 3.4 + VERSION 3.4.1 DESCRIPTION "Emulator of x86-based systems" HOMEPAGE_URL "https://86box.net" LANGUAGES C CXX) diff --git a/src/86box.c b/src/86box.c index 4b647afed..720e33279 100644 --- a/src/86box.c +++ b/src/86box.c @@ -398,9 +398,6 @@ pc_init(int argc, char *argv[]) { char *ppath = NULL, *rpath = NULL; char *cfg = NULL, *p; -#if !defined(__APPLE__) && !defined(_WIN32) - char *appimage; -#endif char temp[2048]; struct tm *info; time_t now; @@ -413,15 +410,20 @@ pc_init(int argc, char *argv[]) /* Grab the executable's full path. */ plat_get_exe_name(exe_path, sizeof(exe_path)-1); - p = path_get_filename(exe_path); + p = path_get_filename(exe_path); *p = '\0'; - -#if !defined(_WIN32) && !defined(__APPLE__) - /* Grab the actual path if we are an AppImage. */ - appimage = getenv("APPIMAGE"); - if (appimage && (appimage[0] != '\0')) { - path_get_dirname(exe_path, appimage); +#if defined(__APPLE__) + c = strlen(exe_path); + if ((c >= 16) && !strcmp(&exe_path[c - 16], "/Contents/MacOS/")) { + exe_path[c - 16] = '\0'; + p = path_get_filename(exe_path); + *p = '\0'; } +#elif !defined(_WIN32) + /* Grab the actual path if we are an AppImage. */ + p = getenv("APPIMAGE"); + if (p && (p[0] != '\0')) + path_get_dirname(exe_path, p); #endif path_slash(exe_path); diff --git a/src/include_make/86box/version.h b/src/include_make/86box/version.h index 8bf418791..f1f0719dd 100644 --- a/src/include_make/86box/version.h +++ b/src/include_make/86box/version.h @@ -22,10 +22,10 @@ #define EMU_VERSION "3.4" #define EMU_VERSION_W LSTR(EMU_VERSION) -#define EMU_VERSION_EX "3.40" +#define EMU_VERSION_EX "3.41" #define EMU_VERSION_MAJ 3 #define EMU_VERSION_MIN 4 -#define EMU_VERSION_PATCH 0 +#define EMU_VERSION_PATCH 1 #define EMU_BUILD_NUM 0 @@ -40,7 +40,7 @@ #define EMU_ROMS_URL "https://github.com/86Box/roms/releases/latest" #define EMU_ROMS_URL_W LSTR(EMU_ROMS_URL) #ifdef RELEASE_BUILD -# define EMU_DOCS_URL "https://86box.readthedocs.io/en/v3.2/" +# define EMU_DOCS_URL "https://86box.readthedocs.io/en/v3.4/" #else # define EMU_DOCS_URL "https://86box.readthedocs.io" #endif diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 09676ee34..dce5ef470 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -207,18 +207,12 @@ MainWindow::MainWindow(QWidget *parent) : qt_mouse_capture(mouse_capture); if (mouse_capture) { this->grabKeyboard(); -#ifdef WAYLAND - if (QGuiApplication::platformName().contains("wayland")) { - wl_mouse_capture(this->windowHandle()); - } -#endif + if (ui->stackedWidget->mouse_capture_func) + ui->stackedWidget->mouse_capture_func(this->windowHandle()); } else { this->releaseKeyboard(); -#ifdef WAYLAND - if (QGuiApplication::platformName().contains("wayland")) { - wl_mouse_uncapture(); - } -#endif + if (ui->stackedWidget->mouse_uncapture_func) + ui->stackedWidget->mouse_uncapture_func(); } }); @@ -515,10 +509,8 @@ void MainWindow::closeEvent(QCloseEvent *event) { } qt_nvr_save(); config_save(); -#if defined __unix__ && !defined __HAIKU__ - extern void xinput2_exit(); - if (QApplication::platformName() == "xcb") xinput2_exit(); -#endif + if (ui->stackedWidget->mouse_exit_func) + ui->stackedWidget->mouse_exit_func(); event->accept(); } diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index 499c6bbac..9a2f2d8a2 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -184,7 +184,12 @@ plat_dir_check(char *path) int plat_getcwd(char *bufp, int max) { +#ifdef __APPLE__ + /* Working directory for .app bundles is undefined. */ + strncpy(bufp, exe_path, max); +#else CharPointer(bufp, max) = QDir::currentPath().toUtf8(); +#endif return 0; } diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp index 88b2395d5..a78202d05 100644 --- a/src/qt/qt_rendererstack.cpp +++ b/src/qt/qt_rendererstack.cpp @@ -42,6 +42,7 @@ extern "C" { #include <86box/video.h> } +extern "C" void macos_poll_mouse(); extern MainWindow *main_window; RendererStack::RendererStack(QWidget *parent) : QStackedWidget(parent) @@ -50,21 +51,45 @@ RendererStack::RendererStack(QWidget *parent) ui->setupUi(this); #if defined __unix__ && !defined __HAIKU__ -# ifdef WAYLAND - if (QApplication::platformName().contains("wayland")) { - wl_init(); + char *mouse_type = getenv("EMU86BOX_MOUSE"), auto_mouse_type[16]; + if (!mouse_type || (mouse_type[0] == '\0') || !stricmp(mouse_type, "auto")) { + if (QApplication::platformName().contains("wayland")) + strcpy(auto_mouse_type, "wayland"); + else if (QApplication::platformName() == "eglfs") + strcpy(auto_mouse_type, "evdev"); + else if (QApplication::platformName() == "xcb") + strcpy(auto_mouse_type, "xinput2"); + else + auto_mouse_type[0] = '\0'; + mouse_type = auto_mouse_type; } + +# ifdef WAYLAND + if (!stricmp(mouse_type, "wayland")) { + wl_init(); + this->mouse_poll_func = wl_mouse_poll; + this->mouse_capture_func = wl_mouse_capture; + this->mouse_uncapture_func = wl_mouse_uncapture; + } else # endif # ifdef EVDEV_INPUT - if (QApplication::platformName() == "eglfs") { + if (!stricmp(mouse_type, "evdev")) { evdev_init(); - } + this->mouse_poll_func = evdev_mouse_poll; + } else # endif - if (QApplication::platformName() == "xcb") { + if (!stricmp(mouse_type, "xinput2")) { extern void xinput2_init(); + extern void xinput2_poll(); + extern void xinput2_exit(); xinput2_init(); + this->mouse_poll_func = xinput2_poll; + this->mouse_exit_func = xinput2_exit; } #endif +#ifdef __APPLE__ + this->mouse_poll_func = macos_poll_mouse; +#endif } RendererStack::~RendererStack() @@ -72,7 +97,6 @@ RendererStack::~RendererStack() delete ui; } -extern "C" void macos_poll_mouse(); void qt_mouse_capture(int on) { @@ -95,32 +119,16 @@ qt_mouse_capture(int on) void RendererStack::mousePoll() { -#ifdef __APPLE__ - return macos_poll_mouse(); -#else /* !defined __APPLE__ */ +#ifndef __APPLE__ mouse_x = mousedata.deltax; mouse_y = mousedata.deltay; mouse_z = mousedata.deltaz; mousedata.deltax = mousedata.deltay = mousedata.deltaz = 0; - mouse_buttons = mousedata.mousebuttons; + mouse_buttons = mousedata.mousebuttons; -# if defined __unix__ && !defined __HAIKU__ -# ifdef WAYLAND - if (QApplication::platformName().contains("wayland")) - wl_mouse_poll(); -# endif - -# ifdef EVDEV_INPUT - if (QApplication::platformName() == "eglfs") - evdev_mouse_poll(); - else -# endif - if (QApplication::platformName() == "xcb") { - extern void xinput2_poll(); - xinput2_poll(); - } -# endif /* defined __unix__ */ -#endif /* !defined __APPLE__ */ + if (this->mouse_poll_func) +#endif + this->mouse_poll_func(); } int ignoreNextMouseEvent = 1; diff --git a/src/qt/qt_rendererstack.hpp b/src/qt/qt_rendererstack.hpp index 9133a4927..6e4fa23d4 100644 --- a/src/qt/qt_rendererstack.hpp +++ b/src/qt/qt_rendererstack.hpp @@ -64,6 +64,11 @@ public: rendererWindow->onResize(width, height); } + void (*mouse_poll_func)() = nullptr; + void (*mouse_capture_func)(QWindow *window) = nullptr; + void (*mouse_uncapture_func)() = nullptr; + void (*mouse_exit_func)() = nullptr; + signals: void blitToRenderer(int buf_idx, int x, int y, int w, int h); void rendererChanged();