Qt 4.8
qmacinputcontext_mac.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 #include <qconfig.h>
42 #include <qglobal.h>
43 #ifndef QT_NO_IM
44 #include <qvarlengtharray.h>
45 #include <qwidget.h>
46 #include <private/qmacinputcontext_p.h>
47 #include "qtextformat.h"
48 #include <qdebug.h>
49 #include <private/qapplication_p.h>
50 #include <private/qkeymapper_p.h>
51 
53 
54 extern bool qt_sendSpontaneousEvent(QObject*, QEvent*);
55 
56 #if (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5)
57 # define typeRefCon typeSInt32
58 # define typeByteCount typeSInt32
59 #endif
60 
62  : QInputContext(parent), composing(false), recursionGuard(false), textDocument(0),
63  keydownEvent(0), lastFocusWid(0)
64 {
65 // createTextDocument();
66 }
67 
69 {
70 #ifndef QT_MAC_USE_COCOA
71  if(textDocument)
72  DeleteTSMDocument(textDocument);
73 #endif
74 }
75 
76 void
78 {
79 #ifndef QT_MAC_USE_COCOA
80  if(!textDocument) {
81  InterfaceTypeList itl = { kUnicodeDocument };
82  NewTSMDocument(1, itl, &textDocument, SRefCon(this));
83  }
84 #endif
85 }
86 
87 
89 {
90  return QString();
91 }
92 
93 
95 {
96 #ifndef QT_MAC_USE_COCOA
97  if(e->type() != QEvent::MouseButtonPress)
98  return;
99 
100  if (!composing)
101  return;
102  if (pos < 0 || pos > currentText.length())
103  reset();
104  // ##### handle mouse position
105 #else
106  Q_UNUSED(pos);
107  Q_UNUSED(e);
108 #endif
109 }
110 
111 #if !defined QT_MAC_USE_COCOA
112 
114 {
115  QTextCharFormat ret;
116  ret.setFontUnderline(true);
117  return ret;
118 }
119 
121 {
122  if (recursionGuard)
123  return;
124  if (!currentText.isEmpty()){
128  currentText = QString();
129  }
130  recursionGuard = true;
132  composing = false;
133  ActivateTSMDocument(textDocument);
134  FixTSMDocument(textDocument);
135  recursionGuard = false;
136 }
137 
139 {
140  return composing;
141 }
142 #endif
143 
145 {
146  if (!w)
149 #ifndef QT_MAC_USE_COCOA
150  if(w)
151  ActivateTSMDocument(textDocument);
152  else
153  DeactivateTSMDocument(textDocument);
154 #endif
156 }
157 
158 
159 #ifndef QT_MAC_USE_COCOA
160 static EventTypeSpec input_events[] = {
161  { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent },
162  { kEventClassTextInput, kEventTextInputOffsetToPos },
163  { kEventClassTextInput, kEventTextInputUpdateActiveInputArea }
164 };
165 static EventHandlerUPP input_proc_handlerUPP = 0;
166 static EventHandlerRef input_proc_handler = 0;
167 #endif
168 
169 void
171 {
172 #ifndef QT_MAC_USE_COCOA
173  if(!input_proc_handler) {
175  InstallEventHandler(GetApplicationEventTarget(), input_proc_handlerUPP,
176  GetEventTypeCount(input_events), input_events,
177  0, &input_proc_handler);
178  }
179 #endif
180 }
181 
182 void
184 {
185 #ifndef QT_MAC_USE_COCOA
186  if(input_proc_handler) {
187  RemoveEventHandler(input_proc_handler);
188  input_proc_handler = 0;
189  }
191  DisposeEventHandlerUPP(input_proc_handlerUPP);
193  }
194 #endif
195 }
196 
198 {
199  EventRef tmpEvent = keydownEvent;
201  if (keydownEvent)
202  RetainEvent(keydownEvent);
203  if (tmpEvent)
204  ReleaseEvent(tmpEvent);
205 }
206 
207 OSStatus
209 {
210 #ifndef QT_MAC_USE_COCOA
211  QScopedLoopLevelCounter loopLevelCounter(QApplicationPrivate::instance()->threadData);
212 
213  SRefCon refcon = 0;
214  GetEventParameter(event, kEventParamTextInputSendRefCon, typeRefCon, 0,
215  sizeof(refcon), 0, &refcon);
216  QMacInputContext *context = reinterpret_cast<QMacInputContext*>(refcon);
217 
218  bool handled_event=true;
219  UInt32 ekind = GetEventKind(event), eclass = GetEventClass(event);
220  switch(eclass) {
221  case kEventClassTextInput: {
222  handled_event = false;
224  bool canCompose = widget && (!context || widget->inputContext() == context)
225  && !(widget->inputMethodHints() & Qt::ImhDigitsOnly
227  || widget->inputMethodHints() & Qt::ImhHiddenText);
228  if(!canCompose) {
229  handled_event = false;
230  } else if(ekind == kEventTextInputOffsetToPos) {
232  handled_event = false;
233  break;
234  }
235 
237  QPoint mp(widget->mapToGlobal(QPoint(mr.topLeft())));
238  Point pt;
239  pt.h = mp.x();
240  pt.v = mp.y() + mr.height();
241  SetEventParameter(event, kEventParamTextInputReplyPoint, typeQDPoint,
242  sizeof(pt), &pt);
243  handled_event = true;
244  } else if(ekind == kEventTextInputUpdateActiveInputArea) {
246  handled_event = false;
247  break;
248  }
249 
250  if (context->recursionGuard)
251  break;
252 
253  ByteCount unilen = 0;
254  GetEventParameter(event, kEventParamTextInputSendText, typeUnicodeText,
255  0, 0, &unilen, 0);
256  UniChar *unicode = (UniChar*)NewPtr(unilen);
257  GetEventParameter(event, kEventParamTextInputSendText, typeUnicodeText,
258  0, unilen, 0, unicode);
259  QString text((QChar*)unicode, unilen / sizeof(UniChar));
260  DisposePtr((char*)unicode);
261 
262  ByteCount fixed_length = 0;
263  GetEventParameter(event, kEventParamTextInputSendFixLen, typeByteCount, 0,
264  sizeof(fixed_length), 0, &fixed_length);
265  if(fixed_length == ULONG_MAX || fixed_length == unilen) {
267  e.setCommitString(text);
268  context->currentText = QString();
269  qt_sendSpontaneousEvent(context->focusWidget(), &e);
270  handled_event = true;
271  context->reset();
272  } else {
273  ByteCount rngSize = 0;
274  OSStatus err = GetEventParameter(event, kEventParamTextInputSendHiliteRng, typeTextRangeArray, 0,
275  0, &rngSize, 0);
276  QVarLengthArray<TextRangeArray> highlight(rngSize);
277  if (noErr == err) {
278  err = GetEventParameter(event, kEventParamTextInputSendHiliteRng, typeTextRangeArray, 0,
279  rngSize, &rngSize, highlight.data());
280  }
281  context->composing = true;
282  if(fixed_length > 0) {
283  const int qFixedLength = fixed_length / sizeof(UniChar);
286  qFixedLength, text.length()-qFixedLength,
288  QInputMethodEvent e(text, attrs);
289  context->currentText = text;
290  e.setCommitString(text.left(qFixedLength), 0, qFixedLength);
291  qt_sendSpontaneousEvent(widget, &e);
292  handled_event = true;
293  } else {
294  /* Apple's enums that they have removed from Tiger :(
295  enum {
296  kCaretPosition = 1,
297  kRawText = 2,
298  kSelectedRawText = 3,
299  kConvertedText = 4,
300  kSelectedConvertedText = 5,
301  kBlockFillText = 6,
302  kOutlineText = 7,
303  kSelectedText = 8
304  };
305  */
306 #ifndef kConvertedText
307 #define kConvertedText 4
308 #endif
309 #ifndef kCaretPosition
310 #define kCaretPosition 1
311 #endif
313  if (!highlight.isEmpty()) {
314  TextRangeArray *data = highlight.data();
315  for (int i = 0; i < data->fNumOfRanges; ++i) {
316  int start = data->fRange[i].fStart / sizeof(UniChar);
317  int len = (data->fRange[i].fEnd - data->fRange[i].fStart) / sizeof(UniChar);
318  if (data->fRange[i].fHiliteStyle == kCaretPosition) {
320  continue;
321  }
323  format.setFontUnderline(true);
324  if (data->fRange[i].fHiliteStyle == kConvertedText)
325  format.setUnderlineColor(Qt::gray);
326  else
328  attrs << QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, start, len, format);
329  }
330  } else {
332  0, text.length(), qt_mac_compose_format());
333  }
334  context->currentText = text;
335  QInputMethodEvent e(text, attrs);
336  qt_sendSpontaneousEvent(widget, &e);
337  handled_event = true;
338  }
339  }
340 #if 0
341  if(!context->composing)
342  handled_event = false;
343 #endif
344 
345  extern bool qt_mac_eat_unicode_key; //qapplication_mac.cpp
346  qt_mac_eat_unicode_key = handled_event;
347  } else if(ekind == kEventTextInputUnicodeForKeyEvent) {
348  EventRef key_ev = 0;
349  GetEventParameter(event, kEventParamTextInputSendKeyboardEvent, typeEventRef, 0,
350  sizeof(key_ev), 0, &key_ev);
351  QString text;
352  ByteCount unilen = 0;
353  if(GetEventParameter(key_ev, kEventParamKeyUnicodes, typeUnicodeText, 0, 0, &unilen, 0) == noErr) {
354  UniChar *unicode = (UniChar*)NewPtr(unilen);
355  GetEventParameter(key_ev, kEventParamKeyUnicodes, typeUnicodeText, 0, unilen, 0, unicode);
356  text = QString((QChar*)unicode, unilen / sizeof(UniChar));
357  DisposePtr((char*)unicode);
358  }
359  unsigned char chr = 0;
360  GetEventParameter(key_ev, kEventParamKeyMacCharCodes, typeChar, 0, sizeof(chr), 0, &chr);
361  if(!chr || chr >= 128 || (text.length() > 0 && (text.length() > 1 || text.at(0) != QLatin1Char(chr))))
362  handled_event = !widget->testAttribute(Qt::WA_InputMethodEnabled);
363  QMacInputContext *context = qobject_cast<QMacInputContext*>(qApp->inputContext());
364  if (context && context->lastKeydownEvent()) {
366  0, false);
367  context->setLastKeydownEvent(0);
368  }
369  }
370  break; }
371  default:
372  break;
373  }
374  if(!handled_event) //let the event go through
375  return eventNotHandledErr;
376 #else
377  Q_UNUSED(event);
378 #endif
379  return noErr; //we eat the event
380 }
381 
383 #endif // QT_NO_IM
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
virtual bool isComposing() const
This function indicates whether InputMethodStart event had been sent to the current focus widget...
virtual void setFocusWidget(QWidget *w)
Sets the widget that has an input focus for this input context.
The QTextCharFormat class provides formatting information for characters in a QTextDocument.
Definition: qtextformat.h:372
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
QPointer< QWidget > widget
The QInputMethodEvent::Attribute class stores an input method attribute.
Definition: qevent.h:441
const QChar at(int i) const
Returns the character at the given index position in the string.
Definition: qstring.h:698
TSMDocumentID textDocument
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
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
static QApplicationPrivate * instance()
virtual QVariant inputMethodQuery(Qt::InputMethodQuery) const
This method is only relevant for input widgets.
Definition: qwidget.cpp:9683
QWidget * focusWidget() const
Returns the widget that has an input focus for this input context.
The QString class provides a Unicode character string.
Definition: qstring.h:83
T * qobject_cast(QObject *object)
Definition: qobject.h:375
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
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
The QChar class provides a 16-bit Unicode character.
Definition: qchar.h:72
bool qt_mac_eat_unicode_key
static QWidget * focus_widget
QMacInputContext(QObject *parent=0)
virtual void reset()
This function can be reimplemented in a subclass to reset the state of the input method.
#define kCaretPosition
#define kConvertedText
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
static EventTypeSpec input_events[]
QString left(int n) const Q_REQUIRED_RESULT
Returns a substring that contains the n leftmost characters of the string.
Definition: qstring.cpp:3664
bool testAttribute(Qt::WidgetAttribute) const
Returns true if attribute attribute is set on this widget; otherwise returns false.
Definition: qwidget.h:1041
static EventHandlerRef input_proc_handler
The QTextFormat class provides formatting information for a QTextDocument.
Definition: qtextformat.h:129
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
#define qApp
static OSStatus globalEventProcessor(EventHandlerCallRef, EventRef, void *)
static const char * data(const QByteArray &arr)
void setUnderlineColor(const QColor &color)
Sets the underline color used for the characters with this format to the color specified.
Definition: qtextformat.h:446
EventRef lastKeydownEvent()
void setLastKeydownEvent(EventRef)
bool translateKeyEvent(QWidget *receiver, const MSG &msg, bool grab)
bool isEmpty() const
bool qt_sendSpontaneousEvent(QObject *, QEvent *)
static QTextFormat qt_mac_compose_format()
signed long OSStatus
QInputContext * inputContext()
This function returns the QInputContext for this widget.
Definition: qwidget.cpp:474
struct OpaqueEventRef * EventRef
The QMouseEvent class contains parameters that describe a mouse event.
Definition: qevent.h:85
The QInputMethodEvent class provides parameters for input method events.
Definition: qevent.h:431
void mouseHandler(int pos, QMouseEvent *)
This function can be reimplemented in a subclass to handle mouse press, release, double-click, and move events within the preedit text.
QRect toRect() const
Returns the variant as a QRect if the variant has type() Rect ; otherwise returns an invalid QRect...
Definition: qvariant.cpp:2416
void setFontUnderline(bool underline)
If underline is true, sets the text format&#39;s font to be underlined; otherwise it is displayed non-und...
Definition: qtextformat.h:432
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:53
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
QKeyMapperPrivate * qt_keymapper_private()
Definition: qkeymapper.cpp:113
struct OpaqueEventHandlerCallRef * EventHandlerCallRef
int x() const
Returns the x coordinate of this point.
Definition: qpoint.h:128
static EventHandlerUPP input_proc_handlerUPP
The QInputContext class abstracts the input method dependent data and composing state.
Definition: qinputcontext.h:83
Qt::InputMethodHints inputMethodHints
What input method specific hints the widget has.
Definition: qwidget.h:224
virtual void setFocusWidget(QWidget *w)
Sets the widget that has an input focus for this input context.
The QEvent class is the base class of all event classes.
Definition: qcoreevent.h:56
Type type() const
Returns the event type.
Definition: qcoreevent.h:303
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
virtual QString language()
This function must be implemented in any subclasses to return a language code (e. ...
QPoint mapToGlobal(const QPoint &) const
Translates the widget coordinate pos to global screen coordinates.
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
#define text
Definition: qobjectdefs.h:80