~ubuntu-branches/ubuntu/precise/hime/precise

« back to all changes in this revision

Viewing changes to src/qt4-im/hime-imcontext-qt.cpp

  • Committer: Package Import Robot
  • Author(s): Yao Wei (魏銘廷)
  • Date: 2012-01-14 00:24:08 UTC
  • Revision ID: package-import@ubuntu.com-20120114002408-e79gagbeg1rt8npv
Tags: upstream-0.9.9
Import upstream version 0.9.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2011 Edward Der-Hua Liu, Hsin-Chu, Taiwan
 
2
 *
 
3
 * This program is free software; you can redistribute it and/or modify
 
4
 * it under the terms of the GNU General Public License as published by
 
5
 * the Free Software Foundation; version 2 of the License.
 
6
 *
 
7
 * This program is distributed in the hope that it will be useful,
 
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
 * GNU General Public License for more details.
 
11
 *
 
12
 * You should have received a copy of the GNU General Public License along
 
13
 * with this program; if not, write to the Free Software Foundation, Inc.,
 
14
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
15
 */
 
16
 
 
17
#include "hime-imcontext-qt.h"
 
18
#include "hime-common-qt.h"
 
19
#include <stdio.h>
 
20
#include <X11/Xlib.h>
 
21
#include <X11/keysym.h>
 
22
#include <X11/Xutil.h>
 
23
#include <cstdio>
 
24
#include "hime-im-client.h"
 
25
#include <QColor>
 
26
#include <QPalette>
 
27
#include <QInputMethodEvent>
 
28
#include <QTextCharFormat>
 
29
 
 
30
using namespace Qt;
 
31
static QWidget *focused_widget;
 
32
 
 
33
typedef QInputMethodEvent::Attribute QAttribute;
 
34
 
 
35
HIMEIMContext::HIMEIMContext ()
 
36
{
 
37
  Display *display = QX11Info::display();
 
38
  if (!(hime_ch = hime_im_client_open(display))) {
 
39
    perror("cannot open hime_ch");
 
40
    return;
 
41
  }
 
42
}
 
43
 
 
44
HIMEIMContext::~HIMEIMContext ()
 
45
{
 
46
  if (hime_ch) {
 
47
    hime_im_client_close(hime_ch);
 
48
    hime_ch = NULL;
 
49
  }
 
50
}
 
51
 
 
52
QString HIMEIMContext::identifierName()
 
53
{
 
54
  return HIME_IDENTIFIER_NAME;
 
55
}
 
56
 
 
57
void HIMEIMContext::mouseHandler (int offset, QMouseEvent *event)
 
58
{
 
59
}
 
60
 
 
61
void HIMEIMContext::widgetDestroyed (QWidget *widget)
 
62
{
 
63
}
 
64
 
 
65
void HIMEIMContext::reset ()
 
66
{
 
67
  if (hime_ch) {
 
68
    hime_im_client_reset(hime_ch);
 
69
    update_preedit();
 
70
  }
 
71
}
 
72
 
 
73
void HIMEIMContext::update_cursor(QWidget *fwidget)
 
74
{
 
75
  hime_im_client_set_window(hime_ch, fwidget->winId());
 
76
  QRect rect = fwidget->inputMethodQuery (ImMicroFocus).toRect ();
 
77
  QPoint point (rect.x (), rect.y () + rect.height ());
 
78
  QPoint gxy = fwidget->mapToGlobal (point);
 
79
  if (hime_ch) {
 
80
    Display *dpy = QX11Info::display();
 
81
    WId ow;
 
82
    int wx, wy;
 
83
    XTranslateCoordinates(dpy, fwidget->winId(), DefaultRootWindow(dpy),
 
84
    0,0,  &wx, &wy, &ow);
 
85
 
 
86
    hime_im_client_set_cursor_location(hime_ch, gxy.x()-wx, gxy.y()-wy);
 
87
  }
 
88
}
 
89
 
 
90
void HIMEIMContext::update_preedit()
 
91
{
 
92
  QList<QAttribute> preedit_attributes;
 
93
//  QString preedit_string;
 
94
  int preedit_cursor_position=0;
 
95
  int sub_comp_len;
 
96
  char *str=NULL;
 
97
  HIME_PREEDIT_ATTR att[HIME_PREEDIT_ATTR_MAX_N];
 
98
  int attN = hime_im_client_get_preedit(hime_ch, &str, att, &preedit_cursor_position, &sub_comp_len);
 
99
 
 
100
  if (hime_ch) {
 
101
    int ret;
 
102
    hime_im_client_set_flags(hime_ch, FLAG_HIME_client_handle_use_preedit, &ret);
 
103
  }
 
104
 
 
105
  preedit_attributes.push_back (QAttribute (QInputMethodEvent::Cursor, preedit_cursor_position, true, 0));
 
106
 
 
107
  const QWidget *focused_widget = qApp->focusWidget ();
 
108
  if (!focused_widget || !str) {
 
109
free_mem:
 
110
    free(str);
 
111
    return;
 
112
  }
 
113
  const QPalette &palette = focused_widget->palette ();
 
114
  if (&palette==NULL)
 
115
    goto free_mem;
 
116
  const QBrush &reversed_foreground = palette.base ();
 
117
  const QBrush &reversed_background = palette.text ();
 
118
 
 
119
#if DBG || 0
 
120
  printf("update_preedit attN:%d '%s'\n", attN, str);
 
121
#endif
 
122
  int i;
 
123
  for(i=0; i < attN; i++) {
 
124
    int ofs0 = att[i].ofs0;
 
125
    int len = att[i].ofs1 - att[i].ofs0;
 
126
 
 
127
    switch (att[i].flag) {
 
128
      case HIME_PREEDIT_ATTR_FLAG_REVERSE:
 
129
          {
 
130
              QTextCharFormat text_format;
 
131
              text_format.setForeground (reversed_foreground);
 
132
              text_format.setBackground (reversed_background);
 
133
              QAttribute qt_attribute (QInputMethodEvent::TextFormat, ofs0, len, text_format);
 
134
              preedit_attributes.push_back (qt_attribute);
 
135
          }
 
136
          break;
 
137
      case HIME_PREEDIT_ATTR_FLAG_UNDERLINE:
 
138
          {
 
139
              QTextCharFormat text_format;
 
140
              text_format.setProperty (QTextFormat::FontUnderline, true);
 
141
              QAttribute qt_attribute (QInputMethodEvent::TextFormat, ofs0, len, text_format);
 
142
              preedit_attributes.push_back (qt_attribute);
 
143
          }
 
144
    }
 
145
  }
 
146
 
 
147
  QInputMethodEvent im_event (QString::fromUtf8(str), preedit_attributes);
 
148
  sendEvent (im_event);
 
149
  free(str);
 
150
}
 
