=== modified file 'Nux/TextEntry.cpp' --- Nux/TextEntry.cpp 2012-04-25 13:59:25 +0000 +++ Nux/TextEntry.cpp 2013-05-24 18:35:29 +0000 @@ -842,6 +842,7 @@ need_im_reset_ = true; #if defined(NUX_OS_LINUX) ime_->Focus(); + nux::GetWindowThread()->GetGraphicsDisplay().XICFocus(); #endif //gtk_im_context_focus_in(im_context_); //UpdateIMCursorLocation(); @@ -864,6 +865,7 @@ need_im_reset_ = true; #if defined(NUX_OS_LINUX) ime_->Blur(); + nux::GetWindowThread()->GetGraphicsDisplay().XICUnFocus(); #endif //gtk_im_context_focus_out(im_context_); } === modified file 'NuxGraphics/Events.cpp' --- NuxGraphics/Events.cpp 2012-01-30 07:53:02 +0000 +++ NuxGraphics/Events.cpp 2013-05-24 18:35:29 +0000 @@ -22,7 +22,6 @@ #include "GLResource.h" #include "Events.h" - namespace nux { MouseButton GetEventButton(unsigned long button_state) @@ -60,7 +59,7 @@ Event::Event() { - Memset(text, 0, sizeof(text)); + dtext = nullptr; for (int i = 0; i < NUX_MAX_VK; i++) { @@ -101,7 +100,6 @@ void Event::Reset() { type = NUX_NO_EVENT; - Memset(text, 0, sizeof(text)); #if defined(NUX_OS_WINDOWS) win32_keycode = 0; win32_keysym = 0; @@ -113,6 +111,9 @@ x11_key_state = 0; #endif + delete[] dtext; + dtext = nullptr; + key_repeat_count = 0; key_modifiers = 0; wheel_delta = 0; @@ -210,7 +211,7 @@ const char* Event::GetText() const { - return text; + return dtext; } === modified file 'NuxGraphics/Events.h' --- NuxGraphics/Events.h 2012-02-07 22:51:46 +0000 +++ NuxGraphics/Events.h 2013-05-24 18:35:29 +0000 @@ -401,7 +401,11 @@ int wheel_delta; //!< Wheel delta. - char text[NUX_EVENT_TEXT_BUFFER_SIZE]; + // To avoid an ABI break + union { + char text[NUX_EVENT_TEXT_BUFFER_SIZE]; + char* dtext; //!< Dynamicly allocated text + }; unsigned long key_modifiers; //!< Key modifiers. A bitwise inclusive OR of values in KeyModifier. unsigned long mouse_state; unsigned short key_repeat_count; //!< Number of time a key is repeated; === modified file 'NuxGraphics/GraphicsDisplayX11.cpp' --- NuxGraphics/GraphicsDisplayX11.cpp 2012-07-20 17:48:02 +0000 +++ NuxGraphics/GraphicsDisplayX11.cpp 2013-05-24 18:35:29 +0000 @@ -35,6 +35,12 @@ #include +#include "XIMController.h" +#include + +// To avoid an ABI break... +std::shared_ptr m_xim_controller; + namespace nux { int GraphicsDisplay::double_click_time_delay = 400; // milliseconds @@ -184,7 +190,17 @@ return(event->type == MapNotify) && (event->xmap.window == (Window) arg); } -// TODO: change windowWidth, windowHeight, to window_size; + void GraphicsDisplay::XICFocus() + { + m_xim_controller->FocusInXIC(); + } + + void GraphicsDisplay::XICUnFocus() + { + m_xim_controller->FocusOutXIC(); + } + + // TODO: change windowWidth, windowHeight, to window_size; static NCriticalSection CreateOpenGLWindow_CriticalSection; bool GraphicsDisplay::CreateOpenGLWindow(const char *WindowTitle, unsigned int WindowWidth, @@ -568,6 +584,16 @@ //XMapRaised(m_X11Display, m_X11Window); } + m_xim_controller = std::make_shared(m_X11Display); + m_xim_controller->SetFocusedWindow(m_X11Window); + + if (m_xim_controller->IsXICValid()) + { + long im_event_mask=0; + XGetICValues(m_xim_controller->GetXIC(), XNFilterEvents, &im_event_mask, NULL); + m_X11Attr.event_mask |= im_event_mask; + } + #ifndef NUX_OPENGLES_20 if (_has_glx_13) { @@ -673,6 +699,16 @@ m_GfxInterfaceCreated = true; + m_xim_controller = std::make_shared(m_X11Display); + m_xim_controller->SetFocusedWindow(m_X11Window); + + if (m_xim_controller->IsXICValid()) + { + long im_event_mask=0; + XGetICValues(m_xim_controller->GetXIC(), XNFilterEvents, &im_event_mask, NULL); + m_X11Attr.event_mask |= im_event_mask; + } + // m_DeviceFactory = new GpuDevice(m_ViewportSize.GetWidth(), m_ViewportSize.GetHeight(), BITFMT_R8G8B8A8); m_DeviceFactory = new GpuDevice(m_ViewportSize.width, m_ViewportSize.height, BITFMT_R8G8B8A8, m_X11Display, @@ -700,6 +736,11 @@ return m_DeviceFactory; } + void GraphicsDisplay::SetFocusedWindowForXIMController(Window window) + { + m_xim_controller->SetFocusedWindow(window); + } + int GraphicsDisplay::GetGlXMajor() const { return _glx_major; @@ -1230,6 +1271,9 @@ { XNextEvent(m_X11Display, &xevent); + if (XFilterEvent(&xevent, None) == True) + return; + if (!_event_filters.empty()) { for (auto filter : _event_filters) @@ -1535,6 +1579,8 @@ m_pEvent->dy = 0; m_pEvent->virtual_code = 0; //nuxDebugMsg("[GraphicsDisplay::ProcessXEvents]: FocusIn event."); + + m_xim_controller->FocusInXIC(); break; } @@ -1550,6 +1596,8 @@ m_pEvent->dy = 0; m_pEvent->virtual_code = 0; //nuxDebugMsg("[GraphicsDisplay::ProcessXEvents]: FocusOut event."); + + m_xim_controller->FocusOutXIC(); break; } @@ -1579,14 +1627,44 @@ //temporary fix for TextEntry widget: filter some keys skip = true; } - - int num_char_stored = XLookupString(&xevent.xkey, buffer, NUX_EVENT_TEXT_BUFFER_SIZE, (KeySym*) &m_pEvent->x11_keysym, NULL); - if (num_char_stored && (!skip)) - { - Memcpy(m_pEvent->text, buffer, num_char_stored); - } - - break; + + if (!skip) + { + int num_char_stored = 0; + if (m_xim_controller->IsXICValid()) + { + delete[] m_pEvent->dtext; + m_pEvent->dtext = nullptr; + + num_char_stored = XmbLookupString(m_xim_controller->GetXIC(), &xevent.xkey, nullptr, + 0, (KeySym*) &m_pEvent->x11_keysym, nullptr); + + if (num_char_stored > 0) + { + int buf_len = num_char_stored + 1; + m_pEvent->dtext = new char[buf_len]; + num_char_stored = XmbLookupString(m_xim_controller->GetXIC(), &xevent.xkey, m_pEvent->dtext, + buf_len, (KeySym*) &m_pEvent->x11_keysym, nullptr); + + m_pEvent->dtext[num_char_stored] = 0; + } + } + else + { + m_pEvent->dtext = new char[NUX_EVENT_TEXT_BUFFER_SIZE]; + num_char_stored = XLookupString(&xevent.xkey, m_pEvent->dtext, NUX_EVENT_TEXT_BUFFER_SIZE, + (KeySym*) &m_pEvent->x11_keysym, nullptr); + + m_pEvent->dtext[num_char_stored] = 0; + } + } + + if (m_pEvent->dtext == nullptr) + { + m_pEvent->dtext = new char[NUX_EVENT_TEXT_BUFFER_SIZE]; + m_pEvent->dtext[0] = 0; + } + break; } case KeyRelease: === modified file 'NuxGraphics/GraphicsDisplayX11.h' --- NuxGraphics/GraphicsDisplayX11.h 2012-01-26 23:01:57 +0000 +++ NuxGraphics/GraphicsDisplayX11.h 2013-05-24 18:35:29 +0000 @@ -35,7 +35,6 @@ /* keysym.h contains keysymbols which we use to resolv what keys that are being pressed */ #include - #include #include @@ -283,6 +282,8 @@ GpuDevice* GetGpuDevice() const; + void SetFocusedWindowForXIMController(Window window); + // Dialog /*bool StartOpenFileDialog(FileDialogOption& fdo); bool StartSaveFileDialog(FileDialogOption& fdo); @@ -342,6 +343,8 @@ void * KeyboardGrabData() { return _global_keyboard_grab_data; } void * PointerGrabData() { return _global_pointer_grab_data; } + void XICFocus(); + void XICUnFocus(); private: void InitGlobalGrabWindow(); === modified file 'NuxGraphics/Makefile.am' --- NuxGraphics/Makefile.am 2012-03-23 12:19:32 +0000 +++ NuxGraphics/Makefile.am 2013-05-24 18:35:29 +0000 @@ -1,4 +1,4 @@ -CLEANFILES = +CLEANFILES = DISTCLEANFILES = EXTRA_DIST = $(srcdir)/GraphicsDisplayWin.cpp \ $(srcdir)/GraphicsDisplayWin.h @@ -85,7 +85,9 @@ $(srcdir)/RenderingPipeTextureBlendShaderSource.h \ $(srcdir)/RunTimeStats.h \ $(srcdir)/VirtualKeyCodesX11.h \ - $(srcdir)/XInputWindow.h + $(srcdir)/XICClient.h \ + $(srcdir)/XInputWindow.h \ + $(srcdir)/XIMController.h source_cpp = \ $(srcdir)/Events.cpp \ @@ -143,7 +145,9 @@ $(srcdir)/RenderingPipeTextureBlend.cpp \ $(srcdir)/GLRenderingAPI.cpp \ $(srcdir)/RunTimeStats.cpp \ - $(srcdir)/XInputWindow.cpp + $(srcdir)/XICClient.cpp \ + $(srcdir)/XInputWindow.cpp \ + $(srcdir)/XIMController.cpp libnux_graphics_@NUX_API_VERSION@_la_SOURCES = \ $(source_cpp) \ === added file 'NuxGraphics/XICClient.cpp' --- NuxGraphics/XICClient.cpp 1970-01-01 00:00:00 +0000 +++ NuxGraphics/XICClient.cpp 2013-05-24 18:35:29 +0000 @@ -0,0 +1,112 @@ +/* +* Copyright 2012-2013 Inalogic® Inc. +* +* This program is free software: you can redistribute it and/or modify it +* under the terms of the GNU Lesser General Public License, as +* published by the Free Software Foundation; either version 2.1 or 3.0 +* of the License. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranties of +* MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR +* PURPOSE. See the applicable version of the GNU Lesser General Public +* License for more details. +* +* You should have received a copy of both the GNU Lesser General Public +* License along with this program. If not, see +* +* Authored by: Brandon Schaefer +* +*/ + +#include "XICClient.h" + +namespace nux +{ + +XICClient::XICClient() + : xic_(NULL) + , xim_style_(0) + , focused_(false) +{ +} + +void XICClient::ResetXIC(XIM xim, Window window) +{ + if (!xim_style_) + SetupXIMStyle(xim); + SetupXIC(xim, window); +} + +void XICClient::SetupXIC(XIM xim, Window window) +{ + xic_ = XCreateIC(xim, XNInputStyle, xim_style_, XNClientWindow, window, XNFocusWindow, window, NULL); +} + +void XICClient::SetupXIMStyle(XIM xim) +{ + int i; + XIMStyles *xim_styles = NULL; + XIMStyle root_style = (XIMPreeditNothing|XIMStatusNothing); + + XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL); + + for (i = 0; i < xim_styles->count_styles; ++i) + if (xim_styles->supported_styles[i] == root_style) + break; + + if (i >= xim_styles->count_styles) + xim_style_ = 0; + xim_style_ = root_style; +} + +bool XICClient::HasXIC() const +{ + return xic_ != NULL; +} + +XIC XICClient::GetXIC() const +{ + return xic_; +} + +void XICClient::Reinitialize() +{ + xic_ = NULL; + xim_style_ = 0; + focused_ = false; +} + +void XICClient::FocusInXIC() +{ + if (xic_ && !focused_) + { + XSetICFocus(xic_); + focused_ = true; + } +} + +void XICClient::FocusOutXIC() +{ + if (xic_ && focused_) + { + XUnsetICFocus(xic_); + focused_ = false; + } +} + +bool XICClient::IsFocused() const +{ + return focused_; +} + +void XICClient::DestroyXIC() +{ + if (xic_) + { + XDestroyIC(xic_); + xic_ = NULL; + } +} + +} //namespace nux === added file 'NuxGraphics/XICClient.h' --- NuxGraphics/XICClient.h 1970-01-01 00:00:00 +0000 +++ NuxGraphics/XICClient.h 2013-05-24 18:35:29 +0000 @@ -0,0 +1,60 @@ +/* +* Copyright 2012-2013 Inalogic® Inc. +* +* This program is free software: you can redistribute it and/or modify it +* under the terms of the GNU Lesser General Public License, as +* published by the Free Software Foundation; either version 2.1 or 3.0 +* of the License. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranties of +* MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR +* PURPOSE. See the applicable version of the GNU Lesser General Public +* License for more details. +* +* You should have received a copy of both the GNU Lesser General Public +* License along with this program. If not, see +* +* Authored by: Brandon Schaefer +* +*/ + +#ifndef XICCLIENT_H +#define XICCLIENT_H + +/* Xlib.h is the default header that is included and has the core functionallity */ +#include + +namespace nux +{ + +class XICClient +{ +public: + XICClient(); + + void ResetXIC(XIM xim, Window window); + + bool HasXIC() const; + XIC GetXIC() const; + + void Reinitialize(); + + void FocusInXIC(); + void FocusOutXIC(); + bool IsFocused() const; + + void DestroyXIC(); +private: + void SetupXIC(XIM xim, Window window); + void SetupXIMStyle(XIM xim); + + XIC xic_; + XIMStyle xim_style_; + + bool focused_; +}; + +} //namespace nux + +#endif // XICClient.h === added file 'NuxGraphics/XIMController.cpp' --- NuxGraphics/XIMController.cpp 1970-01-01 00:00:00 +0000 +++ NuxGraphics/XIMController.cpp 2013-05-24 18:35:29 +0000 @@ -0,0 +1,146 @@ +/* +* Copyright 2012-2013 Inalogic® Inc. +* +* This program is free software: you can redistribute it and/or modify it +* under the terms of the GNU Lesser General Public License, as +* published by the Free Software Foundation; either version 2.1 or 3.0 +* of the License. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranties of +* MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR +* PURPOSE. See the applicable version of the GNU Lesser General Public +* License for more details. +* +* You should have received a copy of both the GNU Lesser General Public +* License along with this program. If not, see +* +* Authored by: Brandon Schaefer +* +*/ + +#include + +#include "XIMController.h" +#include "NuxCore/Logger.h" + +namespace nux +{ + +logging::Logger logger("xim.controller"); + +XIMController::XIMController(Display* display) + : display_(display) + , window_(0) + , xim_(NULL) +{ + InitXIMCallback(); +} + +XIMController::~XIMController() +{ + // The XIC must be destroyed before the XIM + if (xic_client_.HasXIC()) + xic_client_.DestroyXIC(); + + if (xim_) + XCloseIM(xim_); +} + +void XIMController::SetFocusedWindow(Window window) +{ + window_ = window; + if (xim_) + xic_client_.ResetXIC(xim_, window); +} + +bool XIMController::IsXICValid() const +{ + return xic_client_.HasXIC(); +} + +XIC XIMController::GetXIC() const +{ + return xic_client_.GetXIC(); +} + +void XIMController::FocusInXIC() +{ + xic_client_.FocusInXIC(); +} + +void XIMController::FocusOutXIC() +{ + xic_client_.FocusOutXIC(); +} + +void XIMController::InitXIMCallback() +{ + char* const xmodifier = getenv("XMODIFIERS"); + + if (xmodifier && strstr(xmodifier,"ibus") != NULL) + { + LOG_WARN(logger) << "IBus natively supported."; + return; + } + + if (setlocale(LC_ALL, "") == NULL) + { + LOG_WARN(logger) << "Cannot setlocale."; + } + + if (XSupportsLocale()) + { + if (XSetLocaleModifiers("") == NULL) + { + LOG_WARN(logger) << "XSetLocalModifiers Failed."; + } + XRegisterIMInstantiateCallback(display_, NULL, NULL, NULL, + XIMController::SetupXIMClientCallback, + (XPointer)this); + } +} + +void XIMController::SetupXIMClientCallback(Display* dpy, XPointer client_data, XPointer call_data) +{ + XIMController* self = (XIMController*)client_data; + self->SetupXIM(); +} + +void XIMController::EndXIMClientCallback(Display* dpy, XPointer client_data, XPointer call_data) +{ + XIMController* self = (XIMController*)client_data; + self->xim_ = NULL; + self->xic_client_.Reinitialize(); + self->InitXIMCallback(); +} + +void XIMController::SetupXIM() +{ + xim_ = XOpenIM(display_, NULL, NULL, NULL); + if (xim_) + { + SetupXIMDestroyedCallback(); + + if (window_) + xic_client_.ResetXIC(xim_, window_); + + XUnregisterIMInstantiateCallback (display_, NULL, NULL, NULL, + XIMController::SetupXIMClientCallback, + (XPointer)this); + } + else + { + LOG_WARN(logger) << "Failed to open IM."; + } +} + +void XIMController::SetupXIMDestroyedCallback() +{ + XIMCallback destroy_callback; + destroy_callback.callback = (XIMProc)XIMController::EndXIMClientCallback; + destroy_callback.client_data = (XPointer)this; + XSetIMValues (xim_, XNDestroyCallback, &destroy_callback, NULL); +} + +} //namespace nux === added file 'NuxGraphics/XIMController.h' --- NuxGraphics/XIMController.h 1970-01-01 00:00:00 +0000 +++ NuxGraphics/XIMController.h 2013-05-24 18:35:29 +0000 @@ -0,0 +1,62 @@ +/* +* Copyright 2012-2013 Inalogic® Inc. +* +* This program is free software: you can redistribute it and/or modify it +* under the terms of the GNU Lesser General Public License, as +* published by the Free Software Foundation; either version 2.1 or 3.0 +* of the License. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranties of +* MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR +* PURPOSE. See the applicable version of the GNU Lesser General Public +* License for more details. +* +* You should have received a copy of both the GNU Lesser General Public +* License along with this program. If not, see +* +* Authored by: Brandon Schaefer +* +*/ + +#ifndef XIMCONTROLLER_H +#define XIMCONTROLLER_H + +#include "XICClient.h" + +/* Xlib.h is the default header that is included and has the core functionallity */ +#include + +namespace nux +{ + +class XIMController +{ +public: + XIMController(Display* display); + ~XIMController(); + + void SetFocusedWindow(Window window); + + bool IsXICValid() const; + XIC GetXIC() const; + + void FocusInXIC(); + void FocusOutXIC(); +private: + void InitXIMCallback(); + static void SetupXIMClientCallback(Display* dpy, XPointer client_data, XPointer call_data); + static void EndXIMClientCallback(Display* dpy, XPointer client_data, XPointer call_data); + + void SetupXIM(); + void SetupXIMDestroyedCallback(); + + Display* display_; + Window window_; + XIM xim_; + XICClient xic_client_; +}; + +} //namespace nux + +#endif // XIMController.h === modified file 'NuxGraphics/XInputWindow.cpp' --- NuxGraphics/XInputWindow.cpp 2012-01-18 21:08:29 +0000 +++ NuxGraphics/XInputWindow.cpp 2013-05-24 18:35:29 +0000 @@ -22,6 +22,8 @@ #include "XInputWindow.h" #include "GraphicsDisplayX11.h" #include "GLThread.h" +#include "XIMController.h" + // Jay, what is this for? It isn't referenced anywhere. #define xdnd_version 5 @@ -374,8 +376,9 @@ void XInputWindow::Show() { + GetGraphicsDisplay()->SetFocusedWindowForXIMController(window_); + shown_ = true; - if (!mapped_) { XMapRaised(display_, window_);