Nux

Merge lp:~paulliu/nux/nux into lp:nux

Proposed by Ying-Chun Liu
Status: Merged
Merged at revision: 727
Proposed branch: lp:~paulliu/nux/nux
Merge into: lp:nux
Diff against target: 248 lines (+155/-1)
3 files modified
Nux/TextEntry.cpp (+2/-0)
NuxGraphics/GraphicsDisplayX11.cpp (+138/-1)
NuxGraphics/GraphicsDisplayX11.h (+15/-0)
To merge this branch: bzr merge lp:~paulliu/nux/nux
Reviewer Review Type Date Requested Status
Brandon Schaefer (community) Approve
Francis Ginther Abstain
Tim Penhey (community) Abstain
Jay Taoko Pending
Review via email: mp+106875@code.launchpad.net

Description of the change

Hi Nux developers,

I'm adding XIM support for nux.
It makes nux-based apps work with other input methods (fcitx, gcin, hime..).
Please review my commit and ask me to improve it.

Many Thanks,
Paul

To post a comment you must log in.
Revision history for this message
Tim Penhey (thumper) wrote :

Thanks for this. I'm going to pass on this due to my unfamiliarity with input methods, but I'll make sure Jay looks at it :)

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

Hello Ying-Chun, I merged your branch with nux and it crashed running an example. Here are the stack traces:

http://pastebin.ubuntu.com/1078343/

full
http://pastebin.ubuntu.com/1078348/

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

The problem was I didn't have my ibus-daemon on or any IM active...this shouldn't crash nux because of that.

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

Also thanks for this :), this can help a lot!

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

A few comments now:

Some small things:

Could you move that curly bracket to a new line?
98 + void GraphicsDisplay::InitXIM(struct XimClientData *data) {

There are some tabbing issues here.
7 ime_->Focus();
8 + nux::GetWindowThread()->GetGraphicsDisplay().XICFocus();

15 ime_->Blur();
16 + nux::GetWindowThread()->GetGraphicsDisplay().XICUnFocus();

To fix that crash....
Change to:

102 + xmodifier = getenv("XMODIFIERS");
103 + if (xmodifier && strstr(xmodifier,"ibus") != NULL)

As not all machines are guaranteed to have that env var.

Ill need to look more at this, as I am not very familiar with those other IM. We are going to also need to add some testing.

Also thanks again :), this also fixes the Greek and Arabic problem.

review: Needs Fixing
lp:~paulliu/nux/nux updated
616. By Ying-Chun Liu

XIM support for libnux.

This patch adds the XIM support for libnux.
It makes other input methods to work with nux based applications.
This fixes LP:973808 LP:983254 and some other similar bugs.

Revision history for this message
Ying-Chun Liu (paulliu) wrote :

Hi Brandon,

Thanks for the review.
I've fix the issues you mentioned and updated my branch.

Please take a look again.

Many Thanks,
Paul

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

Hello Ying-Chun,

Ive been able to confirm that fcitx (note there is no preedit for fcitx) and hime working in Nux only. (It will not work in unity because unity does not Create an OpenGL window trough Nux). So this fixes bug 973808 for nux only. Though it should be easy to make it work for unity. (The OpenGL window is made in Compiz, so it uses this function in Nux: bool GraphicsDisplay::CreateFromOpenGLWindow)

I wasn't able to get gcin working, which it could be I couldn't understand the tools or any of the setup, as I sadly only know English. I am guessing it will work, but Ill keep trying.

One problem I am unsure about is. Would it be normal for people to use say ibus and another IM? Or is it always the case that only one is used? I am wondering this because if you used hime, fcitx etc then try to use IBus it will not work. A solution is to treat IBus as the default go to IM which can be dealt with when the IBus daemon starts up, which we detect.

Anyway Ill need to dig around some more and also think about a way to test this to make sure it will not cause any regression or other problems with nux or unity. Though it looks good as of now! Thank you!

Brandon Schaefer

Revision history for this message
Ying-Chun Liu (paulliu) wrote :

Hi Brandon,

Normally the user only use one IM. The user can install many IMs, and maybe running them together, but the apps will choose only one IM by XMODIFIERS environment variable. XSetLocaleModifiers() does this. And then we use XRegisterIMInstantiateCallback() which will be based on the value of XMODIFIERS.

BTW, ibus also supports XIM. So that means if without this block: "if (xmodifier && strstr(xmodifier,"ibus") != NULL) {...}", the ibus will use XIM protocol for nux and thus the ibus still works.
We adds the block here just to make sure that there's no regressions when using ibus.
ibus will use the original code, not the XIM.

A normal user would only use one IM because XMODIFIERS is assigned by im-switch.
But advanced user can use "env XMODIFIERS=otherim foo" to launch an app. And that app will use the specified IM. We can detect ibus daemon is running or not. But I think using XMODIFIERS to choose between im should be better and standard.

