Working Input Method support

This commit is contained in:
Jack Andersen 2015-12-24 10:55:23 -10:00
parent aab693ff2f
commit a933edcc40
4 changed files with 50 additions and 115 deletions

View File

@ -139,6 +139,7 @@ public:
virtual void modKeyDown(EModifierKey mod, bool isRepeat) virtual void modKeyDown(EModifierKey mod, bool isRepeat)
{(void)mod;(void)isRepeat;} {(void)mod;(void)isRepeat;}
virtual void modKeyUp(EModifierKey mod) {(void)mod;} virtual void modKeyUp(EModifierKey mod) {(void)mod;}
virtual void utf8FragmentDown(const std::string& str) {(void)str;}
virtual void focusLost() {} virtual void focusLost() {}
virtual void focusGained() {} virtual void focusGained() {}
virtual void windowMoved(const SWindowRect& rect) virtual void windowMoved(const SWindowRect& rect)
@ -220,7 +221,7 @@ public:
virtual bool isFullscreen() const=0; virtual bool isFullscreen() const=0;
virtual void setFullscreen(bool fs)=0; virtual void setFullscreen(bool fs)=0;
virtual void claimKeyboardFocus()=0; virtual void claimKeyboardFocus(const int coord[2])=0;
virtual bool clipboardCopy(EClipboardType type, const uint8_t* data, size_t sz)=0; virtual bool clipboardCopy(EClipboardType type, const uint8_t* data, size_t sz)=0;
virtual std::unique_ptr<uint8_t[]> clipboardPaste(EClipboardType type, size_t& sz)=0; virtual std::unique_ptr<uint8_t[]> clipboardPaste(EClipboardType type, size_t& sz)=0;

View File

