Merge branch 'master' of ssh://github.com/86Box/86Box into cleanup30
# Conflicts: # src/cdrom/cdrom_image.c # src/cdrom/cdrom_image_backend.c
This commit is contained in:
@@ -22,6 +22,14 @@ endif()
|
||||
find_package(Threads REQUIRED)
|
||||
find_package(Qt${QT_MAJOR} COMPONENTS Core Widgets Network OpenGL REQUIRED)
|
||||
find_package(Qt${QT_MAJOR}LinguistTools REQUIRED)
|
||||
# TODO: Is this the correct way to do this, and is it required on any
|
||||
# other platforms or with Qt 5?
|
||||
if(APPLE AND USE_QT6)
|
||||
find_package(Qt6Gui/Qt6QCocoaIntegrationPlugin REQUIRED)
|
||||
find_package(Qt6Widgets/Qt6QMacStylePlugin REQUIRED)
|
||||
find_package(Qt6Gui/Qt6QICOPlugin REQUIRED)
|
||||
find_package(Qt6Gui/Qt6QICNSPlugin REQUIRED)
|
||||
endif()
|
||||
|
||||
add_library(plat STATIC
|
||||
qt.c
|
||||
@@ -232,17 +240,13 @@ if (APPLE AND CMAKE_MACOSX_BUNDLE)
|
||||
set(INSTALL_CMAKE_DIR "${prefix}/Resources")
|
||||
|
||||
# using the install_qt5_plugin to add Qt plugins into the macOS app bundle
|
||||
if (USE_QT6)
|
||||
install_qt5_plugin("Qt6::QCocoaIntegrationPlugin" QT_PLUGINS ${prefix})
|
||||
else()
|
||||
install_qt5_plugin("Qt5::QCocoaIntegrationPlugin" QT_PLUGINS ${prefix})
|
||||
install_qt5_plugin("Qt5::QMacStylePlugin" QT_PLUGINS ${prefix})
|
||||
install_qt5_plugin("Qt5::QICOPlugin" QT_PLUGINS ${prefix})
|
||||
install_qt5_plugin("Qt5::QICNSPlugin" QT_PLUGINS ${prefix})
|
||||
endif()
|
||||
|
||||
install_qt5_plugin("Qt${QT_MAJOR}::QCocoaIntegrationPlugin" QT_PLUGINS ${prefix})
|
||||
install_qt5_plugin("Qt${QT_MAJOR}::QMacStylePlugin" QT_PLUGINS ${prefix})
|
||||
install_qt5_plugin("Qt${QT_MAJOR}::QICOPlugin" QT_PLUGINS ${prefix})
|
||||
install_qt5_plugin("Qt${QT_MAJOR}::QICNSPlugin" QT_PLUGINS ${prefix})
|
||||
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf"
|
||||
"[Paths]\nPlugins = ${_qt_plugin_dir}\n")
|
||||
"[Paths]\nPlugins = PlugIns\n")
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf"
|
||||
DESTINATION "${INSTALL_CMAKE_DIR}")
|
||||
|
||||
@@ -253,8 +257,8 @@ if (APPLE AND CMAKE_MACOSX_BUNDLE)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# Append Qt's lib folder which is two levels above Qt5Widgets_DIR
|
||||
list(APPEND DIRS "${Qt5Widgets_DIR}/../..")
|
||||
# Append Qt's lib folder which is two levels above Qt*Widgets_DIR
|
||||
list(APPEND DIRS "${Qt${QT_MAJOR}Widgets_DIR}/../..")
|
||||
|
||||
include(InstallRequiredSystemLibraries)
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
* Joystick support
|
||||
@@ -56,7 +56,7 @@ void evdev_thread_func()
|
||||
{
|
||||
while (!stopped)
|
||||
{
|
||||
for (int i = 0; i < evdev_mice.size(); i++)
|
||||
for (unsigned int i = 0; i < evdev_mice.size(); i++)
|
||||
{
|
||||
struct input_event ev;
|
||||
int rc = libevdev_next_event(evdev_mice[i].second, LIBEVDEV_READ_FLAG_NORMAL, &ev);
|
||||
@@ -67,7 +67,7 @@ void evdev_thread_func()
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < evdev_mice.size(); i++)
|
||||
for (unsigned int i = 0; i < evdev_mice.size(); i++)
|
||||
{
|
||||
libevdev_free(evdev_mice[i].second);
|
||||
close(evdev_mice[i].first);
|
||||
|
||||
@@ -117,7 +117,7 @@ void DeviceConfig::ConfigureDevice(const _device_* device, int instance, Setting
|
||||
cbox->setObjectName(config->name);
|
||||
auto* model = cbox->model();
|
||||
int currentIndex = -1;
|
||||
int selected;
|
||||
int selected = 0;
|
||||
switch (config->type) {
|
||||
case CONFIG_SELECTION:
|
||||
selected = config_get_int(device_context.name, const_cast<char*>(config->name), config->default_int);
|
||||
@@ -130,7 +130,7 @@ void DeviceConfig::ConfigureDevice(const _device_* device, int instance, Setting
|
||||
break;
|
||||
}
|
||||
|
||||
for (auto* sel = config->selection; (sel->description != nullptr) && (strlen(sel->description) > 0); ++sel) {
|
||||
for (auto* sel = config->selection; (sel != nullptr) && (sel->description != nullptr) && (strlen(sel->description) > 0); ++sel) {
|
||||
int row = Models::AddEntry(model, sel->description, sel->value);
|
||||
if (selected == sel->value) {
|
||||
currentIndex = row;
|
||||
|
||||
@@ -564,7 +564,7 @@ void HarddiskDialog::onExistingFileSelected(const QString &fileName) {
|
||||
else if (((size % 3072) == 0) && (size <= 53477376))
|
||||
heads = 6;
|
||||
else {
|
||||
int i;
|
||||
uint32_t i;
|
||||
for (i = 5; i < 16; i++) {
|
||||
if (((size % (i << 9)) == 0) && (size <= ((i * 17) << 19)))
|
||||
break;
|
||||
|
||||
@@ -82,6 +82,14 @@ extern "C" {
|
||||
#undef KeyRelease
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
// The namespace is required to avoid clashing typedefs; we only use this
|
||||
// header for its #defines anyway.
|
||||
namespace IOKit {
|
||||
#include <IOKit/hidsystem/IOLLEvent.h>
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __HAIKU__
|
||||
#include <os/AppKit.h>
|
||||
#include <os/InterfaceKit.h>
|
||||
@@ -199,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)
|
||||
ui->stackedWidget->mouse_capture(this->windowHandle());
|
||||
} else {
|
||||
this->releaseKeyboard();
|
||||
#ifdef WAYLAND
|
||||
if (QGuiApplication::platformName().contains("wayland")) {
|
||||
wl_mouse_uncapture();
|
||||
}
|
||||
#endif
|
||||
if (ui->stackedWidget->mouse_uncapture)
|
||||
ui->stackedWidget->mouse_uncapture();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -507,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)
|
||||
ui->stackedWidget->mouse_exit();
|
||||
event->accept();
|
||||
}
|
||||
|
||||
@@ -617,6 +617,7 @@ void MainWindow::on_actionSettings_triggered() {
|
||||
plat_pause(currentPause);
|
||||
}
|
||||
|
||||
#if defined(__unix__) && !defined(__HAIKU__)
|
||||
std::array<uint32_t, 256> x11_to_xt_base
|
||||
{
|
||||
0,
|
||||
@@ -944,7 +945,9 @@ std::array<uint32_t, 256> x11_to_xt_vnc
|
||||
0x14B,
|
||||
0x14D,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
std::array<uint32_t, 256> darwin_to_xt
|
||||
{
|
||||
0x1E,
|
||||
@@ -1076,7 +1079,9 @@ std::array<uint32_t, 256> darwin_to_xt
|
||||
0x148,
|
||||
0,
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(__unix__) && !defined(__HAIKU__)
|
||||
static std::unordered_map<uint32_t, uint16_t> evdev_to_xt =
|
||||
{
|
||||
{96, 0x11C},
|
||||
@@ -1096,6 +1101,7 @@ static std::unordered_map<uint32_t, uint16_t> evdev_to_xt =
|
||||
{110, 0x152},
|
||||
{111, 0x153}
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef __HAIKU__
|
||||
static std::unordered_map<uint8_t, uint16_t> be_to_xt =
|
||||
@@ -1208,14 +1214,16 @@ static std::unordered_map<uint8_t, uint16_t> be_to_xt =
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(__unix__) && !defined(__HAIKU__)
|
||||
static std::array<uint32_t, 256>& selected_keycode = x11_to_xt_base;
|
||||
#endif
|
||||
|
||||
uint16_t x11_keycode_to_keysym(uint32_t keycode)
|
||||
{
|
||||
uint16_t finalkeycode = 0;
|
||||
#if defined(Q_OS_WINDOWS)
|
||||
finalkeycode = (keycode & 0xFFFF);
|
||||
#elif defined(__APPLE__)
|
||||
#elif defined(Q_OS_MACOS)
|
||||
finalkeycode = darwin_to_xt[keycode];
|
||||
#elif defined(__HAIKU__)
|
||||
finalkeycode = be_to_xt[keycode];
|
||||
@@ -1252,6 +1260,68 @@ uint16_t x11_keycode_to_keysym(uint32_t keycode)
|
||||
return finalkeycode;
|
||||
}
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
// These modifiers are listed as "device-dependent" in IOLLEvent.h, but
|
||||
// that's followed up with "(really?)". It's the only way to distinguish
|
||||
// left and right modifiers with Qt 6 on macOS, so let's just roll with it.
|
||||
static std::unordered_map<uint32_t, uint16_t> mac_modifiers_to_xt = {
|
||||
{NX_DEVICELCTLKEYMASK, 0x1D},
|
||||
{NX_DEVICELSHIFTKEYMASK, 0x2A},
|
||||
{NX_DEVICERSHIFTKEYMASK, 0x36},
|
||||
{NX_DEVICELCMDKEYMASK, 0x15B},
|
||||
{NX_DEVICERCMDKEYMASK, 0x15C},
|
||||
{NX_DEVICELALTKEYMASK, 0x38},
|
||||
{NX_DEVICERALTKEYMASK, 0x138},
|
||||
{NX_DEVICE_ALPHASHIFT_STATELESS_MASK, 0x3A},
|
||||
{NX_DEVICERCTLKEYMASK, 0x11D},
|
||||
};
|
||||
|
||||
void MainWindow::processMacKeyboardInput(bool down, const QKeyEvent* event) {
|
||||
// Per QTBUG-69608 (https://bugreports.qt.io/browse/QTBUG-69608),
|
||||
// QKeyEvents QKeyEvents for presses/releases of modifiers on macOS give
|
||||
// nativeVirtualKey() == 0 (at least in Qt 6). Handle this by manually
|
||||
// processing the nativeModifiers(). We need to check whether the key() is
|
||||
// a known modifier because because kVK_ANSI_A is also 0, so the
|
||||
// nativeVirtualKey() == 0 condition is ambiguous...
|
||||
if (event->nativeVirtualKey() == 0
|
||||
&& (event->key() == Qt::Key_Shift
|
||||
|| event->key() == Qt::Key_Control
|
||||
|| event->key() == Qt::Key_Meta
|
||||
|| event->key() == Qt::Key_Alt
|
||||
|| event->key() == Qt::Key_AltGr
|
||||
|| event->key() == Qt::Key_CapsLock)) {
|
||||
// We only process one modifier at a time since events from Qt seem to
|
||||
// always be non-coalesced (NX_NONCOALESCEDMASK is always set).
|
||||
uint32_t changed_modifiers = last_modifiers ^ event->nativeModifiers();
|
||||
for (auto const& pair : mac_modifiers_to_xt) {
|
||||
if (changed_modifiers & pair.first) {
|
||||
last_modifiers ^= pair.first;
|
||||
keyboard_input(down, pair.second);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Caps Lock seems to be delivered as a single key press event when
|
||||
// enabled and a single key release event when disabled, so we can't
|
||||
// detect Caps Lock being held down; just send an infinitesimally-long
|
||||
// press and release as a compromise.
|
||||
//
|
||||
// The event also doesn't get delivered if you turn Caps Lock off after
|
||||
// turning it on when the window isn't focused. Doing better than this
|
||||
// probably requires bypassing Qt input processing.
|
||||
//
|
||||
// It's possible that other lock keys get delivered in this way, but
|
||||
// standard Apple keyboards don't have them, so this is untested.
|
||||
if (event->key() == Qt::Key_CapsLock) {
|
||||
keyboard_input(1, 0x3A);
|
||||
keyboard_input(0, 0x3A);
|
||||
}
|
||||
} else {
|
||||
keyboard_input(down, x11_keycode_to_keysym(event->nativeVirtualKey()));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void MainWindow::on_actionFullscreen_triggered() {
|
||||
if (video_fullscreen > 0) {
|
||||
showNormal();
|
||||
@@ -1370,8 +1440,8 @@ void MainWindow::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
if (send_keyboard_input && !(kbd_req_capture && !mouse_capture && !video_fullscreen))
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
keyboard_input(1, x11_keycode_to_keysym(event->nativeVirtualKey()));
|
||||
#ifdef Q_OS_MACOS
|
||||
processMacKeyboardInput(true, event);
|
||||
#else
|
||||
keyboard_input(1, x11_keycode_to_keysym(event->nativeScanCode()));
|
||||
#endif
|
||||
@@ -1397,8 +1467,8 @@ void MainWindow::keyReleaseEvent(QKeyEvent* event)
|
||||
if (!send_keyboard_input)
|
||||
return;
|
||||
|
||||
#ifdef __APPLE__
|
||||
keyboard_input(0, x11_keycode_to_keysym(event->nativeVirtualKey()));
|
||||
#ifdef Q_OS_MACOS
|
||||
processMacKeyboardInput(false, event);
|
||||
#else
|
||||
keyboard_input(0, x11_keycode_to_keysym(event->nativeScanCode()));
|
||||
#endif
|
||||
|
||||
@@ -118,6 +118,11 @@ private:
|
||||
std::unique_ptr<MachineStatus> status;
|
||||
std::shared_ptr<MediaMenu> mm;
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
uint32_t last_modifiers = 0;
|
||||
void processMacKeyboardInput(bool down, const QKeyEvent* event);
|
||||
#endif
|
||||
|
||||
/* If main window should send keyboard input */
|
||||
bool send_keyboard_input = true;
|
||||
bool shownonce = false;
|
||||
|
||||
@@ -190,7 +190,7 @@ void MediaMenu::cassetteMount(const QString& filename, bool wp) {
|
||||
|
||||
if (! filename.isEmpty()) {
|
||||
QByteArray filenameBytes = filename.toUtf8();
|
||||
strncpy(cassette_fname, filenameBytes.data(), sizeof(cassette_fname));
|
||||
strncpy(cassette_fname, filenameBytes.data(), sizeof(cassette_fname) - 1);
|
||||
pc_cas_set_fname(cassette, cassette_fname);
|
||||
}
|
||||
|
||||
@@ -340,6 +340,9 @@ void MediaMenu::floppyExportTo86f(int i) {
|
||||
void MediaMenu::floppyUpdateMenu(int i) {
|
||||
QString name = floppyfns[i];
|
||||
|
||||
if (!floppyMenus.contains(i))
|
||||
return;
|
||||
|
||||
auto* menu = floppyMenus[i];
|
||||
auto childs = menu->children();
|
||||
|
||||
@@ -419,6 +422,8 @@ void MediaMenu::cdromReload(int i) {
|
||||
|
||||
void MediaMenu::cdromUpdateMenu(int i) {
|
||||
QString name = cdrom[i].image_path;
|
||||
if (!cdromMenus.contains(i))
|
||||
return;
|
||||
auto* menu = cdromMenus[i];
|
||||
auto childs = menu->children();
|
||||
|
||||
@@ -524,6 +529,8 @@ void MediaMenu::zipReload(int i) {
|
||||
void MediaMenu::zipUpdateMenu(int i) {
|
||||
QString name = zip_drives[i].image_path;
|
||||
QString prev_name = zip_drives[i].prev_image_path;
|
||||
if (!zipMenus.contains(i))
|
||||
return;
|
||||
auto* menu = zipMenus[i];
|
||||
auto childs = menu->children();
|
||||
|
||||
@@ -621,6 +628,8 @@ void MediaMenu::moReload(int i) {
|
||||
void MediaMenu::moUpdateMenu(int i) {
|
||||
QString name = mo_drives[i].image_path;
|
||||
QString prev_name = mo_drives[i].prev_image_path;
|
||||
if (!moMenus.contains(i))
|
||||
return;
|
||||
auto* menu = moMenus[i];
|
||||
auto childs = menu->children();
|
||||
|
||||
|
||||
@@ -446,11 +446,6 @@ bool NewFloppyDialog::createZipSectorImage(const QString &filename, const disk_s
|
||||
uint32_t total_size = 0;
|
||||
uint32_t total_sectors = 0;
|
||||
uint32_t sector_bytes = 0;
|
||||
uint32_t root_dir_bytes = 0;
|
||||
uint32_t fat_size = 0;
|
||||
uint32_t fat1_offs = 0;
|
||||
uint32_t fat2_offs = 0;
|
||||
uint32_t zero_bytes = 0;
|
||||
uint16_t base = 0x1000;
|
||||
uint32_t pbar_max = 0;
|
||||
|
||||
@@ -466,11 +461,6 @@ bool NewFloppyDialog::createZipSectorImage(const QString &filename, const disk_s
|
||||
if (total_sectors > ZIP_SECTORS)
|
||||
total_sectors = ZIP_250_SECTORS;
|
||||
total_size = total_sectors * sector_bytes;
|
||||
root_dir_bytes = (disk_size.root_dir_entries << 5);
|
||||
fat_size = (disk_size.spfat * sector_bytes);
|
||||
fat1_offs = sector_bytes;
|
||||
fat2_offs = fat1_offs + fat_size;
|
||||
zero_bytes = fat2_offs + fat_size + root_dir_bytes;
|
||||
|
||||
pbar_max = total_size;
|
||||
if (type == FileType::Zdi) {
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QTemporaryFile>
|
||||
#include <QStandardPaths>
|
||||
#include <QCoreApplication>
|
||||
#include <QDateTime>
|
||||
#include <QLocalSocket>
|
||||
@@ -87,6 +88,7 @@ extern "C" {
|
||||
#include <86box/gameport.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/nvr.h>
|
||||
#include <86box/path.h>
|
||||
#include <86box/plat_dynld.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/rom.h>
|
||||
@@ -139,7 +141,7 @@ void plat_get_exe_name(char *s, int size)
|
||||
|
||||
memcpy(s, exepath_temp.data(), std::min((qsizetype)exepath_temp.size(),(qsizetype)size));
|
||||
|
||||
plat_path_slash(s);
|
||||
path_slash(s);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
@@ -182,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;
|
||||
}
|
||||
|
||||
@@ -194,14 +201,14 @@ plat_get_basename(const char *path)
|
||||
}
|
||||
|
||||
void
|
||||
plat_get_dirname(char *dest, const char *path)
|
||||
path_get_dirname(char *dest, const char *path)
|
||||
{
|
||||
QFileInfo fi(path);
|
||||
CharPointer(dest, -1) = fi.dir().path().toUtf8();
|
||||
}
|
||||
|
||||
char *
|
||||
plat_get_extension(char *s)
|
||||
path_get_extension(char *s)
|
||||
{
|
||||
auto len = strlen(s);
|
||||
auto idx = QByteArray::fromRawData(s, len).lastIndexOf('.');
|
||||
@@ -212,7 +219,7 @@ plat_get_extension(char *s)
|
||||
}
|
||||
|
||||
char *
|
||||
plat_get_filename(char *s)
|
||||
path_get_filename(char *s)
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
int c = strlen(s) - 1;
|
||||
@@ -234,7 +241,7 @@ plat_get_filename(char *s)
|
||||
}
|
||||
|
||||
int
|
||||
plat_path_abs(char *path)
|
||||
path_abs(char *path)
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
if ((path[1] == ':') || (path[0] == '\\') || (path[0] == '/'))
|
||||
@@ -247,7 +254,7 @@ plat_path_abs(char *path)
|
||||
}
|
||||
|
||||
void
|
||||
plat_path_normalize(char* path)
|
||||
path_normalize(char* path)
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
while (*path++ != 0)
|
||||
@@ -258,7 +265,7 @@ plat_path_normalize(char* path)
|
||||
}
|
||||
|
||||
void
|
||||
plat_path_slash(char *path)
|
||||
path_slash(char *path)
|
||||
{
|
||||
auto len = strlen(path);
|
||||
auto separator = '/';
|
||||
@@ -266,14 +273,14 @@ plat_path_slash(char *path)
|
||||
path[len] = separator;
|
||||
path[len+1] = 0;
|
||||
}
|
||||
plat_path_normalize(path);
|
||||
path_normalize(path);
|
||||
}
|
||||
|
||||
void
|
||||
plat_append_filename(char *dest, const char *s1, const char *s2)
|
||||
path_append_filename(char *dest, const char *s1, const char *s2)
|
||||
{
|
||||
strcpy(dest, s1);
|
||||
plat_path_slash(dest);
|
||||
path_slash(dest);
|
||||
strcat(dest, s2);
|
||||
}
|
||||
|
||||
@@ -526,11 +533,6 @@ size_t c16stombs(char dst[], const uint16_t src[], int len)
|
||||
#define LIB_NAME_FREETYPE "libfreetype"
|
||||
#define MOUSE_CAPTURE_KEYSEQ "CTRL-END"
|
||||
#endif
|
||||
#ifdef Q_OS_MACOS
|
||||
#define ROMDIR "~/Library/Application Support/net.86box.86box/roms"
|
||||
#else
|
||||
#define ROMDIR "roms"
|
||||
#endif
|
||||
|
||||
|
||||
QMap<int, std::wstring> ProgSettings::translatedstrings;
|
||||
@@ -556,7 +558,7 @@ void ProgSettings::reloadStrings()
|
||||
translatedstrings[IDS_2128] = QCoreApplication::translate("", "Hardware not available").toStdWString();
|
||||
translatedstrings[IDS_2142] = QCoreApplication::translate("", "Monitor in sleep mode").toStdWString();
|
||||
translatedstrings[IDS_2120] = QCoreApplication::translate("", "No ROMs found").toStdWString();
|
||||
translatedstrings[IDS_2056] = QCoreApplication::translate("", "86Box could not find any usable ROM images.\n\nPlease <a href=\"https://github.com/86Box/roms/releases/latest\">download</a> a ROM set and extract it into the \"roms\" directory.").replace("roms", ROMDIR).toStdWString();
|
||||
translatedstrings[IDS_2056] = QCoreApplication::translate("", "86Box could not find any usable ROM images.\n\nPlease <a href=\"https://github.com/86Box/roms/releases/latest\">download</a> a ROM set and extract it into the \"roms\" directory.").toStdWString();
|
||||
|
||||
auto flsynthstr = QCoreApplication::translate("", " is required for FluidSynth MIDI output.");
|
||||
if (flsynthstr.contains("libfluidsynth"))
|
||||
@@ -596,59 +598,22 @@ plat_chdir(char *path)
|
||||
void
|
||||
plat_init_rom_paths()
|
||||
{
|
||||
#if defined __APPLE__
|
||||
QDir::root().mkpath(QStringLiteral("%1/Documents/86Box/roms/").arg(QDir::homePath()));
|
||||
add_rom_path(QStringLiteral("%1/Documents/86Box/roms/").arg(QDir::homePath()).toUtf8().constData());
|
||||
#elif !defined _WIN32
|
||||
if (getenv("XDG_DATA_HOME")) {
|
||||
char xdg_rom_path[1024 + 1] = { 0 };
|
||||
strncpy(xdg_rom_path, getenv("XDG_DATA_HOME"), 1024);
|
||||
plat_path_slash(xdg_rom_path);
|
||||
strncat(xdg_rom_path, "86Box/", 1024);
|
||||
auto paths = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
|
||||
|
||||
if (!plat_dir_check(xdg_rom_path))
|
||||
plat_dir_create(xdg_rom_path);
|
||||
strcat(xdg_rom_path, "roms/");
|
||||
#ifdef _WIN32
|
||||
// HACK: The standard locations returned for GenericDataLocation include
|
||||
// the EXE path and a `data` directory within it as the last two entries.
|
||||
|
||||
if (!plat_dir_check(xdg_rom_path))
|
||||
plat_dir_create(xdg_rom_path);
|
||||
add_rom_path(xdg_rom_path);
|
||||
} else {
|
||||
char home_rom_path[1024] = { 0 };
|
||||
snprintf(home_rom_path, 1024, "%s/.local/share/86Box/", getenv("HOME") ? getenv("HOME") : QDir::homePath().toUtf8().constData());
|
||||
|
||||
if (!plat_dir_check(home_rom_path))
|
||||
plat_dir_create(home_rom_path);
|
||||
strcat(home_rom_path, "roms/");
|
||||
|
||||
if (!plat_dir_check(home_rom_path))
|
||||
plat_dir_create(home_rom_path);
|
||||
add_rom_path(home_rom_path);
|
||||
}
|
||||
if (getenv("XDG_DATA_DIRS")) {
|
||||
char* xdg_rom_paths = strdup(getenv("XDG_DATA_DIRS"));
|
||||
char* xdg_rom_paths_orig = xdg_rom_paths;
|
||||
char* cur_xdg_rom_path = NULL;
|
||||
if (xdg_rom_paths) {
|
||||
while (xdg_rom_paths[strlen(xdg_rom_paths) - 1] == ':') {
|
||||
xdg_rom_paths[strlen(xdg_rom_paths) - 1] = '\0';
|
||||
}
|
||||
QStringList path_list = QString(xdg_rom_paths).split(":");
|
||||
for (auto& cur_path : path_list) {
|
||||
if (cur_path.right(1) != '/')
|
||||
cur_path.push_back('/');
|
||||
add_rom_path((cur_path + "86Box/roms").toUtf8().constData());
|
||||
}
|
||||
}
|
||||
free(xdg_rom_paths_orig);
|
||||
} else {
|
||||
add_rom_path("/usr/local/share/86Box/roms/");
|
||||
add_rom_path("/usr/share/86Box/roms/");
|
||||
}
|
||||
#elif _WIN32
|
||||
auto appDataDir = QDir(qEnvironmentVariable("LOCALAPPDATA"));
|
||||
appDataDir.mkdir("86Box");
|
||||
appDataDir.mkdir("86Box/roms");
|
||||
add_rom_path((appDataDir.path().replace("\\","/") + "/86Box/roms").toUtf8().constData());
|
||||
// Remove the entries as we don't need them.
|
||||
paths.removeLast();
|
||||
paths.removeLast();
|
||||
#endif
|
||||
|
||||
for (auto& path : paths) {
|
||||
#ifdef __APPLE__
|
||||
rom_add_path(QDir(path).filePath("net.86Box.86Box/roms").toUtf8().constData());
|
||||
#else
|
||||
rom_add_path(QDir(path).filePath("86Box/roms").toUtf8().constData());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,21 +50,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")) {
|
||||
this->mouse_init = wl_init;
|
||||
this->mouse_poll = wl_mouse_poll;
|
||||
this->mouse_capture = wl_mouse_capture;
|
||||
this->mouse_uncapture = wl_mouse_uncapture;
|
||||
} else
|
||||
# endif
|
||||
# ifdef EVDEV_INPUT
|
||||
if (QApplication::platformName() == "eglfs") {
|
||||
evdev_init();
|
||||
}
|
||||
if (!stricmp(mouse_type, "evdev")) {
|
||||
this->mouse_init = evdev_init;
|
||||
this->mouse_poll = evdev_mouse_poll;
|
||||
} else
|
||||
# endif
|
||||
if (QApplication::platformName() == "xcb") {
|
||||
if (!stricmp(mouse_type, "xinput2")) {
|
||||
extern void xinput2_init();
|
||||
xinput2_init();
|
||||
extern void xinput2_poll();
|
||||
extern void xinput2_exit();
|
||||
this->mouse_init = xinput2_init;
|
||||
this->mouse_poll = xinput2_poll;
|
||||
this->mouse_exit = xinput2_exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (this->mouse_init)
|
||||
this->mouse_init();
|
||||
}
|
||||
|
||||
RendererStack::~RendererStack()
|
||||
@@ -104,23 +128,9 @@ RendererStack::mousePoll()
|
||||
mousedata.deltax = mousedata.deltay = mousedata.deltaz = 0;
|
||||
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)
|
||||
this->mouse_poll();
|
||||
#endif /* !defined __APPLE__ */
|
||||
}
|
||||
|
||||
int ignoreNextMouseEvent = 1;
|
||||
@@ -174,7 +184,7 @@ RendererStack::mouseMoveEvent(QMouseEvent *event)
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
#ifdef __APPLE__
|
||||
#if defined __APPLE__ || defined _WIN32
|
||||
event->accept();
|
||||
return;
|
||||
#else
|
||||
|
||||
@@ -64,6 +64,12 @@ public:
|
||||
rendererWindow->onResize(width, height);
|
||||
}
|
||||
|
||||
void (*mouse_init)() = nullptr;
|
||||
void (*mouse_poll)() = nullptr;
|
||||
void (*mouse_capture)(QWindow *window) = nullptr;
|
||||
void (*mouse_uncapture)() = nullptr;
|
||||
void (*mouse_exit)() = nullptr;
|
||||
|
||||
signals:
|
||||
void blitToRenderer(int buf_idx, int x, int y, int w, int h);
|
||||
void rendererChanged();
|
||||
|
||||
@@ -151,7 +151,7 @@ void SettingsHarddisks::save() {
|
||||
hdd[i].spt = idx.siblingAtColumn(ColumnSectors).data().toUInt();
|
||||
|
||||
QByteArray fileName = idx.siblingAtColumn(ColumnFilename).data(Qt::UserRole).toString().toUtf8();
|
||||
strncpy(hdd[i].fn, fileName.data(), sizeof(hdd[i].fn));
|
||||
strncpy(hdd[i].fn, fileName.data(), sizeof(hdd[i].fn) - 1);
|
||||
hdd[i].priv = nullptr;
|
||||
}
|
||||
}
|
||||
@@ -247,12 +247,14 @@ static void addDriveFromDialog(Ui::SettingsHarddisks* ui, const HarddiskDialog&
|
||||
QByteArray fn = dlg.fileName().toUtf8();
|
||||
|
||||
hard_disk_t hd;
|
||||
memset(&hd, 0, sizeof(hd));
|
||||
|
||||
hd.bus = dlg.bus();
|
||||
hd.channel = dlg.channel();
|
||||
hd.tracks = dlg.cylinders();
|
||||
hd.hpc = dlg.heads();
|
||||
hd.spt = dlg.sectors();
|
||||
strncpy(hd.fn, fn.data(), sizeof(hd.fn));
|
||||
strncpy(hd.fn, fn.data(), sizeof(hd.fn) - 1);
|
||||
|
||||
addRow(ui->tableView->model(), &hd);
|
||||
ui->tableView->resizeColumnsToContents();
|
||||
|
||||
@@ -60,7 +60,7 @@ void SoftwareRenderer::onBlit(int buf_idx, int x, int y, int w, int h) {
|
||||
|
||||
cur_image = buf_idx;
|
||||
buf_usage[(buf_idx + 1) % 2].clear();
|
||||
|
||||
|
||||
source.setRect(x, y, w, h);
|
||||
update();
|
||||
}
|
||||
|
||||
@@ -48,7 +48,6 @@ int xi2flides[2] = { 0, 0 };
|
||||
|
||||
static Display* disp = nullptr;
|
||||
static QThread* procThread = nullptr;
|
||||
static bool xi2childinit = false;
|
||||
static XIEventMask ximask;
|
||||
static std::atomic<bool> exitfromthread = false;
|
||||
static std::atomic<double> xi2_mouse_x = 0, xi2_mouse_y = 0, xi2_mouse_abs_x = 0, xi2_mouse_abs_y = 0;
|
||||
@@ -106,7 +105,6 @@ void xinput2_proc()
|
||||
if (XGetEventData(disp, cookie) && cookie->type == GenericEvent && cookie->extension == xi2opcode) {
|
||||
switch (cookie->evtype) {
|
||||
case XI_RawMotion: {
|
||||
static int ss = 0;
|
||||
const XIRawEvent *rawev = (const XIRawEvent*)cookie->data;
|
||||
double relative_coords[2] = { 0., 0. };
|
||||
parse_valuators(rawev->raw_values,rawev->valuators.mask,
|
||||
|
||||
Reference in New Issue
Block a user