[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