Problem with modal state and WM_ACTIVATE


#1

I have a DocumentWindow and show a modal DialogWindow if a button is clicked. The modal DialogWindow blocks the DocumentWindow as expected if I try to give the DocumentWindow focus by clicking on it.

The problem is that I can bring the blocked DocumentWindow to front when clicking its taskbar button or Alt+Tab’ing to it. If I click afterwards on the DocumentWindow itself the modal DialogWindow gets in front of it again.

The fix for this problem is to bring the modal DialogWindow to front after the blocked DocumentWindow has been activated. This simple change to the way WM_ACTIVATE is handled in Win32ComponentPeer::peerWindowProc():

[code] case WM_ACTIVATE:
if (LOWORD (wParam) == WA_ACTIVE || LOWORD (wParam) == WA_CLICKACTIVE)
{
modifiersAtLastCallback = -1;
updateKeyModifiers();

                        if (isMinimised())
                        {
                            component->repaint();
                            handleMovedOrResized();

                            if (! isValidMessageListener())
                                return 0;
                        }

                        if (LOWORD (wParam) == WA_CLICKACTIVE
                             && component->isCurrentlyBlockedByAnotherModalComponent())
                        {
                            int mx, my;
                            component->getMouseXYRelative (mx, my);
                            Component* const underMouse = component->getComponentAt (mx, my);

                            if (underMouse != 0 && underMouse->isCurrentlyBlockedByAnotherModalComponent())
                                Component::getCurrentlyModalComponent()->inputAttemptWhenModal();

                            return 0;
                        }

                        handleBroughtToFront();
  •                       if (component->isCurrentlyBlockedByAnotherModalComponent())
    
  •                           Component::getCurrentlyModalComponent()->toFront (true);
    
                          return 0;
                      }
    
                      break;[/code]

#2

well, there’s already code inside Component::Component::internalBroughtToFront() that should do exactly the same thing. I wonder why that’s not working?


#3

My description of the problem was incorrect. The z-order of both windows is always correct and I don’t know what I’ve done to get this behavior; I can’t reproduce it.

The remaining problem is the focus: I can give focus to the blocked DocumentWindow when clicking its taskbar button or Alt+Tab’ing to it. My solution for this problem stays basically the same, but in a different place:

[code]void Component::internalBroughtToFront()
{
[…]
// when brought to the front and there’s a modal component blocking this one,
// we need to bring the modal one to the front instead…

    Component* const cm = getCurrentlyModalComponent();

    if (cm != 0 && cm->getTopLevelComponent() != getTopLevelComponent())
    {
  •       cm->getTopLevelComponent()->toFront (false);
    
  •       cm->getTopLevelComponent()->toFront (true);
      }
    
    }
    }[/code]

Call toFront (true) instead of toFront (false) to give it focus too, otherwise the blocked component stays focused.


#4

Right, that sounds like a better approach. I’ll have a go with that…