I can get gcin running. But gcin is tight binding on a lot of stuff. And yes, the setup is not very simple. I remember I installed a lot of gcin related stuff to make it work. Please make sure that gcin-* is all installed. And click the 4-th button of gcin-tools, make sure that some *Chinese* input methods are enabled.

Yours Sincerely,
Paul

Revision history for this message
Ying-Chun Liu (paulliu) wrote :

To make the preedit working, we have to extend this patch and use another "style".
Currently we are using "XIMStyle root_style = (XIMPreeditNothing|XIMStatusNothing);" so called "root style". Root style is simple and easy to implement.

In order to implement preedit, we have to implement "on the spot style". Needs to add mode codes in.

To implement it, we have to query xim_styles->supported_styles if "on the spot style" is provided by the XIM, and then we provide the info for "on the spot style".
The xim_styes->supported_styles is sorted by users preference. So normally we should implement a lot of different styles and match the first one in supported_styles. I can implement the rest styles but I don't have many time on this currently.

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

Awesome, Ill start writing some test up. Those things will come in later, it would be more important to support this right now. Thank you again! Hopefully I can get some test out in the next couple days (Ill need to add a test for each IM).

I can mess with the idea of using XIM for ibus and with those styling later on :)

As soon as I finish up tests then this will be approve and merged!

Revision history for this message
Francis Ginther (fginther) wrote :

Review was claimed by accident, please ignore.

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

I've been running this branch for a while now, and when my tests get approved this should get merged as well.

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

> I've been running this branch for a while now, and when my tests get approved
> this should get merged as well.

Hi Brandon Schaefer,

Could you also have a look on https://code.launchpad.net/~wengxt/nux/fcitx-support/+merge/114085 ?

Personally I had test this branch and that one for some while, and both branch works for me. However the branch from wengxt had implemented the XIM support in a not so hacky way, and the structure adjustment in that branch makes the IM not bound to IBUS, which is quite a nice improvement to nux in my personal opinion.

