From 1eab99d70c0b300757b5c187a6ead58c51344de7 Mon Sep 17 00:00:00 2001 From: crs Date: Sun, 22 Jun 2003 21:27:38 +0000 Subject: [PATCH] Added support for input methods. Only handling IMs that don't need a precompose area or status area. This includes IMs that do simple dead key composition. This only changes the server. The client still does not decompose a character it cannot generate directly into the keysyms to compose the character. --- lib/platform/CXWindowsPrimaryScreen.cpp | 116 +++++++++++++++++++++++- lib/platform/CXWindowsPrimaryScreen.h | 4 + 2 files changed, 116 insertions(+), 4 deletions(-) diff --git a/lib/platform/CXWindowsPrimaryScreen.cpp b/lib/platform/CXWindowsPrimaryScreen.cpp index 10ddc6eb..e3538cef 100644 --- a/lib/platform/CXWindowsPrimaryScreen.cpp +++ b/lib/platform/CXWindowsPrimaryScreen.cpp @@ -40,7 +40,9 @@ CXWindowsPrimaryScreen::CXWindowsPrimaryScreen( IPrimaryScreenReceiver* primaryReceiver) : CPrimaryScreen(receiver), m_receiver(primaryReceiver), - m_window(None) + m_window(None), + m_im(NULL), + m_ic(NULL) { m_screen = new CXWindowsScreen(receiver, this); } @@ -220,6 +222,11 @@ CXWindowsPrimaryScreen::onEvent(CEvent* event) assert(event != NULL); XEvent& xevent = event->m_event; + // let input methods try to handle event first + if (m_ic != NULL && XFilterEvent(&xevent, None)) { + return true; + } + // handle event switch (xevent.type) { case CreateNotify: @@ -455,18 +462,88 @@ CXWindowsPrimaryScreen::onPostOpen() // get cursor info m_screen->getCursorPos(m_x, m_y); m_screen->getCursorCenter(m_xCenter, m_yCenter); + + // get the input method + CDisplayLock display(m_screen); + m_im = XOpenIM(display, NULL, NULL, NULL); + if (m_im == NULL) { + return; + } + + // find the appropriate style. synergy supports XIMPreeditNothing + // only at the moment. + XIMStyles* styles; + if (XGetIMValues(m_im, XNQueryInputStyle, &styles, NULL) != NULL || + styles == NULL) { + LOG((CLOG_WARN "cannot get IM styles")); + return; + } + XIMStyle style = 0; + for (unsigned short i = 0; i < styles->count_styles; ++i) { + style = styles->supported_styles[i]; + if ((style & XIMPreeditNothing) != 0) { + if ((style & (XIMStatusNothing | XIMStatusNone)) != 0) { + break; + } + } + } + XFree(styles); + if (style == 0) { + LOG((CLOG_WARN "no supported IM styles")); + return; + } + + // create an input context for the style and tell it about our window + m_ic = XCreateIC(m_im, XNInputStyle, style, XNClientWindow, m_window, NULL); + if (m_ic == NULL) { + LOG((CLOG_WARN "cannot create IC")); + return; + } + + // find out the events we must select for and do so + unsigned long mask; + if (XGetICValues(m_ic, XNFilterEvents, &mask, NULL) != NULL) { + LOG((CLOG_WARN "cannot get IC filter events")); + return; + } + XWindowAttributes attr; + XGetWindowAttributes(display, m_window, &attr); + XSelectInput(display, m_window, attr.your_event_mask | mask); +} + +void +CXWindowsPrimaryScreen::onPreClose() +{ + CDisplayLock display(m_screen); + if (m_ic != NULL) { + XDestroyIC(m_ic); + m_ic = NULL; + } + if (m_im != NULL) { + XCloseIM(m_im); + m_im = NULL; + } } void CXWindowsPrimaryScreen::onPreEnter() { assert(m_window != None); + + if (m_ic != NULL) { + XUnsetICFocus(m_ic); + } } void CXWindowsPrimaryScreen::onPreLeave() { assert(m_window != None); + + if (m_ic != NULL) { + XmbResetIC(m_ic); + XSetICFocus(m_ic); + } } void @@ -765,10 +842,41 @@ CXWindowsPrimaryScreen::mapKey(XKeyEvent* event) const CDisplayLock display(m_screen); // convert to a keysym - // FIXME -- we're not properly handling unicode KeySym keysym; - char dummy[1]; - XLookupString(event, dummy, 0, &keysym, NULL); + if (event->type == KeyPress && m_ic != NULL) { + // do multibyte lookup. can only call XmbLookupString with a + // key press event and a valid XIC so we checked those above. + char scratch[32]; + int n = sizeof(scratch) / sizeof(scratch[0]); + char* buffer = scratch; + int status; + n = XmbLookupString(m_ic, event, buffer, n, &keysym, &status); + if (status == XBufferOverflow) { + // not enough space. grow buffer and try again. + buffer = new char[n]; + n = XmbLookupString(m_ic, event, buffer, n, &keysym, &status); + delete[] buffer; + } + + // see what we got. since we don't care about the string + // we'll just look for a keysym. + switch (status) { + default: + case XLookupNone: + case XLookupChars: + keysym = 0; + break; + + case XLookupKeySym: + case XLookupBoth: + break; + } + } + else { + // plain old lookup + char dummy[1]; + XLookupString(event, dummy, 0, &keysym, NULL); + } // convert key switch (keysym & 0xffffff00) { diff --git a/lib/platform/CXWindowsPrimaryScreen.h b/lib/platform/CXWindowsPrimaryScreen.h index 5ac54356..828f73e6 100644 --- a/lib/platform/CXWindowsPrimaryScreen.h +++ b/lib/platform/CXWindowsPrimaryScreen.h @@ -57,6 +57,7 @@ protected: virtual void onPreMainLoop(); virtual void onPreOpen(); virtual void onPostOpen(); + virtual void onPreClose(); virtual void onPreEnter(); virtual void onPreLeave(); virtual void onEnterScreenSaver(); @@ -115,6 +116,9 @@ private: // position of center pixel of screen SInt32 m_xCenter, m_yCenter; + + XIM m_im; + XIC m_ic; }; #endif