Losing focus from widget - common UI problem

Sometimes when using a gamepad, if focus is lost, then no inputs are read so game gets stuck.

How can I find out where focus has gone? Or, better yet, how can I protect against the case of navigable buttons losing focus, and if that happens, ensure that something retains focus so that the widget can still read input?

Anybody know what I’m talking about?

1 Like

Hey @BIGTIMEMASTER!

How is it that you are losing focus? Can you explain what is happening to make you lose focus? Does it just happen when cycling through buttons?

Make sure ALL buttons have something for “OnFocused” (like an outline or color change) so you can tell for sure!

hey thanks @Mind-Brain for the response.

I’m afraid this might be very difficult to solve, though I’ll describe as much as I know here:

all buttons are focusable. They are derived from CommonButtonBase (not generic buttons).

I have an event which adds new buttons to a wrap box (and clears old ones). Most of the time the event fires, focus is lost and ends up on the viewport (so says widget reflector) even though I have the following code in the Get Desired Focus target override:


This code is saying, if there is a button in the wrap box, focus on it, otherwise focus on another button which is always visible.

Another detail:
If I fire up the game (PIE or standalone) and I do not click in the game, I can fire this event (a gamepad or keyboard key) and focus is never lost. But once I click into the game, then if I press the event firing key, then focus will be lost after the event fires.

In Level Editor Play settings I have Game Gets Mouse Control set true:
image

The game viewport client class is common ui one:

If I am using a controller only, widget reflect indicates that a button in the wrap box is focused, however D-pad navigation won’t work until i press the confirm button. Then, after that, it is similar to if i had mouse clicked - focus is lost after pressing the keys which fire the event that removes old buttons and creates new ones.

If there are any Common UI experts I’m happy to pay for a few hours to help solve this (and understand why it’s happening in first place)

I’ll show some of the code involved, just in case there is some detail I’ve overlooked:

in the base class for this widget, an overridden OnKeyDown function reads key events and then triggers these events:

the result is that we end up calling RefreshInventoryDisplay:

First thing this event does is clear out all previous children:

then it gets an array of actors, and for each one of them…

creates a commonbuttonbase derived widget, and adds this to a wrap box:

If there were no actors to add, then I just add a single dummy button:

this dummy button was an attempt to keep focus on the widget. I thought maybe if there was nothing to focus on, that would cause the problem. But it doesn’t seem to make a difference.

I’ve been running through with the widget reflector and I cannot see that anything else is interfering with focus. It just gets lost on this event and goes to the viewport.

There had been some other widgets getting in the way, like random borders, overlays, text, but I set them each to non-hit testable and the final result is that now just the viewport gets focused.

While this widget is active, game is set to UI only mode. Strangely, despite that, player controller was still handling mouse look input. So I had to manually set it to ignore that. I had thought that UI only input mode would automatically disengage mouse look input handling.

edit:
one more additional detail - sometimes after firing the event, Dpad navigation wont work, but if i press joystick, that will navigate. After joystick navigation, then dpad navigation will work again. Very odd - makes me thing some strange bug, but I could just as well be doing things in a strange way. Hard to know, because there is little info about commonUI so far.

1 Like

i’ve done my own system before, but maintaining gamepad focus in a complex widget was really difficult. CommonUI made that a lot easier - everything just kinda magically worked… until now.

Hardcoded input is fine but if i have a wrap box getting populated at runtime, and menu is anything more than just buttons in a list, commonui has been easiest way to handle that I’ve found so far.

There has got to be somebody somewhere who knows the system pretty well. Trouble is, they probably aren’t hanging around the forums. I feel like if I could just ask a few questions it would clear up a lot of issues.

I’m not super hopeful because in livestream they had that is the only info about commonUI, the guy doing the livestream seemed like he was still figuring it out. So like, who is using this in production?!? Where are they? lol

2 Likes

i’ve found some discord with a bunch of UI related professionals and asking there as well.
if i get any answers from elsewhere, will relay here.

Also made a video to showcase problem better:

But i’ve whittled it down a lot more since the original problem. I was having completely crazy issues - way to inconsistent to make sense of. I disabled a plugin that does some editor UI changes just on a hunch and that fixed most problems. Now, as is shown in video, I’m able to reproduce a consistent problem. So, should be able to solve the problem if nothing else than just with a dumb workaround. But hopefully some UI experts might be able to explain why problem happens.

Hey again @BIGTIMEMASTER,

So watching that video you posted, (forgive me if you’re already doing this, I had to just gloss over it) what if: upon tab change, you get the widget, get that wrap box, and set focus to said wrap box at the end of the tab change execution line? I think you’re assuming it should already be set, but I think it’s interrupting focus and looking elsewhere when you change tabs. :confused:

I don’t know if that’s the solution, but what happens if you do that?

2 Likes

@Mind-Brain

i think that solves problem. Thank you!

Was a couple other bugs happening at same time which made issue seem more complicated, but they ended up being unrelated. One of those days where everything everywhere broke at same time, lol.

For this focus issue, adding this failsafe “refocus” bit immediately after changing contents of the wrapbox seems to give me consistent gamepad focus:

This seems like a fine solution and it doesn’t seem to crazy to expect that, if the UMG has a focus target and then it suddenly dissappears, that I must explicitly tell it when and where to refocus.

This does necessitate that I always have a button (or something focus-able) present in the widget - it seems that if focus gets put on the canvas panel it basically gets stuck and cannot find its way back to any buttons that are on top of it.
That bit strikes me as being odd, though perhaps it’s perfectly normal? I took a look a little bit in lyra but it’s mostly c++ which is greek to me.

Well, this problem is solved for now, but would be awesome to know if there is any best practices people know of for handling cases of focus being lost? Like, is there any more universal practice, rather than just having snippets of code for unique edge cases like this?

4 Likes

Solution doesn’t work for me:
I use “Common Activatable widget switcher” and changing transition to 0.0 help me
more details:

And also i have problem with popup widget when i spam “back button” and just clicking confirm (fast creating widget / removing) it cause losing focus.

I had overrided fucntion “Get Desired Focus Target” in Common Widget

And it worked, but after adding:

Problem solved.

I had the almost exact same problem:
I was adding widget items (of the same type) into a WrapBox, and for some reason sometimes the controller would just die after clicking around too much. The only thing that could refresh the input state was clicking manually with the mouse.

I tried adding delay, toggling visibility until click had been handled (Visible->click->NoHitTesting->clickdone->Visible), and other “wacky” stuff. Manual focus also did not solve it for me.

This is (so far) the solution:

But as Edgar Dijkstra famously said:
“Program testing can be used to show the presence of bugs, but never to show their absence!”

So until the bug shows up again, I just delay handling the click event until next frame :confused: