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.
This commit is contained in:
crs 2003-06-22 21:27:38 +00:00
parent 48965e2381
commit 1eab99d70c
2 changed files with 116 additions and 4 deletions

View File

@ -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;
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) {

View File

@ -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