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