diff --git a/etc/iptsd.conf b/etc/iptsd.conf index 3fbd529..aecf5d4 100644 --- a/etc/iptsd.conf +++ b/etc/iptsd.conf @@ -159,3 +159,4 @@ # PositionExp = -0.7 # ButtonMinMag = 1000 # FreqMinMag = 10000 +# AllowSplitEvents = false diff --git a/src/core/generic/application.hpp b/src/core/generic/application.hpp index fff7403..1734e9d 100644 --- a/src/core/generic/application.hpp +++ b/src/core/generic/application.hpp @@ -233,8 +233,15 @@ class Application { if (!m_info.is_touchscreen()) return; - m_dft.input(data); - this->process_stylus(m_dft.get_stylus()); + /* Since all DFT packets update only some of the stylus data, sending an + * event each time a DFT packet arrives causes resending of some stale + * info as though it is current. As a result, the same coordinates, + * pressure, etc. are reported to the system several times. This confuses + * the smoothing algorithms in some software (e.g. Krita), which is why + * we hold off reporting new data to the system until ALL of it is updated. + */ + if (m_dft.input(data) || m_config.dft_allow_split_events) + this->process_stylus(m_dft.get_stylus()); } /*! diff --git a/src/core/generic/config.hpp b/src/core/generic/config.hpp index 80df481..7bb08c7 100644 --- a/src/core/generic/config.hpp +++ b/src/core/generic/config.hpp @@ -65,6 +65,7 @@ class Config { usize dft_mpp2_button_min_mag = 50000; usize dft_mpp2_contact_min_mag = 50000; f64 dft_tilt_distance = 0.6; + bool dft_allow_split_events = false; public: /*! diff --git a/src/core/generic/dft.hpp b/src/core/generic/dft.hpp index d051d7a..1b41afb 100644 --- a/src/core/generic/dft.hpp +++ b/src/core/generic/dft.hpp @@ -54,12 +54,20 @@ class DftStylus { * Loads a DFT window and calculates stylus properties from it. * * @param[in] dft The dft window received from the IPTS hardware. + * @return Whether an event should be emitted by this packet. */ - void input(const ipts::samples::DftWindow &dft) + bool input(const ipts::samples::DftWindow &dft) { switch (dft.type) { case ipts::protocol::dft::Type::Position: this->handle_position(dft); + /* This event type is the most important one. It is the first and + * the last one to arrive. It sets both proximity and lift. It is + * also guaranteed to come regularly whenever we have (or just lost) + * proximity. For all these reasons it MUST ALWAYS be let through + * and it is chosen as THE synchronising event. + */ + return true; break; case ipts::protocol::dft::Type::Button: this->handle_button(dft); @@ -77,6 +85,8 @@ class DftStylus { // Ignored break; } + // Do not emit an event by default. + return false; } /*! diff --git a/src/core/linux/config-loader.hpp b/src/core/linux/config-loader.hpp index 96d56ce..073da29 100644 --- a/src/core/linux/config-loader.hpp +++ b/src/core/linux/config-loader.hpp @@ -188,6 +188,7 @@ class ConfigLoader { this->get(ini, "DFT", "TiltDistance", m_config.dft_tilt_distance); this->get(ini, "DFT", "Mpp2ContactMinMag", m_config.dft_mpp2_contact_min_mag); this->get(ini, "DFT", "Mpp2ButtonMinMag", m_config.dft_mpp2_button_min_mag); + this->get(ini, "DFT", "AllowSplitEvents", m_config.dft_allow_split_events); // Legacy options that are kept for compatibility this->get(ini, "DFT", "TipDistance", m_config.stylus_tip_distance);