151
 
 
152
void HIMEIMContext::update()
 
153
{
 
154
    QWidget *focused_widget = qApp->focusWidget ();
 
155
    if (focused_widget != NULL) {
 
156
        if (focused_widget == NULL) {
 
157
          if (hime_ch)
 
158
            hime_im_client_focus_in(hime_ch);
 
159
        }
 
160
 
 
161
        update_cursor(focused_widget);
 
162
    }
 
163
}
 
164
 
 
165
QString HIMEIMContext::language ()
 
166
{
 
167
    return "";
 
168
}
 
169
 
 
170
void HIMEIMContext::setFocusWidget(QWidget *widget)
 
171
{
 
172
  if (!widget)
 
173
    return;
 
174
 
 
175
  if (focused_widget != widget) {
 
176
#if 0
 
177
    if (focused_widget) {
 
178
      char *rstr;
 
179
      hime_im_client_focus_out2(hime_ch, &rstr);
 
180
      if (rstr) {
 
181
          QString inputText = QString::fromUtf8(rstr);
 
182
          QInputMethodEvent commit_event;
 
183
          commit_event.setCommitString (inputText);
 
184
          sendEvent (commit_event);
 
185
 
 
186
          QList<QAttribute> preedit_attributes;
 
187
          QInputMethodEvent im_event (QString::fromUtf8(""), preedit_attributes);
 
188
          sendEvent (im_event);
 
189
      }
 
190
    }
 
191
    focused_widget = widget;
 
192
#else
 
193
    hime_im_client_focus_out(hime_ch);
 
194
#endif
 
195
  }
 
196
 
 
197
  if (hime_ch) {
 
198
    hime_im_client_set_window(hime_ch, widget->winId());
 
199
  }
 
200
 
 
201
  QInputContext::setFocusWidget (widget);
 
202
//  puts("setFocusWidget");
 
203
  if (hime_ch)
 
204
    hime_im_client_focus_in(hime_ch);
 
205
}
 
206
 
 
207
bool HIMEIMContext::x11FilterEvent (QWidget *widget, XEvent *event)
 
208
{
 
209
  KeySym keysym;
 
210
  char static_buffer[256];
 
211
  char *buffer = static_buffer;
 
212
  int buffer_size = sizeof(static_buffer) - 1;
 
213
 
 
214
  if (event->type != KeyPress && event->type != KeyRelease)
 
215
      return TRUE;
 
216
 
 
217
  XKeyEvent *keve = (XKeyEvent *) event;
 
218
 
 
219
  XLookupString (keve, buffer, buffer_size, &keysym, NULL);
 
220
  int result;
 
221
  char *rstr = NULL;
 
222
  unsigned int state = keve->state;
 
223
 
 
224
 
 
225
  if (event->type == KeyPress) {
 
226
      result = hime_im_client_forward_key_press(hime_ch,
 
227
        keysym, state, &rstr);
 
228
 
 
229
      if (rstr) {
 
230
          QString inputText = QString::fromUtf8(rstr);
 
231
          QInputMethodEvent commit_event;
 
232
          commit_event.setCommitString (inputText);
 
233
          sendEvent (commit_event);
 
234
      }
 
235
  } else {
 
236
     result = hime_im_client_forward_key_release(hime_ch,
 
237
       keysym, state, &rstr);
 
238
  }
 
239
 
 
240
  if (result)
 
241
    update_preedit();
 
242
 
 
243
  update_cursor(widget);
 
244
 
 
245
  if (rstr)
 
246
      free(rstr);
 
247
 
 
248
  return result;
 
249
}
 
250
 
 
251
bool HIMEIMContext::filterEvent (const QEvent *event)
 
252
{
 
253
  return FALSE;
 
254
}
 
255
 
 
256
bool HIMEIMContext::isComposing() const
 
257
{
 
258
  char *str;
 
259
  HIME_PREEDIT_ATTR att[HIME_PREEDIT_ATTR_MAX_N];
 
260
  int preedit_cursor_position, sub_comp_len;
 
261
  hime_im_client_get_preedit(hime_ch, &str, att, &preedit_cursor_position, &sub_comp_len);
 
262
  bool is_compose = str[0]>0;
 
263
  free(str);
 
264
 
 
265
  return is_compose;
 
266
}