gecko-dev/accessible/windows/msaa/AccessibleWrap.cpp
James Teh 3ab0c41716 Bug 1881191 part 1: Don't include MsaaAccessible.h in AccessibleWrap.h. r=nlapre
In a subsequent patch, MsaaAccessible will inherit from uiaRawElmProvider, which is in a different directory.
This causes problems for things outside the a11y module which include (either directly or indirectly) AccessibleWrap.h.
While this could be fixed by exporting more headers, we also end up with type conflicts with Windows API headers.
It's better if we can minimise what gets included anyway.

1. In AccessibleWrap.h, stop including MsaaAccessible.h and forward declare MsaaAccessible.
2. Move the definition of the AccessibleWrap destructor into the cpp. Otherwise, we run into compile errors due to the RefPtr<MsaaAccessible> destructor.
3. AccessibleWrap still has a private UpdateSystemCaretFor function which takes an HWND, which requires windows.h. To avoid including that in AccessibleWrap.h, move it to a static function only inside the cpp file. Rename it to prevent compiler overload confusion.
4. Since code outside the a11y module no longer needs to indirectly include MsaaAccessible, don't export MsaaAccessible.h any more.
5. While we're at it, don't export MsaaIdGenerator.h either, which is never used outside the Windows a11y code.

There should be no functional change here.

Differential Revision: https://phabricator.services.mozilla.com/D202549
2024-02-28 06:50:01 +00:00

142 lines
4.6 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "AccessibleWrap.h"
#include "mozilla/a11y/DocAccessibleParent.h"
#include "AccEvent.h"
#include "nsAccUtils.h"
#include "nsIAccessibleEvent.h"
#include "nsIWidget.h"
#include "nsWindowsHelpers.h"
#include "mozilla/a11y/HyperTextAccessible.h"
#include "mozilla/a11y/RemoteAccessible.h"
#include "ServiceProvider.h"
#include "sdnAccessible.h"
#include "LocalAccessible-inl.h"
using namespace mozilla;
using namespace mozilla::a11y;
/* For documentation of the accessibility architecture,
* see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
*/
////////////////////////////////////////////////////////////////////////////////
// AccessibleWrap
////////////////////////////////////////////////////////////////////////////////
AccessibleWrap::AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc)
: LocalAccessible(aContent, aDoc) {}
AccessibleWrap::~AccessibleWrap() = default;
NS_IMPL_ISUPPORTS_INHERITED0(AccessibleWrap, LocalAccessible)
void AccessibleWrap::Shutdown() {
if (mMsaa) {
mMsaa->MsaaShutdown();
// Don't release mMsaa here because this will cause its id to be released
// immediately, which will result in immediate reuse, causing problems
// for clients. Instead, we release it in the destructor.
}
LocalAccessible::Shutdown();
}
//-----------------------------------------------------
// IUnknown interface methods - see iunknown.h for documentation
//-----------------------------------------------------
MsaaAccessible* AccessibleWrap::GetMsaa() {
if (!mMsaa) {
mMsaa = MsaaAccessible::Create(this);
}
return mMsaa;
}
void AccessibleWrap::GetNativeInterface(void** aOutAccessible) {
RefPtr<IAccessible> result = GetMsaa();
return result.forget(aOutAccessible);
}
////////////////////////////////////////////////////////////////////////////////
// AccessibleWrap
//------- Helper methods ---------
bool AccessibleWrap::IsRootForHWND() {
if (IsRoot()) {
return true;
}
HWND thisHwnd = MsaaAccessible::GetHWNDFor(this);
AccessibleWrap* parent = static_cast<AccessibleWrap*>(LocalParent());
MOZ_ASSERT(parent);
HWND parentHwnd = MsaaAccessible::GetHWNDFor(parent);
return thisHwnd != parentHwnd;
}
static void UpdateSystemCaretForHwnd(HWND aCaretWnd,
const LayoutDeviceIntRect& aCaretRect) {
if (!aCaretWnd || aCaretRect.IsEmpty()) {
return;
}
// Create invisible bitmap for caret, otherwise its appearance interferes
// with Gecko caret
nsAutoBitmap caretBitMap(CreateBitmap(1, aCaretRect.Height(), 1, 1, nullptr));
if (::CreateCaret(aCaretWnd, caretBitMap, 1,
aCaretRect.Height())) { // Also destroys the last caret
::ShowCaret(aCaretWnd);
POINT clientPoint{aCaretRect.X(), aCaretRect.Y()};
::ScreenToClient(aCaretWnd, &clientPoint);
::SetCaretPos(clientPoint.x, clientPoint.y);
}
}
/* static */
void AccessibleWrap::UpdateSystemCaretFor(
Accessible* aAccessible, const LayoutDeviceIntRect& aCaretRect) {
if (LocalAccessible* localAcc = aAccessible->AsLocal()) {
// XXX We need the widget for LocalAccessible, so we have to call
// HyperTextAccessible::GetCaretRect. We should find some way of avoiding
// the need for the widget.
UpdateSystemCaretFor(localAcc);
} else {
UpdateSystemCaretFor(aAccessible->AsRemote(), aCaretRect);
}
}
/* static */
void AccessibleWrap::UpdateSystemCaretFor(LocalAccessible* aAccessible) {
// Move the system caret so that Windows Tablet Edition and tradional ATs with
// off-screen model can follow the caret
::DestroyCaret();
HyperTextAccessible* text = aAccessible->AsHyperText();
if (!text) return;
nsIWidget* widget = nullptr;
LayoutDeviceIntRect caretRect = text->GetCaretRect(&widget);
if (!widget) {
return;
}
HWND caretWnd =
reinterpret_cast<HWND>(widget->GetNativeData(NS_NATIVE_WINDOW));
UpdateSystemCaretForHwnd(caretWnd, caretRect);
}
/* static */
void AccessibleWrap::UpdateSystemCaretFor(
RemoteAccessible* aProxy, const LayoutDeviceIntRect& aCaretRect) {
::DestroyCaret();
// The HWND should be the real widget HWND, not an emulated HWND.
// We get the HWND from the proxy's outer doc to bypass window emulation.
LocalAccessible* outerDoc = aProxy->OuterDocOfRemoteBrowser();
UpdateSystemCaretForHwnd(MsaaAccessible::GetHWNDFor(outerDoc), aCaretRect);
}