/**************************************************************************** ** $Id$ ** ** Implementation of QMultiInputContext class ** ** Copyright (C) 2004 immodule for Qt Project. All rights reserved. ** ** This file is written to contribute to Trolltech AS under their own ** licence. You may use this file under your Qt license. Following ** description is copied from their original file headers. Contact ** immodule-qt@freedesktop.org if any conditions of this licensing are ** not clear to you. ** ** ** This file is part of the input method module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QT_NO_IM #include "qmultiinputcontext.h" #include #include #include #ifndef QT_NO_IM_EXTENSIONS #include #endif #include #define QT_NO_IM_QMULTIINPUTCONTEXT_IMINDEX QMultiInputContext::QMultiInputContext() : QInputContext(), _slave( 0 ), imIndex( 0 ), cachedFocus( FALSE ), cachedFocusWidget( 0 ), cachedHolderWidget( 0 ), beIndirectlyConnected( FALSE ), popup( NULL ), currentIMKey( QString::null ) { keyDict.setAutoDelete( true ); keyDict.clear(); if ( getenv( "QT_IM_MODULE" ) ) { currentIMKey = getenv( "QT_IM_MODULE" ); } else { #ifndef QT_NO_IM_EXTENSIONS QSettings settings; currentIMKey = settings.readEntry( "/qt/DefaultInputMethod", "xim" ); #else currentIMKey = "xim"; #endif } } QMultiInputContext::~QMultiInputContext() { keyDict.clear(); } QString QMultiInputContext::identifierName() { return ( slave() ) ? slave()->identifierName() : ""; } QString QMultiInputContext::language() { return ( slave() ) ? slave()->language() : ""; } #if defined(Q_WS_X11) bool QMultiInputContext::x11FilterEvent( QWidget *keywidget, XEvent *event ) { return ( slave() ) ? slave()->x11FilterEvent( keywidget, event ) : FALSE; } #endif // Q_WS_X11 bool QMultiInputContext::filterEvent( const QEvent *event ) { #if !defined(QT_NO_IM_QMULTIINPUTCONTEXT_IMINDEX) if ( event->type() == QEvent::KeyPress ) { QKeyEvent *keyevent = (QKeyEvent *)event; // filter selection key // Control+Alt+Key_Down: change to next input method // Control+Alt+Key_Up: change to previous input method if ( ( keyevent->state() & Qt::ControlButton ) && ( keyevent->state() & Qt::AltButton ) ) { if ( keyevent->key() == Qt::Key_Up ) { changeInputMethod( --imIndex ); return TRUE; } else if ( keyevent->key() == Qt::Key_Down ) { changeInputMethod( ++imIndex ); return TRUE; } } } #endif return ( slave() ) ? slave()->filterEvent( event ) : FALSE; } void QMultiInputContext::reset() { if ( slave() ) slave()->reset(); } void QMultiInputContext::setFocus() { cachedFocus = TRUE; if ( slave() ) slave()->setFocus(); } void QMultiInputContext::unsetFocus() { cachedFocus = FALSE; if ( slave() ) slave()->unsetFocus(); } void QMultiInputContext::setMicroFocus( int x, int y, int w, int h, QFont *f ) { if ( slave() ) slave()->setMicroFocus( x, y, w, h, f ); } void QMultiInputContext::mouseHandler( int x, QEvent::Type type, Qt::ButtonState button, Qt::ButtonState state ) { if ( slave() ) slave()->mouseHandler( x, type, button, state ); } QFont QMultiInputContext::font() const { return ( slave() ) ? slave()->font() : QInputContext::font(); } void QMultiInputContext::destroyInputContext() { if ( _slave ) { // _slave->reset() may not properly work in the case, so we // manually resets the composing state of text widget if ( _slave->focusWidget() ) { QIMEvent *terminator = new QIMEvent( QEvent::IMEnd, QString::null, -1 ); emit imEventGenerated( _slave->focusWidget(), terminator ); } _slave->deleteLater(); _slave = 0; } } /*! This function is a placeholder for future experiment or extension such as commit string snooping. set beIndirectlyConnected = TRUE to activate this virtual function. */ void QMultiInputContext::postIMEvent( QObject *receiver, QIMEvent *event ) { emit imEventGenerated( receiver, event ); } #if defined(Q_WS_X11) QWidget *QMultiInputContext::focusWidget() const { return ( slave() ) ? slave()->focusWidget() : 0; } QWidget *QMultiInputContext::holderWidget() const { return ( slave() ) ? slave()->holderWidget() : 0; } void QMultiInputContext::setFocusWidget( QWidget *w ) { cachedFocusWidget = w; if ( slave() ) slave()->setFocusWidget( w ); } void QMultiInputContext::setHolderWidget( QWidget *w ) { cachedHolderWidget = w; if ( slave() ) slave()->setHolderWidget( w ); } void QMultiInputContext::releaseComposingWidget( QWidget *w ) { if ( slave() ) slave()->releaseComposingWidget( w ); } #endif bool QMultiInputContext::isComposing() const { return ( slave() ) ? slave()->isComposing() : FALSE; } bool QMultiInputContext::isPreeditRelocationEnabled() { return ( slave() ) ? slave()->isPreeditRelocationEnabled() : FALSE; } QInputContext *QMultiInputContext::slave() { if ( ! _slave ) { #if !defined(QT_NO_IM_QMULTIINPUTCONTEXT_IMINDEX) changeInputMethod( imIndex ); #else changeInputMethod( currentIMKey ); #endif } return _slave; } const QInputContext *QMultiInputContext::slave() const { return _slave; } void QMultiInputContext::changeInputMethod( int newIndex ) { #if !defined(QT_NO_IM_QMULTIINPUTCONTEXT_IMINDEX) QStringList keys = QInputContextFactory::keys(); if ( keys.size() == 0 ) return; if ( newIndex >= (int)keys.size() ) { imIndex = 0; } else if ( newIndex < 0 ) { imIndex = keys.size() - 1; } else { imIndex = newIndex; } changeInputMethod( keys[imIndex] ); #endif } void QMultiInputContext::changeInputMethod( QString key ) { QStringList keys = QInputContextFactory::keys(); if ( keys.size() == 0 ) return; if ( key.isEmpty() ) key = keys[0]; if ( _slave ) { _slave->reset(); delete _slave; } _slave = QInputContextFactory::create( key, cachedHolderWidget ); if ( _slave ) { insertChild( _slave ); const char *method; if ( beIndirectlyConnected ) { method = SLOT(imEventReceived(QObject *,QIMEvent *)); } else { method = SIGNAL(imEventGenerated(QObject *,QIMEvent *)); } connect( _slave, SIGNAL(imEventGenerated(QObject *,QIMEvent *)), this, method ); connect( _slave, SIGNAL(deletionRequested()), this, SLOT(destroyInputContext()) ); if ( cachedFocus ) { _slave->setFocus(); _slave->setFocusWidget( cachedFocusWidget ); } currentIMKey = key; //qDebug( "QMultiInputContext::changeInputMethod(): index=%d, slave=%s", // imIndex, (const char *)_slave->identifierName() ); } } QPtrList *QMultiInputContext::menus() { QInputContextMenu *imSelMenu = new QInputContextMenu; imSelMenu->title = tr( "Select Input &Method" ); imSelMenu->popup = createImSelPopup(); QPtrList *result = new QPtrList; result->append( imSelMenu ); QPtrList *slaveMenus = ( slave() ) ? slave()->menus() : 0; if ( slaveMenus ) { for ( QPtrList::Iterator it = slaveMenus->begin(); it != slaveMenus->end(); ++it ) { QInputContextMenu *slaveMenu = *it; result->append( slaveMenu ); } delete slaveMenus; } return result; } QPopupMenu *QMultiInputContext::createImSelPopup() { if ( popup ) delete popup; popup = new QPopupMenu(); keyDict.clear(); QStringList keys = QInputContextFactory::keys(); for ( uint i=0; i < keys.size(); i++ ) { QString idName = keys[i]; bool isIMSwitcher = idName.startsWith( "imsw-" ); if ( ! isIMSwitcher ) { QString dispName = QInputContextFactory::displayName( idName ); if ( dispName.isEmpty() ) dispName = idName; int id = popup->insertItem( dispName ); keyDict.insert( (long)id, new QString( idName ) ); if ( idName == currentIMKey ) popup->setItemChecked( id, true ); QString descriptionStr = QInputContextFactory::description( idName ); if ( ! descriptionStr.isEmpty() ) popup->setWhatsThis( id, descriptionStr ); } } QObject::connect( popup, SIGNAL(activated(int)), this, SLOT(changeInputMethodWithMenuId(int)) ); return popup; } void QMultiInputContext::changeInputMethodWithMenuId( int menuid ) { QString *key = keyDict.find( (long)menuid ); changeInputMethod( (*key) ); } #endif