Ok, Firstly, I'm including a patch that demonstrates fixes to the crashing in Painter, and the recursion in Photoshop.
The patch assumes that you have already applied Aric's patch from April 23rd.
I'd like feedback on wether the patch is OK, as it was generated on from my local subversion repository, not CVS. Please bear in mind that the code is designed as quick demonstration fixes, not for quality code. Having said that comments are welcome.
********
Secondly, I've done some more investigation into why Photoshop was not seeing tablet pressure. It turns out that this is due to Photoshop requesting tablet events from the desktop window. In the x11drv/event.c file, X11 events are interrogated, and the X11 window converted to a win32 window. This is done using the X11 feature of contexts: Application specific info mapping from an X11 window to user defined value. It appears that the X11 window has no X11 context, and therefore the XInput event handler is passed a hWnd of NULL. This causes the FindOpenContext not match any context. (Hence the recursion) Without a context, no event is posted (Hence the lack of pressure info)
Here's a typical debug trace showing the problem:
trace:event:EVENT_ProcessEvent called. trace:event:EVENT_ProcessEvent Got extention event for hwnd/window (nil)/37, GetFocus()=0x40042 trace:event:X11DRV_ProcessTabletEvent Recieved tablet motion event ((nil)) trace:wintab32:X11DRV_ProcessTabletEvent Recieved tablet motion event ((nil)) trace:wintab32:WTPacketsPeek (0xc00, 64, 0x43c828c4) trace:wintab32:WTPacketsGet (0xc00, 64, 0x1098388) trace:wintab32:TABLET_WindowProc Incomming Message 0x7ff0 (0x00000000, 0x00000000) trace:wintab32:AddPacketToContextQueue Trying Queue c00 (0 10020) trace:wintab32:AddPacketToContextQueue Done ((nil))
********
Thirdly, I've found out why Painter wasn't scaling correctly. There appear to be 2 issues. a. Tablet coordinates should be relative to the window the wintab context is attached to. Currently they are absoloute. b. The default system context as returned by WTInfo contains zero in the lcSysExtX,lcSysExtY fields These fields should contain the
I know how to fix the above problems, and will do so. P.S. Aric, I can now see the race condtion problem you were talking about in Painter.
Cheers -Rob.
Index: dlls/wintab32/context.c =================================================================== --- dlls/wintab32/context.c (.../file:///usr/local/svnroot/wine/trunk) (revision 73) +++ dlls/wintab32/context.c (revision 73) @@ -3,6 +3,7 @@ * * Copyright 2002 Patrik Stridvall * Copyright 2003 Codeweavers, Aric Stewart + * Copyright 2003 Robert North * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -168,11 +169,16 @@ ptr = gOpenContexts; while (ptr) { - TRACE("Trying Context %lx (%x %x)\n",(LONG)ptr->handle,(INT)hwnd, + TRACE("Trying Context %lx hwnd(%x %x)\n",(LONG)ptr->handle,(INT)hwnd, (INT)ptr->hwndOwner);
- if (ptr->hwndOwner == hwnd) + if (ptr->hwndOwner == hwnd) return ptr; + /* Rob 19-6-2003 Added recursion down pointer chein. + to avoid infinite loop. + Use TABLET_FindOpenContext as template. + */ + ptr = ptr->next; } return NULL; } @@ -251,7 +257,13 @@
int static inline CopyTabletData(LPVOID target, LPVOID src, INT size) { - memcpy(target,src,size); +/* + Rob 19-6-2003 + Return size only, if target is NULL: + Was causing horrible crashes in MetaCreation's Painter 5. +*/ + if(target != NULL) + memcpy(target,src,size); return(size); }
@@ -318,39 +330,42 @@
static VOID TABLET_BlankPacketData(LPOPENCONTEXT context, LPVOID lpPkt, INT n) { - int rc = 0; + if(lpPkt != NULL) + { + int rc = 0;
- if (context->context.lcPktData & PK_CONTEXT) - rc +=sizeof(HCTX); - if (context->context.lcPktData & PK_STATUS) - rc +=sizeof(UINT); - if (context->context.lcPktData & PK_TIME) - rc += sizeof(LONG); - if (context->context.lcPktData & PK_CHANGED) - rc += sizeof(WTPKT); - if (context->context.lcPktData & PK_SERIAL_NUMBER) - rc += sizeof(UINT); - if (context->context.lcPktData & PK_CURSOR) - rc += sizeof(UINT); - if (context->context.lcPktData & PK_BUTTONS) - rc += sizeof(DWORD); - if (context->context.lcPktData & PK_X) - rc += sizeof(DWORD); - if (context->context.lcPktData & PK_Y) - rc += sizeof(DWORD); - if (context->context.lcPktData & PK_Z) - rc += sizeof(DWORD); - if (context->context.lcPktData & PK_NORMAL_PRESSURE) - rc += sizeof(UINT); - if (context->context.lcPktData & PK_TANGENT_PRESSURE) - rc += sizeof(UINT); - if (context->context.lcPktData & PK_ORIENTATION) - rc += sizeof(ORIENTATION); - if (context->context.lcPktData & PK_ROTATION) - rc += sizeof(ROTATION); + if (context->context.lcPktData & PK_CONTEXT) + rc +=sizeof(HCTX); + if (context->context.lcPktData & PK_STATUS) + rc +=sizeof(UINT); + if (context->context.lcPktData & PK_TIME) + rc += sizeof(LONG); + if (context->context.lcPktData & PK_CHANGED) + rc += sizeof(WTPKT); + if (context->context.lcPktData & PK_SERIAL_NUMBER) + rc += sizeof(UINT); + if (context->context.lcPktData & PK_CURSOR) + rc += sizeof(UINT); + if (context->context.lcPktData & PK_BUTTONS) + rc += sizeof(DWORD); + if (context->context.lcPktData & PK_X) + rc += sizeof(DWORD); + if (context->context.lcPktData & PK_Y) + rc += sizeof(DWORD); + if (context->context.lcPktData & PK_Z) + rc += sizeof(DWORD); + if (context->context.lcPktData & PK_NORMAL_PRESSURE) + rc += sizeof(UINT); + if (context->context.lcPktData & PK_TANGENT_PRESSURE) + rc += sizeof(UINT); + if (context->context.lcPktData & PK_ORIENTATION) + rc += sizeof(ORIENTATION); + if (context->context.lcPktData & PK_ROTATION) + rc += sizeof(ROTATION);
- rc *= n; - memset(lpPkt,0,rc); + rc *= n; + memset(lpPkt,0,rc); + } }
@@ -856,7 +871,14 @@ */ int WINAPI WTPacketsGet(HCTX hCtx, int cMaxPkts, LPVOID lpPkts) { - int limit; + /* + Rob 19-6-2003 + WTPacketsGet fails with lpPkts set to NULL. + TO DO: Handle null condition. + Null condition flushes queue (Of Max packets????) + */ + int limit = 0; + int maxPktsToGet; LPOPENCONTEXT context; LPVOID ptr = lpPkts;
@@ -872,15 +894,20 @@ return 0; }
- for(limit = 0; limit < cMaxPkts && limit < context->PacketsQueued; limit++) + maxPktsToGet = min(cMaxPkts,context->PacketsQueued); + if(lpPkts != NULL) + { + for(limit = 0; limit < maxPktsToGet; limit++) ptr=TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[limit]); - - if (limit < context->PacketsQueued) + } + + if (maxPktsToGet < context->PacketsQueued) { - memcpy(context->PacketQueue, &context->PacketQueue[limit], - (context->QueueSize - (limit))*sizeof(WTPACKET)); + /* TO DO: Wrong function mem areas overlap. should use memmove*/ + memmove(context->PacketQueue, &context->PacketQueue[maxPktsToGet], + (context->QueueSize - (maxPktsToGet))*sizeof(WTPACKET)); } - context->PacketsQueued -= limit; + context->PacketsQueued -= maxPktsToGet; LeaveCriticalSection(&csTablet);
TRACE("Copied %i packets\n",limit); @@ -911,7 +938,7 @@
if ((rc+1) < context->QueueSize) { - memcpy(context->PacketQueue, &context->PacketQueue[rc+1], + memmove(context->PacketQueue, &context->PacketQueue[rc+1], (context->QueueSize - (rc+1))*sizeof(WTPACKET)); } context->PacketsQueued -= (rc+1); @@ -1080,7 +1107,7 @@
for (limit = 0; limit < cMaxPkts && limit < context->PacketsQueued; limit++) ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[limit]); - + LeaveCriticalSection(&csTablet); TRACE("Copied %i packets\n",limit); return limit; @@ -1099,7 +1126,7 @@ UINT num = 0;
TRACE("(%p, %u, %u, %d, %p, %p)\n", - hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts); + hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts);
context = TABLET_FindOpenContext(hCtx);
@@ -1130,7 +1157,7 @@
/* remove read packets */ if ((end+1) < context->PacketsQueued) - memcpy( &context->PacketQueue[bgn], &context->PacketQueue[end+1], + memmove( &context->PacketQueue[bgn], &context->PacketQueue[end+1], (context->PacketsQueued - ((end-bgn)+1)) * sizeof (WTPACKET));
context->PacketsQueued -= ((end-bgn)+1);
I chatted with Alexandre yesterday and he expressed a number of concerns with how my patch works. He and I are going to work on make that patch suitable for winehq. Then i will get that applied. It should not change any of the functionality. Just trying to preserve DLL separation.
Then i will work with your patch to get that stuff in as well. One, thing.. could you do add a -w to your diff so that we can ignore the changes in white space. that will cause the patch to be smaller and easier for me to see what changes you made.
thanks
-aric
Robert North wrote:
Ok, Firstly, I'm including a patch that demonstrates fixes to the crashing in Painter, and the recursion in Photoshop.
The patch assumes that you have already applied Aric's patch from April 23rd.
I'd like feedback on wether the patch is OK, as it was generated on from my local subversion repository, not CVS. Please bear in mind that the code is designed as quick demonstration fixes, not for quality code. Having said that comments are welcome.
Secondly, I've done some more investigation into why Photoshop was not seeing tablet pressure. It turns out that this is due to Photoshop requesting tablet events from the desktop window. In the x11drv/event.c file, X11 events are interrogated, and the X11 window converted to a win32 window. This is done using the X11 feature of contexts: Application specific info mapping from an X11 window to user defined value. It appears that the X11 window has no X11 context, and therefore the XInput event handler is passed a hWnd of NULL. This causes the FindOpenContext not match any context. (Hence the recursion) Without a context, no event is posted (Hence the lack of pressure info)
Here's a typical debug trace showing the problem:
trace:event:EVENT_ProcessEvent called. trace:event:EVENT_ProcessEvent Got extention event for hwnd/window (nil)/37, GetFocus()=0x40042 trace:event:X11DRV_ProcessTabletEvent Recieved tablet motion event ((nil)) trace:wintab32:X11DRV_ProcessTabletEvent Recieved tablet motion event ((nil)) trace:wintab32:WTPacketsPeek (0xc00, 64, 0x43c828c4) trace:wintab32:WTPacketsGet (0xc00, 64, 0x1098388) trace:wintab32:TABLET_WindowProc Incomming Message 0x7ff0 (0x00000000, 0x00000000) trace:wintab32:AddPacketToContextQueue Trying Queue c00 (0 10020) trace:wintab32:AddPacketToContextQueue Done ((nil))
Thirdly, I've found out why Painter wasn't scaling correctly. There appear to be 2 issues. a. Tablet coordinates should be relative to the window the wintab context is attached to. Currently they are absoloute. b. The default system context as returned by WTInfo contains zero in the lcSysExtX,lcSysExtY fields These fields should contain the
I know how to fix the above problems, and will do so. P.S. Aric, I can now see the race condtion problem you were talking about in Painter.
Cheers -Rob.
Index: dlls/wintab32/context.c
--- dlls/wintab32/context.c (.../file:///usr/local/svnroot/wine/trunk) (revision 73) +++ dlls/wintab32/context.c (revision 73) @@ -3,6 +3,7 @@
- Copyright 2002 Patrik Stridvall
- Copyright 2003 Codeweavers, Aric Stewart
- Copyright 2003 Robert North
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
@@ -168,11 +169,16 @@ ptr = gOpenContexts; while (ptr) {
TRACE("Trying Context %lx (%x %x)\n",(LONG)ptr->handle,(INT)hwnd,
TRACE("Trying Context %lx hwnd(%x %x)\n",(LONG)ptr->handle,(INT)hwnd, (INT)ptr->hwndOwner);
if (ptr->hwndOwner == hwnd)
if (ptr->hwndOwner == hwnd) return ptr;
/* Rob 19-6-2003 Added recursion down pointer chein.
to avoid infinite loop.
Use TABLET_FindOpenContext as template.
*/
} return NULL;ptr = ptr->next;
} @@ -251,7 +257,13 @@
int static inline CopyTabletData(LPVOID target, LPVOID src, INT size) {
- memcpy(target,src,size);
+/*
- Rob 19-6-2003
- Return size only, if target is NULL:
- Was causing horrible crashes in MetaCreation's Painter 5.
+*/
- if(target != NULL)
return(size);memcpy(target,src,size);
}
@@ -318,39 +330,42 @@
static VOID TABLET_BlankPacketData(LPOPENCONTEXT context, LPVOID lpPkt, INT n) {
- int rc = 0;
- if(lpPkt != NULL)
- {
int rc = 0;
- if (context->context.lcPktData & PK_CONTEXT)
rc +=sizeof(HCTX);
- if (context->context.lcPktData & PK_STATUS)
rc +=sizeof(UINT);
- if (context->context.lcPktData & PK_TIME)
rc += sizeof(LONG);
- if (context->context.lcPktData & PK_CHANGED)
rc += sizeof(WTPKT);
- if (context->context.lcPktData & PK_SERIAL_NUMBER)
rc += sizeof(UINT);
- if (context->context.lcPktData & PK_CURSOR)
rc += sizeof(UINT);
- if (context->context.lcPktData & PK_BUTTONS)
rc += sizeof(DWORD);
- if (context->context.lcPktData & PK_X)
rc += sizeof(DWORD);
- if (context->context.lcPktData & PK_Y)
rc += sizeof(DWORD);
- if (context->context.lcPktData & PK_Z)
rc += sizeof(DWORD);
- if (context->context.lcPktData & PK_NORMAL_PRESSURE)
rc += sizeof(UINT);
- if (context->context.lcPktData & PK_TANGENT_PRESSURE)
rc += sizeof(UINT);
- if (context->context.lcPktData & PK_ORIENTATION)
rc += sizeof(ORIENTATION);
- if (context->context.lcPktData & PK_ROTATION)
rc += sizeof(ROTATION);
if (context->context.lcPktData & PK_CONTEXT)
rc +=sizeof(HCTX);
if (context->context.lcPktData & PK_STATUS)
rc +=sizeof(UINT);
if (context->context.lcPktData & PK_TIME)
rc += sizeof(LONG);
if (context->context.lcPktData & PK_CHANGED)
rc += sizeof(WTPKT);
if (context->context.lcPktData & PK_SERIAL_NUMBER)
rc += sizeof(UINT);
if (context->context.lcPktData & PK_CURSOR)
rc += sizeof(UINT);
if (context->context.lcPktData & PK_BUTTONS)
rc += sizeof(DWORD);
if (context->context.lcPktData & PK_X)
rc += sizeof(DWORD);
if (context->context.lcPktData & PK_Y)
rc += sizeof(DWORD);
if (context->context.lcPktData & PK_Z)
rc += sizeof(DWORD);
if (context->context.lcPktData & PK_NORMAL_PRESSURE)
rc += sizeof(UINT);
if (context->context.lcPktData & PK_TANGENT_PRESSURE)
rc += sizeof(UINT);
if (context->context.lcPktData & PK_ORIENTATION)
rc += sizeof(ORIENTATION);
if (context->context.lcPktData & PK_ROTATION)
rc += sizeof(ROTATION);
- rc *= n;
- memset(lpPkt,0,rc);
rc *= n;
memset(lpPkt,0,rc);
- }
}
@@ -856,7 +871,14 @@ */ int WINAPI WTPacketsGet(HCTX hCtx, int cMaxPkts, LPVOID lpPkts) {
- int limit;
- /*
Rob 19-6-2003
WTPacketsGet fails with lpPkts set to NULL.
TO DO: Handle null condition.
Null condition flushes queue (Of Max packets????)
- */
- int limit = 0;
- int maxPktsToGet; LPOPENCONTEXT context; LPVOID ptr = lpPkts;
@@ -872,15 +894,20 @@ return 0; }
- for(limit = 0; limit < cMaxPkts && limit < context->PacketsQueued; limit++)
- maxPktsToGet = min(cMaxPkts,context->PacketsQueued);
- if(lpPkts != NULL)
- {
for(limit = 0; limit < maxPktsToGet; limit++) ptr=TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[limit]);
- if (limit < context->PacketsQueued)
- }
- if (maxPktsToGet < context->PacketsQueued) {
memcpy(context->PacketQueue, &context->PacketQueue[limit],
(context->QueueSize - (limit))*sizeof(WTPACKET));
/* TO DO: Wrong function mem areas overlap. should use memmove*/
memmove(context->PacketQueue, &context->PacketQueue[maxPktsToGet],
}(context->QueueSize - (maxPktsToGet))*sizeof(WTPACKET));
- context->PacketsQueued -= limit;
context->PacketsQueued -= maxPktsToGet; LeaveCriticalSection(&csTablet);
TRACE("Copied %i packets\n",limit);
@@ -911,7 +938,7 @@
if ((rc+1) < context->QueueSize) {
memcpy(context->PacketQueue, &context->PacketQueue[rc+1],
memmove(context->PacketQueue, &context->PacketQueue[rc+1], (context->QueueSize - (rc+1))*sizeof(WTPACKET)); } context->PacketsQueued -= (rc+1);
@@ -1080,7 +1107,7 @@
for (limit = 0; limit < cMaxPkts && limit < context->PacketsQueued; limit++) ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[limit]);
- LeaveCriticalSection(&csTablet); TRACE("Copied %i packets\n",limit); return limit;
@@ -1099,7 +1126,7 @@ UINT num = 0;
TRACE("(%p, %u, %u, %d, %p, %p)\n",
hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts);
hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts);
context = TABLET_FindOpenContext(hCtx);
@@ -1130,7 +1157,7 @@
/* remove read packets */ if ((end+1) < context->PacketsQueued)
memcpy( &context->PacketQueue[bgn], &context->PacketQueue[end+1],
memmove( &context->PacketQueue[bgn], &context->PacketQueue[end+1], (context->PacketsQueued - ((end-bgn)+1)) * sizeof (WTPACKET));
context->PacketsQueued -= ((end-bgn)+1);
Aric Stewart aric-at-codeweavers.com |Wine Mailing Lists| wrote:
I chatted with Alexandre yesterday and he expressed a number of concerns with how my patch works. He and I are going to work on make that patch suitable for winehq. Then i will get that applied. It should not change any of the functionality. Just trying to preserve DLL separation.
Can you discuss a bit further what the separation issues are. I did some thinking about this when I was initially discussing a wintab implementation.
Might be a useful reference for other people looking at dll separation issues.
Then i will work with your patch to get that stuff in as well. One, thing.. could you do add a -w to your diff so that we can ignore the changes in white space. that will cause the patch to be smaller and easier for me to see what changes you made.
thanks
-aric
Ok, so you'll integrate the patches I sent. One suggestion: When you apply the patches, re-work the Packet reading functions to make the flush vs. read functionality clearer. My patch doesn't make the difference clear to the casual observer.
If you want I could do this re-working after you've posted your new patch.
I will work up some fixes to the Photoshop, and Painter issues with the current code, and release patches aganist your forthcoming patch. .... Unless you want to do that?
Cheers -Rob.