[PATCH 1/2] Improved fix for mono bug #692206
authorEberhard Beilharz <eb1@sil.org>
Wed, 29 Jun 2011 06:23:21 +0000 (08:23 +0200)
committerThomas Goldstein <stifu@free.fr>
Wed, 29 Jun 2011 06:32:05 +0000 (08:32 +0200)
In contrast to Xutf8LookupString, XLookupString returns the number
of characters stored in the buffer instead of a status. If the buffer
is too small the output is truncated, but we don't know it. However, it
seems pretty unlikely that a buffer of 24 chars shouldn't be enough for a
single key press, so I simplified the code a little bit.
Also, XLookupString converts the keySym to an ISO Latin-1
character so that there is no need to do an explicit conversion.

Add variable to store Ansi encoding so that we have to get it only once.

Fix a few problems encountered debugging this problem.

mcs/class/Managed.Windows.Forms/System.Windows.Forms/X11Keyboard.cs

index 4ad67fca1942c228a316a3baca7d54989d19f77b..2f92e3df38967bd330a1fc8d6f51ecbe42707aae 100644 (file)
@@ -61,6 +61,7 @@ namespace System.Windows.Forms {
                private bool num_state, cap_state;
                private bool initialized;
                private bool menu_state = false;
+               private Encoding encoding;
 
                private int NumLockMask;
                private int AltGrMask;
@@ -72,6 +73,16 @@ namespace System.Windows.Forms {
                        EnsureLayoutInitialized ();
                }
 
+               private Encoding AnsiEncoding
+               {
+                       get
+                       {
+                               if (encoding == null)
+                                       encoding = Encoding.GetEncoding(new CultureInfo(lcid).TextInfo.ANSICodePage);
+                               return encoding;
+                       }
+               }
+
                public IntPtr ClientWindow {
                        get { return client_window; }
                }
@@ -197,10 +208,10 @@ namespace System.Windows.Forms {
 
                public void FocusIn (IntPtr window)
                {
+                       this.client_window = window;
                        if (xim == IntPtr.Zero)
                                return;
 
-                       this.client_window = window;
                        if (!xic_table.ContainsKey ((long) window))
                                CreateXicForWindow (window);
                        IntPtr xic = GetXic (window);
@@ -212,10 +223,10 @@ namespace System.Windows.Forms {
 
                public void FocusOut (IntPtr window)
                {
+                       this.client_window = IntPtr.Zero;
                        if (xim == IntPtr.Zero)
                                return;
 
-                       this.client_window = IntPtr.Zero;
                        IntPtr xic = GetXic (window);
                        if (xic != IntPtr.Zero) {
                                if (have_Xutf8ResetIC) {
@@ -459,8 +470,7 @@ namespace System.Windows.Forms {
                                if (dead_char != 0) {
                                        byte [] bytes = new byte [1];
                                        bytes [0] = (byte) dead_char;
-                                       Encoding encoding = Encoding.GetEncoding (new CultureInfo (lcid).TextInfo.ANSICodePage);
-                                       buffer = new string (encoding.GetChars (bytes));
+                                       buffer = new string (AnsiEncoding.GetChars (bytes));
                                        res = -1;
                                }
                        } else {
@@ -981,6 +991,7 @@ namespace System.Windows.Forms {
                                xic = XCreateIC (xim,
                                        XNames.XNInputStyle, styleRoot,
                                        XNames.XNClientWindow, window,
+                                       XNames.XNFocusWindow, window,
                                        IntPtr.Zero);
                        }
                        return xic;
@@ -1190,25 +1201,15 @@ namespace System.Windows.Forms {
 
                        status = IntPtr.Zero;
                        IntPtr xic = GetXic (client_window);
-                       if (xic != IntPtr.Zero && have_Xutf8LookupString) {
+                       if (xic != IntPtr.Zero && have_Xutf8LookupString && xevent.type == XEventName.KeyPress) {
                                do {
                                        try {
                                                res = Xutf8LookupString (xic, ref xevent, lookup_byte_buffer, 100, out keysym_res,  out status);
                                        } catch (EntryPointNotFoundException) {
                                                have_Xutf8LookupString = false;
 
-                                               /* Duplicate of the non-xic clause */
-                                               do {
-                                                       res = XLookupString (ref xevent, lookup_byte_buffer, 100, out keysym_res, out status);
-                                                       if ((int) status != -1) // XLookupBufferOverflow
-                                                               break;
-                                                       lookup_byte_buffer = new byte [lookup_byte_buffer.Length << 1];
-                                               } while (true);
-                                               lookup_buffer.Length = 0;
-                                               string s2 = Encoding.ASCII.GetString (lookup_byte_buffer, 0, res);
-                                               lookup_buffer.Append (s2);
-                                               keysym = (XKeySym) keysym_res.ToInt32 ();
-                                               return res;
+                                               // call again, this time we'll go through the non-xic clause
+                                               return LookupString (ref xevent, len, out keysym, out status);
                                        }
                                        if ((int) status != -1) // XLookupBufferOverflow
                                                break;
@@ -1220,15 +1221,9 @@ namespace System.Windows.Forms {
                                keysym = (XKeySym) keysym_res.ToInt32 ();
                                return s.Length;
                        } else {
-                               do {
-                                       res = XLookupString (ref xevent, lookup_byte_buffer, 100, out keysym_res, out status);
-                                       if ((int) status != -1) // XLookupBufferOverflow
-                                               break;
-                                       lookup_byte_buffer = new byte [lookup_byte_buffer.Length << 1];
-                               } while (true);
+                               IntPtr statusPtr = IntPtr.Zero;
                                lookup_buffer.Length = 0;
-                               string s = Encoding.ASCII.GetString (lookup_byte_buffer, 0, res);
-                               lookup_buffer.Append (s);
+                               res = XLookupString (ref xevent, lookup_buffer, len, out keysym_res, out statusPtr);
                                keysym = (XKeySym) keysym_res.ToInt32 ();
                                return res;
                        }
@@ -1294,7 +1289,7 @@ namespace System.Windows.Forms {
                private static extern bool XSetLocaleModifiers (string mods);
 
                [DllImport ("libX11")]
-               internal extern static int XLookupString(ref XEvent xevent, byte [] buffer, int num_bytes, out IntPtr keysym, out IntPtr status);
+               internal extern static int XLookupString(ref XEvent xevent, StringBuilder buffer, int num_bytes, out IntPtr keysym, out IntPtr status);
                [DllImport ("libX11")]
                internal extern static int Xutf8LookupString(IntPtr xic, ref XEvent xevent, byte [] buffer, int num_bytes, out IntPtr keysym, out IntPtr status);