[PATCH v2 07/12] macdrv/wintab32: Implement WTInfoW.

Elaine Lefler elaineclefler at gmail.com
Thu Mar 24 23:46:21 CDT 2022


Signed-off-by: Elaine Lefler <elaineclefler at gmail.com>
---

v2: Splitting into smaller patches as per feedback.

This is the largest of the split patches, but unless "segfaults" or
"doesn't compile" is acceptable patch behavior, I can't split it any
further.

If it's any help, this file looks very similar to winex11.drv/wintab.c.
---
 dlls/winemac.drv/cocoa_wintab.h |  17 ++
 dlls/winemac.drv/wintab.c       | 410 +++++++++++++++++++++++++++++++-
 2 files changed, 426 insertions(+), 1 deletion(-)

diff --git a/dlls/winemac.drv/cocoa_wintab.h b/dlls/winemac.drv/cocoa_wintab.h
index 0fa20f6752c..1b9867c9d34 100644
--- a/dlls/winemac.drv/cocoa_wintab.h
+++ b/dlls/winemac.drv/cocoa_wintab.h
@@ -21,12 +21,29 @@
 #ifndef __WINE_MACDRV_COCOA_WINTAB_H
 #define __WINE_MACDRV_COCOA_WINTAB_H
 
+#include <math.h>
+
 #include "windef.h"
 #include "wintab.h"
 
 /* Extents that shouldn't cause math problems */
 #define TABLET_WIDTH    0x40000000
 #define TABLET_HEIGHT   0x40000000
+/* Largest reportable pressure value */
+#define MAX_PRESSURE    0x7fff
+/* Wacom's demo app teaches developers to assume 1/10th degree.
+ * Best stick to that. */
+#define ANGLE_SCALE     10
+/* Largest reportable angle (360 is included, due to rounding) */
+#define MAX_ANGLE       (360 * ANGLE_SCALE)
+
+#define MAKE_ANGLE_DEG(degrees) ((degrees) * ANGLE_SCALE)
+#define MAKE_ANGLE_RAD(radians) ((radians) * MAKE_ANGLE_DEG(180) / M_PI)
+
+/* Cursor indices */
+#define MACDRV_CURSOR_PEN       0
+#define MACDRV_CURSOR_ERASER    1
+#define MACDRV_CURSOR_CURSOR    2
 
 /* Shared device context */
 extern LOGCONTEXTW macdrv_tablet_ctx DECLSPEC_HIDDEN;
diff --git a/dlls/winemac.drv/wintab.c b/dlls/winemac.drv/wintab.c
index fffae85f735..bd6d6b783e0 100644
--- a/dlls/winemac.drv/wintab.c
+++ b/dlls/winemac.drv/wintab.c
@@ -43,6 +43,29 @@ static size_t registered_hwnd_count = 0;
 static size_t registered_hwnd_cap = 0;
 static HWND* registered_hwnd = NULL;
 
+static const WCHAR CURSOR_NAME_PEN[] = {'P','r','e','s','s','u','r','e',' ','S','t','y','l','u','s',0};
+static const WCHAR CURSOR_NAME_ERASER[] = {'E','r','a','s','e','r',0};
+static const WCHAR CURSOR_NAME_CURSOR[] = {'P','u','c','k',0};
+
+static const UINT CURSOR_COUNT = 3;
+static const WCHAR* const CURSOR_NAMES[CURSOR_COUNT] = {
+    CURSOR_NAME_PEN,
+    CURSOR_NAME_ERASER,
+    CURSOR_NAME_CURSOR
+};
+
+static const UINT CURSOR_TYPES[CURSOR_COUNT] = {
+    CSR_TYPE_PEN,
+    CSR_TYPE_ERASER,
+    CSR_TYPE_MOUSE_2D
+};
+
+static const UINT CURSOR_CAPABILITIES[CURSOR_COUNT] = {
+    CRC_MULTIMODE | CRC_AGGREGATE,
+    CRC_MULTIMODE | CRC_AGGREGATE | CRC_INVERT,
+    CRC_AGGREGATE
+};
+
 static const BYTE BUTTON_COUNT = 16;
 
 BOOL CDECL macdrv_LoadTabletInfo(HWND tablet_hwnd)
