Qt 4.8
qximinputcontext_x11.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/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 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 /****************************************************************************
43 **
44 ** Implementation of QXIMInputContext 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 #include "qplatformdefs.h"
57 #include "qdebug.h"
58 #include "qximinputcontext_p.h"
59 
60 #if !defined(QT_NO_IM)
61 
63 
64 #if !defined(QT_NO_XIM)
65 
67 #include "qplatformdefs.h"
68 
69 #include "qapplication.h"
70 #include "qwidget.h"
71 #include "qstring.h"
72 #include "qlist.h"
73 #include "qtextcodec.h"
74 #include "qevent.h"
75 #include "qtextformat.h"
76 
77 #include "qx11info_x11.h"
78 
79 #include <stdlib.h>
80 #include <limits.h>
82 
83 // #define QT_XIM_DEBUG
84 #ifdef QT_XIM_DEBUG
85 #define XIM_DEBUG qDebug
86 #else
87 #define XIM_DEBUG if (0) qDebug
88 #endif
89 
90 // from qapplication_x11.cpp
91 // #### move to X11 struct
92 extern XIMStyle qt_xim_preferred_style;
93 extern char *qt_ximServer;
94 extern int qt_ximComposingKeycode;
96 
97 XIMStyle QXIMInputContext::xim_style = 0;
98 // moved from qapplication_x11.cpp
99 static const XIMStyle xim_default_style = XIMPreeditCallbacks | XIMStatusNothing;
100 
101 
102 extern "C" {
103 #ifdef USE_X11R6_XIM
104  static void xim_create_callback(XIM /*im*/,
105  XPointer client_data,
106  XPointer /*call_data*/)
107  {
108  QXIMInputContext *qic = reinterpret_cast<QXIMInputContext *>(client_data);
109  // qDebug("xim_create_callback");
110  qic->create_xim();
111  }
112 
113  static void xim_destroy_callback(XIM /*im*/,
114  XPointer client_data,
115  XPointer /*call_data*/)
116  {
117  QXIMInputContext *qic = reinterpret_cast<QXIMInputContext *>(client_data);
118  // qDebug("xim_destroy_callback");
119  qic->close_xim();
120  XRegisterIMInstantiateCallback(X11->display, 0, 0, 0,
121  (XIMProc) xim_create_callback, reinterpret_cast<char *>(qic));
122  }
123 #endif // USE_X11R6_XIM
124 
125  static int xic_start_callback(XIC, XPointer client_data, XPointer) {
126  QXIMInputContext *qic = (QXIMInputContext *) client_data;
127  if (!qic) {
128  XIM_DEBUG("xic_start_callback: no qic");
129  return 0;
130  }
132  if (!data) {
133  XIM_DEBUG("xic_start_callback: no ic data");
134  return 0;
135  }
136  XIM_DEBUG("xic_start_callback");
137 
138  data->clear();
139  data->composing = true;
140 
141  return 0;
142  }
143 
144  static int xic_draw_callback(XIC, XPointer client_data, XPointer call_data) {
145  QXIMInputContext *qic = (QXIMInputContext *) client_data;
146  if (!qic) {
147  XIM_DEBUG("xic_draw_callback: no qic");
148  return 0;
149  }
151  if (!data) {
152  XIM_DEBUG("xic_draw_callback: no ic data");
153  return 0;
154  }
155  XIM_DEBUG("xic_draw_callback");
156 
157 
158  if(!data->composing) {
159  data->clear();
160  data->composing = true;
161  }
162 
163  XIMPreeditDrawCallbackStruct *drawstruct = (XIMPreeditDrawCallbackStruct *) call_data;
164  XIMText *text = (XIMText *) drawstruct->text;
165  int cursor = drawstruct->caret, sellen = 0, selstart = 0;
166 
167  if (!drawstruct->caret && !drawstruct->chg_first && !drawstruct->chg_length && !text) {
168  if(data->text.isEmpty()) {
169  XIM_DEBUG("compose emptied");
170  // if the composition string has been emptied, we need
171  // to send an InputMethodEnd event
173  qic->sendEvent(e);
174  data->clear();
175 
176  // if the commit string has coming after here, InputMethodStart
177  // will be sent dynamically
178  }
179  return 0;
180  }
181 
182  if (text) {
183  char *str = 0;
184  if (text->encoding_is_wchar) {
185  int l = wcstombs(NULL, text->string.wide_char, text->length);
186  if (l != -1) {
187  str = new char[l + 1];
188  wcstombs(str, text->string.wide_char, l);
189  str[l] = 0;
190  }
191  } else
192  str = text->string.multi_byte;
193 
194  if (!str)
195  return 0;
196 
198 
199  if (text->encoding_is_wchar)
200  delete [] str;
201 
202  if (drawstruct->chg_length < 0)
203  data->text.replace(drawstruct->chg_first, INT_MAX, s);
204  else
205  data->text.replace(drawstruct->chg_first, drawstruct->chg_length, s);
206 
207  if (data->selectedChars.size() < data->text.length()) {
208  // expand the selectedChars array if the compose string is longer
209  int from = data->selectedChars.size();
210  data->selectedChars.resize(data->text.length());
211  for (int x = from; x < data->selectedChars.size(); ++x)
212  data->selectedChars.clearBit(x);
213  }
214 
215  // determine if the changed chars are selected based on text->feedback
216  for (int x = 0; x < text->length; ++x)
217  data->selectedChars.setBit(x + drawstruct->chg_first,
218  (text->feedback ? (text->feedback[x] & XIMReverse) : 0));
219 
220  // figure out where the selection starts, and how long it is
221  bool started = false;
222  for (int x = 0; x < qMin(data->selectedChars.size(), data->text.length()); ++x) {
223  if (started) {
224  if (data->selectedChars.testBit(x)) ++sellen;
225  else break;
226  } else {
227  if (data->selectedChars.testBit(x)) {
228  selstart = x;
229  started = true;
230  sellen = 1;
231  }
232  }
233  }
234  } else {
235  if (drawstruct->chg_length == 0)
236  drawstruct->chg_length = -1;
237 
238  data->text.remove(drawstruct->chg_first, drawstruct->chg_length);
239  bool qt_compose_emptied = data->text.isEmpty();
240  if (qt_compose_emptied) {
241  XIM_DEBUG("compose emptied 2 text=%s", data->text.toUtf8().constData());
242  // if the composition string has been emptied, we need
243  // to send an InputMethodEnd event
245  qic->sendEvent(e);
246  data->clear();
247  // if the commit string has coming after here, InputMethodStart
248  // will be sent dynamically
249  return 0;
250  }
251  }
252 
253  XIM_DEBUG("sending compose: '%s', cursor=%d, sellen=%d",
254  data->text.toUtf8().constData(), cursor, sellen);
256  if (selstart > 0)
259  if (sellen)
262  if (selstart + sellen < data->text.length())
264  selstart + sellen, data->text.length() - selstart - sellen,
266  attrs << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, cursor, sellen ? 0 : 1, QVariant());
267  QInputMethodEvent e(data->text, attrs);
268  data->preeditEmpty = data->text.isEmpty();
269  qic->sendEvent(e);
270 
271  return 0;
272  }
273 
274  static int xic_done_callback(XIC, XPointer client_data, XPointer) {
275  QXIMInputContext *qic = (QXIMInputContext *) client_data;
276  if (!qic)
277  return 0;
278 
279  XIM_DEBUG("xic_done_callback");
280  // Don't send InputMethodEnd here. QXIMInputContext::x11FilterEvent()
281  // handles InputMethodEnd with commit string.
282  return 0;
283  }
284 }
285 
287 {
288  text = QString();
290  composing = false;
291  preeditEmpty = true;
292 }
293 
295 {
296  if (QWidget *w = focusWidget())
297  return ximData.value(w->effectiveWinId());
298  return 0;
299 }
300 /* The cache here is needed, as X11 leaks a few kb for every
301  XFreeFontSet call, so we avoid creating and deletion of fontsets as
302  much as possible
303 */
304 static XFontSet fontsetCache[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
305 static int fontsetRefCount = 0;
306 
307 static const char * const fontsetnames[] = {
308  "-*-fixed-medium-r-*-*-16-*,-*-*-medium-r-*-*-16-*",
309  "-*-fixed-medium-i-*-*-16-*,-*-*-medium-i-*-*-16-*",
310  "-*-fixed-bold-r-*-*-16-*,-*-*-bold-r-*-*-16-*",
311  "-*-fixed-bold-i-*-*-16-*,-*-*-bold-i-*-*-16-*",
312  "-*-fixed-medium-r-*-*-24-*,-*-*-medium-r-*-*-24-*",
313  "-*-fixed-medium-i-*-*-24-*,-*-*-medium-i-*-*-24-*",
314  "-*-fixed-bold-r-*-*-24-*,-*-*-bold-r-*-*-24-*",
315  "-*-fixed-bold-i-*-*-24-*,-*-*-bold-i-*-*-24-*"
316 };
317 
318 static XFontSet getFontSet(const QFont &f)
319 {
320  int i = 0;
321  if (f.italic())
322  i |= 1;
323  if (f.bold())
324  i |= 2;
325 
326  if (f.pointSize() > 20)
327  i += 4;
328 
329  if (!fontsetCache[i]) {
330  Display* dpy = X11->display;
331  int missCount;
332  char** missList;
333  fontsetCache[i] = XCreateFontSet(dpy, fontsetnames[i], &missList, &missCount, 0);
334  if(missCount > 0)
335  XFreeStringList(missList);
336  if (!fontsetCache[i]) {
337  fontsetCache[i] = XCreateFontSet(dpy, "-*-fixed-*-*-*-*-16-*", &missList, &missCount, 0);
338  if(missCount > 0)
339  XFreeStringList(missList);
340  if (!fontsetCache[i])
341  fontsetCache[i] = (XFontSet)-1;
342  }
343  }
344  return (fontsetCache[i] == (XFontSet)-1) ? 0 : fontsetCache[i];
345 }
346 
347 extern bool qt_use_rtl_extensions; // from qapplication_x11.cpp
348 #ifndef QT_NO_XKB
349 extern QLocale q_getKeyboardLocale(const QByteArray &layoutName, const QByteArray &variantName);
350 #endif
351 
353 {
354  if (!qt_xim_preferred_style) // no configured input style, use the default
356 
357  xim = 0;
358  QByteArray ximServerName(qt_ximServer);
359  if (qt_ximServer)
360  ximServerName.prepend("@im=");
361  else
362  ximServerName = "";
363 
364  if (!XSupportsLocale())
365 #ifndef QT_NO_DEBUG
366  qWarning("Qt: Locale not supported on X server")
367 #endif
368  ;
369 #ifdef USE_X11R6_XIM
370  else if (XSetLocaleModifiers (ximServerName.constData()) == 0)
371  qWarning("Qt: Cannot set locale modifiers: %s", ximServerName.constData());
372  else
373  XRegisterIMInstantiateCallback(X11->display, 0, 0, 0,
374  (XIMProc) xim_create_callback, reinterpret_cast<char *>(this));
375 #else // !USE_X11R6_XIM
376  else if (XSetLocaleModifiers ("") == 0)
377  qWarning("Qt: Cannot set locale modifiers");
378  else
380 #endif // USE_X11R6_XIM
381 
382 #ifndef QT_NO_XKB
383  if (X11->use_xkb) {
384  QByteArray layoutName;
385  QByteArray variantName;
386 
387  Atom type = XNone;
388  int format = 0;
389  ulong nitems = 0;
390  ulong bytesAfter = 0;
391  uchar *data = 0;
392  if (XGetWindowProperty(X11->display, RootWindow(X11->display, 0), ATOM(_XKB_RULES_NAMES), 0, 1024,
393  false, XA_STRING, &type, &format, &nitems, &bytesAfter, &data) == Success
394  && type == XA_STRING && format == 8 && nitems > 2) {
395 
396  char *names[5] = { 0, 0, 0, 0, 0 };
397  char *p = reinterpret_cast<char *>(data), *end = p + nitems;
398  int i = 0;
399  do {
400  names[i++] = p;
401  p += qstrlen(p) + 1;
402  } while (p < end);
403 
404  QList<QByteArray> layoutNames = QByteArray::fromRawData(names[2], qstrlen(names[2])).split(',');
405  QList<QByteArray> variantNames = QByteArray::fromRawData(names[3], qstrlen(names[3])).split(',');
406  for (int i = 0; i < qMin(layoutNames.count(), variantNames.count()); ++i ) {
407  QByteArray variantName = variantNames.at(i);
408  const int dashPos = variantName.indexOf("-");
409  if (dashPos >= 0)
410  variantName.truncate(dashPos);
411  QLocale keyboardInputLocale = q_getKeyboardLocale(layoutNames.at(i), variantName);
412  if (keyboardInputLocale.textDirection() == Qt::RightToLeft)
413  qt_use_rtl_extensions = true;
414  }
415  }
416 
417  if (data)
418  XFree(data);
419  }
420 #endif // QT_NO_XKB
421 
422 }
423 
424 
429 {
430  ++fontsetRefCount;
431 #ifndef QT_NO_XIM
432  xim = XOpenIM(X11->display, 0, 0, 0);
433  if (xim) {
434 
435 #ifdef USE_X11R6_XIM
436  XIMCallback destroy;
437  destroy.callback = (XIMProc) xim_destroy_callback;
438  destroy.client_data = XPointer(this);
439  if (XSetIMValues(xim, XNDestroyCallback, &destroy, (char *) 0) != 0)
440  qWarning("Xlib doesn't support destroy callback");
441 #endif // USE_X11R6_XIM
442 
443  XIMStyles *styles = 0;
444  XGetIMValues(xim, XNQueryInputStyle, &styles, (char *) 0, (char *) 0);
445  if (styles) {
446  int i;
447  for (i = 0; !xim_style && i < styles->count_styles; i++) {
448  if (styles->supported_styles[i] == qt_xim_preferred_style) {
450  break;
451  }
452  }
453  // if the preferred input style couldn't be found, look for
454  // Nothing
455  for (i = 0; !xim_style && i < styles->count_styles; i++) {
456  if (styles->supported_styles[i] == (XIMPreeditNothing | XIMStatusNothing)) {
457  xim_style = XIMPreeditNothing | XIMStatusNothing;
458  break;
459  }
460  }
461  // ... and failing that, None.
462  for (i = 0; !xim_style && i < styles->count_styles; i++) {
463  if (styles->supported_styles[i] == (XIMPreeditNone |
464  XIMStatusNone)) {
465  xim_style = XIMPreeditNone | XIMStatusNone;
466  break;
467  }
468  }
469 
470  // qDebug("QApplication: using im style %lx", xim_style);
471  XFree((char *)styles);
472  }
473 
474  if (xim_style) {
475 
476 #ifdef USE_X11R6_XIM
477  XUnregisterIMInstantiateCallback(X11->display, 0, 0, 0,
478  (XIMProc) xim_create_callback, reinterpret_cast<char *>(this));
479 #endif // USE_X11R6_XIM
480 
482  // reinitialize input context after the input method
483  // server (like SCIM) has been launched without
484  // requiring the user to manually switch focus.
487  && focusWidget->isEnabled())
489  }
490  // following code fragment is not required for immodule
491  // version of XIM
492 #if 0
493  QWidgetList list = qApp->topLevelWidgets();
494  for (int i = 0; i < list.size(); ++i) {
495  QWidget *w = list.at(i);
496  w->d->createTLSysExtra();
497  }
498 #endif
499  } else {
500  // Give up
501  qWarning("No supported input style found."
502  " See InputMethod documentation.");
503  close_xim();
504  }
505  }
506 #endif // QT_NO_XIM
507 }
508 
513 {
514  for(QHash<WId, ICData *>::const_iterator i = ximData.constBegin(),
515  e = ximData.constEnd(); i != e; ++i) {
516  ICData *data = i.value();
517  if (data->ic)
518  XDestroyIC(data->ic);
519  delete data;
520  }
521  ximData.clear();
522 
523  if ( --fontsetRefCount == 0 ) {
524  Display *dpy = X11->display;
525  for ( int i = 0; i < 8; i++ ) {
526  if ( fontsetCache[i] && fontsetCache[i] != (XFontSet)-1 ) {
527  XFreeFontSet(dpy, fontsetCache[i]);
528  fontsetCache[i] = 0;
529  }
530  }
531  }
532 
533  setFocusWidget(0);
534  xim = 0;
535 }
536 
537 
538 
540 {
541  XIM old_xim = xim; // close_xim clears xim pointer.
542  close_xim();
543  if (old_xim)
544  XCloseIM(old_xim);
545 }
546 
547 
549 {
550  // the name should be "xim" rather than "XIM" to be consistent
551  // with corresponding immodule of GTK+
552  return QLatin1String("xim");
553 }
554 
555 
557 {
559  if (xim) {
560  QByteArray locale(XLocaleOfIM(xim));
561 
562  if (locale.startsWith("zh")) {
563  // Chinese language should be formed as "zh_CN", "zh_TW", "zh_HK"
564  language = QLatin1String(locale.left(5));
565  } else {
566  // other languages should be two-letter ISO 639 language code
567  language = QLatin1String(locale.left(2));
568  }
569  }
570  return language;
571 }
572 
574 {
575  QWidget *w = focusWidget();
576  if (!w)
577  return;
578 
579  ICData *data = ximData.value(w->effectiveWinId());
580  if (!data)
581  return;
582 
583  if (data->ic) {
584  char *mb = XmbResetIC(data->ic);
586  if (mb) {
588  XFree(mb);
589  data->preeditEmpty = false; // force sending an event
590  }
591  if (!data->preeditEmpty) {
592  sendEvent(e);
593  update();
594  }
595  }
596  data->clear();
597 }
598 
600 {
602  ICData *data = ximData.take(w->effectiveWinId());
603  if (!data)
604  return;
605 
606  data->clear();
607  if (data->ic)
608  XDestroyIC(data->ic);
609  delete data;
610 }
611 
613 {
614  if(e->type() != QEvent::MouseButtonPress)
615  return;
616 
617  XIM_DEBUG("QXIMInputContext::mouseHandler pos=%d", pos);
618  if (QWidget *w = focusWidget()) {
619  ICData *data = ximData.value(w->effectiveWinId());
620  if (!data)
621  return;
622  if (pos < 0 || pos > data->text.length())
623  reset();
624  // ##### handle mouse position
625  }
626 }
627 
629 {
630  QWidget *w = focusWidget();
631  if (!w)
632  return false;
633 
634  ICData *data = ximData.value(w->effectiveWinId());
635  if (!data)
636  return false;
637  return data->composing;
638 }
639 
641 {
642  if (!xim)
643  return;
644  QWidget *oldFocus = focusWidget();
645  if (oldFocus == w)
646  return;
647 
648  if (language() != QLatin1String("ja"))
649  reset();
650 
651  if (oldFocus) {
652  ICData *data = ximData.value(oldFocus->effectiveWinId());
653  if (data && data->ic)
654  XUnsetICFocus(data->ic);
655  }
656 
658 
660  return;
661 
662  ICData *data = ximData.value(w->effectiveWinId());
663  if (!data)
664  data = createICData(w);
665 
666  if (data->ic)
667  XSetICFocus(data->ic);
668 
669  update();
670 }
671 
672 
674 {
675  int xkey_keycode = event->xkey.keycode;
676  if (!keywidget->testAttribute(Qt::WA_WState_Created))
677  return false;
678  if (XFilterEvent(event, keywidget->effectiveWinId())) {
679  qt_ximComposingKeycode = xkey_keycode; // ### not documented in xlib
680 
681  update();
682 
683  return true;
684  }
685  if (event->type != XKeyPress || event->xkey.keycode != 0)
686  return false;
687 
688  QWidget *w = focusWidget();
689  if (keywidget != w)
690  return false;
691  ICData *data = ximData.value(w->effectiveWinId());
692  if (!data)
693  return false;
694 
695  // input method has sent us a commit string
696  QByteArray string;
697  string.resize(513);
698  KeySym key; // unused
699  Status status; // unused
700  QString text;
701  int count = XmbLookupString(data->ic, &event->xkey, string.data(), string.size(),
702  &key, &status);
703 
704  if (status == XBufferOverflow) {
705  string.resize(count + 1);
706  count = XmbLookupString(data->ic, &event->xkey, string.data(), string.size(),
707  &key, &status);
708  }
709  if (count > 0) {
710  // XmbLookupString() gave us some text, convert it to unicode
711  text = qt_input_mapper->toUnicode(string.constData() , count);
712  if (text.isEmpty()) {
713  // codec couldn't convert to unicode? this can happen when running in the
714  // C locale (or with no LANG set). try converting from latin-1
715  text = QString::fromLatin1(string.constData(), count);
716  }
717  }
718 
719 #if 0
720  if (!(xim_style & XIMPreeditCallbacks) || !isComposing()) {
721  // ############### send a regular key event here!
722  ;
723  }
724 #endif
725 
727  e.setCommitString(text);
728  sendEvent(e);
729  data->clear();
730 
731  update();
732 
733  return true;
734 }
735 
736 
738 {
739  ICData *data = new ICData;
740  data->widget = w;
741  data->preeditEmpty = true;
742 
743  XVaNestedList preedit_attr = 0;
744  XIMCallback startcallback, drawcallback, donecallback;
745 
746  QFont font = w->font();
747  data->fontset = getFontSet(font);
748 
749  if (xim_style & XIMPreeditArea) {
750  XRectangle rect;
751  rect.x = 0;
752  rect.y = 0;
753  rect.width = w->width();
754  rect.height = w->height();
755 
756  preedit_attr = XVaCreateNestedList(0,
757  XNArea, &rect,
758  XNFontSet, data->fontset,
759  (char *) 0);
760  } else if (xim_style & XIMPreeditPosition) {
761  XPoint spot;
762  spot.x = 1;
763  spot.y = 1;
764 
765  preedit_attr = XVaCreateNestedList(0,
766  XNSpotLocation, &spot,
767  XNFontSet, data->fontset,
768  (char *) 0);
769  } else if (xim_style & XIMPreeditCallbacks) {
770  startcallback.client_data = (XPointer) this;
771  startcallback.callback = (XIMProc) xic_start_callback;
772  drawcallback.client_data = (XPointer) this;
773  drawcallback.callback = (XIMProc)xic_draw_callback;
774  donecallback.client_data = (XPointer) this;
775  donecallback.callback = (XIMProc) xic_done_callback;
776 
777  preedit_attr = XVaCreateNestedList(0,
778  XNPreeditStartCallback, &startcallback,
779  XNPreeditDrawCallback, &drawcallback,
780  XNPreeditDoneCallback, &donecallback,
781  (char *) 0);
782  }
783 
784  if (preedit_attr) {
785  data->ic = XCreateIC(xim,
786  XNInputStyle, xim_style,
787  XNClientWindow, w->effectiveWinId(),
788  XNPreeditAttributes, preedit_attr,
789  (char *) 0);
790  XFree(preedit_attr);
791  } else {
792  data->ic = XCreateIC(xim,
793  XNInputStyle, xim_style,
794  XNClientWindow, w->effectiveWinId(),
795  (char *) 0);
796  }
797 
798  if (data->ic) {
799  // when resetting the input context, preserve the input state
800  (void) XSetICValues(data->ic, XNResetState, XIMPreserveState, (char *) 0);
801  } else {
802  qWarning("Failed to create XIC");
803  }
804 
805  ximData[w->effectiveWinId()] = data;
806  return data;
807 }
808 
810 {
811  QWidget *w = focusWidget();
812  if (!w)
813  return;
814 
815  ICData *data = ximData.value(w->effectiveWinId());
816  if (!data || !data->ic)
817  return;
818 
820  QPoint p;
821  if (w->nativeParentWidget())
822  p = w->mapTo(w->nativeParentWidget(), QPoint((r.left() + r.right() + 1)/2, r.bottom()));
823  else
824  p = QPoint((r.left() + r.right() + 1)/2, r.bottom());
825  XPoint spot;
826  spot.x = p.x();
827  spot.y = p.y();
828 
829  r = w->rect();
830  XRectangle area;
831  area.x = r.x();
832  area.y = r.y();
833  area.width = r.width();
834  area.height = r.height();
835 
836  XFontSet fontset = getFontSet(qvariant_cast<QFont>(w->inputMethodQuery(Qt::ImFont)));
837  if (data->fontset == fontset)
838  fontset = 0;
839  else
840  data->fontset = fontset;
841 
842  XVaNestedList preedit_attr;
843  if (fontset)
844  preedit_attr = XVaCreateNestedList(0,
845  XNSpotLocation, &spot,
846  XNArea, &area,
847  XNFontSet, fontset,
848  (char *) 0);
849  else
850  preedit_attr = XVaCreateNestedList(0,
851  XNSpotLocation, &spot,
852  XNArea, &area,
853  (char *) 0);
854 
855  XSetICValues(data->ic, XNPreeditAttributes, preedit_attr, (char *) 0);
856  XFree(preedit_attr);
857 }
858 
859 
860 #else
861 /*
862  When QT_NO_XIM is defined, we provide a dummy implementation for
863  this class. The reason for this is that the header file is moc'ed
864  regardless of QT_NO_XIM. The best would be to remove the file
865  completely from the pri file is QT_NO_XIM was defined, or for moc
866  to understand this preprocessor directive. Since the header does
867  not declare this class when QT_NO_XIM is defined, this is dead
868  code.
869 */
870 bool QXIMInputContext::isComposing() const { return false; }
874 void QXIMInputContext::reset() {}
875 void QXIMInputContext::update() {}
879 bool QXIMInputContext::x11FilterEvent(QWidget *, XEvent *) { return true; }
880 
881 #endif //QT_NO_XIM
882 
884 
885 #endif //QT_NO_IM
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
void clear()
Clears the contents of the bit array and makes it empty.
Definition: qbitarray.h:85
Qt::LayoutDirection textDirection() const
Returns the text direction of the language.
Definition: qlocale.cpp:2286
The QHash::const_iterator class provides an STL-style const iterator for QHash and QMultiHash...
Definition: qhash.h:395
static QString fromLocal8Bit(const char *, int size=-1)
Returns a QString initialized with the first size characters of the 8-bit string str.
Definition: qstring.cpp:4245
int type
Definition: qmetatype.cpp:239
void truncate(int pos)
Truncates the byte array at index position pos.
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
void setBit(int i)
Sets the bit at index position i to 1.
Definition: qbitarray.h:128
static const char *const fontsetnames[]
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
The QInputMethodEvent::Attribute class stores an input method attribute.
Definition: qevent.h:441
int width
the width of the widget excluding any window frame
Definition: qwidget.h:166
Bool XRegisterIMInstantiateCallback(Display *, struct _XrmHashBucketRec *, char *, char *, XIMProc, XPointer)
QPoint mapTo(QWidget *, const QPoint &) const
Translates the widget coordinate pos to the coordinate system of parent.
Definition: qwidget.cpp:4409
XIMStyle qt_xim_preferred_style
void reset()
This function can be reimplemented in a subclass to reset the state of the input method.
WId effectiveWinId() const
Returns the effective window system identifier of the widget, i.
Definition: qwidget.cpp:2654
QByteArray toUtf8() const Q_REQUIRED_RESULT
Returns a UTF-8 representation of the string as a QByteArray.
Definition: qstring.cpp:4074
void mouseHandler(int x, QMouseEvent *event)
This function can be reimplemented in a subclass to handle mouse press, release, double-click, and move events within the preedit text.
static int xic_start_callback(XIC, XPointer client_data, XPointer)
QString & replace(int i, int len, QChar after)
Definition: qstring.cpp:2005
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
QFont font
the font currently set for the widget
Definition: qwidget.h:181
char * qt_ximServer
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:150
void setCommitString(const QString &commitString, int replaceFrom=0, int replaceLength=0)
Sets the commit string to commitString.
Definition: qevent.cpp:2042
int left() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:240
int width() const
Returns the width of the rectangle.
Definition: qrect.h:303
static LibLoadStatus status
Definition: qlocale_icu.cpp:69
#define QT_END_INCLUDE_NAMESPACE
This macro is equivalent to QT_BEGIN_NAMESPACE.
Definition: qglobal.h:92
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
virtual QVariant inputMethodQuery(Qt::InputMethodQuery) const
This method is only relevant for input widgets.
Definition: qwidget.cpp:9683
QByteArray & prepend(char c)
Prepends the character ch to this byte array.
int height() const
Returns the height of the rectangle.
Definition: qrect.h:306
QWidget * focusWidget() const
Returns the widget that has an input focus for this input context.
int bottom() const
Returns the y-coordinate of the rectangle&#39;s bottom edge.
Definition: qrect.h:249
The QString class provides a Unicode character string.
Definition: qstring.h:83
QLocale q_getKeyboardLocale(const QByteArray &layoutName, const QByteArray &variantName)
bool testBit(int i) const
Returns true if the bit at index position i is 1; otherwise returns false.
Definition: qbitarray.h:124
bool startsWith(const QByteArray &a) const
Returns true if this byte array starts with byte array ba; otherwise returns false.
virtual bool event(QEvent *)
This virtual function receives events to an object and should return true if the event e was recogniz...
Definition: qobject.cpp:1200
#define X11
Definition: qt_x11_p.h:724
bool qt_use_rtl_extensions
static const XIMStyle xim_default_style
union _XEvent XEvent
Definition: qwindowdefs.h:116
static int xic_draw_callback(XIC, XPointer client_data, XPointer call_data)
#define ATOM(x)
Definition: qt_x11_p.h:723
static XFontSet fontsetCache[8]
unsigned char uchar
Definition: qglobal.h:994
bool x11FilterEvent(QWidget *keywidget, XEvent *event)
This function may be overridden only if input method is depending on X11 and you need raw XEvent...
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
QWidget * nativeParentWidget() const
Returns the native parent for this widget, i.
Definition: qwidget.cpp:4514
virtual void widgetDestroyed(QWidget *w)
This virtual function is called when the specified widget is destroyed.
#define XSetIMValues
Definition: qt_x11_p.h:69
int height
the height of the widget excluding any window frame
Definition: qwidget.h:167
bool testAttribute(Qt::WidgetAttribute) const
Returns true if attribute attribute is set on this widget; otherwise returns false.
Definition: qwidget.h:1041
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
#define qApp
QTextCodec * qt_input_mapper
QTextFormat standardFormat(StandardFormat s) const
Returns a QTextFormat object that specifies the format for component s.
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
static QByteArray fromRawData(const char *, int size)
Constructs a QByteArray that uses the first size bytes of the data array.
QString language()
This function must be implemented in any subclasses to return a language code (e. ...
void resize(int size)
Resizes the bit array to size bits.
Definition: qbitarray.cpp:214
Q_CORE_EXPORT void qWarning(const char *,...)
void widgetDestroyed(QWidget *w)
This virtual function is called when the specified widget is destroyed.
static const char * data(const QByteArray &arr)
ICData * createICData(QWidget *w)
QByteArray left(int len) const
Returns a byte array that contains the leftmost len bytes of this byte array.
unsigned long ulong
Definition: qglobal.h:997
int indexOf(char c, int from=0) const
Returns the index position of the first occurrence of the character ch in the byte array...
virtual QFont font() const
Returns the font of the current input widget.
bool isComposing() const
This function indicates whether InputMethodStart event had been sent to the current focus widget...
bool isEnabled() const
Definition: qwidget.h:948
The QMouseEvent class contains parameters that describe a mouse event.
Definition: qevent.h:85
char * XPointer
Definition: qt_x11_p.h:180
void resize(int size)
Sets the size of the string to size characters.
Definition: qstring.cpp:1353
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
The QInputMethodEvent class provides parameters for input method events.
Definition: qevent.h:431
QString toUnicode(const QByteArray &) const
Converts a from the encoding of this codec to Unicode, and returns the result in a QString...
bool bold() const
Returns true if weight() is a value greater than QFont::Normal ; otherwise returns false...
Definition: qfont.h:348
QList< QByteArray > split(char sep) const
Splits the byte array into subarrays wherever sep occurs, and returns the list of those arrays...
uint qstrlen(const char *str)
Definition: qbytearray.h:79
struct _XDisplay Display
Definition: qwindowdefs.h:115
int right() const
Returns the x-coordinate of the rectangle&#39;s right edge.
Definition: qrect.h:246
QHash< WId, ICData * > ximData
QRect rect
the internal geometry of the widget excluding any window frame
Definition: qwidget.h:168
The QFont class specifies a font used for drawing text.
Definition: qfont.h:64
int y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:255
static int fontsetRefCount
QRect toRect() const
Returns the variant as a QRect if the variant has type() Rect ; otherwise returns an invalid QRect...
Definition: qvariant.cpp:2416
static QString fromLatin1(const char *, int size=-1)
Returns a QString initialized with the first size characters of the Latin-1 string str...
Definition: qstring.cpp:4188
void sendEvent(const QInputMethodEvent &event)
Sends an input method event specified by event to the current focus widget.
int x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:252
int key
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:53
void resize(int size)
Sets the size of the byte array to size bytes.
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
if(void) toggleToolbarShown
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
QFactoryLoader * l
int y() const
Returns the y coordinate of this point.
Definition: qpoint.h:131
static int xic_done_callback(XIC, XPointer client_data, XPointer)
#define QT_BEGIN_INCLUDE_NAMESPACE
This macro is equivalent to QT_END_NAMESPACE.
Definition: qglobal.h:91
#define XIM_DEBUG
bool italic() const
Returns true if the style() of the font is not QFont::StyleNormal.
Definition: qfont.h:355
int pointSize() const
Returns the point size of the font.
Definition: qfont.cpp:981
int x() const
Returns the x coordinate of this point.
Definition: qpoint.h:128
static XFontSet getFontSet(const QFont &f)
void setFocusWidget(QWidget *w)
Sets the widget that has an input focus for this input context.
QString & remove(int i, int len)
Removes n characters from the string, starting at the given position index, and returns a reference t...
Definition: qstring.cpp:1867
The QTextCodec class provides conversions between text encodings.
Definition: qtextcodec.h:62
QString identifierName()
This function must be implemented in any subclasses to return the identifier name of the input method...
Qt::InputMethodHints inputMethodHints
What input method specific hints the widget has.
Definition: qwidget.h:224
static const KeyPair *const end
virtual void setFocusWidget(QWidget *w)
Sets the widget that has an input focus for this input context.
void update()
This virtual function is called when a state in the focus widget has changed.
Type type() const
Returns the event type.
Definition: qcoreevent.h:303
static QWidget * focusWidget()
Returns the application widget that has the keyboard input focus, or 0 if no widget in this applicati...
#define Status
Definition: qcursor_x11.cpp:59
int size() const
Returns the number of bits stored in the bit array.
Definition: qbitarray.h:73
void clearBit(int i)
Sets the bit at index position i to 0.
Definition: qbitarray.h:132
#define INT_MAX
int qt_ximComposingKeycode
Bool XUnregisterIMInstantiateCallback(Display *, struct _XrmHashBucketRec *, char *, char *, XIMProc, XPointer)
#define text
Definition: qobjectdefs.h:80
static int area(const QSize &s)
Definition: qicon.cpp:155
static XIMStyle xim_style
ICData * icData() const