mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2024-12-29 11:06:07 +00:00
imgui/renderer: Hide Cursor on Idle Implementation (#1266)
Implement hide cursor on idle w/ idle timeout duration (configurable via GUI). While at it add always and never to hide the cursor options as well. * Revert commit #1211 as to not interfere with the cursor states. * Make hide cursor on idle as the default setting w/ timeout duration of 5 seconds to hide. * Add an input tab in the settings page to add the hide cursor setting, with hiding the idle timeout box with respect to the cursor hide option. Co-authored-by: georgemoralis <giorgosmrls@gmail.com>
This commit is contained in:
parent
96344873d6
commit
f139762c64
|
@ -57,6 +57,8 @@ static bool vkValidationGpu = false;
|
|||
static bool rdocEnable = false;
|
||||
static bool vkMarkers = false;
|
||||
static bool vkCrashDiagnostic = false;
|
||||
static s16 cursorState = HideCursorState::Idle;
|
||||
static int cursorHideTimeout = 5; // 5 seconds (default)
|
||||
|
||||
// Gui
|
||||
std::filesystem::path settings_install_dir = {};
|
||||
|
@ -96,6 +98,14 @@ int getBGMvolume() {
|
|||
return BGMvolume;
|
||||
}
|
||||
|
||||
s16 getCursorState() {
|
||||
return cursorState;
|
||||
}
|
||||
|
||||
int getCursorHideTimeout() {
|
||||
return cursorHideTimeout;
|
||||
}
|
||||
|
||||
u32 getScreenWidth() {
|
||||
return screenWidth;
|
||||
}
|
||||
|
@ -256,6 +266,14 @@ void setBGMvolume(int volume) {
|
|||
BGMvolume = volume;
|
||||
}
|
||||
|
||||
void setCursorState(s16 newCursorState) {
|
||||
cursorState = newCursorState;
|
||||
}
|
||||
|
||||
void setCursorHideTimeout(int newcursorHideTimeout) {
|
||||
cursorHideTimeout = newcursorHideTimeout;
|
||||
}
|
||||
|
||||
void setLanguage(u32 language) {
|
||||
m_language = language;
|
||||
}
|
||||
|
@ -450,6 +468,8 @@ void load(const std::filesystem::path& path) {
|
|||
if (data.contains("Input")) {
|
||||
const toml::value& input = data.at("Input");
|
||||
|
||||
cursorState = toml::find_or<int>(input, "cursorState", HideCursorState::Idle);
|
||||
cursorHideTimeout = toml::find_or<int>(input, "cursorHideTimeout", 5);
|
||||
useSpecialPad = toml::find_or<bool>(input, "useSpecialPad", false);
|
||||
specialPadClass = toml::find_or<int>(input, "specialPadClass", 1);
|
||||
}
|
||||
|
@ -543,6 +563,8 @@ void save(const std::filesystem::path& path) {
|
|||
data["General"]["updateChannel"] = updateChannel;
|
||||
data["General"]["showSplash"] = isShowSplash;
|
||||
data["General"]["autoUpdate"] = isAutoUpdate;
|
||||
data["Input"]["cursorState"] = cursorState;
|
||||
data["Input"]["cursorHideTimeout"] = cursorHideTimeout;
|
||||
data["General"]["backButtonBehavior"] = backButtonBehavior;
|
||||
data["Input"]["useSpecialPad"] = useSpecialPad;
|
||||
data["Input"]["specialPadClass"] = specialPadClass;
|
||||
|
@ -592,6 +614,8 @@ void setDefaultValues() {
|
|||
isFullscreen = false;
|
||||
playBGM = false;
|
||||
BGMvolume = 50;
|
||||
cursorState = HideCursorState::Idle;
|
||||
cursorHideTimeout = 5;
|
||||
screenWidth = 1280;
|
||||
screenHeight = 720;
|
||||
logFilter = "";
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
#include "types.h"
|
||||
|
||||
namespace Config {
|
||||
|
||||
enum HideCursorState : s16 { Never, Idle, Always };
|
||||
|
||||
void load(const std::filesystem::path& path);
|
||||
void save(const std::filesystem::path& path);
|
||||
|
||||
|
@ -16,6 +19,9 @@ bool isFullscreenMode();
|
|||
bool getPlayBGM();
|
||||
int getBGMvolume();
|
||||
|
||||
s16 getCursorState();
|
||||
int getCursorHideTimeout();
|
||||
|
||||
std::string getLogFilter();
|
||||
std::string getLogType();
|
||||
std::string getUserName();
|
||||
|
@ -51,6 +57,8 @@ void setScreenHeight(u32 height);
|
|||
void setFullscreenMode(bool enable);
|
||||
void setPlayBGM(bool enable);
|
||||
void setBGMvolume(int volume);
|
||||
void setCursorState(s16 cursorState);
|
||||
void setCursorHideTimeout(int newcursorHideTimeout);
|
||||
void setLanguage(u32 language);
|
||||
void setNeoMode(bool enable);
|
||||
void setUserName(const std::string& type);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
// Based on imgui_impl_sdl3.cpp from Dear ImGui repository
|
||||
|
||||
#include <imgui.h>
|
||||
#include "common/config.h"
|
||||
#include "imgui_impl_sdl3.h"
|
||||
|
||||
// SDL
|
||||
|
@ -36,6 +37,8 @@ struct SdlData {
|
|||
SDL_Cursor* mouse_cursors[ImGuiMouseCursor_COUNT]{};
|
||||
SDL_Cursor* mouse_last_cursor{};
|
||||
int mouse_pending_leave_frame{};
|
||||
ImVec2 prev_mouse_pos{0, 0};
|
||||
Uint64 lastCursorMoveTime{};
|
||||
|
||||
// Gamepad handling
|
||||
ImVector<SDL_Gamepad*> gamepads{};
|
||||
|
@ -371,6 +374,13 @@ bool ProcessEvent(const SDL_Event* event) {
|
|||
? ImGuiMouseSource_TouchScreen
|
||||
: ImGuiMouseSource_Mouse);
|
||||
io.AddMousePosEvent(mouse_pos.x, mouse_pos.y);
|
||||
if (mouse_pos.x != bd->prev_mouse_pos.x || mouse_pos.y != bd->prev_mouse_pos.y) {
|
||||
bd->prev_mouse_pos.x = mouse_pos.x;
|
||||
bd->prev_mouse_pos.y = mouse_pos.y;
|
||||
if (Config::getCursorState() == Config::HideCursorState::Idle) {
|
||||
bd->lastCursorMoveTime = bd->time;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case SDL_EVENT_MOUSE_WHEEL: {
|
||||
|
@ -447,6 +457,7 @@ bool ProcessEvent(const SDL_Event* event) {
|
|||
return false;
|
||||
bd->mouse_window_id = event->window.windowID;
|
||||
bd->mouse_pending_leave_frame = 0;
|
||||
bd->lastCursorMoveTime = bd->time;
|
||||
return true;
|
||||
}
|
||||
// - In some cases, when detaching a window from main viewport SDL may send
|
||||
|
@ -459,6 +470,7 @@ bool ProcessEvent(const SDL_Event* event) {
|
|||
if (GetViewportForWindowId(event->window.windowID) == NULL)
|
||||
return false;
|
||||
bd->mouse_pending_leave_frame = ImGui::GetFrameCount() + 1;
|
||||
bd->lastCursorMoveTime = bd->time;
|
||||
return true;
|
||||
}
|
||||
case SDL_EVENT_WINDOW_FOCUS_GAINED:
|
||||
|
@ -600,7 +612,18 @@ static void UpdateMouseData() {
|
|||
int window_x, window_y;
|
||||
SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global);
|
||||
SDL_GetWindowPosition(focused_window, &window_x, &window_y);
|
||||
io.AddMousePosEvent(mouse_x_global - (float)window_x, mouse_y_global - (float)window_y);
|
||||
mouse_x_global -= (float)window_x;
|
||||
mouse_y_global -= (float)window_y;
|
||||
io.AddMousePosEvent(mouse_x_global, mouse_y_global);
|
||||
// SDL_EVENT_MOUSE_MOTION isn't triggered before the first frame is rendered
|
||||
// force update the prev_cursor coords
|
||||
if (mouse_x_global != bd->prev_mouse_pos.x || mouse_y_global != bd->prev_mouse_pos.y &&
|
||||
bd->prev_mouse_pos.y == 0 &&
|
||||
bd->prev_mouse_pos.x == 0) {
|
||||
bd->prev_mouse_pos.x = mouse_x_global;
|
||||
bd->prev_mouse_pos.y = mouse_y_global;
|
||||
bd->lastCursorMoveTime = bd->time;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -611,10 +634,25 @@ static void UpdateMouseCursor() {
|
|||
return;
|
||||
SdlData* bd = GetBackendData();
|
||||
|
||||
s16 cursorState = Config::getCursorState();
|
||||
ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
|
||||
if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None) {
|
||||
if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None ||
|
||||
cursorState == Config::HideCursorState::Always) {
|
||||
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
|
||||
SDL_HideCursor();
|
||||
|
||||
} else if (cursorState == Config::HideCursorState::Idle &&
|
||||
bd->time - bd->lastCursorMoveTime >=
|
||||
Config::getCursorHideTimeout() * SDL_GetPerformanceFrequency()) {
|
||||
|
||||
bool wasCursorVisible = SDL_CursorVisible();
|
||||
SDL_HideCursor();
|
||||
|
||||
if (wasCursorVisible) {
|
||||
SDL_WarpMouseInWindow(SDL_GetKeyboardFocus(), bd->prev_mouse_pos.x,
|
||||
bd->prev_mouse_pos.y); // Force refresh the cursor state
|
||||
}
|
||||
|
||||
} else {
|
||||
// Show OS mouse cursor
|
||||
SDL_Cursor* expected_cursor = bd->mouse_cursors[imgui_cursor]
|
||||
|
|
|
@ -47,6 +47,8 @@ QStringList languageNames = {"Arabic",
|
|||
const QVector<int> languageIndexes = {21, 23, 14, 6, 18, 1, 12, 22, 2, 4, 25, 24, 29, 5, 0,
|
||||
9, 15, 16, 17, 7, 26, 8, 11, 20, 3, 13, 27, 10, 19, 28};
|
||||
|
||||
QStringList hideCursorStates = {"Never", "Idle", "Always"};
|
||||
|
||||
SettingsDialog::SettingsDialog(std::span<const QString> physical_devices, QWidget* parent)
|
||||
: QDialog(parent), ui(new Ui::SettingsDialog) {
|
||||
ui->setupUi(this);
|
||||
|
@ -67,6 +69,8 @@ SettingsDialog::SettingsDialog(std::span<const QString> physical_devices, QWidge
|
|||
completer->setCaseSensitivity(Qt::CaseInsensitive);
|
||||
ui->consoleLanguageComboBox->setCompleter(completer);
|
||||
|
||||
ui->hideCursorComboBox->addItems(hideCursorStates);
|
||||
|
||||
InitializeEmulatorLanguages();
|
||||
LoadValuesFromConfig();
|
||||
|
||||
|
@ -170,6 +174,18 @@ SettingsDialog::SettingsDialog(std::span<const QString> physical_devices, QWidge
|
|||
});
|
||||
}
|
||||
|
||||
// Input TAB
|
||||
{
|
||||
connect(ui->hideCursorComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
||||
[this](s16 index) {
|
||||
Config::setCursorState(index);
|
||||
OnCursorStateChanged(index);
|
||||
});
|
||||
|
||||
connect(ui->idleTimeoutSpinBox, &QSpinBox::valueChanged, this,
|
||||
[](int index) { Config::setCursorHideTimeout(index); });
|
||||
}
|
||||
|
||||
// GPU TAB
|
||||
{
|
||||
// First options is auto selection -1, so gpuId on the GUI will always have to subtract 1
|
||||
|
@ -246,6 +262,9 @@ void SettingsDialog::LoadValuesFromConfig() {
|
|||
std::find(languageIndexes.begin(), languageIndexes.end(), Config::GetLanguage())) %
|
||||
languageIndexes.size());
|
||||
ui->emulatorLanguageComboBox->setCurrentIndex(languages[Config::getEmulatorLanguage()]);
|
||||
ui->hideCursorComboBox->setCurrentIndex(Config::getCursorState());
|
||||
OnCursorStateChanged(Config::getCursorState());
|
||||
ui->idleTimeoutSpinBox->setValue(Config::getCursorHideTimeout());
|
||||
ui->graphicsAdapterBox->setCurrentIndex(Config::getGpuId() + 1);
|
||||
ui->widthSpinBox->setValue(Config::getScreenWidth());
|
||||
ui->heightSpinBox->setValue(Config::getScreenHeight());
|
||||
|
@ -311,6 +330,18 @@ void SettingsDialog::OnLanguageChanged(int index) {
|
|||
emit LanguageChanged(ui->emulatorLanguageComboBox->itemData(index).toString().toStdString());
|
||||
}
|
||||
|
||||
void SettingsDialog::OnCursorStateChanged(s16 index) {
|
||||
if (index == -1)
|
||||
return;
|
||||
if (index == Config::HideCursorState::Idle) {
|
||||
ui->idleTimeoutGroupBox->show();
|
||||
} else {
|
||||
if (!ui->idleTimeoutGroupBox->isHidden()) {
|
||||
ui->idleTimeoutGroupBox->hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int SettingsDialog::exec() {
|
||||
return QDialog::exec();
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ private:
|
|||
void LoadValuesFromConfig();
|
||||
void InitializeEmulatorLanguages();
|
||||
void OnLanguageChanged(int index);
|
||||
void OnCursorStateChanged(s16 index);
|
||||
|
||||
std::unique_ptr<Ui::SettingsDialog> ui;
|
||||
|
||||
|
|
|
@ -34,9 +34,18 @@
|
|||
<iconset>
|
||||
<normaloff>:/images/shadps4.ico</normaloff>:/images/shadps4.ico</iconset>
|
||||
</property>
|
||||
<property name="sizeGripEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="modal">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="settingsDialogLayout">
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Shape::NoFrame</enum>
|
||||
</property>
|
||||
|
@ -51,8 +60,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>836</width>
|
||||
<height>446</height>
|
||||
<width>832</width>
|
||||
<height>431</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
@ -62,7 +71,7 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
<number>1</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="generalTab">
|
||||
<attribute name="title">
|
||||
|
@ -369,7 +378,7 @@
|
|||
<x>10</x>
|
||||
<y>30</y>
|
||||
<width>241</width>
|
||||
<height>71</height>
|
||||
<height>92</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
|
@ -485,6 +494,185 @@
|
|||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="inputTab">
|
||||
<attribute name="title">
|
||||
<string>Input</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="inputTabVLayout" stretch="0,0">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="inputTabHLayoutTop" stretch="1,1,1">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="cursorTabLayoutLeft">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="HideCursor">
|
||||
<property name="title">
|
||||
<string>Cursor</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="inputCursorLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="hideCursorGroupBox">
|
||||
<property name="title">
|
||||
<string>Hide Cursor</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="hideCursorLayout">
|
||||
<item>
|
||||
<widget class="QComboBox" name="hideCursorComboBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="idleTimeoutGroupBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>85</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Hide Cursor Idle Timeout</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="IdleTimeoutLayout" stretch="0,0">
|
||||
<property name="leftMargin">
|
||||
<number>70</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="idleTimeoutSpinBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LayoutDirection::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="wrapping">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::ButtonSymbols::UpDownArrows</enum>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>3600</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="displayIntegerBase">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="idleTimeoutDurationLabel">
|
||||
<property name="text">
|
||||
<string>s</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="emptyTabLayoutMiddle">
|
||||
<item>
|
||||
<spacer name="emptyHorizontalSpacerMiddle">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="emptyTabLayoutRight">
|
||||
<item>
|
||||
<spacer name="emptyHorizontalSpacerRight">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="inputTabHLayoutBottom">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="emptyVerticalSpacerBottom">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Policy::MinimumExpanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="grphicsTab">
|
||||
<attribute name="title">
|
||||
<string>Graphics</string>
|
||||
|
|
|
@ -313,9 +313,6 @@ void WindowSDL::onKeyPress(const SDL_Event* event) {
|
|||
if (axis != Input::Axis::AxisMax) {
|
||||
controller->Axis(0, axis, ax);
|
||||
}
|
||||
if (SDL_GetCursor() != NULL) {
|
||||
SDL_HideCursor();
|
||||
}
|
||||
}
|
||||
|
||||
void WindowSDL::onGamepadEvent(const SDL_Event* event) {
|
||||
|
@ -354,9 +351,6 @@ void WindowSDL::onGamepadEvent(const SDL_Event* event) {
|
|||
controller->CheckButton(0, button, event->type == SDL_EVENT_GAMEPAD_BUTTON_DOWN);
|
||||
}
|
||||
}
|
||||
if (SDL_GetCursor() != NULL) {
|
||||
SDL_HideCursor();
|
||||
}
|
||||
break;
|
||||
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
|
||||
axis = event->gaxis.axis == SDL_GAMEPAD_AXIS_LEFTX ? Input::Axis::LeftX
|
||||
|
|
Loading…
Reference in a new issue