Open kaamui opened 11 months ago
First test with Wikipedia widget: I can enter a ^
in the search field. Next try: an arbitrary web page with an input field as widget (https://www.binaryhexconverter.com/hex-to-binary-converter): it also accepts the ^
in the input field.
I am on the current dev
/master
with 1.7.0rc-231003.
Can you type this character at other places, i.e. in a text box or a file name field, e.g. for export or whatever else? So is the problem restricted to widgets?
Might it be a problem with a French keyboard? Here in Germany the ^
key directly produces this character when pressed once. Is it some kind of accent character key in French? What about pressing this key twice or followed by a space?
Ok, can reproduce now when I switch to a French keyboard layout. ^ works as expected in a text box, but not in a widget. I can now start to analyze this further.
Yep sorry for my late reply. I obviously tested it outside widgets context but forgot to precise it.
Didn't tested it at home, but happens with my french-swiss keyboard (qwertz), where the ^
must be combined with a letter or a space, like in a french-french keyboard (azerty).
No issues on the web search bar, not either on a text box, or anywhere else, just widgets
Same with ¨
with the same behavior where you need to combine it with another key
Also forgot to precise that copy-pasting the character works, so it seems to be related to combined keys, indeed
Looks like in english these "combined" keys are called "dead keys", if it can help you on your search.
Also found this Qt-Bug that could potentially be related : https://bugreports.qt.io/browse/QTBUG-69652
I don't think that this bug report is related. We have no Javascript expecting some specific dead key behavior. But still I have no clue what happens. I added debug output to the keyPressEvent
and keyReleaseEvent
handlers in UBGraphicsScene
, UBGraphicsTextItem
, UBGraphicsWidgetItem
and UBWebEngineView
with the following results:
Typing ^a
in a text item:
=== Scene Key Release QKeyEvent(KeyRelease, Key_Dead_Circumflex) ""
=== Text Key Release QKeyEvent(KeyRelease, Key_Dead_Circumflex) ""
=== Scene Key Release QKeyEvent(KeyRelease, Key_A, text="a") "a"
=== Text Key Release QKeyEvent(KeyRelease, Key_A, text="a") "a"
Typing ^a
in a widget:
=== Scene Key Press QKeyEvent(KeyPress, Key_Dead_Circumflex) ""
=== Widget Key Press QKeyEvent(KeyPress, Key_Dead_Circumflex) ""
=== Scene Key Release QKeyEvent(KeyRelease, Key_Dead_Circumflex) ""
=== Widget Key Release QKeyEvent(KeyRelease, Key_Dead_Circumflex) ""
=== Scene Key Press QKeyEvent(KeyPress, Key_A, text="a") "a"
=== Widget Key Press QKeyEvent(KeyPress, Key_A, text="a") "a"
=== Scene Key Release QKeyEvent(KeyRelease, Key_A, text="a") "a"
=== Widget Key Release QKeyEvent(KeyRelease, Key_A, text="a") "a"
Observations:
UBWebEngineView
. I don't know what to follow from that.I also tried to set Qt::WA_InputMethodEnabled
at various places, but with no effect.
To make things even stranger, the issue doesn't occur on Windows ! (tested with the wiki widget)
To make things even stranger, the issue doesn't occur on Windows !
Here we have probably a completely different handling of dead keys so this is not so strange to me.
Here the log with the global event filter:
Web widget:
=== Key Event QKeyEvent(KeyPress, Key_Dead_Circumflex) on QWidgetWindow(0x2556830, name = "MainWindowWindow")
=== Key Event QKeyEvent(KeyPress, Key_Dead_Circumflex) on UBBoardView(0x2571940, name = "ControlView")
=== Key Event QKeyEvent(KeyPress, Key_Dead_Circumflex) on UBGraphicsScene(0x361c040, name = "BoardScene")
=== Scene Key QKeyEvent(KeyPress, Key_Dead_Circumflex) ""
=== Scene Key Press QKeyEvent(KeyPress, Key_Dead_Circumflex) ""
=== Key Event QKeyEvent(KeyPress, Key_Dead_Circumflex) on UBGraphicsW3CWidgetItem(0x36e53d0)
=== Widget Key QKeyEvent(KeyPress, Key_Dead_Circumflex) ""
=== Widget Key Press QKeyEvent(KeyPress, Key_Dead_Circumflex) ""
=== Key Event QKeyEvent(KeyPress, Key_Dead_Circumflex) on QtWebEngineCore::RenderWidgetHostViewQtDelegateWidget(0x37a4700)
=== Key Event QKeyEvent(KeyRelease, Key_Dead_Circumflex) on QWidgetWindow(0x2556830, name = "MainWindowWindow")
=== Key Event QKeyEvent(KeyRelease, Key_Dead_Circumflex) on UBBoardView(0x2571940, name = "ControlView")
=== Key Event QKeyEvent(KeyRelease, Key_Dead_Circumflex) on UBGraphicsScene(0x361c040, name = "BoardScene")
=== Scene Key QKeyEvent(KeyRelease, Key_Dead_Circumflex) ""
=== Scene Key Release QKeyEvent(KeyRelease, Key_Dead_Circumflex) ""
=== Key Event QKeyEvent(KeyRelease, Key_Dead_Circumflex) on UBGraphicsW3CWidgetItem(0x36e53d0)
=== Widget Key QKeyEvent(KeyRelease, Key_Dead_Circumflex) ""
=== Widget Key Release QKeyEvent(KeyRelease, Key_Dead_Circumflex) ""
=== Key Event QKeyEvent(KeyRelease, Key_Dead_Circumflex) on QtWebEngineCore::RenderWidgetHostViewQtDelegateWidget(0x37a4700)
=== Key Event QKeyEvent(KeyPress, Key_A, text="a") on QWidgetWindow(0x2556830, name = "MainWindowWindow")
=== Key Event QKeyEvent(KeyPress, Key_A, text="a") on UBBoardView(0x2571940, name = "ControlView")
=== Key Event QKeyEvent(KeyPress, Key_A, text="a") on UBGraphicsScene(0x361c040, name = "BoardScene")
=== Scene Key QKeyEvent(KeyPress, Key_A, text="a") "a"
=== Scene Key Press QKeyEvent(KeyPress, Key_A, text="a") "a"
=== Key Event QKeyEvent(KeyPress, Key_A, text="a") on UBGraphicsW3CWidgetItem(0x36e53d0)
=== Widget Key QKeyEvent(KeyPress, Key_A, text="a") "a"
=== Widget Key Press QKeyEvent(KeyPress, Key_A, text="a") "a"
=== Key Event QKeyEvent(KeyPress, Key_A, text="a") on QtWebEngineCore::RenderWidgetHostViewQtDelegateWidget(0x37a4700)
=== Key Event QKeyEvent(KeyRelease, Key_A, text="a") on QWidgetWindow(0x2556830, name = "MainWindowWindow")
=== Key Event QKeyEvent(KeyRelease, Key_A, text="a") on UBBoardView(0x2571940, name = "ControlView")
=== Key Event QKeyEvent(KeyRelease, Key_A, text="a") on UBGraphicsScene(0x361c040, name = "BoardScene")
=== Scene Key QKeyEvent(KeyRelease, Key_A, text="a") "a"
=== Scene Key Release QKeyEvent(KeyRelease, Key_A, text="a") "a"
=== Key Event QKeyEvent(KeyRelease, Key_A, text="a") on UBGraphicsW3CWidgetItem(0x36e53d0)
=== Widget Key QKeyEvent(KeyRelease, Key_A, text="a") "a"
=== Widget Key Release QKeyEvent(KeyRelease, Key_A, text="a") "a"
=== Key Event QKeyEvent(KeyRelease, Key_A, text="a") on QtWebEngineCore::RenderWidgetHostViewQtDelegateWidget(0x37a4700)
Browser
=== Key Event QKeyEvent(KeyRelease, Key_Dead_Circumflex) on QWidgetWindow(0x1e843f0, name = "MainWindowWindow")
=== Key Event QKeyEvent(KeyRelease, Key_Dead_Circumflex) on QtWebEngineCore::RenderWidgetHostViewQtDelegateWidget(0x3f2cf00)
=== Key Event QKeyEvent(KeyRelease, Key_Dead_Circumflex) on QStackedWidget(0x2e534f0, name = "qt_tabwidget_stackedwidget")
=== Key Event QKeyEvent(KeyRelease, Key_Dead_Circumflex) on TabWidget(0x2e40a70)
=== Key Event QKeyEvent(KeyRelease, Key_Dead_Circumflex) on BrowserWindow(0x2e82ae0)
=== Key Event QKeyEvent(KeyRelease, Key_Dead_Circumflex) on QWidget(0x1e6d570)
=== Key Event QKeyEvent(KeyRelease, Key_Dead_Circumflex) on UBMainWindow(0x18cde10, name = "MainWindow")
=== Key Event QKeyEvent(KeyRelease, Key_A, text="a") on QWidgetWindow(0x1e843f0, name = "MainWindowWindow")
=== Key Event QKeyEvent(KeyRelease, Key_A, text="a") on QtWebEngineCore::RenderWidgetHostViewQtDelegateWidget(0x3f2cf00)
=== Key Event QKeyEvent(KeyRelease, Key_A, text="a") on QStackedWidget(0x2e534f0, name = "qt_tabwidget_stackedwidget")
=== Key Event QKeyEvent(KeyRelease, Key_A, text="a") on TabWidget(0x2e40a70)
=== Key Event QKeyEvent(KeyRelease, Key_A, text="a") on BrowserWindow(0x2e82ae0)
=== Key Event QKeyEvent(KeyRelease, Key_A, text="a") on QWidget(0x1e6d570)
=== Key Event QKeyEvent(KeyRelease, Key_A, text="a") on UBMainWindow(0x18cde10, name = "MainWindow")
In both cases RenderWidgetHostViewQtDelegateWidget
seems to be the target of the event, but no key press appears in the browser.
I expect the issue to be located on the WebEngine implementation so it's strange to me that the issue is there for macOS and Linux but not for Windows. OK it must be very different for each OS but I was not expecting it to work anywhere.
May be on Windows you never get the dead key events, but the OS is already handling this and only providing the final result? Or it is sending the dead key event, but when pressing "a", it delivers already the correct accented character as text()
?
On Windows, both events appear on the logs at the same time when I press p on the following example on the browser
QKeyEvent(KeyPress, Key_P, text="^")
QKeyEvent(KeyPress, Key_P, text="^")
QKeyEvent(KeyPress, 0, text="p")
QKeyEvent(KeyPress, 0, text="p")
I assume the problem in the QGraphicsProxyWidget
, because this makes the difference. But I have no clue why and where the key press events are eaten in the cases when it works. Why can I not even see them in a global event filter at application level?
I am not sure to understand. I don't see any keyPress events when typing on the webengine browser on Ubuntu where QGraphicsProxyWidget is not involved. I did the same test as above on Ubuntu and I don't have any event (I also check in UBApplication::eventFilter).
I expected the KeyPress events to always show up, and that it would not work if not, not the opposite...
On the other hand, the webengine is a different process, so maybe it "eats them without notifying main thread" ?
I am not sure to understand. I don't see any keyPress events when typing on the webengine browser on Ubuntu where QGraphicsProxyWidget is not involved. I did the same test as above on Ubuntu and I don't have any event (I also check in UBApplication::eventFilter).
That's what I also do not understand. I cannot see the KeyPress events anywhere. Tried also overriding QCoreApplication::notify
where the documentation says:
Note that this function is called for all events sent to any object in any thread.
This is apparently not true.
I expected the KeyPress events to always show up, and that it would not work if not, not the opposite...
Same with me.
On the other hand, the webengine is a different process, so maybe it "eats them without notifying main thread" ?
No. This process does not have the focus so the OS will not deliver key events to it. They always go to the foreground process.
But my main question is: Why don't we see KeyPress in the cases when it works? Where are these events handled and how?
I could create the correct character if I implement my own dead key handler in UBGraphicsWidgetItem::keyPressEvent
and exchange the text with the accented character. But that is no solution.
Observations (WIP):
^p
shows nothing then ^p
on Windows, where it first shows ^
then nothing (probably because it is considered an invalid combination) on LinuxSee https://bugreports.qt.io/browse/QTBUG-79216
Edit: I now think that what is described in this QTBUG is expected behavior: dead keys don't create KeyPress events, but only KeyRelease events. An InputMethod event is used to pass the character constructed by the input method afterwards.
What did you use to track the call stack until === Key Event QKeyEvent(KeyRelease, Key_A, text="a") on QtWebEngineCore::RenderWidgetHostViewQtDelegateWidget(0x3f2cf00)
?
On Windows, the call stack when we end in UBGraphicsWidgetItem::keyPressEvent (only after typing the second key) :
1 UBGraphicsWidgetItem::keyPressEvent UBGraphicsWidgetItem.cpp 579 0x7ff7e91ed0a1
2 QGraphicsItem::sceneEvent qgraphicsitem.cpp 6961 0x7ffba9e07617
3 QGraphicsWidget::sceneEvent qgraphicswidget.cpp 1238 0x7ffba9eba827
4 QGraphicsScenePrivate::sendEvent qgraphicsscene.cpp 1259 0x7ffba9e54cec
5 QGraphicsScene::keyPressEvent qgraphicsscene.cpp 4000 0x7ffba9e4d2c8
6 QGraphicsScene::event qgraphicsscene.cpp 3411 0x7ffba9e4bbd8
7 QApplicationPrivate::notify_helper qapplication.cpp 3671 0x7ffba9831987
8 QApplication::notify qapplication.cpp 3011 0x7ffba982bb47
9 QCoreApplication::notifyInternal2 qcoreapplication.cpp 1061 0x7ffb9aa9ae9f
10 QCoreApplication::sendEvent qcoreapplication.cpp 1457 0x7ffb9aa98f82
11 UBBoardView::keyPressEvent UBBoardView.cpp 208 0x7ff7e90b6e49
12 QWidget::event qwidget.cpp 8714 0x7ffba98928b7
13 QFrame::event qframe.cpp 550 0x7ffba9a005cf
14 QAbstractScrollArea::event qabstractscrollarea.cpp 1042 0x7ffba9a038dc
15 QGraphicsView::event qgraphicsview.cpp 2885 0x7ffba9ea643f
16 UBBoardView::event UBBoardView.cpp 333 0x7ff7e90b6cf6
17 QApplicationPrivate::notify_helper qapplication.cpp 3671 0x7ffba9831987
18 QApplication::notify qapplication.cpp 3033 0x7ffba982bd05
19 QCoreApplication::notifyInternal2 qcoreapplication.cpp 1061 0x7ffb9aa9ae9f
20 QCoreApplication::forwardEvent qcoreapplication.cpp 1077 0x7ffb9aa9af3c
21 QWidgetWindow::handleKeyEvent qwidgetwindow.cpp 716 0x7ffba98e2e0d
22 QWidgetWindow::event qwidgetwindow.cpp 289 0x7ffba98e24b5
23 QApplicationPrivate::notify_helper qapplication.cpp 3671 0x7ffba9831987
24 QApplication::notify qapplication.cpp 3011 0x7ffba982bb47
25 QCoreApplication::notifyInternal2 qcoreapplication.cpp 1061 0x7ffb9aa9ae9f
26 QCoreApplication::sendSpontaneousEvent qcoreapplication.cpp 1469 0x7ffb9aa9ad3b
27 QGuiApplicationPrivate::processKeyEvent qguiapplication.cpp 2363 0x7ffba861ab88
28 QGuiApplicationPrivate::processWindowSystemEvent qguiapplication.cpp 1953 0x7ffba861da5a
29 QWindowSystemInterface::sendWindowSystemEvents qwindowsysteminterface.cpp 1181 0x7ffba85e7d92
30 QWindowsGuiEventDispatcher::sendPostedEvents qwindowsguieventdispatcher.cpp 82 0x7ffba774a2f2
31 QEventDispatcherWin32::processEvents qeventdispatcher_win.cpp 527 0x7ffb9ab6e9b2
32 QWindowsGuiEventDispatcher::processEvents qwindowsguieventdispatcher.cpp 73 0x7ffba774a2a4
33 QEventLoop::processEvents qeventloop.cpp 140 0x7ffb9aa957db
34 QEventLoop::exec qeventloop.cpp 232 0x7ffb9aa95a44
35 QCoreApplication::exec qcoreapplication.cpp 1369 0x7ffb9aa98d09
36 QGuiApplication::exec qguiapplication.cpp 1868 0x7ffba8616388
37 QApplication::exec qapplication.cpp 2812 0x7ffba982b45a
38 UBApplication::exec UBApplication.cpp 418 0x7ff7e90dc6bb
39 main main.cpp 168 0x7ff7e90d8549
40 WinMain qtmain_win.cpp 97 0x7ff7e96a6745
41 invoke_main exe_common.inl 107 0x7ff7e95df762
42 __scrt_common_main_seh exe_common.inl 288 0x7ff7e95df64e
43 __scrt_common_main exe_common.inl 331 0x7ff7e95df50e
44 WinMainCRTStartup exe_winmain.cpp 17 0x7ff7e95df7fe
45 BaseThreadInitThunk KERNEL32 0x7ffc4b397344
46 RtlUserThreadStart ntdll 0x7ffc4b8226b1
What did you use to track the call stack until
=== Key Event QKeyEvent(KeyRelease, Key_A, text="a") on QtWebEngineCore::RenderWidgetHostViewQtDelegateWidget(0x3f2cf00)
?
I was installing a global event filter in main.cpp
:
class MyEventFilter : public QObject
{
public:
MyEventFilter(QObject *parent = nullptr) : QObject(parent) {}
bool eventFilter(QObject *target, QEvent *event) override
{
if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) {
QKeyEvent *ke = static_cast<QKeyEvent *>(event);
qDebug() << "=== Key Event" << ke << "on" << target;
}
// Continue processing the event
return false;
}
};
and later
MyEventFilter filter;
app.installEventFilter(&filter);
This shows the same event with multiple targets.
Also a longer reading: https://www.kdab.com/qt-input-method-depth/
but I don't know whether this can help understanding our problem., as I was not able to create any inputMethodEvents.
Edit: This article explains in detail how a key press is processed when input methods are enabled. It also explains, why we don't receive and QKeyPressEvent in this case. It even explains why we cannot easily affect that programmatically: the final negotiation is between the focus object and the QPlatformInputContext
, which is the interface to the OS specific input method. If the focus object wants to have InputMethodEvents, it gets them. Setting flags on the widgets is not sufficient. They are not the focus object.
bool eventFilter(QObject *target
Oh I didn't know the first argument was the target. On the already existing eventFilter of UBApplication it is called "obj", that is way more precise of course... 😄
On Linux, the call stack when we end in UBGraphicsWidgetItem::keyPressEvent after we type ^
:
1 UBGraphicsWidgetItem::keyPressEvent UBGraphicsWidgetItem.cpp 620 0x5555557673b6
2 QGraphicsItem::sceneEvent qgraphicsitem.cpp 6960 0x7ffff52811b6
**3 QGraphicsScene::keyReleaseEvent qgraphicsscene.cpp 4032 0x7ffff52a1e72** weird
4 QGraphicsScene::event qgraphicsscene.cpp 3410 0x7ffff52b24ff
5 QApplicationPrivate::notify_helper qapplication.cpp 3671 0x7ffff4faf13c
6 QApplication::notify qapplication.cpp 3417 0x7ffff4fb5d10
7 QCoreApplication::notifyInternal2 qcoreapplication.cpp 1061 0x7fffe9f9f8f8
8 UBBoardView::keyPressEvent UBBoardView.cpp 207 0x555555683eeb
9 QWidget::event qwidget.cpp 8686 0x7ffff4fedf47
10 QFrame::event qframe.cpp 550 0x7ffff5095efe
11 QAbstractScrollArea::event qabstractscrollarea.cpp 1042 0x7ffff5098bd3
12 UBBoardView::event UBBoardView.cpp 331 0x555555684374
13 QApplicationPrivate::notify_helper qapplication.cpp 3671 0x7ffff4faf13c
14 QApplication::notify qapplication.cpp 3033 0x7ffff4fb606b
15 QCoreApplication::notifyInternal2 qcoreapplication.cpp 1061 0x7fffe9f9f8f8
16 QWidgetWindow::event qwidgetwindow.cpp 288 0x7ffff5009b73
17 QApplicationPrivate::notify_helper qapplication.cpp 3671 0x7ffff4faf13c
18 QApplication::notify qapplication.cpp 3417 0x7ffff4fb5d10
19 QCoreApplication::notifyInternal2 qcoreapplication.cpp 1061 0x7fffe9f9f8f8
20 QCoreApplication::sendSpontaneousEvent qcoreapplication.cpp 1468 0x7fffe9f9fabe
21 QGuiApplicationPrivate::processKeyEvent qguiapplication.cpp 2346 0x7fffeb98763b
22 QGuiApplicationPrivate::processWindowSystemEvent qguiapplication.cpp 1952 0x7fffeb98c385
23 QWindowSystemInterface::sendWindowSystemEvents qwindowsysteminterface.cpp 1175 0x7fffeb96817b
24 xcbSourceDispatch qxcbeventdispatcher.cpp 105 0x7fffdd4ac3aa
25 g_main_context_dispatch 0x7fffe839c17d
26 ?? 0x7fffe839c400
27 g_main_context_iteration 0x7fffe839c4a3
28 QEventDispatcherGlib::processEvents qeventdispatcher_glib.cpp 423 0x7fffe9ffb11c
29 QEventLoop::exec qeventloop.cpp 232 0x7fffe9f9e30a
30 QCoreApplication::exec qcoreapplication.cpp 1369 0x7fffe9fa72b3
31 UBApplication::exec UBApplication.cpp 417 0x5555556a49a5
32 main main.cpp 168 0x5555556a0e35
Maybe a workaround would be to store the last dead key the user typed, and when we recieve the next key, we create these events
QKeyEvent(KeyPress, Key_P, text="^")
QKeyEvent(KeyPress, Key_P, text="^")
QKeyEvent(KeyPress, 0, text="p")
QKeyEvent(KeyPress, 0, text="p")
send them to the proxy widget and then we reset the dead key data member
This is what happens on the text widget when I also log the InputMethodEvents:
=== Key Event QKeyEvent(KeyRelease, Key_Dead_Circumflex) on QWidgetWindow(0x12aff40, name = "MainWindowWindow")
=== Key Event QKeyEvent(KeyRelease, Key_Dead_Circumflex) on UBBoardView(0x124de80, name = "ControlView")
=== Key Event QKeyEvent(KeyRelease, Key_Dead_Circumflex) on UBGraphicsScene(0x2584420, name = "BoardScene")
=== Scene Key Release QKeyEvent(KeyRelease, Key_Dead_Circumflex) ""
=== Key Event QKeyEvent(KeyRelease, Key_Dead_Circumflex) on UBGraphicsTextItem(0xf871b0)
=== Text Key Release QKeyEvent(KeyRelease, Key_Dead_Circumflex) ""
=== InputMethodEvent QInputMethodEvent(, commit="U+e2") on UBBoardView(0x124de80, name = "ControlView")
=== InputMethodEvent QInputMethodEvent(, commit="U+e2") on UBGraphicsScene(0x2584420, name = "BoardScene")
=== InputMethodEvent QInputMethodEvent(, commit="U+e2") on UBGraphicsTextItem(0xf871b0)
=== Key Event QKeyEvent(KeyRelease, Key_A, text="a") on QWidgetWindow(0x12aff40, name = "MainWindowWindow")
=== Key Event QKeyEvent(KeyRelease, Key_A, text="a") on UBBoardView(0x124de80, name = "ControlView")
=== Key Event QKeyEvent(KeyRelease, Key_A, text="a") on UBGraphicsScene(0x2584420, name = "BoardScene")
=== Scene Key Release QKeyEvent(KeyRelease, Key_A, text="a") "a"
=== Key Event QKeyEvent(KeyRelease, Key_A, text="a") on UBGraphicsTextItem(0xf871b0)
=== Text Key Release QKeyEvent(KeyRelease, Key_A, text="a") "a"
When I press "a" after "^", an InputMethodEvent
is fired with commit="U+e2"
, which is the code of "â". The event is offered to the view, then the scene and finally the text widget.
I found however no way to produce this behavior when the focus is on any other widget than the text widget. Also when the focus is e.g. on a stroke, we get the key press AND release events. Only with the text widget we don't get the key press events, but instead the InputMethodEvent. There must be some magic in the QGraphicsTextItem
.
Maybe a workaround would be to store the last dead key the user typed, and when we recieve the next key, we create these events
QKeyEvent(KeyPress, Key_P, text="^") QKeyEvent(KeyPress, Key_P, text="^") QKeyEvent(KeyPress, 0, text="p") QKeyEvent(KeyPress, 0, text="p")
send them to the proxy widget and then we reset the dead key data member
Did you test whether this could work? And why duplicating the events? Is it intended that the key and the text don't match in these events?
First of all, I simply tested to send an event with ^
as text and the ^
appeared
Maybe a workaround would be to store the last dead key the user typed, and when we receive the next key, we create these events
QKeyEvent(KeyPress, Key_P, text="^") QKeyEvent(KeyPress, Key_P, text="^") QKeyEvent(KeyPress, 0, text="p") QKeyEvent(KeyPress, 0, text="p")
send them to the proxy widget and then we reset the dead key data member
Did you test whether this could work? And why duplicating the events? Is it intended that the key and the text don't match in these events?
The events are duplicated in Windows logs, but I don't intend to reproduce that. I thought that sending both events QKeyEvent(KeyPress, Key_O, text="^"), QKeyEvent(KeyPress, 0, text="o")
would maybe produce the same result (some magic would combine this as a unique accented letter in the widget) but it produced ^o instead of ô
The good news is that we still have a workaround possible, but quite heavy : sending an event with the dead key as text works, as the dead key is written in the input of the widget, so we could create a method dedicated to Not-Windows and the concerned keyboard layouts, where we would map any dead key with any compatible letter, and send an event with the resulting accented character as text.
So I started to search how to do so without having to detail all the cases, and it resulted on ... inputMethod events ^^
So I tried to make them work by overriding QGrqphicsProxyWidget::InputMethodEvent
and QGrqphicsProxyWidget::inputMethodQuery
and set WA_...
to true
, but nothing happens, it never passes through these methods and I don't understand why.
I also downloaded german language and layouts to compare the call stack, or to see if something would be different in the values of the differents objects, but everything looks exactly the same, expect the result (it works with german layout)...
source of my attempt on input methods : https://stackoverflow.com/questions/28793356/qt-and-dead-keys-in-a-custom-widget
edit : I also verified if our custom UBGraphicsWidgetItem::eventFilter
could not be responsible for filtering such events but nope.
I don't have more information or things to test. I'll start to implement the workaround.
I'm not sure how to know if the keyboard layout is concerned by this workaround. Any idea ?
InputMethod::locale()
always return the same value, independently of the layout I choose, so I must be mistaking two things there.
Hi Martin,
Can you please review and test this commit ? => https://github.com/OpenBoard-org/OpenBoard/commit/9c8b668b89b1417a86e6bd1eaec4ced496a47d95
Thank you !
! Huge discovery while testing ! It is getting stranger 😄
Independently of the code I produced (e.g test on the dev branch or the 1.7.1-dev branch, it's the same) :
result : dead keys aren't ignore anymore ! It is handled like it is in the underlying OS
Important Note : After step 6, when typing a dead keys and another key after, we simply never pass on the keyPressEvent of the widget, and we no longer pass through the global filter event ! Like in the web browser.
Then we can probably use another workaround we already have implemented for another problem.
and from various other places.
We could probably call this function after dropping the widget. Have not much time to test this today (it's my wife's birthday ;) but could you give it a try?
We needed this to update the knowledge about the widget position. You remember the problem with the drop down menus? So we call this when moving the widget. May be it also helps for this issue?
Yep ! I'll try this ! Thank you to have taken the time to reply ! Have a great day and happy birthday to your wife !
Yep ! I'll try this ! Thank you to have taken the time to reply ! Have a great day and happy birthday to your wife !
Thanks!
we have https://github.com/letsfindaway/OpenBoard/blob/3251cc13c7287380c1157cfd20abb0d9b247cd2b/src/domain/UBGraphicsWidgetItem.cpp#L743-L751, but this function is never called. May be we just have to activate that?
there is a connect() with this function as a slot, so it may be more complicated, but I'll look at it.
My observations:
Edit: it is probably not blocked. You just have to click again into the input field, even if it looks as if it would be selected and active.
Thank you,
I did not find what's the root action that is making this change of behavior when moving the widget, and quickly moved to another feature I was working on before I found the issue. If you are out of ideas too, maybe we can leave it as-is for now.
when you have time, could you please tell me if the workaround is OK for you (code review but above all no regression with your keyboard layout) ?
Quick check:
Will do a code review in the afternoon.
Quick check:
- so I have to delete the second character to get the desired effect. Other applications produce a single ^ in those cases.
Exact. I forgot this use case. I'll make an exception when second key is space
Another observation:
Edit: it is probably not blocked. You just have to click again into the input field, even if it looks as if it would be selected and active.
Quick check:
- so I have to delete the second character to get the desired effect. Other applications produce a single ^ in those cases.
Exact. I forgot this use case. I'll make an exception when second key is space
... or the same dead key.
I assume that even things like Chinese or Japanese input would work if the InputMethod would work. So your workaround is for Latin alphabets only. But better than nothing anyway!
Let's keep the issue in mind. Probably there will be a solution some day. Maybe I will also create a QTBUG for this and a minimal proof-of-failure.
I will come up with a PR later today as I have some more proposals for changes.
Thank you for your help.
Do you plan to create a proof-of-failure and a ticket in Qt-bugs ?
Also, what do you think of the following call stack ? I'm really surprised to see such a call here :
1 UBGraphicsWidgetItem::keyPressEvent UBGraphicsWidgetItem.cpp 620 0x5555557673b6
2 QGraphicsItem::sceneEvent qgraphicsitem.cpp 6960 0x7ffff52811b6
**3 QGraphicsScene::keyReleaseEvent qgraphicsscene.cpp 4032 0x7ffff52a1e72** weird
4 QGraphicsScene::event qgraphicsscene.cpp 3410 0x7ffff52b24ff
5 QApplicationPrivate::notify_helper qapplication.cpp 3671 0x7ffff4faf13c
6 QApplication::notify qapplication.cpp 3417 0x7ffff4fb5d10
7 QCoreApplication::notifyInternal2 qcoreapplication.cpp 1061 0x7fffe9f9f8f8
Thank you for your help.
You are welcome!
Do you plan to create a proof-of-failure and a ticket in Qt-bugs ?
Yes, during this week.
Also, what do you think of the following call stack ? I'm really surprised to see such a call here :
1 UBGraphicsWidgetItem::keyPressEvent UBGraphicsWidgetItem.cpp 620 0x5555557673b6 2 QGraphicsItem::sceneEvent qgraphicsitem.cpp 6960 0x7ffff52811b6 **3 QGraphicsScene::keyReleaseEvent qgraphicsscene.cpp 4032 0x7ffff52a1e72** weird 4 QGraphicsScene::event qgraphicsscene.cpp 3410 0x7ffff52b24ff 5 QApplicationPrivate::notify_helper qapplication.cpp 3671 0x7ffff4faf13c 6 QApplication::notify qapplication.cpp 3417 0x7ffff4fb5d10 7 QCoreApplication::notifyInternal2 qcoreapplication.cpp 1061 0x7fffe9f9f8f8
See https://github.com/qt/qtbase/blob/b470da91073fab7a51a75d0d6cd3184e297b20cf/src/widgets/graphicsview/qgraphicsscene.cpp#L3871-L3926. The comment says that these two functions are identical. Probably this is already a first step in squashing these two functions into one. However I cannot see something like that in the calling code in QGraphicsScene::event
.
Edit: But the compiler may be smart enough to recognize that!!! So I think it is the compiler optimization which generates only one code for these two functions.
Hi Martin,
The issue is still occurring on MacOS, because the key code received is Qt::KeyUnknown
. I tried to get more info using a native event filter, but I can't obtain more than the VirtualKeyCode
, that changes upon keyboard layout, so no quick/global solution (I would have to handle manually each keyboard layout).
I just found another workaround, like moving the widget a bit : with the input on focus, going to next page and coming back to our page seems to resolve the issue too. So I can see a workaround with the following operation :
So my question is : I know that your tests on moving programmatically the widget didn't produce the expected effect, but could we inject a script to give focus to any input on the page, before doing so (maybe even refresh the page in the js side could work ?) ? Do you think it could work (I'm starting to try this right now) or am I just going to loose time ?
Thanks in advance for your help.
edit : simply adding runScript("document.querySelector('input').focus()");
when mainFrame is loaded seems to do the trick in macOS ! It probably enables InputMethod
void UBGraphicsWidgetItem::mainFrameLoadFinished (bool ok)
{
mInitialLoadDone = true;
mLoadIsErronous = !ok;
runScript("document.querySelector('input').focus()"); //placing it after the update and updatePosition calls produces the same effect
// repaint when initial rendering is done
update();
updatePosition();
}
edit : simply adding
runScript("document.querySelector('input').focus()");
when mainFrame is loaded seems to do the trick in macOS ! It probably enables InputMethod
That means you have solved it now for MacOS? Would this also work for all other platforms?
And I wonder: You invoke this when loading is finished. Will it still work when the focus leaves the widget and re-enters it later without reloading? If yes, then this is a quite elegant workaround!
I don't wonder that sequence of execution does not affect this. runScript
is asynchronous any way and you have no guarantee when the script is actually executed. So call sequence is not that much important.
That means you have solved it now for MacOS? Would this also work for all other platforms?
just reverted the Linux code and tested it on Ubuntu 20.04 and it also workarounds the issue !
And now testing with this to avoid errors on pages with no input : const el = document.querySelector('input'); if (el) el.focus()
Hi Martin,
I just found that it is impossible to type
^
in a widget ! Tested on Linux and Mac on the Wikipedia widget and a custom one I was working on.Do you have any idea what could be possibly implied here ? (tested with 1.6.4 too and no issue)
Thanks in advance for your help.