clutter/stage: Stop emitting older key-focus signals on focus changes

Jonas Dreßler requested to merge verdre/mutter:clutter-key-focus-fix into main

The current way of emitting key-focus-in and key-focus-out events has a specialty when dealing with focus changes that are triggered from inside key-focus-in/out handlers. As noted in a comment of the current code, changing focus from inside a key-focus-out handler looks like this:

1st focus-out, 2nd focus-out, 2nd focus-in, 1st focus-in

The problem here is that we have two consecutive focus-in signals, which can lead to two StWidgets receiving the "focus" CSS pseudoclass and that is something we never want to happen. Although we were able to avoid this issue so far, a similar problem is starting to appear with the recent popupMenu focus changes in the shell:

  • when opening an adjacent panel menu on right/left arrow key presses, the focus moves to the adjacent panel menu button

  • the menu butten then opens its popup menu from inside a key-focus-in handler (see popupMenu.js: _onMenuSourceEnter)

  • the popup menu now grabs focus itself and the stage emits a key-focus-out/in event while still being inside the key-focus-in emission of the other focus change

  • after the new key-focus signals are emitted, the older key-focus-in signal goes on and invokes its object method handler (the signal has the G_SIGNAL_RUN_LAST flag), this method is used in StWidget to add the "focus" pseudoclass

  • while stage key focus is set to the popup menu actor, both the popup menu actor and the panel button have the "focus" CSS pseudoclass

Fix those issues by stopping the emission of key-focus-in/out signals when the key-focus of the stage is changed.

This fixes an issue that appeared with changes to the popup menus of the shell (a popup menu that is opened from inside a key-focus-in handler now sets key focus to another actor while opening).

Merge request reports