Nux

Merge lp:~wengxt/nux/fcitx-support into lp:nux

Proposed by csslayer
Status: Work in progress
Proposed branch: lp:~wengxt/nux/fcitx-support
Merge into: lp:nux
Diff against target: 2061 lines (+1609/-121) (has conflicts)
15 files modified
Nux/InputMethod.cpp (+84/-0)
Nux/InputMethod.h (+127/-0)
Nux/InputMethodFcitx.cpp (+309/-0)
Nux/InputMethodFcitx.h (+83/-0)
Nux/InputMethodIBus.cpp (+97/-50)
Nux/InputMethodIBus.h (+8/-62)
Nux/InputMethodXim.cpp (+202/-0)
Nux/InputMethodXim.h (+69/-0)
Nux/Makefile.am (+19/-2)
Nux/TextEntry.cpp (+5/-5)
Nux/TextEntry.h (+6/-2)
Nux/XimClientData.cpp (+524/-0)
Nux/XimClientData.h (+64/-0)
NuxGraphics/GraphicsDisplayX11.h (+1/-0)
configure.ac (+11/-0)
Text conflict in Nux/Makefile.am
Text conflict in configure.ac
To merge this branch: bzr merge lp:~wengxt/nux/fcitx-support
Reviewer Review Type Date Requested Status
Brandon Schaefer (community) Needs Fixing
Review via email: mp+114085@code.launchpad.net

Description of the change

Hi Nux developer,

Modularize a little bit for input method support in nux, can be refactor to shared library in the future.

fcitx newer than 4.2.4 is required.

To post a comment you must log in.
lp:~wengxt/nux/fcitx-support updated
630. By csslayer

merge nux/trunk

631. By csslayer

change the input method to a global component, not per-text entry

632. By csslayer

merge xim support

Revision history for this message
csslayer (wengxt) wrote :

Hi, I merged Xim support and change how input method works in nux (global instead of per textentry).

Please review.

Revision history for this message
Andrea Azzarone (azzar1) wrote :

Where are tests?

Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

Hello, sorry for be so late to review this....

There is something wrong with restarting IMs in the XIM part. ie. When you restart hime the text entry does not re initialize the xim again which leaves no im working (Only for XIM). Though that is an edge case. In the XIM destructor a XDestroyIC (xic) and XCloseIM(xim) should be there...

Also note this XIM support will not work in Unity. This is because the window getting set for the XIC is the root window for compiz. So when events come through for say the Dash window and get sent through XFilterEvent it will not match the compiz window which the XIC is setup with and fail.

I am also not sure if the XIM support will fit in this way for unity. As we will need an XIC for each window (Dash/Hud). So a possible fix for the XIM part is get the window related to the TextEntry and send that through when focusing the TextEntry...

Seems to be the way to get the window relating to a focused TextEntry.
nux::BaseWindow* window = static_cast<nux::BaseWindow*>(GetTopLevelViewWindow()))
window->GetInputWindowId()

I want to add this Fcitx support in as it communicates directly with fcitx as opposed to going through X. I think the more IMs that get added the harder it will be to maintain. I am really considering dropping all friend classes for the IM stuff and adding public methods into TextEntry to handle anything the IM stuff needs. I don't want to ruin encapsulation for a few protected variables. This will also reduce code in OnCommit for both ibus/fcitx and should for other things. Though this is my fault for programming it like this in the first place...

So right now...we need test for the fcitx support. Preferably in both Unity and Nux, but getting test in for Nux should be fine. Take a look at xtest-text-entry.cpp, this is where we have test for ibus. (It should be renamed to xtest-text-entry-ibus.cpp)

I also wanted to apologize for forcing IBus in Unity. It was not something I wanted to do and I really want to make sure everyone can use any IM they wish.

One last thing...we are in a FF (Feature Freeze) for 12.10. This being said I am not 100% if we can get a FF exception for this branch. If we cannot then this well get held back until 13.04.

Thank you again for this branch :)

review: Needs Fixing
Revision history for this message
Yu Ning (yuningdodo) wrote :

Hi Brandon Schaefer,

Thank you for your review and advises, I may try to improve & fix the XIM part in this branch. Due to I am not familiar with XIM, this may take some time.

Thanks again,
ning

Revision history for this message
Christopher Townsend (townsend) wrote :

Setting to Work in Progress to get it off the active review queue.

Unmerged revisions

632. By csslayer

merge xim support

631. By csslayer

change the input method to a global component, not per-text entry

630. By csslayer

merge nux/trunk

629. By csslayer

