setFocus and Virtual Keyboards
-
Folks,
I am working on a kiosk style Linux based application. We are currently porting it from QT4 to QT5. I am seeing a behavioral difference in the Virtual Keyboards.
In QT4 we had an internal QInputContext derived class that filtered for the RequestSoftwareInputPanel event to show the virtual keyboard. In QT5 we have created a custom keyboard plugin (but have also tested with the QT Virtual Keyboard).
When we open a user input dialog, we do a setFocus on the first input field, and the virtual keyboard appears right away in QT4. In QT5, the virtual keyboard does not appear until a mouse click is performed on the input field in question.
Reading the documentation for setFocus, I tried adding RequestSoftwareInputPanel event to the showEvent call (code here is for a simple test app I am using for development/debugging):
void VKey_Qt5:showEvent(QShowEvent *pEvent) { Q_UNUSED(pEvent); // Force initial focus to 2nd input field this->activateWindow(); this->ui.le_Num->setFocus(); // Try and get virtual keyboard to show QEvent event(QEvent::RequestSoftwareInputPanel); QApplication::sendEvent(this->ui.le_Num,&event); }I moved the focus to the second widget as a way to confirm showEvent was being invoked. But while the focus did go to the second widget, the Virtual Keyboard still did not appear.
At this point, I do not know what to do to get it to appear without the user clicking on the screen. Does anyone have an idea what to do ?
Thanks,
Dale Pennington -
I have a working QPlatformInputContext based virtual keyboard for the QT5, which works fine except for the visible on focus issue. It appeared that the underlying code was handling the visibility processing.
As a test, I tried replacing the the last 2 lines (which was sending a RequestSoftwareInputPanel event with )
QInputMethod *inputMethod = QGuiApplication::inputMethod();
inputMethod->show();However, this also fails to show the keyboard. I added some debug print for the inputMethod's isVisible() function, and it claims false both before and after the show call.
Mouse clicking on the field still brings up the virtual keyboard as expected.
Dale
-
More Info. I placed some debug into the virtual keyboard code. In particular, I already had a setFocusObject function, so I added debug where it was invoked.
Also, in showInputPanel I added code to output when it is invoked, and what the current focus object is (I store it from setFocusObject).
It appears to call setFocusObject much later in the chain that I would expect it to. Looking at the chain of debug prints (this is a single threaded app as far as I know) the order is :
Invoke show event
Invoke setFocus
Invoked inputMethod->show();
Invoked InputContext showInputPanel, but as there is no focus object yet, nothing is made visible.
leave inputMethod->show()sometime later, InputContext setFocusObject is called for the widget in question.
I would have expected the setFocusObject call to have been done during the setFocus call, but apparently it is not. The showInputPanel controls instantiation based on the current FocusObject, and will not do anything if the focus object is not set.
So the question then is, how do we get the InputContext to accept to focus earlier ?
Dale
-
@DalePennington said in setFocus and Virtual Keyboards:
So the question then is, how do we get the InputContext to accept to focus earlier ?
That I currently do not know. One thing you could test is to use a single shot timer with 0 as delay in the show event to set the focus on your line edit and trigger the input event.
Since you are using a designer based widget, I think you can also edit there which widget shall get the default focus.
-
Previously I was letting default focus happen, and the keyboard was not happening there as well.
As a test, I added a sleep(1) after the setFocus call, then added a sleep(1) and another show call at the end. The setFocusObject calls still happened later. My guess is that the setFocus is posting the event rather than sending it, so it is not send to the InputContext until after the showEvent is done processing. And I see no other was to inform the InputContext of the focusObject.
I did try adding a postEvent for the RequestSoftwareInputPanel, but apparently it processes at a higher priority that the internal QInputMethodQuery chain, as it still processes before the focusObject (again most likey due to the other being a chain of events).
One option to try might be the ProcessEvents call, but I am not sure that is a good idea within an event handler I am already in.
Dale
-
Did you try my QTimer suggestion ?
-
I tried the QTImer. With 10 or 5 as a delay it worked, with 0-4 it did not. Not sure I like depending on basically a controlled race condition. I would prefer this code to be deterministic.
An additional observation, it that when using Tab to shift inputs (either real or virtual keyboard), I am seeing the same behavior (i.e. no Virtual Keyboard).
-
As a new try, I trying posting a simulated mouse click in the showEvent function, and that did not work. As a quick validation check, I did it on a 5 ms Timer and that did work.
So at this point, the evidence shows a 5 ms delay on getting the focus notification to the QPlatformInputContext.
At this point, the only focus shift that appears to work as desired is the one from a Mouse Click, and event then the simulated mouse click does not cause events to happen as we desire.
-
Can you provide a minimal compilable example that shows that behaviour ?
-
I'll see what I can do today.
-
I have a tarball of source that can be built to show the issue. How do you want that delivered ?
-
Issue has been placed on bugtracker. Link to issue :