@@ -125,7 +148,392 @@ BOOL CDECL macdrv_LoadTabletInfo(HWND tablet_hwnd)
 UINT CDECL macdrv_WTInfoW(UINT wCategory, UINT nIndex, LPVOID lpOutput)
 {
     TRACE("(%u, %u, %p)\n", wCategory, nIndex, lpOutput);
-    FIXME("Unhandled Category %i\n", wCategory);
+
+    if (IS_WTI_EXTENSIONS_TYPE(wCategory))
+    {
+        FIXME("WTI_EXTENSIONS unimplemented");
+        return 0;
+    }
+    else if (IS_WTI_CURSORS_TYPE(wCategory))
+    {
+        INT cursor_idx = wCategory - WTI_CURSORS;
+        if (cursor_idx < 0)
+            cursor_idx += CURSOR_COUNT;
+        if (cursor_idx < 0 || cursor_idx >= CURSOR_COUNT)
+            return 0;
+        switch (nIndex)
+        {
+            case CSR_NAME:
+                return TABLET_CopyData(lpOutput, CURSOR_NAMES[cursor_idx], (strlenW(CURSOR_NAMES[cursor_idx]) + 1) * sizeof(WCHAR));
+            case CSR_ACTIVE:
+            {
+                BOOL active = 1;
+                return TABLET_CopyData(lpOutput, &active, sizeof(active));
+            }
+            case CSR_PKTDATA:
+                return TABLET_CopyData(lpOutput, &macdrv_tablet_ctx.lcPktData, sizeof(macdrv_tablet_ctx.lcPktData));
+            case CSR_BUTTONS:
+            case CSR_BUTTONBITS:
+                return TABLET_CopyData(lpOutput, &BUTTON_COUNT, sizeof(BUTTON_COUNT));
+            case CSR_BTNNAMES:
+            {
+                static const char* const fmt = "button %d";
+                static char buffer[10];
+                int out_size = 0;
+                PWCHAR out_char = lpOutput;
+                int button;
+
+                /* Each button name is \0-terminated, with an extra \0 at the
+                 * end. */
+                for (button = 0; button < BUTTON_COUNT; button++)
+                {
+                    int name_len;
+
+                    snprintf(buffer, sizeof(buffer), fmt, button);
+                    name_len = strlen(buffer);
+
+                    out_size += name_len + 1;
+                    if (out_char != NULL)
+                    {
+                        int c;
+                        for(c = 0; c <= name_len; c++)
+                            *(out_char++) = buffer[c];
+                    }
+                }
+                if (out_char != NULL)
+                    *out_char = 0;
+                return (out_size + 1) * sizeof(WCHAR);
+            }
+            case CSR_BUTTONMAP:
+            case CSR_SYSBTNMAP:
+            {
+                PBYTE out_byte = lpOutput;
+                int b;
+
+                if (out_byte != NULL)
+                {
+                    /* Always use 1:1 mapping */
+                    for (b = 0; b < BUTTON_COUNT; b++)
+                        out_byte[b] = b;
+                }
+                return BUTTON_COUNT * sizeof(BYTE);
+            }
+            case CSR_NPBUTTON:
+            case CSR_TPBUTTON:
+            {
+                BYTE button = 0;
+                return TABLET_CopyData(lpOutput, &button, sizeof(button));
+            }
+            case CSR_NPBTNMARKS:
+            case CSR_TPBTNMARKS:
+            {
+                static const UINT marks[] = {0, 1};
+                return TABLET_CopyData(lpOutput, &marks, sizeof(marks));
+            }
+            case CSR_NPRESPONSE:
+            case CSR_TPRESPONSE:
+            {
+                static const int POINT_COUNT = 256;
+                PUINT out_uint = lpOutput;
+                int p;
+
+                if (out_uint != NULL)
+                {
+                    /* Linear response */
+                    for (p = 0; p < POINT_COUNT; p++)
+                        out_uint[p] = MAX_PRESSURE * p / POINT_COUNT;
+                }
+                return POINT_COUNT * sizeof(UINT);
+            }
+            case CSR_PHYSID:
+            {
+                DWORD physid = 0xdeadbeef;
+                return TABLET_CopyData(lpOutput, &physid, sizeof(physid));
+            }
+            case CSR_MODE:
+            {
+                UINT mode = (UINT)cursor_idx;
+                if (!(CURSOR_CAPABILITIES[cursor_idx] & CRC_MULTIMODE))
+                    return 0;
+                return TABLET_CopyData(lpOutput, &mode, sizeof(mode));
+            }
+            case CSR_MINPKTDATA:
+            {
+                /* Should be safe to assume all tablets support these */
+                UINT pktdata = PK_CONTEXT | PK_STATUS | PK_TIME | PK_CHANGED
+                    | PK_SERIAL_NUMBER | PK_CURSOR | PK_BUTTONS | PK_X | PK_Y
+                    | PK_NORMAL_PRESSURE;
+                if (!(CURSOR_CAPABILITIES[cursor_idx] & CRC_AGGREGATE))
+                    return 0;
+                return TABLET_CopyData(lpOutput, &pktdata, sizeof(pktdata));
+            }
+            case CSR_MINBUTTONS:
+            {
+                UINT minbuttons = 1;
+                if (!(CURSOR_CAPABILITIES[cursor_idx] & CRC_AGGREGATE))
+                    return 0;
+                return TABLET_CopyData(lpOutput, &minbuttons, sizeof(minbuttons));
+            }
+            case CSR_CAPABILITIES:
+                return TABLET_CopyData(lpOutput, CURSOR_CAPABILITIES + cursor_idx, sizeof(*CURSOR_CAPABILITIES));
+            case CSR_TYPE:
+                return TABLET_CopyData(lpOutput, CURSOR_TYPES + cursor_idx, sizeof(*CURSOR_TYPES));
+            default:
+                FIXME("WTI_CURSORS+%d unhandled index %i\n", cursor_idx, nIndex);
+                return 0;
+        }
+    }
+
+    /* Non-indexed categories */
+    switch (wCategory)
+    {
+        case 0:
+            /* Largest buffer necessary for any category. This is currently
+             * WTI_CURSORS :: CSR_NPRESPONSE (or CSR_TPRESPONSE). */
+            return 256 * sizeof(UINT);
+        case WTI_INTERFACE:
+            switch (nIndex)
+            {
+                case IFC_WINTABID:
+                {
+                    static const WCHAR name[] = {'M','a','c','d','r','v',' ','W','i','n','t','a','b',' ','1','.','1',0};
+                    return TABLET_CopyData(lpOutput, name, sizeof(name));
+                }
+                case IFC_SPECVERSION:
+                {
+                    static const WORD version = (0x01) | (0x01 << 8);
+                    return TABLET_CopyData(lpOutput, &version, sizeof(version));
+                }
+                case IFC_IMPLVERSION:
+                {
+                    static const WORD version = (0x00) | (0x01 << 8);
+                    return TABLET_CopyData(lpOutput, &version, sizeof(version));
+                }
+                case IFC_NDEVICES:
+                {
+                    static const UINT num = 1;
+                    return TABLET_CopyData(lpOutput, &num, sizeof(num));
+                }
+                case IFC_NCURSORS:
+                {
+                    return TABLET_CopyData(lpOutput, &CURSOR_COUNT, sizeof(CURSOR_COUNT));
+                }
+                case IFC_NCONTEXTS:
+                {
+                    static const UINT num = 1;
+                    return TABLET_CopyData(lpOutput, &num, sizeof(num));
+                }
+                default:
+                    FIXME("WTI_INTERFACE unhandled index %i\n", nIndex);
+                    return 0;
+            }
+            break;
+        case WTI_DEFCONTEXT:
+        case WTI_DEFSYSCTX:
+        case WTI_DDCTXS:
+        case WTI_DDCTXS - 1:
+        case WTI_DSCTXS:
+        case WTI_DSCTXS - 1:
+        {
+            BOOL is_sys = (wCategory == WTI_DEFSYSCTX || wCategory == WTI_DSCTXS || wCategory == WTI_DSCTXS - 1);
+            LPLOGCONTEXTW active_ctx = (is_sys ? &macdrv_system_ctx : &macdrv_tablet_ctx);
+            switch (nIndex)
+            {
+                case 0:
+                    return TABLET_CopyData(lpOutput, active_ctx, sizeof(*active_ctx));
+                case CTX_NAME:
+                    return TABLET_CopyData(lpOutput, active_ctx->lcName, (strlenW(active_ctx->lcName) + 1) * sizeof(WCHAR));
+                case CTX_OPTIONS:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcOptions, sizeof(active_ctx->lcOptions));
+                case CTX_STATUS:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcStatus, sizeof(active_ctx->lcStatus));
+                case CTX_LOCKS:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcLocks, sizeof(active_ctx->lcLocks));
+                case CTX_MSGBASE:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcMsgBase, sizeof(active_ctx->lcMsgBase));
+                case CTX_DEVICE:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcDevice, sizeof(active_ctx->lcDevice));
+                case CTX_PKTRATE:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcPktRate, sizeof(active_ctx->lcPktRate));
+                case CTX_PKTDATA:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcPktData, sizeof(active_ctx->lcPktData));
+                case CTX_PKTMODE:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcPktMode, sizeof(active_ctx->lcPktMode));
+                case CTX_MOVEMASK:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcMoveMask, sizeof(active_ctx->lcMoveMask));
+                case CTX_BTNDNMASK:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcBtnDnMask, sizeof(active_ctx->lcBtnDnMask));
+                case CTX_BTNUPMASK:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcBtnUpMask, sizeof(active_ctx->lcBtnUpMask));
+                case CTX_INORGX:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcInOrgX, sizeof(active_ctx->lcInOrgX));
+                case CTX_INORGY:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcInOrgY, sizeof(active_ctx->lcInOrgY));
+                case CTX_INORGZ:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcInOrgZ, sizeof(active_ctx->lcInOrgZ));
+                case CTX_INEXTX:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcInExtX, sizeof(active_ctx->lcInExtX));
+                case CTX_INEXTY:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcInExtY, sizeof(active_ctx->lcInExtY));
+                case CTX_INEXTZ:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcInExtZ, sizeof(active_ctx->lcInExtZ));
+                case CTX_OUTORGX:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcOutOrgX, sizeof(active_ctx->lcOutOrgX));
+                case CTX_OUTORGY:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcOutOrgY, sizeof(active_ctx->lcOutOrgY));
+                case CTX_OUTORGZ:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcOutOrgZ, sizeof(active_ctx->lcOutOrgZ));
+               case CTX_OUTEXTX:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcOutExtX, sizeof(active_ctx->lcOutExtX));
+                case CTX_OUTEXTY:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcOutExtY, sizeof(active_ctx->lcOutExtY));
+                case CTX_OUTEXTZ:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcOutExtZ, sizeof(active_ctx->lcOutExtZ));
+                case CTX_SENSX:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcSensX, sizeof(active_ctx->lcSensX));
+                case CTX_SENSY:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcSensY, sizeof(active_ctx->lcSensY));
+                case CTX_SENSZ:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcSensZ, sizeof(active_ctx->lcSensZ));
+                case CTX_SYSMODE:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcSysMode, sizeof(active_ctx->lcSysMode));
+                case CTX_SYSORGX:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcSysOrgX, sizeof(active_ctx->lcSysOrgX));
+                case CTX_SYSORGY:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcSysOrgY, sizeof(active_ctx->lcSysOrgY));
+                case CTX_SYSEXTX:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcSysExtX, sizeof(active_ctx->lcSysExtX));
+                case CTX_SYSEXTY:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcSysExtY, sizeof(active_ctx->lcSysExtY));
+                case CTX_SYSSENSX:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcSysSensX, sizeof(active_ctx->lcSysSensX));
+                case CTX_SYSSENSY:
+                    return TABLET_CopyData(lpOutput, &active_ctx->lcSysSensY, sizeof(active_ctx->lcSysSensY));
+                default:
+                    FIXME("WTI_DEFSYSCTX unhandled index %i\n", nIndex);
+                    return 0;
+            }
+        }
+        case WTI_DEVICES:
+        case WTI_DEVICES - 1:
+            switch (nIndex)
+            {
+                case DVC_NAME:
+                {
+                    static const WCHAR name[] = {'M','a','c','d','r','v',' ','T','a','b','l','e','t',0};
+                    return TABLET_CopyData(lpOutput, name, sizeof(name));
+                }
+                case DVC_HARDWARE:
+                {
+                    static const UINT hardware = HWC_HARDPROX;
+                    return TABLET_CopyData(lpOutput, &hardware, sizeof(hardware));
+                }
+                case DVC_NCSRTYPES:
+                {
+                    static const UINT num = 0;
+                    return TABLET_CopyData(lpOutput, &num, sizeof(num));
+                }
+                case DVC_FIRSTCSR:
+                {
+                    static const UINT first = 0;
+                    return TABLET_CopyData(lpOutput, &first, sizeof(first));
+                }
+                case DVC_PKTRATE:
+                    return TABLET_CopyData(lpOutput, &macdrv_tablet_ctx.lcPktRate, sizeof(macdrv_tablet_ctx.lcPktRate));
+                case DVC_PKTDATA:
+                    return TABLET_CopyData(lpOutput, &macdrv_tablet_ctx.lcPktData, sizeof(macdrv_tablet_ctx.lcPktData));
+                case DVC_PKTMODE:
+                    return TABLET_CopyData(lpOutput, &macdrv_tablet_ctx.lcPktMode, sizeof(macdrv_tablet_ctx.lcPktMode));
+                case DVC_CSRDATA:
+                {
+                    static const WTPKT data = 0;
+                    return TABLET_CopyData(lpOutput, &data, sizeof(data));
+                }
+                case DVC_XMARGIN:
+                case DVC_YMARGIN:
+                case DVC_ZMARGIN:
+                {
+                    static const INT margin = 0;
+                    return TABLET_CopyData(lpOutput, &margin, sizeof(margin));
+                }
+                case DVC_X:
+                case DVC_Y:
+                case DVC_Z:
+                {
+                    UINT org = (nIndex == DVC_X ? macdrv_tablet_ctx.lcInOrgX : nIndex == DVC_Y ? macdrv_tablet_ctx.lcInOrgY : macdrv_tablet_ctx.lcInOrgZ);
+                    UINT ext = (nIndex == DVC_X ? macdrv_tablet_ctx.lcInExtX : nIndex == DVC_Y ? macdrv_tablet_ctx.lcInExtY : macdrv_tablet_ctx.lcInExtZ);
+                    AXIS ax = {
+                        .axMin = org,
+                        .axMax = org + ext - 1,
+                        .axUnits = TU_NONE,
+                        .axResolution = 1
+                    };
+                    return TABLET_CopyData(lpOutput, &ax, sizeof(ax));
+                }
+                case DVC_NPRESSURE:
+                {
+                    static const AXIS ax = {
+                        .axMin = 0,
+                        .axMax = MAX_PRESSURE,
+                        .axUnits = TU_NONE,
+                        .axResolution = 1
+                    };
+                    return TABLET_CopyData(lpOutput, &ax, sizeof(ax));
+                }
+                case DVC_TPRESSURE:
+                {
+                    static const AXIS ax = {
+                        .axMin = -MAX_PRESSURE,
+                        .axMax = MAX_PRESSURE,
+                        .axUnits = TU_NONE,
+                        .axResolution = 1
+                    };
+                    return TABLET_CopyData(lpOutput, &ax, sizeof(ax));
+                }
+                case DVC_ORIENTATION:
+                {
+                    static const AXIS axes[] = {
+                        /*.orAzimuth = */ {
+                            .axMin = 0,
+                            .axMax = MAX_ANGLE,
+                            .axUnits = TU_CIRCLE,
+                            .axResolution = CASTFIX32(MAX_ANGLE)
+                        },
+                        /*.orAltitude = */ {
+                            .axMin = -MAKE_ANGLE_DEG(90),
+                            .axMax = MAKE_ANGLE_DEG(90),
+                            .axUnits = TU_CIRCLE,
+                            .axResolution = CASTFIX32(MAX_ANGLE)
+                        },
+                        /*.orTwist = */ {
+                            .axMin = 0,
+                            .axMax = MAX_ANGLE,
+                            .axUnits = TU_CIRCLE,
+                            .axResolution = CASTFIX32(MAX_ANGLE)
+                        }
+                    };
+                    return TABLET_CopyData(lpOutput, &axes, sizeof(axes));
+                }
+                case DVC_ROTATION:
+                    /* Unsupported */
+                    return 0;
+                case DVC_PNPID:
+                {
+                    static const WCHAR pnpId[] = {'n','o','n','-','p','l','u','g','-','n','-','p','l','a','y',0};
+                    return TABLET_CopyData(lpOutput, pnpId, sizeof(pnpId));
+                }
+                default:
+                    FIXME("WTI_DEVICES unhandled index %i\n", nIndex);
+                    return 0;
+            }
+            break;
+        default:
+            if (IS_WTI_DEVICES_TYPE(wCategory) || IS_WTI_DDCTXS_TYPE(wCategory)
+                    || IS_WTI_DSCTXS_TYPE(wCategory))
+                /* User error, there's only one device */
+                return 0;
+            FIXME("Unhandled Category %i\n", wCategory);
+    }
     return 0;
 }
 
-- 
2.32.0 (Apple Git-132)




More information about the wine-devel mailing list