mirror of https://github.com/AxioDL/boo.git
Working Input Method support
This commit is contained in:
parent
aab693ff2f
commit
a933edcc40
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -185,7 +185,7 @@ struct WindowWayland : IWindow
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void claimKeyboardFocus()
|
void claimKeyboardFocus(const int coord[2])
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue