diff --git a/etc/iptsd.conf b/etc/iptsd.conf index 140fb2b..4017441 100644 --- a/etc/iptsd.conf +++ b/etc/iptsd.conf @@ -24,6 +24,15 @@ ## # DisableOnStylus = false + +## +## What condition the stylus must be in to disable the touchscreen if DisableOnStylus = true +## connected - Disable if stylus is sending packets (old behavior and default) +## active - Disable if stylus is hovering or being used +## contact - Disable if stylus is in contact with the screen +## +# DisableOnStylusLevel = connected + ## ## How many centimeters a contact can be outside of the screen and still get registered. ## diff --git a/src/apps/daemon/daemon.hpp b/src/apps/daemon/daemon.hpp index 5a633fd..a166c7a 100644 --- a/src/apps/daemon/daemon.hpp +++ b/src/apps/daemon/daemon.hpp @@ -20,6 +20,14 @@ namespace iptsd::apps::daemon { class Daemon : public core::Application { +private: + // Put this enum here as this class is the only one that needs to quickly reference it + enum class DisableOnStylusLevel : u8 { + Connected = 0, + Active, + Contact, + }; + private: // The touch device. std::optional m_touch = std::nullopt; @@ -27,6 +35,9 @@ class Daemon : public core::Application { // The stylus device. std::optional m_stylus = std::nullopt; + // The state of the config setting Touchscreen.DisableOnStylusLevel + DisableOnStylusLevel m_disable_on_stylus_level = DisableOnStylusLevel::Connected; + public: Daemon(const core::Config &config, const core::DeviceInfo &info) : core::Application(config, info) @@ -40,6 +51,13 @@ class Daemon : public core::Application { if (m_info.is_touchscreen() && !m_config.stylus_disable) m_stylus.emplace(config, info); + + if (m_config.touchscreen_disable_on_stylus_level == "active") + m_disable_on_stylus_level = DisableOnStylusLevel::Active; + else if (m_config.touchscreen_disable_on_stylus_level == "contact") + m_disable_on_stylus_level = DisableOnStylusLevel::Contact; + else // catch nonexistent/invalid level as connected, which is the old behavior + m_disable_on_stylus_level = DisableOnStylusLevel::Connected; } void on_start() override @@ -61,8 +79,17 @@ class Daemon : public core::Application { // Enable the touchscreen if it was disabled by a stylus that is no longer active. if (m_config.touchscreen_disable_on_stylus && m_stylus.has_value()) { - if (!m_stylus->active() && !m_touch->enabled()) - m_touch->enable(); + if ((m_disable_on_stylus_level == DisableOnStylusLevel::Active && + !m_stylus->active()) || + (m_disable_on_stylus_level == DisableOnStylusLevel::Contact && + !m_stylus->contact()) || + // stylus cant report a state after its disconnected (obviously), so + // just check if its active for reenabling after connection (this was + // the old behavior) + (m_disable_on_stylus_level == DisableOnStylusLevel::Connected && + !m_stylus->active())) + if (!m_touch->enabled()) + m_touch->enable(); } m_touch->update(contacts); @@ -82,8 +109,13 @@ class Daemon : public core::Application { return; if (m_config.touchscreen_disable_on_stylus && m_touch.has_value()) { - if (m_touch->enabled()) - m_touch->disable(); + if ((m_disable_on_stylus_level == DisableOnStylusLevel::Active && + m_stylus->active()) || + (m_disable_on_stylus_level == DisableOnStylusLevel::Contact && + m_stylus->contact()) || + (m_disable_on_stylus_level == DisableOnStylusLevel::Connected)) + if (m_touch->enabled()) + m_touch->disable(); } m_stylus->update(stylus); diff --git a/src/apps/daemon/stylus.hpp b/src/apps/daemon/stylus.hpp index 70ae415..1123034 100644 --- a/src/apps/daemon/stylus.hpp +++ b/src/apps/daemon/stylus.hpp @@ -36,6 +36,9 @@ class StylusDevice { // Whether the stylus is currently in proximity and sending data. bool m_active = false; + // Whether the stylus is making contact with the screen + bool m_contact = false; + // The last known state of the stylus. ipts::samples::Stylus m_last; @@ -82,6 +85,7 @@ class StylusDevice { void update(const ipts::samples::Stylus &data) { m_active = data.proximity; + m_contact = data.contact; // Switching tools within one frame causes issues, lift the stylus for one frame. if (m_last.rubber != data.rubber) @@ -156,6 +160,16 @@ class StylusDevice { return m_active; } + /*! + * Whether the stylus is currently making contact with the screen. + * + * @return true if, well, it speaks for itself. + */ + [[nodiscard]] bool contact() const + { + return m_contact; + } + private: /*! * Calculates the tilt of the stylus on X and Y axis. diff --git a/src/core/generic/config.hpp b/src/core/generic/config.hpp index f16553d..3fc2aa9 100644 --- a/src/core/generic/config.hpp +++ b/src/core/generic/config.hpp @@ -28,6 +28,7 @@ class Config { bool touchscreen_disable = false; bool touchscreen_disable_on_palm = false; bool touchscreen_disable_on_stylus = false; + std::string touchscreen_disable_on_stylus_level = "connected"; f64 touchscreen_overshoot = 0.5; // [Touchpad] diff --git a/src/core/linux/config-loader.hpp b/src/core/linux/config-loader.hpp index 8ffd944..abf8afc 100644 --- a/src/core/linux/config-loader.hpp +++ b/src/core/linux/config-loader.hpp @@ -155,6 +155,7 @@ class ConfigLoader { this->get(ini, "Touchscreen", "Disable", m_config.touchscreen_disable); this->get(ini, "Touchscreen", "DisableOnPalm", m_config.touchscreen_disable_on_palm); this->get(ini, "Touchscreen", "DisableOnStylus", m_config.touchscreen_disable_on_stylus); + this->get(ini, "Touchscreen", "DisableOnStylusLevel", m_config.touchscreen_disable_on_stylus_level); this->get(ini, "Touchscreen", "Overshoot", m_config.touchscreen_overshoot); this->get(ini, "Touchpad", "Disable", m_config.touchpad_disable);