How would I stop touch input from getting registered as mouse input in an imgui window?

Hello, I’m an oldtime user of vvvv delta.

Getting into gamma right now and creating a drawing app using the realtime stylus api. Now I want to make same realtime onscreen controls for color, brushes etc. The problem I have is that touch events also get registered as mouse input and this makes the stylus input stop. If i’m already drawing and then touch the screen it’s fine and it keeps working, but if I first touch and then try to draw the pen input doesn’t work. So now I’m looking for a method so I can define a region on screen where touch events doesn’t get processed as mouse input.

I’m a visual artist and don’t have a background in coding. While I did manage to implement the realtime stylus api (took me a few days with the help of chatgpt :) ), right now I’m stuck.

I asked chatgpt again for the best method :)

this is the example code it:

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

public class MainForm : Form
{
// Define the constants for touch window flags
private const uint TWF_WANTPALM = 0x2; // Suppresses mouse emulation
private const uint TWF_FINETOUCH = 0x1; // Fine touch input (optional)

// Import the RegisterTouchWindow function from User32.dll
[DllImport("user32.dll")]
public static extern bool RegisterTouchWindow(IntPtr hwnd, uint ulFlags);

public MainForm()
{
    this.Text = "Touch Area Example";
    this.Size = new System.Drawing.Size(400, 300);
    this.Paint += new PaintEventHandler(MainForm_Paint);
    
    // Register this window to receive touch input and suppress mouse emulation
    RegisterTouchWindow(this.Handle, TWF_WANTPALM);
}

private void MainForm_Paint(object sender, PaintEventArgs e)
{
    // Example code to paint the form (e.g., drawing a rectangle)
    e.Graphics.DrawRectangle(System.Drawing.Pens.Black, 50, 50, 200, 100);
}

public static void Main()
{
    Application.Run(new MainForm());
}

}

The original question isn’t that hard. With the InjectNotifications it’s easy to implement the question in the title, but this didn’t solve my problem. I’ll describe my observations what happens and what I want to achieve. Somebody may point me in the right direction.

I have a drawing (stylus) region on screen using the realtime stylus and a touch region for realtime interactions. If I use the mouse the stylus takes over when it hovers the screen and all is fine. When I’m already drawing, and I touch the screen all keeps working and touch works. When i touch the screen and a touchpoint is set to primary the stylus doesn’t send events. When I touch the screen with two points and release the primary point the stylus can take over again and touch works. Is there a way to release this primary touch point when the stylus comes in range? Can I do that with these functions →

[DllImport(“user32.dll”, SetLastError = true)]
public static extern bool ReleaseCapture();

[DllImport(“user32.dll”, SetLastError = true)]
public static extern bool SetCapture(IntPtr hwnd);

Sadly this is quite an advanced topic.

I did a try to dig through source code to find where the actual input handling, but haven’t yet found a source of it, there is some notifications stuff around here witch kind-a looks what you need.

Basically based on this package you have to develop some sort of your own window, witch is going to handle event filtering under the hood…

Try to isolate the problem in an example and post it here as a patch. The question is interesting, but it would be clearer if there was a patch.

thank you @antokhio and @yar for responding! I was just playing around with it again. Looked into setting up a global hook, but that is only possible for mouse and keyboard I’m afraid… I did a different approach a few days ago in creating my own hook with a WndProc override for WM_POINTER messages. Got the stylus working, but this also conflicted with the other inputs. This time the stylus only worked properly if I touched the window while I was drawing😒.

Wouldn’t it be nice to just have a standard Stylusdevice in Gamma just like the Mouse, Keyboard and TouchDevice. Maybe for a feature request? Looked into the StandardLib and it doesn’t seem to hard to implement it jus like the other inputs with the notifications. But well hack I’m not a real coder… seems there needs some updates here to and here
and ofcourse in the VL.Core.Skia.Windows where @antokhio already pointed to. What do you mean with creating my own window? Like an actual window that floats on top of the renderwindow?

I used the following code that also doesn’t seem to work properly as I described above (added some downsampling of the data and smoothing later on):

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using static MyStylusLibrary.StylusCaptureControl;