add fcitx support and make it a little bit modularize

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added file 'Nux/InputMethod.cpp'
--- Nux/InputMethod.cpp 1970-01-01 00:00:00 +0000
+++ Nux/InputMethod.cpp 2012-08-25 13:11:19 +0000
@@ -0,0 +1,84 @@
1/*
2* Copyright 2010 Inalogic® Inc.
3*
4* This program is free software: you can redistribute it and/or modify it
5* under the terms of the GNU Lesser General Public License, as
6* published by the Free Software Foundation; either version 2.1 or 3.0
7* of the License.
8*
9* This program is distributed in the hope that it will be useful, but
10* WITHOUT ANY WARRANTY; without even the implied warranties of
11* MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
12* PURPOSE. See the applicable version of the GNU Lesser General Public
13* License for more details.
14*
15* You should have received a copy of both the GNU Lesser General Public
16* License along with this program. If not, see <http://www.gnu.org/licenses/>
17*
18* Authored by: Brandon Schaefer <brandontschaefer@gmail.com>
19* Jay Taoko <jaytaoko@inalogic.com>
20*
21*/
22
23
24#include "Nux.h"
25
26#include "InputMethod.h"
27#include "InputMethodIBus.h"
28#include "InputMethodFcitx.h"
29#include "InputMethodXim.h"
30
31namespace nux
32{
33 IMEContext* IMEContextFactory::global_context_ = NULL;
34
35 IMEContext::IMEContext()
36 : focused_widget_(NULL)
37 {
38 }
39
40 IMEContext::~IMEContext()
41 {
42 }
43
44 void IMEContext::SetFocusWidget(TextEntry* text_entry)
45 {
46 focused_widget_ = text_entry;
47 }
48
49 void IMEContext::BlurWidget(TextEntry* text_entry)
50 {
51 if (text_entry == focused_widget_)
52 SetFocusWidget(NULL);
53 }
54
55 TextEntry* IMEContext::FocusWidget()
56 {
57 return focused_widget_;
58 }
59
60 IMEContext* IMEContextFactory::Get() {
61 if (global_context_)
62 return global_context_;
63 /* guess user wanted input method */
64 const char* im = g_getenv("NUX_IM");
65 /* fallback to the gtk/qt im module to test */
66 if (!im)
67 im = g_getenv("GTK_IM_MODULE");
68 if (!im)
69 im = g_getenv("QT_IM_MODULE");
70
71 if (g_strcmp0(im, "ibus") == 0)
72 global_context_ = new IBusIMEContext();
73 else if (g_strcmp0(im, "fcitx") == 0)
74 global_context_ = new FcitxIMEContext();
75 else if (g_strcmp0(im, "xim") == 0)
76 global_context_ = new XimIMEContext();
77 else if (g_getenv("XMODIFIERS"))
78 global_context_ = new XimIMEContext();
79 else
80 global_context_ = NULL;
81// global_context_ = XimIMEContext();
82 return global_context_;
83 }
84}
085
=== added file 'Nux/InputMethod.h'
--- Nux/InputMethod.h 1970-01-01 00:00:00 +0000
+++ Nux/InputMethod.h 2012-08-25 13:11:19 +0000
@@ -0,0 +1,127 @@
1/*
2* Copyright 2010 Inalogic® Inc.
3*
4* This program is free software: you can redistribute it and/or modify it
5* under the terms of the GNU Lesser General Public License, as
6* published by the Free Software Foundation; either version 2.1 or 3.0
7* of the License.
8*
9* This program is distributed in the hope that it will be useful, but
10* WITHOUT ANY WARRANTY; without even the implied warranties of
11* MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
12* PURPOSE. See the applicable version of the GNU Lesser General Public
13* License for more details.
14*
15* You should have received a copy of both the GNU Lesser General Public
16* License along with this program. If not, see <http://www.gnu.org/licenses/>
17*
18* Authored by: Brandon Schaefer <brandontschaefer@gmail.com>
19* Jay Taoko <jaytaoko@inalogic.com>
20* Weng Xuetian <wengxt@gmail.com>
21*
22*/
23
24
25#ifndef INPUTMETHOD_H
26#define INPUTMETHOD_H
27
28#include <Nux/TextEntry.h>
29
30namespace nux
31{
32
33 class IMEContext;
34 class TextEntry;
35
36 // FIXME This class should be reworked to replace the mouse_state
37 // with the hardware key_code.
38 class KeyEvent
39 {
40 public:
41
42 KeyEvent(NuxEventType type,
43 unsigned int key_sym,
44 unsigned int key_code, unsigned int event_flags, const char* character)
45 : type_(type)
46 , key_sym_(key_sym)
47 , key_code_(key_code)
48 , key_modifiers_(event_flags)
49 , character_(character ? character : "")
50 {
51 }
52
53 NuxEventType type() const {return type_;}
54 unsigned int key_sym() const {return key_sym_;}
55 unsigned int key_code() const {return key_code_;}
56 unsigned int flags() const {return key_modifiers_;}
57 std::string character() const {return character_;}
58
59 bool IsShiftDown() const { return (key_modifiers_ & KEY_MODIFIER_SHIFT) != 0; }
60 bool IsControlDown() const { return (key_modifiers_ & KEY_MODIFIER_CTRL) != 0; }
61 bool IsCapsLockDown() const { return (key_modifiers_ & KEY_MODIFIER_CAPS_LOCK) != 0; }
62 bool IsAltDown() const { return (key_modifiers_ & KEY_MODIFIER_ALT) != 0; }
63
64 private:
65 EventType type_;
66 unsigned int key_sym_;
67 unsigned int key_code_;
68 unsigned int key_modifiers_;
69 std::string character_;
70
71 KeyEvent(const KeyEvent&);
72 void operator = (const KeyEvent&);
73 };
74
75 // Used for passing data to ProcessKeyEventDone function()
76 class ProcessKeyEventData
77 {
78 public:
79 ProcessKeyEventData(IMEContext* context,
80 const KeyEvent& event)
81 : context(context)
82 , event(event.type(), event.key_sym(), event.key_code(), event.flags(), event.character().c_str())
83 {
84
85 }
86 IMEContext* context;
87 KeyEvent event;
88 };
89
90 // Implements IMEContext to integrate ibus input method framework
91 class IMEContext
92 {
93 public:
94 explicit IMEContext();
95 virtual ~IMEContext();
96
97 // views::IMEContext implementations:
98 virtual void SetFocusWidget(TextEntry* text_entry);
99 virtual void BlurWidget(TextEntry* text_entry);
100 virtual void Reset() = 0;
101 virtual bool FilterKeyEvent(const KeyEvent& event) = 0;
102 virtual void SetSurrounding(const std::wstring& text, int cursor_pos) = 0;
103
104 virtual bool IsConnected() const = 0;
105 virtual bool IsHotkeyEvent(EventType type, unsigned long keysym, unsigned long modifiers) const = 0;
106 virtual bool IsIgnoredKey(unsigned long keysym, unsigned long modifiers) const = 0;
107
108 TextEntry* FocusWidget();
109
110 protected:
111 TextEntry* focused_widget_;
112
113 private:
114 IMEContext(const IMEContext&);
115 void operator = (const IMEContext&);
116 };
117
118 class IMEContextFactory
119 {
120 public:
121 static IMEContext* Get();
122 private:
123 static IMEContext* global_context_;
124 };
125}
126#endif // INPUTMETHODIBUS_H
127
0128
=== added file 'Nux/InputMethodFcitx.cpp'
--- Nux/InputMethodFcitx.cpp 1970-01-01 00:00:00 +0000
+++ Nux/InputMethodFcitx.cpp 2012-08-25 13:11:19 +0000
@@ -0,0 +1,309 @@
1/*
2* Copyright 2012 Weng Xuetian
3*
4* This program is free software: you can redistribute it and/or modify it
5* under the terms of the GNU Lesser General Public License, as
6* published by the Free Software Foundation; either version 2.1 or 3.0
7* of the License.
8*
9* This program is distributed in the hope that it will be useful, but
10* WITHOUT ANY WARRANTY; without even the implied warranties of
11* MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
12* PURPOSE. See the applicable version of the GNU Lesser General Public
13* License for more details.
14*
15* You should have received a copy of both the GNU Lesser General Public
16* License along with this program. If not, see <http://www.gnu.org/licenses/>
17*
18* Authored by: Weng Xuetian <wengxt@gmail.com>
19*
20*/
21
22#include <fcitx/ui.h>
23#include <fcitx-config/hotkey.h>
24
25#include "Nux.h"
26
27#include "InputMethodFcitx.h"
28
29namespace nux
30{
31 FcitxIMEContext::FcitxIMEContext()
32 : IMEContext(),
33 client_(NULL)
34 {
35 client_ = fcitx_client_new();
36 g_signal_connect(client_, "connected", G_CALLBACK(OnConnected_), this);
37 g_signal_connect(client_, "commit-string", G_CALLBACK(OnCommitText_), this);
38 g_signal_connect(client_, "update-formatted-preedit", G_CALLBACK(OnUpdatePreeditText_), this);
39 // todo(csslayer) forward key, surrounding text
40 }
41
42 FcitxIMEContext::~FcitxIMEContext()
43 {
44 g_object_unref(client_);
45 TextEntry* text_entry = FocusWidget();
46 if (!text_entry)
47 return;
48 text_entry->ResetPreedit();
49 }
50
51 void FcitxIMEContext::SetFocusWidget(TextEntry* text_entry)
52 {
53 TextEntry* old_entry_ = FocusWidget();
54
55 if (old_entry_ == text_entry)
56 return;
57
58 if (old_entry_)
59 {
60 old_entry_->ime_active_ = false;
61 if (fcitx_client_is_valid(client_))
62 fcitx_client_focus_out(client_);
63 }
64
65 IMEContext::SetFocusWidget(text_entry);
66
67 bool has_focus = (text_entry != NULL);
68
69 if (!fcitx_client_is_valid(client_))
70 return;
71
72 if (has_focus)
73 {
74 text_entry->ime_active_ = true;
75 fcitx_client_focus_in(client_);
76 }
77 else
78 fcitx_client_focus_out(client_);
79 }
80
81 void FcitxIMEContext::Reset()
82 {
83 if (fcitx_client_is_valid(client_))
84 fcitx_client_reset(client_);
85 }
86
87 void FcitxIMEContext::OnConnected(FcitxClient* client)
88 {
89 int flags = 16 | 2;
90
91 if (fcitx_client_is_valid(client_))
92 fcitx_client_set_capacity(client_, flags);
93 }
94
95 bool FcitxIMEContext::FilterKeyEvent(const KeyEvent& event)
96 {
97 guint keyval = event.key_sym(); // todo(jaytaoko): ui::GdkKeyCodeForWindowsKeyCode(event.key_code(), event.IsShiftDown() ^ event.IsCapsLockDown());
98
99 if (fcitx_client_is_valid(client_)) {
100 guint modifiers = 0;
101
102 if (event.flags() & FcitxKeyState_IgnoredMask)
103 return false;
104
105 if (event.IsShiftDown())
106 modifiers |= FcitxKeyState_Shift;
107 if (event.IsControlDown())
108 modifiers |= FcitxKeyState_Ctrl;
109 if (event.IsAltDown())
110 modifiers |= FcitxKeyState_Alt;
111 if (event.IsCapsLockDown())
112 modifiers |= FcitxKeyState_CapsLock;
113
114 struct timeval current_time;
115 gettimeofday(&current_time, NULL);
116 guint32 time = (current_time.tv_sec * 1000) + (current_time.tv_usec / 1000);
117
118 fcitx_client_process_key(client_,
119 reinterpret_cast<GAsyncReadyCallback>(ProcessKeyEventDone),
120 new ProcessKeyEventData(this, event),
121 keyval, event.key_code(), modifiers,
122 (event.type() == EVENT_KEY_UP) ? 1 : 0,
123 time);
124
125 return true;
126 }
127 return false;
128 }
129
130 void FcitxIMEContext::SetSurrounding(const std::wstring& text, int cursor_pos)
131 {
132 // TODO(penghuang) support surrounding
133 }
134
135 bool FcitxIMEContext::IsConnected() const
136 {
137 return fcitx_client_is_valid(client_);
138 }
139
140 void FcitxIMEContext::UpdateCursorLocation()
141 {
142 nux::Rect strong, weak;
143 TextEntry* text_entry = FocusWidget();
144 if (!text_entry)
145 return;
146 text_entry->GetCursorRects(&strong, &weak);
147
148 // Get the position of the TextEntry in the Window.
149 nux::Geometry geo = text_entry->GetAbsoluteGeometry();
150
151 // Get the Geometry of the window on the display.
152 nux::Geometry window_geo = nux::GetGraphicsDisplay()->GetWindowGeometry();
153
154 fcitx_client_set_cusor_rect(client_,
155 geo.x + window_geo.x + strong.x,
156 geo.y + window_geo.y,
157 0,
158 geo.height);
159 }
160
161 void FcitxIMEContext::OnCommitText(FcitxClient *context, char* text)
162 {
163 //nuxDebugMsg("***FcitxIMEContext::OnCommitText::%s***", text->text);
164 nuxAssert(client_ == context);
165
166 TextEntry* text_entry = FocusWidget();
167 if (!text_entry)
168 return;
169 text_entry->DeleteSelection();
170
171 if (text)
172 {
173 int cursor = text_entry->cursor_;
174 std::string new_text(text_entry->GetText());
175 std::string commit_text (text);
176 new_text.insert (cursor, commit_text);
177
178 text_entry->SetText(new_text.c_str());
179 text_entry->SetCursor(cursor + commit_text.length());
180 UpdateCursorLocation();
181 }
182 }
183
184 void FcitxIMEContext::OnUpdatePreeditText(FcitxClient* context, GPtrArray* array, guint cursor_pos)
185 {
186 //nuxDebugMsg("***FcitxIMEContext::OnUpdatePreeditText***");
187 nuxAssert(client_ == context);
188 TextEntry* text_entry = FocusWidget();
189 if (!text_entry)
190 return;
191
192 if (text_entry->preedit_.empty())
193 UpdateCursorLocation();
194
195 if (array->len)
196 {
197 GString* gstr = g_string_new(NULL);
198 PangoAttrList* preedit_attrs = pango_attr_list_new();
199 unsigned int i = 0;
200 for (i = 0; i < array->len; i++)
201 {
202 size_t bytelen = strlen(gstr->str);
203 FcitxPreeditItem* preedit = static_cast<FcitxPreeditItem*>(g_ptr_array_index(array, i));
204 const gchar* s = preedit->string;
205 gint type = preedit->type;
206
207 PangoAttribute *pango_attr = NULL;
208 if ((type & MSG_NOUNDERLINE) == 0) {
209 pango_attr = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
210 pango_attr->start_index = bytelen;
211 pango_attr->end_index = bytelen + strlen(s);
212 pango_attr_list_insert(preedit_attrs, pango_attr);
213 }
214
215 if (type & MSG_HIGHLIGHT) {
216 guint16 fgred, fggreen, fgblue, bgred, bggreen, bgblue;
217
218 /* todo(csslayer) use style color*/
219 fgred = 0xffff;
220 fggreen = 0xffff;
221 fgblue = 0xffff;
222 bgred = 0x43ff;
223 bggreen = 0xacff;
224 bgblue = 0xe8ff;
225
226 pango_attr = pango_attr_foreground_new(fgred, fggreen, fgblue);
227 pango_attr->start_index = bytelen;
228 pango_attr->end_index = bytelen + strlen(s);
229 pango_attr_list_insert(preedit_attrs, pango_attr);
230 pango_attr = pango_attr_background_new(bgred, bggreen, bgblue);
231 pango_attr->start_index = bytelen;
232 pango_attr->end_index = bytelen + strlen(s);
233 pango_attr_list_insert(preedit_attrs, pango_attr);
234 }
235 gstr = g_string_append(gstr, s);
236 }
237
238 gchar* str = g_string_free(gstr, FALSE);
239 if (text_entry->preedit_attrs_)
240 {
241 pango_attr_list_unref(text_entry->preedit_attrs_);
242 text_entry->preedit_attrs_ = NULL;
243 }
244 text_entry->preedit_attrs_ = preedit_attrs;
245
246 std::string preedit(str);
247 text_entry->preedit_ = preedit;
248 text_entry->preedit_cursor_ = cursor_pos;
249 text_entry->QueueRefresh (true, true);
250 }
251 else
252 {
253 OnHidePreeditText(client_);
254 }
255 }
256
257 void FcitxIMEContext::OnHidePreeditText(FcitxClient *context)
258 {
259 //nuxDebugMsg("***FcitxIMEContext::OnHidePreeditText***");
260 nuxAssert(client_ == context);
261 TextEntry* text_entry = FocusWidget();
262 if (!text_entry)
263 return;
264
265 text_entry->ResetPreedit();
266 text_entry->QueueRefresh (true, true);
267 }
268
269 void FcitxIMEContext::ProcessKeyEventDone(FcitxClient *client, GAsyncResult* res, ProcessKeyEventData *data)
270 {
271 //nuxDebugMsg("***FcitxIMEContext::ProcessKeyEventDone***");
272 std::unique_ptr<ProcessKeyEventData> key_ev(data);
273 nuxAssert(key_ev->context->client_ == context);
274
275 GError *error = NULL;
276 int ret = -1;
277 GVariant* result = g_dbus_proxy_call_finish(G_DBUS_PROXY(client), res, &error);
278 if (error) {
279 g_warning ("Process Key Event failed: %s.", error->message);
280 g_error_free(error);
281 }
282 else if (result) {
283 g_variant_get(result, "(i)", &ret);
284 }
285
286 if (ret <= 0)
287 {
288 FcitxIMEContext* fcitxcontext = static_cast<FcitxIMEContext*>(key_ev->context);
289 TextEntry* text_entry = fcitxcontext->FocusWidget();
290 if (!text_entry)
291 return;
292
293 text_entry->ProcessKeyEvent(key_ev->event.type(),
294 key_ev->event.key_sym(),
295 key_ev->event.flags() | FcitxKeyState_IgnoredMask,
296 key_ev->event.character().c_str(),
297 0);
298 }
299 }
300
301 bool FcitxIMEContext::IsHotkeyEvent(EventType type, unsigned long keysym, unsigned long modifiers) const
302 {
303 return false;
304 }
305
306 bool FcitxIMEContext::IsIgnoredKey(unsigned long keysym, unsigned long modifiers) const {
307 return modifiers & FcitxKeyState_IgnoredMask;
308 }
309}
0310
=== added file 'Nux/InputMethodFcitx.h'
--- Nux/InputMethodFcitx.h 1970-01-01 00:00:00 +0000
+++ Nux/InputMethodFcitx.h 2012-08-25 13:11:19 +0000
@@ -0,0 +1,83 @@
1/*
2* Copyright 2012 Weng Xuetian
3*
4* This program is free software: you can redistribute it and/or modify it
5* under the terms of the GNU Lesser General Public License, as
6* published by the Free Software Foundation; either version 2.1 or 3.0
7* of the License.
8*
9* This program is distributed in the hope that it will be useful, but
10* WITHOUT ANY WARRANTY; without even the implied warranties of
11* MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
12* PURPOSE. See the applicable version of the GNU Lesser General Public
13* License for more details.
14*
15* You should have received a copy of both the GNU Lesser General Public
16* License along with this program. If not, see <http://www.gnu.org/licenses/>
17*
18* Authored by: Weng Xuetian <wengxt@gmail.com>
19*
20*/
21
22
23#ifndef INPUTMETHODFCITX_H
24#define INPUTMETHODFCITX_H
25
26#include <Nux/TextEntry.h>
27#include <Nux/InputMethod.h>
28#include <fcitx-gclient/fcitxclient.h>
29
30namespace nux
31{
32
33 class FcitxIMEContext;
34 class TextEntry;
35
36 // Implements IMEContext to integrate fcitx input method framework
37 class FcitxIMEContext : public IMEContext
38 {
39 public:
40 explicit FcitxIMEContext();
41 virtual ~FcitxIMEContext();
42
43 // views::IMEContext implementations:
44 virtual void SetFocusWidget(TextEntry* text_entry);
45 virtual void Reset();
46 virtual bool FilterKeyEvent(const KeyEvent& event);
47 virtual void SetSurrounding(const std::wstring& text, int cursor_pos);
48
49 virtual bool IsConnected() const;
50 virtual bool IsHotkeyEvent(EventType type, unsigned long keysym, unsigned long modifiers) const;
51 virtual bool IsIgnoredKey(unsigned long keysym, unsigned long modifiers) const;
52
53 protected:
54 private:
55 void UpdateCursorLocation();
56
57 // Event Handlers for FcitxClient
58 static void OnConnected_(FcitxClient* client, void* data) {nuxDebugMsg("***FcitxIMEContext::OnConnected***"); static_cast<FcitxIMEContext*>(data)->OnConnected(client);}
59 void OnConnected(FcitxClient *client);
60
61 static void OnCommitText_(FcitxClient* client, gchar* text, void* data) {static_cast<FcitxIMEContext*>(data)->OnCommitText(client, text);}
62 void OnCommitText(FcitxClient *client, char* text);
63
64 static void OnUpdatePreeditText_(FcitxClient* context, GPtrArray* array, guint cursor_pos, void* data) {reinterpret_cast<FcitxIMEContext*>(data)->OnUpdatePreeditText(context, array, cursor_pos);}
65 void OnUpdatePreeditText(FcitxClient *context, GPtrArray* array, guint cursor_pos);
66
67 void OnHidePreeditText(FcitxClient *context);
68
69 static void ProcessKeyEventDone(FcitxClient* context,
70 GAsyncResult* res,
71 ProcessKeyEventData* data);
72
73 FcitxClient* client_;
74 bool is_focused_;
75 TextEntry* focused_entry_;
76
77 FcitxIMEContext(const FcitxIMEContext&);
78 void operator = (const FcitxIMEContext&);
79 };
80
81}
82#endif // INPUTMETHODIBUS_H
83
084
=== modified file 'Nux/InputMethodIBus.cpp'
--- Nux/InputMethodIBus.cpp 2012-07-03 20:45:25 +0000
+++ Nux/InputMethodIBus.cpp 2012-08-25 13:11:19 +0000
@@ -32,10 +32,10 @@
3232
33 IBusBus* IBusIMEContext::bus_ = NULL;33 IBusBus* IBusIMEContext::bus_ = NULL;
3434
35 IBusIMEContext::IBusIMEContext(TextEntry* text_entry)35 IBusIMEContext::IBusIMEContext()
36 : text_entry_(text_entry),36 : IMEContext(),
37 context_(NULL),37 context_(NULL),
38 is_focused_(false)38 ime_active_(false)
39 {39 {
40 // init ibus40 // init ibus
41 if (!bus_)41 if (!bus_)
@@ -67,24 +67,33 @@
67 DestroyContext();67 DestroyContext();
68 }68 }
6969
70 void IBusIMEContext::Focus()70 void IBusIMEContext::SetFocusWidget(TextEntry* text_entry)
71 {71 {
72 if (is_focused_)72 TextEntry* old_entry_ = FocusWidget();
73 return;73
74 is_focused_ = true;74 if (old_entry_ == text_entry)
7575 return;
76 if (context_)76
77 if (old_entry_)
78 {
79 old_entry_->ime_active_ = false;
80 if (context_)
81 ibus_input_context_focus_out(context_);
82 }
83
84 IMEContext::SetFocusWidget(text_entry);
85
86 bool has_focus = (text_entry != NULL);
87
88 if (!context_)
89 return;
90
91 if (has_focus)
92 {
93 text_entry->ime_active_ = ime_active_;
77 ibus_input_context_focus_in(context_);94 ibus_input_context_focus_in(context_);
78 }95 }
7996 else
80 void IBusIMEContext::Blur()
81 {
82 if (!is_focused_)
83 return;
84
85 is_focused_ = false;
86
87 if (context_)
88 ibus_input_context_focus_out(context_);97 ibus_input_context_focus_out(context_);
89 }98 }
9099
@@ -143,7 +152,9 @@
143 return;152 return;
144 }153 }
145154
146 text_entry_->ime_active_ = false;155 TextEntry* text_entry = FocusWidget();
156 if (text_entry)
157 text_entry->ime_active_ = false;
147158
148 // connect input context signals159 // connect input context signals
149 g_signal_connect(context_, "commit-text", G_CALLBACK(OnCommitText_), this);160 g_signal_connect(context_, "commit-text", G_CALLBACK(OnCommitText_), this);
@@ -159,7 +170,7 @@
159 IBUS_CAP_SURROUNDING_TEXT;170 IBUS_CAP_SURROUNDING_TEXT;
160 ibus_input_context_set_capabilities(context_, caps);171 ibus_input_context_set_capabilities(context_, caps);
161172
162 if (is_focused_)173 if (FocusWidget())
163 ibus_input_context_focus_in(context_);174 ibus_input_context_focus_in(context_);
164175
165 UpdateCursorLocation();176 UpdateCursorLocation();
@@ -183,7 +194,9 @@
183 if (!context_)194 if (!context_)
184 return;195 return;
185196
186 text_entry_->ResetPreedit();197 TextEntry* text_entry = FocusWidget();
198 if (text_entry)
199 text_entry->ResetPreedit();
187 ibus_proxy_destroy(reinterpret_cast<IBusProxy *>(context_));200 ibus_proxy_destroy(reinterpret_cast<IBusProxy *>(context_));
188201
189 nuxAssert(!context_);202 nuxAssert(!context_);
@@ -196,11 +209,15 @@
196209
197 void IBusIMEContext::UpdateCursorLocation()210 void IBusIMEContext::UpdateCursorLocation()
198 {211 {
212 TextEntry* text_entry = FocusWidget();
213 if (!text_entry)
214 return;
215
199 nux::Rect strong, weak;216 nux::Rect strong, weak;
200 text_entry_->GetCursorRects(&strong, &weak);217 text_entry->GetCursorRects(&strong, &weak);
201218
202 // Get the position of the TextEntry in the Window.219 // Get the position of the TextEntry in the Window.
203 nux::Geometry geo = text_entry_->GetAbsoluteGeometry();220 nux::Geometry geo = text_entry->GetAbsoluteGeometry();
204221
205 // Get the Geometry of the window on the display.222 // Get the Geometry of the window on the display.
206 nux::Geometry window_geo = nux::GetGraphicsDisplay()->GetWindowGeometry();223 nux::Geometry window_geo = nux::GetGraphicsDisplay()->GetWindowGeometry();
@@ -245,17 +262,20 @@
245 //nuxDebugMsg("***IBusIMEContext::OnCommitText::%s***", text->text);262 //nuxDebugMsg("***IBusIMEContext::OnCommitText::%s***", text->text);
246 nuxAssert(context_ == context);263 nuxAssert(context_ == context);
247264
248 text_entry_->DeleteSelection();265 TextEntry* text_entry = FocusWidget();
266 if (!text_entry)
267 return;
268 text_entry->DeleteSelection();
249269
250 if (text->text)270 if (text->text)
251 {271 {
252 int cursor = text_entry_->cursor_;272 int cursor = text_entry->cursor_;
253 std::string new_text(text_entry_->GetText());273 std::string new_text(text_entry->GetText());
254 std::string commit_text (text->text);274 std::string commit_text (text->text);
255 new_text.insert (cursor, commit_text);275 new_text.insert (cursor, commit_text);
256276
257 text_entry_->SetText(new_text.c_str());277 text_entry->SetText(new_text.c_str());
258 text_entry_->SetCursor(cursor + commit_text.length());278 text_entry->SetCursor(cursor + commit_text.length());
259 UpdateCursorLocation();279 UpdateCursorLocation();
260 }280 }
261 }281 }
@@ -265,8 +285,12 @@
265 //nuxDebugMsg("***IBusIMEContext::OnUpdatePreeditText***");285 //nuxDebugMsg("***IBusIMEContext::OnUpdatePreeditText***");
266 nuxAssert(context_ == context);286 nuxAssert(context_ == context);
267 nuxAssert(IBUS_IS_TEXT(text));287 nuxAssert(IBUS_IS_TEXT(text));
288
289 TextEntry* text_entry = FocusWidget();
290 if (!text_entry)
291 return;
268292
269 if (text_entry_->preedit_.empty())293 if (text_entry->preedit_.empty())
270 UpdateCursorLocation();294 UpdateCursorLocation();
271295
272 if (visible)296 if (visible)
@@ -306,19 +330,19 @@
306 pango_attr->end_index = g_utf8_offset_to_pointer (text->text, attr->end_index) - text->text;330 pango_attr->end_index = g_utf8_offset_to_pointer (text->text, attr->end_index) - text->text;
307 pango_attr_list_insert (preedit_attrs, pango_attr);331 pango_attr_list_insert (preedit_attrs, pango_attr);
308 }332 }
309 if (text_entry_->preedit_attrs_)333 if (text_entry->preedit_attrs_)
310 {334 {
311 pango_attr_list_unref(text_entry_->preedit_attrs_);335 pango_attr_list_unref(text_entry->preedit_attrs_);
312 text_entry_->preedit_attrs_ = NULL;336 text_entry->preedit_attrs_ = NULL;
313 }337 }
314 text_entry_->preedit_attrs_ = preedit_attrs;338 text_entry->preedit_attrs_ = preedit_attrs;
315 }339 }
316 if (text->text)340 if (text->text)
317 {341 {
318 std::string preedit(text->text);342 std::string preedit(text->text);
319 text_entry_->preedit_ = preedit;343 text_entry->preedit_ = preedit;
320 text_entry_->preedit_cursor_ = preedit.length();344 text_entry->preedit_cursor_ = preedit.length();
321 text_entry_->QueueRefresh (true, true);345 text_entry->QueueRefresh (true, true);
322 }346 }
323 }347 }
324 else348 else
@@ -337,18 +361,26 @@
337 {361 {
338 //nuxDebugMsg("***IBusIMEContext::OnHidePreeditText***");362 //nuxDebugMsg("***IBusIMEContext::OnHidePreeditText***");
339 nuxAssert(context_ == context);363 nuxAssert(context_ == context);
364 TextEntry* text_entry = FocusWidget();
365 if (!text_entry)
366 return;
340367
341 text_entry_->ResetPreedit();368 text_entry->ResetPreedit();
342 text_entry_->QueueRefresh (true, true);369 text_entry->QueueRefresh (true, true);
343 }370 }
344371
345 void IBusIMEContext::OnEnable(IBusInputContext *context)372 void IBusIMEContext::OnEnable(IBusInputContext *context)
346 {373 {
347 //nuxDebugMsg("***IBusIMEContext::OnEnable***");374 //nuxDebugMsg("***IBusIMEContext::OnEnable***");
348 nuxAssert(context_ == context);375 nuxAssert(context_ == context);
349376 ime_active_ = true;
350 text_entry_->ime_active_ = true;377
351 text_entry_->text_changed.emit(text_entry_);378 TextEntry* text_entry = FocusWidget();
379 if (!text_entry)
380 return;
381
382 text_entry->ime_active_ = true;
383 text_entry->text_changed.emit(text_entry);
352 UpdateCursorLocation();384 UpdateCursorLocation();
353 }385 }
354386
@@ -356,9 +388,15 @@
356 {388 {
357 //nuxDebugMsg("***IBusIMEContext::OnDisable***");389 //nuxDebugMsg("***IBusIMEContext::OnDisable***");
358 nuxAssert(context_ == context);390 nuxAssert(context_ == context);
359 text_entry_->ime_active_ = false;391 ime_active_ = false;
360 text_entry_->ResetPreedit();392
361 text_entry_->QueueRefresh (true, true);393 TextEntry* text_entry = FocusWidget();
394 if (!text_entry)
395 return;
396
397 text_entry->ime_active_ = false;
398 text_entry->ResetPreedit();
399 text_entry->QueueRefresh (true, true);
362 }400 }
363401
364 void IBusIMEContext::OnDestroy(IBusInputContext *context)402 void IBusIMEContext::OnDestroy(IBusInputContext *context)
@@ -390,11 +428,16 @@
390428
391 if (!processed)429 if (!processed)
392 {430 {
393 key_ev->context->text_entry_->ProcessKeyEvent(key_ev->event.type(),431 IBusIMEContext* ibuscontext = static_cast<IBusIMEContext*>(key_ev->context);
394 key_ev->event.key_sym(),432 TextEntry* text_entry = ibuscontext->FocusWidget();
395 key_ev->event.flags() | IBUS_IGNORED_MASK,433 if (!text_entry)
396 key_ev->event.character().c_str(),434 return;
397 0);435
436 text_entry->ProcessKeyEvent(key_ev->event.type(),
437 key_ev->event.key_sym(),
438 key_ev->event.flags() | IBUS_IGNORED_MASK,
439 key_ev->event.character().c_str(),
440 0);
398 }441 }
399 }442 }
400443
@@ -515,4 +558,8 @@
515558
516 return false;559 return false;
517 }560 }
561
562 bool IBusIMEContext::IsIgnoredKey(unsigned long keysym, unsigned long modifiers) const {
563 return modifiers & IBUS_IGNORED_MASK;
564 }
518}565}
519566
=== modified file 'Nux/InputMethodIBus.h'
--- Nux/InputMethodIBus.h 2012-06-26 22:35:16 +0000
+++ Nux/InputMethodIBus.h 2012-08-25 13:11:19 +0000
@@ -25,6 +25,7 @@
25#define INPUTMETHODIBUS_H25#define INPUTMETHODIBUS_H
2626
27#include <Nux/TextEntry.h>27#include <Nux/TextEntry.h>
28#include <Nux/InputMethod.h>
28#include <ibus.h>29#include <ibus.h>
2930
30namespace nux31namespace nux
@@ -33,76 +34,22 @@
33 class IBusIMEContext;34 class IBusIMEContext;
34 class TextEntry;35 class TextEntry;
3536
36 // FIXME This class should be reworked to replace the mouse_state
37 // with the hardware key_code.
38 class KeyEvent
39 {
40 public:
41
42 KeyEvent(NuxEventType type,
43 unsigned int key_sym,
44 unsigned int key_code, unsigned int event_flags, const char* character)
45 : type_(type)
46 , key_sym_(key_sym)
47 , key_code_(key_code)
48 , key_modifiers_(event_flags)
49 , character_(character ? character : "")
50 {
51 }
52
53 NuxEventType type() const {return type_;}
54 unsigned int key_sym() const {return key_sym_;}
55 unsigned int key_code() const {return key_code_;}
56 unsigned int flags() const {return key_modifiers_;}
57 std::string character() const {return character_;}
58
59 bool IsShiftDown() const { return (key_modifiers_ & KEY_MODIFIER_SHIFT) != 0; }
60 bool IsControlDown() const { return (key_modifiers_ & KEY_MODIFIER_CTRL) != 0; }
61 bool IsCapsLockDown() const { return (key_modifiers_ & KEY_MODIFIER_CAPS_LOCK) != 0; }
62 bool IsAltDown() const { return (key_modifiers_ & KEY_MODIFIER_ALT) != 0; }
63
64 private:
65 EventType type_;
66 unsigned int key_sym_;
67 unsigned int key_code_;
68 unsigned int key_modifiers_;
69 std::string character_;
70
71 KeyEvent(const KeyEvent&);
72 void operator = (const KeyEvent&);
73 };
74
75 // Used for passing data to ProcessKeyEventDone function()
76 class ProcessKeyEventData
77 {
78 public:
79 ProcessKeyEventData(IBusIMEContext* context,
80 const KeyEvent& event)
81 : context(context)
82 , event(event.type(), event.key_sym(), event.key_code(), event.flags(), event.character().c_str())
83 {
84
85 }
86 IBusIMEContext* context;
87 KeyEvent event;
88 };
89
90 // Implements IMEContext to integrate ibus input method framework37 // Implements IMEContext to integrate ibus input method framework
91 class IBusIMEContext38 class IBusIMEContext : public IMEContext
92 {39 {
93 public:40 public:
94 explicit IBusIMEContext(TextEntry* text_entry);41 explicit IBusIMEContext();
95 virtual ~IBusIMEContext();42 virtual ~IBusIMEContext();
9643
97 // views::IMEContext implementations:44 // views::IMEContext implementations:
98 virtual void Focus();45 virtual void SetFocusWidget(TextEntry* text_entry);
99 virtual void Blur();
100 virtual void Reset();46 virtual void Reset();
101 virtual bool FilterKeyEvent(const KeyEvent& event);47 virtual bool FilterKeyEvent(const KeyEvent& event);
102 virtual void SetSurrounding(const std::wstring& text, int cursor_pos);48 virtual void SetSurrounding(const std::wstring& text, int cursor_pos);
10349
104 bool IsConnected() const;50 virtual bool IsConnected() const;
105 bool IsHotkeyEvent(EventType type, unsigned long keysym, unsigned long modifiers) const;51 virtual bool IsHotkeyEvent(EventType type, unsigned long keysym, unsigned long modifiers) const;
52 virtual bool IsIgnoredKey(unsigned long keysym, unsigned long modifiers) const;
10653
107 protected:54 protected:
108 static std::vector<Event> ParseIBusHotkeys(const gchar** keybindings);55 static std::vector<Event> ParseIBusHotkeys(const gchar** keybindings);
@@ -159,9 +106,8 @@
159 GAsyncResult* res,106 GAsyncResult* res,
160 ProcessKeyEventData* data);107 ProcessKeyEventData* data);
161108
162 TextEntry* text_entry_;
163 IBusInputContext* context_;109 IBusInputContext* context_;
164 bool is_focused_;110 bool ime_active_;
165111
166 static IBusBus* bus_;112 static IBusBus* bus_;
167 static std::vector<Event> hotkeys_;113 static std::vector<Event> hotkeys_;
168114
=== added file 'Nux/InputMethodXim.cpp'
--- Nux/InputMethodXim.cpp 1970-01-01 00:00:00 +0000
+++ Nux/InputMethodXim.cpp 2012-08-25 13:11:19 +0000
@@ -0,0 +1,202 @@
1/*
2* Copyright 2010 Inalogic® Inc.
3*
4* This program is free software: you can redistribute it and/or modify it
5* under the terms of the GNU Lesser General Public License, as
6* published by the Free Software Foundation; either version 2.1 or 3.0
7* of the License.
8*
9* This program is distributed in the hope that it will be useful, but
10* WITHOUT ANY WARRANTY; without even the implied warranties of
11* MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
12* PURPOSE. See the applicable version of the GNU Lesser General Public
13* License for more details.
14*
15* You should have received a copy of both the GNU Lesser General Public
16* License along with this program. If not, see <http://www.gnu.org/licenses/>
17*
18* Authored by: Weng Xuetian <wengxt@gmail.com>
19* Yu Ning <yuningdodo@gmail.com>
20*
21*/
22
23#include "Nux.h"
24
25#include "InputMethodXim.h"
26
27namespace nux
28{
29 extern unsigned int GetModifierKeyState(unsigned int);
30
31 XimIMEContext::XimIMEContext()
32 : IMEContext()
33 {
34 // XIM support
35 memset(&m_ximData,0,sizeof(m_ximData));
36 m_ximData.window = nux::GetGraphicsDisplay()->GetWindowHandle();
37 m_ximData.display = nux::GetGraphicsDisplay()->GetX11Display();
38 m_ximData.InitXIM();
39
40 long im_event_mask=0;
41 if (m_ximData.m_xic)
42 {
43 XGetICValues(m_ximData.m_xic, XNFilterEvents, &im_event_mask, NULL);
44 nux::GetGraphicsDisplay()->m_X11Attr.event_mask |= im_event_mask;
45 }
46
47 event_filter_.filter = XimIMEContext::XEventFilter;
48 event_filter_.data = this;
49 nux::GetGraphicsDisplay()->AddEventFilter(event_filter_);
50
51 // todo(csslayer) forward key, surrounding text
52 }
53
54 XimIMEContext::~XimIMEContext()
55 {
56 nux::GetGraphicsDisplay()->RemoveEventFilter(this);
57 m_ximData.UninitXIM();
58
59 TextEntry* text_entry = FocusWidget();
60 if (!text_entry)
61 return;
62 text_entry->ResetPreedit();
63 }
64
65 void XimIMEContext::SetFocusWidget(TextEntry* text_entry)
66 {
67 TextEntry* old_entry_ = FocusWidget();
68
69 if (old_entry_ == text_entry)
70 return;
71
72 if (old_entry_)
73 {
74 old_entry_->ime_active_ = false;
75 if (IsConnected())
76 m_ximData.XICUnFocus(old_entry_);
77 }
78
79 IMEContext::SetFocusWidget(text_entry);
80
81 bool has_focus = (text_entry != NULL);
82
83 if (!IsConnected())
84 return;
85
86 if (has_focus)
87 {
88 text_entry->ime_active_ = true;
89 m_ximData.XICFocus(text_entry);
90 }
91 else
92 {
93 m_ximData.XICUnFocus(text_entry);
94 }
95 }
96
97 void XimIMEContext::Reset()
98 {
99 if (IsConnected())
100 m_ximData.Reset();
101 }
102
103 bool XimIMEContext::FilterKeyEvent(const KeyEvent& event)
104 {
105 return false;
106 }
107
108 void XimIMEContext::SetSurrounding(const std::wstring& text, int cursor_pos)
109 {
110 // TODO(penghuang) support surrounding
111 }
112
113 bool XimIMEContext::IsConnected() const
114 {
115 return !!m_ximData.m_xic;
116 }
117
118 void XimIMEContext::UpdateCursorLocation()
119 {
120 nux::Rect strong, weak;
121 TextEntry* text_entry = FocusWidget();
122 if (!text_entry)
123 return;
124 text_entry->GetCursorRects(&strong, &weak);
125
126 // Get the position of the TextEntry in the Window.
127 nux::Geometry geo = text_entry->GetAbsoluteGeometry();
128
129 // Get the Geometry of the window on the display.
130 nux::Geometry window_geo = nux::GetGraphicsDisplay()->GetWindowGeometry();
131
132 if (IsConnected())
133 m_ximData.SetCursorLocation(geo.x + window_geo.x + strong.x, geo.y + window_geo.y, 0, 0);
134 }
135
136 bool XimIMEContext::XEventFilter(XEvent xevent, void * data)
137 {
138 XimIMEContext *context = (XimIMEContext*)data;
139 GraphicsDisplay *graphics_display = nux::GetGraphicsDisplay();
140 Event *m_pEvent = graphics_display->m_pEvent;
141
142 if (!context->IsConnected() || !context->m_ximData.textentry)
143 return false;
144
145 if (XFilterEvent(&xevent, None) == True)
146 return true;
147
148 switch(xevent.type)
149 {
150 case KeyPress:
151 {
152 //nuxDebugMsg("[InputMethodXim::XEventFilter]: KeyPress event.");
153 KeyCode keycode = xevent.xkey.keycode;
154 KeySym keysym = NoSymbol;
155 keysym = XKeycodeToKeysym(xevent.xany.display, keycode, 0);
156
157 m_pEvent->key_modifiers = GetModifierKeyState(xevent.xkey.state);
158 m_pEvent->key_repeat_count = 0;
159 m_pEvent->x11_keysym = keysym;
160 m_pEvent->x11_keycode = xevent.xkey.keycode;
161 m_pEvent->type = NUX_KEYDOWN;
162 m_pEvent->x11_timestamp = xevent.xkey.time;
163 m_pEvent->x11_key_state = xevent.xkey.state;
164
165 char buffer[NUX_EVENT_TEXT_BUFFER_SIZE];
166 Memset(m_pEvent->text, 0, NUX_EVENT_TEXT_BUFFER_SIZE);
167
168 bool skip = false;
169 if ((keysym == NUX_VK_BACKSPACE) ||
170 (keysym == NUX_VK_DELETE) ||
171 (keysym == NUX_VK_ESCAPE))
172 {
173 //temporary fix for TextEntry widget: filter some keys
174 skip = true;
175 }
176
177 int num_char_stored = XmbLookupString(context->m_ximData.m_xic, &xevent.xkey, buffer, NUX_EVENT_TEXT_BUFFER_SIZE, (KeySym*) &m_pEvent->x11_keysym, NULL);
178 if (num_char_stored && (!skip))
179 {
180 Memcpy(m_pEvent->text, buffer, num_char_stored);
181 }
182
183 return true;
184 }
185 default:
186 {
187 break;
188 }
189 }
190
191 return false;
192 }
193
194 bool XimIMEContext::IsHotkeyEvent(EventType type, unsigned long keysym, unsigned long modifiers) const
195 {
196 return false;
197 }
198
199 bool XimIMEContext::IsIgnoredKey(unsigned long keysym, unsigned long modifiers) const {
200 return false;
201 }
202}
0203
=== added file 'Nux/InputMethodXim.h'
--- Nux/InputMethodXim.h 1970-01-01 00:00:00 +0000
+++ Nux/InputMethodXim.h 2012-08-25 13:11:19 +0000
@@ -0,0 +1,69 @@
1/*
2* Copyright 2010 Inalogic® Inc.
3*
4* This program is free software: you can redistribute it and/or modify it
5* under the terms of the GNU Lesser General Public License, as
6* published by the Free Software Foundation; either version 2.1 or 3.0
7* of the License.
8*
9* This program is distributed in the hope that it will be useful, but
10* WITHOUT ANY WARRANTY; without even the implied warranties of
11* MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
12* PURPOSE. See the applicable version of the GNU Lesser General Public
13* License for more details.
14*
15* You should have received a copy of both the GNU Lesser General Public
16* License along with this program. If not, see <http://www.gnu.org/licenses/>
17*
18* Authored by: Weng Xuetian <wengxt@gmail.com>
19* Yu Ning <yuningdodo@gmail.com>
20*
21*/
22
23
24#ifndef INPUTMETHODXIM_H
25#define INPUTMETHODXIM_H
26
27#include <Nux/InputMethod.h>
28#include <Nux/XimClientData.h>
29
30namespace nux
31{
32
33 class XimIMEContext;
34 class TextEntry;
35
36 // Implements IMEContext to support XIM protocol
37 class XimIMEContext : public IMEContext
38 {
39 public:
40 explicit XimIMEContext();
41 virtual ~XimIMEContext();
42
43 // views::IMEContext implementations:
44 virtual void SetFocusWidget(TextEntry* text_entry);
45 virtual void Reset();
46 virtual bool FilterKeyEvent(const KeyEvent& event);
47 virtual void SetSurrounding(const std::wstring& text, int cursor_pos);
48
49 virtual bool IsConnected() const;
50 virtual bool IsHotkeyEvent(EventType type, unsigned long keysym, unsigned long modifiers) const;
51 virtual bool IsIgnoredKey(unsigned long keysym, unsigned long modifiers) const;
52
53 protected:
54 private:
55 void UpdateCursorLocation();
56
57 static bool XEventFilter(XEvent xevent, void * data);
58
59 struct XimClientData m_ximData;
60 GraphicsDisplay::EventFilterArg event_filter_;
61 bool is_focused_;
62
63 XimIMEContext(const XimIMEContext&);
64 void operator = (const XimIMEContext&);
65 };
66
67}
68#endif // INPUTMETHODXIM_H
69
070
=== modified file 'Nux/Makefile.am'
--- Nux/Makefile.am 2012-07-27 19:40:40 +0000
+++ Nux/Makefile.am 2012-08-25 13:11:19 +0000
@@ -16,15 +16,24 @@
16 $(GCC_FLAGS) \16 $(GCC_FLAGS) \
17 $(NUX_CFLAGS) \17 $(NUX_CFLAGS) \
18 $(IBUS_CFLAGS) \18 $(IBUS_CFLAGS) \
19<<<<<<< TREE
19 $(GEIS_CFLAGS) \20 $(GEIS_CFLAGS) \
21=======
22 $(FCITX_CFLAGS) \
23>>>>>>> MERGE-SOURCE
20 $(MAINTAINER_CFLAGS)24 $(MAINTAINER_CFLAGS)
2125
22libnux_@NUX_API_VERSION@_la_LIBADD = \26libnux_@NUX_API_VERSION@_la_LIBADD = \
23 $(top_builddir)/NuxCore/libnux-core-@NUX_API_VERSION@.la \27 $(top_builddir)/NuxCore/libnux-core-@NUX_API_VERSION@.la \
24 $(top_builddir)/NuxGraphics/libnux-graphics-@NUX_API_VERSION@.la \28 $(top_builddir)/NuxGraphics/libnux-graphics-@NUX_API_VERSION@.la \
25 $(NUX_LIBS) \29 $(NUX_LIBS) \
30<<<<<<< TREE
26 $(IBUS_LIBS) \31 $(IBUS_LIBS) \
27 $(GEIS_LIBS)32 $(GEIS_LIBS)
33=======
34 $(IBUS_LIBS) \
35 $(FCITX_LIBS)
36>>>>>>> MERGE-SOURCE
2837
29libnux_@NUX_API_VERSION@_la_LDFLAGS = \38libnux_@NUX_API_VERSION@_la_LDFLAGS = \
30 $(NUX_LT_LDFLAGS)39 $(NUX_LT_LDFLAGS)
@@ -96,7 +105,10 @@
96 $(srcdir)/SystemThread.cpp \105 $(srcdir)/SystemThread.cpp \
97 $(srcdir)/TabView.cpp \106 $(srcdir)/TabView.cpp \
98 $(srcdir)/TextEntry.cpp \107 $(srcdir)/TextEntry.cpp \
108 $(srcdir)/InputMethod.cpp \
99 $(srcdir)/InputMethodIBus.cpp \109 $(srcdir)/InputMethodIBus.cpp \
110 $(srcdir)/InputMethodFcitx.cpp \
111 $(srcdir)/InputMethodXim.cpp \
100 $(srcdir)/TextLoader.cpp \112 $(srcdir)/TextLoader.cpp \
101 $(srcdir)/TextureArea.cpp \113 $(srcdir)/TextureArea.cpp \
102 $(srcdir)/Timeline.cpp \114 $(srcdir)/Timeline.cpp \
@@ -112,7 +124,8 @@
112 $(srcdir)/VSplitter.cpp \124 $(srcdir)/VSplitter.cpp \
113 $(srcdir)/WidgetMetrics.cpp \125 $(srcdir)/WidgetMetrics.cpp \
114 $(srcdir)/WindowCompositor.cpp \126 $(srcdir)/WindowCompositor.cpp \
115 $(srcdir)/WindowThread.cpp127 $(srcdir)/WindowThread.cpp \
128 $(srcdir)/XimClientData.cpp
116129
117if HAVE_GEIS130if HAVE_GEIS
118source_cpp += \131source_cpp += \
@@ -192,7 +205,10 @@
192 $(srcdir)/TabView.h \205 $(srcdir)/TabView.h \
193 $(srcdir)/TextEntry.h \206 $(srcdir)/TextEntry.h \
194 $(srcdir)/TextEntryComposeSeqs.h \207 $(srcdir)/TextEntryComposeSeqs.h \
208 $(srcdir)/InputMethod.h \
195 $(srcdir)/InputMethodIBus.h \209 $(srcdir)/InputMethodIBus.h \
210 $(srcdir)/InputMethodFcitx.h \
211 $(srcdir)/InputMethodXim.h \
196 $(srcdir)/TextLoader.h \212 $(srcdir)/TextLoader.h \
197 $(srcdir)/TextureArea.h \213 $(srcdir)/TextureArea.h \
198 $(srcdir)/Timeline.h \214 $(srcdir)/Timeline.h \
@@ -208,7 +224,8 @@
208 $(srcdir)/VSplitter.h \224 $(srcdir)/VSplitter.h \
209 $(srcdir)/WidgetMetrics.h \225 $(srcdir)/WidgetMetrics.h \
210 $(srcdir)/WindowCompositor.h \226 $(srcdir)/WindowCompositor.h \
211 $(srcdir)/WindowThread.h227 $(srcdir)/WindowThread.h \
228 $(srcdir)/XimClientData.h
212229
213if HAVE_GEIS230if HAVE_GEIS
214source_h += \231source_h += \
215232
=== modified file 'Nux/TextEntry.cpp'
--- Nux/TextEntry.cpp 2012-07-17 23:41:38 +0000
+++ Nux/TextEntry.cpp 2012-08-25 13:11:19 +0000
@@ -31,7 +31,7 @@
3131
32#if defined(NUX_OS_LINUX)32#if defined(NUX_OS_LINUX)
33#include <X11/cursorfont.h>33#include <X11/cursorfont.h>
34#include "InputMethodIBus.h"34#include "InputMethod.h"
35#endif35#endif
3636
37namespace nux37namespace nux
@@ -154,7 +154,7 @@
154 , align_(CairoGraphics::ALIGN_LEFT)154 , align_(CairoGraphics::ALIGN_LEFT)
155#if defined(NUX_OS_LINUX)155#if defined(NUX_OS_LINUX)
156 , caret_cursor_(None)156 , caret_cursor_(None)
157 , ime_(new IBusIMEContext(this))157 , ime_(IMEContextFactory::Get())
158#endif158#endif
159 , ime_active_(false)159 , ime_active_(false)
160 , text_input_mode_(false)160 , text_input_mode_(false)
@@ -200,7 +200,7 @@
200200
201#if defined(NUX_OS_LINUX)201#if defined(NUX_OS_LINUX)
202 if (ime_)202 if (ime_)
203 delete ime_;203 ime_->BlurWidget(this);
204#endif204#endif
205 delete canvas_;205 delete canvas_;
206 ResetLayout();206 ResetLayout();
@@ -866,7 +866,7 @@
866 {866 {
867 need_im_reset_ = true;867 need_im_reset_ = true;
868#if defined(NUX_OS_LINUX)868#if defined(NUX_OS_LINUX)
869 ime_->Focus();869 ime_->SetFocusWidget(this);
870#endif870#endif
871 //gtk_im_context_focus_in(im_context_);871 //gtk_im_context_focus_in(im_context_);
872 //UpdateIMCursorLocation();872 //UpdateIMCursorLocation();
@@ -888,7 +888,7 @@
888 {888 {
889 need_im_reset_ = true;889 need_im_reset_ = true;
890#if defined(NUX_OS_LINUX)890#if defined(NUX_OS_LINUX)
891 ime_->Blur();891 ime_->BlurWidget(this);
892#endif892#endif
893 //gtk_im_context_focus_out(im_context_);893 //gtk_im_context_focus_out(im_context_);
894 }894 }
895895
=== modified file 'Nux/TextEntry.h'
--- Nux/TextEntry.h 2012-07-17 23:41:38 +0000
+++ Nux/TextEntry.h 2012-08-25 13:11:19 +0000
@@ -29,7 +29,7 @@
29namespace nux29namespace nux
30{30{
31 class CairoGraphics;31 class CairoGraphics;
32 class IBusIMEContext;32 class IMEContext;
3333
34 class CairoFont34 class CairoFont
35 {35 {
@@ -485,8 +485,12 @@
485 std::list<Rect> cursor_region_;485 std::list<Rect> cursor_region_;
486486
487#if defined(NUX_OS_LINUX)487#if defined(NUX_OS_LINUX)
488 IBusIMEContext* ime_;488 IMEContext* ime_;
489 friend class IMEContext;
489 friend class IBusIMEContext;490 friend class IBusIMEContext;
491 friend class FcitxIMEContext;
492 friend class XimIMEContext;
493 friend struct XimClientData;
490#endif494#endif
491495
492 bool ime_active_;496 bool ime_active_;
493497
=== added file 'Nux/XimClientData.cpp'
--- Nux/XimClientData.cpp 1970-01-01 00:00:00 +0000
+++ Nux/XimClientData.cpp 2012-08-25 13:11:19 +0000
@@ -0,0 +1,524 @@
1/*
2* Copyright 2010 Inalogic® Inc.
3*
4* This program is free software: you can redistribute it and/or modify it
5* under the terms of the GNU Lesser General Public License, as
6* published by the Free Software Foundation; either version 2.1 or 3.0
7* of the License.
8*
9* This program is distributed in the hope that it will be useful, but
10* WITHOUT ANY WARRANTY; without even the implied warranties of
11* MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
12* PURPOSE. See the applicable version of the GNU Lesser General Public
13* License for more details.
14*
15* You should have received a copy of both the GNU Lesser General Public
16* License along with this program. If not, see <http://www.gnu.org/licenses/>
17*
18* Authored by: Ying-Chun Liu <paul.liu@canonical.com>
19* Yu Ning <yuningdodo@gmail.com>
20*
21*/
22
23#include "Nux.h"
24#include "TextEntry.h"
25
26#include "XimClientData.h"
27
28namespace nux
29{
30
31#define PREEDIT_MASK (XIMPreeditCallbacks | XIMPreeditPosition | \
32 XIMPreeditArea | XIMPreeditNothing | XIMPreeditNone)
33#define STATUS_MASK (XIMStatusCallbacks | XIMStatusArea | \
34 XIMStatusNothing | XIMStatusNone)
35#define ALLOWED_MASK (XIMPreeditCallbacks | XIMPreeditNothing | XIMPreeditNone | \
36 XIMStatusCallbacks | XIMStatusNothing | XIMStatusNone)
37
38 /* stolen from gtk+2.24.4/modules/input/gtkimcontextxim.c */
39 static XIMStyle
40 choose_better_style (XIMStyle style1, XIMStyle style2)
41 {
42 XIMStyle s1, s2, u;
43
44 if (style1 == 0) return style2;
45 if (style2 == 0) return style1;
46 if ((style1 & (PREEDIT_MASK | STATUS_MASK))
47 == (style2 & (PREEDIT_MASK | STATUS_MASK)))
48 return style1;
49
50 s1 = style1 & PREEDIT_MASK;
51 s2 = style2 & PREEDIT_MASK;
52 u = s1 | s2;
53 if (s1 != s2) {
54 if (u & XIMPreeditCallbacks)
55 return (s1 == XIMPreeditCallbacks) ? style1 : style2;
56 else if (u & XIMPreeditPosition)
57 return (s1 == XIMPreeditPosition) ? style1 :style2;
58 else if (u & XIMPreeditArea)
59 return (s1 == XIMPreeditArea) ? style1 : style2;
60 else if (u & XIMPreeditNothing)
61 return (s1 == XIMPreeditNothing) ? style1 : style2;
62 else if (u & XIMPreeditNone)
63 return (s1 == XIMPreeditNone) ? style1 : style2;
64 } else {
65 s1 = style1 & STATUS_MASK;
66 s2 = style2 & STATUS_MASK;
67 u = s1 | s2;
68 if (u & XIMStatusCallbacks)
69 return (s1 == XIMStatusCallbacks) ? style1 : style2;
70 else if (u & XIMStatusArea)
71 return (s1 == XIMStatusArea) ? style1 : style2;
72 else if (u & XIMStatusNothing)
73 return (s1 == XIMStatusNothing) ? style1 : style2;
74 else if (u & XIMStatusNone)
75 return (s1 == XIMStatusNone) ? style1 : style2;
76 }
77 return 0; /* Get rid of stupid warning */
78 }
79
80/* Mask of feedback bits that we render
81 */
82#define FEEDBACK_MASK (XIMReverse | XIMUnderline)
83
84 /* stolen from gtk+2.24.4/modules/input/gtkimcontextxim.c */
85 static void
86 add_feedback_attr (PangoAttrList *attrs,
87 const gchar *str,
88 XIMFeedback feedback,
89 gint start_pos,
90 gint end_pos)
91 {
92 PangoAttribute *attr;
93
94 gint start_index = g_utf8_offset_to_pointer (str, start_pos) - str;
95 gint end_index = g_utf8_offset_to_pointer (str, end_pos) - str;
96
97 if (feedback & XIMUnderline)
98 {
99 attr = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE);
100 attr->start_index = start_index;
101 attr->end_index = end_index;
102
103 pango_attr_list_change (attrs, attr);
104 }
105
106 if (feedback & XIMReverse)
107 {
108 attr = pango_attr_foreground_new (0xffff, 0xffff, 0xffff);
109 attr->start_index = start_index;
110 attr->end_index = end_index;
111
112 pango_attr_list_change (attrs, attr);
113
114 attr = pango_attr_background_new (0, 0, 0);
115 attr->start_index = start_index;
116 attr->end_index = end_index;
117
118 pango_attr_list_change (attrs, attr);
119 }
120
121 if (feedback & ~FEEDBACK_MASK)
122 g_warning ("Unrendered feedback style: %#lx", feedback & ~FEEDBACK_MASK);
123 }
124
125 /* derived from gtk+2.24.4/modules/input/gtkimcontextxim.c: gtk_im_context_xim_get_preedit_string() */
126 static void
127 feedbacks_to_pango_attr_list(PangoAttrList **attrs,
128 const char *utf8,
129 int nfeedbacks,
130 XIMFeedback *feedbacks)
131 {
132 int i;
133 XIMFeedback last_feedback = 0;
134 gint start = -1;
135
136 if (attrs)
137 {
138 *attrs = pango_attr_list_new ();
139
140 for (i = 0; i < nfeedbacks; i++)
141 {
142 XIMFeedback new_feedback = feedbacks[i] & FEEDBACK_MASK;
143 if (new_feedback != last_feedback)
144 {
145 if (start >= 0)
146 add_feedback_attr (*attrs, utf8, last_feedback, start, i);
147
148 last_feedback = new_feedback;
149 start = i;
150 }
151 }
152
153 if (start >= 0)
154 add_feedback_attr (*attrs, utf8, last_feedback, start, i);
155 }
156 }
157
158 void XimClientData::InitXIM()
159 {
160#if 0
161 const char *xmodifier;
162
163 /* don't do anything if we are using ibus */
164 xmodifier = getenv("XMODIFIERS");
165 if (xmodifier && strstr(xmodifier,"ibus") != NULL)
166 {
167 nuxDebugMsg("[XimClientData::InitXIM] ibus natively supported");
168 return;
169 }
170#endif
171
172 if (setlocale(LC_ALL, "") == NULL)
173 {
174 nuxDebugMsg("[XimClientData::InitXIM] cannot setlocale");
175 }
176
177 if (!XSupportsLocale())
178 {
179 nuxDebugMsg("[XimClientData::InitXIM] no supported locale");
180 }
181
182 if (XSetLocaleModifiers("") == NULL)
183 {
184 nuxDebugMsg("[XimClientData::InitXIM] XSetLocaleModifiers failed.");
185 }
186
187 if (!XRegisterIMInstantiateCallback(this->display, NULL, NULL, NULL, XimClientData::XIMStartCallback, (XPointer)(this)))
188 {
189 nuxDebugMsg("[XimClientData::InitXIM] Cannot Register IM Init callback");
190 }
191 }
192
193 void XimClientData::UninitXIM()
194 {
195 XUnregisterIMInstantiateCallback(this->display, NULL, NULL, NULL,
196 XimClientData::XIMStartCallback, (XPointer)(this));
197 }
198
199 /* derived from gtk+2.24.4/modules/input/gtkimcontextxim.c: gtk_im_context_xim_reset() */
200 void XimClientData::Reset()
201 {
202 XIC ic = this->m_xic;
203 gchar *result;
204
205 /* restore conversion state after resetting ic later */
206 XIMPreeditState preedit_state = XIMPreeditUnKnown;
207 XVaNestedList preedit_attr;
208 gboolean have_preedit_state = FALSE;
209
210 if (!ic)
211 return;
212
213
214 preedit_attr = XVaCreateNestedList(0,
215 XNPreeditState, &preedit_state,
216 NULL);
217 if (!XGetICValues(ic,
218 XNPreeditAttributes, preedit_attr,
219 NULL))
220 have_preedit_state = TRUE;
221
222 XFree(preedit_attr);
223
224 result = XmbResetIC (ic);
225
226 preedit_attr = XVaCreateNestedList(0,
227 XNPreeditState, preedit_state,
228 NULL);
229 if (have_preedit_state)
230 XSetICValues(ic,
231 XNPreeditAttributes, preedit_attr,
232 NULL);
233
234 XFree(preedit_attr);
235
236 XFree (result);
237 }
238
239 void XimClientData::XICFocus(TextEntry *textentry)
240 {
241 if (this->m_xic)
242 {
243 XSetICFocus(this->m_xic);
244 this->focus_stat=1;
245 this->textentry = textentry;
246 }
247 }
248
249 void XimClientData::XICUnFocus(TextEntry *textentry)
250 {
251 if (this->m_xic)
252 {
253 nuxAssert(this->textentry == textentry);
254 XUnsetICFocus(this->m_xic);
255 this->focus_stat=0;
256 this->textentry = NULL;
257 }
258 }
259
260 /* derived from gtk+2.24.4/modules/input/gtkimcontextxim.c: gtk_im_context_xim_set_cursor_location() */
261 void XimClientData::SetCursorLocation(int x, int y, int width, int height)
262 {
263 XIC ic = this->m_xic;
264
265 XVaNestedList preedit_attr;
266 XPoint spot;
267
268 spot.x = x;
269 spot.y = y;
270
271 preedit_attr = XVaCreateNestedList (0,
272 XNSpotLocation, &spot,
273 NULL);
274 XSetICValues (ic,
275 XNPreeditAttributes, preedit_attr,
276 NULL);
277 XFree(preedit_attr);
278 }
279
280 void XimClientData::XIMEndCallback(Display *dpy, XPointer client_data, XPointer call_data)
281 {
282 struct XimClientData *data;
283
284 data = (struct XimClientData*)client_data;
285 data->m_xim = NULL;
286 data->m_xic = NULL;
287 data->textentry = NULL;
288 }
289
290 void XimClientData::XIMStartCallback(Display *dpy, XPointer client_data, XPointer call_data)
291 {
292 int i;
293 XIMCallback destroy;
294 XIMStyles *xim_styles = NULL;
295 XIMStyle root_style = (XIMPreeditNothing|XIMStatusNothing);
296 XIMStyle preferred_style = (XIMPreeditCallbacks|XIMStatusCallbacks);
297 XIMStyle choosed_style = 0;
298 XIMStyle im_style = 0;
299 const char * name1 = NULL;
300 XVaNestedList list1 = NULL;
301 const char * name2 = NULL;
302 XVaNestedList list2 = NULL;
303 Window win;
304 struct XimClientData *data;
305
306 data = (struct XimClientData*)client_data;
307 win = data->window;
308
309 data->m_xim = XOpenIM(dpy, NULL, NULL, NULL);
310 if (! (data->m_xim))
311 {
312 nuxDebugMsg("[XimClientData::XIMStartCallback] Failed to open IM.");
313 return;
314 }
315 memset(&destroy, 0, sizeof(destroy));
316 destroy.callback = (XIMProc)((XimClientData::XIMEndCallback));
317 destroy.client_data = (XPointer)data;
318 XSetIMValues((data->m_xim), XNDestroyCallback, &destroy, NULL);
319 XGetIMValues((data->m_xim), XNQueryInputStyle, &xim_styles, NULL);
320 for (i=0; i<xim_styles->count_styles; i++)
321 {
322 if (preferred_style == xim_styles->supported_styles[i])
323 {
324 choosed_style = preferred_style;
325 break;
326 }
327 choosed_style = choose_better_style(choosed_style,
328 xim_styles->supported_styles[i]);
329 }
330
331 if (choosed_style == 0)
332 {
333 for (i=0; i<xim_styles->count_styles; i++)
334 {
335 if (xim_styles->supported_styles[i] == root_style)
336 {
337 break;
338 }
339 }
340 if (i>=xim_styles->count_styles)
341 {
342 nuxDebugMsg("[XimClientData::XIMStartCallback] root styles not supported.");
343 return;
344 }
345 im_style = root_style;
346 }
347
348 if ((choosed_style & PREEDIT_MASK) == XIMPreeditCallbacks)
349 {
350 XIMCallback preedit_start;
351 XIMCallback preedit_done;
352 XIMCallback preedit_draw;
353 XIMCallback preedit_caret;
354
355 preedit_start.callback = (XIMProc)((XimClientData::XIMPreeditStartCallback));
356 preedit_start.client_data = (XPointer)data;
357 preedit_done.callback = (XIMProc)((XimClientData::XIMPreeditDoneCallback));
358 preedit_done.client_data = (XPointer)data;
359 preedit_draw.callback = (XIMProc)((XimClientData::XIMPreeditDrawCallback));
360 preedit_draw.client_data = (XPointer)data;
361 preedit_caret.callback = (XIMProc)((XimClientData::XIMPreeditCaretCallback));
362 preedit_caret.client_data = (XPointer)data;
363
364 name1 = XNPreeditAttributes;
365 list1 = XVaCreateNestedList(0,
366 XNPreeditStartCallback, &preedit_start,
367 XNPreeditDoneCallback, &preedit_done,
368 XNPreeditDrawCallback, &preedit_draw,
369 XNPreeditCaretCallback, &preedit_caret,
370 NULL);
371
372 im_style |= XIMPreeditCallbacks;
373 }
374 else if ((choosed_style & PREEDIT_MASK) == XIMPreeditNone)
375 {
376 im_style |= XIMPreeditNone;
377 }
378 else
379 {
380 im_style |= XIMPreeditNothing;
381 }
382
383#if 0
384 if ((choosed_style & STATUS_MASK) == XIMStatusCallbacks)
385 {
386 XIMCallback status_start;
387 XIMCallback status_done;
388 XIMCallback status_draw;
389
390 status_start.callback = (XIMProc)((XimClientData::XIMStatusStartCallback));
391 status_start.client_data = (XPointer)data;
392 status_done.callback = (XIMProc)((XimClientData::XIMStatusDoneCallback));
393 status_done.client_data = (XPointer)data;
394 status_draw.callback = (XIMProc)((XimClientData::XIMStatusDrawCallback));
395 status_draw.client_data = (XPointer)data;
396
397 name2 = XNStatusAttributes;
398 list2 = XVaCreateNestedList(0,
399 XNStatusStartCallback, &status_start,
400 XNStatusDoneCallback, &status_done,
401 XNStatusDrawCallback, &status_draw,
402 NULL);
403
404 im_style |= XIMStatusCallbacks;
405 }
406 else if ((choosed_style & STATUS_MASK) == XIMStatusNone)
407 {
408 im_style |= XIMStatusNone;
409 }
410 else
411 {
412 im_style |= XIMStatusNothing;
413 }
414#endif
415
416 if (name2 && !name1)
417 {
418 name1 = name2;
419 list1 = list2;
420 name2 = NULL;
421 list2 = NULL;
422 }
423
424 data->m_xic = XCreateIC(data->m_xim,
425 XNInputStyle, im_style,
426 XNClientWindow, win,
427 XNFocusWindow, win,
428 name1, list1,
429 name2, list2,
430 NULL);
431 if (!(data->m_xic))
432 {
433 nuxDebugMsg("[XimClientData::XIMStartCallback] failed to register xic");
434 }
435
436 /* TODO: string conversion support */
437
438 if (list1)
439 XFree(list1);
440 if (list2)
441 XFree(list2);
442
443 return;
444 }
445
446 int XimClientData::XIMPreeditStartCallback(XIC xic, XPointer client_data, XPointer call_data)
447 {
448 return -1; /* No Length Limit */
449 }
450
451 void XimClientData::XIMPreeditDoneCallback(XIC xic, XPointer client_data, XPointer call_data)
452 {
453 struct XimClientData *data = (struct XimClientData*)client_data;
454
455 if (data->textentry == NULL)
456 return;
457
458 data->textentry->ResetPreedit();
459 /* FIXME: If the preedit is accepted (press Return for example) then this
460 * QueueRefresh() will lead to a visiable blink in the entry.
461 * However without this QueueRefresh() then the display will not be
462 * refreshed if the preedit is cancelled (press Esc for example).
463 */
464 data->textentry->QueueRefresh(true, true);
465 }
466
467 void XimClientData::XIMPreeditDrawCallback(XIC xic, XPointer client_data,
468 XIMPreeditDrawCallbackStruct *call_data)
469 {
470 struct XimClientData *data = (struct XimClientData*)client_data;
471
472 if (data->textentry == NULL)
473 return;
474
475 if (call_data->text)
476 {
477 std::string &preedit = data->textentry->preedit_;
478 if (call_data->text->encoding_is_wchar)
479 preedit = NString(call_data->text->string.wide_char).GetTStringRef();
480 else
481 preedit = call_data->text->string.multi_byte;
482
483 const char *utf8 = preedit.c_str();
484 PangoAttrList *attrs;
485 feedbacks_to_pango_attr_list(&attrs, utf8,
486 call_data->text->length, call_data->text->feedback);
487
488 if (data->textentry->preedit_attrs_)
489 pango_attr_list_unref(data->textentry->preedit_attrs_);
490
491 data->textentry->preedit_cursor_ = preedit.length();
492 data->textentry->preedit_attrs_ = attrs;
493 data->textentry->QueueRefresh(true, true);
494 }
495 }
496
497 void XimClientData::XIMPreeditCaretCallback(XIC xic, XPointer client_data,
498 XIMPreeditCaretCallbackStruct *call_data)
499 {
500 nuxDebugMsg("[XimClientData::XIMPreeditCaretCallback] TODO");
501 }
502
503 void XimClientData::XIMStatusStartCallback(XIC xic, XPointer client_data, XPointer call_data)
504 {
505 nuxDebugMsg("[XimClientData::XIMStatusStartCallback] TODO");
506 }
507
508 void XimClientData::XIMStatusDoneCallback(XIC xic, XPointer client_data, XPointer call_data)
509 {
510 nuxDebugMsg("[XimClientData::XIMStatusDoneCallback] TODO");
511 }
512
513 void XimClientData::XIMStatusDrawCallback(XIC xic, XPointer client_data,
514 XIMStatusDrawCallbackStruct *call_data)
515 {
516 nuxDebugMsg("[XimClientData::XIMStatusDrawCallback] TODO");
517 }
518
519 void XimClientData::XIMStringConversionCallback(XIC xic, XPointer client_data,
520 XIMStringConversionCallbackStruct * call_data)
521 {
522 nuxDebugMsg("[XimClientData::XIMStringConversionCallback] TODO");
523 }
524}
0525
=== added file 'Nux/XimClientData.h'
--- Nux/XimClientData.h 1970-01-01 00:00:00 +0000
+++ Nux/XimClientData.h 2012-08-25 13:11:19 +0000
@@ -0,0 +1,64 @@
1/*
2* Copyright 2010 Inalogic庐 Inc.
3*
4* This program is free software: you can redistribute it and/or modify it
5* under the terms of the GNU Lesser General Public License, as
6* published by the Free Software Foundation; either version 2.1 or 3.0
7* of the License.
8*
9* This program is distributed in the hope that it will be useful, but
10* WITHOUT ANY WARRANTY; without even the implied warranties of
11* MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
12* PURPOSE. See the applicable version of the GNU Lesser General Public
13* License for more details.
14*
15* You should have received a copy of both the GNU Lesser General Public
16* License along with this program. If not, see <http://www.gnu.org/licenses/>
17*
18* Authored by: Ying-Chun Liu <paul.liu@canonical.com>
19* Yu Ning <yuningdodo@gmail.com>
20*
21*/
22
23
24#ifndef XIMCLIENTDATA_H
25#define XIMCLIENTDATA_H
26
27#include <Nux/Nux.h>
28
29namespace nux
30{
31
32 class TextEntry;
33
34 struct XimClientData
35 {
36 XIM m_xim;
37 XIC m_xic;
38 Window window;
39 Display *display;
40 int focus_stat;
41 TextEntry *textentry;
42
43 void InitXIM();
44 void UninitXIM();
45 void Reset();
46 void XICFocus(TextEntry *textentry);
47 void XICUnFocus(TextEntry *textentry);
48 void SetCursorLocation(int x, int y, int width, int height);
49
50 static void XIMEndCallback(Display *dpy, XPointer client_data, XPointer call_data);
51 static void XIMStartCallback(Display *dpy, XPointer client_data, XPointer call_data);
52 static int XIMPreeditStartCallback(XIC xic, XPointer client_data, XPointer call_data);
53 static void XIMPreeditDoneCallback(XIC xic, XPointer client_data, XPointer call_data);
54 static void XIMPreeditDrawCallback(XIC xic, XPointer client_data, XIMPreeditDrawCallbackStruct *call_data);
55 static void XIMPreeditCaretCallback(XIC xic, XPointer client_data, XIMPreeditCaretCallbackStruct *call_data);
56 static void XIMStatusStartCallback(XIC xic, XPointer client_data, XPointer call_data);
57 static void XIMStatusDoneCallback(XIC xic, XPointer client_data, XPointer call_data);
58 static void XIMStatusDrawCallback(XIC xic, XPointer client_data, XIMStatusDrawCallbackStruct *call_data);
59 static void XIMStringConversionCallback(XIC xic, XPointer client_data, XIMStringConversionCallbackStruct * call_data);
60 };
61
62}
63#endif // XIMCLIENTDATA_H
64
065
=== modified file 'NuxGraphics/GraphicsDisplayX11.h'
--- NuxGraphics/GraphicsDisplayX11.h 2012-05-31 21:32:52 +0000
+++ NuxGraphics/GraphicsDisplayX11.h 2012-08-25 13:11:19 +0000
@@ -465,6 +465,7 @@
465465
466 friend class DisplayAccessController;466 friend class DisplayAccessController;
467 friend class GraphicsEngine;467 friend class GraphicsEngine;
468 friend class XimIMEContext;
468 };469 };
469470
470}471}
471472
=== modified file 'configure.ac'
--- configure.ac 2012-08-13 20:48:38 +0000
+++ configure.ac 2012-08-25 13:11:19 +0000
@@ -192,6 +192,7 @@
192AC_SUBST(IBUS_CFLAGS)192AC_SUBST(IBUS_CFLAGS)
193AC_SUBST(IBUS_LIBS)193AC_SUBST(IBUS_LIBS)
194194
195<<<<<<< TREE
195dnl *********************************************************196dnl *********************************************************
196dnl Enable/disable gestures (geis, from Open Input Framework)197dnl Enable/disable gestures (geis, from Open Input Framework)
197dnl *********************************************************198dnl *********************************************************
@@ -244,6 +245,16 @@
244AC_SUBST(GEIS_LIBS)245AC_SUBST(GEIS_LIBS)
245AC_SUBST(GEIS_PKGS)246AC_SUBST(GEIS_PKGS)
246247
248=======
249PKG_CHECK_MODULES(FCITX,
250 fcitx-gclient
251 fcitx-config
252 )
253
254AC_SUBST(FCITX_CFLAGS)
255AC_SUBST(FCITX_LIBS)
256
257>>>>>>> MERGE-SOURCE
247dnl ************************************258dnl ************************************
248dnl Enable/disable tests259dnl Enable/disable tests
249dnl ************************************260dnl ************************************

Subscribers

People subscribed via source and target branches