|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the QtGui module of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 /**************************************************************************** |
|
43 ** |
|
44 ** Implementation of QInputContext class |
|
45 ** |
|
46 ** Copyright (C) 2003-2004 immodule for Qt Project. All rights reserved. |
|
47 ** |
|
48 ** This file is written to contribute to Nokia Corporation and/or its subsidiary(-ies) under their own |
|
49 ** license. You may use this file under your Qt license. Following |
|
50 ** description is copied from their original file headers. Contact |
|
51 ** immodule-qt@freedesktop.org if any conditions of this licensing are |
|
52 ** not clear to you. |
|
53 ** |
|
54 ****************************************************************************/ |
|
55 |
|
56 //#define QT_NO_IM_PREEDIT_RELOCATION |
|
57 |
|
58 #include "qinputcontext.h" |
|
59 #include "qinputcontext_p.h" |
|
60 |
|
61 #ifndef QT_NO_IM |
|
62 |
|
63 #include "qplatformdefs.h" |
|
64 |
|
65 #include "qapplication.h" |
|
66 #include "qmenu.h" |
|
67 #include "qtextformat.h" |
|
68 #include "qpalette.h" |
|
69 |
|
70 #include <stdlib.h> |
|
71 #include <limits.h> |
|
72 |
|
73 QT_BEGIN_NAMESPACE |
|
74 |
|
75 /*! |
|
76 \class QInputContext |
|
77 \brief The QInputContext class abstracts the input method dependent data and composing state. |
|
78 |
|
79 \ingroup i18n |
|
80 |
|
81 An input method is responsible for inputting complex text that cannot |
|
82 be inputted via simple keymap. It converts a sequence of input |
|
83 events (typically key events) into a text string through the input |
|
84 method specific converting process. The class of the processes are |
|
85 widely ranging from simple finite state machine to complex text |
|
86 translator that pools a whole paragraph of a text with text |
|
87 editing capability to perform grammar and semantic analysis. |
|
88 |
|
89 To abstract such different input method specific intermediate |
|
90 information, Qt offers the QInputContext as base class. The |
|
91 concept is well known as 'input context' in the input method |
|
92 domain. An input context is created for a text widget in response |
|
93 to a demand. It is ensured that an input context is prepared for |
|
94 an input method before input to a text widget. |
|
95 |
|
96 Multiple input contexts that belong to a single input method |
|
97 may concurrently coexist. Suppose multi-window text editor. Each |
|
98 text widget of window A and B holds different QInputContext |
|
99 instance which contains different state information such as |
|
100 partially composed text. |
|
101 |
|
102 \section1 Groups of Functions |
|
103 |
|
104 \table |
|
105 \header \o Context \o Functions |
|
106 |
|
107 \row \o Receiving information \o |
|
108 x11FilterEvent(), |
|
109 filterEvent(), |
|
110 mouseHandler() |
|
111 |
|
112 \row \o Sending back composed text \o |
|
113 sendEvent() |
|
114 |
|
115 \row \o State change notification \o |
|
116 setFocusWidget(), |
|
117 reset() |
|
118 |
|
119 \row \o Context information \o |
|
120 identifierName(), |
|
121 language(), |
|
122 font(), |
|
123 isComposing() |
|
124 |
|
125 \endtable |
|
126 |
|
127 \section1 Licensing Information |
|
128 |
|
129 \legalese |
|
130 Copyright (C) 2003-2004 immodule for Qt Project. All rights reserved. |
|
131 |
|
132 This file is written to contribute to Nokia Corporation and/or its subsidiary(-ies) under their own |
|
133 license. You may use this file under your Qt license. Following |
|
134 description is copied from their original file headers. Contact |
|
135 immodule-qt@freedesktop.org if any conditions of this licensing are |
|
136 not clear to you. |
|
137 \endlegalese |
|
138 |
|
139 \sa QInputContextPlugin, QInputContextFactory, QApplication::setInputContext() |
|
140 */ |
|
141 |
|
142 /*! |
|
143 Constructs an input context with the given \a parent. |
|
144 */ |
|
145 QInputContext::QInputContext(QObject* parent) |
|
146 : QObject(*new QInputContextPrivate, parent) |
|
147 { |
|
148 } |
|
149 |
|
150 |
|
151 /*! |
|
152 Destroys the input context. |
|
153 */ |
|
154 QInputContext::~QInputContext() |
|
155 { |
|
156 } |
|
157 |
|
158 /*! |
|
159 Returns the widget that has an input focus for this input |
|
160 context. |
|
161 |
|
162 The return value may differ from holderWidget() if the input |
|
163 context is shared between several text widgets. |
|
164 |
|
165 \warning To ensure platform independence and support flexible |
|
166 configuration of widgets, ordinary input methods should not call |
|
167 this function directly. |
|
168 |
|
169 \sa setFocusWidget() |
|
170 */ |
|
171 QWidget *QInputContext::focusWidget() const |
|
172 { |
|
173 Q_D(const QInputContext); |
|
174 return d->focusWidget; |
|
175 } |
|
176 |
|
177 |
|
178 /*! |
|
179 Sets the \a widget that has an input focus for this input context. |
|
180 |
|
181 \warning Ordinary input methods must not call this function |
|
182 directly. |
|
183 |
|
184 \sa focusWidget() |
|
185 */ |
|
186 void QInputContext::setFocusWidget(QWidget *widget) |
|
187 { |
|
188 Q_ASSERT(!widget || widget->testAttribute(Qt::WA_InputMethodEnabled)); |
|
189 Q_D(QInputContext); |
|
190 d->focusWidget = widget; |
|
191 } |
|
192 |
|
193 /*! |
|
194 \fn bool QInputContext::isComposing() const |
|
195 |
|
196 This function indicates whether InputMethodStart event had been |
|
197 sent to the current focus widget. It is ensured that an input |
|
198 context can send InputMethodCompose or InputMethodEnd event safely |
|
199 if this function returned true. |
|
200 |
|
201 The state is automatically being tracked through sendEvent(). |
|
202 |
|
203 \sa sendEvent() |
|
204 */ |
|
205 |
|
206 /*! |
|
207 This function can be reimplemented in a subclass to filter input |
|
208 events. |
|
209 |
|
210 Return true if the \a event has been consumed. Otherwise, the |
|
211 unfiltered \a event will be forwarded to widgets as ordinary |
|
212 way. Although the input events have accept() and ignore() |
|
213 methods, leave it untouched. |
|
214 |
|
215 \a event is currently restricted to events of these types: |
|
216 |
|
217 \list |
|
218 \i CloseSoftwareInputPanel |
|
219 \i KeyPress |
|
220 \i KeyRelease |
|
221 \i MouseButtonDblClick |
|
222 \i MouseButtonPress |
|
223 \i MouseButtonRelease |
|
224 \i MouseMove |
|
225 \i RequestSoftwareInputPanel |
|
226 \endlist |
|
227 |
|
228 But some input method related events such as QWheelEvent or |
|
229 QTabletEvent may be added in future. |
|
230 |
|
231 The filtering opportunity is always given to the input context as |
|
232 soon as possible. It has to be taken place before any other key |
|
233 event consumers such as eventfilters and accelerators because some |
|
234 input methods require quite various key combination and |
|
235 sequences. It often conflicts with accelerators and so on, so we |
|
236 must give the input context the filtering opportunity first to |
|
237 ensure all input methods work properly regardless of application |
|
238 design. |
|
239 |
|
240 Ordinary input methods require discrete key events to work |
|
241 properly, so Qt's key compression is always disabled for any input |
|
242 contexts. |
|
243 |
|
244 \sa QKeyEvent, x11FilterEvent() |
|
245 */ |
|
246 bool QInputContext::filterEvent(const QEvent * /*event*/) |
|
247 { |
|
248 return false; |
|
249 } |
|
250 |
|
251 /*! |
|
252 Sends an input method event specified by \a event to the current focus |
|
253 widget. Implementations of QInputContext should call this method to |
|
254 send the generated input method events and not |
|
255 QApplication::sendEvent(), as the events might have to get dispatched |
|
256 to a different application on some platforms. |
|
257 |
|
258 Some complex input methods route the handling to several child |
|
259 contexts (e.g. to enable language switching). To account for this, |
|
260 QInputContext will check if the parent object is a QInputContext. If |
|
261 yes, it will call the parents sendEvent() implementation instead of |
|
262 sending the event directly. |
|
263 |
|
264 \sa QInputMethodEvent |
|
265 */ |
|
266 void QInputContext::sendEvent(const QInputMethodEvent &event) |
|
267 { |
|
268 // route events over input context parents to make chaining possible. |
|
269 QInputContext *p = qobject_cast<QInputContext *>(parent()); |
|
270 if (p) { |
|
271 p->sendEvent(event); |
|
272 return; |
|
273 } |
|
274 |
|
275 QWidget *focus = focusWidget(); |
|
276 if (!focus) |
|
277 return; |
|
278 |
|
279 QInputMethodEvent e(event); |
|
280 QApplication::sendEvent(focus, &e); |
|
281 } |
|
282 |
|
283 |
|
284 /*! |
|
285 This function can be reimplemented in a subclass to handle mouse |
|
286 press, release, double-click, and move events within the preedit |
|
287 text. You can use the function to implement mouse-oriented user |
|
288 interface such as text selection or popup menu for candidate |
|
289 selection. |
|
290 |
|
291 The \a x parameter is the offset within the string that was sent |
|
292 with the InputMethodCompose event. The alteration boundary of \a |
|
293 x is ensured as character boundary of preedit string accurately. |
|
294 |
|
295 The \a event parameter is the event that was sent to the editor |
|
296 widget. The event type is QEvent::MouseButtonPress, |
|
297 QEvent::MouseButtonRelease, QEvent::MouseButtonDblClick or |
|
298 QEvent::MouseMove. The event's button and state indicate |
|
299 the kind of operation that was performed. |
|
300 */ |
|
301 void QInputContext::mouseHandler(int /*x*/, QMouseEvent *event) |
|
302 { |
|
303 // Default behavior for simple ephemeral input contexts. Some |
|
304 // complex input contexts should not be reset here. |
|
305 if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonDblClick) |
|
306 reset(); |
|
307 } |
|
308 |
|
309 |
|
310 /*! |
|
311 Returns the font of the current input widget |
|
312 */ |
|
313 QFont QInputContext::font() const |
|
314 { |
|
315 Q_D(const QInputContext); |
|
316 if (!d->focusWidget) |
|
317 return QApplication::font(); |
|
318 |
|
319 return qvariant_cast<QFont>(d->focusWidget->inputMethodQuery(Qt::ImFont)); |
|
320 } |
|
321 |
|
322 /*! |
|
323 This virtual function is called when a state in the focus widget |
|
324 has changed. QInputContext can then use |
|
325 QWidget::inputMethodQuery() to query the new state of the widget. |
|
326 */ |
|
327 void QInputContext::update() |
|
328 { |
|
329 } |
|
330 |
|
331 /*! |
|
332 This virtual function is called when the specified \a widget is |
|
333 destroyed. The \a widget is a widget on which this input context |
|
334 is installed. |
|
335 */ |
|
336 void QInputContext::widgetDestroyed(QWidget *widget) |
|
337 { |
|
338 Q_D(QInputContext); |
|
339 if (widget == d->focusWidget) |
|
340 setFocusWidget(0); |
|
341 } |
|
342 |
|
343 /*! |
|
344 \fn void QInputContext::reset() |
|
345 |
|
346 This function can be reimplemented in a subclass to reset the |
|
347 state of the input method. |
|
348 |
|
349 This function is called by several widgets to reset input |
|
350 state. For example, a text widget call this function before |
|
351 inserting a text to make widget ready to accept a text. |
|
352 |
|
353 Default implementation is sufficient for simple input method. You |
|
354 can override this function to reset external input method engines |
|
355 in complex input method. In the case, call QInputContext::reset() |
|
356 to ensure proper termination of inputting. |
|
357 |
|
358 You must not send any QInputMethodEvent except empty InputMethodEnd event using |
|
359 QInputContext::reset() at reimplemented reset(). It will break |
|
360 input state consistency. |
|
361 */ |
|
362 |
|
363 |
|
364 /*! |
|
365 \fn QString QInputContext::identifierName() |
|
366 |
|
367 This function must be implemented in any subclasses to return the |
|
368 identifier name of the input method. |
|
369 |
|
370 Return value is the name to identify and specify input methods for |
|
371 the input method switching mechanism and so on. The name has to be |
|
372 consistent with QInputContextPlugin::keys(). The name has to |
|
373 consist of ASCII characters only. |
|
374 |
|
375 There are two different names with different responsibility in the |
|
376 input method domain. This function returns one of them. Another |
|
377 name is called 'display name' that stands for the name for |
|
378 endusers appeared in a menu and so on. |
|
379 |
|
380 \sa QInputContextPlugin::keys(), QInputContextPlugin::displayName() |
|
381 */ |
|
382 |
|
383 |
|
384 /*! |
|
385 \fn QString QInputContext::language() |
|
386 |
|
387 This function must be implemented in any subclasses to return a |
|
388 language code (e.g. "zh_CN", "zh_TW", "zh_HK", "ja", "ko", ...) |
|
389 of the input context. If the input context can handle multiple |
|
390 languages, return the currently used one. The name has to be |
|
391 consistent with QInputContextPlugin::language(). |
|
392 |
|
393 This information will be used by language tagging feature in |
|
394 QInputMethodEvent. It is required to distinguish unified han characters |
|
395 correctly. It enables proper font and character code |
|
396 handling. Suppose CJK-awared multilingual web browser |
|
397 (that automatically modifies fonts in CJK-mixed text) and XML editor |
|
398 (that automatically inserts lang attr). |
|
399 */ |
|
400 |
|
401 |
|
402 /*! |
|
403 This is a preliminary interface for Qt 4. |
|
404 */ |
|
405 QList<QAction *> QInputContext::actions() |
|
406 { |
|
407 return QList<QAction *>(); |
|
408 } |
|
409 |
|
410 /*! |
|
411 \enum QInputContext::StandardFormat |
|
412 |
|
413 \value PreeditFormat The preedit text. |
|
414 \value SelectionFormat The selection text. |
|
415 |
|
416 \sa standardFormat() |
|
417 */ |
|
418 |
|
419 /*! |
|
420 Returns a QTextFormat object that specifies the format for |
|
421 component \a s. |
|
422 */ |
|
423 QTextFormat QInputContext::standardFormat(StandardFormat s) const |
|
424 { |
|
425 QWidget *focus = focusWidget(); |
|
426 const QPalette &pal = focus ? focus->palette() : QApplication::palette(); |
|
427 |
|
428 QTextCharFormat fmt; |
|
429 QColor bg; |
|
430 switch (s) { |
|
431 case QInputContext::PreeditFormat: { |
|
432 fmt.setUnderlineStyle(QTextCharFormat::DashUnderline); |
|
433 break; |
|
434 } |
|
435 case QInputContext::SelectionFormat: { |
|
436 bg = pal.text().color(); |
|
437 fmt.setBackground(QBrush(bg)); |
|
438 fmt.setForeground(pal.background()); |
|
439 break; |
|
440 } |
|
441 } |
|
442 return fmt; |
|
443 } |
|
444 |
|
445 #ifdef Q_WS_X11 |
|
446 /*! |
|
447 This function may be overridden only if input method is depending |
|
448 on X11 and you need raw XEvent. Otherwise, this function must not. |
|
449 |
|
450 This function is designed to filter raw key events for XIM, but |
|
451 other input methods may use this to implement some special |
|
452 features such as distinguishing Shift_L and Shift_R. |
|
453 |
|
454 Return true if the \a event has been consumed. Otherwise, the |
|
455 unfiltered \a event will be translated into QEvent and forwarded |
|
456 to filterEvent(). Filtering at both x11FilterEvent() and |
|
457 filterEvent() in single input method is allowed. |
|
458 |
|
459 \a keywidget is a client widget into which a text is inputted. \a |
|
460 event is inputted XEvent. |
|
461 |
|
462 \sa filterEvent() |
|
463 */ |
|
464 bool QInputContext::x11FilterEvent(QWidget * /*keywidget*/, XEvent * /*event*/) |
|
465 { |
|
466 return false; |
|
467 } |
|
468 #endif // Q_WS_X11 |
|
469 |
|
470 #ifdef Q_OS_SYMBIAN |
|
471 /*! |
|
472 \since 4.6 |
|
473 |
|
474 This function may be overridden only if input method is depending |
|
475 on Symbian and you need raw Symbian events. Otherwise, this function must not. |
|
476 |
|
477 This function is designed to filter raw key events on Symbian, but |
|
478 other input methods may use this to implement some special |
|
479 features. |
|
480 |
|
481 Return true if the \a event has been consumed. Otherwise, the |
|
482 unfiltered \a event will be translated into QEvent and forwarded |
|
483 to filterEvent(). Filtering at both symbianFilterEvent() and |
|
484 filterEvent() in single input method is allowed. |
|
485 |
|
486 \a keywidget is a client widget into which a text is inputted. \a |
|
487 event is inputted QSymbianEvent. |
|
488 |
|
489 \sa filterEvent() |
|
490 */ |
|
491 bool QInputContext::symbianFilterEvent(QWidget * /*keywidget*/, const QSymbianEvent * /*event*/) |
|
492 { |
|
493 return false; |
|
494 } |
|
495 #endif // Q_OS_SYMBIAN |
|
496 |
|
497 QT_END_NAMESPACE |
|
498 |
|
499 #endif //Q_NO_IM |