https://bugs.winehq.org/show_bug.cgi?id=11846
--- Comment #109 from John Chadwick johnwchadwick@gmail.com --- Hey all, I hope you are doing well. It has been a while. It appears the first time I touched this issue was all the way back in 2015.
I am currently in the process of trying to get Painttool SAI 2 to work properly under mainline Wine. One patch is already in (https://source.winehq.org/patches/data/173932), the next is in flight (https://source.winehq.org/patches/data/174062), and I have a third change that should make everything work correctly that I will submit once the second fix is squared away. After that, SAI 2 should work properly in Wine without any need to mess with configurations.
This got me thinking back to SAI 1, and I think I finally fully understand the problem. With a little bit of tracing, I noticed that SAI 1 does some interesting Wintab magic. It creates a top-level, hidden window with the sfl_wintab_window class, and no geometry to speak of.
What's going on here? It appears SAI 1 uses this magic window to receive Wintab32 events. The thing is, Wintab32 events are not like mouse events. It seems that Wintab32 actually handles the contexts as a stack, and hidden top-level windows appear to be treated as covering the entire screen. Painttool SAI 1 uses the WTOverlap function to move its context to the top of the stack when the window is focused, and to the bottom of the stack when the window is unfocused.
Here's where things get tricky: In the Xinput code, XSelectExtensionEvent is called on the X11 window of hOwner (using X11DRV_get_whole_window.) This works in the case where the context == the window where you will be using the tablet. It does *NOT* work in the case of using top level hidden windows to receive Wintab32 events and manually shuffling them using WTOverlap. Even if we patch it to XSelectExtensionEvent on the root window, it won't be able to figure out what context it should send the events to.
The Wintab code should probably register for events in X11DRV_LoadTabletInfo, and it should do so on the X11 root window. X11DRV_AttachEventQueueToTablet should just map the hWnd to a context. But crucially, the way the event handlers work needs to change. Instead of sending the message directly to the hWnd that the event is matched with, the hWnd should be ignored, and we should iterate through a stack of windows, finding the first one that overlaps with the event coordinates. Then, WTOverlap should be implemented to manipulate this stack.
I suspect all of the information we need to determine if a context overlaps is the HWND. So, we already have most of the necessary information. However, we do need a way to propagate the WTOverlap calls back to winex11.drv, which will probably need to come in the form of new graphics driver functions. In the meantime, it's probably not a big deal to ignore WTOverlap since it probably only has an impact when working between different applications.
It's probably going to be valuable to also investigate the behaviors and interactions between various techniques in Windows. For example, what happens when you drag the tablet outside the window? It may not be sufficient to simply route events based on what the top most context matching the geometry is; some additional heuristics may be needed to ensure the events between two button_events from a single cursor are always routed to the same context even if they leave the bounds of the context.
Regardless, I hope we can resolve this issue soon. It's been a long time coming.