mirror of
https://github.com/gryf/wmaker.git
synced 2025-12-19 20:38:08 +01:00
XKeycodeToKeysym was deprecated some time ago and we replaced those function calls to XkbKeycodeToKeysym. Usage of XkbKeycodeToKeysym is not the best as it appears the XKEYBOARD can be disabled via xorg.conf (at least on Linux). So just replacing XKeycodeToKeysym() with XkbKeycodeToKeysym() could cause run-time errors on top of the compilation warning we may have. Better fix is to address the problem without introducing a dependency on XKEYBOARD. W_KeycodeToKeysym is the equivalent code for XKeycodeToKeysym/XkbKeycodeToKeysym using XGetKeyboardMapping instead. As a new function is added to the library WINGs library version is bumped.
248 lines
6.0 KiB
C
248 lines
6.0 KiB
C
|
|
#include <X11/Xlib.h>
|
|
|
|
#include "wconfig.h"
|
|
|
|
#include "WINGsP.h"
|
|
|
|
typedef struct W_IMContext {
|
|
XIM xim;
|
|
XIMStyle ximstyle;
|
|
} WMIMContext;
|
|
|
|
static void instantiateIM_cb(Display * display, XPointer client_data, XPointer call_data)
|
|
{
|
|
/* Parameter not used, but tell the compiler that it is ok */
|
|
(void) display;
|
|
(void) call_data;
|
|
|
|
W_InitIM((W_Screen *) client_data);
|
|
}
|
|
|
|
static void destroyIM_cb(XIM xim, XPointer client_data, XPointer call_data)
|
|
{
|
|
W_Screen *scr = (W_Screen *) client_data;
|
|
W_View *target;
|
|
|
|
/* Parameter not used, but tell the compiler that it is ok */
|
|
(void) call_data;
|
|
|
|
if (scr->imctx->xim != xim)
|
|
return;
|
|
|
|
target = scr->rootView->childrenList;
|
|
while (target != NULL) {
|
|
W_DestroyIC(target);
|
|
target = target->nextSister;
|
|
}
|
|
|
|
wfree(scr->imctx);
|
|
scr->imctx = NULL;
|
|
|
|
XRegisterIMInstantiateCallback(scr->display, NULL, NULL, NULL, instantiateIM_cb, (XPointer) scr);
|
|
}
|
|
|
|
void W_InitIM(W_Screen * scr)
|
|
{
|
|
XIM xim;
|
|
|
|
if (scr->imctx)
|
|
return;
|
|
|
|
xim = XOpenIM(scr->display, NULL, NULL, NULL);
|
|
|
|
if (xim) {
|
|
XIMStyles *im_styles;
|
|
XIMCallback cb;
|
|
int i;
|
|
|
|
scr->imctx = wmalloc(sizeof(WMIMContext));
|
|
scr->imctx->xim = xim;
|
|
|
|
cb.callback = destroyIM_cb;
|
|
cb.client_data = (XPointer) scr;
|
|
if (XSetIMValues(scr->imctx->xim, XNDestroyCallback, &cb, NULL))
|
|
wwarning(_("could not add destroy callback for XIM input method"));
|
|
XUnregisterIMInstantiateCallback(scr->display, NULL, NULL, NULL, instantiateIM_cb, (XPointer) scr);
|
|
/* Get available input style */
|
|
XGetIMValues(scr->imctx->xim, XNQueryInputStyle, &im_styles, NULL);
|
|
|
|
scr->imctx->ximstyle = 0;
|
|
|
|
for (i = 0; i < im_styles->count_styles && scr->imctx->ximstyle == 0; i++) {
|
|
if ((im_styles->supported_styles[i] & XIMPreeditPosition) &&
|
|
(im_styles->supported_styles[i] & XIMStatusNothing)) {
|
|
scr->imctx->ximstyle = XIMPreeditPosition | XIMStatusNothing;
|
|
} else if ((im_styles->supported_styles[i] & XIMPreeditNothing) &&
|
|
(im_styles->supported_styles[i] & XIMStatusNothing)) {
|
|
scr->imctx->ximstyle = XIMPreeditNothing | XIMStatusNothing;
|
|
}
|
|
}
|
|
XFree(im_styles);
|
|
} else {
|
|
XRegisterIMInstantiateCallback(scr->display, NULL, NULL, NULL, instantiateIM_cb, (XPointer) scr);
|
|
}
|
|
}
|
|
|
|
void W_CreateIC(WMView * view)
|
|
{
|
|
WMScreen *scr = W_VIEW_SCREEN(view);
|
|
XVaNestedList preedit_attr = NULL;
|
|
|
|
if (view->xic || !view->flags.realized || !scr->imctx)
|
|
return;
|
|
|
|
if (scr->imctx->ximstyle & XIMPreeditPosition) {
|
|
XPoint spot;
|
|
XRectangle rect;
|
|
int ofs;
|
|
|
|
ofs = (view->size.height - WMFontHeight(scr->normalFont)) / 2;
|
|
|
|
rect.x = ofs;
|
|
rect.y = ofs;
|
|
rect.height = WMFontHeight(scr->normalFont);
|
|
rect.width = view->size.width - ofs * 2;
|
|
spot.x = rect.x;
|
|
spot.y = rect.y + rect.height;
|
|
|
|
// this really needs to be changed, but I don't know how yet -Dan
|
|
// it used to be like this with fontsets, but no longer applies to xft
|
|
preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &spot,
|
|
XNArea, &rect, XNFontInfo, scr->normalFont->font, NULL);
|
|
}
|
|
|
|
view->xic = XCreateIC(scr->imctx->xim, XNInputStyle, scr->imctx->ximstyle,
|
|
XNClientWindow, view->window,
|
|
preedit_attr ? XNPreeditAttributes : NULL, preedit_attr, NULL);
|
|
|
|
if (preedit_attr)
|
|
XFree(preedit_attr);
|
|
|
|
if (view->xic) {
|
|
unsigned long fevent = 0;
|
|
XGetICValues(view->xic, XNFilterEvents, &fevent, NULL);
|
|
XSelectInput(scr->display, view->window,
|
|
ButtonPressMask | ButtonReleaseMask | ExposureMask |
|
|
KeyPressMask | FocusChangeMask | ButtonMotionMask | fevent);
|
|
}
|
|
}
|
|
|
|
void W_DestroyIC(WMView * view)
|
|
{
|
|
if (view->xic) {
|
|
XDestroyIC(view->xic);
|
|
view->xic = 0;
|
|
}
|
|
}
|
|
|
|
static void setPreeditArea(W_View * view)
|
|
{
|
|
WMScreen *scr = W_VIEW_SCREEN(view);
|
|
XVaNestedList preedit_attr = NULL;
|
|
|
|
if (view->xic && (scr->imctx->ximstyle & XIMPreeditPosition)) {
|
|
XRectangle rect;
|
|
int ofs;
|
|
|
|
ofs = (view->size.height - WMFontHeight(scr->normalFont)) / 2;
|
|
rect.x = ofs;
|
|
rect.y = ofs;
|
|
rect.height = WMFontHeight(scr->normalFont);
|
|
rect.width = view->size.width - ofs * 2;
|
|
|
|
preedit_attr = XVaCreateNestedList(0, XNArea, &rect, NULL);
|
|
XSetICValues(view->xic, XNPreeditAttributes, preedit_attr, NULL);
|
|
|
|
if (preedit_attr) {
|
|
XFree(preedit_attr);
|
|
}
|
|
}
|
|
}
|
|
|
|
void W_FocusIC(WMView * view)
|
|
{
|
|
WMScreen *scr = W_VIEW_SCREEN(view);
|
|
|
|
if (view->xic) {
|
|
XSetICFocus(view->xic);
|
|
XSetICValues(view->xic, XNFocusWindow, view->window, NULL);
|
|
|
|
if (scr->imctx->ximstyle & XIMPreeditPosition) {
|
|
setPreeditArea(view);
|
|
}
|
|
}
|
|
}
|
|
|
|
void W_UnFocusIC(WMView * view)
|
|
{
|
|
if (view->xic) {
|
|
XUnsetICFocus(view->xic);
|
|
}
|
|
}
|
|
|
|
void W_SetPreeditPositon(W_View * view, int x, int y)
|
|
{
|
|
WMScreen *scr = W_VIEW_SCREEN(view);
|
|
XVaNestedList preedit_attr = NULL;
|
|
|
|
if (view->xic && (scr->imctx->ximstyle & XIMPreeditPosition)) {
|
|
XPoint spot;
|
|
int ofs;
|
|
|
|
ofs = (view->size.height - WMFontHeight(scr->normalFont)) / 2;
|
|
spot.x = x;
|
|
spot.y = y + view->size.height - ofs - 3;
|
|
preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &spot, NULL);
|
|
XSetICValues(view->xic, XNPreeditAttributes, preedit_attr, NULL);
|
|
if (preedit_attr) {
|
|
XFree(preedit_attr);
|
|
}
|
|
}
|
|
}
|
|
|
|
int W_LookupString(W_View *view, XKeyPressedEvent *event, char *buffer, int buflen, KeySym *keysym, Status *status)
|
|
{
|
|
WMScreen *scr = W_VIEW_SCREEN(view);
|
|
|
|
XSetInputFocus(scr->display, view->window, RevertToParent, CurrentTime);
|
|
|
|
#ifdef X_HAVE_UTF8_STRING
|
|
if (view->xic)
|
|
return Xutf8LookupString(view->xic, event, buffer, buflen, keysym, status);
|
|
#endif
|
|
return XLookupString(event, buffer, buflen, keysym, (XComposeStatus *) status);
|
|
}
|
|
|
|
/*
|
|
* Map a keycode to the corresponding keysym
|
|
* To replace the deprecated X11 function XKeycodeToKeysym
|
|
*/
|
|
KeySym W_KeycodeToKeysym(Display *display, KeyCode keycode, int index)
|
|
{
|
|
static int min_kc = -1;
|
|
static int max_kc;
|
|
int num_syms;
|
|
KeySym *key_syms;
|
|
KeySym ks;
|
|
|
|
if (min_kc == -1) {
|
|
(void) XDisplayKeycodes(display, &min_kc, &max_kc);
|
|
}
|
|
|
|
if (keycode < min_kc || keycode > max_kc || index < 0) {
|
|
return NoSymbol;
|
|
}
|
|
|
|
key_syms = XGetKeyboardMapping(display, keycode, 1, &num_syms);
|
|
if (index >= num_syms) {
|
|
XFree(key_syms);
|
|
return NoSymbol;
|
|
}
|
|
|
|
ks = key_syms[index];
|
|
XFree(key_syms);
|
|
|
|
return ks;
|
|
}
|