mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 381888. Caret tracking broken with Windows screen readers [Cairo-related]. When a11y active, follow Gecko caret around with invisible system caret. r=surkov
This commit is contained in:
parent
1423e531e9
commit
cf34398740
@ -59,7 +59,6 @@ XPIDLSRCS = \
|
|||||||
nsIAccessibleRole.idl \
|
nsIAccessibleRole.idl \
|
||||||
nsIAccessibleStates.idl \
|
nsIAccessibleStates.idl \
|
||||||
nsPIAccessible.idl \
|
nsPIAccessible.idl \
|
||||||
nsIAccessibleCaret.idl \
|
|
||||||
nsIAccessibleDocument.idl \
|
nsIAccessibleDocument.idl \
|
||||||
nsPIAccessibleDocument.idl \
|
nsPIAccessibleDocument.idl \
|
||||||
nsIAccessibleProvider.idl \
|
nsIAccessibleProvider.idl \
|
||||||
|
@ -1,77 +0,0 @@
|
|||||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
||||||
*
|
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the Mozilla Public License Version
|
|
||||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
||||||
* the License. You may obtain a copy of the License at
|
|
||||||
* http://www.mozilla.org/MPL/
|
|
||||||
*
|
|
||||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
||||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
||||||
* for the specific language governing rights and limitations under the
|
|
||||||
* License.
|
|
||||||
*
|
|
||||||
* The Original Code is the Mozilla browser.
|
|
||||||
*
|
|
||||||
* The Initial Developer of the Original Code is
|
|
||||||
* Netscape Communications Corporation.
|
|
||||||
* Portions created by the Initial Developer are Copyright (C) 1999
|
|
||||||
* the Initial Developer. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
*
|
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
|
||||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
|
||||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
||||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
||||||
* of those above. If you wish to allow use of your version of this file only
|
|
||||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
||||||
* use your version of this file under the terms of the MPL, indicate your
|
|
||||||
* decision by deleting the provisions above and replace them with the notice
|
|
||||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
||||||
* the provisions above, a recipient may use your version of this file under
|
|
||||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
||||||
*
|
|
||||||
* ***** END LICENSE BLOCK ***** */
|
|
||||||
|
|
||||||
#include "nsISupports.idl"
|
|
||||||
#include "nsIDOMNode.idl"
|
|
||||||
|
|
||||||
[scriptable, uuid(ef372cc1-0fd4-4e71-ac32-64028e680f17)]
|
|
||||||
interface nsIAccessibleCaret : nsISupports
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Listen to selection events on the focused control.
|
|
||||||
* Only one control's selection events are listened to at a time, per top-level window.
|
|
||||||
* This will remove the previous control's selection listener.
|
|
||||||
* It will fail if aFocusedNode is a document node -- document selection must be listened
|
|
||||||
* to via addDocSelectionListener().
|
|
||||||
* @param aFocusedNode The node for the focused control
|
|
||||||
*/
|
|
||||||
void setControlSelectionListener(in nsIDOMNode aFocusedNode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop listening to selection events for any control.
|
|
||||||
* This does not have to be called explicitly in Shutdown() procedures,
|
|
||||||
* because the implementation of nsIAccessibleCaret will guarantee that.
|
|
||||||
*/
|
|
||||||
void clearControlSelectionListener();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start listening to selection events for a given document
|
|
||||||
* More than one document's selection events can be listened to
|
|
||||||
* at the same time, by a given nsIAccessibleCaret.
|
|
||||||
* @param aDocument Document to listen to selection events for.
|
|
||||||
*/
|
|
||||||
void addDocSelectionListener(in nsIDOMDocument aDocument);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop listening to selection events for a given document
|
|
||||||
* If the document goes away, this method needs to be called for
|
|
||||||
* that document by the owner of the nsIAccessibleCaret
|
|
||||||
* @param aDocument Document to listen to selection events for.
|
|
||||||
*/
|
|
||||||
void removeDocSelectionListener(in nsIDOMDocument aDocument);
|
|
||||||
};
|
|
@ -58,7 +58,7 @@ interface nsIDOMWindow;
|
|||||||
*
|
*
|
||||||
* @status UNDER_REVIEW
|
* @status UNDER_REVIEW
|
||||||
*/
|
*/
|
||||||
[scriptable, uuid(60f8b190-63c4-4919-ac92-a7a8212fc813)]
|
[scriptable, uuid(ae5792a3-77ad-40d6-8450-d28d19b66889)]
|
||||||
interface nsIAccessibleDocument : nsISupports
|
interface nsIAccessibleDocument : nsISupports
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@ -91,11 +91,6 @@ interface nsIAccessibleDocument : nsISupports
|
|||||||
*/
|
*/
|
||||||
readonly attribute nsIDOMWindow window;
|
readonly attribute nsIDOMWindow window;
|
||||||
|
|
||||||
/*
|
|
||||||
* The accessible for the caret belonging to this window.
|
|
||||||
*/
|
|
||||||
readonly attribute nsIAccessible caretAccessible;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The namespace for each ID that is handed back.
|
* The namespace for each ID that is handed back.
|
||||||
*/
|
*/
|
||||||
|
@ -354,9 +354,9 @@ already_AddRefed<nsRootAccessible> nsAccessNode::GetRootAccessible()
|
|||||||
|
|
||||||
// nsRootAccessible has a special QI
|
// nsRootAccessible has a special QI
|
||||||
// that let us get that concrete type directly.
|
// that let us get that concrete type directly.
|
||||||
nsRootAccessible* foo;
|
nsRootAccessible* rootAccessible;
|
||||||
accDoc->QueryInterface(NS_GET_IID(nsRootAccessible), (void**)&foo); // addrefs
|
accDoc->QueryInterface(NS_GET_IID(nsRootAccessible), (void**)&rootAccessible); // addrefs
|
||||||
return foo;
|
return rootAccessible;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIFrame* nsAccessNode::GetFrame()
|
nsIFrame* nsAccessNode::GetFrame()
|
||||||
|
@ -53,46 +53,47 @@
|
|||||||
#include "nsIViewManager.h"
|
#include "nsIViewManager.h"
|
||||||
#include "nsIWidget.h"
|
#include "nsIWidget.h"
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS_INHERITED2(nsCaretAccessible, nsLeafAccessible, nsIAccessibleCaret, nsISelectionListener)
|
NS_IMPL_ISUPPORTS1(nsCaretAccessible, nsISelectionListener)
|
||||||
|
|
||||||
nsCaretAccessible::nsCaretAccessible(nsIDOMNode* aDocumentNode, nsIWeakReference* aShell, nsRootAccessible *aRootAccessible):
|
nsCaretAccessible::nsCaretAccessible( nsRootAccessible *aRootAccessible):
|
||||||
nsLeafAccessible(aDocumentNode, aShell), mCurrentControl(nsnull), mLastNodeWithCaret(nsnull),
|
|
||||||
mLastCaretOffset(-1), mRootAccessible(aRootAccessible)
|
mLastCaretOffset(-1), mRootAccessible(aRootAccessible)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP nsCaretAccessible::Shutdown()
|
nsCaretAccessible::~nsCaretAccessible()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void nsCaretAccessible::Shutdown()
|
||||||
{
|
{
|
||||||
// The caret accessible isn't shut down until the nsRootAccessible owning it is shut down
|
// The caret accessible isn't shut down until the nsRootAccessible owning it is shut down
|
||||||
// Each nsDocAccessible, including the nsRootAccessible, is responsible for clearing the
|
// Each nsDocAccessible, including the nsRootAccessible, is responsible for clearing the
|
||||||
// doc selection listeners they registeed in this nsCaretAccessible
|
// doc selection listeners they registered in this nsCaretAccessible
|
||||||
ClearControlSelectionListener(); // Clear the selection listener for the currently focused control
|
|
||||||
mLastNodeWithCaret = nsnull;
|
|
||||||
mLastUsedSelection = nsnull;
|
|
||||||
|
|
||||||
return nsLeafAccessible::Shutdown();
|
ClearControlSelectionListener(); // Clear the selection listener for the currently focused control
|
||||||
|
mLastTextAccessible = nsnull;
|
||||||
|
mLastUsedSelection = nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP nsCaretAccessible::ClearControlSelectionListener()
|
nsresult nsCaretAccessible::ClearControlSelectionListener()
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryReferent(mCurrentControlSelection));
|
nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryReferent(mCurrentControlSelection));
|
||||||
if (selPrivate) {
|
NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE);
|
||||||
mCurrentControlSelection = nsnull;
|
|
||||||
mCurrentControl = nsnull;
|
mCurrentControlSelection = nsnull;
|
||||||
return selPrivate->RemoveSelectionListener(this);
|
mCurrentControl = nsnull;
|
||||||
}
|
return selPrivate->RemoveSelectionListener(this);
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP nsCaretAccessible::SetControlSelectionListener(nsIDOMNode *aCurrentNode)
|
nsresult nsCaretAccessible::SetControlSelectionListener(nsIDOMNode *aCurrentNode)
|
||||||
{
|
{
|
||||||
mCurrentControl = aCurrentNode;
|
mCurrentControl = aCurrentNode;
|
||||||
mLastNodeWithCaret = nsnull;
|
mLastTextAccessible = nsnull;
|
||||||
|
|
||||||
// When focus moves such that the caret is part of a new frame selection
|
// When focus moves such that the caret is part of a new frame selection
|
||||||
// this removes the old selection listener and attaches a new one for the current focus
|
// this removes the old selection listener and attaches a new one for the current focus
|
||||||
nsCOMPtr<nsIPresShell> presShell =
|
nsCOMPtr<nsIPresShell> presShell =
|
||||||
nsRootAccessible::GetPresShellFor(aCurrentNode);
|
mRootAccessible->GetPresShellFor(aCurrentNode);
|
||||||
if (!presShell)
|
if (!presShell)
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
@ -127,7 +128,7 @@ NS_IMETHODIMP nsCaretAccessible::SetControlSelectionListener(nsIDOMNode *aCurren
|
|||||||
return selPrivate->AddSelectionListener(this);
|
return selPrivate->AddSelectionListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP nsCaretAccessible::AddDocSelectionListener(nsIDOMDocument *aDoc)
|
nsresult nsCaretAccessible::AddDocSelectionListener(nsIDOMDocument *aDoc)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDoc);
|
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDoc);
|
||||||
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
|
||||||
@ -142,7 +143,7 @@ NS_IMETHODIMP nsCaretAccessible::AddDocSelectionListener(nsIDOMDocument *aDoc)
|
|||||||
return selPrivate->AddSelectionListener(this);
|
return selPrivate->AddSelectionListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP nsCaretAccessible::RemoveDocSelectionListener(nsIDOMDocument *aDoc)
|
nsresult nsCaretAccessible::RemoveDocSelectionListener(nsIDOMDocument *aDoc)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDoc);
|
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDoc);
|
||||||
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
|
||||||
@ -168,13 +169,13 @@ NS_IMETHODIMP nsCaretAccessible::NotifySelectionChanged(nsIDOMDocument *aDoc, ns
|
|||||||
|
|
||||||
// Get first nnsIAccessibleText in parent chain and fire caret-move, selection-change event for it
|
// Get first nnsIAccessibleText in parent chain and fire caret-move, selection-change event for it
|
||||||
nsCOMPtr<nsIAccessible> accessible;
|
nsCOMPtr<nsIAccessible> accessible;
|
||||||
nsIAccessibilityService *accService = GetAccService();
|
nsIAccessibilityService *accService = mRootAccessible->GetAccService();
|
||||||
NS_ENSURE_TRUE(accService, NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(accService, NS_ERROR_FAILURE);
|
||||||
// Get accessible from selection's focus node or its parent
|
// Get accessible from selection's focus node or its parent
|
||||||
nsCOMPtr<nsIDOMNode> focusNode;
|
nsCOMPtr<nsIDOMNode> focusNode;
|
||||||
aSel->GetFocusNode(getter_AddRefs(focusNode));
|
aSel->GetFocusNode(getter_AddRefs(focusNode));
|
||||||
if (!focusNode) {
|
if (!focusNode) {
|
||||||
mLastNodeWithCaret = nsnull;
|
mLastTextAccessible = nsnull;
|
||||||
return NS_OK; // No selection
|
return NS_OK; // No selection
|
||||||
}
|
}
|
||||||
nsCOMPtr<nsIDOMNode> nodeWithCaret = focusNode;
|
nsCOMPtr<nsIDOMNode> nodeWithCaret = focusNode;
|
||||||
@ -203,9 +204,10 @@ NS_IMETHODIMP nsCaretAccessible::NotifySelectionChanged(nsIDOMDocument *aDoc, ns
|
|||||||
NS_ENSURE_TRUE(textAcc, NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(textAcc, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
PRInt32 caretOffset;
|
PRInt32 caretOffset;
|
||||||
textAcc->GetCaretOffset(&caretOffset);
|
nsresult rv = textAcc->GetCaretOffset(&caretOffset);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
if (nodeWithCaret == mLastNodeWithCaret && caretOffset == mLastCaretOffset) {
|
if (textAcc == mLastTextAccessible && caretOffset == mLastCaretOffset) {
|
||||||
PRInt32 selectionCount;
|
PRInt32 selectionCount;
|
||||||
textAcc->GetSelectionCount(&selectionCount); // Don't swallow similar events when selecting text
|
textAcc->GetSelectionCount(&selectionCount); // Don't swallow similar events when selecting text
|
||||||
if (!selectionCount) {
|
if (!selectionCount) {
|
||||||
@ -213,122 +215,76 @@ NS_IMETHODIMP nsCaretAccessible::NotifySelectionChanged(nsIDOMDocument *aDoc, ns
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mLastCaretOffset = caretOffset;
|
mLastCaretOffset = caretOffset;
|
||||||
mLastNodeWithCaret = nodeWithCaret;
|
mLastTextAccessible = textAcc;
|
||||||
|
|
||||||
return mRootAccessible->FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED,
|
return mRootAccessible->FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED,
|
||||||
focusNode, nsnull, PR_FALSE);
|
focusNode, nsnull, PR_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<nsICaret>
|
nsRect
|
||||||
nsCaretAccessible::GetLastCaret(nsRect *aRect, PRBool *aIsVisible)
|
nsCaretAccessible::GetCaretRect(nsIWidget **aOutWidget)
|
||||||
{
|
{
|
||||||
*aIsVisible = PR_FALSE;
|
nsRect caretRect;
|
||||||
if (!mLastNodeWithCaret) {
|
NS_ENSURE_TRUE(aOutWidget, caretRect);
|
||||||
return nsnull;
|
*aOutWidget = nsnull;
|
||||||
|
|
||||||
|
if (!mLastTextAccessible) {
|
||||||
|
return caretRect; // Return empty rect
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIPresShell> presShell = GetPresShellFor(mLastNodeWithCaret);
|
nsCOMPtr<nsIAccessNode> lastAccessNode(do_QueryInterface(mLastTextAccessible));
|
||||||
NS_ENSURE_TRUE(presShell, nsnull);
|
NS_ENSURE_TRUE(lastAccessNode, caretRect);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMNode> lastNodeWithCaret;
|
||||||
|
lastAccessNode->GetDOMNode(getter_AddRefs(lastNodeWithCaret));
|
||||||
|
NS_ENSURE_TRUE(lastNodeWithCaret, caretRect);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIPresShell> presShell = mRootAccessible->GetPresShellFor(lastNodeWithCaret);
|
||||||
|
NS_ENSURE_TRUE(presShell, caretRect);
|
||||||
|
|
||||||
nsICaret *caret;
|
nsICaret *caret;
|
||||||
presShell->GetCaret(&caret);
|
presShell->GetCaret(&caret);
|
||||||
NS_ENSURE_TRUE(caret, nsnull);
|
NS_ENSURE_TRUE(caret, caretRect);
|
||||||
|
|
||||||
nsRect caretRect;
|
|
||||||
PRBool isCollapsed;
|
PRBool isCollapsed;
|
||||||
|
nsIView *view;
|
||||||
nsCOMPtr<nsISelection> caretSelection(do_QueryReferent(mLastUsedSelection));
|
nsCOMPtr<nsISelection> caretSelection(do_QueryReferent(mLastUsedSelection));
|
||||||
caret->GetCaretCoordinates(nsICaret::eTopLevelWindowCoordinates, caretSelection,
|
caret->GetCaretCoordinates(nsICaret::eRenderingViewCoordinates, caretSelection,
|
||||||
aRect, &isCollapsed, nsnull);
|
&caretRect, &isCollapsed, &view);
|
||||||
if (!aRect->IsEmpty()) {
|
if (!view || caretRect.IsEmpty()) {
|
||||||
caret->GetCaretVisible(aIsVisible);
|
return nsRect(); // Return empty rect
|
||||||
}
|
}
|
||||||
return caret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return the caret's bounds */
|
|
||||||
NS_IMETHODIMP nsCaretAccessible::GetBounds(PRInt32 *aX, PRInt32 *aY, PRInt32 *aWidth, PRInt32 *aHeight)
|
|
||||||
{
|
|
||||||
*aX = *aY = *aWidth = *aHeight = 0;
|
|
||||||
nsRect caretRect;
|
|
||||||
PRBool isVisible;
|
PRBool isVisible;
|
||||||
nsCOMPtr<nsICaret> caret = GetLastCaret(&caretRect, &isVisible);
|
caret->GetCaretVisible(&isVisible);
|
||||||
if (!caret || caretRect.IsEmpty()) {
|
if (!isVisible) {
|
||||||
return NS_ERROR_FAILURE;
|
return nsRect(); // Return empty rect
|
||||||
}
|
}
|
||||||
|
nsPoint offsetFromWidget;
|
||||||
nsCOMPtr<nsIPresShell> presShell = GetPresShellFor(mLastNodeWithCaret);
|
*aOutWidget = view->GetNearestWidget(&offsetFromWidget);
|
||||||
NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(*aOutWidget, nsRect());
|
||||||
|
|
||||||
nsPresContext *presContext = presShell->GetPresContext();
|
nsPresContext *presContext = presShell->GetPresContext();
|
||||||
NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(presContext, nsRect());
|
||||||
|
|
||||||
nsIViewManager* viewManager = presShell->GetViewManager();
|
caretRect.x = presContext->AppUnitsToDevPixels(caretRect.x + offsetFromWidget.x);
|
||||||
NS_ENSURE_TRUE(viewManager, NS_ERROR_FAILURE);
|
caretRect.y = presContext->AppUnitsToDevPixels(caretRect.y + offsetFromWidget.y);
|
||||||
|
caretRect.width = presContext->AppUnitsToDevPixels(caretRect.width);
|
||||||
nsIView *view = nsnull;
|
|
||||||
viewManager->GetRootView(view);
|
|
||||||
NS_ENSURE_TRUE(view, NS_ERROR_FAILURE);
|
|
||||||
|
|
||||||
nsIWidget* widget = view->GetWidget();
|
|
||||||
NS_ENSURE_TRUE(widget, NS_ERROR_FAILURE);
|
|
||||||
|
|
||||||
caretRect.x = presContext->AppUnitsToDevPixels(caretRect.x);
|
|
||||||
caretRect.y = presContext->AppUnitsToDevPixels(caretRect.y);
|
|
||||||
caretRect.width = presContext->AppUnitsToDevPixels(caretRect.width);
|
|
||||||
caretRect.height = presContext->AppUnitsToDevPixels(caretRect.height);
|
caretRect.height = presContext->AppUnitsToDevPixels(caretRect.height);
|
||||||
|
|
||||||
nsRect caretScreenRect;
|
(*aOutWidget)->WidgetToScreen(caretRect, caretRect);
|
||||||
widget->WidgetToScreen(caretRect, caretScreenRect);
|
|
||||||
|
|
||||||
*aX = caretScreenRect.x;
|
// Correct for character size, so that caret always matches the size of the character
|
||||||
*aY = caretScreenRect.y;
|
// This is important for font size transitions, and is necessary because the Gecko caret uses the
|
||||||
*aWidth = caretScreenRect.width;
|
// previous character's size as the user moves forward in the text by character.
|
||||||
*aHeight = caretScreenRect.height;
|
PRInt32 charX, charY, charWidth, charHeight;
|
||||||
|
if (NS_SUCCEEDED(mLastTextAccessible->GetCharacterExtents(mLastCaretOffset, &charX, &charY,
|
||||||
return NS_OK;
|
&charWidth, &charHeight,
|
||||||
}
|
nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE))) {
|
||||||
|
caretRect.height -= charY - caretRect.y;
|
||||||
NS_IMETHODIMP nsCaretAccessible::GetRole(PRUint32 *_retval)
|
caretRect.y = charY;
|
||||||
{
|
|
||||||
*_retval = nsIAccessibleRole::ROLE_CARET;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsCaretAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
|
|
||||||
{
|
|
||||||
*aState = 0;
|
|
||||||
if (aExtraState)
|
|
||||||
*aExtraState = 0;
|
|
||||||
|
|
||||||
NS_ENSURE_TRUE(mLastNodeWithCaret, NS_ERROR_FAILURE);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPresShell> presShell = GetPresShellFor(mLastNodeWithCaret);
|
|
||||||
NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
|
|
||||||
|
|
||||||
nsRect caretRect;
|
|
||||||
PRBool isVisible;
|
|
||||||
GetLastCaret(&caretRect, &isVisible);
|
|
||||||
if (!isVisible) {
|
|
||||||
*aState = nsIAccessibleStates::STATE_INVISIBLE;
|
|
||||||
}
|
}
|
||||||
return NS_OK;
|
|
||||||
}
|
return caretRect;
|
||||||
|
|
||||||
NS_IMETHODIMP nsCaretAccessible::GetParent(nsIAccessible **aParent)
|
|
||||||
{
|
|
||||||
NS_ADDREF(*aParent = mRootAccessible);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
NS_IMETHODIMP nsCaretAccessible::GetPreviousSibling(nsIAccessible **_retval)
|
|
||||||
{
|
|
||||||
*_retval = nsnull;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP nsCaretAccessible::GetNextSibling(nsIAccessible **_retval)
|
|
||||||
{
|
|
||||||
*_retval = nsnull;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,14 +38,15 @@
|
|||||||
#ifndef __nsCaretAccessible_h__
|
#ifndef __nsCaretAccessible_h__
|
||||||
#define __nsCaretAccessible_h__
|
#define __nsCaretAccessible_h__
|
||||||
|
|
||||||
#include "nsBaseWidgetAccessible.h"
|
|
||||||
#include "nsIWeakReference.h"
|
#include "nsIWeakReference.h"
|
||||||
|
#include "nsIAccessibleText.h"
|
||||||
|
#include "nsICaret.h"
|
||||||
#include "nsIDOMNode.h"
|
#include "nsIDOMNode.h"
|
||||||
#include "nsIAccessibleCaret.h"
|
|
||||||
#include "nsISelectionListener.h"
|
#include "nsISelectionListener.h"
|
||||||
#include "nsRect.h"
|
#include "nsRect.h"
|
||||||
|
|
||||||
class nsRootAccessible;
|
class nsRootAccessible;
|
||||||
|
class nsIView;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This special accessibility class is for the caret, which is really the currently focused selection.
|
* This special accessibility class is for the caret, which is really the currently focused selection.
|
||||||
@ -54,10 +55,11 @@ class nsRootAccessible;
|
|||||||
*
|
*
|
||||||
* The important selections are the one owned by each document, and the one in the currently focused control.
|
* The important selections are the one owned by each document, and the one in the currently focused control.
|
||||||
*
|
*
|
||||||
* The caret accesible does not exist within the normal accessible tree; it lives in a different world.
|
* The caret accessible is no longer an accessible object in its own right.
|
||||||
* In MSAA, it is retrieved with via the WM_GETOBJECT message with lParam = OBJID_CARET,
|
* On Windows it is used to move an invisible system caret that shadows the Mozilla caret. Windows will
|
||||||
|
* also automatically map this to the MSAA caret accessible object (via OBJID_CARET).
|
||||||
* (as opposed to the root accessible tree for a window which is retrieved with OBJID_CLIENT)
|
* (as opposed to the root accessible tree for a window which is retrieved with OBJID_CLIENT)
|
||||||
* In ATK, the caret accessible is never exposed as an accessible object, but is used to fire
|
* For ATK and Iaccessible2, the caret accessible is used to fire
|
||||||
* caret move and selection change events.
|
* caret move and selection change events.
|
||||||
*
|
*
|
||||||
* The caret accessible is owned by the nsRootAccessible for the top level window that it's in.
|
* The caret accessible is owned by the nsRootAccessible for the top level window that it's in.
|
||||||
@ -68,36 +70,52 @@ class nsRootAccessible;
|
|||||||
* selection listener when the doc goes away via removeDocSelectionListener().
|
* selection listener when the doc goes away via removeDocSelectionListener().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class nsCaretAccessible : public nsLeafAccessible, public nsIAccessibleCaret, public nsISelectionListener
|
class nsCaretAccessible : public nsISelectionListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
NS_DECL_ISUPPORTS
|
||||||
|
|
||||||
nsCaretAccessible(nsIDOMNode* aDocumentNode, nsIWeakReference* aShell, nsRootAccessible *aRootAccessible);
|
nsCaretAccessible(nsRootAccessible *aRootAccessible);
|
||||||
|
virtual ~nsCaretAccessible();
|
||||||
/* ----- nsIAccessible ----- */
|
void Shutdown();
|
||||||
NS_IMETHOD GetParent(nsIAccessible **_retval);
|
|
||||||
NS_IMETHOD GetRole(PRUint32 *_retval);
|
|
||||||
NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
|
|
||||||
NS_IMETHOD GetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height);
|
|
||||||
NS_IMETHOD GetNextSibling(nsIAccessible **_retval);
|
|
||||||
NS_IMETHOD GetPreviousSibling(nsIAccessible **_retval);
|
|
||||||
|
|
||||||
/* ----- nsIAccessibleCaret ------ */
|
|
||||||
NS_DECL_NSIACCESSIBLECARET
|
|
||||||
|
|
||||||
/* ----- nsISelectionListener ---- */
|
/* ----- nsISelectionListener ---- */
|
||||||
NS_DECL_NSISELECTIONLISTENER
|
NS_DECL_NSISELECTIONLISTENER
|
||||||
|
|
||||||
/* ----- nsIAccessNode ----- */
|
/**
|
||||||
NS_IMETHOD Init()
|
* Listen to selection events on the focused control.
|
||||||
{
|
* Only one control's selection events are listened to at a time, per top-level window.
|
||||||
#ifdef DEBUG_A11Y
|
* This will remove the previous control's selection listener.
|
||||||
mIsInitialized = PR_TRUE;
|
* It will fail if aFocusedNode is a document node -- document selection must be listened
|
||||||
#endif
|
* to via AddDocSelectionListener().
|
||||||
return NS_OK;
|
* @param aFocusedNode The node for the focused control
|
||||||
}
|
*/
|
||||||
NS_IMETHOD Shutdown();
|
nsresult SetControlSelectionListener(nsIDOMNode *aCurrentNode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop listening to selection events for any control.
|
||||||
|
* This does not have to be called explicitly in Shutdown() procedures,
|
||||||
|
* because the nsCaretAccessible implementation guarantees that.
|
||||||
|
*/
|
||||||
|
nsresult ClearControlSelectionListener();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start listening to selection events for a given document
|
||||||
|
* More than one document's selection events can be listened to
|
||||||
|
* at the same time, by a given nsCaretAccessible
|
||||||
|
* @param aDocument Document to listen to selection events for.
|
||||||
|
*/
|
||||||
|
nsresult AddDocSelectionListener(nsIDOMDocument *aDoc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop listening to selection events for a given document
|
||||||
|
* If the document goes away, this method needs to be called for
|
||||||
|
* that document by the owner of the caret
|
||||||
|
* @param aDocument Document to listen to selection events for.
|
||||||
|
*/
|
||||||
|
nsresult RemoveDocSelectionListener(nsIDOMDocument *aDoc);
|
||||||
|
|
||||||
|
nsRect GetCaretRect(nsIWidget **aOutWidget);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The currently focused control -- never a document.
|
// The currently focused control -- never a document.
|
||||||
@ -111,9 +129,8 @@ private:
|
|||||||
// If it was on a control, then mLastUsedSelection == mCurrentControlSelection
|
// If it was on a control, then mLastUsedSelection == mCurrentControlSelection
|
||||||
// Otherwise, it's for a document where the selection changed
|
// Otherwise, it's for a document where the selection changed
|
||||||
nsCOMPtr<nsIWeakReference> mLastUsedSelection; // Weak ref to nsISelection
|
nsCOMPtr<nsIWeakReference> mLastUsedSelection; // Weak ref to nsISelection
|
||||||
nsCOMPtr<nsIDOMNode> mLastNodeWithCaret;
|
nsCOMPtr<nsIAccessibleText> mLastTextAccessible;
|
||||||
PRInt32 mLastCaretOffset;
|
PRInt32 mLastCaretOffset;
|
||||||
already_AddRefed<nsICaret> GetLastCaret(nsRect *aRect, PRBool *aIsVisible);
|
|
||||||
|
|
||||||
nsRootAccessible *mRootAccessible;
|
nsRootAccessible *mRootAccessible;
|
||||||
};
|
};
|
||||||
|
@ -168,10 +168,10 @@ NS_IMETHODIMP nsDocAccessible::GetRole(PRUint32 *aRole)
|
|||||||
if (docShellTreeItem) {
|
if (docShellTreeItem) {
|
||||||
nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
|
nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
|
||||||
docShellTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
|
docShellTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
|
||||||
|
PRInt32 itemType;
|
||||||
|
docShellTreeItem->GetItemType(&itemType);
|
||||||
if (sameTypeRoot == docShellTreeItem) {
|
if (sameTypeRoot == docShellTreeItem) {
|
||||||
// Root of content or chrome tree
|
// Root of content or chrome tree
|
||||||
PRInt32 itemType;
|
|
||||||
docShellTreeItem->GetItemType(&itemType);
|
|
||||||
if (itemType == nsIDocShellTreeItem::typeChrome) {
|
if (itemType == nsIDocShellTreeItem::typeChrome) {
|
||||||
*aRole = nsIAccessibleRole::ROLE_CHROME_WINDOW;
|
*aRole = nsIAccessibleRole::ROLE_CHROME_WINDOW;
|
||||||
}
|
}
|
||||||
@ -188,6 +188,9 @@ NS_IMETHODIMP nsDocAccessible::GetRole(PRUint32 *aRole)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (itemType == nsIDocShellTreeItem::typeContent) {
|
||||||
|
*aRole = nsIAccessibleRole::ROLE_DOCUMENT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
@ -349,13 +352,6 @@ NS_IMETHODIMP nsDocAccessible::GetNameSpaceURIForID(PRInt16 aNameSpaceID, nsAStr
|
|||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP nsDocAccessible::GetCaretAccessible(nsIAccessible **aCaretAccessible)
|
|
||||||
{
|
|
||||||
// We only have a caret accessible on the root document
|
|
||||||
*aCaretAccessible = nsnull;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP nsDocAccessible::GetWindowHandle(void **aWindow)
|
NS_IMETHODIMP nsDocAccessible::GetWindowHandle(void **aWindow)
|
||||||
{
|
{
|
||||||
*aWindow = mWnd;
|
*aWindow = mWnd;
|
||||||
@ -666,13 +662,13 @@ nsresult nsDocAccessible::AddEventListeners()
|
|||||||
nsCOMPtr<nsIDocShellTreeItem> rootTreeItem;
|
nsCOMPtr<nsIDocShellTreeItem> rootTreeItem;
|
||||||
docShellTreeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem));
|
docShellTreeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem));
|
||||||
if (rootTreeItem) {
|
if (rootTreeItem) {
|
||||||
nsCOMPtr<nsIAccessibleDocument> rootAccDoc = GetDocAccessibleFor(rootTreeItem, PR_TRUE);
|
GetDocAccessibleFor(rootTreeItem, PR_TRUE); // Ensure root accessible is created;
|
||||||
nsCOMPtr<nsIAccessible> caretAccessible;
|
nsRefPtr<nsRootAccessible> rootAccessible = GetRootAccessible();
|
||||||
rootAccDoc->GetCaretAccessible(getter_AddRefs(caretAccessible));
|
NS_ENSURE_TRUE(rootAccessible, NS_ERROR_FAILURE);
|
||||||
nsCOMPtr<nsIAccessibleCaret> caretAccessibleIface(do_QueryInterface(caretAccessible));
|
nsRefPtr<nsCaretAccessible> caretAccessible = rootAccessible->GetCaretAccessible();
|
||||||
if (caretAccessibleIface) {
|
if (caretAccessible) {
|
||||||
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(mDocument);
|
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(mDocument);
|
||||||
caretAccessibleIface->AddDocSelectionListener(domDoc);
|
caretAccessible->AddDocSelectionListener(domDoc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -697,12 +693,10 @@ nsresult nsDocAccessible::RemoveEventListeners()
|
|||||||
|
|
||||||
nsRefPtr<nsRootAccessible> rootAccessible(GetRootAccessible());
|
nsRefPtr<nsRootAccessible> rootAccessible(GetRootAccessible());
|
||||||
if (rootAccessible) {
|
if (rootAccessible) {
|
||||||
nsCOMPtr<nsIAccessible> caretAccessible;
|
nsRefPtr<nsCaretAccessible> caretAccessible = rootAccessible->GetCaretAccessible();
|
||||||
rootAccessible->GetCaretAccessible(getter_AddRefs(caretAccessible));
|
if (caretAccessible) {
|
||||||
nsCOMPtr<nsIAccessibleCaret> caretAccessibleIface(do_QueryInterface(caretAccessible));
|
|
||||||
if (caretAccessibleIface) {
|
|
||||||
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(mDocument);
|
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(mDocument);
|
||||||
caretAccessibleIface->RemoveDocSelectionListener(domDoc);
|
caretAccessible->RemoveDocSelectionListener(domDoc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,9 +38,7 @@
|
|||||||
// NOTE: alphabetically ordered
|
// NOTE: alphabetically ordered
|
||||||
#include "nsAccessibilityService.h"
|
#include "nsAccessibilityService.h"
|
||||||
#include "nsAccessibleEventData.h"
|
#include "nsAccessibleEventData.h"
|
||||||
#include "nsCaretAccessible.h"
|
|
||||||
#include "nsHTMLSelectAccessible.h"
|
#include "nsHTMLSelectAccessible.h"
|
||||||
#include "nsIAccessibleCaret.h"
|
|
||||||
#include "nsIBaseWindow.h"
|
#include "nsIBaseWindow.h"
|
||||||
#include "nsICaret.h"
|
#include "nsICaret.h"
|
||||||
#include "nsIDocShell.h"
|
#include "nsIDocShell.h"
|
||||||
@ -321,11 +319,7 @@ nsresult nsRootAccessible::AddEventListeners()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!mCaretAccessible) {
|
if (!mCaretAccessible) {
|
||||||
mCaretAccessible = new nsCaretAccessible(mDOMNode, mWeakShell, this);
|
mCaretAccessible = new nsCaretAccessible(this);
|
||||||
nsCOMPtr<nsPIAccessNode> accessNode(do_QueryInterface(mCaretAccessible));
|
|
||||||
if (accessNode && NS_FAILED(accessNode->Init())) {
|
|
||||||
mCaretAccessible = nsnull;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fire accessible focus event for pre-existing focus, but wait until all internal
|
// Fire accessible focus event for pre-existing focus, but wait until all internal
|
||||||
@ -356,23 +350,21 @@ nsresult nsRootAccessible::RemoveEventListeners()
|
|||||||
target->RemoveEventListener(NS_LITERAL_STRING("pagehide"), this, PR_TRUE);
|
target->RemoveEventListener(NS_LITERAL_STRING("pagehide"), this, PR_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsPIAccessNode> caretAccessNode(do_QueryInterface(mCaretAccessible));
|
if (mCaretAccessible) {
|
||||||
if (caretAccessNode) {
|
mCaretAccessible->Shutdown();
|
||||||
caretAccessNode->Shutdown();
|
|
||||||
mCaretAccessible = nsnull;
|
mCaretAccessible = nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nsDocAccessible::RemoveEventListeners();
|
return nsDocAccessible::RemoveEventListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP nsRootAccessible::GetCaretAccessible(nsIAccessible **aCaretAccessible)
|
already_AddRefed<nsCaretAccessible>
|
||||||
|
nsRootAccessible::GetCaretAccessible()
|
||||||
{
|
{
|
||||||
*aCaretAccessible = nsnull;
|
|
||||||
if (mCaretAccessible) {
|
if (mCaretAccessible) {
|
||||||
CallQueryInterface(mCaretAccessible, aCaretAccessible);
|
NS_ADDREF(NS_STATIC_CAST(nsISupports*, mCaretAccessible));
|
||||||
}
|
}
|
||||||
|
return mCaretAccessible;
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsRootAccessible::TryFireEarlyLoadEvent(nsIDOMNode *aDocNode)
|
void nsRootAccessible::TryFireEarlyLoadEvent(nsIDOMNode *aDocNode)
|
||||||
|
@ -41,11 +41,11 @@
|
|||||||
#include "nsDocAccessibleWrap.h"
|
#include "nsDocAccessibleWrap.h"
|
||||||
#include "nsHashtable.h"
|
#include "nsHashtable.h"
|
||||||
#include "nsIAccessibleDocument.h"
|
#include "nsIAccessibleDocument.h"
|
||||||
|
#include "nsCaretAccessible.h"
|
||||||
#include "nsIDocument.h"
|
#include "nsIDocument.h"
|
||||||
#include "nsIDOMFocusListener.h"
|
#include "nsIDOMFocusListener.h"
|
||||||
#include "nsIDOMFormListener.h"
|
#include "nsIDOMFormListener.h"
|
||||||
#include "nsIDOMXULListener.h"
|
#include "nsIDOMXULListener.h"
|
||||||
#include "nsIAccessibleCaret.h"
|
|
||||||
#include "nsITimer.h"
|
#include "nsITimer.h"
|
||||||
|
|
||||||
#define NS_ROOTACCESSIBLE_IMPL_CID \
|
#define NS_ROOTACCESSIBLE_IMPL_CID \
|
||||||
@ -81,9 +81,6 @@ class nsRootAccessible : public nsDocAccessibleWrap,
|
|||||||
// ----- nsIDOMEventListener --------------------------
|
// ----- nsIDOMEventListener --------------------------
|
||||||
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
|
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
|
||||||
|
|
||||||
// nsIAccessibleDocument
|
|
||||||
NS_IMETHOD GetCaretAccessible(nsIAccessible **aAccessibleCaret);
|
|
||||||
|
|
||||||
// nsIAccessNode
|
// nsIAccessNode
|
||||||
NS_IMETHOD Init();
|
NS_IMETHOD Init();
|
||||||
NS_IMETHOD Shutdown();
|
NS_IMETHOD Shutdown();
|
||||||
@ -106,6 +103,8 @@ class nsRootAccessible : public nsDocAccessibleWrap,
|
|||||||
nsIDOMEvent *aFocusEvent,
|
nsIDOMEvent *aFocusEvent,
|
||||||
PRBool aForceEvent = PR_FALSE);
|
PRBool aForceEvent = PR_FALSE);
|
||||||
|
|
||||||
|
already_AddRefed<nsCaretAccessible> GetCaretAccessible();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nsCOMPtr<nsITimer> mFireFocusTimer;
|
nsCOMPtr<nsITimer> mFireFocusTimer;
|
||||||
static void FireFocusCallback(nsITimer *aTimer, void *aClosure);
|
static void FireFocusCallback(nsITimer *aTimer, void *aClosure);
|
||||||
@ -124,7 +123,7 @@ class nsRootAccessible : public nsDocAccessibleWrap,
|
|||||||
#endif
|
#endif
|
||||||
already_AddRefed<nsIDocShellTreeItem>
|
already_AddRefed<nsIDocShellTreeItem>
|
||||||
GetContentDocShell(nsIDocShellTreeItem *aStart);
|
GetContentDocShell(nsIDocShellTreeItem *aStart);
|
||||||
nsCOMPtr<nsIAccessibleCaret> mCaretAccessible;
|
nsRefPtr<nsCaretAccessible> mCaretAccessible;
|
||||||
PRPackedBool mIsInDHTMLMenu;
|
PRPackedBool mIsInDHTMLMenu;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -879,7 +879,8 @@ NS_IMETHODIMP nsHyperTextAccessible::GetRangeExtents(PRInt32 aStartOffset, PRInt
|
|||||||
{
|
{
|
||||||
nsIntRect boundsRect;
|
nsIntRect boundsRect;
|
||||||
nsIFrame *endFrameUnused;
|
nsIFrame *endFrameUnused;
|
||||||
if (!GetPosAndText(aStartOffset, aEndOffset, nsnull, &endFrameUnused, &boundsRect)) {
|
if (!GetPosAndText(aStartOffset, aEndOffset, nsnull, &endFrameUnused, &boundsRect) ||
|
||||||
|
boundsRect.IsEmpty()) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -531,6 +531,7 @@ void nsAccessNodeWrap::InitAccessibility()
|
|||||||
void nsAccessNodeWrap::ShutdownAccessibility()
|
void nsAccessNodeWrap::ShutdownAccessibility()
|
||||||
{
|
{
|
||||||
NS_IF_RELEASE(gTextEvent);
|
NS_IF_RELEASE(gTextEvent);
|
||||||
|
::DestroyCaret();
|
||||||
|
|
||||||
if (!gIsAccessibilityActive) {
|
if (!gIsAccessibilityActive) {
|
||||||
return;
|
return;
|
||||||
|
@ -1511,15 +1511,9 @@ nsAccessibleWrap::FireAccessibleEvent(nsIAccessibleEvent *aEvent)
|
|||||||
nsCOMPtr<nsIAccessNode> accessNode(do_QueryInterface(accessible));
|
nsCOMPtr<nsIAccessNode> accessNode(do_QueryInterface(accessible));
|
||||||
NS_ENSURE_STATE(accessNode);
|
NS_ENSURE_STATE(accessNode);
|
||||||
|
|
||||||
if (eventType == nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED) {
|
if (eventType == nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED ||
|
||||||
// Fire additional old-style MSAA caret events as well as the IA2 event
|
eventType == nsIAccessibleEvent::EVENT_FOCUS) {
|
||||||
nsRefPtr<nsRootAccessible> rootAccessible = GetRootAccessible();
|
UpdateSystemCaret();
|
||||||
if (rootAccessible) {
|
|
||||||
nsCOMPtr<nsIAccessible> caretAccessible;
|
|
||||||
void* handle = nsnull;
|
|
||||||
rootAccessible->GetWindowHandle(&handle);
|
|
||||||
NotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, (HWND)handle, OBJID_CARET, CHILDID_SELF);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PRInt32 childID = GetChildIDFor(accessible); // get the id for the accessible
|
PRInt32 childID = GetChildIDFor(accessible); // get the id for the accessible
|
||||||
@ -1664,3 +1658,38 @@ void nsAccessibleWrap::GetXPAccessibleFor(const VARIANT& aVarChild, nsIAccessibl
|
|||||||
NS_IF_ADDREF(*aXPAccessible);
|
NS_IF_ADDREF(*aXPAccessible);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nsAccessibleWrap::UpdateSystemCaret()
|
||||||
|
{
|
||||||
|
// Move the system caret so that Windows Tablet Edition and tradional ATs with
|
||||||
|
// off-screen model can follow the caret
|
||||||
|
::DestroyCaret();
|
||||||
|
|
||||||
|
nsRefPtr<nsRootAccessible> rootAccessible = GetRootAccessible();
|
||||||
|
if (!rootAccessible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsRefPtr<nsCaretAccessible> caretAccessible = rootAccessible->GetCaretAccessible();
|
||||||
|
if (!caretAccessible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIWidget *widget;
|
||||||
|
nsRect caretRect = caretAccessible->GetCaretRect(&widget);
|
||||||
|
HWND caretWnd;
|
||||||
|
if (caretRect.IsEmpty() || !(caretWnd = (HWND)widget->GetNativeData(NS_NATIVE_WINDOW))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create invisible bitmap for caret, otherwise its appearance interferes
|
||||||
|
// with Gecko caret
|
||||||
|
HBITMAP caretBitMap = CreateBitmap(1, caretRect.height, 1, 1, NULL);
|
||||||
|
if (::CreateCaret(caretWnd, caretBitMap, 1, caretRect.height)) { // Also destroys the last caret
|
||||||
|
::ShowCaret(caretWnd);
|
||||||
|
RECT windowRect;
|
||||||
|
::GetWindowRect(caretWnd, &windowRect);
|
||||||
|
::SetCaretPos(caretRect.x - windowRect.left, caretRect.y - windowRect.top);
|
||||||
|
::DeleteObject(caretBitMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -296,6 +296,15 @@ class nsAccessibleWrap : public nsAccessible,
|
|||||||
// Helper methods
|
// Helper methods
|
||||||
static PRInt32 GetChildIDFor(nsIAccessible* aAccessible);
|
static PRInt32 GetChildIDFor(nsIAccessible* aAccessible);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* System caret support: update the Windows caret position.
|
||||||
|
* The system caret works more universally than the MSAA caret
|
||||||
|
* For example, Window-Eyes, JAWS, ZoomText and Windows Tablet Edition use it
|
||||||
|
* We will use an invisible system caret.
|
||||||
|
* Gecko is still responsible for drawing its own caret
|
||||||
|
*/
|
||||||
|
void UpdateSystemCaret();
|
||||||
|
|
||||||
virtual void GetXPAccessibleFor(const VARIANT& aVarChild, nsIAccessible **aXPAccessible);
|
virtual void GetXPAccessibleFor(const VARIANT& aVarChild, nsIAccessible **aXPAccessible);
|
||||||
NS_IMETHOD GetNativeInterface(void **aOutAccessible);
|
NS_IMETHOD GetNativeInterface(void **aOutAccessible);
|
||||||
|
|
||||||
|
@ -5223,30 +5223,19 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT
|
|||||||
#ifdef ACCESSIBILITY
|
#ifdef ACCESSIBILITY
|
||||||
case WM_GETOBJECT:
|
case WM_GETOBJECT:
|
||||||
{
|
{
|
||||||
LRESULT lAcc = 0;
|
*aRetValue = 0;
|
||||||
IAccessible *msaaAccessible = NULL;
|
|
||||||
if (lParam == OBJID_CLIENT) { // oleacc.dll will be loaded dynamically
|
if (lParam == OBJID_CLIENT) { // oleacc.dll will be loaded dynamically
|
||||||
nsCOMPtr<nsIAccessible> rootAccessible = GetRootAccessible(); // Held by a11y cache
|
nsCOMPtr<nsIAccessible> rootAccessible = GetRootAccessible(); // Held by a11y cache
|
||||||
if (rootAccessible) {
|
if (rootAccessible) {
|
||||||
|
IAccessible *msaaAccessible = NULL;
|
||||||
rootAccessible->GetNativeInterface((void**)&msaaAccessible); // does an addref
|
rootAccessible->GetNativeInterface((void**)&msaaAccessible); // does an addref
|
||||||
}
|
if (msaaAccessible) {
|
||||||
}
|
*aRetValue = LresultFromObject(IID_IAccessible, wParam, msaaAccessible); // does an addref
|
||||||
else if (lParam == OBJID_CARET) { // each root accessible owns a caret accessible
|
msaaAccessible->Release(); // release extra addref
|
||||||
nsCOMPtr<nsIAccessible> rootAccessible = GetRootAccessible(); // Held by a11y cache
|
result = PR_TRUE; // We handled the WM_GETOBJECT message
|
||||||
nsCOMPtr<nsIAccessibleDocument> accDoc(do_QueryInterface(rootAccessible));
|
|
||||||
if (accDoc) {
|
|
||||||
nsCOMPtr<nsIAccessible> accessibleCaret;
|
|
||||||
accDoc->GetCaretAccessible(getter_AddRefs(accessibleCaret));
|
|
||||||
if (accessibleCaret) {
|
|
||||||
accessibleCaret->GetNativeInterface((void**)&msaaAccessible);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (msaaAccessible) {
|
|
||||||
lAcc = LresultFromObject(IID_IAccessible, wParam, msaaAccessible); // does an addref
|
|
||||||
msaaAccessible->Release(); // release extra addref
|
|
||||||
}
|
|
||||||
return (*aRetValue = lAcc) != 0;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user