@ -25,7 +25,7 @@ DBusConnection* RegisterDBus(const char* appName, bool& isFirst);
namespace boo namespace boo
{ {
static LogVisor::LogModule Log("boo::ApplicationXCB"); static LogVisor::LogModule Log("boo::ApplicationXlib");
XlibCursors X_CURSORS; XlibCursors X_CURSORS;
int XCB_GLX_EVENT_BASE = 0; int XCB_GLX_EVENT_BASE = 0;
@ -266,7 +266,6 @@ public:
return; return;
} }
/* Create the fontset */
char** missing_charsets; char** missing_charsets;
int num_missing_charsets = 0; int num_missing_charsets = 0;
char* default_string; char* default_string;
@ -275,28 +274,14 @@ public:
-misc-fixed-*-r-*-*-*-130-*-*-*-*-*-*", -misc-fixed-*-r-*-*-*-130-*-*-*-*-*-*",
&missing_charsets, &num_missing_charsets, &missing_charsets, &num_missing_charsets,
&default_string); &default_string);
/*
* if there are charsets for which no fonts can
* be found, print a warning message.
*/
if (num_missing_charsets > 0)
{
std::string warn("The following charsets are missing:\n");
for(int i=0 ; i<num_missing_charsets ; ++i)
warn += std::string(missing_charsets[i]) + '\n';
XFreeStringList(missing_charsets);
warn += "The string '" + std::string(default_string) + "' will be used in place.";
Log.report(LogVisor::Warning, warn.c_str());
}
/* figure out which styles the IM can support */ /* figure out which styles the IM can support */
XIMStyles* im_supported_styles; XIMStyles* im_supported_styles;
XIMStyle app_supported_styles; XIMStyle app_supported_styles;
XGetIMValues(m_xIM, XNQueryInputStyle, &im_supported_styles, nullptr); XGetIMValues(m_xIM, XNQueryInputStyle, &im_supported_styles, nullptr);
/* set flags for the styles our application can support */ /* set flags for the styles our application can support */
app_supported_styles = XIMPreeditNone | XIMPreeditNothing | XIMPreeditArea; app_supported_styles = XIMPreeditNone | XIMPreeditNothing | XIMPreeditPosition;
app_supported_styles |= XIMStatusNone | XIMStatusNothing | XIMStatusArea; app_supported_styles |= XIMStatusNone | XIMStatusNothing;
/* /*
* now look at each of the IM supported styles, and * now look at each of the IM supported styles, and
* chose the "best" one that we can support. * chose the "best" one that we can support.

View File

@ -185,7 +185,7 @@ struct WindowWayland : IWindow
} }
void claimKeyboardFocus() void claimKeyboardFocus(const int coord[2])
{ {
} }

View File

@ -70,7 +70,18 @@ void GLXEnableVSync(Display* disp, GLXWindow drawable);
extern int XINPUT_OPCODE; extern int XINPUT_OPCODE;
static uint32_t translateKeysym(XKeyEvent* ev, ESpecialKey& specialSym, EModifierKey& modifierSym, XIC xIC) static std::string translateUTF8(XKeyEvent* ev, XIC xIC)
{
char chs[512];
KeySym ks;
Status stat;
int len = Xutf8LookupString(xIC, ev, chs, 512, &ks, &stat);
if (len > 1 && (stat == XLookupChars || stat == XLookupBoth))
return std::string(chs, len);
return std::string();
}
static char translateKeysym(XKeyEvent* ev, ESpecialKey& specialSym, EModifierKey& modifierSym)
{ {
KeySym sym = XLookupKeysym(ev, 0); KeySym sym = XLookupKeysym(ev, 0);
@ -112,21 +123,10 @@ static uint32_t translateKeysym(XKeyEvent* ev, ESpecialKey& specialSym, EModifie
modifierSym = EModifierKey::Alt; modifierSym = EModifierKey::Alt;
else else
{ {
#if 0 char ch = 0;
unsigned n; KeySym ks;
XkbGetIndicatorState(d, XkbUseCoreKbd, &n); XLookupString(ev, (char*)&ch, 1, &ks, nullptr);
uint32_t utf = xkb_keysym_to_utf32(sym); return ch;
if ((n & 0x01) != 0 ^ (state & ShiftMask) != 0)
return toupper(utf);
else
return utf;
#endif
uint32_t utf = 0;
KeySym sym;
Status stat;
XmbLookupString(xIC, ev, (char*)&utf, 4, &sym, &stat);
if (stat == XLookupChars || stat == XLookupBoth)
return utf;
} }
return 0; return 0;
} }
@ -603,13 +603,17 @@ public:
* Now go create an IC using the style we chose. * Now go create an IC using the style we chose.
* Also set the window and fontset attributes now. * Also set the window and fontset attributes now.
*/ */
XVaNestedList list = XVaCreateNestedList(0, XNFontSet, fontset, nullptr); XPoint pt = {0,0};
XVaNestedList nlist;
m_xIC = XCreateIC(xIM, XNInputStyle, bestInputStyle, m_xIC = XCreateIC(xIM, XNInputStyle, bestInputStyle,
XNClientWindow, m_windowId, XNClientWindow, m_windowId,
XNPreeditAttributes, list, XNFocusWindow, m_windowId,
XNStatusAttributes, list, XNPreeditAttributes, nlist = XVaCreateNestedList(0,
XNSpotLocation, &pt,
XNFontSet, fontset,
nullptr),
nullptr); nullptr);
XFree(list); XFree(nlist);
if (m_xIC == nullptr) if (m_xIC == nullptr)
{ {
Log.report(LogVisor::FatalError, "Couldn't create input context."); Log.report(LogVisor::FatalError, "Couldn't create input context.");
@ -899,9 +903,20 @@ public:
} }
} m_clipData; } m_clipData;
void claimKeyboardFocus() void claimKeyboardFocus(const int coord[2])
{ {
XLockDisplay(m_xDisp); XLockDisplay(m_xDisp);
if (!coord)
{
XUnsetICFocus(m_xIC);
XUnlockDisplay(m_xDisp);
return;
}
getWindowFrame(m_wx, m_wy, m_ww, m_wh);
XPoint pt = {short(coord[0]), short(m_wh - coord[1])};
XVaNestedList list = XVaCreateNestedList(0, XNSpotLocation, &pt, nullptr);
XSetICValues(m_xIC, XNPreeditAttributes, list, nullptr);
XFree(list);
XSetICFocus(m_xIC); XSetICFocus(m_xIC);
XUnlockDisplay(m_xDisp); XUnlockDisplay(m_xDisp);
} }
@ -998,63 +1013,12 @@ public:
reply.xselection.property = se->property; reply.xselection.property = se->property;
if (se->target == S_ATOMS->m_targets) if (se->target == S_ATOMS->m_targets)
{ {
#if 0
if (se->selection == XA_PRIMARY)
{
std::vector<Atom> x(sel_formats.GetCount());
for (int i=0 ; i<sel_formats.GetCount() ; ++i)
{
x[i] = XAtom(sel_formats[i]);
}
XChangeProperty(m_xDisp, se->requestor, se->property, XA_ATOM,
32, 0, (unsigned char*)x.data(),
sel_formats.GetCount());
}
else if (se->selection == S_ATOMS->m_clipboard)
{
std::vector<Atom> x(data.GetCount());
for (int i=0 ; i<data.GetCount() ; ++i)
{
x[i] = data.GetKey(i);
}
XChangeProperty(m_xDisp, se->requestor, se->property, XA_ATOM,
32, 0, (unsigned char*)x.data(),
data.GetCount());
}
#endif
Atom ValidTargets[] = {GetClipboardTypeAtom(m_clipData.m_type)}; Atom ValidTargets[] = {GetClipboardTypeAtom(m_clipData.m_type)};
XChangeProperty(m_xDisp, se->requestor, se->property, XA_ATOM, XChangeProperty(m_xDisp, se->requestor, se->property, XA_ATOM,
32, 0, (unsigned char*)ValidTargets, m_clipData.m_type != EClipboardType::None); 32, 0, (unsigned char*)ValidTargets, m_clipData.m_type != EClipboardType::None);
} }
else else
{ {
#if 0
if (se->selection == XA_PRIMARY)
{
String fmt = XAtomName(se->target);
int i = sel_formats.Find(fmt);
if (i >= 0 && sel_ctrl)
{
String d = sel_ctrl->GetSelectionData(fmt);
XChangeProperty(m_xDisp, se->requestor, se->property, se->target, 8, PropModeReplace,
d, d.GetLength());
}
else
reply.xselection.property = 0;
}
else if (se->selection == S_ATOMS->m_clipboard)
{
int i = data.Find(se->target);
if (i >= 0)
{
String d = data[i].Render();
XChangeProperty(m_xDisp, se->requestor, se->property, se->target, 8, PropModeReplace,
d, d.GetLength());
}
else
reply.xselection.property = 0;
}
#endif
if (se->target == GetClipboardTypeAtom(m_clipData.m_type)) if (se->target == GetClipboardTypeAtom(m_clipData.m_type))
{ {
XChangeProperty(m_xDisp, se->requestor, se->property, se->target, 8, PropModeReplace, XChangeProperty(m_xDisp, se->requestor, se->property, se->target, 8, PropModeReplace,
@ -1256,27 +1220,6 @@ public:
m_ww = event->xconfigure.width; m_ww = event->xconfigure.width;
m_wh = event->xconfigure.height; m_wh = event->xconfigure.height;
if (m_bestStyle & XIMPreeditArea)
{
XRectangle preedit_area;
preedit_area.width = event->xconfigure.width*4/5;
preedit_area.height = 0;
GetPreferredGeometry(XNPreeditAttributes, &preedit_area);
preedit_area.x = event->xconfigure.width - preedit_area.width;
preedit_area.y = event->xconfigure.height - preedit_area.height;
SetGeometry(XNPreeditAttributes, &preedit_area);
}
if (m_bestStyle & XIMStatusArea)
{
XRectangle status_area;
status_area.width = event->xconfigure.width/5;
status_area.height = 0;
GetPreferredGeometry(XNStatusAttributes, &status_area);
status_area.x = 0;
status_area.y = event->xconfigure.height - status_area.height;
SetGeometry(XNStatusAttributes, &status_area);
}
if (m_callback) if (m_callback)
{ {
SWindowRect rect = SWindowRect rect =
@ -1293,7 +1236,13 @@ public:
EModifierKey modifierKey; EModifierKey modifierKey;
unsigned int state = event->xkey.state; unsigned int state = event->xkey.state;
event->xkey.state &= ~ControlMask; event->xkey.state &= ~ControlMask;
uint32_t charCode = translateKeysym(&event->xkey, specialKey, modifierKey, m_xIC); std::string utf8Frag = translateUTF8(&event->xkey, m_xIC);
if (utf8Frag.size())
{
m_callback->utf8FragmentDown(utf8Frag);
return;
}
char charCode = translateKeysym(&event->xkey, specialKey, modifierKey);
EModifierKey modifierMask = translateModifiers(state); EModifierKey modifierMask = translateModifiers(state);
if (charCode) if (charCode)
m_callback->charKeyDown(charCode, modifierMask, false); m_callback->charKeyDown(charCode, modifierMask, false);
@ -1312,7 +1261,7 @@ public:
EModifierKey modifierKey; EModifierKey modifierKey;
unsigned int state = event->xkey.state; unsigned int state = event->xkey.state;
event->xkey.state &= ~ControlMask; event->xkey.state &= ~ControlMask;
uint32_t charCode = translateKeysym(&event->xkey, specialKey, modifierKey, m_xIC); char charCode = translateKeysym(&event->xkey, specialKey, modifierKey);
EModifierKey modifierMask = translateModifiers(state); EModifierKey modifierMask = translateModifiers(state);
if (charCode) if (charCode)
m_callback->charKeyUp(charCode, modifierMask); m_callback->charKeyUp(charCode, modifierMask);