1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qwsinputcontext_p.h"
43 #include "qinputcontext_p.h"
44 #include "qwsdisplay_qws.h"
45 #include "qwsevent_qws.h"
46 #include "private/qwscommand_qws_p.h"
47 #include "qwindowsystem_qws.h"
48 #include "qevent.h"
49 #include "qtextformat.h"
50 
51 #include <qbuffer.h>
52 
53 #include <qdebug.h>
54 
55 #ifndef QT_NO_QWS_INPUTMETHODS
56 
57 QT_BEGIN_NAMESPACE
58 
59 static QWidget* activeWidget = 0;
60 
61 //#define EXTRA_DEBUG
62 
QWSInputContext(QObject * parent)63 QWSInputContext::QWSInputContext(QObject *parent)
64     :QInputContext(parent)
65 {
66 }
67 
reset()68 void QWSInputContext::reset()
69 {
70     QPaintDevice::qwsDisplay()->resetIM();
71 }
72 
73 
setFocusWidget(QWidget * w)74 void QWSInputContext::setFocusWidget( QWidget *w )
75 {
76     QWidget *oldFocus = focusWidget();
77     if (oldFocus == w)
78         return;
79 
80     if (w) {
81         QWSInputContext::updateImeStatus(w, true);
82     } else {
83         if (oldFocus)
84             QWSInputContext::updateImeStatus(oldFocus, false);
85     }
86 
87     if (oldFocus) {
88         QWidget *tlw = oldFocus->window();
89         int winid = tlw->internalWinId();
90 
91         int widgetid = oldFocus->internalWinId();
92         QPaintDevice::qwsDisplay()->sendIMUpdate(QWSInputMethod::FocusOut, winid, widgetid);
93     }
94 
95     QInputContext::setFocusWidget(w);
96 
97     if (!w)
98         return;
99 
100     QWidget *tlw = w->window();
101     int winid = tlw->winId();
102 
103     int widgetid = w->winId();
104     QPaintDevice::qwsDisplay()->sendIMUpdate(QWSInputMethod::FocusIn, winid, widgetid);
105 
106     //setfocus ???
107 
108     update();
109 }
110 
111 
widgetDestroyed(QWidget * w)112 void QWSInputContext::widgetDestroyed(QWidget *w)
113 {
114     if (w == QT_PREPEND_NAMESPACE(activeWidget))
115         QT_PREPEND_NAMESPACE(activeWidget) = 0;
116     QInputContext::widgetDestroyed(w);
117 }
118 
update()119 void QWSInputContext::update()
120 {
121     QWidget *w = focusWidget();
122     if (!w)
123         return;
124 
125     QWidget *tlw = w->window();
126     int winid = tlw->winId();
127 
128     int widgetid = w->winId();
129     QPaintDevice::qwsDisplay()->sendIMUpdate(QWSInputMethod::Update, winid, widgetid);
130 
131 }
132 
mouseHandler(int x,QMouseEvent * event)133 void QWSInputContext::mouseHandler( int x, QMouseEvent *event)
134 {
135     if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease)
136         QPaintDevice::qwsDisplay()->sendIMMouseEvent( x, event->type() == QEvent::MouseButtonPress );
137 }
138 
activeWidget()139 QWidget *QWSInputContext::activeWidget()
140 {
141     return QT_PREPEND_NAMESPACE(activeWidget);
142 }
143 
144 
isComposing() const145 bool QWSInputContext::isComposing() const
146 {
147     return QT_PREPEND_NAMESPACE(activeWidget) != 0;
148 }
149 
translateIMQueryEvent(QWidget * w,const QWSIMQueryEvent * e)150 bool QWSInputContext::translateIMQueryEvent(QWidget *w, const QWSIMQueryEvent *e)
151 {
152     Qt::InputMethodQuery type = static_cast<Qt::InputMethodQuery>(e->simpleData.property);
153     QVariant result = w->inputMethodQuery(type);
154     QWidget *tlw = w->window();
155     int winId = tlw->winId();
156 
157     if ( type == Qt::ImMicroFocus ) {
158         // translate to relative to tlw
159         QRect mf = result.toRect();
160         mf.moveTopLeft(w->mapTo(tlw,mf.topLeft()));
161         result = mf;
162     }
163 
164     QPaintDevice::qwsDisplay()->sendIMResponse(winId, e->simpleData.property, result);
165 
166     return false;
167 }
168 
translateIMInitEvent(const QWSIMInitEvent * e)169 bool QWSInputContext::translateIMInitEvent(const QWSIMInitEvent *e)
170 {
171     Q_UNUSED(e);
172     qDebug("### QWSInputContext::translateIMInitEvent not implemented ###");
173     return false;
174 }
175 
translateIMEvent(QWidget * w,const QWSIMEvent * e)176 bool QWSInputContext::translateIMEvent(QWidget *w, const QWSIMEvent *e)
177 {
178     QDataStream stream(e->streamingData);
179     QString preedit;
180     QString commit;
181 
182     stream >> preedit;
183     stream >> commit;
184 
185     if (preedit.isEmpty() && QT_PREPEND_NAMESPACE(activeWidget))
186         w = QT_PREPEND_NAMESPACE(activeWidget);
187 
188     QInputContext *qic = w->inputContext();
189     if (!qic)
190         return false;
191 
192     QList<QInputMethodEvent::Attribute> attrs;
193 
194 
195     while (!stream.atEnd()) {
196         int type = -1;
197         int start = -1;
198         int length = -1;
199         QVariant data;
200         stream >> type >> start >> length >> data;
201         if (stream.status() != QDataStream::Ok) {
202             qWarning("corrupted QWSIMEvent");
203             //qic->reset(); //???
204             return false;
205         }
206         if (type == QInputMethodEvent::TextFormat)
207             data = qic->standardFormat(static_cast<QInputContext::StandardFormat>(data.toInt()));
208         attrs << QInputMethodEvent::Attribute(static_cast<QInputMethodEvent::AttributeType>(type), start, length, data);
209     }
210 #ifdef EXTRA_DEBUG
211     qDebug() << "preedit" << preedit << "len" << preedit.length() <<"commit" << commit << "len" << commit.length()
212              << "n attr" << attrs.count();
213 #endif
214 
215     if (preedit.isEmpty())
216         QT_PREPEND_NAMESPACE(activeWidget) = 0;
217     else
218         QT_PREPEND_NAMESPACE(activeWidget) = w;
219 
220 
221     QInputMethodEvent ime(preedit, attrs);
222     if (!commit.isEmpty() || e->simpleData.replaceLength > 0)
223         ime.setCommitString(commit, e->simpleData.replaceFrom, e->simpleData.replaceLength);
224 
225 
226     extern bool qt_sendSpontaneousEvent(QObject *, QEvent *); //qapplication_qws.cpp
227     qt_sendSpontaneousEvent(w, &ime);
228 
229     return true;
230 }
231 
232 Q_GUI_EXPORT void (*qt_qws_inputMethodStatusChanged)(QWidget*) = 0;
233 
updateImeStatus(QWidget * w,bool hasFocus)234 void QWSInputContext::updateImeStatus(QWidget *w, bool hasFocus)
235 {
236     Q_UNUSED(hasFocus);
237 
238     if (!w || !qt_qws_inputMethodStatusChanged)
239         return;
240     qt_qws_inputMethodStatusChanged(w);
241 }
242 
243 
244 QT_END_NAMESPACE
245 
246 #endif // QT_NO_QWS_INPUTMETHODS
247