Rikki,
Please try to apply the following patch against the new CVS version (on /dlls/x11drv directory). This patch will allow keyboard.c to use your locale setting by the usage of xkb extension on X11R6. Please notice that this requires that you *don't have* xkbdisable on your XF86Config file (or XF86Config-4).
-------- Original Message -------- Subject: dead keys treatment using XmbLookupString Date: Wed, 08 Jan 2003 12:48:06 -0200 From: Mauro Carvalho Chehab mchehab@brturbo.com To: wine-patches@winehq.com
*Modifyied files*: keyboard.c window.c desktop.c *CVS Version*: 20021225
*Change Log: *Add dead key support using XmbLookupString on ToUnicode function, if *xkb* is available otherwise It falls back to the old code. The first Window will be used to define the XIC used by the functions. *
Author*: Mauro Carvalho Chehab mchehab@brturbo.com ______________________________________________________________________________________________
--- keyboard.c 8 Jan 2003 11:24:51 -0000 1.1 +++ keyboard.c 8 Jan 2003 14:30:53 -0000 @@ -1389,6 +1389,44 @@ wine_tsx11_unlock(); }
+#ifdef HAVE_XKB +static XIM xim = (XIM) NULL; +static XIC xic = (XIC) NULL; +#endif +/******************************************************************* + * KeyboardWindow (X11DRV.@) + * Called from desktop.c and window.c after Window creating + * This routine allows usage of XmbLookupString by ToUnicode. + * Only the first opened window will be used. It means that + * all windows will share the same locale. + * + */ +void X11DRV_KeyboardWindow (Display *display, Window w) +{ +#ifdef HAVE_XKB + char *p; + + if (xic) return; /* Only the first window will be used */ + + if ((p = XSetLocaleModifiers("")) != NULL && *p) + xim = XOpenIM(display, NULL, NULL, NULL); + if (!xim && (p = XSetLocaleModifiers("@im=none")) != NULL && *p) + xim = XOpenIM(display, NULL, NULL, NULL); + if (!xim) ERR_(key)( "Failed to open input method.\n"); + else { + xic = XCreateIC(xim, + XNInputStyle, XIMPreeditNothing | XIMStatusNothing, + XNClientWindow, w, + XNFocusWindow, w, + NULL); + if (!xic) { + ERR_(key)( "Failed to create input context.\n"); + XCloseIM(xim); + xim=NULL; + } + } +#endif +}
/*********************************************************************** * X11DRV_MappingNotify @@ -1741,6 +1779,7 @@ * FIXME : should do the above (return 2 for non matching deadchar+char combinations) * */ + INT X11DRV_ToUnicode(UINT virtKey, UINT scanCode, LPBYTE lpKeyState, LPWSTR bufW, int bufW_size, UINT flags) { @@ -1756,6 +1795,9 @@ TRACE("Key UP, doing nothing\n" ); return 0; } + memset (&e,0,sizeof(e)); + + e.type = KeyPress; e.display = display; e.keycode = 0; e.state = 0; @@ -1814,7 +1856,15 @@ } else TRACE("Found keycode %d (0x%2X)\n",e.keycode,e.keycode);
- ret = XLookupString(&e, (LPVOID)lpChar, 2, &keysym, NULL); +#ifdef HAVE_XKB + if (xic) { + ret = XmbLookupString(xic,&e, (LPVOID)lpChar, sizeof(lpChar), &keysym, NULL); + } else { + ret = XLookupString(&e, (LPVOID)lpChar, sizeof(lpChar), &keysym, NULL); + } +#else + ret = XLookupString(&e, (LPVOID)lpChar, sizeof(lpChar), &keysym, NULL); +#endif wine_tsx11_unlock();
if (ret == 0) --- window.c 8 Jan 2003 11:24:51 -0000 1.1 +++ window.c 8 Jan 2003 14:30:53 -0000 @@ -43,6 +43,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
extern Pixmap X11DRV_BITMAP_Pixmap( HBITMAP ); +extern X11DRV_KeyboardWindow (Display *display, Window w);
#define HAS_DLGFRAME(style,exStyle) \ (((exStyle) & WS_EX_DLGMODALFRAME) || \ @@ -199,6 +200,7 @@ CWEventMask | CWBitGravity | CWBackingStore | CWColormap, &attr ); XSaveContext( display, data->icon_window, winContext, (char *)win->hwndSelf ); wine_tsx11_unlock(); + if (data->client_window) X11DRV_KeyboardWindow (display, data->whole_window);
TRACE( "created %lx\n", data->icon_window ); SetPropA( win->hwndSelf, icon_window_atom, (HANDLE)data->icon_window ); @@ -686,6 +688,7 @@ wine_tsx11_unlock(); return 0; } + X11DRV_KeyboardWindow (display, data->whole_window);
/* non-maximized child must be at bottom of Z order */ if ((win->dwStyle & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD) @@ -732,6 +735,7 @@ CWEventMask | CWBitGravity | CWBackingStore, &attr ); if (data->client_window && is_client_window_mapped( win )) XMapWindow( display, data->client_window ); + if (data->client_window) X11DRV_KeyboardWindow (display, data->whole_window); wine_tsx11_unlock(); return data->client_window; } --- desktop.c 8 Jan 2003 11:24:51 -0000 1.1 +++ desktop.c 8 Jan 2003 14:30:53 -0000 @@ -30,6 +30,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
+extern X11DRV_KeyboardWindow (Display *display, Window w);
/* desktop window procedure */ static LRESULT WINAPI desktop_winproc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) @@ -141,6 +142,8 @@ win = XCreateWindow( display, DefaultRootWindow(display), x, y, width, height, 0, screen_depth, InputOutput, visual, CWBackPixel | CWEventMask | CWCursor | CWColormap, &win_attr ); + + if (win) X11DRV_KeyboardWindow (display, win);
/* Set window manager properties */ size_hints = XAllocSizeHints();
On Wed, Jan 08, 2003 at 12:55:15PM -0200, Mauro Carvalho Chehab wrote:
Rikki,
Please try to apply the following patch against the new CVS version (on /dlls/x11drv directory). This patch will allow keyboard.c to use your locale setting by the usage of xkb extension on X11R6. Please notice that this requires that you *don't have* xkbdisable on your XF86Config file (or XF86Config-4).
I applied the patch and did a recompile on todays CVS. I see a change, but it does not fix things for Icelandic. My mute key is:
[ra@morticia ra]$ xmodmap -pke | grep dead_acute keycode 48 = dead_acute Adiaeresis dead_circumflex dead_caron
Its dead_acute I need to get working. With your patch it still doesnt work, but pressing "alt and the mute key" (dead_circumflex) works. So I can get characters like â ê û î :)
Btw, that key is incorrect from the XFree.org people. That Adiaeresis is not supposed to be there and causes wine to complain:
fixme:keyboard:X11DRV_KEYBOARD_DetectLayout Your keyboard layout was not found! Using closest match instead (Icelandic keyboard layout) for scancode mapping. Please define your layout in windows/x11drv/keyboard.c and submit them to us for inclusion into future Wine releases. See the Wine User Guide, chapter "Keyboard" for more information.
I enabled debugging and its that key thats causing the complaint. All the others are right.
So I added the Adiaeresis to the definition for the Icelandic keymap in keyboard.c and the complaint went away, but it's still not working :)
Rikki,
As far as I know, wine keyboard.c uses XFree86 Keymap table to compare your key definitions with their internal geometry. After that, it maps every scan code to a virtual key. The virtual key is mapped back to a scan code and to an unicode symbol by ToUnicode function. During this proccess, it uses part of the original xfree mapping. On the original ToUnicode function, it uses the function XLookupString (a Xlib function) to map scan code->symbol. This function is capable to work with latin characters, but it doesn't implement dead keys translation on the current XFree86 implementations. In the past, there was some Xlib hacking that changes this behavor (X11 R5 implementations). The new standard (X11 R6) creates the xkb extensions, that provides new functions to treat locale imput data (XmbLookupString, Xutf8LookupString and XwcLookupString). What it does is to use XFree86 locale settings to make this map. The dead key treatment is defined on /usr/X11R6/lib/X11/locale. The geometry of their keyboards, used by xkb, are on /usr/X11R6/lib/X11/xkb (RedHat) or /etc/X11/xkb (Mandrake). The file symbols/is, for example, contains some icelandic definitions. From your answer, I would try to fix the XFree86 keyboard mapping on symbols/is. I guess that this will solve both XFree and Wine (patched).
Richard Allen wrote:
On Wed, Jan 08, 2003 at 12:55:15PM -0200, Mauro Carvalho Chehab wrote:
Rikki,
Please try to apply the following patch against the new CVS version (on /dlls/x11drv directory). This patch will allow keyboard.c to use your locale setting by the usage of xkb extension on X11R6. Please notice that this requires that you *don't have* xkbdisable on your XF86Config file (or XF86Config-4).
I applied the patch and did a recompile on todays CVS. I see a change, but it does not fix things for Icelandic. My mute key is:
[ra@morticia ra]$ xmodmap -pke | grep dead_acute keycode 48 = dead_acute Adiaeresis dead_circumflex dead_caron
Its dead_acute I need to get working. With your patch it still doesnt work, but pressing "alt and the mute key" (dead_circumflex) works. So I can get characters like â ê û î :)
Btw, that key is incorrect from the XFree.org people. That Adiaeresis is not supposed to be there and causes wine to complain:
fixme:keyboard:X11DRV_KEYBOARD_DetectLayout Your keyboard layout was not found! Using closest match instead (Icelandic keyboard layout) for scancode mapping. Please define your layout in windows/x11drv/keyboard.c and submit them to us for inclusion into future Wine releases. See the Wine User Guide, chapter "Keyboard" for more information.
I enabled debugging and its that key thats causing the complaint. All the others are right.
So I added the Adiaeresis to the definition for the Icelandic keymap in keyboard.c and the complaint went away, but it's still not working :)
On Mon, Jan 13, 2003 at 12:07:10PM -0200, Mauro Carvalho Chehab wrote:
From your answer, I would try to fix the XFree86 keyboard mapping on symbols/is. I guess that this will solve both XFree and Wine (patched).
I was aware of symbols/is. I've even sent in a fix for that key to both RedHat and XFree86.org. But thats not the problem here. the dead_acute (áýúíóÁÉÝÚÍÓ) is working just fine in X and all X applications. It doesnt matter which WM I use. fvwm, windowmaker, gnome or kde. Accented chars have been fine in X for a long time now. Its just in wine they are broken. The only problem symbols/is caused is that one key was not recognized during wine startup so wine rightfully decided to use the Icelandic keymap because it was the closest to what was running at the time. Since my last mail, I've fixed symbols/is and keyboard.c so the dead_acute key is correct and no complaining happens in wine now. The problem with it was that shift-dead_key was wrong, and thats very seldom used.
PS: thanks for taking the time to help me with this problem :)
On Mon, Jan 13, 2003 at 12:07:10PM -0200, Mauro Carvalho Chehab wrote:
I've been studying this quite a bit. With this patch, I've verifyed that some of the dead keys work, and some not. If I change the IS keymap so Im using dead_circumflex instead of dead_acute, then dead (accented) characters do work, but obviously not the right ones. This leads me to think that dead_acute characters are handled differently by wine than dead_circumflex characters are.
Mauro, do you think I could be on to something here ?
Rikki,
As far as I know, wine keyboard.c uses XFree86 Keymap table to compare your key definitions with their internal geometry. After that, it maps every scan code to a virtual key. The virtual key is mapped back to a scan code and to an unicode symbol by ToUnicode function. During this proccess, it uses part of the original xfree mapping. On the original ToUnicode function, it uses the function XLookupString (a Xlib function) to map scan code->symbol. This function is capable to work with latin characters, but it doesn't implement dead keys translation on the current XFree86 implementations. In the past, there was some Xlib hacking that changes this behavor (X11 R5 implementations). The new standard (X11 R6) creates the xkb extensions, that provides new functions to treat locale imput data (XmbLookupString, Xutf8LookupString and XwcLookupString). What it does is to use XFree86 locale settings to make this map. The dead key treatment is defined on /usr/X11R6/lib/X11/locale. The geometry of their keyboards, used by xkb, are on /usr/X11R6/lib/X11/xkb (RedHat) or /etc/X11/xkb (Mandrake). The file symbols/is, for example, contains some icelandic definitions. From your answer, I would try to fix the XFree86 keyboard mapping on symbols/is. I guess that this will solve both XFree and Wine (patched).
Rikki,
May be... Wine uses the idea to map keys into vkeys and then mapping back to keys... If something goes wrong on this proccess, it could produce strange results... I can give you some new ideas, but as far as I never seen an Icelandic keyboard, and of course don't have one to hack, you have to try some hacking by yourself. I advice you to try (on this order): 1) May be your keyboard layout is not like a pure QWERTY keyboard. On Brasilian keyboards, we have 49 "main" keys instead of 48. So, I had to include this new key on the layout, generating the 'main_key_scan_abnt_qwerty' and the corresponding 'main_key_vkey_abnt_qwerty' tables, mapping the virtual key VK_OEM_8 to the new key (c cedilla), after ASFGHJKL. You can see these on the current Wine-CVS code. Please notice that the routines that maps keys to vkeys espects to receive some specific VK_OEM_<n> codes for some keys, like '' (mapped as VK_OEM_7) on X11DRV_InitKeyboard. In fact, the only available VK I found was VK_OEM_8. 2) on ToUnicode (with my patch applyied), what is the return of ret=XmbLookupString? Please notice that, if the return is zero, it will use the Xlib function 'MultiByteToWideChar' after running a code to map the dead keys. Maybe the KEYBOARD_MapDeadKeysym is not treating your dead_circumflex keycode correctly. 3) For brazilian keyboards I need only to change XLookupString to XmbLookupString on KEYBOARD_ToUnicode function, in order to use XKB treatment instead of Xlib, but there are some other points where that function is used. Looking at a glance, I haven't found any reason to change, but you can try to understand better the other calls.
I hope these comments can help you.
Mauro.
Richard Allen wrote:
On Mon, Jan 13, 2003 at 12:07:10PM -0200, Mauro Carvalho Chehab wrote:
I've been studying this quite a bit. With this patch, I've verifyed that some of the dead keys work, and some not. If I change the IS keymap so Im using dead_circumflex instead of dead_acute, then dead (accented) characters do work, but obviously not the right ones. This leads me to think that dead_acute characters are handled differently by wine than dead_circumflex characters are.
Mauro, do you think I could be on to something here ?
Rikki,
As far as I know, wine keyboard.c uses XFree86 Keymap table to compare your key definitions with their internal geometry. After that, it maps every scan code to a virtual key. The virtual key is mapped back to a scan code and to an unicode symbol by ToUnicode function. During this proccess, it uses part of the original xfree mapping. On the original ToUnicode function, it uses the function XLookupString (a Xlib function) to map scan code->symbol. This function is capable to work with latin characters, but it doesn't implement dead keys translation on the current XFree86 implementations. In the past, there was some Xlib hacking that changes this behavor (X11 R5 implementations). The new standard (X11 R6) creates the xkb extensions, that provides new functions to treat locale imput data (XmbLookupString, Xutf8LookupString and XwcLookupString). What it does is to use XFree86 locale settings to make this map. The dead key treatment is defined on /usr/X11R6/lib/X11/locale. The geometry of their keyboards, used by xkb, are on /usr/X11R6/lib/X11/xkb (RedHat) or /etc/X11/xkb (Mandrake). The file symbols/is, for example, contains some icelandic definitions. From your answer, I would try to fix the XFree86 keyboard mapping on symbols/is. I guess that this will solve both XFree and Wine (patched).