Thanks.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'Nux/TextEntry.cpp'
--- Nux/TextEntry.cpp 2012-07-03 23:24:53 +0000
+++ Nux/TextEntry.cpp 2012-07-09 14:05:24 +0000
@@ -856,6 +856,7 @@
856 need_im_reset_ = true;856 need_im_reset_ = true;
857#if defined(NUX_OS_LINUX)857#if defined(NUX_OS_LINUX)
858 ime_->Focus();858 ime_->Focus();
859 nux::GetWindowThread()->GetGraphicsDisplay().XICFocus();
859#endif860#endif
860 //gtk_im_context_focus_in(im_context_);861 //gtk_im_context_focus_in(im_context_);
861 //UpdateIMCursorLocation();862 //UpdateIMCursorLocation();
@@ -878,6 +879,7 @@
878 need_im_reset_ = true;879 need_im_reset_ = true;
879#if defined(NUX_OS_LINUX)880#if defined(NUX_OS_LINUX)
880 ime_->Blur();881 ime_->Blur();
882 nux::GetWindowThread()->GetGraphicsDisplay().XICUnFocus();
881#endif883#endif
882 //gtk_im_context_focus_out(im_context_);884 //gtk_im_context_focus_out(im_context_);
883 }885 }
884886
=== modified file 'NuxGraphics/GraphicsDisplayX11.cpp'
--- NuxGraphics/GraphicsDisplayX11.cpp 2012-04-16 18:37:21 +0000
+++ NuxGraphics/GraphicsDisplayX11.cpp 2012-07-09 14:05:24 +0000
@@ -184,6 +184,111 @@
184 return(event->type == MapNotify) && (event->xmap.window == (Window) arg);184 return(event->type == MapNotify) && (event->xmap.window == (Window) arg);
185 }185 }
186186
187 void GraphicsDisplay::XICFocus()
188 {
189 if (m_ximData.m_xic)
190 {
191 XSetICFocus(m_ximData.m_xic);
192 m_ximData.focus_stat=1;
193 }
194 }
195
196 void GraphicsDisplay::XICUnFocus()
197 {
198 if (m_ximData.m_xic)
199 {
200 XUnsetICFocus(m_ximData.m_xic);
201 m_ximData.focus_stat=0;
202 }
203 }
204
205 void GraphicsDisplay::XIMEndCallback(Display *dpy, XPointer client_data, XPointer call_data)
206 {
207 struct XimClientData *data;
208
209 data = (struct XimClientData*)client_data;
210 data->m_xim = NULL;
211 data->m_xic = NULL;
212 }
213
214 void GraphicsDisplay::XIMStartCallback(Display *dpy, XPointer client_data, XPointer call_data)
215 {
216 int i;
217 XIMCallback destroy;
218 XIMStyles *xim_styles = NULL;
219 XIMStyle root_style = (XIMPreeditNothing|XIMStatusNothing);
220 Window win;
221 struct XimClientData *data;
222
223 data = (struct XimClientData*)client_data;
224 win = * (data->window);
225
226 data->m_xim = XOpenIM(dpy, NULL, NULL, NULL);
227 if (! (data->m_xim))
228 {
229 nuxDebugMsg("[GraphicsDisplay::XIMStartCallback] Failed to open IM.");
230 return;
231 }
232 memset(&destroy, 0, sizeof(destroy));
233 destroy.callback = (XIMProc)((GraphicsDisplay::XIMEndCallback));
234 destroy.client_data = (XPointer)data;
235 XSetIMValues((data->m_xim), XNDestroyCallback, &destroy, NULL);
236 XGetIMValues((data->m_xim), XNQueryInputStyle, &xim_styles, NULL);
237 for (i=0; i<xim_styles->count_styles; i++)
238 {
239 if (xim_styles->supported_styles[i] == root_style)
240 {
241 break;
242 }
243 }
244 if (i>=xim_styles->count_styles)
245 {
246 nuxDebugMsg("[GraphicsDisplay::XIMStartCallback] root styles not supported.");
247 return;
248 }
249 data->m_xic = XCreateIC(data->m_xim, XNInputStyle, root_style, XNClientWindow, win, XNFocusWindow, win, NULL);
250 if (!(data->m_xic))
251 {
252 nuxDebugMsg("[GraphicsDisplay::XIMStartCallback] failed to register xic");
253 }
254 return;
255 }
256
257 void GraphicsDisplay::InitXIM(struct XimClientData *data)
258 {
259 const char *xmodifier;
260
261 /* don't do anything if we are using ibus */
262 xmodifier = getenv("XMODIFIERS");
263 if (xmodifier && strstr(xmodifier,"ibus") != NULL)
264 {
265 nuxDebugMsg("[GraphicsDisplay::InitXIM] ibus natively supported");
266 return;
267 }
268
269 if (setlocale(LC_ALL, "") == NULL)
270 {
271 nuxDebugMsg("[GraphicsDisplay::InitXIM] cannot setlocale");
272 }
273
274 if (!XSupportsLocale())
275 {
276 nuxDebugMsg("[GraphicsDisplay::InitXIM] no supported locale");
277 }
278
279 if (XSetLocaleModifiers("") == NULL)
280 {
281 nuxDebugMsg("[GraphicsDisplay::InitXIM] XSetLocaleModifiers failed.");
282 }
283
284 if (!XRegisterIMInstantiateCallback(*(data->display), NULL, NULL, NULL, GraphicsDisplay::XIMStartCallback, (XPointer)(data)))
285 {
286 nuxDebugMsg("[GraphicsDisplay::InitXIM] Cannot Register IM Init callback");
287 }
288 }
289
290
291
187// TODO: change windowWidth, windowHeight, to window_size;292// TODO: change windowWidth, windowHeight, to window_size;
188 static NCriticalSection CreateOpenGLWindow_CriticalSection;293 static NCriticalSection CreateOpenGLWindow_CriticalSection;
189 bool GraphicsDisplay::CreateOpenGLWindow(const char *WindowTitle,294 bool GraphicsDisplay::CreateOpenGLWindow(const char *WindowTitle,
@@ -568,6 +673,19 @@
568 //XMapRaised(m_X11Display, m_X11Window);673 //XMapRaised(m_X11Display, m_X11Window);
569 }674 }
570675
676 // XIM support
677 memset(&m_ximData,0,sizeof(m_ximData));
678 m_ximData.window = &m_X11Window;
679 m_ximData.display = &m_X11Display;
680 InitXIM(&m_ximData);
681
682 long im_event_mask=0;
683 if (m_ximData.m_xic)
684 {
685 XGetICValues(m_ximData.m_xic, XNFilterEvents, &im_event_mask, NULL);
686 m_X11Attr.event_mask |= im_event_mask;
687 }
688
571#ifndef NUX_OPENGLES_20689#ifndef NUX_OPENGLES_20
572 if (_has_glx_13)690 if (_has_glx_13)
573 {691 {
@@ -1229,6 +1347,8 @@
1229 if (XPending(m_X11Display))1347 if (XPending(m_X11Display))
1230 {1348 {
1231 XNextEvent(m_X11Display, &xevent);1349 XNextEvent(m_X11Display, &xevent);
1350 if (XFilterEvent(&xevent, None) == True)
1351 return;
12321352
1233 if (!_event_filters.empty())1353 if (!_event_filters.empty())
1234 {1354 {
@@ -1535,6 +1655,10 @@
1535 m_pEvent->dy = 0;1655 m_pEvent->dy = 0;
1536 m_pEvent->virtual_code = 0;1656 m_pEvent->virtual_code = 0;
1537 //nuxDebugMsg("[GraphicsDisplay::ProcessXEvents]: FocusIn event.");1657 //nuxDebugMsg("[GraphicsDisplay::ProcessXEvents]: FocusIn event.");
1658 if (m_ximData.m_xic && m_ximData.focus_stat==1)
1659 {
1660 XSetICFocus(m_ximData.m_xic);
1661 }
1538 break;1662 break;
1539 }1663 }
15401664
@@ -1550,6 +1674,11 @@
1550 m_pEvent->dy = 0;1674 m_pEvent->dy = 0;
1551 m_pEvent->virtual_code = 0;1675 m_pEvent->virtual_code = 0;
1552 //nuxDebugMsg("[GraphicsDisplay::ProcessXEvents]: FocusOut event.");1676 //nuxDebugMsg("[GraphicsDisplay::ProcessXEvents]: FocusOut event.");
1677
1678 if (m_ximData.m_xic)
1679 {
1680 XUnsetICFocus(m_ximData.m_xic);
1681 }
1553 break;1682 break;
1554 }1683 }
15551684
@@ -1580,7 +1709,15 @@
1580 skip = true; 1709 skip = true;
1581 }1710 }
1582 1711
1583 int num_char_stored = XLookupString(&xevent.xkey, buffer, NUX_EVENT_TEXT_BUFFER_SIZE, (KeySym*) &m_pEvent->x11_keysym, NULL);1712 int num_char_stored = 0;
1713 if (m_ximData.m_xic)
1714 {
1715 num_char_stored = XmbLookupString(m_ximData.m_xic, &xevent.xkey, buffer, NUX_EVENT_TEXT_BUFFER_SIZE, (KeySym*) &m_pEvent->x11_keysym, NULL);
1716 }
1717 else
1718 {
1719 num_char_stored = XLookupString(&xevent.xkey, buffer, NUX_EVENT_TEXT_BUFFER_SIZE, (KeySym*) &m_pEvent->x11_keysym, NULL);
1720 }
1584 if (num_char_stored && (!skip))1721 if (num_char_stored && (!skip))
1585 {1722 {
1586 Memcpy(m_pEvent->text, buffer, num_char_stored);1723 Memcpy(m_pEvent->text, buffer, num_char_stored);
15871724
=== modified file 'NuxGraphics/GraphicsDisplayX11.h'
--- NuxGraphics/GraphicsDisplayX11.h 2012-01-26 23:01:57 +0000
+++ NuxGraphics/GraphicsDisplayX11.h 2012-07-09 14:05:24 +0000
@@ -67,6 +67,15 @@
67 67
68 DNDACTION_NONE,68 DNDACTION_NONE,
69 };69 };
70
71 struct XimClientData
72 {
73 XIM m_xim;
74 XIC m_xic;
75 Window *window;
76 Display **display;
77 int focus_stat;
78 };
70 79
71#define NUX_THREADMSG (WM_APP+0)80#define NUX_THREADMSG (WM_APP+0)
72#define NUX_THREADMSG_START_RENDERING (WM_APP+1) // Connection established // start at WM_APP81#define NUX_THREADMSG_START_RENDERING (WM_APP+1) // Connection established // start at WM_APP
@@ -84,6 +93,7 @@
84 int m_X11Screen;93 int m_X11Screen;
85 Window m_X11Window;94 Window m_X11Window;
86 XVisualInfo *m_X11VisualInfo;95 XVisualInfo *m_X11VisualInfo;
96 struct XimClientData m_ximData;
8797
88 int m_ParentWindow;98 int m_ParentWindow;
89#ifndef NUX_OPENGLES_2099#ifndef NUX_OPENGLES_20
@@ -342,10 +352,15 @@
342 352
343 void * KeyboardGrabData() { return _global_keyboard_grab_data; }353 void * KeyboardGrabData() { return _global_keyboard_grab_data; }
344 void * PointerGrabData() { return _global_pointer_grab_data; }354 void * PointerGrabData() { return _global_pointer_grab_data; }
355 void XICFocus();
356 void XICUnFocus();
345357
346 private:358 private:
347 void InitGlobalGrabWindow();359 void InitGlobalGrabWindow();
348 360
361 void InitXIM(struct XimClientData *client_data);
362 static void XIMEndCallback(Display *dpy, XPointer client_data, XPointer call_data);
363 static void XIMStartCallback(Display *dpy, XPointer client_data, XPointer call_data);
349 void HandleXDndPosition(XEvent event, Event* nux_event);364 void HandleXDndPosition(XEvent event, Event* nux_event);
350 void HandleXDndEnter (XEvent event);365 void HandleXDndEnter (XEvent event);
351 void HandleXDndStatus (XEvent event);366 void HandleXDndStatus (XEvent event);

Subscribers

People subscribed via source and target branches