From 83708272fbd48b9a65342cc66af5c0a3837d7a13 Mon Sep 17 00:00:00 2001 From: Michele Calgaro Date: Wed, 14 May 2014 22:06:08 +0900 Subject: Workaround Qt/Tde/X? bug for handling Meta key as Alt key in terminal emulation after restored sessions. This resolves bug 1026 for good. --- konsole/konsole/TEWidget.cpp | 16 ++++++-------- konsole/konsole/TEWidget.h | 1 + konsole/konsole/TEmuVt102.cpp | 12 +++++----- konsole/konsole/TEmuVt102.h | 3 ++- konsole/konsole/TEmulation.cpp | 50 +++++++++++++++++++++++++++++++++++++++++- konsole/konsole/TEmulation.h | 8 ++++++- konsole/konsole/konsole.cpp | 15 +++++++++++-- 7 files changed, 86 insertions(+), 19 deletions(-) diff --git a/konsole/konsole/TEWidget.cpp b/konsole/konsole/TEWidget.cpp index 75545a1e0..71db16143 100644 --- a/konsole/konsole/TEWidget.cpp +++ b/konsole/konsole/TEWidget.cpp @@ -1901,7 +1901,7 @@ bool TEWidget::eventFilter( TQObject *obj, TQEvent *e ) return false; // not us if ( e->type() == TQEvent::KeyPress ) { - TQKeyEvent* ke = (TQKeyEvent*)e; + TQKeyEvent *ke = TQT_TQKEYEVENT(e); actSel=0; // Key stroke implies a screen update, so TEWidget won't // know where the current selection is. @@ -1915,14 +1915,12 @@ bool TEWidget::eventFilter( TQObject *obj, TQEvent *e ) } emit keyPressedSignal(ke); // expose - - // in Qt2 when key events were propagated up the tree - // (unhandled? -> parent widget) they passed the event filter only once at - // the beginning. in qt3 this has changed, that is, the event filter is - // called each time the event is sent (see loop in TQApplication::notify, - // when internalNotify() is called for KeyPress, whereas internalNotify - // activates also the global event filter) . That's why we stop propagation - // here. + return true; + } + if ( e->type() == TQEvent::KeyRelease ) + { + TQKeyEvent* ke = (TQKeyEvent*)e; + emit keyReleasedSignal(ke); // expose return true; } if ( e->type() == TQEvent::Enter ) diff --git a/konsole/konsole/TEWidget.h b/konsole/konsole/TEWidget.h index 1e2c36d87..767190e57 100644 --- a/konsole/konsole/TEWidget.h +++ b/konsole/konsole/TEWidget.h @@ -153,6 +153,7 @@ public slots: signals: void keyPressedSignal(TQKeyEvent *e); + void keyReleasedSignal(TQKeyEvent *e); void mouseSignal(int cb, int cx, int cy); void changedFontMetricSignal(int height, int width); void changedContentSizeSignal(int height, int width); diff --git a/konsole/konsole/TEmuVt102.cpp b/konsole/konsole/TEmuVt102.cpp index 8eeb25d54..e0efab745 100644 --- a/konsole/konsole/TEmuVt102.cpp +++ b/konsole/konsole/TEmuVt102.cpp @@ -927,12 +927,12 @@ void TEmuVt102::onScrollLock() the complications towards a configuration file [see KeyTrans class]. */ -void TEmuVt102::onKeyPress( TQKeyEvent* ev ) +void TEmuVt102::doKeyPress( TQKeyEvent* ev ) { - if (!listenToKeyPress) return; // someone else gets the keys emit notifySessionState(NOTIFYNORMAL); -//printf("State/Key: 0x%04x 0x%04x (%d,%d)\n",ev->state(),ev->key(),ev->text().length(),ev->text().length()?ev->text().ascii()[0]:0); + //printf("State/Key: 0x%04x 0x%04x (%d,%d)\n", ev->state(),ev->key(), + // ev->text().length(),ev->text().length()?ev->text().ascii()[0]:0); // lookup in keyboard translation table ... int cmd = CMD_none; @@ -979,7 +979,8 @@ void TEmuVt102::onKeyPress( TQKeyEvent* ev ) if (cmd==CMD_send) { - if (((ev->state() & TQt::AltButton) || (metaKeyMode && (ev->state() & TQt::MetaButton))) && !metaspecified) + if ((ev->state() & TQt::AltButton) || + (metaKeyMode && ((ev->state() & TQt::MetaButton) || metaIsPressed) && !metaspecified)) sendString("\033"); emit sndBlock(txt,len); return; @@ -988,7 +989,8 @@ void TEmuVt102::onKeyPress( TQKeyEvent* ev ) // fall back handling if (!ev->text().isEmpty()) { - if ((ev->state() & TQt::AltButton) || (metaKeyMode && (ev->state() & TQt::MetaButton))) + if ((ev->state() & TQt::AltButton) || + (metaKeyMode && ((ev->state() & TQt::MetaButton) || metaIsPressed))) sendString("\033"); // ESC, this is the ALT prefix TQCString s = m_codec->fromUnicode(ev->text()); // encode for application // FIXME: In Qt 2, TQKeyEvent::text() would return "\003" for Ctrl-C etc. diff --git a/konsole/konsole/TEmuVt102.h b/konsole/konsole/TEmuVt102.h index 05f30ac04..8832a73d8 100644 --- a/konsole/konsole/TEmuVt102.h +++ b/konsole/konsole/TEmuVt102.h @@ -60,7 +60,8 @@ public: void changeGUI(TEWidget* newgui); ~TEmuVt102(); - virtual void onKeyPress(TQKeyEvent*); + virtual void doKeyPress(TQKeyEvent*); + public slots: // signals incoming from TEWidget void onMouse(int cb, int cx, int cy); diff --git a/konsole/konsole/TEmulation.cpp b/konsole/konsole/TEmulation.cpp index 3aa1cfad4..d7cd13780 100644 --- a/konsole/konsole/TEmulation.cpp +++ b/konsole/konsole/TEmulation.cpp @@ -99,6 +99,7 @@ TEmulation::TEmulation(TEWidget* w) connected(false), listenToKeyPress(false), metaKeyMode(false), + metaIsPressed(false), m_codec(0), decoder(0), keytrans(0), @@ -124,6 +125,8 @@ void TEmulation::connectGUI() this,TQT_SLOT(onHistoryCursorChange(int))); TQObject::connect(gui,TQT_SIGNAL(keyPressedSignal(TQKeyEvent*)), this,TQT_SLOT(onKeyPress(TQKeyEvent*))); + TQObject::connect(gui,TQT_SIGNAL(keyReleasedSignal(TQKeyEvent*)), + this,TQT_SLOT(onKeyReleased(TQKeyEvent*))); TQObject::connect(gui,TQT_SIGNAL(beginSelectionSignal(const int,const int,const bool)), this,TQT_SLOT(onSelectionBegin(const int,const int,const bool)) ); TQObject::connect(gui,TQT_SIGNAL(extendSelectionSignal(const int,const int)), @@ -152,6 +155,8 @@ void TEmulation::changeGUI(TEWidget* newgui) this,TQT_SLOT(onHistoryCursorChange(int))); TQObject::disconnect(gui,TQT_SIGNAL(keyPressedSignal(TQKeyEvent*)), this,TQT_SLOT(onKeyPress(TQKeyEvent*))); + TQObject::disconnect(gui,TQT_SIGNAL(keyReleasedSignal(TQKeyEvent*)), + this,TQT_SLOT(onKeyReleased(TQKeyEvent*))); TQObject::disconnect(gui,TQT_SIGNAL(beginSelectionSignal(const int,const int,const bool)), this,TQT_SLOT(onSelectionBegin(const int,const int,const bool)) ); TQObject::disconnect(gui,TQT_SIGNAL(extendSelectionSignal(const int,const int)), @@ -276,11 +281,30 @@ void TEmulation::onRcvChar(int c) /*! */ - void TEmulation::onKeyPress( TQKeyEvent* ev ) { if (!listenToKeyPress) return; // someone else gets the keys + + // HACK - workaround for what looks like a bug in Qt. + // Specifically keep track of when the meta button is pressed or released. + // Upon restarting TDE, restored windows do not received the correct KeyEvent state + // when multiple keys are pressed: the MetaButton is missing. + // Instead on new created window, MetaButton information is correct. + // Ex: + // Meta is pressed --> the state is correct, both before and after + // State: Before=0x0000/After=0x0800 Key: 0x1022 + // Then h is presed --> the state does not contain the MetaButton anymore + // State: Before=0x0000/After=0x0000 Key: 0x0048 + if (ev->key() == TQt::Key_Meta) + metaIsPressed = true; + + doKeyPress(ev); +} + +void TEmulation::doKeyPress( TQKeyEvent* ev ) +{ emit notifySessionState(NOTIFYNORMAL); + if (scr->getHistCursor() != scr->getHistLines() && !ev->text().isEmpty()) scr->setHistCursor(scr->getHistLines()); if (!ev->text().isEmpty()) @@ -297,6 +321,30 @@ void TEmulation::onKeyPress( TQKeyEvent* ev ) } } +void TEmulation::onKeyReleased( TQKeyEvent* ev ) +{ + if (!listenToKeyPress) return; // someone else gets the keys + + // HACK - workaround for what looks like a bug in Qt. + // Specifically keep track of when the meta button is pressed or released. + // Upon restarting TDE, restored windows do not received the correct KeyEvent state + // when multiple keys are pressed: the MetaButton is missing. + // Instead on new created window, MetaButton information is correct. + // Ex: + // Meta is pressed --> the state is correct, both before and after + // State: Before=0x0000/After=0x0800 Key: 0x1022 + // Then h is presed --> the state does not contain the MetaButton anymore + // State: Before=0x0000/After=0x0000 Key: 0x0048 + if (ev->key() == TQt::Key_Meta || !(ev->stateAfter() & TQt::MetaButton)) + metaIsPressed = false; + + doKeyReleased(ev); +} + +void TEmulation::doKeyReleased( TQKeyEvent* ke ) +{ +} + // Unblocking, Byte to Unicode translation --------------------------------- -- /* diff --git a/konsole/konsole/TEmulation.h b/konsole/konsole/TEmulation.h index 6eac5f91b..b50afc608 100644 --- a/konsole/konsole/TEmulation.h +++ b/konsole/konsole/TEmulation.h @@ -55,7 +55,12 @@ public slots: // signals incoming from TEWidget virtual void onImageSizeChange(int lines, int columns); virtual void onHistoryCursorChange(int cursor); - virtual void onKeyPress(TQKeyEvent*); + + // HACK + void onKeyPress(TQKeyEvent*); // This should not be overwritten by derived classes + virtual void doKeyPress(TQKeyEvent*); // Instead this function should be overwritten if necessary + void onKeyReleased(TQKeyEvent*); // This should not be overwritten by derived classes + virtual void doKeyReleased(TQKeyEvent*); // Instead this function should be overwritten if necessary virtual void clearSelection(); virtual void copySelection(); @@ -121,6 +126,7 @@ protected: bool connected; // communicate with widget bool listenToKeyPress; // listen to input bool metaKeyMode; // true -> meta key is handled as Alt + bool metaIsPressed; // true -> the meta key has been pressed down - HACK void setCodec(int c); // codec number, 0 = locale, 1=utf8 diff --git a/konsole/konsole/konsole.cpp b/konsole/konsole/konsole.cpp index f59ae83da..646edd96b 100644 --- a/konsole/konsole/konsole.cpp +++ b/konsole/konsole/konsole.cpp @@ -2376,8 +2376,12 @@ void Konsole::disableMasterModeConnections() for (; to_it.current(); ++to_it) { TESession *to = to_it.current(); if (to!=from) + { disconnect(from->widget(),TQT_SIGNAL(keyPressedSignal(TQKeyEvent*)), to->getEmulation(),TQT_SLOT(onKeyPress(TQKeyEvent*))); + disconnect(from->widget(),TQT_SIGNAL(keyReleasedSignal(TQKeyEvent*)), + to->getEmulation(),TQT_SLOT(onKeyReleased(TQKeyEvent*))); + } } } } @@ -2392,9 +2396,12 @@ void Konsole::enableMasterModeConnections() TQPtrListIterator to_it(sessions); for (; to_it.current(); ++to_it) { TESession *to = to_it.current(); - if (to!=from) { + if (to!=from) + { connect(from->widget(),TQT_SIGNAL(keyPressedSignal(TQKeyEvent*)), to->getEmulation(),TQT_SLOT(onKeyPress(TQKeyEvent*))); + connect(from->widget(),TQT_SIGNAL(keyReleasedSignal(TQKeyEvent*)), + to->getEmulation(),TQT_SLOT(onKeyReleased(TQKeyEvent*))); } } } @@ -3736,8 +3743,12 @@ void Konsole::detachSession(TESession* _se) { for(; from_it.current(); ++from_it) { TESession *from = from_it.current(); if(from->isMasterMode()) + { disconnect(from->widget(), TQT_SIGNAL(keyPressedSignal(TQKeyEvent*)), - _se->getEmulation(), TQT_SLOT(onKeyPress(TQKeyEvent*))); + _se->getEmulation(), TQT_SLOT(onKeyPress(TQKeyEvent*))); + disconnect(from->widget(), TQT_SIGNAL(keyReleasedSignal(TQKeyEvent*)), + _se->getEmulation(), TQT_SLOT(onKeyReleased(TQKeyEvent*))); + } } } -- cgit v1.2.1