Implemented get_accValue(), put_accName(), and put_accValue(). Merged the contents of accessibilitynotes into accessibility.h. More TODOs.
This commit is contained in:
parent
6264cf1fee
commit
cc49202006
|
@ -1,5 +1,17 @@
|
||||||
// 24 december 2014
|
// 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:
|
// notes:
|
||||||
// - TODO figure out what to do about header
|
// - 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)
|
// - 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:
|
// TODOs:
|
||||||
// - make sure E_POINTER and RPC_E_DISCONNECTED are correct returns for IAccessible
|
// - make sure E_POINTER and RPC_E_DISCONNECTED are correct returns for IAccessible
|
||||||
// - return last error on newTableAcc() in all accessible functions
|
// - 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
|
// uncomment this to debug table linked list management
|
||||||
//#define TABLE_DEBUG_LINKEDLIST
|
//#define TABLE_DEBUG_LINKEDLIST
|
||||||
|
@ -320,13 +335,49 @@ static HRESULT STDMETHODCALLTYPE tableAccget_accName(IAccessible *this, VARIANT
|
||||||
return E_FAIL;
|
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)
|
static HRESULT STDMETHODCALLTYPE tableAccget_accValue(IAccessible *this, VARIANT varChild, BSTR *pszValue)
|
||||||
{
|
{
|
||||||
if (TA->t == NULL || TA->std == NULL) {
|
HRESULT hr;
|
||||||
// TODO set values on error
|
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;
|
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)
|
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;
|
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)
|
static HRESULT STDMETHODCALLTYPE tableAccput_accName(IAccessible *this, VARIANT varChild, BSTR szName)
|
||||||
{
|
{
|
||||||
if (TA->t == NULL || TA->std == NULL) {
|
HRESULT hr;
|
||||||
// TODO set values on error
|
tableAccWhat what;
|
||||||
|
|
||||||
|
if (TA->t == NULL || TA->std == NULL)
|
||||||
return RPC_E_DISCONNECTED;
|
return RPC_E_DISCONNECTED;
|
||||||
}
|
what = TA->what;
|
||||||
return IAccessible_put_accName(TA->std, varChild, szName);
|
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)
|
static HRESULT STDMETHODCALLTYPE tableAccput_accValue(IAccessible *this, VARIANT varChild, BSTR szValue)
|
||||||
{
|
{
|
||||||
if (TA->t == NULL || TA->std == NULL) {
|
HRESULT hr;
|
||||||
// TODO set values on error
|
tableAccWhat what;
|
||||||
|
|
||||||
|
if (TA->t == NULL || TA->std == NULL)
|
||||||
return RPC_E_DISCONNECTED;
|
return RPC_E_DISCONNECTED;
|
||||||
}
|
what = TA->what;
|
||||||
return IAccessible_put_accValue(TA->std, varChild, szValue);
|
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 = {
|
static const IAccessibleVtbl tableAccVtbl = {
|
||||||
|
|
|
@ -1,6 +1,14 @@
|
||||||
// 8 december 2014
|
// 8 december 2014
|
||||||
|
|
||||||
// TODO move to api.h? definitely move somewhere
|
// 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)
|
static int isCheckboxChecked(struct table *t, intptr_t row, intptr_t column)
|
||||||
{
|
{
|
||||||
return notify(t, tableNotificationGetCellData, row, column, 0) != 0;
|
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");
|
panic("error setting Table cell text color");
|
||||||
if (SetBkMode(dc, TRANSPARENT) == 0)
|
if (SetBkMode(dc, TRANSPARENT) == 0)
|
||||||
panic("error setting transparent text drawing mode for Table cell");
|
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)
|
if (DrawTextExW(dc, text, -1, r, DT_END_ELLIPSIS | DT_LEFT | DT_NOPREFIX | DT_SINGLELINE, NULL) == 0)
|
||||||
panic("error drawing Table cell text");
|
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)
|
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)
|
if (DeleteDC(idc) == 0)
|
||||||
panic("error deleting Table compatible DC for image cell drawing");
|
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)
|
static void drawCheckboxCell(struct table *t, HDC dc, struct drawCellParams *p, RECT *r)
|
||||||
|
|
Loading…
Reference in New Issue