summaryrefslogtreecommitdiff
authormickeyl <mickeyl>2003-10-19 19:47:13 (UTC)
committer mickeyl <mickeyl>2003-10-19 19:47:13 (UTC)
commitb96ee77f28d8d2e697528290204f15913c3f4c3e (patch) (side-by-side diff)
tree603b15d584bfcd9ee90b2e95a6852c028d7d5247
parent38d72acc2225b88b2f561fa59565d4c66261f1c3 (diff)
downloadopie-b96ee77f28d8d2e697528290204f15913c3f4c3e.zip
opie-b96ee77f28d8d2e697528290204f15913c3f4c3e.tar.gz
opie-b96ee77f28d8d2e697528290204f15913c3f4c3e.tar.bz2
This patch finish the work on the resizable inputmethods.
- in "floating" mode, input methods now remember their geometry - if closed via (x), the inputmethod button is toggled accordingly - eliminated the focus problem
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/launcher/inputmethods.cpp88
-rw-r--r--core/launcher/inputmethods.h1
2 files changed, 75 insertions, 14 deletions
diff --git a/core/launcher/inputmethods.cpp b/core/launcher/inputmethods.cpp
index d89a366..8f3e812 100644
--- a/core/launcher/inputmethods.cpp
+++ b/core/launcher/inputmethods.cpp
@@ -1,232 +1,232 @@
/**********************************************************************
** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
**
** This file is part of the Qtopia Environment.
**
** 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.
**
** 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/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
#define QTOPIA_INTERNAL_LANGLIST
#include "inputmethods.h"
#include <qtopia/config.h>
#include <qtopia/qpeapplication.h>
#include <qtopia/inputmethodinterface.h>
#include <qtopia/global.h>
#include <qpopupmenu.h>
#include <qpushbutton.h>
#include <qtoolbutton.h>
#include <qwidgetstack.h>
#include <qwidget.h>
#include <qlayout.h>
#include <qtimer.h>
#include <qdir.h>
#include <stdlib.h>
#include <qtranslator.h>
#include <qtl.h>
#ifdef Q_WS_QWS
#include <qwindowsystem_qws.h>
#include <qwsevent_qws.h>
#include <qcopchannel_qws.h>
#endif
/* ### SingleFloppy if someone is interested? */
#if 0
#ifdef QT_NO_COMPONENT
#include "../plugins/inputmethods/handwriting/handwritingimpl.h"
#include "../plugins/inputmethods/keyboard/keyboardimpl.h"
#include "../3rdparty/plugins/inputmethods/pickboard/pickboardimpl.h"
#endif
#endif
/* XPM */
static const char * tri_xpm[]={
"9 9 2 1",
"a c #000000",
". c None",
".........",
".........",
".........",
"....a....",
"...aaa...",
"..aaaaa..",
".aaaaaaa.",
".........",
"........."};
int InputMethod::operator <(const InputMethod& o) const
{
return name() < o.name();
}
int InputMethod::operator >(const InputMethod& o) const
{
return name() > o.name();
}
int InputMethod::operator <=(const InputMethod& o) const
{
return name() <= o.name();
}
/*
Slightly hacky: We use WStyle_Tool as a flag to say "this widget
belongs to the IM system, so clicking it should not cause a reset".
*/
class IMToolButton : public QToolButton
{
public:
IMToolButton::IMToolButton( QWidget *parent ) : QToolButton( parent )
{ setWFlags( WStyle_Tool ); }
};
InputMethods::InputMethods( QWidget *parent ) :
QWidget( parent, "InputMethods", WStyle_Tool | WStyle_Customize ),
mkeyboard(0), imethod(0)
{
Config cfg( "Launcher" );
cfg.setGroup( "InputMethods" );
- inputWidgetStyle = QWidget::WStyle_Customize | QWidget::WStyle_StaysOnTop | QWidget::WGroupLeader;
- inputWidgetStyle |= cfg.readBoolEntry( "Float", false ) ? QWidget::WStyle_DialogBorder : QWidget::WStyle_Tool;
+ inputWidgetStyle = QWidget::WStyle_Customize | QWidget::WStyle_StaysOnTop | QWidget::WGroupLeader | QWidget::WStyle_Tool;
+ inputWidgetStyle |= cfg.readBoolEntry( "Float", false ) ? QWidget::WStyle_DialogBorder : 0;
inputWidgetWidth = cfg.readNumEntry( "Width", 100 );
setBackgroundMode( PaletteBackground );
QHBoxLayout *hbox = new QHBoxLayout( this );
kbdButton = new IMToolButton( this);
kbdButton->setFocusPolicy(NoFocus);
kbdButton->setToggleButton( TRUE );
if (parent->sizeHint().height() > 0)
kbdButton->setFixedHeight( parent->sizeHint().height() );
kbdButton->setFixedWidth( 32 );
kbdButton->setAutoRaise( TRUE );
kbdButton->setUsesBigPixmap( TRUE );
hbox->addWidget( kbdButton );
connect( kbdButton, SIGNAL(toggled(bool)), this, SLOT(showKbd(bool)) );
kbdChoice = new IMToolButton( this );
kbdChoice->setFocusPolicy(NoFocus);
kbdChoice->setPixmap( QPixmap( (const char **)tri_xpm ) );
if (parent->sizeHint().height() > 0)
kbdChoice->setFixedHeight( parent->sizeHint().height() );
kbdChoice->setFixedWidth( 13 );
kbdChoice->setAutoRaise( TRUE );
hbox->addWidget( kbdChoice );
connect( kbdChoice, SIGNAL(clicked()), this, SLOT(chooseKbd()) );
connect( (QPEApplication*)qApp, SIGNAL(clientMoused()),
this, SLOT(resetStates()) );
imButton = new QWidgetStack( this ); // later a widget stack
imButton->setFocusPolicy(NoFocus);
if (parent->sizeHint().height() > 0)
imButton->setFixedHeight( parent->sizeHint().height() );
hbox->addWidget(imButton);
imChoice = new QToolButton( this );
imChoice->setFocusPolicy(NoFocus);
imChoice->setPixmap( QPixmap( (const char **)tri_xpm ) );
if (parent->sizeHint().height() > 0)
imChoice->setFixedHeight( parent->sizeHint().height() );
imChoice->setFixedWidth( 13 );
imChoice->setAutoRaise( TRUE );
hbox->addWidget( imChoice );
connect( imChoice, SIGNAL(clicked()), this, SLOT(chooseIm()) );
loadInputMethods();
QCopChannel *channel = new QCopChannel( "QPE/IME", this );
connect( channel, SIGNAL(received(const QCString&, const QByteArray&)),
this, SLOT(qcopReceive(const QCString&, const QByteArray&)) );
}
InputMethods::~InputMethods()
{
Config cfg("qpe");
cfg.setGroup("InputMethod");
if (imethod)
cfg.writeEntry("im", imethod->name() );
if (mkeyboard)
cfg.writeEntry("current", mkeyboard->name() );
unloadInputMethods();
}
void InputMethods::hideInputMethod()
{
kbdButton->setOn( FALSE );
}
void InputMethods::showInputMethod()
{
kbdButton->setOn( TRUE );
}
void InputMethods::showInputMethod(const QString& name)
{
int i = 0;
QValueList<InputMethod>::Iterator it;
InputMethod *im = 0;
for ( it = inputMethodList.begin(); it != inputMethodList.end(); ++it, i++ ) {
QString lname = (*it).libName.mid((*it).libName.findRev('/') + 1);
if ( (*it).name() == name || lname == name ) {
im = &(*it);
break;
}
}
if ( im )
chooseKeyboard(im);
}
void InputMethods::resetStates()
{
if ( mkeyboard && !mkeyboard->newIM )
mkeyboard->interface->resetState();
}
QRect InputMethods::inputRect() const
{
if ( !mkeyboard || !mkeyboard->widget || !mkeyboard->widget->isVisible() )
return QRect();
else
return mkeyboard->widget->geometry();
}
void InputMethods::unloadInputMethods()
{
unloadMethod( inputMethodList );
unloadMethod( inputModifierList );
inputMethodList.clear();
inputModifierList.clear();
}
void InputMethods::unloadMethod( QValueList<InputMethod>& list ) {
QValueList<InputMethod>::Iterator it;
for (it = list.begin(); it != list.end(); ++it )
(*it).releaseInterface();
}
QStringList InputMethods::plugins()const {
QString path = QPEApplication::qpeDir() + "/plugins/inputmethods";
QDir dir( path, "lib*.so" );
return dir.entryList();
}
@@ -405,162 +405,222 @@ void InputMethods::chooseIm()
QValueList<InputMethod>::Iterator it;
for ( it = inputModifierList.begin(); it != inputModifierList.end(); ++it, i++ ) {
pop.insertItem( (*it).name(), i );
if ( imethod == &(*it) )
pop.setItemChecked( i, TRUE );
}
QPoint pt = mapToGlobal(imChoice->geometry().topRight());
QSize s = pop.sizeHint();
pt.ry() -= s.height();
pt.rx() -= s.width();
i = pop.exec( pt );
if ( i == -1 )
return;
InputMethod *im = &inputModifierList[i];
chooseMethod(im);
}
void InputMethods::chooseKeyboard(InputMethod* im)
{
if ( im != mkeyboard ) {
if ( mkeyboard && mkeyboard->widget->isVisible() )
mkeyboard->widget->hide();
mkeyboard = im;
kbdButton->setPixmap( *mkeyboard->icon() );
}
if ( !kbdButton->isOn() )
kbdButton->setOn( TRUE );
else
showKbd( TRUE );
}
static bool keyboardCompatible(InputMethod *keyb, const QString &imname )
{
if ( !keyb || !keyb->newIM || !keyb->extInterface->compatible().count() )
return TRUE;
if ( keyb->extInterface->compatible().contains(imname) )
return TRUE;
return FALSE;
}
// Updates the display of the soft keyboards available to the current input method
void InputMethods::updateKeyboards(InputMethod *im )
{
uint count;
if ( im ) {
QString imname = im->libName.mid(im->libName.findRev('/') + 1);
if ( mkeyboard && !keyboardCompatible(mkeyboard, imname) ) {
kbdButton->setOn( FALSE );
showKbd( FALSE );
mkeyboard = 0;
}
count = 0;
QValueList<InputMethod>::Iterator it;
for ( it = inputMethodList.begin(); it != inputMethodList.end(); ++it ) {
if ( keyboardCompatible( &(*it), imname ) ) {
if ( !mkeyboard ) {
mkeyboard = &(*it);
kbdButton->setPixmap( *mkeyboard->icon() );
}
count++;
}
}
} else {
count = inputMethodList.count();
if ( count && !mkeyboard ) {
mkeyboard = &inputMethodList[0];
kbdButton->setPixmap( *mkeyboard->icon() );
} else if (!count){
mkeyboard = 0; //might be redundant
}
}
if ( count > 1 )
kbdChoice->show();
else
kbdChoice->hide();
if ( count )
kbdButton->show();
else
kbdButton->hide();
}
void InputMethods::chooseMethod(InputMethod* im)
{
if ( im != imethod ) {
updateKeyboards( im );
Config cfg("qpe");
cfg.setGroup("InputMethod");
if (im )
cfg.writeEntry("im", im->name() );
if (mkeyboard)
cfg.writeEntry("current", mkeyboard->name() );
QWSServer::setCurrentInputMethod( 0 );
imethod = im;
if ( imethod && imethod->newIM )
QWSServer::setCurrentInputMethod( imethod->extInterface->inputMethod() );
else
QWSServer::setCurrentInputMethod( 0 );
if ( im )
imButton->raiseWidget(im->widget);
else
imButton->hide(); //### good UI? make sure it is shown again!
}
}
void InputMethods::qcopReceive( const QCString &msg, const QByteArray &data )
{
if ( imethod && imethod->newIM )
imethod->extInterface->qcopReceive( msg, data );
}
void InputMethods::showKbd( bool on )
{
if ( !mkeyboard )
- return;
-
- if ( on ) {
- mkeyboard->resetState();
- // HACK... Make the texteditor fit with all input methods
- // Input methods should also never use more than about 40% of the screen
- int height = QMIN( mkeyboard->widget->sizeHint().height(), 134 );
- mkeyboard->widget->resize( qApp->desktop()->width() * (inputWidgetWidth*0.01), height );
- mkeyboard->widget->move( 0, mapToGlobal( QPoint() ).y() - height );
- mkeyboard->widget->show();
- } else {
- mkeyboard->widget->hide();
+ return;
+
+ if ( on )
+ {
+ mkeyboard->resetState();
+
+ int height = QMIN( mkeyboard->widget->sizeHint().height(), 134 );
+ int width = qApp->desktop()->width() * (inputWidgetWidth*0.01);
+ int left = 0;
+ int top = mapToGlobal( QPoint() ).y() - height;
+
+ if ( inputWidgetStyle & QWidget::WStyle_DialogBorder )
+ {
+ qDebug( "InputMethods: reading geometry." );
+ Config cfg( "Launcher" );
+ cfg.setGroup( "InputMethods" );
+ int l = cfg.readNumEntry( "absX", -1 );
+ int t = cfg.readNumEntry( "absY", -1 );
+ int w = cfg.readNumEntry( "absWidth", -1 );
+ int h = cfg.readNumEntry( "absHeight", -1 );
+
+ if ( l > -1 && t > -1 && w > -1 && h > -1 )
+ {
+ qDebug( "InputMethods: config values ( %d, %d, %d, %d ) are ok.", l, t, w, h );
+ left = l;
+ top = t;
+ width = w;
+ height = h;
+ }
+ else
+ {
+ qDebug( "InputMethods: config values are new or not ok." );
+ }
+ }
+ else
+ {
+ qDebug( "InputMethods: no floating selected." );
+ }
+ mkeyboard->widget->resize( width, height );
+ mkeyboard->widget->move( left, top );
+ mkeyboard->widget->show();
+ mkeyboard->widget->installEventFilter( this );
+ }
+ else
+ {
+ if ( inputWidgetStyle & QWidget::WStyle_DialogBorder )
+ {
+ QPoint pos = mkeyboard->widget->pos();
+ QSize siz = mkeyboard->widget->size();
+ qDebug( "InputMethods: saving geometry." );
+ Config cfg( "Launcher" );
+ cfg.setGroup( "InputMethods" );
+ cfg.writeEntry( "absX", pos.x() );
+ cfg.writeEntry( "absY", pos.y() );
+ cfg.writeEntry( "absWidth", siz.width() );
+ cfg.writeEntry( "absHeight", siz.height() );
+ cfg.write();
+ mkeyboard->widget->hide();
+ mkeyboard->widget->removeEventFilter( this );
+ }
}
emit inputToggled( on );
}
bool InputMethods::shown() const
{
return mkeyboard && mkeyboard->widget->isVisible();
}
QString InputMethods::currentShown() const
{
return mkeyboard && mkeyboard->widget->isVisible()
? mkeyboard->name() : QString::null;
}
void InputMethods::sendKey( ushort unicode, ushort scancode, ushort mod, bool press, bool repeat )
{
#if defined(Q_WS_QWS)
QWSServer::sendKeyEvent( unicode, scancode, mod, press, repeat );
#endif
}
+
+bool InputMethods::eventFilter( QObject* o, QEvent* e )
+{
+ if ( e->type() == QEvent::Close )
+ {
+ ( (QCloseEvent*) e )->ignore();
+ showKbd( false );
+ kbdButton->setOn( false );
+ return true;
+ }
+ return false;
+}
diff --git a/core/launcher/inputmethods.h b/core/launcher/inputmethods.h
index 246661a..55ac020 100644
--- a/core/launcher/inputmethods.h
+++ b/core/launcher/inputmethods.h
@@ -1,112 +1,113 @@
/**********************************************************************
** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
**
** This file is part of the Qtopia Environment.
**
** 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.
**
** 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/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
#ifndef __INPUT_METHODS_H__
#define __INPUT_METHODS_H__
#include <qtopia/qlibrary.h>
#include <qtopia/inputmethodinterface.h>
#include <qwidget.h>
#include <qvaluelist.h>
class QToolButton;
class QWidgetStack;
struct InputMethod
{
#ifndef QT_NO_COMPONENT
QLibrary *library;
#endif
QWidget *widget;
QString libName;
bool newIM;
union {
InputMethodInterface *interface;
ExtInputMethodInterface *extInterface;
};
inline void releaseInterface() {
newIM ? (void)extInterface->release() : (void)interface->release();
library->unload();
delete library; library = 0l;
}
inline QString name() const { return newIM ? extInterface->name() : interface->name(); }
inline QPixmap *icon() const { return newIM ? extInterface->icon() : interface->icon(); }
inline QUnknownInterface *iface() { return newIM ? (QUnknownInterface *)extInterface : (QUnknownInterface *)interface; }
inline void resetState() { if ( !newIM ) interface->resetState(); }
int operator <(const InputMethod& o) const;
int operator >(const InputMethod& o) const;
int operator <=(const InputMethod& o) const;
};
class InputMethods : public QWidget
{
Q_OBJECT
public:
InputMethods( QWidget * );
~InputMethods();
QRect inputRect() const;
bool shown() const;
QString currentShown() const; // name of interface
void showInputMethod(const QString& id);
void showInputMethod();
void hideInputMethod();
void unloadInputMethods();
void loadInputMethods();
+ virtual bool eventFilter( QObject *, QEvent * );
signals:
void inputToggled( bool on );
private slots:
void chooseKbd();
void chooseIm();
void showKbd( bool );
void resetStates();
void sendKey( ushort unicode, ushort scancode, ushort modifiers, bool, bool );
void qcopReceive( const QCString &msg, const QByteArray &data );
private:
void setPreferedHandlers();
/*static */QStringList plugins()const;
/*static */void installTranslator( const QString& );
void unloadMethod( QValueList<InputMethod>& );
void chooseMethod(InputMethod* im);
void chooseKeyboard(InputMethod* im);
void updateKeyboards(InputMethod *im);
private:
QToolButton *kbdButton;
QToolButton *kbdChoice;
QWidgetStack *imButton; // later will be widget stack
QToolButton *imChoice;
InputMethod *mkeyboard;
InputMethod *imethod;
QValueList<InputMethod> inputMethodList;
QValueList<InputMethod> inputModifierList;
int inputWidgetStyle;
int inputWidgetWidth;
};
#endif // __INPUT_METHODS_H__