From cc492020060158b76956b91ca8ea5934c5763705 Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Tue, 17 Feb 2015 12:18:31 -0500 Subject: [PATCH] Implemented get_accValue(), put_accName(), and put_accValue(). Merged the contents of accessibilitynotes into accessibility.h. More TODOs. --- wintable/accessibility.h | 91 +++++++++++++++++++++++++++++++++++----- wintable/draw.h | 14 +++++-- 2 files changed, 91 insertions(+), 14 deletions(-) diff --git a/wintable/accessibility.h b/wintable/accessibility.h index a64bb4a..662a6f5 100644 --- a/wintable/accessibility.h +++ b/wintable/accessibility.h @@ -1,5 +1,17 @@ // 24 december 2014 +// implement MSAA-conformant accessibility +// we need to use MSAA because UI Automation is too new for us +// unfortunately, MSAA's documentation is... very poor. very ambiguous, very inconsistent (just run through this file's commit history and watch the TODO progression to see) +// resources: +// http://msdn.microsoft.com/en-us/library/ms971338.aspx +// http://msdn.microsoft.com/en-us/library/windows/desktop/cc307844.aspx +// http://msdn.microsoft.com/en-us/library/windows/desktop/cc307847.aspx +// http://blogs.msdn.com/b/saraford/archive/2004/08/20/which-controls-support-which-msaa-properties-and-how-these-controls-implement-msaa-properties.aspx +// http://msdn.microsoft.com/en-us/library/ms971325 +// http://msdn.microsoft.com/en-us/library/windows/desktop/dd318017%28v=vs.85%29.aspx +// http://msdn.microsoft.com/en-us/library/windows/desktop/dd373624%28v=vs.85%29.aspx + // notes: // - TODO figure out what to do about header // - a row extends as far right as the right edge of the last cell in the row; anything to the right of that is treated as table space (just like with mouse selection) @@ -12,6 +24,9 @@ // TODOs: // - make sure E_POINTER and RPC_E_DISCONNECTED are correct returns for IAccessible // - return last error on newTableAcc() in all accessible functions +// - figure out what should be names and what should be values +// - figure out what to do about that header row +// - http://acccheck.codeplex.com/ // uncomment this to debug table linked list management //#define TABLE_DEBUG_LINKEDLIST @@ -320,13 +335,49 @@ static HRESULT STDMETHODCALLTYPE tableAccget_accName(IAccessible *this, VARIANT return E_FAIL; } +// this differs quite much from what is described at https://msdn.microsoft.com/en-us/library/ms971325 static HRESULT STDMETHODCALLTYPE tableAccget_accValue(IAccessible *this, VARIANT varChild, BSTR *pszValue) { - if (TA->t == NULL || TA->std == NULL) { - // TODO set values on error + HRESULT hr; + tableAccWhat what; + WCHAR *text; + + if (pszValue == NULL) + return E_POINTER; + // TODO set pszValue to zero? + if (TA->t == NULL || TA->std == NULL) return RPC_E_DISCONNECTED; + what = TA->what; + hr = normalizeWhat(TA, varChild, &what); + if (hr != S_OK) + return hr; + switch (what.role) { + case ROLE_SYSTEM_TABLE: + // TODO really? + return IAccessible_get_accValue(TA->std, varChild, pszValue); + case ROLE_SYSTEM_ROW: + // TODO + return DISP_E_MEMBERNOTFOUND; + case ROLE_SYSTEM_CELL: + switch (TA->t->columnTypes[what.column]) { + case tableColumnText: + text = getCellText(TA->t, what.row, what.column); + // TODO check for error + *pszValue = SysAllocString(text); + returnCellData(TA->t, what.row, what.column, text); + return S_OK; + case tableColumnImage: + // TODO + return DISP_E_MEMBERNOTFOUND; + case tableColumnCheckbox: + // TODO!!!!!! + return DISP_E_MEMBERNOTFOUND; + } } - return IAccessible_get_accValue(TA->std, varChild, pszValue); + // TODO actually do this right + // TODO un-GetLastError() this + panic("impossible blah blah blah TODO write this"); + return E_FAIL; } static HRESULT STDMETHODCALLTYPE tableAccget_accDescription(IAccessible *this, VARIANT varChild, BSTR *pszDescription) @@ -891,22 +942,40 @@ static HRESULT STDMETHODCALLTYPE tableAccaccDoDefaultAction(IAccessible *this, V return DISP_E_MEMBERNOTFOUND; } +// inconsistencies, inconsistencies +// https://msdn.microsoft.com/en-us/library/windows/desktop/dd318491%28v=vs.85%29.aspx says to just return E_NOTIMPL and not even bother with an implementation; in fact it doesn't even *have* the documentation anymore +// http://blogs.msdn.com/b/saraford/archive/2004/08/20/which-controls-support-which-msaa-properties-and-how-these-controls-implement-msaa-properties.aspx says never to return E_NOTIMPL from an IAccessible method (but it also discounts RPC_E_DISCONNECTED (not explicitly), so I'm guessing this is a much older document) +// let's just do what our put_accValue() does and do full validation, then just return DISP_E_MEMBERNOTFOUND +// I really hope UI Automation isn't so ambiguous and inconsistent... too bad I'm still choosing to support Windows XP while its market share (compared to *every other OS ever*) is still as large as it is static HRESULT STDMETHODCALLTYPE tableAccput_accName(IAccessible *this, VARIANT varChild, BSTR szName) { - if (TA->t == NULL || TA->std == NULL) { - // TODO set values on error + HRESULT hr; + tableAccWhat what; + + if (TA->t == NULL || TA->std == NULL) return RPC_E_DISCONNECTED; - } - return IAccessible_put_accName(TA->std, varChild, szName); + what = TA->what; + hr = normalizeWhat(TA, varChild, &what); + if (hr != S_OK) + return hr; + // don't support setting values anyway; do return the above errors just to be safe + return DISP_E_MEMBERNOTFOUND; } static HRESULT STDMETHODCALLTYPE tableAccput_accValue(IAccessible *this, VARIANT varChild, BSTR szValue) { - if (TA->t == NULL || TA->std == NULL) { - // TODO set values on error + HRESULT hr; + tableAccWhat what; + + if (TA->t == NULL || TA->std == NULL) return RPC_E_DISCONNECTED; - } - return IAccessible_put_accValue(TA->std, varChild, szValue); + what = TA->what; + hr = normalizeWhat(TA, varChild, &what); + if (hr != S_OK) + return hr; + // don't support setting values anyway; do return the above errors just to be safe + // TODO defer ROW_SYSTEM_TABLE to the standard accessible object? + return DISP_E_MEMBERNOTFOUND; } static const IAccessibleVtbl tableAccVtbl = { diff --git a/wintable/draw.h b/wintable/draw.h index 650e3e2..3aeb300 100644 --- a/wintable/draw.h +++ b/wintable/draw.h @@ -1,6 +1,14 @@ // 8 december 2014 // TODO move to api.h? definitely move somewhere +static WCHAR *getCellText(struct table *t, intptr_t row, intptr_t column) +{ + return (WCHAR *) notify(t, tableNotificationGetCellData, row, column, 0); +} +static void returnCellData(struct table *t, intptr_t row, intptr_t column, void *what) +{ + notify(t, tableNotificationFinishedWithCellData, row, column, (uintptr_t) what); +} static int isCheckboxChecked(struct table *t, intptr_t row, intptr_t column) { return notify(t, tableNotificationGetCellData, row, column, 0) != 0; @@ -25,10 +33,10 @@ static void drawTextCell(struct table *t, HDC dc, struct drawCellParams *p, RECT panic("error setting Table cell text color"); if (SetBkMode(dc, TRANSPARENT) == 0) panic("error setting transparent text drawing mode for Table cell"); - text = (WCHAR *) notify(t, tableNotificationGetCellData, p->row, p->column, 0); + text = getCellText(t, p->row, p->column); if (DrawTextExW(dc, text, -1, r, DT_END_ELLIPSIS | DT_LEFT | DT_NOPREFIX | DT_SINGLELINE, NULL) == 0) panic("error drawing Table cell text"); - notify(t, tableNotificationFinishedWithCellData, p->row, p->column, (uintptr_t) text); + returnCellData(t, p->row, p->column, text); } static void drawImageCell(struct table *t, HDC dc, struct drawCellParams *p, RECT *r) @@ -70,7 +78,7 @@ static void drawImageCell(struct table *t, HDC dc, struct drawCellParams *p, REC if (DeleteDC(idc) == 0) panic("error deleting Table compatible DC for image cell drawing"); - notify(t, tableNotificationFinishedWithCellData, p->row, p->column, (uintptr_t) bitmap); + returnCellData(t, p->row, p->column, bitmap); } static void drawCheckboxCell(struct table *t, HDC dc, struct drawCellParams *p, RECT *r)