diff --git a/README.md b/README.md index be73ad4..01a0765 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ The GUI minimizes to system tray / notification area. You can reopen the GUI by ## Download -### http://hwk.fi/TabletDriver/TabletDriverV0.1.4.zip +### http://hwk.fi/TabletDriver/TabletDriverV0.1.5.zip # @@ -61,7 +61,7 @@ The GUI minimizes to system tray / notification area. You can reopen the GUI by * https://aka.ms/vs/15/release/vc_redist.x86.exe 2. Unzip the driver to a folder (Shorter path is recommended, for example `C:\Temp\TabletDriver`) -3. Uninstall all other tablet drivers. +3. Uninstall all other tablet drivers. If you have problems with uninstalling the Wacom drivers, check the GitHub issue [#1](https://github.com/hawku/TabletDriver/issues/1) 4. Run `install_vmulti_driver.bat`. It might need a restart if there is another vmulti driver installed. 5. If you have Huion or Gaomon tablet, you need to run `install_huion_64.bat`, which is in the `driver_huion` directory. 6. Start the TabletDriverGUI.exe @@ -92,6 +92,12 @@ If you want to compile the code and don't want to install anything from the Tabl # ## Changelog +>**v0.1.5:** +> - New tablet configurations: Wacom CTL-4100 (USB only model), XP-Pen G540 Pro, XP-Pen Deco 01 and Huion osu!tablet +> Thanks to /u/THEqrunt for capturing the XP-Pen Deco 01 USB data. +> - Added `ResetDistance` command, it controls the relative mode position reset distance. +> - Code refactoring. + >**v0.1.4:** > - Modified the Wacom CTL-471 full area size (147.20 x 92.25 mm to 152 x 95 mm) > - New tablet configurations: Wacom PTH-850 and Huion H430P diff --git a/TabletDriverGUI/MainWindow.xaml.cs b/TabletDriverGUI/MainWindow.xaml.cs index 7801ed7..5f4d1bc 100644 --- a/TabletDriverGUI/MainWindow.xaml.cs +++ b/TabletDriverGUI/MainWindow.xaml.cs @@ -24,7 +24,7 @@ public partial class MainWindow : Window { // Version - public string Version = "0.1.4"; + public string Version = "0.1.5"; // Console stuff private List commandHistory; @@ -1546,8 +1546,17 @@ private void ParseDriverStatus(string line) // if (variableName == "tablet") { - Title = "TabletDriverGUI - " + stringValue; - notifyIcon.Text = Title; + string title = "TabletDriverGUI - " + stringValue; + Title = title; + + // Limit notify icon text length + if (title.Length > 63) + { + notifyIcon.Text = title.Substring(0, 63); + } else + { + notifyIcon.Text = title; + } SetStatus("Connected to " + stringValue); } diff --git a/TabletDriverService/Main.cpp b/TabletDriverService/Main.cpp index d8de81e..be4a980 100644 --- a/TabletDriverService/Main.cpp +++ b/TabletDriverService/Main.cpp @@ -46,6 +46,8 @@ void RunTabletThread() { bool isFirstReport = true; bool isResent = false; double x, y; + TabletFilter *filter; + bool filterTimedEnabled; chrono::high_resolution_clock::time_point timeBegin = chrono::high_resolution_clock::now(); chrono::high_resolution_clock::time_point timeNow = chrono::high_resolution_clock::now(); @@ -60,10 +62,10 @@ void RunTabletThread() { // Read tablet position // status = tablet->ReadPosition(); + // Position OK if(status == Tablet::PacketValid) { isResent = false; - // Position invalid // Invalid packet id } else if(status == Tablet::PacketInvalid) { @@ -111,17 +113,40 @@ void RunTabletThread() { } // - // Packet filter + // Packet filters // - if(tablet->filterPacket != NULL && tablet->filterPacket->isEnabled) { - tablet->filterPacket->SetTarget(tablet->state.position); - tablet->filterPacket->Update(); - tablet->filterPacket->GetPosition(&tablet->state.position); + // Is there any filters? + if(tablet->filterPacketCount > 0) { + + // Loop through filters + for(int filterIndex = 0; filterIndex < tablet->filterPacketCount; filterIndex++) { + + // Filter + filter = tablet->filterPacket[filterIndex]; + + // Enabled? + if(filter != NULL && filter->isEnabled) { + + // Process + filter->SetTarget(tablet->state.position); + filter->Update(); + filter->GetPosition(&tablet->state.position); + } + + } + } + + + // Timed filter enabled? + filterTimedEnabled = false; + for(int filterIndex = 0; filterIndex < tablet->filterTimedCount; filterIndex++) { + if(tablet->filterTimed[filterIndex]->isEnabled) + filterTimedEnabled = true; } // Do not write report when timed filter is enabled - if(tablet->filterTimed == NULL || !tablet->filterTimed->isEnabled) { + if(tablet->filterTimedCount == 0 || !filterTimedEnabled) { // Relative mode if(vmulti->mode == VMulti::ModeRelativeMouse) { @@ -165,34 +190,40 @@ void RunTabletThread() { // VOID CALLBACK FilterTimerCallback(_In_ PVOID lpParameter, _In_ BOOLEAN TimerOrWaitFired) { Vector2D position; + TabletFilter *filter; + + // Set position + position.Set(tablet->state.position); - TabletFilter *filter = tablet->filterTimed; + // Loop through filters + for(int filterIndex = 0; filterIndex < tablet->filterTimedCount; filterIndex++) { - // Filter enabled? - if(!filter->isEnabled) return; + // Filter + filter = tablet->filterTimed[filterIndex]; - // Set filter targets - filter->SetTarget(tablet->state.position); + // Filter enabled? + if(!filter->isEnabled) return; - // Update filter position - filter->Update(); + // Set filter targets + filter->SetTarget(position); - // Set output vector - filter->GetPosition(&position); + // Update filter position + filter->Update(); + // Set output vector + filter->GetPosition(&position); + } + + + // // Relative mode + // if(vmulti->mode == VMulti::ModeRelativeMouse) { // Map position to virtual screen (values between 0 and 1) mapper->GetRotatedTabletPosition(&position.x, &position.y); - // Large distance -> Reset relative position - double distance = tablet->state.position.Distance(vmulti->relativeData.lastPosition); - if(distance > 10) { - vmulti->ResetRelativeData(position.x, position.y); - } - // Create VMulti report vmulti->CreateReport( tablet->state.buttons, @@ -207,12 +238,17 @@ VOID CALLBACK FilterTimerCallback(_In_ PVOID lpParameter, _In_ BOOLEAN TimerOrWa vmulti->reportRelativeMouse.x != 0 || vmulti->reportRelativeMouse.y != 0 - ) { + ) { vmulti->WriteReport(); } + + } + + // // Absolute / Digitizer mode - } else { + // + else { // Map position to virtual screen (values betweeb 0->1) @@ -338,8 +374,10 @@ int main(int argc, char**argv) { running = true; // Timed filter timer - tablet->filterTimed->callback = FilterTimerCallback; - tablet->filterTimed->StartTimer(); + if(tablet->filterPacketCount > 0) { + tablet->filterTimed[0]->callback = FilterTimerCallback; + tablet->filterTimed[0]->StartTimer(); + } // Start the tablet thread tabletThread = new thread(RunTabletThread); @@ -389,8 +427,8 @@ void CleanupAndExit(int code) { // Delete filter timer if(tablet != NULL) { - if(tablet->filterTimed != NULL) { - tablet->filterTimed->StopTimer(); + if(tablet->filterTimedCount != 0) { + tablet->filterTimed[0]->StopTimer(); } } diff --git a/TabletDriverService/PositionRingBuffer.cpp b/TabletDriverService/PositionRingBuffer.cpp new file mode 100644 index 0000000..7a5acbb --- /dev/null +++ b/TabletDriverService/PositionRingBuffer.cpp @@ -0,0 +1,97 @@ +#include "stdafx.h" +#include "PositionRingBuffer.h" + + +// +// Constructor +// +PositionRingBuffer::PositionRingBuffer() { + maxLength = sizeof(buffer) / sizeof(Vector2D); + length = 0; + count = 0; + index = 0; + isValid = false; +} + + +// +// Destructor +// +PositionRingBuffer::~PositionRingBuffer() { +} + + +// +// Set buffer length +// +void PositionRingBuffer::SetLength(int len) { + if(len > maxLength) { + length = maxLength; + } else { + length = len; + } +} + + +// +// Add position to buffer +// +void PositionRingBuffer::Add(Vector2D vector) { + buffer[index].x = vector.x; + buffer[index].y = vector.y; + index++; + count++; + if(count > length) { + count = length; + } + if(index >= length) { + index = 0; + } + isValid = true; +} + + +// +// Get position history from the buffer +// +bool PositionRingBuffer::GetLatest(Vector2D *output, int delta) { + int newIndex; + + // Buffer empty? + if(count == 0) return false; + + // Valid delta? + if(delta > 0 || delta <= -count) return false; + + newIndex = index - 1 + delta; + + // Limits + if(newIndex < 0) newIndex = count + newIndex; + + if(newIndex < 0 || newIndex >= count) { + return false; + } + + output->x = buffer[newIndex].x; + output->y = buffer[newIndex].y; + return true; +} + + +// +// Reset buffer +// +void PositionRingBuffer::Reset() { + count = 0; + index = 0; + isValid = false; +} + + + +// +// [] operator +// +Vector2D *PositionRingBuffer::operator[](std::size_t index) { + return &(buffer[index]); +} \ No newline at end of file diff --git a/TabletDriverService/PositionRingBuffer.h b/TabletDriverService/PositionRingBuffer.h new file mode 100644 index 0000000..f41fe42 --- /dev/null +++ b/TabletDriverService/PositionRingBuffer.h @@ -0,0 +1,25 @@ +#pragma once + +#include "Vector2D.h" + +class PositionRingBuffer { +public: + Vector2D buffer[100]; + int maxLength; + int length; + int count; + int index; + bool isValid; + + void SetLength(int length); + void Add(Vector2D vector); + bool GetLatest(Vector2D *output, int delta); + void Reset(); + + Vector2D *operator[](std::size_t index); + + + PositionRingBuffer(); + ~PositionRingBuffer(); +}; + diff --git a/TabletDriverService/ProcessCommand.cpp b/TabletDriverService/ProcessCommand.cpp index 49997b8..e4d90e3 100644 --- a/TabletDriverService/ProcessCommand.cpp +++ b/TabletDriverService/ProcessCommand.cpp @@ -211,7 +211,7 @@ bool ProcessCommand(CommandLine *cmd) { LOG_INFO("Tablet skew = Shift X-axis %0.2f mm per Y-axis mm\n", tablet->settings.skew); } - // Skew + // Type else if(cmd->is("Type")) { if(tablet == NULL) return false; @@ -418,6 +418,15 @@ bool ProcessCommand(CommandLine *cmd) { LOG_INFO("Relative mode sensitivity = %0.2f px/mm\n", vmulti->relativeData.sensitivity); } + // + // Relative mode reset distance + // + else if(cmd->is("ResetDistance")) { + if(!CheckTablet()) return true; + vmulti->relativeData.resetDistance = cmd->GetDouble(0, vmulti->relativeData.resetDistance); + LOG_INFO("Relative mode reset distance = %0.2f mm\n", vmulti->relativeData.resetDistance); + } + // // VMulti output mode @@ -545,7 +554,7 @@ bool ProcessCommand(CommandLine *cmd) { // Set parameters } else { - int length = cmd->GetInt(0, tablet->noise.bufferLength); + int length = cmd->GetInt(0, tablet->noise.buffer.length); double distanceThreshold = cmd->GetDouble(1, tablet->noise.distanceThreshold); int iterations = cmd->GetInt(2, tablet->noise.iterations); @@ -560,12 +569,12 @@ bool ProcessCommand(CommandLine *cmd) { else if(iterations > 100) iterations = 100; // Set - tablet->noise.SetBufferLength(length); + tablet->noise.buffer.SetLength(length); tablet->noise.distanceThreshold = distanceThreshold; tablet->noise.iterations = iterations; // Enable filter - if(tablet->noise.bufferLength > 0) { + if(tablet->noise.buffer.length > 0) { tablet->noise.isEnabled = true; LOG_INFO("Noise Reduction = %d packets, %0.3f mm threshold, %d iterations\n", length, distanceThreshold, iterations); } else { diff --git a/TabletDriverService/Tablet.cpp b/TabletDriverService/Tablet.cpp index 53151d8..5705238 100644 --- a/TabletDriverService/Tablet.cpp +++ b/TabletDriverService/Tablet.cpp @@ -54,8 +54,13 @@ Tablet::Tablet() { memset(&state, 0, sizeof(state)); // Filters - filterTimed = &smoothing; - filterPacket = &noise; + filterTimed[0] = &smoothing; + filterTimedCount = 1; + filterPacket[0] = &noise; + //filterPacket[1] = &peak; + filterPacketCount = 1; + + peak.isEnabled = true; // Button map memset(&buttonMap, 0, sizeof(buttonMap)); @@ -120,8 +125,13 @@ bool Tablet::Init() { if(usbDevice != NULL) { BYTE buffer[64]; int status; + + // String Id 200 status = usbDevice->ControlTransfer(0x80, 0x06, (0x03 << 8) | 200, 0x0409, buffer, 64); + + // String Id 100 status += usbDevice->ControlTransfer(0x80, 0x06, (0x03 << 8) | 100, 0x0409, buffer, 64); + if(status > 0) { return true; } diff --git a/TabletDriverService/Tablet.h b/TabletDriverService/Tablet.h index 4d482f2..ed0a4ba 100644 --- a/TabletDriverService/Tablet.h +++ b/TabletDriverService/Tablet.h @@ -7,6 +7,7 @@ #include "TabletSettings.h" #include "TabletFilterSmoothing.h" #include "TabletFilterNoiseReduction.h" +#include "TabletFilterPeak.h" #include "TabletBenchmark.h" #include "Vector2D.h" @@ -66,11 +67,16 @@ class Tablet { // Noise reduction filter TabletFilterNoiseReduction noise; + // Peak filter + TabletFilterPeak peak; + // Timed filter - TabletFilter *filterTimed; + TabletFilter *filterTimed[10]; + int filterTimedCount; // Packet filter - TabletFilter *filterPacket; + TabletFilter *filterPacket[10]; + int filterPacketCount; // Benchmark TabletBenchmark benchmark; diff --git a/TabletDriverService/TabletDriverService.vcxproj b/TabletDriverService/TabletDriverService.vcxproj index 900ca69..082859c 100644 --- a/TabletDriverService/TabletDriverService.vcxproj +++ b/TabletDriverService/TabletDriverService.vcxproj @@ -171,6 +171,7 @@ xcopy /C /Y "$(ProjectDir)config\init.cfg" "$(SolutionDir)TabletDriverGUI\bin\De + @@ -178,6 +179,7 @@ xcopy /C /Y "$(ProjectDir)config\init.cfg" "$(SolutionDir)TabletDriverGUI\bin\De + @@ -189,12 +191,14 @@ xcopy /C /Y "$(ProjectDir)config\init.cfg" "$(SolutionDir)TabletDriverGUI\bin\De + + diff --git a/TabletDriverService/TabletDriverService.vcxproj.filters b/TabletDriverService/TabletDriverService.vcxproj.filters index 8e46824..4b88f4e 100644 --- a/TabletDriverService/TabletDriverService.vcxproj.filters +++ b/TabletDriverService/TabletDriverService.vcxproj.filters @@ -63,6 +63,12 @@ Header Files + + Header Files + + + Header Files + @@ -113,6 +119,12 @@ Source Files + + Source Files + + + Source Files + diff --git a/TabletDriverService/TabletFilterNoiseReduction.cpp b/TabletDriverService/TabletFilterNoiseReduction.cpp index 2ba06a5..9d3cb10 100644 --- a/TabletDriverService/TabletFilterNoiseReduction.cpp +++ b/TabletDriverService/TabletFilterNoiseReduction.cpp @@ -6,10 +6,6 @@ // Constructor // TabletFilterNoiseReduction::TabletFilterNoiseReduction() { - bufferMaxLength = sizeof(buffer) / sizeof(Vector2D); - bufferLength = 0; - bufferPositionCount = 0; - bufferCurrentIndex = 0; distanceThreshold = 0; iterations = 10; } @@ -20,19 +16,6 @@ TabletFilterNoiseReduction::TabletFilterNoiseReduction() { TabletFilterNoiseReduction::~TabletFilterNoiseReduction() { } - -// -// Set buffer length -// -void TabletFilterNoiseReduction::SetBufferLength(int length) { - if(length > bufferMaxLength) { - bufferLength = bufferMaxLength; - } else { - bufferLength = length; - } -} - - // // TabletFilter methods // @@ -40,16 +23,16 @@ void TabletFilterNoiseReduction::SetBufferLength(int length) { // Set target position void TabletFilterNoiseReduction::SetTarget(Vector2D targetVector) { lastTarget.Set(targetVector); - AddBuffer(targetVector); + buffer.Add(targetVector); } -// Get current position +// Set position void TabletFilterNoiseReduction::SetPosition(Vector2D vector) { position.x = vector.x; position.y = vector.y; } -// Get current position +// Get position bool TabletFilterNoiseReduction::GetPosition(Vector2D *outputVector) { outputVector->x = position.x; outputVector->y = position.y; @@ -60,9 +43,9 @@ bool TabletFilterNoiseReduction::GetPosition(Vector2D *outputVector) { void TabletFilterNoiseReduction::Update() { // One position in the buffer? - if(bufferPositionCount == 1) { - position.x = buffer[0].x; - position.y = buffer[0].y; + if(buffer.count == 1) { + position.x = buffer[0]->x; + position.y = buffer[0]->y; return; } @@ -70,57 +53,29 @@ void TabletFilterNoiseReduction::Update() { GetGeometricMedianVector(&position, iterations); // Reset the buffer when distance to last target position is larger than the threshold - if(isValid) { + if(buffer.isValid) { double distance = lastTarget.Distance(position); if(distance > distanceThreshold) { - ResetBuffer(); + buffer.Reset(); position.Set(lastTarget); } } } - - -// -// Reset buffer -// -void TabletFilterNoiseReduction::ResetBuffer() { - bufferPositionCount = 0; - bufferCurrentIndex = 0; - isValid = false; -} - -// -// Add position to buffer -// -void TabletFilterNoiseReduction::AddBuffer(Vector2D vector) { - buffer[bufferCurrentIndex].x = vector.x; - buffer[bufferCurrentIndex].y = vector.y; - bufferCurrentIndex++; - bufferPositionCount++; - if(bufferPositionCount > bufferLength) { - bufferPositionCount = bufferLength; - } - if(bufferCurrentIndex >= bufferLength) { - bufferCurrentIndex = 0; - } - isValid = true; -} - // // Average Position Vector // bool TabletFilterNoiseReduction::GetAverageVector(Vector2D *output) { double x, y; - if(!isValid) return false; + if(!buffer.isValid) return false; x = y = 0; - for(int i = 0; i < bufferPositionCount; i++) { - x += buffer[i].x; - y += buffer[i].y; + for(int i = 0; i < buffer.count; i++) { + x += buffer[i]->x; + y += buffer[i]->y; } - output->x = x / bufferPositionCount; - output->y = y / bufferPositionCount; + output->x = x / buffer.count; + output->y = y / buffer.count; return true; } @@ -147,9 +102,9 @@ bool TabletFilterNoiseReduction::GetGeometricMedianVector(Vector2D *output, int denominator = 0; // Loop through the buffer and calculate a denominator. - for(i = 0; i < bufferPositionCount; i++) { - dx = candidate.x - buffer[i].x; - dy = candidate.y - buffer[i].y; + for(i = 0; i < buffer.count; i++) { + dx = candidate.x - buffer[i]->x; + dy = candidate.y - buffer[i]->y; distance = sqrt(dx*dx + dy * dy); if(distance > minimumDistance) { denominator += 1.0 / distance; @@ -163,9 +118,9 @@ bool TabletFilterNoiseReduction::GetGeometricMedianVector(Vector2D *output, int next.y = 0; // Loop through the buffer and calculate a weighted average - for(i = 0; i < bufferPositionCount; i++) { - dx = candidate.x - buffer[i].x; - dy = candidate.y - buffer[i].y; + for(i = 0; i < buffer.count; i++) { + dx = candidate.x - buffer[i]->x; + dy = candidate.y - buffer[i]->y; distance = sqrt(dx*dx + dy * dy); if(distance > minimumDistance) { weight = 1.0 / distance; @@ -173,8 +128,8 @@ bool TabletFilterNoiseReduction::GetGeometricMedianVector(Vector2D *output, int weight = 1.0 / minimumDistance; } - next.x += buffer[i].x * weight / denominator; - next.y += buffer[i].y * weight / denominator; + next.x += buffer[i]->x * weight / denominator; + next.y += buffer[i]->y * weight / denominator; } // Set the new candidate vector diff --git a/TabletDriverService/TabletFilterNoiseReduction.h b/TabletDriverService/TabletFilterNoiseReduction.h index 7ca33a9..fba34ed 100644 --- a/TabletDriverService/TabletFilterNoiseReduction.h +++ b/TabletDriverService/TabletFilterNoiseReduction.h @@ -1,14 +1,13 @@ #pragma once + +#include "PositionRingBuffer.h" + class TabletFilterNoiseReduction : public TabletFilter { public: - Vector2D buffer[100]; - int bufferMaxLength; - int bufferLength; - int bufferPositionCount; - int bufferCurrentIndex; + + PositionRingBuffer buffer; Vector2D position; Vector2D lastTarget; - bool isValid; int iterations; double distanceThreshold; @@ -18,9 +17,6 @@ class TabletFilterNoiseReduction : public TabletFilter { bool GetPosition(Vector2D *outputVector); void Update(); - void SetBufferLength(int length); - void ResetBuffer(); - void AddBuffer(Vector2D vector); bool GetAverageVector(Vector2D *output); bool GetGeometricMedianVector(Vector2D *output, int iterations); diff --git a/TabletDriverService/TabletFilterPeak.cpp b/TabletDriverService/TabletFilterPeak.cpp new file mode 100644 index 0000000..22448e5 --- /dev/null +++ b/TabletDriverService/TabletFilterPeak.cpp @@ -0,0 +1,77 @@ +#include "stdafx.h" +#include "TabletFilterPeak.h" + +#define LOG_MODULE "Peak" +#include "Logger.h" + +// +// Constructor +// +TabletFilterPeak::TabletFilterPeak() { + + // Buffer length + buffer.SetLength(3); + + // Default distance threshold + distanceThreshold = 10; +} + + +// +// Destructor +// +TabletFilterPeak::~TabletFilterPeak() { +} + + +// +// TabletFilter methods +// +// Set target position +void TabletFilterPeak::SetTarget(Vector2D targetVector) { + buffer.Add(targetVector); +} +// Set position +void TabletFilterPeak::SetPosition(Vector2D vector) { + position.x = vector.x; + position.y = vector.y; +} +// Get position +bool TabletFilterPeak::GetPosition(Vector2D *outputVector) { + outputVector->x = position.x; + outputVector->y = position.y; + return true; +} +// Update +void TabletFilterPeak::Update() { + Vector2D oldPosition; + double distance; + + // Buffer valid? + if( + buffer.GetLatest(&oldPosition, -1) + && + buffer.GetLatest(&position, 0) + ) { + + // Jump longer than the distance threshold? + distance = oldPosition.Distance(position); + if(distance > distanceThreshold) { + + /* + LOG_DEBUG("PEAK! %0.2f,%0.2f -> %0.2f,%0.2f = %0.2f mm\n", + oldPosition.x, oldPosition.y, + position.x, position.y, + distance + ); + */ + + position.x = oldPosition.x; + position.y = oldPosition.y; + + // Reset buffer + buffer.Reset(); + + } + } +} \ No newline at end of file diff --git a/TabletDriverService/TabletFilterPeak.h b/TabletDriverService/TabletFilterPeak.h new file mode 100644 index 0000000..9396b49 --- /dev/null +++ b/TabletDriverService/TabletFilterPeak.h @@ -0,0 +1,22 @@ +#pragma once + +#include "PositionRingBuffer.h" +#include "Vector2D.h" + +class TabletFilterPeak : public TabletFilter { +public: + + PositionRingBuffer buffer; + Vector2D position; + double distanceThreshold; + + void SetTarget(Vector2D targetVector); + void SetPosition(Vector2D vector); + bool GetPosition(Vector2D *outputVector); + void Update(); + + + TabletFilterPeak(); + ~TabletFilterPeak(); +}; + diff --git a/TabletDriverService/VMulti.cpp b/TabletDriverService/VMulti.cpp index 85be417..918a962 100644 --- a/TabletDriverService/VMulti.cpp +++ b/TabletDriverService/VMulti.cpp @@ -38,6 +38,7 @@ VMulti::VMulti() { // Relative mouse data memset(&relativeData, 0, sizeof(relativeData)); relativeData.sensitivity = 1; + relativeData.resetDistance = 50; // Monitor info UpdateMonitorInfo(); @@ -131,8 +132,8 @@ void VMulti::CreateReport(BYTE buttons, double x, double y, double pressure) { dy = y - relativeData.lastPosition.y; distance = sqrt(dx * dx + dy * dy); - // Reset position when position jumps 10 millimeters - if(distance > 10) { + // Reset relative position when the move distance is long enough + if(distance > relativeData.resetDistance) { ResetRelativeData(x, y); dx = 0; dy = 0; diff --git a/TabletDriverService/VMulti.h b/TabletDriverService/VMulti.h index 342f406..cf6fadb 100644 --- a/TabletDriverService/VMulti.h +++ b/TabletDriverService/VMulti.h @@ -60,6 +60,7 @@ class VMulti { Vector2D lastPosition; Vector2D targetPosition; double sensitivity; + double resetDistance; } relativeData; diff --git a/TabletDriverService/config/tablet.cfg b/TabletDriverService/config/tablet.cfg index bfe1703..8966573 100644 --- a/TabletDriverService/config/tablet.cfg +++ b/TabletDriverService/config/tablet.cfg @@ -276,6 +276,7 @@ MaxPressure 2047 KeepTipDown 2 packets Width 152.0 Height 95.0 +#Feature 0x83 0x02 0x00 InitFeature 0x02 0x02 Type WacomIntuos @@ -302,6 +303,7 @@ Type WacomIntuos # Wacom CTL-4100 # Tablet 0x056a 0x0376 0xFF0D 0x0001 +Tablet 0x056a 0x0374 0xFF0D 0x0001 Name "Wacom CTL-4100" ReportId 0x10 ReportLength 192 @@ -317,6 +319,7 @@ Type Wacom4100 # Wacom CTL-4100 (Wacom drivers installed) # Tablet 0x056a 0x0376 0xFF00 0x000A +Tablet 0x056a 0x0374 0xFF00 0x000A Name "Wacom CTL-4100 (Wacom drivers installed)" ReportId 0x10 ReportLength 193 @@ -393,6 +396,22 @@ Height 76.2 InitReport 0x02 0xB0 0x02 0x00 0x00 0x00 0x00 0x00 +# +# XP-Pen G540 Pro +# +Tablet 0x28BD 0x0061 0xFF0A 0x0001 +Name "XP-Pen G540 Pro" +ReportId 0x02 +ReportLength 8 +DetectMask 0x80 +MaxX 45720 +MaxY 29210 +MaxPressure 8191 +Width 147.0 +Height 101.6 +InitReport 0x02 0xB0 0x02 0x00 0x00 0x00 0x00 0x00 + + # # XP-Pen G640 # @@ -404,11 +423,27 @@ DetectMask 0x80 MaxX 32000 MaxY 20000 MaxPressure 8191 -width 160.0 +Width 160.0 Height 100.0 InitReport 0x02 0xB0 0x02 0x00 0x00 0x00 0x00 0x00 +# +# XP-Pen Deco 01 +# +Tablet 0x28BD 0x0042 0xFF0A 0x0001 +Name "XP-Pen Deco 01" +ReportId 0x02 +ReportLength 8 +DetectMask 0x80 +MaxX 25400 +MaxY 15875 +MaxPressure 8191 +Width 254.0 +Height 158.75 +InitReport 0x02 0xB0 0x02 0x00 0x00 0x00 0x00 0x00 + + # # Huion 420 # @@ -484,4 +519,17 @@ Width 160.0 Height 120.0 +# +# Huion osu!tablet +# +Tablet "{62F12D4C-3431-4EFD-8DD7-8E9AAB18D30C}" 200 HVAN +Name "Huion osu!tablet (check the GitHub issue #99)" +ReportId 0x07 +ReportLength 8 +DetectMask 0x80 +MaxX 8340 +MaxY 4680 +MaxPressure 2047 +Width 101.6 +Height 56.6