January 13th, 2026
like2 reactions

Clipping the focus item when looking for its on-screen location, part 2

Last time, we clipped the focus item to the containing window so that we considered only the visible portion of the item. But we found that some programs use a dummy 0×0 window as their window for system focus, while visual focus remains elsewhere. How can we clip the focus item to the correct bounds?

It took a little thinking, but I realized that I can clip to the accessible parent of the focus item.

So first, a little more refactoring.

bool GetAccessibleBounds(IAccessible* acc, LONG childId, RECT* rc)
{
    VARIANT vt;
    vt.vt = VT_I4;
    vt.lVal = childId;

    if (acc->accLocation(&rc->left, &rc->top,
                         &rc->right, &rc->bottom, vt) == S_OK) {
        rc->right += rc->left;
        rc->bottom += rc->top;
        return true;
    } else {
        *rc = {};
        return false;
    }
}

This obtains the bounds of an accessible item in the form of a RECT. We can now use the rectangle manipulation functions to intersect the object’s bounds with the bounds of its parent.

bool SetCursorPosToLocation(IAccessible* acc, LONG childId)
{
    RECT rcObject;
    if (GetAccessibleBounds(acc, childId, &rcObject)) {
        RECT rcParent;
        if (childId != CHILDID_SELF) {
            if (GetAccessibleBounds(acc, CHILDID_SELF, &rcParent)) {
                IntersectRect(&rcObject, &rcObject, &rcParent);
            }
        } else {
            wil::com_ptr_nothrow<IDispatch> dispParent;
            if (acc->get_accParent(dispParent.put()) == S_OK &&
                dispParent) {
                auto accParent = dispParent.try_query<IAccessible>();
                if (accParent &&
                    GetAccessibleBounds(accParent.get(), CHILDID_SELF,
                                        &rcParent)) {
                    IntersectRect(&rcObject, &rcObject, &rcParent);
                }
            }
        }
        SetCursorPos(rcObject.right - 1, rcObject.bottom - 1);
        return true;
    }
    return false;
}

After getting the accessible bounds of the target, we also get the bounds of its parent. There are two ways to find the parent.

  • If the childId is not CHILDID_SELF, then we are the parent element of the target, so we can ask for the accessible bounds of ourselves.
  • Otherwise, we are the target, so we cann get_accParent to get our parent, and then get the bounds of that parent.

In either case, if the bounds were obtained successfully, then we intersect the target’s bounding rectangle with the parent’s bounding rectangle, and then position the cursor at the bottom right corner.

We got rid of the hwndClip parameter, so we can remove it from the call sites, returning the code to the version before we added the clip window.

I found that this didn’t always succeed in clipping the item to the parent. For example, if you highlight a clipped item in File Explorer in Tiles view, the cursor still moves to the invisible bottom right corner of the unclipped tile.

We’ll investigate this next time.

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

1 comment

Sort by :
  • Кирилл Ярин 2 hours ago

    > I found that this didn’t always succeed in clipping the item to the parent. For example, if you highlight a clipped item in File Explorer in Tiles view, the cursor still moves to the invisible bottom right corner of the unclipped tile.

    I imagine in that situation, assuming that item can fit into the parent, user would want parent window to scroll to position where that item is not clipped, as the goal of moving mouse cursor to something is usually to interact with that something.