public class StylusWindowHook : NativeWindow
{
// Windows pointer message constants
private const int WM_POINTERDOWN = 0x0246;
private const int WM_POINTERUP = 0x0247;
private const int WM_POINTERUPDATE = 0x0245;
private const int WM_POINTERMOVE = 0x0243; // Occasionally used by some drivers

[DllImport("user32.dll")]
private static extern bool GetPointerPenInfo(uint pointerId, ref POINTER_PEN_INFO penInfo);

[DllImport("user32.dll")]
private static extern bool GetPointerType(uint pointerId, out POINTER_INPUT_TYPE pointerType);

public event EventHandler<StylusEventArgs> StylusDown;
public event EventHandler<StylusEventArgs> StylusMove;
public event EventHandler<StylusEventArgs> StylusUp;

public StylusWindowHook(IntPtr hWnd)
{
    // Attach to the provided window handle
    AssignHandle(hWnd);
}

protected override void WndProc(ref Message m)
{
    // Respond only to pointer messages
    if (m.Msg == WM_POINTERDOWN ||
        m.Msg == WM_POINTERUPDATE ||
        m.Msg == WM_POINTERUP ||
        m.Msg == WM_POINTERMOVE)
    {
        Console.WriteLine($"[Pointer] msg=0x{m.Msg:X4}");
        HandleStylus(ref m);
    }

    base.WndProc(ref m);
}

private void HandleStylus(ref Message m)
{
    // Retrieve the pointer ID from the low-order word of wParam
    uint pointerId = (uint)(m.WParam.ToInt64() & 0xFFFF);

    // Retrieve pointer type (pen, mouse, touch, etc.)
    if (!GetPointerType(pointerId, out POINTER_INPUT_TYPE pType))
    {
        Console.WriteLine($"[Pointer] GetPointerType failed (ID {pointerId})");
        return;
    }

    Console.WriteLine($"[Pointer] Type = {pType}");

    // Only handle pen input
    if (pType == POINTER_INPUT_TYPE.PT_PEN)
    {
        var penInfo = new POINTER_PEN_INFO();

        // Retrieve pen-specific information
        if (!GetPointerPenInfo(pointerId, ref penInfo))
        {
            Console.WriteLine("[Pointer] GetPointerPenInfo failed");
            return;
        }

        // Extract screen coordinates
        var screenX = penInfo.pointerInfo.ptPixelLocation.x;
        var screenY = penInfo.pointerInfo.ptPixelLocation.y;

        // Parse pressure (if supported by the device)
        float pressure = 0f;
        if ((penInfo.penMask & PEN_MASK.PEN_MASK_PRESSURE) != 0)
        {
            float maxPressure = 1024f; // Adjust max pressure based on your device
            pressure = penInfo.pressure / maxPressure;
        }

        // Fire the appropriate stylus event
        var args = new StylusEventArgs
        {
            X = screenX,
            Y = screenY,
            Pressure = pressure,
            IsPen = true
        };

        switch (m.Msg)
        {
            case WM_POINTERDOWN:
                Console.WriteLine("[Pointer] --> StylusDown event");
                StylusDown?.Invoke(this, args);
                break;

            case WM_POINTERUPDATE:
            case WM_POINTERMOVE:
                Console.WriteLine("[Pointer] --> StylusMove event");
                StylusMove?.Invoke(this, args);
                break;

            case WM_POINTERUP:
                Console.WriteLine("[Pointer] --> StylusUp event");
                StylusUp?.Invoke(this, args);
                break;
        }
    }
    else
    {
        // Log unsupported pointer types (mouse, touch, etc.)
        Console.WriteLine($"[Pointer] Unsupported pointer type: {pType}");
    }
}

// Stylus event arguments
public class StylusEventArgs : EventArgs
{
    public int X { get; set; }
    public int Y { get; set; }
    public float Pressure { get; set; }
    public bool IsPen { get; set; }
}

}

(post deleted by author)

@yar the test patch with the RealtimeStylus
DrawingInWindow.zip (238.4 KB)