Skip to content

Commit

Permalink
Implement DFT partial update bundling
Browse files Browse the repository at this point in the history
Sending an event every time a DFT packet arrives causes issues
with smoothing in some applications (e.g. Krita) due to the
same data being resent several times as though it is a new event.
This workaround bundles all the updates together and sends them
as one event fixing this problem.
  • Loading branch information
AndyGozas committed Feb 16, 2025
1 parent e211f37 commit bea7f97
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 3 deletions.
1 change: 1 addition & 0 deletions etc/iptsd.conf
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,4 @@
# PositionExp = -0.7
# ButtonMinMag = 1000
# FreqMinMag = 10000
# AllowSplitEvents = false
11 changes: 9 additions & 2 deletions src/core/generic/application.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}

/*!
Expand Down
1 change: 1 addition & 0 deletions src/core/generic/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
/*!
Expand Down
12 changes: 11 additions & 1 deletion src/core/generic/dft.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -77,6 +85,8 @@ class DftStylus {
// Ignored
break;
}
// Do not emit an event by default.
return false;
}

/*!
Expand Down
1 change: 1 addition & 0 deletions src/core/linux/config-loader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit bea7f97

Please sign in to comment.