From kde-devel Tue Dec 28 16:27:00 2004 From: Vladimir Prus Date: Tue, 28 Dec 2004 16:27:00 +0000 To: kde-devel Subject: Konqueror crash when closing tabs caused by KAccel Message-Id: <200412281927.01336.ghost () cs ! msu ! su> X-MARC-Message: https://marc.info/?l=kde-devel&m=110425131804283 Hello, we've run into konqueror crash, and after some investigation the problem boils down to a question about accelerator handling in KDE and QT. When typing Ctrl-W in konqueror, it should close the current tab. However, in some cases, when I type that when keyboard is in russian layout, konqueror crashes. Tracing the event handling in debugger shows some differences between handling of event in english and russian layouts. When I type Ctrl-W in english layout, the QApplication::x11ProcessEvent arrives at this code block: if ( qt_x11EventFilter(event) ) // send through app filter return 1; The qt_x11EventFilter indirectly calls KAccelEventHandler::x11Event, KAccel for Ctrl-W is invoked and tab is closed. The call to qt_x11EventFilter returns 1 and x11ProcessEvent immediately exits. When I type Ctrl-W in russian layout, the call to KAccelEventHandle::x11Event does not find the accelerator, and the above "return" is not executed. Later, QApplication::x11ProcessEvent calls QETWidget::translateKeyEvent, which has this code: if ( qt_tryAccelEvent( this, &a ) ) return TRUE; } This code finds the KAccel for Ctrl-W, and closes the tab. But, qt_tryAcelEvent returns false. The reason is unclear -- here's the relevant code: bool QAccelManager::tryAccelEvent( QWidget* w, QKeyEvent* e ) { if ( Qt::NoMatch == currentState ) { ........ QApplication::sendSpontaneousEvent( w, e ); if ( e->isAccepted() ) return FALSE; } This "return FALSE" is actually executed. I'd expect that if event is accepted, it means accelerator is found, so TRUE should be returned. But if I change this to "return TRUE" this code is activated for every keypress, not only accelerators, and keyboard does not work at all. So, tryAccelEvent and qt_tryAcelEvent return false, and QETWidget::translateKeyEvent goes on, and eventually ends with segfault in KApplication::notify: if ((t == QEvent::AccelOverride) || (t == QEvent::KeyPress)) { static const KShortcut& _selectAll = KStdAccel::selectAll(); QLineEdit *edit = ::qt_cast(receiver); The crash happens on the last line, supposedly because 'receiever' was part of just destroyed tab. The reason why Qt finds the accelerator while KDE does not is that Qt, when searching the accelerator for KeyPress event with keycode==25, explicitly tries both Ctrl-W and Ctrl-CyrillicTse keys. As far as I can tell, KDE tries only Ctrl-CyrillicTse. Here's the relevant code: bool KAccelEventHandler::x11Event( XEvent* pEvent ) { .... if( pEvent->type == XKeyPress ) { KKeyNative keyNative( pEvent ); Constructor of KKeyNative does XLookupString, which gives different result in english and cyrillic keyboard mode (XK_W for english keyboard, XK_Cyrillic_Tse for russian keyboard). If the code is modified to be: bool KAccelEventHandler::x11Event( XEvent* pEvent ) { .... if( pEvent->type == XKeyPress ) { unsigned int tmp = pEvent->xkey.state; pEvent->xkey.state &= ~0x2000; KKeyNative keyNative( pEvent ); pEvent->xkey.state = tmp; Konqueror no longer crashes. However, this does not look like an acceptable solution. So the question is: what is the real solution? TIA, Volodya >> Visit http://mail.kde.org/mailman/listinfo/kde-devel#unsub to unsubscribe <<