From 4b2a9a5718688b56a083d3cf137eb6bd00bb8e74 Mon Sep 17 00:00:00 2001 From: kervala Date: Thu, 27 May 2010 10:04:43 +0200 Subject: [PATCH] Changed: #941 Dead keys are not working on Linux --- .../src/3d/driver/opengl/driver_opengl.cpp | 49 +++++++-------- .../3d/driver/opengl/unix_event_emitter.cpp | 61 ++++++++++++++++--- .../src/3d/driver/opengl/unix_event_emitter.h | 5 ++ 3 files changed, 84 insertions(+), 31 deletions(-) diff --git a/code/nel/src/3d/driver/opengl/driver_opengl.cpp b/code/nel/src/3d/driver/opengl/driver_opengl.cpp index 8c0d2fd7b..063b3c7e6 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl.cpp +++ b/code/nel/src/3d/driver/opengl/driver_opengl.cpp @@ -245,15 +245,15 @@ extern "C" /* static Bool WndProc(Display *d, XEvent *e, char *arg) { - nlinfo("3D: glop %d %d", e->type, e->xmap.window); - CDriverGL *pDriver = (CDriverGL*)arg; - if (pDriver != NULL) - { - // Process the message by the emitter - pDriver->_EventEmitter.processMessage(); - } - // TODO i'don t know what to return exactly - return (e->type == MapNotify) && (e->xmap.window == (Window) arg); + nlinfo("3D: glop %d %d", e->type, e->xmap.window); + CDriverGL *pDriver = (CDriverGL*)arg; + if (pDriver != NULL) + { + // Process the message by the emitter + pDriver->_EventEmitter.processMessage(); + } + // TODO i'don t know what to return exactly + return (e->type == MapNotify) && (e->xmap.window == (Window) arg); } */ #endif // NL_OS_UNIX @@ -867,7 +867,7 @@ bool CDriverGL::setDisplay(nlWindow wnd, const GfxMode &mode, bool show, bool re _hDC = NULL; return false; } - } + } else { _FullScreen= false; @@ -1074,21 +1074,21 @@ bool CDriverGL::setDisplay(nlWindow wnd, const GfxMode &mode, bool show, bool re visual_info = glXChooseVisual(dpy, DefaultScreen(dpy), sAttribList16bpp); if(visual_info == NULL) { - nlerror("glXChooseVisual() failed"); + nlerror("glXChooseVisual() failed"); } else { - nldebug("3D: glXChooseVisual OK"); + nldebug("3D: glXChooseVisual OK"); } ctx = glXCreateContext (dpy, visual_info, None, GL_TRUE); if(ctx == NULL) { - nlerror("glXCreateContext() failed"); + nlerror("glXCreateContext() failed"); } else { - nldebug("3D: glXCreateContext() OK"); + nldebug("3D: glXCreateContext() OK"); } XSetWindowAttributes attr; @@ -1136,6 +1136,8 @@ bool CDriverGL::setDisplay(nlWindow wnd, const GfxMode &mode, bool show, bool re XChangeWindowAttributes(dpy, win, attr_flags, &attr); } + const char *title="NeL window"; + XSizeHints size_hints; size_hints.x = 0; size_hints.y = 0; @@ -1147,13 +1149,14 @@ bool CDriverGL::setDisplay(nlWindow wnd, const GfxMode &mode, bool show, bool re size_hints.max_width = width; size_hints.max_height = height; +#ifdef X_HAVE_UTF8_STRING + Xutf8SetWMProperties (dpy, win, (char*)title, (char*)title, NULL, 0, &size_hints, NULL, NULL); +#else XTextProperty text_property; - // FIXME char*s are created as const char*, but that doesn't work - // with XStringListToTextProperty()'s char** ... - const char *title="NeL window"; XStringListToTextProperty((char**)&title, 1, &text_property); - XSetWMProperties (dpy, win, &text_property, &text_property, 0, 0, &size_hints, 0, 0); +#endif + glXMakeCurrent (dpy, win, ctx); XMapRaised (dpy, win); @@ -1310,8 +1313,6 @@ bool CDriverGL::setDisplay(nlWindow wnd, const GfxMode &mode, bool show, bool re if(_Extensions.EXTSeparateSpecularColor) { glLightModeli((GLenum)GL_LIGHT_MODEL_COLOR_CONTROL_EXT, GL_SEPARATE_SPECULAR_COLOR_EXT); - - } _VertexProgramEnabled= false; @@ -3594,7 +3595,7 @@ void CDriverGL::initFragmentShaders() // nglEndFragmentShaderATI(); GLenum error = glGetError(); - nlassert(error == GL_NONE); + nlassert(error == GL_NONE); // The same but with a diffuse map added nglBindFragmentShaderATI(ATIWaterShaderHandle); @@ -3608,7 +3609,7 @@ void CDriverGL::initFragmentShaders() nglEndFragmentShaderATI(); error = glGetError(); - nlassert(error == GL_NONE); + nlassert(error == GL_NONE); nglBindFragmentShaderATI(0); } @@ -4139,8 +4140,8 @@ void CDriverGL::checkTextureOn() const nlassert(!flag2D); nlassert(flagCM); break; - default: - break; + default: + break; } } dgs.activeTextureARB(currTexStage); diff --git a/code/nel/src/3d/driver/opengl/unix_event_emitter.cpp b/code/nel/src/3d/driver/opengl/unix_event_emitter.cpp index 04d508cba..ca3a07b5f 100644 --- a/code/nel/src/3d/driver/opengl/unix_event_emitter.cpp +++ b/code/nel/src/3d/driver/opengl/unix_event_emitter.cpp @@ -29,12 +29,42 @@ namespace NLMISC { CUnixEventEmitter::CUnixEventEmitter ():_dpy(NULL), _win(0), _PreviousKey(KeyNOKEY) { + _im = 0; + _ic = 0; +} + +CUnixEventEmitter::~CUnixEventEmitter() +{ + if (_ic) XDestroyIC(_ic); + if (_im) XCloseIM(_im); } void CUnixEventEmitter::init (Display *dpy, Window win) { _dpy = dpy; _win = win; + + createIM(); +} + +void CUnixEventEmitter::createIM() +{ + _im = XOpenIM(_dpy, NULL, NULL, NULL); + if (_im) + { + _ic = XCreateIC(_im, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, _win, XNFocusWindow, _win, NULL); +// XSetICFocus(_ic); + } + else + { + _ic = 0; + nlwarning("XCreateIM failed"); + } + + if (!_ic) + { + nlwarning("XCreateIC failed"); + } } void CUnixEventEmitter::submitEvents(CEventServer & server, bool allWindows) @@ -352,14 +382,28 @@ void CUnixEventEmitter::processMessage (XEvent &event, CEventServer &server) } Case(KeyPress) { + uint keyCode = event.xkey.keycode; + KeySym k = XKeycodeToKeysym(_dpy, keyCode, 0); char Text[256]; - KeySym k; int c = 0; - c = XLookupString(&event.xkey, Text, sizeof(Text), &k, NULL); + + // if key event is filtered, we must NOT use XLookupString + if (!XFilterEvent(&event, _win)) + { + Status status = XLookupNone; + +#ifdef X_HAVE_UTF8_STRING + if (_ic) + c = Xutf8LookupString(_ic, &event.xkey, Text, sizeof(Text), &k, &status); +#endif + + if (status == XLookupNone) + c = XLookupString(&event.xkey, Text, sizeof(Text), &k, NULL); + } TKey key = getKeyFromKeySym(k); if(key == KeyNOKEY) - key = getKeyFromKeycode(event.xkey.keycode); + key = getKeyFromKeycode(keyCode); server.postEvent (new CEventKeyDown (key, getKeyButton(event.xbutton.state), _PreviousKey != key, this)); _PreviousKey = key; @@ -371,10 +415,9 @@ void CUnixEventEmitter::processMessage (XEvent &event, CEventServer &server) Text[c] = '\0'; if(c>0) { - for (int i = 0; i < c; i++) - { - server.postEvent (new CEventChar ((ucchar)(unsigned char)Text[i], noKeyButton, this)); - } + ucstring ucstr; + ucstr.fromUtf8(Text); + server.postEvent (new CEventChar (ucstr[0], noKeyButton, this)); } break; } @@ -389,8 +432,10 @@ void CUnixEventEmitter::processMessage (XEvent &event, CEventServer &server) break; } Case(FocusIn) + if (_ic) XSetICFocus(_ic); return; Case(FocusOut) + if (_ic) XUnsetICFocus(_ic); return; Case(Expose) break; @@ -398,6 +443,8 @@ void CUnixEventEmitter::processMessage (XEvent &event, CEventServer &server) XRefreshKeyboardMapping((XMappingEvent *)&event); break; Case(DestroyNotify) + // XIM server has crashed + createIM(); break; Case(ConfigureNotify) /* if (event.xconfigure.width==gmaxx && event.xconfigure.height==gmaxy) { diff --git a/code/nel/src/3d/driver/opengl/unix_event_emitter.h b/code/nel/src/3d/driver/opengl/unix_event_emitter.h index 0c434f4b2..1a118094a 100644 --- a/code/nel/src/3d/driver/opengl/unix_event_emitter.h +++ b/code/nel/src/3d/driver/opengl/unix_event_emitter.h @@ -41,6 +41,7 @@ public: /// Constructor CUnixEventEmitter(); + virtual ~CUnixEventEmitter(); void init (Display *dpy, Window win); @@ -55,9 +56,13 @@ public: void processMessage (XEvent &event, CEventServer &server); private: + void createIM(); + Display *_dpy; Window _win; TKey _PreviousKey; + XIM _im; + XIC _ic; };